Стандартные функции работы со троками

Цель и порядок работы

Цель работы – ознакомиться с возможностями ввода-вывода языка C++, освоить основные операции работы со строками и файлами.

 

Порядок выполнения работы:

- ознакомиться с описанием лабораторной работы;

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

- написать программу и отладить ее на ЭВМ;

- оформить отчет.

Краткая теория

В библиотеке C++ имеется набор классов для управления вводом-выводом. В отличие от функций буферизованного ввода-вывода библиотек C (таких, как printf и scanf, не выполняющих никаких проверок на соответствие аргументов форматной строке) классы потоков C++ безопасны в отношении типа. Ввод-вывод использует механизм перегрузки операций, гарантирующий вызов нужной функции-операции для указанного типа данных. Это главное преимущество потоков языка C++.

2.1 Строки в C++

Ввод-вывод строк

В C++ есть два вида строк С-строки и класс string стандартной библиотеки C++.

C-строка представляет собой массив символов, завершающийся символом с кодом 0. Класс string более безопасен в использовании, чем C-строки, но и более ресурсоемок. Для грамотного использования этого класса требуется знание объектно-ориентированного программирования. Кроме этого существуют более функциональные и удобные в использовании классы библиотеки .net, которые будут рассмотрены позже, поэтому ограничимся рассмотрением C-строк.

 

Память под строки, как и под другие массивы, может выделяться как компилятором, так и непосредственно в программе. Длина динамической строки может задаваться выражением, длина нединамической строки должна быть только константным выражением. Чаще всего длина строки задается частным случаем константного выражения – константой. Удобно задавать длину с помощью именованной константы, поскольку такой вариант, во-первых, лучше читается, а во-вторых, при возможном изменении длины строки потребуется изменить программу только в одном месте:

 

const int len_str = 100;

char msg[len_str];

 

При задании длины необходимо учитывать завершающий нуль-символ. Например, в строке, приведенной выше, можно хранить не 100 символов, а только 99. Строки можно при описании инициализировать строковыми константами, при этом нуль-символ в позиции, следующей за последним заданным символом, формируется автоматически:

 

const int len_str = 100;

char msg[len_str] = "Новая строка";

 

Если строка при определении инициализируется, ее размерность можно опускать (компилятор сам выделит память, достаточную для размещения всех символов строки и завершающего нуля):

 

char msg[ ] = "Новая строка"; //13 символов

 

Для размещения строки в динамической памяти надо описать указатель на char, а затем выделить память с помощью new или mallос (первый способ предпочтительнее).

 

char *p = new char[len_str];

 

Естественно, что в этом случае длина строки может быть переменной и задаваться на этапе выполнения программы. Динамические строки, как и другие динамические массивы, нельзя инициализировать при создании.

 

Для ввода-вывода строк используются как уже известные нам объекты cin и cout, так и функции, унаследованные из библиотеки С.

Рассмотрим сначала первый способ:

 

#include "stdafx.h"

#include <iostream>

 

using namespace std;

 

int main()

{

const int n = 80;

char s[n];

cin >> s;

cout << s << endl;

return 0;

}

 

Строки вводится точно так же, как и переменные других типов.

При вводе строки из нескольких слов, программа выведет только первое слово. Это связано с тем, что ввод выполняется до первого пробельного символа (то есть пробела, знака табуляции или символа перевода строки '\n')

Если требуется ввести строку, состоящую из нескольких слов, в одну строковую переменную, используются методы getline или get класса istream, объектом которого является cin.

 

#include "stdafx.h"

#include <iostream>

 

using namespace std;

 

int main()

{

const int n = 80;

char s[n];

cin.getline(s, n);

cout << s << endl;

return 0;

}

 

Метод getline считывает из входного потока n - 1 символов или менее (если символ перевода строки встретится раньше) и записывает их в строковую переменную s, Символ перевода строки также считывается (удаляется) из входного потока, но не записывается в переменную, вместо него размещается завершающий '\0'. Если в строке исходных данных более n - 1 символов, следующий ввод будет выполняться из той же строки, начиная с первого несчитанного символа. Метод get работает аналогично, но оставляет в потоке символ перевода строки. В строковую переменную добавляется завершающий ноль.

Если в программе требуется ввести несколько строк, метод getl1nе удобно использовать в заголовке цикла, например:

 

