'How do I search the structure?

I'm not quite getting a structure search. I have a task, I need to search for students by full name, year of birth, group number or course number. I can search by group number or course number, but the search by full name and date of birth is problematic.

Here are my code and my input file. (I'm sorry if my code is unprofessional, I'm just learning and I need to pass this task, but I'm having no luck and I have no one to turn to for help)

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

struct Student
{
    string name;
    string yearob;
    int course;
    int group;
};
ostream& operator<<(ostream& out, const Student obj)
{
    out << obj.name << " " << obj.yearob << " " << obj.group << " " << obj.course;
    return out;
}

int main()
{
    setlocale(LC_ALL, "");
    int search = 0;
    string name_s, yearob_s;
    int course_s, group_s;
    int chek = 1;
    while (chek == 1)
    {
        cout << "Enter 1 to start, 0 to exit > ";
        cin >> chek;
        switch (chek)
        {
        case(0):
            break;
        case(1):
        {
            int leng = 0;
            string s;
            ifstream fle("input.txt");
            while (getline(fle, s))
            {
                leng += 1; 
            }
            Student* list = new Student[leng];
            int a = 0;

            fle.close();
            ifstream file("input.txt");

            string ss, buff;
            while (getline(file, s))
            {
                buff.assign(s);
                list[a].course = buff[0] - '0';
                buff.erase(0, 2);

                ss += buff[0];
                ss += buff[1];
                list[a].group = stoi(ss);
                ss.clear();
                buff.erase(0, 3);

                for (int i = 0; i < 4; i++)
                    list[a].yearob += buff[i];
                buff.erase(0, 5);

                list[a].name.assign(buff);
                a += 1;
                buff.clear();
            }
            cout << "What parameter should be used to find students: 1 - by name, 2 - by year of birth, 3 - by course, 4 - by group number: ";
            
            cin >> search;
            switch (search) {
            case(1):
                cin >> name_s;
                for (int i = 0; i <= leng; i++) {
                    if (list[i].name.find(name_s, 10)) {
                        cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
                    }
                    else {
                        continue;
                    }
                }
            case(2):
                cin >> yearob_s;
                for (int i = 0; i <= leng; i++) {
                    if (list[i].yearob.find(yearob_s, 5)) {
                        cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
                    }
                    else {
                        continue;
                    }
                }
            case(3): {
                cin >> course_s;
                for (int i = 0; i <= leng; i++) {
                    if (course_s == list[i].course) {
                        cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
                    }
                    else {
                        continue;
                    }
                }
            }
            case(4):
                cin >> group_s;
                for (int i = 0; i <= leng; i++) {
                    if (group_s == list[i].group) {
                        cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
                    }
                    else {
                        continue;
                    }
                }
            }


                file.close();
                continue;
            }
        default:
        {
            cout << "Input error" << endl;
            continue;
        }
        }
        }
    }

Input file:

2 01 1999 Cody Hoyt
2 01 2002 Danielle Robyn Diaz
3 01 1999 Mayra Marie Collins
2 05 2000 Marc Nunez
4 05 2000 Tricia Gilmore
5 04 2001 Dale Lucas
1 01 1998 Ruby Merritt
2 01 2001 Tabitha Jenkins
4 02 1995 George Kris Oneill
2 03 1999 Bonnie Blair


Solution 1:[1]

Just maybe a shorter version of your code. I provide it not as a solution to your main question (because the following code is pretty advanced), but as an example of how you could avoid repeating code and making big nested constructions.

Here I moved out the code of reading students from a file into a separate function, and inside it should easily read each student using operator>> from a file. Similarly you can define operator<< to specify in which format you want students to be printed.

The repetitive code of printing filtered students is moved into a single function, that iterates all students and prints only pass a given test. You then give this test as a lambda function in each branch of switch operator

#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <functional>

using namespace std;

struct Student
{
    string name;
    string yearob;
    int course;
    int group;
};
ostream& operator<<(ostream& out, const Student& stud)
{
    out << stud.name << ", " << stud.course << " course, " << stud.group << " group, " << stud.yearob << " year of birth; " << endl;
    return out;
}

istream& operator>>(istream& in, Student& stud)
{
    in >> stud.course >> stud.group >> stud.yearob >> stud.name;
    return in;
}

vector<Student> read_students_file(const string& filename) {
    vector<Student> students;
    ifstream file(filename);
    while (file)
    {
        students.push_back({}); // insert empty student
        file >> students[students.size() - 1]; // fill student
    }
    file.close();
    return students ;
}

void print_filtered(const vector<Student>& students, function<bool(const Student&)> should_print) {
    for (const Student& student : students) {
      if (should_print(student)) {
          cout << student;
      }
    }
}

int main()
{
    setlocale(LC_ALL, "");
    while (true)
    {
        cout << "Enter 1 to start, 0 to exit > ";
        int check;
        cin >> check;
        if (check == 0) {
          break;
        } else if (check != 1) {
          continue;
        }
        
        vector<Student> students = read_students_file("input.txt");
            
        cout << "What parameter should be used to find students: 1 - by name, 2 - by year of birth, 3 - by course, 4 - by group number: ";
        int search_variant;
        cin >> search_variant;
        switch (search_variant) {
          case(1): {
            string find_name;
            cin >> find_name;
            print_filtered(students,
              [&](auto& student){ return student.name == find_name; });
            break;
          }
          case(2): {
            string find_yearob;
            cin >> find_yearob;
            print_filtered(students,
              [&](auto& student){ return student.yearob == find_yearob; });
            break;
          }
          case(3): {
            int find_course;
            cin >> find_course;
            print_filtered(students, 
              [&](auto& student){ return student.course == find_course; });
            break;
          }
          case(4): {
            int find_group;
            cin >> find_group;
            print_filtered(students,
              [&](auto& student){ return student.group == find_group; });
            break;
          }
          default: {
            cout << "Input error" << endl;
            continue;
          }
        }
    }
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alexey Larionov