Ir para o conteúdo
StraightEdge

Arrays bidimensionais

Mensagens Recomendadas

StraightEdge

Tenho que fazer um projecto, utilizando arrays bidimensionais, com o seguinte menu:

1 - Introduzir dados

2 - Visualizar dados

3 - Retificar a idade/altura dado o número do aluno

4 - Média de idades da turma

5 - Média de alturas da turma

6 - Número de alunos com mais de 16 anos com altura inferior à média

7 - Número de alunos com idade superior à media de idades

8 - Aluno mais alto

9 - Sair

Ora bem, os projectos costumam correr-me sempre bem.

Por exemplo, naquele sobre o Euro Milhões que postei aqui, reformulei por completo e consegui um 18.

Mas não sei o que se passa com este, que nada me dá certo. Nem sequer a leitura de dados.

Program ficha5 ;
Var
IdAlt : array [1..2,1..30] of Integer ;
idade , altura , op , n , ret , somamed , somamedd , conta , max , aux: Integer ;
totalmed, totalmedd : Real ;

Procedure LerDados ;
Begin
Writeln('Introduza o número de alunos');
Readln(n);

For idade := 1 To n Do
Begin
 For altura := 1 To n Do
 Begin
 Writeln('Introduza a idade e altura do ', idade ,' aluno');
 Readln(IdAlt[idade,altura]);
 End ;
End ;
ClrScr;
End ;

Procedure VerDados ;
Begin
aux := 0 ;
Writeln('Nr Id Alt');
For idade := 1 To n Do
Begin
aux := aux + 1 ;
Write(aux);
For altura := 1 to n Do
Begin
Write(' ');
Write(IdAlt[idade,altura]);
 End ;
Writeln ;
End ;
End ;
Procedure RetificarDados ;
Begin
Writeln('Introduza o número do aluno que pretende retificar');
Readln(ret);


For idade := 1 To n Do
Begin
For altura := 1 To n Do
Begin
If idade = ret Then
Writeln('Introduza a idade do aluno');
Readln(IdAlt[ret,ret]);
Writeln('Introduza a altura do aluno');
Readln(IdAlt[ret,ret]);
End ;
End ;
ClrScr;
End ;Procedure MediaIdades ;
Begin
Writeln('Média de idades da turma: ');
For idade := 1 To n Do
Begin
For altura := 1 To n Do
Begin
Somamed := Somamed + IdAlt[idade,altura];
End ;
End ;
totalmed := somamed / n ;
Writeln(totalmed:3:2);
End ;

Procedure MediaAlturas ;
Begin
Writeln('Média de alturas da turma: ');
For altura := 1 To n Do
Begin
For idade := 1 To n Do
Begin
Somamedd := Somamedd + IdAlt[idade,altura];
End ;
End ;
totalmedd := somamed / n ;
Writeln(totalmedd:3:2);
End ;
Procedure Mais16AlturaInferior ;
Begin
For idade := 1 To n Do
Begin
For altura := 1 To n Do
Begin


End ;
End ;
End ;Procedure IdadeSuperiorMedia ;
Begin
For idade := 1 To n Do
Begin
For altura := 1 To n Do
Begin
If IdAlt[idade,altura] > totalmed Then
conta := conta + 1 ;
End ;
End ;
Writeln('Existem ',conta,' alunos com idade superior à media');
End ;
Procedure AlunoMaisAlto ;
Begin
For idade := 1 To n Do
Begin
For altura := 1 To n Do
Begin
If IdAlt[idade,altura] > max Then
max := IdAlt[idade,altura] ;
End ;
End ;
Writeln('O aluno mais alto é o aluno número ', altura) ;
End ;Begin
Somamed := 0 ;
Somamedd := 0 ;
Conta := 0 ;
max := 0 ;
Repeat
Writeln('____________________________ MENU ____________________________');
Writeln('1 - Introduzir dados');
Writeln('2 - Visualizar dados');
Writeln('3 - Retificar a idade/altura dado o número do aluno');
Writeln('4 - Média de idades da turma');
Writeln('5 - Média de alturas da turma');
Writeln('6 - Número de alunos com mais de 16 anos com altura inferior à média');
Writeln('7 - Número de alunos com idade superior à media de idades');
Writeln('8 - Aluno mais alto');
Writeln('9 - Sair');
Readln(op);
Case op of
1 : LerDados ;
2 : VerDados ;
3 : RetificarDados ;
4 : MediaIdades ;
5 : MediaAlturas ;
6 : Mais16AlturaInferior ;
7 : IdadeSuperiorMedia ;
8 : AlunoMaisAlto ;
End ;
Until op = 9 ;
End.

