Problem: fgets() und die Schleife
-
Servus,
Ich bin noch relativ neu in der C Programmierung und bräuchte mal einen kleinen Denkanstoß, deswegen entschuldige ich mich schonmal für den "unsauberen" Style. Dies ist bestimmt nicht der erste Thread zu meinem Problem, aber in meinem C-Programm geschehen unerklärliche Dinge. Habe schon einige Foren durchkämmt aber noch keine präzise Antwort zu meinem Problem gefunden:Ich möchte eine String Liste mit Hilfe der stdin füllen und dann Alphabetisch sortieren. In der Funktion createStringList() findet die Hauptarbeit statt. Bei der Ausführung des Programms überspringt er mir stehst die erste Eingabe und schreibt mir irgend ein Müll in den ersten String, auch das Löschen des Puffers führt zu merkwürdigen Ereignisse, vielleicht weiß jemand von euch Rat.
/* return the number of the single strings by using standard in */ int getNumStr(void) { int numStr = 0; do { (void) printf("Insert a size for the String List between 1 and 1024:\n"); scanf("%d", &numStr); } while(numStr < 1 && numStr > 1024); return numStr; } /* creates a String List and fills it by using std in */ char **createStringList(int numberOfStrings) { int lv; char **stringList = malloc(numberOfStrings * sizeof(char)); if(stringList == NULL) { (void) printf("Allocation of Memory failed!\n"); exit(EXIT_FAILURE); } /* fflush(stdin); getchar(); */ for(lv = 0; lv < numberOfStrings; lv++) { stringList[lv] = calloc(SINGLE_STRING_SIZE, sizeof(char)); if(stringList[lv] == NULL) { (void) printf("Allocation of Memory failed!\n"); exit(EXIT_FAILURE); } (void) printf("Insert your %d. String:\n", lv + 1); stringList[lv] = fgets(stringList[lv], SINGLE_STRING_SIZE, stdin); } (void) printf("\n\n"); return stringList; }
ohne das fflush(stdin);getChar(); wird die erste Eingabe immer übersprungen:
Insert a size for the String List between 1 and 1024: 5 Insert your 1. String: Insert your 2. String: asdf Insert your 3. String: sdfg Insert your 4. String: fjghjg Insert your 5. String: efdf Unsorted StringList: asdf sdfg fjghjg efdf Sorted StringList: ?asdf efdf fjghjg sdfg
und mit:
alexanders-mbp:Aufgabe2 afrat001$ ./String_Sort Insert a size for the String List between 1 and 1024: 5 Insert your 1. String: asad Insert your 2. String: gdfd Insert your 3. String: rtzr Insert your 4. String: cvbcv Insert your 5. String: sdfs Unsorted StringList: `gdfd rtzr cvbcv sdfs Sorted StringList: cvbcv gdfd rtzr sdfs
ich verstehe leider nicht Genau was da vor sich geht (Geist in der Maschine oder meine Dummheit)
danke schonmal
-
Ich habe dein Programm nicht durchgesehen, aber ...
scanf
lässt alle Zeichen die nicht zu dem FOrmatspecifier passen im Eingabestrom stehen. Dazu gehört auch das '\n' von der Entertaste.
fgets
liest dies ein und beendet damit die erste Eingabe.
Probier malscanf("%d ", &numStr); ^ mit dem Leerzeichen nach dem d
... was ich doch gesehen habe ist char **stringList = malloc(numberOfStrings * sizeof(char));
Da passt was nicht. Denn du berechnest Platz fürchar
und bekommst somit einen (einfachen) Zieger aufchar
. stringList ist aber ein Doppelzeiger.
Du willst dachar **stringList = malloc(numberOfStrings * sizeof(char*));
-
afrat001 schrieb:
ohne das fflush(stdin);getChar(); wird die erste Eingabe immer übersprungen:
fflush mit stdin ist Anfängermüll, das hast du von zweifelhaften Quellen abgeschrieben.
afrat001 schrieb:
ich verstehe leider nicht Genau was da vor sich geht (Geist in der Maschine oder meine Dummheit)
Der Compiler hat immer recht, ergo?
-
Ich mag den Jürgen Wolf zwar nicht, aber hier hatta wohl mal recht:
Jürgen Wolf schrieb:
In diesem Beispiel wurde als erster Buchstabe »a« eingegeben und Taste Enter gedrückt. Dieses Taste Enter (ASCII-Code = 10 = \n = newline) befindet sich immer noch im Puffer der Standardeingabe und wird automatisch für das zweite Zeichen verwendet.
Drei Möglichkeiten haste:
1. fflush (das ist aber kacke).
2. Inner Schleife so lange Zeichen vom Eingabestrom holen, bis die Zeilenumbrüche weg sind.
3. fgets mit sscanf.Siehe auch: http://openbook.galileocomputing.de/c_von_a_bis_z/004_c_ein_ausgabe_001.htm
@Wutz: nicht immer, oh nein. Ich könnte da Geschichten erzählen, wo der Linker und der Compiler sich gegenseitig in die Fresse geschlagen haben und Code produziert haben, der gut läuft, solange nur im 32-Bit-Bereich gearbeitet wird - aber das ist eine andere Geschichte
-
Inputputter schrieb:
Ich mag den Jürgen Wolf zwar nicht, aber hier hatta wohl mal recht:....
Die Aussage stimmt, aber die Lösungen dafür sind nicht gut.
Die beste Möglichkeit hat der Herr Wolf nicht genannt.
Ein Leerzeichen im Formatstring vor dem %c:printf("2. Buchstabe : "); scanf(" %c",&b);
Was das Leerzeichen bedeutet, kannst du gerne selber nachlesen.
Aber nicht bei Wolf, sondern z.B: http://www.cplusplus.com/reference/cstdio/scanf/ oder http://en.cppreference.com/w/c/io/fscanf
-
Danke, jetzt is alles klar, habe nicht weit genug gedacht. Der Fehler kommt vom vorherigen scanf, habe an der falschen stelle nach einem Fehler gesucht. Und natürlich den sizeof(char*) auch ein grober Schnitzer. Danke für die schnelle Antwort.
-
} while(numStr < 1 && numStr > 1024);
Diese Bedingung ist nie erfüllt.
-
Wo hast du eigentlich das
(void)
vor demprintf
her?
-
Mein prof in Algorithmen legt sehr viel Wert auf so einen Stil, es ist dafür da um zu zeigen, das die printf Funktion eigentlich einen Rückgabewert hat, diesen aber verwerfen soll. Und ich denke mir halt wenn mans eh erst lernt kann man es sich auf direkt angewöhnen.
-
Dein prof hat keine Ahnung.
Irgendetwas wegzucasten nur um Compilermeldungen zu vermeiden oder solche Casts gar zu (wohlwollend formuliert) Dokumentationszwecken zu verwenden, ist purer Dilettantismus.
Immer, und in jeder Programmiersprache.
Dein prof hat keine Ahnung.
-
afrat001 schrieb:
Mein prof in Algorithmen legt sehr viel Wert auf so einen Stil, es ist dafür da um zu zeigen, das die printf Funktion eigentlich einen Rückgabewert hat, diesen aber verwerfen soll. Und ich denke mir halt wenn mans eh erst lernt kann man es sich auf direkt angewöhnen.
Das fehlt dann aber an einigen Stellen, z.B. bei scanf, bei lv++ und überhaupt bei jeder Zuweisung. Die haben auch Rückgabewerte, die du ignorierst. Besser aber du ignorierst solche Tipps. Professoren sind meistens auch nicht gerade die Überprogrammierer, insbesondere was praktische Dinge wie Stil angeht.
-
Ja dann hab ichs da wohl vergessen, gut zu wissen. Mache mir erst Gedanken um den Stil wenn ichs richtig drauf habe solange akzeptiere ich so etwas eben. Außerdem bekommt man eh von jedem andere vorgaben von daher muss ich es sowieso dieses Semester so machen, vll will ein anderer Prof nächstes Semester was anderes.