Programação
Programação
Programação
instrução composta
instruções de selecção
instruções repetitivas
A instrução if-else (se-então-senão) permite uma selecção de duas alternativas disjuntas (selecção
dicotómica) de execução das instruções A e B (B pode não existir: instrução vazia), de acordo com o
valor lógico de uma expressão (condição) C, conforme ilustra o diagrama de fluxo seguinte.
if (condição)
instrução1;
[else
instrução2;]
Exemplo 3.1
Determinar se um inteiro lido é par ou ímpar.
#include <stdio.h>
main()
{
int n;
if (n % 2 == 0) /* condição */
printf("O número é par\n");
else
printf("O número é ímpar\n");
}
Notar a condição (entre parêntesis) n % 2 == 0. Trata-se de uma expressão lógica (ou Booleana)
expressa através do operador de igualdade == (não confundir com a atribuição de valor, =). A
avaliação de uma expressão lógica resulta num valor verdadeiro ou falso.
Operador
Significado
relacional
< menor que
<= menor ou igual que
> maior
>= maior ou igual que
== igual a
!= diferente de
Operadores lógicos:
Expressão Resultado
a != 0 && b < 0 verdadeiro
a !=0 && b = 0 falso
!(a >= 0) falso
a >=0 || ! (b != 0) verdadeiro
Em C não existe um tipo Booleano de dados. Qualquer valor numérico diferente de zero é
interpretado como verdadeiro; zero é interpretado como falso.
Exemplo 3.2
Interpretar o seguinte programa.
#include <stdio.h>
main()
{
int x = 2;
if (x)
printf("Isto é escrito\n");
else
printf("Isto não é escrito");
}
Exemplo 3.3
Determinar se um inteiro lido é positivo e par.
#include <stdio.h>
main()
{
int x;
printf("Escreva um número inteiro:");
scanf("%d",&x);
if (x >= 0 && x % 2 == 0)
printf("O número é positivo e par\n");
else
printf("O número é negativo ou ímpar\n");
}
Regras de precedência:
Operador
!
< <= > >=
== !=
&&
||
Exemplo 3.4
#include <stdio.h>
#include <math.h>
main()
{
/* calcula maior raiz de ax^2 + bx + c = 0, a>=0 */
float a, b, c;
double discr;
if (discr < 0)
printf("Raízes complexas !\n")
else
printf("Maior raiz = %E\n", (-b+sqrt(discr))/(2*a) );
}
Notas:
• A inclusão da header file math.h permite a utilização de várias funções matemáticas tais
como: sin, cos, atan, exp, log, fabs (valor absoluto de real), sqrt.
• Por forma a incluir o código destas funções é necessário efectuar uma "linkagem" com a
respectiva biblioteca. Isto é feito com a opção -lm; assim, se o programa for guardado em
pol2.c a compilação será feita com:
gcc pol2.c -lm -o pol2.out
• Podem utilizar-se outras funções úteis (tal como abs, valor absoluto de um inteiro) existentes
na biblioteca standard <stdlib.h>, sem necessitar de qualquer menção especial no código
ou na compilação. Outras implementações de C exigem a directiva #include
<stdlib.h>.
• Podemos inspeccionar a forma de utilizar uma função usando o comando man do Linux.
Assim, p. ex., man sqrt informar-nos-á de que a função sqrt tem um argumento de tipo
double e fornece um valor de tipo double.
Na descrição sintáctica de if-else (ou de qualquer outra instrução de controlo) podemos sempre,
onde se menciona instrução, usar uma instrução composta em vez de uma instrução simples.
Exemplo 3.5
#include <stdio.h>
#include <math.h>
main()
{
/* Calcula raizes de ax^2 + bx + c = 0 */
float a, b, c;
double discr, x1, x2;
printf("Escreva os valores de a, b e c:");
scanf("%f%f%f",&a, &b, &c);
if (discr < 0)
printf("Raizes complexas !\n")
else
{ /* bloco de instruções */
discr = sqrt(discr);
x1 = (-b + discr) / (2*a);
x2 = (-b - discr) / (2*a);
printf("Raizes : %E , %E\n", x1, x2);
}
}
...
int a, b , c;
if (a > b)
if (b > c)
printf("a > b > c\n");
else
printf("a > b; c >= b\n");
...
if (a > b)
{
if (b>c)
printf("a > b > c\n");
}
else
printf("b >= a\n");
A instrução switch (comutador) permite lidar de forma eficiente com selecções não dicotómicas.
Consiste numa enumeração de instruções alternativas, conforme o valor de uma expressão:
switch (expressão)
{
case constante1: instruções1;
case constante2: instruções2;
...
case constanteN: instruçõesN;
[default: instruções;]
}
• A expressão pode ser do tipo char, int ou long.
• Depois de avaliada remeterá para o caso de valor constante correspondente (do mesmo tipo)
sendo assim executada a respectiva instrução (simples ou bloco) bem como as que se seguem
até terminar a chaveta final do switch.
• Para sair do switch usa-se a instrução break.
• A parte opcional default toma conta dos valores não enumerados em case.
Exemplo 3.6
#include <stdio.h>
main()
{
/* Escreve o resultado c, de a operado com b;
aceita apenas os operadores + e * (ou x) */
float a, b, c;
char op;
switch (op)
{
case '+' : c = a + b; printf("c = %f\n", c); break;
case '*' :
case 'x' : c = a * b; printf("c = %f\n", c); break;
default: printf("Operador inválido !\n");
}
}
• while
• do-while
• for
3.3.1 Instrução while
while (condição_C)
instrução_A;
Exemplo 3.7
Escrever os primeiros dez números naturais.
Algoritmo Implementação em C
#include <stdio.h>
main()
{
inicializar n=1;
int n = 1;
while (n <=10)
enquanto n for <=10 fazer:
{
• escrever o valor de n; printf("%d\n", n);
• incrementar n de 1; n = n + 1;
}
}
Exemplo 3.8
Escrever um programa que leia números inteiros a partir do teclado e acumule a some dos
números positivos. O programa termina se o número lido for zero e nessa altura escreve a soma.
Algoritmo Implementação em C
#include <stdio.h>
inicializar soma corrente com main()
0; {
ler primeiro número, n; int n, soma = 0;
scanf("%d", &n);
while (n != 0)
enquanto n for ! = 0 fazer:
{
• Se n > 0 acumule à if (n > 0)
soma; soma = soma + n;
• ler próximo número, n; scanf("%d", &n);
}
escrever o valor da soma. printf("%d\n", soma);
}
Exemplo 3.9
Escrever um programa que determine e escreva no ecrã quantas vezes um determinado número
lido é divisível por 2.
Algoritmo Implementação em C
inicializar n_vezes com 0; #include <stdio.h>
ler o número n; main()
{
int n, n_vezes = 0;
enquanto n for divisível por
printf("Escreva o número:");
2 fazer:
scanf("%d", &n);
• incrementar while (n % 2 == 0 && n != 0)
n_vezes; {
• actualizar n para o n_vezes = n_vezes +1:
seu n = n / 2;
quociente de div. por }
2; printf("%d\n", n_vezes);
}
escrever o valor de
n_vezes.
Exemplo 3.10
Escrever um programa que determine o máximo de uma sequência de valores inteiros lidos do
teclado, terminada com zero, assinalando a posição em que esse máximo ocorreu.
Algoritmo Implementação em C
#include <stdio.h>
main()
{
int n, max, pos_corr = 1,
inicalizar pos_corr=1 e pos_max = 1;
pos_max=1;
printf("Escreva o 1.o
ler o primeiro número n; número:");
scanf("%d", &n);
inicializar max=n;
max = n;
enquanto n for !=0 fazer:
while (n != 0)
• ler próximo número,
{
n;
printf("Escreva novo
• incrementar pos_corr número:");
de 1; scanf("%d", &n);
• se n > max então: pos_corr = pos_corr + 1;
actualizar max=n; if (n > max)
actualizar {
pos_max=pos_corr max = n;
pos_max = pos_corr;
escrever o valor de max, e }
pos_max. }
printf("O máximo é %d e
ocorreu na posição %d\n", max,
pos_max);
}
Notar que este algoritmo usa extensivamente a ideia de actualização de valor, já referida aquando da
instrução if-else e que tem uma aplicação muito frequente em algoritmia. Podemos por analogia
considerar max uma marca de um depósito de água que se move para cima sempre que a água no
depósito sobe.
Exemplo 3.11
Escrever um programa que determine o factorial, n!, de um número inteiro n >=0. Por
definição n!=n.(n-1)! e 0!=1!=1.
Algoritmo Implementação em C
inicializar fact com 1; #include <stdio.h>
ler o número n; main()
inicializar termo corrente {
com n; int n, termo;
long fact = 1;
enquanto termo for > 1 printf("Escreva o número:");
fazer: scanf("%d", &n);
• fact = fact *
termo; termo = n;
• termo = termo -1; while (termo > 1)
escrever o valor de fact. {
fact = fact * termo:
termo = termo - 1;
}
printf("factorial=%d\n", fact);
}
Notar que, neste exemplo, para n=0, 1 o programa calcula correctamente (por definição de factorial)
fact=1. Importa declarar fact como long (melhor ainda unsigned long) dado que a função fact
cresce rapidamente.
É frequente, em laços, usar-se incrementos (x=x+1) ou decrementos (x=x-1) tal como nos exemplos
anteriores. A linguagem C dispõe de operadores de incremento (++) e decremento (--) para este
efeito.
Exemplo 3.12
Exemplo Significado
x++; (ou
x = x + 1;
++x;)
x--; (ou --
x = x - 1;
x;)
y = x; x = x +
y = x++;
1;
y = ++x; x = x + 1; y = x;
Atribuição composta:
Sempre que temos uma atribuição do tipo:
var = var op (expressão)
var op = expressão
Exemplo 3.13
do
instrução_A;
while (condição_C);
Exemplo 3.14
Implementação alternativa do Exemplo 3.11:
Algoritmo Implementação em C
#include <stdio.h>
main()
{
int n, termo;
inicializar fact com 1; long fact = 1;
printf("Escreva o número:");
ler o número n;
scanf("%d", &n);
inicializar termo corrente
com n;
termo = n;
do
enquanto termo for > 1 fazer:
{
• fact = fact * termo; fact *= termo;
• termo = termo -1; termo--;
escrever o valor de fact. }
while (termo > 1);
printf("factorial=%d\n",
fact);
}
A diferença face à solução anterior é que agora dá o resultado errado fact=0 para n=0, consequência
da execução de (pelo menos uma vez) da 1ª instrução do laço.
Podemos forçar o fim de um laço usando a instrução break (já referida na instrução switch).
Assim, resolveríamos o problema anterior inserindo a seguinte instrução em do-while:
...
termo = n;
do
{
if (termo == 0) break;
fact *= termo:
termo--;
}
while (termo > 1);
for
(inicializações; condição_C; pós-instrução)
instrução_A;
Algoritmo Implementação em C
#include <stdio.h>
inicializar n=1;
main()
{
enquanto n for <=10 fazer:
int n;
• escrever o valor de for (n=1; n <= 10; n++)
n; printf("%d\n", n);
• incrementar n de 1; }
Exemplo 3.16
Escrever um programa que gere uma tabela de 10 quadrados e cubos dos naturais, a partir e
com incrementos de respectivamente de 2 e 3.
#include <stdio.h>
main()
{
int i, x, y;
for (i=1, x=2, y=3; i <= 10; i++, x += 2, y += 3)
printf("Quad. de %d=%d, Cubo de %d=%d\n", x, x*x, y, y*y*y);
}
Exemplo 3.17
Escrever um programa que gere uma tabela das primeiras 20 potências de 2.
Algoritmo Implementação em C
inicializar n=1; (contador do #include <stdio.h>
laço) main()
inicializar var. corrente pot2 {
com 1 (= 2^0); int n;
float pot2 = 1.0;
enquanto n for <=20 fazer: for (n=1; n <= 20; n++)
• actualizar pot2 {
(multiplicando por 2 o pot2 *= 2.0;
seu valor anterior); printf("2^%d = %f\n", n,
• Escrever o valor de pot2);
pot2; }
• Incrementar n de 1; }
Exemplo 3.20
Escrever um programa que simule sucessivas vezes a experiência de atirar um dado ao ar,
usando a função standard (<stdlib>) de geração de números aleatórios rand(). A simulação
deve parar quando saírem dois seis consecutivos. Nesse momento devem ser escritas no ecrã quantas
subsequências contínuas de valores <=3 foram encontradas.
A função rand() fornece sempre um valor inteiro longo, pseudo-aleatório entre 0 e um certo valor
constante (RAND_MAX). A fim de obter um valor inteiro x em [1, k], teremos que usar: x = 1 +
rand() % k. Para obter um valor real em [0,1] usar (float) rand()/RAND_MAX.
A fim de detectar as subsequências precisamos de uma variável auxiliar que indique quando estamos
dentro de uma subsequência. Designemos essa variável lógica por seq (0= falso; 1 (ou qualquer valor
diferente de 0)= verdadeiro). A variável nseq contará o número de subsequências detectadas. A
condição de paragem usa também uma variável lógica stop.
Algoritmo:
O aluno deverá notar que a determinação de uma solução algorítmica segue habitualmente uma
abordagem estruturada top-down, que parte das estruturas mais exteriores procurando especificar as
mais interiores.
Perante o enunciado anterior, teremos, seguindo do "exterior" para o "interior":
Implementação em C:
#include <stdio.h>
main()
{
int fp, fa; /* fp: face precedente; fa: face actual */
int seq=0, nseq=0; /* seq: subsequência "ON";
nseq: nº de subseq. */
int stop=0; /* condição de paragem */
do {
fa=1+rand()%6; printf("%d, ", fa);
if (seq && fa > 3) seq=0;
if (!seq && fa <= 3) {
seq=1; nseq++;
}
if (fp==6 && fa==6) stop=1;
fp=fa;
}
while (!stop);
printf("\nNº de subsequências: %d\n", nseq);
}
Nota: Frequentemente é necessário gerar números aleatórios num certo intervalo, e.g. [0,1]. Efectua-
se isto como ilustra o seguinte programa:
#include <stdio.h>
#include <stdlib.h> /* contém a definição de RAND_MAX */
main()
{
int i, float x;
for (i=0; i<20; i++) {
x=rand();
printf("%f\n", x/RAND_MAX);
}
}