NSScanner
-
-
Alles anzeigen
Quellcode
- if([scanner scanString:@"clrmamepro" intoString:nil])
- {
- NSString *name, *description, *category, *version, *author;
- [fileTypeTF setStringValue:[NSString stringWithFormat:@"ClrMamePro"]];
- [scanner scanString:@"name \"" intoString:nil];
- [scanner scanUpToCharactersFromSet:klammerSet intoString:&name];
- [fileNameTF setStringValue:[NSString stringWithFormat:@"%@", name]];
- [scanner scanString:@"description \"" intoString:nil];
- [scanner scanUpToString:@"\"" intoString:&description];
- [fileDescriptionTF setStringValue:[NSString stringWithFormat:@"%@", description]]
- }
in Zeile 8 bekomme ich den SIGSEGV.
und die zu parsende Datei:
[/quote]
Aha,
das ist m.E. doch eindeutig was da passiert.
* Du liest erst mal bis name "
* dann bis das Ganze mit klammerSet beendet wird (das ist das zweite " hinter PH GBA"
* und dann passiert es: der scanner bleibt auf dem zweiten " stehen
* und findet KEIN description ", bleibt also wieder stehen - weil scanUpToCharactersFromSet: das Abbruchzeichen nicht mitliest
* und versucht dann bis zu einem " zu lesen - und viola, da steht er ja!
* und genau deshalb hat er beim scanUpToString:@"\"" genau 0 Zeichen gelesen und verändert die Variable description nicht
* die ist auf dem Stack und deshalb eher zufällig initialisiert
* das führt oft (aber nicht immer) zu einem SIGSEGV
* und es kann v.a. davon abhängen was zuvor auf dem Stack steht. Wenn das zufällig eine Uhrzeit ist, dann hängt es von der Sekunde ab in der man es ausführt. Wenn es ein Datum ist gehts am Dienstag nicht

Vorschlag zur Lösung
* scanString:"\"" intoString:NULL hinter den scanUpTo...
* und alle Variablen die an intoString: gehen mit =@"" initialisieren
* immer mit if() abfragen, ob die Daten tatsächlich gescannt wurden und eine Fehlermeldung ausgeben - denn lt. Murphy geht es 2 Jahre gut und dann speist mal jemand eine falsche Datei ein...
-- hns -
Das war das, was ich auch geschrieben hatte. Nur stimmt das nicht. Er gibt als Pattern @"description \"" an. NSScanner _soll_ wenigstens lesen, bis dieses Pattern irgendwann noch einmal im Stream auftaucht. Ob es teilweise bereits aufgetaucht ist, _sollte_ keine Rolle spielen.Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
Die grundsätzliche Richtung stimmt - auf jeden Fall liest der scanUpToCharactersFromSet: nichts, gibt NO zurück und lässt die NSString-Pointer unverändert, also uninitialisiert, was dann das TextField nicht mag.
Nur hakt das Teil an einer anderen Stelle: scanString: intoString: liest nur dann, wenn der Scanner bereits an der Stelle ist, wo der String auftaucht. Wenn man bis hinter eine bestimmte Stelle scannen will (was hier offensichtlich passieren soll), kann man erst [scanUpToString:marker :NULL] und dann [scanString:marker :NULL] verwenden. Und, wie hns bereits sagte, immer nur das Ergebnis von intoString nehmen, wenn die entsprechende scan-Methode YES zurückgibt.
@tom: Danke für die ausgiebige Revision meines Codes, aber damit gab's gar kein Problem
Über Coding conventions kann man gerne mal in 'nem anderen Thread diskutieren, ich finde ifs so äußerst schön... Multigrad - 360°-Produktfotografie für den Mac -
Aha mattik, das erklärt einiges
Dacht scanString liest solange bis er den entsprechenden String gefunden hat, so stehts aber auch in der Doku:
- (BOOL)scanString:(NSString *)string intoString:(NSString **)stringValue
Scans for string and, if a match is found, returns an equivalent string object by reference in stringValue. Returns YES if stringValue matches the characters at the scan location; otherwise returns NO.
Invoke this method with nil as stringValue to simply scan past a given string.
Zumindest klingt das für mich so als würde der solange suchen bis der string gefunden wurde.
Was macht denn [scanUpToString:marker :NULL]?
Und wieso schreibst du immer NULL statt nil? Gibt es da einen unterschied? -
@tom: Danke für die ausgiebige Revision meines Codes, aber damit gab's gar kein Problem
Ja, hatte schon gesehen, dass ich euch verwechselt habe.
Nein, es gab damit ein Problem. Soll ich dir mal eine Datei schicken, die das zum Absturz bringt? Du willst doch nicht, dass die Dateien deiner App zukünftig in der Liste der gefährlichen Schädlinge auftauchen?
Über Coding conventions kann man gerne mal in 'nem anderen Thread diskutieren, ich finde ifs so äußerst schön...
? Wie machst du denn Verzweigungen?
Nur hakt das Teil an einer anderen Stelle: scanString: intoString: liest nur dann, wenn der Scanner bereits an der Stelle ist, wo der String auftaucht. Wenn man bis hinter eine bestimmte Stelle scannen will (was hier offensichtlich passieren soll), kann man erst [scanUpToString:marker :NULL] und dann [scanString:marker :NULL] verwenden.
So bin ich früher auch immer vorgegangen. Ich hatte mich erst "herangerobbt". Aufgrund dieses Trheads habe ich aber mal in die Doku geschaut und anderes gefunden:
"Scans for string and, if a match is found, returns ..."
Oder hat sich da etwas seit .4 geändert?Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
Original von Tom9811
Trheads habe ich aber mal in die Doku geschaut und anderes gefunden:
"Scans for string and, if a match is found, returns ..."
Und gleich im nächsten Satz steht:
"Returns YES if stringValue matches the characters at the scan location; otherwise returns NO."
Michael -
Ja, das beschreibt den Rückgabewert, den er gar nicht verwendet. Gerade deshalb (weil es im zweiten Satz ausdrücklich erwähnt wird), muss man davon ausgehen, dass der erste Satz diese Einschränkung nicht enthält.
Ich mache heute abend mal ein paar Testläufe.Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
Bin mir jetzt nicht mehr wirklich sicher warum aber habs jetzt geschafft bis zur Version zu kommen.
Jetzt macht aber die Version ärger und ich weiß nicht warum.
Alles anzeigenQuellcode
- if([scanner scanString:@"clrmamepro (" intoString:nil])
- {
- NSString *name, *description, *category, *version, *author, *check;
- [fileTypeTF setStringValue:[NSString stringWithFormat:@"ClrMamePro"]];
- if([scanner scanString:@"name " intoString:nil])
- {
- [scanner scanUpToCharactersFromSet:letterSet intoString:&check];
- i=0;
- do
- {
- if([check characterAtIndex:i] =='"')
- {
- [scanner scanUpToString:@"\"" intoString:&name];
- [scanner scanString:@"\"" intoString:nil];
- }
- else
- {
- [scanner scanCharactersFromSet:letterSet intoString:&name];
- }
- i++;
- }
- while([check characterAtIndex:i-1] != '"' && i<=[check length]);
- [fileNameTF setStringValue:[NSString stringWithFormat:@"%@", name]];
- }
- else
- {
- NSLog(@"Fehler bei Name");
- }
- if([scanner scanString:@"description " intoString:nil])
- {
- [scanner scanUpToCharactersFromSet:letterSet intoString:&check];
- i=0;
- do
- {
- if([check characterAtIndex:i] =='"')
- {
- [scanner scanUpToString:@"\"" intoString:&description];
- [scanner scanString:@"\"" intoString:nil];
- }
- else
- {
- [scanner scanCharactersFromSet:letterSet intoString:&description];
- }
- i++;
- }
- while([check characterAtIndex:i-1] != '"' && i<=[check length]);
- [fileDescriptionTF setStringValue:[NSString stringWithFormat:@"%@", description]];
- }
- else
- {
- NSLog(@"Fehler bei Description");
- }
- if([scanner scanString:@"category " intoString:nil])
- {
- [scanner scanUpToCharactersFromSet:letterSet intoString:&check];
- i=0;
- do
- {
- if([check characterAtIndex:i] =='"')
- {
- [scanner scanUpToString:@"\"" intoString:&category];
- [scanner scanString:@"\"" intoString:nil];
- }
- else
- {
- [scanner scanCharactersFromSet:letterSet intoString:&category];
- }
- i++;
- }
- while([check characterAtIndex:i-1] != '"' && i<=[check length]);
- [fileCategoryTF setStringValue:[NSString stringWithFormat:@"%@", category]];
- }
- else
- {
- NSLog(@"Fehler bei Category");
- }
- if([scanner scanString:@"version " intoString:nil])
- {
- [scanner scanUpToCharactersFromSet:letterSet intoString:&check];
- i=0;
- do
- {
- if([check characterAtIndex:i] =='"')
- {
- [scanner scanUpToString:@"\"" intoString:&version];
- [scanner scanString:@"\"" intoString:nil];
- }
- else
- {
- [scanner scanCharactersFromSet:letterSet intoString:&version];
- }
- i++;
- }
- while([check characterAtIndex:i-1] != '"' && i<=[check length]);
- [fileVersionTF setStringValue:[NSString stringWithFormat:@"%@", name]];
- }
- else
- {
- NSLog(@"Fehler bei Version");
- }
- }
Wie ihr vielleicht erkennen könnt habe ich jetzt ständig den selben code, kann ich da eigentlich die TextFields auch über ints ansprechen so dass ich den Code nur einmal habe und dann je nachdem wie oft das gelaufen ist ein anderes TextField anzusprechen. Würde ein paar Variablen sparen und das ganze auch flexibler machen.
Ich verstehe jetzt nur nicht wieso er mir Fehler bei Version ausgibt. Ist doch dasselbe wie oben drüber auch. Der Fehler müsste diesmal ja bei Category stecken aber hab das auch schon mehrmals kontrolliert, ist immer dasselbe wie oben drüber auch nur in andere Strings gespeichert. -
Michael weist zutreffend darauf hin, dass der Rückgabewert nur dann YES ist, wenn er den String exakt an dieser Stelle findet. Wenn du also jedesmal das Ergebnis abfragen möchtest, dann musst du dich erst an diese Stelle "heranrobben", dann den String lesen ...
Ich verstehe die Doku so:
Wenn du einen scanString schickst, sucht er sich die nächste Stelle, an der der String auftaucht und "überliest" den String. Ansonsten würde der zweite Parameter ja auch überhaupt keinen Sinn ergeben. Da stünde ja immer der übergebene String drin.
Er gibt aber nur dann ein YES zurück, wenn du bereits an der richtigen Stelle warst.Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
Ja, er scheint dabei aber die whitespaces zu ignorieren, dadurch bin ich dann schon an der richtigen Stelle. Sonst würden die anderen (name, description, category) ja auch nicht funktionieren. Mache bei version nichts anders.
-
-
Original von Tom9811
Michael weist zutreffend darauf hin, dass der Rückgabewert nur dann YES ist, wenn er den String exakt an dieser Stelle findet.
Außer es sind, wie MetalSnake anmerkte, zwischen der scanLocation und dem zu scannenen String Whitespace-Characters bzw. Zeichen, die man mit -setCharactersToBeSkipped: festgelegt hat. Die werden dann überlesen. Habe ich gerade noch mal ausprobiert.
Grundsätzlich gilt aber, dass der "foundString" nur das Erwartete enthält, wenn die Methode YES zurückgibt.
Michael -
Original von MetalSnake
Ich verstehe jetzt nur nicht wieso er mir Fehler bei Version ausgibt. Ist doch dasselbe wie oben drüber auch. Der Fehler müsste diesmal ja bei Category stecken aber hab das auch schon mehrmals kontrolliert, ist immer dasselbe wie oben drüber auch nur in andere Strings gespeichert.
Manchmal wird man "betriebsblind". :] In Zeile 100 müsste wohl statt "name" "version" stehen. Aber warum arbeitest Du immer mit -stringWithFormat:? Schreib doch einfach:
Michael -
@Michael: Den Fehler hatte ich inzwischen auch schon gefunden aber das wäre mir schon aufgefallen wenn er in das TextField überhaupt was geschrieben hätte

