1

I'm trying to compile this code in C, its purpose is to accumulate data from a .dat file with structs that have information about marks, age, gender. When I compile it, an error shows that say "segmentation fault", I wrote a printf to show me the value of i, j and k; because I think them are the problem, here is the code and a photo of the failure: `

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>


struct persona {
    int edad; //EDAD DE 12-65//
    int notas; //NOTAS DE 0-10//
    char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
    char exi; //EXI 1=SI 2=NO
};

struct reg {
    int notas;
    int contex;
    int cont;
};

const int imax = 7;
const int jmax = 6;
const int kmax = 3;

struct reg A[imax][jmax][kmax];



void retardo() {
    for(int i=0; i < 11000; i++) {
        for(int j=0; j < 11000; j++) {
        }
    }
}
void processbar() {
    system("pause");
    system("cls");
    int i, j;
    
    for(i=0; i < 20 ; i++) {
        printf("Cargando... \n");
        printf("====================\n");
        
        for(j=0; j < i ; j++) {
            printf("X");
        }
        printf("\n====================\n");
        retardo();
        system("cls");
    }
}


void etario(int j, char grupoed[10]) //ASIGNAMOS LOS RANGOS ETARIOS//
{
    switch(j)
    {
        case(1):
            grupoed ="12-15";
            break;
        case(2):
            grupoed ="16-25";
            break;
        case(3):
            grupoed ="26-35";
            break;
        case(4):
            grupoed ="36-45";
            break;
        case(5):
            grupoed ="46-55";
            break;
        case(6):
            grupoed = "56-65";
        default:
            printf("\nHa ocurrido un error");
    }
}

void grupoed(struct persona p, int j) {
    if( p.edad < 12) {
        printf("\nexiste un error en la edad");
    }
    if(p.edad < 16) {
        j = 1;
    }
    if(p.edad < 26) {
        j = 2;
    }
    if(p.edad < 36) {
        j = 3;
    }
    if(p.edad < 46) {
        j = 4;
    }
    if(p.edad < 56) {
        j = 5;
    }
    if(p.edad < 66) {
        j = 6;
    }
    else {
        printf("\nexists un error en la edad");
    }
}

void niveling(struct persona p, int i) {
    if(p.notas < 2) {
        i = 1;
    }
    if(p.notas < 4) {
        i = 2;
    }
    if(p.notas < 6) {
        i = 3;
    }
    if(p.notas < 8) {
        i = 4;
    }
    if(p.notas < 10) {
        i = 5;
    }
}

void femasc(struct persona p, int k) {
    if(p.sexo = 'M') {
        k = 1;
    }
    else {
        if(p.sexo = 'F') {
            k = 2;
        }
    }
}

void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k) {
    for (i = 1; i < 7; i++)
    {
        for (j = 1; i < 6; j++)
        {
            for (k = 1; i < 3; k++)
            {
                A[i][j][k] = {0,0,0};
            }
        }
    }
}

int main() {
    struct reg A[imax][jmax][kmax];
    void processbar();
    void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k);
    struct persona p;
    struct reg;
    int i, j, k,rangomay, rangomen, rangointmay, resmay, resmen, jex, jmay, jmen, NIV, GRUPOET, sexo, cantidadM, califM, cantidadF, califF, grupoetario;
    char grupoed[10];
    float prom_m, prom_f;

    FILE *entrada; //ABRO ARCHIVO
    entrada=fopen("datospersonas.dat","rb");
    if (entrada == NULL){
        exit(1);
        printf("\nError al abrir el archivo");
    }
    else {
        printf("\nArchivo abierto exitosamente!");
    }

    while(!(feof(entrada))){
        void niveling(struct persona p, int i);
        void grupoedad(struct persona p, int j);
        void femasc(struct persona p, int k);
    
        printf("\n%d",i);
        printf("\n%d",j);
        printf("\n%d",k);

        A[i][j][k].notas = A[i][j][k].notas + p.notas;
        A[i][j][k].cont = A[i][j][k].cont;
        if(p.exi = 'S') {
            A[i][j][k].contex = A[i][j][k].contex + 1;
        }
        fread(&p,sizeof(p),1,entrada); //LEO ARCHIVO
    }

    for(i = 1; i < 6; i++) { //TOTALIZO HOMBRES Y MUJERES
        for(j = 1; i < 7; i++) {
            A[i][j][3].notas = A[i][j][3].notas + A[i][j][2].notas;
            A[i][j][3].cont = A[i][j][3].cont + A[i][j][2].cont;
            A[i][j][3].contex = A[i][j][3].contex + A[i][j][2].contex;
        }
    }

    for(j = 1; j < 7; j++) {
        for(i = 1; i < 6; i++) {
            cantidadM = cantidadM + A[i][j][1].cont;
            califM = califM + A[i][j][1].notas;
        }
    }

    prom_m = califM / cantidadM; //PROMEDIO DE CALIFICACIONES DE LOS HOMBRES

    for(j = 1; j < 7; j++) {
        for(i = 1; i < 6; i++) {
            cantidadF = cantidadF + A[i][j][2].cont;
            califF = califF + A[i][j][2].notas;
        }
    }

    prom_f = califF / cantidadM; //PROMEDIO DE CALIFICACIONES MUJERES

    for(k = 1; k < 3; k++) {
        for(i = 1; i < 6; i++) {
            for(j = 1; j < 7; j++) {
               A[6][j][k].cont = A[6][j][k].cont + A[i][j][k].cont;
               A[6][j][k].contex = A[6][j][k].contex + A[i][j][k].cont;
               A[6][j][k].notas = A[6][j][k].notas + A[i][j][k].notas;
            }
        }
    }

    for(j = 1; j < 7; j++) {
        A[6][j][3].cont = A[6][j][1].cont + A[6][j][2].cont;
        A[6][j][3].cont = A[6][j][1].contex + A[6][j][2].contex;
        A[6][j][3].notas = A[6][j][1].notas + A[6][j][2].notas;
    }
    
    resmay = A[6][1][3].contex;
    for(j = 1; j < 7; j++) {
        if(A[6][j][3].contex > resmay) {
            resmay = A[6][j][3].contex;
            jex = j;
        }
    }

    for(k = 1; k < 3; k++) {
        for(j = 1; j < 7; j++) {
            A[7][j][k].notas = A[6][j][k].notas / A[6][j][k].cont;
        }
    }

    resmen = A[7][1][3].notas;
    resmay = A[7][1][3].notas;
    for(j = 1; j < 7; j++) {
        if(A[7][j][3].notas > resmay) {
            resmay = A[7][j][3].notas;
            jmay = j;
        }
        else {
            if(A[7][j][3].notas < resmen) {
                resmen = A[7][j][3].notas;
                jmen = j;
            }
        }
    }

    void etario(int jmay);
    printf("\nEl rango etario con mayor calificacion en promedio fue el comprendido entre: %s", grupoed, " años");
    void etario(int jmen);
    printf("\nEl rango etario con menor calificacion en promedio fue el comprendido entre: %s", grupoed, " años");
    printf("\nEl promedio de calificaciones en femeninos fue: %f", prom_f);
    printf("\nEl promedio de calificaciones en masculinos fue: %f", prom_m);
    void etario(int jex);
    printf("\nEl rango etario con mayor interes en rendir examenes internacionales es el comprendido entre: %s", grupoed, "años");

    fclose(entrada);

    system("pause");
    return 0;
}

` enter image description here

Just in case, here is the file that generates the .dat file...

`

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>

struct persona {
    int edad; //EDAD DE 12-65//
    int notas; //NOTAS DE 0-10//
    char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//
    char exi; //EXI 1=SI 2=NO
};

void generacion()
{
    FILE *entrada;
    entrada=fopen("datospersonas.dat","w+");
    if (entrada == NULL){
        exit(1);
    }
    fclose(entrada);
}

int main()
{
    int s;
    int exi;
    generacion();
    persona p;
    FILE* entrada;
    entrada=fopen("datospersonas.dat","w+");

        for (size_t i=0;i<30; i++)
        {
            p.edad =(rand() %53)+12;
            p.notas =(rand() %9)+1;
            s=(rand() %2)+1;
            if(s == 1){
                p.sexo='M';
            }
            else{
                p.sexo='F';
            }
            exi=(rand() %2)+1;
            if(exi == 1){
                p.exi='S';
            }
            else{
                p.exi='N';
            }
            fwrite(&p, sizeof(struct persona),1,entrada);
            printf("edad: %d\n",p.edad);
            printf("nota: %d\n",p.notas);
            printf("sexo: %c\n",p.sexo);
            printf("esta interesado en rendir examenes internacionales: %c\n",p.exi);
        }
        fclose(entrada);
        return 0;
}

`

I have try writting the print and also process with less structs, I started compiling 500 structs, and now im trying to do it with less than 50...

  • How does this comment `char sexo; //SEXO 1=MASCULINO Y 2=FEMENINO//` match this line `p.sexo='M';`? If you use `sexo` as an index, the array must be larger than 3 entries. Also this `if(p.sexo = 'F')` should raise a compiler warning. You need comparison (`==`), not an assignment. – Gerhardh Nov 19 '22 at 15:31
  • BTW: Why do you show different code in that picture than you pose here. The faulty place is not present in the code you show here. The lines `k=sexo; A[i][j][k].notes = ...` that cause the crash are not present. Why don't you show the real code? – Gerhardh Nov 19 '22 at 15:33
  • What is this supposed to do? `if(p.sexo = 'M') {k = 1;}`? Variable `k` is only a local copy that is not visible to the caller. Check your textbook regarding "call by value" vs call "by reference" – Gerhardh Nov 19 '22 at 15:36
  • Hello, first of all thank you very much for helping @Gerhardh . Secondly, i haven't realize this if(p.sexo = 'F' but now i have corrected it, also the line that you show I am not showing are 3 lines that simply assign variables that results from the function to i, j and k; because i think that it's more efficient just asigning directly to i, j and k... But that doesnt solve the problem – Martin Manuel Malgor Marto Mal Nov 19 '22 at 15:38
  • Aside: The `printf` calls in the form `printf("[ ... ]: %s", grupoed, " años")` are not going to do what you want. The third argument is ignored, as there is no associated *format specifier*. Use `printf("[ ... ]: %s%s", grupoed, " años")` or just `printf("[ ... ]: %s años", grupoed)`. – Oka Nov 19 '22 at 15:51
  • Aside: Unless you have a purposeful reason to busy-wait, `retardo` can be replaced with a call to [`Sleep`](https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-sleep). – Oka Nov 19 '22 at 15:55

