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

98
задан Jim Fell 9 June 2016 в 14:27
поделиться

8 ответов

Вы нуждаетесь в управлении динамической памятью и используете эти 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;
}

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

76
ответ дан TheConstructor 24 November 2019 в 05:16
поделиться

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

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

я надеюсь, что это помогает.

-3
ответ дан David Allan Finch 24 November 2019 в 05:16
поделиться

Я столкнулся с той же проблемой некоторое время назад, это было моим solutuion, надежда, которой это помогает.

/*
 * 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;
}
0
ответ дан dsm 24 November 2019 в 05:16
поделиться

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

#include <stdio.h>

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

Да, это не безопасно, можно сделать переполнение буфера, это не проверяет на конец файла, это не поддерживает кодировку и много другого материала. На самом деле я даже не думал, сделало ли это КАКОЙ-ЛИБО этот материал. Я соглашаюсь, что отчасти завинтил:), Но... когда я вижу вопрос как, "Как считать строку из консоли в C?", я предполагаю, что человеку нужно что-то простое, как добирается () а не 100 строк кода как вышеупомянутый. На самом деле я думаю, если бы Вы пытаетесь записать те 100 строк кода в действительности, Вы сделали бы намного больше ошибок, чем Вы сделали бы, выбрали Вас, добирается;)

10
ответ дан Paul Kapustin 24 November 2019 в 05:16
поделиться

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

char line[1024];

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

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

char line[1024];

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

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

15
ответ дан Jonathan Leffler 24 November 2019 в 05:16
поделиться

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

11
ответ дан Tim 24 November 2019 в 05:16
поделиться

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

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

#include <stdio.h>

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 ==, ПУСТОЙ УКАЗАТЕЛЬ возвращается и буфер строки мог бы быть неизменным (который является, почему установка первого символа к '\0' удобна).

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

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

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

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

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

5
ответ дан orcmid 24 November 2019 в 05:16
поделиться

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

27
ответ дан Jonathan Leffler 24 November 2019 в 05:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: