Как читать строку с консоли в C?

Каков самый простой способ прочитать полную строку в программной консоли C. Введенный текст может иметь переменную длину, и мы не можем делать никаких предположений о его содержании.

Вам необходимо динамическое управление памятью и использовать функцию fgets для чтения вашей строки. Однако, похоже, нет способа увидеть, сколько символов он читает. Таким образом, вы используете 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; } 

Примечание . Никогда не используйте! Он не выполняет проверку границ и может переполнять ваш буфер

Если вы используете библиотеку GNU C или другую библиотеку, совместимую с POSIX, вы можете использовать getline() и передать stdin для файлового streamа.

Возможно, вам понадобится использовать цикл character by character (getc ()), чтобы убедиться, что у вас нет переполнения буфера и не усекайте ввод.

Очень простая, но небезопасная реализация для чтения строки для статического распределения:

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

Более безопасная реализация без возможности переполнения буфера, но с возможностью не читать всю строку, такова:

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

Не «разница на единицу» между указанной длиной, объявляющей переменную, и длиной, указанной в строке формата. Это исторический артефакт.

Итак, если вы искали аргументы команды, взгляните на ответ Тима. Если вы просто хотите прочитать строку с консоли:

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

Да, это не безопасно, вы можете сделать переполнение буфера, оно не проверяет конец файла, оно не поддерживает кодировки и много других вещей. На самом деле я даже не думал, сделал ли это ЛЮБОЙ из этого. Я согласен, что я немного испортил 🙂 Но … когда я вижу такой вопрос, как «Как читать строку с консоли в C?», Я предполагаю, что человеку нужно что-то простое, например gets (), а не 100 строк кода как выше. На самом деле, я думаю, если вы попытаетесь написать эти 100 строк кода в реальности, вы сделали бы еще много ошибок, чем вы бы сделали, если бы вы выбрали get;)

Пример использования строки getline

Упоминается об этом ответе, но вот пример.

Это POSIX 7 , выделяет нам память и многократно использует выделенный буфер в цикле.

Pointer newbs, прочитайте следующее: Почему первым аргументом getline является указатель на указатель «char **» вместо «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; } 

реализация glibc

Нет POSIX? Возможно, вы хотите взглянуть на реализацию glibc 2.23 .

Он разрешает getdelim , который является простым расширением POSIX для линии getline с произвольным терминатором строк.

Он удваивает выделенную память, когда требуется увеличение, и выглядит поточно-безопасным.

Это требует некоторого макрорасширения, но вряд ли вы сделаете гораздо лучше.

Как и было предложено, вы можете использовать getchar () для чтения с консоли до тех пор, пока не вернется конец строки или EOF, создав свой собственный буфер. Динамический динамический рост может возникать, если вы не можете установить разумный максимальный размер строки.

Вы также можете использовать fgets как безопасный способ получить строку в виде строки с нулевым символом:

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

Если вы исчерпали вход в консоль или если по какой-либо причине операция завершилась неудачно, возвращается eof == NULL, и буфер строки может не измениться (именно поэтому установка первого символа на «\ 0» удобна).

fgets не будет переполнять строку [], и это гарантирует, что после успешного приема возвращается нуль.

Если конец линии был достигнут, символ, предшествующий завершающему «\ 0», будет «\ n».

Если до окончания ‘\ 0’ не заканчивается ‘\ n’, может быть, есть больше данных или что следующий запрос будет сообщать о конце файла. Вам нужно будет сделать еще один fgets, чтобы определить, что есть. (В этом отношении цикл с getchar () проще.)

В приведенном выше (примерном) примере кода, если строка [sizeof (line) -1] == ‘\ 0 “после успешных fgets, вы знаете, что буфер заполнен полностью. Если это положение выполняется «\ n», вы знаете, что вам повезло. В противном случае в stdin есть либо больше данных, либо конец файла. (Когда буфер не заполнен полностью, вы все равно можете быть в конце файла, и в конце текущей строки также может быть не \ \ n \. Поскольку вам нужно отсканировать строку, чтобы найти и / или исключить любой «\ n» до конца строки (первый «\ 0» в буфере), я склонен предпочитать использование getchar () в первую очередь.)

Сделайте то, что вам нужно сделать, чтобы иметь дело с тем, что все еще больше, чем количество, которое вы читаете в качестве первого fragmentа. Примеры динамически растущего буфера могут быть созданы для работы с getchar или fgets. Есть несколько сложных случаев, которые нужно учитывать (например, запоминание того, что следующий вход начинается с позиции «\ 0», которая закончила предыдущий ввод до того, как буфер был расширен).

Многие люди, такие как я, приходят на этот пост с заголовком, соответствующим тому, что искали, хотя в описании говорится о переменной длине. В большинстве случаев мы знаем длину заранее.

Если вы знаете длину перед рукой, попробуйте ниже:

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

источник: https://www.tutorialspoint.com/c_standard_library/c_function_fgets.htm

Как читать строку с консоли в C?

  • Создание собственной функции – это один из способов, который поможет вам добиться чтения строки с консоли на C.

  • Я использую динамическое распределение памяти, чтобы выделить достаточно объем памяти, необходимый для хранения всех символов строки вместе с символом '\0' .

  • И здесь я использую цикл для сканирования каждого символа строки один за другим с помощью функции getchar() до тех пор, пока пользователь не вводит символ '\n' или 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; } 
  • Теперь вы можете прочитать полную строку следующим образом:

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

Вот пример программы, использующей 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 } 

ввод образца:

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

выход образца:

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

Некоторое время назад я сталкивался с той же проблемой, это было моим решением, надеюсь, что это поможет.

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

В BSD-системах и Android вы также можете использовать fgetln :

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

Вот так:

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

line не завершается нулем и содержит \n (или независимо от используемой вами платформы) в конце. Он становится недействительным после следующей операции ввода-вывода в streamе.

Что-то вроде этого:

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

Эта функция должна делать то, что вы хотите:

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

Надеюсь, это поможет.

  • Как читать из stdin с помощью fgets ()?
  • Чтение из stdin flush stdout?
  • Очистить stdin перед чтением
  • Как читать из файла или stdin в Bash?
  • Как заставить ssh получить пароль от stdin
  • setvbuf не может сделать stdin небуферизованным
  • Чтение двоичных данных из std :: cin
  • Почему я получаю «Необработанный тип исключения IOException»?
  • Сравнить два дерева каталогов
  • Как читать из stdin по строкам в узле
  • nodejs, как читать нажатия клавиш от stdin
  • Давайте будем гением компьютера.