我如何用C中的字符对结构进行排序?

问题描述 投票:0回答:2

我使用该策略按数字对结构进行排序,但是此策略不起作用。

#include <stdio.h>
#define MAX 1000

typedef struct person_{
    char name[100];
    int age;
}person;

void scan_person(person *ptr);
void print_ind(person p);

int name_index_min(person *ptr, int N, int st);

void swap(person *x, person *y);

void sort_name_as(person *ptr, int N);
void sort_name_ds(person *ptr, int N);

int main () {
    person individulas[MAX];
    int n_ind;

    puts("Enter Number of people:");
    scanf("%d",&n_ind);
    for (int i = 0; i < n_ind; i++)
        scan_person(individulas + i);

    printf("\n");

    sort_name_as(individulas,n_ind);
    for (int i = 0; i < n_ind; i++)
        print_ind(individulas[i]); 

    puts("\n");

    sort_name_ds(individulas,n_ind);
    for (int i = 0; i < n_ind; i++)
        print_ind(individulas[i]);   

    printf("\n"); 
      return 0;
}   

void scan_person(person *ptr){

    printf("\nEnter Name & Surename :");
    scanf("\n%99[^\n]", ptr->name);

    printf("Enter Age :");
    scanf ("%d%*c", &(ptr->age));
    printf("\n");
}
void print_ind(person p){
    printf("%s %d  ", p.name, p.age);
}
int name_index_min(person *ptr, int N, int st){

    int min = st;
    for (int i = st+1; i < N; i++)
        if(ptr[i].name < ptr[min].name)
            min = i;
    return min;
}
int name_index_max(person *ptr, int N, int st){

    int max = st;
    for (int i = st+1; i < N; i++)
        if(ptr[i].name > ptr[max].name)
            max = i;
    return max;
}

void swap(person *x, person *y){
    person temp = *x;
    *x = *y;
    *y = temp;
}

void sort_name_as(person *ptr, int N){
    int aux;
    for (int i = 0; i < N-1; i++){
        aux = name_index_min(ptr, N, i);
        if (aux != i)
            swap(ptr + i, ptr + aux);
    }
}

void sort_name_ds(person *ptr, int N){
    int aux;
    for (int i = 0; i < N-1; i++){
        aux = name_index_max(ptr, N, i);
        if (aux != i)
            swap(ptr + i, ptr + aux);
    }
}

这里是示例:

输入:

输入人数:3

输入姓名和名称:Jeffrey L. Davis输入年龄:80

输入姓名和姓:Yaseen Nur al Din Khoury输入年龄:80

输入名称和名称:Joeri Ong输入年龄:80

输出:

