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

книги / Технологии разработки объектно-ориентированных программ на язык C++. Основы структурного программирования на алгоритмическом языке C++

.pdf
Скачиваний:
4
Добавлен:
12.11.2023
Размер:
3.17 Mб
Скачать

int main()

 

{

 

setlocale(LC_ALL, "rus");

 

ofstream file ("C:\game\F1.txt");

 

if (file.is_open())

// Вызов метода

is_open()

 

cout << " Файл открыт!" << endl;

else

cout << "Файл не открыт!” << endl; return 0;

}

При открытии файла для записи программа создаст пустой файл с этим именем, если по указанному адресу он не существует.

Запись в файл

Запись в файл происходит с помощью операторов «<<» и endl, что похоже на вывод на консоль, где вместо cin используется имя созданного объекта. Можно записывать строки, символы, числа:

ofstream file ("C:\game\F1.txt"); double one = 5.74;

file << “Hello ” << one << endl;

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

Для закрытия файла используется метод close(). Любой файл обязательно нужно закрывать, чтобы в программе не возникло ошибок.

Например:

file.close();

Методы форматирования

Методы форматирования используются для точной разметки данных, заносимых в файл. Метод width() указывает ширину вводимого числа в символах, а precision() – количество знаков дробной части вещественного числа. Если первым методом указано больше символов, чем занимает число, то остальное место будет автоматически занято пробелами.

111

Например:

file.width(15);

file.precision(5); file << 5.6782345; /*

Будет введено 5.67823, причем вначале допишутся пробелы до 15 символов

*/

13.2. Открытие файла для чтения. Работа с файлом в режиме чтения

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

ifstream file2 (“C:\game\F1.txt”);

После открытия файла для чтения необходимо проверить, открылся ли он. Это делается с помощью is_open() так, как описано выше.

Считывание из файла

Считывание из файла происходит разными способами. Первый способ – использование оператора «>>».

int one; double two; string three;

file2 >> one >> two >> three;

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

Второй способ – использование метода getline(). Этот метод считывает всю строку из файла до ее конца и заносит в переменную

112

типа string. В скобках указываются переменная, куда записываются данные, и количество символов для чтения. Если длина строки превысит допустимое количество, то чтение этой строки завершится.

string str; file2.getline(str, 20); cout << str << endl;

На экран консоли будет выведена первая строка файла. После этого курсор уже стоит на второй строке и можно считать ее. Так можно дойти до конца файла. Это удобнее всего делать в цикле с использованием метода eof(), который проверяет, не достигнут ли еще конец файла.

while (file2.eof()) { file2.getline(str, 20); cout << str << endl;

}

13.3. Режимы открытия

Режимы открытия файлов устанавливают характер использования файлов. Чтобы использовать определенный режим открытия, необходимо написать ключевое слово ios_base. Вот основные из них:

ios_base::in – открытие файля для чтения;

ios_base::out – открытие файла для записи;

ios_base::ate – перемещение указателя в конец файла при открытии;

ios_base::app – открытие файла для записи в конец файла;

ios_base::trunс – удаление содержимого файла при открытии;

ios_base::binary – открытие в двоичном режиме.

Объекты ofstream и ifstream автоматически включают соответствующие им режимы из первых двух. Остальные при необходимости можно указать после имени файла. Режимы можно комбинировать, записав их через «|»:

ofstream file("C:\game\F1.txt", ios_base::app| ios_base::trunс);

113

/*

Открываем файл для добавления информации к концу файла, удалив все содержимое

*/

Задания для самостоятельной работы:

Разработать и написать программу для выполнения следующей задачи: скопировать из файла F1 в файл F2 все строки, не содержащие букву А и расположенные между строками с номерами

N1 и N2.

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

114

Глава 14. ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ

Динамические структуры данных – это структуры данных, па-

мять под которые выделяется и освобождается по мере необходимости [4].

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

Например, надо проанализировать текст и определить, какие слова и в каком количестве в нем встречаются, причем эти слова нужно расставить по алфавиту. В таких случаях применяют данные особой структуры, которые представляют собой отдельные элементы, связанные с помощью ссылок. Каждый элемент (узел) состоит из двух областей памяти: поля данных и ссылок. Ссылки – это адреса других узлов этого же типа, с которыми данный элемент логически связан. В языке С++ для организации ссылок используются специальные переменные – указатели. При добавлении нового узла в такую структуру выделяется новый блок памяти и (с помощью ссылок) устанавливаются связи этого элемента с уже существующими. Для обозначения конечного элемента в цепи используются ссылки на область памяти NULL.

14.1. Одно- и двунаправленные списки

Линейный однонаправленный список (рис. 14.1) – это структура данных, состоящая из элементов одного типа, связанных между собой последовательно посредством указателей. Каждый элемент списка имеет указатель на следующий элемент. Последний элемент списка указывает на NULL. Элемент, на который нет указателя, является первым (головным) элементом списка [17].

Линейный двунаправленный список (рис. 14.2) – это структура данных, состоящая из последовательности элементов, каждый из которых содержит информационную часть и два указателя на со-

115

седние элементы. При этом два соседних элемента должны содержать взаимные ссылки друг на друга [19].

Рис. 14.1. Однонаправленный список

Рис. 14.2. Двунаправленный список

Реализация однонаправленного списка через структуры

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

Список в виде структуры имеет два поля: ключ – значение, которое будет хранить элемент списка, и указатель на следующий элемент списка.

