【问题标题】:sorting structs in C with pointers用指针对C中的结构进行排序
【发布时间】:2012-09-26 03:24:36
【问题描述】:

我刚开始学习 C,对幕后发生的事情知之甚少。我正在为一个数据结构类动态学习它,这使事情变得有点困难。

更新:我已将程序剥离下来,并从内存开始。我在那里有分配和解除分配功能,我得到一个 malloc 错误:Q1(9882) malloc: * error for object 0x7fff59daec08: pointer being free was not assigned * 在 malloc_error_break 中设置断点进行调试

Update2 这是我修改后的代码,它仍然缺少一些东西,我的几个 printf 语句没有显示出来:

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

static int size = 10;

struct student{
    int id;
    int score;
};

struct student* allocate(){
     /*Allocate memory for ten students*/
     struct student *s = malloc(size*(sizeof(struct student)));
     assert(s != 0);
     /*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++){
        y = rand() % size + 1;
        while(dupe(id, i, y)){
            y = rand() % size + 1;
        }
        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);
    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] = *stud;
    }
    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;
    char c[] = "------------------------------\n";
    /*call allocate*/
    stud = allocate();
    /*call generate*/
    generate(&stud);
    /*call output*/
    printf("%s", c);
    output(&stud);
    /*call summary*/

    /*call deallocate*/
    deallocate(stud);

    return 0;
}

【问题讨论】:

  • 作业标签是deprecated
  • 请不要修改代码,因为它会使答案无效,请提交一个新问题。我看到您这样做了……请参阅我对您的新问题的广泛回答。并接受正确的答案,否则没有人会费心花时间。

标签: c sorting pointers


【解决方案1】:
students = &students[x];

这会改变students 指向的位置,因此下次通过循环时,您将从那里偏移,而不是从一开始。也就是说,你会得到originalstudents[0]originalstudents[1]originalstudents[1+2]originalstudents[1+2+3] 等。sd 也有同样的问题。

相反,您想使用不同的变量,例如

struct student* st = &students[x];
printf("id = %d\tscore = %d\n", st->id, st->score);
etc

另外,sd 是干什么用的?您似乎无缘无故地分配了一些空间并将学生复制到 sd 。分配的空间没有保存或返回......这是内存泄漏。哦,等等,我明白了..你按照他们的 id 对 sd 中的学生重新排序。所以你应该在完成后释放内存。但是对于学生和 sd,您需要一个指向数组的指针而不是指向数组元素的指针。您可以使用许多不同的命名约定,但最好使用一致的命名约定。例如:

void output(struct Student* students){
    struct Student *idstudents = allocate(); /* sorted by id */
    if (!idstudents)
        /* handle allocation error */;

    for (int x = 0; x < 10; x++){
        struct Student* student = &students[x];
        printf("id = %d\tscore = %d\n", student->id, student->score);
        struct Student* idstudent = &idstudents[student->id];
        *idstudent = *student; /* copy all fields at once */
        printf("id = %d\tscore = %d\n", idstudent->id, idstudent->score);/* pointless here, since we just printed the same info via student */
    }

    for (int x = 0; x < 10; x++){
        struct Student* idstudent = &idstudents[x];
        printf("id = %d\tscore = %d\n", idstudent->id, idstudent->score);
    }
    deallocate(idstudents);
}

【讨论】:

  • 我已经编辑了上面的内容以显示我的 malloc,它似乎正在抛出程序。在我修复我的排序之前,我不确定如何解决这个问题。
【解决方案2】:

您的 output() 函数滥用了指针,因此您正在践踏您的学生数据。尝试这样的事情(假设 ID 是数组索引,因为这就是您使用它们的方式):

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

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

int main()
{ 
    struct student* stud = NULL; 

    /*call allocate*/ 
    stud = allocate(); 

    /*call generate*/ 

    /*call output*/ 
    output(stud);

    /*call summary*/ 

    /*call deallocate*/ 
    deallocate(stud); 

    return 0; 
} 

void output(struct student* students)
{ 
    /*allocate array for sorting*/
    struct student *sd = allocate(); 

    struct student *stud; 

    /*make copy of students in sorted order*/
    for (int x = 0; x < 10; ++x)
    { 
        stud = &students[x]; 
        printf("id = %d\tscore = %d\n", stud->id, stud->score); 
        sd[stud->id] = *stud; 
    } 

    /*output sorted students*/
    for (int x = 0; x < 10; ++x)
    { 
        stud = &sd[x]; 
        printf("id = %d\tscore = %d\n", stud->id, stud->score); 
    } 

    /*deallocate array for sorting*/
    deallocate(sd); 
} 

