C++ 字符串和文件有问题
我正在为我的CS课程做一个实验,包括打开三个文件并根据获得的数据向第四个文件提供输出。我遇到了一些问题(我对C++有些生疏),代码让我头疼。我遇到过字符串错误和分段错误C++ 字符串和文件有问题,c++,file-io,segmentation-fault,C++,File Io,Segmentation Fault,我正在为我的CS课程做一个实验,包括打开三个文件并根据获得的数据向第四个文件提供输出。我遇到了一些问题(我对C++有些生疏),代码让我头疼。我遇到过字符串错误和分段错误 #include <iostream> #include <iomanip> #include <fstream> #include <list> #include <vector> #include <algorithm> using namespace
#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;
}
}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
//必要的物体/结构
struct student{//创建一个包含与学生一致的所有数据的结构
字符串ID、姓名、地址、电话;
布尔是查询中的布尔;
list class_Grade;//动态列表包含所有字母等级,因为我们不知道有多少字母等级
};
//原型
bool readStudentFile(字符串、向量);
bool readgrade文件(字符串、向量)//如果读取成功,则返回布尔值将报告
bool readQueryFile(字符串、向量);
无效输出报告文件(字符串、向量);
浮动计算器EGPA(学生)//将所有计算和读取传递给函数,以简化和管理代码
无效报告文件错误(int)//报告文件错误。“1”是学生,“2”是年级,“3”是查询
int-isname(字符串,向量);
int main(int argc,const char*argv[]
{
vector studentList;//允许学生数量的范围
如果(!readStudentFile(“students.txt”,studentList)){
如果(!readgrade文件(“grades.txt”,studentList)){
如果(!readQueryFile(“query.txt”,studentList))
输出报告文件(“report.txt”,studentList);
其他的
报告文件错误(3);
}
其他的
报告文件错误(2);
}
其他的
reportFileError(1);
返回0;//终止
/*
如果(!readStudentFile(argv[1],studentList)){
如果(!ReadGrade文件(argv[2],学生列表)){
if(!readQueryFile(argv[3],studentList))
输出报告文件(argv[4],学生列表);
其他的
报告文件错误(3);
}
其他的
报告文件错误(2);
}
其他的
reportFileError(1);
返回0;//终止
*/
}
bool readStudentFile(字符串文件toread,向量studentInfo)
{
河流充填;
int指数=0;
//infle.open(fileToRead.c_str());原始打开行
open(fileToRead.c_str(),ifstream::in);
如果(!infle.good())
返回false;
else while(!infle.eof()){//按顺序读取
getline(infle,studentInfo[index].ID);
getline(infle,studentInfo[index].name);
getline(infle,studentInfo[index].地址);
getline(infle,studentInfo[index].phone);
++index;//我们使用前缀确保在跳回else之前增加索引
}
infle.close();
返回true;
}
bool readgrade文件(字符串文件读取,向量studentInfo)
{
河流充填;
字符串温度;
int-sameID=0;
open(fileToRead.c_str(),ifstream::in);
if(infle.fail())
返回false;
还有(!infle.eof()){//还有更多吗?好的,我们走吧!
cin.ignore();//我们的计算不需要类ID
getline(infle,temp);//获取学生ID
sameID=isSame(temp,studentInfo);//在我们的ID列表中找到它
如果(sameID!=-1){//如果存在匹配项,则获取字母等级
getline(填充、温度);
学生信息[sameID]。班级成绩。向后推(临时);
}
//没有匹配?忽略。
}
infle.close();
返回true;
}
bool readQueryFile(字符串文件toread,向量studentInfo)
{
河流充填;
int-sameID=0;
字符串温度;
open(fileToRead.c_str(),ifstream::in);
if(infle.fail())
返回false;
else while(!infle.eof()){
getline(填充、温度);
sameID=isSame(temp,studentInfo);//我们得到一个ID,比较它
if(sameID!=-1)//如果它在那里,我们将标记它不报告由于错误导致的GPA为0
studentInfo[sameID]。是否在\u Query=true;
}
infle.close();
返回true;
}
void outputreport文件(字符串fileToWrite,向量studentInfo)
{
出流孔的直径;
open(fileToWrite.c_str(),ifstream::out);
setf(ios::fixed | ios::showpoint);
对于(int x=0;x outFile您的函数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);
基于您的代码,您会立即想到两个问题。首先,当您创建一个向量(如studentList
)时,默认大小和容量均为0。当您访问向量(如studentList[index]
)时,您正在访问向量末尾之外的内容,并覆盖一些随机内存
如果您知道最大学生数(看起来与您不一样),则可以将向量初始化为向量studentList(maxNumberOfStudents)
。这将为您提供一个包含maxNumberOfStudent条目的向量,其中每个条目包含所有字段的默认构造版本(对于字符串,它们将为空)。或者,您可以使用类似于studentList.push_back(student())
的方法将一个新条目附加到向量。您可能可以使用一种更简洁的方法来执行此操作,但这是一般的想法
第二,将学生列表
向量传递给要通过引用传递的函数(向量和学生列表
)时。如果没有&
,则传递的是值,这意味着您每次都在复制向量。由于多个函数修改向量,如果通过值传递,则将