Используя следующий код:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Пользователь может ввести свое имя, но когда он вводит имя с пробелом, как Lucas Aardvark
, то scanf()
просто обрезает все после Lucas
. Как сделать scanf()
разрешенные пробелы
sizeof(char) + 256
это опечатка.Ответы:
Людям (и особенно новичкам) никогда не следует использовать
scanf("%s")
илиgets()
или любые другие функции, которые не имеют защиты от переполнения буфера, если вы не знаете наверняка, что ввод всегда будет иметь определенный формат (и, возможно, даже тогда).Помните, что чем
scanf
означает «отформатировано отсканированное изображение», и есть гораздо менее отформатированные данные, чем данные, введенные пользователем. Это идеально, если вы полностью контролируете формат входных данных, но обычно не подходит для ввода пользователем.Используйте
fgets()
(который имеет защиту от переполнения буфера), чтобы получить ввод в строку иsscanf()
оценить ее. Поскольку вам просто нужно то, что пользователь ввел без синтаксического анализа,sscanf()
в этом случае вам все равно не нужно :источник
fgets()
. Тогда это действительно выглядит проще в использованииscanf()
. +1scanf
имеет неопределенное поведение при переполнении числового преобразования ( N1570 7.21.6.2p10 , последнее предложение, формулировка не изменилась с C89), что означает, что ни одна изscanf
функций не может безопасно использоваться для числового преобразования ненадежного ввода.scanf
это в задании, они поступили неправильно, и вы можете сказать им, что я так сказал, и если они захотят поспорить со мной по этому поводу , мой адрес электронной почты легко найти в моем профиле.Пытаться
Надеюсь, это поможет.
источник
s
из конца входной строки, поскольку в некоторых случаях он является избыточным и неверным (как указано в предыдущих комментариях).[
это собственный спецификатор формата, а не его разновидностьs
.В этом примере используется инвертированный набор сканирования, поэтому scanf продолжает принимать значения, пока не встретит символ новой строки '\ n', поэтому пробелы также сохраняются.
источник
%20[^\n]s
для предотвращения переполнения буфераs
!Вы можете использовать это
Или это
DEMO
источник
scanf("%19[^\n]", name);
(все еще +1 для краткого ответа)sizeof(char)
по определению всегда равно 1, поэтому нет необходимости умножать на него.Не используйте
scanf()
для чтения строк без указания ширины поля. Вам также следует проверить возвращаемые значения на наличие ошибок:В качестве альтернативы используйте
fgets()
:источник
Вы можете использовать эту
fgets()
функцию для чтения строки или использовать ееscanf("%[^\n]s",name);
так, чтобы чтение строки прекращалось при обнаружении символа новой строки.источник
s
здесь не местоgetline()
Тем не менее, теперь часть POSIX.
Он также решает проблему выделения буфера, о которой вы спрашивали ранее, хотя вы должны позаботиться о
free
памяти.источник
Если кто-то все еще ищет, вот что у меня сработало - прочитать строку произвольной длины, включая пробелы.
Спасибо множеству постеров в Интернете за то, что они поделились этим простым и элегантным решением. Если это сработает, то заслуга принадлежит им, но все ошибки - мои.
источник
errno
и очистить выделенную память.s
не место там после сканированияВы можете использовать
scanf
для этого небольшую хитрость. Фактически, вы должны разрешить ввод данных, пока пользователь не нажмет Enter (\n
). Это будет учитывать каждый символ, включая пробел . Вот пример:Как это работает? Когда пользователь вводит символы из стандартного ввода, они будут храниться в строковой переменной до первого пробела. После этого остальная часть записи останется во входном потоке и будет ждать следующего сканирования. Далее у нас есть
for
цикл, который берет char за char из входного потока (до\n
) и добавляет их к концу строки переменной, таким образом формируя полную строку, аналогичную вводу пользователя с клавиатуры.Надеюсь, это кому-то поможет!
источник
Хотя вам действительно не следует использовать
scanf()
для такого рода вещей, потому что есть гораздо лучшие вызовы, такие какgets()
илиgetline()
, это можно сделать:источник
gets
он устарел и был удален ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ) из стандарта. Это даже хуже ,scanf
потому что, по крайней мере, у последнего есть способы сделать это безопасным.источник
s
не место там после сканирования