C++ memcmp排序

C++ memcmp排序,c++,c,performance,sorting,stl,C++,C,Performance,Sorting,Stl,我有一个缓冲区和几个指针。我想根据指针指向的缓冲区中的字节对指针进行排序 可以为qsort()和stl::sort()提供自定义比较函数。例如,如果缓冲区以零结尾,我可以使用strcmp: int my_strcmp(const void* a,const void* b) { const char* const one = *(const char**)a, const two = *(const char**)b; return ::strcmp(one,two); } 但是,

我有一个缓冲区和几个指针。我想根据指针指向的缓冲区中的字节对指针进行排序

可以为qsort()和stl::sort()提供自定义比较函数。例如,如果缓冲区以零结尾,我可以使用strcmp:

int my_strcmp(const void* a,const void* b) {
  const char* const one = *(const char**)a,
  const two = *(const char**)b;
  return ::strcmp(one,two);
}
但是,如果缓冲区不是以零结尾的,我必须使用memcmp(),它需要一个长度参数


是否有一种整洁、有效的方法可以在没有全局变量的情况下将缓冲区的长度输入到我的比较函数中?

能否将缓冲区指针+长度打包到一个结构中,并将该结构的指针作为
void*
传递?

是否有不能将缓冲区终止为null的原因

如果不是,既然你使用C++,你可以编写自己的函数对象:

 struct MyStrCmp {
    MyStrCmp (int n): length(n) { }
    inline bool operator< (char *lhs, char *rhs) {
       return ::strcmp (lhs, rhs, length);
    }
    int length;
 };
 // ...
 std::sort (myList.begin (), myList.end (), MyStrCmp (STR_LENGTH));
struct MyStrCmp{
MyStrCmp(int n):长度(n){}
内联布尔运算符<(字符*lhs,字符*rhs){
返回:strcmp(左、右、长);
}
整数长度;
};
// ...
std::sort(myList.begin()、myList.end()、MyStrCmp(STR_LENGTH));

对于std::sort,您可以使用如下函数:

struct CompString {
    CompString(int len) : m_Len(len) {}
    bool operator<(const char *a, const char *b) const {
        return std::memcmp(a, b, m_Len);
    }
private:
    int m_Len;
};
编辑:来自评论建议(我猜两个字符串都在一个公共缓冲区中?)

struct CompString{
CompString(const unsigned char*e):end(e){}
布尔运算符()(常量无符号字符*a,常量无符号字符*b)常量{
返回std::memcmp(a,b,std::min(end-a,end-b))<0;
}
私人:
常量无符号字符*常量结束;
};

您可以使用函子(将长度指定给函子的构造函数)或Boost.Lambda(使用适当的长度)。

我不清楚您在问什么。但我会努力的,假设

  • 你只有一个缓冲区
  • 您有一个某种类型的指针数组,该数组经过某种方式的处理,使其部分或全部内容指向缓冲区
这相当于:

char *buf = (char*)malloc(sizeof(char)*bufsize);
for (int i=0; i<bufsize; ++i){
    buf[i] = some_cleverly_chosen_value(i);
}

char *ary[arraysize] = {0};
for(int i=0; i<arraysize; ++i){
   ary[i] = buf + some_clever_function(i);
}

/* ...do the sort here */
继续使用strcmp。即使您不控制缓冲区的填充,这也是可能的

如果你不得不生活在别人交给你的缓冲区里,你可以

  • 使用一些全局存储(这是您要求避免的,也是出于良好的考虑)
  • 将排序函数交给比原始指针(支持额外数据的结构或类的地址)更复杂的对象。为此,您需要控制上述代码中
    ary
    的定义
  • 使用支持额外输入的排序函数。或者按照建议进行排序,或者使用自制的解决方案(我确实建议将其作为学生的练习,但在现实生活中不建议使用)。无论哪种情况,额外的数据都可能是指向缓冲区结尾的指针

  • memcmp
    应在不相等的第一个字节上停止,因此长度应较大,即到缓冲区的末尾。那么它返回零的唯一方法就是它是否到达缓冲区的末尾


    (顺便说一句,我自己倾向于合并排序。它稳定且性能良好。)

    对于C函数
    qsort()
    ,不,如果不使用全局变量,就无法将长度传递给比较函数,这意味着无法以线程安全的方式完成。有些系统有一个函数(r代表可重入),允许您传递一个额外的上下文参数,然后将其传递给比较函数:

    int my_comparison_func(void *context, const void *a, const void *b)
    {
        return memcmp(*(const void **)a, *(const void **)b, (size_t)context);
    }
    
    qsort_r(data, n, sizeof(void*), (void*)number_of_bytes_to_compare, &my_comparison_func);
    

    您可以使用如下黑客:

    int buffcmp(const void *b1, const void *b2)
    {
        static int bsize=-1;
        if(b2==NULL) {bsize=*(int*)(b1); return 0;}
        return memcmp(b1, b2, idsize);
    }
    
    首先将其调用为
    buffcmp(&bsize,NULL)
    ,然后将其作为比较函数传递给
    qsort


    当然,在
    buffcmp(NULL,NULL)
    等情况下,通过添加更多
    if
    语句,可以使比较行为更自然

    注意:std::sort接受迭代器而不是容器。哈哈至少你的std::sort调用是正确的。。忘记迭代器;)谢谢,你的回答被接受了,因为你的回答比埃文快一点,而且埃文已经有很多分数了。我把埃文的评论写成了一个工作版本;也请更新你的代码?@Will:aww,rep bias:(.哦,没什么不好的感觉,很高兴你能得到一个有效的解决方案。是的,但是memcmp()怎么做呢?)知道缓冲区有多大吗?这就是目前的问题。我想这只是一个管道问题。编写自己的合并排序并传递任何您关心的信息是最糟糕的。什么?!?问题陈述不清楚。一个字节?两个字节?直到缓冲区的结尾?指针的值?所有这些都是有效的第二句话:“我想根据指针指向的缓冲区中的字节对指针进行排序。”OP询问如何将缓冲区大小传递到排序例程的比较函数中。您的回答在这方面没有提供任何帮助。我真的不觉得这一点很清楚。我确信他指的是从指针到结尾,因为他没有抱怨其他使用该意思的答案,但是……无论如何,我会找到一个答案BSD系统,包括MacOS X,包括qsort_r();其他平台似乎没有。struct CompString{CompString(const unsigned char*e):end(e){}bool operator()(const unsigned char a,const unsigned char*b)const{return(-1==::memcmp(a,b,{end-a,end-b))}private:const unsigned char const end;};这种方法让我开始了。我刚刚发布了一些小的更正。请更新代码。我无法编译运算符<,但函数重载了()为了完整起见,我应该说我的解决方案没有考虑字节匹配的时间-直到缓冲区的末尾,但是很明显一个字符串会比另一个字符串长…您在原始请求中暗示所有被比较的字符串都是相同长度的…您创建了这些字符串的新数组使用自定义比较函数对其进行结构化和排序。如果必须访问原始数组(而不是基础数据),则可以维护指针或
    char *buf = (char*)malloc(sizeof(char)*(bufsize+1));
    buf[bufsize]='\0';
    
    int my_comparison_func(void *context, const void *a, const void *b)
    {
        return memcmp(*(const void **)a, *(const void **)b, (size_t)context);
    }
    
    qsort_r(data, n, sizeof(void*), (void*)number_of_bytes_to_compare, &my_comparison_func);
    
    int buffcmp(const void *b1, const void *b2)
    {
        static int bsize=-1;
        if(b2==NULL) {bsize=*(int*)(b1); return 0;}
        return memcmp(b1, b2, idsize);
    }