Конструкторы и присваивание строк

В классе string определено несколько конструкторов. Ниже в упрощенном виде приведены заголовки наиболее употребительных:

string( );

string(const char * );

string(const char *, int n);

string(string &);

Первый конструктор создает пустой объект класса string, второй - объект класса string на основе С-строки, третий - объект класса string из n символов строки, указанной первым параметром. Последний конструктор является конструктором копирования, который создает новый объект как копию объекта, переданного ему в качестве параметра.

В классе string определены три операции присваивания:

string& operator=(const string& str);

string& operator=(const char* s);

string& operator=(char c);

Таким образом, строке можно присваивать другую строку класса string, С-строку или отдельный символ, например:

string s1;

string s2("Вася");

string s3(s2);

s1 = 'X';

s1 = "Вася";

s2 = s3;

Размеры строк устанавливаются автоматически так, чтобы объект мог содержать присваиваемое ему значение.

Операции

В таблице 1.6 приведены допустимые для объектов класса string операции:

Таблица 1.6 - Операции класса string.

Операция Действие Операция Действие
= присваивание > больше
+ конкатенация >= больше или равно
== равенство [ ] индексация
!= неравенство << вывод
< меньше >> ввод
<= меньше или равно += добавление

 

Применение данные операций со строками класса string аналогично тому, как это делается со стандартными типами. Использование некоторых операций (присваивания, конкатенации, сравнения) уже было рассмотрено ранее.

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

Присваивание и добавление частей строк

Для присваивания части одной строки другой служит функция assign:

assign(const string& str);

assign(const string& str, size_type pos, size_type n);

assign(const char* s, size_type n);

Первая форма функции присваивает строку str вызывающей строке (действие функции эквивалентно операции присваивания):

string s1("Вася"), s2;

s2.assign(s1); // Равносильно s2 = s1;

Вторая форма присваивает вызывающей строке n символов строки str, начиная с позиции pos. Если pos + n больше, чем длина строки, записываются все символы до конца строки. Если pos больше длины строки, порождается исключение out_of_range.

Третья форма присваивает вызывающей строке n первых символов C-строки s.

Для добавления части одной строки к другой служит функция append:

append(const string& str );

append(const string& str, size_type pos, size_type n);

append(const char* s, size_type n);

Первая форма функции добавляет строку str к концу вызывающей строки (действие функции эквивалентно операции конкатенации +).

Вторая форма добавляет к вызывающей строке n символов строки str, начиная с позиции pos. Если pos + n больше, чем длина строки, записываются все символы до конца строки. Если pos больше длины строки, порождается исключение out_of_range. Если длина результата больше максимально допустимой длины строки, порождается исключение length_error.

Третья форма добавляет к вызывающей строке n первых символов C-строки s.

Преобразования строк

Для вставки в одну строку части другой строки служит функция insert:

insert(size_type pos1, const string& str );

insert(size_type posl, const string& str, size_type pos2, size_type n);

insert(size_type pos, const char* s, size_type n);

Первая форма функции вставляет в вызывающую строку, начиная с позиции posl, строку str. Таким образом, вызывающая строка замещается строкой, состоящей из первых pos1 символов вызывающей строки, за которыми следует строка str целиком, а после нее располагаются остальные символы вызывающей строки.

Если pos1 больше длины строки, порождается исключение out_of_range. Если длина результата больше максимально допустимой длины строки, порождается исключение length_error.

Вторая форма функции вставляет в вызывающую строку, начиная с позиции posl, n символов строки str, начиная с позиции начиная с позиции pos2. Таким образом, вызывающая строка замещается строкой, состоящей из первых pos1 символов вызывающей строки, за которыми следуют n элементов строки str, начиная с позиции pos2, а после них располагаются остальные символы вызывающей строки.

Если n больше длины строки str, строка копируется от позиции pos2 до конца.. Если posl или pos2 больше длины соответствующей строки, порождается исключение out_of_range. Если длина результата больше максимально допустимой длины строки, порождается исключение length_error.

Третья форма функции вставляет в вызывающую строку, начиная с позиции pos, n символов С-строки s.

Для удаления части строки служит функция erase:

erase(size_type pos = 0, size_type n = npos);

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

Величина npos является статическим членом класса string и представляет собой самое большое положительное число типа size_type.

