• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

FDomingos

Ordenar números

14 mensagens neste tópico

Tenho de fazer um programa em C,que peça 3 números inteiros e os escreva por ordem decrescente de valor.

O programa deverá utilizar o procedimento ordenaTresiInteiros (int *x,int*y,int*z) para efectuar a ordenação dos valores das variáveis e o procedimento trocaInteiros (int *x, int*y) para efectuar as trocas necessárias.

Até agora, já fiz isto:

#include <stdio.h>
int ordenaTresInteiros (int,int,int);
int trocaInteiros (int,int);
int x,y,z;
void main()
{
printf ("Introduza três números inteiros\n");
scanf ("%d,%d,%d, &x,&y,&z);
ordenaTresInteiros (x,y,z));
printf ("Os tres numeros ordenados sao %d %d %d",x,y,z);
}

int ordenaTresInteiros (x,y,z)
{
int y1;
if (x>y)
	trocaInteiros(x,y);
if (z>x){
	y1=y;
	y=z;
	trocaInteiros(x,y);
	z=y1;
return 0;
}

Mas dá erros, e ainda não os consegui descobrir.

Agradecia a vossa ajuda.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tens o scanf mal construído, não fechaste as aspas.  E tens que passar os endereços de x y e z à função ordenaTresInteiros.

Depois faltam-me os tipos dos argumentos no cabeçalho da função ordenaTresInteiros, olha para o enunciado que deste e copia o que está entre parêntesis ;)

Isto deve tratar dos problemas de sintaxe. Depois tens que rever o que estás a fazer no 2º if da ordenaTresInteiros.  E não te esquças de implementar a função trocaInteiros!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Boas pessoal,

desculpem estar a trazer este post antigo ao decima, mas é mesmo este exercício que eu estou agora a fazer e já há umas 2 horas que ando ás marteladas para o resolver.

Não é de uma importância capital, mas estou a fazer revisões e não gosto de deixar exercícios inacabados para trás.

Actualmente estou neste ponto :

#include <stdio.h>
#include <stdlib.h>

void ordenaTresInteiros (int *x, int *y, int *z)
{
if (*x<*y)
   trocaInteiros(&x,&y);
if (*y<*z)
   trocaInteiros(&y,&z);
if (*x<*y)
   trocaInteiros(&x,&y);
}

void trocaInteiros (int *x, int *y)
{
int aux;
aux = *x;
*x = *y;
*y = aux;
}

int main(){
int x, y, z;
printf("Introduza três inteiros: \n");
scanf("%d%d%d", &x, &y, &z);
ordenaTresInteiros (&x, &y, &z);
printf("\n%d / %d / %d\n", x, y, z);
return 0;
}

Parece que tenho tudo e não deixei erros de síntaxe, o erro muito provávelmente está nos endereços mas não consegui acertar no escrita certo e é um tema que não domino muito.

O exercício pedia também de definir os sub-programas como "int trocaInteiros ( int * x, int * y)" mas como não devolvem nada, achei mais lógico e limpo definí-los como void. Está errado ?

Basicamente o programa funciona, ele troca os endereços, mas no fim, imprime o resultado sem alteração,... não entendo o que me falta.

Se alguem poder dar uma ajudinha, agradecia muito ! :)

Artur.

Editado por pmg
GeSHi
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

tens dois problemas:

- estás a chamar uma função ainda não declarada : "trocaInteiros" dentro da função "ordenaTresInteiros"

- o que estás a enviar para o função "trocaInteiros" não são ponteiros para inteiros mas sim ponteiros para ponteiros para inteiros

>> eleva o nível de mensagens de warning do teu compilador !!!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

tens dois problemas:

- estás a chamar uma função ainda não declarada : "trocaInteiros" dentro da função "ordenaTresInteiros"

- o que estás a enviar para o função "trocaInteiros" não são ponteiros para inteiros mas sim ponteiros para ponteiros para inteiros

>> eleva o nível de mensagens de warning do teu compilador !!!

Hehe, resultou !! Um grande obrigado mesmo !

Pois, o que dizes faz todo o sentido agora que está à frente dos olhos. Ainda vou ter de andar muito tempo ás cabeçadas para isto se tornar mais automático.

O detalhe dos ponteiros para os ponteiros para inteiros nunca lá ia chegar mas mal li o comentário até "doeu" de tão óbvio que é.

Mais uma vez obrigado.

