C - 如何在文本文件中搜索学生记录

C++ - how can I search for a student record by name in a text file?

本文关键字:搜索 记录 文件 文本      更新时间:2023-10-16

我正在尝试输入学生或完整/部分ID的名称,并在找到整个记录后打印出整个记录。

这是我的代码:

    class student {
    public:
        char name[32]; 
        char id[15];
        int results;
        string grade;
        void add_record();
        void display_record();
        void search_by_name();
        void search_by_id();
        void print_grade(int result);
    };
    void student::search_by_name(){
        char sname[32];
        student obj;
        ifstream file ("Text_File.txt");
            cout << "Enter name to find: ";
            cin >> sname;
        if (file.is_open()) {
            if (!file.eof()) {
                if(name == sname) {
                    file.read((char*)& sname,sizeof(sname));
                    cout << "n Student Name:t" << name;
                    cout << "n Student ID:t" << id;
                    cout << "n Results:t" << results;
                    cout << "n Grade:t" ;
                    obj.print_grade(results);}
                }
                else {
                    cout << "Student not found.";
          } 
          else {
                cout << "Unable to open file.";
            } 
            }
}
    void student::search_by_id(){
        char id[15];
        int result;
        student obj;
        ifstream file ("Text_File.txt");
        cout << "Enter ID number: ";
        cin >> id;
        if (file.is_open())
            if (file >> id) {
                cout << "n Student Name:t" << obj.name;
                cout << "n Student ID:t" << obj.id;
                cout << "n Results:t" << obj.results;
                cout << "n Grade:t" ;
                obj.print_grade(obj.results);
            }
            else {
                cout << "Name not found";
            }
        else {
            cout << "Unable to open file.";
        }
    }
    int main () {
        student obj;
        int choice;
        cout << "n Choose search method: ";
        cout << "n 1. Find by name.";
        cout << "n 2. Find by ID";
        cout << "nn Enter your choice: ";
        cin >> choice;    
        switch (choice) {
        case 1:
            obj.search_by_name();
            break;
        case 2:
            obj.search_by_id();
            break;
        default:
            cout << "Invalid choice! Please enter 1 or 2 as your choice.";
            break;
        }           
    }

我没有任何错误,但是我也没有任何输出。如果您注意到,我尝试了search_by_name()search_by_id()的两种不同的逻辑,但是什么都没有起作用。

由于我对C 不太熟悉,请帮助我获得所需的输出。

编辑:这是Text_File.txt的样子:

 Student Name:  john
 Student ID:    122a
 Results:   85
 Grade:     A
 Student Name:  sam
 Student ID:    123654r
 Results:   97
 Grade:     A+

 Student Name:  rose
 Student ID:    1254ds
 Results:   85
 Grade:     A

这在C 中并不小。我同意将IO和student类型分开的建议。

另外,将student记录的概念和其中的"数据库"分开(我将使用std::vector)。

解析是这里复杂的部分。您的问题有一些评论,但让我通过仅使用标准库功能来合理地准确地解析它来扩展建议。

活在coliru

#include <string>     // std::string, std::getline
#include <iostream>   // std::cin, std::cout
#include <fstream>    // std::ifstream
#include <vector>     // std::vector
#include <functional> // std::function
#include <iterator>   // std::istream_iterator
#include <algorithm>  // std::find_if
auto const EVERYTHING = 1024; // arbitrary, but suffices for normal console input
struct  student {
    std::string name;
    std::string id;
    int results;
    std::string grade;
};
std::ostream& operator<<(std::ostream& os, student const& s) {
    return os
        << "Student Name:  " << s.name << "n"
        << "Student ID:    " << s.id   << "n"
        << "Results:   "     << s.results << "n"
        << "Grade:     "     << s.grade << "n";
}
std::istream& operator>>(std::istream& is, student& into) {
    struct parser {
        std::istream& _is;
        bool student(student& into) {
            return name(into.name) && 
                id(into.id) &&
                results(into.results) &&
                grade(into.grade) &&
                _is.ignore(EVERYTHING, 'n'); 
        }
      private:
        bool lit(std::string const& expected) {
            std::string actual;
            return _is >> actual && actual == expected;
        }
        bool remainder(std::string& into) {
            std::string tail;
            bool ok = _is >> into && std::getline(_is, tail);
            if (ok)
                into += tail;
            return ok;
        }
        bool name(std::string& into) {
            return lit("Student") && lit("Name:") && remainder(into);
        }
        bool id(std::string& into) {
            return lit("Student") && lit("ID:") && remainder(into);
        }
        bool results(int& into) {
            return lit("Results:") && (_is >> into).ignore(EVERYTHING, 'n');
        }
        bool grade(std::string& into) {
            return lit("Grade:") && remainder(into);
        }
    } parser{is};
    if (!parser.student(into))
        is.setstate(std::ios::failbit);
    return is;
}
int main() {
    std::ifstream file("input.txt");
    std::vector<student> const database(std::istream_iterator<student>(file), {});
    // for debug
    std::copy(database.begin(), database.end(), std::ostream_iterator<student>(std::cout, "n"));
    std::function<bool(student const&)> query;
    std::cout << "n Choose search method: ";
    std::cout << "n 1. Find by name.";
    std::cout << "n 2. Find by ID";
    std::cout << "nn Enter your choice: ";
    int choice = 0;
    std::cin >> choice;
    std::cin.ignore(EVERYTHING, 'n');
    std::cin.clear();
    switch (choice) {
    case 1:
        {
            std::cout << "Enter name: ";
            std::string name;
            if (getline(std::cin, name))
                query = [name](student const& s) { return s.name == name; };
        }
        break;
    case 2:
        {
            std::cout << "Enter id: ";
            std::string id;
            if (getline(std::cin, id))
                query = [id](student const& s) { return s.id == id; };
        }
        break;
    default:
        std::cout << "Invalid choice! Please enter 1 or 2 as your choice.";
        break;
    }
    if (query) {
        auto match = std::find_if(database.begin(), database.end(), query);
        if (match == database.end())
            std::cout << "No matching record foundn";
        else
            std::cout << "Matching record:n" << *match << "n";
    }
}

打印

 Enter your choice: 1
 Enter name: sam
 Matching record:
 Student Name:  sam
 Student ID:    123654r
 Results:   97
 Grade:     A+

 Enter your choice: 2
 Enter name: 123654r
 Matching record:
 Student Name:  sam
 Student ID:    123654r
 Results:   97
 Grade:     A+

 Enter your choice: 3
 Invalid choice! Please enter 1 or 2 as your choice.

首先,您要实现的目标还不清楚。无论如何,我将尝试向您突出一些要点,以便您可以考虑它们并重写您的代码,以便对您(以及其他所有人)有意义。

  • 在成员函数中,search_by_name()您正在从用户中获取输入,并将用户输入的文本与name成员变量进行比较。如果它们匹配,那么您将不必要地读取sname缓冲区中的32个字符,而对此一无所知。此外,您只需将其他成员变量打印到标准输出即可。那么,您使用C 文件流使用文件I/O的目的是什么?功能search_by_id()
  • 也是如此
  • 理想情况下,您应该为Student类提供constructor,以初始化对象

请考虑上述点,让我们知道您是否还有更多查询/问题。