【问题标题】:I don't know how to simulate input stop in C++我不知道如何在 C++ 中模拟输入停止
【发布时间】:2021-06-24 13:59:12
【问题描述】:

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

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

,然后我按 Enter 会读取另一个学生,所以我写:

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;
}

等级.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

等级.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;
}
中位数.h
#ifndef GUARD_median_h
#define GUARD_median_h

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

#endif
中位数.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];
}

【问题讨论】:

    标签: c++ io


    【解决方案1】:

    要传递EOF,您需要按Ctrl+D

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

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

    因此,您可以考虑以下方法。我们在main.cpp 中的循环保持不变,它仍然迭代read() 返回的输入流。我们在read() 中管理读取逻辑,如果输入被命令停止,则返回设置了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);
    }
    

    【讨论】:

    • 所以这个问题,我解决了,但代码仍然无法工作。它不会输出任何东西。我在grade.h 中发现了一个问题。第二个函数:double grade(double, double, const std::vector&lt;double&gt;&amp;); . Visual Studio 一直说找不到函数定义,但是这个函数的定义在grade.cpp中。
    • 我发现了错误。它在 Main.cpp 的 for 循环中。我写 i = !students.size() 所以 for 循环永远不会打开。当我纠正它时,它终于像预期的那样工作了。非常感谢@rawrex 的输入帮助。
    猜你喜欢
    • 2020-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-11
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多