输出文件覆盖错误

时间:2014-04-23 06:40:44

标签: c++ output overwrite

这只是跟my last question一起,有人让我上传文件,所以我会删除所有无用的功能,并且主要代码特别是与输出有关,这是我的第3个关于堆栈溢出的问题所以我仍然不知道它是如何工作的,如果你想回答,请查看my last (2nd) question了解详情。这是代码:

#include <iostream>
#include <iomanip>
#include <fstream>

using namespace std;

const int MAX_SIZE = 1000;

struct Student
{
string studentID;
string firstName;
char midInitial;
string lastName;
};


void menu()
{
   cout<<"         CLASS ROSTER APPLICATION"<<endl;
   cout<<"========================================="<<endl;
   cout<<"ADD a student record..................[A]"<<endl;
   cout<<"DELETE a student......................[D]"<<endl;
   cout<<"EDIT a student record.................[E]"<<endl;
   cout<<"INQUIRY about a student...............[I]"<<endl;
   cout<<"LIST all students.....................[L]"<<endl;
   cout<<"QUIT the system.......................[Q]"<<endl;
}


int linearSearch(const Student roster[], int numStuds, string sID)
{
   int i;
   for (i=0; i<numStuds; i++)
   {
       if (roster[i].studentID == sID)
          return i;
   }
   return -1;
}


void selSort(Student roster[], int numStuds)
{
int minIDPos;
Student tempStudRecord;
int i,j;
for (i=0; i<numStuds-1; i++)
{
    minIDPos = i;
    for (j=i+1; j<numStuds; j++)
    {
        if (roster[j].studentID < roster[minIDPos].studentID)
            minIDPos = j;
    }
    tempStudRecord = roster[i];
    roster[i] = roster[minIDPos];
    roster[minIDPos] = tempStudRecord;
 }
}


void listStudents(const Student roster[], int numStuds)
{
 cout<<"C L A S S  R O S T E R"<<endl;
cout<<"Student ID #  First Name   M.I.  Last Name"<<endl;
cout<<"---------------------------------------------"<<endl;
 int i2=0;  //just a counter.
 while (i2<numStuds)
 {
    cout<<left;
    cout<<setw(14)<<roster[i2].studentID<<setw(13)<<roster[i2].firstName;
    cout<<roster[i2].midInitial<<".    "<<roster[i2].lastName;
    cout<<endl;
    i2++;
 }
 cout<<right;
  cout<<"---------------------------------------------"<<endl;
cout<<"Enrollment: "<<i2<<endl;

}

int main()
{
Student roster[MAX_SIZE];
fstream inFile;
fstream outFile;
string filename, sID;
Student newStudent;
int numStuds = 0;
char choice;
int i;
cout<<"Enter the name of the data file> ";
cin>>filename;
/** 7. open the data file for input **/
inFile.open(filename.c_str(), ios::in);

if (inFile)
{
    /** 8. write a while loop to read the data from the file
     into the roster array; the numStuds (number of Students)
     must be updated as the records are read from the file.

     Also, close the file after its contents are read into the
     roster array.
     **/
    while (!inFile.eof() && numStuds < MAX_SIZE)
    {
        inFile>>roster[numStuds].studentID>>roster[numStuds].firstName;
        inFile>>roster[numStuds].midInitial>>roster[numStuds].lastName;
        numStuds++;
    }
    inFile.close();
}
do
{
    cout<<endl;
    menu();
    cout<<endl;
    cout<<"Select an option-> ";
    cin>>choice;
    cout<<endl;
    switch(toupper(choice))
    {
        case 'A': cout<<"Enter the student ID #> ";
            cin>>newStudent.studentID;
            cout<<"Enter the student's first name> ";
            cin>>newStudent.firstName;
            cout<<"Enter the student's middle initial> ";
            cin>>newStudent.midInitial;
            cout<<"Enter the student's last name> ";
            cin>>newStudent.lastName;
            addStudent(roster,numStuds,newStudent);
            break;

        case 'D': /** 9. write code here to remove a student from the roster **/
            cout<<"Enter the student ID Number: ";
            cin>>sID;
            deleteStudent(roster, numStuds, sID);
            break;

        case 'E': /** 10. write code to edit the record for a student with a specified ID # **/
            cout<<"Enter the student ID Number: ";
            cin>>sID;
            editStudent(roster, numStuds, sID);
            break;

        case 'I': /** 11. write code to perform an inquiry (obtain full name) on a student with
                   with a specified ID # **/
            cout<<"Enter the student ID Number: ";
            cin>>sID;
            studentInquiry(roster, numStuds, sID);
            break;

        case 'L': /** 12. write code to sort and then generate class roster **/
            selSort(roster, numStuds);
            listStudents(roster, numStuds);
            break;

        case 'Q': break;

        default:  cout<<"Invalid menu choice...try again!"<<endl;
    }
}while(toupper(choice) != 'Q');

/** 13. open the data file in output mode and error-check to ensure
 that it was successfully opened.
 **/
outFile.open(filename.c_str(), ios::out);
    if (!outFile)
    {
            cout<<"Unable to open "<<filename<<" for output. "<<endl;
            return -1;
    }


/** 14. overwrite the data file in the order:
 student ID, firstname, middle initial and last name, one record per line.
 make sure that you have spaces between the fields.
 **/           
for (i=0;i<numStuds;i++)   
{
    outFile<<roster[i].studentID<<" "<<roster[i].firstName<<" ";
    outFile<<roster[i].midInitial<<" "<<roster[i].lastName<<endl;
} 


/** 15. close the output file **/
outFile.close();

return 0;
}

1 个答案:

答案 0 :(得分:2)

这里

while (!inFile.eof() && numStuds < MAX_SIZE) {
  inFile >> roster[numStuds].studentID >> roster[numStuds].firstName;
  inFile >> roster[numStuds].midInitial >> roster[numStuds].lastName;
  numStuds++;
}

numStuds的值保持高于应有的值,因为inFile.eof()只会在文件结束后返回true,直到您实际上已经尝试阅读文件的末尾。

修复它的一种方法是将其更改为

while (numStuds < MAX_SIZE &&
  (inFile >> roster[numStuds].studentID >> roster[numStuds].firstName >>
  roster[numStuds].midInitial >> roster[numStuds].lastName)
) {
  numStuds++;
}

虽然你最好定义一个为你读取结构的函数

std::istream& operator>>(std::istream& stream, Student& student)
{
  stream >> student.studentID >> student.firstName
         >> student.midInitial >> student.lastName;
  return stream;
} 

其工作原理如下:

while (inFile >> roster[numStuds]) {
  numStuds++;
}

正如@JoachimPileborg所建议的,以下情况会更好(一旦为你的结构定义operator>>):

std::vector<Student> roster;

//...

std::copy(
  std::istream_iterator<Student>(inFile),
  std::istream_iterator<Student>(),
  std::back_inserter(roster)
);