Рефераты. Средства ввода-вывода в Си++

Приведем фрагмент программы, в котором используется функция fopen() для открытия файла по имени TEST.

FILE *fp;

fp = fopen("test", "w");

Следует сразу же указать на недостаточность такого кода в программе. Хотя приведенный код технически правильный, но его обычно пишут немного по-другому.

FILE *fp;

if ((fp = fopen("test", "w")==NUL)

{

printf("Ошибка при открытии файла.\n\r")"

exit(1);

}


Рис. 1


Этот метод помогает при открытии файла обнаружить любую ошибку.

Например, защиту от записи или полный диск. Причем, обнаружить еще до того, как программа попытается в этот файл что-то записать. Поэтому всегда нужно вначале получить подтверждение, что функция fopen() выполнилась успешно, и лишь затем выполнять c файлом другие операции. Ниже на рисунке 1 приведена небольшую часть программы, которая. подтверждает или не подтверждает открытие файла. Результаты работы указанной программы приведены на рисунке 2.


Рис. 2.

Потоковый ввод-вывод

 

На уровне потокового ввода-вывода обмен данными производится побайтно. Такой ввод-вывод возможен как для собственно устройств побайтового обмена (печатающее устройство, дисплей), так и для файлов на диске, хотя устройства внешней памяти, строго говоря, являются устройствами поблочного обмена, т.е. за одно обращение к устройству производится считывание или запись фиксированной порции данных. Чаще всего минимальной порцией данных, участвующей в обмене с внешней памятью, являются блоки в 512 байт или 1024 байта. При вводе с диска (при чтении из файла) данные помещаются в буфер операционной системы, а затем побайтно или определенными порциями передаются программе пользователя. При выводе данных в файл они накапливаются в буфере, а при заполнении буфера записываются в виде единого блока на диск за одно обращение к последнему. Буферы операционной системы реализуются в виде участков основной памяти. Поэтому пересылки между буферами ввода-вывода и выполняемой программой происходят достаточно быстро в отличие от реальных обменов с физическими устройствами.

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

При работе с потоком можно производить следующие действия:

·                          открывать и закрывать потоки (связывать указатели на потоки с конкретными файлами);

·                          вводить и выводить: символ, строку, форматированные данные, порцию данных произвольной длины;

·                          анализировать ошибки потокового ввода-вывода и условие достижения конца потока (конца файла);

·                          управлять буферизацией потока и размером буфера;

·                          получать и устанавливать указатель (индикатор) текущей позиции

При открытии потока могут возникнуть следующие ошибки: указанный файл, связанный с потоком, не найден (для режима "чтение"); диск заполнен или диск защищен от записи и т.п. Необходимо также отметить, что при выполнении функции fopen() происходит выделение динамической памяти. При её отсутствии устанавливается признак ошибки "Not enough memory" (недостаточно памяти). В перечисленных случаях указатель на поток приобретает значение NULL. Заметим, что указатель на поток в любом режиме, отличном от аварийного никогда не бывает равным NULL.

Приведем типичную последовательность операторов, которая используется при открытии файла, связанного с потоком:

if ((fp = fopen("t.txt","w")) == NULL)

perror("ошибка при открытии файла t.txt \n");

exit(0);

}

Где NULL - нулевой указатель, определенный в файле stdio.h.

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

int fclose (указатель_на_поток);

Открытый файл можно открыть повторно (например, для изменения режима работы с ним) только после того, как файл будет закрыт с помощью функции fclose().

Когда программа начинает выполняться, автоматически открываются пять потоков, из которых основными являются:

·                          стандартный поток ввода (на него ссылаются, используя предопределенный указатель на поток stdin);

·                          стандартный поток вывода (stdout);

·                          стандартный поток вывода сообщений об ошибках (stderr).

По умолчанию стандартному потоку ввода stdin ставится в соответствие клавиатура, а потокам stdout и stderr соответствует экран дисплея.

Одним из наиболее эффективных способов осуществления ввода-вывода одного символа является использование библиотечных функций getchar( ) и putchar(). Прототипы этих функций имеют следующий вид:

int getchar(void);

int putchar(int c);

