cin.ignore(), cin.ignore(1, '\n') and scanf("\n")

69 Views Asked by At

I have this assignment. If I use cin.ignore(), the result is false, and cin.ignore(1, '\n') and scanf("\n"), the result is true. I don't know why I fail. Please, help me

This assignment:

Write a program to declare a class SinhVien (Student) with the following information: Student ID, Full name, Class, and GPA (float). The constructor has no parameters, and assigns the default values (empty string, 0) to the attributes.

The program must use the stream operators to input and output student objects with cin and cout.

The program must read the information of N students from the keyboard (without student ID). Then, the program must sort the students by GPA in descending order and print out the list of students on the screen, one line per student.

In the case of Student ID, it is automatically generated according to the rule of adding the code B20DCCN followed by the automatically increasing integer value from 001 (maximum is 099). Full name is processed to bring it to the standard form. Date of birth is normalized to the form dd/mm/yyyy

Input:

The first line contains the number of students N (0 < N < 50).

Each student is recorded on 4 lines, respectively for Full name, Class, Date of birth, and GPA.

In which:

Full name is not more than 30 characters. Class is in the correct format usually used at PTIT Date of birth has enough 3 parts of day, month, and year but may not be in the correct format dd/mm/yyyy. GPA is guaranteed to be within the 4-point scale with 2 at most 2 digits after the decimal point. The data ensures that no two students have the same GPA.

Output:

Print out the list of students with full Student ID, Full name, Class, Date of birth (normalized), GPA (with 2 digits after the decimal point) that have been sorted by GPA in descending order.

And my code:

#include <iostream>
#include <sstream>
#include <algorithm>
#include <string>
#include <iomanip>

using namespace std;

std::string so(int k)
{
    std::string st = std::to_string(k);
    if (st.length() == 1)
        st = "0" + st;
    return st;
}

class SinhVien
{
private:
public:
    static int dem;
    float gpa;
    std::string code, name, grade, date;

    friend std::istream &operator>>(std::istream &input, SinhVien &object)
    {
        object.code = "B20DCCN0" + so(++dem);
        // input.ignore();
        input.ignore(1, '\n');
        /*         if (dem == 1)
                    scanf("\n");
                else input.ignore(); */

        auto formatName = [](std::string &st)
        {
            std::stringstream sst(st);
            std::string temp;
            st = "";
            while (sst >> temp)
            {
                for (char &c : temp)
                    if (isupper(c))
                        c = tolower(c);
                temp[0] = toupper(temp[0]);
                st += temp + " ";
            }
            st.pop_back();
        };

        std::getline(input, object.name);
        formatName(object.name);
        std::getline(input, object.grade);

        auto formatDate = [](std::string &st)
        {
            if (st[2] != '/')
                st = "0" + st;
            if (st[5] != '/')
                st.insert(3, "0");
        };
        std::getline(input, object.date);
        formatDate(object.date);
        input >> object.gpa;
        return input;
    }

    friend std::ostream &operator<<(std::ostream &output, SinhVien object)
    {
        output << object.code << " " << object.name << " " << object.grade << " " << object.date << " " << std::fixed << std::setprecision(2) << object.gpa << std::endl;
        return output;
    }
};

int SinhVien::dem = 0;

void sapxep(SinhVien a[], int n)
{
    auto compare = [](SinhVien a, SinhVien b) -> bool
    {
        return a.gpa > b.gpa;
    };
    std::sort(a, a + n, compare);
}

int main()
{
    SinhVien ds[50];
    int N, i;
    cin >> N;
    for (i = 0; i < N; i++)
    {
        cin >> ds[i];
    }
    sapxep(ds, N);
    for (i = 0; i < N; i++)
    {
        cout << ds[i];
    }
    return 0;
}

If I use cin.ingore(), my program is RTE (Runtime Error)

1

There are 1 best solutions below

2
James Kanze On

I don't really understand why you're using ignore to begin with. Without a count, it will skip to the next \n, regardless of how many characters that it. With the count, it will skip at most than many characters. So after a std::getline (which removes the '\n' from the stream_), it will skip the next line completely without a count, and will skip the initial character of the line with a count. (The scanf variant will skip the next character if it is a '\n', and set an error state otherwise.) You might want to skip initial white space in general (input >> ws) -- this will extract nothing if the next character in the stream is not a white space (which includes '\n'), but as the input is line oriented, I'd go with the suggestion of others here: use std::getline exclusively to extract data from the file, and the parse each line.

Also, you really should check the state of the stream after each std::getline, to make sure it has worked.