使用C中的struct按名称和等级对学生列表进行排序

时间:2013-05-13 00:14:59

标签: c sorting struct

我正在编写一个程序,按名称和等级对学生列表进行排序。我在尝试编译时收到以下错误:

ex11.c: In function 'compareByGrade':
ex11.c:46: error: request for member 'grade' in something not a structure or union
ex11.c:47: error: request for member 'grade' in something not a structure or union
ex11.c: In function 'compareByName':
ex11.c:56: error: request for member 'name' in something not a structure or union
ex11.c:57: error: request for member 'name' in something not a structure or union

这是头文件:

#define CLASS_SIZE 10

struct student {
    char *name;
    int  idnumber;
    char grade;
};

这是主文件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ex11.h"

int main(void)
{
    int c, i;
    FILE *data;
    struct student tmp, class[CLASS_SIZE];
    void *nameArray[CLASS_SIZE], *gradeArray[CLASS_SIZE];
    static int compareByGrade(const void *first, const void *second);
    static int compareByName(const void *first, const void *second);

    data = fopen("data", "r");                         /* open data file */

/* Move data into struct */

    for (i = 0; i < CLASS_SIZE; ++i) {
            fscanf(data, "%s%d%c", tmp.name, tmp.idnumber, tmp.grade);
            class[i].name = tmp.name;
            class[i].idnumber = tmp.idnumber;
            class[i].grade = tmp.grade;
    }
    fclose(data);                                     /* close data file */
    qsort(nameArray, CLASS_SIZE, sizeof(*nameArray), &compareByName);
    qsort(gradeArray, CLASS_SIZE, sizeof(*gradeArray), &compareByGrade);
}

/* Function to sorty by grade */

static int compareByGrade(const void *first, const void *second)
{
    const char *firstGrade = (*(const char **) first) -> grade; /* line 46 */
    const char *secondGrade = (*(const char **) second) -> grade; /* line 47 */

    return strcmp(firstGrade, secondGrade);
}

/* Function to sort by name */

static int compareByName(const void *first, const void *second)
{
    const char *firstName = (*(const char **) first) -> name; /* line 56 */
    const char *secondName = (*(const char **) second) -> name; /* line 57 */

    return strcmp(firstName, secondName);
}

我做错了什么?

3 个答案:

答案 0 :(得分:1)

同意xaxxon。 程序处理struct student类,nameArray和gradeArray永远不会被初始化。

BTW,我想不要使用一个名为class的结构,它与C ++的关键字混淆。

grade是char,但是strcmp()需要字符串来比较。

建议: 在main()中,

qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByName);
qsort(class, CLASS_SIZE, sizeof(struct student*), &compareByGrade);

和外面,

int compareByGrade(const void *first, const void *second)
{
    const char firstGrade = ((struct student *)first) -> grade;
    const char secondGrade = ((struct student *)second) -> grade;
    return firstGrade<secondGrade?-1:(firstGrade==secondGrade?0:1);
}

/* Function to sort by name */

int compareByName(const void *first, const void *second)
{
    const char *firstName = ((struct student *)first) -> name;
    const char *secondName = ((struct student *)second) -> name;

    return strcmp(firstName, secondName);
}

compareByGrade()的返回值的表达式将以compareByName()

的相同方式起作用

答案 1 :(得分:0)

const char *firstGrade = (*(const char **) first) -> grade;
const char *secondGrade = (*(const char **) second) -> grade;

'first'被强制转换为指向char的双指针,然后取消引用,所以你有一个char *。然后你用 - &gt;取消引用它到char,char不是结构或联合,也没有成员等级(因为它不能)。

名称相同的问题。

那就是说,我看不到你在哪里填充nameArray或gradeArray,所以即使你修复了编译错误,你也会遇到很多运行时错误。

答案 2 :(得分:0)

有很多事情你做错了。其中包括:

  • 通常,您打印出对数组进行排序的结果(或者使用它们执行某些操作,如果只是为了验证数组是否已排序)。
  • 您通常会根据结构编写比较函数 - 例程将const struct student *伪装成const void *
  • 您有一个包含指针的数据结构,但您没有为该指针指定空间以指向。
  • 您读入未分配的空间。
  • 您不测试fopen()fscanf()是否正常工作。
  • 您的扫描格式字符串不允许ID号和等级之间的空格。

这是基于你写的内容(松散地)的工作代码。

代码

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

#define CLASS_SIZE 10

struct student
{
    char name[20];
    int  idnumber;
    char grade;
};

static int compareByGrade(const void *first, const void *second);
static int compareByName(const void *first, const void *second);
static void print_students(const char *tag, const struct student *class, size_t size);

int main(void)
{
    FILE *data;

    if ((data = fopen("data", "r")) == 0)
    {
        fprintf(stderr, "failed to open file data\n");
        exit(1);
    }

    struct student class[CLASS_SIZE];

    for (int i = 0; i < CLASS_SIZE; ++i)
    {
        char name[20];
        int  idnumber;
        char grade;
        if (fscanf(data, "%19s %d %c", name, &idnumber, &grade) != 3)
        {
            fprintf(stderr, "failed to read student %d\n", i);
            exit(1);
        }
        strcpy(class[i].name, name);
        class[i].idnumber = idnumber;
        class[i].grade = grade;
    }
    fclose(data);

    qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByName);
    print_students("By name", class, CLASS_SIZE);
    qsort(class, CLASS_SIZE, sizeof(class[0]), &compareByGrade);
    print_students("By grade", class, CLASS_SIZE);
    return 0;
}

static int compareByGrade(const void *p1, const void *p2)
{
    const struct student *s1 = (const struct student *)p1;
    const struct student *s2 = (const struct student *)p2;

    if (s1->grade > s2->grade)
        return +1;
    else if (s1->grade < s2->grade)
        return -1;
    else
        return strcmp(s1->name, s2->name);
}

static int compareByName(const void *p1, const void *p2)
{
    const struct student *s1 = (const struct student *)p1;
    const struct student *s2 = (const struct student *)p2;

    return strcmp(s1->name, s2->name);
}

static void print_students(const char *tag, const struct student *class, size_t size)
{
    printf("%s (%zu students):\n", tag, size);
    for (size_t i = 0; i < size; i++)
        printf("%2zu: %-20s %4d %c\n", i, class[i].name, class[i].idnumber, class[i].grade);
}

注意compareByName()函数如何首先确定成绩等级,然后按名称进行比较。

数据集

student1 1234 A
student2 2345 B
junior03 3456 C
junior04 4356 D
sophomore12 5234 F
sophomore13 6345 B
senior19 3419 C
senior99 4399 D
fresher29 7456 C
fresher31 8356 A

输出

By name (10 students):
 0: fresher29            7456 C
 1: fresher31            8356 A
 2: junior03             3456 C
 3: junior04             4356 D
 4: senior19             3419 C
 5: senior99             4399 D
 6: sophomore12          5234 F
 7: sophomore13          6345 B
 8: student1             1234 A
 9: student2             2345 B
By grade (10 students):
 0: fresher31            8356 A
 1: student1             1234 A
 2: sophomore13          6345 B
 3: student2             2345 B
 4: fresher29            7456 C
 5: junior03             3456 C
 6: senior19             3419 C
 7: junior04             4356 D
 8: senior99             4399 D
 9: sophomore12          5234 F