【问题标题】:Selection sort using strings inside structs使用结构内的字符串进行选择排序
【发布时间】:2013-10-25 23:05:25
【问题描述】:

我被困住了。我正在尝试使用选择排序通过strcmp 字符串彼此按字母顺序排列结构。问题是我不知道如何对结构内部的字符串进行选择排序,只使用指针,没有索引。

我的结构看起来像:

struct customer
{
char  customer_name[MAX_NAME_LENGTH];  /* Last name of customer    */
float amount_owed;                     /* Amount customer owes     */
int   priority;                        /* Priority of customer     */
};

还有我的函数调用:

sort_customers(quantity, p_customer_records);

以及定义:

/**********************************************************************/
/*                     Sort the customer database                     */
/**********************************************************************/
void sort_customers(int quantity, struct customer *p_customer_start)
{
struct customer *p_customer,
                     *p_outer,
                     *p_inner,
                     temp_customer;

for(p_customer = p_customer_start;
    (p_customer-p_customer_start) < quantity; p_customer++)
{
    p_inner = p_customer;

    for(p_outer = p_inner + 1;
        (p_outer-p_inner) <= quantity; p_outer++)
        if(strcmp(p_inner->customer_name, p_outer->customer_name) < 0)
            p_inner = p_outer;

    temp_customer = *p_customer;
    *p_customer   = *p_inner;
    *p_inner      = temp_customer;

    p_inner++;
}
return;
}

老实说,我不知道该怎么做。我无法在互联网上或我的书中找到任何可以帮助我解决此问题的东西。现在,此函数将名称向后排序。我很确定这很容易。我只是想念一些东西。我认为另一双眼睛会有所帮助。希望一切都是描述性的,以帮助任何人了解正在发生的事情。

【问题讨论】:

  • 如果它正在工作但排序倒退,请将比较从 &lt; 0 更改为 &gt; 0。或者将参数的顺序颠倒到strcmp()。您应该仔细考虑内部循环及其上限。你在数组中有元素 0..quantity-1,所以我想你也想要一个 &lt; quantity ;您可以通过循环到&lt; quantity-1 来稍微优化外循环。就目前而言,您有超出范围访问数组的危险。
  • @JonathanLeffler 好的,所以我认为可能是别的东西。我只是尝试了您评论的所有内容,但没有任何改变。还有其他建议吗?
  • 还没有;我将不得不用编译器来查看它...
  • @JonathanLeffler 好的,如果你能为我做到这一点,我将非常感激。谢谢您的帮助!如果您需要更多信息,我可以给您。
  • 是否有特定原因需要选择排序?还是您只想对您的客户列表进行排序?

标签: c sorting pointers struct


【解决方案1】:

你的问题是内循环的循环控制:

for (p_outer = p_inner + 1;
     (p_outer-p_inner) < quantity; p_outer++)

您需要检查数组的开头:

for (p_outer = p_inner + 1;
     (p_outer-p_customer_start) < quantity; p_outer++)

使用下标处理两个数组索引可能会更容易。

工作代码(修复了“交换”打印中的错误):

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

enum { MAX_NAME_LENGTH = 16 };
struct customer
{
    char  customer_name[MAX_NAME_LENGTH];  /* Last name of customer    */
    float amount_owed;                     /* Amount customer owes     */
    int   priority;                        /* Priority of customer     */
};

static void sort_customers(int quantity, struct customer *p_customer_start)
{
    struct customer *p_customer,
                    *p_outer,
                    *p_inner,
                    temp_customer;

    for (p_customer = p_customer_start;
            (p_customer-p_customer_start) < quantity; p_customer++)
    {
        p_inner = p_customer;
        printf("Inner: %s\n", p_inner->customer_name);

        for (p_outer = p_inner + 1;
                (p_outer-p_customer_start) < quantity; p_outer++)
        {
            printf("Compare: %s vs %s\n", p_inner->customer_name, p_outer->customer_name);
            if (strcmp(p_inner->customer_name, p_outer->customer_name) > 0)
                printf("Change!\n"),
                p_inner = p_outer;
        }
        printf("Swap B: %s vs %s\n", p_customer->customer_name, p_inner->customer_name);
        temp_customer = *p_customer;
        *p_customer   = *p_inner;
        *p_inner      = temp_customer;
        printf("Swap A: %s vs %s\n", p_customer->customer_name, p_inner->customer_name);
        //p_inner++;
    }
}

static void dump_customers(int n, struct customer *c)
{
    printf("Customers (%d):\n", n);
    for (int i = 0; i < n; i++)
        printf("%-10s %6.2f %4d\n", c[i].customer_name, c[i].amount_owed, c[i].priority);
}

int main(void)
{
    struct customer data[] =
    {
        { "Max", 23.45, 2 },
        { "Carla", 34.75, 1 },
        { "Zach", 39.21, 22 },
    };
    int quantity = 3;

    dump_customers(quantity, data);
    sort_customers(quantity, data);
    dump_customers(quantity, data);

    return 0;
}

失败版本的输出:

Customers (3):
Max         23.45    2
Carla       34.75    1
Zach        39.21   22
Inner: Max
Compare: Max vs Carla
Change!
Compare: Carla vs Zach
Compare: Carla vs 
Change!
Compare:  vs @?Q?
Compare:  vs 
Swap B: Max vs 
Swap A:  vs Max
Inner: Carla
Compare: Carla vs Zach
Compare: Carla vs Max
Swap B: Carla vs Carla
Swap A: Carla vs Carla
Inner: Zach
Compare: Zach vs Max
Change!
Compare: Max vs @?Q?
Change!
Compare: @?Q? vs 
Change!
Compare:  vs 
Compare:  vs 
Swap B: Zach vs 
Swap A:  vs Zach
Customers (3):
             0.00    0
Carla       34.75    1
            -0.00 32767
Segmentation fault: 11

当它继续运行时,很明显内循环的边界存在问题。

工作版本的输出:

Customers (3):
Max         23.45    2
Carla       34.75    1
Zach        39.21   22
Inner: Max
Compare: Max vs Carla
Change!
Compare: Carla vs Zach
Swap B: Max vs Carla
Swap A: Carla vs Max
Inner: Max
Compare: Max vs Zach
Swap B: Max vs Max
Swap A: Max vs Max
Inner: Zach
Swap B: Zach vs Zach
Swap A: Zach vs Zach
Customers (3):
Carla       34.75    1
Max         23.45    2
Zach        39.21   22

请注意我如何在每一个转折点打印有用的信息。 printf("Change!\n"), 表示法并不优雅——但它适用于调试目的。 dump_customers() 函数是您应该或多或少自动为自己编写的东西(并且在调试时经常使用)。当事情出错时,它可以更容易地看到。这不是我最好的转储功能;它应该接受一个标签字符串作为参数,可能还有一个FILE *fp 来写入。对于更大的数组,它应该在每行前面打印行号。尽管如此,打印每个数据结构的函数的基本思想还是很有帮助的。

【讨论】:

    猜你喜欢
    • 2013-11-03
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多