Usando o seguinte código:
char *name = malloc(sizeof(char) + 256);
printf("What is your name? ");
scanf("%s", name);
printf("Hello %s. Nice to meet you.\n", name);
Um usuário pode digitar seu nome, mas quando ele digita um nome com um espaço como Lucas Aardvark
, scanf()
apenas corta tudo depois Lucas
. Como faço para scanf()
permitir espaços
sizeof(char) + 256
foi um erro de digitação.Respostas:
As pessoas (e especialmente os iniciantes) nunca devem usar
scanf("%s")
ougets()
ou quaisquer outras funções que não possuam proteção contra estouro de buffer, a menos que você tenha certeza de que a entrada sempre terá um formato específico (e talvez nem isso).Lembre-se do que
scanf
significa "digitalização formatada" e há muito pouco menos formatado que os dados inseridos pelo usuário. É ideal se você tiver controle total do formato dos dados de entrada, mas geralmente inadequado para a entrada do usuário.Use
fgets()
(que possui proteção contra estouro de buffer) para inserir sua entrada em uma sequência esscanf()
avaliá-la. Como você deseja apenas o que o usuário digitou sem analisar, não é realmente necessáriosscanf()
, neste caso:fonte
fgets()
. Na verdade, parece mais fácil usar entãoscanf()
. +1scanf
tem comportamento indefinido se a conversão numérica exceder o limite ( N1570 7.21.6.2p10 , última frase, redação inalterada desde C89), o que significa que nenhuma dasscanf
funções pode ser usada com segurança na conversão numérica de entrada não confiável.scanf
disser que você deve usar uma tarefa, eles estão errados ao fazê-lo, e você pode dizer a eles que eu disse e se eles querem discutir comigo sobre isso , meu endereço de e-mail é facilmente encontrado no meu perfil.Experimentar
Espero que ajude.
fonte
s
final da string de entrada, pois é supérfluo e incorreto em certos casos (como apontado nos comentários anteriores).[
é o seu próprio especificador de formato, em vez de alguma variação desses
.Este exemplo usa um conjunto de varredura invertido, portanto o scanf continua recebendo valores até encontrar uma nova linha '\ n' -, para que os espaços sejam salvos também
fonte
%20[^\n]s
para evitar buffer overflowss
lá!Você pode usar isso
Ou isto
DEMO
fonte
scanf("%19[^\n]", name);
(ainda +1 para a resposta concisa)sizeof(char)
é por definição sempre 1, então não há necessidade de multiplicar por ela.Não use
scanf()
para ler strings sem especificar a largura do campo. Você também deve verificar os valores de retorno para erros:Como alternativa, use
fgets()
:fonte
Você pode usar a
fgets()
função para ler uma string ou usarscanf("%[^\n]s",name);
para que a leitura da string termine ao encontrar um caractere de nova linha.fonte
s
não pertence lágetline()
Agora parte do POSIX, no entanto.
Ele também cuida do problema de alocação de buffer que você perguntou anteriormente, embora seja necessário cuidar da
free
memória.fonte
Se alguém ainda está procurando, aqui está o que funcionou para mim - ler um comprimento arbitrário de string, incluindo espaços.
Agradecemos a muitos pôsteres na web por compartilhar esta solução simples e elegante. Se funcionar, o crédito vai para eles, mas quaisquer erros são meus.
fonte
errno
e limpar a memória alocada.s
não pertence a esse local após o scansetVocê pode usar
scanf
para esse fim com um pequeno truque. Na verdade, você deve permitir a entrada do usuário até que ele pressione Enter (\n
). Isso considerará todos os personagens, incluindo o espaço . Aqui está um exemplo:Como isso funciona? Quando o usuário insere caracteres da entrada padrão, eles serão armazenados na variável de sequência até o primeiro espaço em branco. Depois disso, o restante da entrada permanecerá no fluxo de entrada e aguarde o próximo scanf. Em seguida, temos um
for
loop que pega char por char do fluxo de entrada (até\n
) e os anexa ao final da string variável , formando assim uma string completa igual à entrada do usuário do teclado.Espero que isso ajude alguém!
fonte
Embora você realmente não deva usar
scanf()
esse tipo de coisa, porque há chamadas muito melhores, comogets()
ougetline()
, isso pode ser feito:fonte
gets
foi preterido e removido ( stackoverflow.com/questions/30890696/why-gets-is-deprecated ) do padrão. É ainda pior quescanf
porque pelo menos o último tem maneiras de torná-lo seguro.fonte
s
não pertence lá após a scanset