No conheço isso do nível de warning mas vou fazer uma pesquisa. Agradecido ! Actualmente utilizo o CodeBlocks com o Gnu gcc e não conheço mais nada :-X.

Deixo aqui o programa a funcionar, caso no futuro mais alguem venha a fazer pesquisa no google para a solução, como eu fiz.

#include <stdio.h>
#include <stdlib.h>

void trocaInteiros (int **x, int **y)
{
int aux;
aux = **x;
**x = **y;
**y = aux;
}

void ordenaTresInteiros (int *x, int *y, int *z)
{
if (*x<*y)
   trocaInteiros(&x,&y);
if (*y<*z)
   trocaInteiros(&y,&z);
if (*x<*y)
   trocaInteiros(&x,&y);
}

int main(){
int x, y, z;
printf("Introduza três inteiros: \n");
scanf("%d%d%d", &x, &y, &z);
ordenaTresInteiros (&x, &y, &z);
printf("\n%d / %d / %d\n", x, y, z);
return 0;
}

Editado por pmg
Falta LP
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

flag do gcc para elevar o nível de warnings : -Wall

o código :

#include <stdio.h>
#include <stdlib.h>

// nada de ** ...
void trocaInteiros (int *x, int *y) {
 int aux;
 aux = *x;
 *x = *y;
 *y = aux;
}

void ordenaTresInteiros (int *x, int *y, int *z)
{
if (*x<*y) trocaInteiros(x,y); // <-- enviar somente o ponteiro
if (*y<*z) trocaInteiros(y,z); // <-- enviar somente o ponteiro
if (*x<*y) trocaInteiros(x,y); // <-- enviar somente o ponteiro
}

int main(){
 int x, y, z;

 printf("Introduza três inteiros: \n");
 scanf("%d%d%d", &x, &y, &z);

 ordenaTresInteiros (&x, &y, &z);

 printf("\n%d / %d / %d\n", x, y, z);

 return 0;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já encontrei a opção para activar o -Wall. Obrigado ! :D

Sim, efectivamente, estaria a enviar para o trocaInteiros o "endereço do ponteiro do inteiro" o algo assim do genero, não ?

Estranho que tambem funciona-se sem dar qualquer erro :-/.

Obrigado pela dica !

Maravilha de forum em que o pessoal explica o porquê das coisas sem mandar logo vir com um gajo :).

Abraço,

Artur.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Estranho que tambem funciona-se sem dar qualquer erro :-/.

não estava programaticamente errado

estava até correcto e fazia o pretendido, no entanto tinhas isto no teu post inicial :

O exercício pedia também de definir os sub-programas como "int trocaInteiros ( int * x, int * y)"

logo terás de seguir o protótipo da função, mesmo ignorando o valor de retorno

Maravilha de forum em que o pessoal explica o porquê das coisas sem mandar logo vir com um gajo :).

eu não sou a pessoa mais indicada a se dizer isso, eu sou das pessoas que manda vir com as outras. depende sempre do tipo de questão e/ou a forma que a questão é esposta

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Relativamente ao prototipo : "int trocaInteiros ( int * x, int * y)"

Foi o que me baralhou mais, não consegui entender o que é que pretendia retornar.

Não me parecia fazer sentida enviar os ponteiros e depois pedir algo de volta. Se eu bem percebi o principio dos ponteiros é precisamente para não se ter e recuperar nada, já que ele vai alterar directament a informação no seu "endereço" na RAM. Ou pelo menos isto é o meu nível actual de comprensão da coisa....

Cheguei a um ponto em que experimentei um "Return *x, *y;" que o compilador não me deu como errado. Mas depois não sabia como recuperar duas variáveis diferentes,... isso é mesmo possivel ? Ou o compilador só deixo passar por ter o nível de warning demasiado baixo ?

Por fim, finalmente cheguei ao "return 0;" mas aí parecia estar errado... porque é que me vão pedir para utilizar o type INT para não revolver nada ? Devia ser mesmo o propósito do exercício.

Relativamente a mandar vir com os outros, português não é a minha primeira lingua, mando bítaques a torto e a direito, faço perguntas de íniciante que não entende visivelmente nada (tenho consciencia disso :D) num forum onde ainda nem sequer me apresentei. No entanto sempre foste solicito, para mim é 5 estrelas :D.

O

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

o valor de retorno é normalmente usado não para devolver dados mas sim para sinalizar uma operação correcta. isto pelas duas seguintes razões