Функция getchаr( ) осуществляет ввод одного символа. При обращении она возвращает в вызвавшую ее функцию один введенный символ.

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

Обратите внимание на то, что функция getchar( ) вводит очередной байт информации (символ) в виде значения типа int. Это сделано для того, чтобы гарантировать успешность распознавания ситуации "достигнут конец файла". Дело в том, что при чтении из файла с помощью функции getchar() может быть достигнут конец файла. В этом случае операционная система в ответ на попытку чтения символа передает функции getchar() значение EOF (End of File). Константа EOF определена в заголовочном файле stdio.h и в разных операционных системах имеет значение 0 или -1. Таким образом, функция getchar() должна иметь возможность прочитать из входного потока не только символ, но и целое значение. Именно с этой целью функция getchar( ) всегда возвращает значение типа int.

В случае ошибки при вводе функция getchar() также возвращает EOF.

При наборе текста на клавиатуре коды символов записываются во внутренний буфер операционной системы, Одновременно они отображаются (для визуального контроля) на экране дисплея. Набранные на клавиатуре символы можно редактировать (удалять и набирать новые). Фактический перенос символов из внутреннего буфера в программу происходит при нажатии клавиши . При этом код клавиши также заносится во внутренний буфер. Таким образом, при нажатии на (Клавишу 'А' и клавишу (завершение ввода) во внутреннем буфере оказываются: код символа 'А' и код клавиши . ) Об этом необходимо помнить, если вы рассчитываете на ввод функцией getchar() одиночного символа.

Приведём в пример программу копирования из стандартного ввода в стандартный вывод:

#include

int main()

{

int c;

while ((c=getchar())!=EOF)

Putchar(c);

return 0;

}

Для завершения приведенной выше программы копирования необходимо ввести с клавиатуры сигнал прерывания Ctrl+C.

Одной из наиболее популярных операций ввода-вывода является операция ввода-вывода строки символов. В библиотеку языка Си для обмена данными через Стандартные потоки ввода-вывода включены функции ввода-вывода строк gets() и puts(), которые удобно использовать при создании диалоговых систем. Прототипы этих функций имеют следующий вид:

char * gets (char * s);  /* Функция ввода */

int puts (char * s); /* Функция вывода */

Обе функции имеют только один аргумент - указатель s на массив символов. Бели строка прочитана удачно, функция gets( ) возвращает адрес того массива s, в который производился ввод строки. Если произошла ошибка, то возвращается NULL.

Функция puts() в случае успешного завершения возвращает последний выведенный символ, который всегда является символом ‘\n’. Если произошла ошибка, то возвращается EOF.

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


Для работы со стандартными потоками в режиме форматного ввода-вывода определены две функции:

printf( ) - форматный вывод;

scanf( ) - форматный ввод.

Прототип функции printf() имеет вид:

int printf(const char *format,...);

При обращении к функции printf() возможны две формы задания первого параметра:

int printf ( *форматная строка, список_аргументов);

int printf (указателъ_на_форматную_строку,. список_аргументов);

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

Возвращаемое значение функции printf() - число напечатанных символов; а в случае ошибки - отрицательное число.

Форматная_строка ограничена двойными кавычками и может включать произвольный текст, управляющие символы и спецификации преобразования данных. Текст и управляющие символы из форматной строки просто копируются в выходной поток. Форматная строка обычно размещается в списке фактических параметров функции, что соответствует первому варианту вызова функции printf(). Второй вариант предполагает, что первый фактический параметр - это указатель типа char *, a сама форматная строка определена в программе как обычная строковая константа или переменная.

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

Если аргументов недостаточно для данной форматной строки, то результат зависит от реализации (от операционной системы и от системы программирования). Если аргументов больше, чем указано в форматной строке, "лишние" аргументы игнорируются. Гарантируется, что при любом количестве параметров и любом их типе после выполнения функций printf() дальнейшее выполнение программы будет корректным.


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

 

% флаги ширина_поля. точностъ спецификатор

Символ % является признаком спецификации преобразования. В спецификации преобразования обязательными являются только два элемента: признак % и спецификатор.

Спецификатор     Тип аргумента     Формат вывода  

d                              int, char,unsigned        Десятичное целое со знаком

