Jump to content
Dexter's Lab

Problema com código par/impar, maior/menor

Recommended Posts

Dexter's Lab

Boas, estou há algum tempo a tentar resolver este problema e estou completamente encravado no porquê de isto me estar a dar estes valores.

O exercício é, primeiro, para receber um limite de valores que se vai digitar.

Depois, o utilizador digita esse numero de valores.

O programa devolve o par maior e menor, o impar maior e menor.

Contudo, para começar, estão a entrar pares para o filtro impar e vice versa. Ou seja, os impares aparecem onde deviam aparecer os pares.

Segundo, não estou a conseguir obter os resultados maiores/menores que deveria.

Gostaria de perceber convosco o que estou a fazer de errado.

# include <stdio.h>

/*Pedir limite de numeros a analisar. Mostra o maior e menor par, o maior e menor impar*/

int maior (int a);
int menor (int b);

int main ()
{
int val, cont, num;
int pmaior, pmenor, imaior, imenor;

pmaior = pmenor = imaior = imenor = 0;

printf ("Limite de numeros a analisar: ");  scanf ("%d",&val);
printf ("\n");

for (cont = 0; cont < val; cont ++) {

	printf ("%d valor: ", cont+1);  scanf ("%d", &num);

	if ((cont%2)==0) {
					 pmaior = maior (num);
					 pmenor = menor (num);
					 }

	else if (!(cont%2)==0) {
						   imaior = maior (num);
						   imenor = menor (num);
						   }
	}

	printf ("\t \t MAIOR \t MENOR \n \n");
	printf ("PARES: \t \t %d \t %d \n", pmaior, pmenor);
	printf ("IMPARES: \t %d \t %d", imaior, imenor);

getche ();
return 0;
}

int maior (int a)
{
int maior = 0;

 if (maior == 0) {
	   maior = a;
	   }
	   else if (a > maior) {
			maior = a;
			}

			return maior;
}

int menor (int b)
{
int menor = 0;

	 if (menor == 0) {
		   menor = b;
		   }
		   else if (b < menor) {
				menor = b;
				}

				return menor;
}

Agradeço a atenção e disponibilidade. Também agradeço a paciência e a pedagogia, uma vez que só programo em C há 1 mês e meio.

Cumprimentos

Edited by Dexter's Lab
Falta LP

Share this post


Link to post
Share on other sites
pmg

So uma ajudita ... o teu problema esta na definicao de "maior".

42 é maior?

Para saberes se um numero é maior que outro tens de comparar os dois numeros.

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Não sei se percebi, porque eu acho que estou a compará-los:

int maior (int a) // recebe o parâmetro para "a"
{
       int maior = 0; // "maior" é 0, para não haverem erros na primeira volta e
                      // receber à vontade o valor do utilizador

        if (maior == 0) {
                  maior = a; // se o maior for 0 (que e o que acontece na primeira
                             // volta) o "maior" recebe o valor que veio de parâmetro
                  }
                  else if (a > maior) {
                               maior = a; //senão (isto é para as voltas seguintes),
                                          // sempre que o valor a for maior que a
                                          // variável "maior", ele atribui-lhe o seu
                                          // valor; de modo a que fica sempre com o
                                          // valor maior
                               }

                               return maior;
}

Edited by pmg
apaguei formatacao, adicionei GeSHi

Share this post


Link to post
Share on other sites
HappyHippyHippo

int maior (int a)
{
 int maior = 0;
 if (maior == 0) { // sim, maior é igual a zero (acabaste de fazer a atribuição)
   maior = a;      // isto é sempre executado
 }
 else {
   // ... irrelevante
 }

 return maior;
}

pensa no que deves comparar e como o fazer


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
pmg

Não sei se percebi, porque eu acho que estou a compará-los:

int maior (int a) // recebe o parâmetro para "a"
{
       int maior = 0; // "maior" é 0, para não haverem erros na primeira volta e
                      // receber à vontade o valor do utilizador

        if (maior == 0) {
                  maior = a; // se o maior for 0 (que e o que acontece na primeira
                             // volta) o "maior" recebe o valor que veio de parâmetro
                  }
                  else if (a > maior) {
                               maior = a; //senão (isto é para as voltas seguintes),
                                          // sempre que o valor a for maior que a
                                          // variável "maior", ele atribui-lhe o seu
                                          // valor; de modo a que fica sempre com o
                                          // valor maior
                               }

                               return maior;
}

Ao fazeres int maior = 0; o programa vai sempre fazer isso. Nao o vai fazer apenas na primeira volta.

Sempre que se executar a funcao maior vai ser 0 e a primeira parte do if sera executada.

