target = "Очень долго"; /* синтаксическая ошибка */
Ответственность за обеспечение в целевом массиве достаточного пространства для размещения копии источника возлагается на вас. Следующий код приводит к проблеме:
char * str;
strcpylstr, "Невозмутимость С"); // проблема
Этот вызов strcpy() копирует строку "Невозмутимость С" но адресу, указанному в str, но переменная str не инициализирована, так что копия может оказаться где угодно!
Короче говоря, функция strcpy() принимает в качестве аргументов два указателя на строки. Второй указатель, который ссылается на исходную строку, может быть объявленным указателем, именем массива или строковой константой. Первый указатель, ссылающийся на копию, должен указывать на объект данных, такой как массив с размером, достаточным для хранения этой строки. Вспомните, что объявление массива приводит к выделению пространства под данные, а при объявлении указателя пространство выделяется только для размещения одного адреса.
Другие свойства функции strcpy()
Функция strcpy() обладает еще двумя свойствами, которые вы можете счесть удобными. Во-первых, ее типом является char *. Она возвращает значение своего первого аргумента — адрес символа. Во-вторых, первый аргумент не обязательно должен указывать на начало массива; это позволяет копировать только часть массива. Оба свойства продемонстрированы в листинге 11.26.
Символьные строки и строковые функции 457
Листинг 11.26. Программа сору2. с

Ниже показан вывод: наихудшим
Будьте лучшим, чем могли бы быть.
Будьте наихудшим наихудшим
Обратите внимание, что функция strcpy() копирует нулевой символ из исходной строки. В этом примере нулевой символ перезаписывает букву е в слове чем внутри сору, так что новая строка заканчивается словом наихудшим (рис. 11.5). Кроме того, ps указывает на восьмой элемент (с индексом 7) массива сору, поскольку в первом аргументе передается сору + 7. Таким образом, вызов puts (ps) выводит строку, начиная с этой позиции.

Рис. 11.5. Функция strcpy() использует указатели
458 глава 11
Аккуратный выбор: функция strncpy()
Функции strcpy() присуща та же проблема, что и strcat() — ни одна из них не проверяет, умещается ли на самом деле исходная строка в целевую строку. Более безопасный способ копирования строк предусматривает применение функции strncpy(). Эта функция принимает третий аргумент, в котором указывается максимальное количество копируемых символов. В листинге 11.27 приведена переписанная версия кода из листинга 11.25, в которой вместо strcpy() используется strncpy! )• Чтобы показать, что происходит в случае, когда размер исходной строки слишком велик, для целевых строк в коде выбран небольшой размер (семь элементов, шесть символов).
Листинг 11.27. Программа соруЗ.с

Символьные строки и строковые функции 459
Ниже показаны результаты пробного запуска:
Введите 5 слов, начинающиеся с буквы q:
квазар
квота
кристалл
квалификация
конкурс
Список принятых слов:
квазар
квота
кристал
квалифи
конкурс
Вызов функции strncpy (target, source, n) копирует вплоть до n символов либо до появления нулевого символа (в зависимости от того, что произойдет раньше) из source в target. Следовательно, если количество символов в source меньше n, копируется вся строка, включая нулевой символ. Эта функция никогда не копирует более n символов, так что если данный лимит исчерпан до достижения конца исходной строки, то нулевой символ не добавляется. Таким образом, финальный результат может содержать, а может и не содержать нулевой символ. По этой причине значение п в программе выбрано на единицу меньше размера целевого массива, а последний элемент массива установлен в нулевой символ:
strncpy(qwords[i], temp, TARGSIZE - 1); qwords[i] [TARGSIZE - 1] = ‘\0’;
Это обеспечивает сохранение строки. Если исходная строка в действительности умещается в целевую строку, то скопированный вместе с ней нулевой символ помечает настоящий конец строки. Если исходная строка в целевую не умещается, то конец строки помечается последним нулевым символом.
ФУНКЦИЯ sprintf()
Функция sprintf() объявлена в заголовочном файле stdio.h, а не в string.h. Она работает подобно printf(), но осуществляет запись в строку, а не па дисплей. Таким образом, она предоставляет способ объединения нескольких элементов в единую строку. Первый аргумент sprintf() — это адрес целевой строки. Остальные аргументы аналогичны аргументам в printf() — строка спецификации преобразования и список элементов, предназначенных для записи.
Читать дальше