Aus Konsole einlesen
-
Hallo Leute!
Bin noch C-Anfänger und habe eine grundlegende Verständisfrage:
Wenn ich nun von der Konsole einlese und dies dann in einem char speichere, also z.B. sowas:
char data[128]; printf("Eingabe: ") gets(data);
Wie kann ich dann verhindern, dass, wenn z.B. jemand 200 Zeichen eingibt, mein Proramm crasht, weil eben für mein char nur 128 Zeichen reserviert sind??
Auch wenn ich die Zeichenanzahl erhöhe, gibt es ja immer eine Grenze, ab wann es zu einem Überlauf kommt, oder bin ich da jetzt komplett daneben?
-
Mit
fgets
kannst du eine Obergrenze angeben. Als "Datei" gibst du dannstdin
, also den Filedeskriptor der Standardeingabe, an.
-
In dem du andere Funktionen nimmst, an denen du die Größe deines Feldes übergeben kannst.
Z.B fgetsfgets(data,128,stdin);
fgets liest das Zeilenendezeichen '\n' (von der Entertaste) mit ein.
oder scanf. Der [] Specifier liest alle angegebenen Zeichen ein. Das ^ negiert die Auswahl.
scanf("%127[^\n]", data);
liest alle Zeichen bis zum auftreten von '\n', aber maximal 127 Zeichen ein.
Das '\n' steht dann aber noch im Eingabestrom und muss da noch irgendwie abgeholt werden: http://www.c-plusplus.net/forum/p1146014#1146014
-
danke erstmals!
hab mir das mit dem tastaturbuffer leeren mal angesehen, allerdings versteh ich die vorgeschlagene "alternative" für fflush(stdin) nicht ganz:
int c; // int c, nicht char c. while ((c = getchar()) != EOF && c != '\n'); // kein {} block, stimmt so
wo ist hier dann die anweisung, wenn der {} Block fehlt, bzw. was soll solange gemacht werden, bis ein EOF oder ein newline kommt?
-
Das getchar() im Schleifenkopf selbst macht hier die Arbeit.
Außerdem machst du dir das Leben viel zu schwer. Du weißt ja schon, dass das nächste zeichen ein newline ist (falls du scanf und nicht fgets benutzt). Je nachdem was für eine Leseaktion als nächstes folgt brauchst du es noch nicht einmal auszulesen, da z.B. scanf standardmäßig whitespaces ignoriert.
-
OK, wenn ich also einlese und die '\n' nicht berücksichtige, kann ich sozusagen auch Sätze mit Leerzeichen auf einmal einlesen.
Mit meinem Programm möchte ich von der Konsole einlesen und das Eingelesene dann über TCP/IP an einen Server weiterleiten. Mit
scanf("%127[^\n]", data); while ((c = getchar()) != EOF && c != '\n');
funktioniert das Einlesen und Abspeichern in ein 128 Byte Array soweit, allerdings habe ich das Problem, dass, wenn z.B. nur die Entertaste gedrückt wird, immer noch das zuvor eingelesene gesendet wird. Ich möchte hier allerings, dass nur gesendet wird, wenn auch wirklich etwas (also nicht nur ein Enter) eingegeben wurde.
So funktioniert es zwar, allerdings kann ich dann keine Whitespaces mehr miteinlesen, d.h. senden:
scanf("%127s]", data); while ((c = getchar()) != EOF && c != '\n');
-
#include <stdio.h> #include <string.h> int main() { char text[128]; while (!feof(stdin) && puts("Bitte Textzeile eingeben:")) if (fgets(text, sizeof(text), stdin)) { unsigned len = strlen(text); printf("Eingegebener Text(mit Zeilenumbruch): %s" , text); if (text[len-1] == '\n') text[len-1] = 0; printf("Eingegebener Text(ohne Zeilenumbruch): %s\n" , text); } }
Dieses Programm verwirft keine halben Zeilen sondern liest bei Zeilen über 128 Zeichen den Rest der Zeile als nächste Zeile. Kann man natürlich auch anders machen, aber ich nahm mal ganz stark an, dass du hier keine Benutzereingaben verwerfen möchtest.
-
wenn ich dein programm so kompiliere, lässt er mich aber nichts eingeben sondern terminiert gleich...?
-
Das kann ich nicht nachvollziehen. Dann wäre stdin und/oder stdout bei dir gar nicht verfügbar.
-
... oder puts() liefert 0 zurück.
-
DirkB schrieb:
... oder puts() liefert 0 zurück.
Ach Mist! Klar, das wird es sein. "Non-negative" schließt ja eine Null nicht aus. Ich mache einfach zu viel C++.
Also entweder:
while (!feof(stdin) && puts("Bitte Textzeile eingeben:") > 0)
oder einfach ohne solche Hacks:
while (!feof(stdin)) { puts("Bitte Textzeile eingeben:"); if (fgets(text, sizeof(text), stdin)) { unsigned len = strlen(text); printf("Eingegebener Text(mit Zeilenumbruch): %s" , text); if (text[len-1] == '\n') text[len-1] = 0; printf("Eingegebener Text(ohne Zeilenumbruch): %s\n" , text); } }
-
SeppJ schrieb:
Ach Mist! Klar, das wird es sein. "Non-negative" schließt ja eine Null nicht aus. Ich mache einfach zu viel C++.
Also entweder:
while (!feof(stdin) && puts("Bitte Textzeile eingeben:") > 0)
Wäre da ein >= nicht angebrachter?
Doch lieber ohne Hack
-
ich hab jetzt mal ein Minimalbeispiel erstellt, um grundlegend zu zeigen, wie ich es momentan implementiert habe:
#include <stdio.h> #include <string.h> int main() { char data[128]; int c; while (1) { printf("Eingabe: "); scanf("%127[^\n]", data); while ((c = getchar()) != EOF && c != '\n'); printf ("Gesendet: %s\n", data); } }
Das Ganze funktioniert soweit, allerdings nimmt er immer den zuletzt eingegebenen Inhalt und sendet diesen. Soll heißen, wenn ich z.B. "xy" eingebe und beim nächsten Durchlauf nur Enter drücke, sendet er trotzdem "xy". Ohne dem [^\n] allerdings kann ich keine Leerzeichen einlesen...
-
Nun, scanf ändert nichts an der Variablen, wenn nichts eingelesen wurde.
Du kannst den Rückgabewert von scanf auswerten.
Darin steht, wieviel Parameter scanf erfolgreich lesen konnte. siehe: http://www.cplusplus.com/reference/clibrary/cstdio/scanf/if (1 == scanf("%127[^\n]", data)) printf ("Gesendet: %s\n", data); while ((c = getchar()) != EOF && c != '\n');
oder so ähnlich.
-
danke, die Lösung gefällt mir gut!
-
SeppJ schrieb:
while (!feof(stdin)) { ; if (fgets(text, sizeof(text), stdin)) }
Das feof ist hier redundant, fgets selbst prüft dies schon und es prüft noch mehr, nämlich auch evtl. Einlesefehler.
Also wennschon, dannwhile( puts("Bitte Textzeile eingeben:"), fgets(text, sizeof(text), stdin) ) { ... }