1 Answers1

1

There are two major problems with the code shown:

  1. How are functions called?

Functions are called by invoking their name, followed by an argument list.

This

fread(&p, sizeof(p), 1, entrada);

is an example of the fread function being called.

These

void processbar();
void matrizcero(struct reg A[imax][jmax][kmax], int i, int j, int k);

and these

void niveling(struct persona p, int i);
void grupoedad(struct persona p, int j);
void femasc(struct persona p, int k);

are examples of function declarations. They let the compiler know a function exists, what type of arguments it accepts, and what type of value it returns. Typically you find these at the top of a file (often referred to as forward declarations), or in header files (where the function is defined in a separate source file). This lets functions relied upon by other functions expose that they exist before they are defined.

For example:

/* function declaration */ 
int foo(int);

/* function definition, relies on `foo` */
int bar(void)                                     
{                                                 
    return 4 + foo(1);                            
}                         

/* finally `foo` is defined */
int foo(int a)                      
{                                   
    return a + a;                   
}

without the initial declaration of foo, bar would not know what type of arguments foo accepts, and what type of value it returns.


  1. How to retrieve data from a function.

C is an entirely pass-by-value language. This means functions receive copies of the values given as arguments. Sometimes functions accept pointers as arguments, but those pointer values are still copies. It is the use of indirection with a pointer value that allows C to mimic the pass-by-reference behaviour found in other languages.

Function arguments are treated as local variables within the function. Changing the value of a function argument does not change the value of any variable in the caller's scope. Variables with the same name, but in different scopes, do not refer to the same object.

For example, this program prints 0 and then 1.

#include <stdio.h>
                         
void foo(int a) 
{              
    a = 0;     
    printf("%d\n", a);
}                  
                       
int main(void)             
{
    int a = 1;
    foo(a);
    printf("%d\n", a);
}  

If foo had changed a in the caller's scope, it would print 0 and then 0, but we see that is not the case.

The main way to retrieve data from a function is to use its return value. A function may use the return keyword to return a value to its caller.

For example, the niveling could be changed to return an int:

int niveling(struct persona p)          
{                      
    if (p.notas < 2)   
        return 1;  
    if (p.notas < 4)   
        return 2;      
    if (p.notas < 6)         
        return 3;
    if (p.notas < 8)
        return 4;
    if (p.notas < 10)
        return 5;
    
    return 0;
}

This function is then used as:

struct persona per = { .notas = 7 };
int i = niveling(per);

A non-void function must always return a value of the appropriate type.

In the case of etario, calling it with an array argument is correct, but you must use strcpy to copy the contents of the string literal into the array.

void etario(int j, char grupoed[10])
{
    switch (j) {
        case 1:
            strcpy(grupoed, "12-15")
            break;
        /* ... */
    }
}

After fixing your program with the above information there are still some critical issues.

Your main loop is malformed, as fread is only called at the end of the loop, where it should be called towards the start of the loop. You also need to check that the return value of fread is equal to the expected number of bytes (sizeof p) before trying to use the data read. Failing these two things, p is either uninitialized or indeterminate, and using its value is surely to invoke Undefined Behaviour.

See also: Why is “while( !feof(file) )” always wrong?

Out of bounds access: if jmax is 6, then the last valid index in the second dimension of your A array is 5.

There are several instances where the array A is accessed out of bounds, such as,

/* `j` reaches `6`, an invalid index */
for(j = 1; j < 7; j++) {
    for(i = 1; i < 6; i++) {
        cantidadM = cantidadM + A[i][j][1].cont;

and where you have used i instead of j, or some similar typographic error:

for (i = 1; i < 7; i++) {
    /* `i` is used in the condition of the inner loop  */
    for (j = 1; i < 6; j++)

If you create "constants" like imax, jmax, and kmax, then you should use them throughout your code instead of using magic numbers everywhere. Constants are conventionally uppercase as well.

Example:

const int IMAX = 7;
const int JMAX = 6;

/* ... */

for (int i = 0; i < IMAX; i++)          
    for (int j = 0; j < JMAX; j++)
        /* ... */

You also have syntax issues such as:

if (p.sexo = 'M')

= is the assignment operator. == is the equality operator.


Conclusion: A good compiler with a competent warning level would help you greatly, so you should turn your compiler warnings way up. With MSVC, use at least /W4 or /Wall, and possibly /Wx to enforce better coding practices. See: Warning levels.

You also need to study the language more closely. Consider picking up a good C textbook.

Oka
  • 23,367
  • 6
  • 42
  • 53