2016-10-09 5 views
-1

im Versuch, bestimmte Daten aus einer Zeichenfolge zu extrahieren, die wie folgt lautet:C++ unvollständige Ausgabe beim Aufteilen der Zeichenfolge

2833ae7~2be;2833ae8~2272 

, was ich tun möchte, ist spaltete es zuerst durch den Doppelpunkt, dann wird jeder Datensatz, zu finden, wenn es enthält 2be dann die Datensätze aufgeteilt, die sie von ~2be enthält, und geben sie mir den Wert kurz vor ~2be

ich einige Aufsätze haben, und dieser Code Art es tut, aber das Problem ist, dass es mir nicht gibt tun die volle Ausgabe:

i
#include <string> 
#include <sstream> 
#include <vector> 
#include <iostream> 
using namespace std; 

vector<string> split(string str,string sep){ 
    char* cstr=const_cast<char*>(str.c_str()); 
    char* current; 
    vector<string> arr; 
    current=strtok(cstr,sep.c_str()); 
    while(current!=NULL){ 
     arr.push_back(current); 
     current=strtok(NULL,sep.c_str()); 
    } 
    return arr; 
} 

int main(){ 
string items = "2833ae7~2be;2833ae8~2272"; 
vector<string> food = split(items, ";"); 
for(unsigned int i = 0; i < food.size(); i++) 
{ 
    if(food[i].find("2be") != string::npos) 
    { 
     vector<string> arr = split(food[i],"~2be"); 


     cout << "Output ("<< i << ") = " << arr[0] << endl; 

     }// end if 

}// end for 

    return 0; 
}// end main 

Der Ausgang erhalten ist:

Output <0> = 833a 

Wenn es sein sollte:

Output <0> = 2833ae7 

, was im falsch machen?

+0

Das erste Problem ist, dass Sie C-String-Funktionen für Ihre 'std :: string' Objekte verwenden. Das 'c' in' c_str' steht für * constant *. Die Daten sollten nicht geändert werden. Von [dieser 'c_str'-Referenz] (http://en.cppreference.com/w/cpp/string/basic_string/c_str):" Schreiben in das Zeichen-Array, auf das über c_str() zugegriffen wird, ist ein undefiniertes Verhalten. " Und die 'strtok'-Funktion * schreibt * in die Zeichenfolge. Dass du ein "const_cast" machen musst, sollte ein Hinweis darauf sein, dass du etwas tust, was du nicht tun solltest. –

+0

Sie verwenden 'strtok' nicht korrekt. Das zweite Argument für die Funktion ist eine Zeichenfolge, die den Satz Trennzeichen enthält, die als Token verwendet werden. Wenn Sie '" ~ 2be "' an die Funktion übergeben, wird versucht, eines dieser Zeichen im ersten Argument zu finden. Wenn das erste Argument "2833ae7" ist, bricht es bei der ersten "2" ab und gibt eine leere Zeichenfolge zurück. –

+0

'current = strtok (cstr, sep.c_str())' - Undefiniertes Verhalten. Das 'strtok' mutiert die Daten, die an es übergeben werden, und' cstr' zeigt auf ein 'const char *'. – PaulMcKenzie

Antwort

0

Wie andere in den Kommentaren erwähnt haben, ist das Ändern des Zeichenarrays, das Sie von std::string::c_str() erhalten, ein undefiniertes Verhalten. strtok() ändert seinen Parameter, um die Token zu markieren, so dass Sie ihn hier nicht verwenden können.

Das Teilen eines std::string durch ein single-char-Trennzeichen ist nicht schwer. Eine Möglichkeit, es tun könnte, ist wie folgt:

std::vector<std::string> split(const std::string &input, std::string::value_type delim) 
{ 
    std::stringstream ss(input); 
    std::vector<std::string> tokens; 
    std::string token; 
    while (std::getline(ss, token, delim)) 
    { 
     tokens.push_back(token); 
    } 

    return tokens; 
} 

Sie können dann Ihre Zeichenfolge wie folgt aufgeteilt:

std::vector<std::string> tokens = split("2833ae7~2be;2833ae8~2272", ';'); 

Dies gibt Ihnen einen Vektor enthält zwei Elemente: „2833ae7 ~ 2be“ und " 2833ae8 ~ 2272 ".

Jetzt für den zweiten Teil können Sie nicht die gleiche split() Methode verwenden, da es nur für Single-Char-Trennzeichen funktioniert. Aber man könnte so etwas wie dies stattdessen tun:

for (std::size_t index = 0; index < tokens.size(); ++index) 
{ 
    if (tokens[index].find("2be") != std::string::npos) 
    { 
     std::string::size_type pos = tokens[index].find("~2be"); 

     std::cout << "Output (" << index << ") = " << tokens[index].substr(0, pos) << "\n"; 
    } 
} 

die gleiche Idee verwenden können Sie auch versuchen, die split() Methode neu zu schreiben, um es für String-Trennzeichen funktioniert, nicht nur Single-char diejenigen wie meine Version.

Verwandte Themen