3

のような文字列があります7X1234 XY1236 NM1235。最初の2つのアルファベットを無視して、最後の4桁の数字のみを使用してこの文字列をソートしたいと思います。また、それらの数字を比較して、それらが連続しているかどうかを確認したいと思います。

これを実現する方法の 1 つは、これらの文字列を ( ) としてアルファベットと数字に分割し7X and 1234、数字文字列を int にレキシカル キャストして作業することです。しかし、数字列を並べ替えて比較する際に、最後に付け7X直す方法である数字部分にアルファベット部分を再度関連付けるにはどうすればよいでしょうか。1234C++

要するに、私が持っているなら、私は7X1234 XY1236 NM1235 BV1238得る必要があります7X1234 NM1235 XY1236 BV1238

文字列の数値部分が連続しているかどうかを調べたかったことについては詳しく説明しませんでした。今、1234 1236 1235 1238 のような int しかないとき、私は以下のようなことをします

            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

数値の文字エンコード値は、数字が表す数値と同じ順序で並べられるため、最後の 4 桁で文字列比較を行うことができます。

#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呼び出しでラムダを直接使用することもできます。

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を使用して、文字列の先頭から直接ではなく、文字列の先頭に 2 のオフセットを加えたインデックスを作成するコンパレータ関数を提供します。

たとえば、コンパレータ関数は次のようになります。

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

int文字列をカプセル化し、 and および文字列フィールドを持つクラスを作成する必要があります。このクラスは、比較演算子をオーバーロードできます。

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);
}

次に、3 番目のパラメーターとしてstd::vector<std::string>渡すことを並べ替えることができます。mycomparator

C++11 では、匿名ラムダが適しているケースでもあります...

#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;
}

配列内の文字列がXX9999フォーマットされていることを100%確信している場合は、代わりに使用できます

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

比較を行うためにメモリ割り当てを必要としないため、より効率的です。

于 2013-08-09T09:23:14.010 に答える
0

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 に答える