2015-12-02 81 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

非常感謝。 –