在C中对字符串数组进行排序 [英] Sorting an array of strings in C

查看:109
本文介绍了在C中对字符串数组进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个任务已经工作了几个小时,但我似乎做得不太正确.分配是取一个随机数的名称(来自stdin),对它们进行排序,然后按字母顺序输出.我找不到任何专门处理这种排序的在线站点,并且没有运气尝试在我的代码中实现qsort().

I have an assignment I've been working on for a few hours now, and I can't seem to get it quite right. The assignment is to take a random number of names (from stdin), sort them, and then output them in alphabetical order. I can't find any sites online that handle this kind of sorting specifically, and have had no luck trying to implement qsort() into my code.

#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排序,因为它没有被声明为指针.有什么想法吗?

The main problem is, when I go to output my code, I cannot use the char *input variable because of how its declared. The temp[] will display, but will not be sorted by qsort because it is not declared as a pointer. Any ideas?

推荐答案

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

You can't declare your input array like that. Since you know how many the user requires, you can dynamically allocate the array:

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

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

Likewise, when you read your strings in, they need somewhere to go. Simply passing an uninitialized pointer to scanf is not okay. I suggest you define the maximum length of a name and have a temporary buffer for reading it:

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);
}

[注意,这不会阻止用户溢出'name'缓冲区.我仅出于说明目的使用 scanf ]

[Note this does not prevent the user from overflowing the 'name' buffer. I used scanf for illustrative purposes only]

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

You seem to be passing the wrong array length to qsort. Try this:

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

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

When you are finished, you need to release memory for all the names and the array.

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

您能解释一下吗整个代码中的**声明?我不确定他们是什么用于,尽管我知道stringcmp的功能已被广泛使用算法,我不知道它是如何工作的;我被双打甩了取消引用标记.

could you explain the ** declarations throughout the code? I'm not sure what they're used for, although I know the function for stringcmp is a widely used algorithm, I have no idea how it works; I'm thrown off by the double de-reference markers.

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

Yep, in the case where I used it, I am telling C that to get a single character, I have to dereference a pointer twice. When you index a pointer, it's dereferencing. So I allocated an array by requesting a block of memory containing num * sizeof(char*) bytes. Because I assigned that pointer to a char**, the compiler knows that I am pointing to a chunk of memory that contains char* values.

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

If I ask for input[0] (this is the same as *input) it should look at the very start of that memory and pull out enough bytes to form a char*. When I ask for input[1], it skips past those bytes and pulls out the next bunch of bytes that form a char*. Etc... Likewise, when I index a char*, I am pulling out single characters.

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

In your stringcmp function, you have the following situation. You passed a void* pointer to qsort so it doesn't actually know the size of the data values stored in your array. That's why you have to pass both the array length AND the size of a single element. So qsort just blindly rips through this arbitrary-length array of arbitrary-sized values and fires off memory addresses that ought to contain your data for comparison. Because qsort doesn't know anything else about your array elements except where they are located, it just uses void*.

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

But YOU know that those pointers are going to be the memory addresses of two of your array elements, and that your array elements are char*. So you need the address of a char* (hence you cast the pointers to char**). Now you need to dereference these pointers when you call strcmp() because that function requires a char* (ie a value that points directly to the memory containing your string characters). That is why you use the * in strcmp(*ia, *ib).

这篇关于在C中对字符串数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