Ir ao conteúdo

Posts recomendados

Postado

Sempre que esse código entra no 2 loop pra fazer a leitura do vetor ele para de funcionar mas aparentemente não encontro erro algum. Onde posso ter errado? 

#include <stdio.h>
#include <string.h>
#define tf 5 

struct produto {
	int cod;
	char nome[15];
	double preco;
	int qtdade;
};


void leitura (struct produto prod[tf]){
	int i;
	for (i=0;i<tf;i++){
		printf ("\nEntre com o codigo do produto: "); 
		scanf ("%d", &prod[i].cod); 
		
		printf ("\nEntre com o nome do produto: "); 
		fflush (stdin);
		fgets (prod[i].nome,15,stdin);
		
		printf ("\nEntre com o preco do produto: "); 
		scanf ("%lf", &prod[i].preco);
		
		printf ("\nEntre com a quantidade disponivel do produto: "); 
		scanf ("%d", prod[i].qtdade);
		
		printf ("\n\n________________________________\n\n"); 
	}
}

void exibe (struct produto prod [tf]){
	int i;
	for (i=0;i<tf;i++){
		printf ("\nCodigo do produto: %d", prod[i].cod);
		printf ("\nNome do produto: %s", prod[i].nome);
		printf ("\nPreco: %.2lf", prod[i].preco);
		printf ("\nQuantidade: %d", prod[i].qtdade);
		printf ("\n\n______________________________________\n\n");
	}
}

void compra (struct produto prod [tf]){
	int i; 
	int pos = -1;
	int codigo, pedido; 
	
	do {
		printf ("\nQual o codigo do produto que deseja? "); 
		scanf ("%d", &codigo);
		printf ("\nQual a quantidade de produtos que deseja? "); 
		scanf ("%d", &pedido); 
		
		for (i=0;i<tf;i++){
			if (prod[i].cod == codigo)
			pos = i;
		}
		
		if (pos == -1)
		printf ("\nNao achou!"); 
		
		else {
			if (prod[pos].qtdade < pedido)
			printf ("\nQuantidade indisponivel!");
			
			else {
				prod[pos].qtdade = prod[pos].qtdade - pedido; 
				printf ("\nCompra efetuada com sucesso! Novo estoque do produto %s eh de %d", prod[pos].nome, prod[pos].qtdade);
			}
		}
		
	}
	while (codigo != 0);
}


int main (){
	struct produto prod[tf];
	int opcao =0;
	
	while (opcao != 4){
		printf ("\n\n################# MENU ###############");
		printf ("\n1 - Cadastra produtos");
		printf ("\n2 - Exibe produtos");
		printf ("\n3 - Fazer uma compra");
		printf ("\n4 - Sair");
		printf ("\nQual a sua opcao? "); 
		scanf ("%d", &opcao); 
		
		switch (opcao){
			case 1: leitura (prod);
					break; 
			case 2: exibe (prod);
					break;
			case 3: compra (prod);
					break;
			default: 
					printf ("\nOpcao invalida!");
		}
	}
}

 

Postado
34 minutos atrás, Gabbie1 disse:
scanf ("%d", prod[i].qtdade);

 

 

Faltou o & para passar o endereço da variável, ao invés do valor guardado nela, para a função scanf.

 

 

 

E no lugar de fflush(stdin) use algo como:

void limpastdin(){
    int ch;
    while((ch = getchar()) != '\n' && ch != EOF);
}

Ou assim:

for(int ch = getchar(); ch != '\n' && ch != EOF; ch = getchar());

 

  • Obrigado 1
Postado
13 minutos atrás, isrnick disse:

 

Faltou o & para passar o endereço da variável, ao invés do valor guardado nela, para a função scanf.

 

 

 

E no lugar de fflush(stdin) use algo como:

void limpastdin(){
    int ch;
    while((ch = getchar()) != '\n' && ch != EOF);
}