Очистку всей строки можно выполнить с помощью функции clear:

void clear( );

Для замены части строки служит функция replace:

replace(size_type pos1, size_type n1, const string& str);

replace(size_type pos1, size_type n1, const string& str, size_type pos2, size_type n2);

replace(size_type pos1, size_type n1, const char* s, size_type n2);

Первая форма функции заменяет n1 символов вызывающей строки, начиная с позиции pos1, на строку str целиком.

Втрая форма функции заменяет n1 символов вызывыающей строки, начиная с позиции pos1, на n2 символов строки str, начиная с позиции pos2.

Если pos1 или pos2 больше длины соответствующей строки, порождается исключение out_of_range. Если длина результата больше максимально допустимой длины строки, порождается исключение length_error.

Третья форма функции заменяет nl символов вызывающей строки на n2 символов С-строки s.

Пример: использования функций изменения содержимого строк.

#include <string.h>

#include <iostream.h>

int main ( ){

string s1("прекрасная королева"), s2("лe"), s3("кopoвa");

cout << "s1= " << s1 << end;

cout << "s2= " << s2 << end;

cout << "s3= " << s3 << end;

cout << "после insert:" << end;

cout << "s3= " << s3.insert(4, s2) << end;

cout << "s3= " << s3.insert(7, "к") << end;

s1.erase(0,3);

cout << "после erase:" << end;

cout << "s1= " << s1.erase(12,2) << end;

cout << "после replace:" << end;

cout << "s1= " << s1.replace(0,3, s3, 4, 2) << end;

return 0; }

Результат работы программы:

s1= прекрасная королева

s2= ле

s3= корова

после insert:

s3= королева

s3= королевка

после erase:

s1= красная корова

после replace:

s1= лесная корова

Для обмена содержимого двух строк служит функция swap;

swap(string& s);

Функция обменивает содержимым вызывающую строку со строкой s.

Для выделения части строки служит функция substr:

string substr(size_type pos = 0, size_type n = npos) const;

Функция возвращает подстроку вызываемой строки длиной n, начиная с позиции pos. Если pos больше длины строки, порождается исключение out_of_range. Если n больше длины строки, возвращается весь остаток строки.

Для преобразования строки класса string в C-строку предназначены функции:

const char* c_str( ) const;

const char* data() const;

size_type сору (char* s, size_type n, size_type pos = 0) const;

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

Вторая функция при преобразовании не добавляет в конец строки нуль-символ.

Третья функция копируетв строку s n элементов вызывающей строки, начиная с позиции pos. Нуль-символ в результирующий массив не заносится. Функция возвращает количество скопированных элементов.

Операция сложения может конкатенировать объекты класса string не только между собой, но и с С-строками.

Пример: конкатенация С-строк и строк класса string.

#include <string.h>

#include <iostream.h>

int main ( ){

string s1( "hello" );

const char *pc = ", ";

string s2( "world" );

string s3 = s1 + pc + s2 + "\n";

return 0;

}

В данном примере компилятор автоматически преобразовывает С-строки в объекты класса string. Возможно и простое присваивание С-строки строке класса string:

string s1;

const char *pc = "a character array";

s1 = pc;

Обратное преобразование, однако, не работает. Попытка выполнить следующую инициализацию С-строки строкой класса string вызовет ошибку компиляции:

char *str = s1;

Чтобы осуществить такое преобразование, необходимо явно вызвать функцию c_str( ):

char *str = s1.c_str( ); // почти правильно

const char *str = s1.c_str( ); // правильно

Функция c_str( ) возвращает указатель на символьный массив, содержащий строку объекта string в том виде, в каком она находилась бы в С-строке.

Первый вариант (указатель char *) не совсем корректен, т.к. функция c_str( ) возвращает указатель на константный массив. Во втором варианте (указатель const char *) запрещена модификация содержимого объекта через этот указатель.

Для поиска предусмотрено большое разнообразие функций. Ниже приведены основные:

size_type find(const string& str, size_type pos = 0) const;

Ищет самое левое вхождение строки str в вызывающую строку, начиная с позиции pos, и возвращает позицию строки или npos, если строка не найдена.

size_type find(char с, size_type pos = 0) const;

Ищет самое левое вхождение символа с в вызывающую строку, начиная с позиции pos, и возвращает позицию символа или npos, если символ не найден.

size_type rfind(const str1ng& str, size_type pos = npos) const;

Ищет самое правое вхождение строки str в вызывающую строку, до позиции pos, и возвращает позицию строки или npos, если строка не найдена.

size_type rfind(char с, size_type pos = npos) const;

Ищет самое правое вхождение символа с в вызывающую строку, до позиции pos, и возвращает позицию символа или npos, если символ не найден.

size_type find_first_of(const string& str, size_type pos = 0) const;

Ищет самое левое вхождение любого символа строки str в вызывающую строку, начиная с позиции pos, и возвращает позицию символа или npos, если вхождение не найдено.

size_type find_first_of(char с, size_type pos = 0) const;

Ищет самое левое вхождение символа с в вызывающую строку, начиная с позиции pos, и возвращает позицию символа или npos, если вхождение не найдено.

size_type find_last_of(const string& str, size_type pos = npos) const;

Ищет самое правое вхождение любого символа строки str в вызывающую строку, начиная с позиции pos, и возвращает позицию символа или npos, если вхождение не найдено.

size_type find_last_of(char с, size_type pos = npos) const;

Ищет самое правое вхождение символа с в вызывающую строку, начиная с позиции pos, и возвращает позицию символа или npos, если вхождение не найдено.

size_type find_first_not_of(const string& str, size_type pos = 0) const;

Ищет самую левую позицию, начиная с позиции pos, для которой ни один символ строки str не совпадает с символом вызывающей строки.

size_type find_first_not_of(char с, size_type pos = 0) const;

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

size_type find_last_not_of(const string& str, size_type pos = npos) const;

Ищет самую правую позицию до позиции pos, для которой ни один символ строки str не совпадает с символом вызывающей строки.

size_type find_last_not_of(char с, size_type pos = npos) const;

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

Для каждой функции существует вариант, позволяющий искать в заданной строке С-подстроки.

Пример: применение функций поиска.

#include <string.h>

#include <iostream.h>

int main ( ){

string s1("лecнaя королева"), s2("лe");

cout << "s1= " << s1 << end;

cout << "s2= " << s2 << end;

int i = s1.find(s2);

int j = sl.rfind(s2);

cout << "первое s2 в s1 " << i << end;

cout << "последнее s2 в s1" << j << end;

cout << "первое о в s1 " << s1.find ('o') << end;

cout << "последнее о в s1 " << s1.rfind ( 'о' ) << end;

cout << "первое в s1 " << s1.find_first_of("aбвгдe") << end;

cout << "последнее в s1 " << s1.find_last_of("aбвгдe") << end;

}

Результат работы программы:

s1= лесная королева

s2= ле

первое s2 в s1 0

последнее s2 в s1 11

первое о в s1 8

последнее о в s1 10

первое в s1 1

последнее в s1 14

Для сравнения строк целиком применяются перегруженные операции отношения, а если требуется сравнивать части строк, используется функция compare:

int compare(const string& str) const;

int compare(size_type pos1, size_type n1, const string& str) const;

int compare(size_type pos1, size_type n1,const string& str, size_type pos2. size_type n2) const;

Первая форма функции сравнивает две строки целиком и возвращает значение, меньшее 0, если вызывающая строка меньше str, равное нулю - если строки одинаковы, и большее нуля - если вызывающая строка больше. Эта форма является аналогом функции сравнения строк strstr библиотеки С.

Вторая форма функции сравнивает со строкой str n1 символов вызывающей строки, начиная с pos1.

Третья форма функции сравнивает n1 символов вызывающей строки, начиная с pos1, с подстрокой строки str длиной n2 символов, начиная с pos2.

Аналогичные формы функций существуют и для сравнения строк типа string с С-строками.

Пример: использование функции сравнения строк.

#include <string.h>

#include <iostream.h>

int main (){

string s1("лесная королева"), s2("лe"), s3("корова");

cout << "s1= " << s1 << end;

cout << "s2= " << s2 << end;

cout << "s3= " << s3 << end;

if (s2.compare(s3) > 0) cout << "s2 > s3 " << end;

if (s1.compare(7, 4, s3) < 0) cout << "s1[7-10] < s3 " << end;

if (s1.compare(7, 4, s3, 0, 4 ) == 0) cout << "s1[7-10] << s3[0-3] " << end;

}

 

