puts (s2); // ошибка! нет последнего '\0'
s2[2] = '\0'; // добавляем символ окончания строки
Puts (s2); // вывод
}
Проблемы при копировании строк
При копировании стандартные функции strcpy и strncpy поступают так: определяют
количество символов, которые надо скопировать и затем переписывают их, начиная с первого символа до последнего. Если области источника и приемника не перекрываются, то все проходит нормально. Но попробуем «раздвинуть» строку, например для того, чтобы вставить что-то в ее середину. Пусть в строке s1 записано имя и фамилия человека, а в строке s2 – его отчество.Надо получить в строке s1 полностью имя, фамилию и отчество.
#include <stdio.h>
#include <string.h>
Main()
{
int n;
char s1[80] = "Иван Рождественский",
s2[] = "Петрович ";
n = strlen(s2); // длина второй строки
strcpy (s1+5, s1+5+n); // пытаемся раздвинуть на n символов
strncpy(s1+5, s2, n); // вставляем отчество в середину
puts (s1);
}
При первом вызове strcpy мы хотели скопировать конец строки, начиная с символа с номером 5 (он шестой с начала, так как нумерация идет с нуля) вправо на n символов (объявленная__длина массива символов – 80 – позволяет это сделать). Однако из-за того, что копирование выполнялось с начала блока данных, скопировав на новое место первый символ фамилии ('Р') функция стерла букву 'н' (справа на 9 символов) и т.д. В результате получили
|
|
s1 = "Иван РождествеРождествеРождес"
В следующей строчке мы скопировали в середину отчество (без завершающего нуля) и получили
s1 = "Иван Петрович РождествеРождес"
Таким образом, вся задумка не удалась из-за того, что функция копирования работает в данном случае неверно. Выход из этой ситуации такой – написать свою функцию копирования, которая копирует не с начала блока, а с конца (однако она будет неверно работать в обратной ситуации– при сжатии строки). Например, так:
void strcpy1 (char s1[], char s2[])
{
int n = strlen(s2);
while (n >= 0)
{
s1[n] = s2[n];
n --;
}
}
Заметьте, что завершающий нуль строки s2 также копируется. Если использовать в нашем
примере эту функцию вместо strcpy, то получим желаемый результат.
Возникает вопрос: можно ли сделать функцию, которая всегда правильно копирует? Конечно, можно, хотя это и не просто. Для этого в самой функции надо использовать вспомогательную строку (ее называют буфером) и в ней формировать результат так, чтобы в процессе копирования не портилась исходная строка. Когда результат в буфере готов, его останется скопировать в то место, где была исходная строка и удалить память, выделенную под буфер. Попробуйте написать такую функцию, если известно, что ее будут использовать для копирования строк длиной не более 80 символов.
Объединение строк
|
|
Еще одна функция – strcat (от str ing con cat enation – сцепка строк) позволяет добавить
строку источник в конец строки-приемника (завершающий нуль записывается автоматически).
Надо только помнить, что приемник должен иметь достаточный размер, чтобы вместить обе исходных строки. Функция strcat автоматически добавляет в конец строки-результата завершающий символ '\0'.
#include <stdio.h>
#include <string.h>
Main()
{
char s1[80] = "Могу, ",
s2[] = "хочу, ", s3[] = "надо!";