Come leggere una riga dalla console in C?

Qual è il modo più semplice per leggere una riga intera in un programma di console C Il testo inserito potrebbe avere una lunghezza variabile e non possiamo assumere alcuna ipotesi sul suo contenuto.

Hai bisogno di una gestione dynamic della memoria e usa la funzione fgets per leggere la tua linea. Tuttavia, sembra che non ci sia modo di vedere quanti personaggi ha letto. Quindi tu usi fgetc:

 char * getline(void) { char * line = malloc(100), * linep = line; size_t lenmax = 100, len = lenmax; int c; if(line == NULL) return NULL; for(;;) { c = fgetc(stdin); if(c == EOF) break; if(--len == 0) { len = lenmax; char * linen = realloc(linep, lenmax *= 2); if(linen == NULL) { free(linep); return NULL; } line = linen + (line - linep); linep = linen; } if((*line++ = c) == '\n') break; } *line = '\0'; return linep; } 

Nota : mai usare ottiene! Non esegue il controllo dei limiti e può sovraccaricare il buffer

Se si utilizza la libreria GNU C o un’altra libreria compatibile con POSIX, è ansible utilizzare getline() e passare lo stdin ad esso per il stream di file.

Potrebbe essere necessario utilizzare un ciclo carattere per carattere (getc ()) per assicurarsi di non avere buffer overflow e di non troncare l’input.

Un’implementazione molto semplice ma non sicura per leggere la riga per l’allocazione statica:

 char line[1024]; scanf("%[^\n]", line); 

Un’implementazione più sicura, senza possibilità di buffer overflow, ma con la possibilità di non leggere l’intera linea, è:

 char line[1024]; scanf("%1023[^\n]", line); 

Non la “differenza di uno” tra la lunghezza specificata che dichiara la variabile e la lunghezza specificata nella stringa di formato. È un artefatto storico.

Quindi, se stavi cercando argomenti di comando, dai un’occhiata alla risposta di Tim. Se vuoi solo leggere una riga dalla console:

 #include  int main() { char string [256]; printf ("Insert your full address: "); gets (string); printf ("Your address is: %s\n",string); return 0; } 

Sì, non è sicuro, puoi fare un sovraccarico del buffer, non controlla la fine del file, non supporta le codifiche e molte altre cose. In realtà non pensavo nemmeno se ne avesse mai fatto. Sono d’accordo che mi sono un po ‘fregato 🙂 Ma … quando vedo una domanda come “Come leggere una riga dalla console in C?”, Suppongo che una persona abbia bisogno di qualcosa di semplice, come gets () e non 100 righe di codice come sopra. In realtà, penso che se provassi a scrivere quelle 100 righe di codice nella realtà, faresti molti più errori, di quanto avresti fatto se avessi scelto;)

esempio getline

Menzionato su questa risposta, ma qui è un esempio.

È POSIX 7 , assegna la memoria per noi e riutilizza il buffer allocato su un loop in modo gradevole.

Newbie puntatore, leggi questo: Perché il primo argomento di getline è un puntatore al puntatore “char **” invece di “char *”?

 #define _XOPEN_SOURCE 700 #include  #include  int main(void) { char *line = NULL; size_t len = 0; ssize_t read = 0; while (read != -1) { puts("enter a line"); read = getline(&line, &len, stdin); printf("line = %s", line); printf("line length = %zu\n", read); puts(""); } free(line); return 0; } 

implementazione di glibc

Nessun POSIX? Forse vuoi vedere l’ implementazione di glibc 2.23 .

Risolve per getdelim , che è un semplice superset POSIX di getline con un terminatore di riga arbitrario.

Raddoppia la memoria allocata ogni volta che è necessario un aumento e sembra thread-safe.

Richiede qualche espansione macro, ma è improbabile che tu faccia molto meglio.

Come suggerito, è ansible utilizzare getchar () per leggere dalla console finché non viene restituito un fine riga o un EOF, creando il proprio buffer. Il buffer di crescita può verificarsi dynamicmente se non è ansible impostare una dimensione di linea massima ragionevole.

