Обработка текстовых файлов

Для ввода/вывода в текстовый файл можно непосредственно применять операции<< и >>.

Пример вывода в файл:

#include <iostream.h>

#include <fstream.h>

Void main(void)

{

ofstream out(“myfile.txt”);

if (!out)

{

cout<<”Не могу открыть файл\n”; return 1;

}

out<<10<<” “<<10<<” “<<2004;

out<<”Строка выводится очень просто”;

Out.close();

}

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

#include <iostream.h>

#include <fstream.h>

Void main(void)

{

Char ch;

Int i;

Float f;

char str[80];

ifstream in(“myfile.txt”);

if (!in)

{ cout<<”Не могу открыть файл\n”; return 1; }

in>>i; in>>f; in>>ch; in>>str;

cout<<i<<” “<<f<<” “<<ch<<endl;

cout<<str<<endl;

In.close();

}

 

Для чтения символьных данных можно использовать функциюgetline()с прототипом из iostream.h

char *getline(char *s,int n);

s -строка (массив) для ввода;n -количество читаемых символов.

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

#include<iostream.h>

#include<conio.h>

#include<string.h>

#include<fstream.h>

#include<stdio.h>

Void main(void)

{

ofstream fcout("aaa.cpp");

Ifstream fcin;

char *tmp=new char[80];

char *fname=new char[20];

char *word=new char[80];

char *ptr;

int a=0;

cout<<"Give name file:"<<endl;

Do

{

If(a)

{

cout<<"Invalid name file!! Give correct name:"<<endl;

}

Cin.getline(fname,20);

Fcin.open(fname);

a=1;

} while(!fcin);

cout<<"\give word:";

Cin.getline(word,80);

while(!fcin.eof()) /* read line from file */

{

Fcin.getline(tmp,80);

if ((ptr=strstr(tmp,word))!=NULL)

{

cout<<tmp<<endl;

fcout<<tmp<<endl;

}

}

Fcout .close();

Fcin .close();

Getch();

}

Двоичный ввод/вывод.

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

ifstream &get(char &ch);

ofstream &put(char ch);

Функция get()читает символ из потока и присваивает значение переменнойch.Функция put()записывает символchв поток. Пример программы копирования файла на экран.

#include <iostream.h>

#include <fstream.h>

Void main(void)

{

Char ch;

Ifstream in;

in.open(“myfile.bin”,ios::binary,1);

if(!in)

{

cout<<”\n не могу открыть файл”);

Return 1;

}

while(in.get(&ch))

cout<<ch;

In.close();

}

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

Пример программы копирования строки в файл

#include <iostream.h>

#include <fstream.h>

Oid main(void)

{

char *p=”Hello, World!”;

ofstream out(“test”);

if(!out)

{

cout<<”Не могу открыть файл\n”;

Return 1;

}

while (*p)

out.put(*p++);

Out.close();

}

Для быстрой обработки двоичных данных можно использовать функции read(), write() с прототипами:

ifstream &read(unsigned char *buf, int num); ofstream &write(unsigned char *buf, int num);

Функция read() читает из потока num байт и помещает их в buf. Функция write() записывает в поток num байт из буфера buf.

Пример

#include <iostream.h>

#include <fstream.h>

Void main(void)

{

float numbers[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 0};

Int i;

ofstream out(“test”);

if (!out)

{

cout<<”Не могу открыть файл \n”;

Return 1;

}

out.write((unsigned char *) numbers, sizeof numbers);

Out.close();

for(i=0;i<10;i++)

numbers[i]=0;

ifstream in(“test”);

if (!in)

{

cout<<”Не могу открыть файл \n”;

Return 1;

}

in.read((unsigned char *) numbers, sizeof numbers);

for(i=0;i<10;i++)

cout<<numbers[i]<<” “;

cout<<”\n”;

cout<<”Было прочитано”<<in.gcount()<<” символов\n”;

In.close();

}

Функция gcount() возвращает количество прочитанных байт последним вызовом функции read().

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

