在C a a中进行统计过程的问题

np8igboo  于 2022-12-03  发布在  其他
关注(0)|答案(1)|浏览(125)

我尝试用C编译这段代码,它的目的是从一个.dat文件中积累数据,其中的结构体有关于标记、年龄、性别的信息。当我编译它时,一个错误显示说“分段错误”,我写了一个printf来显示i、j和k的值;因为我认为它们是问题所在,下面是代码和失败的照片:`

#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;
}

一个
为了以防万一,下面是生成.dat文件的文件...
`

#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;
}

`
我已经尝试写打印,也处理较少的结构体,我开始编译500个结构体,现在我试图做它与不到50...

dvtswwa3

dvtswwa31#

显示的代码有两个主要问题:
1.如何调用函数?
通过调用函数名称,后跟参数列表来调用函数。
这是

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

是呼叫fread函式的范例。
这些

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

并且这些

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

function declarations的例子。它们让编译器知道一个函数存在,它接受什么类型的参数,以及它返回什么类型的值。通常你会在文件的顶部找到这些(通常称为 * 转发声明 *),或在头文件中(其中函数是在单独的源文件中 * 定义 * 的)。这使得其他函数所依赖的函数在定义之前就公开了它们的存在。
例如:

/* 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;                   
}

如果没有foo的初始声明,bar将不知道foo接受什么类型的自变量,以及它返回什么类型的值。
1.如何从函数中检索数据。
C语言是一种完全 * 按值传递 * 的语言。这意味着函数接收作为参数给出的值的 * 副本 *。有时函数接受指针作为参数,但那些 * 指针值 * 仍然是副本。它是使用间接与指针值,使C模仿在其他语言中发现的 * 按引用传递 * 行为。
函数参数在函数中被视为 * 局部变量 *。更改函数参数的值不会更改调用方的scope中任何变量的值。具有相同名称但在不同作用域中的变量不会引用同一对象。
例如,这个程式会先打印0,然后再打印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);
}

如果foo在调用者的作用域中更改了a,它将打印0,然后打印0,但我们看到情况并非如此。
从一个函数中检索数据的主要方法是使用它的返回值。一个函数可以使用return关键字向它的调用者返回一个值。
例如,可以将niveling更改为返回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;
}

此函数随后用作:

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

void函数必须始终返回适当类型的值。
对于etario,使用数组参数调用它是正确的,但必须使用strcpy将字符串文字的内容复制到数组中。

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

使用上述信息修复程序后,仍然存在一些关键问题。
您的主循环格式不正确,因为fread只在循环的 * 结尾 * 调用,而它应该在循环的开头调用。您还需要检查fread的返回值是否等于预期的字节数(sizeof p),否则p不是未初始化就是不确定的,使用它的值肯定会调用Undefined Behaviour
另请参阅:Why is “while( !feof(file) )” always wrong?
越界访问:如果jmax6,则A数组的第二维中的最后一个有效索引是5
数组A的访问超出界限的情况有几种,例如,

/* `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;

以及您使用了i而不是j,或一些类似的印刷错误:

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

如果你创建了imaxjmaxkmax这样的“常量”,那么你应该在整个代码中使用它们,而不是在所有地方都使用幻数。
示例:

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

/* ... */

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

您也会遇到语法问题,例如:

if (p.sexo = 'M')

=是指派运算子。==是相等运算子。
结论:一个好的编译器加上足够的警告级别会对你有很大的帮助,所以你应该把你的编译器警告级别调高。对于MSVC,至少使用/W4/Wall,也可能使用/Wx来强制更好的编码实践。请参见:Warning levels
你还需要更仔细地学习这门语言。考虑学一门好的C textbook

相关问题