I have an array of initialized structures, I need to perform a simple sorting by field (name) in alphabetical order. I know that I need to use qsort() , but I can't do anything. Help please write a function that sorts the mass array.

 #include <stdio.h> #include <stdlib.h> #include <string.h> int my_compare(const void*,const void*); typedef struct test{ char name[100]; char surname[100]; char sname[100]; char posada[100]; char buff[100]; int staz; char buff2[100]; int oklad; }mass[8] ; int main() { /* struct test{ char name[100]; char surname[100]; char sname[100]; char posada[100]; char buff[100]; int staz; char buff2[100]; int oklad; }mass[8] ; */ FILE *fo; if((fo=fopen("C:\\Users\\andyb\\Desktop\\test2.txt","r"))==NULL) printf("error"); for(int i=1;i<8;i++) { fgets(mass[i].name,50,fo); fgets(mass[i].surname,50,fo); fgets(mass[i].sname,50,fo); fgets(mass[i].posada,50,fo); fgets(mass[i].buff,50,fo); mass[i].staz=atoi(mass[i].buff); fgets(mass[i].buff2,50,fo); mass[i].oklad=atoi(mass[i].buff2); } fclose(fo); for(int i=1;i<8;i++) { printf("%s%s%s%s%d\n%d\n",mass[i].name,mass[i].surname,mass[i].sname,mass[i].posada,mass[i].staz,mass[i].oklad); } qsort( mass, sizeof(mass)/sizeof(mass[0]), sizeof(mass[0]), my_compare ); for(int i=1;i<8;i++) { printf("%s%s%s%s%d\n%d\n",mass[i].name,mass[i].surname,mass[i].sname,mass[i].posada,mass[i].staz,mass[i].oklad); } return 0; } int my_compare(const void *a,const void *b) { const test *pa = (const test *)pa; const test *pb = (const test *)pb; /* Сравниваем имена и возвращаем 1, 0 или -1, в зависимости от результата (без учёта регистра): */ return strcmp( pa->name, pb->name ); } 

    3 answers 3

    This typedef ad

      typedef struct test{ char name[100]; char surname[100]; char sname[100]; char posada[100]; char buff[100]; int staz; char buff2[100]; int oklad; }mass[8] ; 

    introduces the mass type specifier as an alias for the struct test[8] . This declaration does not create any object of this type.

    You should write

      typedef struct test{ char name[100]; char surname[100]; char sname[100]; char posada[100]; char buff[100]; int staz; char buff2[100]; int oklad; } test; ^^^^^^ 

    Then inside main you can declare an array of the appropriate type as follows

     #define N 8 int main( void ) { test mass[N]; ^^^^^^^^^^^^^ 

    Note that in C, the main function with no parameters is declared as

     int main( void ) ^^^^ 

    In addition, it does not make much sense to declare buff and buff2 data members in a structure in order to use them as buffers for reading integer data members of the structure. You can simply enter a local variable into main for this purpose, such as

     char buff[100]; 

    In this case, the structure declaration will look like

      typedef struct test{ char name[100]; char surname[100]; char sname[100]; char posada[100]; int staz; int oklad; } test; 

    Instead of the magic number 8, it is better to use a named constant declared as

     #define N 8 

    or if the compiler supports variable-length arrays, then how

     const int N = 8; 

    Array indices in C start at 0. Therefore, this loop statement

     for(int i=1;i<8;i++) { 

    wrong. Should write

     for ( int i = 0; i < N; i++ ) { 

    It is also not clear why in sentences like this

     fgets(mass[i].name,50,fo); 

    the magic number is 50, whereas the corresponding member of the structure, declared as an array, has 100 elements.

    It would be better to write

     fgets( mass[i].name, sizeof( mass[i].name ), fo ); 

    Keep in mind that the fgets function adds a newline character to the array in which it reads data. It is advisable to remove this newline character from the array. This can be done as follows.

     fgets( mass[i].name, sizeof( mass[i].name ), fo ); mass[i].name[strcspn( mass[i].name, "\n" )] = '\0'; 

    In the function my_compare you have a typo:

     int my_compare(const void *a,const void *b) { const test *pa = (const test *)pa; ^^^ const test *pb = (const test *)pb; ^^^ 

    Must be

     int my_compare(const void *a,const void *b) { const test *pa = (const test *)a; ^^^ const test *pb = (const test *)b; ^^^ 
    • Corrected everything, thanks for the answer - andybelous

    The qsort() prototype looks like this:

     void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 

    Here base is a pointer to an array, nmemb is the number of items in it, size is the size of one item, and compar is a function to compare items. In your case, it might look like this:

     int my_compare( const void * a, const void * b ) { /* Теперь pa и pb указывают на сравниваемые элементы массива: */ const test *pa = (const test *)a; const test *pb = (const test *)b; /* Сравниваем имена и возвращаем 1, 0 или -1, в зависимости от результата (без учёта регистра): */ return strcmp( pa->name, pb->name ); } 

    So the call could be like this:

     qsort( mass, sizeof(mass)/sizeof(mass[0]), sizeof(mass[0]), my_compare ); 

    I hope this information is enough to figure it out.


    The correct typedef is :

     typedef struct { char name[100]; char surname[100]; char sname[100]; char posada[100]; char buff[100]; int staz; char buff2[100]; int oklad; } test; int main() { test mass[8]; } 
    • The problem is that the function does not see the structure, since it is declared in the function main () - andybelous
    • and I can't access its elements - andybelous
    • @andybelous, what function, why not see? Show your code in question how it all looks. - PinkTux
    • added the whole program - andybelous
    • @andybelous, I don’t see any problem at all. Once again, carefully read about the work of qsort . She doesn’t need to “see” any structure, it’s enough that you pass the pointer to the array of structures you are sorting with the first argument. - PinkTux

    So the program is not compiled. or not working?

    Regarding the compilation, you have already been told how to fix the type definition.

    And about the performance, I doubt this code:

     const test *pa = (const test *)pa; const test *pb = (const test *)pb; 

    I would venture to suggest that you wanted to write:

     const test *pa = (const test *)a; const test *pb = (const test *)b;