Ou quem preferir já com o tabulamento: http://pastebin.com/Uy0ePVb6

O que se passa aqui? O que estou a fazer de mal?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Ou não percebi bem o que queres, ou tu não percebeste bem como funcionam os arrays.

1º Precisas guardar para n alunos a sua idade e a sua altura, certo?

O teu procedimento LerDados não está a fazer isso.

Imagina o seguinte:

Quantos alunos?

5

Com aqueles dois for's, o que te vai acontecer é que ele vai tentar ler um só valor 25 vezes (5 x 5), pois o FOR interior (altura), que corre 5 vezes de cada vez que é chamado, vai ser executado também 5 vezes, pois é esse o numero de vezes que o FOR exterior corre.

O que precisas é ler dois valores durante 5 vezes.

Ou seja, apenas um FOR, e lá dentro, dois readln's.

Outra coisa é que a idade e a altura não são posições do array, mas sim valores.como tens, se a idade for 15 anos, por exemplo, e a altura for 170cm ele vai tentar gravar (alguma coisa) na posição 15,170 do array, quando este terá no máximo 2,30. Erro na certa.

Então, o que precisavas era algo do tipo:

Procedure LerDados;
var
  Contador:Integer;
Begin
  // Lê o numero de alunos
  Writeln('Introduza o número de alunos');
  Readln(n);

  // Corre o ciclo n vezes, usando uma variável de controle "Contador"
  For Contador := 1 To n Do
     Begin
        // Lê a idade para a primeira coluna do array (coluna 1), na linha correspondente ao aluno (Contador)
        Writeln('Introduza a idade do ',Contador,'º aluno');
        Readln(IdAlt[1,Contador]);

        // Lê a altura para a segunda coluna do array (coluna 2), na linha correspondente ao aluno (Contador)
        Writeln('Introduza a altura do ',Contador,'º aluno');
        Readln(IdAlt[2,Contador]);
     End;

  ClrScr;
End;

Não cheguei a ver o resto do programa, mas com isto penso que já podes começar a corrigir os demais problemas.

Imagina o array bidimensional como uma tabela, com linhas e colunas. Os valores que usas dentro de [] são apenas as posições, sendo que lá dentro é que se guarda os valores.

Por exemplo:

O aluno 5 tem 15 anos e 160cm de altura

IdAlt[1,5] = 15

IdAlt[2,5] = 160

O aluno 8 tem 22 anos e 180cm de altura

IdAlt[1,8] = 22

IdAlt[2,8] = 180

| 1 | 2 |
----------
1|   |   |
----------
2|   |   |
----------
3|   |   |
----------
4|   |   |
----------
5| 15|160|
----------
6|   |   |
----------
7|   |   |
----------
8| 22|180|
----------
9|   |   |

Se continuares com duvidas, vai pondo aqui...


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
StraightEdge

Pois, de facto não percebi mesmo muito bem como se funciona os arrays. No dia em que se deu a matéria, eu estava um bocado doente e não me consegui concentrar como costume.

Bem, ao que interessa...

Já percebi um bocado melhor as arrays com o teu post. Muitíssimo obrigado.

Podes só explicar detalhadamente aqueles 1 e 2 ali nos Readln? Como funciona ao certo?

É que nunca falamos disso na aula mas já ouvi falar de tal coisa só que era com 0 e 1.

Vou tentar fazer o resto a partir da base do teu post.

Se houver mais alguma dúvida, meto aqui.

Obrigado!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Eh bem, estive a ver por alto o teu código, e estás a fazer uma confusão do camandro. A ver se organizas as ideias... :D

Estás a fazer confusão por uma razão, entre outras. Estás habituado a fazer o readln de uma variável com um nome, e agora parece estranho ver dentro de um readln um número em si.

Os números são os índices de um elemento da Array.

Posto isto, não há problema em ser 1 e 2. Isso depende do intervalo que definires na array. Eu posso muito bem definir em Pascal o seguinte:

var PontosFuncao : array [-10..10] of real;

Aqui o primeiro elemento desta array unidimensional é -10. Noutras linguagens é que é mandatório ser 0 (zero), mas Pascal dá-te esta pequena liberdade. Contudo, recomenda-se que se comece, nesta linguagem, em 0 ou em 1. Cada uma destas hipóteses tem um motivo:

  • Começar em 0 - é o padrão actual de muitas linguagens ter o primeiro índice como sendo zero.
  • Começar em 1 - baseia-se num padrão do Pascal que está presente, por exemplo, nas Strings. Enquanto que na maioria das LP's o primeiro caracter da String é de índice 0, em Pascal é de índice 1 (o índice 0 tem outra função específica - indicar o tamanho da string). Na realidade, antigamente não havia o tipo String, que é syntax sugar para aquilo que havia antigamente; podes praticamente definir "String", de uma forma "ligeira", da seguinte forma:
    type TString = packed array [1..255] of char;
    


Por isso a maioria dos programadores de Pascal que gosta de seguir a "tradição" e um pouco aquilo que é mais óbvio começa as suas Arrays no índice 1. Mas a escolha é tua, e depende também das situações e razões.

Voltando ao porquê de estar 1 e 2... A tabela que o @nunopicado apresentou deveria explicar bem isso. Mas vamos ver:

A Array tem a seguinte definição:

var IdAlt : array [1..2, 1..9] of integer;

Ou seja, aos nossos olhos será uma tabela com 2 colunas e 9 linhas. A coluna 1 regista a idade e a coluna 2 regista a altura em cm. As 9 linhas correspondem a 9 registos destes dados.

Quando queres registar a idade do aluno nº 4, tu tens de ir ao índice (1,4) - registar a idade (coluna 1) do aluno 4 (linha 4).

IdAlt[1,4] := 13;  // o aluno 4 tem 13 anos de idade.

E agora vamos registar a sua altura (coluna 2):

IdAlt[2,4] := 174;  // o aluno 4 tem 1,74 m de altura.

Vamos traduzir num ciclo for que leia estes dados acerca dos 9 alunos:

for i := 1 to 9 do begin
  writeln('ALUNO ', i);
  write('Insira a idade do aluno: ');
  readln(IdAlt[1,i]); // a idade do aluno I está na coluna 1.

  write('Insira a altura, em cm, do aluno: ');
  readln(IdAlt[2,i]); // a altura do aluno I está na coluna 2.
end;

Como bons programadores que somos, vamos facilitar a leitura do código. Metemos em constantes quais são os índices (colunas) que guardam estes dados:

const IDADE  = 1;  // a idade está na coluna 1
     ALTURA = 2;  // a altura está na coluna 2

Logo, o código ficará assim:

const MAXALUNOS = 9;
     IDADE  = 1;  // a idade está na coluna 1
     ALTURA = 2;  // a altura está na coluna 2
var IdAlt : array [1..2, 1..MAXALUNOS] of integer;
// ...

for i := 1 to MAXALUNOS do begin
  writeln('ALUNO ', i);
  write('Insira a idade do aluno: ');
  readln(IdAlt[iDADE,i]);

  write('Insira a altura, em cm, do aluno: ');
  readln(IdAlt[ALTURA,i]);
