2015-12-02 37 views
1

我正在编写一个C++ dll来对从VBA传递过来的SAFEARRAY进行排序。将索引数组排序到主数组

我没有使用任何OLE库,而是直接访问数组描述符和数据。

我对排序任何本机VBA类型的数组没有任何问题。例如,下面的代码片段排序BSTRs数组:

long * p = (long*)pData; 

std::sort(p, p + elems, comparestring); 

...使用这种比较函数:

bool comparestring(const long& lhs, const long& rhs) { 

    wchar_t * lhs_ = (wchar_t*)lhs; 
    wchar_t * rhs_ = (wchar_t*)rhs; 

    return _wcsicmp(lhs_, rhs_) < 0; 
} 

我知道我欺骗在这里,因为wchar_tBSTR很大的不同,但在Excel字符串的有效内容中有一个零字符并不常见,所以我对此很满意。以上运作良好。

技术问题

我想的dll任选能够索引的同伴数组进行排序到初级数据数组。在这种模式下,只有索引数组将被排序,而不会改变源数据。

我的研究表明lamda仿函数可能是最有希望的路径,因为我宁愿不为其他数组或向量的数据或配对分配内存。

特别是,this answer seems very promising

但是,我不能解决如何适应我的情况,我正在处理从pData开始的BSTR的原始指针。

我曾尝试以下:

long * p = (long*)pData; 

long ndx[5]; 

for (int i = 0; i < 5; i++) ndx[i] = i + 1; 

std::sort(ndx[0], ndx[4], [&p](long i1, long i2) { comparestring((*p) + i1, (*p) + i2); }) 

我使用VC++ 2015和下面的错误上面的结果:

Error C2893 Failed to specialize function template 'iterator_traits<_Iter>::iterator_category std::_Iter_cat(const _Iter &)'

我的C语言编程的日子古代历史(早于存在的C + +),所以我挣扎了一下。感谢任何帮助。

UPDATE

代码现在看起来是这样..它编译,但执行后的ndx顺序不正确:

long * p = (long*)pData; 

long ndx[5]; 

for (int i = 0; i < 5; i++) ndx[i] = i + 1; 

std::sort(ndx, ndx + 5, [&p](long i1, long i2) { return comparestring(*p + i1, *p + i2); }) 
+0

拉姆达需要返回一个布尔值(例如'返回comparestring .....' –

+0

你也可能是指'NDX,NDX + 5'而不是' ndx [0],ndx [4]'。这应该使它编译,但在我看来,你的指针抛出骇客仍然生产垃圾 –

+0

谢谢。我尝试使用将'比较字符串'里面的三个语句直接放入lambda,并且尽管它会返回一个布尔值,但我得到了完全相同的错误 –

回答

1

此代码:

long ndx[5]; 
for (int i = 0; i < 5; i++) ndx[i] = i + 1; 
std::sort(ndx[0], ndx[4], [&p](long i1, long i2) { comparestring((*p) + i1, (*p) + i2); }) 

应该可能是:

long ndx[5]; 
for (int i = 0; i < 5; i++) ndx[i] = i; 
std::sort(ndx, ndx + 5, [&](long i1, long i2) { return comparestring(*(p + i1), *(p + i2)); } 

std::sort的前两个参数是一个迭代器范围。如果使用std::begin(ndx)std::end(ndx),那么样式会更好(假设您的编译器与C++ 11兼容)。

此外,第二行可以写成std::iota(std::begin(ndx), std::end(ndx), 0);

+1

非常感谢。 –