Результат работы программы:

s1= лесная королева

s2= ле

s3= корова

s2 > s3

s1[7-10] < s3

s1[7-10] == s3[0-3]

Получение характеристик строки (длину строки и объем памяти, занимаемый строкой):

size_type size() const;

size_type length() const;

size_type max_size() const; // Максимальная длина строки

size_type capacity() const;

bool empty() const;

Первая и вторая функции вычисляют длину строки, при этом функция lengh учитывает нуль-символ, а функция size этого не делает. Четвертая функция вычисляет объем памяти, занимаемый строкой.

Функция empty проверяет, пуста ли строка.

Пример: вычисление длины строки.

#include <string.h>

int main ( ) {

string st( "Цена бутылки вина" );

cout << "Длина строки \"" << st << "\": " << st.size()

return 0;

}

Пример: вычисление длины строки.

#include <string>

int main ( ) {

string st( "Цена бутылки вина\n" );

cout << "Число символов в строке: " << st.size( ) <<endl;

cout << "Длина строки: " << st.lenght( );

cout << "Объем памяти: " << st.capacity( ) << " байт";

return 0;

}

Результат работы программы:

Число символов в строке: 17

Длина строки: 18

Объем памяти: 18 байт

Пример: проверка, является ли строка пустой.

#include <string.h>

int main ( ) {

string st2; // пустая строка

if (!st.size( )) cout << "пустая"; // проверка, не равен ли размер строки нулю

if (st.empty( )) cout << "пустая"; // применение специальной функции

return 0;

}

Доступ к символам строким

Обращение к отдельным символам для строк класса string возможно с помощью операции индексации.

Пример: заменить все точки символами подчеркивания.

#include <string.h>

int main ( ) {

string str( "fa.disney.com");

int size = str.size( );

for ( int i = 0; i < size; ++i )

if ( str[ i ] == '.' ) str[ i ] = '_';

return 0;

}

 

Для решения предыдущей задачи удобнее использовать функцию replace:

replace( str.begin( ), str.end( ), '.', '_' );

Данная функция заменяет символы, равные третьему параметру функции, на символы, равные четвертому параметру функции. В качестве первого и второго параметра должны быть переданы указатели на начало и на конец строки. Данные указатели возвращаются функциями begin и end соответственно.

Работать со строками класса string через указатели нельзя, т.к. для них не соблюдается соответствие между адресом первого элемента строки и именем, как для С-строк, т.е. &s[0] не равно s.

Кроме операции индексации, для доступа к элементу символу строки класса string определена функция at:

string s("Bacя");

cout << s.at(1); // Будет выведен символ а

Если индекс превышает длину строки, порождается исключение out_of_range.

 

Тема 1.20

Потоки и доступ к файлам

 

При вводе/выводе данные рассматриваются как поток байтов. Физически поток представляет собой файл или устройство (например, клавиатуру или дисплей).

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

Использовать потоки удобнее в простых случаях ввода/вывода, не требующих форматирования. Кроме того, потоковые операции можно переопределить для собственных классов. Ввод/вывод в стиле С удобнее использовать при форматированном выводе в программах, не использующих объектно-ориентированную технику.

В лекции 4 был рассмотрены оба способа для стандартного ввода/вывода (для ввода с клавиатуры и вывода на дисплей). В данной лекции рассматривается файловый ввод/вывод в стиле С. Файловые потоки C++ будут рассматриваться во второй части курса.

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

Открытие потока

Работа с потоком начинается с его открытия.Поток можно открыть для чтения и/или записи в двоичном или текстовом режиме.

Функция открытия потока имеет формат:

FILE* fopen(const char* filename, const char* mode);

Первый параметр функции - имя открываемого файла в виде С-строки, второй - С-строка, определяющая режим открыгия файла.

В качестве второго параметра могут указываться следующие значения:

"r" - открыть файл для чтения;

"w" - открыть пустой файл для записи (если файл существует, он стирается);

"а" - открыть файл для добавления информации в его конец;

"r+" - открыть файл для чтения и записи (файл должен существовать);

"w+" - открыть пустой файл для чтения и записи (если файл существует, он стирается);