- limite de retorno de um único valor (se bem que pode ser de qualquer tipo)

- inexistência de um modelo de padronizado de gestão de erros na linguagem

devido a estas limitações da linguagem, é normal (e irás ver em muitos locais) este tipo de abordagem ao problema

o código completo para a função seria:

int trocaInteiros (int *x, int *y)
{
 int aux;

 if (x == NULL || y == NULL)
   return -1;

 aux = *x;
 *x = *y;
 *y = aux;

 return 0;
}

int main()
{
 int x = 11, y = 22;

 printf("valores iniciais de x e y : %d %d\n", x, y);

 if (trocaInteiros(&x, NULL) != 0)
 {
   printf("Erro na troca de valores : um ou mais dos ponteiros passados como argumento é invalido");
   return -1;
 }

 printf("valores finais de x e y : %d %d\n", x, y);

 return 0;
}

isto parece ser código estúpido e sem sentido porque ninguém iria escrever o que apresentei, no entanto é somente um exemplo do uso do valor de retorno para confirmação do sucesso da operação. isto porque, como deves perceber, isto não passa de um exemplo académico onde nos casos reais, este tipo de problemas é algo que aparece em cada 5 minutos

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sei que off-topic, mas queria realcar algo em relacao ao troca numeros, assim como forma mais rapida e eficiente de inicializar uma variavel a zero e atraves do Xor daquela variavel com ela mesmo (e o que o C# faz quanda declara-se uma variavel e ela nao e inicializada), a forma mais eficiente e rapida de trocar o valor de duas variaveis seria fazer o Xor delas sem a necissidade de um terceira variavel auxiliar.

O troca numeros podia ficar em algo como:

int trocaInteiros (int *x, int *y)
{
   if (x == NULL || y == NULL) return -1;

   *x ^= *y;
   *y ^= *x;
   *x ^= *y;

   return 0;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

if (trocaInteiros(&x, NULL) != 0)

//Aqui estás a enviar o ponteiro de x, e e um valor nulo. Mas é o único sitio onde fazes uma chamada ao sub-programa,... logo em nenhum caso envia o ponteiro do y para o sub-programa ? Ou estou a ver mal ?

if (x == NULL || y == NULL)

return -1;

//Logo, ele vai SEMPRE devolver -1,.... não ?

###############

Sei que off-topic, mas queria realcar algo em relacao ao troca numeros, assim como forma mais rapida e eficiente de inicializar uma variavel a zero e atraves do Xor daquela variavel com ela mesmo (e o que o C# faz quanda declara-se uma variavel e ela nao e inicializada), a forma mais eficiente e rapida de trocar o valor de duas variaveis seria fazer o Xor delas sem a necissidade de um terceira variavel auxiliar.

O troca numeros podia ficar em algo como:

int trocaInteiros (int *x, int *y)
{
if (x == NULL || y == NULL) return -1;

*x ^= *y;
*y ^= *x;
*x ^= *y;

return 0;
}

Não conhecia essa.... básicamente, ele altera o valor, mas o valor de base ainda fica acessivel até ao fim do sub-programa, certo ?

Isso funciona tudo no stdio.h ?

Editado por Artur551
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

@Artur551 quando estas a postar codigo utiliza a tag para codigo <>.

Quando invocamos :

trocaInteiros(&x, &y);

estamos a passar a referencias para as variaveis x e y e nao os seus ponteiros, acho que e melhor fazeres as distincoes das nomenclaturas para nao

confudires no futuro.

Nao, nao precisas do incluir nada para usufruires deste operador ele e built-in, assim como nao precisas incluir nenhum ficheiro ou fazer a linkagem de nenhuma biblioteca para usufruires das estruturas de controlo e outros operados (logicos e relacionais).

Editado por eatg75
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

//Aqui estás a enviar o ponteiro de x, e e um valor nulo. Mas é o único sitio onde fazes uma chamada ao sub-programa,... logo em nenhum caso envia o ponteiro do y para o sub-programa ? Ou estou a ver mal ?

isto parece ser código estúpido e sem sentido porque ninguém iria escrever o que apresentei, no entanto é somente um exemplo do uso do valor de retorno para confirmação do sucesso da operação. isto porque, como deves perceber, isto não passa de um exemplo académico onde nos casos reais, este tipo de problemas é algo que aparece em cada 5 minutos

Editado por HappyHippyHippo
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora