为什么输入流会从输入的第二行剪切一些字符

时间:2019-01-29 18:50:18

标签: c++

我正在编写一个简单的c ++程序,该程序从输入中读取学生的姓氏,然后是期中,期末和各种作业成绩(例如:Carlo 2 5 7 8)。 问题在于,从输入的第二行开始,它削减了一些学生的姓氏。

一个例子。

Enter the surname of each student followed by the midterm, final, and homework grades.
Carlo 2 3 4 5
Bonandrini 2 3 4 5

Carlo     3.4
onandrini 3.4

如您所见,第二个名字在前面缺少a。 我尝试了不同的名称和名称的长度,但是没有任何变化,它仍然可以剪切名称。 据我了解,问题出在输入本身。

#include<vector>
#include<iostream>
#include<string>
#include<algorithm>
#include<ios>
#include<iomanip>
#include<stdexcept>

template<typename T>
T median(std::vector<T> vec) // Not passed by name because we sort the vector
{
    typedef typename std::vector<T>::size_type vec_sz;
    vec_sz size = vec.size();

    if(!size)
        throw std::domain_error("Median of an empty vector");

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

    vec_sz pos = size / 2;

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

template<typename T>
std::istream& operator>>(std::istream& stream, std::vector<T>& vec)
{
    if(stream) // If stream is actually open
    {
        vec.clear(); // In case the vector wasn't empty

        T x; 
        while(stream >> x)
            vec.push_back(x);


        stream.clear();
    }
    return stream;
}

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

double grade(const StudentInfo& student)
{
    return 0.2 * student.midterm + 0.4 * student.final + 0.4 * median<double>(student.homework);
}

std::istream& operator>>(std::istream& stream, StudentInfo& student)
{
    stream >> student.name >> student.midterm >> student.final;

    stream >> student.homework;

    return stream;
}

int main()
{
    std::cout << "Enter the surname of each student followed by the midterm, final, and homework grades" << std::endl;
    std::vector<StudentInfo> students;

    std::string::size_type maxlen = 0;
    StudentInfo student;
    while(std::cin >> student) 
    {
       maxlen = std::max(maxlen, student.name.size());
        students.push_back(student);
    }

    std::sort(students.begin(), students.end(), 
    [](const StudentInfo& student1, const StudentInfo& student2){ return student1.name < student2.name; });

    for(StudentInfo student : students)
    {
        // + 1 to put a space between the name and the grade
        std::cout << student.name << std::string(maxlen + 1 - student.name.size(), ' ');

        try{
            double points = grade(student);
            std::streamsize prec = std::cout.precision();
            std::cout << std::setprecision(3) << points << std::setprecision(prec);
        }
        catch(std::domain_error e){
            std::cout << e.what();
        }

        std::cout << std::endl;
    }
}

程序应输出具有适当年级的学生列表。

1 个答案:

答案 0 :(得分:0)

我将假设名称是“ First Last”或“ Last,First”之类的意思。

如果是这种情况,则问题出在您使用std :: stream >> std :: string上。此输入限定空格。除非您告诉它,否则空格后的所有内容均视为新字符串。如果期中字符串不是双精度数,则空格后面的部分将显示在此处。相反,它只是忽略它,因为它不知道如何将其转换为字符串。

您需要的是std :: stream.getline()可能会解决问题。