Seite 1 von 1
Klammern und Kommas im String sollen zu einer Liste führen
Verfasst: 17. Juni 2011 03:49
von feldmaus
Guten Morgen,
ich versuche mit dem folgenden Code einen QString in ein QList zu überführen. Als Beispiel soll
"(das) Essen" zu
["das Essen", "Essen"] führen, oder
"eine Menge, viel" soll zu
["eine Menge", "viel"] führen.
Mein derzeitiger Code ist leider nicht flexibel genug, soll heißen es wird nur ein einfacher Klammer-Ausdruck berücksichtigt, wenn ich allerdings z.b.
"(o, a) tenista" habe versagt mein Code, da in der Klammer ein Komma ist, was mein Code falsch interpretieren würde. Wünschen würde ich mir das mein Code mit EINEM Klammer-Ausdruck und mit beliebig vielen Kommas in diesem Klammer-Ausdruck klar kommt. Außerhalb von Klammer-Ausdrücken sind ja beliebig viele Kommas erlaubt.
Hier mein jetziger Code:
Code: Alles auswählen
void KEduVocText::setList( const QString & expr )
{
Qlist liste = expr.simplified().split(",", QString::SkipEmptyParts);
QList modListe;
foreach(Qstring str, liste) {
if ( str.contains( QRegExp("\(.*\)") ) ) {
modListe << str.replace( QRegExp("\(([^<]*)\)"), "" ).simplified()
<< str.replace( QRegExp("\(([^<]*)\)"), "\\1" ).
simplified();
}
else {
modListe << str;
}
}
d->m_list = modListe;
}
Grüße Markus
EDIT: Der Ausdruck "
expression1 (irgendwas, weiter was) expression2", sollte auch zu einem korrektem Ergebnis führen.
Verfasst: 17. Juni 2011 11:14
von RHBaum
selbst ohne Code faellts mir schwer, eindeutige Ergebnisse vorherzusagen
was soll zum beispiel bei "(eine) Menge, viel" rauskommen ?
Ich versteh das prinzip noch ned ganz ^^
keine Ahnung, ob sich das durch regexp loesen laesst.
Und wenn DU mit RegExp nicht weiter kommst, wirst du wohl tiefer in die stringinterpretation einsteigen muessen. Sowas wie eine Art Programmiersprache schreiben.
Such mal nach Token Tokenizer, da solltest vielleicht Ansatzpunkte finden.
Ciao ...
Verfasst: 17. Juni 2011 11:32
von feldmaus
RHBaum hat geschrieben:was soll zum beispiel bei "(eine) Menge, viel" rauskommen ?
Ergebnis:
["eine Menge", "Menge", "viel"]
Die Wörter in Klammern sind immer optional und können, müssen aber nicht, zum korrekten Ergebnis führen.
Hintergrund ist eine Vokabel-Software in der die vom Benutzer eingegebenen Wörter auf Richtigkeit geprüft werden.
Grüße Markus
Verfasst: 17. Juni 2011 12:45
von feldmaus
EDIT: DER CODE ist hier
So habe meinen Code ausgebessert, allerdings noch ungetestet. kdevelop highlighted aber alle wörter, also ist auch alles deklariert.
Mein Code enthält zwei ineinander verschachtelte Schleifen, leider weiß ich nicht wie ich es sonst vermeiden kann. Die zu verarbeitenden Zeichenketten sind aber nicht lang. Vielleicht hat der eine oder andere noch Tuning Ideen, Schönheitskorrekturen oder findet Fehler.
Code: Alles auswählen
void KEduVocText::setList( const QString & expr )
{
QStringList liste = expr.simplified().split(",", QString::SkipEmptyParts);
QStringList modListe;
foreach (QString str, liste) {
if ( str.contains( QRegExp("\(.*\)") ) ) {
QStringList bracketExpr = str
.section( QChar::Mark_Enclosing, 1, 1 )
.split( ",", QString::SkipEmptyParts );
for ( int i; i < bracketExpr.size(); ++i ) {
bracketExpr[i] = bracketExpr[i].simplified();
}
QStringList nonBracketExpr = str.replace( QRegExp("\(.*\)"), "," )
.split( "," ) ;
nonBracketExpr[0] = nonBracketExpr[0].simplified();
nonBracketExpr[1] = nonBracketExpr[1].simplified();
QString pre = nonBracketExpr[0] , post = nonBracketExpr[1];
foreach ( QString elem, bracketExpr ) {
modListe << pre+elem+post;
}
modListe << pre+post;
}
else {
modListe << str;
}
}
d->m_list = modListe;
}
Am liebsten würde ich diesen Code noch dokumentieren, weiß aber nicht ob das Gut ist in einem so großen Programm (parley) was rein zu schreiben. Was meint Ihr? Und wenn dokumentieren, dann wie?
Grüße Markus
Verfasst: 17. Juni 2011 12:46
von kater
Na so schwer ist das doch nicht. Hast ein guten Anfang. Problem ist, dass du nicht mit split den String anhand den Kommas trennen kannst. Da auch Kommas in Klammern vorkommen.
Regex kann ich leider auch nicht. Daher durchlaufe den String doch einfach von Hand von links nach rechts. Merke dir die Positionen der Kommas, wenn sie nicht nach einer offenen Klammer stehen.
Also einfach merken. Offene Klammer gefunden ja/nein. Komma Position merken ja/nein.
Dann kannst du den String zerlegen.
Und mit den Teilstücken machst du weiten. Keine Kammer im Teilstück vorhanden? -> Ferig. Wenn nicht, Teilstück weiter zerlegen. Da funktioniert dann die split() Funktion gut.
So, oder so ähnlich jedenfalls

