2010-11-21 17 views
5

Ho scritto il seguente programma per leggere riga per riga da un file e memorizzarlo nell'array delle parole. L'output dovrebbe essere composto da due parole casuali dall'array. Ma sorprendentemente la matrice di parole contiene solo l'ultima parola letta ripetutamente. Qualche aiuto su cosa è andato storto?Lettura da un file e memorizzazione nell'array

int main(){ 
int i = 0; 
char line_buffer[BUFSIZ]; 
char* words[20]; 
FILE *fp = fopen("input.txt", "r"); 
    while (fgets(line_buffer, sizeof(line_buffer), fp)) { 
    //printf("%s", line_buffer); 
    words[i] = line_buffer; 
    i = i + 1; 
} 
printf("%d", i); 
int j = rand()%8; 
    int k = (j+1)%8; 
printf("%s %s", words[j], words[k]); 
fclose(fp); 
return 0; 
} 

input.txt

nematode knowledge 
empty bottle 
nevertheless 
claustrophobia 
metamorphosis 
acknowledgement 
impossibility 
never gave up 
+8

Non ti arrenderò mai! Mai ... oh, scusa. –

+0

Ho rimosso il tag Python –

+0

Ho notato:) ... –

risposta

6

Si legge ogni riga di dati nello stesso buffer, quindi l'ultima riga sovrascrive tutte le righe precedenti. Dovrai allocare lo spazio per ogni linea in un modo o nell'altro: allocazione di memoria dinamica con malloc() (o eventualmente strdup()) o utilizzando una matrice di dimensioni fisse (che limita la quantità di dati che il programma può gestire in modo sicuro). Avrai anche bisogno di trattare i newline nei dati letti.

Si ottiene credito per l'utilizzo di fgets() e non si utilizza gets(); questa è una decisione corretta al 100%.


#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 

enum { MAXLINES = 30 }; 

int main(void) 
{ 
    int i = 0; 
    char lines[MAXLINES][BUFSIZ]; 
    FILE *fp = fopen("input.txt", "r"); 

    if (fp == 0) 
    { 
     fprintf(stderr, "failed to open input.txt\n"); 
     exit(1); 
    } 
    while (i < MAXLINES && fgets(lines[i], sizeof(lines[0]), fp)) 
    { 
     lines[i][strlen(lines[i])-1] = '\0'; 
     i = i + 1; 
    } 
    fclose(fp); 
    printf("%d\n", i); 
    srand(time(0)); 
    int j = rand() % i; 
    int k = (j+1) % i; 
    printf("%s %s\n", lines[j], lines[k]); 
    return 0; 
} 

Questo controlla che il file è stato aperto correttamente, chiude il file non appena la lettura è completa, e assicura che non fa scattare un overflow dello stack con la lettura più linee che l'array può contenere. Spreca molto spazio sovra-allocando lo spazio in modo che ogni linea possa essere molto lunga (sebbene le linee siano in genere piuttosto corte). Se una linea è più lunga di BUFSIZ, verrà letta in un paio di voci adiacenti in lines. Non presuppone che ci siano 8 righe nel file di dati. Fa zapping del newline alla fine di ogni riga (a meno che una linea non sia divisa, nel qual caso zappa l'ultimo carattere prima della divisione sulla prima delle due linee). Seziona il generatore di numeri casuali con l'ora corrente. Sembra strano che tu voglia sempre solo linee adiacenti dal file.

+0

Non l'ho capito completamente .. Puoi mostrare l'allocazione con un codice di esempio? Gli array di dimensioni fisse lo faranno. – razor35

1

Hai inizializzare il generatore di numeri casuali con srand? Una spiegazione, con un esempio di come usarlo is available here.

2

Sovrascrivi ripetutamente la memoria in line_buffer. L'array di parole contiene solo i puntatori di questa variabile.

È necessario utilizzare una matrice multidimensionale o allocare memoria in fase di esecuzione.

Btw: accadranno brutte cose quando si passa più di 20 linee per il codice ...

3
int main(){ 
int i = 0; 

int BUFSIZE = 1000; 
char* words[20]; 
FILE *fp = fopen("input.txt", "r"); 
if (fp == 0){ 
     fprintf(stderr, "Error while opening"); 
     exit(1); 
} 

words[i] = malloc(BUFSIZE); 
    while (fgets(words[i], BUFSIZE, fp)) { 
     i++; 
     words[i] = malloc(BUFSIZE); 
} 
printf("Output: \n"); 
srand(time(NULL)); 
int j = rand()%i; 
int k = (j+1)%i; 
fflush(stdout); 
printf("%d - %s %d -%s", j, words[j], k, words[k]); 

int x; 
for(x = 0; x<i; x++) 
     free(words[x]); 
scanf("%d", x); 
fclose(fp); 
return 0; 
} 

ps. Controlla il risultato malloc