Verwenden Sie den folgenden Code:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Ein Benutzer kann seinen Namen eingeben, aber wenn er einen Namen mit einem Leerzeichen wie eingibt Lucas Aardvark
, wird danach scanf()
einfach alles abgeschnitten Lucas
. Wie scanf()
erlaube ich Leerzeichen?
sizeof(char) + 256
war ein Tippfehler.Antworten:
Personen (und insbesondere Anfänger) sollten niemals
scanf("%s")
odergets()
andere Funktionen verwenden, die keinen Pufferüberlaufschutz haben, es sei denn, Sie wissen mit Sicherheit, dass die Eingabe immer ein bestimmtes Format hat (und möglicherweise auch dann nicht).Denken Sie daran, dass dies
scanf
für "Scan-formatiert" steht und dass kaum etwas weniger formatiert ist als vom Benutzer eingegebene Daten. Es ist ideal, wenn Sie die vollständige Kontrolle über das Eingabedatenformat haben, aber im Allgemeinen nicht für Benutzereingaben geeignet sind.Verwenden Sie
fgets()
( mit Pufferüberlaufschutz), um Ihre Eingabe in eine Zeichenfolge zu übertragen undsscanf()
auszuwerten. Da Sie nur das wollen, was der Benutzer ohne Analyse eingegeben hat, brauchen Siesscanf()
in diesem Fall sowieso nicht wirklich :quelle
fgets()
. Dann sieht es tatsächlich einfacher ausscanf()
. +1scanf
das Verhalten undefiniert ist, wenn die numerische Konvertierung überläuft ( N1570 7.21.6.2p10 , letzter Satz, Wortlaut seit C89 unverändert), was bedeutet, dass keine derscanf
Funktionen sicher für die numerische Konvertierung nicht vertrauenswürdiger Eingaben verwendet werden kann.scanf
eine Aufgabe verwenden müssen, waren sie falsch, und Sie können ihnen sagen, dass ich es gesagt habe, und wenn sie mit mir darüber streiten wollen kann meine E-Mail-Adresse leicht aus meinem Profil gefunden werden.Versuchen
Hoffentlich hilft das.
quelle
s
vom Ende der Eingabezeichenfolge entfernt, da es in bestimmten Fällen sowohl überflüssig als auch falsch ist (wie in früheren Kommentaren erwähnt).[
ist eher ein eigener Formatbezeichner als eine Variation dess
einen.In diesem Beispiel wird ein invertiertes Scanset verwendet, sodass scanf so lange Werte aufnimmt, bis es auf eine '\ n' - neue Zeile stößt, sodass auch Leerzeichen gespeichert werden
quelle
%20[^\n]s
, um Pufferüberläufe zu verhinderns
!Sie können dies verwenden
Oder dieses
DEMO
quelle
scanf("%19[^\n]", name);
(immer noch +1 für die prägnante Antwort)sizeof(char)
ist per Definition immer 1, so dass es nicht nötig ist, damit zu multiplizieren.Verwenden Sie diese Option nicht
scanf()
zum Lesen von Zeichenfolgen, ohne eine Feldbreite anzugeben. Sie sollten auch die Rückgabewerte auf Fehler überprüfen:Alternativ können Sie Folgendes verwenden
fgets()
:quelle
Sie können die
fgets()
Funktion zum Lesen einer Zeichenfolge verwenden oder dasscanf("%[^\n]s",name);
Lesen von Zeichenfolgen beenden, wenn ein Zeilenumbruchzeichen auftritt.quelle
s
gehört nicht dorthingetline()
Jetzt ein Teil von POSIX.
Es behebt auch das Pufferzuordnungsproblem, nach dem Sie zuvor gefragt haben, obwohl Sie sich um
free
den Speicher kümmern müssen .quelle
Wenn noch jemand sucht, hat Folgendes für mich funktioniert: Lesen einer beliebigen Länge von Zeichenfolgen einschließlich Leerzeichen.
Vielen Dank an viele Poster im Internet für das Teilen dieser einfachen und eleganten Lösung. Wenn es funktioniert, geht der Kredit an sie, aber alle Fehler sind meine.
quelle
errno
den zugewiesenen Speicher überprüfen und bereinigen.s
gehört nicht dorthin nach dem ScansetSie können
scanf
für diesen Zweck mit einem kleinen Trick verwenden. Eigentlich sollten Sie Benutzereingaben zulassen, bis der Benutzer Enter (\n
) drückt . Dies berücksichtigt jedes Zeichen, einschließlich des Leerzeichens . Hier ist ein Beispiel:Wie funktioniert das? Wenn der Benutzer Zeichen aus der Standardeingabe eingibt, werden diese bis zum ersten Leerzeichen in einer Zeichenfolgenvariablen gespeichert . Danach bleibt der Rest des Eintrags im Eingabestream und wartet auf den nächsten Scan. Als nächstes haben wir eine
for
Schleife, die char für char aus dem Eingabestream (bis\n
) nimmt und sie an das Ende der Zeichenfolgenvariablen anfügt , wodurch eine vollständige Zeichenfolge gebildet wird, die der Benutzereingabe über die Tastatur entspricht.Hoffe das hilft jemandem!
quelle
Während Sie
scanf()
für solche Dinge wirklich nicht verwenden sollten , weil es viel bessere Anrufe wiegets()
oder gibtgetline()
, kann es getan werden:quelle
gets
veraltet und aus dem Standard entfernt wurde ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ). Es ist noch schlimmer ,scanf
weil zumindest letzteres Möglichkeiten hat, es sicher zu machen.quelle
s
gehört nicht dorthin nach dem Scanset