Лабораторные / Лр №10.Файлы / Теоретические замечания
.odtРабота с файлами
Работа с файлами имеет несколько особенностей. Во-первых, для чтения строки можно использовать функцию fscanf. Однако эта функция читает только одно слово и останавливается на первом пробеле. Поэтому функция fscanf применяется тогда, когда надо читать файл по словам. Вот пример чтения слова из открытого файла с указателем fp:
#include <stdio.h>
main()
{
char s[80];
FILE *fp;
fp = fopen ( "input.dat", "r" );
fscanf ( fp, "%s", s );
printf ( "Первое слово файла - %s", s );
fclose ( fp );
}
Если надо читать всю строку с пробелами, используют функцию fgets. Она принимает три параметра:
• имя символьной строки, в которую записать данные;
• максимальную длину этой строки; функция не допускает выхода за границы строки;
если строка в файле длиннее, чем можно записать в память, читается только начальная часть, а остальное – при следующих вызовах fgets;
• указатель на файл.
Если функция fgets не может прочитать строку из файла (например, если нет больше строк),то она возвращает в качестве результата специальное значение NULL. Это свойство можно использовать для обработки ошибок и прекращения ввода данных.
#include <stdio.h>
main()
{
char s[80];
FILE *fp;
fp = fopen ( "input.dat", "r" );
if ( NULL == fgets ( s, 80, fp ) )
printf ( "Не удалось прочитать строку" );
else
printf ( "Первая строка файла - %s", s );
fclose ( fp );
}
Функция fgets читает строку из файла, пока не случится одно из двух событий:
• встретится символ перехода на новую строку '\n';
• прочитано столько символов, что они заняли всю строку (с учетом последнего нуля), например, в нашем случае она остановится, если прочтет 79 символов.В конце строки будет поставлен символ '\0'. Кроме того, если был найден символ перехода на новую строку '\n', он сохраняется и в строке s.
Задача. В каждой строке файла input.dat заменить все буквы 'A' на 'Б' и вывести измененный текст в файл output.dat.
Обратите внимание, что в этой задаче файл может быть любой длины. Но мы можем обрабатывать строки последовательно одну за другой, так как для обработки одной строки не нужны предыдущие и следующие.
Для чтения из файла используем цикл while.Он заканчивает работу, если функция fgets вернет значение NULL, то есть все строки обработаны.
#include <stdio.h>
main()
{
char s[80];
int i;
FILE *fin, *fout;
fin = fopen ( "input.dat", "r" );
fout = fopen ( "output.dat", "w" );
while ( NULL != fgets ( s, 80, fin ) ) // читаем строку
{
i = 0; // начинаем с s[0]
while ( s[i] != '\0' ) { // пока не конец строки
if ( s[i] == 'А' ) s[i] = 'Б'; // меняем символ
i ++; // переходим к следующему символу
}
fprintf ( fout, "%s", s ); // выводим строку в файл
}
fclose ( fin );
fclose ( fout );
}
Обратите внимание, что мы не поставили символ перехода на новую строку при вызове функции fprintf. Это связано с тем, что при чтении функция fgets сохраняет символ '\n' в конце каждой строки (кроме последней), поэтому строки будут выведены в выходной файл так же, как они были записаны в исходном файле.
Файлы
Ввод и вывод символов
Описание функций ввода-вывода из стандартной библиотеки подключается директивой
#include <stdio.h>
int c = getchar(); – ввод символов.
putchar(char); – вывод символов.
> – перенаправление стандартного потока ввода.
< – перенаправление стандартного потока вывода.
| – конвейер программ.
Форматный вывод – printf(format, params)
Каждая спецификация преобразования начинается с символа % и заканчивается символом преобразования. Между % и символом преобразования могут находиться:
знак минус – выравнивание по левому краю
число – ширина поля для вывода (заполняющий символ ‘ ‘ или ’0′)
точка – отделяет ширину поля от точности
число – точность представления
Символ преобразования:
d – десятичная форма,
o – восьмеричная форма,
x – 16-ичная форма,
u – десятичное беззнаковое,
c – символ,
s – строка,
e – вещественное в показательной форме,
f – вещественное xxx.yyy,
g – вещественное, как e или f, что короче.
Форматный ввод – scanf(format, params)
Выполняет те же преобразования, что printf, но в обратном направлении.
Строка форматов может содержать:
пробельные символы – они игнорируются
обычные символы – предположительно совпадают с символами входного потока
спецификации преобразования – состоит из символа %, необязательного символа подавления присваивания *, необязательной ширины поля и символа преобразования.
Поле ввода определяется как строка символов, отличная от пробельных символов. Поле продолжается до первого пробельного символа или пока не исчерпана ширина поля.
void main()
{
int i;
char* s = (char*)malloc(32);
scanf("%d, %3s", &i, s);
}
Форматное преобразование в памяти
sscanf(input, format, params)
sprintf(output, format, params)
void main()
{
int i;
char* s = (char*)malloc(32);
char* input = "123,asdf";
sscanf(input, "%d, %3s", &i, s);
}
Доступ к файлам
Прежде чем считывать из некоторого файла или записывать в него, этот файл открывают с помощью функции fopen() из стандартной библиотеки.
Функция возвращает указатель на структуру с именем FILE.
FILE *file = fopen(file name, mode);
Если во время открытия файла происходит ошибка, функция возвращает NULL.
Допустимыми режимами являются: чтение “r”, запись “w” и добавление “a”.
+ означает, что файл уже существует.
c = getc(F) c = getchar()
putc(F*, c) putchar(c)
fscanf(F*,…) scanf(…)
fprintf(F*,…) printf(…)
fgets(…, F*) gets(…)
fputs(…, F*) fputs(…)
fclose(FILE*); – закрывает файл.
Пример. Построчный вывод файла на экран с нумерацией строк.
void main()
{
char *buf = (char*)calloc(sizeof(char), 100);
FILE *f = fopen("111.txt", "r");
int count = 0;
while (fgets(buf, 100, f) != NULL) {
printf("%d. %s", ++count, buf);
}
fclose(f);
}
fseek()
Для произвольного перемещения по файлу используется функция fseek() с тремя параметрами: указатель на структуру FILE, смещение и точка отсчета.
Указатели на стандартные файловые структуры
При запуске программы автоматически открываются три файла, которые снабжены определенными указателями файлов. Этими файлами являются стандартный ввод, стандартный вывод и стандартный вывод ошибок; соответствующие указатели файлов называются stdin, stdout и stderr.
Указатели являются константами, а не переменными, так что не пытайтесь им
что-либо присваивать.