Ir ao conteúdo
  • Cadastre-se

C Repetição da última linha do printf


Ezequiel André

Posts recomendados

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
Link para o comentário
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.
 
  • Curtir 2
  • Obrigado 1
Link para o comentário
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

Link para o comentário
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.

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...