Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Использование встроенного отладчика. 2 страница




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

 

pfinfile = fopen("input.dat","r");

 

Когда начинается выполнение приложения, автоматически открываются пять следующих потоков: стандартное устройство ввода (standard input — stdin), стандартное устройство вывода (standard output — stdout), стандартное устройство сообщений об ошибках (standard error — stderr), стандартное устройство печати (standard printer — stdprn) и стандартное вспомогательное устройство (standard auxiliary — stdaux).

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

Эти пять файловых указателей можно использовать во всех функциях, которые имеют в качестве параметра указатель на поток. Некоторые функции, например getchar() и putchar(), автоматически используют stdin или stdout. Поскольку указатели stdin, stdout, stderr, stdprn и stdaux являются константами, а не переменными, нельзя присвоить им новое значение указателя на поток.

 

7.21.2. Файлы.

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

 

/* расскажите, что находится в файле "test" */

#include <stdio.h>

void main()

{

FILE *in; /* описываю указатель на файл */

int ch;

if ((in = fopen("test.txt", "r"))!= NULL)

/* открываю test для чтения, проверяя, существует ли он */

/* указатель FILE ссылается теперь на test */

{

while ((ch = getc(in))!= EOF) /* получаю символ из in */

putc(ch, stdout); /* посылаю на стандартный вывод */

fclose(in); /* закрываю файл */

}

else

printf("I couldn't open file \"test\" \n");

}

 

Функцией fopen() управляют три основных параметра. Первый — имя файла, который следует открыть. Он является и первым аргументом fopen(); в нашем случае это " test".

Второй параметр [и второй аргумент fopen()] описывает, как должен использоваться файл. Вот три основных применения файла:

"r": файл нужно считать

"w*: файл нужно записать

"а": файл нужно дополнить

 

Некоторые системы предоставляют еще дополнительные возможности, но мы будем придерживаться этих. Заметим, что используемые нами коды являются строками, а не символьными константами; следовательно, они заключаются в двойные кавычки. При применении "r" открывается существующий файл. При двух других применениях тоже будет открываться существующий файл, но если такого файла нет, он будет создан.

Внимание: Если вы используете "w" для существующего файла, то старая версия его стирается, и ваша программа начинает на "чистом месте".

Третий параметр является указателем на файл; это значение возвращается функцией:

 

FILE *in;

in = fopen("test", "r");

 

Теперь in является указателем на файл "test". С этого момента программа ссылается на файл при помощи указателя in, а не по имени test.

Если вы очень сообразительны, то теперь можете задать такой вопрос: «Если fopen() возвращает указатель на ' FILE' в качестве аргумента, то почему мы не должны объявить fopen() как функцию указателя на ' FILE'?» Хороший вопрос. Ответ заключается в том, что это описание сделал для нас файл stdio.h, который содержит строку

 

FILE *fopen();

 

Есть еще один важный момент относительно функции fopen(), которую мы использовали. Если fopen() не способна открыть требуемый файл, она возвращает значение 'NULL' (определенное в stdio.h как 0). Почему она не смогла открыть файл? Вы можете попросить ее считать файл, который не существует. Вот почему мы имеем в программе строку

 

if ((in = fopen("test", "r"))!= NULL)

 

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

Закрыть файл проще.

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

 

/*

В данной программе на С показано, как объявлять и использовать

файлы для ввода и вывода. Программа считывает значение order_price

из файла customer.txt и вычисляет значение billing_price,

записываемое в файл billing.txt

*/

#include <stdio.h>

#define MIN_DISCOUNT 0.97

#define MAX_DISCOUNT 0.95

main ()

{

float forder_price, fbilling_price;

FILE *fin,*fout;

fin=fopen ("customer.txt", "r");

fout=fopen ("billing.txt", "w");

while (fscanf(fin,"%f",&forder_price)!= EOF) {

fprintf(fout,"Your order of \t\t$%8.2f\n", forder_price);

if (forder_price < 10000)

fbilling_price = forder_price * MIN_DISCOUNT;

else fbilling_price = forder_price * MAX_DISCOUNT;

fprintf(fout,"is discounted to \t$%8.2f.\n\n",

fbilling_price);

}

return(0);

}

 

Каждый файл в программе на С должен быть связан с некоторым указателем файла (file pointer). Указатель файла указывает на информацию, описывающую различные атрибуты файла, включая путь к файлу, его имя и статус. Указатель файла представляет из себя переменную-указатель типа FILE, описанную в stdio.h. В данном операторе, взятом из нашего примера, объявляется два файла *fin и *fout:

 

