Jump to content
StraightEdge

Arrays bidimensionais

Recommended Posts

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?

Share this post


Link to post
Share on other 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.

Share this post


Link to post
Share on other 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!

Share this post


Link to post
Share on other 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

Edited by thoga31

Knowledge is free!

Share this post


Link to post
Share on other 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} ]

Edited by pwseo

Share this post


Link to post
Share on other 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!

Edited by StraightEdge

Share this post


Link to post
Share on other 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.

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.