Dúvida com código simples [RESOLVIDO]

1. Dúvida com código simples [RESOLVIDO]

douglas
dsbonafe

(usa Fedora)

Enviado em 02/09/2014 - 13:45h

Senhores, criei um código que realiza a leitura de um conjunto de nomes de pessoas e os armazena numa matriz denominada Nome[][], utilizando ponteiros. A intenção é apresentar uma utilidade dos ponteiros de forma evidente como apontador. A leitura é finalizada quando a palavra "fim" é digitada.
Entretanto, ao compilar com o gcc e executar no prompt do Windows, ele entra num loop maluco.

Segue o código.
Desde já, grato.


#include<stdio.h>
#include<string.h>

int main(int argc, char** argv){
char Nome[100][30], *Pnome;
Pnome = &Nome[0][0];
printf("\n Digite um nome. Para finalizar digite fim: \t");
scanf("%[^\n]", Pnome);
while(strcmp(strlwr(Pnome), "fim") != 0){
printf("\n Digite o proximo nome. Para finalizar, fim:\t");
scanf("%[^\n]", Pnome);
}
printf("\n *** Dados Lidos: ");
Pnome = &Nome[0][0];
while(strcmp(strlwr(Pnome), "fim") !=0){
printf("\n\t%s", Pnome);
Pnome+=30;
}
printf("\n\n Fim do programa!");
return 0;
}



  


2. Solução

douglas
dsbonafe

(usa Fedora)

Enviado em 02/09/2014 - 17:01h

Não existe mais essa entrada no scanf. Isso é antigo.


#include<stdio.h>
#include<string.h>

int main(int argc, char** argv){
char Nome[100][30], *Pnome;
Pnome = &Nome[0][0];
printf("\n Digite um nome. Para finalizar digite fim: \t");
scanf("%s", Pnome);
while(strcmp(strlwr(Pnome), "fim") != 0){
printf("\n Digite o proximo nome. Para finalizar, fim:\t");
scanf("%s", Pnome);
}
printf("\n *** Dados Lidos: ");
Pnome = &Nome[0][0];
while(strcmp(strlwr(Pnome), "fim") !=0){
printf("\n\t%s", Pnome);
Pnome+=30;
}
printf("\n\n Fim do programa!");
return 0;
}



3. Re: Dúvida com código simples [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 02/09/2014 - 18:24h

dsbonafe escreveu:

Não existe mais essa entrada no scanf. Isso é antigo.


Errado. O formatador “%[...]” em scanf() existe, sim, e é extremamente útil. Se você trocar por “%s”, não vai conseguir ler nomes com espaços.

O problema é que, do jeito como você estava fazendo antes, você não consumia o '\n' no final da linha, e como suas leituras só podiam consumir o que não fosse '\n', o programa realmente entrava em loop.

A forma correta (e completa, você pode não querer tratar todos os casos) de fazer seria o seguinte.

char *Pnome;
int tamanho, tamanho_com_nl;

/* ... */

/*
scanf() retorna no número de conversões bem sucedidas. No caso abaixo, só
há uma conversão ("%29[^\n]"), de modo que o valor de retorno tem de ser igual
a 1. Essa conversão tem o tamanho máximo limitado a 29 caracteres, de modo a
caber nos 30 bytes de cada nome, incluindo o byte nulo após os 29 caracteres
do nome (o byte nulo é gravado na 30ª posição se a string exceder 29 caracteres).

O primeiro "%n" serve para informar o número de caracteres consumidos do buffer
de entrada logo após a conversão da string. O "%*c" serve para consumir o pró-
ximo caráter, que supomos ser um '\n', mas sem o atribur a uma variável. O "%n"
seguinte é um outro medidor de caracteres consumidos, após o consumo do suposto
'\n'. Ele pode ser usado para identificar a falta do '\n', principalmente ao
final do fluxo de entrada.

Note que "%n" não é contado como conversão de entrada, mesmo com scanf() fazendo
atribuição de valores às variáveis apontadas pelos respectivos ponteiros.
*/
if(scanf("%29[^\n]%n%*c%n", Pnome, &tamanho, &tamanho_com_nl)==1){
/* Leitura OK. */
if(tamanho_com_nl>tamanho){
/* '\n' presente e consumido. */
}
else{
/* '\n' ausente. Possível final prematuro do arquivo. */
}
}
else {
/* Erro de leitura */
}



#include<stdio.h>
#include<string.h>

int main(int argc, char** argv){
char Nome[100][30], *Pnome;
Pnome = &Nome[0][0];
printf("\n Digite um nome. Para finalizar digite fim: \t");
scanf("%s", Pnome);
while(strcmp(strlwr(Pnome), "fim") != 0){
printf("\n Digite o proximo nome. Para finalizar, fim:\t");
scanf("%s", Pnome);
}
printf("\n *** Dados Lidos: ");
Pnome = &Nome[0][0];
while(strcmp(strlwr(Pnome), "fim") !=0){
printf("\n\t%s", Pnome);
Pnome+=30;
}
printf("\n\n Fim do programa!");
return 0;
}


O que não existe, pelo menos de acordo com os padrões ISO C e ISO C++, é strlwr(). Isso parece ser um Microsoftismo. E feio: seu digitar o nome "Paulo", essa função vai mudar a string lida para "paulo".

Posso estar muito cego, mas não estou vendo, no loop de leitura, alguma coisa para passar Pnome de um nome para o próximo (algo como o “Pnome+=30”, que existe no loop de impressão). Em todo caso, eu diria que é mais elegante e a prova de erros converter mesmo esse incremento para “Pnome+=sizeof Nome[0]”: desse modo, se você mudar a largura máxima do nome na hora de declarar Nome, não terá de localizar todas as ocorrências de 30 no programa, decidir quais delas se referem a nomes, e alterar as que identificar que o fazem.

Não esqueça de imprimir um '\n' depois da última mensagem do programa. Caso contrário, após o programa terminar, a última linha pode embolar com o prompt do shell ou alguma outra coisa que seja impressa no console por outro programa.






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts