Сводная ведомость результатов экзаменационной сессии

Уровень сложности:

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

  • список студентов (ФИО);
  • список студентов, которые сдали все экзамены только на 5;
  • список студентов, которые имеют хотя-бы одну тройку по экзаменам;
  • список студентов, у которых есть двойки. Если студент, имеет более чем одну двойку, он исключается из списка.

Задачу решил Naikon, он, как всегда, впереди всех. Собственно, вот код:

#include <iostream>
#include <fstream>
#include <windows.h>
#include <vector>
using namespace std;
struct Student
{
    void fn_student_list()///Выводим список студентов
    {
        for(unsigned int i=0;i<vec_FIO.size();++i)cout<<vec_FIO[i]<<endl;
    }
    vector<string>vec_FIO;
    vector<int> vec_math,vec_physics,vec_chemistry,vec_geometry,vec_rus;
    void fn_student_exam_5()///Список студентов которые сдали все экзамены только на пять
    {
        bool five=false;
        for(unsigned int i=0;i<vec_FIO.size();++i)
        {
            unsigned int sum=0;
            if(vec_math[i]==5)sum+=5;
            if(vec_physics[i]==5)sum+=5;
            if(vec_chemistry[i]==5)sum+=5;
            if(vec_geometry[i]==5)sum+=5;
            if(vec_rus[i]==5)sum+=5;
            if(sum==25)
            {
                cout<<vec_FIO[i]<<endl;
                five=true;
            }

        }
        if(five==false)cout<<"Таких студентов нет :("<<endl;
    }
    void fn_student_exam_3()///Список студентов которые имеют хотя-бы одну тройку по экзаменам
    {
        bool three=false;
        for(unsigned int i=0;i<vec_FIO.size();++i)
        {
            unsigned int sum=0;
            if(vec_math[i]==3)sum++;
            if(vec_physics[i]==3)sum++;
            if(vec_chemistry[i]==3)sum++;
            if(vec_geometry[i]==3)sum++;
            if(vec_rus[i]==3)sum++;
            if(sum>=1)
            {
                cout<<vec_FIO[i]<<endl;
                three=true;
            }
        }
        if(three==false)cout<<"Таких студентов нет :("<<endl;
    }
    void fn_student_exam_2()///Список студентов у которых есть двойки
    {
        bool two=false;
        for(unsigned int i=0;i<vec_FIO.size();++i)///удаляем студентов у котороыъ больше одной двойки
        {
            int sum=0;
            if(vec_math[i]==2)sum++;
            if(vec_physics[i]==2)sum++;
            if(vec_chemistry[i]==2)sum++;
            if(vec_geometry[i]==2)sum++;
            if(vec_rus[i]==2)sum++;
            if(sum>=2)
            {
                vec_FIO.erase(vec_FIO.begin()+i);
                vec_math.erase(vec_math.begin()+i);
                vec_physics.erase(vec_physics.begin()+i);
                vec_chemistry.erase(vec_chemistry.begin()+i);
                vec_geometry.erase(vec_geometry.begin()+i);
                vec_rus.erase(vec_rus.begin()+i);
            }
        }
        for(unsigned int i=0;i<vec_FIO.size();++i)///Выводим список студентов
        {
            unsigned int sum=0;
            if(vec_math[i]==2)sum++;
            if(vec_physics[i]==2)sum++;
            if(vec_chemistry[i]==2)sum++;
            if(vec_geometry[i]==2)sum++;
            if(vec_rus[i]==2)sum++;
            if(sum>=1)
            {
                cout<<vec_FIO[i]<<endl;
                two=true;
            }
        }
        if(two==false)cout<<"Таких студентов нет :("<<endl;
    }
};
int main()
{
    Student student;
    string str,fstr;
    SetConsoleOutputCP(1251);
    int value,math,physics,chemistry,geometry,rus,number_of_students=0;
    ifstream in("file.txt");
    if(!in)///Если не смогли открыть файл
    {
        cout<<"Can't open file\n";
        return 1;
    }
    getline(in,str);
	while(in>>str)
    {
		fstr+=str+' ';
		for(int i=0;i<2;++i)
		{
			in>>str;
			fstr+=str+' ';
		}
        student.vec_FIO.push_back(fstr);
		fstr.clear();
		in>>math;
        student.vec_math.push_back(math);
		in>>physics;
        student.vec_physics.push_back(physics);
		in>>chemistry;
        student.vec_chemistry.push_back(chemistry);
		in>>geometry;
        student.vec_geometry.push_back(geometry);
		in>>rus;
        student.vec_rus.push_back(rus);
        number_of_students++;
        if(number_of_students==20)break;
    }
    in.close();///Закрыли файл
    start:cout<<"\n1. Список студентов (ФИО)"<<endl;
    cout<<"2. Список студентов которые сдали все экзамены только на пять."<<endl;
    cout<<"3. Список студентов которые имеют хотя-бы одну тройку по экзаменам."<<endl;
    cout<<"4. Список студентов у которых есть двойки."<<endl;
    cout<<"(если студент имеет больше одной двойки он исключается из списка)."<<endl;
    cout<<"5. Введите 'q' для выхода"<<endl;
    cout<<"Пожалуйста сделайте свой выбор: ";
    char c;
    cin>>c;
    switch(c)
    {
        case '1':
        {
            student.fn_student_list();
            goto start;
        }
        case '2':
        {
            student.fn_student_exam_5();
            goto start;
        }
        case '3':
        {
            student.fn_student_exam_3();
            goto start;
        }
        case '4':
        {
            student.fn_student_exam_2();
            goto start;
        }
        case 'q':
        {
                return 0;
        }
        default:
        {
            cout<<"Неверный ввод :( Попробуйте снова\n";
            goto start;
        }
    }
    return 0;
}

