使用C ++中

时间:2017-06-22 02:01:41

标签: 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,依此类推......这样good_6将为1,good_7将为2等等。但是现在good_10对应于1而good_100对应于2,依此类推。

我在向量上尝试了std :: sort但是值已经排序了,只是没有按照我想要的方式(基于_之后的整数)。即使我只是得到最后一个整数并对其进行排序,它仍然会被分类为1,100,101 ......

任何帮助将不胜感激。感谢。

5 个答案:

答案 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;)。