【问题标题】:Proper use of structures and pointers正确使用结构和指针
【发布时间】:2016-12-20 03:27:04
【问题描述】:

我必须声明一个“struct”类型的向量,对于每 n 个学生,它会为学生所属的组(类似于计数器)、他们的姓名和成绩创建一个值。

程序必须输出在这些组中找到的成绩最高的学生的姓名。我必须在堆上分配向量(我只知道堆的理论解释,但我不知道如何应用它)并且我必须使用指针遍历向量。

例如,如果我给 n 值 4,将有 4 名学生,程序将输出最高成绩以及他们的姓名,如 here 所示。

这将输出 Ana 10 和 Eva 10。

我试了一下,但我不知道如何扩展或修复它,所以如果可能的话,我很感激在此类问题中堆和指针的实际应用方面我能获得的所有帮助。

p>
#include <stdio.h>
#include <stdlib.h>

struct students {
    int group;
    char name[20];
    int grade;
};

int main()
{
    int v[100], n, i;
    scanf("%d", n);
    for (i = 0; i < n; i++) {
          v[i].group = i;
          scanf("%s", v[i].name);
          scanf("%d", v[i].grade);
    }
    for (i = 0; i < n; i++) {
          printf("%d", v[i].group);
          printf("%s", v[i].name);
          printf("%d", v[i].grade);
    }
    return 0;
}

这里我只是想创建矢量,但没有任何效果..

【问题讨论】:

  • scanf("%d", n); --> scanf("%d", &amp;n);scanf("%d", v[i].grade); --> scanf("%d", &amp;v[i].grade);

标签: c struct scanf


【解决方案1】:

看来,int v[100]; 并不是你想要的。删除它。

您可以采用两种方式中的任何一种。

  • Use a VLA。扫描到用户n的值后,像struct students v[n];一样定义数组并继续。

  • 定义一个固定大小的数组,如struct students v[100];,并使用大小来限制循环条件。

也就是说,

  • scanf("%d", n); 应该是 scanf("%d", &amp;n);,因为 %d 需要一个指向 scanf() 的整数类型参数的指针。其他情况也是如此。
  • scanf("%s", v[i].name); 最好是 scanf("%19s", v[i].name); 以避免输入过长导致缓冲区溢出的可能性。

【讨论】:

  • 这似乎已经解决了我最初的错误,现在我必须使用我认为的 malloc 函数在堆中分配向量,并使用指针遍历向量,然后输出最高成绩和学生'的名字,你能帮我吗?
  • @user2877858 好吧,一步一步的教程超出了范围。请继续,编写代码,如果您遇到任何问题,请回来提出新问题。我们会在这里提供帮助。
【解决方案2】:

即使您使用scanf 询问学生(组)的数量,您也使用v[100] 对该值的上限进行了硬编码。因此,我将您的输入变量n(学生人数)传递给malloc,以便分配创建n 学生数组所需的空间。

另外,我使用qsort 对输入数组v 进行排序,其中最后一个元素是max 值。这里qsort 接受一个结构数组并遵循传递给comp 函数的指针来计算比较的差异。

最后,我在最后一个循环中打印了排序后的结构数组。

#include <stdio.h>
#include <stdlib.h>
struct students {
    int  group;
    char name[20];
    int  grade;
};

int comp(const void *a, const void *b)
{
   return ((((struct students *)a)->grade > ((struct students *)b)->grade) - 
            (((struct students *)a)->grade < ((struct students *)b)->grade));
}

int main()
{
   int n;
   printf("Enter number of groups: ");
   scanf("%d", &n);
   printf("\n");    
   struct students *v = malloc(n * sizeof(struct students));
   int i;
   for(i = 0; i < n; i++)
   {
      v[i].group = i;
      printf("\nName: ");
      scanf("%s", v[i].name);
      printf("Grade: ");
      scanf("%d", &v[i].grade);
   }
   qsort(v, n, sizeof(*v), comp);
   for(i = 0; i < n; i++)
   {
      printf("Group %d, Name %s, grade %d\n", v[i].group, v[i].name, v[i].grade);
   }
   return (0);
}

【讨论】:

    【解决方案3】:

    您需要将独立数组 v[100] 替换为引用您的结构的结构数组:

    struct students v[100];
    

    但是,如果您想使用malloc 在堆上分配内存,则需要执行以下操作:

    struct students *students = malloc(n * sizeof(struct students));
    
    /* Check void* return pointer from malloc(), just to be safe */
    if (students == NULL) {
         /* Exit program */
    }
    

    free最后从malloc()请求的内存,像这样:

    free(students);
    students = NULL;
    

    此外,添加到@Sourav Ghosh 的答案中,检查scanf() 的返回值也很好,尤其是在处理整数时。

    而不是简单地:

    scanf("%d", &n);
    

    更安全的方法是:

    if (scanf("%d", &n) != 1) {
         /* Exit program */
    }
    

    说了这么多,你的程序可能看起来像这样:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define NAMESTRLEN 20
    
    typedef struct {  /* you can use typedef to avoid writing 'struct student' everywhere */
        int group;
        char name[NAMESTRLEN+1];
        int grade;
    } student_t;
    
    int
    main(void) {
        int n, i;
    
        printf("Enter number of students: ");
        if (scanf("%d", &n) != 1) {
            printf("Invalid input.\n");
            exit(EXIT_FAILURE);
        }
    
        student_t *students = malloc(n * sizeof(*students));
        if (!students) {
            printf("Cannot allocate memory for %d structs.\n", n);
            exit(EXIT_FAILURE);
        }
    
        for (i = 0; i < n; i++) {
            students[i].group = i;
    
            printf("Enter student name: ");
            scanf("%20s", students[i].name);
    
            printf("Enter students grade: ");
            if (scanf("%d", &(students[i].grade)) != 1) {
                printf("Invalid grade entered.\n");
                exit(EXIT_FAILURE);
            }
        }
    
        printf("\nStudent Information:\n");
        for (i = 0; i < n; i++) {
            printf("Group: %d Name: %s Grade: %d\n", 
                    students[i].group, 
                    students[i].name, 
                    students[i].grade);
        }
    
        free(students);
        students = NULL;
    
        return 0;
    }
    

    【讨论】:

    • 非常感谢您的详细回复,我将通过它尝试尽可能多地学习,对于没有早点看到它,我深表歉意
    • @user2877858 不用担心 :)。如果您需要任何澄清,请告诉我。
    • 如果 *students 没有以任何形式声明,你怎么能使用它?
    • student_t *students中声明。你对哪一行感到困惑?
    • 如果您愿意,可以将 malloc() 调用替换为 student_t *students = malloc(n * sizeof(student_t));。他们都做同样的事情,只是偏好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-08
    • 2013-06-18
    • 2019-03-30
    • 1970-01-01
    相关资源
    最近更新 更多