end;

Espero que tenhas percebido melhor as Arrays com este post e mais o do @nunopicado. Mais alguma coisa, não hesites em perguntar ;)

Cumprimentos.

EDIT: a explicação acerca do comprimento das Strings está corrigido xD

Editado por thoga31

Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

Um pequeno reparo: o motivo pelo qual as strings em pascal começam no índice 1 deve-se ao facto de que, classicamente, uma string é (pseudo-)definida da seguinte forma:

type
 string = packed record
   length: byte;
   content: array [0..254] of char;
 end;

O primeiro byte é, portanto, um contador que indica o comprimento da string e localiza-se na posição #0 da mesma, se a virmos como uma cadeia linear de bytes.

Isto leva ao limite conhecido dos 255 caracteres por string (o máximo que um byte consegue representar), limite este que é actualmente irrelevante, graças ao suporte para huge strings oferecido pelos compiladores.

Relativamente ao resto, queria apenas referir que penso fazer mais sentido definir a array com as informações de forma a que o primeiro índice indique o aluno e não a coluna:

IdAlt = array [1..MAXALUNOS, 1..2] of integer

Isto possibilita código que me parece mais intuitivo:

IdAlt[ {nº do aluno}, {ALTURA | IDADE} ]

Editado por pwseo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
StraightEdge

Boa, consegui!

Tinha que entregar isto amanhã e se não fosse vocês, nunca iria perceber o raio da confusão que eu estava a fazer... e que confusão vergonhosa para um programador. Um mil obrigados para vocês! :thumbsup:

Vou deixar aqui o algoritmo que fiz:


Program ficha5 ;
Var
IdAlt : array [1..2,1..30] of Integer ;
n , op : Integer ;
mediaaltura , mediaidade : Real ;

Procedure LerDados;
Var
i : Integer;
Begin
Writeln('Introduza o número de alunos');
Readln(n);
For i := 1 To n Do
Begin
Writeln('Introduza a idade do ', i ,' aluno');
	  Readln(IdAlt[1,i]);

	  Writeln('Introduza a altura do ', i ,' aluno');
	  Readln(IdAlt[2,i]);
   End;
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End;


Procedure VerDados ;
Var
i : Integer;
Begin
Writeln('Número	 Idade	 Altura');
For i := 1 To n Do
Begin
Write(i ,'		  ', IdAlt[1,i] ,'		  ', IdAlt[2,i]);
Writeln;
End ;
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;


Procedure RetificarDados ;
Var
retificar , i : Integer ;
Begin
Writeln('Introduza o número do aluno que pretende retificar');
Readln(retificar);
For i := 1 To n Do
Begin
If (retificar = i) Then
Begin
Writeln('Introduza a idade do ', i ,' aluno');
	  Readln(IdAlt[1,i]);

	  Writeln('Introduza a altura do ', i ,' aluno');
	  Readln(IdAlt[2,i]);
   End;
   End ;
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;


Procedure MediaIdades ;
Var
i , soma : Integer ;
Begin
Soma := 0 ;
For i := 1 To n Do
Begin
Soma := Soma + IdAlt[1,i] ;
End ;
Mediaidade := soma/n ;
Writeln('Média de idades = ', mediaidade:3:2);
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;

Procedure MediaAlturas ;
Var
i , soma : Integer ;
Begin
Soma := 0 ;
For i := 1 To n Do
Begin
Soma := Soma + IdAlt[2,i] ;
End ;
Mediaaltura := soma/n ;
Writeln('Média de alturas = ', mediaaltura:3:2);
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;

Procedure Mais16AlturaInferior ;
Var
i : Integer ;
Begin
Writeln('Número	 Idade	 Altura');
For i := 1 To n Do
Begin
If (IdAlt[1,i] > 16) and (IdAlt[2,i] < mediaaltura) Then
Begin
Write(i ,'		  ', IdAlt[1,i] ,'		  ', IdAlt[2,i]);
Writeln;
End ;
End ;
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;

