way to make the c++ read without using sentinel

need a way to make my program read info like this.


i have this in my assignment:

1463491 Ali 4 72 65 81 85
1730005 Yousef 5 91 82 94 75 87
5437330 Amna 3 68 72 63
2600004 Abrat 4 52 83 74 66
1300002 Sadiq 2 72 61

i should make the program read the numbers from this file, as you can see there is no -999 or any sign after the numbers, and i'm not allowed to modify the folder to add any sentienl


so how can i make my program read that and stop????


i just reach chapter 11 which it classes.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     for (int i = 0 ; i < numOfStudents ; i ++)
    {
       fcin >>ID>>NAME;

       int y = 0 ;

       while (fcin)  // fcin is as ifstream fcin
       {
           fcin >> S_marks[y];

           y ++;

           cout <<endl<< S_marks[y]<<endl;
       }

       section[i].set(ID, NAME, S_marks ,y);
    }
The sentinel for the grades is the end of the line.
The sentinel for the students is the end of the file.
When a C++ stream reaches the end and you try to extract data from it, it gets put into a failure state. You can simply check that failure state.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <vector>
#include <string>
#include <sstream>

struct Student
{
    int id;
    std::string name;
    std::vector<int> grades;

    friend std::istream &operator>>(std::istream &is, Student &s)
    {
        is >> s.id >> s.name;
        s.grades.clear();
        std::string grades;
        std::getline(is, grades);
        std::istringstream iss {grades};
        int grade;
        while(iss >> grade) //keep reading until no more greades
        {
            s.grades.push_back(grade);
        }
        return is;
    }
};

int main()
{
    std::ifstream ifs {"students.txt"};
    std::vector<Student> students;
    {
        Student s;
        while(ifs >> s) //see line 12
        {
            students.push_back(s);
        }
    }
    //...rest of your program...
}
EDIT: ne555 noticed that the number after the name might be the number of grades - in that case, use his solution, not mine.
Last edited on
I suppose that the number next to the name indicates the quantity of marks to be read
So
1
2
3
4
fin >> id >> name >> n;
marks.resize( n );
for(int K=0; K<n; ++K)
   fin >> marks[K];


If that is not the case, then you can read the line (till the '\n') and process it.

1
2
3
4
5
6
7
8
9
fin >> id >> name;

std::string line;
std::getline( fin, line );
std::istringstream input(line);

int foo;
while( input>>foo )
   marks.push_back( foo );
i really appreciate what you did, but it's too advance.

this what i did in my program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

const int sizeArray = 50;


struct personalInfo
{
    string id , name ;
};

class student
{
     private:
     personalInfo person;
     int numberOfCourses;
     float average ;
     int marks[sizeArray]; // an array of student's marks


     public:
     void set(string ,string ,int S_marks[] , int);
     void getPerson(string &, string& ) const;
     void print()const;
     void findAverage( );  //is used to calculate the average mark for each student.
     float getAverage( );
    // student (int = 1);

};

int maxAverageIndex(int, student [ ]);

int main ()
{
    ifstream fcin ;
    ofstream fout;

    fcin.open("student.txt");

    student section[sizeArray] ;
    int numOfStudents;
    int S_marks[sizeArray];
    string ID, NAME;


    cin>>numOfStudents;

    for (int i = 0 ; i < numOfStudents ; i ++)
    {
       fcin >>ID>>NAME;

       int y = 0 ;

       while (fcin) 
       {
           fcin >> S_marks[y];

           y ++;

        //  >>>>>>>>> cout <<endl<< S_marks[y]<<endl; this only to check and its just keep showing zeros
       }

       section[i].set(ID, NAME, S_marks ,y);
    }



for ( int i = 0 ; i < numOfStudents ; i ++)
{
    section[i].findAverage();
    section[i].print();
}



fcin.close();

    return 0 ;
}


void student::set(string ID,string NAME,int S_marks[], int y)
{
    person.id= ID;
    person.name = NAME;

    for (int u = 0 ; u < y ; u ++)
    {
        marks[u] = S_marks[u];
    }


 numberOfCourses = y;
}

void student::getPerson(string & ID, string & NAME ) const
{
    ID = person.id;
    NAME= person.name;
}

void student::findAverage( )
  {
      average= 0 ;
      for (int x= 0 ; x < numberOfCourses ; x ++)
      {
           average = average + marks[x];
      }

  }

void student::print ()const
{
    cout << "Student "<<person.name<<"  with id "<< person.id <<" has average "
    <<average<<" of "<<numberOfCourses+1 << "courses."<<endl;




    for ( int y = 0 ; y < 3 ; y ++)
    {

        cout << marks[y]<<"   ";
    }
    cout<<endl;
}



THERE is no number of the grades and this is the problem
Last edited on
Maybe you missed ne555's post?
yes and i didn't notice that the number after the name is for the number of the grades.


sorry about that.


NOW the problem is really easy. i thank you both ^^
Topic archived. No new replies allowed.