Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

qsort sort struct not working as intended [duplicate]

23 views
Skip to first unread message

jian he

unread,
Oct 22, 2022, 3:26:53 PM10/22/22
to

Hello world!
Original post: https://stackoverflow.com/questions/74166424/qsort-sort-struct-not-working-as-intended
I really don't know how to solve this problem.
--------------------------------
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAXS 128
#define MAXB 32
typedef struct info{
char name[MAXB];
char address[MAXB];
char citystate[MAXB];
char zip[MAXB];
}info;

int compare(const void *s1,const void *s2);

int main(int argc, char *argv[])
{
int idx = 0;
info *addr[MAXS] = {NULL};
FILE *fp = NULL;

if(argc != 3){
fprintf(stderr,"usage: program, inputfile, outputfile\n");
exit(EXIT_FAILURE);
}

if((fp = fopen(argv[1],"r")) == NULL){
fprintf(stderr,"input file cannot open\n");
exit(EXIT_FAILURE);
}

for(idx = 0; idx < MAXS;){
int a1, a2,a3,a4;
char buf[MAXB] = "";
info tmp = {.name = ""};

if(!fgets(buf, MAXB,fp)) break; /* read/validate lines */
a1 = ((buf[MAXB-2] && buf[MAXB-2] != '\n') ||
!sscanf(buf,"%31[^\n]", tmp.name));

if(!fgets(buf, MAXB,fp)) break; /* read/validate lines */
a2 = ((buf[MAXB-2] && buf[MAXB-2] != '\n') ||
!sscanf(buf,"%31[^\n]", tmp.address));

if(!fgets(buf, MAXB,fp)) break; /* read/validate lines */
a3 = ((buf[MAXB-2] && buf[MAXB-2] != '\n') ||
!sscanf(buf,"%31[^\n]", tmp.citystate));

if(!fgets(buf, MAXB,fp)) break; /* read/validate lines */
a4 = ((buf[MAXB-2] && buf[MAXB-2] != '\n') ||
!sscanf(buf,"%31[^\n]", tmp.zip));

if(a1 || a2 || a3 || a4) continue;

if(!(addr[idx] = malloc(sizeof *addr[idx]))){
fprintf(stderr,"error: no mem\n ");
exit(EXIT_FAILURE);
}
/* copy tmp to addr[idx] and increment index */
memcpy(addr[idx++],&tmp, sizeof tmp);
}

fclose(fp);
printf("idx=%d\n",idx);
for(int t = 0; t<idx; t++){
printf("%-8s\t%-22s\t%-20s\t%s\n"
,addr[t]->name,addr[t]->address
,addr[t]->citystate,addr[t]->zip
);
}
printf("\n\n");
qsort(addr,MAXS,sizeof *addr,compare);
for(int t = 0; t<idx; t++){
printf("%-8s\t%-22s\t%-20s\t%s\n"
,addr[t]->name,addr[t]->address
,addr[t]->citystate,addr[t]->zip
);
}
exit(EXIT_SUCCESS);
}

int compare(const void *s1,const void *s2)
{
const struct info* e1 = s1;
const struct info* e2 = s2;
// int temp = strcmp(addr[0]->zip,addr[1]->zip);
// printf("|%s|vs|%s|= %d\n",e1->zip,e2->zip, (strcmp(e1->zip,e2->zip)));
// if(e1->zip < e2->zip) return -1;
//if(e1->zip > e2->zip) return 1;
//return 0;
return strcmp(e1->zip, e2->zip);
}
-----------
structaddr.txt file content:

A1, A2
20294 Lorenzana Dr
Woodland Hills, CA
91364
B1, B2
19831 Henshaw St
Culver City, CA
94023
C1, C2
5142 Dumont Pl
Azusa, CA
91112
D1, D2
20636 De Forest St
Woodland Hills, CA
91364

compile it:

gcc -Wall -Wextra -O3 -pedantic -Wshadow -Ofast \
-Wno-declaration-after-statement \
test.c \
&& ./a.out dat/structaddr.txt dat/structaddrout.txt

qsort before and after, printf output is the same. In compare function, also tried return strcmp(e1->zip, e2->zip); ,but still the printf return (twice) is the same. expected sort order by zip, 91112, 91364, 94023.
---------------------end of message-----------------------------------------------

Andrey Tarasevich

unread,
Oct 22, 2022, 4:03:51 PM10/22/22
to
On 10/22/2022 12:26 PM, jian he wrote:
> qsort(addr,MAXS,sizeof *addr,compare);

What is this? Why are you attempting to sort `MAXS` elements, while in
reality only `idx` elements are filled in?

> int compare(const void *s1,const void *s2)
> {
> const struct info* e1 = s1;
> const struct info* e2 = s2;
> // int temp = strcmp(addr[0]->zip,addr[1]->zip);
> // printf("|%s|vs|%s|= %d\n",e1->zip,e2->zip, (strcmp(e1->zip,e2->zip)));
> // if(e1->zip < e2->zip) return -1;
> //if(e1->zip > e2->zip) return 1;
> //return 0;
> return strcmp(e1->zip, e2->zip);
> }

You `addr` array contains pointers to `struct info`.

This means that your `compare` will NOT receive pointers to `struct
info`, as you incorrectly assumed. It will receive pointers-to-pointers
to `struct info`.

The prologue to your `compare` should look as follows

int compare(const void *s1,const void *s2)
{
const struct info* e1 = *(const struct info *const *) s1;
const struct info* e2 = *(const struct info *const *) s2;
...

--
Best regards,
Andrey


jian he

unread,
Oct 23, 2022, 12:40:00 AM10/23/22
to
Problem solved. Thanks.
0 new messages