正确使用结构和指针

时间:2016-12-20 03:27:04

标签: c struct scanf

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

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

例如,如果我给n值4,那么将有4名学生,程序将输出最高等级及其名称here

这将输出Ana 10和Eva 10。

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

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

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

3 个答案:

答案 0 :(得分:2)

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

您可以采用以下两种方式之一。

  • Use a VLA。从用户扫描n的值后,将数组定义为struct students v[n];并继续。

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

那就是说,

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

答案 1 :(得分:1)

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

另外,我使用qsort对输入数组v进行排序,其中最后一个元素是max值。这里qsort接受一个结构数组和deference指针传递给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);
}

答案 2 :(得分:0)

您需要使用引用结构的结构数组替换独立数组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;
}