"а+"- открыть файл для чтения и добавления информации в его конец.

Режим открытия может также содержать символы t (текстовый режим) или b (двоичный режим). По умолчанию устанавливается текстовый режим.

Данные режимы отличаются обработкой символов перехода на новую строку. В текстовом режиме комбинация символов «возврат каретки» и «перевод строки» (0x13 0x10) при вводе преобразуются в одиночный символ перевода строки (при выводе выполняется обратное преобразование). В двоичном режиме эти преобразования не выполняются.

При успешном открытии потока функция fopen возвращает указатель на предопределенную структуру типа FILE, содержащую всю необходимую для работы с потоком информацию, или NULL в противном случае.

Пример:

FILE * f = fopen("d:\\cpp\\data", "rb+");

Указатель f будет использоваться в дальнейших операциях с потоком. Его передают функциям ввода/вывода в качестве параметра.

В начале работы программы открываются пять потоков:

· стандартный поток ввода stdin,

· стандартный поток вывода stdout,

· стандартный поток вывода сообщений об ошибках stderr,

· стандартный дополнительный поток stdaux,

· стандартная поток печати stdprn.

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

Ввод/вывод в поток

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

С помощью функций setvbuf и setbuf можно управлять размерами и наличием буферов.

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

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

Операции ввода/вывода выполняются начиная с текущей позиции потока, которая определяется положением указателя потока.Указатель устанавливается при открытии на начало или конец файла (в соответствии с режимом открытия) и изменяется автоматически после каждой операции, ввода/вывода.

Текущее положение указателя можно получить с помощью функций ftel1 и fgetpos и задать явным образом с помощью функций fseek и fsetpos. Эти функции нельзя использовать для стандартных потоков.

Закрытие потока

Поток закрывается либо при завершении программы, либо явным образом с помощью функции:

int fclose(FILE*);

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

Обработка ошибок

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

К функциям обработки ошибок относятся, например, feof (функция, осуществляющая проверку на достижение конца файла) и terror (функция, осуществляющая проверку на ошибку ввода/вывода).

Функции ввода-вывода в стиле С (заголовочный файл stdio.h)

Очищение флага ошибок при работе с потоком

void clearerr(FILE *f);

Очищает флаги ошибок для потока f (флаги ошибок не сбрасываются, пока не будет вызвана одна из функций сlearerr, fseek, fsetpos или rewind).

Закрытие потока ввода/вывода

int fclose (FILE *f);

Функция закрывает поток ввода/вывода f.

Проверка на достижение конеца файла

int feof(FILE * f );

Функция возвращает EOF или значение, отличное от 0, если достигнут конец файла, в противном случае возвращает 0.

Возвращает код ошибки при работе с потоком

int ferror (FILE *f);

Функция возвращает целое, означающее код ошибки; 0 — отсутствие ошибки.

Запись данных из буфера

int fflush (FILE * f );

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

Чтение символа из потока

int fgetc(FILE * f );

Функция возвращает очередной символ в форме int из потока f. Если символ не может быть прочитан, то возвращается значение EOF.

Нахождение текущей позиции в файле

int fgetpos(FILE *f, fpos_t *pos);

Возвращает текущую позицию в файле, связанном с потоком f, и копирует значение по адресу pos. Это значение позднее может использоваться функцией fsetpos. Возвращаемое значение имеет тип fpos_t.

Чтение из потока в строку n символов

char *fgets(char *s, int n, FILE * f );

Читает не более n-1 байт из потока f в строку s, прекращая чтение при обнаружении символа новой строки или конца файла. Символ новой строки при чтении не отбрасывается, а помещается в конец строки. Прочитанная строка дополняется ограничителем строки ('\0'). При обнаружении ошибки или конца файла возвращается NULL, в противном случае — указатель на строку s.

Открытие потока ввода/вывода

FILE *fopen(const char *fname, const char *mode);

Открывает файл с именем fname для работы в режиме, указанном строкой mode. При успешном открытии возвращается указатель на поток (таким образом, полученный поток связывается с файлом), в противном случае — NULL.

Запись данных в поток в определенном формате

int fprintf (FILE *f, const char *fmt, ...);

Записывает в поток f переменные, список которых обозначен многоточием (...), в формате, указанном строкой fmt. Возвращает число записанных символов.