Procedure IdadeSuperiorMedia ;
Var
i : Integer ;
Begin
Writeln('Número	 Idade	 Altura');
For i := 1 To n Do
Begin
If (IdAlt[1,i] > mediaidade) Then
Begin
Write(i ,'		  ', IdAlt[1,i] ,'		  ', IdAlt[2,i]);
Writeln;
End ;
End ;
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;

Procedure AlunoMaisAlto ;
Var
i , maximo , auxiliarnumero , auxiliaridade : Integer ;
Begin
maximo := 0 ;
For i := 1 To n Do
Begin
If (IdAlt[2,i] > maximo) Then
Begin
maximo := IdAlt[2,i] ;
auxiliarnumero := i ;
auxiliaridade := IdAlt[1,i] ;
End ;
End ;
Writeln('Número	 Idade	 Altura');
Write(auxiliarnumero ,'		  ', auxiliaridade ,'		  ', maximo);
Writeln;
Writeln('Pressione qualquer tecla para voltar ao menu');
Readkey;
ClrScr;
End ;

Begin
Repeat
Writeln(' ');
Writeln('____________________________ MENU ____________________________');
Writeln('1 - Introduzir dados');
Writeln('2 - Visualizar dados');
Writeln('3 - Retificar a idade/altura dado o número do aluno');
Writeln('4 - Média de idades da turma');
Writeln('5 - Média de alturas da turma');
Writeln('6 - Número de alunos com mais de 16 anos com altura inferior à média');
Writeln('7 - Número de alunos com idade superior à media de idades');
Writeln('8 - Aluno mais alto');
Writeln('9 - Sair');
Readln(op);

Case op of
1 : LerDados ;
2 : VerDados ;
3 : RetificarDados ;
4 : MediaIdades ;
5 : MediaAlturas ;
6 : Mais16AlturaInferior ;
7 : IdadeSuperiorMedia ;
8 : AlunoMaisAlto ;
End ;
Until op = 9 ;
End.

Ou então, http://pastebin.com/wWVCy9T7

Mil obrigados, mais uma vez!

Editado por StraightEdge

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
nunopicado

Ainda que já esteja feito, podes melhorar.

1º Usa as constantes como sugeriu o Thoga. É melhor, mais legível, e sempre demonstras ao professor que não andas a brincar! ;)

2º Inverter as medidas do array, como disse o pwseo. Fica mais intuitivo.

3º Corrigir o procedimento RetificarDados.

Não tens de correr todas as posições para corrigir apenas uma. Deves remover o FOR e aceder directamente à posição do array:

Writeln('Introduza o número do aluno que pretende retificar');
Readln(retificar);
Writeln('Introduza a idade do ', retificar ,' aluno');
Readln(IdAlt[1,retificar]);
Writeln('Introduza a altura do ', retificar ,' aluno');
Readln(IdAlt[2,retificar]);

4º Procedimentos de MediaIdades e MediaAlturas - Tal como tens, se o utilizador escolher no menu as opções 6 ou 7 antes de escolher as opções 5 ou 4 respectivamente, vais ter problemas, porque tanto a opção 6 como a 7 se baseiam nos valores das variaveis globais de medias, que que só são definidas nas opções 5 e 4.

Assim, o ideal era converteres esses dois procedimentos em funções que devolvessem o valor sempre que fossem chamadas.

Caso não o queiras fazer, pelo menos, no inicio dos procedimentos 6 e 7, chama os procedimentos 5 e 4 para preencher a variavel.


"A humanidade está a perder os seus génios... Aristóteles morreu, Newton já lá está, Einstein finou-se, e eu hoje não me estou a sentir bem!"

> Não esclareço dúvidas por PM: Indica a tua dúvida no quadro correcto do forum.

Partilhar esta mensagem


Ligação 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

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.