Как читать строку с клавиатуры, используя C? - PullRequest
46 голосов
/ 10 октября 2011

Я хочу прочитать строку, введенную пользователем.Я не знаю длину строки.Поскольку в CI нет строк, объявил указатель:

char * word;

и использовал scanf для чтения ввода с клавиатуры:

scanf("%s" , word) ;

, но я получил ошибку сегментации.

Как я могу прочитать ввод с клавиатуры в C, когда длина неизвестна?

Ответы [ 5 ]

51 голосов
/ 10 октября 2011

У вас нет места для word - это просто висячий указатель .

Изменение:

char * word;

до:

char word[256];

Обратите внимание, что здесь 256 - произвольный выбор - размер этого буфера должен быть больше, чем максимально возможная строка, с которой вы можете столкнуться.

Обратите также внимание, что fgets является лучшим (более безопасным) вариантом, чем scanf для чтения строк произвольной длины, поскольку он принимает аргумент size, что, в свою очередь, помогает предотвратить переполнения буфера:

 fgets(word, sizeof(word), stdin);
17 голосов
/ 10 октября 2011

Не могу понять, почему здесь есть рекомендация использовать scanf(). scanf() безопасен, только если вы добавляете параметры ограничения в строку формата - например, %64s или около того.

Намного лучше использовать char * fgets ( char * str, int num, FILE * stream );.

int main()
{
    char data[64];
    if (fgets(data, sizeof data, stdin)) {
        // input has worked, do something with data
    }
}

(непроверенные)

15 голосов
/ 12 июня 2014

При чтении ввода из любого файла (включая стандартный ввод), где вы не знаете длину, часто лучше использовать getline, а не scanf или fgets, потому что getline будет обрабатывать выделение памяти для вашей строкиавтоматически, если вы предоставляете нулевой указатель для получения введенной строки.Этот пример иллюстрирует:

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

int main (int argc, char *argv[]) {

    char *line = NULL;  /* forces getline to allocate with malloc */
    size_t len = 0;     /* ignored when line = NULL */
    ssize_t read;

    printf ("\nEnter string below [ctrl + d] to quit\n");

    while ((read = getline(&line, &len, stdin)) != -1) {

        if (read > 0)
            printf ("\n  read %zd chars from stdin, allocated %zd bytes for line : %s\n", read, len, line);

        printf ("Enter string below [ctrl + d] to quit\n");
    }

    free (line);  /* free memory allocated by getline */

    return 0;
}

Соответствующие части:

char *line = NULL;  /* forces getline to allocate with malloc */
size_t len = 0;     /* ignored when line = NULL */
/* snip */
read = getline (&line, &len, stdin);

Установка line в NULL заставляет getline автоматически выделять память.Пример вывода:

$ ./getline_example

Enter string below [ctrl + d] to quit
A short string to test getline!

  read 32 chars from stdin, allocated 120 bytes for line : A short string to test getline!

Enter string below [ctrl + d] to quit
A little bit longer string to show that getline will allocated again without resetting line = NULL

  read 99 chars from stdin, allocated 120 bytes for line : A little bit longer string to show that getline will allocated again without resetting line = NULL

Enter string below [ctrl + d] to quit

Так что с getline вам не нужно угадывать, какова будет длина строки вашего пользователя.

4 голосов
/ 24 февраля 2017
#include<stdio.h>

int main()
{
    char str[100];
    scanf("%[^\n]s",str);
    printf("%s",str);
    return 0;
}

input: чтение строки
ouput: печать строки

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

1 голос
/ 10 октября 2011

Вы должны иметь указатель, чтобы указать где-нибудь, чтобы использовать его.

Попробуйте этот код:

char word[64];
scanf("%s", word);

Это создает массив символов длины 64 и читает входные данные для него. Обратите внимание, что если длина ввода превышает 64 байта, массив слов переполняется, и ваша программа становится ненадежной.

Как указал Дженс, было бы лучше не использовать scanf для чтения строк. Это было бы безопасным решением.

char word[64]
fgets(word, 63, stdin);
word[63] = 0;
...