Запись символа в поток

int fputc(int ch, FILE *f);

Функция записывает символ ch в поток f. При ошибке возвращает значение EOF, иначе — записанный символ.

Запись строки символов в поток

int fputs(const char *s,FILE *f);

Записывает строку символов s в поток f. Символ конца строки в файл не записывается. При ошибке возвращает значение EOF, иначе — неотрицательное число.

Чтение данных из потока ввода

size_t fread (void *buffer, size_t size, size_t count, FILE *stream);

Считывает connt элементов size байтов в область, заданную указателем buffer, из потока stream. Функция возвращает количество прочитанных элементов, которое может быть меньше count, если при чтении произошла ошибка или встретился конец файла.

Открытие потока ввода/вывода

FILE *freopen(const char *fname, const char *mode, FILE * f );

Работает аналогично fopen, но предварительно закрывает поток f, если тот был ранее открыт.

Ввод из файла форматированных данных

int fscanf (FILE *f, const char *fmt [,par1, par2, ...]);

Вводит строку параметров par1, раr2 и т. д. в формате, определенном строкой fmt, из файла f. Возвращает число переменных, которым присвоено значение.

Перемещение позиции в файле относительно текущей

int fseek (FILE *f, long off, int org);

Перемещает текущую позицию в файле, связанном с потоком f, на позицию off, отсчитываемую от значения org, которое должно быть равно одной из трех констант, определенных в stdiо.h:

SEEK_CUR — от текущей позиции указателя,

SEEK_END — от конца файла,

SEEK_SET — от начала файла.

Перемещение текущей позиции в файле относительно его начала

int fsetpos(FILE *f, const fpos_t *pos);

Перемещает текущую позицию в файле, связанном с потоком f, на позицию *pos, предварительно полученную с помощью функции fgetpos.

Нахождение текущей позиции в файле

long int ftell(FILE *f);

Возвращает текущую позицию в файле, связанном с потоком f, как длинное целое.

Запись данных из заданного буфера в поток

size_t fwrite (const void *p, size_t size, size_t n, FILE * f );

Записывает n элементов длиной size байт из буфера, заданного указателем р, в поток f. Возвращает число записанных элементов.

Чтение символа из потока

int getc(FILE *f);

Возвращает очередной символ в форме int из потока f. Если символ не может быть прочитан, то возвращается значение EOF.

Печать сообщения об ошибке

void perror(const char *s);

печатает строку вида "s: error сообщение". Если значением s является NULL (строка пустая), то печатается только сообщение об ошибке. Cообщение определяется на основе значения глобальной переменной errno. Вывод производится в стандартный поток ошибок stderr.

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

int printf (const char *fmt, ...);

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

Запись символа в поток

int putc(int ch, FILE * f );

записывает символ ch в поток f. Возвращает записываемый символ, в случае ошибки - значение EOF. Работает полностью аналогично функции fputc.

Удаление файла

int remove(const char *filename);

удаляет существующий файл. В случае успеха возвращает нулевое значение, иначе – ненулевое.

Переименование файла

int rename(const char *oldname, const char *newname);

переименовывает существующий файл или папку. В случае успеха возвращает нулевое значение, иначе — ненулевое.

Очистка флагов ошибок при работе с потоком и переход к началу файла

void rewind(FILE *f);

очищает флаги ошибок в потоке f и устанавливает текущую позицию на начало файла.

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

int scanf(сonst char *fmt [,par1, par2, ...]);

вводит строку параметров par1, раr2, … в формате, определенном строкой fmt, со стандартного устройства ввода. Возвращает число переменных, которым присвоено значение.

Установка буферизации потока ввода/вывода

void setbuf(FILE *f, char *p);

устанавливает для потока f буфер ввода/выводаа , заданный указателем р. Размер буфера должен быть равен BUFSIZ. Если указатель р равен nul1, то буферизация отменяется.

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

void setvbuf (FILE *f, char *p, int mode, size_t size);

устанавливает для потока f буфер ввода/вывода, заданный указателем р. Параметр mode указывает режим, а size – размер буфера. В случае успеха возвращает нулевое значение, иначе – ненулевое. Параметр mode является целым, принимающим одно из значений: _IOFBF (полная буферизация), _IONBF (запрет буферизации) и _IOLBF (для вывода – построчная буферизация, т.е. опустошение буфера при записи в него символа новой строки).

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

