the program stops on the 10th turn of a for. c ++

1

It happens that the program I have stops.

You're supposed to read:

  • Name
  • Certificate
  • 5 releases
  • Major release
  • Average number of launches

All that in a array / vector , eh open a for that runs through the 10 athletes, the for 9 cycles, in the 10th reads the name and card of the athlete number 10 and just after "reading" the first launch the program stops working.

  

"Proyecto.exe has stopped working"

(those launches are inside a matrix, so I use for to save code lines)

All that happened after you changed all the initial values of each for from 0 to 1

for (i=0 ; i<10 ; i++)  ------>>   for (i=1 ; i<11 ; i++)
#include <iomanip>
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

using namespace std;

int main(int argc, char *argv[]) {
    struct atleta {
        char n[30];
        float lm,l[5],prom,pr;
        int ced,acc;
    };
    struct atleta at[10]; //Esta vaina es la estructura //

    int m,i,j,k,f1,f2,c1,c2,f3,c3,f4,c4,q,w,t,e;
    float lm2;
    int op;
    char resp='s';

    while (resp=='s' || resp=='S')
    {
    //menu <<abre//
    cout<<endl<<"Bienvenido al programa, escoga una de las siguientes opciones para continuar";
    cout<<endl;
    cout<<endl<<"ingresar datos de los atletas (recomendado)= 1";
    cout<<endl<<"Modificar los datos de un atleta= 2";
    cout<<endl<<"Mostrar un listado de todos los atletas= 3";
    cout<<endl<<"Mostar los datos de un atleta segun su cedula= 4";
    cout<<endl<<"Mostar los datos del ganador= 5";
    cout<<endl<<"Atletas cuyo promedio es supera los 70 metros=; 6";
    cout<<endl<<"Salir= 7";
    for (k=1;k<2;k++)
    {
        op=0;
        cout<<endl<<endl<<"Indique su opcion: ";    cin>>op;
        if(op<=0)
        {
            //system ("cls");
            cout<<endl<<"Indique una opcion valida1";
            k--;

        }
        else
        {

        }
    }

    //menu <<cierra//

    switch (op) 
    {
    case 1:
        system ("cls");
        for(i=1;i<11;i++) //leer datos de los 10 atletas <<abre// este es el original
        {
            cout<<endl<<"Indique el nombre del atleta Nº"<<i<<": ";
            fflush(stdin);
            gets (at[i].n);

            for (j=1;j<2;j++) //leer y validar la cedula <<abre//
            {
                cout<<endl<<"Indique la cedula del atleta: ";
                cin>>at[i].ced;
                if (at[i].ced>0 && at[i].ced<=99999999)
                {
                    //cout<<endl<<"Cedula Valida";
                }   
                else
                {
                cout<<endl<<"Ingrese una cedula valida";
                j--;
                }
            } //leer y validar la cedula <<cierra//

            cout<<endl<<"A continuacion indique los 5 lanzamientos del atleta";
            cout<<endl;
            at[i].acc=0;
            for (c1=1;c1<6;c1++) //leer y validar los 5 lanzamientos <<abre//
            {
                cout<<endl<<"ingrese el lanzamiento numero "<<c1<<": "; 
                cin>>at[i].l[c1]; //el for principal se ejecuta 10 veces a la 10ma vez el exe deja de funcionar justo aqui

                if (at[i].l[c1]<0)
                    c1--;
                else
                {

                }
                at[i].acc=at[i].acc+at[i].l[c1]; //promedio de lanzamientos del atleta de turno <<abre//

            } //leer y validar los 5 lanzamientos <<cierra//
            cout<<at[i].acc<<endl;
            at[i].prom=(at[i].acc)/5;       //promedio de lanzamientos del atleta de turno <<cierra//
            cout<<at[i].prom<<endl;
            //calcular el lanzamiento mayor del atleta <<abre//
            at[i].lm=0;

                for (c2=1;c2<6;c2++)
            {
                    if (at[i].l[c2]>at[i].lm)
                        at[i].lm=at[i].l[c2];
                    else
                        at[i].lm=at[i].lm;
            } //calcular el lanzamiento mayor del altleta <<cierra//

        } //ingresar los datos de los 10 atletas <<cierra//
        break;
    case 2: //modificar los datos de un atleta
        cout<<endl<<"indique el numero del altleta a modificar";
        cin>>m;
        for (e=1;e<2;e++)
        {
            if (m<0 && m>10)
            {
                cout<<endl<<"indique un numero valido";
                e--;
            }
            else{}
        }
        cout<<endl<<"indique el nombre";
        cin>>at[m].n;
        cout<<endl<<"indique la cedula";
        cin>>at[m].ced;
        for (t=1;t<2;t++)
        {
            if (at[t].ced>0 && at[t].ced<=99999999)
            {}  
            else
            {
                cout<<endl<<"Ingrese una cedula valida";
                t--;
            }
        };
        for (f1=1;f1<6;f1++)
        {
            cout<<endl<<"Indique el lanzamiento Nº"<<f1<<" :";
            cin>>at[m].l[f1];

            if(at[m].l[f1]<0)
            {
                cout<<endl<<"Indique una cantidad valida";
                f1--;
            }
            else {}
        }
        break;
    case 3: //mostrar los datos de todos los atletas
        system ("cls");
        cout<<endl<<"N"<<"==Ced"<<"==L1"<<"==L2"<<"==L3"<<"==L4"<<"==L5"<<"==LM"<<"==Prom"<<endl;
        for (f4=1;f4<11;f4++)
        {
            cout<<at[f4].n<<"=="<<at[f4].ced;
            for (c4=1;c4<6;c4++)
            {
                cout<<"=="<<at[f4].l[c4];
            }
            cout<<"=="<<at[f4].lm<<"=="<<at[f4].prom<<endl;
        }
        break;
    case 4: //datos de un atleta segun su cedula (utilizando una funcion)
        system ("cls");

        break;
    case 5: //atleta ganador y sus datos
        system ("cls");
        lm2=0;
        for (f3=1;f3<11;f3++)
        {
            if (at[f3].lm>lm2)
                lm2=at[f3].lm;
            else
                lm2=lm2; //lanzamiento mayor calculado//
        }
        for(f2=1;f2<11;f2++)
        {
            if(lm2==at[f2].lm)
            {
                cout<<endl<<"Atleta ganador";
                cout<<at[f2].n<<"="<<at[f2].ced;
                for (c3=1;c3<6;c3++)
                {
                    cout<<"="<<at[f2].l[c3];
                }
                cout<<"="<<at[f2].lm;
                cout<<"="<<at[f2].prom;
            }
            else {}
        }
        break;
    case 6: //atletas con un promedio mayor a 70
        system ("cls");
        for(q=1;q<11;q++)
        {
            at[q].pr=0;
            if(at[q].prom>70)
            {
                at[q].pr=at[q].prom;
            }
            else{}
        }
        for (w=1;w<11;w++)
        {
            if(at[w].pr>70)
            {
                cout<<at[w].n<<"="<<at[w].ced;
                for (c4=1;c4<6;c4++)
                {
                    cout<<"="<<at[w].l[c4];
                }
                cout<<"="<<at[w].lm;
                cout<<"="<<at[w].prom<<endl;
            }
            else{}
        }
        break; 
    case 7: //salir
        system ("cls");
        cout<<endl;
        break;
    default:
        system ("cls");
        cout<<endl<<"Indique una opcion valida"<<endl;
    } //switch case <<cierra//
    cout<<endl<<"para volver al menu presione 's', para salir del programa presione cualquier otra tecla"; cin>>resp;
    system ("cls");
    } //while <<cierra//
    return 0;
}
    