#include "stdafx.h"

#include <iostream>

 

using namespace std;

 

int main()

{

const int n = 80;

char s[n];

while (cin.getline(s, n))

{

cout << s << endl;

};

return 0;

}

 

Рассмотрим теперь способы ввода-вывода строк, перекочевавшие в С++ из языка С. Во-первых, можно использовать для ввода строки известную нам функцию scanf, а для вывода – printf, задав спецификацию формата %s.

Ввод будет выполняться так же, как и для классов ввода-вывода – до первого пробельного символа. Чтобы ввести строку, состоящую из нескольких слов, используется спецификация %c (символы) с указанием максимального количества вводимых символов, например:

 

scanf("%10c", s);

 

Количество символов может быть только целой константой. При выводе можно задать перед спецификацией %s количество позиций, отводимых под строку:

 

printf("%10s", s);

 

Строка при этом выравнивается по правому краю отведенного поля. Если заданное количество позиций недостаточно для размещения строки, оно игнорируется, и строка выводится целиком.

Библиотека содержит также функции, специально предназначенные для ввода-вывода строк: gets и puts.

Функция gets(s) читает символы с клавиатуры до появления символа новой строки и помещает их в строку s (сам символ новой строки в строку не включается, вместо него в строку заносится нуль-символ).

Функция puts(s) выводит строку s на стандартное устройство вывода, заменяя завершающий 0 символом новой строки. Возвращает неотрицательное значение при успехе или EOF при ошибке.

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

 

Операции со строками

Для строк не определена операция присваивания, поскольку строка является не основным типом данных, а массивом. Присваивание выполняется с помощью функций стандартной библиотеки или посимвольно «вручную» (что менее предпочтительно, так как чревато ошибками). Например, чтобы присвоить строке p строку a, можно воспользоваться функциями strcpy или strncpy, а для определения длинны строки – strlen.

 

#include "stdafx.h"

#include <iostream>

#include <string.h>

 

 

using namespace std;

 

int main()

{

char a[100] = "Working with a strings";

 

size_t m = strlen(a) + 1; //добавим 1 для учета нуль-символа

 

char *p = new char [m];

 

strcpy(p, a);

strncpy(p, a, strlen(a) + 1);

 

 

return 0;

}

 

Замечание. Использование функций strcpy и strncpy может быть небезопасным, так как они не проверяют размер буфера-приемника, что может привести к выходу за границы и затиранию чужих областей памяти. Выход за границы строки и отсутствие нуль-символа являются распространенными причинами ошибок в программах обработки строк. Для решения этой проблемы можно использовать безопасные версии функций: strcpy_s и strncpy_s, и избавить себя от собственноручного отслеживания размеров строки. При запуске программы компилятор выдает соответствующее предупреждение, которое можно проигнорировать в данном случае.

 

Для использования этих функций к программе следует подключить заголовочный файл <string.h>.

Функция strcpy(dst, src) копирует все символы строки, указанной вторым параметром (src), включая завершающий 0, в строку, указанную первым параметром (dst). Функция strncpy(dst, src, n) выполняет то же самое, но не более n символов, то есть числа символов, указанного третьим параметром. Если нуль-символ в исходной строке встретится раньше, копирование прекращается, а оставшиеся до n символы строки dst заполняются нуль-символами. В противном случае (если n меньше или равно длине строки src) завершающий нуль-символ в dst не добавляется.

Обе эти функции возвращают указатель на результирующую строку. Если области памяти, занимаемые строкой-назначением и строкой-источником, перекрываются, поведение программы не определено.

Функция strlen(src) возвращает фактическую длину строки а, не включая нуль-символ.

Программист должен сам заботиться о том, чтобы в строке-приемнике хватило места для строки-источника (в данном случае при выделении памяти значение переменной m должно быть больше или равно 100), и о том, чтобы строка всегда имела завершающий нуль-символ.

 

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

Аналогичные функции преобразования строки в длинное целое число (long) и в вещественное число с двойной точностью (double) называются atol и atof соответственно.

 

//Пример применения функций преобразования

#include "stdafx.h"

#include <iostream>

#include <string.h>

 

using namespace std;

 

int main()

{

char a[] = "15) Кол-во - 249 шт. Цена - 499.99 руб.";

 

int num;

long quantity;

double price;

 

num = atoi(a);

quantity = atol(&a[12]);//12 - смещение начала кол-ва

price = atof(&a[27]); //27 - смещение начала цены

 

cout << num << ' ' << quantity << ' ' << price;

 

return 0;

}

 

Замечание. При переводе вещественных чисел разделитель целой и дробной части зависит от настроек локализации. По умолчанию используется символ точка. При изменении локализации (функция setlocale(LC_ALL, "Russian")), разделитель меняется на принятый в России, т.е. символ запятая.

 

Библиотека предоставляет также различные функции для, сравнения строк и подстрок, объединения строк, поиска в строке символа и подстроки и выделения из строки лексем.

Работа с символами

Для хранения отдельных символов используются переменные типа char. Их ввод-вывод также может выполняться как с помощью классов ввода-вывода, так и с помощью функций библиотеки.

При использовании классов ввод-вывод осуществляется как с помощью операций помещения в поток и извлечения из потока, так и методов get() и get(char).

Вводимые символы могут разделяться или не разделяться пробельными символами, поэтому таким способом ввести символ пробела нельзя. Для ввода любого символа, включая пробельные, можно воспользоваться методами get() и get(char).

Метод get() возвращает код извлеченного из потока символа или EOF, а метод get(c) записывает извлеченный символ в переменную, переданную ему в качестве аргумента, а возвращает ссылку на поток.

В заголовочном файле <stdiо.h> определена функция getchar() для ввода символа со стандартного ввода, а также putchar() для вывода.

Рассмотрим пример использования функций работы с символами.

 

//Пример применения функций работы со строками

#include "stdafx.h"

#include <iostream>

#include <stdio.h>

 

using namespace std;

 

int main()

{

setlocale(LC_ALL, "Russian");

 

char a, b, c, d, e;

cin >> a >> b;

cout << a << ' ' << b << endl;

 

c = cin.get();

cin.get(d);

 

cout << c << ' ' << d << endl;

 

e = getchar();

putchar(e);

 

return 0;

}

 

В библиотеке также определен целый ряд функций, проверяющих принадлежность символа какому-либо множеству, например множеству букв (isalfa), разделителей (isspace), знаков пунктуации (ispunct), цифр (isdigit) и т. д. Описание этих функций приведено ниже.

 

Стандартные функции работы со троками

2.1.4.1 <string.h> (<cstring>) – функции работы со строками в стиле C

 

void *memchr(const void *p, int ch, size_t n);

Ищет первое вхождение символа в блок памяти.

Функция возвращает указатель на первое вхождение байта, представленного младшим байтом аргумента ch в блоке памяти p длиной n.

 

int memcmp(const void *p1, const void *p2, size_t n);

Сравнивает блоки памяти

Функция сравнивает два блока памяти и возвращает значение: меньше нуля, равное нулю или больше нуля – аналогично кодам возврата функции strcmp.

 

void *memcpy(void *dest, const void *src, size_t n);

Копирует блок памяти

Функция копирует блок памяти длиной n байт из адреса src по адресу dest.

 

void *memmove(void *dest, const void *src, size_t n);

Переносит блок памяти

Функция аналогична memcpy, но блоки dest и src могут перекрываться.

 

void *memset(const void *р, int ch, size_t n);

Заполняет блок памяти символом

Функция заполняет блок памяти символом, взятым из младшего байта ch.

 

char *strcat(char *s1, char *s2);

Складывает строки

Функция добавляет s2 к s1 и возвращает s1. В конец результирующей строки добавляется нуль-символ.

 

char *strchr(char *s, int ch);

Ищет символ в строке

Функция возвращает указатель на первое вхождение символа ch в строку s, если его нет, то возвращается NULL.

 

int strcmp(char *s1, char *s2);

Сравнивает строки

Функция сравнивает строки и возвращает отрицательное (если s1 меньше s2), нулевое (если s1 равно s2) или положительное (если s1 больше s2) значение.

 

char *strcoll(char *s1, char *s2);

Сравнивает строки с учетом установленной локализации

Функция сравнивает строки аналогично strcmp, но учитывает установки локализации.

 

char *strcpy(char *s1, char *s2);

Копирует одну строку в другую

Функция копирует s2 в s1 и возвращает s1.

 

size_t strcspn(char *s1, char *s2);

