
техпрог / Comp-Sci-12a
.pdf
Материалы к лекции 12
Объектно-ориентированное программирование
Файловый ввод-вывод в C и C++
Схема работы с файлами на языке C
Файлы представляют собой области памяти на внешнем носителе и могут использоваться для долговременного хранения информации. Файлы имеют имена и организованы в иерархическую древовидную структуру. В системах MS DOS и UNIX файлы не имеют предопределенной структуры и являются просто линейными массивами байт. Доступ к элементам файла осуществляется последовательно и происходит в так называемой ―позиции чтения-записи‖, которая автоматически продвигается при операциях чтениязаписи.
Системные вызовы работаю с файлами как с неструктурированным массивом байт, что не всегда удобно при программировании задач, ориентированных на обработку текста.
В языке C имеется специальная библиотека функций stdio – стандартная библиотека ввода-вывода (standard input/output library).
Схема работы с файлами с помощью этой библиотеки следующая.
1.Каждый открытый файл должен иметь указатель типа FILE, используемый для ссылок на файл. Функции C работают не с именами файлов, а с указателями на файл.
2.С помощью функции fopen() указатель на файл связывается с физическим файлом на диске и указывается режим открытия файла.
3.После выполнения операция с файлом, необходимо вызвать функцию закрытия файла fclose().
Как записать информацию в текстовый файл – простой пример
Пример. Запись в файл (как принято в C).
// file1.cpp : Пример записи в текстовый файл
//
#include "stdafx.h" #include <stdio.h> #include <iostream> using namespace std;
FILE *f, *fopen();
int _tmain(int argc, _TCHAR* argv[])
{
int i,x;

f=fopen("c:\\tmp\\result.txt","w");
for(i=0;i<100;i++)
{
x=i*2;
fprintf(f," %d ",x);
}
fclose(f);
return 0;
}
Пример. Запись в файл с проверкой дисковой операции (как принято в C). Если fopen() не может открыть файл, возвращается значение NULL
// file2.cpp : Пример записи в файл
//
#include "stdafx.h" #include <stdio.h> #include <iostream> using namespace std; FILE *f, *fopen();
int _tmain(int argc, _TCHAR* argv[])
{
int i,x;
if((f=fopen("inf.txt","w"))==NULL)
{
printf("File-Error!!!"); return 1;
}
for(i=0;i<100;i++)
{
x=i*2;
fprintf(f," %d ",x);
}
fclose(f); return 0;
}
Как прочитать информацию из текстового файла – простые примеры
Пример. Чтение данных из файла
// file3.cpp : Чтение из файла
//
#include "stdafx.h" #include <stdio.h> #include <iostream> using namespace std;
FILE *f, *fopen();

int _tmain(int argc, _TCHAR* argv[])
{
int i,t; int x[10];
if((f=fopen("c:\\tmp\\dannye.txt","r"))==NULL)
{
printf("File-Error!!!"); return 1;
}
for(i=0;i<10;i++)
{
fscanf(f,"%d",&t);
x[i]=t;
cout<<"\n x="<<x[i];
}
fclose(f);
return 0;
}
Пример. Чтение всей информации из файла. С помощью функции feof() можно определить установлен ли индикатор конца файла
// file4.cpp : Чтение из файла
//
#include "stdafx.h" #include <stdio.h> #include <iostream> using namespace std; FILE *f, *fopen();
int _tmain(int argc, _TCHAR* argv[])
{
int i,t; int x[10];
if((f=fopen("c:\\tmp\\dannye.txt","r"))==NULL)
{
printf("File-Error!!!"); return 1;
}
i = 0;
while (!feof(f))
{
fscanf(f,"%d",&t);
x[i]=t;
cout<<"\n x="<<x[i++];
}
fclose(f); return 0;
}

