Faculdade de Engenharia da Universidade do Porto

LICENCIATURA EM ENGENHARIA INFORMÁTICA E COMPUTAÇÃO INTRODUÇÃO À PROGRAMAÇÃO DE COMPUTADORES II - 1999/2000 EXERCÍCIOS João Pascoal Faria (jpf@fe.up.pt)

1. Introdução ao ambiente de programação
1.1. Siga o seguinte guião:
• Arranque o Microsoft Visual C++ 5.0 a partir de Start → Programs → Microsoft Visual C++ 5.0 → Microsoft Visual C++ 5.0. • Crie um novo projecto e espaço de trabalho ("workspace"), com a opção File → New ... → Projects, fornecendo os seguintes dados: Win32 Console Application Location = c:\temp (ou outro directório com permissão de escrita) Project name = ip2 (ou outro nome à sua escolha) √ Create new workspace • Crie um ficheiro com a opção File → New ... → File, fornecendo os seguintes dados: C++ Source File File name = c:\temp\ip2\ip2.c (ou outro nome) √ Add to project • Na janela de edição do ficheiro acabado de abrir, introduza o seguinte programa em C: #include <stdio.h> main() { printf("Ola!\n"); return 0; } • Crie o executável com a opção Build → Build ip2.exe • Corra o executável com a opção Build → Execute ip2.exe • Corra o executável fora do Visual C++, a partir do Windows Explorer e a partir da MS-DOS Prompt (o executável estará em c:\temp\ip2\debug\ip2.exe) • Experimente introduzir e executar outros programas apresentados nas aulas teóricas. • Explore à sua vontade o ambiente de trabalho do Visual C++!

1.2. No sistema operativo Linux, crie um ficheiro de texto ola.c com o mesmo conteúdo do exercício
anterior, usando um editor de texto à sua escolha ( emacs, vi, pico, etc.). Compile o programa com o comando:

gcc ola.c -o ola Execute o ficheiro executável ola criado por este comando.

2. Introdução à programação em C
2.1. [Deitel 2.7] Identifique e corrija os erros em cada uma das instruções seguintes (Nota: pode existir
mais do que um erro por instrução): a) b) c) d) e) f) g) h) i) j) scanf("%d", value); printf("O produto de %d e %d é %d\n", x, y); firstNumber + secondNumber = sumOfNumbers if (number => largest) largest == number; */ Programa para determinar o maior de três inteiros /* Scanf("%d", anInteger); printf("O resto da divisão de %d por %d é \n", x, y, x % y); if (x = y); printf(%d é igual a %d\n", x, y); printf("A soma é %d\n," x + y); Printf("O valor introduzido foi: %d\n, &value);

2.2. [Deitel 2.12] O que aparece escrito no ecrã, se é que é aparece alguma coisa, em resultado da
execução de cada uma das seguintes instruções em C? Suponha que x = 2 e y = 3. a) b) c) d) e) f) g) h) i) printf("%d", x); printf("%d", x + x); printf("x="); printf("x=%d", x); printf("%d = %d", x + y, y + x); z = x + y; scanf("%d%d", &x, &y); /* printf("x + y = %d", x + y); */ printf("\n");

2.3. [Deitel 2.15] Indique a ordem de avaliação dos operadores em cada uma das seguintes instruções
em C, e mostre o valor de x após a execução de cada uma das instruções. a) b) c) x = 7 + 3 * 6 / 2 - 1; x = 2 % 2 + 2 * 2 - 2 / 2; x = (3 * 9 * (3 + (9 * 3 / (3))));

2.4. [Deitel 2.19] Escreva um programa em C que leia 3 inteiros diferentes introduzidos pelo teclado, e
apresente no ecrã a soma, a média, o produto, o menor e o maior desses números. Use apenas a forma

++x. ++x. y). ++y. [Deitel 3. while (y > 0) { printf"%d\n". ++x. else printf("A idade é menor que 65\n").de selecção simples (sem else) da instrução if. while (x <= 10) { y = x * x. printf("%d\n".h> main() { int x = 1. while (x <= 10) { total += x. total += y.13] O que escreve o programa seguinte? #include <stdio. O diálogo deve aparecer no ecrã com o seguinte aspecto: Introduza três inteiros diferentes: 13 27 14 A soma é 54 A média é 18 O produto é 4914 O menor é 13 O maior é 27 3. int x = 1. } c) While (x <= 100) total += x. total). y. y). return 0. } b) d) 3. } .2.11] Identifique e corrija os erros em cada uma das alíneas seguintes (Nota: pode existir mais do que um erro por alínea): a) if (age >= 65). [Deitel 3. total. printf("A idade é maior ou igual que 65\n"). } printf("O total é %d\n". Introdução à programação estruturada 3. total = 0.1.

o programa deve também imprimir o comprimento da sequência. printf("$$$$$\n"). b) supondo que o comprimento da sequência é indicado previamente. deve proceder da seguinte forma: 1. Escreva um programa em C que leia uma sequência de números inteiros.6. [Deitel 3. depure e execute o programa em C.31] Determine a saída produzida em cada uma das alíneas seguintes.35] Uma capicua é um número ou um texto que se lê da mesma maneira de trás para a frente e da frente para trás.5. (Sugestão: Comece por aplicar as convenções habituais de "indentação". a não ser que se indique outra coisa através de chavetas {}. Por exemplo. printf("$$$$$\n").) b) Generalize o programa da alínea (a) por forma a tratar inteiros com qualquer número de dígitos.4. no caso em que x = 9 e y = 11. Note que o compilador de C ignora a "indentação". e no caso em que x = 11 e y = 9. if (x < 10) { if (y < 10) printf("*****\n").34] Escreva um programa que leia o comprimento do lado de um quadrado (entre 1 e 20) e escreva no ecrã um quadrado "oco" com asteriscos. 2. 3. Note também que o compilador de C associa um else ao if mais próximo. os seguintes números são capicuas: 12321.4 a 3. Leia o enunciado do problema. e determine e imprima a soma. [Deitel 3. 555. Escreva um programa em C. No caso da alínea (a). else printf("#####\n"). 3. 45554 e 11611. a) supondo que o fim da sequência é indicado pelo valor 0 (que já não faz parte da sequência).3. Por exemplo.9). } b) Para cada um dos exercícios seguintes (3. Teste. se o comprimento dado for 5. (Sugestão: Use os operadores de divisão e módulo para separar o inteiro nos seus dígitos. a média. 3. o menor e o maior dos números. } else { printf("#####\n"). [Deitel 3.) a) if (x < 10) if (y < 10) printf("*****\n").3. Formule o algoritmo usando pseudo-código e refinamento sucessivo "top-down". 4. a saída do programa deve ser: ***** * * * * * * ***** 3. . a) Escreva um programa que leia um inteiro de 3 dígitos e determine se é ou não uma capicua.