u                              int, char,unsigned        Десятичное целое без знака 

o                              int, char,unsigned        Восьмеричное целое без знака

x                              int, char,unsigned        Шестнадцатеричное целое без знака; при выводе используются символы “0..9a..f”

X                             int, char,unsigned        Шестнадцатеричное целое без знака; при выводе используются символы "0...9A...F”

f         double, float         Вещественное значение со знаком в виде:

Знак_числа dddd.dddd

где dddd - одна или более десятичных цифр. Количество цифр перед десятичной точкой зависит от величины выводимого числа, а количество цифр после десятичной точки зависит от требуемой точности. Знак числа при отсутствии модификатора '+' изображается только для отрицательного числа.

Форматный ввод из входного потока.


Форматный ввод из входного потока осуществляется функцией scanf(). Прототип функции scanf( ) имеет вид:

int scanf(const char * format, …);

При обращении к функции scanf() возможны две формы задания первого параметра:

int scanf ( форматная строка, список аргументов );

int scanf(указатель_на_форматную _строку, список_аргументов);

Функция scanf() читает последовательности кодов символов (байты) из входного потока и интерпретирует их в соответствии с форматной_строкой как целые числа, вещественные числа, одиночные символы, строки. В первом варианте вызова функции форматная строка размещается непосредственно в списке фактических параметров. Во втором варианте вызова предполагается, что первый фактический параметр - это указатель типа char *, адресующий собственно форматную строку. Форматная строка в этом случае должна быть определена в программе как обычная строковая константа или переменная.

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

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

Последовательность кодов символов, которую функция scanf() читает, из входного потока, как правило, состоит из полей (строк), разделенных символами промежутка или обобщенными пробельными символами. Поля просматриваются и вводятся функцией scanf() посимвольно. Ввод поля прекращается, если встретился пробельный символ или в спецификации преобразования точно указано количество вводимых символа.

Функция scanf() завершает работу, если исчерпана форматная строка. При успешном завершении scanf() возвращает количество преобразованных и введенных полей (точнее, количество объектов, получивших значения при вводе). Значение EOF возвращается при возникновении ситуации "конец файла"; значение -1 - при возникновении ошибки преобразования данных.

Рассмотрим форматную строку функции scanf(): "code: %d %*s %c %s"

Строка "code:" присутствует во входном потоке для контроля вводимых данных и поэтому указана в форматной строке. Спецификации преобразования задают следующие действия:

%d - ввод десятичного целого;

%*s - пропуск строки;

%с - ввод одиночного символа;

%s - ввод строки.

Приведем результаты работы программы для трех различных наборов входных данных.

1.Последовательность символов исходных данных:

code:    5    поле2    D   asd

Результат выполнения программы:

i=5    c=D    s=asd    ret=3

Значением переменной ret является код возврата функц»-scanf(). Число 3 говорит о том, что функция scanf() ввела данные без ошибки и было обработано 3 входных поля (строки "code:" и "поле2" пропускаются при вводе).

Заключение.


В данной работе были рассмотрены особенности операций ввода-вывода в языке програмирования Си/С++, в которых есть много общего. Рассмотрены понятия «функции» и «потока», их виды и особенности функционирования в языке программирования.

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

Литература


1.                  Подбельский В.В. Программирование на языке С. М.: Финансы и статистика, 1999.

2.                  В.В.Подбельский, С.С.Фомин «Язык Си++». – М.: Финансы и статистика, 2003.

3.                  Павловская Т.А., Щупак Ю.А. С/С++. Структур-ное программирование (практикум). – Спб.: Пи-тер, 2004.

4.                  Аляев Ю.А., Козлов О.А. Программирование. Pascal, C++, Visual Basic. М.: Финансы и стати-стика, 2004.

5.                  Гуденко Д., Петроченко Д. Сборник задач по программированию. – Спб.: Питер, 2003.

6.                  Культин Н. С/С++ в задачах и примерах.. БХВ – Петербург, 2004.

7.                  Фридман А., Кландер Л. И др. С/С++. Алгоритмы и примеры. М. Бином, 2003.


Страницы: 1, 2



2012 © Все права защищены
При использовании материалов активная ссылка на источник обязательна.