首页 > 解决方案 > 如何按升序排列结构数组中的结构?

问题描述

如果这听起来令人困惑,我很抱歉,我会尽量清楚。我有一个结构数组,其中数组存储了一个我定义为名片的结构。但是,在将任何新名片添加到数组之前,我必须根据员工 ID 的整数值以升序存储结构。

这是结构:

typedef struct{
int nameCardID;
char personName[20];
char companyName[20];
} NameCard;

因此,我尝试使用关系运算符来比较 ID 的值,并以升序将其复制到另一个名为 fakeHolder 的临时数组,然后最终复制到实际数组。但是,在将我的数据输入为 ID 9、7、5 后,我似乎无法理解为什么它不按顺序排列。

这是我的辅助功能:

int addNameCard(NameCard *nc, int *size){
    int i = 0;
    // Why is this a pointer?
    NameCard fakeHolder[10];
    char dummy[100];
    char *p;
    printf("addNameCard():\n");
    if(*size == MAX){
        printf("The name card holder is full");
        // To quit the program
        return 0;
    }
    // Keeps it to Fake Name Card Holder First
    printf("Enter nameCardID:\n");
    scanf("%d", &fakeHolder->nameCardID);
    scanf("%c", &dummy);
    printf("Enter personName:\n");
    fgets(fakeHolder->personName, 20, stdin);
    if(p = strchr(fakeHolder->personName, '\n')){
        *p = '\0';
    }
    printf("Enter companyName:\n");
    fgets(fakeHolder->companyName, 20, stdin);
    if(p = strchr(fakeHolder->companyName, '\n')){
        *p = '\0';
    }
    // Compare the ID value
    for(int j = 0; j < *size; j += 1){
        if(fakeHolder->nameCardID == (nc+j)->nameCardID){
            printf("The nameCardID has already existed");
        }
        else if(fakeHolder->nameCardID < (nc+j)->nameCardID){
            fakeHolder[(j+1)].nameCardID = (nc+j)->nameCardID;
            strcpy(fakeHolder[(j+1)].personName,(nc+j)->personName);
            strcpy(fakeHolder[(j+1)].companyName, (nc+j)->companyName);
        }
    }
    *size += 1;
    // Transfer to the Actual Name Card Holder
    for(int k = 0; k < *size; k += 1){
        (nc+k)->nameCardID = fakeHolder[k].nameCardID;
        strcpy((nc+k)->personName, fakeHolder[k].personName);
        strcpy((nc+k)->companyName, fakeHolder[k].companyName);
    }
    printf("The name card has been added successfully\n");
    return 0;
}

标签: arrayscstruct

解决方案


您当前的代码有几个问题,您可以重写它以使其更易于维护和使用。例如,

  • i(in int i = 0;) 未被使用
  • scanf("%c", &dummy);我认为,是否有去除尾随\n的 - 但是一个用于读取单个字符的 100 字符缓冲区......令人惊讶。请参阅 scanf() 将新行 char 留在缓冲区中,以大量讨论“在整数之后跟踪内容”的不同方法。
  • 拆分addNameCard为 2 个函数,一个实际请求 NameCard,另一个将其插入到数组中,这样可以更好地划分职责,并使您的程序更易于测试。避免将输入/输出与程序逻辑混合。

你问的问题可以通过标准库qsort函数来解决,如下:

#include <stdlib.h>

typedef struct{
    int nameCardID;
    char personName[20];
    char companyName[20];
} NameCard;

void show(NameCard *nc, int n) {    
    for (int i=0; i<n; i++, nc++) {
        printf("%d,%s,%s\n", 
            nc->nameCardID, nc->personName, nc->companyName);
    }
}

// comparison functions to qsort must return int and receive 2 const void * pointers
// they must then return 0 for equal, or <0 / >0 for lower/greater
int compareCardsById(const void *a, const void *b) {
    return ((NameCard *)a)->nameCardID - ((NameCard *)b)->nameCardID;
}

int main() {
    NameCard nc[10];
    nc[0] = (NameCard){1, "bill", "foo"};
    nc[1] = (NameCard){3, "joe", "bar"};
    nc[2] = (NameCard){2, "ben", "qux"};
    show(nc, 3);
    // calling the libraries' sort on the array; see "man qsort" for details
    qsort(nc, 3, sizeof(NameCard), compareCardsById);
    show(nc, 3);
    return 0;
}

推荐阅读