Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
Ezequiel André

C Repetição da última linha do printf

Recommended Posts

Boa noite pessoal. Estou engatinhando em um pequeno projeto em C e não estou com o código fonte todo pronto, estou criando em partes. E já na primeira parte, a que deveria mostrar a lista de itens de um arquivo, a última linha fica repetindo. Estou usando o "fscanf"  para ler do arquivo. Se alguém puder me ajudar a resolver, ou me explicar onde estou errando, agradeço. Segue o código fonte, lembrando que as outras funções eu ainda não implantei.Segue também imagem das telas de execução, só para pré-visualização

 

#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<windows.h>
void gotoxy(int x, int y){
  COORD coord;
  coord.X = x;
  coord.Y = y;
  SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
typedef struct{
	int cod;
	char nome[15];
	float quant;
	float valor;
	float v_total;
	float v_venda;
	float lucro;
}Dados;
int head(){
	for(int i = 0 ; i < 6 ; i++){
		for(int j = 0 ; j < 50 ; j++){
			if(i==0){
				if(j==0){
					printf("%c",201);
				}
				if(j==49){
					printf("%c\n",187);
				}
				else{
					printf("%c",205);
				}
			}
			if(i==5){
				if(j==0){
					printf("%c",200);
				}
				if(j==49){
					printf("%c\n",188);
				}
				else{
					printf("%c",205);
				}
			}
						
		}if(i>1&&i<5){
				printf("%c%50c\n",186,186);
			}
	}
	gotoxy(2,2);
	printf("\tSISTEMA DE GERENCIAMENTO DE ESTOQUE\n\n\n");
	
}
int body(){
	for(int i = 0 ; i < 17 ; i++){
		for(int j = 0 ; j < 50 ; j++){
			if(i==0){
				if(j==0){
					printf("%c",201);
				}
				if(j==49){
					printf("%c\n",187);
				}
				else{
					printf("%c",205);
				}
			}
			if(i==16){
				if(j==0){
					printf("%c",200);
				}
				if(j==49){
					printf("%c\n",188);
				}
				else{
					printf("%c",205);
				}
			}
						
		}if(i>1&&i<16){
				printf("%c%50c\n",186,186);
			}
	}
}
int menu(int *op){
	head();
	body();
	gotoxy(2,6);
	printf("Digite a opcao desejada:");
	int j=1;
	printf("\n\n");
	
	for(int i = 9 ; i < 16 ; i++){
		
		if(i==9){
			gotoxy(2,i);
			printf("%d- Mostrar relatorio do estoque",j);
			j++;
		}
		if(i==10){
			gotoxy(2,i);
			printf("%d- Salvar relatorio do estoque",j);
			j++;
		}
		if(i==11){
			gotoxy(2,i);
			printf("%d- Inserir item no estoque",j);
			j++;
		}
		if(i==12){
			gotoxy(2,i);
			printf("%d- Localizar item no estoque",j);
			j++;
		}
		if(i==13){
			gotoxy(2,i);
			printf("%d- Excluir item do estoque",j);
			j++;
		}
		if(i==14){
			gotoxy(2,i);
			printf("%d- Ajuda",j);
			j++;
		}
		if(i==15){
			gotoxy(2,i);
			printf("%d- Sair",j);
			j++;
		}	
	}
	gotoxy(27,6);
	scanf("%d",&*op);
	system("cls");
	//return *op;
}
int main(){
	Dados dados;
	FILE *txt;
	int opcao;
	
	do{
		menu(&opcao);
		system("cls");
		switch(opcao){
			case 1:{
				head();
				body();
				
				if((txt=fopen("estoque.txt","r"))==NULL){
					printf("Não foi possivel aabrir o arquivo");
				}
				else{
					int i=8;
					gotoxy(1,7);
					printf("COD  NOME     QUANT VALOR VALOR_V VALOR_T  LUCRO");
					while(!feof(txt)){
						fscanf(txt," %d %s %f %f %f %f %f",&dados.cod,&dados.nome,&dados.quant,&dados.valor,&dados.v_venda,&dados.v_total,&dados.lucro);
						++i;
						gotoxy(2,i);
						printf("%d  %s\t%.2f%5.2f%6.2f%9.2f%8.2f",dados.cod,dados.nome,dados.quant,dados.valor,dados.v_venda,dados.v_total,dados.lucro);
					}
				}
					fclose(txt);
					gotoxy(2,6);
					printf("Para sair digite 7:");
					gotoxy(22,6);
					scanf("%d",&opcao);
				
			}
			case 2:{
				printf("tchau");
				break;
			}
		}
	}while(opcao!=7);
	
	gotoxy(1,20);
	return 0;
}

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

O problema é a causa do mal uso de feof devido a um falho de lógica. Muito comumente programadores, na sua amplia maioria novatos, fazem um mal uso do feof, achando que ele tem o comportamento de "averiguar se existe mais dados por ler", quando deveria saber, que o verdadeiro comportamento do feof é: "Que aconteceu com a ultima leitura?".
Suponhamos que seu programa leu todas as linhas do arquivo menos a ultima.

  1. fscanf faz a leitura da ultima linha e não teve problemas, porém já não há mais dados que ler.
  2. i incrementou.
  3. gotoxy foi para (2, i).
  4. printf imprimiu os dados corretamente.
  5. (ponto critico!) feof retorna false pois teve uma leitura exitosa, não encontrou o fim do arquivo.
  6. (ERRO)Repete o laço uma vez mais, pois como falei, feof retornou false, porém agora o fscanf falha, pois não há mais dados que ler pois agora sim foi atingido o EOF que marca o fim do arquivo.
  7. Continuam os erros, i incrementa, e não deveria pois não foram lidos novos dados.
  8. gotoxy foi para (2, i), lembre que o i já não é o mesmo, pois incrementou em 1 e mudou a posição.
  9. printf imprime os mesmos dados que da anterior vez pois desta ultima não foram gravados novos dados, porém os dados antigos continuam na estrutura, e por isso se repete.


Pense nisso.... nesse seu while você pergunta por feof(Atingiu o fim do arquivo?), logo no inicio, antes de ler nada. Como o programa vai saber si atingiu o fim do arquivo se você ainda não leu nada? Entendeu? O feof averigua se a ultima leitura foi exitosa, e não se a seguinte leitura vai ser exitosa, esse é o problema.

Como arrumar isso?
Em vez de usar feof, você pode usar o próprio valor de retorno de fscanf para saber se a leitura foi correta, pois fscanf retorna os seguintes valores conforme os seguintes casos:

Conforme o valor de retorn de fscanf descrito em http://www.cplusplus.com/reference/cstdio/feof/

Citação

Com sucesso, a função retorna o número de itens da lista de argumentos preenchidos com sucesso. Essa contagem pode coincidir com o número esperado de itens ou ser menor (inclusive zero) devido a uma falha correspondente, um erro de leitura ou ter atingido o final do arquivo(EOF).

Se um erro de leitura ocorrer ou o final do arquivo for atingido durante a leitura, o indicador apropriado é configurado (feof ou ferror). E, se qualquer um acontece antes que qualquer dado possa ser lido com sucesso, EOF é retornado.

Se um erro de codificação ocorrer interpretando caracteres amplos, a função define errno para EILSEQ.


fscanf, scanf, printf, etc, são funçoes, funções podem retornar valores, e essas em particular retornam, é conveniente você estudar o valor de retorno dessas funções.

para nosso caso bastaria com mudar essa parte:

 

while(!feof(txt)){
	fscanf(txt," %d %s %f %f %f %f %f",&dados.cod,&dados.nome,&dados.quant,&dados.valor,&dados.v_venda,&dados.v_total,&dados.lucro);
	++i;
	gotoxy(2,i);
	printf("%d  %s\t%.2f%5.2f%6.2f%9.2f%8.2f",dados.cod,dados.nome,dados.quant,dados.valor,dados.v_venda,dados.v_total,dados.lucro);printf
}
Por essa outra:

 

while(	fscanf(txt," %d %s %f %f %f %f %f",&dados.cod,&dados.nome,&dados.quant,&dados.valor,&dados.v_venda,&dados.v_total,&dados.lucro) != EOF ){
	++i;
	gotoxy(2,i);
	printf("%d  %s\t%.2f%5.2f%6.2f%9.2f%8.2f",dados.cod,dados.nome,dados.quant,dados.valor,dados.v_venda,dados.v_total,dados.lucro);printf
}

Com isso a leitura deveria ser feita de forma correta.

Deixo avisado que não provei seu código, ignoro se tem mais erros, me limito a lhe explicar somente o tema da consulta. Caso tiver mais erros exponha em um novo tema, ou incluso neste mesmo post. Faça a prova e me conte se funcionou.
  Editado por vangodp
  • Curtir 2
  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
 

Funcionou perfeitamente. Eu já havia tentado antes colocar o fscanf dentro do whille , mas da seguinte forma:

"while((fscanf(txt,"%d %s%f............., &dados.cod,&.......)!=NULL), mas também não funcionou. 

