После обширного исследования всех вариантов «перечислений» в Scala я опубликовал гораздо более полный обзор этого домена в другом потоке StackOverflow . Он включает в себя решение шаблона «запечатанный характер + случайный объект», где я решил проблему упорядочения инициализации класса / объекта JVM.
Людям (и особенно новичкам) никогда не следует использовать 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;
}
Попробуйте
char str[11];
scanf("%10[0-9a-zA-Z ]", str);
Надеюсь, это поможет.
Не используйте 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);
}
В этом примере используется инвертированный набор сканирования, поэтому 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;
}
Теперь, тем не менее, является частью POSIX.
Он также решает проблему распределения буфера, о которой вы спрашивали ранее, хотя вы должны принять забота о освобождает
память.