简体   繁体   English

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

[英]sorting structs in C with pointers

I am just starting in C and have very little clue as to what's going on behind the scenes. 我只是从C语言开始,对于幕后发生的事情几乎一无所知。 I'm learning it on the fly for a data structures class which makes things a bit harder. 我正在为数据结构类动态学习它,这使事情变得更加困难。

Update: I've stripped the program back down and am starting with memory and on up. 更新:我将程序剥离下来,从内存开始,然后继续。 I have the allocate and deallocate functions in there and I'm getting a malloc error: Q1(9882) malloc: * error for object 0x7fff59daec08: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug 我在其中有分配和取消分配功能,并且遇到了malloc错误:Q1(9882)malloc: *对象0x7fff59daec08的错误:未分配释放的指针*在malloc_error_break中设置断点以进行调试

Update2 here's my revised code, it's still missing something, a couple of my printf statements aren't showing up: 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;
}
students = &students[x];

This changes where students points, so the next time through the loop you will be offseting from there, not from the beginning. 这会改变students指向的位置,因此下一次通过循环时,您将从那里偏移,而不是从头开始。 That is, you're getting originalstudents[0] , originalstudents[1] , originalstudents[1+2] , originalstudents[1+2+3] , etc. You have the same problem with sd . 也就是说,你要originalstudents[0] originalstudents[1] originalstudents[1+2] originalstudents[1+2+3]等你有同样的问题sd

Instead you want to use a different variable, something like 相反,您想使用其他变量,例如

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

Also, what is sd for? 另外,SD是做什么用的? You seem to allocate some space and copy students to sd for no apparent reason. 您似乎没有明显的理由分配一些空间并将学生复制到sd。 The allocated space isn't saved or returned ... it's a memory leak. 分配的空间没有保存或返回……这是内存泄漏。 Oh, wait, I see .. you reorder the students in sd in order of their id. 哦,等等,我知道..您按学生ID的顺序对他们重新排序。 So you just should free the memory when you're done. 因此,您只需要在完成后释放内存即可。 But for both students and sd, you need a different pointer to the array than to the elements of the array. 但是对于学生和sd,您需要一个指向数组的指针,而不是指向数组元素的指针。 There are many different naming conventions you could use, but it's good to use a consistent one. 您可以使用许多不同的命名约定,但是最好使用一致的命名约定。 For example: 例如:

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);
}

Your output() function is misusing pointers so you are trampling all over your student data. 您的output()函数滥用了指针,因此您在践踏所有学生数据。 Try something like this (assuming the IDs are array indexes, because that is how you are using them): 尝试这样的事情(假设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); 
} 

Since you have hard-coded the number of students, you can eliminate the need for dynamically allocating a new array of students in output() , and just sort the pointers you already have in the original array: 由于已经对学生数量进行了硬编码,因此可以消除在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); 
    } 
} 

Update : now that you have shown more of your code, you are still making some big mistakes with the pointers. 更新 :现在,您已经显示了更多代码,仍然在使用指针时犯了一些大错误。 Your code, as you have shown it, should not even compile. 如所示,您的代码甚至不应编译。 Try this instead: 尝试以下方法:

#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; 
} 

This statement 这个说法

students = &students[x];

modifies the incoming argument. 修改传入的参数。 You have lost what 'students' pointed to, which is the beginning of struct student [] . 您已经失去了“学生”所指的内容,这是struct student []的开始。

Remove this statement and try running you program again. 删除该语句,然后尝试再次运行程序。

There are other errors, but this should get you unstuck. 还有其他错误,但这会让您感到困惑。

Pointers are hard. 指针很难。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM