【问题标题】:Sorting an incrementing list in C在C中对递增列表进行排序
【发布时间】:2018-05-21 00:49:58
【问题描述】:

我正在尝试创建一个员工列表,并在每次添加新员工时根据年龄对列表进行排序。我遇到的问题是只有 1 名员工的列表是“排序的”。如果我突然添加另一个员工,所有年龄都变为 0。这是我的代码:

#include <stdio.h>
#include <string.h>
#include "employee.h"

int i = 0;
unsigned int employee_get_num (struct employee* list)
{
    unsigned int i;

    for (i=0; list[i].name[0]; i++);

    return i;
}

void employee_sort (struct employee* list)
{
    int n = i;
    int I, j;
    int tmp;

    printf("There are %d employees\n", n);
    for(I=0; I<n; I++)
        printf("Age: %d\n", list[i-1].age);

    for(I=0; I<(n-1); I++)
        for(j=0; j<n-I-1; j++)
            if(list[j].age > list[j+1].age){
                tmp = list[j].age;
                list[j].age = list[j+1].age;
                list[j+1].age = tmp;
            }
    printf("Sorted list:\n");
    for(I=0; I<n; I++)
        printf("%d\n", list[i-1].age);  // only printing zeros for some reason
}


void employee_add (struct employee* list)
{
    i = i+1;    // i is global, keeps track of employees
    char first[128];
    char last[128];
    char space[] = " ";

    printf ("First Name: ");
    scanf ("%s", first);
    printf("Last Name: ");
    scanf ("%s", last);
    // Concatenate first and last name into one string
    strcpy(list[i-1].name, first);
    strcat(list[i-1].name, space);
    strcat(list[i-1].name, last);

    printf (" Age: ");
    scanf("%u", &(list->age));
    printf ("Wage: ");
    scanf("%u", &(list->wage));

    employee_sort(&list[i-1]);
}

我认为我可能没有正确增加。

头文件:

#ifndef _employee_h_
#define _employee_h_

struct employee {
    char name[128];
    unsigned int age;
    unsigned int wage;
};

unsigned int employee_get_num (struct employee* list);
void employee_print (struct employee* e);
void employee_print_all (struct employee* list);
void employee_sort (struct employee* array);
void employee_add (struct employee* list);
void employee_delete (struct employee* list);

#endif

main()(在 menu.c 中)

int main (unsigned int argc, char** argv)
{
    struct employee list[MAX];

    unsigned int running = 1;

    /* Set all bits in the employee array to zero */
    memset (list, 0, MAX*sizeof(struct employee));

    while (running) {
        switch (print_menu()) {
            case OPTION_ADD:
                employee_add(list);
                break;
            case OPTION_DEL:
                employee_delete(list);
                break;
            case OPTION_LIST:
                employee_print_all(list);
                break;
            case OPTION_QUIT:
                running = 0;
                break;
        };

    }

    return 0;
}

我省略了 menu.c 的其余部分,因为它只打印您将在下面看到的菜单。

输出应如下所示:

[1] Add New Employee
[2] Delete an Employee
[3] List All by Age (Acending)
[4] Quit
------------------------
Selection: 1
First Name: Bob
Last Name: Smith
 Age: 40
Wage: 60000
There are 1 employees
 Age: 40
Sorted list:
40

[1] Add New Employee
[2] Delete an Employee
[3] List All by Age (Acending)
[4] Quit
------------------------
Selection: 1
First Name: John
Last Name: Connor
 Age: 35
Wage: 62000
There are 2 employees
 Age: 40
 Age: 35
Sorted list:
35
40

我添加了一些额外的打印语句只是为了显示它应该做什么。

我也担心它只会对年龄而不是其余信息进行排序

【问题讨论】:

  • list[] 显然是程序中最重要的变量,您没有向我们展示它的声明。而且你没有 main()。返回一些实际的代码。
  • 旁注:重复的strcatSchlemiel the Painter's Algorithm 的定义。您的strcpy+strcat 最好一步完成:sprintf((list[i-1].name, "%s %s", first, last);(或snprintf 以避免潜在的缓冲区溢出)。
  • 我添加了 header 和 main()。我应该早点把它们包括在内。感谢 strcat 的建议
  • 考虑使用实际列表而不是数组,它更适合您的用例,即您可以插入排序列表并保持排序,而无需每次都移动数据。

标签: c arrays list sorting


【解决方案1】:

首先在employee_add 中调用employee_sort 时,您将传递最后一个结构元素。通过第一个员工。将employee_add 中的最后一行更改为

employee_sort(list);

下一个问题

如果我突然添加另一个员工,所有年龄都变为 0

不,它没有。在employee_sortfor循环中排序前,将其改为

printf("There are %d employees\n", n);
    for(I=0; I<n; I++)
        printf("Age: %d\n", list[I].age);

下一个

在输入年龄和工资时将其更改为

scanf("%u", &(list[i-1].age));
scanf("%u", &(list[i-1].wage));

我也担心它只会对年龄而不是其余信息进行排序

是的,您只是对年龄进行排序,您应该根据年龄对整个结构进行排序。

for(I=0; I<(n-1); I++)
        for(j=0; j<n-I-1; j++)
            if(list[j].age > list[j+1].age){
                tmp = list[j];
                list[j] = list[j+1];
                list[j+1] = tmp;
            }

以及打印排序列表的最终问题

 printf("Sorted list:\n");
    for(I=0; I<n; I++)
        printf("%d\n", list[I].age); 

PS 请注意每个 printf 中的 list[I] 而不是 list[i+1]

编辑
不用自己排序,可以在stdlib.h头文件的函数中使用qsortbiult。

实现:你需要定义一个比较器函数,因为你没有传统的数组来排序

只需定义一个函数

int comparator(const struct employee *p, const struct employee *q)
{
    int l = p->age;
    int r = q->age;
    return (l - r);
}

然后像这样对列表进行排序调用qsort

qsort(list,i,sizeof(list[0]),comparator);

【讨论】: