Ir para o conteúdo

PARTE I - Preliminares. Programação básica.

Aqui começam por ser dados os grandes alicerces essenciais para se programar em Pascal. As estruturas essenciais, as principais palavras reservadas, a estruturação básica de um programa em Pascal. Esta é uma parte totalmente teórica, que terá a sua consolidação na Parte II, só de aplicações práticas dos assuntos agora tratados.

1. Breve história, nível da linguagem e compiladores

Após a criação do Assembly como primeira linguagem de programação que não exigia que o programador escrevesse os seus programas directamente em código binário, Niklaus Wirth criou, em 1971, a primeira linguagem de programação estruturada à qual, em homenagem ao grande matemático Blaise Pascal, deu o nome de Pascal. Esta foi uma linguagem baseada originalmente no ALGOL-60.

Niklaus Wirth preocupou-se em aproximar a linguagem de programação da linguagem do ser humano, em particular, claro está, o inglês. Depois do seu sucesso com o lançamento do Pascal, hoje em dia discute-se se esta é uma linguagem de baixo nível, médio nível ou alto nível. Se considerarmos que estas denominações foram criadas baseadas na proximidade da linguagem de programação à linguagem humana, constatamos que o Pascal é de alto nível. Contudo, actualmente confunde-se estas designações com as potencialidades que a linguagem oferece, e, devido a isto, muitos dizem que Pascal é de baixo nível.

Ora, um dos compiladores mais antigos e dos mais famosos do mundo é o Turbo Pascal. Contudo, mais compiladores e IDEs têm saído, muitos na tentativa de criar um compilador/IDE com um ambiente gráfico muito mais agradável que o Turbo Pascal, como é o caso do Dev-Pascal (IDE que utiliza o GNU Pascal ou o Free Pascal como compilador subjacente). O compilador mais utilizado é o primeiro referido, havendo um compilador baseado neste e também muito utilizado, que é o Free Pascal. Qualquer um destes IDEs/compiladores é muito bom, apesar de muitas divergências quanto a este tema. Existem compiladores que aceitam operadores da linguagem C, tais como: += -= *= /=.

Escolhido um IDE/compilador, e partindo do pressuposto que sabem as bases sobre Lógica e Algoritmos, passamos então a referir os tipos de variáveis com que mais se trabalha, os principais operadores e afins, condições e ciclos, bem como as principais declarações do pascal, os procedimentos e as funções.

2. Variáveis e tipos de dados

Os principais tipos de dados são os seguintes:

  • Integer – número inteiro (há vários tipos de integers)
  • Real – número real (também há vários tipos de reals)
  • String – cadeia de caracteres (texto)
  • Char – caractere
  • Array – matriz de valores, de 1, 2 ou mais dimensões
  • Boolean – booleano: verdadeiro ou falso - ver mais informações no Anexo 1.
  • Text – ficheiro de texto simples
  • File -- ficheiro (pode ser especializado em qualquer tipo)
  • Pointer -- tal como File, podemos ter pointers de qualquer tipo

Nenhuma variável poderá ter o nome de um destes tipos de dados, ou seja, por exemplo, nunca uma variável de número inteiro poderá ser chamada de Array, pois esta é uma palavra reservada1 do Pascal.

3. Operações e operadores

3.1. Igualdade, Diferença e Negação

A igualdade e a diferença são úteis essencialmente em condições. A resposta que estes operadores devolvem ao programa é do tipo booleana: verdadeiro ou falso. Por exemplo, no caso de 2 = 2 será devolvido True (verdadeiro), pois, de facto, 2 é igual ( = ) a 2. Já no caso de 2 <> 2 será devolvido False (falso), pois 2 não é diferente de 2. Já no caso de ser escrito NOT (2 <> 2), será devolvido que é verdade, pois, de facto, 2 não é diferente de 2.

  • = – igual a
  • <> – diferente de
  • not – não

3.2. Soma, subtracção, multiplicação e divisão