Система ввода/вывода С++, так же как и в языке С, оперирует потоками (streams). В начале выполнения программы автоматически открывается 4 предопределенных потока: cin, cout, cerr, clog. Поток cinсвязан со стандартным вводом, поток cout – со стандартным выводом. Потоки cerrи clog также связаны со стандартным выводом. Поток cerr –небуферизованный, т. е. вызывает немедленный вывод. Поток clogбуферизован, и вывод происходит только тогда, когда наполнится буфер. Оба этих потока используются для вывода сообщений об ошибках.По умолчанию поток cinсвязан с клавиатурой, cout – с дисплеем, но они могут быть перенаправлены на другие устройства.

При работе с потоками используются две операции. Операция << - inserting (вставка данных в поток),операция >> - extracting (извлечение данных из потока).

В следующем примере применяются данные операции.

#include <iostream.h>

Void main(void)

{

char name[100];

cout<<”\n Пожалуйста, введите ваше имя:”;

cin>>name;

cout>>”\n Привет,”;

cout<<name;

}

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

Форматирующие функции-элементы.

Данные функции принадлежат классу ios.К ним относятся функции: width(), fill(), precision().

Функция width

int width() возвращает текущее значение внутренней переменной ширины поля потока.

int width(int ) устанавливает значение внутренней переменной ширины поля потока.

Замечания к применению:

- применяемая при вводе функция может быть использована для задания максимального числа читаемых символов;

- применяемая при выводе функция задает минимальную ширину поля вывода;

- если ширина поля меньше заданной, то дополнение символами fill;

- если выходное поле больше указанного, то значениеwidthигнорируется;

- по умолчание значение width равно 0;

- width обнуляется после каждого помещения данных в поток.

Пример

#include <iostream.h>

const int MAX_LEN = 10; const int FLD_WIDTH = 10;

Void main(void)

{

char name[MAX_LEN];

int x=2867; int y=20051; int z=017;

cout<<”|n Give name “<<”(max “<<MAX_LEN-1<<” symbols): “;

Cin.width(MAX_LEN);

cin>>name;

cout<<”\n Hello, “<<name;

Cout.width(FLD_WIDTH);

cout<<x<<”\n”;

Cout.width(FLD_WIDTH);

cout<<y<<”\n”;

Cout.width(FLD_WIDTH);

cout<<z<<”\n”;

}

Функция fill

int fill() возвращает текущий символ заполнения;

int fill(char) устанавливает внутренний заполняющий символ и возвращает его предыдущее значение.

Символом заполнения по умолчанию является пробел. Пример

#include <iostream.h>

const int FLD_WIDTH = 10; const int FILL_CHAR = ‘0’;

Void main(void)

{

int x=2867, y=20051;

Cout.fill(FILL_CHAR);

Cout.width(FLD_WIDTH);

cout<<x<<”\n”;

Cout.width(FLD_WIDTH);

cout<<y<<”\n”;

}

Функция precision

int precision() возвращает текущее символ значение точности;

int precision(int) устанавливает внутреннюю переменную точности вещественных чисел потока и возвращает прежнее значение. Замечания к применению:

- по умолчанию точность равна 6 цифрам;

- если установлен флаг scientific или fixed, precisionзадает общее число значащих цифр;

- если не установлен ни один из флагов scientific или fixed, precisionзадает общее число значащих цифр;

Пример иллюстрирует применение precision

#include <iostream.h>

Void main(void)

{

float f = 3456.141592;

double d = 50.2345639101;

Cout.precision(4);

cout<<d<<’\n’; // выводит ’50.23’

cout<<f<<’\n’; // выводит ’3456’

Cout.precision(3);

cout<<f<<’\n’; // выводит ’3.46e+3’

}

Флаги форматирования.

В потоках С++ имеются флаги формата. Они задают, каким образом форматируется ввод и вывод. Флаги являются битовыми полями, хранящимися в переменной типа long.В следующей таблице приведены функции, предусмотренные в классе iosдля управления флагами формата.

Функция Описание
long ios::flags() Возвращает текущие флаги потока
long ios::flags(long) Присваивает флагам значение, сообщаемое параметром, и возвращает прежнее значение флагов
long ios::setf(long,long) Присваивает флагам, биты которых установлены во втором параметре, значения соответствующих бит первого параметра. Возвращает прежнее значение всех флагов.
long ios::setf(long) Устанавливает флаги, биты которых установлены в параметре; возвращает прежнее значение всех флагов.
long ios::unsetf(long) Сбрасывает флаги, биты которых установлены в параметре; возвращает прежнее значение всех флагов.

 

