C++ 使用C+中字符串末尾的整数值对字符串向量进行排序+;
我有一个目录,其中包含文件C++ 使用C+中字符串末尾的整数值对字符串向量进行排序+;,c++,sorting,vector,C++,Sorting,Vector,我有一个目录,其中包含文件{“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替换第二个名称,依此类推。。。好的6是1,好的7是2,依此类推。但是现在good_10对应于1,good_100对应
{“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替换第二个名称,依此类推。。。好的6是1,好的7是2,依此类推。但是现在good_10对应于1,good_100对应于2,依此类推
我尝试了对vector进行std::sort,但这些值已经排序,只是没有按照我所希望的方式(基于x之后的整数)排序。即使我只得到最后一个整数并对其进行排序,它仍然会被排序为1100101
任何帮助都将不胜感激。谢谢。您可以使用自定义函数将字符串与数字的特殊大小写进行比较:
#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;
}
}
}
}
可以使用自定义函数将字符串与数字的特殊大小写进行比较:
#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;
}
}
}
}
我认为你可以玩弄你的数据结构。例如,您可以将数据转换为
vector
,而不是vector
。然后{“good_6”,“good_7”,“good_8”…,“good_660”}
应该是{(6,“good”),(7,“good”),(7,“good”)…,(660,“good”)}
。最后,你把它转换回来,做你想做的事
另一种方法是定义自己的比较器,根据需要进行精确的比较。我认为您可以随意使用数据结构。例如,您可以将数据转换为
vector
,而不是vector
。然后{“good_6”,“good_7”,“good_8”…,“good_660”}
应该是{(6,“good”),(7,“good”),(7,“good”)…,(660,“good”)}
。最后,你把它转换回来,做你想做的事
另一种方法是定义自己的比较器,以便根据需要进行精确的比较。您可以使用空字符串替换字符串“good_u”,并使用转换字符串的其余整数部分。假设获得的值为x
创建std::map并以这种方式填充它myMap[x]=vec\u元素
然后您可以从m.begin()
遍历到m.end()
,以查找排序顺序
代码:
您可以使用来将字符串“good_”替换为空字符串,并使用来转换字符串的其余部分。假设获得的值为x
创建std::map并以这种方式填充它myMap[x]=vec\u元素
然后您可以从m.begin()
遍历到m.end()
,以查找排序顺序
代码:
通过以下比较功能成功完成此操作:
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;
}
bool numericStringComapre(常量std::string&s1,常量std::string&s2)
{
大小\u t found下划线=s1。查找(“”);
大小\u t foundDot=s1。查找(“.”)中的最后一个;
字符串s11=s1.substr(found下划线+1,foundDot-found下划线-1);
FoundUnderline=s2。查找(“”);
foundDot=s2。查找(“.”)中的最后一个;
字符串s22=s2.substr(found下划线+1,foundDot found下划线-1);
int i1=stoi(s11);
inti2=stoi(s22);
如果(i1
完整的文件名是良好的\u 0.png,因此find \u last \u of(“.”)。通过以下比较函数,成功地实现了这一点:
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;
}
bool numericStringComapre(常量std::string&s1,常量std::string&s2)
{
大小\u t found下划线=s1。查找(“”);
大小\u t foundDot=s1。查找(“.”)中的最后一个;
字符串s11=s1.substr(found下划线+1,foundDot-found下划线-1);
FoundUnderline=s2。查找(“”);
foundDot=s2。查找(“.”)中的最后一个;
字符串s22=s2.substr(found下划线+1,foundDot found下划线-1);
int i1=stoi(s11);
inti2=stoi(s22);
如果(i1
完整的文件名是好的,因此查找(“.”)的最后一个文件名。如果我理解你的问题,你只是在排序方面遇到了问题,而不是在排序后如何更改名称 这样的东西可能适合你:
#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
std::向量v;
字符缓冲区[64]={};
对于(尺寸i=1;i<10;++i)
{
sprintf(缓冲区,“良好的%d”,i*3);
v、 推回(缓冲器);
sprintf(缓冲区,“坏的%d”,i*2);
v、 推回(缓冲器);
}
随机洗牌(v.begin(),v.end());
用于(常数自动和s:v)
{
如果我理解你的问题,你只是排序有问题,而不是排序后如何更改名称
这样的东西可能适合你:
#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
std::向量v;
字符缓冲区[64]={};
对于(尺寸i=1;i<10;++i)
{
sprintf(缓冲区,“良好的%d”,i*3);
v、 推回(缓冲器);
sprintf(缓冲区,“坏的%d”,i*2);
v、 推回(缓冲器);
}
随机洗牌(v.begin(),v.end());
用于(常数自动和s:v)
{
std::您是否需要定义自定义排序方法…您是否应用了该方法?将内联代码放入`backticks`
以使其可读您需要定义自定义排序方法…您是否应用了该方法?将内联代码放入`backticks`
以使其可读