int sprint(char *buffer, const char *format[, argument, ... ]);

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

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

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

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

Открытие потока двоичного ввода/вывода во временный файл

FILE *tmpfile(vold);

открывает временный файл в режиме двоичного ввода/вывода и возвращает указатель на поток.

Создание уникального имени файла

char *tmpnam(char *s);

создает уникальное имя файла, которое может быть успешно использовано как имя временного файла. Различные строки генерируются ТМР_МАХ (константа определена в файле stdio. h и равна 65535). Параметр s - либо 0, либо указатель на массив, состоящий не менее, чем из L_tmpnam символов (L_tmpnam определено в stdio.h). Если s равно 0, функция оставляет имя генерированного временного файла во внутреннем статическом объекте и возвращает указатель на этот объект. Если S не равно 0, функция помещает результат в указанный массив, и возвращает s.

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

int ungetc (int ch, FILE *f);

возвращает символ ch обратно во входной поток f. Возвращает ch, а с случае ошибки – значение EOF.

Запись данных в в поток в определенном формате

int vfprintf(FILE *stream, char *format, va_list arglist);

функция аналогична функции fprintf, но имеет доступ к указателю на список аргументов, а не к самому списку.

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

int vprintf(const char *format, va_list arglist);

функция аналогична функции printf, но имеет доступ к указателю на список аргументов, а не к самому списку.

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

int vsprintf(char *string, const char *format, va_list arglist);

функция аналогична функции sprintf, но имеет доступ к указателю на список аргументов, а не к самому списку.

Функции для работы с многобайтовыми символами

Для работы с символами, код которых превышает один байт (например, Unicode) предназначены функции fgetwc, fgetws , fputwc, fputws, fwprintf, fwscanf, getwc, putwc, swprintf, swscanf, ungetwc, vfwprintf, vswprintf, vwprintf , printf, wscanf.

Данные функции аналогичны функциям для работы с однобайтовыми символами, но принимают параметр типа wint_t. Этот тип является целочисленным типом для хранения символов расширенного набора (заголовочный файл wctype.h).

Например, функция чтения символа из потока fgetwc имеет формат, аналогичный формату функции fgetc, и отличается только типом возвращаемого значения:

wint_t fgetwc(FILE * f );

Функция возвращает очередной символ в форме wint_t из потока f. Если символ не может быть прочитан, то возвращается значение WEOF.

Пример:работа с потоками

В файле хранятся сведения о мониторах. В каждой строке указан тип, оптовая и розничная цены и примечание. Для простоты данные в каждой строке записаны единообразно: первые 20 символов занимает тип монитора, далее по 5 символов целые числа, представляющие оптовую и розничную цены, затем примечание длиной не более 40 символов.

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

#include <iostream.h>

#inclucle <stdio.h>

#include <stdlib.h>

#include <string.h>

int main( ){

FILE *fi, *fo;

if ((fi = fopen("d:\\c\\file.txt", "r")) == 0){

cout << "Ошибка открытия входного файла";

return 1;

}

if ((fo = fopen("d:\\c\\binfile.out", "w+b")) == 0){

cout << "Ошибка открытия выходного файла";

return 1;

}

const int dl = 80;

char s[dl];

struct {

char type[20];

int opt, rozn;

char comm[40];

} mon;

int kol = 0; // Количество записей в файле

while (fgets(s, dl,fi)){ // Преобразование строки в структуру

strncpy(mon.type, s, 19);

mon.type[19]='\0';

mon.opt = atoi(&s[20]);

mon.rozn = atoi(&s[25]);

strncpy(mon.comm, &s[30], 40);

fwrite(&mon, sizeof mon, 1, fo);

kol++;

}

fclose(fi);

int i;

cin >> i; // Номер записи

if (i >= kol){

cout << "Запись не существует";

return 1;

}

fseek(fo, (sizeof mon)*i, SEEK_SET); // Установка указателя текущей

// позиции файла на запись i

fread(&mon, sizeof mon, 1, fo);

cout << "type " << mon.type << " opt " << mon.opt << " rozn " << mon.rozn << endl;

fclose(fo); return 0; }

Тема 1.21