A melhor maneira seria passares 2 valores para a funcao ... e guardares informacao sobre o maior ate ao momento na funcao que chama esta.

Ha maneiras de fazer variaves guardarem o valor de uma chamada a funcao para outra, mas isso é um topico mais avancadito

Podes ler, se te interessar, sobre variaveis com o static.

Nota que o identificador maior é usado duas vezes com dois significados diferentes. Fora das funcoes é o nome duma funcao, denro da funcao maior é o nome duma variavel. Habitua-te a nao dar o mesmo identificador a "coisas" com significados diferentes.

Edited by pmg
Informacao sobre static dentro dum spoiler; nota sobre uso duplicado de identificador

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Já resolvi a questão dos pares e ímpares trocados. Eu estava a ler o contador em vez do valor digitado. Erro de distração. Agora a questão do maior/menor é que me está a ser um completo desafio.

int main ()
{
int val, cont, num;
[b]int hlp_1 = 0;[/b]
int pmaior, pmenor, imaior, imenor;

pmaior = pmenor = imaior = imenor = 0;

printf ("Limite de numeros a analisar: "); scanf ("%d",&val);
printf ("\n");

for (cont = 0; cont < val; cont ++) {

printf ("%do valor: ", cont+1); scanf ("%d", &num);

[b]if ((num%2)==0) {[/b]
[b]pmaior = maior (num, hlp_1);[/b]
pmenor = menor (num);
}

...

[b]int maior (int a, int maior_val)[/b]
[b]{[/b]

[b]if (a > maior_val) {[/b]
[b]maior_val = a;[/b]
[b]}[/b]

[b]return maior_val;[/b]

Não entendo. Mesmo assim não vai lá.

O valor só seria 0 no primeiro momento de entrar porque vem de antes e de fora do ciclo. Nos outros já não seria 0, supostamente. Mesmo assim a função não me está a guardar o número mais alto mas sim o último par que encontrou.

Edited by apocsantos
geshi

Share this post


Link to post
Share on other sites
thoga31

Estás a fazer o mesmo... hlp_1 é sempre 0, não estás a comparar se o número inserido pelo utilizador é maior que o que já está definido como maior...

Isto diz-te algo?

if (num > par_maior) par_maior = num;

Edited by thoga31

Knowledge is free!

Share this post


Link to post
Share on other sites
Dexter's Lab

Estás a fazer o mesmo... hlp_1 é sempre 0, não estás a comparar se o número inserido pelo utilizador é maior que o que já está definido como maior...

Isto diz-te algo?

if (num > par_maior) par_maior = num;

O que me está a criar mais dificuldade é o fato de na primeira volta ter de começar o valor com que vou comparar ser 0, para evitar erros de ele comparar aquele valor com um valor qualquer que esteja naquele espaço de memória. O problema é que, depois de o deixar a 0 não consigo com que ele efetue isso somente na primeira volta.

Pensei que se ele tivesse sido declarado fora e antes do ciclo for que já não fosse buscar mais o valor que lhe foi atribuído no início...

Edited by Dexter's Lab

Share this post


Link to post
Share on other sites
pmg

Para alterar o valor duma variavel dentro doutro funcao, tens de passar o endereco da variavel.

Se passas o valor da variavel, qualquer alteracao é local na funcao chamada

Passagem do valor

num = 42;
hlp_1 = 17;
pmaior = maior(num, hlp_1);
// depois da funcao, independentemente do que ela faz
// tanto num como hlp_1 continuam com o mesmo valor de antes.

Passagem do endereco

num = 42;
hlp_1 = 17;
pmaior = maior(num, &hlp_1);
// depois da funcao
// num continua com o mesmo valor de antes
// mas hlp_1 pode ter sido alterado

é claro que a funcao maior deve ser diferente para os dois exemplos de cima

Para o primeiro exemplo o prototipo deve ser int maior(int, int);

e para o segundo exemplo deve ser int maior(int, int *);

Edited by pmg
prototipo

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Para alterar o valor duma variavel dentro doutro funcao, tens de passar o endereco da variavel.

Se passas o valor da variavel, qualquer alteracao é local na funcao chamada

Passagem do valor

num = 42;
hlp_1 = 17;
pmaior = maior(num, hlp_1);
// depois da funcao, independentemente do que ela faz
// tanto num como hlp_1 continuam com o mesmo valor de antes.

Passagem do endereco

num = 42;
hlp_1 = 17;
pmaior = maior(num, &hlp_1);
// depois da funcao
// num continua com o mesmo valor de antes
// mas hlp_1 pode ter sido alterado

é claro que a funcao maior deve ser diferente para os dois exemplos de cima

Para o primeiro exemplo o prototipo deve ser int maior(int, int);

e para o segundo exemplo deve ser int maior(int, int *);

Ah! Era provavelmente o ingrediente que me faltava. Não conhecia isso. Na verdade eu ainda não aprendi funções sob orientação do meu professor. Apenas andei a pesquisar e treinar durante as férias as passagens de parâmetros e sub-procedimentos para poder chegar à escola já preparado nessa matéria. Pensei que funções se resumissem muito apenas a isso. Afinal não. São estes toques que me fascinam na programação.

Muito obrigado, pessoal, pelo conhecimento.

Pmg, onde posso ler específicamente sobre isso (endereço de memória (&))? Aconselhas-me alguma peça literária que contenha atenção a esse fator ou algum artigo na net? Sempre o usei no Scanf, mas pensei que fosse próprio dessa função e não um elemento essencial em todo o C. Espectacular, se me permitem a opinião.

Share this post


Link to post
Share on other sites
pmg

O nome usual para este tipo de passagem de parametros (com o &) é "passagem por referencia".

Se nao te importares de veres montanhas de coisas relacionadas com C++ pesquisa por "pass by value" e "pass by reference".

Nota que o conceito de referencia é bastante mais abrangente em C++ do que em C (eu nao sei C++, por isso interpreta este paragrafo com um pé atras).

Em C, todos os parametros sao passados por valor (ou o valor proprio da variavel ou o valor do endereco de memoria onde essa variavel reside).

O assunto relacionado com o operador & é o assunto de ponteiros. Talvez seja melhor esperares pelo professor para teres um apoio mais proximo quando comecares a mexer com ponteiros.

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

pelas razões acima referidas, o que deverias usar para concretizar o teu problema seria o uso do valor de retorno

int maior_par(int valor, int maior_actual)
{
 if (valor % 2 == 0)
 {
   if (valor > maior_actual)
   {
     return valor;
   }
 }

 return maior_actual;
}

int main()
{
 // ...
 pmaior = maior_par(valor, pmaior);
 // ...
}

depois de teres o código a funcionar (mais ou menos) apresenta o que tens porque poderão existir casos particulares onde verás tudo a dar bronca


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Dexter's Lab

Boas, só vi novamente este tópico agora.

Acabei por concluir o programa hoje de manhã, por enquanto, sem funções - que teria sido logo de início muito fácil.

Mostro-vos já como está pois agora quero trabalhá-lo para ter funções, que esse sim será para mim o desafio.

Se no entanto tiverem alguma indicação e crítica agradecerei. Peço-vos que sejam chatos nesse sentido.

# include <stdio.h>

/*Pedir limite de numeros a analisar. Mostra o maior e menor par, o maior e menor impar*/

int main ()
{
int val, cont, num;
int pmaior = 0, pmenor;
int imaior = 0, imenor;

printf ("Limite de numeros a analisar: "); scanf ("%d",&val);
printf ("\n");

for (cont = 0; cont < val; cont ++) {

printf ("%do valor: ", cont+1); scanf ("%d", &num);

if ((num%2)==0) {
if (pmaior == 0) {
pmenor = num;
}
else if (num < pmenor) {
pmenor = num;
}

if (num > pmaior) {
pmaior = num;
}
}

else if (!(num%2)==0) {
if (imaior == 0) {
imenor = num;
}
else if (num < imenor) {
imenor = num;
}

if (num > imaior) {
imaior = num;
}
}
}

printf ("\t \t MAIOR \t MENOR \n \n");
printf ("PARES \t \t %d \t %d \n", pmaior, pmenor);
printf ("IMPARES \t %d \t %d", imaior, imenor);

getche ();
return 0;
}

Há algo a fazer para melhorar o código antes de avançá-lo para funções?

Edited by pmg
correcao ao GeSHi

Share this post


Link to post
Share on other sites
pmg

Se no entanto tiverem alguma indicação e crítica agradecerei. Peço-vos que sejam chatos nesse sentido.

...

Há algo a fazer para melhorar o código antes de avançá-lo para funções?

Indentacao: escolhe um estilo de indentacao e usa-o

Nao compliques as condicoes logicas

if (!(num % 2) == 0)

pode ser escrito assim, com o operador "diferente de"

if ((num % 2) != 0)

Edited by pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

quais os valores de menores que te aparecem ?

se meter valores negativos, quais os valores maiores que te aparecem ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Dexter's Lab

Existe muita diferença entre colocar (!(num%2)==0), ((num%2)==1), ((num%2)!=0)?

Em que situações se usa então o operador lógico NOT?

Em relação à Indentação, o meu código está colocado, mas no copy paste e porque o coloquei em Código ficou assim chegado à esquerda.

HHHippo, neste teste este foi o output:

Limite de numeros a analisar: 8

1o valor: 8

2o valor: 7

3o valor: -3

4o valor: -2

5o valor: -45

6o valor: 8

7o valor: 78

8o valor: -23

MAIOR MENOR

PARES 78 -2

IMPARES 7 -45

Share this post


Link to post
Share on other sites
HappyHippyHippo

Existe muita diferença entre colocar (!(num%2)==0), ((num%2)==1), ((num%2)!=0)?

Em que situações se usa então o operador lógico NOT?

o resultado é igual, a diferença na na legibilidade do código

HHHippo, neste teste este foi o output:

desculpa, testa com todos negativos


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
pmg

E se meteres so valores negativos (nem zero nem nada acima de zero)?

Em que situações se usa então o operador lógico NOT?

Eu gosto de "ler" o codigo tal e qual como se fosse portugues (ou ingles). A expressao if (!(a == 0)) ... e lida mais ou menos assim: "se a nao for igual a zero"; eu prefiro ler "se a for diferente de zero" if (a != 0) ...

Um exemplo onde o operador NOT se pode aplicar muito logicamente e com funcoes que devolvem um valor booleano

if (!isblank(ch)) // se ch nao for um espaco em branco

ou para "inverter" condicoes compostas

if (!((100 <= a) && (a <= 999))) // se a estiver fora do intervalo 100 a 999


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
Dexter's Lab

Bem observado. Como estão iniciados a zero é isto que resulta.

Limite de numeros a analisar: 6

1o valor: -6

2o valor: -78

3o valor: -9

4o valor: -4

5o valor: -35

6o valor: -6

MAIOR MENOR

PARES 0 -6

IMPARES 0 -35

Penso que já resolvi. Eis a mudança que fiz no código tanto para o par como para o ímpar:

		if ((num%2)==0) {
					 if (pmaior == 0) {
							   pmenor = num;
							   }
							   else if (num < pmenor) {
									pmenor = num;
									}

					 if (num > pmaior) {
							 pmaior = num;
							 }
[b]						 else if (pmaior == 0 && num < pmaior) {[/b]
[b]								 pmaior = num;[/b]
[b]								 }[/b]

					 }

Novo teste:

Limite de numeros a analisar: 6

1o valor: -2

2o valor: -7

3o valor: -8

4o valor: -78

5o valor: -9

6o valor: -1

MAIOR MENOR

PARES -2 -78

IMPARES -1 -9

Share this post


Link to post
Share on other sites
pmg

So para ser mauzinho (LOL): testa com os seis numeros -1 0 1 2 3 4 :)


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

Vou procurar resolver.

empurrãozinho : como sabes que o valor pmaior ou pmenor ou imaior ou imenor contem um valor inserido ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
Dexter's Lab

Já me apareceu corretamente o menor sendo 0 e os outros valores corretos também.

	else if ((num%2)!=0) {
					[b] if (iaux == 0) [/b]{
							   imenor = num;
[b]								   iaux++;[/b]
							   }
							   else if (num < imenor) {
									imenor = num;
									}

					 if (num > imaior) {
							 imaior = num;
							 }
[b]								 else if (iaux == 0 && num < imaior) {[/b]
							 iaux++;
							 imaior = num;
							 }
					 }

Adicionei outra variável que tomou lugar ao pmaior/imaior com a referência do 0 para demarcar a primeira volta.

Assim o programa já não vbloqueia o 0 de pertencer aos pares.

empurrãozinho : como sabes que o valor pmaior ou pmenor ou imaior ou imenor contem um valor inserido ?

Neste momento, na primeira volta nenhum o tem. Apenas o auxiliar tem o valor de 0.

A cada volta que recolhe numeros pares e impares empurra-os para a variável correspondente e mantêm-se até ser empurrado um novo numero par/impar, superior/inferior.

Não sei se era aqui que querias chegar. Desculpa se não era.

Share this post


Link to post
Share on other sites
HappyHippyHippo

estás a ir bem, mas agora testa estes valores :

1 3 5 7 -4 9

deveria aparecer :

pmenor = -4

pmaior = -4

imenor = 1

imaior = 9

no entanto, parece-me que irá aparecer

pmenor = -4

pmaior = 0

imenor = 1

imaior = 9


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
thoga31

@Dexter's Lab, a inicialização deverá ser feita com o primeiro valor inserido. É isto que te está a faltar. Depois disso é que se faz o ciclo com comparação.

pmaior = pmenor = imaior = imenor = num;
for(i = 1; i < total; i++) { // etc...

Não podes começar com o valor 0, se não há sempre os problemas que te têm aparecido com os inputs que te têm proposto.

  • Vote 1

Knowledge is free!

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.