Hallo
ich möchte einen String Zeichen für Zeichen parsen und die analysierten
Zeichen dann abschneiden. Dazu übergebe ich den String einer
Unterfunktion. Dort drin wird der Zeiger "line" auch schön auf das
nächste Zeichen gesetzt, in der Main steht der Zeiger dann (beim 2.
Aufruf) aber wieder am Anfang. Als ob die Unterfunktion nur mit einer
Kopie arbeitet.
Woran könnte das liegen?
panca schrieb:> // ich hätte erwartet, dass danach nur noch ein "ALLO" in line steht.
der Zeiger line wird als Wert übergeben und ist damit eine Kopie.
Entweder den neuen Zeiger als Return zurückgeben oder als Zeiger
übergeben. (ja Zeiger auf Zeiger)
Beachte auch Deine Ungenauigkeit bei der Schreibweise von line und
linie.
Schnapp Dir am besten ein gutes C-Buch und arbeite das systematisch
durch. Dir fehlen Grundlagen.
Wäre ja auch Blödsinn, denn wenn line verändert würde, dann hätte man
keinen gültigen Zeiger mehr auf das 256 Byte Array das unter dem Namen
angelegt wurde.
Du kannst einen 2. Zeiger als returnwert zurückgeben, der auf das in der
Unterfunktion gefundene Zeichen zeigt
char * Foo(char* line) {
char *tmp = line;
....
return tmp;
}
Der Andere schrieb:> Wäre ja auch Blödsinn [...]> char * Foo(char* line) {> char *tmp = line;
Genauso Blödsinn, denn line ist in Foo() lokal und ändert keine
gleichnamigen Variablen außerhalb dieser Funktion.
Sorry ;-)
Frank M. schrieb:> Der Andere schrieb:>> Wäre ja auch Blödsinn [...]>> char * Foo(char* line) {>> char *tmp = line;>> Genauso Blödsinn, denn line ist in Foo() lokal und ändert keine> gleichnamigen Variablen außerhalb dieser Funktion.
Er schrieb, dass der geänderte Zeiger als Rückgabewert bei seinem
Vorschlag zurückgegeben wird.
Der Andere schrieb:> Du kannst einen 2. Zeiger als returnwert zurückgeben, der auf das in der> Unterfunktion gefundene Zeichen zeigt
Steffen R. schrieb:> Er schrieb, dass der geänderte Zeiger als Rückgabewert bei seinem> Vorschlag zurückgegeben wird.
Der geänderte Zeiger muss sogar zurückgegeben werden! Sonst bekommt
main() immer wieder denselben Pointer zurück und bewegt sich kein Stück
vorwärts - egal wie oft Foo() aufgerufen wird.
Es soll aber der komplette String "analysiert" werden. Deshalb muss
Foo() den Pointer hinter dem abgeschnittenen Zeichen zurückliefern,
damit main() damit den Rest des Strings durchlaufen kann.
Ähnlich funktioniert es mit der Standard-Lib-Funktion strchr(), nur muss
man hier das Inkrementieren noch selbst machen, um weiterzukommen, denn
strchr() liefert den Pointer auf das gefundene Zeichen.
Random .. schrieb:> bool Foo(char** line)> {> if (**line== 'A') {> // tuwas> }> *line++; // 1. Zeichen Abschneiden, restlichen String analysieren> return true;> }
Warum erhöhst Du hier unnötig die Komplexität? Was soll ein
Rückgabewert, der immer true ist und den Du zudem in main() komplett
ignorierst? Du kannst doch direkt line als neuen Wert zurückgeben, spart
ein Sternchen. Dann ist der Rückgabewert wenigstens sinnvoll.
Übrigens:
> *line++; // 1. Zeichen Abschneiden, restlichen String analysieren
ist ein Fehler, es muss nämlich bei "char ** line" als Parameter dann
auch heißen:
(*line)++;
Soviel zu Fehlern, die man sich einhandelt, wenn man es unnötig
verkompliziert.
Obs ... Trocken-Coding ...
> Rückgabewert, der immer true ist
zwischendrin gibt es natürlich eine Fehlerbehandlung mit "return false".
Das wollte ich mit dem "return true" anzeigen.
Random .. schrieb:> zwischendrin gibt es natürlich eine Fehlerbehandlung mit "return false".
Ja, wenn es diese tatsächlich gibt (z.B. es gibt kein weiteres Zeichen
'A'), dann wäre es eine sinnvolle Methode. Dann muss man den Fehler aber
auch in der aufrufenden Funktion abfangen und nicht einfach ignorieren
;-)
Die libc-Funktion strchr() machts anders: Sie liefert dann einfach einen
Null-Pointer statt den Pointer auf den Reststring (inkl. 'A') zurück.
Frank M. schrieb:> Genauso Blödsinn, denn line ist in Foo() lokal und ändert keine> gleichnamigen Variablen außerhalb dieser Funktion.>> Sorry ;-)
Dafür gabs zwei Gründe:
Für den Anfänger ist vieleicht einfacher nicht implizit den Zeiger auf
das übergebene Array zu nehmen.
In der Funktion könnte es ja nötig sein, trotzdem noch den Zeiger auf
den Anfang des Arrays zzu haben.
Also hab ich einen extra Zeiger definiert und zugewiesen.
Frank M. schrieb:> Genauso Blödsinn, denn line ist in Foo() lokal und ändert keine> gleichnamigen Variablen außerhalb dieser Funktion.
Ah, jetzt habe ich verstanden was du nicht an meinem Posting verstanden
hast.
Der TO hat die globale Variable
char line[256] = "HALLO";
übergeben und erwartet, daß dieser globale Pointer auf das Array "line"
dann verändert wird.
Du meintest eher die lokale Übergabevariable "line" in Foo()
Der Andere schrieb:> Ah, jetzt habe ich verstanden was du nicht an meinem Posting verstanden> hast.
Du hast die Funktion Foo() nur unvollständig skizziert:
> char * Foo(char* line) {> char *tmp = line;> ....> return tmp;> }
Wie soll man das also allumfänglich verstehen? ;-)
Wo machst Du denn jetzt den abschließenden Increment in Foo()? Mit tmp
oder mit line? Nach Deiner Skizze weiterhin mit line. Dann ruft main()
die Funktion Foo() aber immer mit demselben Pointer auf. Das ist nicht
gerade zielführend.
Am besten schreibst Du mal die komplette Funktion Foo() unter der
Verwendung der tmp-Variablen hin. Dann kann man auch darüber reden.
Frank M. schrieb:> Wie soll man das also allumfänglich verstehen? ;-)
Wo ist der Grund, daß ich den Rest der Funktion des TO nochmal
abschreiben soll.
Ausserdem wollte ich einen Hinweis geben, und nicht eine vollständige
Lösung zu dem noch nicht mal bekannten wirklichen Problems des TO
hinschreiben.
Denn dann schreibt er ab und lernt nichts daraus.
Aber wenn du das machen möchtest, bitte schön :-)
Der Andere schrieb:> Wo ist der Grund, daß ich den Rest der Funktion des TO nochmal> abschreiben soll.
Okay, dann mache ich das mal für Dich. Das Ergebnis wäre dann:
1) line++ am Ende hat weiterhin null Effekt.
2) Es wird der Original-Pointer wieder zurückgegeben, ein wiederholter
Aufruf von Foo(line), wie es der TO will, führt nur dazu, dass
Foo() immer wieder denselben Teil von line durchackert, ohne recht
vorwärtszukommen.
> Denn dann schreibt er ab und lernt nichts daraus.
Der Lerneffekt Deiner Funktionsskizze ist leider Null.
Nimm C++. Da gibt es std::string mit entsprechenden Funktionen. Und den
String einfach als Referenz übergeben, da wird dann in der Funktion
keine Kopie sondern das Original geändert.
Kostet zwar Platz und Rechenzeit, aber man braucht nicht denken.
Random .. schrieb:> Richtig wäre:> char* Foo(char* line)
Ja, zum Beispiel :-)
Deshalb schrieb ich ja schon ganz weit oben:
Frank M. schrieb:> So wird ein Schuh daraus:> char * Foo(char* str)
Aber trotzdem: die Berichtigung syntaktischer Fehler reicht hier bei
weitem nicht.
> Schnapp Dir am besten ein gutes C-Buch und arbeite das systematisch> durch. Dir fehlen Grundlagen.
Ich war mir schon beim Schreiben der Überschrift sicher, dass wieder
diese blöde Antwort kommt. Warum wird bei C Fragen immer auf das Buch
verwiesen?
Ich hab 4 C Bücher hier. Galileo Press und K&R. Und hatte die vor Jahren
auch durch, aber trotzdem hat mich das konrete Beispiel verwirrt.
panca schrieb:> Ich war mir schon beim Schreiben der Überschrift sicher, dass wieder> diese blöde Antwort kommt. Warum wird bei C Fragen immer auf das Buch> verwiesen?
Weil du einer Idee nachläufst, die nicht wirklich nachvollziehbar
aussieht und bei den Anderen eher verständnisloses Kopfschütteln
verursacht. Ich verstehe den Sinn deiner Zeilen auch nicht, denn du
willst was parsen und das offenbar einzeln für jedes Zeichen einzeln -
wozu?
Wenn es das ist, was du vorhast, warum erwartest du dann, daß aus deinem
HALLO ein ALLO wird?
Also, in den meisten Fällen wollen die Leute eine Zeichenkette nach
Token auseinandernehmen. Das bedeutet, daß man 1. Leerzeichen übergeht,
2. die an der dann aktuellen Stelle anstehenden Zeichen mit einem
zweiten String vergleicht und 3. (zumeist) auf ein nachfolgendes
Trennzeichen abtestet.
Also sowas wie "if (PI*Ottokar) soll dann die Tokens
if
Klammerauf
PI
mal
Ottokar
Klammerzu
ergeben. Und das Leerzeichen nach if wird übergangen.
Also: Drücke dein Problem lieber so aus, daß man den Wunsch dahinter
verstehen kann.
W.S.
Naja, manchmal schadet es nicht wenn man sich nochmals den K&R
reinzieht, den hast du dann eh in 1 Stunde durch.
Zu diesen Thema würde ich dir auch Literatur zu Regulär Ausdrücke,
Endliche Automaten und Kontextfrei Sprachen empfehlen.
Das Drachenbuch:
Compilerbau 1 + 2 von Alfed V. Aho/Ravi Sethi/Jeffrey D. Ullmann
Grundlagen der Theoretischen Infromatik mit Anwendungen Gottfied Vossen
/Kurt Ulrich Witt
Dazu solltest du dann flex und bison kennen lernen.