Как я успел увидеть, код платформо-зависимый, обратите внимание на заголовки, строка 3, там подключен файл <windows.h>. То есть, под линуксом уже такую программу сразу не скомпилируешь. Но из этой ситуации можно легко выбраться. В программе функция SetConsoleOutputCP(1251); для установки кодировки cp-1251, это необходимо, если в консоли появляются каракули вместо символов русского алфавита. Но в линуксе с отображением кириллицы в консоли все в порядке, а значит и эта функция не нужна. Так что, те, кто на линуксе работают, перед компиляцией программы, смело комментируйте строки 3 и 95, они вам не нужны.

Входные данные из файла:

  • Ф.И.О Алгебра Физика Химия Геометрия Русс. язык
  • Иванов И. И. 3 4 4 4 5
  • Карпов И. С. 5 5 5 5 3
  • Петров С. К. 3 3 4 4 3
  • Борзенков А. А. 4 4 4 4 4
  • Константинов П. П. 5 5 5 5 5

Смотри на результат работы программы:

CppStudio.com
1. Список студентов (ФИО)
2. Список студентов которые сдали все экзамены только на пять.
3. Список студентов которые имеют хотя-бы одну тройку по экзаменам.
4. Список студентов у которых есть двойки.
(если студент имеет больше одной двойки он исключается из списка).
5. Введите 'q' для выхода
Пожалуйста сделайте свой выбор: 1
Иванов И. И.
Карпов И. С.
Петров С. К.
Борзенков А. А.
Константинов П. П.
1. Список студентов (ФИО)
2. Список студентов которые сдали все экзамены только на пять.
3. Список студентов которые имеют хотя-бы одну тройку по экзаменам.
4. Список студентов у которых есть двойки.
(если студент имеет больше одной двойки он исключается из списка).
5. Введите 'q' для выхода
Пожалуйста сделайте свой выбор:
2
Константинов П. П.
1. Список студентов (ФИО)
2. Список студентов которые сдали все экзамены только на пять.
3. Список студентов которые имеют хотя-бы одну тройку по экзаменам.
4. Список студентов у которых есть двойки.
(если студент имеет больше одной двойки он исключается из списка).
5. Введите 'q' для выхода
Пожалуйста сделайте свой выбор: 3
Иванов И. И.
Карпов И. С.
Петров С. К.
1. Список студентов (ФИО)
2. Список студентов которые сдали все экзамены только на пять.
3. Список студентов которые имеют хотя-бы одну тройку по экзаменам.
4. Список студентов у которых есть двойки.
(если студент имеет больше одной двойки он исключается из списка).
5. Введите 'q' для выхода
Пожалуйста сделайте свой выбор: 4
Таких студентов нет :(
1. Список студентов (ФИО)
2. Список студентов которые сдали все экзамены только на пять.
3. Список студентов которые имеют хотя-бы одну тройку по экзаменам.
4. Список студентов у которых есть двойки.
(если студент имеет больше одной двойки он исключается из списка).
5. Введите 'q' для выхода
Пожалуйста сделайте свой выбор:
Следующие статьи помогут вам в решении данной задачи:
Автор: admin
Дата: 13.09.2012
Поделиться:

Комментарии

  1. Alistra

    Юзала код, который представлен в решении. В итоге он не считывает все строки и смысл удалять двоечников из массива если в файле они всё ровно останутся. Не судите строго мой код, это моя первая задача такой сложности. Реализовала удаление двоечников из самого файла и вывод их данных. Хотелось бы услышать критику(оценку).)))

  2. Alistra

    //getline(fin, str); - это 76 строка, и если в файле нет первой строки-заголовка списка. Ее нужно закоментировать
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <iomanip>
    
    using namespace std;
    
    class Student
    {
    public:
    	Student() {
    		AssesOf1 =AssesOf2 =AssesOf3=AssesOf4=AssesOf5=0;
    		Surname = Name = Patronymic = "";
    	}
    	Student(string Surname, string Name, string Patronymic, int AssesOf1,
    		int AssesOf2, int AssesOf3, int AssesOf4, int AssesOf5) {
    		this->Surname = Surname;
    		this->Name = Name;
    		this->Patronymic = Patronymic;//патронэмик
    		this->AssesOf1 = AssesOf1;
    		this->AssesOf2 = AssesOf2;
    		this->AssesOf3 = AssesOf3;
    		this->AssesOf4 = AssesOf4;
    		this->AssesOf5 = AssesOf5;
    	}
    
    	void PrintAllData() {//вывод всех данных
    		cout << setiosflags(ios::left);
    		cout<<setw(23) << Surname + " " + Name + " " + Patronymic;
    		cout << "\t";
    		cout.width(3); cout << AssesOf1;
    		cout.width(3); cout << AssesOf2;
    		cout.width(3); cout << AssesOf3;
    		cout.width(3); cout << AssesOf4;
    		cout.width(3); cout << AssesOf5;
    		cout << endl;
    	}
    	void Print() {//вывод только ФИО
    		cout << setiosflags(ios::left);
    		cout << setw(23) << Surname + " " + Name + " " + Patronymic;
    	}
    	string Surname,Name,Patronymic;
    	int AssesOf1, AssesOf2, AssesOf3, AssesOf4, AssesOf5;
    };
    //глобальные переменные
    string File = "Statement.txt";//файл с ведомостью
    const int AmountAssessment_of = 5;//количество оценок
    bool EditFile = false;//для проверки был ли файл отредактирован
    
    void ArrNumber(int *Number, int size, Student &list)//присваиваем оценки
    {
    	list.AssesOf1 = Number[0];
    	list.AssesOf2 = Number[1];
    	list.AssesOf3 = Number[2];
    	list.AssesOf4 = Number[3];
    	list.AssesOf5 = Number[4];
    }
    
    void ReadFile(Student * List2, int SizeStatement) //читает файл и заполняет массив Список2(Список студентов)
    {
    	Student list;//для считывания одного объекта
    	string str;//переменная для файла
    	int number[AmountAssessment_of] = { 0 };//массив для оценок
    	
    	ifstream fin;
    	fin.open(File);
    	if (!fin.is_open()) {
    		cout << "Файл не открылся!\n";
    	}
    	else {
    		int i = 0;//итератор для оценок
    		int j = 0; //итератор для строк
    		int x = 0;//итератор для ФИО
    		getline(fin, str);//если есть заголовок(оглавление списка)то мы его считываем и никуда не запоминаем
    		while (!fin.eof()) {//считываем по строке(символы до первого пробела)
    			fin >> str;
    			if (str == "5" || str == "4" || str == "3" || str == "2") {
    				number[i] = stoi(str);//преобразование строки в число и заполнение массива для хранения оценок
    				i++;
    			}
    			else {
    				if (x == 0)
    					list.Surname = str;
    				else if (x == 1)
    					list.Name = str;
    				else if (x == 2)
    					list.Patronymic = str;
    				x++;
    			}
    			if (i == 5) {
    				ArrNumber(number, AmountAssessment_of, list);//функция присваевает массив чисел в переменные объекта
    				List2[j] = list;//присваеваем считанный объект в массив объектов
    				j++;//+строка для массива объектов
    				x = 0; i = 0;
    			}
    		}
    	}
    	fin.close();
    }
    
    void FindAndShowDataOnRequest(Student *List2,int SizeStatement,int value) //искать и показать данные по запросу
    {
    	for (int i = 0; i < SizeStatement; i++)
    	{
    		if (value == 2 && List2[i].AssesOf1 == 5 && List2[i].AssesOf2 == 5 && List2[i].AssesOf3 == 5
    			&& List2[i].AssesOf4 == 5 && List2[i].AssesOf5 == 5) {
    			List2[i].Print();
    			cout << endl;
    		}
    		else if (value == 3 && (List2[i].AssesOf1 == 3 || List2[i].AssesOf2 == 3 || List2[i].AssesOf3 == 3
    			|| List2[i].AssesOf4 == 3 || List2[i].AssesOf5 == 3)) 
    		{
    			List2[i].Print();
    			cout << endl;
    		}
    	}
    }
    
    void DeletRow(Student *List2,  int* arr, int SizeStatement, int i22);//прототив дл видимости функции
    
    void ControlForTwos(Student *List2, int SizeStatement) {//контроль за двойками
    
    	int *ArrayOnDelete = new int [SizeStatement];//массив для хранения нумераций строк, которые по условию нужно удалить
    	int iter2 = 0;//итератор для посчета двоек
    	int i22 = 0;//если больше чем одна двойка
    
    	for (int i = 0; i < SizeStatement; i++)
    	{
    			if (List2[i].AssesOf1 == 2) iter2++;
    			
    			if (List2[i].AssesOf2 == 2) iter2++;
    			
    			if (List2[i].AssesOf3 == 2) iter2++;
    			
    			if (List2[i].AssesOf4 == 2) iter2++;
    			
    			if (List2[i].AssesOf5 == 2) iter2++;
    			
    			if (iter2 == 1) {//если одна двойка выводим
    				List2[i].Print();
    				cout << endl;
    				iter2 = 0;
    			}
    			if (iter2 > 1) {//если больше одной двойки
    				ArrayOnDelete[i22] = i;//сохраняем номер строки
    				i22++;
    				iter2 = 0;
    			}
    	}
    	if (i22 > 0) {//если есть хоть одна строка на удаление
    	int *arr = new int[i22];//зная сколько строк надо удалить, выделяем отдельно массивдля точного хранения данных
    	for (int i = 0; i < i22; i++) {
    		arr[i] = ArrayOnDelete[i];
    	}
    	delete[]ArrayOnDelete;
    		DeletRow(List2,arr,SizeStatement,i22);//функция удаления строки
    	}
    }
    void DeletRow(Student *List2, int* arr, int SizeStatement, int i22) //удаляет строки в которых болше 1 двойки
    {
    	cout << "\nИз списка удалены: \n\n";
    	Student *copyList2 = new Student[SizeStatement-i22];//массив в который сохраним уже отредактированный список 
    	int j = 0;//итератор для массива int 
    	for (int i = 0; i < SizeStatement-i22; i++)//проходимся по новому списку
    	{    for (int q = 0; q < SizeStatement; q++) {//и по старому
    			if (arr[j] != q) {//если строка не совпадает с значением массива int значит можно присвоить объект в новый массив
    				copyList2[i] = List2[q];
    				i++;
    			}
    			else {
    				List2[q].PrintAllData();//информируем пользователя какие строки будут удалены из файла
    				cout  << endl;
    				j++;//двигаемся по массиву со списком строк на удаление
    			}
    		}
    	}
    	delete[]arr;//массив строк на удаление УДАЛЯЕМ
    	ofstream of;//для записи отредактированного массива объектов
    	of.open(File, ios_base::trunc);//условие:удалить содержимое если есть
    	if (!of.is_open()) {
    		cout << "Файл не открылся!\n";
    	}
    	else {
    		for (int i = 0; i < SizeStatement-i22; i++)//по новому массиву записываем все объекты
    		{
    			of << copyList2[i].Surname<<" "<< copyList2[i].Name<<" "<< copyList2[i].Patronymic <<" "<< copyList2[i].AssesOf1<<" "
    			<< copyList2[i].AssesOf2<<" "<< copyList2[i].AssesOf3<<" "<< copyList2[i].AssesOf4<<" "<< copyList2[i].AssesOf5<< endl;
    		}
    	}
    	delete[]copyList2;//массив больше не нужен все отредактированные данные в файле
    	of.close();
    	EditFile = true;//сообщаем о том что файл редактировался
    }
    
    int ConsiderLines()//считаем строки для выделения нужного массива
    {
    	int row=0;//количество строк
    	int i = 0;//итераток оценок
    	char ch;
    	ifstream fin;
    	fin.open(File);
    	if (!fin.is_open()) {
    		cout << "Файл не открылся\n";
    	}
    	else {
    		while (fin.get(ch))
    		{
    			if (ch == '5' || ch == '4' || ch == '3' || ch == '2') {
    				i++;
    				if (i == 5) {
    					row++;
    					i = 0;
    				}
    			}
    		}
    	}
    	fin.close();
    	return row;
    }
    
    int main()
    {
    	setlocale(LC_ALL, "rus");
    
    	int number = 0;//выбор из меню
    	bool TestData = true;//для контроля за заполненностью основного массива объектов с которым работает меню
    	int SizeStatement = ConsiderLines();//количество строк в файле
    	Student *List2 = new Student[SizeStatement];//для сохранения всего списка
    	while (number != 5) {
    		cout << "______________________________\n";
    		cout << "1\tсписок студентов(ФИО)\n";
    		cout << "2\tсписок студентов, которые сдали все экзамены только на 5\n";
    		cout << "3\tсписок студентов, которые имеют хотя - бы одну тройку по экзаменам\n";
    		cout << "4\tсписок студентов, у которых есть двойки.Если студент, имеет более чем одну двойку, он исключается из списка.\n";
    		cout << "5\tвыход из программы\n";
    		cout << "____________________________\n";
    		cout << "Ввод: ";
    		while (!(cin >> number)){//проверка на корректность ввода
    			cin.clear();
    			while (cin.get() != '\n');
    			cout << "\nНеверный ввод. Повторите." << endl;
    			cout << "Ввод: ";
    		}
    		switch (number)
    		{
    		case 1://список всех ФИО
    			ReadFile(List2,SizeStatement);//читаем файл и создаем копию данных в массиве объектов
    			TestData = false;//запоминаем что массив заполнен
    			for (int i = 0; i < SizeStatement; i++){
    					List2[i].Print();
    					cout << endl;
    			}
    			break;
    		case 2://отличники
    			if (TestData == true) {//если массив не был заполнен
    				ReadFile(List2, SizeStatement);
    				TestData = false;
    			}
    			FindAndShowDataOnRequest(List2,SizeStatement,number); //искать и показать данные по запросу
    			break;
    		case 3://хотя бы одна тройка
    			if (TestData == true) {//если массив не был заполнен
    				ReadFile(List2, SizeStatement);
    				TestData = false;
    			}
    			FindAndShowDataOnRequest(List2, SizeStatement,number); //искать и показать данные по запросу
    			break;
    		case 4://двоишники
    			if (TestData == true) {//если массив не был заполнен
    				ReadFile(List2, SizeStatement);
    				TestData = false;
    			}
    			ControlForTwos(List2, SizeStatement);//проверка: выводит учащихся с 1 двойкой и удаляет из файла учащихся с >1 двойкой.
    			if (EditFile == true) {//если из файл были удалены данные
    				SizeStatement = ConsiderLines();//пересчитываемтся количество строк в файле
    				ReadFile(List2, SizeStatement);//читаем отредактированный файл и создаем копию данных в массиве объектов
    				EditFile = false;
    				TestData = false;//сообщаем что основной массив заполнен
    			}
    			break;
    		case 5:
    			cout << "Работа закончена. Спасибо, за старания!\n";
    			break;
    		default:
    			cout << "\nДанные по команде отсутствуют!\n Проверьте вводимое значение!\n";
    			break;
    		}
    		number = 0;
    	}
    	system("pause");
    	return 0;
    }
  3. Den4ik

    А можно в эту программу добавить пункт добавления новых студентов?

  4. admin
  5. Сергей Клементьев

    Решение есть, а в строке «статус» стоит прочерк :-)

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.