paulo1205
(usa Ubuntu)
Enviado em 20/05/2015 - 20:32h
Thihup escreveu:
Sim, Paulo, também achei muito estranho quando eu ajudei ele em outro tópico[1]. Ele não quis alterar pois eu imagino que foi um trabalho "Copy-Paste", ou escreveu para teste. Mesmo assim, ele não quis utilizar o '[^\n]'. Mas fazer o que? Não podemos forçar ninguém a fazer nada contra a sua vontade, então tá certo ;)
A sua alteração não corrigiu a questão do "s" que está sobrando depois do "%[^,]" (ou do "%[^\n]", na sua versão). A rigor, ele vai fazer com que a string de formatação nunca seja totalmente encontrada.
Os colchetes e o que vai entre eles não são uma espécie de prefixo da conversão
%s . Antes,
%[ é um outro tipo de conversão, com regras bem diferentes da conversão
%s .
Além do mais, o correto seria sempre testar o valor de retorno de
scanf (), para saber se ela conseguiu fazer todas as conversões. O Ubuntu, por exemplo, vem com o GCC configurado de modo tal que o compilador emite avisos (e às vezes dá erro) se você usar
scanf () sem jogar o valor retornado numa variável ou usá-lo como parte da expressão em um
if ou
while .
Mas mesmo isso nem sempre é suficiente para saber se houve uma correspondência exata entre a string de formatação e os caracteres consumidos da entrada de dados. Por exemplo, os caracteres consumidos mas que não sejam parte de uma conversão com atribuição de valor (e.g. espaços que sejam pulados, caracteres usados como delimitadores e dados consumidos em conversões com atribuição suprimida por meio do prefixo "*") não são refletidos no valor retornado pela função. Algumas vezes, é necessário usar a atribuição
%n (que é uma atribuição que não consome caracteres da entrada e, portanto, não é considerada uma conversão e também não é conta para o valor de retorno da função) para identificar a efetivação de certas partes da verificação da string de formatação.
Por exemplo, os dois blocos de código abaixo produzem o mesmo efeito final.
int skip_and_count_spaces(void){
int ch, n_spaces;
n_spaces=0;
while(isspace(ch=getchar()))
n_spaces++;
if(ch!=EOF)
unget(stdin, ch); /* Devolve o não-espaço para o buffer de leitura. */
else if(n_spaces==0)
return -1; /* Indica erro de leitura com valor negativo. */
return n_spaces;
}
int skip_and_count_spaces(void){
int n_spaces, result;
n_spaces=0;
result=scanf(" %n", &n_spaces);
/*
Não há nenhuma conversão, então result só pode
valer 0 ou EOF.
*/
if(result==EOF || (n_spaces==0 && feof(stdin))
return -1; /* Indica erro de leitura com valor negativo. */
return n_spaces;
}
Este outro par de códigos também faz a mesma coisa.
char buffer[80];
if(fgets(buffer, sizeof buffer, stdin)==NULL){
if(feof(stdin))
fprintf(stderr, "Fim de arquivo antes de começar a ler.\n");
else
fprintf(stderr, "Erro de leitura.\n");
}
else{
int length=strlen(buffer);
if(buffer[length-1]=='\n'){
if(length==1)
printf("Leu linha vazia (apenas o '\\n').\n");
else
printf("Leu linha completa com %d caracteres (incluindo '\\n').\n", length);
}
else if(length+1<sizeof buffer){
if(feof(stdin)){
printf("EOF prematuro após ler com sucesso %d caracteres.\n", length);
else
printf("Leitura interrompida após %d caracteres.\n", length);
}
else{
printf("Tamanho da linha excedeu tamanho do buffer.\n");
}
}
char buffer[80], fmt_string[30];
int result, consumed, consumed2;
/*
Gera uma string de formatação para scanf() com a cara
"%@[^\n]%n%*1[\n]%n", onde "@" é substituído pelo tamanho
máximo da string que buffer pode conter.
*/
sprintf(fmt_string, "%%%zd[^\n]%%n%%*1[\n]%%n", (sizeof buffer)-1);
consumed2=consumed=0;
result=scanf(fmt_string, buffer, &consumed, &consumed2);
if(result!=1){
if(feof(stdin))
fprintf(stderr, "Fim de arquivo antes de começar a ler.\n");
else
fprintf(stderr, "Erro de leitura.\n");
}
else{
if(consumed2>consumed){
if(consumed2==1)
printf("Leu linha vazia (apenas o '\\n').\n");
else
printf("Leu linha completa com %d caracteres (incluindo '\\n').\n", consumed2);
}
else if(consumed+1<sizeof buffer){
if(feof(stdin)){
printf("EOF prematuro após ler com sucesso %d caracteres.\n", consumed);
else
printf("Leitura interrompida após %d caracteres.\n", consumed);
}
else{
printf("Tamanho da linha excedeu tamanho do buffer.\n");
}
}
No meu dia a dia, quando pessoas me ofendem, eu finjo-me de bobo, mas... Não deixo passar!
Cara, na boa... Essa sua nova mensagem final é até pior que a anterior. Seria melhor -- para você mesmo! -- deixar os choramingos e as ameaças não tão veladas de lado. Se você tiver algum problema pessoal para resolver, resolva-o fora do espaço público do fórum.