Se declararmos as variáveis A e B como números inteiros (Integer), então estas operações serão dadas segundo a seguinte lista:

  • Soma: A + B
  • Subtracção: A - B
  • Multiplicação: A * B
  • Divisão: A / B

Contudo, no caso da divisão, o Pascal tem dois operadores que devolvem um o resultado da divisão como um número inteiro e outro o primeiro resto da divisão:

  • Resultado inteiro: A div B
  • Primeiro resto: A mod B

3.3. Gravar um resultado numa variável – atribuição

O resultado destas últimas operações pode ser gravado numa variável (atribuído a uma variável) para depois ser utilizado noutros processos e cálculos. Em Pascal, o comando (operador) que dá ordem para gravar (atribuir) um valor numa variável é :=. Este processo é denominado de atribuição. Por exemplo, se quisermos somar duas variáveis inteiras, A e B, e atribuir o resultado a uma variável inteira chamada resultado, será escrito resultado := A+B. As variáveis array têm uma forma diferente de serem atribuídas, apesar de utilizarem este operador. Tal será visto mais à frente.

3.4. Valor absoluto e truncado, logaritmo, seno, co-seno e tangente, número ao quadrado e raiz quadrada

Continuando com a variável A do tipo Integer:

  • Valor absoluto: abs(A)
  • Valor truncado: trunc(A)
  • Logaritmo neperiano (de base e): ln(A)
  • Seno (ângulo em radianos, só): sin(A)
  • Co-seno (ângulo em radianos, só): cos(A)
  • Número ao quadrado: sqr(A)
  • Raiz quadrada: sqrt(A)

Ora, pela fórmula da tangente, esta á calculada por sin(A)/cos(A). É claro que, se o co-seno valer zero então o programa dará erro e irá abaixo. Mais à frente, nas condições, veremos como transpor esta situação.

4. Declarações e noções sobre Pascal

4.1. Declarações iniciais e de variáveis e enunciações básicas

Um programa em Pascal tem de se iniciar com as seguintes declarações:

  • Nome do programa
  • Bibliotecas a utilizar
  • Variáveis, tipos e constantes

O nome do programa é enunciado com a palavra reservada program, que deverá ter o mesmo nome do ficheiro que contém o código-fonte, tirando a extensão do ficheiro (*.pas, *.pp ou outra). As bibliotecas são conjuntos de operações e funções que, sem estas estarem enunciadas, não serão reconhecidas pelo compilador. Por exemplo, o comando gettime, que obtém a hora do computador, só funciona com a biblioteca dos. As bibliotecas a utilizar são declaradas com uses. A biblioteca mais utilizada e que contém as funções básicas é a biblioteca crt – esta é a biblioteca obrigatória para quase todos os programas. Por fim, as variáveis são declaradas pela palavra reservada var. Contudo, para além destas, existem os Tipos de Variável e as Constantes. As constantes são valores que nunca são alterados ao longo do programa. Podem ser de qualquer tipo, sendo o mais comum número real, como por exemplo o valor de pi. As constantes são enunciadas com const. Já no caso de um conjunto de variáveis for todo do mesmo tipo (que não seja um tipo de dado simples predefinido), pode-se criar um tipo de variável com um nome dado por nós, para além dos enunciados anteriormente. Os novos tipos criados pelo programador são declarados por type. Por exemplo:

program exemplo;
uses crt;
type lista = array[1..10] of integer;
var avaliacoes:lista;
    n:string;
const pi=3.14;

Como pode ser visto por este exemplo, uma instrução é sempre seguida de ponto e vírgula, excepto nalguns casos, dos quais um deles será abordado mais à frente, que é com a palavra reservada else. Para além disso, um tipo de variável é definido por nome_do_tipo = tipo_de_dado. Neste caso, foi declarado que lista é do tipo array de 1 dimensão, constituído por dez elementos, que começa no elemento nº 1 e acaba no elemento nº 10, e este array é feito de variáveis integer. As constantes também são enunciadas como uma igualdade. Sempre que no programa for escrito numa instrução, segundo o exemplo dado, pi, o programa irá assumir o valor 3.14. Caso se tente atribuir um resultado qualquer a pi, o compilador dará erro na compilação. As variáveis são declaradas segundo a estrutura var nome_variavel : tipo_variavel;. Neste caso, foi enunciado que a variável n é do tipo String.

Os arrays, como matrizes de variáveis, têm de ser declaradas quanto à sua dimensão2 e ao tipo de variáveis que comporta: var nome : array [dimensão] of tipo_variavel;. A dimensão pode ser uni ou multidimensionais, ou seja, uma simples lista ou uma espécie de tabela de valores. Por exemplo:

var list_numeros : array [0..5] of real;
    tabela : array [0..5,0..3] of real;

A variável list_numeros pode ser apresentada aos nossos olhos da seguinte forma:

list_numeros
0
1
2
3
4
5

Já a variável tabela pode ser apresentada desta forma:

tabela
0,0 0,1 0,2 0,3
1,0 1,1 1,2 1,3
2,0 2,1 2,2 2,3
3,0 3,1 3,2 3,3
4,0 4,1 4,2 4,3
5,0 5,1 5,2 5,3

Por fim, após a declaração do programa, das bibliotecas, dos tipos de variáveis e/ou das variáveis e/ou das constantes, para o programa ser inicializado e finalizado resta-nos o seguinte:

program exemplo;  // declarações iniciais
uses crt;
var A:integer;

begin  // INÍCIO

// programa principal

end. // FIM

4.2. Atribuir valores num array

Continuando com as variáveis list_numero e tabela, vamos atribuir valores dentro de cada um destes arrays. Na list_numero, vamos atribuir um valor na localização 2, neste caso -4.5:

list_numero[2] := -4.5

Assim, considerando que os restantes elementos do array ainda não foram alterados, o array list_numero terá o seguinte aspecto gráfico (quando uma variável é declarada, e esta é do tipo numérico, o seu valor inicial é, por defeito, 0 (zero)):

list_numeros
0
0
-4.5
0
0
0

Já para atribuir este valor em tabela na posição (3,1):

tabela[3,1] := -4.5

O aspecto final do array será:

tabela
0 0 0 0
0 0 0 0
0 0 0 0
0 -4.5 0 0
0 0 0 0
0 0 0 0

Os arrays podem ser dinâmicos, ou seja, a sua dimensão pode variar a qualquer ponto do programa, podendo passar de 1D (tipo lista) para 3D, e voltar para 2D (tipo matriz/tabela). Estes arrays só são abordados na Parte IV por ser um tema complexo para o propósito da Parte I (se estás já interessado, vê 6. Arrays dinâmicos).

4.3. Escrita de textos e leitura de dados

O programa pode escrever textos e receber dados, como é óbvio – realiza operações de input e de output. Para escrever um texto e fazer parágrafo:

writeln('Texto');

Contudo, se quisermos escrever um texto e deixar o cursor a piscar à frente deste, escrevemos:

write('Texto ');

Para ler dados:

readln(variável);

A variável lida tem de coincidir com o seu tipo. Por exemplo, se a variável for a A, do tipo Integer, faremos:

readln(A);

No caso de introduzirmos um número real ou um texto em vez de um número inteiro, o programa irá abaixo. Por isso há que avisar o utilizador desse facto:

write('Introduza um numero inteiro: ');
readln(A);

5. Estruturas de Decisão e de Repetição

Estruturas de decisão são instruções estruturadas que permitem ao programa (computador) analisar uma determinada condição e, consoante esta seja verdadeira ou falsa, irá decidir o que realizar de seguida. Doravante, nesta parte, para simplificar, serão designadas por condições, que é, de facto, uma outra designação bastante comum e muito utilizada mesmo entre profissionais. Já as estruturas de repetição são instruções estruturadas que obrigam o programa repetir um conjunto de instruções conforme a condição é verdadeira ou falsa. Doravante, serão designadas por ciclos.

5.1. Condição if… then… else…

Esta condição dá uma ordem ao programa do tipo Se… Então… Senão…:

if (condição) then begin
(comandos1)
end
else begin
(comandos2)
end;

