Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Программирование задач с применением структурированных данных. Лабораторный практикум.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
1 Мб
Скачать
☆
v.erase(v.begin()); //Содержимое v: 2 3 4 5
v.erase(v.begin(), v.begin() + 2); //Содержимое v: 4 5
Следует обратить внимание, что вторым параметром задается не послед­ний удаляемый элемент, а элемент, следующий за ним.
Функция swap служит для обмена элементов двух векторов одного типа, но необязательно одного размера:
vector <int> v1, v2;
…
v1.swap(v2); //Эквивалентно v2.swap(v1)
Для векторов определены операции сравнения ==, !=, <, <=, > и >=. Два вектора считаются равными, если равны их размеры и все соответствующие па­ры элементов. Один вектор меньше другого, если первый из элементов одного вектора, не равный соответствующему элементу другого, меньше него (то есть сравнение лексикографическое).
Для эффективной работы с векторами в стандартной библиотеке опреде­лены шаблоны функций, называемые алгоритмами. Они включают в себя поиск значений, сортировку элементов, вставку, замену, удаление и другие операции.

9.2. Общие сведения о модулях

Имена программных элементов, таких как переменные, функции, классы и т. д., должны быть объявлены до их использования. Например, нельзя просто написать x = 42 без первого объявления "x".
Объявление указывает компилятору, является ли элемент переменной, функцией классом или какой-либо другой конструкцией. Кроме того, каждое имя должно быть объявлено (прямо или косвенно) в каждом CPP-файле, в ко­тором оно используется. При компиляции программы каждый CPP-файл ком­пилируется независимо в единицу компиляции. Компилятор не знает, какие имена объявляются в других единицах компиляции. Это означает, что если про­граммист определяет класс или функцию или глобальную переменную, необхо­димо предоставить объявление этой конструкции в каждом дополнительном CPP-файле, который использует его. Каждое объявление этой конструкции должно быть точно идентичным во всех файлах. Небольшое несоответствие приведет к ошибкам, когда компоновщик попытается объединить все блоки компиляции в одну программу.
Чтобы свести к минимуму вероятность ошибок, C++ принял соглашение об использовании файлов заголовков для хранения объявлений. Программист делает объявления в файле заголовка, а затем использует директиву #include в каждом CPP-файле или другом файле заголовка, который требует этого объяв­ления. Директива #include вставляет копию файла заголовка непосредственно в CPP-файл перед компиляцией.
141
В следующем примере показан распространенный способ объявления класса и последующего использования его в другом исходном файле.
Сначала следует создать файл заголовка – my_class.h Он содержит опре­деление класса, но следует обратить внимание, что определение является не­полным; функция-метод do_something не определена:
// my_class.h
namespace N
{
class my_class
{
public:
void do_something();
};
}
Затем следует создать файл реализации (обычно с расширением CPP или аналогичного расширения). Потом надо вызвать файл my_class.cpp и предоста­вить определение для объявления метода. Далее добавляют директиву #include для файла "my_class.h", чтобы объявление my_class было вставлено в этот в CPP-файл. Следует обратить внимание, что кавычки используются для файлов заголовков в том же каталоге, что и исходный файл, а угловые скобки исполь­зуются для заголовков стандартной библиотеки.
// my_class.cpp
#include "my_class.h" // header in local directory
#include <iostream> // header in standard library
using namespace N;
using namespace std;
void my_class::do_something()
{
cout << "Doing something!" << endl;
}
Теперь можно использовать my_class в другом CPP-файле. Для этого до­бавляют с помощью #include файл заголовка, чтобы компилятор извлекал нуж­ные объявление. Тогда компилятор будет знать, что my_class является классом, который имеет метод do_something().
// my_program.cpp
#include "my_class.h"
using namespace N;
int main()
{
my_class mc;
mc.do_something();
return 0;
}
142
Как правило, файлы заголовков имеют директиву #pragma once , чтобы убедиться, что они не вставляются несколько раз в один CPP-файл.
Так как файл заголовка может быть включен несколькими файлами, он не может содержать определения, которые могут создавать несколько определе­ний одного и того же имени. Следующие действия не допускаются или счита­ются некорректными:
– встроенные определения типов в пространстве имен или в глобальной области;
– определения функций, отличных от встроенных функций;
– определения переменных, отличных от const;
– агрегатные определения;
– безымянные пространства имен;
– директивы using.
Использование директивы using не обязательно приведет к ошибке, но может вызвать проблему, так как она добавляет пространство имен в область в каждом CPP-файле, который прямо или косвенно включает этот заголовок.

9.3. Пример программы на С++

