2017-06-22 72 views
1

的端部使用整數值排序串矢量我有一個包含文件{"good_6", good_7", "good_8"...,"good_660"}一個目錄中,使用READDIR讀它並在載體中我得到{"good_10", "good_100", "good_101", "good_102"...}存儲後。在C++中的字符串

我想要做的是保持向量中的文件名爲{"good_6", good_7", "good_8"...,"good_660"},然後用1替換第一個名字,然後用2替換...等等,這樣good_6將是1,good_7將是2等等上。但是現在good_10對應於1,而good_100對應於2等等。

我試過std :: sort向量,但值已經排序,只是不是我想要的方式(基於_之後的整數)。即使我只是得到最後的整數和排序,它仍然會被排序爲1,100,101 ...

任何幫助,將不勝感激。謝謝。

+0

您需要定義自定義排序方法....你申請了嗎? – orbit

+1

將內嵌代碼放入'\'反引號\''以使其可讀 –

回答

1

您可以使用與數字的特殊情況下,比較字符串的自定義函數:

#include <ctype.h> 

int natural_string_cmp(const char *sa, const char *sb) { 
    for (;;) { 
     int a = (unsigned char)*sa++; 
     int b = (unsigned char)*sb++; 

     /* simplistic version with overflow issues */ 
     if (isdigit(a) && isdigit(b)) { 
      const char *sa1 = sa - 1; 
      const char *sb1 = sb - 1; 
      unsigned long na = strtoul(sa1, (char **)&sa, 10); 
      unsigned long nb = strtoul(sb1, (char **)&sb, 10); 

      if (na == nb) { 
       if ((sa - sa1) == (sb - sb1)) { 
        /* XXX should check for '.' */ 
        continue; 
       } else { 
        /* Perform regular strcmp to handle 0 :: 00 */ 
        return strcmp(sa1, sb1); 
       } 
      } else { 
       return (na < nb) ? -1 : +1; 
      } 
     } else { 
      if (a == b) { 
       if (a != '\0') 
        continue; 
       else 
        return 0; 
      } else { 
       return (a < b) ? -1 : 1; 
      } 
     } 
    } 
} 

根據您的排序算法,您可能需要使用額外的間接水平把它包起來:

int natural_string_cmp_ind(const void *p1, const void *p2) { 
    return natural_string_cmp(*(const char * const *)p1, *(const char * const *)p2); 
} 


char *array[size]; 

... // array is initialized with filenames 

qsort(array, size, sizeof(*array), natural_string_cmp_ind); 
0

我想你可以玩弄你的數據結構。例如,而不是vector<string>,您可以將您的數據轉換爲vector< pair<int, string> >。那麼{"good_6", "good_7", "good_8"...,"good_660"}應該是{(6, "good"), (7, "good"), (7, "good")..., (660, "good")}。最後,你將它轉換回來,做你想做的任何事情。

另一種方法是將自己的比較器定義爲您想要的確切比較結果。

0

您可以使用string::replace將字符串「good_」替換爲空字符串,並使用stoi轉換字符串的其餘整數部分。可以說,獲得的價值是x

創建std :: map並使用這種方式填充myMap[x] = vec_element

然後你可以遍歷從m.begin()直到m.end()找到排序順序。

代碼:

myMap[ stoi(vec[i].replace(0,5,""))] = vec[i]; 

for(MapType::iterator it = myMap.begin(); it != myMap.end(); ++it) { 
    sortedVec.push_back(it->second); 
-1

託管與以下比較功能做到這一點:

bool numericStringComapre(const std::string& s1, const std::string& s2) 
{ 
    size_t foundUnderScore = s1.find_last_of("_"); 
    size_t foundDot = s1.find_last_of("."); 
    string s11 = s1.substr(foundUnderScore+1, foundDot - foundUnderScore - 1); 

    foundUnderScore = s2.find_last_of("_"); 
    foundDot = s2.find_last_of("."); 
    string s22 = s2.substr(foundUnderScore+1, foundDot-foundUnderScore - 1); 

    int i1 = stoi(s11); 
    int i2 = stoi(s22); 

    if (i1 < i2) return true; 

    return false; 
} 

完整的文件名是good_0.png,因此該find_last_of( 「」)。

0

如果我理解你的問題,那麼你只是在排序時遇到問題,而不是在排序後你打算如何改變名稱。

像這樣的事情可能會爲你工作:

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 
#include <tuple> 
#include <string.h> 

int main() 
{ 
    std::vector<std::string> v; 
    char buffer[64] = {}; 
    for (size_t i = 1; i < 10; ++i) 
    { 
     sprintf(buffer, "good_%d", i * 3); 
     v.push_back(buffer); 
     sprintf(buffer, "bad_%d", i * 2); 
     v.push_back(buffer); 
    } 
    std::random_shuffle(v.begin(), v.end()); 
    for (const auto& s : v) 
    { 
     std::cout << s << "\n"; 
    } 
    std::sort(v.begin(), v.end(), 
     [](const std::string& lhs, const std::string& rhs) 
    { 
     //This assumes a lot about the contents of the strings 
     //and has no error checking just to keep things short. 
     size_t l_pos = lhs.find('_'); 
     size_t r_pos = rhs.find('_'); 
     std::string l_str = lhs.substr(0, l_pos); 
     std::string r_str = rhs.substr(0, r_pos); 
     int l_num = std::stoi(lhs.substr(l_pos + 1)); 
     int r_num = std::stoi(rhs.substr(r_pos + 1)); 
     return std::tie(l_str, l_num) < std::tie(r_str, r_num); 
    }); 
    std::cout << "-----\n"; 
    for (const auto& s : v) 
    { 
     std::cout << s << "\n"; 
    } 
    return 0; 
}