2010-03-24 15 views
5

Wie kann man unbegrenzte Zeichen in eine char* Variable lesen, ohne die Größe anzugeben?So lesen Sie unbegrenzte Zeichen in C

Zum Beispiel sagen, ich möchte die Adresse eines Mitarbeiters lesen, der auch mehrere Zeilen nehmen kann.

+2

Die Antworten unten zeigen die Mechanik des Problems, und ich würde Sie ermutigen, sie zu studieren Eine gemeinsame Implementierung ist "getline". – dmckee

+0

Sie müssen sicherstellen, dass Ihre Hardware unbegrenzten Speicher hat! – theglauber

Antwort

8

Sie müssen beginnen, indem Sie die zu erwartende Größe "erraten", und dann einen Puffer so groß zuweisen, dass Sie malloc verwenden. Wenn das zu klein ist, verwenden Sie realloc, um die Größe des Puffers zu ändern, um ein bisschen größer zu sein. Beispielcode:

char *buffer; 
size_t num_read; 
size_t buffer_size; 

buffer_size = 100; 
buffer = malloc(buffer_size); 
num_read = 0; 

while (!finished_reading()) { 
    char c = getchar(); 
    if (num_read >= buffer_size) { 
     char *new_buffer; 

     buffer_size *= 2; // try a buffer that's twice as big as before 
     new_buffer = realloc(buffer, buffer_size); 
     if (new_buffer == NULL) { 
      free(buffer); 
      /* Abort - out of memory */ 
     } 

     buffer = new_buffer; 
    } 
    buffer[num_read] = c; 
    num_read++; 
} 

Dies ist nur aus der Spitze von meinem Kopf, und vielleicht (sprich: wahrscheinlich) Fehler enthalten, aber sollten Sie eine gute Idee geben.

+1

@Codeka - Sie sollten vermeiden, 'x = Realloc (x, newsize);' Wenn Realloc fehlschlägt, verlieren Sie den ursprünglichen Zeiger, und Sie verlieren Speicher. Eine Ausnahme von dieser Regel ist jedoch, dass es in Ordnung ist, wenn Ihre Richtlinie für einen Zuweisungsfehler den Prozess beendet. –

+0

Aber, Vorsicht ... wenn der Realloc fehlschlägt, haben Sie den vorherigen Pufferzeiger geleakt. Man sollte etwas wie "void * sav = ptr; if ((ptr = realloc (ptr, newsiz)) == null) {frei (sav); } ' –

+0

Danke Jungs, das ist richtig. Ich werde mein Beispiel aktualisieren ... es ist eine Weile her, seit ich gerade C verwendet habe :) –

0

Wie wäre es, nur einen 1KB-Puffer (oder 4KB) auf den Stapel zu setzen, hinein zu lesen, bis Sie das Ende der Adresse finden, und dann einen Puffer der richtigen Größe zuweisen und die Daten dorthin kopieren? Sobald Sie von der Funktion zurückkehren, wird der Stack-Puffer entfernt und Sie haben nur einen einzigen Aufruf an malloc.

+0

Was passiert, wenn die Adresse größer als der 1k oder 4k Puffer auf dem Stapel ist? – Gabe

+1

@gabe: Wie schreibt man eine 4KB Adresse auf einen Umschlag? – tomlogic

+0

Wenn Sie die Größe einer Eingabezeichenfolge nicht kennen und versuchen, sie in einen Puffer fester Größe einzulesen, ist dies die Quelle nicht bekannter Sicherheitsprobleme im C-Code. – Gabe

1

Musste nur Ex7.1, S. 330 von Anfang C, von Ivor Horton, 3. Auflage beantworten. Nahm ein paar Wochen um zu trainieren. Ermöglicht die Eingabe von Floating-Zahlen, ohne im Voraus anzugeben, wie viele Zahlen der Benutzer eingeben soll. Speichert die Zahlen in einem dynamischen Array und gibt dann die Zahlen und den Durchschnittswert aus. Verwenden von Code :: Blocks mit Ubuntu 11.04. Ich hoffe es hilft.

/*realloc_for_averaging_value_of_floats_fri14Sept2012_16:30 */ 

#include <stdio.h> 
#include <stdlib.h> 
#define TRUE 1 

int main(int argc, char ** argv[]) 
{ 
    float input = 0; 
    int count=0, n = 0; 
    float *numbers = NULL; 
    float *more_numbers; 
    float sum = 0.0; 

    while (TRUE) 
    { 
     do 
     { 
      printf("Enter an floating point value (0 to end): "); 
      scanf("%f", &input); 
      count++; 
      more_numbers = (float*) realloc(numbers, count * sizeof(float)); 
      if (more_numbers != NULL) 
      { 
       numbers = more_numbers; 
       numbers[count - 1] = input; 
      } 
      else 
      { 
       free(numbers); 
       puts("Error (re)allocating memory"); 
       exit(TRUE); 
      } 
     } while (input != 0); 

     printf("Numbers entered: "); 
     while(n < count) 
     { 
      printf("%f ", numbers[n]); /* n is always less than count.*/ 
      n++; 
     } 
     /*need n++ otherwise loops forever*/ 
     n = 0; 
     while(n < count) 
     { 
      sum += numbers[n];  /*Add numbers together*/ 
      n++; 
     } 
     /* Divide sum/count = average.*/ 
     printf("\n Average of floats = %f \n", sum/(count - 1)); 
    } 
    return 0; 
} 

/* Success Fri Sept 14 13:29 . That was hard work.*/ 
/* Always looks simple when working.*/ 
/* Next step is to use a function to work out the average.*/ 
/*Anonymous on July 04, 2012*/ 
/* http://www.careercup.com/question?id=14193663 */ 
+0

Guter Versuch! Einige Leistungsvorschläge - versuchen Sie, viele Reallocs zu vermeiden, sie beinhalten das Kopieren von allem. Stattdessen realloc um einen Faktor von 2 oder 4, und zählen sowohl den verfügbaren Speicherplatz und den belegten Speicherplatz. Außerdem kann der Durchschnitt zur Laufzeit ohne Vorinstallation berechnet werden. – qdot