【问题标题】:C pointer troubles [closed]C指针问题[关闭]
【发布时间】:2012-09-26 20:52:08
【问题描述】:

这是对这个问题的跟进:

sorting structs in C with pointers

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

我是 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;
}

【问题讨论】:

  • (students + j)-&gt;id 通常写成students[j].id
  • 有几个问题,但是打开编译器警告对你来说都是显而易见的;单步执行代码并检查变量也应该有很大帮助。
  • 请不要编辑您最初提交的代码!这会使答案无效。如果您想发布新版本的代码,请将其作为附加编辑。
  • 对不起,从现在开始,谢谢大家的帮助。

标签: c sorting pointers struct


【解决方案1】:

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

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

由于stud 的类型为student*&amp;stud 的类型为student**,但您将其传递给期望student* 的函数...只需传递stud,而不是&amp;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-&gt;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-&gt;y === (*x).y。所以,(students + j)-&gt;id === (*(students + j)).id === students[j].id,这是写它的首选方式。

students = &sd;

这个语句没有做任何事情,因为 students 在它之后没有被使用,这是一个类型错误(&amp;sd 的类型是 student**),如果你转身,你的编译器会再次警告你关于警告(gcc 的 -Wall)。

你在这里尝试做的是改变调用者中的学生,但这并没有这样做。您需要将学生的地址传入(即,有一个 struct student** pstudents 参数,然后取消引用以获取 students),或者更好的是 return 新数组(必须被释放,直到你完成使用它)。

此问题列表不一定详尽。

【讨论】:

  • 吉姆,非常感谢!这是我的更新:删除断言,将静态 int 更改为普通 int(尝试 #define 并得到一堆错误),使用 -1 分配学生 ID(ID 要求为 1-10),切换到 do/ while循环,更改为students[j].id命名法,将students = &sd更改为students = sd,添加编译器警告。最终的 printf 没有排序,所以我一定是传递了 students = sd 参考错误?
  • @hobbes131 我想我已经为此付出了足够的努力。如果对您有帮助,请接受我的回答,并继续调试您的程序……您会从尝试自己解决这些问题中获得更多好处。
  • @hobbes131 好的,我又进行了一次编辑...您的结果未排序,因为您仍在使用原始的未排序数组。您分配了一个数组,将排序后的值放入,然后释放它,将其丢弃。
【解决方案2】:

我会指出程序中关于指针使用的几个错误,

main内,

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

generate(stud);
output(stud);

sort

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

output

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-13
    • 1970-01-01
    • 1970-01-01
    • 2023-01-08
    • 1970-01-01
    相关资源
    最近更新 更多