3

这是对这个问题的跟进:

用指针对C中的结构进行排序

我已经修改了修改后的代码,我认为排序应该可以工作,但我感觉我没有正确使用指针。我的 printf 语句没有显示在控制台上,它们在评论中被标记。

我是 C 新手,所以这可能很明显,但我只是不知道如何在打印语句不打印时进行调试。

当前编译器警告:

Q1.c: In function 'generate':
Q1.c:28: warning: implicit declaration of function 'time'
Q1.c:35: warning: implicit declaration of function 'dupe'
Q1.c: In function 'output':
Q1.c:61: warning: implicit declaration of function 'sort'
Q1.c: At top level:
Q1.c:68: warning: conflicting types for 'sort'
Q1.c:61: warning: previous implicit declaration of 'sort' was here
Q1.c: In function 'sort':
Q1.c:82: warning: implicit declaration of function 'deallocate'
Q1.c: At top level:
Q1.c:90: warning: conflicting types for 'deallocate'
Q1.c:82: warning: previous implicit declaration of 'deallocate' was here

代码是:

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

int SIZE = 10;
static char c[] = "------------------------------\n";

struct student{
    int id;
    int score;
};

struct student* allocate(){
     /*Allocate memory for ten students*/
     struct student *s = malloc(SIZE* sizeof*s);
     /*return the pointer*/
     return s;
}

void generate(struct student* students){
    /*Generate random ID and scores for ten students, ID being between 1 and 10, scores between 0 and 100*/
    srand((unsigned int)time(NULL));
    int id[SIZE];
    int y;

    for (int i = 0; i < SIZE; i++){
        do{
        y = rand() % SIZE + 1;
        } while(dupe(id, i, y));
        id[i] = y;
    }

    for (int j = 0; j < SIZE; j++){
        students[j].id = id[j];
        students[j].score = rand() % 101;
        printf("ID: %d\tScore: %d\n", students[j].id, students[j].score);
    }
}

int dupe(int id[], int SIZE1, int i){
    for (int x = 0; x < SIZE1; x++){
        if(id[x] == i)
            return 1;
    }
    return 0;
}

void output(struct student* students){
     /*Output information about the ten students in the format:
              ID1 Score1
              ID2 score2
              ID3 score3
              ...
              ID10 score10*/
    sort(students);
    printf("post sort students.\n %s", c);
    for(int x = 0; x < SIZE; x++){
        printf("ID: %d\tScore: %d\n", students[x].id, students[x].score); //print stmt not showing
    }
}

void sort(struct student* students){
    struct student *sd = allocate();

    struct student *stud;

    for(int i = 0; i < SIZE; i++){
        stud = &students[i];
        sd[stud->id -1] = *stud;
    }
    printf("sorted SD.\n %s", c);
    for(int x = 0; x < SIZE; x++){
        printf("ID: %d\tScore: %d\n", sd[x].id, sd[x].score); //print stmt not showing
    }
    students = sd;
    deallocate(sd);
}

void summary(struct student* students){
     /*Compute and print the minimum, maximum and average scores of the ten students*/

}

void deallocate(struct student* stud){
     /*Deallocate memory from stud*/
    free(stud);
}

int main(){
    struct student* stud = NULL;
    /*call allocate*/
    stud = allocate();
    /*call generate*/
    generate(stud);
    /*call output*/
    printf("%s", c);
    output(stud);
    /*call summary*/

    /*call deallocate*/
    deallocate(stud);

    return 0;
}
4

2 回答 2

10

“我的 printf 语句没有显示在控制台上”

你确定你的程序在它到达那一步之前没有崩溃吗?

既然stud有类型student*&stud就有类型student**,但是你将它传递给期望的函数student*......只是传递stud,而不是&stud。在编译器中打开警告,它会告诉你这些事情。

assert(s != 0);

这是不恰当的做法。assert应该只用于测试逻辑错误,而不是用于正常故障情况,例如内存不足。

struct student *s = malloc(size*(sizeof(struct student)));

这没关系,但我建议

struct student* s = malloc(size * sizeof *s);

因为它不那么冗长并且不依赖于类型。

static int size = 10;

在 C 中,这不是一个常量(并且不会通过添加const关键字而变为常量)。由于您使用它作为本地数组的大小,因此您调用了并非在所有 C 编译器中都可用的 VLA(可变长度数组)功能。在C中,这样做更正常

#define SIZE 10

或者

enum { SIZE = 10 };

这会给你带来麻烦:

ID being between 1 and 10

(除了它应该说“1 和 SIZE”)。您分配一个 SIZE 元素数组,然后使用您的学生 ID 作为索引,但只有 0..SIZE-1 是有效索引...... SIZE 不是。因此,您需要按 索引student->id - 1,或使您的 ID 为 0 索引。

    y = rand() % size + 1;
    while(dupe(id, i, y)){
        y = rand() % size + 1;
    }

可以写成

do
{
    y = rand() % size + 1;
} while(dupe(id, i, y));

但是,我认为这并不能满足您的要求。您确保学生 ID 与索引不同,但没有理由这样做。您要保证的是,没有两个学生 ID 是相同的,但您并没有这样做。一种可能性是扫描所有先前分配的 ID,如果已经分配,​​则选择另一个。另一种方法是将所有 ID 1 .. SIZE 放入一个数组中,然后随机将项目从数组中拉出,将数组的顶部元素移动到该插槽中,并将数组的大小减小 1,直到你'我清空了数组并分配了所有的 ID。

(students + j)->id

C 有一些等价规则:*(x + y)===x[y]x->y=== (*x).y。所以,(students + j)->id=== (*(students + j)).id=== students[j].id,这是写它的首选方式。

students = &sd;

这个语句没有做任何事情,因为students它后面没有使用,它是一个类型错误(&sdhas type student**),如果你打开警告,你的编译器会再次警告你(-Wall for gcc)。

您在这里尝试做的是更改呼叫者中的学生,但这并没有这样做。您需要传递学生的地址(即,有一个struct student** pstudents参数,然后将其取消引用到 get students),或者更好return的是新数组(在您完成使用之前不得释放)。

这个问题清单不一定是详尽的。

于 2012-10-05T16:52:05.337 回答
0

我会指出我在程序中可以找到的关于指针使用的一些错误,

里面main

你应该打电话给generate()output()

generate(stud);
output(stud);

sort,

students = &sd;应该students = sd;改为

output,

sort(&students);应该sort(students);改为

于 2012-10-05T17:13:13.200 回答