A *scanf()
família de funções retorna o número de "itens de entrada" (ou seja, especificações de conversão) correspondidos e atribuídos com sucesso:
VALOR DE RETORNO
Em caso de sucesso, essas funções retornam o número de itens de entrada correspondidos e atribuídos com sucesso; este valor pode ser inferior ao previsto, ou mesmo nulo, no caso de uma falha precoce na correspondência.
Agora, considere uma string de formato que contém algumas especificações de conversão intercaladas com alguns caracteres literais e termina em um ou mais caracteres literais :
// read the response to a CSI 14 t request
int r = sscanf(input, "\033[4;%d;%dt", &resp_y, &resp_x);
Considere quatro entradas potenciais para esta chamada sscanf:
"\033[4;100;200t"
"\033[4;100;200"
"\033[4;100;200foobar"
"\033[4;100;200tfoobar"
Pelo que entendi, neste caso o valor de retorno ( r
) será definido 2
em todos os três casos. No entanto, apenas a entrada (1) é válida, enquanto as entradas (2) e (3) são inválidas e a entrada (4) contém dados finais.
Qual é a maneira mais limpa/correta de distinguir (1) de (2) e (3) e de (4), ou seja, garantir que toda a string de formato foi correspondida com sucesso com toda a entrada?
Estou interessado em respostas a esta pergunta para ambos sscanf()
e fscanf()
.
Usar:
Observe que a atribuição a
n
não é contada como uma 'conversão', portanto não é contada no valor de retorno.Se quiser garantir que toda a string foi usada com
sscanf()
, você pode verificar:Esta técnica
%n
pode ser usada com qualquerscanf()
família de funções. Embora eu tenha vinculado à documentação POSIX, o padrão C diz as mesmas coisas. Se você estiver lendo um arquivo (fscanf()
ouscanf()
melhorsscanf()
), provavelmente não desejará verificar o valor den
mais do que o mostrado no primeiro trecho. Se você quiser testar uma nova linha (ou outro espaço em branco), não poderá fazer isso tão facilmente comscanf()
- consulte Qual é o efeito do espaço em branco à direita em umascanf()
string de formato? .Semelhante à boa resposta de @Jonathan Leffler .
Use
" %n"
para registrar o deslocamento da varredura.Não apenas use
"%n"
, considere" %n"
primeiro consumir 0 ou mais espaços em branco. Isso é útil, poisinput
geralmente tem um rastro potencial'\n'
(talvez vindo do formuláriofgets()
) e um formato" "
elimina a necessidade deinput
ter espaços em branco à direita, como'\n'
, removidos. Isso permite que o deslocamento de digitalização salvo seja o fim da linha.O código também pode verificar
r == 2
cintos e suspensórios , mas isso não é necessário, poisn
só será diferente de zero ser == 2
.Nota: combinar a
"%n"
não contribui para o valor de retorno.Para ter certeza de que tudo foi
input
usado, teste também seinput[n]
é um caractere nulo ." A maneira mais limpa/correta de distinguir " tais entradas é evitar a
scanf
família de funções.Em vez disso, escreva seu próprio analisador que implemente todas as verificações necessárias.