由于您已经硬编码了学生人数,因此您无需在output() 中动态分配新的学生数组,只需对原始数组中已有的指针进行排序:

void output(struct student* students)
{ 
    /*array for sorting*/
    struct student* sd[10]; 

    struct student *stud; 

    /*sort students*/
    for (int x = 0; x < 10; ++x)
    { 
        stud = &students[x]; 
        printf("id = %d\tscore = %d\n", stud->id, stud->score); 
        sd[stud->id] = stud; 
    } 

    /*output sorted students*/
    for (int x = 0; x < 10; ++x)
    { 
        stud = sd[x]; 
        printf("id = %d\tscore = %d\n", stud->id, stud->score); 
    } 
} 

更新:现在您已经展示了更多代码,但您仍然在使用指针时犯了一些大错误。正如您所展示的,您的代码甚至不应该编译。试试这个:

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

static const int numStudents = 10; 

struct student
{ 
    int id; 
    int score; 
}; 

struct student* allocate()
{ 
     /*Allocate memory for ten students*/ 
     struct student *s = malloc(numStudents * sizeof(struct student)); 
     assert(s != 0); 
     /*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*/ 
    int id[numStudents]; 
    int y; 
    struct student* stud;

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

    for (int j = 0; j < numStudents; j++)
    { 
        stud = &students[j];
        stud->id = id[j]; 
        stud->score = rand() % 101; 
    } 
} 

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

void output(struct student* students)
{ 
     /*Output information about the students in the format: 
              ID1 Score1 
              ID2 score2 
              ID3 score3 
              ... 
              ID10 score10*/ 

    struct student* stud;

    for(int x = 0; x < numStudents; x++)
    { 
        stud = &students[x];
        printf("ID: %d\tScore: %d\n", stud->id, stud->score);
    } 
} 

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

    for(int i = 0; i < numStudents; i++)
    { 
        stud = &students[i]; 
        sd[stud->id - 1] = *stud; 
    } 

    for(int x = 0; x < numStudents; x++)
    { 
        stud = &sd[x]; 
        students[x] = *stud; 
    } 

    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()
{ 
    /*seed random number generator*/
    srand(time(NULL)); 

    struct student* stud = NULL; 
    const char* c = "------------------------------\n"; 

    /*allocate students and generate info*/ 
    stud = allocate(); 
    generate(stud); 
    output(stud); 

    printf("%s", c); 

    /*sort students*/ 
    sort(students); 
    output(stud); 

    printf("%s", c); 

    /*display summary*/ 
    summary(stud); 

    /*deallocate students*/ 
    deallocate(stud); 

    return 0; 
} 

【讨论】:

  • 我刚刚尝试重新导入文件,因为我收到了奇怪的输出错误,并且我丢失了所有内容。至少我在这里复制了一些!只发布分配和释放,它给了我一个 malloc 错误。
  • 您的allocate() 函数返回了错误的内存地址。它返回的是本地s变量本身的栈地址,但是需要返回变量指向的堆地址,也就是malloc()返回的内存地址。
  • 好的,我已经更新了我的代码,并尝试实施您关于如何用排序的学生填充数组的建议。我不完全在那里,我不确定我错过了什么。我猜它是一个指针......
  • 您的学生 ID 是从 1 开始的 (1-10),但您将它们用作数组索引,而不是从 0 开始 (0-9)。此外,您的 sort() 函数期望 struct student* 作为输入,但您传递给它的是 struct student**,它甚至不应该编译。
【解决方案3】:

此声明

students = &students[x];

修改传入的参数。你丢失了'students'指向的东西,这是struct student []的开头。

删除此语句并尝试再次运行您的程序。

还有其他错误,但这应该会让你摆脱困境。

指针很难。

【讨论】:

  • 删除语句将使循环始终在同一个条目上运行。指针并没有什么特别难的地方。
猜你喜欢
  • 1970-01-01
  • 2012-02-25
  • 2016-11-29
  • 2020-03-15
  • 2015-12-13
  • 1970-01-01
  • 2014-07-04
  • 1970-01-01
相关资源
最近更新 更多