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() S) 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...
CodePudding user response:
There are two major problems with the code shown:
- 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.
- 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 compile with a competent warning level would help you greatly, so you need to 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.