Ir ao conteúdo
  • Cadastre-se

C Struct em C, Loop


Gabbie1

Posts recomendados

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!");
		}
	}
}

 

Link para o comentário
Compartilhar em outros sites

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
Link para o comentário
Compartilhar em outros sites

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?

Link para o comentário
Compartilhar em outros sites

42 minutos atrás, Gabbie1 disse:

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.

Quando você trabalhar com arquivos vai dar problema.

 

43 minutos atrás, Gabbie1 disse:

O que ele faz exatamente?

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

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

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 2
Link para o comentário
Compartilhar em outros sites

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 2
Link para o comentário
Compartilhar em outros sites

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