简体   繁体   English

在 qsort function 中执行指向字符串的正确方法

[英]Proper way to do a pointer-to-string in a qsort function

Let's say I have an array of strings I want to sort, such as:假设我有一个要排序的字符串数组,例如:

{"one", "two", "three", "four"};

Using qsort what would be the proper cast operation when passing those strings?使用qsort传递这些字符串时正确的转换操作是什么?

int scmp(const void *p1, const void *p2) {
    // string1 = ???   
};

My thought is the item would be a "pointer-to-string", and since a string is a "pointer-to-char", this would give me a "pointer-to-pointer-char".我的想法是该项目将是“指向字符串的指针”,并且由于字符串是“指向字符的指针”,这会给我一个“指向指针的字符”。 Is the following the correct way to do this?以下是正确的方法吗?

// 1. Pointer-to String
(String) *

// 2. String = Pointer-to-char
(char*) *

// 3. What about const-ness? Doesn't qsort require the 'value' to be const? 
//    Also, what about string = unsigned char -- is that important here?
(const char*) *

So, would the proper definition of string1 be:那么, string1的正确定义是:

int scmp(const void *p1, const void *p2) {
    const char* string1 = (const char**) p1;
};

Is the the correct way to do it?是正确的方法吗? You can see how tedious (for me at least) it is to figure out what the pointer declarations (or cast in this case) is.您可以看到弄清楚指针声明(或在本例中为强制转换)是多么乏味(至少对我而言)。 Is there a more straightforward way to do it -- that is, a way where if I know I want a "pointer-to-string" I can do it (in the proper way, with const and unsigned or whatever) in less than five minutes?有没有更直接的方法来做到这一点 - 也就是说,如果我知道我想要一个“指向unsignedconst ”,我可以在不到5分钟?

qsort provides the comparison function with two const pointers to the elements of the array begin sorted. qsort提供比较 function 与两个指向数组元素的 const 指针开始排序。 You're sorting an array of "strings", which is to say an array of char* .您正在对“字符串”数组进行排序,也就是说char*数组。 An array of char* is char*[] , a pointer to an element in such an array is a pointer to char* , which would be char** , and a const pointer to an element in that array would be char*const* . char*数组是char*[] ,指向此类数组中元素的指针是指向char*的指针,即char** ,指向该数组中元素的 const 指针是char*const* .

You'll probably end up using strcmp to compare the two strings, or something similar.您可能最终会使用strcmp来比较两个字符串或类似的东西。 If it were strcmp itself, you would end up with:如果它是strcmp本身,你最终会得到:

int scmp(void const* va, void const* vb) {
  const char* a = *(char* const*)va;
  const char* b = *(char* const*)vb;
  return strcmp(a, b);
}

I added unnecessary but harmless const qualifiers to a and b , because strcmp doesn't mutate its arguments.我在ab中添加了不必要但无害的const限定符,因为strcmp不会改变它的 arguments。 Other than that, the example code is pretty well the same as what you would find if you looked at the example code in man qsort除此之外,示例代码与您在man qsort中查看示例代码时所发现的非常相似

It's kind of messy because of how qsort() uses pointers to elements , so if the elements themselves are pointers then you need to somehow convert void* into char* but also de-reference it one step along the way.由于qsort()如何使用指向元素的指针,这有点混乱,所以如果元素本身是指针,那么您需要以某种方式将void*转换为char* ,但还要在此过程中取消对它的引用。

Here's an example of how you'd write such a function:下面是一个如何编写 function 的示例:

int qs_strcmp(const void* a, const void* b) {
  return strcmp(*((const char**) a), *((const char**) b));
}

And a test program to show how it works:还有一个测试程序来展示它是如何工作的:

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


int main(void) {
  char *list[] = {
    "boba",
    "dada",
    "zapa",
    "cobb",
    "acdc",
    "abba"
  };

  int list_len = sizeof(list) / sizeof(char*);

  qsort(&list[0], list_len, sizeof(char*), qs_strcmp);

  for (int i = 0; i < list_len; ++i) {
    printf("%s\n", list[i]);
  }

  return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM