-2

I am trying to enter a name of a student or full/partial ID and print out the whole record after finding it.

Here is my code:

    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 << "\n\n 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;
        }           
    }

I got no errors, but I am not getting any output either. If you notice, I tried two different logic for search_by_name() and search_by_id() but nothing is working.

Since I am not very familiar with C++, kindly help me to get the required output.

EDIT: Here is what Text_File.txt looks like:

 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
Reem Shams
  • 37
  • 3
  • 10
  • 1
    First of all, please read [Why is iostream::eof inside a loop condition considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) Then you should know that the condition `name == sname` compares two *pointers*. And two pointers that will *never* be equal. To compare old C-style string (or *null-terminated byte strings* as they're really called) use [`std::strcmp`](http://en.cppreference.com/w/cpp/string/byte/strcmp). – Some programmer dude Nov 27 '17 at 08:26
  • Did your code even compiled? Please post code which compiles on your system and also provide information how you are writing records in file i.e. what is structure of records in text file so that we can check whether you are parsing records properly or not. – Pravar Jawalekar Nov 27 '17 at 08:32
  • Having an object that represents a single student also manage the entire database of students is making things more complicated than they need to be. – molbdnilo Nov 27 '17 at 08:39
  • @PravarJawalekar I added the content of my text file @Someprogrammerdude I changed `if (name==sname)` to `if (strcmp(sname,name)` but now I am getting garbage value. @molbdnilo so are you suggesting that I make an array of objects for each student? – Reem Shams Nov 27 '17 at 08:47
  • You didn't even write any code to read any file. What is there to answer? – sehe Nov 27 '17 at 09:28
  • 1
    The file format for `"Text_File.txt"` is rather complicated for beginners. Are you sure that's what the file looks like? For a beginner class, the file has a simple format, for example first line is `"Reem Shams"`, not `"Student Name: Reem Shams"`. If it is the later, you need to read the line with `std::getline`, and parse the line using `std::string::substr` – Barmak Shemirani Nov 27 '17 at 09:31
  • I concur with @BarmakShemirani although I would not suggest going so lowlevel (ever, really) parsing the input. See my answer – sehe Nov 27 '17 at 16:09

2 Answers2

1

This is not trivial in C++. I concur with the suggestion to separate IO and the student type.

Also, separate the notion of a student record and a "database" of them (I'll use std::vector).

Parsing is the complicated part here. Some remarks are at your question, but let me extend the advice by showing how you would reasonably accurately parse it using just standard library features.

Live On 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 << "\n\n 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 found\n";
        else
            std::cout << "Matching record:\n" << *match << "\n";
    }
}

Prints

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

Or

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

Or

 Enter your choice: 3
 Invalid choice! Please enter 1 or 2 as your choice.
sehe
  • 328,274
  • 43
  • 416
  • 565
  • I appreciate your help but I am getting errors when compiling the code. – Reem Shams Nov 27 '17 at 11:18
  • Don't tell me you're using Borland C++. It was merely an example anyways. You will not turn this in as your assignment since (a) it's unethical (b) it will be obvious you didn't write it. Lastly, I linked to a live version that you can play with for testing! [c++11 also provided now](http://coliru.stacked-crooked.com/a/5d14307ab7fed6ea). – sehe Nov 27 '17 at 16:03
0

First of all, It is not much clear what you are trying to achieve. Anyway I will try to highlight some points to you so that you can think over them and rewrite your code so that it makes sense to you (and everyone else).

  • In member function, search_by_name() you are taking input from user and comparing user-entered text with name member variable. If they match then you are unnecessarily reading 32 characters in sname buffer and doing nothing with it. Further you just print other member variables to standard output. So what was your purpose of using file I/O using c++ files streams? Same goes for function search_by_id().
  • You should ideally have provided constructor for Student class to initialize objects when you create them

Please consider above points and let us know if you still have more queries/questions.

Pravar Jawalekar
  • 545
  • 1
  • 5
  • 18