FILE *fin, *fout;

 

Следующие операторы программы открывают два различных потока и связывают каждый файл с соответствующим потоком:

 

fin=fopen ("a: \\customer.dat", "r");

fout=fopen("a:\\billing.dat", "w");

 

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

Второй параметр в функции fopen() — режим файла. Файлы могут открываться либо в текстовом, либо в двоичном режиме. При вводе в текстовом режиме большинство компиляторов С преобразуют последовательности типа "возврат каретки/перевод строки" в символы новой строки. При выводе — наоборот. Двоичные файлы такому преобразованию не подвергаются. В табл. 5.4 перечислены все возможные режимы файлов.

 

Таблица 5.4. Режимы файлов, возможные в С

 

Тип доступа Описание
a Открывается в режиме добавления. Если файл отсутствовал, он создается. Все операции записи добавляют информацию в конец файла. Указатель файла можно перемещать при помощи fseek() или rewind(); он всегда перемещается к концу файла перед выполнением любой операции записи.
a+ То же, что и выше, но также возможно чтение
r Открывается только для чтения, если файл отсутствует или не обнаружен, вызов open выдает ошибку
r+ Открывается для чтения и записи. Если файл отсутствует или не обнаружен, вызов open выдает ошибку
w Открывает пустой файл для записи. Если файл существует, его содержимое уничтожается.
w+ Открывает пустой файл для чтения записи. Если файл существует, его содержимое уничтожается.

 

Режимы г+, w+ и а+ разрешают чтение и запись. (Файл открывается для обновления.) При переходе от чтения к записи и наоборот не забывайте позиционировать указатель файла при помощи fsetpos(), fseek() или rewind()

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

 

/*

В данной программе на С показано, как объявлять и использовать

файлы для ввода и вывода. Программа считывает значение order_price

из файла customer.txt и вычисляет значение billing_price,

записываемое в файл billing.txt

*/

#include <stdio.h>

#include<iomanip.h>

#define MIN_DISCOUNT.97

#define MAX_DISCOUNT.95

main ()

{

float forder_price, fbilling_price;

FILE *fin,*fout;

fin=fopen ("customer.txt", "r");

fout=fopen ("billing.txt", "w");

while (fscanf(fin,"%f",&forder_price)!= EOF) {

fprintf(fout,"Your order of \t$%8.2f\n", forder_price);

if (forder_price < 10000)

fbilling_price = forder_price * MIN_DISCOUNT;

else fbilling_price = forder_price * MAX_DISCOUNT;

fprintf(fout,"is discounted to \t$%8.2f.\n\n", fbilling_price);

}

fclose(fin);

fclose(fout);

return(0);

}

 

Следующая программа выполняет те же функции, что и предыдущая, но на языке C++:

 

 

// В данной программе на C++ показано, как объявлять и использовать

// файлы для ввода и вывода. Программа считывает значение order price

// из файла customer.dat и вычисляет значение billing_price,

// записываемое в файл billing.dat

#include <fstream.h>

#include <stream.h>

#include <iomanip.h>

#define MIN_DISCOUNT 97

#define MAX_DISCOUNT 95

main()

