3

我有像7X1234 XY1236 NM1235. 我想使用最后 4 个数字对这个字符串进行排序,只忽略最初的两个字母。另外,我想比较这些数字以查看它们是否是连续的。

我能想到的实现这一点的一种方法是将这些字符串在字母和数字之间拆分为 ( 7X and 1234) 并进行词法转换,将数字字符串转换为 int 并对其进行处理。但是,我怎样才能将字母部分再次与数字部分相关联,即在对数字字符串进行排序和比较时如何在末尾7X再次添加前缀?1234C++

简而言之,如果我有7X1234 XY1236 NM1235 BV1238我需要得到7X1234 NM1235 XY1236 BV1238

我没有详细说明我想知道字符串的数字部分是否是连续的。现在,当我只有像 1234 1236 1235 1238 这样的整数时,我会执行以下操作

            std::vector<int> sortedDigits{1234 1235 1236 1238};
            int count = 1;
            int pos = 0;
            std::vector<std::pair<int, int> > myVec;
            myVec.push_back(std::make_pair(sortedDigits[pos], count));
            for(size_t i = 1; i < sortedDigits.size(); ++i)
            {
                if(sortedDigits[i] != (sortedDigits[i-1] + 1))
                {
                   count = 1;
                   myVec.push_back(std::make_pair(sortedDigits[i], count) );
                   ++pos;
                }
                else
                {
                    sortedDigits[pos].second = ++count;
                }
            }  

所以最后我得到(1234, 3)(1238, 1)

我不知道当字符串存在时我怎么能得到这样的东西?

4

7 回答 7

11

由于数字的字符编码值与它们所代表的数字的顺序相同,因此您可以对最后四位数字进行字符串比较:

#include <cstring>
#include <string>

// Requires: a.size() >= 2, b.size() >= 2
bool two_less(std::string const & a, std::string const & b)
{
    return std::strcmp(a.data() + 2, b.data() + 2) < 0;
}

现在sort与谓词一起使用:

#include <algorithm>
#include <vector>

std::vector<std::string> data { "7X1234", "YX1236" };

std::sort(data.begin(), data.end(), two_less);

在 C++11 中,特别是如果您没有重复使用它,您也可以直接在sort调用中使用 lambda:

std::sort(data.begin(), data.end(),
         [](std::string const & a, std::string const & b)
         { return std::strcmp(a.data() + 2, b.data() + 2) < 0; });

然后,如果您需要改变它,您甚至可以将数字“2”设为捕获的变量。

于 2013-08-09T09:21:48.077 回答
2

使用qsort并提供一个比较器函数,该函数索引到字符串的开头加上两个偏移量,而不是直接从字符串的开头开始。

例如,您的比较器函数可能如下所示:

int compare (const void * a, const void * b)
{
    char * a_cmp = ((char *)a)+2;
    char * b_cmp = ((char *)b)+2;
    return strcmp(a_cmp, b_cmp);
}
于 2013-08-09T09:21:32.270 回答
1

例如,您可以像这样制作结构

struct combined{
    string alph;
    int numeral;
};

将这些放在 C++ 标准容器中

并将这种算法与用户定义的比较对象一起使用。

于 2013-08-09T09:20:26.613 回答
1

您应该创建一个类来封装您的字符串并具有一个intand 和字符串字段。此类可以重载比较运算符。

class NumberedString
{
private:
   int number;
   string originalString;

public:
   NumberedString(string original) { ... }

   friend bool operator> (NumberedString &left, NumberedString &right);
   friend bool operator<=(NumberedString &left, NumberedString &right);

   friend bool operator< (NumberedString &left, NumberedString &right);
   friend bool operator>=(NumberedString &left, NumberedString &right);
};
于 2013-08-09T09:21:42.510 回答
1

你可以定义你的比较器

bool mycomparator(const std::string& a, const std::string& b) {
    return a.substr(2) < b.substr(2);
}

然后你可以将你的std::vector<std::string>传递排序mycomparator为第三个参数。

在 C++11 中,这也是匿名 lambda 非常适合的情况......

#include <vector>
#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, const char *argv[])
{
    std::vector<std::string> data = {"7X1234", "XY1236", "NM1235", "BV1238"};
    std::sort(data.begin(), data.end(),
              [](const std::string& a, const std::string& b) {
                  return a.substr(2) < b.substr(2);
              });
    for (auto x : data) {
        std::cout << x << std::endl;
    }
    return 0;
}

如果您 100% 确定数组中的字符串XX9999格式正确,则可以改用

return strncmp(a.data()+2, b.data()+2, 4) < 0;

这更有效,因为不需要任何内存分配来进行比较。

于 2013-08-09T09:23:14.010 回答
0

使用 a std::map<int, std::string>,使用 int 值作为键,将相应的字符串作为值。然后,您可以简单地遍历地图并检索字符串;它们已经按排序顺序排列。

于 2013-08-09T09:22:08.380 回答
0

像这样的东西怎么样:

std::string str[] = { "7X1234", "XY1236", "NM1235" };

std::map<int, std::string> m;

for(s : str)
{
    std::ostringstream ss(s.substr(2));
    int num;
    ss >> num;
    m[num] = s;
}
for(i : m)
{
   std::cout << i->second << " ";
}
std::cout << std::endl;

我刚刚输入了这个,所以可能存在轻微的拼写错误/错误,但原则应该有效。

于 2013-08-09T09:25:14.523 回答