[Joeri Ong 80 Jeffrey L. Davis 80 Yaseen Nur al Din Khoury 80 //升序

[Yaseen Nur al Din Khoury 80 Jeffrey L.Davis 80 Joeri Ong 80 // descendig order

c arrays sorting data-structures structure
2个回答
2
投票

[每当您遇到C语言中的排序问题时,您都应该立即考虑qsort。它是一种高效灵活的分类功能,可以处理需要分类的任何类型的对象。通常让新的C程序员感到害怕的是,您必须编写一个compare()函数来告诉qsort如何比较和排序数组中的两个pointers to elements。比较函数的原型是:

int compare (const void *a, const void *b)

ab的所有指针都是指向当前正在比较的数组中两个元素的指针。您唯一的工作是将它们转换为正确的类型,然后告诉qsort您希望它们如何进行比较。让我们看一下您的第一个函数,该函数首先比较以age升序,然后如果年龄相等,则接下来比较名称,以便所有具有相同年龄的患者按字母顺序排序,从原型开始:

int compasc (const void *a, const void *b)      /* qsort compare ascending by age */
{

[不知道您的数组元素是什么类型(这里是stuct person),因此ab的类型将是[[pointer-to struct person。您的工作只是将指针ab转换为键入person*,例如

const person *pa = a, *pb = b;
所以没有void *指针ab,而是在函数中使用了person*指针papb。如果年龄不同,请比较年龄并返回,例如

if (pa->age != pb->age) return (pa->age > pb->age) - (pa->age < pb->age);

否则,年龄是相等的,因此您可以用name进行比较,例如

return (strcmp (pa->name, pb->name)); }

就是您需要的比较功能。全部是:

int compasc (const void *a, const void *b) /* qsort compare ascending by age */ { const person *pa = a, *pb = b; if (pa->age != pb->age) return (pa->age > pb->age) - (pa->age < pb->age); return (strcmp (pa->name, pb->name)); }

按年龄进行降序比较与age的比较操作相同,否则将导致按年龄降序排序。无论如何,如果年龄相等,则按名称按字母顺序排序。

[您在定义要在数组中使用的struct person的最大数量的常数方面做得很好,但是您也可以为name的大小声明一个常数,例如]]

#define MAXNM 100 #define MAXP 1000 typedef struct person { char name[MAXNM]; int age; } person;

note:

'_'已从person_中删除,因为POSIX对保留以下划线开头/结尾的名称很挑剔-不需要结构tag和< [typdef
名称不同)main()中,最好使用面向行的输入功能(例如fgets()或POSIX getline())来一次读取用户输入的行。这样可以确保在stdin中没有任何多余的未读字符,它们可能在下次尝试读取时咬住您。因此,只需声明一个简单的字符数组buf作为缓冲区来容纳所有输入行。然后,您可以使用sscanf()从该行中获取所需的内容以处理所有转换。要读取并存储阵列中的所有数据,可以执行以下操作:int main (void) { int n_ind = 0; person individuals[MAXP] = {{ .name = "" }}; while (n_ind < MAXP) { char buf[MAXP] = ""; /* buffer to hold line of input */ person tmp = { .name = "" }; /* temporary struct to fill */ fputs ("\nenter name & surname: ", stdout); if (!fgets (buf, MAXNM, stdin)) return 1; if (*buf == '\n') break; buf[strcspn (buf, "\n")] = 0; /* trim trailing '\n' */ strcpy (tmp.name, buf); fputs ("enter age: ", stdout); if (!fgets (buf, MAXP, stdin)) return 1; if (sscanf (buf, "%d", &tmp.age) == 1) /* validate age conversion */ individuals[n_ind++] = tmp; /* add tmp to array update n_ind */ }

note:
fgets()还使您能够检查第一个字符是否为'\n'-允许您在name提示符下单独使用

Enter作为指示,用户已完成输入操作-您无需输入它们将输入多少。您只需不断添加名称,直到用户在name提示符下单独按下Enter为止。)现在排序对于qsort变得微不足道,只需传递您的数组,元素数,每个元素的大小以及您想使用qsort的比较函数,剩下的工作,例如]] qsort (individuals, n_ind, sizeof *individuals, compasc); /* sort ascending */

就是按年龄升序的-现在individuals数组将按年龄然后按名称排序。

将它与升序和降序一起放置:

#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXNM 100 #define MAXP 1000 typedef struct person { char name[MAXNM]; int age; } person; int compasc (const void *a, const void *b) /* qsort compare ascending by age */ { const person *pa = a, *pb = b; if (pa->age != pb->age) return (pa->age > pb->age) - (pa->age < pb->age); return (strcmp (pa->name, pb->name)); } int compdesc (const void *a, const void *b) /* qsort compare descending by age */ { const person *pa = a, *pb = b; if (pa->age != pb->age) return (pa->age < pb->age) - (pa->age > pb->age); return (strcmp (pa->name, pb->name)); } int main (void) { int n_ind = 0; person individuals[MAXP] = {{ .name = "" }}; while (n_ind < MAXP) { char buf[MAXP] = ""; /* buffer to hold line of input */ person tmp = { .name = "" }; /* temporary struct to fill */ fputs ("\nenter name & surname: ", stdout); if (!fgets (buf, MAXNM, stdin)) return 1; if (*buf == '\n') break; buf[strcspn (buf, "\n")] = 0; /* trim trailing '\n' */ strcpy (tmp.name, buf); fputs ("enter age: ", stdout); if (!fgets (buf, MAXP, stdin)) return 1; if (sscanf (buf, "%d", &tmp.age) == 1) /* validate age conversion */ individuals[n_ind++] = tmp; /* add tmp to array update n_ind */ } qsort (individuals, n_ind, sizeof *individuals, compasc); /* sort ascending */ puts ("\nascending order by age:"); for (int i = 0; i < n_ind; i++) printf (" %-24s %2d\n", individuals[i].name, individuals[i].age); qsort (individuals, n_ind, sizeof *individuals, compdesc); /* sort descending */ puts ("\ndescending order by age:"); for (int i = 0; i < n_ind; i++) printf (" %-24s %2d\n", individuals[i].name, individuals[i].age); }

示例使用/输出

按年龄排序,如果年龄相等,则按名称排序:$ ./bin/individualsbyage enter name & surname: Jeffrey L Davis enter age: 80 enter name & surname: Yaseen Nur al Din Khoury enter age: 80 enter name & surname: Joeri Ong enter age: 80 enter name & surname: ascending order by age: Jeffrey L Davis 80 Joeri Ong 80 Yaseen Nur al Din Khoury 80 descending order by age: Jeffrey L Davis 80 Joeri Ong 80 Yaseen Nur al Din Khoury 80

现在是一个简单的示例,显示如果年龄不同,则将获得正确的排序:

$ /bin/individualsbyage

enter name & surname: Jeffrey L Davis
enter age: 81

enter name & surname: Yaseen Nur al Din Khoury
enter age: 80

enter name & surname: Joeri Ong
enter age: 79

enter name & surname:

ascending order by age:
  Joeri Ong                   79
  Yaseen Nur al Din Khoury    80
  Jeffrey L Davis             81

descending order by age:
  Jeffrey L Davis             81
  Yaseen Nur al Din Khoury    80
  Joeri Ong                   79

qsort的另一个好处是,它除了可以进行快速分类优化之外,还可以被100,000个(如果不是'1,000,000)人使用和测试,并且已经过验证。 (不是这样,您只是碰巧整夜凑在一起)

如果您有其他疑问,请通过电子邮件与我联系。

您的方法的主要问题是,您正在比较名称的内存地址,而不是数组中包含的值。
当您通过名称引用数组时,实际上是在获取其地址。我建议您使用strcmp比较最小/最大搜索功能上的name数组。

快速查看您的代码显示,这是其中的唯一问题。

此方法的实现带有稍微简化的输入(使用ABC作为名称):https://onlinegdb.com/r1NkRiNKL


0
投票
© www.soinside.com 2019 - 2024. All rights reserved.