Malloc und scanf
Ich bin sehr kompetent in ein paar scripting-Sprachen, aber ich bin schließlich Zwang mich zu lernen raw C. ich bin nur Herumspielen mit einigen grundlegenden Sachen (I/O). Wie kann ich reservieren, heap-Speicher, speichern einer Zeichenfolge in den Speicher, und dann spucken Sie es wieder aus? Dies ist, was ich haben jetzt, wie kann ich es machen das korrekt?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *toParseStr = (char*)malloc(10);
scanf("Enter a string",&toParseStr);
printf("%s",toParseStr);
return 0;
}
Derzeit bin ich immer komisch Ausgabe wie '8'\'.
Sie brauchen nicht zu werfen, die den Rückgabetyp von
Es ist erwähnenswert, dass, sollten Sie wahrscheinlich den Stapel hier.
malloc(3)
im ISO-C-mit <stdlib.h>
enthalten.Es ist erwähnenswert, dass, sollten Sie wahrscheinlich den Stapel hier.
InformationsquelleAutor Backus | 2010-07-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Erstens, die Zeichenfolge in
scanf
ist, gibt die input es geht, zu erhalten. Um die Anzeige einer Zeichenkette vor der Annahme von Tastatureingaben verwendenprintf
wie gezeigt.Zweitens, Sie brauchen nicht zu dereferenzieren
toParseStr
da es zeigt, um ein Zeichen-array der Größe 10, wie Sie zugewiesen mitmalloc
. Wenn Sie wurden mit einer Funktion, die würde, zeigen Sie es auf einem anderen Speicher-Ort, dann&toParseStr
erforderlich ist.Angenommen, Sie wollten eine Funktion schreiben, die Speicher reservieren. Dann müssten Sie
&toParseStr
da änderst du den Inhalt der pointer-variable (die eine Adresse im Speicher --- Sie selbst sehen können, durch den Druck seiner Inhalte).Wie Sie sehen können, es akzeptiert
char ** ptr_string
das liest sich wie ein Zeiger speichert die Speicherposition einen Zeiger, die wird speichern die Speicher-Adresse (nach dermalloc
Betrieb) das erste byte von einem zugewiesenen blockn
bytes (derzeit sind es einige Müll-Speicher-Adresse, da es nicht initialisiert ist).Drittens, es wird empfohlen, um Speicher frei, die Sie zuordnen. Obwohl dies Ihr ganzes Programm, und dieser Speicher wird freigegeben, wenn das Programm beendet wird, es immer noch gute Praxis.
Rufen Sie
fflush(stdout);
zwischen dem Druck der Eingabeaufforderung, und ruftscanf
. Die meisten Implementierungen wird dies für Sie tun, höflich zu sein, aber es ist nicht zwingend.InformationsquelleAutor Jacob
Müssen Sie
scanf
eine Konvertierung format, so dass es weiß, Sie wollen Lesen Sie einen string-gerade jetzt, du bist nur das anzeigen was auch immer Müll zufällig in den Speicher, den Sie zugeordnet haben. Anstatt zu versuchen, um zu beschreiben, all die Probleme, hier ist etwas code, der sollte zumindest in der Nähe zu arbeiten:Edit: In diesem Fall
free
ing der string macht keinen wirklichen Unterschied, aber wie andere haben darauf hingewiesen, es ist eine gute Gewohnheit zu kultivieren, dennoch.%9s
imscanf
.Im Gegensatz zu einigen Menschen, die glauben, Spülung
stdout
ist nicht erforderlich ist, um die Eingabeaufforderung angezeigt wird, bevor das Eingangssignal ist zu Lesen, es sei denn, die Umsetzung ist gut und wirklich kaputt ist. Für diejenigen, die wirklich interessiert, siehe §7.19.3.stdout
können nur dann voll gepuffert, wenn ermittelt werden kann nicht beziehen sich auf ein interaktives Gerät.Sie irren sich.
stdout
noch line-buffered das bedeutet nichts zeigt, bis ein newline ausgegeben. POSIX empfiehlt, dass Implementierungen flushstdout
und andere line-buffered-streams, Wann immer Lesen, aber es ist eine deutliche performance-Einbußen zu Scannen, öffnen Sie den Datei-Liste für line-buffered-streams (vor allem bei threads und locking) und einer Implementierung können wählen, nicht zu tun, und für sehr gute Gründe. Soweit ich weiß, ISO-C macht nur wenige/keine Anforderungen an die Pufferung Semantik. Damit Sie sollte flush!InformationsquelleAutor Jerry Coffin
Mit
scanf()
(oderfscanf()
auf Daten, die du nicht kontrollierst), standardmäßig "%s" Bezeichner ist eine fast bestimmte Art und Weise, um sich selbst in Probleme mit buffer-overflows.Das klassische Beispiel ist, dass ich geben Sie die Zeichenfolge "Dieser string ist so mehr als 10 Zeichen" in Ihrem Programm, das chaos wird Folgen, Katzen und Hunde werden beginnen, zusammen zu schlafen und eine Nackte Singularität kann auch angezeigt werden und verbrauchen die Erde (die meisten Leute nur sagen "Undefiniertes Verhalten", aber ich denke meine Beschreibung ist besser).
Ich aktiv raten von der Verwendung von Funktionen, die nicht in Schutz. Ich möchte Sie bitten (vor allem als Neuling auf C) um
fgets()
Lesen Ihre Eingabe, da Sie kontrollieren können, buffer overflows mit die es viel einfacher, und es ist mehr geeignet, einfache Online-Eingabe alsscanf()
.Sobald Sie eine Linie, Sie können dann rufen
sscanf()
auf es zu Inhalt Ihres Herzens, die, übrigens, Sie brauchen nicht zu tun, in diesem speziellen Fall, da du bist nur immer ein raw-string sowieso.Würde ich verwenden:
fgets
hat Vorteilescanf
undfscanf
haben Bestimmungen zur Verhinderung von buffer overflows als gut.Das ist ein guter Punkt, @Jerry, aber ich habe selten Leute gesehen, die Verwendung der Breite Bezeichner, die mit "%s" 🙂 Da die meisten meiner Konsole I/O-code, in der Regel line-basierte Eingabe, "%s " ist ungeeignet für Sie immer die weiße Raum. Aber seit deiner Antwort ist eigentlich Recht in diesem Fall +1 für Sie.
Eine weitere interessante Möglichkeit ist
scanf("%9[^\n]", your_string);
-- line-orientierten string Eingabe vonscanf
, für was auch immer das Wert ist.Sarg:
scanf
undfscanf
sind in der Regel schwer zu bedienen ist auch aus anderen Gründen. IMO ist es besser für jedermann, das ist kein C-Experte zu vermeiden, Sie vollständig. Trotzdem, +1 für die einzige Antwort, die warnt davor, die potenziellen Pufferüberlauf.für die nette
%[
Vorschlag. So wenige Menschen wissen, dass es existiert. Es ist tatsächlich hilfreich für die Umsetzung ist ein vollständig portable version von GNUgetline
/getdelim
auf normal ISO C. Und wenn Sie%n
nachdem es, können Sie sogar das Lesen byte-Zählung, falls die gelesenen Daten enthält eingebettete null-bytes.InformationsquelleAutor paxdiablo
Brauchen Sie nicht eine
&
vortoParseStr
imscanf
ist es ja schon ein Zeigernennen Sie auch
free(toParseStr)
danachWährend wahr, das ist nicht wirklich die Quelle eines Problems (der
&
ist unnötig, aber harmlos in diesem Fall).Es ist harmlos, weil der Formatbezeichner nicht angeben, keine Argumente, aber sobald er behebt Sie haben eine %s wie in Ihrer Antwort, es geht um Ursache erzeugt einen segfault
Ja, aber es zeigt nur eine relativ kleine problem, wo gibt es viele andere, die sind viel ernster. Insbesondere zu ändern, dass bestimmten Punkt (wobei der rest des Codes unverändert) nicht bieten keine (sichtbare) Verbesserung in seinem Verhalten überhaupt.
InformationsquelleAutor Sanjay Manohar
Ersten, die Fehler, die halten Sie Ihr Programm von der Arbeit:
scanf(3)
nimmt ein format-string genau wieprintf(3)
, nicht um eine Zeichenfolge zu drucken für die Benutzer. Zweitens, Sie waren übergeben der Adresse des ZeigerstoParseStr
, anstatt der ZeigertoParseStr
.Ich habe auch entfernt die unnötige Umwandlung von Ihrem Anruf
malloc(3)
.Eine Verbesserung, die Ihr Programm noch benötigt, ist die Verwendung
scanf(3)
'sa
option, um Speicher für Sie-so dass einige joker setzen zehn Zeichen in dein string nicht starten stampfenden auf unabhängigen Speicher. (Ja, die C mal jemandem überschreiben, der fast den gesamten Adressraum mit diesem Programm, wie geschrieben. Riesen-Sicherheitslücke. 🙂scanf
hat keinea
option. Dies ist eine GNU-Erweiterung, die ist nicht nur flippig, sondern KONFLIKTE mit ISO-C (%a
ist eine von den Planern zu Lesen, eine floating-point-Zahl!). Es sollte unbedingt vermieden werden.Danke; ich war nicht bewusst diese Erweiterung des öfteren mit ISO-C.
InformationsquelleAutor sarnold