{

float forder_price, fbilling_price;

lfstream fin ("a:\\customer.dat");

of stream fout ("a:\\billmg.dat");

{ fin >> forder_price;

while (!fin.eof()) {

fout << setiosflags(ios::fixed);

fout << "Your order of \t\t$" << setprecision \

<< setw(8) << forder_price << "\n";

if (forder_price < 10000)

fbilling_price = forder_price * MIN_DISCOUNT;

else fbilling_price = forder_price * MAX_DISCOUNT;

fout << "is discounted to \t$" << setprecision \

<< setw(8) << fbilling_price << ".\n\n";

fin >> forder_price;

}

fin. close ();

fout.close();

return(0);

}

 

Ввод/вывод дисковых файлов в C++ немного отличается от соответствующего ввода/вывода в С. В C++ имеются два средства в библиотеке потоков: объект streambuf и потоки. Одна и та же модель выполняет ввод/вывод как для клавиатуры и терминала, так и для диска. Одни и те же операторы и операции выполняются аналогичным образом. Это значительно упрощает программирование, в котором всегда были сложности и разночтения. Для упрощения дискового файлового ввода/вывода в библиотеке потоков описан объект filebuf, производный от стандартного типа streambuf. Так же как и родительский класс, объект filebuf управляет буфером, только в последнем случае буфер связан с дисковым файлом.

 

7.21.3. Текстовые файлы с буферизацией.

Функции fopen() и fclose() работают с текстовыми файлами с «буферизацией». Под буферизацией мы понимаем, что вводимые и выводимые данные запоминаются во временной области памяти, называемой буфером. Если буфер заполнился, содержимое его передается в блок, и процесс буферизации начинается снова. Одна из основных задач fclose() заключается в том, чтобы «освободить» любые частично заполненные буфера, если файл закрыт.

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

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

 

7.21.4. Переназначение ввода и вывода.

Современные операционные системы рассматривают клавиатуру и видео-дисплей как файлы. Это имеет смысл постольку, поскольку система может читать с клавиатуры так же, как она читает из дискового или ленточного файла; то же можно сказать и о видеодисплее.

Предположим, что программа читает с клавиатуры и пишет на дисплей. Допустим, что вы хотите, чтобы ввод шел из файла с именем SAMPLE.DAT. Ту же самую программу можно использовать, если указать системе заменить ввод с клавиатуры, рассматриваемой как файл, на ввод из другого файла, а именно — файла SAMPLE.DAT. Процесс изменения стандартного устройства ввода или вывода называется переназначением (или переадресацией — redirection) ввода или вывода. Переназначение ввода и вывода не представляет трудностей. Для переназначения ввода используется символ <, а для переназначения вывода >. Допустим, что выполняемая программа называется REDIRECT. Следующая системная команда запускает программу REDIRECT и использует для ввода вместо клавиатуры файл SAMPLE.DAT:

 

redirect < sample.dat

 

В следующей команде переназначаются и ввод (SAMPLE.DAT), и вывод (SAMPLE.BAK):

 

redirect < sample.dat > sample.bak

 

Последняя команда переназначает только вывод (SAMPLE.BAK):

 

redirect > sample.bak

 

Заметим, однако, что стандартный файл ошибок STDERR переназначать нельзя.

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

Для того чтобы соединить стандартный вывод одной программы со стандартным вводом другой программы, нужно назначить между ними конвейерную пересылку при помощи символа вертикальной черты "|". Следовательно, для связи стандартного вывода программы PROCESS 1 со стандартным вводом программы PROCESS2 достаточно указать:

 

Process1 | process2

 

Операционная система обеспечит все операции физической пересылки данных с выхода PROCESS 1 на вход PROCESS2.

 

7.21.5. Изменение буфера потока.

По умолчанию все файлы, открытые при помощи потоковых функций (stdin(), stdout() и stdprn()), буферизируются. Исключение составляют открытые потоки stderr и stdaux, которые по умолчанию не буферизируются, кроме случаев, когда они используются с группой функций printf() или scanf() — тогда им назначается временный буфер. Можно задать буферизацию потоков stderr и stdaux при помощи функций setbuf() или setvbuf(). Потоки stdin, stdout и stdprn очищаются автоматически при их заполнении. При помощи двух функций setbuf() и setvbuf() можно сделать буферизированный поток небуферизированным и наоборот. Обращаем внимание на то, что буферы, выделяемые системой, недоступны для пользователя, а буферы, которые назначаются при помощи функций setbuf() и setvbuf(), именуются пользователем, и с ними можно работать как с переменными. Буферы потоков, определяемые пользователем, очень полезны для проверки ввода и вывода до того, как возникнут какие-либо системные ошибки.

Можно назначить буфер любого размера; при использовании функции setbuf() размер определяется константой BUFSIZ, описанной в файле stdio.h. Синтаксис функции setbuf() выглядит так:

 

void setbuf(FILE *stream, char *buffer);

 

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

 

/*

Программа на С, демонстрирующая описание и назначение буфера

потоку stderr

*/

#include "stdafx.h"

#include "E:\LECTURE\AlgorithmProgramming\AlgorithmProgramming 02\Universal_HederFile.h"

 

void StopWait(void);

 

char cmyoutputbuffer[BUFSIZ];

main(void)

{

/* связь буфера с небуферизированным выходным потоком */

setbuf(stderr, cmyoutputbuffer); /* строка, которую нужно */ /*ЗАКАМЕНТИРУЙ для 2 варианта*/

/* заполнение буфера выходного потока */

fputs("Sample output inserted into the\n",stderr); /*"Пример вывода в" */

fputs("output stream buffer.\n",stderr); /* "буфер выходного потока." */

/* вывод буфера выходного потока */

fflush(stderr);

 

StopWait(); /* Wait a little */

return (0);

}

 

Попробуйте запустить программу второй раз, закомментировав оператор setbuf(). В этом случае программа не будет связывать буфер с stderr. Вы увидите различие после запуска программы? Когда stderr не буферизируется, встроенный отладчик выдает сообщение каждого оператора fputs() сразу же после выполнения оператора.

В следующей программе используется функция setvbuf(); ее синтаксис выглядит следующим образом:

 

int setvbuf (FILE *stream, char *buffer, int buftype, size_t bufsize);

 

В этом примере размер буфера задается явно, а не при помощи константы BUFSIZ, описанной в файле stdio.h:

 

/*

Программа на С, демонстрирующая использование функции setvbuf()

*/

#include "stdafx.h"

#include "E:\LECTURE\AlgorithmProgramming\Universal_HederFile.h"

void StopWait(void);

 

#define MYBUFSIZ 512

 

main (void)

{

char ichar, cmybuffer[MYBUFSIZ];

FILE *pfinfile, *pfoutfile;

pfinfile = fopen("E:\\LECTURE\\AlgorithmProgramming\\sample.in", "r");

pfoutfile = fopen("E:\\LECTURE\\AlgorithmProgramming\\sample.out", "w");

if (setvbuf(pfinfile, cmybuffer, _IOFBF, MYBUFSIZ)!= 0)

printf("pfinfile buffer allocation error\n"); /* ошибка назначения */

else /* буфера */

printf("pfinfile buffer created\n"); /* буфер создан */

if (setvbuf(pfoutfile, NULL, _IOLBF, 132)!= 0)

printf("pfoutfile buffer allocation error\n"); /* ошибка назначения*/

else

/* буфера */

printf("pfoutfile buffer created\n");

/* буфер создан */

while(fscanf(pfinfile,"%c",&ichar)!= EOF)

fprintf(pfoutfile,"%c",ichar);

fclose(pfinfile);

fclose(pfoutfile);

 

StopWait(); /* Wait a little */

return (0);

}

 

В программе создается доступный пользователю буфер, на который указывает pfinfile, и автоматически выделенный (malloc()) буфер, на который указывает pfoutfile. Последний из двух буферов описан как buftype, _IOLBF или строчный буфер. Другие опции, описанные в файле stdio.h: _IOFBF — полная буферизация и _IONBF — отсутствие буферизации. Напоминаем, что при использовании функций setbuf() и setvbuf() вместо автоматически выделяемого буфера для ввода/вывода используется buffer, назначенный пользователем. Если в случае использования setbuf() пара-метр buffer равен null, то ввод/вывод будет небуферизированным. В противном случае он буферизируется полностью.

Если в случае использования setvbuf() параметр buffer равен null, то буфер выделяется при помощи функции malloc(). При создании buffer функция setvbof() использует параметр bufsize, который определяет количество выделяемой и автоматически освобождаемой при закрытии памяти.

 

7.21.6. Закрытие потоков.

Две функции fclose() и fcloseall() используются для закрытия потока или всех потоков, соответственно. Функция fclose() закрывает отдельный файл, а функция fcloseall() закрывает все открытые потоки, за исключением stdin, stdout, stderr, stdprn и stdaux. Однако, если ваша программа не закрывает поток явно, то он закрывается автоматически по ее завершению. Поскольку количество потоков, открытых одновременно, ограничено, то желательно закрывать поток по окончанию работы с ним.

Наш пример показывает, как закрывать файл:

 

fclose(in);

 

Просто используйте функцию fclose(). Заметим, что аргументом ее является in, указатель на файл, а не test, имя файла.

Для программы, более серьезной, чем эта, следовало бы посмотреть, успешно ли закрыт файл. Функция fclose() возвращает значение 0, если файл закрыт успешно, и — 1 в противном случае.

 

7.22. Низкоуровневый ввод и вывод в С.

В следующем списке перечислены наиболее часто используемые в про-граммах функции низкоуровневого ввода и вывода:

 

Функция Описание
close() Закрывает дисковый файл
lseek() Поиск указанного байта в файле
open() Открывает дисковый файл
read() Читает данные в буфер
unlink() Удаляет файл из подкаталога
write() Записывает буфер данных

 

Функции низкоуровневого ввода и вывода не буферизируют и не форматируют данные. Доступ к файлам, открываемых функциями нижнего уровня, осуществляется при помощи описателя файла (handle — целое число, используемое операционной системой для обращения к файлу). Для открытия файлов используется функция ореn(). Для открытия файла с атрибутами совместного использования (sharing) можно использовать макрос sopen().

Низкоуровневые функции отличаются от своих аналогов — потоковых функций — тем, что они не требуют включения заголовочного файла stdio.h. Однако, могут быть полезны некоторые часто используемые константы, предопределенные в stdio.h: например, EOF и NULL. Объявления низкоуровневых функций дается в заголовочном файле io.h.

Первоначально данная система дискового ввода/вывода была создана для операционной системы UNIX. Поскольку комитет по стандарту ANSI С решил не стандартизовывать эту UNIX-подобную систему небуферизированного, низкоуровневого ввода/вывода, то ее нельзя рекомендовать для дальнейшего использования. Для всех новых разработок рекомендуется использовать стандартизованную систему буферизированного ввода/вывода.

 

7.23. Ввод и вывод символов.

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

 

7.23.1. Использование функций getc(), putc(), fgetc() и fputc().

Две функции getc() и putc() работают аналогично функциям getchar() и putchar(). Разница заключается в том, что вы должны сообщить новичкам, какой файл следует использовать. Таким образом, наш «старый дружище»

 

ch = getchar();

 

предназначен для получения символа от стандартного ввода, а

 

ch = getc(in);

 

— для получения символа от файла, на который указывает in. Аналогично функция

 

putc(ch, out);

 

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

 

putc(ch, stdout);

 

где stdout является указателем на стандартный вывод. Таким образом, этот оператор эквивалентен

 

putchar(ch);

 

Действительно, оператор putchar(ch) определен директивой #define так же как функция putc(ch, stdout) определена в файле stdio.h. Этот ужасный файл к тому же определяет в директиве #define указатели stdout и stdin на стандартный вывод и стандартный ввод системы.

Наиболее общими из всех функций ввода/вывода являются те, которые работают с отдельными символами. Функция getc() вводит один символ из указанного файлового потока:

 

int ic;

ic = getc(stdin);

 

Символ вводится при указании имени функции getc(), и затем возвращаемое значение присваивается переменной ic. Если же вас удивит, почему переменная ic не имеет тип char, то это объясняется тем, что функция getc() согласно прототипу возвращает тип int. Это нужно для того, чтобы можно было иметь системно-зависимый размер указателя конца файла, который может не совпадать с размером отдельного байта типа char.

Функция getc() преобразует целое число в беззнаковый символ. Использование беззнакового символа вместо целого числа гарантирует, что ASCII-символы, имеющие значение > 127, не будут представляться как отрицательные значения. Следовательно, отрицательные значения можно использовать для представления нестандартных ситуаций, например, ошибок и конца входного файла. К примеру: конец файла обычно представляется значением -1, хотя в стандарте ANSI С записано, что только константа EOF может иметь некоторое отрицательное значение.

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

Дополнением к функции getc() служит putc(). Функция putc() выдает один символ в файловый поток, представленный заданным указателем файла. Для вывода введенного выше символа на стандартное устройство вывода используется следующий оператор:

 

putc(ic,stdout);

 

Функция getc() обычно буферизируется, и когда приложение запрашивает символ, управление не передается программе до тех пор, пока в стандартном входном файловом потоке не будет введен символ возврата каретки. Все символы, введенные до символа возврата каретки, хранятся в буфере и передаются последовательно в программу, которая повторно вызывает функцию getc() до тех пор, пока буфер не опустеет. После того, как при помощи getc() символ возврата каретки передан в программу, следующий запрос символов вызывает накопление символов в буфере до тех пор, пока опять не будет введен символ возврата каретки. Это означает, что функцию getc() нельзя использовать для обработки одиночных клавиш, когда не требуется дополнительного нажатия клавиши возврата каретки. И одно последнее замечание: на самом деле getc() и putc() являются не истинными функциями, а макросами. Функции fgetc() и fputс() идентичны их аналогам макросам getc() и putc().

 

1.23.1.1. Простая программа сжатия файла.

В нашем примере имя файла, который следовало открыть, было записано в программе. Мы не обязаны считаться с этим ограничением. Используя аргументы командной строки, можно сообщить нашей программе имя файла, который хотим считать. В нашем следующем примере так и происходит. С помощью, примитивного приема сжимается содержимое — остается только каждый третий символ. Наконец, сжатая версия размещается в новый файл, имя которого состоит из старого имени с добавкой.red (сокращение слова reduced). Обычно весьма важны первый и последний элементы (аргумент командной строки и добавка к имени файла). Само же сжатие имеет более ограниченное применение, но, как вы увидите, им можно пользоваться.

 

/* сожмите ваши файлы в 2—3 раза! */

 

#include <stdio.h>

#include<string.h>

void main(int argc, char *argv[])

{

FILE *in, *out; /* описывает два указателя типа FILE */




Поделиться с друзьями:


Дата добавления: 2015-01-03; Просмотров: 719; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.167 сек.