Консольный ввод-вывод
При запуске программы на Си автоматически открываются пять потоков, основными из которых являются следующие:
Стандартный поток ввода stdin
Стандартный поток вывода stdout
Стандартный поток вывода сообщений об ошибках stderr
Стандартный поток ввода stdin по умолчанию соответствует клавиатуре, а потоки stdout и stderr - экрану монитора.
Для управления вводом-выводом с помощью этих потоков используются ряд функций:
getchar(): ввод с клавиатуры одного символа
putchar(): вывод на консоль одного символа
gets() / fgets(): ввод одной строки
puts(): вывод одной строки на консоль
scanf(): ввод с форматированием данных
printf(): вывод с форматированием данных
Функции printf и scanf уже рассматиривались ранее, поэтому посмотрим, как применять остальные функции.
Ввод и вывод символов
Для ввода одного символа с клавиатуры применяется функция getchar(), которая имеет следующий прототип:
1
int getchar(void);
В качестве результата функция возвращает числовой код введенного символа.
Для вывода отдельного символа на консоль предназначена функция putchar() со следующим прототипом:
1
int putchar(int c);
Выводимый символ в виде числового кода передается в putchar в качестве параметра, он же возвращается функцией.
Следует сказать, что на самом деле функции getchar() и putchar() полноценными функциями не являются, а определены как макросы в заголовочном файле stdio.h:
1
2
#define getchar() getc(stdin)
#define putchar(c) putc((c), stdout)
При использовании функции getchar следует учитывать, что при печати текста посредством клавиатуры в буфер операционной системы заносятся коды печатаемых символов, а сами символы отображаются на экране. Поучение программой введенного символа из буфера производится с помощью нажатия клавиши Enter.
И если буфер операционной системы не пуст, то при вызове функции getc() она получает очередной символ из буфера. Если же буфер пуст, то происходит чтение байта из потока ввода с помощью системной функции, название которой зависит от операционной системы.
При этом при нажатии клавиши Enter, в буфер также помещается код этой клавиши. То есть если мы введем один символ и нажмем на Enter, в буфере окажутся два числовых кода - введенного символа и клавиши Enter. И это надо учитывать при работе с функцией getchar. В частости, рассмотрим простой, но показательный пример:
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main(void)
{
printf("1");
getchar(); // ожидание ввода символа
printf("2");
getchar(); // ожидание ввода символа
printf("3");
return 0;
}
Сначала на экран выводится цифра 1, после чего функция getchar ожидает ввода символа. Если после ввода символа мы нажмем Enter, то в буфер будет помещены два числовых кода - введеного символа и клавиши Enter. Поэтому при втором вызове getchar эта функция считывает байт из буфера - то есть числовой код клавиши Enter.
Например, введем при первом вызове функции getchar символ "a", а затем Enter:
1a
23
Но если при каждом вызове getchar мы будем только нажимать клавишу Enter, тогда в буфер будет заноситься только код этой клавиши, и соответственно программа будет работать, как и ожидалось:
1
2
3
Применим функции getchar и putchar для ввода и вывода символов с клавиатуры:
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main(void)
{
int c;
while((c=getchar())!=EOF)
{
putchar(c);
}
return 0;
}
Функция getchar считывает числовой код символа, который потом выводится в функции putchar. Для вывода из программы необходимо ввести комбинацию клавиш Ctrl+C.
Ввод и вывод строк
Вывод строк и puts
Для вывода одной строки на консоль предназначена функция puts() со следующим прототипом:
1
int putchar(char *s);
В качестве параметра передается указатель на строку, а возвращаемым результатом функции является последний выведенный символ.
При этом функция puts() будет выводить символы переданной строки, пока не дойдет до нулевого символа '\0'. Если же выводимый массив символов не содержит этого символа, то результат программы неопределен. Например:
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main(void)
{
puts("Hello World"); // выводим строковый литерал
char* name = "Hello Metanit.com";
puts(name); // выводим значение переменной
return 0;
}
Консольный вывод:
Hello World
Hello Metanit.com
Ввод строк и fgets
Для ввода строки с клавиатуры применяется функция fgets(), которая имеет следующий прототип:
1
char *fgets(char *str, int n, FILE *stream);
В качестве первого параметра передается указатель на строку. Второй параметр указывает, сколько символов необходимо считать из потока в строку. Третий параметр указывает на поток ввода.
Например, считаем строку с консоли и затем выведем ее на консоль:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#define MAX 15
int main(void)
{
char name[MAX];
puts("Enter name:");
fgets(name, MAX, stdin);
printf("Your name: %s", name);
return 0;
}
Здесь функция fgets считывает не более 15 символов в строку name. Если будет введено больше символов, то fgets все равно считает не более 15 символов. Таким образом функция позволяет проверить количество считываемых символов и поэтому считается безопасной.
Пример работы программы:
Enter name:
Tom
Your name: Tom
Ввод строк и gets
Для ввода строки с клавиатуры также может применяться функция gets(), которая имеет следующий прототип:
1
char *gets(char *s);
Вводимые данные помещаются в массив, на который указывает указатель *s, передаваемый в функцию в качестве параметра. При успешном прочтении строки функция возвращает адрес этого массива s. А в случае ошибки возвращается значение NULL.
При вводе символов функция gets() завершает свою работу при вводе символа '\n', то есть при нажатии на клавишу Enter. Но вместо этого символа в строку записывается нулевой символ '\0', который и будет указывать на завершение строки. Однако поскольку эта функция не проверяет количество введенных символов, то она считается не безопасной. Поэтому при компиляции программы с этой функцией ряд компиляторов могут выдавать предупреждение.
Используем функции для ввода строки:
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
int main(void)
{
char name[20];
puts("Enter name:");
gets(name);
printf("Your name: %s", name);
return 0;
}
Данная программа работает также, как и в предыдущем примере с функцией fgets.