2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Функция, которая удаляет нужный символ из строки [C ]
Сообщение01.08.2012, 09:25 
Аватара пользователя
Вновь из Кернигана-Ритчи не могу понять устройство следующей функции.
Цитата: "Для примера рассмотрим функцию squeeze (s, с), которая удаляет все вхождения
символа с из строки s.
Используется синтаксис C
/* squeeze: удаляет все символы с из строки s */
void squeeze(char s [] , int c)
{
    int i, j ;
    for (i = j = 0; s[i] != '\0'; i++)
    if (s[i] != c)
        s [j+ + ] = s [i] ;
    s[j] = '\0';
}

Всякий раз, когда встречается символ, отличный от с, он копируется в текущую
позицию j, и только затем j инкрементируется, чтобы подготовиться к приему
следующего символа. Эта форма в точности эквивалентна следующей":
Используется синтаксис C
if (s[i] != с) {
    s[j] = s[i] ;
    j++;
}

Вопрос:
Почему после первого, отличного от 'с' символа цикл продолжает выполняться? Допустим s[0] отличен от с, тогда s[1] = '\0', но ведь в заголовке for s[i] != '\0'. Объясните пожалуйста.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 10:10 
Аватара пользователя
Dosaev в сообщении #601751 писал(а):
Допустим s[0] отличен от с, тогда s[1] = '\0',


Почему? С чего Вы это взяли?

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 10:16 
Dosaev в сообщении #601751 писал(а):
Допустим s[0] отличен от с, тогда s[1] = '\0',

Нолик ведь присваивается после цикла, а не внутри.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 10:49 
Аватара пользователя
ewert в сообщении #601762 писал(а):
Нолик ведь присваивается после цикла, а не внутри.

Аа, вон оно как. Тут просто без { } написано, поэтому показалось, что в цикле. Спасибо.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 14:42 
Аватара пользователя
Принято указывать вложенность отступами. Если вы смотрите в книге на пример, обращайте внимание на отступы, и потом аккуратно их воспроизводите (здесь вы неправильно воспроизвели даже оператор + +, с пробелом - так не скомпилируется). Обратите внимание:
Используется синтаксис C
/* squeeze: удаляет все символы с из строки s */
void squeeze(char s [] , int c)
{
    int i, j;
    for (i = j = 0; s[i] != '\0'; i++)
        if (s[i] != c)
            s [j++] = s [i] ;
    s[j] = '\0';
}

"читается взглядом" как:
Используется синтаксис C
/* squeeze: удаляет все символы с из строки s */  <-- 0-й уровень вложенности - текст на уровне файла
void squeeze(char s [] , int c)
{
|   int i, j;                                     <-- 1-й уровень вложенности - текст на уровне функции,
|   for (i = j = 0; s[i] != '\0'; i++)                  то есть 0-й уровень вложенности в функции
|   |   if (s[i] != c)                            <-- 1-й уровень вложенности в функции, вложено в for
|   |   |   s [j++] = s [i] ;                     <-- 2-й уровень вложенности в функции, вложено в for - if
|   s[j] = '\0';                                  <-- снова 0-й уровень вложенности в функции
}


Разумеется, по правилам языка так делать не обязательно (компилятор всё "скушает"), но для читаемости текста другим человеком - обязательно. Это абсолютно общепринятая традиция, и нарушается, только если надо специально читателя запутать.

Ещё полезно раздельные смысловые части функции зрительно отделять одну от другой пустыми строками, и/или комментариями. Но это уже дело вкуса. То есть, тот же текст можно написать так:
Используется синтаксис C
/* squeeze: удаляет все символы с из строки s */
void squeeze(char s [], int c)
{
    int i, j;

    for (i = j = 0; s [i] != '\0'; i++)
        if (s [i] != c)
            s [j++] = s [i];

    s [j] = '\0';
}

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 16:55 
Аватара пользователя
Munin в сообщении #601864 писал(а):
(здесь вы неправильно воспроизвели даже оператор + +, с пробелом - так не скомпилируется)

Это я понимаю, просто скопировал код прямо из книги, и поэтому так вышло. Извините, не обратил внимание.
Munin в сообщении #601864 писал(а):
обращайте внимание на отступы

Да, спасибо, вы очень щепетильны :-) Но дело в том, что мне показалось, что оператор присваивания s[j++] = s[i] не относится к циклу. Да, он относится к условию if, а if в свою очередь лежит в цикле, это понятно. Но для меня это не означало, что он принадлежит for. Короче говоря, оператор присваивания лежал в for-е через if, и для меня это не показалось очевидным.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 17:29 
Dosaev в сообщении #601914 писал(а):
и для меня это не показалось очевидным.

Так ведь именно из-за недисциплинированности отступов и показалось, так всегда бывает.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 17:56 
Аватара пользователя
Ну, значит, привыкайте, у вас ещё большая дорога впереди.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 20:22 
Еще можно всегда-всегда брать тела циклов/ветвлений в фигурные скобки, даже если там всего одна строчка. Здорово ускоряет момент, когда ты понимаешь, что функцию пора резать на пять маленьких :-)

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 20:53 
Аватара пользователя

(Оффтоп)

Joker_vD в сообщении #602014 писал(а):
Еще можно всегда-всегда брать тела циклов/ветвлений в фигурные скобки, даже если там всего одна строчка. Здорово ускоряет момент, когда ты понимаешь, что функцию пора резать на пять маленьких

Тут бывает в обратную сторону причинно-следственная связь. Функцию пора резать, когда она не умещается в голове и на экране. А добавляя почти пустых строк, вы её текстуально увеличиваете и зрительно усложняете.

 
 
 
 Re: Функция, которая удаляет нужный символ из строки
Сообщение01.08.2012, 21:19 

(Оффтоп)

Joker_vD в сообщении #602014 писал(а):
Еще можно всегда-всегда брать тела циклов/ветвлений в фигурные скобки, даже если там всего одна строчка.

Я их в фигурные скобки никогда не беру попросту потому, что в Сях не программирую. Зато, напротив, коротенькие тела циклов стараюсь уместить в одну строчку даже при нескольких командах в теле -- просто для пущей читабельности (хотя бы для себя самого потом), и пусть меня потом пуристы травят, мне интереснее результат. С третьей стороны, иногда и однооператорные тела беру в операторные скобки, но это уже лишь с прицелом на возможные дальнейшие модификации, а так нет. С четвёртой: независимо от всего предыдущего, отступы -- это святое, и за отступление от них следует сжигать на костре.

 
 
 [ Сообщений: 11 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group