Пример. Составить программу, формирующую сведения о студентах.
Каждый студент описывается с помощью класса, содержащего следую­щие поля:
– номер зачетки (ключ);
– ФИО студента;
– группа;
– курс.
Класс должен быть сохранен в двух файлах – заголовочном (.h) с описа­нием класса, и файлом (.cpp) с реализациями конструкторов и методов класса.
Данные хранятся в виде вектора.
Программа должна реализовывать следующие операции в виде отдельных функций или методов класса:
– формирование меню для выбора действия пользователем;
– ввод данных в вектор;
– вывод данных из вектора в виде таблицы;
– поиск элемента в векторе по ФИО студента (предусмотреть ввод части ФИО для поиска);
– редактирование элемента в векторе по указанному номеру зачетки;
– удаление элемента из вектора по заданному ключу;
– сортировка элементов в векторе по заданному полю.
143
Текст файла Students.h
//Файл Student.h содержит описание класса Student
#pragma once
#include<string>
#include <iostream>
class Student //Класс, описывающий студента
{
private:
std::string num_zach; //Номер зачетки
std::string fio; //ФИО студента
std::string gruppa; //Группа
int kurs; //Курс
public:
//Конструкторы класса
Student();
Student(const Student& obj);
Student(const std::string& _num_zach, const std::string& _fio, const std::string& _gruppa, int _kurs);
//Методы получения доступа к значениям полей класса
std::string get_num_zach() const;
std::string get_fio() const;
std::string get_gruppa() const;
int get_kurs() const;
//Методы для задания значений полей класса
void set_num_zach(std::string new_num_zach);
void set_fio(std::string new_fio);
void set_gruppa(std::string new_gruppa);
void set_kurs(int new_kurs);
//Метод для вывода содержимого полей класса на экран
void show() const;
};
144
Текст файла Students.cpp
//Файл Student.cpp - содержит реализацию методов класса Student
#include "Student.h"
using namespace std;
//Реализация конструкторов
Student::Student() : kurs(0) {}
Student::Student(const Student& obj) : num_zach(obj.num_zach), fio(obj.fio), gruppa(obj.gruppa), kurs(obj.kurs) {}
Student::Student(const string& _num_zach, const string& _fio, const string& _gruppa, int _kurs) : num_zach(_num_zach), fio(_fio), gruppa(_gruppa), kurs(_kurs)
{}
//Реализация методов получения доступа к значениям полей класса
string Student::get_num_zach() const { return num_zach; }
string Student::get_fio() const { return fio; };
string Student::get_gruppa() const { return gruppa; };
int Student::get_kurs() const { return kurs; };
//Реализация методов для задания значений полей класса
void Student::set_num_zach(string new_num_zach) { num_zach = new_num_zach; }
void Student::set_fio(string new_fio) { fio = new_fio; };
void Student::set_gruppa(string new_gruppa) { gruppa = new_gruppa; };
void Student::set_kurs(int new_kurs) { kurs = new_kurs; };
//Реализация метода для вывода содержимого полей класса на экран
void Student::show() const {
cout << "Номер зачетки : " << num_zach << endl;
cout << "ФИО : " << fio << endl;
cout << "Группа : " << gruppa << endl;
cout << "Курс : " << kurs << endl << endl;
}
145
Текст файла главной программы
// Файл главной программы
#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
#include <algorithm>
#include <Windows.h>
#include "Student.h"
using namespace std;
//Вектор, содержащий объекты класса Student
vector<Student> List;
void menu(); //Функция прорисовки меню
void hline(); //Функция, рисующая горизонтальную линию
//Функции-компараторы для разных полей объекта класса Student
bool comp_zach(Student a, Student b);
bool comp_fio(Student a, Student b);
bool comp_gruppa(Student a, Student b);
bool comp_kurs(Student a, Student b);
//Функция для поиска данных по ФИО студента
int find(vector<Student>L, string key);
void vvod(vector<Student>& L); //Функция ввода данных
void edit(vector<Student>& L); //Функция редактирования данных
void vivod(vector<Student>L); //Функция вывода данных
void search(vector<Student>L); //Функция поиска данных
void sortirovka(vector<Student>L); //Функция сортировки
void del(vector<Student>& L); //Функция удаления данных
//Главная функция программы
int main()
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
int n = 0;
//Цикл обработки действий пользователя
while (n != 7)
{
menu();
cin >> n;
146
switch (n)
{
case 1: vvod(List); break;
case 2: vivod(List); break;
case 3: edit(List); break;
case 4: search(List); break;
case 5: sortirovka(List); break;
case 6: del(List); break;
case 7: break;
default: cout << "Неверный вариант выбора" << endl;
}
}
}
//Реализация функции прорисовки меню
void menu()
{
cout << endl << " МЕНЮ " << endl;
cout << "1. Ввод данных" << endl;
cout << "2. Вывод данных" << endl;
cout << "3. Редактирование данных" << endl;
cout << "4. Поиск студента по ФИО" << endl;
cout << "5. Сортировка данных" << endl;
cout << "6. Удаление данных" << endl;
cout << "7. Выход" << endl;
cout << "Введите номер пункта меню для дальнейшей работы" << endl;
}
//Реализация функции поиска элемента по ключу
int find(vector<Student>L, string key) {
for (int i = 0; i < L.size(); i++)
{
if (L[i].get_num_zach() == key)
{
return i;
}
}
return -1;
}
//Функция-компаратор для сортировки вектора по номеру зачетки
bool comp_zach(Student a, Student b)
{
return a.get_num_zach() < b.get_num_zach();
}
147
//Функция-компаратор для сортировки вектора по ФИО студента
bool comp_fio(Student a, Student b)
{
return a.get_fio() < b.get_fio();
}
//Функция-компаратор для сортировки вектора по группе
bool comp_gruppa(Student a, Student b)
{
return a.get_gruppa() < b.get_gruppa();
}
//Функция-компаратор для сортировки вектора по курсу
bool comp_kurs(Student a, Student b)
{
return a.get_kurs() < b.get_kurs();
}
//Реализация функции ввода данных
void vvod(vector<Student>& L)
{
char choise; //Переменная для запоминания выбора пользователя
string num_zach, fio, gruppa; //Переменные для заполнения данных о студенте
int kurs;
while (true)
{
cout << "Введите номер зачетки" << endl;
while (cin.get() != '\n');
getline(cin, num_zach);
cout << "Введите ФИО студента " << endl;
getline(cin, fio);
cout << "Введите группу" << endl;
getline(cin, gruppa);
cout << "Введите курс" << endl;
cin >> kurs;
//Добавление нового элемента в вектор
L.push_back(Student(num_zach, fio, gruppa, kurs));
//Запрос подтверждения на ввод новой записи
while (true)
{
cout << "Продолжить ввод? Введите д - если да, н - если нет" << endl;
cin >> choise;
148
//Программа находится в режиме ожидания, пока пользователь не введет 'д' или 'н'
if (choise == 'д' || choise == 'н') break;
}
//Если пользователь ввел 'н', то выходим из цикла
if (choise == 'н') break;
}
}
//Реализация функции вывода данных
void vivod(vector<Student>L)
{
//Прорисовка шапки таблицы
cout << " Студенты " << endl;
hline();
cout << "| Номер зачетки | ФИО студента | Группа | Курс |" << endl;
hline();
//Вывод на экран элементов вектора
for (int i = 0; i < L.size(); i++)
{
cout << "| " << setw(13) << L[i].get_num_zach();
cout << " | " << setw(20) << L[i].get_fio();
cout << " | " << setw(10) << L[i].get_gruppa();
cout << " | " << setw(4) << L[i].get_kurs() << " |" << endl;
}
hline();
}
//Реализация функции редактирования элемента вектора
void edit(vector<Student>& L)
{
//Переменные для заполнения данных о студенте
string num_zach;
string fio, gruppa;
int kurs;
cout << "Введите номер зачетки для поиска" << endl;
while (cin.get() != '\n');
getline(cin, num_zach);
//Поиск по номеру зачетки студента в векторе
int ind = find(L, num_zach);
//Если нашелся студент - вывод найденных сведений и
//предложение отредактировать нужные поля
if (ind !=-1)
{
149
cout << endl << "Данные найдены" << endl;
L[ind].show();
cout << endl << "Введите новый номер зачетки или 0, если хотите оставить старый" << endl;
getline(cin, num_zach);
if (num_zach != "0")
L[ind].set_num_zach(num_zach);
cout << "Введите новые ФИО или 0, если хотите оставить старые" << endl;
getline(cin, fio);
if (fio != "0")
L[ind].set_fio(fio);
cout << "Введите новую группу или 0, если хотите оставить старую" << endl;
getline(cin, gruppa);
if (gruppa != "0")
L[ind].set_gruppa(gruppa);
cout << "Введите новый номер курса или 0, если хотите оставить старый" << endl;
cin >> kurs;
if (kurs != 0)
L[ind].set_kurs(kurs);
cout << endl << "Редактирование окончено" << endl;
}
else
cout << "Данные для редактирования не найдены" << endl;
}
//Реализация функции поиска студентов по ФИО
void search(vector<Student>L)
{
string fio;
cout << "Введите ФИО или часть ФИО для поиска" << endl;
while (cin.get() != '\n');
getline(cin, fio);
cout << endl << "Результаты поиска:" << endl;
for (int i = 0; i < L.size(); i++)
{
string fio_st = L[i].get_fio();
cout << fio_st << endl;
//Поиск введенной пользователем подстроки в ФИО текущего студента
//npos - максимально возможная позиция символа в строке +1
if (fio_st.find(fio) != fio_st.npos)
L[i].show();
}
150
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]