wake-up-neo.com

c ++ Zeichenkette nach Zeichen aufteilen?

Wie kann ich eine Zeichenfolge wie "102:330:3133:76531:451:000:12:44412" durch das Zeichen ":" aufteilen und alle Zahlen in ein int-Array schreiben (Zahlenfolge wird immer 8 sein)? Vorzugsweise ohne Verwendung einer externen Bibliothek wie boost.

Außerdem frage ich mich, wie ich nicht benötigte Zeichen aus der Zeichenfolge entfernen kann, bevor sie verarbeitet werden, beispielsweise "$" und "#".

10
user2705775

stringstream kann all dies tun.

  1. Trennen Sie einen String und speichern Sie ihn im int-Array:

    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. Entfernen Sie nicht benötigte Zeichen aus der Zeichenfolge, bevor sie verarbeitet werden, z. B. $ und #: genauso wie bei der Verarbeitung von : oben.

9
herohuyongtao

Die Standardmethode in C ist die Verwendung von strtok wie andere beantwortet haben. strtok ist jedoch nicht C++-ähnlich und auch unsicher . Die Standardmethode in C++ ist die Verwendung von 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];

Falls die Eingabe immer eine feste Anzahl solcher Token hat, kann sscanf eine andere einfache Lösung sein

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

Ich musste zuvor etwas Code schreiben und fand eine Frage zu Stack Overflow, um einen String nach Trennzeichen zu teilen. Hier ist die ursprüngliche Frage: link .

Sie können dies mit std::stoi zum Erstellen des Vektors verwenden.

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, ':');

Hier ist eine funktionierende Ideone-Probe .

4
Lander

Hier ist ein Weg ... nicht der klügste, aber schnell zu schreiben (8 Wiederholungen, die anscheinend eine Schleife rechtfertigen). Dieser Parsing-Ansatz ist sehr nützlich, also gut zu lernen. !(iss >> c) stellt sicher, dass in der Zeichenfolge keine Leerzeichen nachgestellt werden.

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

Sie können strtok() verwenden, um Ihre Zeichenfolge aufzuteilen, möglicherweise in while-Schleife.

Wenn Sie einen individuellen String erhalten, können Sie atoi(xxx) für die Konvertierung in ints verwenden. 

0
Digital_Reality

Wahr ! es gibt keine elven magie

Es hat irgendwie geantwortet hier

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

Demo hier

0
P0W

Um die Zeichen '#' und '$' zu entfernen, können Sie den Standardalgorithmus std::remove_if verwenden. Wenn Sie jedoch die folgende Zeichenfolge "12 # 34" eingeben, wird nach dem Entfernen von "#" "1234" angezeigt. Wenn Sie möchten, dass der Ergebnisstring als "12 34" oder "12:34" angezeigt wird, sollten Sie anstelle von std::remove_ifstd::replace_if verwenden.

Darunter befindet sich ein Beispielcode, der die Aufgabe ausführt. Sie müssen Header hinzufügen

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

Die Ausgabe ist

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

umfassen 

#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

Eine andere Lösung, die die regulären Ausdrücke in C++ 11 verwendet.

#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