我不知道如何在 C++ 中模拟输入停止

I don't know how to simulate input stop in C++

所以我有一个程序,它为每个学生加载成绩并输出姓名和最终成绩。它是 Accelerated C++ 书中的程序,我发现了一个问题,我不知道如何模拟停止输入。

输入示例:
Harry 98 58 78 56 98 78 58 58

,然后我按回车,会读到另一个学生,所以我写:

Jack 88 54 33 89 54 67 15 78

现在我按 Enter 并想停止阅读学生并查看输出,但我如何在程序中没有其他条件的情况下执行此操作。我读了一些关于 EOF 的文章,但是当我尝试 Ctrl+Z 时,这似乎不起作用。


代码

main.cpp

#include <algorithm>
#include <iomanip>
#include <ios>
#include <stdexcept>
#include <string>
#include <vector>
#include "grade.h"
#include "student_info.h"

using namespace std;


int main() {
    vector<Student_info> students;
    Student_info record;
    string::size_type maxlen = 0;


    while (read(cin, record)) {
        maxlen = max(maxlen, record.name.size());
        students.push_back(record);
    }

    sort(students.begin(), students.end(), compare);

    for (vector<Student_info>::size_type i = 0;
        i = !students.size(); ++i) {

        cout << students[i].name
            << string(maxlen + 1 - students[i].name.size(), ' ');

        try {
            double final_grade = grade(students[i]);
            streamsize prec = cout.precision();
            cout << setprecision(3) << final_grade
                << setprecision(prec);
        }
        catch (domain_error e) {
            cout << e.what();
        }
        cout << endl;
    }

    return 0;
}

grade.h

#ifndef GUARD_grade_h
#define GUARD_grade_h

#include <vector>
#include "student_info.h"

double grade(double, double, double);
double grade(double, double, const std::vector<double>&);
double grade(const Student_info &);

#endif // !GUARD_grade_h

grade.cpp

#include <vector>
#include <stdexcept>
#include "median.h"
#include "student_info.h"
#include "grade.h"

using std::domain_error; using std::vector;

double grade(double midterm, double final, double homeworks) 
{
    return 0.2 * midterm + 0.4 * final + 0.4 * homeworks;
}

double grade(double midterm, double final, const vector<double> &hm)
{
    if (hm.size() == 0)
        throw domain_error("student has done no homework");
    return grade(midterm, final, median(hm));
}

double grade(const Student_info& s)
{
    return grade(s.midterm, s.final, s.homework);
}
student_info.h
#ifndef GUARD_student_info_h
#define GUARD_student_info_h

#include <iostream>
#include <string>
#include <vector>

struct Student_info {
    std::string name;
    double midterm, final;
    std::vector<double> homework;
};

bool compare(const Student_info&, const Student_info&);
std::istream& read(std::istream&, Student_info&);
std::istream& read_hw(std::istream&, std::vector<double>&);

#endif // !GUARD_student_info_h
student_info.cpp
#include "student_info.h"
#include <vector>
#include <iostream>
#include <string>

using std::istream;     using std::vector;

bool compare(const Student_info& x, const Student_info& y) {
    return x.name < y.name;
}

istream& read_hw(istream& in, vector<double>& hm) {
    if (in) {
        //get rid of previous contents
        hm.clear();

        //read homework grades
        double x;
        while (in >> x)
            hm.push_back(x);
        //clear the stream so that input will work for the next student
        in.clear();
    }
    return in;
}

istream& read(istream& is, Student_info& s) {
    
    is >> s.name >> s.midterm >> s.final;

    read_hw(is, s.homework);
    return is;
}
median.h
#ifndef GUARD_median_h
#define GUARD_median_h

#include <vector>
double median(std::vector<double>);

#endif
median.cpp
#include "median.h"
#include <vector>
#include <algorithm>
#include <stdexcept>

using std::domain_error;    using std::sort;    using std::vector;

double median(vector<double> vec) {
    typedef vector<double>::size_type vc_sz;
    vc_sz size = vec.size();
    if (size == 0)
        throw domain_error("median of an empty vector");

    sort(vec.begin(), vec.end());

    vc_sz mid = size / 2;

    return size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2
        : vec[mid];
}

要通过 EOF 你需要按 Ctrl+D.

如果这不起作用,您可能需要考虑引入 “停止字符串”。您将在每次开始新输入系列时检查一个。一般是以下形式:

if (input_string != stop_string) 
    /* continue further */;
else 
    /* stop getting input */;

所以,你可以看看下面的方法。我们让 main.cpp 中的循环保持不变,它仍然迭代由 read() 编辑的输入流 return。我们管理 read() 和 return 输入流中的读取逻辑,如果命令停止输入,则设置 eofbit

istream& read(istream& is, Student_info& s) {
    // I added this print for clarity of tests
    std::cout << "Enter name, midterm, final (or 'stop'): " << '\n';
    std::string current_input;
    is >> current_input;
    if (current_input != "stop") { // If not `stop`, then it is a name
        s.name = current_input;
        is >> s.midterm >> s.final; // Get input further
    } else { // We hit `stop`, set EOF, return
        is.setstate(std::ios_base::eofbit);
        return is;
    }
    read_hw(is, s.homework);
    return is;
}

read_hw() 函数中有第二个循环,没有建议的退出:

//read homework grades
double x;
while (in >> x) { // While we have valid input...
    hm.push_back(x);
}

您可以通过输入一个非数字值来停止这个。但是您也可以考虑在这里引入一个“停止字符”。像这样:

//read homework grades
double x;
while (in >> x) {
    if (x == -1) // If a user inputs -1, we stop looping
        break;
    hm.push_back(x);
}