2017-06-22 70 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; 
}