Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Вывод информации по запросу пользователя


Автор: EagleBoss 14.5.2020, 22:33
Здравствуйте, товарищи!
У меня задание, реализовать поиск информации в текстовом файле (типа база данных), которую запрашивает пользователь.
Мне нужно сделать поиск по студентам, получившим такую-то оценку по предмету. Пользователь вводит оценку и ему выводит список студентов с этой оценкой (список тот, что берёт из файла, соответственно). Ну дк вот, допустим пользователь ввёл оценку 3, и ему вылазит список всех студентов с оценкой 3. Программа полностью функционирует, но хотелось бы добавить ещё поиск по студентам с оценкой, вот пример, как это можно осуществить "значение в контейнере мап должно быть вектором, который хранит структуру, в которой есть поле для дисциплины строковое и поле числовое для оценки", но осуществить для меня это трудновато, прошу помощи, друзья. Код приложил.

Код

#include <iostream>
#include <map>
#include <string>
#include <fstream>
#include <thread>
#include <mutex>
#include <conio.h>
#include <Windows.h>
using namespace std;
 
mutex Locker;
multimap <string, string> stud;
bool StudentsBookChanged = false;
bool SaveResult = true;
bool ExitProc = false;
string FN = "Students.txt";
 
string Replace(string Source, char c1, char c2)
{
    for (int i = 0; i < Source.length(); i++)
        if (Source[i] == c1) Source[i] = c2;
    return Source;
}
 
void SetStudent(string FIO, string predmet)
{
    Locker.lock();
    stud.insert(make_pair(FIO, predmet));
    StudentsBookChanged = true;
    Locker.unlock();
}
 
void PrintStudentList()
{
    system("cls");
    auto i = stud.begin();
    while (i != stud.end())
    {
        string StudentName = i->first;
        cout << "ФИО: " << i->first << endl;
        while (i != stud.end() && i->first == StudentName)
        {
            cout << "Предмет и оценка: " << i->second << endl;
            i++;
            cout << endl;
        }
    }
    cout << endl << "Нажмите любую клавишу...";
    _getch();
}
 
bool SaveStudentsBook(string FileName)
{
    ofstream f(FileName);
    if (f)
    {
        for (auto i : stud)
        {
            string s = Replace(i.first, ' ', '_');
            string s1 = Replace(i.second, ' ', '-');
            f << s << "\t" << s1 << endl;
        }
        f.close();
        return true;
    }
    return false;
}
 
void LoadStudentsBook(string FileName)
{
    ifstream f(FileName);
    string s, s1;
    if (f)
    {
        while (f >> s >> s1)
        {
            s = Replace(s, '_', ' ');
            stud.insert(make_pair(s, s1));
        }
        f.close();
    }
}
 
void SaverThreadProc(bool &result)
{
    while (!ExitProc)
    {
        if (StudentsBookChanged)
        {
            result = SaveStudentsBook(FN);
            Locker.lock();
            StudentsBookChanged = false;
            Locker.unlock();
        }
        int c = clock();
        int c2;
        do
        {
            this_thread::yield();
            c2 = clock();
        } while (c2 - c < 10000 && !ExitProc);
    }
    if (StudentsBookChanged)
    {
        result = SaveStudentsBook(FN);
    }
}
 
char mainMenu()
{
    system("cls");
    cout << "1. Добавить/изменить студента" << endl;
    cout << "2. Вывод списка студентов" << endl;
    cout << "3. Удалить студента" << endl;
    cout << "0. Выход" << endl;
    cout << "Ваш выбор >>";
    return _getch();
}
 
void DoSetStudent()
{
    string n, t;
    system("cls");
    cout << "Введите ФИО Студента: ";
    getline(cin, n);
    cout << "Введите предмет и оценку: ";
    getline(cin, t);
    SetStudent(n, t);
}
 
void DeleteStudent()
{
    string n;
    system("cls");
    cout << "Введите ФИО студента: ";
    getline(cin, n);
    if (stud.count(n) == 0)
    {
        cout << "Студент не найден. Нажмите любую клавишу...";
        _getch();
        return;
    }
 
    Locker.lock();
    stud.erase(n);
    StudentsBookChanged = true;
    Locker.unlock();
    cout << "Студент успешно удален. Нажмите любую клавишу...";
    _getch();
}
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
    LoadStudentsBook(FN);
    thread BackgroungSaver(SaverThreadProc, ref(SaveResult));
    char key = 0;
    while (key != '0')
    {
        key = mainMenu();
        switch (key)
        {
        case '1':
            DoSetStudent();
            break;
        case '2':
            PrintStudentList();
            break;
        case '3':
            DeleteStudent();
            break;
        }
    }
    ExitProc = true;
    if (BackgroungSaver.joinable()) BackgroungSaver.join();
    if (SaveResult)
        cout << "\n\nСписок студентов успешно записан в файл. Нажмите любую клавишу...";
    else
        cout << "\n\nОшибка записи списка студентов. Нажмите любую клавишу...";
    _getch();
}

Автор: xvr 15.5.2020, 09:49
Для начала исправьте ошибки в том, что уже есть.
1. При записи в файл вы обрабатываете обе строки, а при чтении только одну
2. Thread записи в файл блокирует не то, что нужно (нужно блокировать собственно запись, а не только сброс флага)

Далее нужно сделать ввод оценки отдельно от предмета (сейчас это всё вводится в виде строки, и одному богу известно что там где)

И только потом можно делать поиск по оценке

PS.  Как то у вас PrintStudentList разительно по стилю отличается от остальной программы. Сами писали?

Автор: EagleBoss 15.5.2020, 10:40
Нет, не совсем сам, пару фрагментов программы написал, а прогу уже по видео преподавателя писал. Но, спасибо, учтём.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)