Strings mit nicht definierter Länge in C lesen

8

zuerst (wie immer) Ich möchte mich über mein Englisch entschuldigen, es ist vielleicht nicht klar genug.

Ich bin nicht so gut in der C-Programmierung, und ich wurde gebeten, eine "String" -Eingabe mit undefinierter Länge zu lesen.

Das ist meine Lösung

%Vor%

Bitte, ich würde es begrüßen, wenn Sie mir helfen würden, indem Sie mir sagen, ob es eine gute Idee ist oder mir eine andere Idee gibt (und mir auch sagt, ob es eine "richtige" Verwendung für Zeiger ist).

Vielen Dank im Voraus

BEARBEITEN: Nun, danke für Ihre Antworten, sie waren sehr nützlich. Jetzt poste ich editierten (und ich hoffe besser) Code, könnte vielleicht nützlich sein für jemanden, der neu in C ist (wie ich) und wieder gefüttert wird.

%Vor%

PS:

  • Es scheint genug, um die Größe der "Palabra" langsam zu erhöhen.

  • Ich bin mir nicht sicher, ob Capture getchar() in ein int und dann in ein char umwandeln ist der korrekte Weg zu hadle EOF-Fallstrick

Marco Aviles 30.08.2010, 06:32
quelle

5 Antworten

23
  1. Sehen Sie sich die Definition von POSIX getline() an.

  2. Denken Sie daran, dass Sie den Rückgabewert von realloc() ; Es ist nicht garantiert, dass der neue Speicherblock an derselben Position wie der alte beginnt.

  3. Wissen, dass malloc(0) möglicherweise einen Null-Zeiger zurückgibt oder einen Nicht-Null-Zeiger zurückgibt, der unbrauchbar ist (weil er auf null Byte Speicher verweist).

  4. Sie können ' *list = 'palabra = newChar();'; nicht schreiben, wenn die Liste auf Null Bytes des zugewiesenen Speichers zeigt; Du hast keine Erlaubnis, dort zu schreiben. Wenn Sie einen NULL-Wert zurückbekommen, erhalten Sie wahrscheinlich einen Core-Dump. In jedem Fall rufen Sie ein undefiniertes Verhalten auf, nämlich " Eine schlechte Idee ™". ( Danke )

  5. Der main() in readLine() verliert Speicher - vorausgesetzt, Sie beheben die anderen bereits erwähnten Probleme.

  6. Der Code in getchar() berücksichtigt nicht die Möglichkeit, EOF zu erhalten, bevor er einen Zeilenumbruch erhält. das ist schlecht und wird zu einem Core-Dump führen, wenn die Speicherzuweisung (endgültig) fehlschlägt.

  7. Ihr Code weist eine schlechte Leistung auf, da er jeweils ein Zeichen zuweist. In der Regel sollten Sie mehr als ein zusätzliches Zeichen gleichzeitig zuweisen. Beginnen Sie mit einer anfänglichen Zuweisung von vielleicht 4 Bytes und verdoppeln Sie die Zuweisung jedes Mal, wenn Sie mehr Speicherplatz benötigen. Halten Sie die anfängliche Zuweisung klein, damit der Neuzuweisungscode ordnungsgemäß getestet wird.

  8. Der Rückgabewert von int ist ein char , nicht ein char . Auf den meisten Computern können 256 verschiedene positive Zeichenwerte zurückgegeben werden (auch wenn char ein signierter Typ ist) und ein separater Wert EOF, der sich von allen fgetc() -Werten unterscheidet. (Der Standard ermöglicht die Rückgabe von mehr als 256 verschiedenen Zeichen, wenn die Maschine über Bytes verfügt, die jeweils größer als 8 Bit sind.) ( Thanks ) Der C99-Standard §7.19.7.1 sagt von getchar() :

      

    Wenn der Dateiende-Indikator für den Eingabestream, auf den der Stream zeigt, nicht gesetzt ist, und a   Wenn das nächste Zeichen vorhanden ist, erhält die Funktion fgetc das Zeichen als vorzeichenlos   Zeichen konvertiert in ein int und rückt den zugehörigen Dateipositionsindikator für das Zeichen vor   Stream (falls definiert).

    (Hervorhebung hinzugefügt.) Er definiert getc() in getc() und definiert fgetc() in realloc() .

  9. (Leihgabe: Danke ). Das erste Argument für '%code%' ist der Zeiger auf den Anfang des aktuell zugewiesenen Speichers, nicht ein Zeiger auf den Zeiger auf den Anfang des aktuell zugewiesenen Speichers. Wenn Sie keine Kompilierungswarnung erhalten haben, kompilieren Sie nicht genügend Warnungen für Ihren Compiler. Sie sollten die Warnungen bis zum Maximum aufdrehen. Sie sollten die Warnungen des Compilers beachten - sie weisen normalerweise auf Fehler in Ihrem Code hin, besonders während Sie noch die Sprache lernen.

  10. Es ist oft einfacher, die Zeichenfolge ohne Null-Terminator zu behalten, bis Sie wissen, dass Sie das Ende der Zeile (oder das Ende der Eingabe) erreicht haben. Wenn keine Zeichen mehr zu lesen sind (vorerst), fügen Sie den Nullwert hinzu, damit die Zeichenfolge ordnungsgemäß beendet wird, bevor sie zurückgegeben wird. Diese Funktionen benötigen nicht, dass die Zeichenfolge ordnungsgemäß beendet wird, während sie gelesen werden, solange Sie verfolgen, wo Sie sich in der Zeichenfolge befinden. Stellen Sie jedoch sicher, dass Sie immer genug Platz haben, um die NUL %code% am Ende der Zeichenfolge hinzuzufügen.

