CAPíTULO 1
TIPOS E VALORES:
OPERAÇÕES:
Uma operação é realizada com valores, na Unidade Aritmética-Lógica da máquina, e
produz como resultado outro valor, que fica armazenado temporariamente nos registros,
podendo ser usado em operações subseqüentes.
As operações podem ser unárias ou binárias , dependendo se operam sobre um ou dois
valores. Uma operação é formada por um operador e um ou
doisoperandos (operação unária ou binária). Os operadores possíveis dependem do tipo dos
operandos envolvidos.
Caso a operação envolva um operando real e um inteiro, o resultado será sempre real:
30 – 2.5 resultado: 27.5
30 / 4.0 resultado: 7.5
c) Operadores relacionais binários, operando sobre inteiros e reais, com resultado lógico:
> < >= <= <> =
> (maior) ex: 20 > 30 resultado: falso (não)
< (menor) ex: 20 < 30 resultado: verdadeiro (sim)
>= (maior ou igual) ex: 20 >=
30 resultado: falso 20>=20 resultado: verdadeiro
<= (menor ou igual) ex: 20 <= 30 resultado: verdadeiro
<> (diferente) ex: 20 <> 30 resultado: verdadeiro 30.6 <> 10.78 (verdadeiro)
= (igual) ex: 20 = 20 resultado: verdadeiro
Comparação de caracteres:
O operadores relacionais também podem ser usados para comparar dois valores do tipo
caractere. Por exemplo, é correto escrever a operação: ‘d’ > ’b’
Nas linguagens de programação em geral, e em Pascal em particular, essas comparações
devem ser interpretadas de forma especial.
A linguagem permite utilizar 256 caracteres diferentes. Os caracteres são colocados em
ordem, em uma tabela que começa na posição 0 e vai até 255. Essa tabela é hoje em dia
um padrão da indústria, e é conhecida como “tabela ASCII”. A cada posição da tabela
corresponde um caractere. O “valor” de cada caractere é na realidade o numero inteiro
que representa a posição desse caractere na tabela. O caractere em si deve ser visto
apenas como um símbolo, ou um desenho.
A tabela é longa, mas é importante saber alguns detalhes úteis:
- os caracteres das letras maiúsculas estão na tabela em ordem alfabética
- os caracteres das letras minúsculas também.
- os caracteres dos algarismos (‘0’ a ‘9’) seguem a ordem crescente dos números
- as letras acentuadas estão em posições sempre acima de 128
- algumas teclas do teclado correspondem a 2 caracteres seguidos. A tecla ENTER
corresponde ao caractere CR (carriage return, ou retorno de carro), da posição 13,
seguido do caractere LF (line feed, ou alimentação de linha), da posição 10.
O programador Pascal não precisa saber mais detalhes sobre as posições dos caracteres
na tabela para poder programar sem problemas, mas por curiosidade a tabela é mostrada
parcialmente abaixo:
etc etc
Outro ponto importante a ressaltar, é que fica difícil comparar letras acentuadas com as
demais, para determinar a ordem alfabética relativa. Vemos acima o exemplo de ‘à’ e do
‘á’, em posições muito distantes das demais letras. Infelizmente o padrão da tabela ASCII
vale apenas para os primeiros 128 caracteres, e as letra acentuadas estão em uma área da
tabela que não é padronizada. Ainda existem em operação muitos ambientes de
programação com valores diferentes entre si para as letras acentuadas. Por esse motivo, o
uso de letras acentuadas em muitas aplicações é desencorajado. Neste curso evitaremos
trabalhar com letras acentuadas.
Operadores binários:
OU-INCLUSIVO (OU)
E
OU-EXCLUSIVO (XOU)
Operador unário:
NÃO
Significados:
OU : para a OU b ser Verdadeiro, basta um dos operandos, ou ambos, ter o valor
Verdadeiro.
E: para a E b valer Verdadeiro, ambos os operandos devem valer Verdadeiro
XOU: para a XOU b valer Verdadeiro, apenas um dos operandos pode valer
Verdadeiro, o outro deve valer Falso.
NÃO: negação do operando.
x y x ou y x E y x XOU y não x
F F F F F V
F V V F V V
V F V F V F
V V V V F F
E AND
OU-EXCLUSIVO EXCLUSIVE-OR (XOR)
(XOU)
NÃO NOT
Uma variável consiste de um identificador ao qual é associada uma área de memória onde
podem ser armazenados valores de um determinado tipo. Uma variávelsimples corresponde
a apenas um valor. Uma variável composta representa um agrupamento de valores na
memória da máquina.
Por exemplo, o identificador nota pode representar uma área da memória onde é
armazenado um valor real (a nota de um aluno). Então, se a nota do aluno for, digamos, 8.5,
podemos associar o identificador nota com o valor 8.5. Variáveis compostas serão vistas
mais adiante.
Uma constante é um identificador que corresponde a uma área da memória onde fica
armazenado um valor que não deve ser alterado pelo algoritmo. Por exemplo, o
identificador PI pode ser associado a uma área da memória onde será armazenado o valor
3.1416 no inicio de um algoritmo, mas que não deverá ser mais modificado.
Um identificador pode ser formado por letras, algarismos e o caractere sublinhado (‘_’) em
qualquer quantidade, desde que não iniciado por um algarismo. Em geral procura-se formar
uma palavra que lembre mnemonicamente o significado do valor correspondente no
problema que está sendo resolvido pelo algoritmo.
Por exemplo, o identificador salário pode ser associado a um valor real que representa o
salário de alguém, e o identificador achou pode ser associado a um valor lógico que indica
se a busca por um determinado valor numérico em uma lista foi bem sucedida ou não.
EXPRESSÕES:
Uma expressão é uma fórmula contendo valores, operandos, identificadores de variáveis ou
constantes, e outros símbolos permitidos, e que pode ser calculada de modo a ser reduzida a
um valor final. No cálculo de uma expressão os identificadores são substituídos pelos
valores correspondentes que estão na memória no momento em que a expressão é
calculada.
As operações que fazem parte de uma expressão são executadas da esquerda para a direita,
respeitando as regras de precedência.
Regras de Precedência:
maior precedência: - unário, NÃO
* / div mod E
+ - (binário) OU OU-EXCLUSIVO
menor precedência > < >= <= <> =
PI + 3 * x – 3.1
3.1416 + 3 * 10 – 3.1 (subst. dos valores dos identificadores)
3.1416 + 30 – 3.1 (* tem precedência sobre +)
33.1416 – 3.1 ( + e – tem a mesma precedência, então a operação mais à esquerda
é feita primeiro)
30.0416 (valor final da expressão)
OBS: usar parênteses em excesso não é erro: (3+4) ou ((3+4)) tem o mesmo valor que
3+4
Neste próximo exemplo, a expressão se reduz a um valor lógico. Note que não são
necessários parênteses porque a precedência dos operadores relacionais é menor que a dos
operadores aritméticos:
PI + 3*x > x – 2
3.1416 + 3 * 10 > 10 –2
3.1416 + 30 > 10-2
33.1416 > 10 – 2
33.1416 > 8 ( - tem precedência sobre >)
verdadeiro (valor final da expressão)
Como o operador OU tem precedência sobre o operador >, a operação 20 OU 100 deveria
ser feita primeiro. Mas não é possível fazer essa operação, porque o operador OU só se
aplica a operandos lógicos. Existe nessa fórmula um erro de sintaxe (forma gramatical
errada). Para corrigir o erro, introduzimos parênteses para forçar que a operação relacional
seja feita antes:
Nota: essa observação é válida para a linguagem Pascal. Na linguagem C, por exemplo, os
operadores lógicos têm menor precedência que os operadores relacionais. Por isso, em C, a
expressão acima sem parênteses estaria correta.
Expressões Triviais:
Uma única constante literal, ou um único identificador de variável, constitui uma expressão
trivial, mas é uma expressão legitima:
Por exemplo:
3 é uma expressão trivial, seu valor é 3.
Se x tem o valor 3, a expressão: x é trivial, com valor 3.
CAPíTULO 2
INSTRUÇÕES OU COMANDOS
COMANDO DE ATRIBUIÇÃO: :=
Exemplo: supondo que x vale 3 no momento em que o comando abaixo for realizado,
então:
y := 2 * x + 10
faz a expressão ser calculada e reduzida ao valor 16, e em seguida, esse valor é transferido
para a variável y que passa então a ter também o valor 16. O valor anterior que y tinha é
perdido.
Uma atribuição usa muitas vezes uma expressão trivial do lado direito, como em:
y := 10 (a expressão da direita vale 10, e esse valor é transferido para a variável y)
Esta é a outra forma pela qual se pode alterar o valor de uma variável na memória.
Primeiramente é importante saber que os dados digitados pelo teclado são lidos pela
máquina como uma linha de texto. Após digitar os dados, é necessário apertar a tecla
ENTER para sinalizar que terminamos a linha. Nesse momento, os caracteres digitados
serão colocados em uma memória intermediaria, conhecida popularmente como o buffer do
teclado. O caractere correspondente à tecla ENTER também irá para o buffer.
Pelo fato de ser uma linha de texto, os dados digitados formam uma seqüência de valores
de caracteres terminando com o valor do caractere ENTER. Se, por exemplo, for digitado o
número –3.25 seguido de ENTER, então o buffer conterá os 5 caracteres do número (o
caractere ‘-‘, seguido do caractere ‘3’, seguido do caractere ‘.’, etc.), e após eles o caractere
da tecla ENTER. É muito importante se ter essa noção de que o que digitamos não são
“números”, mas sim uma seqüência de caracteres.
Números reais podem ser digitados em formato convencional (como 567.8), ou em notação
cientifica (ex: 5.678E2 ou 0.567e+02 ou outra forma equivalente). Caracteres são digitados
sem as aspas simples. (ex. A)
Suponha que o comando ler(x) foi executado, e x é do tipo inteiro. Se digitarmos mais de
um número na mesma linha, então o primeiro número será copiado para o valor de x, e os
demais caracteres permanecerão no buffer esperando serem lidos pelos próximos comandos
de leitura.
Por exemplo, suponha a seqüência de comandos seguinte, onde x e z são variáveis inteiras,
e y é uma variável real:
ler(x)
ler(y)
ler(z)
ler(x)
Inicialmente, como o buffer está vazio, a máquina pára e espera que uma linha de
caracteres seja digitada, finalizando com ENTER. Suponha que o usuário digite:
34 -567.45 98 <ENTER>
(A quantidade de espaços entre os números é irrelevante, devendo ser pelo menos 1. Não é
permitido separar os números por virgulas ou outros caracteres A notação <ENTER>
acima significa pressionar a tecla ENTER.)
A máquina vai procurar construir um inteiro com esses caracteres. Vai lendo o ‘4’, depois o
‘5’ , depois o ‘6’, até deparar com o ponto. Nesse ponto o programa abortará a execução,
pois um inteiro não pode conter ponto decimal.
esperando que n receba o valor 25, letra1 receba o valor ‘A’, e letra2 receba o valor ‘B’. O
resultado porém será inesperado. Na realidade, n receberá o valor 25, letra1 receberá o
caractere que é o espaço que segue o ‘5’, e letra2 receberá o caractere ‘A’. Os demais
caracteres depois do A permanecerão no buffer e poderão ser lidos por outros comandos de
leitura que seguirem.
Como então é possível ler um caractere depois de um número? Já vimos que a forma:
25AB
não é possível, porque deve sempre existir pelo menos um “valor branco” (espaço,
tabulação ou o caractere ENTER) após cada numero.
e digitar:
25<ENTER>
AB<ENTER>
O comando ler(n) lerá o número 25 para a variável n, os 2 caracteres do <ENTER> serão
ignorados por conta do comando novaLinha, e a máquina lerá os caracteres da segunda
linha. Agora a letra A será associada à variável letra1, e a letra B (valor 66) será associada
à variável letra2, corretamente. Observe que os caracteres A e B são digitados em
seqüência, sem nenhum espaço entre eles. Caso existisse um espaço entre eles, a
variável letra2 receberia o valor do espaço.
O comando escrever( ) recebe uma expressão como argumento. O efeito desse comando é
normalmente de escrever o resultado da expressão no dispositivo padrão de saída, que em
geral é o monitor de vídeo.
OBS: Os valores serão escritos na tela na posição onde estiver o cursor. É preciso atenção
para levar em conta onde o cursor estará quando o comandoescrever() for realizado.
Uma seqüência de caracteres, delimitada por um par de aspas simples, é uma expressão
válida em Pascal e pode ser usada nos comandos de escrita. Elas serão escritas literalmente
no campo correspondente. Como as demais expressões, um formato pode ser adicionado
para especificar o tamanho ocupado na linha de saída. Caso um formato não seja
especificado, o tamanho usado será o menor possível.
Por exemplo, supondo que uma variável inteira n tenha o valor 30, o comando abaixo
imprime duas expressões, a literal 'n+5 = ' seguida do valor calculado de n+5.
escrever ('n+5 = ', n+5)
fará com que seja escrita na tela a frase: n+5 = 35
write (<expressão>)
equivale ao que foi descrito acima para escrever(<expressão>)
writeln
O cursor avança para o inicio da próxima linha na tela de saída. Equivale a escrever o
caractere <ENTER> ou novalinha.
FORMATOS DE SAÍDA
Os números reais serão impressos na notação cientifica se o formato não indicar o número
de casas decimais.
Note que o comando escrever( ) não acrescenta nenhum espaço após escrever cada valor de
expressão. Isso deve ser providenciado pelo programador. Por exemplo, se imprimir os
valores de x e y (inteiros) e z (real), valendo 153, 10245 e -32.767, respectivamente, o
comando:
escrever (x,y,z) escreverá na tela algo como:
15310245-3.27670000000000000E+001 o que pode ser muito desagradável.
Para ter uma saída mais legível, devemos levar em conta a necessidade dos espaços entre os
valores, e colocar um formato adequado para cada valor, com casas decimais para os
números reais. O comando:
escrever(x:5, y:6, z:9:2) escreverá na tela o seguinte (note o arredondamento de z):
153 10245 -32.77
Nos exemplos abaixo, as colunas de texto foram numeradas para melhor visualização:
colunas da tela--- 1 2 3 4 5 6 7 8 9 10 11 12 13
>
escrever(x:4) - 1 0
escrever(y:9:1) 2 5 . 7
escrever(y/2:12) 1 . 2 8 4 0 0 E + 0 1
escrever(y/2:8:3) 1 2 . 8 4 0
escrever(y/2+1:10:0) 1 4
escrever(letra) A
escrever(letra:5) A
Nota: O formato de impressão em notação cientifica pode variar ligeiramente entre várias implementações.
OBSERVAÇÕES ADICIONAIS:
Valores lógicos são impressos da seguinte forma (em Pascal):
verdadeiro --- > TRUE
falso --- > FALSE
O número de colunas usadas pode também ser controlado com o formato.
CAPíTULO 3
Nas definições abaixo, as palavras e símbolos que não estão entre os sinais de
< e > são considerados como elementos da linguagem Pascal e devem ser
escritos literalmente. As frases entre os sinais < e > são explicações em
português do que deve entrar no lugar delas. Dizemos que essas frases estão
escritas na meta-linguagem (a linguagem que usamos para definir uma outra
linguagem).
program <identificador>;
<declarações de constantes>
<declarações de variáveis>
<bloco>
Note a primeira palavra deve ser program e que o último caractere deve ser
um ponto-final, após o <bloco>.
Exemplo:
var
x,y:integer;
w,z:real;
letra1:char;
terminou: boolean;
Observações:
O bloco de comandos:
Note que, pela definição acima, um programa pode ter zero comandos, e ainda
ser um programa “bem formado”, embora não sirva para nada.
Exemplo de um programa:
program exemplo;
const
n1= 5;
n2= 3;
var
x,y:integer;
comp: boolean;
begin
writeln('Digite um multiplo de ',n1, ' e outro multiplo de ', n2, ': ');
read(x,y);
comp:= x > y;
readln; readln;
end.
program exemplo2;
(******************************************************************
*******************************************************************)
var
n1,n2,x,y:integer;
comp: boolean;
begin
n1:=5;
n2:=3;
writeln('Digite um multiplo de ',n1, ' e outro multiplo de ', n2, ': ');
read(x,y);
comp:= x > y;
readln; readln;
end.
Exemplo:
Seja o comando:
se (x mod 2 = 0) e (x < y) então escrever (x div 2) senão escrever (x+y)
(x mod 2= 0) e (x <y)
(0 = 0) e Verdade
Verdade e Verdade
Verdade
(x mod 2= 0) e (x <y)
(1 = 0) e Verdade
Falso e Verdade
Falso
c) Comando case:
Alem disso os valores não podem ser repetidos, ou seja, um valor só pode
aparecer em apenas um dos casos.
Sintaxe:
case <expressão> of
...
else
Comando;
...
Comando;
end
OBS: A parte do else pode não existir. Nesse caso, nada ocorrerá se nenhum dos casos for verificado.
Exemplo:
No exemplo abaixo, a expressão é uma variável c , do tipo caractere. O primeiro caso é uma lista
com duas faixas de valores, e inclui todas as letras maiúsculas entre A e Z, e todas as letras
minúsculas entre a e z. O segundo caso inclui os dígitos de 0 a 9. O terceiro caso inclui uma lista
com 4 valores , que são os caracteres usados para as operações aritméticas. Caso a expressão c não
tenha nenhum desses valores, os dois comandos após o else serão executados.
program exemplo;
var c: char;
begin
write('Entre com um caractere: ');
readln(c);
case c of
'A'..'Z','a'..'z': writeln('Caractere lido e'' letra.');
'0'..'9': begin
writeln('Caractere lido e'' um digito ');
writeln('entre 0 e 9');
end;
'+','-','*','/': writeln('Caractere lido e'' um operador matematico.');
else writeln('O caractere lido nao e'' letra, nem digito,');
writeln('nem operador matematico.');
end;
end.
Para melhor compreender o exemplo acima, segue abaixo o programa
equivalente usando comandos if..then...else equivalentes:
program exemplo_if;
var c: char;
begin
readln(c);
then begin
writeln('entre 0 e 9');
end
else begin
end;
end.
EXERCÍCIOS DE FIXAÇÃO:
ax2 + bx + c = 0
a) Existem duas raízes reais com valores <valor 1> e <valor 2>
Até 12.696,00 - -
A Base de cálculo acima é obtida subtraindo o total das deduções do rendimento bruto tributável
recebido no ano. O imposto é calculado em partes, um valor para cada faixa de rendimentos.
CAPíTULO 4
Na fase inicial da programação, quando ainda não haviam programas muito grandes, as linguagens de
programação dispunham apenas do comando goto(literalmente significando “vá para”) para forçar a
repetição de comandos. A ele dá-se o nome de desvio incondicional.
Apesar do seu uso não ser mais recomendado hoje em dia, a compreensão do funcionamento do
comando goto ajuda bastante a entender o funcionamento dos modernos comandos de repetição que
serão vistos mais adiante.
O comando goto é usado junto com um ponto de retorno chamado de rótulo (label em inglês). Qualquer
comando Pascal pode ser precedido por um rótulo seguido de : e o comando goto pode ser usado para
forçar um retorno do programa para qualquer um dos rótulos definidos. Rótulos são declarados na seção
de declarações do programa, precedidos da palavra-chave label. Um rótulo pode ser qualquer
identificador, ou um inteiro entre 0 e 9999. A sintaxe do comando é: goto <nome do rótulo>
Os exemplos abaixo ajudam a entender o mecanismo.
Seja obter a soma dos inteiros de 1 até um valor n qualquer maior que 1:
Exemplo 4.1 :
01:program testgoto;
02:var x,soma,n:integer;
03:label 1;
04:begin
05:soma:=0;
06:x:=1;
07:write('Ate'' que numero deseja somar os inteiros? ');
08:readln(n);
09:1: soma:=soma+x;
10:x:= x+1;
11:if x <= n then goto 1;
12:writeln('A soma de 1 a ', n, ' e'' igual a ', soma);
13:end.
No programa acima, as linhas estão numeradas para melhor compreensão das explicações. A seqüência
de comandos acima fará com que o programa fique repetindo os comandos das linhas 9, 10 e 11
enquanto o valor de x não ultrapassar o valor de n. Outra maneira de dizer a mesma coisa, é dizer que
essas linhas serão repetidas até que o valor de x ultrapasse o valor de n. Os comandos entre um rótulo e
o comando goto para esse rótulo recebem o nome de laço de repetição.
O programa seguinte mostra um exemplo mais complexo. Desejamos imprimir a seqüência de inteiros da
forma:
122333444455555 etc.
Note que a seqüência tem um laço dentro de outro laço. O laço mais “externo” faz com que os números
da seqüência variem de 1 até n, e o laço mais “interno” faz com que, para cada numero k, entre 1 e n,
este seja repetido k vezes.
Exemplo 4.2 :
01:program tesgoto2;
02:var x,k,n:integer;
03:label 1,2;
04:begin
05:write('Valor maximo da sequencia(< 20): ');
06:readln(n);
07:k:=0;
08:1: k:= k+1;
09: x:=1; {x conta quantas vezes k sera' escrito}
10: 2: write(k);
11: if x<k then
12: begin
13: x:= x+1;
14: goto 2;
15: end;
16:if k<n then goto 1;
17:end.
No programa acima, os comandos das linhas 08 a 16 formam o laço mais externo, e os comandos das
linhas 10 a 15 formam o laço mais interno.
O comando while
Significado:
“A expressão lógica é calculada. Se o seu valor for True, o comando é executado, e em seguida a
expressão volta a ser calculada. Enquanto o valor da expressão for True, o processo se repete: o
comando é executado, e a expressão volta a ser calculada. Caso o valor da expressão seja False, o
comando não é executado, e o controle passa para a próxima instrução após o while”.
Note que, se a expressao lógica for falsa logo na primeira vez que for calculada, o
<comando-a-repetir> não será executado nem uma vez. Obviamente, o <comando-a-
repetir> deve conter elementos que façam com que a expressão lógica se torne falsa após
um número finito de voltas, caso contrário o laço de repetição nunca terminará. Esse tipo de
erro chama-se de laço infinito, e quando ocorre diz-se, no jargão popular de computação,
que o programa entrou em “loop”. (“Loop” é a palavra inglesa para laço, e pronuncia-
se lup). A única forma de sair desse erro é forçar o fim do programa. No ambiente Turbo
Pascal isso é feito pressionando a tecla Control (CTRL), e BREAK, simultaneamente.
Exemplo 4.3:
program ex4_3;
var i: integer;
begin
i:=0;
while i < 5 do
begin
i:= i+1;
write(i)
end;
end.
Exemplo 4.4:
program ex4_4;
var
i: integer;
label 1;
begin
i:=0;
1: if i < 5 then
begin
i:= i+1;
write(i);
goto 1;
end;
end.
A seguir mostramos como ficam os exemplos 4.1 e 4.2 acima, quando o comando goto é substituído pelo
comando while:
Exemplo 4.5:
program ex4_5;
var x,soma,n:integer;
begin
soma:=0;
x:=1;
write('Ate'' que numero deseja somar os inteiros? ');
readln(n);
while x <= n do
begin
soma:=soma+x;
x:= x+1;
end;
writeln('A soma de 1 a ', n, ' e'' igual a ', soma);
end.
Exemplo 4.6:
program ex4_6;
(******************************************
Este programa imprime a seqüência
122333444455555... nnnn, de 1 a n.
Utiliza dois laços de repetição while,
um dentro do outro.
******************************************)
var x,k,n:integer;
begin
write('Valor maximo da sequencia(< 20): ');
readln(n);
k:=0;
while k<n do
begin
k:= k+1;
write(k);
x:=1; {x conta quantas vezes k sera' escrito}
while x<k do
begin
write(k);
x:= x+1;
end; {fim do while interno}
end; {fim do while externo}
end.
A linguagem Pascal ainda dispõe de dois outros comandos para construir laços de repetição:
O comando repeat
A diferença principal de significado entre o comando while e o comando repeat é que, no comando
repeat, a seqüência de comandos a repetir é executada sempre pelo menos uma vez, enquanto que no
comando while o comando a repetir pode não ser nunca executado.
O exemplo abaixo mostra como fica o programa do exemplo 4.3 quando o while é substituído por um
repeat:
Exemplo 4.7:
program ex4_7;
(************************
uso de repeat..until
************************)
var i: integer;
begin
i:=0;
repeat
i:= i+1;
write(i)
until i>=5
end.
O comando for
O comado for é uma forma abreviada de se escrever o comando while, para alguns casos particulares
mais freqüentes. A descrição abaixo se refere ao caso em que a variável de controle é inteira, mas esse
comando pode ser usado com qualquer variável de controle que seja ordinal, ou seja, cujos elementos
possuam umaordem determinada, como é o caso dos caracteres e outros tipos enumerados ainda não
vistos.
Formas sintáticas:
for <variável de controle> := <expressão inicial inteira> to <expressão final
inteira> do <comando a repetir>
Significado:
“a expressão inicial é calculada e a expressão final é calculada (ambas inteiras)
com os valores na memória no momento em que o comando for inicia. A variável de
controle recebe o valor inicial. Se esse valor for menor ou igual que o valor final,
então o comando a repetir é executado, a variável de controle é incrementada de
1 unidade, e o novo valor da variável é comparado com o valor final. Enquanto o
valor da variável de controle for menor ou igual ao valor final, o comando a repetir
será novamente executado, e a variável novamente incrementada. O comando
termina quando o valor da variável de controle ficar maior que o valor final.”
IMPORTANTE: a expressão inicial e final são calculadas apenas uma vez, no inicio da execução do
comando for. Mesmo que valores de variáveis que façam parte da expressão final forem alterados pelo
comando a repetir, isso não altera o valor final que será usado nos testes de comparação.
Significado:
“a expressão inicial é calculada e a expressão final é calculada (ambas inteiras)
com os valores na memória no momento em que o comando for inicia. A variável de
controle recebe o valor inicial. Se esse valor for maior ou igual que o valor final,
então o comando a repetir é executado, a variável de controle é decrementada de
1 unidade, e o novo valor da variável é comparado com o valor final. Enquanto o
valor da variável de controle for maior ou igual ao valor final, o comando a repetir
será novamente executado, e a variável novamente decrementada. O comando
termina quando o valor da variável de controle ficar menor que o valor final.”
program ex4_8;
(**************************
uso de for incrementando
a variável de controle
**************************)
var i,n: integer;
begin
write ('Digite um valor de n inteiro: ');
readln(n);
for i:= 1 to n do write(i);
end.
Compare com o programa 4.3 ou 4.7. Não é necessário incrementar a variavel i explicitamente, pois isso
é feito automaticamente pelo comando for. E também não é preciso fazer o teste se i ainda é menor que
n, pois isso também é feito automaticamente. Com isso o programa fica simplificado. A forma ideal de
“ler” o programa acima é: “para i variando de 1
até 5, imprima o valor de i”.
O exemplo seguinte escreve a seqüência invertida, na forma: n n-1 .... 4321, para um n inteiro qualquer:
Exemplo 4.9:
program ex4_9;
(**************************
uso de for decrementando
a variável de controle
**************************)
var i,n: integer;
begin
write ('Digite um valor de n inteiro: ');
readln(n);
for i:= n downto 1 do write(i);
end.
Nota: em Pascal existem duas funções especiais pré-definidas, que servem para fazer a associação entre
os caracteres e suas posições na tabela de caracteres. São elas:
ord (c) onde c é uma expressão que representa um caractere. A função retorna um inteiro entre 0 e
255, que é a posição (ou número de ordem) do caractere na tabela. Ex: ord (‘A’) é 65.
chr(n) onde n é uma expressão inteira com valor entre 0 e 255. A função retorna o caractere que fica na
posição n da tabela. Por ex: chr(65) é ‘A’.
Seja agora escrever um programa para listar todos os 256 elementos da tabela em uma única tela de
saída. A tela tem 24 linhas, com 80 caracteres em cada linha.
Podemos ver toda a tabela em uma única tela se tivermos 11 colunas, com 24 caracteres em cada uma
(11 x 24 = 264). Para as 11 colunas caberem em uma linha, cada coluna deve ter 7 caracteres. A saída
terá a aparência seguinte (apenas alguns caracteres são mostrados aqui, os demais estão representados
por um -):
coluna j→
0 1 2 3 4 5 6 7 8 9 10
linha i
↓
0 - 24 - 48 0 72 H 96 - 120 x 144 - 168 - 192 - 216 - 240 -
1 - 25 - 49 1 73 I 97 a 121 y 145 - 169 - 193 - 217 - 241 -
2 - 26 - 50 2 74 J 98 b 122 z 146 - 170 - 194 - 218 - 242 -
..........................................................................
..........................................................................
23 - 47 - 71 G 95 - 119 w 143 - 167 - 191 - 215 - 239 -
O programa deve ter um laço de repetição para escrever as 24 linhas e, para cada linha, outro laço para
escrever as 11 colunas.
Vamos usar a variável i para numerar as linhas de 0 a 23, e a variável j para numerar as colunas, de 0 a
10. Uma análise do quadro acima mostra que a posição do caractere k está na linha i e coluna j que
satisfazem a relação: k = j* 24 + i .
O programa deve levar ainda em consideração que alguns caracteres não representam símbolos a serem
escritos. Eles são usados como sinais de controle para o dispositivo de saída (monitor de vídeo ou
impressora) e portanto não convém que se tente imprimi-los. No lugar deles, colocamos duas letras que
indicam a sua função. São eles:
O caractere da posição 0 também não tem representação impressa, ele é o caractere nulo, na tabela
representado por NUL. O caractere 7 também não tem representação impressa, e tem o nome de BEL.
O programa abaixo cria então a tabela desejada. Note que em cada coluna, o valor de k é escrito com 3
posições, seguido do caractere chr(k), ocupando 2 posições, e seguido de mais 2 espaços para
completar as 7 posições da coluna. Para os caracteres especiais que não tem representação impressa, a
expressão chr(k) é substituída por uma palavra adequada, ou por espaços:
program tabela;
uses crt;
var i,j,k: integer;
begin
clrscr;
for i:= 0 to 23 do begin
for j:= 0 to 10 do begin
k:= j* 24 + i;
if k<=255 then begin
write(k:3);
case k of
0: write(' NUL');
7: write(' BEL');
8: write(' BS ');
10: write(' LF ');
13: write (' CR ');
else write(chr(k):2, ' ');
end; {case}
end; {if}
end; {for interno}
writeln;
end; {for externo}
end.
CAPíTULO 5
1 2 3 4 5 6
etc.
A forma geral é:
var <identificador do vetor>: array [<intervalo das posições>] of <tipo dos valores do vetor>
A mesma operação pode ser feita com apenas um comando de repetição for, usando uma
variável de controle para representar as posições do vetor:
for i:= 1 to 6 do v[i]:=0;
É fácil imaginar o que isso representa de simplificação para a manipulação de vetores
grandes.
Da mesma forma, para ler do teclado todos os valores do vetor v, seriam também
necessários 6 comandos:
read (v[1]);
read (v[2]);
read (v[3]);
read (v[4]);
read (v[5]);
read (v[6]);
Todos esses comandos podem ser substituídos por um único comando for:
for i:= 1 to 6 do read(v[i]);
O que se pode e o que não se pode fazer com vetores, na linguagem Pascal:
Nota: essas regras não se aplicam ao tipo string que é um caso especial de vetor de
caracteres com regras própria, e que será visto mais adiante.
Não é possível:
a) Não se pode ler todo um vetor diretamente com um comando read. Não se pode
escrever: read(v);
É necessário ler casa a casa, diretamente, ou com um laço de repetição como for no
exemplo acima.
b) Não se pode escrever todos os elementos de um vetor com um único comando write.
Não é permitido escrever: write(v). Também nesse caso cada elemento deve ser tratado
como uma variável independente, por exemplo:
for i:= 1 to 6 do write(v[i]:3);
c) Não é possível copiar os valores dos elementos de um vetor para outro com um único
comando de atribuição. Ou seja, dados dois vetores v e w, ambos do mesmo tamanho e
do mesmo tipo, não é permitido fazer: w:= v; . Também aqui é necessário trabalhar
elemento a elemento, e o comando for mais uma vez é indicado:
for i:= 1 to 6 do w[i]:= v[i];
c) Não existe comandos ou funções que dão o tamanho (número de elementos) de um vetor.
d) Não é permitido tentar acessar uma posição fora do intervalo de posições definido para o
vetor. A tentativa causará um erro em tempo de execução e o programa abortará. No caso
do vetor v acima, por exemplo, não é permitido escrever: v[8]:= 20, read(v[8]) ou
write (v[8]) porque a faixa de valores das posições vai de 1 a 6 apenas.
O que é permitido:
a) A faixa de valores das posições não precisa começar em 1. Qualquer intervalo de valores
pode ser usado na definição de um vetor. Por exemplo, podemos definir um vetor assim:
var v:array[15..20] of real;
Nesse caso o vetor v terá apenas os elementos: v[15], v[16], v[17], v[18], v[19] e v[20]
b) As posições não precisam ser necessariamente números inteiros. Podem ser qualquer
tipo ordinal, ou seja, que possa ser definido por uma seqüência ordenadade valores. Por
exemplo, os caracteres em Pascal formam uma seqüência ordenada na tabela de
caracteres, e podem portanto serem marcadores de posição em um vetor.
Podemos definir um vetor assim:
var letras: array['a'..'z'] of integer;
Nesse caso os elementos do vetor
são: letras['a'], letras['b'], ….., letras['z']
Um uso possível para esse vetor poderia ser que cada posição poderia guardar a
quantidade de vezes que a letra dessa posição aparece em uma determinada frase.
Exemplos de uso:
Ordenação de números:
Fazer um programa para ler n valores inteiros quaisquer, n <50, onde o valor de n deve ser
previamente fornecido pelo usuário.
Em seguida, o programa deve escrever na tela os valores em ordem numérica crescente.
A solução utiliza um algoritmo de ordenação .
O algoritmo abaixo é conhecido como ordenação por seleção. Os números são colocados
em um vetor definido com 50 posições. Inicialmente, procura-se a posição no vetor
(posMenor) onde está o menor número. Se essa posição for diferente da posição 1, então
troca-se os valores das casas 1 e posMenor. Isso garante que o menor elemento agora está
na posição 1. A seguir, repete-se o processo a partir da posição 2. Ou seja, procura-se a
posição do menor elemento da posição 2 em diante, que será posMenor. Se o valor de
posMenor for diferente de 2, troca-se os valores das casas 2 e posMenor. O processo é
repetido a partir da posição 3, depois 4, etc, até n-1. Nesse ponto o vetor estará com os
valores ordenados. Basta então escrever na tela os valores das posições 1 a n e teremos os
números em ordem crescente.
program ordenasel;
const nmax=50;
var
v: array[1..nmax] of integer;
i,j,n,posMenor,temp: integer;
begin
writeln('Digite um inteiro menor ou igual a ' ,nmax, ' : ');
readln(n);
writeln('Digite ',n,' inteiros separados por espacos');
for i:=1 to n do read(v[i]);
for i:=1 to n-1 do begin
posMenor:=i;
for j:=i+1 to n do
if v[j] < v[posMenor] then posMenor := j;
if i <> posMenor then begin
temp := v[i];
v[i] := v[posMenor];
v[posMenor] := temp;
end;
end;
writeln;
for i:=1 to n do write(v[i]:4);
end.
O tipo STRING
A linguagem Pascal original não possuía o tipo string. Hoje em dia, todas as versões
modernas de Pascal estendido possuem esse tipo (Turbo Pascal, Free Pascal, etc).
O tipo string é um caso especial de vetor de caracteres criado especialmente para tratar
com texto: palavras, frases, etc, onde a seqüência de caracteres deve ser tratada como uma
única entidade. A palavra string significa uma cadeia de caracteres. Cada posição de uma
string contém apenas um caractere.
As regras para vetores em geral não se aplicam às strings. Em particular, é permitido paara
strings:
a) ler uma string inteira com um único comando read ou readln: readln(frase);
b) escrever uma string inteira com um único comando write ou writeln: writeln(frase);
c) atribuir uma string diretamente: frase2:= frase;
d) escrever o valor literal de uma string entre aspas simples e usar em comandos de
atribuição ou de escrita: frase:= ‘rio de janeiro’; write(‘rio de janeiro’);
e) Caracteres individuais e strings podem ser usados de forma idêntica:
frase:= ‘a’; faz a string frase ser uma string com apenas o caractere ‘a’.
f) O uso da função length() que dá o tamanho (número de caracteres) de uma string.
g) O uso do operador de concatenação +, que permite unir duas strings produzindo uma
string que é a concatenação das duas: ‘ab’ + ‘cd’ produz a string ‘abcd’. O mesmo
pode ser obtido com a função concat(). Também aqui pode-se misturar strings com
caracteres de qualquer maneira: ‘a’ + ‘b’ dá a string ‘ab’, etc. O operador e a função
podem ser usados para concatenar varias strings e/ou caracteres:
Ex: frase := frase1 + frase2 + ‘!’;
frase := concat(frase1, frase2, ‘!’);
h) É possível comparar duas strings diretamente, usando os operadores relacionais
=, <>, >, <, >=, e <=, onde a comparação é feita pela ordem dos elementos na
tabela de caracteres, o que garante a ordem alfabética para strings contendo apenas
letras maiúsculas ou apenas minúsculas:
‘cde’ < ‘fgh’ dará true e ‘AB’ = ‘CD’ dará false
i) A posição zero de uma string contém sempre um número inteiro que é o tamanho da
string. Esse valor pode ser obtido usando a função ord(). Por exemplo, para imprimir o
tamanho da string frase, pode-se escrever: write ( ord(frase[0]); Na realidade a função
length() obtém o seu valor consultando a posição 0 da string.
program ordenanomes;
(**********************************************************************
algoritmo de selacao para ordenar nomes em ordem alfabética.
**********************************************************************)
const nmax=50;
var
v: array[1..nmax] of string;
i,j,n,posMenor: integer;
temp:string;
begin
writeln('Digite um inteiro menor ou igual a ' ,nmax, ' : ');
readln(n);
writeln('Digite ',n,' strings, uma em cada linha);
for i:=1 to n do readln(v[i]);
for i:=1 to n-1 do begin
posMenor:=i;
for j:=i+1 to n do
if v[j] < v[posMenor] then posMenor := j;
if i <> posMenor then begin
temp := v[i];
v[i] := v[posMenor];
v[posMenor] := temp;
end;
end;
writeln;
for i:=1 to n do writeln(v[i]);
end.
MATRIZES – vetores com mais de 1 dimensão:
2 30 17 35 7
0
1 2 3 4 5 (posições na linha)
Quando há mais de uma dimensão, damos o nome de matriz a esse arranjo de variáveis. O
caso mais comum é a matriz de 2 dimensões. Os elementos ficam dispostos em um plano,
composto por várias linhas do mesmo tamanho, como abaixo:
colunas
1 40 34 50 27 linhas
2 ↓
25 4 18 80
3 0 3 65 11
1 2 3 4
Na matriz de inteiros acima, existem 3 linhas, cada linha com 4 colunas, ou 3x4 (três por
quatro). Essa matriz pode ser declarada assim:
var mat: array[1..3, 1..4] of integer;
Após o nome da matriz, são colocados entre colchetes os intervalos em que ficam os
números das linhas, e os números das colunas, nessa ordem. Note que também aqui os
elementos da matriz devem ser todos do mesmo tipo.
Cada elemento da matriz é identificado pela notação: mat[i,j], onde i é o número da
linha, e j o número da coluna, onde se encontra o elemento. Na figura acima, temos então
que mat[1,1] tem o valor 40.
O comando for... do é muito usado para processar os valores de matrizes.
Exemplos:
a) Para zerar todos os elementos de uma matriz m, com 3 linhas e 4 colunas, declarada
como:
var
m: array[1..3, 1..4] of integer;
basta fazer:
for i:= 1 to 3 do
for j:= 1 to 4 do m[i,j] := 0;
Nota: é usual usar-se a variável i para representar as linhas de uma matriz, a variável j para
representar as colunas.
b) Para ler do teclado valores para preencher a matriz acima (12 valores):
for i:= 1 to 3 do
for j:= 1 to 4 do read(m[i,j] );
Nota: O usuário poderá digitar todos os 12 números em uma só linha (separados por
espaços), ou um número por linha, ou, melhor, 4 números por linha, de forma a visualizar
melhor a matriz.
CAPíTULO 6
Conceituação:
Sub-programas são partes de um programa que podem ser consideradas como tarefas
relativamente independentes das demais. Por isso, podem ser programadas de forma
separada, recebem um nome, e depois podem usadas várias vezes dentro do programa
bastando serem “chamadas” pelo nome.
Há duas categorias clássicas de sub-programas: funções e procedimentos.
Funções:
Uma função é um sub-programa que realiza uma tarefa de calcular e produzir como
resultado um valor, o qual será usado por outras partes do programa:
Ex: o programa abaixo usa a função pré-definida sqrt(n), que calcula a raiz quadrada de um
real n, e dá como resultado um valor real:
Exemplo 6-1:
program ex6_1;
var L1,L2,H: real;
begin
L1:= 3.0;
L2:= 4.0;
H:= sqrt(L1*L1+L2*L2);
writeln('A hipotenusa do triangulo retangulo de lados ', L1:3:1, ' e
',
L2:3:1, ' e'' ' ,H:3:1);
end.
No exemplo acima, a função sqrt já vem pré-definida na linguagem Pascal, e pode ser
utilizada diretamente. Note o seguinte:
a) a função tem um argumento real n, ou seja, para usá-la é preciso fornecer um valor real
entre parênteses. A definição de uso é sqrt(n) onde n deve ser um valor real.
b) esse argumento pode ser qualquer expressão real, no exemplo foi L1*L1+L2*L2.
c) a função realiza uma tarefa, através de um algoritmo próprio, para calcular a raiz
quadrada. Essa tarefa constitui o sub-programa, que nesse caso já está armazenado no
computador em forma compilada.
d) quando o programa for executar o comando: H:= sqrt(L1*L1+L2*L2);
vai ocorrer o seguinte:
- primeiro, a expressão do argumento será calculada, para obter o seu valor. No
caso, será calculado o valor 3.0*3.0 + 4.0*4.0 que dá 25.0.
- em seguida o programa entrará em um estado de suspensão da sua execução, e o
controle da execução passará para o primeiro comando do sub-programa sqrt.
- antes de iniciar o sub-programa, o valor calculado do argumento, no caso 25.0,
será passado como valor inicial de uma variável especial do sub-programa que
representa o argumento da função. Essa variável é chamada de parâmetro de valor e
a operação é chamada de passagem de parâmetro.
- o sub-programa executará seus comandos, e a raiz quadrada do argumento será
calculada, obtendo o valo 5.0, nesse caso.
- ao terminar, o sub-programa repassará o valor obtido de volta para o programa. Isso
é feito substituindo a aplicação da função, sqrt(L1*L1+L2*L2),pelo resultado
obtido.
- nesse ponto o controle da execução voltará para o programa no ponto em que havia
interrompido, e o programa executará o comando: H:= 5.0;continuando a
execução normalmente a partir desse ponto.
program ex6_2;
var
x:integer;
function fat(n:integer): longint;
var
i: integer;
f: longint;
begin
f:=1;
for i:= 2 to n do f:= f*i;
fat:= f;
end; {fim da declaracao da funcao}
Voltando então para a execução do Exemplo 6-2, vemos que o laço de repetição fará com
que a função fat seja chamada várias vezes, cada vez com um argumento diferente. A cada
vez, o programa será interrompido, o controle será passado para a função, um resultado será
obtido e repassado de volta ao programa, substituindo a aplicação da função.
program ex6_3;
var
frase:string;
i: integer;
function maiuscula(c:char):char;
{essa funcao converte letras minusculas em maiusculas}
begin
case c of
'a'..'z': maiuscula:= chr(ord('A') + ord(c)-ord('a'));
else maiuscula:= c;
end;
end;
begin
writeln('Digite uma frase. Ela sera'' re-escrita em letras maiusculas: ');
readln (frase);
for i:=1 to length(frase) do frase[i] := maiuscula(frase[i]);
writeln(frase);
end.
Note que a função foi aplicada a um argumento do tipo char, e que o valor resultante
também é do tipo char. Para alterar as letras da string frase, foi necessário usar um laço de
repetição para aplicar a função sucessivamente a cada caractere da frase.
No próximo exemplo, a função será aplicada a toda a frase de uma vez (o argumento é do
tipo string) e o resultado também será do tipo string, isto é, a função retorna a frase inteira
alterada:
program ex6_4;
var
frase:string;
i: integer;
function maiusc_str(s:string):string;
{essa funcao retorna uma string com todas as letras maiusculas}
var i: integer;
begin
for i:= 1 to length(s) do
case s[i] of
'a'..'z': s[i]:= chr(ord('A') + ord(s[i])-ord('a'));
end;
maiusc_str:= s;
end;
begin
writeln('Digite uma frase. Ela sera'' re-escrita em letras maiusculas:
');
readln (frase);
writeln(maiusc_str(frase));
end.
Uma observação importante: a função não altera a string frase. Ela retorna outra string, com
as letras alteradas, que substituirá a expressão maiusc_str(frase).É essa string retornada
que será impressa. O valor original da string frase não foi alterado.
Exemplo 6-5:
program ex6_5;
var
frase: string;
i,n: integer;
Procedimentos
Exemplo 6-6:
program ex6_6;
uses crt; {necessario para usar gotoxy e clrscr}
var linhamedia,colunamedia: integer;
m:string;
procedure msg(frase:string; x,y: integer);
begin
gotoxy(x,y);
write(frase);
end;
begin
clrscr;
msg('esta frase na linha 1 coluna 1', 1, 1);
msg('esta frase na linha 3 coluna 2', 2, 3);
msg('esta frase na linha 5 coluna 3', 3, 5);
m:= 'meio da tela';
linhamedia:=12;
colunamedia:=40;
msg(m,colunamedia-length(m) div 2,linhamedia);
end.
Parâmetros de Referência
Até agora todos os parâmetros usados nos exemplos de funções e procedimentos
foram parâmetros de valor. Um parâmetro de valor é uma variável local do sub-programa,
que tem a propriedade de receber um valor inicial passado durante a chamada. Fora disso,
comporta-se como uma variável local normal, como as demais definidas na seção var.
As variáveis locais de um sub-programa existem em um espaço de memória próprio, que só
é acessível ao sub-programa. Por esse motivo, os parâmetros de valor não podem ser
”vistos” pelo programa externo ao sub-programa. Apenas o resultado do cálculo da função
pode retornar ao programa.
Os parâmetros de referência, ou parâmetros variáveis, permitem que valores calculados no
sub-programa possam ser repassados ao programa, de forma diferente do mecanismo de
retorno de função.
O mecanismo usado no parâmetro de referência é o seguinte:
a) na definição do procedimento, os parâmetros de referência devem ser precedidos do
prefixo var.
b) Na chamada do procedimento, os argumentos usados no lugar de parâmetros de
referência devem ser obrigatoriamente nomes de variáveis do programa, e não
expressões.
c) Quando o procedimento é chamado, o parâmetro de referencia recebe, não mais um
valor, mas uma referência para a variável correspondente do programa. Na prática, isso
significa que o parâmetro do sub-programa, e a variável correspondente do programa,
passam a ser a mesma variável, como se fossem sinônimos. O efeito é que tudo que
acontece com um parâmetro de referência do sub-programa vai se refletir
imediatamente na variável correspondente do programa. Ou seja, quando o sub-
programa termina, e devolve o controle de execução ao programa, as variáveis passadas
por referência para o sub-programa podem ter sido alteradas.
E R A L D O 1 2 3
4 5 6 7 8 9 10
R I O D E J
1
A N E I R O
2
3
4
5
6
7
8
9
10
A codificação é completada reescrevendo a matriz em forma de string, desta vez escrevendo os caracteres
segundo as colunas, a partir da coluna 1, apenas para as linhas usadas.
Completando o exemplo acima, a frase codificada fica da forma seguinte:
UDERANARINIDAOEVEL IE DRRFDEOSEO ID J
O interessante é que o mesmo processo pode ser usado tanto para codificar
como para decodificar. Para decodificar, toma-se a frase codificada, desta vez
com chave (no. de colunas) igual ao número de linhas usado na codificação
original, obtendo a matriz transversa abaixo:
1 2 3 4 5 6 7 8 9 10
U D E R A 1
NA R I N 2
3
I D A O E 4
V E L I 5
6
E D R 7
8
R F D E O 9
10
S E O
I D J
Basta usar o processo de codificação para obter a
frase original, lendo coluna a coluna.
A função usa uma matriz 10x10, podendo acomodar frases de até 100
caracteres.
program codifica_matr;
{Este programa codifica textos usando o metodo da matriz transposta}
var
frase: string;
chave:integer;