Puoi anche usare Fgets come metodo sicuro per ottenere una riga come stringa C terminata da null:

 #include  char line[1024]; /* Generously large value for most situations */ char *eof; line[0] = '\0'; /* Ensure empty line if no input delivered */ line[sizeof(line)-1] = ~'\0'; /* Ensure no false-null at end of buffer */ eof = fgets(line, sizeof(line), stdin); 

Se si è esaurito l’input della console o se l’operazione non è riuscita per qualche motivo, viene restituito == NULL e il buffer di riga potrebbe non essere cambiato (motivo per cui l’impostazione del primo carattere su “\ 0” è utile).

fgets non riempirà eccessivamente la linea [] e si assicurerà che ci sia un nullo dopo l’ultimo carattere accettato su un risultato positivo.

Se la fine della linea è stata raggiunta, il carattere che precede il termine ‘\ 0’ sarà un ‘\ n’.

Se non è terminato ‘\ n’ prima della fine ‘\ 0’, potrebbe essere che ci siano più dati o che la richiesta successiva riporti la fine del file. Dovrai fare un altro compito per determinare quale è quale. (A questo proposito, il loop con getchar () è più facile.)

Nel codice di esempio (aggiornato) precedente, se line [sizeof (line) -1] == ‘\ 0’ dopo aver eseguito correttamente i fgets, si sa che il buffer è stato riempito completamente. Se quella posizione è preceduta da un ‘\ n’, sai che sei stato fortunato. Altrimenti, ci sono più dati o una fine di file avanti nello stdin. (Quando il buffer non è riempito completamente, si può ancora essere alla fine del file e potrebbe anche non esserci un \ n alla fine della riga corrente. Poiché è necessario eseguire la scansione della stringa per trovare e / o eliminare qualsiasi ‘\ n’ prima della fine della stringa (il primo ‘\ 0’ nel buffer), sono propenso a preferire l’uso di getchar () in primo luogo.)

Fai quello che devi fare per occuparti c’è ancora più linea rispetto alla quantità che hai letto come il primo pezzo. Gli esempi di crescita dynamic di un buffer possono essere fatti funzionare con getchar o con fgets. Ci sono alcuni casi complicati da evitare (come ricordare che il prossimo input inizia a memorizzare nella posizione di “\ 0” che ha terminato l’input precedente prima che il buffer fosse esteso).

Molte persone, come me, vengono in questo post con il titolo corrispondente a ciò che viene cercato, sebbene la descrizione stia parlando della lunghezza variabile. Per la maggior parte dei casi, conosciamo la lunghezza in anticipo.

Se conosci la lunghezza prima della mano, prova di seguito:

 char str1[1001] = { 0 }; fgets(str1, 1001, stdin); // 1000 chars may be read 

fonte: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm

Come leggere una riga dalla console in C?

  • Costruire la propria funzione , è uno dei modi in cui è ansible ottenere la lettura di una riga dalla console in C.

  • Uso l’allocazione dynamic della memoria per allocare solo la quantità sufficiente di memoria necessaria per contenere tutti i caratteri di una riga insieme al carattere '\0' .

  • E qui sto usando un loop per scansionare ogni carattere della stringa uno per uno usando la funzione getchar() fino a quando l’utente non inserisce il carattere '\n' o EOF

     //the function to read lines of variable length char* scan_line(char *line) { int ch; //as getchar() returns `int` if( (line = malloc(sizeof(char))) == NULL) //allocating memory { //checking if allocation was successful or not printf("unsuccessful allocation"); exit(1); } line[0]='\0'; for(int index = 0; ( (ch = getchar())!='\n' ) && (ch != EOF) ; index++) { if( (line = realloc(line, (index + 2)*sizeof(char))) == NULL ) { //checking if reallocation was successful or not printf("unsuccessful reallocation"); exit(1); } line[index] = (char) ch; //type casting `int` to `char` line[index + 1] = '\0'; //inserting null character at the end } return line; } 
  • Ora puoi leggere una riga intera in questo modo:

     char *line = NULL; line = scan_line(line); 

