Лекции по информатике
  • Регистрация
1 1 1 1 1 1 1 1 1 1 Рейтинг 0.00 (0 Голоса)

В С++ каждый файл рассматривается как последовательный поток байтов. Каждый файл завершается или маркером конца файла (EOF – end-of-file) или указанным числом байтов, записанным в служебную структуру данных поддерживающей системой.

Когда файл открывается, то создается объект и с этим объектом связывается поток. С++ автоматически создает четыре объекта: cin, cout, cerr и clog. Потоки, связанные с этими объектами, обеспечивают каналы связи между программой и отдельными файлами или устройствами.

Для обработки файлов в С++ должны быть включены заголовочные файлы <iostream. h> и <fstream. h>. Файл <fstream. h> включает определения классов потоков Ifstream (для ввода из файла), Ofstream (для вывода в файл) и Fstream (для ввода-вывода файлов). Файлы открываются путем создания объектов этих классов потоков. Эти классы потоков являются производными (т. е. наследуют функциональные возможности) соответственно от классов Istream, Ostream и Iostream. Таким образом, соответствующие функции-элементы, операции и манипуляторы могут быть применены и к потокам файлов.

С++ не предписывает никакой структуры файлу. Программист должен задавать структуру файла в соответствии с требованиями прикладных программ.

При открытии файла конструктору объекта Ifstream, Ofstream или Fstream передаются два аргумента: имя файла и режим открытия файла. Для объекта Ofstream режим открытия файла может быть или Ios::Out для вывода данных в файл, или Ios::App – для добавления данных в конец файла без модификации уже имеющихся в файле данных. Существующие файлы, открываемые режимом Ios::Out, усекаются – все данные в файле отбрасываются. Если указанный файл не существует, он создается с заданным именем. Объявление

Ofstream outClientFile(“clients. dat”,ios::out)

Создает объект OutClientFile класса Ofstream, связанный с файлом Clients.Dat, который открывается для вывода.

Список режимов открытия файла приведен в таблице.

Таблица 1. Список режимов открытия файла

Ios::app

Записать все данные в конец файла

Ios::ate

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

Ios::in

Открыть файл для ввода

Ios::out

Открыть файл для вывода

Ios::trunk

Отбрасывать содержимое файла, если он существует (по умолчанию это выполняется и для ios::out)

Ios::nocreate

Если файл не существует, то операция его открытия не выполняется

Ios::noreplace

Если файл существует, то операция его открытия не выполняется

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

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

Для описанного выше файла clients. dat, с которым связан outClientFile, ввод значения переменной account из файла имеет вид:

OutClientFile >> account;

Вывод в файл имеет вид:

OutClientFile << account << “ “ << name << “ “ << balance;

В этом примере в файл записываются значения переменных account, name, balance, разделенные пробелами.

Ввод/вывод заканчивается, когда будет встречен признак конца файла. В операционной системе UNIX этому символу соответствует комбинация клавиш Ctrl+d, а в IBM PC и совместимых – Ctrl+z.

Функция-элемент Write класса Ostream выводит фиксированное число байтов, начиная с от заданного места в памяти, в заданный поток. Функция-элемент Read класса
Istream вводит фиксированное число байтов из заданного потока в область памяти.

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

Неформатированный ввод-вывод осуществляется с помощью функций-членов Get(), Put(), Read() И Write() соответствующих классов istream, ostream, iostream. При этом можно выделить два варианта организации: строко-ориентированный и символьный. Первый вариант удобен для работы с текстовыми файлами. Символьный ввод-вывод используется в первую очередь для работы с бинарными файлами.

В отношении базовых типов и символьных массивов по умолчанию установлены следующие стандартные правила форматирования:

Символы и строки символов выводятся в привычном виде;

Числа выводятся в десятичной системе счисления;

Знак у положительных чисел не выводится;

У целых чисел выводятся только значащие цифры (незначащие старшие нули отбрасываются);

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

В классе Ios объявлены флаги форматирования потока, которые позволяют изменить принятое по умолчанию представление данных. Устанавливать флаги форматирования можно с помощью функции Flags() – члена класса Ios. Новая совокупность флагов может быть получена с помощью операции | (побитного ИЛИ) и констант, приведенных ниже в таблице. С помощью функции Setf() можно устанавливать отдельные флаги.

