Программа 39. Анализ успеваемости

В данном примере речь идет об анализе успеваемости некоторой студенческой группы в одну из экзаменационных сессий. Программа создает файл, содержащий фамилии студентов и их оценки за 4 экзамена. Пусть экзаменационная оценка может иметь 4 значения: неуд, уд, хор и отл, в этом случае для ее кодирования достаточно двух бит, так как с помощью двух бит можно создать 4 комбинации. В программе объявлена структура marks с четырьмя полями шириной по 2 бита, которые могут содержать значения оценок. Таким образом, все 4 оценки студента можно разместить в одном байте.

Для хранения как фамилии студента, так и его оценок используется структура student.

Предусмотрены два режима работы программы. Если первую строку программы записать в виде

# define EXIST_FILE 0 // Нет файла с результатами сессии

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

# define EXIST_FILE 1 // Имеется файл с результатами сессии

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

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

// Файл Progress.cpp

# define EXIST_FILE 0 // Нет файла с результатами сессии

/* Макрос EXIST_FILE устанавливается в нуль,

если создается новый файл, и в единицу, если файл существует */

struct marks {

unsigned ex1: 2; // Целое значение после

unsigned ex2: 2; // двоеточия – это ширина поля в битах

unsigned ex3: 2;

unsigned ex4: 2;

};

struct student{

char fam[20]; // fam - стpока для фамилии

marks rez; // rez - поле с оценками

};

enum numbers{neud = 0, ud = 1, hor = 2, otl = 3};

/* Пеpечисление numbers вводит имена для заданных

целых значений */

#include <iostream.h>

// prn_mrk: печать оценки в словесной форме

void prn_mrk(int mrk)

{

mrk == neud ? cout << "неуд " : mrk == ud ? cout << "уд " :

mrk == hor ? cout << "хор " : cout << "отл ";

}

#include <stdlib.h>

#include <fstream.h>

#include <conio.h>

void main()

{

student st;

int m1, m2, m3, m4, i;

char filename [20]; // Массив для имени файла

fstream f; // Файловый поток

cout << "\n Программа анализа результатов сессии \n";

cout << "Введите имя файла \n";

cin.getline(filename, 20);

#if EXIST_FILE // Если файл существует

f.open(filename, ios::in|ios::binary); // Файл открывается на чтение

// как бинарный

if(!f){ // Если файл открыть не удалось

cerr << " Файл не найден \n";

exit(1); // завершение программы

}

#endif

#if !EXIST_FILE // Если файла пока нет

f.open(filename, ios::in|ios::out|ios::binary); // Файл открывается на

// чтение и запись как бинарный

if(!f){ // Если файл открыть не удалось

cerr << " Ошибка открытия файла \n";

exit(1); // завершение программы

}

cout << "Вводите фамилии студентов и их оценки "

"в виде чисел (2, 3, 4, 5). \n"

"Разделитель - пробел, конец ввода Ctrl+Z.\n";

while(cin >> st.fam >> m1 >>m2 >>m3 >> m4){ // Пока не достигнут

// конец входного потока

st.rez.ex1 = m1 - 2; // Оценки хранятся в виде,

st.rez.ex2 = m2 - 2; // уменьшенном на две единицы,

st.rez.ex3 = m3 - 2; // так как отведенные для них поля

st.rez.ex4 = m4 - 2; // могут хранить значения только от 0 до 3

// Запись информации о студенте в файл

f.write((char*)(&st), sizeof(student));

}

#endif

f.seekg(0, ios::beg); // Переход к началу файла

cout << "\n РЕЗУЛЬТАТЫ СЕССИИ \n";

// Чтение и печать содержимого файла

while(f.read((char*)&st, sizeof(student)) != NULL){

cout << st.fam << ": " << st.rez.ex1 + 2 << ", " << st.rez.ex2 + 2

<< ", "<< st.rez.ex3 + 2 << ", " << st.rez.ex4 + 2;

cout << "(";

prn_mrk(st.rez.ex1); // Печать оценок

prn_mrk(st.rez.ex2); // в словесной форме

prn_mrk(st.rez.ex3);

prn_mrk(st.rez.ex4);

cout << ")\n";

}

f.close();

getch();

}

Далее приведены результаты двух запусков программы. Первый запуск был сделан в предположении, что файл данных не существовал
(# define EXIST_FILE 0):

Пpогpамма анализа результатов сессии

Введите имя файла

rezstud.cpp

Вводите фамилии студентов и их оценки в виде чисел (2, 3, 4, 5).

Разделитель - пробел, конец ввода Ctrl+Z.

Иванов 3 4 5 3

Петров 4 4 3 5

Сидоров 4 4 5 4

^Z

РЕЗУЛЬТАТЫ СЕССИИ

Иванов: 3, 4, 5, 3( уд хор отл уд )

Петров: 4, 4, 3, 5( хор хор уд отл )

Сидоров: 4, 4, 5, 4( хор хор отл хор )

Второй запуск был сделан в предположении, что файл данных уже создан (# define EXIST_FILE 1):

Пpогpамма анализа результатов сессии

Введите имя файла

rezstud.cpp

РЕЗУЛЬТАТЫ СЕССИИ

Иванов: 3, 4, 5, 3( уд хор отл уд )

Петров: 4, 4, 3, 5( хор хор уд отл )

Сидоров: 4, 4, 5, 4( хор хор отл хор )

Задачи 167-174. Структуры

167. Дополните программу 36 выводом статистики, то есть общего количества прочитанных слов, числа различных ключевых слов, встреченных в тексте и количества ключевых слов, не вошедших в текст.

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

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

170. Объединение из программы 38 позволяет получать различные значения числа с плавающей точкой путем изменения отведенных под него байтов. Напишите программу, реализующую такой способ задания чисел с плавающей точкой и установите внутреннее представление и значение наибольшего и наименьшего положительного числа типа float.

171. Напишите программу для установления внутреннего представления и значения наименьшего числа типа float и наименьшего по модулю отрицательного числа того же типа.

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

173. Напишите программу для установления внутреннего представления и значения наименьшего отрицательного числа типа double и наименьшего по модулю отрицательного числа этого типа.

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

Глава 15. Классы

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

Классы являются инструментом объектно-ориентированного программирования, в котором во главе угла стоят данные.

Класс – это определяемый пользователем тип. Тип является конкретным представлением некоторой концепции. Например, встроенный тип float вместе с операциями +, -, *, / представляет конкретное воплощение математической концепции вещественного числа. Новые типы создаются для определения концепции, не выражаемой непосредственно встроенными типами.

15.1. Структуры в C++. Инкапсуляция

В языке C++ в состав структур могут входить не только данные, как это имеет место в языке C, но и функции. Объединение в структуре и данных и функций для их обработки называется инкапсуляцией. Достоинством инкапсуляции является полное описание модели в одном месте, что упрощает работу с моделью. Функции, входящие в структуру, имеют непосредственный свободный доступ к данным, хранящимся в структуре.

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

Наши рекомендации