Verfasst: 17. Juni 2011 13:36
von feldmaus
Mein kdevelop meckert rum, dass QRegExp() mit meinem Klammer-Zeichen nicht klar kommt.
Wie müsste ich QRegExp() eine Klammer als Zeichen übergeben?
oder
oder
...???
Laut
QT Doku von QRegExp muss ich
"\\\(" schreiben, also drei mal Backslash. Ich bekomme aber vom Compiler eine Warning
unknown escape sequence: '\)'.
Klammern und Kommas im String sollen zu einer Liste führen
Verfasst: 17. Juni 2011 22:10
von sowas
Hallo,
mit QRegExp() kenne ich mich nicht aus. Ich würde es so lösen.
Wenn es geht, den Text mehrmals parsen, zuerst nach Klammern suchen, wenn es welche gibt, feststellen ob zwischen den Klammern Kommata stehen, diese würde ich z.B. durch eine Raute '#' ersetzen. Beim nächsten Durchgang stören die Kommata nicht mehr.
Zum Schluss die Rauten löschen oder durch andere Zeichen ersetzten.
bk
Verfasst: 19. Juni 2011 16:08
von FaS
@sowas: mit einem anderen Zeichen ersetzen> Nein, das würde unnötige Ausnahmeregelungen erfordern.
@feldmaus: \ Ist ein Escape-Zeichen in C-Strings, das hat nichts mit Qt zu tun! QRegExp braucht \( und \ schreibt man in C++ '\\', also musst du im Code "\\(" stehen haben.
Tuning-Ideen> Nicht QRegExp verwenden, so ähnlich vorgehen wie kater beschrieben hat, einfach von links nach rechts durchgehen:
- klammer auf? pre speichern
- klammer zu? klammerinhalt in liste speichern
- komma oder string-ende erreicht? post speichern; klammerinhalt leer? post in die ergebnisliste packen, ansonsten klammerinhalt durchgehen und zusammen mit pre und post in die ergebnisliste packen
Gruß
FaS
Verfasst: 20. Juni 2011 19:01
von feldmaus
Danke,
ich komme gerade nicht weiter. Ich will das doch so machen wie ursprünglich überlegt. In meiner Funktion nutze ich QStringList.section( QChar::Mark_Enclosing, 1, 1 ) um die Klammerausdrücke zu selektieren. Nun macht er dies nicht, in der QT-Doku steht nicht welche Zeichen mit Mark_Enclosing gemeint sind. Kann mir das Jemand verraten?
Grüße Markus
Verfasst: 21. Juni 2011 13:03
von feldmaus
FaS hat geschrieben:\ Ist ein Escape-Zeichen in C-Strings, das hat nichts mit Qt zu tun! QRegExp braucht \( und \ schreibt man in C++ '\\', also musst du im Code "\\(" stehen haben.
Wenn ich das Whitespace Zeichen nutzen will '\s' muss ich dann auch '\\s' schreiben?
Irgendwie schaffe ich es nicht eine korrekte Liste aus z.b. '(o, a) tenista' zu erhalten. Die Liste die er mir gibt sieht wie folgt aus ["(", "a) tenista"]. Ich habe als Befehl folgenden verwendet:
Code: Alles auswählen
QStringList liste = expr.simplified().split(QRegExp("([^\\(][.\\s]*),"),
QString::SkipEmptyParts);
Dabei soll QRegExp nur Kommas ausserhalb von Klammern selektieren.
Grüße Markus
Verfasst: 22. Juni 2011 22:36
von FaS
Entschuldige meine späte Antwort.
QChar::Mark_Enclosing
Das ist eine Unicode-Kategorie, also nicht was du suchst, Google "Mark Enclosing", erstes Ergebnis. Aber hast du dann wohl selbst gemerkt.
Die Klammern sollten hier überflüssig sein, da keine capturing groups benötigt werden. Also wird Qt in diesem Kontext logsich äquivalent folgendes übergeben:
Wörtlich: (ein Zeichen != Klammer auf), (kein Zeichen oder beliebiger white space), (Komma). Dies trifft auf "o," zu, also diente das in deinem Beispiel als Trenner. Komplexere Selektionen scheinen mit split() nicht möglich.
Ich empfehle immernoch meinen genannten Ansatz, das ist viel einfacher als mit regulären Ausdrücken herumzuwurschteln, und schneller obendrein.
Verfasst: 23. Juni 2011 19:55
von Troll.Soft
moin auch,
ich denke, der von Sowas weiter oben erwähnte Ansatz führt am leichtesten zum Ziel.
tschüß
Troll.Soft