Hab noch ein paar Fehler entdeckt, habe jetzt das letterSet auf alphanumericCharacterSet umgestellt damit auch die Zahlen erkannt werden.
Version klappt mittlerweile auch, außer die Ausstiegsbedingung. Werd den Code jetzt erstmal wieder aufräumen (zuviel NSLogs und auskommentierte Dinge drin) dann nochmal alles durchgehen, pause machen, nochmal alles durchgehen und gegebenenfalls wieder hier rein stellen
-
Ist die Frage, was man erwartet. Wie gesagt: Früher habe ich mich auch "herangerobbt", also erst bis zum Match gelesen und dann den Match. Aber es ist wohl nicht erforderlich. YES wird allerdings nicht retuniert.
Zum Beitrag unten (set und stringWithFormat) Das hatte ich ihm auch schon gesagt. Keine Ahnung, warum er das drin lassen will.Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
Original von Tom9811
Ist die Frage, was man erwartet.
Na, bei der Methode erwartet man wohl, dass der gesuchte String dann auch indirekt zurück gegeben wird.
Original von Tom9811
Wie gesagt: Früher habe ich mich auch "herangerobbt", also erst bis zum Match gelesen und dann den Match. Aber es ist wohl nicht erforderlich.
So lange man sicher ist, dass von der aktuellen -scanLocation aus bis zum gesuchten String nur -charactersToBeSkipped dazwischen sind, ist es nicht erforderlich. Sobald aber auch nur ein einziges anderes Zeichen dazwischen hängt, klappt es nicht mehr.
Original von Tom9811
YES wird allerdings nicht retuniert.
Doch wird es. Du wolltest doch Testläufe machen. Ich habe welche gemacht. Wenn der gesuchte String gefunden und zurück gegeben wird, gibt es YES zurück, sonst NO. Das bedeutet allerdings, dass die Dokumentation da zumindest ungenau, wenn nicht gar falsch ist. Ich sollte doch mal die neueste Dokumentation laden. Vielleicht ist es da schon korrigiert.
Michael -
So bin grad wieder zurück gekommen, wofür ich die do-while Schleifen drin hatte weiß ich auch nicht mehr genau, wollte eigentlich den check String durchgehen und gucken ob ein Anführungszeichen drin ist, aber die Schleife scheint überflüssig zu sein.
Die Version hab ich jetzt jedenfalls auch drin, Author werde ich dann gleich machen. auf anhieb hats mal wieder nicht geklappt aber hab mir das jetzt noch nicht wirklich angeguckt.
stringWithFormat benutze ich weil es das erste war was ich damals gefunden hatte als ich wissen wollte wie man was in TextFields schreibt. Hätte dass denn irgendeinen Vorteil wenn ich nur setStringValue schreibe?
@Tom früher hast du dich auch herangerobbt, so wie ich jetzt? Wie machst du das denn heute?
@Michael ich habe die aktuelle Doku und da stehts so drin wie ich es weiter oben schon eingefügt hatte, also scheinbar nicht geändert.
update: Hab statt des alphaNummericCharacterSets jetzt einen eigenen erstellt mit folgenden Zeichen:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzäöüÄÖÜß1234567890()
und schon klappt auch der author, der hatte sich noch an der letzten Klammer bei der Version festgehangen.
Was ist mit meiner Frage weiter oben:
kann ich da eigentlich die TextFields auch über ints ansprechen so dass ich den Code nur einmal habe und dann je nachdem wie oft das gelaufen ist ein anderes TextField anspreche?
update2: Bin mit dem Parsen jetzt fast fertig
Es fehlt nur noch eine Kleinigkeit, und zwar habe ich mit scanHexInt eine hex Zahl aus der Datei gelesen und die in einem unsigned int gespeichert, nun will ich diese Zahl in ein NSMutableArray hinzufügen. Bei Strings klappt es ja wunderbar mit addObject, aber die Zahl will er nicht annehmen. Da bekomme ich dann:
warning: passing argument 1 of 'addObject:' makes pointer from integer without a cast
Als was soll ich das denn casten?
Oder wäre es besser wenn ich die Hex Zahl gleich als String einlese und dann erst später wenn ich es aus dem Array wieder raushole in ein hex wandle?
Mir würds ja besser gefallen wenn ich es gleich als Zahl im Array speichern könnte. Hätte auch einen Lerneffekt, Strings in Arrays speichern kann ich ja schon.
-
Na, bei der Methode erwartet man wohl, dass der gesuchte String dann auch indirekt zurück gegeben wird.
Naja, den habe ich -bis auf die skipped- ja schon. Ich fände es sinnvoller, wenn ich den dazwischenliegenden String belkäme. Den kenne ich immerhin noch nicht.
So lange man sicher ist, dass von der aktuellen -scanLocation aus bis zum gesuchten String nur -charactersToBeSkipped dazwischen sind, ist es nicht erforderlich. Sobald aber auch nur ein einziges anderes Zeichen dazwischen hängt, klappt es nicht mehr.
Jepp, daskann ich nachvollziehen.
Text = "Dies ist ein Text"
Scan "Dies" -> "Dies"
Scan "ein" -> Es steht noch "Dies" im String.
Doch wird es. Du wolltest doch Testläufe machen.
Konnte ich leider erst heute morgen machen, nachdem meine Freundin ihre USt-Voranmeldung erstellen musste. Dabei stellte sich mir gleich noch eine Frage: Wieso muss sie dazu im Internet auf Seiten surfen, die Angebote für Bikinis enthalten? Ich habe sie besser nicht gefragt.
Ich habe welche gemacht. Wenn der gesuchte String gefunden und zurück gegeben wird, gibt es YES zurück, sonst NO. Das bedeutet allerdings, dass die Dokumentation da zumindest ungenau, wenn nicht gar falsch ist.
Sie ist definitiv falsch.
Ich sollte doch mal die neueste Dokumentation laden. Vielleicht ist es da schon korrigiert.
Ich müsste eigentlich die neueste haben und dort steht es noch so, wie ich es beschrieb und du es offenbar auch stehen hast.Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"? -
@Tom früher hast du dich auch herangerobbt, so wie ich jetzt? Wie machst du das denn heute?
Seit dem 11.07.05 20:48 hatte ich das Problem noch nicht:
So bin ich früher auch immer vorgegangen. Ich hatte mich erst "herangerobbt". Aufgrund dieses Trheads habe ich aber mal in die Doku geschaut und anderes gefunden:
"Scans for string and, if a match is found, returns ..."
Aber ich werde es zukünftig ach nicht so machen, da offenbar die Doku fehlerhaft ist. Er vehält sich entgegen der Doku so, wie ich es früher gemacht habe. (Wobei ich beim besten Willen nicht sagen kann, ob ich das damals gestetst habe oder einfach vorsichtig war. Ich hatte auch einen Kampf mit NSScanner.)Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?