Обработка текстовых файлов
Для ввода/вывода в текстовый файл можно непосредственно применять операции<< и >>.
Пример вывода в файл:
#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;
}
}