2010-03-24 15 views
5

Come leggere caratteri illimitati in una variabile char* senza specificare la dimensione?Come leggere caratteri illimitati in C

Ad esempio, si supponga di voler leggere l'indirizzo di un dipendente che può anche assumere più righe.

+2

Le risposte seguenti dimostrano la meccanica del problema e io ti incoraggerei a studiarle Un'implementazione comune è 'getline'. – dmckee

+0

Devi iniziare assicurandoti che il tuo hardware abbia memoria illimitata! – theglauber

risposta

8

Devi iniziare "indovinare" la dimensione che ti aspetti, quindi allocare un buffer così grande usando malloc. Se risulta troppo piccolo, si usa realloc per ridimensionare il buffer in modo che sia un po 'più grande. Esempio di codice:

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++; 
} 

questa è solo la parte superiore della mia testa, e potrebbe (leggi: probabilmente) contenere degli errori, ma dovrebbe darvi una buona idea.

+1

@Codeka - si dovrebbe evitare 'x = realloc (x, newsize);' Se realloc fallisce, si perde il puntatore originale e si perde memoria. Detto questo, un'eccezione a questa regola è che va bene se il criterio su un errore di alloc è terminare il processo. –

+0

Ma, attenzione ... se il realloc fallisce hai perso il precedente puntatore del buffer. Uno dovrebbe fare qualcosa come "void * sav = ptr; if ((ptr = realloc (ptr, newsiz)) == null) {free (sav); } ' –

+0

Grazie ragazzi, è corretto. Aggiornerò il mio esempio ... è passato un po 'di tempo da quando ho usato C: –

0

Che ne dici di mettere un solo buffer da 1 KB (o 4KB) nello stack, leggendolo fino a trovare la fine dell'indirizzo, quindi allocare un buffer della dimensione corretta e copiare i dati su di esso? Una volta che si ritorna dalla funzione, il buffer di stack si spegne e si ha una sola chiamata a malloc.

+0

Cosa succede quando l'indirizzo è più grande del buffer 1k o 4k nello stack? – Gabe

+1

@gabe: come si scrive un indirizzo 4KB su una busta? – tomlogic

+0

Non conoscendo le dimensioni di una stringa di input e cercando di leggerlo in un buffer di dimensione fissa è la fonte di innumerevoli problemi di sicurezza nel codice C. – Gabe

1

Dovevo solo rispondere a Ex7.1, pg 330 di Beginning C, di Ivor Horton, 3a edizione. Ci sono voluti un paio di settimane per allenarsi. Consente l'immissione di numeri mobili senza specificare in anticipo quanti numeri l'utente inserirà. Memorizza i numeri in un array dinamico, quindi stampa i numeri e il valore medio. Uso di Code :: Blocks con Ubuntu 11.04. Spero che sia d'aiuto.

/*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

Bel tentativo! Un paio di suggerimenti per le prestazioni: cerca di evitare molte riallocazioni, implicano la copia di tutto ciò che ti circonda. Invece riallocalo di un fattore 2 o 4, e mantieni il conteggio sia dello spazio disponibile che dello spazio utilizzato. Inoltre, la media può essere calcolata in fase di runtime senza preimpostare nulla. – qdot

Problemi correlati