在C ++中读取文件,搜索并将信息显示到结构数组时出现问题

时间:2019-07-12 13:19:40

标签: c++ arrays struct

很抱歉,如果这看起来很愚蠢,我对C ++还是很陌生,我无法显示从输入文件读取到结构数组中的信息。

我有3个功能。一个用于将我的文件读入数组,一个用于提示用户在数组中搜索特定的结构,最后一个用于显示数组的内容。

我不确定readFile()displayAllStudents()是否损坏。我可以从文件输出第一行,但其余为0。接下来,我的selectStudent()可能很糟糕;我无法为自己要完成的工作找到好的解决方案。

我已经尝试过这里发布的许多解决方案,但是我的问题似乎很特殊,所以我希望我能帮助指出正确的方向。

Input file and desired output.


    ID   CLA   OLA   Quiz   Homework   Exam   Bonus   Total   FinalGrade   
c088801    10    15      4         15     56       5 
c088802     9    12      2         11     46       2 
c088803     8    10      3         12     50       1
c088804     5     5      3         10     53       3
c088805     3    11      1         10     45       0 
c088806     8    14      2         11     40      -1  
c088807     4    12      2         12     48      -2
c088808    10    10      3         11     36       0
c088809     8     8      3         11     39       0
c088810     6     9      4          9     47       3
c088811     8     7      3         13     41       3
c088812     4    11      3         11     37       1
c088813     9    15      2          8     50       2
c088814     8    12      2         10     48       4
c088815     6     8      1          7     45       1
c088816     7     7      2          6     51       2
c088817     8     9      2         12     38       2 
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

struct Student {
    char ID[7];
    int CLA;
    int OLA;
    int Quiz;
    int Homework;
    int Exam;
    int Bonus;
    int Total;
    int FinalGrade;
};
const int SIZE = 20;

//Function prototypes
void readFile(Student[]);
int selectStudent(Student[]);
void displayAllStudents(Student[]);

int main() {
    Student Roster[SIZE] = {};                  //Initalizes array

    readFile(Roster);
    //selectStudent(Roster);
    displayAllStudents(Roster);

    system("pause");
    return 0;
}

//This function will read the text file into our array of structures.
void readFile(Student Roster[]) {
    ifstream inFile("point.dat");                   //Reads input file
    string line;

    getline(inFile, line);                          //Skips first line of file

    for (int i = 0; i < SIZE; i++) {                
            inFile >> Roster[i].ID >> Roster[i].CLA >> Roster[i].OLA >>
                Roster[i].Quiz >> Roster[i].Homework >> Roster[i].Exam >>
                Roster[i].Bonus >> Roster[i].Total >> Roster[i].FinalGrade;
    }

}

//This function will prompt user to select an individual student ID
//then display that student's information.
int selectStudent(Student Roster[]) {
    char* cNumber;

    cout << "Please enter the student's c-number:" << endl;
    cin >> cNumber;

    for(int i; i < SIZE; i++){
        if(strcmp(Roster[i].ID, cNumber)==0){
            return i;
        }
    }
    return -1;
}

//This function will display all our student information
void displayAllStudents(Student Roster[]) {
    cout << "     ID   CLA   OLA   Quiz   Homework   Exam   Bonus   Total   FinalGrade" << endl;

    for (int i = 0; i < SIZE; i++) {
        cout << Roster[i].ID[0] << Roster[i].ID[1] << Roster[i].ID[2] << Roster[i].ID[3] << Roster[i].ID[4] << Roster[i].ID[5] << Roster[i].ID[6]
            << " " << Roster[i].CLA << " " << Roster[i].OLA << " " << Roster[i].Quiz << " " <<
            Roster[i].Homework << " " << Roster[i].Exam << " " << Roster[i].Bonus << " " <<
            Roster[i].Total << " " << Roster[i].FinalGrade << endl;
    }
}


My output.

     ID   CLA   OLA   Quiz   Homework   Exam   Bonus   Total   FinalGrade
c088801 10 15 4 15 56 5 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
        0 0 0 0 0 0 0 0
Press any key to continue . . .

3 个答案:

答案 0 :(得分:1)

readFile中,当您在此处读取文件的内容时,已假定每个Student结构的所有字段都包含数据。

        inFile >> Roster[i].ID >> Roster[i].CLA >> Roster[i].OLA >>
            Roster[i].Quiz >> Roster[i].Homework >> Roster[i].Exam >>
            Roster[i].Bonus >> Roster[i].Total >> Roster[i].FinalGrade;

由于您输入的TotalFinalGrade列中没有内容,因此当您的程序第一次点击>> Roster[i].Total时,它实际上是在尝试读取第二个学生的ID,< em> c088802 ,它不是Roster[i].Total期望的整数值。

如果您知道输入数据永远不会在TotalFinalGrade列中包含内容,则可以从文件读取循环中删除>> Roster[i].Total >> Roster[i].FinalGrade

