paulo1205
(usa Ubuntu)
Enviado em 18/06/2019 - 22:33h
Prezado,
Se você tem valores separados por espaços, então a conversão
"%s" só vai ler um valor, pois ela só recebe caracteres que não sejam considerados espaços.
scanf () é uma função complexa. Eu recomendo fortemente que você leia sua documentação com bastante atenção, pois há algumas conversões que descartam espaços, outras que não o fazem e meios de forçar o descarte de espaços mesmo que não haja conversão nenhuma, formas de usar a sintaxe de uma conversão sem gravar valor em variável nenhuma, meios de requerer um texto arbitrário, maneiras de medir quantos caracteres foram consumidos e o grau de sucesso das conversões realizadas.
Se quiser ler linhas inteiras, a maneira mais simples é usar
fgets (). Alternativamente, aprenda a usar a conversão
"%[" de
scanf (), mas saiba desde já que ela dá mais trabalho (abaixo eu mostro um exemplo de uso de
"%[" ).
strtok () serve para separar pedaços de uma
string , procurando por separadores entre os
tokens e retornando um ponteiro para o próximo
token que tenha sido separado com sucesso, mas modificando a
string original.
Como sua leitura só pegou um valor, já que a conversão com
"%s" já não aceitou receber espaços, o uso de
strtok () no seu programa foi inútil. Se você passar a usar
fgets () numa linha que realmente inclua espaços, pode ser que faça mais sentido. O exemplo abaixo mostra o uso de
fgets () junto com
strtok ().
#define MAX_LINE_LENGTH 1024
char line[MAX_LINE_LENGTH];
if(fgets(line, sizeof line, stdin)==NULL){
fprintf(stderr, "Erro de leitura. Abortando programa.\n");
exit(1);
}
int i=0;
char *token=strtok(line, " \t"); // Utiliza espaço ou tabulação como separadores entre os tokens;
while(token!=NULL){
printf(" %dº token: \"%s\".\n", ++i, token);
token=strtok(NULL, " \t");
}
Entretanto, se você já souber de antemão que o(s) valor(es) a ser(em) lido(s) é(são) um() numérico(s), pode já chamar
scanf () com especificador(es) de conversão(ões) numérica(s). O bloco abaixo mostra um exemplo que espera ler linhas inteiras compostas por dois valores numéricos e uma
string , separados entre si por espaços, mas depois do início da
string , outros espaços que ocorram antes do fim da linha serão considerados partes da
string , de modo que uma linha com a forma “
5.29 2 leite condensado ” produz elementos com valores
5.29 ,
2 e
"leite condensado" , respectivamente.
double d;
int i;
char nome[50];
// ‘a’, ‘b’ e ‘c’ são contadores de caracteres consumidos na chamada a scanf().
int a, b, c;
// Tenta ler uma linha na forma “valor_double valor_inteiro string_(incluindo_possíveis_espaços) \n” ('\n' é a marca de fim de linha).
// Eu uso ‘a’ para medir a quantidade de caracteres consumidos antes de ler o nome, ‘b’ para os caracteres consumidos após o nome, e ‘c’ para
// ver se a marca de fim de linha estava presente ou não (para tanto, uso três pseudo-conversões "%n" ). O valor de retorno da função é o
// número de conversões (não incluindo pseudo-conversões e conversões com atribuição suprimida com "*" ). Se a>0 e b>0, o valor de b-a
// corresponderá ao comprimento da string lida. Se c==0, significa que faltou a marca de fim de linha, sugerindo que o texto pode ter ficado
// truncado (linha longa demais, se b-a==49, ou erro de leitura, se b-a<49).
a=b=c=0;
if(scanf("%lf %d %n%49[^\n]%n%*1[\n]%n", &d, &i, &a, nome, &b, &c)<3 || b<=a){
/* Erro de leitura: formato inesperado. */
// Dá algum tratamento ao erro de formato.
}
else if(c<=b){
/* Faltou a marca de fim de linha. */
if(a-b==49){
/* Usuário digitou mais do que 49 caracteres antes de apertar <Enter>. */
// Dá o tratamento adequado.
}
else{
/* String menor quee 49 caracteres: pode ser por fim de dados ou por erro, e pode até ser aceitável para você. */
// Dá o tratamento adequado.
}
}
else{
/* Leu tudo, incluindo o fim de linha. */
// Usa os valores lidos.
}
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)