2013-04-23 8 views
6

Come separare le linee che provengono da una tubazione. Nel tubo c'è questo testo:Leggere da linea del tubo per linea in C

HALLO:500\n 
TEST:300\N 
ADAD 
ADAWFFA 
AFAGAGAEG 

voglio separare le linee dal tubo perché voglio salvare i valori nelle variabili.

Ecco il mio codice C:

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

#define BUFFERSIZE 1 

int main(int argc, char **argv){ 
    unsigned char  buffer[BUFFERSIZE]; 
    FILE       *instream; 
    int       bytes_read=0; 
    int       buffer_size=0; 


    buffer_size=sizeof(unsigned char)*BUFFERSIZE; 
    /* open stdin for reading */ 
    instream=fopen("/dev/stdin","r"); 

    /* did it open? */ 
    if(instream!=NULL){ 
     /* read from stdin until it's end */ 
     while((bytes_read=fread(&buffer, buffer_size, 1, instream))==buffer_size){ 
      fprintf(stdout, "%c", buffer[0]); 
     } 
    } 
    /* if any error occured, exit with an error message */ 
    else{ 
     fprintf(stderr, "ERROR opening stdin. aborting.\n"); 
     exit(1); 
    } 

    return(0); 
} 

È questo il modo giusto di leggere dal tubo per la migliore linea per linea?

+0

"per il meglio" è una domanda soggettiva. Stai davvero affrontando qualche problema? – abasu

+0

Sostituisci 'fread' con [' fgets'] (http://pubs.opengroup.org/onlinepubs/009695399/functions/fgets.html). –

risposta

13

Di solito viene chiamato solo in lettura dallo standard. Il programma non dovrebbe preoccuparsi se l'input è una pipe, un file reindirizzato o una tastiera.

fread leggerà solo fino a quando il buffer è pieno. Usa i comandi per leggere una riga.

Anche la dimensione del buffer deve essere abbastanza grande da contenere la linea. Per piccoli programmi una tantum, puoi semplicemente scegliere un numero. Oppure c'è un nome standard BUFSIZ che ti dà un piuttosto grande buffer. Quanto grande? Grande abbastanza. Veramente? Probabilmente.

fgets copierà il carattere di fine riga nella stringa a meno che la stringa non si riempia per prima. Quindi puoi testare l'ultimo carattere per capire se la linea è stata troncata o meno. Con input ragionevoli, non succederà. Ma un approccio più robusto alloca un buffer più grande, copia la linea parziale e chiama ancora fgets tp continua a cercare di ottenere una linea completa.

#include <stdio.h> 

int main() { 
    char buf[BUFSIZ]; 
    fgets(buf, sizeof buf, stdin); 
    if (buf[strlen(buf)-1] == '\n') { 
     // read full line 
    } else { 
     // line was truncated 
    } 
    return 0; 
} 

Questo si ottiene a metà strada verso protetto dalla temuta buffer overflow problema. fgets non scriverà più della dimensione passata. L'altra metà, come detto sopra, sta facendo qualcosa di sensato con le possibili linee parziali che possono derivare da linee di input inaspettatamente lunghe.

+0

ok hai avuto un buon esempio per l'utilizzo di fgets? – bladepit

+1

Lo farei. Ma dovresti imparare a fare "man fgets" per te stesso. (È la prima cosa che farei per scrivere un esempio: ottengo sempre gli argomenti indietro quando scrivo senza controllo.) –

+1

Non sto cercando di sembrare moccioso. Penso davvero che sia meglio per me non scrivere un esempio del genere. –

1

Ecco un'altra opzione (non sono completamente sicuro che sia un modo "corretto"): utilizzare il numero di byte letti dalla funzione read. In questo esempio stavo leggendo da stdin anche se è stato effettuato un reindirizzamento in modo che il file fd in 0 sia un file/pipe/qualsiasi cosa sia necessario.

while ((nbytes=read(STDIN_FILENO, buffer, MAX_PIPE_SIZE)) > 0) { 
    write(STDOUT_FILENO, buffer, nbytes); 
    }