struct List { // Структура список

int data; // Данные элемента списка

list* next; // Указатель на следующий элемент

};

Данная структура имеет имя list и содержит два поля: int data, list* next (указатель имеет тип list, так как указывает на эту же структуру)[11].

Создание списка:

// Функция создания списка из n элементов list* make_list(int n) {

list* first, *p; /*

first – указатель на первый элемент, p – с помощью

116

него добавляем еще элементы

*/

 

 

first =

NULL;

// Пока списка нет, first

 

 

указывает на NULL

cout <<

"Введите 1 элемент: ";

p = new

list;

// Выделение памяти для первого

элемента

 

 

cin >> p->data;

// Ввод элемента

first =

p;

// first указывает на первый

 

 

элемент

for (int i = 2; i <= n; i++) { list* h = new List;

// Выделение памяти под следующий элемент p->next = h;

/*

Присвоение указателю предшествующего элемента указателя на следующий элемент

*/

p = p->next; // Переход к следующему элементу cout << "Введите " << i << " элемент: ";

cin >> p->data; // Ввод нового элемента p->next = NULL; /* Указатель нового элемента

указывает на конец списка */

}

return first;

// Возвращение указателя на первый элемент списка

}

Подробнее: в строках 4–6 вводится первый элемент. Затем в цикле от 2 до n (начальное количество элементов в списке) вводятся остальные элементы. В строке 9 выделяется память для нового элемента. Затем в строке 10 указателю первого элемента присваивается указатель на только что созданный элемент, и в строке 11 осуществляется переход к следующему элементу. Указателю только введенного элемента присваивается NULL, так как он пока что является последним. В строке 16 возвращается указатель на первый элемент.

117

// Удаляем из памяти первый элемент

Вывод списка на экран:

void print_list(List*first) {

 

if (first == NULL) {

// Если список пуст

cout << "Список пустой\n";

 

}

 

List* p = first;

 

while (p != NULL) {

 

cout << p->data << " ";

// Вывод значения

 

элемента списка

p = p->next;

// Переход к следующему

 

элементу

}

 

cout << endl;

 

}

 

Подробнее: параметром передается указатель на первый элемент однонаправленного списка. В строке 2 выполняется проверка, пустой список или нет. В строке 6 указателю p присваивается указатель на первый элемент списка. В цикле (строки 7–10) выводятся значения каждого элемента списка, пока p не указывает на NULL.

Удаление четных элементов из списка:

void delete_element(List* &first) { List* p = first;

// p содержит указатель на первый элемент while (p->data % 2 == 0) {

/*

Если первый элемент четный и все последующие за ним тоже четные

*/

List* q = first;

// Сохранили указатель на первый элемент в переменную q

first = p->next;

//Теперь first указывает на второй элемент списка

delete q;

118

p = first;

/* Обнулили p (p указывает

 

на новый первый элемент

 

списка) */

if (p == NULL) return;

/* Так как больше элементов

 

нет, то выполнение функции

 

закончено */

}

 

while (p->next != NULL) {

 

if (p->next->data % 2 == 0) {

List* q = p->next; /* Сохранили указатель на удаляемый элемент */

p->next = p->next->next; /*

Указателю первого элемента присвоили указатель на третий элемент

*/ delete q;

}

else p = p->next;

}

}

Подробнее: параметром передается по ссылке указатель на первый элемент однонаправленного списка. В строке 2 начинается цикл while и выполняется, пока подряд идут четные числа. В строке 4 сохраняется указатель на первый элемент, а затем указателю first присваивается указатель на второй элемент и первый элемент списка удаляется из памяти. Если список состоит только из четных элементов, то функция прекращается (строка 8). Данный цикл удалит все первые четные элементы, а это значит, что следующий цикл (строка 10) начнется с нечетного числа и он будет выполняться, пока следующий элемент не будет NULL. Если за нечетным числом идет четное (строка 11), то элемент удаляется так же, как и в прошлом цикле, только вместо first используется p–>next, а вместо p–>next p–>next–>next (т.е. работа осуществляется с числом, стоящим после нечетного числа), а если за нечетным числом идет нечетное, то осуществляется переход указателя p к следующему числу (строка 16).

119

Добавление элементов в начало списка:

void add_begin(List* &first) { for (int i = 0; i < 3; i++) {

List* h = new List;

// Выделили память под новый

 

элемент

cout << "Введите " << i + 1 << " число: ";

cin >> h->data;

// Ввели значение

h->next = first;

/* Присвоили новому элементу

 

указатель на первый элемент

 

*/

first = h;

/* И наш новый элемент стал

 

первым элементом списка */

}

}

Подробнее: параметром передается по ссылке указатель на первый элемент однонаправленного списка. Тело цикла выполняется ровно три раза, так как необходимо добавить три числа в начало списка. В строке 3 выделяется память для нового элемента списка, затем вводится число (значение нового элемента). Указателю нового элемента присваивается указатель на первый элемент списка (строка 6), и указателю на первый элемент (first) присваивается указатель на новый элемент, т.е. новый элемент стал первым в списке.

Главная функция:

int main() {

 

setlocale(LC_ALL, "Rus");

 

int size;

// Количество элементов

 

в списке

cout << "Введите количество элементов: ";

cin >> size;

 

List* list = make_list(size);

// Создание списка

print_list(list);

// Печать списка

delete_element(list);

// Удаление четных чисел

 

из списка

cout << "Новый список: ";

 

print_list(list);

// Печать списка

120

Соседние файлы в папке книги