Ou assim:

for(int ch = getchar(); ch != '\n' && ch != EOF; ch = getchar());

 

Obrigada!!

Qual o problema com o fflush? Muita gente me diz pra não usar mas eu não entendo o porque. Sou iniciante, até agora ele não me deu problema. 

O que ele faz exatamente?

Postado

stdin é um stream/fluxo de entrada, mas a função fflush é para esvaziar streams de saída, e tem comportamento indefinido para streams de entrada:

https://en.cppreference.com/w/c/io/fflush

http://www.cplusplus.com/reference/cstdio/fflush/

https://www.geeksforgeeks.org/use-fflushstdin-c/

 

Então, apesar de que em algumas implementações de compilador usar fflush(stdin) vai limpar a stdin, isso não é garantido, então você poderia compilar o mesmo código C com compiladores diferentes no mesmo sistema e funcionar com um mas não usando outro, apesar da função ser parte da biblioteca padrão.

 

Por exemplo, teste esse seu código aqui do tópico em um compilador online:

https://www.onlinegdb.com/online_c_compiler

https://repl.it/languages/c

 

E verá que nesse caso o fflush não limpa a stdin como esperado, resultando que o fgets pega o "\n" como entrada e guarda em prod[ i ].nome .

 

Portanto, não é recomendado usar fflush para limpar stdin pois não há garantia de que vai esvaziar a stdin como se espera.

 

Ou seja, basicamente usar fflush(stdin) é um mau design que pode levar a erros.

  • Curtir 1
Postado
14 minutos atrás, KXSY disse:

Quando você trabalhar com arquivos vai dar problema.

 

ele esvasia o buffer de um arquivo associado (nesse caso e o stdin= standar input= entrada padrão), mandando toda a informação para o arquivo.

há outros arquivos padrões como

stdout=saída padrão (geralmente e o video)

stderr=video

stdin=teclado

você pode notar que o seu teclado não é um arquivo, você não pode abri-lo (No windows até que pode).

Entendi. Deve dar um problemão mesmo 😧

Vou logo tratar de parar de usar, já que tô perto de ter que estudar ponteiros etc

adicionado 2 minutos depois
4 minutos atrás, isrnick disse:

E verá que nesse caso o fflush não limpa a stdin como esperado, resultando que o fgets pega o "\n" como entrada e guarda em prod[ i ].nome .

Por isso eu sempre tinha que declarar minhas strings com 1 caracter a mais senão dava problema. Achei que isso fosse com strings no geral.

  • Haha 1
Postado
Em 18/06/2019 às 19:24, Gabbie1 disse:

Por isso eu sempre tinha que declarar minhas strings com 1 caracter a mais senão dava problema. Achei que isso fosse com strings no geral.

 

O vetor de caracteres precisa ter 1 char a mais que a string para poder armazená-la, pois precisa guardar o caractere nulo '\0', que indica o fim da string, isso é fato para qualquer string:

 

 

Mas estamos falando sobre outra coisa aqui no tópico.

 

Toda vez que você digita algo no terminal (no caso do Windows seria o terminal cmd.exe), como por exemplo "123" e em seguida aperta Enter, é adicionado um caractere nova linha '\n' ao final da sequência de caracteres digitado quando você apertou Enter.

 

Então nesse nosso exemplo a string digitada de fato seria essa "123\n", que contém 4 caracteres não nulos '1', '2', '3', '\n'.

 

Nessa caso um scanf usando especificador %d pegaria os caracteres digitados que são relevantes para ele, os números 123, mas fica sobrando na stdin aquilo que ele não usou, nesse caso o '\n'.

 

Agora, se colocar um fgets logo em seguida terá o problema de que ele vai capturar esse "\n" que ficou sobrando, ao invés de esperar que o usuário digite algo novo.

 

Por isso precisamos limpar a stdin após o scanf e antes do fgets.

  • Obrigado 1

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...