Смекни!
smekni.com

Организация ввода-вывода (стр. 2 из 3)

# include <conio.h>

#include <string.h>

void main()

{

char c; int i; long 1; float f; double d; long double 1d;

unsigned int ui;

int Age; char str[10]; char*pc;

clrscr();

рrintf("&bsol;nВведите символ с=");

fflush(stdin); scanf("%c", &c);

printf("Введено с - %c", c);

printf("&bsol;nВведите через пробел целое и длинное целое"); fflush(stdin); int j=scanf("%d %ld", &i, &1);

printf("Введено %d аргументов:i = %i, 1 = %ld", j, i, 1 ) ;

printf("&bsol;nВведите беззнаковое целое");

fflush(stdin); scanf("%u", &ui);

printf("Введено ui = %u", ui);

printf("&bsol;nВведите через запятую вещ.числа float, double и&bsol;

long double&bsol;n");

fflush(stdin); scanf("%f,%lf,%Lf", & f, &d, &ld); //фиксир.&bsol;

//или плав. точка

printf("&bsol;Введено float = %g, double = %g, long double =&bsol;

%Lg",f,d,ld);

printf("&bsol;nВведите строку&bsol;n");

fflush(stdin); scanf("%10s", str); //фиксир. или плав. точка

printf("Введена строка %s", str);

printf("&bsol;nВведите адрес ячейки&bsol;n" );

fflush(stdin); scanf("%Fp", &pc); //фиксир. или плав. точка

printf("Введен адрес %Fp, содержимое ячейки по этому&bsol;

адресу %с", рс, *рс );

do

{

fflush(stdin);

printf("&bsol;nВведите возраст:");

}

while( scanf("%d", &Age) != 1 || 0 > Age || Age > 100);

fflush(stdin);

printf("&bsol;nВозраст = %d", Age);

if(!getch())getch();

}

Пример 4.

Найти первое целое число в текстовом файле.

#include <stdio.h>

void main()

{

char str[1000];

int i;

FILE *fp = fopen("ex.txt", "w+"); // Проверка опущена!

fputs("Год 1997 - число простое", fp);

rewind(fp);

fscanf(fp, "%[^0-9]%i", str, &i);

printf("&bsol;nПредыдущие символы :%s&bsol;nпeрвoe число = %i",

str, i);

}

4. Вопросы и ответы

Вопрос. Как правильно "заморозить" экран?

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

getch();

Он нормально сработает, если "разморозить" экран нажатием клавиши, имеющей однобайтовый ascii-код. Это -такие клавиши, как Esc, Enter, Tab, буквы, цифры основной клавиатуры, и т.д.. Функция getch() считывает этот код, и программа продолжается. Но при нажатии некоторых других клавиш в буфер ввода-вывода с клавиатуры записываются два числа: 0 и расширенный код, совпадающий, как правило, со scan-кодом клавиши. Функция getch() считает 0, программа продолжится, а при последующем вызове getch() будет считан оставшийся, ненужный scan-код. Даже если getch() стоял в конце программы, то при повторном запуске программы буфер ввода-вывода с клавиатуры не будет очищен, getch() считает scan-код и программа не "заморозится". Таким образом, программа будет приостанавливаться через раз ! Правильнее будет вставить строку

if( !getch()) getch();

Другой вариант - ожидание в бесконечном цикле нажатия клавиши

while( !kbhit());

Он подходит только в конце программы, т.к. дальнейший вызов getch() считает случайно нажатую клавишу.

Вопрос. Как правильно использовать scanf при вводе?

Ответ. Допустим нужно ввести с клавиатуры возраст человека в переменную Age типа int.

do

{

fflush(stdin);

printf("&bsol;nВведите возраст:");

}

while(scanf("%d", &Age) != 1);

fflush(stdin);

printf("&bsol;nВозраст = %d", Age); //Отладочная проверка

В реальной программе желательно произвести проверку на осмысленность введенного значения. В данном случае, вероятно, 0 <= Age <= 100. Тогда условие в цикле while может принять вид

while( scanf("%d", & Age) != 1|| 0 > Age || Age > 100);

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

5. Обзор функций ввода-вывода

Таблица 7

Назначение Имя функции С каким работает потоком Особенности
Файл stdin/ stdout Консоль
1.Ввод символа getc, fgets X X - - - - макро, эхо функция, эхо
getchar, fgetchar - - X X - - макро, Enter функция, Enter
getch getche - - - - X X без эха, без Enter эхо, без Enter
kbhit ungetc ungetch - X - - - - X - X
2.Вывод символа putc putchar putch X - - - X - - - X
З.Ввод строки fgets gets cgets X - - - X - - - X с проверкой без проверки с проверкой
4. Вывод строки fputs puts cputs X - - - X - - - X без CR/LF cCR/LF без CR/LF
5.Форматный ввод fscanf scanf cscanf sscanf X - - - - X - - - - X - ввод из строки
6.Форматный вывод fprintf printf cprintf sprintf X - - - - X - - - - X - Вывод в строку

Замечания:

1. Под консолью понимается клавиатура при вводе и дисплей (или монитор) при выводе информации.

2. По умолчанию под стандартным вводом stdin понимается ввод с клавиатуры, под стандартным выводом stdout понимаетсявывод на монитор. Кроме них, существуют другие стандартные потоки:

- stderr - устройство стандартного вывода ошибок (монитор),

- stdaux - вспомогательное устройство (последовательный
com-порт)

- stdprn - принтер (параллельный 1tp-порт) Потоки stdin/stdout нельзя легально перенаправить программным способом в файл, т. к. они являются макроопределениями. Но перенаправление можно осу ществить с помощью команды DOS >. Например,

hello.exe > ex.txt

В этом случае все, что шло в поток stdout, пойдет в файл ex.txt.

Например,

#include <stdio.h>

#include <conio.h>

#include <mem.h>

void main()

{

clrscr();

FILE *fp = fopen("exl.txt", "w+");

if(fp = NULL)

{

рerrоr("Ошибка при открытии файла"); // вывод в stderr return;

};

FILE *pbuf=stdin; int с = getc(stdin);

fclose(fp);

}

Функция fgetc и макрокоманда getc

Прототипы:

int fgetc(FILE *stream);

int getc(FILE *stream);

Возвращает: символ, расширенный до int без продолжения знака. В случае ошибки или конца файла возвращает EOF ( = -1 = 0xFFFF).

Описание. Считывает очередной символ из входного потока и увеличивает указатель текущего положения (СР - current position) на 1. При вводе с клавиатуры (stream=stdin) выполняется после нажатия клавиши Enter. Макрокоманда getc полностью аналогична функции fgetc. В файле stdio.h определена, как

#define getc(f) ((--((f)->level) >= 0) ? (unsigned char)(*(f)-->curp++) &bsol; :_fgetc (f))

Разберите синтаксис этого макроса !

Хотя getc и fgetc аналогичны, но лучше пользоваться макросом по следующей причине. Чтение из файла происходит блоками по 256b, 512b и т.д. После обработки одного блока в ОЗУ с диска считывается следующий блок. Макрос работает с текущим блоком напрямую, как видно из определения, и обращается к функции fgetc только после обработки этого блока. Функция fgetc также работает с блоком в ОЗУ, но каждое обращение к нему реализуется через вызов функции. Таким образом, использование getc увеличивает скорость за счет увеличения кода. Использование fgetc уменьшает код ценой уменьшения скорости.

Функция fgetchar и макрокоманда getchar

Прототипы: int fgetchar(void);

int getchar(void);

Возвращает : символ, расширенный до int без продолжения знака. В случае ошибки или конца файла возвращает EOF. Описание. Считывает очередной символ из стандартного входного потока и увеличивает СР на 1. Поток stdin, как и любой открытый файл, имеет буфер с размером по умолчанию 512b. Функция выполняется после нажатия клавиши Enter, после чего вводит 1 символ. Остальные введенные символы остаются в буфере, ожидая своей участи. Макрос getchar аналогичен функции fgetchar.

Функции getch и getche

Прототипы: int getch(void);

int getche(void);

Возвращают: символ, расширенный до int без продолжения знака.

Описание. Функция getch выводит символ на монитор, getche - не выводит. Функции имеют буфер на два символа: в случае нажатия

клавиши с расширенным кодом туда записывается 0 и scan-код нажатой клавиши. Не ожидают нажатия Enter. Буфер не очищается даже при повторном запуске программы.

Функция kbhit

Прототип: int kbhit(void);

Возвращает : 1, если к моменту вызова функции была нажата, но не обработана какая-нибудь клавиша; 0-в противном случае.

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

Функция ungetc

Прототип: int ungetc(int d,FILE*stream);

Возвращает: символ d, посланный обратно во входной поток stream, и EOF в случае ошибки.

Описание. Выталкивает символ d обратно во входной поток stream. Вернуть можно только один символ. Следующее чтение из потока вернет символ d. Символ с расширенным кодом вернуть не удастся.

Функция ungetch

Прототип: int ungetch(int d);

Описание. Аналогична ungetc, но выталкивает символ d обратно в буфер клавиатуры.

Функция fgets

Прототип: char *fgets(char *target, int n, FILE * stream); Описание. Вводит из stream не более n символов в строку по адресу target. Ввод заканчивается при встрече символа &bsol;n. Возвращает target при успешном вводе и NULL при встрече конца файла или в случае ошибки.

Функция gets

Прототип: char *gets(char *target);

Описание. Вводит из stdin строку по адресу target. Число вводимых символов не ограничено. В остальном похожа на fgets.

Функция cgets

Прототип: char *cgets(char *target);

Описание. Читает строку из консоли. str[0] должно содержать максимальную длину вводимой строки. По окончании str[l] содержит число реально введенных символов. Введенная строка начинается с элемента str[2]. Для перехода на новую строку в формат нужно вставить два символа: &bsol;n&bsol;r. Возвращает начало введенной строки str[2].

Функция fputs

Прототип : int fputs(const char *s, FILE *stream);

Описание. Записывает строку в поток. Возвращает последний записанный символ.

Функция puts

Прототип: int puts(const char *s);

Описание. Записывает строку в поток stdout. Возвращает последний записанный символ.