asked by Kristhian Quintero 18.11.2017 в 23:51
source

4 answers

4

If you debug your program step by step, the problem would be obvious to you. I advise you to do it as a didactic exercise. Meanwhile, I explain the problem:

Arrangements.

  • Arrays are a memory space that stores objects of the same type. They are defined this way: tipo nombre[tamaño] , you have an arrangement of type atleta declared like this:

    atleta at[10];
    
  • Fixes in C ++ are indexed from 0 , so at[0] corresponds to the first position, at[1] to the second, at[2] to the third, and so on.
  • Fixes in C ++ are stored in contiguous memory, this implies that between the start of at[0] and the beginning of at[1] there will be a number of bits equivalent to sizeof(atleta) since atleta is the type of the data stored in the at fix.
  • C ++ does not check limits on fixes, so it is possible to access elements that do not correspond to those managed by the fix.
  • Although in C ++ it is possible to access elements outside the limits of the array, doing so can cause the program to throw errors at run time.

Your arrangement.

You have an arrangement of 10 atleta :

atleta at[10];

That in memory will look like this:

As you can see, you have a variable called at that points to the beginning of 10 contiguous elements (count them, they are exactly 10, even if they start at 0 and end at 9).

Your code.

  

All that happened after you changed all the initial values of each for from 0 to 1

     
for (i=0 ; i<10 ; i++)  ------>>   for (i=1 ; i<11 ; i++)
  

Originally you went through the arrangement of the position 0 to the position 9 (since the value 10 violates the condition <10 ) and as those are exactly the positions that your arrangement has at everything worked correctly.

With the new change you go through the arrangement of the position 1 (which is the second position of the array) to the position 10 (which does not exist as the positions reach up to 9 ).

Trying to work with the 10 position (which is not assigned to the at fix) causes the program to fail at run time.

Other things to consider.

  • You have misspellings.
  • In C ++ the keyword struct is not part of the type, so it is not necessary to define variables of type struct :

       /*struct*/ atleta at[10];
    // ~~~~~~~~~~ <-- innecesario!
    
  • C headers adapted to C ++ have no extension and have the prefix " c ", so <stdio.h> , <stdlib.h> and <math.h> would be <cstdio> , <cstdlib> and <cmath> (see this question for more details).
  • You do not need the C headers that you are including, even if you included them correctly (which has not been the case, see previous point).
answered by 20.11.2017 / 09:27
source
5
  

All that happened after changing all the initial values of each for from 0 to 1

The indexes start always at 0 ... Why then endeavor to reinvent the wheel and start them at 1?

If you make that change you have to change all the accesses to the vector:

at[i]   // MAL!!!!!
at[i-1] // BIEN

If you do not do this, two things happen:

  • In the first iteration ( i==1 ), you are accessing directly to the second element, then you will be ignoring the first element always . This does not cause execution errors but is not a desired behavior.
  • In the last iteration ( i==10 ), you will be accessing an element that does not belong to the vector. What happens here is that you access memory that does not belong to your vector ... if the memory you access belongs to your program you will step on memory and the program will become erratic ... if the memory does not belong to you, the Operating System will kill your process to avoid corrupting memory of other processes.
  • So, I suggest you do yourself a favor and get used to traversing the vectors in the range (0..n-1) instead of the range (1..n). You will get your code compatible with that of 100% of the programmers who know how to do things.

    And already speaking we talk about your code:

    ¿??

    This code does not make any sense:

    for (k=1;k<2;k++)
    {
        op=0;
        cout<<endl<<endl<<"Indique su opcion: ";    cin>>op;
        if(op<=0)
        {
            //system ("cls");
            cout<<endl<<"Indique una opcion valida1";
            k--;
    
        }
        else
        {
    
        }
    }
    

    Your idea is to iterate until the user enters a valid option ... for that there exists while whose translation while is more appropriate to this context. For the benefit of your own health, try to make the code as legible as possible:

    do
    {
      cout<<endl<<endl<<"Indique su opcion: ";
      cin>>op;
      if(op<=0)
        cout<<endl<<"Indique una opcion valida\n";
    } while( op <= 0 );
    

    Do not mix buffers

    In your program you are using the libraries iostream and stdio.h . The first one is typical of C ++ and the second one reminiscent to maintain some compatibility with C ... but you should not use it .

    One of the reasons that many gurus that are learning to justify that C is much faster than C ++ is that the reading of data in C ++ is very slow ... well this is because, just by keeping stdio.h , it forces both systems to be synchronized ... which creates an overexertion in the C ++ layer ... however what these gurus do not know is that this synchronization it can be disabled ... allowing readings in C ++ to be faster than those in C.

    std::ios_base::sync_with_stdio(false); // Para desincronizar los streams
    

    The readings with iostream are much safer because they have the advantage of being typed ... which does not happen with the proper functions of C. This feature makes the compiler can warn you about certain aberrations or misconceptions .. .C functions will not show warnings and you will find the error when executing the application.

    Now, as this option exists and someone can activate it at any time, it does not seem a good idea to base the good work of your program on the assumption that this does not exist or will never be done.

    To read a line from the console, think something like this:

    std::string s;
    std::getline(std::cin, s);
    

    Instead of

    gets (at[i].n);
    

    Likewise, consider using std::string instead of char[] .

    fflush is not for inbound streams

    fflush is intended to run on output devices and is indicated in the documentation :

      

    In all other cases, the behavior depends on the specific library implementation. In some implementations, flushing a stream open for reading causes its input buffer to be cleared ( but this is not portable expected behavior ).

    That is:

      

    In all other cases, the behavior will depend on the implementation of the library. In some implementations, calling fflush for a stream reading results in emptying it (but it is not a portable behavior).

    So, avoid this:

    fflush(stdin);
    

    To clean the input buffer in C ++ use this:

    #include <limits>
    
    std::cin.ignore(std::numeric_limits<int>::max(),'\n');
    

    This function eliminates all of them until a line break ('\ n') is found, which will also be deleted ... or the input buffer will be completely emptied.

    And well, there would be more things but we will leave it for another day, otherwise there will not be anyone who will read this answer.

        
    answered by 20.11.2017 в 09:25
    0

    When you have a menu of options, it is best to use a do {options menu} while (condition here);

    And if before it worked for you because you did not leave it as it was?, I recommend you validate errors with try catch if possible in c because usually I only know Java. Remember that when something works do not touch it. and it is possible that your problem is based on that since they are 10, you start from 1 and not from 0 to 10, maybe you have to put for (int i = 1, i < = 10; i ++) {your codes here} Etc .. test the problem between counters and accumulators is always usually initialization.

        
    answered by 19.11.2017 в 00:17
    0

    After the line that says cout<<endl<<"A continuacion indique los 5 lanzamientos del atleta"; , you make a for where c1 goes from 1 to 5, but you are trying to go through the array l which has 5 elements, but the elements of an array do not begin to be enumerated from 1 but from scratch. You must be careful with those things. It seems that the exceptions caused by trying to access a registry of invalid RAM is what stops your program.

        
    answered by 19.11.2017 в 04:37