3. } c) O código seguinte deve ler um inteiro e um caracter e imprimir os dois. b) O código seguinte deve imprimir se um dado inteiro é par ou ímpar: e) O código seguinte deve imprimir os inteiros ímpares de 999 até 1: . (Sugestão: Não é possível construir um triângulo com um lado maior do que a soma dos outros dois.) 4. Controlo de programa 4. respectivamente. x >= 1. Exemplo: Introduza a primeira hora no formato hhmm: 1845 Introduza a segunda hora no formato hhmm : 0620 A soma é: 1 0105 Sugestões: Ler cada hora do dia para um inteiro.42] Escreva um programa que leia o raio de um círculo (do tipo float) e calcule e imprima o diâmetro.000001) printf("%. x). d) for (x = . x >= . x >= 1. com 2 casas decimais. o perímetro e a área do círculo. x).44] Escreva um programa que leia três valores positivos do tipo float. em que hh indica as horas (de 0 a 23) e mm os minutos (de 0 a 59). o quociente e o resto da divisão inteira por 100 dão as horas e os minutos. [Deitel 3. x += 2) printf("%d\n".000001.9.5 a)-g)] Encontre e corrija os erros em cada uma das alíneas seguintes: a) For (x = 100. printf("Inteiro: %d\nCaracter: %c\n". em que d é o número de dias (0 ou 1). x += .7. 3. Para escrever um inteiro n (representando horas ou minutos) em 2 casas preenchidas com zeros à esquerda. Escreva um programa que leia duas horas do dia no formato hhmm.1.14159 para π.8.2d". Suponha que o utilizador introduz 100 A. charVal).0001. e calcule e imprima a respectiva soma no formato d hhmm. x). case 1: printf("Inteiro ímpar\n"). e determine se esses valores poderiam representar as medidas dos lados de um triângulo. usar a instrução: printf("%. x++) printf("%d\n". switch (value % 2) { case 0: printf("Inteiro par\n"). for (x = 999. 3.7f\n". [Deitel 3. Use o valor 3. [Deitel 4. charVal = getchar(). scanf("%d". &intVal). intVal.n).

3.7] Escreva instruções for para imprimir cada uma das seguintes sequências de valores: a) 1. contador). 8. do m = m * 10 + aux mod 10 while aux / = 10. 4. x++). /* Nesta altura. " é uma capicua\n") else printf(n. 23 c) 20. h) O programa seguinte pretende responder à questão 3. total += x. /* mas por ordem inversa.6.f) O código seguinte deve imprimir os inteiros pares de 2 até 100: contador = 2. 2. " não é uma capicua\n"). 13. do printf("Introduza um inteiro positivo: "). 2. 6. -4. if (m = n) printf(n.b): #include <stdio. } While (contador < 100). 8. 7 b) 3. } return 0 4. main { int n. contador += 2. 18.2. m deve ter os mesmos digitos que n. x <= 150.h>. g) O código seguinte deve somar os inteiros de 100 até 150 (suponha que total é inicializado com 0): for (x = 100. n). 5. int aux = n. int m = 0. while n > 0. scanf("%f". 14. [Deitel 4. Do { if (contador % 2 == 0) printf("%d\n". -10 .

. 2 raízes reais iguais ou 2 raízes complexas conjugadas. 1! 2 ! 3! (Sugestão: calcule cada termo a partir do termo imediatamente anterior.. 4. Escreva um programa para determinar as raízes da equação quadrática ax2+bx+c=0. os anos 1996 e 2000 são bissextos.14] O factorial de um número n não-negativo é denotado por n! e é definido da seguinte forma: n! = n ⋅ (n-1) ⋅ (n-2) ⋅ . e os respectivos valores (com 3 casas decimais). o operador "/" refere-se ao quociente da divisão inteira...4..1 se o ano for bissexto e 0 se o ano for comum Nesta fórmula. ⋅ 1 n! = 1 (para n =0) (para n ≥1) a) Escreva um programa que leia repetidamente números inteiros não-negativos e calcule e imprima o seu factorial.mês: 1=Março.. Utilize a função sqrt da biblioteca de funções matemáticas para calcular a raiz quadrada de um número em vírgula flutuante..dois últimos dígitos do ano (exemplo: 98) D .3. Exemplo: Introduza os coeficientes: 2.) . em vez do tipo int. 12=Fevereiro C . sendo os coeficientes a. O programa deve indicar se a equação tem 2 raízes reais diferentes.4.5 -1 16 Há 2 raízes complexas conjugadas: 0. Escreva instruções for para calcular a soma dos primeiros n termos (com n inteiro previamente definido) de cada uma das séries seguintes: a) Série que dá o valor da constante matemática π: 4− 4 4 4 4 4 + − + − +. a) Escreva um programa que calcule e imprima o número de dias de um mês/ano indicado pelo utilizador.(1 + L) * (M / 11)] mod 7 em que W ..dia do mês. terminando quando é introduzido um número negativo. enquanto que os anos 1998 e 1900 são comuns.. 3 5 7 9 11 1 1 1 + + +.522i 4. usasse cada um dos seguintes tipos: long.2) / 10 + Y + (Y / 4) + (C / 4) .. short e char? c) Escreva um programa que imprima uma tabela de factoriais dos números de 1 a 15. (Sugestão: utilize um único ciclo for.. 1=segunda.) b) Qual é o maior número cujo factorial é calculado correctamente pelo programa da alínea (a)? Porquê? E se. b e c fornecidos pelo utilizador.dia da semana: 0=domingo. M .200-2.522i e 0.dois primeiros dígitos do ano (exemplo: 19) Y .200+2.6. (Sugestão: utilize a instrução switch. O dia da semana correspondente a uma data pode obter-se através da seguinte fórmula: W = [D + (26 * M .) 4. 1! 2 ! 3! b) Série que dá o valor da constante matemática e: 1+ (Sugestão: calcule cada termo a partir do termo imediatamente anterior. 2=Abril. [Deitel 3.2 * C . e ainda os anos múltiplos de 400. Por exemplo. etc.5.. Os anos bissextos são os anos múltiplos de 4 que não são múltiplos de 100.) 4. (Sugestão: utilize um ciclo for dentro de um ciclo while.47. 11=Janeiro. 10=Dezembro=10. a começar em 1 L .) c) Série que dá o valor de e-x (com x real positivo previamente definido): 1− x x2 x3 + − +.

if (i * i <= n) printf("%d não é primo!\n". Um número é primo se apenas for divisível pela unidade e por si próprio. Escreva um programa que imprima o número Romano equivalente a um número decimal entre 1 e 1000 introduzido pelo utilizador. 4. while (1) { printf("Introduza um inteiro positivo (0 termina): "). i * i <= n. &n). Exemplo: Mês (1 a 12): 2 Ano (com 4 dígitos): 1999 Dom Seg Ter Qua 1 2 3 7 8 9 10 14 15 16 17 21 22 23 24 28 Qui 4 11 18 25 Sex 5 12 19 26 Sab 6 13 20 27 4. se o resto da divisão inteira de a por b for zero. continue. i.n).8. scanf("%d". 4. else printf("%d é primo!\n".n). if (n < 0) { printf("Não aceita números negativos!\n").b) Escreva um programa que mostre no ecrã o calendário de um mês/ano indicado pelo utilizador. } . a) Escreva um programa que leia um número e determine se é primo ou não.7. b) Escreva um programa que imprima os 100 primeiros números primos. c) Escreva um programa que imprima todos os números primos inferiores a 10000. if (!n) break. i++) if ( ! (n % i) ) break. } for (i = 2. Restruture o seguinte código por forma a evitar o uso das instruções break e continue: int n. Diz-se que um número a é divisível por um número b.9.

x = y. e imprime o valor de round(x. (float) x). b) c) d) register auto int x = 7. } return number * number. .2.. f) int sum(int n) { if (n == 0) return 0. terminando quando o utilizador introduz x=0.n) com um número suficientemente grande de casas decimais. cube(float number) { return number * } /* protótipo */ /* definição */ number * number. [Deitel 5. printf("%f\n". arredonda x para as centésimas (isto é. Escreva uma função double round(double x. e) double square(double number) { double number. para 2 casas decimais). retornando o valor arredondado.50] Encontre os erros existentes em cada um dos seguintes segmentos de programas e explique como os corrigiria: a) float cube(float). Inclua essa função num programa de teste que pede ao utilizador valores de x e n.45678.11] A função floor pode ser usada para arredondar um número em vírgula flutuante para um certo número de casas decimais. Por exemplo. unsigned n) que arredonda um número em vírgula flutuante ( x) para um certo número de casas decimais ( n). } 5.5. float y = 123. int randomNumber = srand().5) / 100. . else return n + sum(n). int x. [Deitel 5. a instrução: y = floor(x * 100 + 0. Funções 5..1.

as dezenas (nada. centenas.31] Escreva um programa que simule o lançamento de uma moeda. para imprimir em romano.. que só recebe 0 ou 1). II. XX. char letra5. muito mais rápidas). No entanto. Por exemplo. ou IX). dezenas ou unidades). para verificar se n é primo. 5. 'D'. b) Uma implementação directa desta função gasta n-1 multiplicações em vírgula flutuante. . Cada uma destas funções deve receber como argumento um número entre 0 e 9 (excepto a função para imprimir os milhares.. 'M'). c) Existe uma implementação iterativa (simples) que tire partido das propriedades indicadas na alínea anterior? 5.. x1 = x. Escreva uma implementação recursiva da função PotenciaNatural tirando partido destas fórmulas. e imprimir os resultados. O 1º argumento recebido por esta função é o dígito decimal.. cada uma destas funções deve ser implementada através de uma única chamada a uma função mais genérica com o seguinte protótipo: void para_romano(int digito. . se n fôr par (≥2). Refaça o exercício 4. a) Escreva uma função mdc(x. unsigned n) que retorne o valor de xn. o itálico é usado para expressões matemáticas.42] O maior divisor comum (mdc) de dois inteiros x e y é o maior inteiro que divide tanto x como y (com resto 0).5. contar o número de vezes que sai cada uma das faces. Os argumentos seguintes indicam os caracteres a usar. x40 pode ser calculado com apenas 6 multiplicações em vírgula flutuante (e mais algumas operações aritméticas com inteiros..7. Refaça o exercício 4. e o Courier bold para código C. usando um ciclo for. char letra1. [Deitel 5. Para cada lançamento. C. char letra10). que retorna 1 se n for primo e 0 no caso contrário. escrevendo uma função int primo(int n).y)=mdc(y. ou XC) e as unidades (nada. seguindo a definição acima. 5. as centenas (nada. . se n for ímpar (≥3) x2 = x⋅x. b) É sabido que mdc(x. xn = x⋅[x(n-1)/2]2. O programa deve efectuar 100 lançamentos. sem recorrer à biblioteca de funções matemáticas.5. 1 Conforme o leitor já deve ter reparado. x0 = 1 Por exemplo. dividindo o programa em funções para imprimir os milhares (nada ou M). Note que. X.29. 'C'.3.. I. ou CM).8 (programa para imprimir o número Romano equivalente a um número decimal entre 1 e 1000). Por sua vez. utilizável em todas as alíneas. . para imprimir 6 centenas em romano.y) tirando partido das propriedades referidas em b).6..y) capaz de calcular o maior divisor comum de dois inteiros. sem argumentos. de 0 a 9. o número de operações em vírgula flutuante pode ser drasticamente reduzido se atendermos a que: xn = [xn/2]2. 1 c) Desenvolva uma versão não recursiva da função mdc(x. a) Escreva uma implementação iterativa desta função. basta dividir n pelos números de 2 a (int)sqrt(n).. de acordo com o peso do dígito (milhares. que retorna 0 para cara e 1 para coroa. o programa deve imprimir Cara ou Coroa.0)=x. bastaria invocar para_romano(6. O programa principal deve chamar uma função separada cara_ou_coroa.y) directamente a partir destas propriedades..7. [Deitel 5. 5.4. Pretende-se implementar uma função double PotenciaNatural(double x. 5. Escreva uma versão recursiva da função mdc(x.x mod y) e mdc(x.

str)..2. A função deve colocar os coeficientes no vector coefs e deve retornar o grau do polinómio. a)-d)] Encontre os erros existentes em cada um dos seguintes segmentos de programas: a) b) c) d) Suponha que foi definido: char str[3]. a[1].1. até um máximo de 20 apostas. O programa deve produzir um resultado do seguinte tipo (os cabeçalhos de linhas e colunas são dispensáveis): n\k* 12 13 0 1 2 3 4 5 6 7 8 9 10 11 ********************************************************************* ****** 0 * 1 1 * 1 1 2 * 1 2 1 3 * 1 3 3 1 4 * 1 4 6 4 1 5 * 1 5 10 10 5 1 6 * 1 6 15 20 15 6 1 7 * 1 7 21 35 35 21 7 1 8 * 1 8 28 56 70 56 28 8 1 9 * 1 9 36 84 126 126 84 36 9 1 10 * 1 10 45 120 210 252 210 120 45 10 1 11 * 1 11 55 165 330 462 462 330 165 55 11 1 12 * 1 12 66 220 495 792 924 792 495 220 66 12 1 13 * 1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1 (Sugestão: Utilize um vector para guardar os valores da linha corrente.. 9] = 2.001. /* O utilizador introduz ola */ Suponha que foi definido: int a[3]. O programa aceitará polinómios com grau desde 0 até 20. Suponha que foi definido: double d[2][10]. 100. a[3]). Para calcular a linha seguinte (n). d[1.4. "Arrays" 6. basta acrescentar um 1 na coluna n e somar ao elemento da coluna k o elemento da coluna k-1. [Deitel 6.) 6. 1000.0001}. Cada polinómio será representado por um vector com os coeficientes em vírgula flutuante e por um inteiro sem sinal com o grau do polinómio.. 1.13. Escreva um programa para gerar várias apostas do totoloto todas diferentes entre si. e represente o conjunto de apostas por um vector de até 20 apostas.6.01. Escreva um programa para imprimir o triângulo de Pascal de altura 14. os valores de nCk para 0≤k≤n≤13. Pretende-se escrever uma programa para efectuar operações com polinómios. scanf("%s".3. O número de apostas a gerar é dado pelo utilizador. isto é. 6. float f[3] = {1. printf("%d %d %d\n".1. a) Escreva uma função int lePolinomio(float coefs[]) para ler um polinómio. .) 6. (Sugestão: Represente cada aposta por um vector de 6 números crescentes (compreendidos entre 1 e 49). para k=n-1. a[2]. .345. 10.

7 (o que quer dizer que a rainha da linha 0 está na coluna 0.. não há duas rainhas na mesma coluna. estão todas as rainhas na mesma diagonal! O problema inicial pode agora ser formulado da seguinte forma: encontrar uma permutação deste vector de 8 números em que não fiquem duas rainhas . No entanto. Escreva um função maximos_locais que imprima todos os máximos locais e respectivas posições. Esta segunda expressão pode ser calculada "de dentro para fora". Escreva um programa com um pequeno menu que permita integrar e testar todas as funções escritas nas alíneas anteriores. a rainha da linha 1 está na coluna 1. a) Escreva funções para ler e escrever uma matriz. use um vector int S[8].8. Pretende-se escrever um programa para jogar mastermind (sem visual gráfico).. Sendo i o nº da linha e j o nº da coluna. as duas diagonais correspondentes podem ser numeradas i+j e i+7-j. const float c) Escreva uma função float calculaPolinomio(int grau. considerando que qualquer elemento da matriz pode ser um máximo local. float x). a0+a1x+a2x2+a3x3 = a0+(a1+(a2+(a3)x)x)x. No 1º caso é necessário achar a "reunião" dos factores primos e no 2º caso é necessário achar a "intersecção" dos factores primos. Para representar uma solução do problema. d) Diz-se que um elemento de uma matriz é um máximo local se for superior a todos os seus vizinhos. Introduzir polinómio Mostrar polinómio Calcular valor de polinómio num ponto Terminar 6. por exemplo. unsigned factores[32]) para decompor um número inteiro positivo n. . A chave é uma sequência de 5 cores diferentes. c) Escreva uma função para multiplicar duas matrizes e colocar o resultado numa terceira. Escreva uma função void factoresPrimos(unsigned n. (Sugestão: Para minimizar o número de operações em vírgula flutuante. A chave é gerada aleatoriamente pelo computador.b) Escreva uma função void escrevePolinomio(int coeficientes[]). em que S[i] indica a coluna (entre 0 e 7) em que se encontra a rainha que se encontra na linha i (entre 0 e 7). entre 2 e 232-1. 1. Os factores primos são colocados no vector factores[]. b) Escreva uma função para transpor uma matriz. para calcular e retornar o valor de um polinómio num ponto x. O número máximo de tentativas é 10. o computador responde com a respectiva pontuação (número de cores certas no sítio certo e número de cores certas no sítio errado). Desta forma.) d) Escreva um programa para integrar e testar as funções anteriores.5. etc. apresentando um menu do tipo: 1. 6. na mesma coluna ou na mesma diagonal)? Escreva um programa para achar pelo menos uma solução (ou todas as soluções) para este problema.26] O problema das oito rainhas pode ser formulado da seguinte forma: é possível colocar oito rainhas num tabuleiro de xadrez sem se atacarem mutuamente (i. 2. sem que nenhumas duas rainhas estejam na mesma linha.. e o utilizador tenta adivinhar a chave..e.6. [Baseado em Deitel 6. 3. Use depois esta função para achar o mmc (menor múltiplo comum) e o mdc (maior divisor comum) de pares de números dados pelo utilizador. seguidos de um 0 no fim.). e as diagonais numeradas de 0 a 14. A cada tentativa do utilizador. para escrever um polinómio. atenda a que. 6. Sugestão: Considere as linhas e colunas de um tabuleiro de xadrez numeradas de 0 a 7. const float coefs[]. Suponha que este vector é preenchido com os números 0.7. 6. As cores são representadas por números de 1 a 8. Esta representação impede que duas rainhas estejam na mesma linha. por ordem não decrescente. Pretende-se construir um programa que permite efectuar operações sobre matrizes quadradas. grau. O computador deve ainda assinalar as tentativas inconsistentes com as pontuações obtidas nas tentativas anteriores (uma tentativa é inconsistente se as pontuações anteriores se alterarem no caso da chave ser substituída por essa tentativa). em factores primos. 4.

a[0]. 2. Por exemplo. 4}. 11. 4.2f\n". o erro existente em cada um dos seguintes segmentos de programa. 80. void (*f)(int)) { for ( . 7. } void mostra(int n) { printf("%5. *(nomes+1). p = a. Utilize vectores para marcar as diagonais ocupadas. *p2). 1. printf("%d %d\n". x. y. p2 = &y. sizeof(nomes) / sizeof(char *)). printf("%c%s %s %s\n". 3. 2.0). *p. 17. 6. mostra). p1 = &x.2f %. nomes[0]+1. int size. 3}. size>0. int a[4] = {0. for (p = v.na mesma diagonal. p[1]. nomes[2]). 0}. 5. a) int *numero. 2. . *p1. *(a+3)). a)-g)] Indique e corrija. n / 100. Apontadores 7. forall(v. *p2. 1. O que imprime cada um dos seguintes segmentos de programa? a) int x = 1. 13. printf("%d %d %d %d ". **nomes. 5. printf("%d\n". *p = &x. "José". float x = 3. } main() { b) c) d) e) f) int v[4] = {57. *p. *p2 = *p1. 7. x. *numero). printf("%d %d %d %d\n".14. *p1. } 7. char *nomes[] = {"João". size--) (*f)(*v++). 7. "Joaquim"}. uma solução possível é {3. p++) printf("%d\n". return 0. printf("%. *p). *(p+2). ++*p1. 0. sizeof(nomes). *p.2f%%\n".6. 63.1. *p). *p = x.2. 90}. Note que há 8! = 40320 permutações possíveis. int v[] = {1. void forall(int *v. 19. y. se possível. [Deitel 7.

float xPtr = &x. i 8 9 2 5 j 6 1 3 7 2.3.3. Inicializar j = última posição do array 1. com valores ≤x do lado esquerdo e valores ≥x do lado direito. float x = 19. A figura seguinte ilustra o passo 1 do algoritmo. c) d) e) f) g) h) 7. *s != '\0'. intPtr = realPtr. Escolher um elemento arbitrário (x) do array (v) não ordenado. long *intPtr.3. void *genericPtr = numPtr.2. da seguinte forma: 1.3. Passo de partição: 1. for ( . Se i < última posição do array.2. Se i ≤ j. resultado. incrementar i 1. [Wirth] O Quicksort (também designado método de ordenação por partição) é um método de ordenação de arrays muito eficiente que se baseia num algoritmo recursivo do seguinte tipo: 1. s). int *x. short *numPtr.2. char * const p2 = s. 2. 1. ou seja: 2. incrementar i e decrementar j Passo recursivo: Efectuar o passo 1 para cada um dos sub-arrays (esquerdo e direito) não ordenados.b) float *realPtr. char *s. p1[2] = 'e'.1. Enquanto v[j] > x. *s). inclusivé.3. Partir o array em dois sub-arrays. xPtr).2.2. printf("%f\n". const char * p1 = s.34. x = y.1. char s[] = "isto é um array de caracteres". char s[] = "ola". int contador. desde que o seu comprimento seja maior do que 1. p2[2] = 'e'. ordenar sub-array entre a posição i e a última posição. inclusivé. x 4 j < i 3 1 x ≤ 2 4 5 6 9 x ≥ 8 7 . ordenar o sub-array entre a primeira posição e a posição j. printf("%s\n". decrementar j 1.1. por exemplo o do meio.1.2. Enquanto v[i] < x. Enquanto i ≤ j fazer: 1. Inicializar i = primeira posição do array 1. resultado = *genericPtr + 7. Se j > primeira posição do array.3.2. trocar v[i] com v[j].2. s++) printf("%c ". y.2.2.

char *dezenas [] = {"". c) Escreva e teste uma versão alternativa da função quicksort.a) Escreva uma função recursiva quicksort para ordenar um array de inteiros pelo método exposto..25] A seguinte matriz de 0's e 1's representa um labirinto de 8 x 8 (com o trajecto entre a entrada e a saída realçado a bold): → 1 0 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 0 1 1 1 1 0 1 1 0 1 1 0 0 0 1 1 0 0 1 0 1 0 1 1 1 1 1 0 1 0 1 1 1 0 0 0 1 0 1 1 1 0 → 1 1 1 1 1 Os 1's representam as paredes. e) 7. consiste em "seguir sempre pela direita". e deve marcar a entrada com E e a saída com S (caso exista saída). "CEM". recebendo como argumentos os endereços do primeiro e do último elemento do array a ordenar."DEZANOVE"}. e apontadores para receber a linha e coluna de entrada.. A função deve receber como argumento a matriz de caracteres que descreve o labirinto. para escrever no ecrã um número n. int size). entre 0 e 9999.) d) Escreva um programa para integrar e testar as funções anteriores. . "UM" . recebendo como argumentos o endereço do primeiro elemento e o número de elementos do array a ordenar. o elemento da coluna j da linha i tem um offset de m*i+j posições em relação ao elemento da 1ª coluna da 1ª linha. "DUZENTOS".. "NOVENTA"}. a) Escreva uma função atravessaLabirinto para atravessar um labirinto 8 x 8. A função deve receber como argumentos a matriz de caracteres que descreve o labirinto."DOIS" . A função deve substituir 0 por X ao longo do caminho percorrido. [adaptado de Deitel 7. bem como a linha e coluna de entrada (na fronteira do labirinto). dezenas e centenas por extenso: char *unidades [] = {"ZERO". (Sugestão: Atenda a que.. tendo como argumentos a matriz de caracteres a ser preenchida com 0's e 1's. . .. por extenso.5. A função deve ter o seguinte protótipo: void quicksort (int *v. Um método simples para encontrar a saída garantidamente (não necessariamente pelo caminho mais curto). Por exemplo.. . 7. Escreva uma função void numExtenso(unsigned n). . . b) Escreva um pequeno programa para testar a função anterior. "NOVECENTOS"}. "DEZ". char *centenas [] = {"". numExtenso(2432) deve produzir: DOIS MIL QUATROCENTOS E TRINTA E DOIS Sugestão: Utilize arrays de strings para guardar as designações das unidades. numa matriz com m colunas. não necessariamente quadrados. b) Escreva uma função geraLabirinto para gerar aleatoriamente um labirinto 8 x 8 (não necessariamente com saída). c) Escreva uma função imprimeLabirinto para imprimir um labirinto.4. Se o labirinto não tiver nenhuma saída. "VINTE". Generalizar as funções anteriores (acrescentado ou modificando argumentos se necessário) para trabalhar com labirintos de qualquer dimensão. . acaba por se voltar à posição de partida.

