Как разрешить ввод пробелов с помощью scanf?

После обширного исследования всех вариантов «перечислений» в Scala я опубликовал гораздо более полный обзор этого домена в другом потоке StackOverflow . Он включает в себя решение шаблона «запечатанный характер + случайный объект», где я решил проблему упорядочения инициализации класса / объекта JVM.

117
задан alk 17 June 2018 в 16:39
поделиться

5 ответов

Людям (и особенно новичкам) никогда не следует использовать scanf ("% s") или gets () или любые другие функции, которые не имеют защиты от переполнения буфера, если вы не знаете наверняка, что входные данные всегда будут иметь определенный формат (и, возможно, даже в этом случае).

Помните, что scanf означает «сканирование отформатировано», и очень мало меньше форматируется по сравнению с данными, введенными пользователем. Это' Идеально, если у вас есть полный контроль над форматом входных данных, но, как правило, не подходит для ввода пользователем.

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

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

/* Maximum name size + 1. */

#define MAX_NAME_SZ 256

int main(int argC, char *argV[]) {
    /* Allocate memory and check if okay. */

    char *name = malloc(MAX_NAME_SZ);
    if (name == NULL) {
        printf("No memory\n");
        return 1;
    }

    /* Ask user for name. */

    printf("What is your name? ");

    /* Get the name, with size limit. */

    fgets(name, MAX_NAME_SZ, stdin);

    /* Remove trailing newline, if there. */

    if ((strlen(name) > 0) && (name[strlen (name) - 1] == '\n'))
        name[strlen (name) - 1] = '\0';

    /* Say hello. */

    printf("Hello %s. Nice to meet you.\n", name);

    /* Free memory and exit. */

    free (name);
    return 0;
}
171
ответ дан 24 November 2019 в 01:35
поделиться

Попробуйте

char str[11];
scanf("%10[0-9a-zA-Z ]", str);

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

118
ответ дан 24 November 2019 в 01:35
поделиться

Не используйте scanf () для чтения строк без указания ширины поля. Вам также следует проверить возвращаемые значения на наличие ошибок:

#include <stdio.h>

#define NAME_MAX    80
#define NAME_MAX_S "80"

int main(void)
{
    static char name[NAME_MAX + 1]; // + 1 because of null
    if(scanf("%" NAME_MAX_S "[^\n]", name) != 1)
    {
        fputs("io error or premature end of line\n", stderr);
        return 1;
    }

    printf("Hello %s. Nice to meet you.\n", name);
}

В качестве альтернативы используйте fgets () :

#include <stdio.h>

#define NAME_MAX 80

int main(void)
{
    static char name[NAME_MAX + 2]; // + 2 because of newline and null
    if(!fgets(name, sizeof(name), stdin))
    {
        fputs("io error\n", stderr);
        return 1;
    }

    // don't print newline
    printf("Hello %.*s. Nice to meet you.\n", strlen(name) - 1, name);
}
8
ответ дан 24 November 2019 в 01:35
поделиться

В этом примере используется инвертированный набор сканирования, поэтому scanf продолжает принимать значения до тех пор, пока не встретит символ новой строки '\ n', поэтому пробелы также сохраняются

#include <stdio.h>

int main (int argc, char const *argv[])
{
    char name[20];
    scanf("%[^\n]s",name);
    printf("%s\n", name);
    return 0;
}
49
ответ дан 24 November 2019 в 01:35
поделиться

getline ()

Теперь, тем не менее, является частью POSIX.

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

4
ответ дан 24 November 2019 в 01:35
поделиться
Другие вопросы по тегам:

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