Ou seja, se a condição for verdadeira, então são executados os comandos1, senão são executados os comandos2.

Por exemplo, se a variável A, do tipo Real, for positiva ou nula, mostra-se o texto “numero positivo ou nulo”, caso contrário mostra-se o texto “numero negativo”:

write('Introduza um numero real: ');
readln(A);
if (A>=0) then begin
   writeln('Numero positivo ou nulo');
end
else begin
     writeln('Numero negativo');
end;

5.2. Ciclo repeat… until…

Este ciclo obriga o programa a executar a mesma série de instruções até que a condição imposta seja satisfeita (verdadeira). Por exemplo, se quisermos que o utilizador introduza um número inteiro positivo e não nulo:

repeat  // Repetir...
       readln(A);
until (A>0);  // ATÉ QUE (A>0)

5.3. Ciclo while… do…

Este ciclo faz o mesmo que o cilo Repeat… Until…, contudo fá-lo com a lógica contrária. Enquanto o ciclo anterior dizia Repetir até que a condição seja verdadeira, este ciclo diz Repetir enquanto a condição for verdadeira. Recorrendo ao mesmo exemplo anterior, mas aplicando este ciclo:

while (A<=0) do begin // ENQUANTO (A <= 0)...
      readln(A);
end;

Todavia, é necessário um cuidado extra com este ciclo. Enquanto o ciclo Repeat… Until… é executado pelo menos uma vez, pois a condição imposta só é analisada após uma iteração3, no ciclo While… a condição é a primeira coisa a ser analisada. Caso esteja de imediato satisfeita, nenhuma iteração é realizada. Para evitar esta falha, deve-se “reiniciar” a(s) variável/eis em questão:

A := -1;  // A é, desde já, um número negativo, o que NÃO satisfaz a condição do ciclo
while NOT (A>0) do begin  // Enquanto A não é maior que zero…
      readln(A);
end;

5.4. Ciclo for… to/downto… do…

Este é um ciclo que é muito útil, por exemplo, para escrever o conteúdo de um array. Voltando ao array anteriormente descrito, tabela, consideremos que o programa já lhe atribuiu valores – para escrever o seu conteúdo no ecrã:

program exemplo;
uses crt;
var tabela:array[0..5,0..3] of real;
    i,j:integer;
begin
     // commandos anteriores, quaisquer, que atribuiram valores no array
     for i:=0 to 5 do begin
         for j:=0 to 3 do begin
             write(tabela[i,j],'; ');
         end;
     writeln;
     end;
end.

É incrementado à variável i (contador) o valor 1 após o conjunto de comandos ter sido realizado, assim como à variável j. O conjunto de comandos que está dentro do primeiro ciclo for só termina quando i assumir o valor 5. Assim acontece com o segundo ciclo: só termina quando j valer 3. Contudo, poder-se-á escrever a ordem da tabela ao contrário. Em vez de começarmos pelo valor [0,0] e terminarmos no valor [5,3], começamos em [5,3] e acabamos em [0,0]. Em vez de escrevermos, no ciclo, to, escrevemos downto, que significa que se incrementa o valor -1 à variável contador do ciclo (a variável diminui em uma unidade):

program exemplo;
uses crt;
var tabela:array[0..5,0..3] of real;
    i,j:integer;
begin
     // commandos anteriores, quaisquer, que gravaram valores no array
     for i:=5 downto 0 do begin
         for j:=3 downto 0 do begin
             write(tabela[i,j]);
         end;
         writeln;
     end;
     readln;  // impede que o programa feche logo com o END final, esperando que seja premido ENTER
end.

Mais à frente, na Parte II, é dada uma excelente exemplificação da utilização deste ciclo.

5.5. Condição Case of… else

Esta condição pode poupar a utilização excessiva de condições if. Esta instrução diz-nos Caso a variável assuma este valor, então…. Se se pretender classificar uma nota de 0 a 20 em termos qualitativos, ter-se-á, por exemplo, o seguinte:

program avaliacoes;
uses crt;
var nota:integer;

