C指针麻烦

hob*_*131 3 c sorting struct pointers

这是对这个问题的跟进:

用指针在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
Run Code Online (Sandbox Code Playgroud)

代码是:

#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;
}
Run Code Online (Sandbox Code Playgroud)

Jim*_*ter 10

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

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

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

assert(s != 0);
Run Code Online (Sandbox Code Playgroud)

这是不正确的做法.assert应仅用于测试逻辑错误,而不是用于正常故障情况,例如内存不足.

struct student *s = malloc(size*(sizeof(struct student)));
Run Code Online (Sandbox Code Playgroud)

这没关系,但我建议

struct student* s = malloc(size * sizeof *s);
Run Code Online (Sandbox Code Playgroud)

因为它不那么冗长,也不依赖于类型.

static int size = 10;
Run Code Online (Sandbox Code Playgroud)

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

#define SIZE 10
Run Code Online (Sandbox Code Playgroud)

要么

enum { SIZE = 10 };
Run Code Online (Sandbox Code Playgroud)

这会给你带来麻烦:

ID being between 1 and 10
Run Code Online (Sandbox Code Playgroud)

(除了它应该说"1和SIZE"这一事实).您分配一个SIZE元素数组,然后使用您的学生ID作为索引,但只有0..SIZE-1是有效索引... SIZE不是.所以你需要索引student->id - 1,或者让你的ID被索引.

    y = rand() % size + 1;
    while(dupe(id, i, y)){
        y = rand() % size + 1;
    }
Run Code Online (Sandbox Code Playgroud)

这可以写成

do
{
    y = rand() % size + 1;
} while(dupe(id, i, y));
Run Code Online (Sandbox Code Playgroud)

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

(students + j)->id
Run Code Online (Sandbox Code Playgroud)

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

students = &sd;
Run Code Online (Sandbox Code Playgroud)

这个语句没有做任何事情,因为students它没有在它之后使用,而且它是一个类型错误(&sd有类型student**),如果你打开警告(-Wall for gcc),你的编译器也会警告你.

你在这里要做的是改变呼叫者的学生,但这不是那样做的.您需要传递学生的地址(即,有一个struct student** pstudents参数然后取消引用才能获得students),或者更好的是,return新数组(在您使用它之前不得取消分配).

这份问题清单不一定是详尽无遗的.