Result in repeated C ++ screen [closed]

1

When I search for a student, I get the result twice or return to the previous menu. This is my code:

#include <iostream>
#include <windows.h>
#include <vector>
#include <stdio.h>
#include <conio.h>
#define TOTAL 1000

using namespace std;

struct Alumno
{
    char apellido[50];
    char nombre[50];
    int dni;
    int legajo;
};

int Ingresar_Alumno (int &e)
{
    FILE *cho;
    Alumno vectoralumno[TOTAL];

    if (cho=fopen("cho.dat", "wb+"))
    {
            cout << "ingrese el nombre del alumno: ";
            cin >> vectoralumno[e].nombre;

            cout << "ingrese el apellido del alumno: ";
            cin >> vectoralumno[e].apellido;

            cout << "ingrese legajo del alumno: ";
            cin >> vectoralumno[e].legajo;

            cout << "ingrese el DNI del alumno: ";
            cin >> vectoralumno[e].dni;

        fwrite(vectoralumno,sizeof(struct Alumno),1,cho);

        }
    fclose(cho);
    e++;
}

void BuscarDNI(int dni, int &q)
{
    Alumno dchof;
    FILE *x;
    if(x=fopen("cho.dat","rb"))
    {
        fseek(x,0,SEEK_SET);

        while (!feof(x))
        {

            fread(&dchof,sizeof(struct Alumno),1,x);

            if(dni == (dchof.dni))
            {
                Search:
                cout << "El alumno buscado es: " << endl;
                cout << "Nombre: " << dchof.nombre << endl;
                cout << "Apellido: " << dchof.apellido << endl;
                cout << "Legajo: " << dchof.legajo << endl;
                cout << "DNI: " << dchof.dni << endl;
                cout<< "Toque cualquier boton para volver al menu anterior" << endl;
                getch();
            }
        }
        if(dni!=dchof.dni)
        {
            cout<< "Error: DNI Incorrecto" << endl;
            cout<< "Toque cualquier boton para volver al menu anterior" << endl;
            getch();
        }
    }
    fclose(x);
}

int main()
{
    int a,op=0,e=0,q=0;
    int dni;
    MainMenu:
do
{

    system("cls");
    cout << "Elija alguna opcion para empezar" << endl;
    cout << " " << endl;
    cout << "1 - Ingresar nuevo alumno" << endl;
    cout << "2 - Buscar alumno" << endl;
    cout << "3 - " << endl;
    cout << "4 - " << endl;
    cout << "5 -  " << endl;
    cout << "6 - Salir" << endl;
    cout << " " << endl;
    cout << "Ingrese una opcion deseada: ";
    cin >> op;
    system("cls");
    switch (op)
    {
        case 1:

            Ingresar_Alumno(e);
            system("cls");
        break;

        case 2:

            cout<< "Buscar alumno por DNI: ";
            cin >> dni;
            BuscarDNI(dni,q);

        break;

        case 3:
        break;

        case 6:
        break;

        default:
            cout<< "ERROR: OPCION INCORRECTA "<< endl;
            getch();
            system ("cls");
            break;
    }
}while(op!=6);
return 0;
}

A snapshot of my running program:

    
asked by Salva Castro 25.05.2017 в 00:41
source

2 answers

2
while (!feof(x))
{
  fread(&dchof,sizeof(struct Alumno),1,x);

You're assuming that feof inspects the file and checks if the internal pointer is at the end of the file ... and it's not like that. feof consults a flag that is activated when an operation is performed that exceeds the end of the file.

That is, if you have 2 records in the file you will get the following sequence:

  • feof() == 0
  • fread() the first record is read
  • feof() == 0
  • fread() the second record is read
  • feof() == 0
  • fread() erroneous reading
  • feof() == 1

A more appropriate way to program this part could be like this:

if(x=fopen("cho.dat","rb"))
{
  fseek(x,0,SEEK_SET); // (1)

  fread(&dchof,sizeof(struct Alumno),1,x);
  while (!feof(x))
  {
    if(dni == (dchof.dni))
    {
      // ...
    }

    fread(&dchof,sizeof(struct Alumno),1,x);
  }
  // ...
}

Note: The line with the comment is a line that you can save. When opening a file in read mode, the internal pointer always will be found at the beginning of it.

If you do not like to repeat the line of fread you can try something such that:

if(x=fopen("cho.dat","rb"))
{
  while ( true )
  {
    fread(&dchof,sizeof(struct Alumno),1,x);
    if( feof(x) )
      break;

    if(dni == (dchof.dni))
    {
      // ...
    }
  }
  // ...
}

Even, since you're in C ++, if you compile with C ++ 11 or higher you could use a lambda:

if(x=fopen("cho.dat","rb"))
{
  auto lambda = [&](){
    fread(&dchof,sizeof(struct Alumno),1,x);
    return feof();
  };

  while ( lambda() )
  {
    if(dni == (dchof.dni))
    {
      // ...
    }
  }
  // ...
}

Although, of course, already set to program in C ++ perhaps you should take a look at the C ++ classes for file management.

    
answered by 25.05.2017 / 11:01
source
1

The While (! feof (x))

That is the problem. When you read the first line

fread(&dchof,sizeof(struct Alumno),1,x);

fread returns a value; if the reading is correct, fread returns the total number of items read successfully, otherwise it will return an error

In your case, first read the line and save the result in dchof. Then you compare, print and the cycle is done again (because the file has not been reached), the function fread is executed again, and there it returns that the end of the file has actually been reached, but it does not overwrite dchof, because what the comparison returns to be positive and the result is printed again.

The While (fread ())

There are many ways to solve this error. One that I like is this: Do the while directly with what I want to read:

 while ( fread(&dchof,sizeof(struct Alumno),1,x) )
 {

    if(dni == (dchof.dni))
    {
        Search:
        cout << "El alumno buscado es: " << endl;
        cout << "Nombre: " << dchof.nombre << endl;
        cout << "Apellido: " << dchof.apellido << endl;
        cout << "Legajo: " << dchof.legajo << endl;
        cout << "DNI: " << dchof.dni << endl;
        cout<< "Toque cualquier boton para volver al menu anterior" << endl;
        getch();
     }
 }

Greetings

    
answered by 25.05.2017 в 02:13