如果您知道输入数据可能不完整,但不知道将填充多少行,则应该可以这样做,尽管可能有更好的方法。

for (int i = 0; i < SIZE; i++) {
    getline(infile, line);
    stringstream ss(line);

    ss >> Roster[i].ID;

    int value, count = 0;
    while(ss >> value){
        switch(count)
        {
           case 0: Roster[i].CLA = value;
           break;
           case 1: Roster[i].OLA = value;
           break;
           case 2: Roster[i].Quiz = value;
           break;
           ...
           case 7: Roster[i].FinalGrade = value;
           break;
        }
        ++count;
    }        
}

答案 1 :(得分:0)

恕我直言,您应该改变看法,让对象从流中读取其成员:

struct Student
{
    std::string ID;
    //...
    friend std::istream& operator>>(std::istream& input, Student& s);
};

std::istream& operator>>(std::istream& input, Student& s)
{
    input >> s.ID;
    input >> s.CLA;
    //...
    input >> s.FinalGrade;
    return input;
};

然后您可以通过一个简单的循环读取数据:

std::vector<Student> database;
Student s;
while (infile >> s)
{
    database.push_back(s);
}

我在这里做了两个微妙的更改:1)使用std::string作为ID,2)使用std::vector代替数组。

std::vector是从文件读取时使用的出色数据结构,它会根据需要扩展。使用数组时,您将必须继续检查是否有溢出,并根据需要重新分配以容纳新项目。

我相信您的问题是将operator>>与字符数组一起使用。没有方法可以将输入限制为数组的大小。您可能希望将数组增加1,以允许终止nul字符(可以附加在operator>>后面)。 C样式的字符串(字符数组)以nul字符终止,因此您将始终需要该额外的数组插槽。

答案 2 :(得分:0)

我完全同意托马斯·马修斯的说法。

此外,我想展示一个完整的例子。

我将所有学生的数据方法打包在一个struct Student中。所有整数数据都存储在一个std::vector中,并且可以通过索引进行访问。这使生活更轻松。

然后,我们使提取操作符重载。这样,我们可以轻松读取一名学生的完整数据。出于调试目的,我们也使插入程序过载。

请注意:这样一来,通过简单地使用vectors范围构造函数,将所有学生数据读入vector都是一种方法。

所有数据的输出都是超简单的单行代码。

出于乐趣,我还添加了the printSelectedStudendData函数。

请参阅:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <iomanip>

std::istringstream testDataFile(
R"#(c088801    10    15      4         15     56       5 
c088802     9    12      2         11     46       2 
c088803     8    10      3         12     50       1
c088804     5     5      3         10     53       3
c088805     3    11      1         10     45       0 
c088806     8    14      2         11     40      -1  
c088807     4    12      2         12     48      -2
c088808    10    10      3         11     36       0
c088809     8     8      3         11     39       0
c088810     6     9      4          9     47       3
c088811     8     7      3         13     41       3
c088812     4    11      3         11     37       1
c088813     9    15      2          8     50       2
c088814     8    12      2         10     48       4
c088815     6     8      1          7     45       1
c088816     7     7      2          6     51       2
c088817     8     9      2         12     38       2 
)#");

constexpr size_t NumberOfEntriesToRead = 6;

struct Student
{
    std::string ID;             // Student ID
    std::vector<int> data;      // Student related Data

    // Overload extractor operator >> to read all elements of a student
    friend std::istream& operator >> (std::istream& is, Student& s) {
        s.data.clear(); is >> s.ID; 
        std::copy_n(std::istream_iterator<int>(is), NumberOfEntriesToRead, std::back_inserter(s.data));
        return is;
    }

    // Overload inserter operator << to write all elements of a student to a stream
    friend std::ostream& operator << (std::ostream& os, const Student& s) {
        os << std::setw(10) << s.ID;    
        std::for_each(s.data.begin(), s.data.end(), [&os](int i) { os << std::setw(10) << i; });
        return os;
    }
};

void printSelectedStudendData(std::vector<Student>& vs)
{
    std::cout << "\nEnter the c-number of the student:\n\n";
    std::string cNumber{}; std::cin >> cNumber;
    std::vector<Student>::iterator found = std::find_if(vs.begin(), vs.end(), [&cNumber](const Student & s) {return s.ID == cNumber; });
    if (found != vs.end()) 
        std::cout << "\n\nData of student with c-Number '" << cNumber << "'  :\n\n" << *found << "\n\n\n";
    else 
        std::cout << "\n\nCould not find Student with c-Number '" << cNumber << "'\n\n\n";

}

int main()
{
    // Read all data in vector of students. Use vectors range constructor
    std::vector<Student> students{ std::istream_iterator<Student>(testDataFile), std::istream_iterator<Student>()};

    // Search for a student and show his data
    printSelectedStudendData(students);

    // Write all Data to console
    std::copy(students.begin(), students.end(), std::ostream_iterator<Student>(std::cout, "\n"));
    return 0;
}

我希望这会有所帮助。 。