Лекция 4.

Ввод/вывод


Работа с вводом информации из внешней памяти в оперативную память и выводом информации из оперативной памяти во внешнюю память реализована и помещена в библиотеку ввода/вывода.

Мы уже знаем, что функции перед их вызовом должны быть задекларированы. Декларации библиотечных функций ввода/вывод находятся в системном файле stdio.h. Таким образом, для декларирования функций ввода/вывода достаточно включить этот файл в свою программу:


Пример 1.


#include <stdio.h>

int main(void) {

printf(“Hello, World!\n”);

return 0;

}


Функции printf() и scanf() осуществляют вывод на консоль и ввод с клавиатуры.

Первым параметром этих функций является текстовая константа: символы в двойных кавычках.

Следующих параметров может быть сколь угодно много.


Пример 2.


#include <stdio.h>

int main(void) {

printf(“Input two numbers\n”);

scanf(“%d%d”, &n, &m);

printf(“%d * %d = %d\n”, n, m, n*m);

return 0;

}


Для функции printf() все параметры, начиная со второго, это любые выражения, в том числе значение переменных.

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

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

Для указания места, куда подставлять эти значения, используется символ %. Сразу после этого символа идет информация о формате: одна буква (d, f и пр.) для обозначения типа формата (целый десятичный, вещественное число и пр.) и опционально перед ней числа и другие символы, регулирующие точный формат.

Для функции scanf() все параметры, начиная со второго, - это адреса переменных. Такая разница объясняется тем, что функция scanf() возвращает в вызвавшую ее функцию множество прочитанных данных. Из прошлой лекции нам известно, что для возврата из функции более чем одного результата удобно использовать адреса переменных, куда функция (например, scanf()) положит эти данные.


Пример 3. Печать вещественнных чисел с заданнным количеством цифр после десятичной точки. Число d напечатается с тремя цифрами до десятичной точки, недостающие цифры будут дополнены нулями.


float f = 1.4;

double d = 28.15;

printf(“f: %.5f, d: %03.10lf\n”);


Результат работы программы из примера 3:


1.40000

028.1500000000


Работа с файлами

Работа с файлами реализована в C с тем же интерфейсом, что и стандартный ввод/вывод.

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

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

Функция fopen пробует получить требуемый доступ к файлу и если получилось, то заносит информацию о файле (дескриптор) в специальную таблицу в оперативной памяти компьютера, называемую таблицой дескрипторов, и возвращает адрес дескриптора в этой таблице.

Вся дальнейшая работа с этим файлом (чтение, запись, завершение работы) выполняется с использованием его дескриптора.


Пример 3. Вызов функции, начинающей работу с файлами.


FILE *IN, *OUT;

IN = fopen(“tmp.dat”, “r”);

OUT = fopen(“tmp.res”, “w”);


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


Пример 4. Проверка успеха выполнения функции fopen.


FILE *IN;

IN = fopen(“tmp.dat”, “r”);

if (IN == NULL) {

printf(“File not opened\n”);

return -1;

}


Принято для сравнения указателей (адресов) с нулем использовать не число 0, а имя NULL, чтобы подчеркнуть, что это не просто число, а указатель (в данном случае на дескриптор файла).


После того, как проверено, что функция fopen вернула не NULL, можно считать, что работа с файлом начата успешна(говорят, что «файл открыт»).

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

Ввод/вывод начинается с начала файла и происходит последовательно: после считывания или записи информации следующая операция чтения/записи будет выполняться сразу за считанной или записанной информацией.

Самые удобные функции для считывания/записи информации из файла — это fscanf() и fprintf(). С их помощью можно читать и записывать информацию различного формата.

Функция fscanf() возвращает число прочитанных объектов. Таким образом, всегда можно проверить, сработала ли она успешно, то есть удалось ли ей прочитать все элементы, которые требовалось.


Пример 5. Ввод из файла tmp.dat целых чисел в десятичной записи.


FILE *IN;

IN = fopen(“tmp.dat”, “r”);

if (IN == NULL) {

printf(“File not opened\n”);

return -1;

}

while (fscanf(IN, “%d”, &n) == 1) {

printf(“%d\n”, n);

}

fclose(IN);


Если в файле находится следующий текст (целые десятичные числа с разделителями пробел, запятая и конец строки):


1 2, 5

-1

8 10


то на экран будет выведена следующая информация:


1

2

5

-1

8

10