Таблица 2. Некоторые флаги форматирования

Dec

Использовать десятичное представление

Fixed

Для вещественных чисел использовать представление с фиксированной точкой

Hex

Использовать шестнадцатеричное представление

Left

Прижимать к левому краю при выводе

Right

Прижимать к правому краю

Scientific

Для вещественных чисел использовать «научное» представление: порядок и мантисса, разделенные символом E или E

Showbase

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

Showpos

При выводе положительных чисел выводить знак «+»

Skipws

Пропускать пробельные символы при вводе

Uppercase

При выводе чисел использовать буквы верхнего регистра

Примеры ввода информации из файла и вывода информации в файл показаны при выполнении задачи 2 контрольной работы. В частности, в программе показано использование функций seekg, read и write при работе с файлами произвольного доступа.

Для вывода в файл «student. dat» 100 записей blankStudent используются функции:

Объявление файла (производится только вывод в файл):

ofstream inOutStudent("student. dat", ios::out);

//проверка

if (!inOutStudent) {

cerr << "Файл не может быть открыт" << endl;

exit(1);

}

STUDENT blankStudent = {0, " ", " ", " ", 0, (0,0,0,0,0)};

Запись:

for (int i=1;i<=100;i++)

inOutStudent. write((char *) &blankStudent, sizeof(blankStudent));

При выполнении задачи 2 производятся работы с тем же файлом «student. dat», однако теперь предусматривается как вывод в файл произвольного доступа, так и ввод данных из него. Соответственно объявление файла имеет вид:

Fstream inOutStudent("student. dat", ios::in|ios::out);

При обновлении содержимого записи вначале выполняется считывание записи из файла произвольного доступа «student. dat»:

updateFile. seekg((studNumber - 1)*sizeof(Student));

updateFile. read((char *) &Student, sizeof(Student));

А затем после изменения содержимого структуры Student она записывается обратно в файл произвольного доступа:

updateFile. seekp((studNumber - 1)*sizeof(Student));

updateFile. write((char *) &Student, sizeof(Student));

Задача 1

Создать структуру с именем Order, содержащую следующие поля:

Plat – расчетный счет плательщика;

Pol – расчетный счет получателя;

Summa – перечисляемая сумма в грн.

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

Ввод данных с клавиатуры в массив Spisok, состоящий из 6 элементов типа Order;

Вывод на экран данных о всех записях в массиве Spisok;

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

Программа использует заголовочные файлы <iostream. h> и <stdlib. h>, которые содержат описания объектов для работы с потоками.

Поскольку в Украине банковский счет может содержать до 14 цифр, то длина строк Plat и Pol принята равной 14. Объявление структуры имеет вид:

