Home > Blockchain >  How can I arrange the structs in an array of structs in an ascending order?
How can I arrange the structs in an array of structs in an ascending order?

Time:11-05

I am sorry if this sounds confusing, I will try to be as clear as possible. I have an array of structs, where the array stores a struct that I have defined as a Business Card. However, before adding any new business cards into the array, I have to store the structs in ascending order based on the integer value of the Employee ID.

Here is the struct:

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

Hence, I tried to use relational operators to compare between the values of the ID and copy it in ascending order to another temporary array I named fakeHolder, before finally copying over to the actual array. However, I can't seem to understand why it is not in order after inputting my data as ID 9, 7, 5.

Here is my helper function:

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

CodePudding user response:

Your current code has several problems, and you can rewrite it to be much more maintainable and easier to work with. For example,

  • i (in int i = 0;) is not being used
  • scanf("%c", &dummy); is there, I assume, to remove trailing \n - but a 100-char buffer for a single character to read is... surprising. See scanf() leaves the new line char in the buffer for lots of discussion on different approaches to "trailing stuff after integer".
  • splitting addNameCard into 2 functions, one to actually request a NameCard and another to insert it into the array, would divide up responsibilities better, and make your program easier to test. Avoid mixing input/output with program logic.

The question you ask can be solved via the standard library qsort function, as follows:

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