C++ ifstream <incomplete type> | Reading only the first time in for()

This is the Debuger Watch: https://gyazo.com/162553614833642f37bf8737fc3d2572

This is the for loop:

for(int i=1;i<=n;i++)
{
getline(cinF,a[i].name);
cinF>>a[i].day>>a[i].month>>a[i].year;
cinF>>a[i].nota1>>a[i].nota2;
cinF>>a[i].absenteT;
cinF>>a[i].motivate;

a[i].absente=a[i].absenteT-a[i].motivate;
a[i].medie=(a[i].nota1+a[i].nota2)/2;
}

Here's the struct:

struct student{
int year;
int month;
int day;
string name;
float nota1;
float nota2;
float medie;
int absenteT;
int absente;
int motivate;};

The txt file:

Sandu Razvan
26 9 2000
8 10
30
15
Stere Eduard
2 6 2001
6 9
20
10
Bala Robert
1 4 2000
4 7
10
5

And declared: ifstream cinF;

If I call the function (that's wokring just fine) "display" I get this for the first name:

Name: Sandu Razvan
Data de nastere: 26 9 2000
Note: 8 10
Medie: 9
Absente: 30
Absente motivate: 15

and that's what I get if I want to display the second name and data:

Name:
Data de nastere: 0 7011888 7011784
Note: 2.8026e-045 1.56172e-038
Medie: 7.80859e-039
Absente: 7011724
Absente motivate: 4199040
A few comments.

a) using formatted input cinF>> together with getline() can cause problems because of a newline left in the input buffer after the last cinF >>. Solution, ignore rest of that line until the newline '\n' is reached.

b) instead of looping for a fixed number of times, only loop while the file has actually been read successfully. Keep a count of how many times that happens (how many records were successfully read from the file).

c) array subscripts start at 0, not 1. Possibly you may have out-of-bounds array access.

Suggested code:
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
#include <iostream>
#include <string>
#include <fstream>

using namespace std;

struct student {
    int year;
    int month;
    int day;
    string name;
    float nota1;
    float nota2;
    float medie;
    int absenteT;
    int absente;
    int motivate;

};
    
void display(const student & s)
{
    cout << "Name:             " << s.name << '\n';
    cout << "Data de nastere:  " << s.day << ' ' << s.month << ' ' << s.year << '\n';
    cout << "Note:             " << s.nota1 << ' ' << s.nota2 << '\n';
    cout << "Medie:            " << s.medie << '\n';
    cout << "Absente:          " << s. absenteT << '\n';
    cout << "Absente motivate: " << s.motivate << "\n\n";
}    
    
int main()
{
    const int n = 10;
    student a[n];
    
    ifstream cinF("data.txt");
    
    if (!cinF)
    {
        cout << "File not open\n";
        return 1;
    }

    int i = 0;
    
    for (  ; i<n && getline(cinF, a[i].name); i++) // getline is part of loop condition
    {
        cinF >> a[i].day >> a[i].month >> a[i].year;
        cinF >> a[i].nota1 >> a[i].nota2;
        cinF >> a[i].absenteT;
        cinF >> a[i].motivate;
        cinF.ignore(100, '\n');  // ignore until end of line
        
        
        a[i].absente = a[i].absenteT - a[i].motivate;
        a[i].medie   = (a[i].nota1 + a[i].nota2) / 2;
    }    
    
    int count = i; // This is the actual number of student records which were read
    
    for (int i=0; i<count; i++)
    {
        display(a[i]);
    }
        
}


Note:

Line 44. loop counter starts from 0, same as array subscripting.

Line 46. File input is part of the loop condition. That means the body of the loop is entered only after successful input.

Line 52. ignore up to 100 characters, or until a newline is found. This prepares for the next iteration of the loop which begins with getline(). Otherwise, an empty line is read (name.size() == 0) and in addition the next cinF >> will fail because instead of finding an integer, it finds the student name.

Line 59. Save the loop counter, it represents the number of student records read from the file.

Line 61. Use the saved count to set the limit for the loop.
Topic archived. No new replies allowed.