Program with file reading falls in an infinite loop when executing in one machine, nor in another one

closed account (10X9216C)
Hello,
I have the following Problem:

I help a friend programming a game for a class project. The program must load the previously played games from a text file. For every game, it is stored: game id, player name, target position (2 numbers between 0 and 9) and player shots (2 numbers 0~9). There are 4 shots for game, and there are always 4 lines with information about shots. If player hits target with less than 4 shots, the remaining lines are filled with -1. This is an example of file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
John Stevens
8 8
1 1
4 4
7 7
8 7
2
Michael Ferguson
2 3
1 1
3 3
2 3
-1 -1
3
John Stevens
1 1
1 1
-1 -1
-1 -1
-1 -1


Well, I write the following code for reading the games and put it into a list:
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
#include <fstream.h>
//...
struct Partida{
       int identificador;
       string nombre;
       Coordenadas ubicacion;
       Coordenadas intentos [N_INTENTOS];
};
//...
int main (void){
//...
    string fich="historico.dat";
    ifstream fe;
    Partida partida;    
    Puntero lpartidas=NULL, aux, upartida=NULL;
//...
    partida.identificador=0;
    fe.open(fich.c_str());
    if (!fe){
       cout<<"File "<<fich<<" not find or could not be opened."<<endl;
       cout<<"No historical results."<<endl;
    }
    else{
         do{  
            fe>>partida.identificador;
            if(fe.eof()) break;   
            fe>>partida.nombre;
            fe>>partida.ubicacion.fila;
            fe>>partida.ubicacion.columna;
            for(i=0;i<N_INTENTOS;i++){
                     fe>>partida.intentos[i].fila;
                     fe>>partida.intentos[i].columna;
            }
            
            // Insert game in game list
            aux=new Nodo;
            aux->partida=partida;
            aux->sig=NULL;
            if(upartida!=NULL)
                upartida->sig=aux;
            else
                lpartidas=aux;
            upartida=aux;
        }while(!fe.eof());
         fe.close ();
    }


In my system (Windows 7 64 bit) it works fine. In my friend's system (Windows 7 64 bit, too) the same executable crashes. I compile the same code in his system and it crashes too. Adding "couts" to the code I see the problem is in the code I copy previously. The do-while loop enters in infinite loop. The executable compiled in my friend's system runs in my system without infinite loop. Both executables works fine in a third system (Windows XP).

To sum up, not matters where is compiled, this code enters in an infinite loop in my friend's system, but not in mine or another one. I don't know or imagine why.

We will continue programming in my system, and probably that piece of code will be changed. But I never have seen the same executable entering in an infinite loop depending of the machine where it's running. It's normal? What causes it? How can I prevent it?

Here is the executable and the code: http://www.mediafire.com/?61yqaoh6ab7v86z (you're antivirus can detect it, because... in your system this can have an infinite loop with memory allocating, and that's a rudimentary virus, really)
And here is the only the code (it's in spanish, sorry about that, and excuse my bad English):
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include <iostream>
#include <string>
#include <stdlib.h>
#include <fstream.h>
#include <math.h>
using namespace std;

int const FILAS=10;
int const COLUMNAS=10;
int const N_INTENTOS=4;
typedef int mat[FILAS][COLUMNAS];
typedef bool matbool[FILAS][COLUMNAS];

struct Coordenadas
{ 
       int fila;
       int columna;
};

struct Partida
{
       int identificador;
       string nombre;
       Coordenadas ubicacion;
       Coordenadas intentos [N_INTENTOS];
};

struct Nodo;
typedef Nodo * Puntero;
struct Nodo
{
       Partida partida;
       Puntero sig;
};       

int main (void)
{
    int f, c, i, j, fil, col, nm=0, ganadas=0, perdidas=0, puntos;
    float  distancias=0;
    char jugar;
    string nombre;
    mat matriz;
    matbool introducidas;
    Coordenadas intentos[N_INTENTOS];
    
    ofstream fsal; //output file, fichero de salida
    ifstream fent; // input file, fichero de entrada
    
    Partida partida;
    
    Puntero lpartidas, aux;
    lpartidas=NULL;

    srand(time(NULL));
    
    cout<<"Como te llamas?"<<endl;
    getline (cin, nombre);
    
    fent.open  ("historico.dat") ;
    if (!fent)
       cout<<"El fichero no se abrio correctamente"<<endl;
    else 
       { 
                    
             fent>>partida.identificador;
             fent>>partida.nombre;
             fent>>partida.ubicacion.fila;
             fent>>partida.ubicacion.columna;
             for(i=0;i<N_INTENTOS;i++)
                 {
                 fent>>partida.intentos[i].fila;
                 fent>>partida.intentos[i].columna;
                 }
                 
             
             aux=new Nodo;
             aux->partida=partida;
             aux->sig=lpartidas;
             lpartidas=aux;
             
             fent.close();
       }    
             
             
             
    
    
    
    // Inicializar las partidas de esta ejecucion
    partida.identificador=1;
    partida.nombre=nombre;
    do
    {
    
    f=rand()%FILAS;
    c=rand()%COLUMNAS;
    
    partida.ubicacion.fila=f;
    partida.ubicacion.columna=c;
    
    for(i=0;i<FILAS;i++)
          for(j=0;j<COLUMNAS;j++)
          { 
            matriz[i][j]=abs(f-i)+abs(c-j);
            introducidas[i][j]=false;
          }
            
   nm=0;
        
    do 
    {
     system("cls");    
    cout<<"  0 1 2 3 4 5 6 7 8 9"<<endl;
    cout<<"  ___________________"<<endl;
    for(i=0;i<FILAS;i++){
       cout<<i<<"_";
       for(j=0;j<COLUMNAS;j++){
           if(introducidas[i][j]){  //Si la luz es verde :
             if(matriz[i][j]>9)     //y si la distancia entre el barquito y mi coordenada es mayor que 9
                 cout<<">";        //se mostrará por pantalla el símnbolo '>'
             else                  //y si no lo es
                 cout<<matriz[i][j];  // el numero que indica la distancia entre el barco, y yo 
           }
           else                      // si no (si la luz no es verde)
              cout<<" ";           //saca un espacio
           if(j!=COLUMNAS-1)
              cout<<" ";
       }
       cout<<"_"<<i<<endl;
    }
    cout<<"  ___________________"<<endl;
    cout<<"  0 1 2 3 4 5 6 7 8 9"<<endl;
    cout<<"Numero de movimientos: "<<nm<<endl;
    cout<<"Introduzca fila: ";
    cin>>fil;
    cout<<"Introduzca columna: ";
    cin>>col;
    introducidas[fil][col]=true;
    partida.intentos[nm].fila=fil;
    partida.intentos[nm].columna=col;    
    nm++;
    
    distancias+=matriz[fil][col];    
    }
    while((fil!=f || col!=c )&& nm<N_INTENTOS);
    
    if(fil==f && col==c)
             { cout<<"Has ganado. (ya lo modificaremos)";
              ganadas++;
              }
    else
       { cout<<"Has perdido. Lo siento, ninyo.";   
        perdidas++;}
        
    for(i=nm; i<N_INTENTOS; i++){
              partida.intentos[nm].fila=-1;
              partida.intentos[nm].columna=-1;
    }
        
        // Insertar la partida en la lista de partidas
        aux=new Nodo;
        aux->partida=partida;
        aux->sig=lpartidas;
        lpartidas=aux;
    
    partida.identificador++;
        
    puntos=(int)(1000*(1/(1+distancias)));
    cout<<"Tu puntuacion es: "<<puntos<<endl;
    
    cout<<"Partidas ganadas: "<<ganadas<<endl;
    cout<<"Partidas perdidas: "<<perdidas<<endl;        
        
    cout<<"Quieres volver a jugar? Responde S, si quieres y N si no quieres !! "<<endl;
    cin>>jugar;
    
}

    while (jugar=='S');
    
    
    
    fsal.open ("historico.dat");
    if (!fsal)
        cout<<"Meeeeeeeeeeeeec"<<endl;
    else{
         // Recorrer la lista de partidas e ir escribiendolas en fichero
        aux=lpartidas;
         while(aux!=NULL){
             partida=aux->partida;
             // Escribir la partida en fichero
             fsal<<partida.identificador<<endl;
             fsal<<partida.nombre<<endl;
             fsal<<partida.ubicacion.fila<<' '<<partida.ubicacion.columna<<endl;
             for(i=0;i<N_INTENTOS;i++)
                 fsal<<partida.intentos[i].fila<<' '<<partida.intentos[i].columna<<endl;
                 
             aux=aux->sig;
         }
        fsal.close ();
    }
    
    system ("pause");
    return 0;
}
Use getline() when reading strings with spaces.
You should also use fe.good() instead of fe.eof() . You may never reach end of file if another error occurs.

This should work:
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
         do{
            fe>>partida.identificador;

            fe.ignore('\n');
            getline(fe,partida.nombre);

            fe>>partida.ubicacion.fila;
            fe>>partida.ubicacion.columna;
            for(int i=0;i<N_INTENTOS;i++){
                     fe>>partida.intentos[i].fila;
                     fe>>partida.intentos[i].columna;
            }
 
            // Insert game in game list
            aux=new Nodo;
            aux->partida=partida;
            aux->sig=NULL;
            if(upartida!=NULL)
                upartida->sig=aux;
            else
                lpartidas=aux;
            upartida=aux;

        }while(fe.good());
         fe.close ();
    }
closed account (10X9216C)
Yes, your solution works! (Well, it avoids the infinite loop)

In later executions I obtained the infinite loop in my system, too. The problem, as you say, it's that another error occurs and I never reach end of file. I checked it and failbit was set.

Also, the
1
2
fe.ignore('\n');
getline(fe,partida.nombre);
makes it capable of reach the end of file.

However, it causes problems, too. I think I find the cause.

That's a problem reading mixed integers and lines:

fe>>partida.identificador;
An integer (1, for example) is read into partida.identificador. The newline following the 1 is still sitting on the input buffer.

getline(fe,partida.nombre);
The getline() immediately processes the newline that is still on the input buffer. partida.nombre becomes an empty string.

Your solution tries to avoid it adding a fe.ignore('\n'); before the getline. This would grab the character '\n' off of the input buffer and discard it. But this causes partida.nombre and the rest of fields not read correctly and set the failbit.

I suppose this is caused by the newline representation in Windows (this post is in the Windows Programming forum), the CR+LF or "\r\n". When I call the ignore function without parameters (fe.ignore();) it works fine.

Thank you very much!
Last edited on
Topic archived. No new replies allowed.