В следующей таблице описаны флаги форматирования

 

Флаг Умолчание Описание
ios::skipws X Если установлен, при вводе игнорируются предшествующие пробелы
ios::left   Если установлен, данные при выводе выравниваются по левой границе поля.
ios::right X Если установлен или если сброшены ios::left и ios::internal, данные при выводе выравниваются по правой границе поля.
ios::internal   Если установлен, знак числа выводится с левого края поля, а число выравнивается по правому краю. Промежуток заполняется символами fill
ios::dec X Если установлен, числа выводятся по основанию 10 (как десятичные)
ios::oct   Если установлен, числа выводятся по основанию 8(как восьмеричные)
ios::hex   Если установлен, числа выводятся по основанию 16(как шестнадцатиричные)
ios::showbase   Если установлен, при выводе чисел добавляется индикатор основания(“0x” для 16-тиричных и “0” для восьмиричных).
ios::showpoint   Если установлен, при выводе чисел типа float, double, long double показывается десятичная точка.
ios::uppercase   Если установлен, буквы от A до F в 16-ч числах выводятся в верхнем регистре.
ios::showpos   Если установлен, выводится знак + для положительных значений
ios::scientific   Если установлен, вещественные числа выводятся в научной нотации (т.е. n.xxxEy, 1.234e2)
ios::fixed   Если установлен, вещественные числа выводятся в нотации с фиксированной точкой (т.е. nnn.ddd, 123.45)

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

#include <iostream.h>

#include <limits.h>

Void main(void)

{

int i=0;

cout<<”Введите целое с необязательными пробелами впереди: “;

// при чтении пробелы будут пропущены

cin>>i;

// показать число…

cout<<”Вы ввели “ << i << endl;

// удалить оставшиеся в потоке символы

cin.ignore( INT_MAX, ‘\n’);

cout<<”Введите целое с необязательными пробелами впереди: “;

// Сбросить флаг skipws

cin.unsetf(ios::skipws);

// Эта операция не будет игнорировать пробелы

cin >> i;

}

#include <iostream.h>

Void main(void)

{

int x = 1678;

// показать значение

cout<<”Значение x= “<<x<<’\n’;

// сохранить значения флагов

long savedFlags = cout.flags;

// установить основание 16 с индикацией

cout.setf(ios::showbase|ios::hex);

// вывести значение снова

cout<<” Значение x=”<< x <<’\n’;

}

#include <iostream.h>

Void main(void)

{

float f = 2.3456789e6;

double d = 3.0e9;

cout << “Значение f = “ << f <<’\n’;

cout << “Значение d = “ << d <<’\n’;

// выводить знак + для положительных значений

cout.setf(ios::showpos);

// вывести значения снова

cout << “Значение f = “ << f <<’\n’;

cout << “Значение d = “ << d <<’\n’;

}

Манипуляторы.

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

Простые манипуляторы

Манипуляторы, не требующие указания аргументов, называются простыми. Предопределенные простые манипуляторы описаны в следующей таблице.

Манипулятор Описание
endl Помещает в выходной поток символ новой строки (\n) и вызывает манипулятор flush
ends Помещает в выходной поток нулевой символ (\0). Обычно используется для указания конца строки.
flush Принудительно записывает все выходные данные на соответствующие физические устройства.
dec Устанавливает основание 10 (см. ios::dec)
hex Устанавливает основание 16 (см. ios::hex)
oct Устанавливает основание 8 (см. ios::oct)
ws Заставляет игнорировать при выводе ведущие пробельные символы (см. ios::skipws)

Пример иллюстрирует использование простых манипуляторов

#include <iostream.h>

#include <iomanip.h>

Void main(void)

{

Int i;

cout << “Введите число:”; cin >> i;

if (!cin) cout << “Ошибочный ввод ….”<<endl;

Else

{

// применить манипуляторы hex, oct, dec

cout<<”Hex: << hex << i << endl;

cout<<”Oct: << oct << i << endl;

cout<<”Dec: << dec << i << endl;

}

}