Ищет один из символов одной строки в другой

Функция возвращает значение индекса любого из символов из s2 в строке s1.

 

char *strerror(size_t n);

Возвращает указатель на строку с описанием ошибки

Функция возвращает указатель на строку с описанием ошибки номер n.

 

struct tm strftime(char *s, size_t size, fmt, const struct tm *ctm);

Преобразует время в формате fmt в формат tm

Функция возвращает отформатированную строку с датой и временем на основе формата fmt. Значение функции имеет тип time_t, соответствующий типу tm.

 

size_t strlen(char *s);

Возвращает длину строки

Функция возвращает длину строки (без учета символа завершения строки).

 

char *strncat(char *s1, char *s2, size_t n);

Складывает одну строку с n символами другой

Функция добавляет не более п символов из s2 к s1 и возвращает s1. Первый символ s2 пишется на место завершающего нуль-символа строки s1. Если длина строки s2 меньше n, переписываются все символы s2. К строке s1 добавляется нуль-символ. Если строки перекрываются, поведение не определено.

 

int strncmp(char *s1, char *s2, size_t n);

Сравнивает одну строку с n символами другой

Функция сравнивает первую строку и первые n символов второй строки и возвращает отрицательное (если s1меньше s2), нулевое (если s1 равно s2) или положительное (если s1 больше s2) значение.

 

char *strncpy(char *s1, char *s2, size_t n);

Копирует первые n символов одной строки в другую

Функция копирует не более n символов из s2 в s1 и возвращает s1. Если длина исходной строки превышает или равна n, нуль-символ в конец строки s1 не добавляется. В противном случае строка дополняется нуль-символами до n-го символа. Если строки перекрываются, поведение не определено.

 

char *strpbrk(char *s1, char *s2);

Ищет один из символов одной строки в другой

Функция возвращает указатель на символ, являющийся первым вхождением любого из символов из s2 в строку s1, если его нет, возвращается NULL.

 

char *strrchr(char *s,int ch);

Ищет символ в строке

Функция возвращает указатель на первое вхождение символа ch в строку s справа, если его нет, возвращает NULL.

 

size_t strspn(char *s1, char *s2);

Ищет символ одной строки, отсутствующий в другой

Функция возвращает индекс первого символа в s1, отсутствующего в s2.

 

char *strstr(char *s1, char *s2);

Ищет подстроку в строке

Функция выполняет поиск первого вхождения подстроки s2 в строку s1. В случае удачного поиска, возвращает указатель на элемент из s1, с которого начинается s2, и NULL в противном случае.

 

double strtod(const char *str, char **end);

Преобразует строку в число

Функция преобразует строку символов в числовое значение и возвращает его. При переполнении возвращает +/-HUGE_VAL При невозможности выполнить преобразование или исчезновении порядка возвращает 0. В обоих последних случаях errno устанавливается в ERANGE. end указывает на символ, на котором преобразование завершается.

 

char *strtok(char *s1, char *s2);

Выделяет из строки лексемы

Функция возвращает следующую лексему из s1, отделенную любым из символов из набора s2.

 

double strtol(const char *str, char **end, int radix);

Преобразует строку в число с учетом системы счисления

Функция преобразует строку символов в числовое значение с учетом указанной системы счисления radix и возвращает полученное число. Функция пропускает возможные начальные пробелы и заканчивает преобразование на первом символе, который не может появиться в образе числа. Параметр end является адресом указателя типа char*; этот указатель будет содержать адрес первого непреобразованного символа. При переполнении возвращает LONG_МАХ или LONG_MIN. При невозможности выполнить преобразование возвращает 0. В обоих последних случаях errno устанавливается в ERANGE.

 

double strtoul(const char *str, char **end, int radix);

Преобразует строку в число с учетом системы счисления

Функция работает аналогично strtol, но работает с беззнаковым длинным целым. При переполнении возвращает ULONG_MAX.

 

size_t strxfrm(char *s1, char *s2, size_t n);

Преобразует строки на основе текущей локализации

Функция преобразует строку из s2 и помещение ее в s1 на основе текущей локализации. Преобразуется не более n символов.

 

2.1.4.2 <stdio.h> (<cstdio>) – функции ввода-вывода в стиле C

 

int snprintf(wchar_t *buffer, const wchar_t *format[, argument, …]);