Ecco un programma di esempio che utilizza la funzione scan_line() :

 #include  #include  //for dynamic allocation functions char* scan_line(char *line) { .......... } int main(void) { char *a = NULL; a = scan_line(a); //function call to scan the line printf("%s\n",a); //printing the scanned line free(a); //don't forget to free the malloc'd pointer } 

esempio di input:

 Twinkle Twinkle little star.... in the sky! 

uscita di esempio:

 Twinkle Twinkle little star.... in the sky! 

Ho incontrato lo stesso problema qualche tempo fa, questa era la mia soluzione, spero che sia d’aiuto.

 /* * Initial size of the read buffer */ #define DEFAULT_BUFFER 1024 /* * Standard boolean type definition */ typedef enum{ false = 0, true = 1 }bool; /* * Flags errors in pointer returning functions */ bool has_err = false; /* * Reads the next line of text from file and returns it. * The line must be free()d afterwards. * * This function will segfault on binary data. */ char *readLine(FILE *file){ char *buffer = NULL; char *tmp_buf = NULL; bool line_read = false; int iteration = 0; int offset = 0; if(file == NULL){ fprintf(stderr, "readLine: NULL file pointer passed!\n"); has_err = true; return NULL; } while(!line_read){ if((tmp_buf = malloc(DEFAULT_BUFFER)) == NULL){ fprintf(stderr, "readLine: Unable to allocate temporary buffer!\n"); if(buffer != NULL) free(buffer); has_err = true; return NULL; } if(fgets(tmp_buf, DEFAULT_BUFFER, file) == NULL){ free(tmp_buf); break; } if(tmp_buf[strlen(tmp_buf) - 1] == '\n') /* we have an end of line */ line_read = true; offset = DEFAULT_BUFFER * (iteration + 1); if((buffer = realloc(buffer, offset)) == NULL){ fprintf(stderr, "readLine: Unable to reallocate buffer!\n"); free(tmp_buf); has_err = true; return NULL; } offset = DEFAULT_BUFFER * iteration - iteration; if(memcpy(buffer + offset, tmp_buf, DEFAULT_BUFFER) == NULL){ fprintf(stderr, "readLine: Cannot copy to buffer\n"); free(tmp_buf); if(buffer != NULL) free(buffer); has_err = true; return NULL; } free(tmp_buf); iteration++; } return buffer; } 

Sui sistemi BSD e su Android puoi anche usare fgetln :

 #include  char * fgetln(FILE *stream, size_t *len); 

Così:

 size_t line_len; const char *line = fgetln(stdin, &line_len); 

La line non è terminata con null e contiene \n (o qualsiasi altra cosa venga utilizzata dalla tua piattaforma) alla fine. Diventa non valido dopo la successiva operazione di I / O sul stream.

Qualcosa come questo:

 unsigned int getConsoleInput(char **pStrBfr) //pass in pointer to char pointer, returns size of buffer { char * strbfr; int c; unsigned int i; i = 0; strbfr = (char*)malloc(sizeof(char)); if(strbfr==NULL) goto error; while( (c = getchar()) != '\n' && c != EOF ) { strbfr[i] = (char)c; i++; strbfr = (void*)realloc((void*)strbfr,sizeof(char)*(i+1)); //on realloc error, NULL is returned but original buffer is unchanged //NOTE: the buffer WILL NOT be NULL terminated since last //chracter came from console if(strbfr==NULL) goto error; } strbfr[i] = '\0'; *pStrBfr = strbfr; //successfully returns pointer to NULL terminated buffer return i + 1; error: *pStrBfr = strbfr; return i + 1; } 

Questa funzione dovrebbe fare ciò che vuoi:

 char* readLine( FILE* file ) { char buffer[1024]; char* result = 0; int length = 0; while( !feof(file) ) { fgets( buffer, sizeof(buffer), file ); int len = strlen(buffer); buffer[len] = 0; length += len; char* tmp = (char*)malloc(length+1); tmp[0] = 0; if( result ) { strcpy( tmp, result ); free( result ); result = tmp; } strcat( result, buffer ); if( strstr( buffer, "\n" ) break; } return result; } char* line = readLine( stdin ); /* Use it */ free( line ); 

Spero che aiuti.