很抱歉,如果这看起来很愚蠢,我对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 . . .
答案 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;
由于您输入的Total
和FinalGrade
列中没有内容,因此当您的程序第一次点击>> Roster[i].Total
时,它实际上是在尝试读取第二个学生的ID,< em> c088802 ,它不是Roster[i].Total
期望的整数值。
如果您知道输入数据永远不会在Total
和FinalGrade
列中包含内容,则可以从文件读取循环中删除>> 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;
}
我希望这会有所帮助。 。