Struct ORDER {

char Plat[14];

char Pol[14];

double Summa;

В качестве синонима определен тип Order :

Typedef struct ORDER Order;

И две переменные этого типа:

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

cout << setiosflags(ios::right) << setw(3) << i << " "

<< setiosflags(ios::left) << setw(14) << Spisok[i].Plat << " "

<< setiosflags(ios::left) << setw(14) << Spisok[i].Pol << " "

<< setiosflags(ios::right) << Spisok[i].Summa << endl;

А вывод тех же данных с использованием функции printf имеет вид:

printf("%d %14s %14s %12.2f\n",

i, Spisok[i].Plat, Spisok[i].Pol, Spisok[i].Summa);

Листинг программы приведен на отдельном листе.

Order Spisok[6], BufRec;

Переменная Bufrec используется для временного хранения данных до занесения их в Spisok.

Листинг программы Contr1.cpp

// Создать структуру с именем Order, содержащую следующие поля:

// Plat - расчетный счет плательщика;

// Pol - расчетный счет получателя;

// Summa - перечисляемая сумма в грн.

// Написать программу, выполняющую следующие действия:

// - ввод данных с клавиатуры данных в массив Spisok, состоящий из

// 6 элементов типа Order

// - вывод на экран данных о всех записях в массиве Spisok

// - вывод на экран суммы, перечисляемой плательщиком, расчетный счет

// которого вводится с клавиатуры. Если такого плательщика нет,

// выдать сообщение об этом

#include <iostream. h>

#include <stdlib. h>

#include <iomanip. h>

// заголовочный файл стандартного С для наглядности форматирования

#include <stdio. h>

#include <string. h>

// объявление структуры

// в Украине банковский расчетный счет может содержать до 14 цифр

Struct ORDER {

char Plat[14];

char Pol[14];

double Summa;

};

// определяем новый тип с именем Order, как синоним

// типа struct ORDER

Typedef struct ORDER Order;

Order Spisok[6], BufRec;

Main()

{

int i, j, recNum, nr=6, result;

char bufPlat[14],bufPol[14], *buf;

double bufSumma;

// ввод данных

cout << "БУХГАЛТЕРСКИЕ ОПЕРАЦИИ" << endl;

cout << "Ввод информации" << endl;

for (i=0;i<=nr-1;i++)

{

cout << "Запись " << i << endl;

cout << "Плательщик -> ";

cin >> bufPlat;

cout << "Получатель -> ";

cin >> bufPol;

cout << "Перечисляемая сумма -> ";

cin >> bufSumma;

strcpy(Spisok[i].Plat, bufPlat);

strcpy(Spisok[i].Pol, bufPol);

Spisok[i].Summa=bufSumma;

};

// вывод на экран данных о всех записях в массиве Spisok

cout << "ДАННЫЕ ОБ ОПЕРАЦИЯХ\n";

cout << "N Плательщик Получатель Сумма\n";

for (i=0; i<=nr-1; i++)

{

// пример использования вывода С++

// cout << setiosflags(ios::right) << setw(3) << i << " "

// << setiosflags(ios::left) << setw(16) << Spisok[i].Plat << " "

// << setiosflags(ios::left) << Spisok[i].Pol << " "

// << setiosflags(ios::right) << Spisok[i].Summa << endl;

// вывод с использованием функций стандартного С

printf("%d %14s %14s %12.2f\n",

i, Spisok[i].Plat, Spisok[i].Pol, Spisok[i].Summa);

};

// поиск в массиве

// переменная result используется для подсчета найденных записей

// (плательщик может выполнить несколько платежей)

cout << "\nВЫДАЧА СПРАВОК\n";

cout << "Введите номер счета плательщика -> "; cin >> buf;

result=0;

for (i=0;i<=nr-1;i++)

{

if (strcmp(Spisok[i].Plat, buf) == 0)

{

cout << "Запись " << i << endl;

cout << "Получатель: " << Spisok[i].Pol << endl;

cout << "Сумма: " << Spisok[i].Summa << endl;

result++;

}

}

if (result == 0)

cout << "Записей не обнаружено\n";

return 0;

}

Задача 2

Написать программу, которая позволяет записывать, считывать, добавлять и изменять данные в файл произвольного доступа, содержащем информацию в виде структуры, содержащей сведения о студентах STUDENT с полями: Name – фамилия и инициалы, Group – номер группы, Session – массив из 5 оценок за сессию.

 

При использовании файла произвольного доступа рекомендуется структуру записей выбирать так, чтобы одно из полей для каждой записи имело уникальное значение (так называемое ключевое поле). В заданной структуре ни одно из полей не может быть ключевым (например, среди студентов могут быть однофамильцы и тезки, группа содержит более одного студента и т. д.). Поэтому заданную структуру дополним ключевым полем sNum – «номер студента». В качестве номера может быть использован номер зачетной книжки. Данное поле можно рассматривать и просто как номер записи. В любом случае в файле не должно быть записей с одинаковым значением ключевого поля. Запись с нулевым значением номера считается пустой.

Для удобства тестирования программа разбита на две части:

Создание файла произвольного доступа, содержащего 100 пустых записей (программа Cont02a. cpp);

Собственно программа работы с файлом произвольного доступа (Contr02.cpp).

Листинг программы Contr02a. cpp приведен на отдельном листе. В результате работы программы создается файл students. dat, содержащий 100 пустых записей.

Программа Contr02.cpp выводит на экран меню со списком возможных операций:

cout << endl << "Выберите операцию:" << endl

<< "1 - вывод данных" << endl

<< "2 - изменение записи" << endl

<< "3 - добавление записи" << endl

<< "4 - удаление записи" << endl

<< "5 - окончание работы" << endl << "? ";

В зависимости от выбора вызывается одна из следующих функций:

Void displayRecords(fstream&);

Void updateRecord(fstream&);

Void newRecord(fstream&);

Void deleteRecord(fstream&);

Void outputLine(ostream&,STUDENT);

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

Функция displayRecords выводит в стандартный поток cout сведения о всех записях. При этом вызывается функция void outputLine(ostream&,STUDENT). Одним из параметров функции является объект типа ostream. В данной программе в качестве потока вывода указан стандартныйпоток cout :

If (Student. sNum!= 0) outputLine(cout, Student);

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

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

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

Функция deleteRecord производит удаление записи. Удаление производится путем записывание пустой записи blankStudent на место заданной.

Листинг программы Contr02a. cpp

// Написать программу, которая позволяет записывать, считывать,

// добавлять и изменять данные в файле произвольного доступа,

// содержащем информацию в виде структуры, содержащей сведения о

// студентах STUDENT с полями: Name - имя студента, Group -

// номер группы, Session - массив из 5 оценок за сессию

// ЧАСТЬ 1 - СОЗДАНИЕ ФАЙЛА ПРОИЗВОЛЬНОГО ДОСТУПА

#include <iostream. h>

#include <fstream. h>

#include <stdlib. h>

// объявление структуры

Struct STUDENT {

int sNum; // номер студента или зачетки - для уникальности записи

char lastName[20];

char firstName[20];

char fathName[20];

int Group;

int Session[5];

};

Main()

{

ofstream inOutStudent("student. dat", ios::out);

//проверка

if (!inOutStudent) {

cerr << "Файл не может быть открыт" << endl;

exit(1);

}

STUDENT blankStudent = {0, " ", " ", " ", 0, (0,0,0,0,0)};

for (int i=1;i<=100;i++)

inOutStudent. write((char *) &blankStudent, sizeof(blankStudent));

return 0;

}

Листинг программы Contr02.cpp

// Написать программу, которая позволяет записывать, считывать,

// добавлять и изменять данные в файле произвольного доступа,

// содержащем информацию в виде структуры, содержащей сведения о

// студентах STUDENT с полями: Name - имя студента, Group -

// номер группы, Session - массив из 5 оценок за сессию

#include <iostream. h>

#include <fstream. h>

#include <iomanip. h>

#include <stdlib. h>

// объявление структуры

Struct STUDENT {

int sNum; // номер студента или зачетки - для уникальности записи

char lastName[20];

char firstName[20];

char fathName[20];

int Group;

int Session[5];

};

STUDENT Student, blankStudent = {0, " ", " ", " ", 0, (0,0,0,0,0)};

// вспомогательные функции

Int enterChoice(void); // выбор из меню

Void displayRecords(fstream&);

Void updateRecord(fstream&);

Void newRecord(fstream&);

Void deleteRecord(fstream&);

Void outputLine(ostream&,STUDENT);

Main()

{

fstream inOutStudent("student. dat", ios::in|ios::out);

//проверка

if (!inOutStudent) {

cerr << "Файл не может быть открыт" << endl;

exit(1);

}

int choice;

while ( ( choice = enterChoice() ) !=5) {

switch (choice) {

case 1:

displayRecords(inOutStudent);

break;

case 2:

updateRecord(inOutStudent);

break;

case 3:

newRecord(inOutStudent);

break;

case 4:

deleteRecord(inOutStudent);

break;

default:

cerr << "Неверно указан номер операции" << endl;

break;

}

inOutStudent. clear(); // сброс индикатора конца файла

}

return 0;

}

// выбор из меню

Int enterChoice(void)

{

cout << endl << "Выберите операцию:" << endl

<< "1 - вывод данных" << endl

<< "2 - изменение записи" << endl

<< "3 - добавление записи" << endl

<< "4 - удаление записи" << endl

<< "5 - окончание работы" << endl << "? ";

int menuChoice;

cin >> menuChoice;

return menuChoice;

}

Void displayRecords(fstream &dataFile)

{

dataFile. seekg(0);

STUDENT Student;

dataFile. read((char *) &Student, sizeof(Student));

while (!dataFile. eof()) {

if (Student. sNum!= 0) outputLine(cout, Student);

dataFile. read((char *) &Student, sizeof(Student));

}

}

// Изменение записи

Void updateRecord(fstream &updateFile)

{

int studNumber;

STUDENT Student;

do {

cout << "изменение: Введите номер студента (1 - 100): ";

cin >> studNumber;

} while (studNumber < 1 || studNumber > 100);

updateFile. seekg((studNumber - 1)*sizeof(Student));

updateFile. read((char *) &Student, sizeof(Student));

if (Student. sNum!=0) {

outputLine(cout, Student);

cout << endl << "Введите новые данные: номер группы и массив оценок: ";

int newGroup, newSession[5];

// для простоты вместо цикла указываем непосредственно элементы

// массива оценок

cin >> newGroup >> newSession[0] >> newSession[1]

>> newSession[2] >> newSession[3] >> newSession[4];

Student. Group=newGroup;

for (int i=0; i<=4; i++) Student. Session[i]=newSession[i];

outputLine(cout, Student);

updateFile. seekp((studNumber - 1)*sizeof(Student));

updateFile. write((char *) &Student, sizeof(Student));

}

else

cerr << "Запись номер " << studNumber << "не заполнена" << endl;

}

// добавление новой записи

Void newRecord(fstream &insertFile)

{

cout << "добавление: Введите новый номер студента (1 - 100): ";

int newNum;

cin >> newNum;

insertFile. seekg((newNum-1)*sizeof(Student));

STUDENT Student;

insertFile. read((char *) &Student, sizeof(Student));

if (Student. sNum == 0) {

cout << "Введите фамилию, имя и отчество студента: ";

cin >> Student. firstName >> Student. lastName >> Student. fathName;

cout << "Введите номер группы и массив оценок: ";

cin >> Student. Group >> Student. Session[0] >> Student. Session[1]

>> Student. Session[2] >> Student. Session[3] >> Student. Session[4];

Student. sNum = newNum;

insertFile. seekp((newNum-1)*sizeof(Student));

insertFile. write((char *) &Student, sizeof(Student));

}

else

cerr << "Номер " << newNum << " уже содержит информацию" << endl;

}

// удаление записи

Void deleteRecord(fstream &deleteFile)

{

cout << "Введите удаляемый номер студента (1 - 100): ";

int delNum;

cin >> delNum;

STUDENT Student;

deleteFile. seekg((delNum-1)*sizeof(Student));

deleteFile. read((char *) &Student, sizeof(Student));

if (Student. sNum!= 0) {

deleteFile. seekp((delNum-1)*sizeof(Student));

deleteFile. write((char *) &blankStudent, sizeof(Student));

cout << "Запись о студенте номер " << delNum << "удалена";

}

else

cerr << "Номер " << delNum << " не содержит информации" << endl;

}

// вывод строки с информацией о клиенте

Void outputLine(ostream &output, STUDENT s)

{

output << setiosflags(ios::right) << setw(4) << s. sNum << " "

<< setiosflags(ios::left) << s. firstName << " "

<< setiosflags(ios::left) << s. lastName << " "

<< setiosflags(ios::left) << s. fathName << " "

<< setw(4) << s. Group

<< "оценки: " ;

for (int i=0;i<=4; i++) output << s. Session[i] << " " ;

output<< endl;

}

Добавить комментарий


Защитный код
Обновить

По темам:

История Украины

Культурология

Высшая математика

Информатика

Охотоведение

Статистика

География

Военная наука

Английский язык

Генетика

Разное

Технологиеские темы

Украинский язык

Филология

Философия

Химия

Экология

Социология

Физическое воспитание

Растениевосдство

Педагогика

История

Психология

Религиоведение

Плодоводство

Экономические темы

Бухгалтерские темы

Маркетинг

Иностранные языки

Ветеринарная медицина

Технические темы

Землеустройство

Медицинские темы

Творчество

Лесное и парковое хозяйство