Ввод и вывод данных / Valentin Gubarev

Возможности для ввода и вывода данных не являются частью языка Си. Необходимые для ввода и вывода данных функции имеются в стандартной библиотеке и специфицированы в заголовочном файле stdio.h.

Библиотечные функции ввода и вывода точно определяются стандартом ANSI, таким образом, программы, которые при взаимодействии с системным окружением не выходят за рамки возможностей стандартной библиотеки являются кроссплатформенными на уровне компиляции.

Стандартный ввод и вывод

Текстовый поток состоит из последовательности строк. Каждая строка заканчивается символом новой строки.

Чтение одного символа из стандартного ввода (по умолчанию с клавиатуры) производится с помощью функции getchar().

int getchar();

В качестве результата каждого своего вызова функция getchar() возвращает следующий символ ввода или, если обнаружен конец файла, константу EOF (End Of File). Именованная константа EOF определена в stdio.h и обычно равна -1, однако не следует в программе вместо EOF использовать -1.

Запись одного символа в стандартный вывод (по умолчанию экран) производится с помощью функции putchar(int).

int putchar(int);

Вызов функции putchar(symbol) отправляет символ symbol в стандартный вывод (печатает на экране символ symbol) и возвращает значение symbol или, в случае ошибки, EOF.

Пример программы, получающей на входе последовательность различных символов и выводящей символы с кодом на единицу большую. Для окончания работы программы необходимо ввести пробел и нажать кнопку Enter. Код кнопки пробел - 0x20 (записан в шестнадцатеричной позиционной системе счисления). Вместо 0x20 можно было написать 32, а ещё лучше пробел выделенный апострофами - ‘ ‘.

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() {
    int c;
    while( ( c = getchar() ), c != 0x20 ) {
        if(c > 0x20)
            putchar(c+1);
    }
    return 0;
}

При нажатии на кнопки клавиатуры на экране отображаются те же символы, которые нажаты на клавиатуре - это не действие вышеописанной программы, нажмите на Enter и только после этого Вы увидите работу программы.

Например, введите abcd123 и нажмите Enter, на экране, кроме надписи abcd123 должна появится надпись bcde234 (результат работы вышеуказанной программы).

Пример программы, которая печатает только цифры.

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() {
    int c;
    while( ( c = getchar() ), c != 0x20 ) {
        if('0' <= c && c <= '9')
            putchar(c);
    }
    return 0;
}

Например, введите a9b2c1 и нажмите Enter, на экране, кроме надписи a9b2c1 должна появится надпись 921 (результат работы вышеуказанной программы).

Дело в том, что во многих библиотеках компиляторов эта функция реализуется таким образом, что она заполняет буфер ввода до тех пор, пока не будет нажата клавиша Enter, то есть реализуется построчно буферизированным способом.

В библиотеках большинства компиляторов в заголовочном файле <conio.h> имеется описание функций getch() и getche(), которые не используют буфер.

Для понимания разницы работы этих функций поочерёдно запустите программы с различными строчками, которые даны чуть ниже.

1
2
3
printf("%c", getch());
printf("%c", getche());
printf("%c", getchar());

Попробуйте при работе программы ввести надпись hello, с первой строчкой, получится ввести только h, после чего программа завершит свою работу, а на экране будет отображено h, это работа printf(). Со второй строчкой на экране увидим hh, так как getche() сама отображает символ на экране. С третьей же строчкой проблем с набором hello возникнуть не должно, но по нажатию на Enter, будет ещё выведено h, так как в буфере находится всё слово hello и первый символ - это h.

Форматный вывод

Для организации форматного вывода может быть использована функция printf().

int printf(char *format, ...)

Многоточие означает, что число и типы аргументов могут изменяться. Знак многоточие может стоять только в конце списка аргументов. Функция printf() возвращает количество записанных (напечатанных) символов.

Функция printf() использует свой первый аргумент (Си строку format), чтобы определить, сколько ещё ожидается аргументов и какого они будут типа.

Форматная строка содержит два вида объектов: обычные символы, которые копируются в выходной поток, и спецификации преобразования. Спецификации преобразования начинаются со знака % и заканчивается символом-спецификатором.

Между % и символом-спецификатором могут быть расположены (в указанном ниже порядке) следующие элементы:

Символы спецификаторы:

Ширину и точность можно специфицировать с помощью *, в этом случает величина берётся из следующего аргумента.

Шаблон спецификации преобразования.

[-][минимальная ширина поля][.точность][h | l][Символ-спецификатор]

Далее на каждой новой строке представлен пример, попробуйте определить, что будет выведено и проверьте правы ли Вы, набрав код и запустив программу на компьютере.

1
2
3
4
5
printf("%*.*f",8,3,12.123456789);
printf("\n%.*s",printf("%*.*f",8,3,12.123456789),"1234567890");
printf("\n%.*s",printf("%-*.*f",8,3,12.123456789),"1234567890");
printf("\n%10.*s",printf("%-*.*f",8,3,12.123456789),"1234567890");
printf("\n%-10.*s",printf("%-*.*f",8,3,12.123456789),"1234567890");

Теперь пример с применением %n

1
2
3
4
5
6
7
8
#include <stdio.h>
int main(void) {
    _set_printf_count_output(1);
    int count = 0;
    printf("%.2f%n\ncount = %d\n", 3.14, &count, count);
    printf("count = %d\n", count);
    return 0;
}

Для функций: scanf(), getc(), gets() и getchar(), а также функций printf(), putc() и puts() с помощью функции freopen() возможно перенаправление потоков в файл, а для функций: getch() и getche() нет, они определены в <conio.h> и предназначены для работы с клавиатурой.

Пример использования freopen()

1
2
3
freopen("first.txt", "rt", stdin);
char ch;
scanf("%c", &ch);

scanf("%c", &ch); в третьей строке не будет ожидать ввода с клавиатуры, а считает один символ из файла first.txt, который определён функцией freopen() в первой строке.

Лицензия Creative Commons
Code More Team - GitHub