Java verfügt über eine praktische Split-Methode:
String str = "The quick brown fox";
String[] results = str.split(" ");
Gibt es eine einfache Möglichkeit, dies in C++ zu tun?
Java verfügt über eine praktische Split-Methode:
String str = "The quick brown fox";
String[] results = str.split(" ");
Gibt es eine einfache Möglichkeit, dies in C++ zu tun?
Wenn die maximale Länge der zu tokenisierenden Eingabezeichenfolge bekannt ist, kann man dies ausnutzen und eine sehr schnelle Version implementieren. Ich skizziere im Folgenden die Grundidee, die sowohl von strtok() als auch von der in Jon Bentleys "Programming Perls" (2. Auflage, Kapitel 15) beschriebenen "Suffix-Array"-Datenstruktur inspiriert wurde. Die C++-Klasse bietet in diesem Fall nur eine gewisse Organisation und Benutzerfreundlichkeit. Die gezeigte Implementierung kann leicht erweitert werden, um führende und nachfolgende Leerzeichen in den Token zu entfernen.
Grundsätzlich kann man die Trennzeichen durch string-terminierende ' \0 Zeichen und setzen Zeiger auf die Token in der geänderten Zeichenfolge. Im Extremfall, wenn die Zeichenkette nur aus Trennzeichen besteht, erhält man die Länge der Zeichenkette plus 1, was zu leeren Token führt. Es ist praktisch, die zu ändernde Zeichenkette zu duplizieren.
Header-Datei:
class TextLineSplitter
{
public:
TextLineSplitter( const size_t max_line_len );
~TextLineSplitter();
void SplitLine( const char *line,
const char sep_char = ',',
);
inline size_t NumTokens( void ) const
{
return mNumTokens;
}
const char * GetToken( const size_t token_idx ) const
{
assert( token_idx < mNumTokens );
return mTokens[ token_idx ];
}
private:
const size_t mStorageSize;
char *mBuff;
char **mTokens;
size_t mNumTokens;
inline void ResetContent( void )
{
memset( mBuff, 0, mStorageSize );
// mark all items as empty:
memset( mTokens, 0, mStorageSize * sizeof( char* ) );
// reset counter for found items:
mNumTokens = 0L;
}
};
Implementierungsdatei:
TextLineSplitter::TextLineSplitter( const size_t max_line_len ):
mStorageSize ( max_line_len + 1L )
{
// allocate memory
mBuff = new char [ mStorageSize ];
mTokens = new char* [ mStorageSize ];
ResetContent();
}
TextLineSplitter::~TextLineSplitter()
{
delete [] mBuff;
delete [] mTokens;
}
void TextLineSplitter::SplitLine( const char *line,
const char sep_char /* = ',' */,
)
{
assert( sep_char != '\0' );
ResetContent();
strncpy( mBuff, line, mMaxLineLen );
size_t idx = 0L; // running index for characters
do
{
assert( idx < mStorageSize );
const char chr = line[ idx ]; // retrieve current character
if( mTokens[ mNumTokens ] == NULL )
{
mTokens[ mNumTokens ] = &mBuff[ idx ];
} // if
if( chr == sep_char || chr == '\0' )
{ // item or line finished
// overwrite separator with a 0-terminating character:
mBuff[ idx ] = '\0';
// count-up items:
mNumTokens ++;
} // if
} while( line[ idx++ ] );
}
Ein Szenario für die Verwendung wäre:
// create an instance capable of splitting strings up to 1000 chars long:
TextLineSplitter spl( 1000 );
spl.SplitLine( "Item1,,Item2,Item3" );
for( size_t i = 0; i < spl.NumTokens(); i++ )
{
printf( "%s\n", spl.GetToken( i ) );
}
Ausgabe:
Item1
Item2
Item3
Dies ist eine einfache Schleife zur Tokenisierung mit nur Standardbibliotheksdateien
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <conio.h>
class word
{
public:
char w[20];
word()
{
for(int j=0;j<=20;j++)
{w[j]='\0';
}
}
};
void main()
{
int i=1,n=0,j=0,k=0,m=1;
char input[100];
word ww[100];
gets(input);
n=strlen(input);
for(i=0;i<=m;i++)
{
if(context[i]!=' ')
{
ww[k].w[j]=context[i];
j++;
}
else
{
k++;
j=0;
m++;
}
}
}
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.
234 Stimmen
Ich kann nicht glauben, dass diese Routineaufgabe in C++ so viel Kopfzerbrechen macht
6 Stimmen
Seine nicht Kopfschmerzen in C + + - es gibt verschiedene Möglichkeiten, um es zu erreichen. Programmierer sind weniger bewusst, C + + als c # - seine über Marketing und Investitionen ... siehe dies für verschiedene C + + Optionen, um das gleiche zu erreichen: cplusplus.com/faq/sequenzen/strings/split
11 Stimmen
@hB0 gehen durch viele Fragen Antworten und immer noch nicht entscheiden, bedeutet, ist ein Kopfschmerz. die eine braucht, dass die Bibliothek, die andere ist nur für Leerzeichen, die andere nicht behandeln Leerzeichen.
3 Stimmen
Mögliches Duplikat von Eine Zeichenkette in C++ aufteilen?
8 Stimmen
Warum muss in C++ alles ein Kampf sein?
2 Stimmen
C++ ist eine leistungsfähige Sprache, die keine Einheitslösung für die Zeichenkettenmanipulation bietet. Für diese Anwendung ist manchmal alles, was Sie wollen, das letzte Token oder die ersten paar Token, aber ein "Split" wird alles tokenisieren, ohne bedarfsorientierte Stopps. Unabhängig davon sind String-Operationen in jeder Sprache teuer, und deshalb hat sich der C++-Standard ausdrücklich gegen übermäßig vereinfachende Schnittstellen ausgesprochen, die die wahre Komplexität verbergen.
0 Stimmen
@JohnPhuNguyen:
a "split" will tokenize everything without any need-based stops
. Kein Scherz. Das ist genau das Verhalten, das erwünscht ist.1 Stimmen
Interessanterweise sind alle Antworten auf diese Frage auch Antworten auf
Why are Java and Python so much more popular than C++?
.1 Stimmen
@stackoverflowuser2010 Ich glaube, Sie haben den Punkt nicht verstanden. Ja, das ist genau das Verhalten, das bei einem einheitlichen Ansatz erwünscht ist, was ich auch gesagt habe. Und es ist relevant für die Antwort auf die Frage, warum es in Java einfacher zu machen ist als in C++. Die CPP-Standardbibliothek vermeidet explizit alle Komfortmethoden, die die algorithmische Komplexität abstrahieren - deshalb können One-Size-Fits-All-Methoden angeboten werden, werden aber nicht angeboten.
0 Stimmen
@JohnPhuNguyen: Ich verstehe nicht, was Sie meinen mit
one size fits all
. In dieser Frage gibt es nur eine Größe: Tokenize a string. Es gibt keine andere Größe.0 Stimmen
@stackoverflowuser2010 Was ich meine ist, dass die Tokenisierung eine teure Funktion ist, die oft generisch verwendet wird, auch wenn sie nicht benötigt wird. C++ fördert die Implementierung spezifischer Anwendungsfälle anstelle der Tokenisierung, da der eigentliche Akt der Tokenisierung selten benötigt wird. Es wird oft als Mittel verwendet, um etwas in einer Zeichenkette zu finden. Stattdessen bietet C++ (unter anderem) Regex-Matching, das zwar teuer ist, aber bei weitem nicht so teuer wie die String-Manipulation, die in Tokenizern stattfindet. Ja, ein Tokenizer wird leicht für jede Lösung passen, aber er ist selten die beste Lösung. C++ rät davon ab, diesen Weg zu gehen.
1 Stimmen
Eine Lösung für genau diese Frage scheint hier zu liegen: riptutorial.com/cplusplus/example/2148/tokenize