Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.02.2010, 21:59   #1
Valter
Пользователь
 
Регистрация: 29.03.2008
Сообщений: 51
По умолчанию Моя strcat

Здравствуйте, уважаемые!

Осваиваю C. Написал программу, использующую ф-ю strcat(), но не библиотечную, а мою собственную. Возник вопрос следующего содержания...

В таком варианте работа ф-и неверна:

Код:
void strcat2(char* s, char* t)
{
    while ((*s++) != '\0')
        ;
    while ((*s++ = *t++) != '\0')
        ;
}
при печати в вызывающей программе в конец s[] не добавляется t[], то есть
Код:
printf("\nResult:\n%s", string1);
выводит только изначальную s[] без t[] в конце.


В таком - работа ф-и верна:

Код:
void strcat2(char* s, char* t)
{
    while (*s != '\0')
        s++;
    while ((*s++ = *t++) != '\0')
        ;
}
Вся разница - в первом while. Непонятно, почему в нем нельзя использовать оператор инкремента на указателе в самом условии? Объясните, пожалуйста, если не трудно.
Valter вне форума Ответить с цитированием
Старый 11.02.2010, 22:13   #2
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

*s++ - разыменовывает s, затем увеличивает указатель s на один
то есть сначала он находит '\0', а затем тут же увеличивает указатель на 1
то есть после цикла
Код:
while((*s++) != '\0');
s указывает на символ, следующий за нулём
netrino вне форума Ответить с цитированием
Старый 12.02.2010, 00:07   #3
Valter
Пользователь
 
Регистрация: 29.03.2008
Сообщений: 51
По умолчанию

Точно.

То есть в первом while при достижении конца строки, из конструкции (*s++) для сравнения c '\0' берется еще не увеличенный на 1 указатель s, потом он разыменовывается *s для получения самого значения, оно сравнивается с '\0', в результате чего тело цикла первого while (пусть и пустое) не выполняется и следующей итерации не будет, но при этом указатель все равно сдвигается на 1 вследствие внутреннего инкремента в условии.

Но этого не происходит, когда увеличение указателя выделено отдельно в тело цикла, как во втором while.

Все так, я ничего не упустил?

Спасибо, netrino!

PS: н-да, надо осторожнее с инкрементами/декрементами в условиях, не первый раз уже на одни и те же грабли встаю...(
Valter вне форума Ответить с цитированием
Старый 12.02.2010, 00:14   #4
Valter
Пользователь
 
Регистрация: 29.03.2008
Сообщений: 51
По умолчанию

Кстати, а в случае
Код:
((*s++ = *t++) != '\0')
тоже происходит выход за границы? Ведь при этом оба указателя s и t после того, как в s[] скопировался '\0' из конца t[], и сравнился с '\0' в условии, тоже увеличиваются на 1. Здесь тоже была бы ошибка, если бы я, скажем, еще стал дописывать к строке другие строки?
Valter вне форума Ответить с цитированием
Старый 12.02.2010, 00:18   #5
netrino
Участник клуба
 
Аватар для netrino
 
Регистрация: 15.07.2008
Сообщений: 1,933
По умолчанию

Цитата:
Сообщение от Valter Посмотреть сообщение
Все так, я ничего не упустил?
Всё верно

Цитата:
Сообщение от Valter
Кстати, а в случае
Код:

((*s++ = *t++) != '\0')

тоже происходит выход за границы? Ведь при этом оба указателя s и t после того, как в s[] скопировался '\0' из конца t[], и сравнился с '\0' в условии, тоже увеличиваются на 1. Здесь тоже была бы ошибка, если бы я, скажем, еще стал дописывать к строке другие строки?
Да, в данном случае это не критично, так как s и t больше не используются, но тем не менее Вы правы )
Кстати, в принципе это можно было бы записать короче:
Код:
while(*s++); // первый цикл
while(*s++ = *t++); // второй цикл
При достижении нуля, он попадает в условие while и выступает в качестве false, хотя, безусловно, это не столь очевидная запись

Последний раз редактировалось netrino; 12.02.2010 в 00:22.
netrino вне форума Ответить с цитированием
Старый 12.02.2010, 00:30   #6
Valter
Пользователь
 
Регистрация: 29.03.2008
Сообщений: 51
По умолчанию

Цитата:
Сообщение от netrino Посмотреть сообщение
Да, в данном случае это не критично, так как s и t больше не используются, но тем не менее Вы правы )
То есть, если бы я их использовал дальше, и после последнего while еще было бы что-то с этими указателями, то снова была бы ошибка при записи...

Ну а так - да, действительно, они же локальные копии, после выхода - уничтожаются и уже не важно, куда они указывали в конце работы этой функции. Именно так, кстати, рекомендуют писать Ритчи с Керниганом.


Цитата:
Кстати, в принципе это можно было бы записать короче:...
это не столь очевидная запись
Знаю, поэтому я специально так не пишу, во всяком случае, пока.
Valter вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Моя музыка Манжосов Денис :) Свободное общение 0 08.11.2009 19:35
strcat larry Win Api 3 20.07.2009 12:44
не работает strcat(),strcpy() MeGaTpoH Общие вопросы C/C++ 5 25.01.2009 17:31
Моя прога RealSHELS Софт 12 16.07.2008 23:59
Моя библиотека mochaliviy Свободное общение 3 11.01.2008 13:23