2. (Sugestão: Use as funções isalpha e isalnum. Escreva um função int identificadorValido(char *str) que verifica se uma string (str) contém um identificador válido. por forma a escrever o número por extenso numa string. (Sugestão: Use a função strcat. Escreva uma função void normalizaNome(char *nomePtr.6. char *normPtr) para normalizar um nome (apontado por nomePtr) da seguinte forma: as minúsculas são convertidas para maiúsculas. Exemplos: -1.) 8. uma letra seguida de zero ou mais letras ou dígitos.1. (Sugestão: Use a função isdigit.) 8. (Sugestão: Use a função strstr. usando a função do problema anterior. "DAS". int mes. Considere que cada palavra do nome não tem mais de 40 caracteres. Na string.. O programa deve terminar quando aparece uma linha vazia. isto é.4. "JANEIRO". toupper e strcat.) 8. char *s2) para contar o número de ocorrências não sobrepostas da string s1 na string s2. Usando a função do problema anterior. "DA".000$00 67.4. int ano).6. char *str) . é usado o cifrão ( $) para separar os escudos dos tostões e centavos e é usado o ponto ( . O montante pode ser precedido do sinal menos (-). O protótipo da novo função será: void numExtenso(unsigned n. em vez de o escrever no ecrã. Refaça a função numExtenso() do exercício 7.. 8.5. char *str) com o objectivo oposto da função anterior. para escrever no ecrã uma data por extenso. sequências de vários espaços ou tabs entre duas palavras são substituídos por um único espaço.7. strcmp.1998) deve produzir: VINTE E SETE DE MARÇO DE MIL NOVECENTOS E NOVENTA E OITO Escreva um pequeno programa para testar esta função. Escreva uma função void formataMontante(double montante.) 8. escreva uma função void dataExtenso(int dia. espaços ou tabs no início ou no fim são suprimidos. . Escreva uma função int contaOcorrências(char *s1.718$30 14$50 . Sugestão: Utilize um array de strings para guardar as designações dos meses por extenso: char *meses[] = {"". com 256 caracteres no máximo) e imprimir os nomes normalizados correspondentes no "standard ouput". são removidas as palavras "DE". Caracteres e cadeias de caracteres (strings) 8. (Sugestão: Guarde as palavras a eliminar num array de strings e use as funções strtok. "DO". "DEZEMBRO"}. dataExtenso(27.. "FEVEREIRO". 8. Escreva uma função double converteMontante(char *str) para converter uma string com um montante em dinheiro para double. Escreva um programa para ler nomes do "standard input" (um nome em cada linha. Por exemplo. O nome normalizado é colocado no array de caracteres apontado por normPtr.) . "DOS" e "E". (Sugestão: Use as funções gets e puts.) 8.7.5.) para separar grupos de 3 dígitos.3.

(Sugestão: Use as funções getchar e putchar.) 9. Implementa e teste as seguintes funções: /* Lê uma data do "standard input". Escreva um programa que copie caracteres do "standard input" para o "standard output". mes. igual ou menor do que a 2ª data (d2). Suponha que. DOUBLE}. double d_value. até um máximo de 50 linhas de 80 caracteres. Senão. */ void escreve_data(struct data d). Retorna 1. 9. Suponha que se define o seguinte tipo de estrutura para representar datas: struct data { int dia. }. */ .8. no formato dia/mês/ano. lê-o para um long. Retorna a estrutura que descreve a data. com o mês de 1 a 12 e o ano com 4 dígitos. /* Escreve uma data no "standard output". */ int compara_datas(struct data d1. union number_value { long l_value. struct number { enum number_types type. Escreva uma variante da função quicksort do exercício 7. ano. suprimindo as sequências de caracteres começadas em "/*" e terminadas em "*/" (início e fim de comentário em C). */ struct data le_data(void). enumerações e manipulação ao bit 9. 8.1. /* indica qual o campo usado na união */ union number_value value. para implementar uma calculadora capaz de trabalhar com números inteiros ou em vírgula flutuante. lê-o para um double. bem como as sequências de caracteres começadas em "//" e terminadas com o caracter de mudança de linha.8. Se o número for introduzido com o ponto decimal ou com o "E" da notação exponencial. Retorna a estrutura com o tipo e o valor lido.3 (ver Resposta a exercícios seleccionados). para ordenar um array de strings em vez de um array de inteiros. se definem os seguintes tipos de dados e protótipos de funções: enum number_types {LONG. Usando essa variante. }. uniões. e escreva as mesmas linhas ordenadas alfabeticamente no "standard output". /* Lê um número do "standard input".9. 0 ou –1 conforme a 1ª data (d1) é maior. typedef struct number NUMBER. struct data d2).2. no mesmo formato entendido por "le_data". Estruturas. }. escreva um programa que leia várias linhas do "standard input". /* Compara duas datas.

codifica e retorna os dias de comparência ao trabalho de um dado funcionário num dado mês. /* Escreve o número descrito por "num" no "standard output". char *mes. baseadas nessa representação: /* Lê. void add_numbers(const NUMBER *numPtr1. 9. NUMBER num2). 9. Suponha que as notas obtidas pelos alunos a um teste se encontram num ficheiro de texto "notas. Cada um das restantes linhas do ficheiro tem o nome do aluno e a nota respectiva. */ NUMBER add_numbers(NUMBER num1. a) Implementa e teste as funções anteriores. separados por um ou mais espaços ou "tabs".dat". */ void write_number(NUMBER num). Se pelo menos um dos números for do tipo double. usando apontadores para estruturas em vez de estruturas na chamada das funções.3. char *mes. Senão. Refaça o exercício 6. em que o i-ésimo bit a 1 (0) significa que o funcionário compareceu (faltou) ao trabalho no dia i (1≤i≤n. usando a notação apropriada ao tipo. A 1ª linha do ficheiro tem o número de alunos que compareceram ao teste. 10. /* Soma dois números inteiros ou em vírgula flutuante e retorna a estrutura com o tipo e o valor resultante.º de dias do mês). . Escreva também uma instrução para desactivar todos os bits. /* Conta os dias de comparência ao trabalho de um dado funcionário num dado mês (irrelevantes para o caso). void write_number(const NUMBER *numPtr). e operações bit-a-bit para tratar as duas diagonais. desactivar (colocar a 0) e testar (retornando 1 ou 0) o i-ésimo bit de uma variável a do tipo unsigned. o resultado é do tipo double. */ int conta_dias_trab(unsigned dias_trab). NUMBER *sumPtr). em vez de dois vectores. Implemente e teste as seguintes funções. Manipulação de ficheiros 10. o resultado é do tipo long. com i entre 0 e 31.4. usando dois inteiros. Os protótipos passam a ser: void read_number(NUMBER *numPtr). unsigned dias_trab). */ void escreve_dias_trab(char *nome_func. A nota é indicada por um inteiro entre 0 e 20.NUMBER read_number(void). Comece por escrever instruções ou expressões para activar (colocar a 1). /* Imprime os dias de comparência ao trabalho de um dado funcionário num dado mês. const NUMBER *numPtr2. b) Implementa versões alternativas das funções anteriores. */ unsigned le_dias_trab(char *nome_func. int n_dias_mes). A assiduidade de um funcionário num mês pode ser codificada num inteiro de 32 bits sem sinal (unsigned).8 (ver exercícios resolvidos).1.

char unidade_medida [10]. O ficheiro é constituído por registos do seguinte tipo: struct artigo { char nome_artigo [40]. }. o programa deve criar o ficheiro vazio. com o número de ocorrências de cada nota (0.2. /* string */ float quantidade_em_stock.dat". Quando se introduzem dados pelo teclado. Estruturas de dados dinâmicas 11. 4. Cada linha do ficheiro tem a nota e o número de alunos com essa nota. um apontador para uma string (array de caracteres terminado em '\0') alocada dinâmicamente contendo uma linha lida do standard input. O programa deve começar por abrir o ficheiro. 6. /* string */ float preco_unitario. deve apresentar um menu com as seguintes opções: 1. 11. }.A partir dessas notas. 5. Cada artigo é descrito por uma estrutura do seguinte tipo: struct artigo { char nome_artigo [40]. No caso do ficheiro não existir.dat" com dados de artigos em stock. /* string */ float quantidade_em_stock. Por uma questão de generalidade.. 20).. separados por um espaço. (baseado em 10. char unidade_medida [10]. Escreva um programa que lê um conjunto de linhas do standard input e as escreve de volta no standard output por ordem inversa. Sugestão: Use as funções gets(s) e puts(s). As linhas de entrada devem ser guardadas em memória numa lista ligada usada como pilha ("last in first out").2. Escreva um programa que construa o ficheiro "histograma.dat" a partir do ficheiro "notas. A função gets retorna NULL quando encontra o fim dos dados de entrada (EOF). Suponha que as linhas de entrada não têm mais de 1000 caracteres.. Escreva um programa para efectuar a manutenção de um ficheiro binário "artigos. Listar o conteúdo do ficheiro Inserir um novo artigo no fim do ficheiro Procurar um artigo pelo nome Procurar um artigo pela posição no ficheiro Modificar os dados do último artigo procurado Terminar Antes de terminar.2) Escreva um programa para efectuar a manutenção de uma lista de artigos. . 3. 1. 11. o programa deve perguntar ao utilizador os nomes dos ficheiros no início da sua execução. /* string */ float preco_unitario. 2. 10. pretende-se construir um ficheiro de texto "histograma. Cada nó da lista deve conter dois campos: um apontador para o nó seguinte.dat". o fim dos dados é geralmente sinalizado com Ctrl-D em UNIX e com Ctrl-Z em DOS/WINDOWS.1. Seguidamente. 2. . o programa deve fechar o ficheiro.

O programa deve apresentar um menu com as seguintes opções: 7. A lista deve estar ordenada por nome de artigo. .A lista de artigos deve ser representada em memória por uma lista ligada. pede confirmação e só depois o elimina da lista) 10. mostra os dados actuais. o programa deve libertar a memória ocupada pela lista. Cada nó da lista deve ter uma estrutura do tipo indicado acima e um apontador para o nó seguinte. Listar (imprime o conteúdo da lista em formato tabular) Inserir um artigo (pergunta os dados do artigo e insere na lista) Eliminar um artigo pelo nome (pergunta o nome do artigo. 8. Procurar um artigo pelo nome (pergunta o nome do artigo e mostra os respectivos dados) 12. No ínico do programa a lista está vazia. mostra os dados actuais e pede os novos dados) 11. Terminar Antes de terminar. 9. Modificar um artigo (mantendo o nome) (pergunta o nome do artigo. Não podem existir dois artigos com o mesmo nome.

Sign up to vote on this title
UsefulNot useful