Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 结构和指针卡住了_C_File_Pointers_Struct - Fatal编程技术网

C 结构和指针卡住了

C 结构和指针卡住了,c,file,pointers,struct,C,File,Pointers,Struct,我在C作业计划中面临一些问题: 在选项#4,成绩只按降序排列,而在#5,成绩不会改变,只交换学生的姓名和分数 在选项#8,从文件输入的字符串和浮点将不会显示,我希望选项8是灵活的(通过选项#7输入文件时显示从文件或仅显示从#1菜单选项输入)。以下是该文件的示例: 80.64 John 90.40 Jane 78.00 Jake 守则: #include <stdio.h> #include <stdlib.h> #include <string.h>

我在C作业计划中面临一些问题:

  • 在选项#4,成绩只按降序排列,而在#5,成绩不会改变,只交换学生的姓名和分数

  • 在选项#8,从文件输入的字符串和浮点将不会显示,我希望选项8是灵活的(通过选项#7输入文件时显示从文件或仅显示从#1菜单选项输入)。以下是该文件的示例:

    80.64 John
    90.40 Jane
    78.00 Jake
    
  • 守则:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct Studata{
        float min, max;
        int many;
        char *max1, *min1, gx, gn;
    }studata;
    
    struct Student{
        char name[100], grade;
        float score[100];
    };
    
    float average(struct Student student[100]){
        float sum;
        for(int i=0; i<student.many; i++){
            sum += studata[i].score;
        }
        return sum/(float)student.many;
    }
    
    void MM(struct Student student[100]){
        int i;
        studata.min = 0;
        studata.max = 100;
        for (i=0; i<studata.many; i++){
            if(*student[i].score > studata.min){
                studata.min = student[i].score;
                studata.min1 = student[i].name;
                studata.gn = student[i].grade;
            }
        }
        for (i=0; i<studata.many; i++){
            if(student[i].score < studata.min){
                studata.max = student[i].score;
                studata.max1 = student[i].name;
                studata.gx = student[i].grade;
            }
        }
    
    }
    
    void swapname(char *a, char *b){
        char z[100];
        strcpy(z, a);
        strcpy(a, b);
        strcpy(b, z);
    }
    
    void swapscore(float a, float b){
        float temporary = a;
        a = b;
        b = temporary;
    }
    
    void swapgrade(char A1, char B1) {
        char C1 = A1;
        A1 = B1;
        B1 = C1;
    }
    
    void Bubblesort(int mode, struct Student student[100]) {
        int i, j;
        if(mode == 1) {
            for (i=0; i<studata.many; i++) {
                for (j=i+1; j<studata.many; j++) {
                    if(student[j].score > student[i].score) {
                        swapname(student[i].name, student[j].name);
                        swapscore(student[i].score, student[j].score);
                        swapgrade(student[i].grade, student[j].grade);
                    }
                }
            }
        }
        else if(mode == 0) {
            for(i=0; i<studata.many; i++) {
                for(j=i+1; j<studata.many; j++) {
                    if(student[j].score < student[i].score) {
                        swapname(student[i].name, student[j].name);
                        swapscore(student[i].score, student[j].score);
                        swapgrade(student[i].grade, student[j].grade);
                    }
                }
            }
        }
    }
    
    int main(){
        struct Student student[100];
        int selection=1;
        FILE *file;
        
        while (selection <= 8 && selection >= 1) {
            printf("\n\n\t-------MENU-------\n\n");
            printf("0. Enter Data of Students\n");
            printf("1. Calculate the Average\n");
            printf("2. Show Maximum and Minimum\n");
            printf("3. Sort Score Ascending\n");
            printf("4. Sort Score Descending\n");
            printf("5. Save Scores\n");
            printf("6. Load Scores from File\n");
            printf("7. Load All Data\n");
            printf("Choice (Other than 1-8 to Exit): ");
            scanf("%d", &selection);
            
            if(selection == 1) {
                printf("=============================\n");
                printf("\nHow many students would you like to input: ");
                scanf(" %d", &studata.many);
                 for (int i=0; i<studata.many; i++) {
                    printf("\nStudent-%d Name\t: ", i+1);
                    scanf(" %[^\n]s", student[i].name);
                 
                    printf("Student-%d Score\t: ", i+1);
                    scanf(" %f", &student[i].score);
                    while(student[i].score > 100 || student[i].score < 0) {
                         printf("Hey, wrong input, please input correctly, okay?");
                         printf("\nStudent-%d Score\t: ", i+1);
                         scanf(" %f",&student[i].score);
                    }
    
                    if (student[i].score <= 100 && student[i].score >= 90 ) {
                        student[i].grade= 'A';
                    }
                    else if (student[i].score < 90 && student[i].score >= 80) {
                        student[i].grade= 'B';
                    }
                    else if (student[i].score < 80 && student[i].score >=70) {
                        student[i].grade= 'C';
                    }
                    else if (student[i].score < 70 && student[i].score >=60) {
                        student[i].grade= 'D';
                    }
                    else if (student[i].score < 60 && student[i].score >=50) {
                        student[i].grade= 'E';
                    }
                    else {
                        student[i].grade = 'F';
                    }
                }
            }
    
            else if(selection == 2) {
                printf("=============================\n");
                printf("Average of Score is %.2f", average(student));
            }
            else if(selection == 3) {
                MM(student);
                printf("=============================\n");
                printf("Minimum\t: %s || %4.2f || %c\n", studata.max1, studata.max, studata.gx);
                printf("Maximum\t: %s || %4.2f || %c\n", studata.min1, studata.min, studata.gn);
            }
            else if(selection == 4) {
                printf("=============================\n");
                Bubblesort(0,student);
                for(int i=0; i<studata.many; i++) {
                    printf("   %s : %5.2f --> %c\n", student[i].name, student[i].score, student[i].grade);
                }
            }
            else if(selection == 5) {
                printf("=============================\n");
                Bubblesort(1,student);
                for(int i=0; i<studata.many; i++) {
                    printf("   %s : %5.2f --> %c\n", student[i].name, student[i].score, student[i].grade);
                }
            }
            else if(selection == 6) {
                char filename[100];
                printf("=============================\n");
                printf("Name of the file (with ext.): ");
                scanf(" %[^\n]s", filename);
                file = fopen(filename, "w");
                for(int i=0; i<studata.many; i++) {
                    fprintf(file,"%.2f %s\n", student[i].score, student[i].name);
                }
                fclose(file);
            }
            else if(selection == 7) {
                char filename[100];
                char sub_ch;
                int i;
    
                printf("Enter name of file you want to open (with extension): ");
                scanf(" %[^\n]s", filename);
                file = fopen(filename, "r");
                while (file == NULL) {
                    printf("I'm Error! Reinput? (Y/n): ");
                    scanf("%c", &sub_ch);
                    if(sub_ch == 'Y') {
                        printf("Enter name of file you want to open (with extension): ");
                        scanf(" %[^\n]s", filename);
                    }
                    file = fopen(filename, "r");
                    if(sub_ch == 'n') {
                        exit(1);
                    }
                }
                
                printf("=============================\n");
                fscanf(file, "%f %s", &student[i].score, student[i].name);
                while (!feof(file)) {
                    if (student[i].score <= 100 && student[i].score >= 90 ) {
                        student[i].grade= 'A';
                    }
                    else if (student[i].score < 90 && student[i].score >= 80) {
                        student[i].grade= 'B';
                    }
                    else if (student[i].score < 80 && student[i].score >=70) {
                        student[i].grade= 'C';
                    }
                    else if (student[i].score < 70 && student[i].score >=60) {
                        student[i].grade= 'D';
                    }
                    else if (student[i].score < 60 && student[i].score >=50) {
                        student[i].grade= 'E';
                    }
                    else {
                        student[i].grade= 'F';
                    }
                    printf("%s %8.2f --> %c\n", student[i].name, student[i].score, student[i].grade);
                    fscanf(file, "%f %s", &student[i].score, student[i].name);
                }
                fclose(file);
            }
            else if(selection == 8) {
                printf("=============================\n");
                for (int i=0; i<studata.many; i++) {
                    printf("Name || Score || Grade\t: %s || %3.2f || %c\n", student[i].name, student[i].score, student[i].grade);
                }
            }
        }
        return 0;
    }
    
    #包括
    #包括
    #包括
    Studata结构{
    浮动最小值,最大值;
    int多;
    字符*max1,*min1,gx,gn;
    }斯图达塔;
    结构学生{
    字符名称[100],等级;
    浮动分数[100];
    };
    浮动平均值(结构学生[100]){
    浮点数;
    对于(int i=0;i=70){
    学生[i]。成绩='C';
    }
    否则如果(学生[i]。分数<70和学生[i]。分数>=60){
    学生[i]。成绩='D';
    }
    否则如果(学生[i]。分数<60和学生[i]。分数>=50){
    学生[i]。成绩='E';
    }
    否则{
    学生[i]。成绩='F';
    }
    printf(“%s%8.2f-->%c\n”,学生[i]。姓名,学生[i]。分数,学生[i]。成绩);
    fscanf(文件“%f%s”,&student[i]。分数,student[i]。姓名);
    }
    fclose(文件);
    }
    else if(选择==8){
    printf(“==============================================\n”);
    
    对于(int i=0;i在上面的技巧上进行扩展,使您的代码如此难以阅读(和维护)的原因是您忽略了上面注释中的(2)。您的实现(应用于数据的逻辑)与您的界面(您与用户的交互方式)并没有分开.相反,您的代码在一个跨越多行屏幕的菜单中混乱在一起

    将实现与接口分开可以使每个接口的逻辑保持独立且可读。以下是一些可以改进接口代码和实现的其他方面:

    不要用不必要的重复输出函数调用来扰乱实现

    在编译过程中,compile with将所有相邻的字符串文本串联起来,这些字符串仅由空格分隔。这意味着您不需要10次单独调用
    printf()
    来输出菜单。事实上,由于您显示的菜单中不需要进行任何转换,因此您不需要调用variadic
    printf()
    函数,更不用说调用它10次了。因为您需要线端控制,只需调用一次
    fputs()
    ,例如

        fputs ("\n\n\t-----------MENU-----------\n\n"
                     " 0. Enter Data of Students\n"
                     " 1. Calculate the Average\n"
                     " 2. Show Maximum and Minimum\n"
                     " 3. Sort Score Ascending\n"
                     " 4. Sort Score Descending\n"
                     " 5. Save Scores\n"
                     " 6. Load Scores from File\n"
                     " 7. Load All Data\n\n"
                     "Choice (Other than 1-8 to Exit): ", stdout);
    
    如果您希望在最后有一个
    '\n'
    输出,那么只需使用
    put()
    就可以了。一个调用就可以使菜单可读

    创建逻辑函数以实现您的界面

    您不需要在代码体的
    while
    循环中包含10行菜单。如果您创建一个短函数来显示菜单,例如:

    void show_menu (void)
    {
        fputs ("\n\n\t-----------MENU-----------\n\n"
                     " 0. Enter Data of Students\n"
                     " 1. Calculate the Average\n"
                     " 2. Show Maximum and Minimum\n"
                     " 3. Sort Score Ascending\n"
                     " 4. Sort Score Descending\n"
                     " 5. Save Scores\n"
                     " 6. Load Scores from File\n"
                     " 7. Load All Data\n\n"
                     "Choice (Other than 1-8 to Exit): ", stdout);
    }
    
    然后主循环可以保持可读性,例如

    while (selection <= 8 && selection >= 1) {
        show_menu();
    
    在没有验证的情况下,当在
    if(selection==1)
    中访问
    selection
    (它现在持有一个不确定的值)时,调用未定义的行为。至少必须捕获错误并退出,例如

        if (scanf("%d", &selection) != 1) {
            fputs ("error: invalid integer input.\n", stderr);
            exit (EXIT_FAILURE);
        }
    
    要优雅地处理错误,您需要知道使用
    scanf()
    ,当发生匹配失败时,从输入流中提取字符的过程将在该点停止,导致失败的违规字符将留在输入流中未读。必须在下一次尝试输入之前清除违规字符,否则输入将因相同原因再次失败,导致无限长的错误在很多情况下都会循环。这个网站上有数百个答案,展示了如何正确使用
    scanf()

    更好的解释是,您不使用
    scanf()
    获取用户输入,而是使用具有适当大小的缓冲区(字符数组)的
    fgets()
    ,然后使用
    sscanf()
    从缓冲区中检索所需的任何值,这消除了输入流中未读字符的任何可能性

    不要将界面与实现混为一谈

    <> P> >没有代码,如果…..否则……如果……/Cord>逻辑用于确定字母级别应该在程序循环的中间。正如上面的 SujMeNuu()>代码>,该实现应该在一个简短的函数中,可以从主循环调用,例如

    char get_ltrgrade (float f)             /* return letter grade given float score */
    {
        if      (f >= 90) return 'A';
        else if (f >= 80) return 'B';
        else if (f >= 70) return 'C';
        else if (f >= 60) return 'D';
        else              return 'F';
    }
    
    然后,您只需对
    get\u ltrgrade();

    将您的数据结构与您拥有的数据相匹配

    您使用的
    struct Student
    struct Studata
    与您显示的输入数据不匹配。您显示的输入数据每个学生都有一个分数。要匹配您的数据,仅使用
    struct Student
    就可以了。现在,如果您有多个班级的学生,那么
    struct Studata
    开始变得更有意义。
    float score>[100];
    允许每个学生获得多个分数,但这与您显示的数据不匹配,并且在
    struct student
    中没有计数器来跟踪该学生的有效分数。从您显示的情况来看,
    浮动分数:
    更有意义

    使用
    qsort()对数组进行排序

    C提供
    qsort()
    来处理任何类型的排序数组。
    qsort()
    函数的效率将比您编写的任何排序都高出几个数量级,并且经过几十年的测试。新的C程序员通常避免使用
    qsort()
    ,因为它需要编写一个简短的
    compare()
    通常小于5-1的函数
    char get_ltrgrade (float f)             /* return letter grade given float score */
    {
        if      (f >= 90) return 'A';
        else if (f >= 80) return 'B';
        else if (f >= 70) return 'C';
        else if (f >= 60) return 'D';
        else              return 'F';
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    
    #define MAXC 1024       /* if you need a constant, #define one (or more) */
    #define MAXN  128
    #define MAXS  256
    
    typedef struct {        /* typedef allows use of student_t as type */
        char name[MAXN],
            ltrgrade;
        float score;
    } student_t;
    
    char get_ltrgrade (float f)             /* return letter grade given float score */
    {
        if      (f >= 90) return 'A';
        else if (f >= 80) return 'B';
        else if (f >= 70) return 'C';
        else if (f >= 60) return 'D';
        else              return 'F';
    }
    
    /* qsort compare by student_t->scoore (descending),
     * change to >, < for ascending sort.
     */
    int compare_score (const void *a, const void *b)
    {
        student_t *sa = (student_t*)a,
                  *sb = (student_t*)b;
        
        return (sa->score < sb->score) - (sa->score > sb->score);
    }
    
    int main (int argc, char **argv) {
        
        char buf[MAXC];                     /* buffer to hold each line read from file */
        student_t student[MAXS];            /* array of student_t (MAXS of them) */
        size_t n = 0;                       /* array index (counter) */
        /* use filename provided as 1st argument (stdin by default) */
        FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
        
        if (!fp) {  /* validate file open for reading */
            perror ("file open failed");
            return 1;
        }
        
        /* while array not full, read each line into buf, VALIDATE read */
        while (n < MAXS && fgets (buf, MAXC, fp)) {
            /* split line into score and name, VALIDATE conversion */
            if (sscanf (buf, "%f %127[^\n]", &student[n].score, student[n].name) == 2) {
                /* get letter grade based on score */
                student[n].ltrgrade = get_ltrgrade (student[n].score);
                n += 1;     /* increment index only on valid converison */
            }
            else            /* handle error */
                fprintf (stderr, "error: invalid line format, student[%zu].\n", n);
        }
        if (fp != stdin)   /* close file if not stdin */
            fclose (fp);
        
        qsort (student, n, sizeof *student, compare_score);     /* sort by score */
        
        for (size_t i = 0; i < n; i++)                          /* output result */
            printf ("%-12s  %6.2f  %c\n", 
                    student[i].name, student[i].score, student[i].ltrgrade);
        
        return 0;
    }
    
        qsort (student, n, sizeof *student, compare_score);     /* sort by score */
    
    $ ./bin/studata dat/studata.txt
    Jane           90.40  A
    John           80.64  B
    Jake           78.00  C