Выводит строку параметров в определенном формате

Функция выводит в строку buffer значения переменных, перечисленных в списке, обозначенном многоточием, в формате, определенном строкой format. Является аналогом функции sprintf для многобайтных символов.

 

int swscanf(const wchar_t *buf, const wchar_t *format, ...);

Вводит данные из строки

Функция аналогично функции scanf вводит данные, но не с клавиатуры, а из строки символов, переданной ей первым параметром. Аргумент buf – строка символов, из которой вводятся значения, format – строка формата, в соответствии с которой происходит преобразование данных, а многоточие указывает на наличие необязательных аргументов, соответствующих адресам вводимых значений. Является аналогом функции sscanf для многобайтных символов.

 

int sprintf(char *buffer, const char *format[,argument, …]);

Выводит строку параметров в определенном формате

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

 

int sscanf(const char *buf, const char *format [,par1, par2, … ]);

Вводит данные из строки

Функция аналогично функции scanf вводит данные, но не с клавиатуры, а из строки символов, переданной ей первым параметром. Аргумент buf – строка символов, из которой вводятся значения, format – строка формата, в соответствии с которой происходит преобразование данных, а многоточие указывает на наличие необязательных аргументов, соответствующих адресам вводимых значений.

 

2.1.4.3<ctype.h> (<cctype>) – функции классификации и преобразования типов

 

int tolower(int ch);

Возвращает символ в нижнем регистре

Функция получает параметр ch и возвращает его в нижнем регистре. В параметре ch используется только младший байт.

 

int toupper(int ch);

Возвращает символ в верхнем регистре

Функция получает параметр ch и возвращает его в верхнем регистре. В параметре ch используется только младший байт.

 

int towlower(wint_t ch);

Возвращает символ в нижнем регистре

Функция получает символ ch и возвращает его в нижнем регистре. Является аналогом функции tolower для многобайтных символов.

 

int towupper(wint_t ch);

Возвращает символ в верхнем регистре

Функция получает символ ch и возвращает его в верхнем регистре. Является аналогом функции toupper для многобайтных символов.

 

int isalnum(int ch);

Проверяет, является ли символ буквой или цифрой

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой или цифрой, или false в противном случае.

 

int isalpha(int ch);

Проверяет, является ли символ буквой

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой, или false в противном случае.

 

int iscntrl(int ch);

Проверяет, является ли символ управляющим

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является управляющим символом (типа line feed, del, табуляции и тому подобных, большинство из которых находятся в диапазоне 0x01 – 0х1F (для кодировки ASCII)), или false в противном случае.

 

int isdigit(int ch);

Проверяет, является ли символ цифрой

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является цифрой, или false в противном случае.

 

int isgraph(int ch);

Проверяет, является ли символ видимым

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является видимым (то есть он не является символом пробела, табуляции и т. д.) или false в противном случае.

 

int islower(int ch);

Проверяет, является ли символ буквой нижнего регистра

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой нижнего регистра, или false в противном случае.

 

int isprint(int ch);

Проверяет, является ли символ печатаемым

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является печатаемым (isgraph + пробел), или false в противном случае.

 

int ispunct(int ch);

Проверяет, является ли символ символом пунктуации

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является символом пунктуации (то есть печатаемым, но не буквой, не цифрой, не пробелом), или false в противном случае.

 

int isspace(int ch);

Проверяет, является ли символ разграничительным

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

 

int isupper(int ch);

Проверяет, является ли символ буквой верхнего регистра

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является буквой верхнего регистра, или false в противном случае.

 

int iswalnum(wint_t сh);

Проверяет, является ли символ буквой или цифрой

Функция возвращает значение true, если символ ch является буквой или цифрой, или false в противном случае. Является аналогом функции isalnum для многобайтных символов.

 

int iswalpha(wint_t ch);

Проверяет, является ли символ буквой

Функция возвращает значение true, если символ ch является буквой, или false в противном случае. Является аналогом функции isalpha для многобайтных символов.

 

int iswcntrl(wint_t сh);

Проверяет, является ли символ управляющим

Функция возвращает значение true, если символ ch является управляющим символом (типа line feed, del, табуляции и тому подобных, большинство из которыхнаходятся в диапазоне 0х01 — 0x1F (для кодировки ASCII)), или false в противном случае. Является аналогом функции iscntrl для многобайтных символов.

 

