Como ler uma linha do console em C?

Qual é a maneira mais simples de ler uma linha completa em um programa do console C O texto typescript pode ter uma duração variável e não podemos fazer nenhuma suposição sobre seu conteúdo.

Você precisa de gerenciamento de memory dinâmica e use a function fgets para ler sua linha. No entanto, parece não haver maneira de ver quantos caracteres ele lê. Então você usa 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 : Nunca use fica! Ele não faz verificação de limites e pode estourar seu buffer

Se você estiver usando a biblioteca GNU C ou outra biblioteca compatível com POSIX, você pode usar getline() e passar stdin para ela para o stream de arquivos.

Pode ser necessário usar um loop caractere por caractere (getc ()) para garantir que você não tenha estouro de buffer e não trunque a input.

Uma implementação muito simples, mas insegura, para ler a linha para alocação estática:

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

Uma implementação mais segura, sem a possibilidade de estouro de buffer, mas com a possibilidade de não ler toda a linha, é:

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

Não é a ‘diferença por um’ entre o comprimento especificado declarando a variável e o comprimento especificado na string de formato. É um artefato histórico.

Então, se você estava procurando argumentos de comando, dê uma olhada na resposta de Tim. Se você quiser apenas ler uma linha do console:

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

Sim, não é seguro, você pode fazer buffer overrun, ele não verifica o final do arquivo, ele não suporta codificações e muitas outras coisas. Na verdade, nem pensei se isso acontecia. Eu concordo que eu meio que atrapalhei 🙂 Mas … quando eu vejo uma pergunta como “Como ler uma linha do console em C?”, Eu assumo que uma pessoa precisa de algo simples, como gets () e não 100 linhas de código como acima. Na verdade, eu acho, se você tentar escrever essas 100 linhas de código na realidade, você cometeria muitos erros, do que você teria feito se você tivesse escolhido;)

exemplo runline getline

Mencionado nesta resposta, mas aqui está um exemplo.

É POSIX 7 , aloca memory para nós e reutiliza bem o buffer alocado em um loop.

Ponteiro newbs, leia isto: Por que o primeiro argumento de getline é um ponteiro para o ponteiro “char **” em vez de “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; } 

implementação glibc

Não POSIX? Talvez você queira examinar a implementação do glibc 2.23 .

Ele resolve getdelim , que é um superconjunto POSIX simples de getline com um terminador de linha arbitrário.

Ele duplica a memory alocada sempre que o aumento é necessário e parece seguro para thread.

Isso requer alguma expansão macro, mas é improvável que você faça muito melhor.

Como sugerido, você pode usar getchar () para ler do console até que um fim de linha ou um EOF seja retornado, construindo seu próprio buffer. O crescimento dynamic do buffer pode ocorrer se você não conseguir definir um tamanho de linha máximo razoável.

Você também pode usar fgets como uma maneira segura de obter uma linha como uma string C-terminada por 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 você esgotou a input do console ou se a operação falhou por algum motivo, eof == NULL é retornado e o buffer de linha pode permanecer inalterado (é por isso que configurar o primeiro caractere como ‘\ 0’ é útil).

fgets não sobrecarregarão a linha [] e assegurarão que haja um nulo após o último caractere aceito em um retorno bem-sucedido.

Se o fim de linha foi atingido, o caractere que precede a terminação ‘\ 0’ será um ‘\ n’.

Se não houver finalização ‘\ n’ antes do final ‘\ 0’, pode ser que haja mais dados ou que o próximo pedido relate o fim do arquivo. Você terá que fazer outros fgets para determinar qual é qual. (A este respeito, o loop com getchar () é mais fácil.)

No código de exemplo (atualizado) acima, se a linha [sizeof (line) -1] == ‘\ 0’ após fgets bem-sucedidos, você sabe que o buffer foi preenchido completamente. Se essa posição for seguida por um ‘\ n’, você sabe que teve sorte. Caso contrário, há mais dados ou um fim de arquivo adiantado em stdin. (Quando o buffer não é preenchido completamente, você ainda pode estar em um fim de arquivo e também pode não haver um ‘\ n’ no final da linha atual. Desde que você tem que digitalizar a string para encontrar e / ou eliminar qualquer ‘\ n’ antes do final da string (o primeiro ‘\ 0’ no buffer), estou inclinado a preferir usar getchar () em primeiro lugar.)

Faça o que você precisa fazer para lidar com o fato de ainda existir mais linha do que a quantidade que você lê como o primeiro pedaço. Os exemplos de crescimento dynamic de um buffer podem ser feitos para trabalhar com getchar ou fgets. Há alguns casos de borda complicados a serem observados (como lembrar de ter a próxima input iniciada armazenada na posição de ‘\ 0’ que terminou a input anterior antes que o buffer fosse estendido).

Muitas pessoas, como eu, chegam a este post com o título que corresponde ao que é procurado, embora a descrição esteja dizendo sobre comprimento variável. Na maioria dos casos, sabemos o tamanho de antemão.

Se você sabe o comprimento antes da mão, tente abaixo:

 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

Como ler uma linha do console em C?

  • Construindo sua própria function , é uma maneira de ajudá-lo a conseguir ler uma linha do console em C.

  • Eu estou usando alocação de memory dinâmica para alocar apenas a quantidade suficiente de memory necessária para armazenar todos os caracteres de uma linha junto com o caractere '\0' .

  • E aqui estou usando um loop para escanear cada caractere da string, um por um, usando a getchar() até que o usuário insira '\n' ou caractere 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; } 
  • Agora você pode ler uma linha completa desta maneira:

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

Aqui está um exemplo de programa usando a function 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 } 

input de amostra:

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

exemplo de saída:

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

Eu me deparei com o mesmo problema há algum tempo atrás, esta foi a minha solução, espero que ajude.

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

Em sistemas BSD e Android, você também pode usar o fgetln :

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

Igual a:

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

A line não é terminada em nulo e contém \n (ou o que sua plataforma está usando) no final. Ele se torna inválido após a próxima operação de E / S no stream.

Algo assim:

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

Esta function deve fazer o que você quer:

 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 ); 

Eu espero que isso ajude.