【问题标题】:Sorting an array of strings in C在C中对字符串数组进行排序
【发布时间】:2012-09-13 11:09:39
【问题描述】:

我已经完成了几个小时的任务,但我似乎无法完全正确地完成它。任务是获取随机数量的名称(来自标准输入),对它们进行排序,然后按字母顺序输出。我在网上找不到任何专门处理这种排序的网站,并且没有运气尝试将 qsort() 实现到我的代码中。

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


int stringcmp(const void *a, const void *b) 
{ 
    const char **ia = (const char **)a;
    const char **ib = (const char **)b;
    return strcmp(*ia, *ib);
} 

void main(int argc, char *argv[])
{
     char *input[] = {" "};
     char temp[20][20];
     int i = 0;
     int num = 0;
     int place = 0;
     int stringlen = sizeof(temp) / sizeof(char);


          printf("How many names would you like to enter? ");
          scanf("%d", &num);

          while (place < num)
          {
                printf("Please input a name(first only): ");
                scanf("%s", input[place]);
                printf("The name you entered is: ");
                printf("%s\n", input[place]);

                place++;
          }
          //qsort(temp, stringlen, sizeof(char *), stringcmp);      <-- just an idea I was messing with
          qsort(input, stringlen, sizeof(char *), stringcmp);

          printf("Names:\n");

          for(i=0; i<place; i++)
               printf("%s\n", input[i]);



          system("PAUSE");
          return(EXIT_SUCCESS);

}

主要问题是,当我去输出我的代码时,我不能使用 char *input 变量,因为它是如何声明的。 temp[] 将显示,但不会按 qsort 排序,因为它未声明为指针。有什么想法吗?

【问题讨论】:

标签: c arrays string sorting qsort


【解决方案1】:

修复程序的一种快速方法是将input 声明为指针数组,如下所示:

char *input[20];

当您读入名称时,使用tmp[place] 作为缓冲区,并将指针存储到input,如下所示:

scanf("%19s", tmp[place]);
input[place] = tmp[place];

现在对input 进行排序应该可以正常工作了。

这有一个限制,最多 20 行,每行 20 个字符。如果你在课堂上了解了malloc,你应该能够通过动态分配字符串和字符串数组来解决这个问题。

【讨论】:

    【解决方案2】:

    你不能这样声明你的输入数组。既然知道用户需要多少,就可以动态分配数组:

    char **input = malloc(num * sizeof(char*));
    

    同样,当你读入你的字符串时,它们需要去某个地方。简单地将未初始化的指针传递给scanf 是不行的。我建议你定义一个名字的最大长度,并有一个临时缓冲区来读取它:

    const size_t MAX_NAME = 50;
    char name[MAX_NAME];
    
    ...
    
    for( i = 0; i < num; i++ )
    {
        printf("Please input a name(first only): ");
        scanf("%s", name);
        input[i] = strdup(name);
    }
    

    [请注意,这不会阻止用户溢出“名称”缓冲区。我使用scanf 仅用于说明目的]

    您似乎将错误的数组长度传递给qsort。试试这个:

      qsort(input, num, sizeof(char *), stringcmp);
    

    完成后,需要为所有名称和数组释放内存。

    for( i = 0; i < num; i++ ) free(input[i]);
    free(input);
    

    你能解释一下吗 整个代码中的**声明?我不确定它们是什么 用于,虽然我知道 stringcmp 的函数是一个广泛使用的函数 算法,我不知道它是如何工作的;我被双重抛弃 取消引用标记。

    是的,在我使用它的情况下,我告诉 C 要获取单个字符,我必须取消引用指针两次。当你索引一个指针时,它就是解引用。所以我通过请求一个包含num * sizeof(char*)字节的内存块来分配一个数组。因为我将该指针分配给char**,所以编译器知道我指向的内存块包含char* 值。

    如果我要求input[0](这与*input 相同),它应该查看该内存的最开始并提取足够的字节以形成char*。当我请求input[1] 时,它会跳过这些字节并拉出形成char* 的下一组字节。等等...同样,当我索引 char* 时,我会提取单个字符。

    在您的stringcmp 函数中,您有以下情况。您将void* 指针传递给qsort,因此它实际上并不知道存储在数组中的数据值的大小。这就是为什么你必须同时传递数组长度和单个元素的大小。所以qsort 只是盲目地撕开这个由任意大小值组成的任意长度数组,并触发应该包含您的数据以进行比较的内存地址。因为qsort 除了它们所在的位置之外,对你的数组元素一无所知,所以它只使用void*

    但是您知道这些指针将是您的两个数组元素的内存地址,并且您的数组元素是char*。所以您需要char* 的地址(因此您将指针转换为char**)。现在您需要在调用strcmp() 时取消引用这些指针,因为该函数需要char*(即直接指向包含字符串字符的内存的值)。这就是您在strcmp(*ia, *ib) 中使用* 的原因。

    【讨论】:

    • 好的。我现在已经让这部分工作了。但是为了显示输出,我假设你不能只索引输入?
    • 你当然可以。看,我的两个循环都索引到input。通过索引它,您会在索引请求的位置获得char*char* 指向一个字符串。
    • 感谢您的帮助。如果你不介意我问,你能解释一下整个代码中的 ** 声明吗?我不确定它们的用途,虽然我知道 stringcmp 的函数是一种广泛使用的算法,但我不知道它是如何工作的;我被双重取消引用标记所迷惑。如果没有,别担心!
    • 不用担心,我已经编辑了我的答案并试图解释。我希望这是有道理的 =)
    猜你喜欢
    • 1970-01-01
    • 2012-08-31
    • 2013-09-22
    • 2011-08-14
    • 2021-08-16
    • 2011-09-04
    • 2014-08-10
    • 2011-04-24
    相关资源
    最近更新 更多