int iswctype(wint_t с, wctype_t desc);

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

Функция возвращает ненулевое значение, если символ c обладает свойством desc, или нулевое в противном случае.

 

int iswdigit(wint_t сh);

Проверяет, является ли символ цифрой

Функция возвращает значение true, если символ ch является цифрой, или false в противном случае. Является аналогом функции isdigit для многобайтных символов.

 

int iswgraph(wint_t сh);

Проверяет, является ли символ видимым

Функция возвращает значение true, если символ ch является видимым (то есть он не является символом пробела, табуляции и т. д.) или false в противном случае. Является аналогом функции isgraph для многобайтных символов.

 

int iswlower(wint_t сh);

Проверяет, является ли символ буквой нижнего регистра

Функция возвращает значение true, если символ ch является буквой нижнего регистра, или false в противном случае. Является аналогом функции islower для многобайтных символов.

 

int iswprint(wint_t сh);

Проверяет, является ли символ печатаемым

Функция возвращает значение true, если символ ch является печатаемым (iswgraph + пробел), или false в противном случае. Является аналогом функции isprint для многобайтных символов.

 

int iswpunct(wint_t сh):

Проверяет, является ли символ символом пунктуации

Функция возвращает значение true, если символ ch является символом пунктуации (то есть печатаемым, но не буквой, не цифрой, не пробелом), или false в противном случае. Является аналогом функции ispunct для многобайтных символов.

 

int iswspace(wint_t сh);

Проверяет, является ли символ разграничительным

Функция возвращает значение true, если символ ch является символом пробела или табуляцией, или символом новой строки, или символом новой страницы (символом перевода формата), или false в противном случае. Является аналогом функции issрасе для многобайтных символов.

 

int iswupper(wint_t сh);

Проверяет, является ли символ буквой верхнего регистра

Функция возвращает значение true, если символ ch является буквой верхнего регистра, или false в противном случае. Является аналогом функции isupper для многобайтных символов.

 

int iswxdigit(wint_t ch);

Проверяет, является ли символ символом

Функция возвращает значение true, если символ ch является символом шестнадцатеричной цифры (цифры, а также буквы от А до F в нижнем или верхнем регистрах), или false в противном случае. Является аналогом функции isxdigit для многобайтных символов.

 

int isxdigit(int сh);

Проверяет, является ли символ символом шестнадцатеричной цифры

Функция выделяет младший байт параметра ch и возвращает значение true, если символ ch является символом шестнадцатеричной цифры (цифры, а также буквы от A до F в нижнем или верхнем регистрах), или false в противном случае.

 

Потоки ввода-вывода

В C++ существует несколько классов потоков:

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

- Класс ios является базовым классом потоков ввода-вывода.

- Классы istream и ostream – производные от ios и обеспечивают работу потоков соответственно ввода и вывода.

- Класс iostream является производным от двух предыдущих и предусматривает функции, как для ввода, так и для вывода.

- Классы ifstream, ofstream и fstream предназначены для управления файловым вводом-выводом.

- Классы istrstream и ostrstream управляют резидентными потоками (форматированием строк в памяти).

 

Для работы с потоками необходимо подключить заголовочный файл <iostream>. Кроме того, может потребоваться подключить файлы <fstream> (файловый ввод-вывод), <iomanip> (параметризованные манипуляторы) и <strstream> (форматирование в памяти).

 

Библиотека ввода-вывода C++ предусматривает четыре предопределенных объекта-потока, связанных со стандартными входным и выходным устройствами.

 

Таблица 11.1 Предопределенные объекты-потоки C++

Имя Класс Описание
cin istream Ассоциируется со стандартным вводом (клавиатурой).
cout ostream Ассоциируется со стандартным выводом (экраном).
cerr ostream Ассоциируется со стандартным устройством ошибок (экраном) без буферизации.
clog ostream Ассоциируется со стандартным устройством ошибок (экраном)с буферизацией.

 

Основными классами ввода-вывода C++ являются istream и ostream. Первый из них перегружает операцию правого сдвига (>>), которая служит в нем для ввода данных и называется операцией извлечения из потока. Класс ostream перегружает соответственно операцию левого сдвига (<<); она применяется для вывода и называется операцией передачи в поток.

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

Подробней форматирование ввода-вывода рассмотрено в лабораторной работе №2.

 

Состояние объекта класса ios (и производных от него) содержится в его закрытом элементе _state в виде набора битов (Таблица 11.2).

 

 

Таблица 11.2 биты состояния потока

Бит Описание
goodbit С потоком все в порядке (на самом деле это не какой-то бит, а 0 — отсутствие битов ошибки).
eofbit Показывает, что достигнут конец файла.
failbit Индицирует ошибку формата или преобразования. После очистки данного бита работа с потоком может быть продолжена.
badbit Индицирует серьезную ошибку потока, связанную обычно с буферными операциями или аппаратурой. Скорее всего, поток далее использовать невозможно.

 

Для опроса или изменения состояния потока в классе ios имеется ряд функций и операций.

- int rdstate(); Возвращает текущее состояние.

- bool eof(); Возвращает true, если установлен eofbit.

- bool good(); Возвращает true, если не установлен ни один из битов ошибки.

- bool fail(); Возвращает true, если установлен failbit или badbit.

- bool bad(); Возвращает true, если установлен badbit.

- void clear(int = 0); Сбрасывает биты ошибки (по умолчанию) или устанавливает состояние потока в соответствии с аргументом.

- void setstate(int); Устанавливает состояние битов ошибки с соответствии с аргументом.

- operator void *(); Возвращает нулевой указатель, если установлен какой-либо из битов ошибки.

- bool operator !(); Возвращает true, если установлен какой-либо из битов ошибки.

 

Файловые потоки

Файловые потоки библиотеки ввода-вывода реализуют объектно-ориентированную методику работы с дисковыми файлами. Имеется три класса таких потоков:

- ifstream специализирован для ввода из дисковых файлов.

- ofstream специализирован для записи дисковых файлов.

- fstream управляет как вводом, так и записью на диск.

 

Эти классы выводятся соответственно из istream, ostream и iostream. Таким образом, они наследуют все их функциональные возможности (перегруженные операции ”<<” и ”>>” для встроенных типов, флаги форматирования и состояния, манипуляторы и т.д.).

Чтобы работать с файловым потоком, нужен, во-первых, объект потока, а во-вторых, открытый файл, связанный с этим объектом.

 

Каждый из трех классов файловых потоков имеет четыре конструктора.

- Конструктор, создающий объект без открытия файла:

- ifstream();

- ofstream();

- fstream();

- Конструктор, создающий объект, открывающий указанный файл и закрепляющий этот файл за потоком. Аргументами являются имя файла, режим открытия и режим защиты (в Windows не используется);

- ifstream(const char *name, int mode=ios::in, long prot=0666);

- ofstream(const char *name, int mode=ios::out, long prot=0666);

- fstream(const char *name, int mode, long prot = 0666);

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

- ifstream(int file);

- ofstream(int file);

- fstream(int file);

- Конструктор, создающий объект и связывающий с ним уже открытый файл; объект ассоциируется указанным буфером:

- ifstream(int file, char *buf, int len);

- ofstream(int file, char *buf, int len);

- fstream(int file, char *buf, int len);

 

При использовании конструктора, создающего объект без открытия файла, необходимо дополнительно вызвать метод open(), который позволяет открыть файл с удобным для нас вариантом задания параметров.

Режимы открытия файла

Параметр mode, который имеет вторая форма конструктора, задает режим открытия файла. Для значений параметра класс ios определяет символические константы, перечисленные в таблице 11.3.

 

Таблица 11.3. Константы класса ios для режимов открытия файла

Константа Описание
арр Открытие для записи в конец файла.
ate При открытии позиционирует указатель на конец файла.
binary Файл открывается в двоичном (не текстовом) режиме.
in Файл открывается для ввода.
out Файл открывается для вывода.
trunc Если файл существует, его содержимое теряется.

 

Константы можно комбинировать с помощью поразрядного OR. Для конструкторов классов ifstream и ofstream параметр mode имеет значения по умолчанию – соответственно ios::in и ios::out.

Закрытие файла

В классах файловых потоков имеется функция close(), которая сбрасывает содержимое потока и закрывает ассоциированный с ним файл.

Кроме того, деструктор потока автоматически закрывает файл при уничтожении объекта потока.

При ошибке закрытия файла устанавливается флаг failbit.