我有一个包含文件{"good_6", good_7", "good_8"...,"good_660"}
的目录,在使用 readdir 读取并存储到向量后,我得到{"good_10", "good_100", "good_101", "good_102"...}
。
我想要做的是将文件名保存为向量中的{"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 :(得分: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);
答案 1 :(得分:0)
我认为您可以使用您的数据结构。例如,您可以将数据转换为vector<string>
,而不是vector< pair<int, string> >
。然后{"good_6", "good_7", "good_8"...,"good_660"}
应为{(6, "good"), (7, "good"), (7, "good")..., (660, "good")}
。最后,你将它转换回来做你想做的任何事情。
另一种方法是定义自己的比较器,以便按照你想要的方式进行精确比较。
答案 2 :(得分: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 );
答案 3 :(得分: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;
}
答案 4 :(得分:-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(&#34;。&#34;)。