我正在为我的CS课程做一个实验室,该课程涉及打开三个文件,并根据获得的数据向第四个文件提供输出。我遇到了一些问题(我在C ++上相当生疏),代码让我很头疼。我在字符串和分段错误方面遇到了错误
#include <iostream>
#include <iomanip>
#include <fstream>
#include <list>
#include <vector>
#include <algorithm>
using namespace std;
//Necessary objects/structures
struct student { //create a structure to contain all data consistent to the student
string ID, name, address, phone;
bool is_In_Query;
list<string> class_Grade; //Dynamic list to contain all letter grades since we don't know how many there will be
};
//Prototypes
bool readStudentFile(string, vector<student>);
bool readGradeFile(string, vector<student>);//returning a boolean will report if read was a success
bool readQueryFile(string, vector<student>);
void outputReportFile(string, vector<student>);
float calculateGPA(student); //Pass all calculations and reading to functions to simplify and manage code
void reportFileError(int); //Reports a file error. "1" is Student, "2" is Grade, "3" is Query
int isSame(string, vector<student>);
int main(int argc, const char* argv[])
{
vector<student> studentList; //Allow a range in number of students
if (!readStudentFile("students.txt", studentList)){
if (!readGradeFile("grades.txt", studentList)){
if(!readQueryFile("query.txt", studentList))
outputReportFile("report.txt", studentList);
else
reportFileError(3);
}
else
reportFileError(2);
}
else
reportFileError(1);
return 0; //Termination
/*
if (!readStudentFile(argv[1], studentList)){
if (!readGradeFile(argv[2], studentList)){
if(!readQueryFile(argv[3], studentList))
outputReportFile(argv[4], studentList);
else
reportFileError(3);
}
else
reportFileError(2);
}
else
reportFileError(1);
return 0; //Termination
*/
}
bool readStudentFile(string fileToRead, vector<student> studentInfo)
{
ifstream inFile;
int index = 0;
//inFile.open(fileToRead.c_str()); Original opening line
inFile.open(fileToRead.c_str(), ifstream::in);
if (!inFile.good())
return false;
else while (!inFile.eof()) { //Read in order
getline(inFile, studentInfo[index].ID);
getline(inFile, studentInfo[index].name);
getline(inFile, studentInfo[index].address);
getline(inFile, studentInfo[index].phone);
++index; //We use a prefix to insure that index is incremented BEFORE the jump back to the else-while
}
inFile.close();
return true;
}
bool readGradeFile(string fileToRead, vector<student> studentInfo)
{
ifstream inFile;
string temp;
int sameID = 0;
inFile.open(fileToRead.c_str(), ifstream::in);
if (inFile.fail())
return false;
else while (!inFile.eof()) { //Got more? Ok, let's go!
cin.ignore(); //The class ID is not necessary for our computation
getline(inFile, temp); //Obtain student ID
sameID = isSame(temp, studentInfo); //Find it in our list of IDs
if (sameID != -1){ //If there is a match, get letter grade
getline(inFile, temp);
studentInfo[sameID].class_Grade.push_back(temp);
}
//No match? Ignored.
}
inFile.close();
return true;
}
bool readQueryFile(string fileToRead, vector<student> studentInfo)
{
ifstream inFile;
int sameID = 0;
string temp;
inFile.open(fileToRead.c_str(), ifstream::in);
if (inFile.fail())
return false;
else while (!inFile.eof()) {
getline(inFile, temp);
sameID = isSame(temp, studentInfo); //We get an ID, compare it
if (sameID != -1) //If it's in there, we'll flag it to not report a GPA of 0 due to a bug
studentInfo[sameID].is_In_Query = true;
}
inFile.close();
return true;
}
void outputReportFile(string fileToWrite, vector<student> studentInfo)
{
ofstream outFile;
outFile.open(fileToWrite.c_str(), ifstream::out);
outFile.setf(ios::fixed | ios::showpoint);
for(int x = 0; x < studentInfo.size(); x++){
if (studentInfo[x].is_In_Query){
outFile << setw(12) << studentInfo[x].ID;
outFile << fixed << setprecision(2) << setw(7) << calculateGPA(studentInfo[x]);
outFile << studentInfo[x].name;
}
}
cout << "Finished.\n";
}
float calculateGPA(student scholar)
{
float gpa = 0;
if (scholar.class_Grade.size() == 0)
return 0;
else {
for(list<string>::iterator it = scholar.class_Grade.begin(); it != scholar.class_Grade.end(); ++it)
{
if(*it == "A")
gpa += 4.0;
else if (*it == "A-")
gpa += 3.7;
else if (*it == "B+")
gpa += 3.4;
else if (*it == "B")
gpa += 3.0;
else if (*it == "B-")
gpa += 2.7;
else if (*it == "C+")
gpa += 2.4;
else if (*it == "C")
gpa += 2;
else if (*it == "C-")
gpa += 1.7;
else if (*it == "D+")
gpa += 1.4;
else if (*it == "D")
gpa += 1.0;
else if (*it == "D-")
gpa += 0.7;
else if (*it == "E")
gpa += 0;
}
}
gpa = gpa / scholar.class_Grade.size();
return gpa;
}
int isSame(string id, vector<student> studentInfo)
{
for (int x = 0; x < studentInfo.size(); x++)
{
if (id.compare(studentInfo[x].ID) == 0)
return x;
}
return -1;
}
void reportFileError(int report_num)
{
switch(report_num){
case 1 :
cout << "No valid student file" << endl;
break;
case 2 :
cout << "No valid grade file" << endl;
break;
case 3 :
cout << "No valid query file" << endl;
break;
}
}
(我希望我把它正确地放在代码块中)
如果我尝试使用预定义文件名或CLI参数中的文件名,我会得到相同的错误。我猜它要么与我制造的结构有关,要么与我过度的复杂性有关。
所有文件都包含在我的代码和可执行文件的目录中
答案 0 :(得分:1)
您的函数readStudentFile
直接写入尚未调整大小的矢量。
你必须在索引之前调整大小:
studentInfo.resize( studentInfo.size() + 1 );
student & record = studentInfo.back();
getline(inFile, record.ID);
getline(inFile, record.name);
getline(inFile, record.address);
getline(inFile, record.phone);
或者创建一个记录并附加它:
student record;
getline(inFile, record.ID);
getline(inFile, record.name);
getline(inFile, record.address);
getline(inFile, record.phone);
studentInfo.push_back(record);
答案 1 :(得分:1)
根据您的代码立即浮现在脑海中的两个问题。首先,当你创建一个像studentList
这样的向量时,默认大小和容量都是0.然后当你访问像studentList[index]
这样的向量时,你访问超出向量的末尾并覆盖一些随机的记忆。
如果您知道学生的最大数量(看起来不像),那么您可以将矢量初始化为vector<student> studentList(maxNumberOfStudents)
。这将为您提供一个带有maxNumberOfStudent条目的向量,其中每个条目包含所有字段的默认构造版本(对于字符串,它们将为空)。或者,您可以使用studentList.push_back(student())
之类的内容向向量追加新条目。你可以用更清洁的方式来做到这一点,但这是一般的想法。
其次,将studentList
向量传递给函数时,您需要通过引用(vector<student>& studentList
)传递它。没有&
,你传递的值就意味着你每次都要复制矢量。由于有几个函数修改了向量,如果你通过值传递,你将修改副本,但原始文件将保持不变。
希望有所帮助!