I am writing a seating reservation program in C that involves an option wherein the occupants that are assigned to their seats can be sorted alphabetically. When I choose the option to sort them, the function does sort the last and first names alphabetically, however, in the process of doing so, takes the last and first name parameters and moves them to different seats.
I am currently using the qsort function to sort the names that are stored in a struct called 'SEAT', which contains the first and last name chars as well as the seat ID and assigned ints.
SEAT struct:
typedef struct seat { // struct used to hold all SEAT variables
int seatID;
int occupied;
char lastname[MAXNAME];
char firstname[MAXNAME];
} SEAT;
The qsort functions are inside of a larger function called 'alphasortSeat' and uses two other functions called 'lastnameCompare' and 'firstnameCompare' as their CompareFuncion arguments.
I want this function, when called, to alphabetically sort the names by either first or last names without it moving the data to seemingly random seat assignments.
For example: Seat 1 is assigned to: Bob Jenkins and Seat 2 is assigned to: Xi Jinping.
After calling and executing the function, the names are sorted alphabetically but it now prints:
Seat 1 is assigned to Bob Jenkins
Seat 7 is assigned to Xi Jingping
(In actuality, the names have now moved to Seat 11 and Seat 12 respectively.)
Here is the code I am currently using:
main.c:
scanf_s(" %c", &choice[0], MAXCHOICELEN);
switch (choice[0]) {
//.....
case 'c':
alphasortSeat(seats, MAXSEAT); // sorting the occupants by alphabetical order
break;
//.....
library.c:
//.....
COMPARE FUNCTIONS:
int lastnameCompare(const void* a, const void* b) { // function that compares lastname(s) in order to properly sort them later on alphabetically
const SEAT* seatA = (const SEAT*)a;
const SEAT* seatB = (const SEAT*)b;
return strcmp(seatA->lastname, seatB->lastname);
}
int firstnameCompare(const void* a, const void* b) { // function that compares firstname(s) in order to properly sort them later on alphabetically
const SEAT* seatA = (const SEAT*)a;
const SEAT* seatB = (const SEAT*)b;
return strcmp(seatA->firstname, seatB->firstname);
}
ALPHABETICAL SORTING FUNCTION:
void alphasortSeat(SEAT seats[], int seatNum) { // alphabetically sort names function
char alphaChoice;
printf("Sort by first or last name (f or l): ");
scanf_s(" %c", &alphaChoice, MAXCHOICELEN);
if (alphaChoice == 'f') {
qsort(seats, seatNum, sizeof(SEAT), firstnameCompare); // qsort functions used to order the letters
// qsort_s not used, "context" parameter (MAXSEAT) caused warnings (not needed).
for(int i = 0; i < seatNum; i++){
if (seats[i].occupied) {
printf("\n %s %s is assigned to seat %d.", seats[i].firstname, seats[i].lastname, seats[i].seatID);
}
}
}
else if (alphaChoice == 'l') {
qsort(seats, seatNum, sizeof(SEAT), lastnameCompare);
for (int i = 0; i < seatNum; i++) {
if (seats[i].occupied) {
printf("\n %s %s is assigned to seat %d.", seats[i].lastname, seats[i].firstname, seats[i].seatID);
}
}
}
else {
fprintf(stderr, "\n\nERROR: Invalid character entered.\n\n"); // error statement for invalid character
return;
}
}
//.....
library.h:
int lastnameCompare(const void* a, const void* b);
int firstnameCompare(const void* a, const void* b);
void alphasortSeat(SEAT seats[], int seatNum);
I feel like the main problem is that I am not properly using qsort, or that my compare functions are not doing their job like they should. I am only a beginner in C and I am curious as to why my code would create such a weird error.
I was not able to reproduce your issue. As you are a new around here the following would be a minimal, non-interactive code example that would make it easy to help you. If you don't need both firstname and lastname sort to demonstrate the issue leave one of them out.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXNAME 42
typedef struct seat {
int seatID;
int occupied;
char lastname[MAXNAME];
char firstname[MAXNAME];
} SEAT;
#define genFieldCompare(field) \
int field ## Compare(const void *a, const void *b) {\
const SEAT *seatA = a;\
const SEAT *seatB = b;\
return strcmp(seatA->field, seatB->field);\
}
genFieldCompare(firstname);
genFieldCompare(lastname);
#undef genFieldCompare
void printSeat(const SEAT seats[], int seatNum) {
for(int i = 0; i < seatNum; i++)
if (seats[i].occupied)
printf("%s %s is assigned to seat %d.\n", seats[i].firstname, seats[i].lastname, seats[i].seatID);
printf("\n");
}
int main(void) {
SEAT seats[] = {
{2, 1, "AXi", "Jinping"},
{1, 1, "Jenkins", "Bob"}
};
const size_t seatNum = sizeof seats / sizeof *seats;
qsort(seats, seatNum, sizeof *seats, firstnameCompare);
printSeat(seats, seatNum);
qsort(seats, seatNum, sizeof *seats, lastnameCompare);
printSeat(seats, seatNum);
}
All upper case symbols (SEAT) are by convention reserved for symbolic constants (and enum values). If you don't need struct seat
just leave out seat
and use that for the typedef
symbol name.
The fancy genFieldCompare
macro is just to make the code a little shorter, and to ensure they are implemented exactly the same way other than the two different field names.
Example output:
Bob Jenkins is assigned to seat 1.
Jinping AXi is assigned to seat 2.
Jinping AXi is assigned to seat 2.
Bob Jenkins is assigned to seat 1.
To reproduce your issue I would expect Bob to no longer be assigned seat 1, and similar Jingping to no longer be assigned seat 2.