§ 8. Строки

§ 8.1 Массивы символов

Строго говоря, строк в языке C нет, а есть массивы символов.

#define SIZE 16u
char string1[SIZE] = "Hello, world!"; // Необязательная инициализация.
H e l l o ,   w o r l d ! \0

Строку завершает нулевой символ (\0), за ним (если строка занимает не весь буфер) идёт мусор.

Динамические строки создаются по аналогии с массивами.

size_t size = 16u;
char* string2 = malloc(sizeof(char) * size2); // sizeof(char) всегда равно 1.
strcpy(string2, "Hello, world!");

Чтобы изменять значение, содержащееся в строке, можно менять отдельные символы.

string1[12] = '?';
string2[12] = '?';

Вывод строк выглядит аналогично.

printf("%s\n", string1);
puts(string1);

printf("%s\n", string2);
puts(string2);

А если нужно изменить всю строку, то используется функция копирования strcpy() (эта и другие функции находятся в заголовочном файле <string.h>), пример можно увидеть выше.

А если попытаться изменить строку по-наивному? С «настоящей строкой» это вообще не пройдёт.

string1 = "Hello, world!";

С динамической строкой, на первый взгляд, всё будет хорошо. Но когда вы попытаетесь изменить полученную строку, то произойдёт страшная ошибка. Потому что копирования символов не произойдёт, а будет скопирован указатель на память только для чтения. (А даже если вы не будете менять строку, то при завершении программы или ещё раньше при попытке очистить память только для чтения случится критическая ошибка.)

string2 = "Hello, world!";

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

if (string1 == string2) // Ложь (в общем случае).
{
    printf("The same.\n");
}
else
{
    printf("Different.\n");
}

Поэтому для сравнения придумали специальную функцию. Её результат равен 0, если строки совпадают. Если результат отрицательный, первая строка находилась бы в словаре перед второй, и наоборот.

if (strcmp(string1, string2) == 0)
{
    printf("The same.\n");
}
else
{
    printf("Different.\n");
}

Не забываем освобождать выделенную память.

free(string2);

§ 8.2 Строковый ввод и вывод

Есть особое семейство функций, похожее на printf() и scanf(), но вывод (и ввод) осуществляется не в стандартный поток ввода-вывода, а в строку (из строки).

#define BUFFER_SIZE 256u
char buffer[BUFFER_SIZE];

sprintf(buffer, "%d", 84);

printf("%s", buffer);
int a = 0;
sscanf(buffer, "%d", &a);
14 июня 2018