ВОПРОС. Если в файле более 10 чисел (например, 100), смогут ли они сохраниться в массиве x?
Отметим, что в системе UNIX признак конца файла в самом файле не хранится. Система определяет длину файла в байтах, признак конца файла (EOF) вырабатывается стандартными функциями тогда, когда обнаруживается, что указатель чтения достиг конца файла, т.е. позиция чтения стала равной длине файла.
В системе MS DOS признак конца файла (EOF) хранится в текстовых файлах явно и обозначается CTRL/Z.
Проверка на конец файла при посимвольном чтении может быть такой
int ch;
…
while ((ch=getchar(f)) != EOF)
{
…
}
Операции с файлами – примеры
Пример. Чтение из файла и выделение слов.
#include <stdio.h> #include <ctype.h> #include <string.h> #include <iostream> using namespace std; FILE *f, *fopen(); int get_word(char *); int main()
{char word[80];/* слово, выделенное из файла */
int kol=0; /* количество слов в в файле */ if((f=fopen("readme.txt","r"))==NULL){printf("File-
Error!!!"); return 1;} while (get_word(word))
{/* цикл продолжается пока get_word() не равно 0*/ kol++; cout<<word<<' ';
}
fclose(f); return 0;
}
int get_word(char *a)
{/* возвращает 1, если из файла прочитано слово*/ /* слово передается через параметр a*/

char ch, i=1;
while (!isalpha(ch=getc(f))&&ch!=EOF); if(ch==EOF) return 0;/* файл кончился*/ a[0]=ch;
while(isalpha(ch=getc(f))&&ch!=EOF) a[i++]=ch; a[i]='\0';
return 1;
}
Пояснения. По поводу символьных функций см., например, С. Прата, стр. 255. Функция isalpha() возвращает true, если аргумент является символом алфавита.
Стандартные задачи на файлы
1.Дан текстовый файл f, получить копию файла f в файле g.
2.Даны текстовые файлы f и g. Записать в файл h сначала компоненты файла f, а затем
— компоненты файла g.
3.Даны текстовые файлы f и g. Написать программу, которая печатает информацию вперемежку из двух файлов: одна строка из файла f, другая – из файла g и т.д.
4.Написать программу сравнения двух текстовых файлов – на печать должна выводится первая из различающихся строк, а также номер этой строки и позицию символа, в котором они различаются.
5. Дан текстовый файл f. Создать файл g, образованный из файла f заменой всех прописных букв одноименными строчными.
6.Дан текстовый файл f. Подсчитать количество строк и символов в файле f. Указание (из А.Богатырев. Язык Си в системе UNIX, стр. 130): надо подсчитать количество символов ‘\n’ в файле и учесть, что последняя строка файла может не иметь этого символа на конце. Поэтому, если последний символ файла не есть ‘\n’, то нужно добавить к счетчику строк 1.
7.Дан текстовый файл f. Подсчитать количество вхождений каждого из символов алфавита в файле f.
8. Дан текстовый файл f. Подсчитать количество слов в файле f.
9. Дан текстовый файл f. Подсчитать в файле f количество слов заданной длины n.
10. Подсчитать количество вхождений данного слова s в текстовый файл.
11. Дан текстовый файл f, содержащий информацию в кодировке DOS (OEM – 866). Преобразовать информацию в кодировку Windows (Win-1251).

12. Дан текстовый файл f, содержащий информацию на русском языке. Преобразовать текст, заменив символы кириллицы на ―подходящие‖ латинские буквы (для букв, не имеющих аналогов в латинице, использовать сочетания букв, например, ―ж‖ — ―zh‖, ―х‖
— ―kh‖, ―ц‖ — ―ts‖, ―ч‖ — ―ch‖, ―ш‖ — ―sh‖, ―щ‖ — ―tsh‖, ―ю‖ — ―ju‖, ―я‖ — ―ja‖).
Преобразованный текст записать в файл g.
13. Дан текстовый файл f. Найти слово (слова), встречающиеся наиболее часто.
14. Дан текстовый файл f. Вычислить количество вхождений каждого символа в файле f. Результат сохранить в массиве.
Система ввода – вывода языка C++
Язык C++, как уже было показано, поддерживает операции с файлами с использованием функций, объявленных в stdio.h. Таким образом, можно использовать тот же код, что и в программах на языке C. Заметим, что вместо директивы, принятой в программе на C,
#include <stdio.h>
в программах на языке C++ записывают
#include <cstdio> using namespace std;
Рекомендуется в программах на C++ использовать ввод-вывод с использованием набора классов, определенных в заголовочных файлах iostream (iostream.h) и fstream (fstream.h).
С точки зрения программы, написанной на C++, ввод-вывод представляется как поток байтов. При вводе программа читает байты из потока ввода, а при выводе вставляет байты в поток вывода. Байты потока поступают с клавиатуры, из другой программы, с устройства хранения данных (например, диск). Управление вводом предполагает две стадии:
Присоединение потока ввода к программе
Связывание потока с файлом.
Пример. Создаѐм файл (“test.txt”) для записи, записываем в него информацию и закрываем. Снова открываем этот же файл, но уже для чтения, выводим часть информации из файла на экран.
#include <iostream> #include <fstream> using namespace std; int main()

{ofstream fout("test.txt"); // создание файла для вывода
if(!fout) { cout << "Файл открыть невозможно\n"; return 1; } fout << "Hello!\n";
fout << 100 <<' '<<200<< endl;
fout.close(); // Чтение из файла:
ifstream fin("test.txt"); // открытие файла для ввода
if(!fin) { cout << "Файл открыть невозможно\n"; return 1; } char str[80];
int i;
fin >> str >> i;
cout << str << ' ' << i << endl;
fin.close();
return 0;
}
Пример. Создаѐм файл (primer.txt) и записываем в него информацию, введенную с клавиатуры.
#include <iostream> #include <fstream> using namespace std; int main()
{
ofstream my_out("primer.txt"); // файл для вывода
if(!my_out) { cout << "Файл открыть невозможно\n"; return 1; } char str[80];
cout << "Vvodim stroku, okonchim - !\n"; do
{cout << "Stroka= "<<endl; cin >> str;
my_out << str << endl;
} while (*str != '!');
my_out.close();
return 0;
}
Пример. Читаем из одного файла, преобразуем информацию и записываем в другой файл.
#include <iostream> #include <fstream> using namespace std; int main()

{ifstream fin("file1.txt"); /* этот файл уже создан (из
него вводим) */
ofstream fout("file2.txt"); /* этот файл будет создан (в
него записываем) */
if(!fout) { cout << "Файл открыть невозможно\n"; return 1; } if(!fin) { cout << "Файл открыть невозможно\n"; return 1; } char ch;
fin.unsetf(ios::skipws); // не пропускать пробелы
while(!fin.eof()) {
fin >> ch; if(ch==',') ch = '|';
if(!fin.eof()) fout << ch;
}
fin.close();
fout.close();
return 0;
}
Пример. Подсчет числа слов в текстовом файле
#include <iostream> #include <fstream> #include <cctype> using namespace std; int main()
{
ifstream in("file1.txt");
if(!in) { |
cout |
<< "File--Error!!!!!\n"; return 1; } |
int count |
= 0; |
char ch; |
in >> ch; // нахождение первого символа не пробела in.unsetf(ios::skipws); // не пропускать пробелы while(!in.eof()) {
in >> ch;
if(isspace(ch)|| in.eof()) { count++; while(isspace(ch) && !in.eof()) in >> ch;
}
}
cout << "Vsego slov: " << count << '\n'; in.close();
return 0;
}