Siehe Kernighan & amp; Pike "Die Praxis des Programmierens" für viele relevante Diskussionen. Ich denke auch, dass Maguire 'Writing Solid Code' relevante Ratschläge zu bieten hat, für alle ist es etwas veraltet. Sie sollten sich jedoch bewusst sein, dass es solche gibt, die das Buch ausradieren. Folglich empfehle ich TPOP über WSC (aber Amazon hat WSC von $ 0.01 + p & amp; p, während TPOP beginnt bei $ 20.00 + p & amp; p - dies kann der Markt sprechen).

TPOP war zuvor bei Ссылка und Ссылка , aber beide sind jetzt (2015-08-10) kaputt. Siehe auch Wikipedia auf TPOP .

    
Jonathan Leffler 30.08.2010, 06:56
quelle
5
  • Sie weisen immer ein Byte weniger zu als Sie verwenden. Zum Beispiel am Anfang vergeben Sie Platz für null Zeichen und versuchen dann, das (nicht existierende) erste Zeichen auf 'realloc' zu setzen.

  • malloc() nimmt keinen Zeiger auf einen Zeiger als ersten Parameter. Es sollte so verwendet werden:

    %Vor%
  • Wenn Sie nicht genügend Arbeitsspeicher benötigen, müssen Sie überprüfen, ob realloc() oder %code% NULL zurückgegeben hat.

  • Es wäre effizienter, am Anfang einen größeren Puffer zuzuweisen und ihn in größeren Schritten zu vergrößern, anstatt jedes hinzugefügte Zeichen separat neu zuzuweisen.

sth 30.08.2010 06:51
quelle
2

Das erste Argument für den Aufruf von realloc in

%Vor%

sollte lst und nicht &lst

sein

Auch der von realloc zurückgegebene Zeiger muss nicht immer derselbe sein wie das erste Argument. Wenn kein freier Speicher neben dem vorhandenen Speicher gefunden wird, wird ein vollständig anderer Block zugewiesen und seine Adresse wird zurückgegeben.

%Vor%     
codaddict 30.08.2010 06:54
quelle
1

Abgesehen von den Fehlern in Ihrem Code, denke ich, ist es besser, eine Zeichenfolge variabler Länge in C zu erstellen. Sobald Sie das haben, können Sie eine getLine () -Funktion schreiben. Diese Zeichenfolge variabler Länge enthält das Konzept der Kapazität, so dass ihre Größe in Blöcken von Potenzen von 2 statt eins nach dem anderen zunimmt.

%Vor%

Sobald Sie diese Implementierung durchgeführt haben, die für dieses Problem und viele andere nützlich ist, können Sie die getLine-Funktion erstellen:

%Vor%

Jetzt können Sie es einfach benutzen:

%Vor%     
Baltasarq 30.08.2010 07:50
quelle
1

Hier ein Arbeitsbeispiel für Realloc und Fgets. Sein C89, kein POSIX benötigt. Sie können den Parameter mit Ihrem eigenen vorab zugewiesenen Speicher oder NULL festlegen. Ein Abschluss "frei" wird immer benötigt.

%Vor%     
user411313 30.08.2010 10:08
quelle

Tags und Links