Лекция 8. Посимвольный ввод-вывод. Строки

Символы

Символ в языке C представляет собой число типа char, используемое для хранения кода символа в определённой кодировке. Для облегчения работы с символами существуют так называемые символьные константы, которые компилятор заменяет на числа-коды соответствующих символов.

Примеры символьных констант:

'A' .. 'Z'
'a' .. 'z'
'0' .. '9'
':' ',' '"'
'\n' '\t' '\''
'\0'

Все эти обозначения описывают один символ, несмотря на то, что некоторые спецсимволы могут записываться двумя символами в исходном коде, например ‘\n’.

Код ‘\0’ называется символом конца строки (не путать с символом перевода строки) и имеет специальное назначение, которое мы обсудим далее.

char c = 'A';
printf("view = %c, code = %d\n", c, c);
// выведет строку "view = A, code = 65\n"

Таким образом, можно выводить сами символы по формату %c и их числовые коды по формату %d.

Посимвольный ввод-вывод

Пример программы, подсчитывающей количество символов, введённых пользователем с клавиатуры. Окончание ввода обозначается в Linux комбинацие клавиш Ctlr+d, в консоли Windows – комбинацией Ctrl+z Enter.

Для посимвольного ввода мы используем фукнцию getchar, которая возвращает прочитанный символ как число типа int. Это кажется немного странным, ведь для считывания одного символа нам необходим все лишь char, а не int. Но это легко объяснить, если принять во внимание, что кромер 256 настоящих символов, которые могут встретиться во вводе с клавиатуры, getchar возвращает ещё один псевдосимвол EOF, обозначающий концев ввода (EOF – end of file). Так как в char он уже не помещается, тип результата getchar Керниган и Ритчи расширили до int.

#include <stdio.h>

int main()
{
    int c;
    int count = 0;
    // Обратите внимание на дополнительные скобки вокруг присваивания,
    // они обязательны, так как у = приоритет меньше, чем у !=,
    // и без скобок != выполнится первым.
    while((c = getchar()) != EOF) {
        ++count;
    }
    printf("Character count: %d\n", count);
    return 0;
}

Строки

Строки в C – это массивы символов (целых чисел типа char). Конец строки обозначается символом ‘\0’.

char str[200];    // Строка длиной от 0 до 199 символов. 1 символ расходуется на замыкающий '\0'.
str[0] = 'h';
str[1] = 'e';
str[2] = str[3] = 'l';
str[4] = 'o';
str[5] = '\0';    // символ конца строки.

str[6] = 'A'; // Не имеет ни какого значения, так как идёт после символа конца строки.

// Рассмотрим несколько способов вывести строку. Способ №1, вывести посимвольно вручную:

int i;
for (i = 0; str[i] != '\0'; ++i) {
    printf("%c", str[i]);
}

// Второй способ заключается в передаче строки в функцию printf вместе с форматом %s.
// Функция printf в этом случае сама внутри себя пройдёт циклом по строке
// и выведет все её символы, не включая '\0'.

printf("%s", str); // выведет "hello"

// Заметим, что в обоих случаях не будет выведен ни символ конца строки,
// ни символы, хранящиеся после него.

// Если мы передвинем символ конца строки ближе к началу строки,
// это приведёт к тому, что оба метода выведут "he".

str[2] = '\0';
printf("%s", str);   // Выведет "he"

Стандартные функции для работы со строками

В стандартной библиотеке C уже есть несколько функций для работы со строками:

char str[200];

scanf("%s", str);   // Обратите внимание: для строк & в scanf не нужен.

int len = strlen(str);   // Узнали длину введённой строки.

strcpy(str, "hello, world");    // Скопировали в str строку "hello, world", включая завершающий '\0'.

// К сожалению, функция strcpy не всегда безопасна, так как не всегда мы можем гарантировать,
// что в строке-приёмнике будет достаточно место, чтобы вместить копию строки. В этом случае
// можно использовать strncpy, которой нужно передать дополнительный параметр-размер
// строки-приёмника.

char str2[200];
strncpy(str2, str, 200); // Будет скопировано не более 199 символов, на конце всегда будет '\0', даже
                         // если строка будет скопирована не целиком.

Инициализация строк

char str[10] = "hello"; // В качестве инициализирующего значения может стоять только строковая константа

приведённый выше пример выделит память из 10 символов, и скопирует в строку 6 символов hello0 После этих символов в строке str будет “мусор”.