begin
     write('Introduza uma nota, de 0 a 20: ');
     readln(nota);
     case nota of
          0..9:writeln('Insuficiente');
          10..14:writeln('Suficiente');
          15..17:writeln('Bom');
          18..20:writeln('Excelente');
     else begin
          if (nota<0) then writeln('ERRO! Nota nao pode ser negativa!');
          if (nota>20) then writeln('ERRO! Nota nao pode ser maior que 20!');
     end;
     readln;
end.

Caso mais do que uma instrução tenha que ser executada em determinado caso, a estrutura será:

case nota of
     0..9:begin
          writeln('Insuficiente.');
          writeln('Chumbou!');
          end;
     10..14: // etc...
end;

6. Procedimentos e funções

6.1. Procedimentos

Dentro de um programa pode existir um subprograma. Estes subprogramas são designados, em Pascal, por procedimentos, e são declarados antes do bloco principal do programa pela expressão reservada procedure. Por exemplo, podemos criar um procedimento para calcular a raiz quadrada de um número, sem que tal seja feito no bloco principal:

program raiz;
uses crt;
var a,resultado:real;

procedure calc_raiz;
begin
     resultado:=SQR(a);
end;

begin
     write('Introduza valor A: ');
     readln(a);
     calc_raiz;  // chama o procedimento
     writeln('A raiz quadrada de A e: ',resultado);
     readln;
end.

6.2. Funções

O mesmo pode ser feito através de uma função. Podemos, por exemplo, criar uma função, num programa, que calcule a tangente de um número sem ser necessário calcular no meio do bloco principal todas as contas necessárias. Uma função é declarada antes do bloco principal através da palavra reservada function. Dever-se-á ter em conta que uma função devolve um valor e um procedimento não, ou seja, uma função é da mesma hierarquia das funções padrão do Pascal, como abs, e os procedimentos são subprogramas dentro do programa principal que executam instruções sem devolverem absolutamente nada no fim. Veja-se o exemplo:

program tang_ang;
uses crt;
var angulo:real;

procedure ler_angulo;
begin
     write('Introduza angulo em radianos: ');
     readln(angulo);
end;

function tangente(a:real):real;
begin
     tangente:=SIN(a)/COS(a);
end;

begin
     ler_angulo;  // procedimento que vai ler o ângulo, mas nada devolve.
     writeln('A tangente do angulo e: ',tangente(angulo));  // função que calcula a tangente e devolve o seu resultado.
     readln;
end.

6.3. Passagem por Parâmetro / Passagem por Referência

Ver o documento Passagem por Parâmetro / Passagem por Referência do membro nunopicado. ;-)

6.4. Procedimentos e Funções encadeados

Ver o documento Procedimentos e Funções encadeados da minha autoria (thoga31). :-)

7. Arredondamentos

Em Pascal é possível, claro está, arredondar valores. Existem dois métodos distintos. Através da função padrão round, que arredonda só às unidades e pode ser atribuído o resultado a uma variável, ou através de um código que utiliza dois pontos ( : ). Por exemplo, para arredondar um resultado do tipo real (sendo este a variável resultado) às unidades:

var i : integer;
    resultado : real;
// ...
i := round(resultado);

Com o método dos dois pontos, podemos indicar o espaço que o número ocupa e o arredondamento que tem, do género: número:espaço:arredondamento. Por exemplo:

write(resultado:12:5);

Neste caso, se o resultado for 34.56356976356, irá aparecer algo como (sendo “#” indicação de um espaço vazio): ####34.56357 Já se for escrito:

write(resultado:0:2);

Irá aparecer exactamente como: 34.56 Atenção!: este método só serve para a escrita com os procedimentos padrão write e writeln.


  1. Palavra com uma função bem definida, que não pode ser redefinida. Apresenta-se uma lista na Parte VI. 

  2. Mais propriamente, é o conjunto do array. Contudo, tal conceito só será abordado na Parte V. 

  3. Nome dado a cada vez que o bloco de instruções dentro de uma estrutura de repetição é processado.