web-dev-qa-db-ja.com

c ++文字列を文字で分割しますか?

102:330:3133:76531:451:000:12:44412」などの文字列を「:」文字で分割し、すべての数値をint配列に入れるにはどうすればよいですか(数値シーケンスは常に8の長さになります)ブーストなどのライブラリ。

また、「$」や「#」など、処理前に文字列から不要な文字を削除するにはどうすればよいのでしょうか?

11
user2705775

stringstreamはこれらすべてを実行できます。

  1. 文字列を分割し、int配列に保存します。

    string str = "102:330:3133:76531:451:000:12:44412";
    std::replace(str.begin(), str.end(), ':', ' ');  // replace ':' by ' '
    
    vector<int> array;
    stringstream ss(str);
    int temp;
    while (ss >> temp)
        array.Push_back(temp); // done! now array={102,330,3133,76531,451,000,12,44412}
    
  2. $#など、処理される前の文字列から不要な文字を削除します。上記の:を処理する方法と同じです。

8
herohuyongtao

Cの標準的な方法は、他の人が答えたように strtok を使用することです。ただし、strtokC++のようなものではなく、 安全でない でもありません。 C++の標準的な方法は、 std::istringstream を使用することです

std::istringstream iss(str);
char c; // dummy character for the colon
int a[8];
iss >> a[0];
for (int i = 1; i < 8; i++)
    iss >> c >> a[i];

入力が常にそのような固定数のトークンを持っている場合、sscanfは別の簡単な解決策かもしれません

std::sscanf(str, "%d:%d:%d:%d:%d:%d:%d:%d", &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8);
8
phuclv

以前にこのようなコードを作成する必要があり、区切り文字で文字列を分割するためのStack Overflowに関する質問を見つけました。元の質問は次のとおりです。 link

これをstd::stoiとともに使用して、ベクターを構築できます。

std::vector<int> split(const std::string &s, char delim) {
    std::vector<int> elems;
    std::stringstream ss(s);
    std::string number;
    while(std::getline(ss, number, delim)) {
        elems.Push_back(std::stoi(number));
    }
    return elems;
}

// use with:
const std::string numbers("102:330:3133:76531:451:000:12:44412");
std::vector<int> numbers = split(numbers, ':');

これは動作する理想的なサンプルです

5
Lander

ここに一つの方法があります...最も賢い方法ではなく、書くのが速いです構文解析へのこのアプローチは非常に広く有用であり、学ぶのに適しています。 !(iss >> c)は、文字列に後続の非空白文字がないことを保証します。

std::istringstream iss(the_string);
char c;
int n[8];
if (iss >> n[0] >> c && c == ':' &&
    iss >> n[1] >> c && c == ':' &&
    iss >> n[2] >> c && c == ':' &&
    iss >> n[3] >> c && c == ':' &&
    iss >> n[4] >> c && c == ':' &&
    iss >> n[5] >> c && c == ':' &&
    iss >> n[6] >> c && c == ':' &&
    iss >> n[7] && !(iss >> c))
    ...
1
Tony Delroy

おそらくwhileループで、strtok()を使用して文字列を分割できます。

個々の文字列を取得したら、atoi(xxx)を使用してintに変換できます。

0
Digital_Reality

本当だ! elven magic はありません

そのちょっと答えた ここ

#include <cstring>
#include <iostream>
#include<cstdlib>
#include<vector>

int main() 
{
    char input[100] = "102:330:3133:76531:451:000:12:44412";
    char *token = std::strtok(input, ":");
    std::vector<int> v;

    while (token != NULL) {
        v.Push_back( std::strtol( token, NULL, 10 ));
        token = std::strtok(NULL, ":");
    }

    for(std::size_t i =0 ; i < v.size() ; ++i)
        std::cout << v[i] <<std::endl;
}

デモ ここ

0
P0W

文字「#」と「$」を削除するには、標準アルゴリズムstd::remove_ifを使用できます。ただし、たとえば次の文字列「12#34」がある場合は、「#」を削除すると「1234」が生成されることを考慮してください。結果の文字列が「12 34」または「12:34」に見える必要がある場合は、std::remove_ifの代わりにstd::replace_ifを使用することをお勧めします。

以下に、タスクを実行するサンプルコードを示します。ヘッダーを含める必要があります

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>

int main()
{
    char s[] = "102:$$330:#3133:76531:451:000:$12:44412";

    std::cout << s << std::endl;

    char *p = std::remove_if( s, s + std::strlen( s ), 
        []( char c ) { return ( c == '$' || c == '#' ); } );
    *p = '\0';

    std::cout << s << std::endl;

    const size_t N = 8;
    int a[N];

    p = s;
    for ( size_t i = 0; i < N; i++ )
    {
        a[i] = strtol( p, &p, 10 );
        if ( *p == ':' ) ++p;
    }

    for ( int x : a ) std::cout << x << ' ';
    std::cout << std::endl;
}

出力は

102:$$330:#3133:76531:451:000:$12:44412
102:330:3133:76531:451:000:12:44412
102 330 3133 76531 451 0 12 44412
0

含める

#include <string.h>

int main ()
{
  char str[] ="102:330:3133:76531:451:000:12:44412";
  char * pch;
  printf ("Splitting string \"%s\" into tokens:\n",str);
  pch = strtok (str,":");
  while (pch != NULL)
  {
    printf ("%s\n",pch);
    pch = strtok (NULL, ":");
  }
  return 0;
}
0
Imtiaz Emu

C++ 11の正規表現機能を使用する別のソリューション。

#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <regex>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    const std::string s = "102:330:3133:76531:451:000:12:44412";

    // Replace each colon with a single space
    const std::regex pattern(":");
    const std::string r = std::regex_replace(s, pattern, " ");

    std::istringstream ist(r);

    std::vector<int> numbers;
    std::copy(std::istream_iterator<int>(ist), std::istream_iterator<int>(),
        std::back_inserter(numbers));

    // We now have a vector of numbers

    // Print it out
    for (auto n : numbers)
    {
        std::cout << n << " ";
    }
    std::cout << std::endl;

    return 0;
}
0
user515430