Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы разработки программ на языке С++ для систем информационной безопасности. Учебное пособие

.pdf
Скачиваний:
1
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
Ввод и вывод информации в файлы
71
14. ВВОД И ВЫВОД
ИНФОРМАЦИИ В ФАЙЛЫ
Файл – структура данных для хранения информации на устройствах долговременного хранения.
Все функции по обслуживанию файлов возлагаются на операционную систему. Чтобы выполнить чтение или запись данных из файла, прикладная программа должна реализовать следующие действия:
1. Открыть файл. Операция открытия заключается в том, что со сто-
роны программы операционной системы отправляется запрос, который со­держит имя файла, дополнительную информацию для доступа и выполнения операции. Операционная система по этому запросу пытается отыскать файл и проверяет допустимость выполнения запрошенных действий. Если файл существует и операции допустимы, то файл считается открытым для при­кладной программы (о чем она получает сообщение).
2. Если файл открыт, то посредством библиотечных функций чтения и
записи осуществляется обмен информацией с файлом. При записи информа­ции в общем случае не гарантируется ее мгновенная фиксация в файле на внешнем устройстве. Обычно записываемые данные сохраняются в промежу­точных системных буферах. Для явной записи необходимо вызвать соответ­ствующую функцию сохранения данных на устройство и очистки буфера.
3. После завершения работы с файлом он должен быть закрыт. Соот-
ветствующая функция отправляет запрос операционной системе, по кото­рому очищаются промежуточные буферы и при необходимости снимаются блокировки с файлов.
Примерная последовательность действий программы при использова­нии информации, хранимой в файле, приведена ниже.
1. Открыть входной файл и считать его содержимое в переменные про-
граммы.
2. Закрыть входной файл. Выполнить обработку, подготовить входные
данные.
3. Открыть выходной файл.
4. Записать выходные переменные в файл.
5. Закрыть выходной файл
14. Ввод и вывод информации в файлы
72
Таблица 47
Запись в файл функциями библиотеки С
FILE* f; F=fopen(“TextFile.txt”,”w”); If9f==NULL) printf(“\n File open error ! \n”); else { char Str[]=”Строка”; int Num=55; fprintf(f,”Строка для записи в файл = %s, число = %d”, Str, Num); fclose(f); }
В библиотеке С++ имеется несколько семейств функций ввода-вы­вода. В табл. 47 приведен пример программного кода записи данных в файл, который использует функции стандартной библиотеки языка С. В табл. 48 показан пример чтения данных.
Таблица 48
Чтение из файла функциями библиотеки С
f = fopen(“TextFile.txt”,”r”); if( f == Null) printf(“\n File open error ! \n”); else { charStr [100]; int Num; int res = fscanf(f,”%s%*s%*s%*s%*s%*s%*s%*s%*s%*s%d”,Str,&Num); fclose(f); }
Особенностью рассматриваемых библиотечных функций является ис­пользование форматной строки функциями fprintf и fscanf.
Альтернативным вариантом ввода-вывода в файлы может считаться набор функций библиотеки С++. Для встроенных типов не требуется фор­матная строка. Считается, что текст программы становится более понятным и естественным благодаря использованию операторов ввода-вывода.
14. Ввод и вывод информации в файлы
73
Таблица 49
Запись в файл функциями библиотеки С++
#include “stadfx.h” #include <fstream> #include <iostream> using namespace std;
int _tmain(int argc, _TCHAR* argv[]) { fstream OutFile;
OutFile.open(L”Экспериментально созданный файл.txt”,
ios_base::out); OutFile << endl <<”Строка вывода \n в этот файл“; OutFile << endl <<”Еще одна строка“ << endl; OutFile.close(); return 0; }
Рис. 17. Запись в файл функциями библиотеки С++
На рис. 17 показан пример программного кода записи в файл. Следует
обратить внимание на заголовочные файлы и наличие строки
using namespace std;
которая определяет пространство имен библиотеки С++. Переменная OutFile является объектом класса fstream. На врезке рис.17 показана подсказка MS Visual Studio, облегчающая использование класса fstream.
14. Ввод и вывод информации в файлы
74
Таблица 50
Чтение из файла функциями библиотеки С++
OutFile.open(L”Экспериментально созданный файл.txt”, ios_base::in); char Str1[100],Str2[100]; OutFile >> Str1; OutFile >> Str2;
return 0;
В табл. 50 показан пример чтения из файла. При чтении из файла с помощью оператора >> выполняется контроль типа переменной. Это озна­чает, что считываемые символы преобразуются к значению соответствую­щему типу переменной. Например, если считывается строка, в нее поме­щаются последовательно символы до тех пор, пока не будет встречен сим­вол-разделитель. По умолчанию таковым является пробел, запятая, точка с запятой, точка.
Обмен данными с файлом осуществляется функциями из библиотек С++ в основном на уровне встроенных типов С++. Более сложные объекты для сохранения в файл должны декомпозироваться на простые элементы. Рассмотрим эту процедуру на примере ввода данных, представляющих со­бой строки со специальным разделителем. В табл. 51 показаны две строки текстового файла, причем всякая строка файла имеет три поля, каждое из которых отделено символом #.
Таблица 51
Строки со специальным разделителем
Петров А.А.#12.12.1991#город Таганрог
Сидоров С.Л.#01.06.1996#село Несветайское
Программный код в табл. 52 позволяет ввести описанные данные в массив структурных переменных из 10 элементов. Для этого использованы методы getline класса fstream.
Все операции чтения и записи в файлах связаны с перемещением аб­страктного указателя файла. При открытии файла этот указатель помеща­ется в известную позицию, например, в начало. Любое чтение или запись, автоматически перемещают указатель в позицию, следующую за последним обработанным байтом. Это нужно учитывать, если программа считывает или
14. Ввод и вывод информации в файлы
75
записывает информацию в файл с произвольной позиции. Среди файловых функций имеются функции перемещения указателя.
Перемещение указателя в файле, открытом с помощью класса fstream, выполняется с использованием метода seekp. Метод включает два параметра: число со знаком, указывающее на количество позиций смещения (одна пози­ция – один байт) и константа класса, указывающая на «точку отсчета» смеще­ния (ios::end – относительно конца файла, ios::beg – относительно начала, ios::cur – относительно текущей позиции). В табл.51 показаны примеры под­сказки для установки нужной константы. Перемещение за пределы файла невоз­можно, указатель будет установлен соответственно в последней либо в первой позиции. Признак ошибки при этом не генерируется.
Таблица 52
Ввод строк со специальным разделителем из файла
struct { char Name[50]; char BDate[15]; char Place [50]; } User[10]; fstream InFile; InFile.open(L”NewFile.txt”, ios::in); int count = 0; while ( ! InFile.eof() && (count < 10 ) ) {
InFile.getline(User[count].Name,50,’#’); InFile.getline(User[count].BDate,15,’#’);
InFile.getline(User[count].Place,50); count++; } InFile.close();
При обработке текстов, находящихся в файлах, следует учитывать наличие «невидимых» символов, которые не отображаются пользователю, но используются при отображении текста на устройствах. Перемещение указа­теля в файле должно учитывать наличие таких символов (символы формати­рования имеют коды: OD – перевод строки, OA – возврат каретки). В табл. 52 показан фрагмент текста с параллельной 16-ричной кодировкой.
Для того чтобы сохранять в файлах объекты произвольных классов, необходимо организовать запись тех свойств, которые относятся к простым
14. Ввод и вывод информации в файлы
76
типам. Например, чтобы сохранить в файле объект класса string, следует с помощью метода c_str() получить указатель на строку в стиле С++, т.е. сим­вольный массив с нулевым ограничителем. Строка такого типа сохраняется в файле оператором <<. Аналогично любая структурная переменная записы- вается и считывается по отдельным полям.
Рис. 18. Константы направления перемещения указателя файла
Рис. 19. Символы текста и символы форматирования текста
Классы строк и строковых потоков
77
15. КЛАССЫ СТРОК И СТРОКОВЫХ ПОТОКОВ
Класс string является одним из типов, которые объявлены в заголовоч- ном файле string.
String – класс для обработки символьных строк. В отличие от масси­вов языка Си, в классе присутствует набор методов, облегчающих выполне­ние операций над массивами и делающих эту обработку более надежной. Вот некоторые достоинства класса:
• строка способна динамически изменять свою длину;
• строки допускают объединение с использованием оператора сумми-
рования (+);
• в классе имеются методы для поиска символов и фрагментов строк
в различных вариациях условий;
• имеются методы для выделения из строк фрагментов нужной длины
и с требуемой позицией.
Ниже приведен список некоторых полезных методов класса string:
Таблица 53
Методы класса string
• clear
Очищает строку от символов
• compare
Сравнивает строку с указанной
• empty
Возвращает признак того, что строка пуста
• find
Ищет заданную подстроку
• insert
Вставляет подстроку
• length
Возвращает число символов в строке
• replace
Заменяет указанные символы другими
• substr
Выделяет подстроку
15. Классы строк и строковых потоков
78
Помимо перечисленных выше методов на практике применяют ме-
тоды size(), resize(), append().
Метод size() возращает длину строки. Возвращаемое значение явля-
ется беззнаковым типом (как и во всех случаях, когда функция возращает значение, равное длине строке или индексу элемента – эти значения беззна­ковые). Поэтому нужно аккуратно выполнять операцию вычитания из зна­чения, которое возвращает size(). Например, ошибочной будет запись цикла, перебирающего все символы строки, кроме последнего, в виде for (int i = 0; i < S.size() – 1; ++i).
Кроме того, у строк есть метод length(), который также возвращает
длину строки.
Метод resize изменяет длину строки. К примеру, после применения S.resize(n) новая длина строки становится равна n. При этом строка может как уменьшиться, так и увеличиться. Если вызвать в виде S.resize(n, c), где c – символ, то при увеличении длины строки добавляемые символы будут равны c.
Метод append добавляет в конец строки несколько символов, другую строку или фрагмент другой строки. Имеет много способов вызова.
• S.append(n, c) – добавляет в конец строки n одинаковых символов,
равных с. n имеет целочисленный тип, c – char.
• S.append(T) – добавляет в конец строки S содержимое строки T.
T может быть объектом класса string или C-строкой.
• S.append(T, pos, count) – добавляет в конец строки S символы строки
T, начиная с символа с индексом pos количеством count.
Методы find может быть заменен на следующие частные методы:
• find_first_of – ищет в данной строке первое появление любого из
символов данной строки str. Возвращается номер этого символа или значе­ние string::npos.
Если задано значение pos, то поиск начинается с позиции pos, возра­щаемое значение будет не меньше, чем pos. Если значение pos не указано, то считается, что оно равно 0 – поиск осуществляется с начала строки.
S.find_first_of(str, pos = 0) – искать первое вхождение любого символа строки str начиная с позиции pos. Если pos не задано, то начиная с начала строки S.
• find_last_of
15.1. Конструкторы строк
79
Ищет в данной строке последнее появление любого из символов дан-
ной строки str. Способы вызова и возвращаемое значение аналогичны ме­тоду find_first_of.
• find_first_not_of
Ищет в данной строке первое появление символа, отличного от сим-
волов строки str. Способы вызова и возвращаемое значение аналогичны ме­тоду find_first_of.
• find_last_not_of
Ищет в данной строке последнее появление символа, отличного от символов строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
Строки можно объявлять и одновременно присваивать им значения:
string S1, S2 = "Hello,world";
Строка S1 будет пустой, строка S2 будет состоять из 11 символов.
15.1. Конструкторы строк
Строки можно создавать с использованием следующих конструк­торов:
• string()– конструктор по умолчанию (без параметров) создает пу-
стую строку.
• string(string & S) –копия строки S
• string(size_t n, char c) – повторение символа c заданное число n раз.
• string(size_t c) – строка из одного символа c.
• string(string & S, size_t start, size_t len) – строка, содержащая не бо-
лее, чем len символов данной строки S, начиная с символа номер start.
Конструкторы можно вызывать явно, например, так:
S + = string(10, 'a');
В этом примере явно вызывается конструктор string для создания строки, состоящей из 10 символов 'a'.
Неявно конструктор вызывается при объявлении строки с указанием дополнительных параметров. Например, так:
string S(10, 'a');
15. Классы строк и строковых потоков
80
15.2. Арифметические операторы
Со строками можно выполнять следующие арифметические опера-
ции:
= – присваивание значения; += – добавление в конец строки другой строки или символа; + – конкатенация двух строк, конкатенация строки и символа; ==, != – посимвольное сравнение; <, >, <=, >= – лексикографическое сравнение.
То есть можно скопировать содержимое одной строки в другую при по-
мощи операции S1 = S2, сравнить две строки на равенство при помощи S1 = S2, сравнить строки в лексикографическом порядке при помощи S1 < S2, или сделать сложение (конкатенацию) двух строк в виде S = S1 + S2.
Для ввода-вывода строк в файл допускается использовать операторы
>> и <<. В табл. 54 показан пример программного кода.
Полезным для программирования может оказаться использование строковых потоков. Обработка строковых потоков совершенно аналогична обработке файловых потоков. Использование привычного синтаксиса и освоенных обобщений, и соглашений дает возможность более эффективного программирования.
Таблица 54
Вывод объекта string в файл
string s; s=” String text “; fstream outFile; outFile.open(“TextOut.txt”,ios_base::out); if(!outFile.bad()) { outFile << s; } outFile.close();
В табл. 55 приведен программный код, формирующий строку даты через использование класса строкового потока.
Для использования функциональности класса строкового потока
stringstream необходимо включить соответствующий заголовочный файл (табл. 55).
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]