Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用C+中字符串末尾的整数值对字符串向量进行排序+;_C++_Sorting_Vector - Fatal编程技术网

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`
以使其可读