Agora está tudo certo, Muito obrigado e espero que este post ajude a quem estiver com esta duvida também, por que pesquisei em vários lugares e não achei uma explicação tão boa. 

Muito obrigado

Compartilhar este post


Link para o post
Compartilhar em outros sites

De nada.
Lembre que funções retornam valores, e que se aprender sobre esses valores, você será um melhor programador. Na pagina cplusplus.com, por exemplo(existem outras como cppreference e etc), é uma pagina de referencia e explica o funcionamento de cada função.

É importante destacar que uma função é algo parecido a isso aqui:
mc-01-moedor-de-carne-eletrico-premium-5

Neste caso a função é a maquina de moer carne. Esta maquina(função) aceita carne em pedaços grandes, ou pequenos, ou sei lá >_<(Dados: ints, chars, structs, etc), e pela saída ela retorna(return) a carne moída. Isso pode ser a analogia de uma função perfeitamente, porém não todas as funções fazem a mesma coisa, nem todas as maquinas por suposto. No seguinte caso você pode ver outro exemplo:
258234_1_400.jpg

Neste claro exemplo a "função" aceita os mesmo tipos de dados, porém internamente trabalha de forma diferente, e por suposto retorna outro tipo de dado, que é a lingüiça neste caso, e não carne moída como no caso anterior.

O que eu quero lhe ressaltar, é que você não precisa saber como a função trabalha por dentro, para poder usa-la de forma efetiva somente se precisa saber 3 coisas.

  1. Que tipo de dados aceita.
  2. O que é o que faz(para que serve).
  3. E o que é o que retorna(Em caso de retornar algo claro.)

Com saber esses 3 dados anteriores sobre qualquer função, você será capaz de usa-la de forma efetiva, e é justamente isso para que servem as paginas de referencia, como cplusplus.com por exemplo, entre outras coisas. Essas paginas de referencia lhe ajudam a saber essas 3 coisas sobre qualquer função da biblioteca padrão, e mais.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário






Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×