Строкой (строчкой) в языке Си называется массив типа
char
. Элементами маассива являются коды соответствующиx
символов.
Последним элементом массива является 0 — маркер конца строки.
Длиной строки называется количество ее букв, не включая маркер конца строки.
Предполагается, что одна буква кодируется одним элементом типа
char
, то есть кодировка содержит не более 255 букв. Программы на
Си могут некорректно работать с современными кодировками типа
UTF-8. Многобайтовые кодировки мы не рассматриваем.
Для хранения строки из n символов нужно выделить как минимум n+1 байт памяти.
Наличие маркера конца строки позволяет при передаче строки в функцию не передавать ее длину. Рассмотрим в качестве примера прототип и возможную реализацию функции вычисления длины строки.
int string_length(const char *s) {
int len = 0;
while(*s++) {
len++;
}
return len;
}
Во-первых, функция получает только адрес начала строки. Во-вторых,
заметим, что если в строке пропущен маркер конца строки, то
результат выполнения этой функции не определен, и ее вызов может
привести к ошибке сегментирования, если цикл while выйдет за
пределы памяти, отведенной операционной системой процессу.
Для вывода строк можно использовать функции семейства printf
(printf, fprintf, sprintf и т.п.). В строке формата нужно поставить %s
.
const char *str = "This is a string";
printf("The string is: '%s'\n", str);
Для ввода строк есть функция
char *fgets(char *s, int size, FILE *stream);
Параметр size
определяет максимальный размер строки, включая маркер конца строки.
Память для хранения строки должна быть выделена заранее.
Функции семейства scanf считывают их входного потока одно слово.
scanf("%s", str); /* ОПАСНО */
Либо с ограничением длины:
scanf("%12s", str); /* Будет записано не более 13 символов, включая 0. */
При работе со строками часто возникают следующие ошибоки.
char *s;
не достаточно. Нужно выделить память.)
s1 = s2;
. Если после этого изменить строку s2, то изменится и s1. Копировать нужно посимвольно.
Стандартная бибилиотека предоставляет набор функций для работы со строками.
Для работы с нми нужно подключить заголовочный файл #include <strings.h>
.
int strcmp(const char *s1, const char *s2);
Возвращает: отрицательное число, если s1 меньше s2, 0, если равны, и положительно число, если s1 больше s2.
int strncmp(const char *s1, const char *s2, size_t n);
char *stpcpy(char *dest, const char *src);
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
Возвращает адрес, где в строке haystack первый раз встречается строка needle. Если needle не встречается, то возвращается значене NULL
.
/*
** Чтение длинной строки.
**
** Функция считывает из текущей позиции файла f строчку сколь угодно
** большого размера. Символ перевода строки '\n' копируется в выходную
** строчку, если он был во входном фале.
** Память для хранения выходной строки динамически выделяется.
** Вызывающая функция должна освободить память вызовом free.
**
** Возвращаемое значение:
** адрес строки, если чтение прошло успешно
** NULL, если не удалось прочитать исходную строчку.
*/
char *read_long_string(FILE *f)
{
char buf[1024];
buf[0] = 0;
sprintf(stderr, "This is a prototype!\n");
char *s = fgets(buf, 1024, f);
if(s) {
int len = strlen(s);
char *result = malloc(len + 1);
strcpy(result, s);
return result;
}
return NULL;
}
int main() {
char *s = read_long_string(stdin);
// ....
free(s);
return 0;
}