user3038079
user3038079

Reputation: 137

C++ Reading from a file

I have been trying to do this all day but something is just not OK. I'm trying to make a system that reads students from text file and creates three new files. The three files are: Normal, Failed, New. Everything depends of the student's number. If it has 'D' in the beginning the student should go to the file with failed students. If there is 'I' in front of the number the student should go to the file named "New". If there is nothing in the beginning the student should go to the "Normal" file.

The problem is that if the students data is inserted manually to the file by the user everything is ok. But I have a function that reads student's data and inserts it in the main file. If there is nothing in front of the number everything is ok when I try to read all students from the file. But if there is a letter, the data is not being written in the proper(any) file.

Here is example: Let's have a ready file with data in it:

989123 John Brown //Should go to the "Normal" file 
I112233 Steve Round //Should go to the "New" file 
D101010 Wayne Bruce //Should go to the "Failed" file

And if I try to read the data and insert it into the proper files everything is ok. But let's say that the user has choosed the "Add student" option from the applications menu. And the user inserts a new record. For example:

D818181 Some Guy //Should go to the "Failed" file

but it doesn't go there. I don't know what's the reason. If the user has entered a student number without any letter everything is OK but if there is a letter it is not shown in the file. I hope you got my mind. Here is the code. Every help will be appreciated.

#include<iostream>
#include<fstream>
#include<string>
using namespace std;

struct Student
{
    int number;
    string name;
    string secondName;
};

Student Failed[50], New[50], Normal[50];
int o = -1; 
int v = -1;
int n = -1;

int MakeInt(string number, bool ignoreFirst)
{  
    int num; 
    if(ignoreFirst)
    {
        number[0] = '0';
        num = atoi(number.c_str());
    }
    else
    {
        num = atoi(number.c_str());
    }
    return num; 
}

void zapis_student(string number, string name, string secondName)
{
    if(number[0] == 'D')
    { 
        int num = MakeInt(number, true);
        Student temp;
        temp.number = num;
        temp.name= name;
        temp.secondName = secondName;
        o++;
        Failed[o] = temp;
    }
    else if(number[0] == 'I')
    {
        int num = MakeInt(number, true);
        Student temp;
        temp.number = num;
        temp.name = name;
        temp.secondName = secondName;
        v++;
        New[v] = temp;
    }
    else
    {
        int num = MakeInt(number, false);

        Student temp;
        temp.number = num;
        temp.name = name;
        temp.secondName = secondName;
        n++;
        Normal[n] = temp;
    }
}

void ReadFile()
{
    ifstream fp("studenti.txt", ios::in);
    if(fp.fail())
    {
        cout<<"Error!"<<endl; 
    }

    while(fp.good())
    {
        string number, name, secondName;
        fp >> number >> name >> secondName;
        zapis_student(number, name, secondName);
    }
    fp.close();
}


void sortir(Student a[], int br)
{
    for(int i = 0; i < br; i++)
    {
        for(int j = 0; j < br-1; j++)
        {
            if(a[j].number>a[j+1].number)
            {
                Student buf = a[j];
                a[j] = a[j+1];
                a[j+1] = buf;
            }
        }
    }
}

void MakeFile(Student a[], int br, char ime_fail[])
{ 
    ofstream fp(ime_fail); 
    for(int i = 0; i < br; i++)
    {
        fp << a[i].number << " " << a[i].name << " " << a[i].secondName << endl;
    }
    fp.close();
}

void AddStudent()
{
    fstream fp("studenti.txt", ios::app);
    string number, firstName, secondName;
    cin >> number >> firstName >> secondName;
    fp << number << " " << firstName << " " << secondName << endl;
    fp.close();
}

void SortStudents()
{
    sortir(Failed, o);
    sortir(New, v);
    sortir(Normal, n);
}

int main ()
{   int ans;
    do
    {   cout<<"******************************Menu***********************************"<<endl;
        cout<<"*                                                                   *"<<endl;
        cout<<"* 1. Add student.                                                   *"<<endl;
        cout<<"* 2. Read file.                                                     *"<<endl;
        cout<<"* 3. Sort students.                                                 *"<<endl;
        cout<<"* 4. Make Normal file.                                              *"<<endl;
        cout<<"* 5. Make Failed file.                                              *"<<endl;
        cout<<"* 6. Make New file.                                                 *"<<endl;
        cout<<"* 7. Exit!                                                         *"<<endl;
        cout<<"*                                                                   *"<<endl;
        cout<<"*********************************************************************"<<endl;
        cout<<endl<<"Choice: "<<endl;
    do
    {cin>>ans;} while((ans<1)||(ans>7));
    switch(ans)
    { case 1:AddStudent();break;
      case 2:ReadFile();break;
      case 3:SortStudents();break;
      case 4:MakeFile(Normal, n, "Normal.txt");cout<<"Suzdaden e fail NovaGrupa.txt!\n";break; 
      case 5:MakeFile(Failed, o, "Failed.txt");cout<<"Suzdaden e fail Izklucheni.txt!\n";break;
      case 6:MakeFile(New, v, "New.txt");cout<<"Suzdaden e fail Vlizashti.txt!\n";break;
      case 7:exit(1);
    }
    }
    while(ans!=7);
}

Upvotes: 0

Views: 135

Answers (1)

ShinTakezou
ShinTakezou

Reputation: 9671

You have just one single student per type; since you start from -1, you finish the reading with 0, which is the right index for the first element but the wrong count of elements! To fix this, I simply suggest you to start with 0, use the index and then increment. E.g.

   int o = 0;

...

    Failed[o] = temp;
    o++;

(swapped the lines), so that o keeps the count of how many student of that kind you've read so far.

Note: you also need to handle properly the end of file and cope with the case when there's nothing that can be converted to an integer by atoi: you try anyway (and you don't have a way to notice it), and the "normal" count can be one unit greater (after the fix; before the fix, it's the correct count!)

Other suggestions

  • Do not use atoi (for which you should include cstdlib, and you don't)… do not ignore compiler warnings
  • Last argument of MakeFile should be const char *
  • Use better names for variable: o, v, n are poorly named.

Upvotes: 4

Related Questions