1

我有一个任务我已经做了几个小时了,但我似乎无法完全正确地完成它。任务是获取随机数量的名称(来自标准输入),对它们进行排序,然后按字母顺序输出。我在网上找不到任何专门处理这种排序的网站,并且尝试在我的代码中实现 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 排序,因为它未声明为指针。有任何想法吗?

4

2 回答 2

6

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

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*)所以我通过请求一个包含字节的内存块来分配一个数组。因为我将该指针分配给 a char**,所以编译器知道我指向的是一块包含char*值的内存。

如果我要求input[0](这*inputchar*. 当我要求时input[1],它会跳过这些字节并拉出形成char*. 等等......同样,当我索引 a 时char*,我正在提取单个字符。

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

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

于 2012-09-21T02:57:43.080 回答
2

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

char *input[20];

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

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

现在排序input应该可以正常工作。

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

于 2012-09-21T02:53:36.207 回答