Você está na página 1de 161

Algoritmos

Prof. Wander Antunes Gaspar Valente


Verso 2011f

31 de julho de 2011

Sumrio
Sumrio Prefcio 1 Introduo aos Algoritmos 1.1 Introduo Organizao de Computadores . . . . . . . . . . . . . . 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2 1.3 Modelo de von Neumann . . . . . . . . . . . . . . . . . . . . . Bases de Numerao . . . . . . . . . . . . . . . . . . . . . . . Bit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Byte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Codicao ASCII . . . . . . . . . . . . . . . . . . . . . . . . Grandezas Derivadas do Byte . . . . . . . . . . . . . . . . . . Palavra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i 1 3 3 3 4 4 5 6 6 6 6 8

Memria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programao de Computadores . . . . . . . . . . . . . . . . . . . . . 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5

Linguagem de Mquina . . . . . . . . . . . . . . . . . . . . . 10 Linguagem de Montagem . . . . . . . . . . . . . . . . . . . . 10 Linguagem de Alto Nvel . . . . . . . . . . . . . . . . . . . . . 11 Compilao . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 Ligao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 Pseudocdigo . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 i

1.4

Algoritmos 1.4.1

ii 1.4.2

SUMRIO Fluxograma . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 19

2 Introduo Programao em C 2.1 2.1.1 2.1.2 2.2 2.3 2.4

Linguagem de Programao C . . . . . . . . . . . . . . . . . . . . . . 19 Ambiente de Desenvolvimento Integrado para C . . . . . . . . 20 Exemplo Preliminar . . . . . . . . . . . . . . . . . . . . . . . 20

Sada de Dados na Sada Padro . . . . . . . . . . . . . . . . . . . . 22 Comentrios em C . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 Tipos de Dados Primitivos . . . . . . . . . . . . . . . . . . . . . . . . 25 2.4.1 2.4.2 2.4.3 Tipos Inteiros . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Tipos de Ponto Flutuante . . . . . . . . . . . . . . . . . . . . 26 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

2.5 2.6 2.7 2.8

Especicadores de Formato . . . . . . . . . . . . . . . . . . . . . . . 27 Variveis de Memria . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 2.6.1 Declarao de Variveis na Memria . . . . . . . . . . . . . . 28 Comando de Atribuio . . . . . . . . . . . . . . . . . . . . . . . . . 29 Operadores Aritmticos . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 Operador Menos Unrio . . . . . . . . . . . . . . . . . . . . . 32 Operador Mdulo . . . . . . . . . . . . . . . . . . . . . . . . . 32 Diviso Inteira . . . . . . . . . . . . . . . . . . . . . . . . . . 34 Precedncia de Operadores Aritmticos . . . . . . . . . . . . . 35 Expresses Aritmticas no Corpo da Funo printf() . . . . 36 Controle do Nmero de Dgitos Decimais . . . . . . . . . . . . 37 Controle do Comprimento do Campo de Sada . . . . . . . . . 37 Exibio de Zeros No Signicativos . . . . . . . . . . . . . . 38 Alinhamento Esquerda . . . . . . . . . . . . . . . . . . . . . 39 . . . . . . . . . . . . . . . . . 40

2.9

Controle e Formatao de Sada . . . . . . . . . . . . . . . . . . . . . 37 2.9.1 2.9.2 2.9.3 2.9.4

2.10 Denio de Constantes na Memria . . . . . . . . . . . . . . . . . . 39 2.11 Entrada de Dados na Entrada Padro 2.11.1 Especicadores de Formato para scanf() . . . . . . . . . . . 41

SUMRIO

iii

2.12 Constantes e Funes Matemticas . . . . . . . . . . . . . . . . . . . 43 2.12.1 Constantes Matemticas . . . . . . . . . . . . . . . . . . . . . 45 2.12.2 Funes Matemticas . . . . . . . . . . . . . . . . . . . . . . 45 2.12.3 Valor Absoluto . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3 Estruturas de Seleo 3.1 3.2 3.3 3.1.1 3.2.1 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.4 3.5 3.6 3.7 3.8 49

Operadores Relacionais . . . . . . . . . . . . . . . . . . . . . . . . . . 49 Expresses Envolvendo Operadores Relacionais . . . . . . . . 50 Estrutura de Seleo if-else . . . . . . . . . . . . . . . . . . 50 Operador Lgico && . . . . . . . . . . . . . . . . . . . . . . . 57 Operador Lgico || . . . . . . . . . . . . . . . . . . . . . . . . 57 Operador Lgico ! . . . . . . . . . . . . . . . . . . . . . . . . 58 Expresses Relacionais e Operadores Lgicos . . . . . . . . . 58 Problemas de Mltiplas Opes . . . . . . . . . . . . . . . . . 60 Estruturas de Seleo da Linguagem C . . . . . . . . . . . . . . . . . 50 Operadores Lgicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

Operador Condicional Ternrio . . . . . . . . . . . . . . . . . . . . . 62 Precedncia de Operadores . . . . . . . . . . . . . . . . . . . . . . . . 63 3.5.1 Tabela de Precedncia Entre Operadores . . . . . . . . . . . . 64 Comando de Desvio Condicional switch . . . . . . . . . . . . . . . . 64 Funes para Teste de Caracteres . . . . . . . . . . . . . . . . . . . . 68 Operador Aritmtico de Atribuio . . . . . . . . . . . . . . . . . . . 70 71

4 Estruturas de Repetio 4.1 4.1.1 4.2

Operadores de Incremento e Decremento . . . . . . . . . . . . . . . . 71 Formas Pr-xada e Ps-xada para os Operadores de Incremento e Decremento . . . . . . . . . . . . . . . . . . . . . . . 72 Forma Geral da Estrutura for . . . . . . . . . . . . . . . . . 73 Lao Innito . . . . . . . . . . . . . . . . . . . . . . . . . . . 75 Estruturas for Avanadas . . . . . . . . . . . . . . . . . . . . 77

Estrutura de Repetio for . . . . . . . . . . . . . . . . . . . . . . . 73 4.2.1 4.2.2 4.2.3

iv 4.2.4 4.3 4.3.1 4.3.2 4.3.3 4.4 4.5 4.6 4.7 4.4.1

SUMRIO Laos Aninhados . . . . . . . . . . . . . . . . . . . . . . . . . 80 Forma Geral da Estrutura while . . . . . . . . . . . . . . . . 82 Flag ou Sentinela . . . . . . . . . . . . . . . . . . . . . . . . . 83 Estrutura while Sempre Verdadeira . . . . . . . . . . . . . . 84 Forma Geral da Estrutura do-while . . . . . . . . . . . . . . 86

Estrutura de Repetio while . . . . . . . . . . . . . . . . . . . . . . 82

Estrutura de Repetio do-while . . . . . . . . . . . . . . . . . . . . 86 Comando continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88 Consistncia na Entrada de Dados . . . . . . . . . . . . . . . . . . . 89 Nmeros Pseudoaleatrios . . . . . . . . . . . . . . . . . . . . . . . . 91 4.7.1 4.7.2 Semente de Randomizao . . . . . . . . . . . . . . . . . . . . 92 Escopo dos Nmeros Pseudo-Aleatrios Gerados . . . . . . . . 93 97

5 Estruturas Homogneas 5.1 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.2 5.2.1 5.2.2 5.2.3

Estruturas Homogneas Unidimensionais . . . . . . . . . . . . . . . . 97 Declarao de um Array . . . . . . . . . . . . . . . . . . . . . 98 Arrays e Comandos de Repetio . . . . . . . . . . . . . . . . 99 Diretiva #define . . . . . . . . . . . . . . . . . . . . . . . . . 101 Atribuio de Valor na Declarao do Array . . . . . . . . . . 102 Arrays e Nmeros Pseudoaleatrios . . . . . . . . . . . . . . . 104 Percorrimento de Matriz em C . . . . . . . . . . . . . . . . . 107 Inicializao de Matrizes . . . . . . . . . . . . . . . . . . . . . 108 Atribuio de Valor aos Elementos de uma Matriz . . . . . . . 109 113

Estruturas Homogneas Bidimensionais . . . . . . . . . . . . . . . . . 106

6 Cadeias de Caracteres 6.1 6.2 6.3 6.4

Cadeias de Caracteres em C . . . . . . . . . . . . . . . . . . . . . . . 113 Entrada de cadeias de caracteres . . . . . . . . . . . . . . . . . . . . 116 Converso de Cadeias de Caracteres em Tipos Numricos . . . . . . . 121 Funes de C para Cadeias de Caracteres . . . . . . . . . . . . . . . . 124

SUMRIO 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.5

v Cpia de Cadeias de Caracteres . . . . . . . . . . . . . . . . . 124 Tamanho de Cadeias de Caracteres . . . . . . . . . . . . . . . 126 Concatenao de Cadeias de Caracteres . . . . . . . . . . . . 127 Comparao de Cadeias de Caracteres . . . . . . . . . . . . . 129 Pesquisa em uma Cadeia de Caracteres . . . . . . . . . . . . . 130

Vetor de Cadeias de Caracteres . . . . . . . . . . . . . . . . . . . . . 132 137 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137

7 Funes 7.1 7.2 7.3 7.4 7.5 Modularizao

Argumentos de Entrada e Tipos de Retorno . . . . . . . . . . . . . . 140 Funes e Estruturas Homogneas . . . . . . . . . . . . . . . . . . . . 144 Funes e Cadeias de Caracteres . . . . . . . . . . . . . . . . . . . . 147 Tipos Especiais de Variveis . . . . . . . . . . . . . . . . . . . . . . . 148 7.5.1 7.5.2 Variveis Globais . . . . . . . . . . . . . . . . . . . . . . . . . 148 Variveis Estticas . . . . . . . . . . . . . . . . . . . . . . . . 149

7.6 7.7

Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 Bibliotecas de Funes . . . . . . . . . . . . . . . . . . . . . . . . . . 152

vi

SUMRIO

Prefcio
Notas de aula da disciplina Algoritmos ministrada aos alunos do curso de Bacharelado em Sistemas de Informao do Centro de Ensino Superior de Juiz de Fora. Horrio das aulas no segundo semestre letivo de 2011: teras e quintas-feiras das 18h50min s 20h30min. de competncia do professor o lanamento quinzenalmente a frequncia no aluno online. A disciplina possui 4 crditos, o que equivale a 72 horas/aula. O limite mximo de faltas, que corresponde a 25%, representa 18 horas/aula.

SUMRIO

Captulo 1 Introduo aos Algoritmos


No se pode criar experincia. preciso passar por ela. Albert Einstein

1.1 Introduo Organizao de Computadores


1.1.1 Modelo de von Neumann
O modelo lgico de computador proposto por von Neumann pode ser descrito pela Figura 1.1.

Figura 1.1: Modelo de Arquitetura de von Neumann

CAPTULO 1. INTRODUO AOS ALGORITMOS Unidade de controle: a unidade de controle controla o funcionamento da unidade lgica e aritmtica e da memria. Alm disso, ela distribui e organiza tarefas, transfere informaes da entrada para a memria e da memria para a sada. Memria: a memria o dispositivo de armazenamento de informao do computador. Nela so armazenados tanto as instrues de um programa quanto os dados necessrios para a sua execuo. A memria dividida em espaos com endereos. Unidades de entrada e sada: a unidade de entrada traduz informao (por exemplo, letras, nmeros, imagens, marcas magnticas) de uma variedade de dispositivos de entrada em impulsos eltricos que a CPU entenda. A unidade de sada traduz os dados processados, enviados pela CPU em forma de impulsos eltricos, em palavras ou nmeros, que so impressos por impressoras ou mostrados em monitores de vdeo.

1.1.2

Bases de Numerao

Por questes de Engenharia (conabilidade, menor consumo de energia, menor dissipao de calor), os computadores utilizam a base numrica binria (dgitos 0 e 1) em lugar da base numrica decimal (dgitos 0 e 9). Outras bases numricas tambm utilizadas em Cincia da Computao so a octal (dgitos 0 a 7) e hexadecimal (dgitos 0 a 9 e A a F). Isso se deve fcil converso entre a base binria e as bases octal e hexadecimal associado uma representao mais concisa e inteligvel (Figura 1.2). Cada 4 dgitos em um nmero na representao binria corresponde a um nmero na representao hexadecimal. Por exemplo, (101111001101)2 = (BCD)16 e (13A)16 = (000100111010)2 . Analogamente, cada 3 dgitos binrios correspondem a um dgito octal. Por exemplo, (101111001101)2 = (5715)8 . Em decimal, 5 83 + 7 82 + 1 81 + 5 80 = (3021)10 .

1.1.3

Bit

Bit (simplicao para dgito binrio, BInary digiT em ingls) a menor unidade de informao que pode ser codicada e manipulada em um computador digital. Um bit tem um nico valor, 0 ou 1, ou verdadeiro ou falso, ou neste contexto, quaisquer dois valores mutuamente exclusivos.

1.1. INTRODUO ORGANIZAO DE COMPUTADORES

Figura 1.2: Bases de Numerao utilizadas em Computao Fisicamente, o valor de um bit armazenado como uma carga eltrica acima ou abaixo de um nvel padro em um nico capacitor dentro de um dispositivo de memria. Mas, bits podem ser representados sicamente por vrios meios: luz (em bras ticas), ondas eletromagnticas (rede wireless), polarizao magntica (discos rgidos).

1.1.4 Byte
Denomina-se byte (contrao de BinarY term) unidade bsica de tratamento de informao em computadores digitais. Por padronizao de mercado, 1 byte equivale a 8 bits contguos. A primeira codicao de 1 byte = 8 bits deveu-se empresa IBM em 1960 com a criao da tabela ASCII. Como cada bit pode conter 2 valores binrios diferentes, 1 byte (8 bits) pode representar 256 valores numricos distintos na base 2. A Tabela 1.1 apresenta os valores mnimo e mximo que podem ser armazenados em 1 byte. 1 27 + 1 26 + 1 25 + 1 24 + 1 23 + 1 22 + 1 21 + 1 20 = 255 Cada byte pode armazenar um caractere (letra, nmero ou smbolo), de acordo com alguma tabela de codicao.

CAPTULO 1. INTRODUO AOS ALGORITMOS Tabela 1.1: Valores mnimo e mximo em 1 byte 0 0 0 1 1 1 0 0 0 1 1 1 0 0 1 1

1.1.5

Codicao ASCII

ASCII (acrnimo para American Standard Code for Information Interchange, que em portugus signica Cdigo Padro Americano para o Intercmbio de Informao) uma codicao de caracteres de oito bits criado pela IBM. Originalmente ASCII usava apenas 7 bits (capaz de representar 128 caracteres) mas posteriormente estendeu-se para 8 bits para suportar os caracteres acentuados usados em diversos idiomas como o portugus. A Figura 1.3 apresenta a codicao ASCII para os principais caracteres imprimveis dos idiomas ocidentais.

1.1.6

Grandezas Derivadas do Byte

Uma vez que os computadores utilizam aritmtica binria (base 2), os valores numricos so expressos em potncias de dois e no em potncias de dez, embora sejam usados os mesmos nomes para os mltiplos. Assim, 1 quilobyte (KB) equivale a 210 bytes = 1.024 bytes, 1 megabyte (MB) equivale a 220 bytes = 1.048.576 bytes e 1 gigabyte (GB) equivale a 230 bytes = 1.073.741.824 bytes.

1.1.7

Palavra

Uma palavra (word) um valor xo para um determinado processador. Assim, um Pentium possui uma palavra de 32 bits. Isso signica que 1 palavra de 32 bits so processados por vez nesse processador e indica a sua capacidade de processamento.

1.2

Memria

Memria o componente de um computador cuja funo armazenar informaes a serem manipuladas pelo sistema. A Figura 1.4 apresenta uma analogia entre uma memria de computador e um arquivo de chas em uma empresa.

1.2. MEMRIA

Figura 1.3: Caracteres imprimveis da tabela ASCII

CAPTULO 1. INTRODUO AOS ALGORITMOS

Figura 1.4: Analogia entre memria de computador e chrio manual Na realidade, existem diversos tipos de memria em um computador: Memria principal: (memria RAM Random Access Memory Memria de Aceso Randmico). Memria cache: construda com tecnologia RAM, inserida entre a UCP e a memria principal. Registradores: dispositivos de armazenamento existentes no interior dos processadores, com o objetivo de conter os dados, instrues e endereos de memria RAM a serem processados pela UCP. Memria secundria: discos rgidos, mdias ticas, pen drives. A A Figura 1.5 apresenta a relao entre o custo e o desempenho dos tipos de memria existentes. A memria principal endereada por bytes (clulas), comeando pelo endereo 0 (byte 0) at o ltimo byte disponvel. A A Figura 1.6 apresenta um exemplo de alocao de bytes na memria principal de um computador.

1.3

Programao de Computadores

Uma linguagem de programao uma codicao criada para instruir um computador a realizar uma determinada tarefa. Para que um computador execute qualquer tarefa necessrio fornecer um cdigo, escrito em uma linguagem de programao.

1.3. PROGRAMAO DE COMPUTADORES

Figura 1.5: Relao custo versus desempenho dos tipos de memria

Figura 1.6: Alocao de bytes na memria do computador

10

CAPTULO 1. INTRODUO AOS ALGORITMOS

1.3.1

Linguagem de Mquina

O tipo mais primitivo de linguagem de programao chamado de linguagem de mquina, assim chamado porque a nica codicao que o computador entende diretamente. Os primeiros computadores baseados no modelo de Von Neumann utilizavam unicamente a programao em linguagem de mquina. A Figura 1.7 apresenta um trecho de um programa codicado em linguagem de mquina.

Figura 1.7: Trecho de programa em linguagem de mquina

1.3.2

Linguagem de Montagem

Uma linguagem de montagem ou assembly uma notao legvel por humanos para o cdigo de mquina de um computador. A linguagem de montagem foi a primeira evoluo no sentido de tornar a programao de computadores mais fcil e menos tediosa. A Figura 1.8 apresenta um trecho de um programa codicado em linguagem assembly.

Figura 1.8: Trecho de programa em linguagem de montagem

1.3. PROGRAMAO DE COMPUTADORES

11

Por exemplo, enquanto um computador sabe o que a instruo 10110000 01100001 faz, para os programadores mais fcil recordar a representao equivalente em uma instruo mnemnica da linguagem de montagem MOV AL 61. Tal instruo ordena que o valor hexadecimal 61 (97, em decimal) seja movido para o registrador AL do processador.

1.3.3 Linguagem de Alto Nvel


Uma linguagem de alto nvel, ou orientada ao problema, permite que o programador especique a realizao de uma tarefa pelo computador de uma forma muito mais prxima da linguagem humana do que da linguagem de mquina ou de montagem. Uma das principais metas das linguagens de programao de alto nvel permitir que programadores tenham uma maior produtividade, permitindo expressar suas intenes mais fcil e rapidamente. Linguagens de programao de alto nvel tambm tornam os programas menos dependentes de computadores ou ambientes computacionais especcos (propriedade chamada de portabilidade). Isto acontece porque programas escritos em linguagens de programao de alto nvel so traduzidos para o cdigo de mquina especco do computador em que ser executado. Desde o surgimento do Fortran, centenas de linguagens de programao j foram desenvolvidas. A Figura 1.9 apresenta algumas das linguagens mais bem sucedidas ao longo dos ltimos 50 anos.

1.3.4 Compilao
Compilao o processo de anlise de um programa escrito em uma linguagem de alto nvel, chamado programa fonte (ou cdigo fonte) e sua converso (ou traduo) em um programa equivalente em linguagem binria de mquina (programa objeto ou cdigo objeto). O processo de compilao de um programa fonte em programa objeto feito pelo compilador da linguagem. Assim, um compilador C converte um cdigo fonte escrito em linguagem C para a linguagem de mquina do computador subjacente. A Figura 1.10 apresenta o processo de compilao.

1.3.5 Ligao
Existe uma srie de tarefas que o programador no precisa incluir no cdigo fonte. Exemplos dessas tarefas so como apresentar informao na tela, como obter dados do teclado, como ler ou gravar em um disco rgido. O cdigo para essas tarefas em

12

CAPTULO 1. INTRODUO AOS ALGORITMOS

Figura 1.9: Linguagens de alto nvel bem sucedidas no ltimos 50 anos

1.3. PROGRAMAO DE COMPUTADORES

13

Figura 1.10: Processo de compilao

14

CAPTULO 1. INTRODUO AOS ALGORITMOS

geral organizado em arquivos formando uma biblioteca (library) de rotinas fornecida em conjunto com o compilador da linguagem. O que importa ao programador ligar (linkeditar) o cdigo objeto gerado pelo processo de compilao com as rotinas da biblioteca necessrias para a execuo do programa. A Figura 1.11 apresenta o processo de linkedio.

Figura 1.11: Processo de linkedio Todo esse processo seria muito simples se no ocorressem erros. Na prtica, o programador deve lidar com a possibilidade de acontecerem erros ao programar. Por exemplo, o compilador no ir gerar o cdigo objeto se houver algum erro no cdigo fonte (erro de compilao). Outro exemplo, um programa executvel no ser gerado a partir de um cdigo objeto se uma ou mais rotinas disponveis nas bibliotecas da linguagem no forem encontradas (erro de linkedio). Mesmo que todo o processo de compilao e ligao funcione corretamente, gerando um programa executvel, isso no garante que o programador no tenha cometido erros. necessrio vericar se a ao do programa corresponde de fato ao que foi projetado (erro de lgica).

1.4. ALGORITMOS

15

Portanto, o diagrama apresentado na Figura 1.12 ilustra de forma mais realstica a realidade do trabalho do programador.

1.4 Algoritmos
Um algoritmo consiste em uma sequncia de instrues sem ambiguidade que executada at que determinada condio se verique. O conceito de algoritmo frequentemente ilustrado pelo exemplo de uma receita, embora muitos algoritmos sejam mais complexos. Eles podem repetir passos (fazer iteraes) ou necessitar de decises (tais como comparaes ou lgica) at que a tarefa seja completada. Um algoritmo corretamente executado no ir resolver um problema se estiver implementado incorretamente ou se no for apropriado ao problema. Um algoritmo no representa, necessariamente, um programa de computador, e sim os passos necessrios para realizar uma tarefa. Sua implementao pode ser feita por um computador, por outro tipo de mquina ou mesmo por um ser humano. Diferentes algoritmos podem realizar a mesma tarefa usando um conjunto diferenciado de instrues em mais ou menos tempo, espao ou esforo do que outros. Tal diferena pode ser reexo da complexidade computacional aplicada. Por exemplo, um algoritmo para se vestir pode especicar que voc vista primeiro as meias e os sapatos antes de vestir a cala enquanto outro algoritmo especica que voc deve primeiro vestir a cala e depois as meias e os sapatos. Fica claro que o primeiro algoritmo mais difcil de executar que o segundo apesar de ambos levarem ao mesmo resultado. Etimologia: a palavra algoritmo tem origem no sobrenome, Al-Khwarizmi, do matemtico persa do sculo IX, Mohamed ben Musa, cujas obras foram traduzidas no ocidente cristo no sculo XII, tendo uma delas recebido o nome Algorithmi de numero indorum, sobre os algoritmos usando o sistema de numerao decimal.

1.4.1 Pseudocdigo
Pseudocdigo uma forma genrica de escrever um algoritmo, utilizando uma linguagem simples (nativa a quem o escreve, de forma a ser entendida por qualquer pessoa) sem necessidade de conhecer a sintaxe de nenhuma linguagem de programao. Alguns livros introdutrios de programao utilizam algum tipo de pseudocdigo para ilustrar os seus exemplos, de forma que todos os estudantes possam

16

CAPTULO 1. INTRODUO AOS ALGORITMOS

Figura 1.12: Processo de linkedio

1.4. ALGORITMOS

17

entend-los independentemente da linguagem que vierem a utilizem. O Exemplo 1.1 apresenta um pseudocdigo em lngua portuguesa. Exemplo 1.1 Exemplo de pseudocdigo. escreva: Qual a nota do aluno? leia nota se nota maior ou igual a sete ento: escreva Ele passou seno: escreva: Ele foi reprovado fim do se fim do programa Embora no caso da lngua portuguesa existam alguns interpretadores de pseudocdigo, nenhum tem a projeo das linguagens Pascal ou C, que no caso da lngua inglesa se assemelham bastante a um pseudocdigo.

1.4.2 Fluxograma
Fluxograma um tipo de diagrama, e pode ser entendido como uma representao esquemtica de um processo. Em programao, trata-se de uma ferramenta para a elaborao de algoritmos que, em uma etapa posterior, podem usados como base para que o programador escreva um programa fonte. No existe uma padronizao para os smbolos utilizados em uxogramas. A Figura 1.13 apresenta alguns smbolos comumente empregados em uxogramas para representar algoritmos.

18

CAPTULO 1. INTRODUO AOS ALGORITMOS

Figura 1.13: Smbolos usados em uxogramas.

Captulo 2 Introduo Programao em C


Nada complicado se nos prepararmos previamente Confcio

2.1 Linguagem de Programao C


C uma linguagem de programao criada em 1972, por Dennis Ritchie, no AT&T Bell Labs, para desenvolver o sistema operacional UNIX (que foi originalmente escrito em Assembly). Desde ento, tornou-se uma das linguagens de programao mais usadas, e inuenciou muitas outras, especialmente C++, que foi desenvolvida como uma extenso de C. Em 1978, Brian Kernighan e Dennis Ritchie publicaram a primeira edio do livro The C Programming Language. Esse livro, conhecido pelos programadores de C, como K&R, serviu durante muitos anos como uma especicao informal da linguagem. No m da dcada de 1970, C comeou a substituir BASIC como a linguagem de programao de microcomputadores mais usada. Durante a dcada de 1980, foi adaptada para uso no PC IBM, e a sua popularidade comeou a aumentar signicativamente. Ao mesmo tempo, Bjarne Stroustrup e sua equipe nos laboratrios Bell, comeou a trabalhar num projeto onde se adicionavam construes de orientao objetos linguagem C. O produto desse trabalho, chamado C++, nos dias de hoje a linguagem de programao mais usada no desenvolvimento do sistema operacional Windows e da maioria das aplicaes de grande porte; C permanece mais popular no mundo UNIX. Em 1983, o instituto norte-americano de padres (ANSI) formou um comit para estabelecer uma especicao do padro da linguagem C. Aps um processo longo e rduo, o padro foi completo em 1989 e raticado como ANSI X3.159-1989 19

20

CAPTULO 2. INTRODUO PROGRAMAO EM C

Programming Language C. Esta verso da linguagem frequentemente referida como ANSI C. Em 1990, o padro ANSI C, aps sofrer umas modicaes menores, foi adotado pela Organizao Internacional de Padres (ISO) como ISO/IEC 9899:1990.

2.1.1

Ambiente de Desenvolvimento Integrado para C

IDE, do ingls Integrated Development Environment ou Ambiente Integrado de Desenvolvimento, um programa de computador que rene caractersticas e ferramentas de apoio ao desenvolvimento de software com o objetivo de agilizar este processo. As caractersticas e ferramentas mais comuns encontradas nos IDEs so: Editor: edita o cdigo fonte do programa escrito nas linguagens suportadas pelo IDE; Compilador: compila o cdigo fonte do programa em cdigo objeto; Linkeditor: liga o cdigo objeto s bibliotecas necessrias e gera um cdigo executvel; Depurador: (debugger) auxilia no processo de encontrar e corrigir erros (bugs) no cdigo fonte do programa, na tentativa de aprimorar a qualidade de software; Os principais IDES disponveis atualmente como software livre e compatveis com o desenvolvimento em linguagem C na plataforma Windows so: Netbeans, Eclipse, Dev-C++ e Code::Block. Na disciplina Algoritmos do Bacharelado em Sistemas de Informao do CES/JF ser utilizado o IDE Dev-C++ disponvel em http://www.bloodshed.net/devcpp.html.

2.1.2

Exemplo Preliminar

Escreva seu primeiro programa fonte em linguagem C. Depois salve-o com o nome Exemplo1.c, compile e execute-o no IDE Dev-C. Para escrever um novo cdigo fonte, a partir do menu principal, selecione Arquivo Novo Arquivo Fonte. Digite as linhas de cdigo a seguir. #include <stdio.h> int main(void) { printf("Alo, mundo!"); system("pause"); return 0; }

2.1. LINGUAGEM DE PROGRAMAO C

21

Para compilar, linkeditar e executar o programa, selecione Executar Compilar & Executar no menu principal do DEV-C ou utilize a hot-key F9. Se no houver erros de compilao ou ligao, a execuo dever apresentar em uma janela do DOS a mensagem: Alo, mundo! seguido de Pressione qualquer tecla para continuar... Entendendo o Exemplo Preliminar preciso entender todos os componentes desse programa fonte C. O termo #include trata-se de uma diretiva ao pr-processador. O arquivo de cabealho <stdio.h> necessrio sempre que o programa C utilizar a instruo printf(). O programa C composto de uma ou mais funes. Uma funo um bloco de cdigo fonte que possui um nome e delimitado por chaves de abertura e fechamento. main() a funo mais importante em C porque a partir dela que tem incio a execuo do programa. No exemplo preliminar, a funo main() possui 3 linhas de cdigo. A linha de cdigo printf("Alo, mundo!"); uma instruo para exibir alguma informao na sada padro do computador (vdeo). Nesse exemplo, a informao a ser apresentada a cadeia de caracteres "Alo, mundo!". Observe que uma cadeia de caracteres deve ser delimitada por aspas duplas. A instruo printf() tambm uma funo, assim como main(), porm, no precisa ser codicada pelo programador. Ela faz parte da biblioteca de recursos da linguagem C. Uma funo pode receber argumentos para serem manipulados em seu cdigo. Os argumentos devem ser inseridos entre parnteses, logo aps o nome da funo. Assim, "Alo, mundo!" fornecido como argumento para a funo printf(). Observe que main seguido por (void) que signica, nesse contexto, sem argumentos, ou seja, nesse exemplo, nenhum argumento deve ser passado funo main(). Todas as trs linhas de cdigo no interior de main() terminam em ponto-evrgula. Isso uma exigncia do compilador C: toda instruo tem que terminar com esse caractere delimitador. A funo system("pause"); usada para fazer uma pausa na execuo do programa. Sem essa linha, o usurio no teria tempo de ver a sada do cdigo na tela. Ateno: voc deve salvar o seu cdigo fonte com o suxo .c do contrrio o Dev-C acusar erro de compilao na funo system(). Finalmente, a instruo return 0; especica que, ao terminar a execuo de main(), retornado um valor inteiro 0 (zero) para o Sistema Operacional subjacente. Esse cdigo representa que o programa terminou a execuo sem erros. Valores

22

CAPTULO 2. INTRODUO PROGRAMAO EM C

diferentes de zero podem ser usados para representar execues terminadas com algum tipo de erro. Os termos return, int e void so exemplos de palavras reservadas da linguagem C. Isso implica que possuem um signicado nico e denido para o compilador. Se voc digitar erradamente alguma delas o compilador acusar erro. No Dev-C observe que tais palavras so apresentadas sempre em negrito.

2.2

Sada de Dados na Sada Padro

A funo printf() a forma mais usual de se exibir informao na sada padro, ou seja, no monitor de vdeo. A funo printf() requer a biblioteca stdio.h que deve ser informada em uma diretiva ao pr-processador #include. Uma cadeia de caracteres permite a incluso de caracteres de controle, identicados pelo delimitador barra invertida (\). O caractere de controle \n signica avanar o cursor para o incio da prxima linha. O Exemplo 2.1 ilustra o emprego do caractere de controle \n para o avano do cursor. Exemplo 2.1 Emprego de funo printf() com caractere de controle para avano do cursor. #include <stdio.h> int main(void) { printf("Alo, mundo!\n"); system("pause"); return 0; } Alo, mundo! Pressione qualquer tecla para continuar... A simples incluso de uma nova chamada funo printf() no implica no avano do cursor para o incio da prxima linha. Essa ao deve ser explicitamente representada pelo uso do caractere de controle \n. O Exemplo 2.2 gera a mesma sada do Exemplo 2.1 porm utilizando duas chamadas funo printf(). Exemplo 2.2 Funo printf() e uso do caractere de controle para avano do cursor.

2.2. SADA DE DADOS NA SADA PADRO #include <stdio.h> int main(void) { printf("Alo, "); printf("mundo!\n"); system("pause"); return 0; } Alo, mundo! Pressione qualquer tecla para continuar...

23

Observe que programas fonte apresentados at o momento utilizam um recurso visual denominado indentao, onde os comandos presentes na funo main() entre as chaves de abertura e fechamento possuem um recuo na linha. O uso correto e consistente da indentao do cdigo fonte consiste em uma boa prtica de programao pois muito importante para facilitar a leitura e o entendimento do algoritmo e deve ser utilizado em todos os programas desenvolvidos. A Tabela 2.1 apresenta os principais caracteres de controle que podem ser utilizados para a formatao de sada com a funo printf(). Tabela 2.1: Caracteres de controle para uso na funo printf() Caractere \n \t \r \b \'' \' \\ Formatao Avano para o incio da prxima linha Avano para a prxima tabulao Retorno para o incio da linha atual Retrocesso Insero de uma aspas duplas Insero de um apstrofo Insero de uma barra invertida

Exerccio 2.1 Escreva um programa C para exibir na tela a sada: CES/JF SISTEMAS DE INFORMACAO DISCIPLINA: ALGORITMOS

24

CAPTULO 2. INTRODUO PROGRAMAO EM C

Exerccio 2.2 Escreva um programa C para exibir na tela a sada: 65 "A" 66 "B" 67 "C" 68 "D"

2.3

Comentrios em C

Uma boa prtica de programao consiste em documentar o cdigo fonte, com o objetivo de facilitar o seu entendimento e posterior manuteno. A documentao pode ser realizada atravs de comentrios, conforme apresentado no Exemplo 2.3. Exemplo 2.3 Comentrios em cdigo fonte C. /* Programa para exibir uma mensagem na tela */ #include <stdio.h> int main(void) { printf("Alo, mundo!\n"); /* sada na tela */ system("pause"); return 0; } Qualquer trecho de cdigo fonte delimitado por /* e */ no considerado pelo compilador. Voc pode inserir comentrios em qualquer parte de um programa C. Comentrios de Linha Como alternativa, C oferece comentrios de linha, delimitados por //. Comentrios de linha podem ser inseridos em qualquer posio de uma linha no cdigo fonte e, nesse caso, o restante da linha ser desconsiderado durante o processo de compilao (Exemplo 2.4). Exemplo 2.4 Comentrios de linha em C. // Programa para exibir uma mensagem na tela #include <stdio.h> int main(void) { printf("Alo, mundo!\n"); // sada na tela system("pause"); return 0; }

2.4. TIPOS DE DADOS PRIMITIVOS

25

2.4 Tipos de Dados Primitivos


Os tipos de dados primitivos com os quais C trabalha so os nmeros inteiros e os nmeros reais (tambm chamados nmeros de ponto utuante no contexto da linguagem). A insero do ponto decimal dene para o compilador C um valor numrico como sendo de ponto utuante e a delimitao por apstrofos dene um valor inteiro como sendo um caractere da tabela ASCII. Caracteres ASCII podem ser armazenados em qualquer tipo de dado inteiro, embora usualmente se usa o tipo char.

2.4.1 Tipos Inteiros


A linguagem C oferece mais de um tipo de dado inteiro conforme apresentado na Tabela 2.2, que inclui a faixa de valores vlida para o compilador do IDE DevC++. Observe que a faixa de valores pode variar entre os diversos compiladores C existentes. Tabela 2.2: Tipos de dados inteiros Tipo char short int int long int Bytes 1 2 4 4 Faixa de Valores -128 a +127 -32.768 a +32.767 -2.147.438.648 a +2.147.438.647 -2.147.438.648 a +2.147.438.647

Observe que caracteres da tabela ASCII so normalmente referenciados atravs do tipo inteiro char. Isso est correto. Lembre-se que cada cdigo ASCII corresponde a um nmero inteiro na tabela. Os tipos short int e long int podem ser abreviados por short e long respectivamente. Modicador unsigned O modicador unsigned altera a faixa de valores de cada um dos tipos primitivos apresentados ao descartar valores negativos. A Tabela 2.3 apresenta os valores mximos e mnimos para os tipos inteiros com o modicador unsigned.

26

CAPTULO 2. INTRODUO PROGRAMAO EM C Tabela 2.3: Tipos de dados inteiros com o modicador unsigned Tipo unsigned unsigned unsigned unsigned Bytes 1 2 4 4 Faixa de Valores 0 a +255 0 a +65.535 0 a +4.294.967.295 0 a +4.294.967.295

char short int int long int

2.4.2

Tipos de Ponto Flutuante

A linguagem C tambm oferece mais de um tipo de dado de ponto utuante para armazenamento de valores numricos reais, conforme apresentado na Tabela 2.4. Observe que a faixa de valores pode variar entre os diversos compiladores C existentes. Tabela 2.4: Tipos de dados de ponto utuante Tipo float double Bytes Faixa de Valores Preciso 38 4 3.4 10 6 dgitos decimais 308 8 1.7 10 15 dgitos decimais

2.4.3

Constantes

Uma constante representa um valor xo, que pode ser de qualquer um dos tipos primitivos apresentados. Observe que uma constante do tipo ponto utuante se diferencia de uma constante do tipo inteiro pela insero do ponto decimal. Constantes do tipo caractere devem ser delimitadas por apstrofos. O Exemplo 2.5 ilustra a aplicao dos tipos primitivos e de constantes em C. Exemplo 2.5 Tipos primitivos e constantes em C. #include <stdio.h> int main(void) { printf("Inteiro..: %d\n",10); printf("Real.....: %f\n",10.);

2.5. ESPECIFICADORES DE FORMATO printf("Caractere: %c\n",'A'); system("pause"); return 0; } Inteiro..: 10 Real.....: 10.000000 Caractere: A

27

2.5 Especicadores de Formato


A funo printf() exige um especicador de formato para tipos primitivo includo como parte do argumento. Os principais especicadores de formato so %d para int, %f para float e %c para char. A constante cadeia de caracteres includa na funo printf(), delimitada por apstrofos, deve conter um especicador de formato para cada constante de um tipo primitivo a ser exibida. Aps a vrgula, informado o valor propriamente dito, compatvel com o especicador de formato denido. Por padro, valores do tipo ponto utuante float e double so apresentados com 6 dgitos decimais. Exerccio 2.3 Escreva um programa C para exibir na tela a sada a seguir usando tipos primitivos: 10 10.000000 A

2.6 Variveis de Memria


Uma varivel consiste em um segmento de memria compreendendo um ou mais bytes contguos. Cada varivel deve possuir um nome, que usado para referenciar o local na memria onde encontram-se armazenadas as informaes guardadas na varivel. No possvel nomear duas variveis distintas com o mesmo nome. Recomendase empregar nomes mneumnicos ao se declarar variveis de memria. Entretanto, a denio de variveis em C deve seguir um conjunto de regras para nomeao. Pode conter letras maisculas e minsculas, dgitos numricos e o caractere de sublinhar.

28

CAPTULO 2. INTRODUO PROGRAMAO EM C Deve comear por letra ou caractere de sublinhar. Pode conter at 31 caracteres. Palavras reservadas da linguagem no podem ser usadas como nomes de variveis.

Alm disso, importante observar que C diferencia caracteres alfabticos maisculos e minsculos. Portanto, possvel, embora no seja recomendvel, denir variveis de memria distintas com nomes var1, VAR1 e Var1.

2.6.1

Declarao de Variveis na Memria

Para que uma varivel de memria possa ser utilizada em um programa C deve inicialmente ser declarada. A declarao requer, nessa ordem, a especicao do tipo de dado e do nome da varivel, conforme as regras para nomeao de variveis. uma boa prtica de programao declarar todas as variveis a serem usadas logo no incio do programa, antes de quaisquer outros comandos. Essa prtica facilita o entendimento do algoritmo e evita erros. A inicializao de uma varivel de memria feita a partir do operador de atribuio representado pelo smbolo de igualdade (=). O Exemplo 2.6 apresenta um programa fonte onde declarada e inicializada uma varivel de memria do tipo inteiro. Exemplo 2.6 Declarao e inicializao de uma varivel de memria do tipo inteiro. #include <stdio.h> int main(void) { int num; num = 10; printf("Conteudo da variavel num: %d\n", num); system("pause"); return 0; } Conteudo da variavel num: 10 A especicao de formato deve ser compatvel com o tipo de dado. Caso ocorra inconsistncia entre o formato e o tipo de dado, o compilador no apresentar erro mas o valor ser exibido na sada padro de forma incorreta, conforme ilustrado no Exemplo 2.7.

2.7. COMANDO DE ATRIBUIO

29

Exemplo 2.7 Compatibilidade entre o tipo de dado e o especicador de formato. #include <stdio.h> int main(void) { int num1 = 10; float num2 = 10; printf("%f %d\n",num1,num2); system("pause"); return 0; } 0.000000 1076101120

2.7 Comando de Atribuio


Como possvel observar a partir dos Exemplos 2.6 e 2.7, o comando de atribuio (=) pode ser usado para alocar um determinado valor a uma varivel de memria, desde que compatvel com o tipo primitivo denido. A varivel que recebe o valor do comando de atribuio deve corresponder ao lado esquerdo do sinal de igualdade e o lado direito pode ser uma varivel, uma constante ou uma expresso aritmtica que contenha variveis, constantes e operadores aritmticos. Ateno: o comando de atribuio no pode ser entendido como igualdade aritmtica. A varivel de memria que recebe a atribuio deve obrigatoriamente estar do lado esquerdo da expresso. O Exemplo 2.8 apresenta um programa C com uso incorreto do comando de atribuio. Nesse caso, o compilador acusar erro de compilao. Exemplo 2.8 Uso incorreto do comando de atribuio em C. #include <stdio.h> int main(void) { int num; 10 = num; // Uso incorreto do comando de atribuio. printf("Conteudo da variavel num: %d\n", num); system("pause"); return 0; }

30

CAPTULO 2. INTRODUO PROGRAMAO EM C

A expresso no lado direito de um comando de atribuio pode conter constantes e variveis, conforme apresentado no Exemplo 2.9 Exemplo 2.9 Exemplos de comandos de atribuio com constantes e variveis. #include <stdio.h> int main(void) { int num1; num1 = 10; int num2; num2 = num1; printf("num1: %d\n", num1); printf("num2: %d\n", num2); system("pause"); return 0; } num1: 10 num2: 10 Exerccio 2.4 Escreva um programa C para denir 3 variveis, uma de cada um dos tipos primitivos apresentados (int, float e char), atribuir valores e exibir os valores atribudos na tela. Exerccio 2.5 Ainda no programa do Exerccio 2.4, inclua linhas de instruo para alterar os valores das variveis denidas e reapresente os valores na tela. Observe que a declarao e a inicializao de uma varivel de memria podem ser denidos em uma nica linha de cdigo, conforme apresentado no Exemplo 2.10. Exemplo 2.10 Declarao e atribuio de valor a varivel em uma nica instruo. #include <stdio.h> int main(void) { int num = 10; printf("Conteudo da variavel num: %d\n", num); system("pause"); return 0; } Conteudo da variavel num: 10

2.8. OPERADORES ARITMTICOS

31

2.8 Operadores Aritmticos


As operaes aritmticas fundamentais empregam os seguintes smbolos em C: + para a adio, - para a subtrao, * para a multiplicao e / para a diviso. Na linguagem C, um operador aritmtico deve ser utilizado em conjunto com dois operandos, que podem ser constantes ou variveis numricas. Por padro, uma operao aritmtica na qual os dois operandos forem do tipo inteiro processada como uma operao inteira e o resultado tambm um valor do tipo inteiro (Exemplo 2.11). Se pelo menos um dos operandos for do tipo ponto utuante, a operao ser processada em ponto utuante e o resultado ser um valor em ponto utuante (Exemplo 2.12). Exemplo 2.11 Operadores aritmticos onde os operandos so valores numricos do tipo inteiro. #include <stdio.h> int main(void) { int num1 = 10; int num2 = 5; printf("Adicao.......: printf("Subtracao....: printf("Multiplicacao: printf("Divisao......: system("pause"); return 0; } Adicao.......: Subtracao....: Multiplicacao: Divisao......: 15 5 25 2

%d\n", %d\n", %d\n", %d\n",

10 + 5); num1 - 5); 5 * num2); num1 / num2);

Exemplo 2.12 Operadores aritmticos onde os operandos so valores numricos de ponto utuante. #include <stdio.h> int main(void) { float num1 = 10; float num2 = 5; printf("Adicao.......: %f\n", 10.0 + 5.);

32

CAPTULO 2. INTRODUO PROGRAMAO EM C printf("Subtracao....: %f\n", num1 - 5.); printf("Multiplicacao: %f\n", 5.0 * num2); printf("Divisao......: %f\n", num1 / num2); system("pause"); return 0;

} Adicao.......: Subtracao....: Multiplicacao: Divisao......: 15.000000 5.000000 25.000000 2.000000

Observe que uma constante numrica com ponto decimal interpretada pelo compilador C como sendo de ponto utuante.

2.8.1

Operador Menos Unrio

Como exceo, o operador para a subtrao pode ser empregado com um nico operando, conforme apresentado no Exemplo 2.13. Exemplo 2.13 Operador Menos Unrio. #include <stdio.h> int main(void) { int num = 10; num = -num; printf("%d\n", num); system("pause"); return 0; } -10

2.8.2

Operador Mdulo

Alm das quatro operaes aritmticas bsicas, C oferece o operador mdulo ou resto da diviso inteira, cujo smbolo %. Observe que a operao de resto da diviso inteira vlida apenas quando usada com variveis ou constantes do tipo primitivo inteiro. Os Exemplos 2.14 e 2.15 ilustram a aplicao do operador mdulo.

2.8. OPERADORES ARITMTICOS Exemplo 2.14 Resto da diviso inteira com constantes do tipo inteiro. #include <stdio.h> int main(void) { printf("Modulo %d\n", 10 % 3); system("pause"); return 0; } Modulo 1

33

Exemplo 2.15 Resto da diviso inteira com varivel e constante do tipo inteiro. #include <stdio.h> int main(void) { int n = 10; printf("Modulo %d\n", n % 3); system("pause"); return 0; } Modulo 1 Observe a partir do Exemplo 2.16 que no h limite para o nmero de constantes ou variveis em um nico printf(). Exemplo 2.16 Funo printf() com mais de um caractere de controle. #include <stdio.h> int main(void) { int num1 = 10; int num2 = 3; int num3 = num1 + num2; printf("%d + %d = %d\n", num1, num2, num3); system("pause"); return 0; } 10 + 3 = 13

34

CAPTULO 2. INTRODUO PROGRAMAO EM C

2.8.3

Diviso Inteira

A operao de diviso processada de acordo com o tipo dos operandos associados. Caso os dois operadores sejam do tipo inteiro, a diviso tambm ser inteira e o resultado, consequentemente ser inteiro (Exemplo 2.17). Exemplo 2.17 Diviso com operandos inteiros. #include <stdio.h> int main(void) { int num1 = 10; int num2 = 3; int num3 = num1 / num2; printf("%d / %d = %d\n", num1, num2, num3); system("pause"); return 0; } 10 / 3 = 3 Em uma operao de diviso com operandos do tipo inteiro, mesmo que o valor calculado seja atribudo a uma varivel de ponto utuante, a operao de diviso permanece inteira (Exemplo 2.18). Exemplo 2.18 Diviso com operandos inteiros e atribuio a varivel de ponto utuante. #include <stdio.h> int main(void) { int num1 = 10; int num2 = 3; float num3 = num1 / num2; printf("%d / %d = %f\n", num1, num2, num3); system("pause"); return 0; } 10 / 3 = 3.000000 Se pelo menos um dos operandos envolvidos em uma operao de diviso for do tipo ponto utuante ento a operao ser real e o resultado ser um nmero de ponto utuante (Exemplo 2.19).

2.8. OPERADORES ARITMTICOS Exemplo 2.19 Diviso com operandos de tipos distintos. #include <stdio.h> int main(void) { int num1 = 10; float num2 = 3; float num3 = num1 / num2; printf("%d / %f = %f\n", num1, num2, num3); system("pause"); return 0; } 10 / 3.000000 = 3.333333

35

2.8.4 Precedncia de Operadores Aritmticos


A precedncia dos operadores aritmticos apresentada na Tabela 2.5. Tabela 2.5: Precedncia de operadores aritmticos Operador ( ) * / % + Descrio Parnteses Menos unrio Multiplicao, diviso e mdulo Adio e subtrao

Como pode ser observado, o uso de parnteses permite a mudana na ordem de precedncia dos operadores. O Exemplo 2.20 ilustra alguns casos de precedncia entre operadores. Exemplo 2.20 Precedncia em operadores. #include <stdio.h> int main(void) { int num; num = 2 + 3 * 5; printf("%d \n", num); num = (2 + 3) * 5;

36

CAPTULO 2. INTRODUO PROGRAMAO EM C printf("%d \n", num); num = -num * 2 + 50; printf("%d \n", num); system("pause"); return 0;

} 17 25 0

2.8.5

Expresses Aritmticas no Corpo da Funo printf()

Embora no seja uma boa prtica de programao, possvel inserir expresses aritmticas no corpo da funo printf(), conforme apresentado no Exemplo 2.21. Exemplo 2.21 Expresso matemtica no corpo da funo printf(). #include <stdio.h> int main(void) { int num1 = 10; int num2 = 3; printf("%d + %d = %d\n", num1, num2, num1 + num2); system("pause"); return 0; } 10 + 3 = 13 Exerccio 2.6 Escreva um programa C para denir e atribuir valor a 2 variveis de memria do tipo int. Exibir na tela o resultado das cinco operaes aritmticas com as variveis denidas. Exerccio 2.7 Escreva um programa C para denir e atribuir valor a 2 variveis de memria do tipo float. Exibir na tela o resultado das quatro operaes aritmticas bsicas com as variveis denidas. Exerccio 2.8 Escreva um programa C para denir e atribuir valor a 2 variveis de memria, uma do tipo int e uma do float. Exibir na tela o resultado das quatro operaes aritmticas bsicas com as variveis denidas.

2.9. CONTROLE E FORMATAO DE SADA

37

2.9 Controle e Formatao de Sada


2.9.1 Controle do Nmero de Dgitos Decimais
Por padro, a sada de valores de ponto utuante na sada padro (vdeo) a partir da funo printf() exibida com 6 dgitos decimais. O modicador de preciso permite controlar o nmero de dgitos decimais, conforme apresentado no Exemplo 2.22. Exemplo 2.22 Controle do nmero de dgitos decimais com o modicador de preciso. #include <stdio.h> int main(void) { float num1 = 10; float num2 = 3; float num3 = num1 / num2; printf("%.1f / %.1f = %.1f\n", num1, num2, num3); system("pause"); return 0; } 10.0 / 3.0 = 3.3

2.9.2 Controle do Comprimento do Campo de Sada


Alm do nmero de dgitos decimais, o especicador de formato usado na funo printf() permite controlar o comprimento total do campo de sada para todos os tipos de dados numricos, conforme apresentado no Exemplo 2.23. Exemplo 2.23 Controle do comprimento do campo de sada na funo printf(). #include <stdio.h> int main(void) { float num1 = 10; int num2 = 3; float num3 = num1 / num2; printf("%5.1f / %4d = %5.1f\n", num1, num2, num3); system("pause");

38 return 0; } 10.0 / 3 =

CAPTULO 2. INTRODUO PROGRAMAO EM C

3.3

Observe que se o especicador de formato denir um comprimento de campo menor que o mnimo necessrio para a correta exibio do valor numrico a ser exibido, o compilador C ir desconsiderar o tamanho do campo especicado (Exemplo 2.24). Exemplo 2.24 Controle de comprimento do campo menor que o necessrio para exibio do valor numrico. #include <stdio.h> int main(void) { float num1 = 100; int num2 = 3; float num3 = num1 / num2; printf("%3.1f / %1d = %2.1f\n", num1, num2, num3); system("pause"); return 0; } 10.0 / 3 = 33.3

2.9.3

Exibio de Zeros No Signicativos

O controle do comprimento de campo permite tambm a exibio dos zeros no signicativos na sada de valores numricos a partir da funo printf(). Esse recurso obtido ao antepor-se um dgito 0 entre o especicador de formato % e o controle do comprimento de campo, conforme apresentado no Exemplo 2.25. Exemplo 2.25 Exibio de zeros no signicativos a partir do controle do comprimento do campo. #include <stdio.h> int main(void) { float num1 = 3.1416; int num2 = 323;

2.10. DEFINIO DE CONSTANTES NA MEMRIA printf("%08.4f\n", num1); printf("%06d\n",num2); system("pause"); return 0; } 003.1416 000323

39

2.9.4 Alinhamento Esquerda


Por padro, valores numricos so alinhados direita. possvel, entretanto, modicar a exibio dos valores numricos alterando-se o alinhamento para a esquerda, conforme apresentado no Exemplo 2.26. Exemplo 2.26 Alinhamento de valores numricos esquerda. #include <stdio.h> int main(void) { float num1 = 100.0; int num2 = 15; printf("%7.1f\n",num1); printf("%-7.1f\n",num1); printf("%5d\n",num2); printf("%-5d\n",num2); system("pause"); return 0; } 100.0 100.0 15 15

2.10 Denio de Constantes na Memria


Para se denir uma constante na memria e alocar um valor que no pode ser alterado posteriormente durante a execuo do programa, utiliza-se a palavra reservada

40

CAPTULO 2. INTRODUO PROGRAMAO EM C

const (Exemplo 2.27). Observe que se o programador tentar alterar o valor de uma constante previamente denida, o compilador acusar um erro. Exemplo 2.27 Declarao de constantes na memria. #include <stdio.h> int main(void) { int raio = 2; const float pi = 3.1415926; float area; area = pi * raio * raio; printf("Area do circulo de raio %d: %.2f\n",raio, area); system("pause"); return 0; } Area do circulo de raio 2: 12.57

2.11 Entrada de Dados na Entrada Padro


A funo scanf() a forma mais usual de fazer a entrada de dados a partir da entrada padro (teclado). Para seu correto funcionamento necessrio especicar a biblioteca <stdio.h>. A funo scanf() recebe como argumento uma constante cadeia de caracteres com um ou mais especicadores de formato seguido por um ou mais endereos de memria de variveis previamente denidas no cdigo fonte do programa C. O Exemplo 2.28 apresenta um caso de uso simples da funo scanf(). Exemplo 2.28 Funo para entrada de dados scanf(). #include <stdio.h> int main(void) { int num; printf("Digite um numero inteiro: "); scanf("%d", &num); printf("Voce digitou o numero %d.\n", num); system("pause"); return 0; }

2.11. ENTRADA DE DADOS NA ENTRADA PADRO

41

Digite um numero inteiro: 6 Voce digitou o numero 6. A varivel de memria que recebe o valor digitado pelo usurio deve ser precedida pelo operador endereo de memria, representado pelo smbolo &. A omisso do operador & no causa erro de compilao mas pode determinar a abortagem da execuo do programa.

2.11.1 Especicadores de Formato para scanf()


A funo scanf() exige a especicao do tipo de dado, com os mesmos especicadores de formato usados na funo printf(): %d para tipos inteiros, %f para tipos de ponto utuante e %c para caracteres da tabela ASCII. A funo scanf() permite a entrada de dados para mais de uma varivel de memria. Nesse caso, para cada entrada de dados, deve corresponder um especicador de formato e uma varivel de memria precedida pelo operador de endereo (Exemplo 2.29). Exemplo 2.29 Entrada de mltiplos valores com scanf(). #include <stdio.h> int main(void) { int num1; int num2; printf("Digite dois numeros inteiros: "); scanf("%d%d", &num1, &num2); printf("Voce digitou os numeros %d e %d.\n", num1, num2); system("pause"); return 0; } Digite dois numeros inteiros: 4 7 Voce digitou os numeros 4 e 7. A funo scanf() tambm permite o uso do especicador de tamanho para delimitar o nmero de caracteres a serem alocados para uma varivel. O Exemplo 2.30 apresenta um caso de uso desse recurso.

42

CAPTULO 2. INTRODUO PROGRAMAO EM C

Exemplo 2.30 Controle do nmero de caracteres aceitos para uma varivel a partir do especicador de tamanho na funo scanf(). #include <stdio.h> int main(void) { int dia; int mes; int ano; printf("Digite a data atual no formato DDMMAAAA: "); scanf("%2d%2d%4d", &dia, &mes, &ano); printf("Data: %02d/%02d/%d\n", dia, mes, ano); system("pause"); return 0; } Digite a data atual no formato DDMMAAAA: 09082010 Data: 09/08/2010 Tambm possvel inserir outros caracteres no especicador de formato de uma chamada funo scanf(). Nesse caso, o respectivo caractere deve ser informado na entrada de dados do usurio na posio solicitada. O Exemplo 2.31 ilustra o recurso. Exemplo 2.31 Outros caracteres na entrada de dados atravs da funo scanf(). #include <stdio.h> int main(void) { int hora; int min; printf("Digite a hora atual no formato HH:MM "); scanf("%2d:%2d", &hora, &min); printf("%2d horas e %2d minutos.\n", hora, min); system("pause"); return 0; } Digite a hora atual no formato HH:MM 14:47 14 horas e 47 minutos. Exerccio 2.9 Escreva um programa C que solicite ao usurio a entrada de 3 nmeros inteiros quaisquer. O programa deve calcular e apresentar na tela a soma dos nmeros informados pelo usurio.

2.12. CONSTANTES E FUNES MATEMTICAS

43

Exerccio 2.10 Escreva um programa C que solicite ao usurio a entrada de 3 nmeros reais quaisquer. O programa deve calcular e apresentar na tela a mdia aritmtica dos nmeros. Exerccio 2.11 Escreva um programa C que solicite ao usurio o salrio de um funcionrio e que calcule e mostre na tela o novo salrio, sabendo-se que houve um reajuste de 12.5%. Exerccio 2.12 Escreva um programa C que calcule e apresente na tela a rea de um tringulo retngulo. Os valores da base e altura devem ser fornecidos pelo usurio em tempo de execuo. Exerccio 2.13 Escreva um programa C que solicite ao usurio a digitao do seu ano de nascimento. O programa deve calcular e apresentar na tela: (a) a idade do usurio e (b) em qual ano ter 65 anos. Exerccio 2.14 Escreva um programa C que calcule e apresente na tela a mdia ponderada de duas notas fornecidas pelo usurio em tempo de execuo. Considere peso 2 para a primeira prova e 3 para a segunda prova. Exerccio 2.15 Escreva um programa C que solicite ao usurio o valor da hora atual no formato HHMMSS. O programa deve calcular e mostrar na tela o total de segundos transcorridos desde o incio do dia. Exerccio 2.16 Escreva um programa C que solicite ao usurio a digitao de um nmero real. O programa deve exibir na tela o valor inteiro mais prximo do nmero real informado. Por exemplo, se o nmero digitado for 3.8, o valor inteiro mais prximo 4. Exerccio 2.17 Escrever um programa C que solicite ao usurio a digitao de um nmero inteiro no intervalo [100, 999]. Calcular a soma dos algarismos do nmero digitado. Por exemplo, se o nmero for 234, a soma deve ser 9.

2.12 Constantes e Funes Matemticas


O arquivo de cabealho math.h inclui as declaraes necessrias para diversas funes matemticas disponveis nos compiladores C, incluindo-se funes para calcular potncia e raiz quadrada, funes trigonomtricas para clculos que envolvem seno,

44

CAPTULO 2. INTRODUO PROGRAMAO EM C

cosseno e tangente, alm de constantes para nmeros irracionais como, por exemplo, e 2. Uma chamada a uma funo matemtica pode ser ser associada a um comando de atribuio ou utilizada diretamente em um printf() para exibio na sada padro do sistema. O Exemplo 2.32 apresenta a chamada a uma funo matemtica em um comando de atribuio. Exemplo 2.32 Clculo do valor absoluto de um nmero inteiro fornecido pelo usurio. #include <stdio.h> #include <math.h> int main(void) { int num; int valorabs; printf("Digite um numero inteiro qualquer: "); scanf("%d", &num); valorabs = abs(num); printf("Valor absoluto de %d: %d.\n", num, valorabs); system("pause"); return 0; } Digite um numero inteiro qualquer: -5 Valor absoluto de -5: 5. O Exemplo 2.33 apresenta a chamada a uma funo matemtica em um printf(). Exemplo 2.33 Clculo do valor absoluto de um nmero inteiro fornecido pelo usurio. #include <stdio.h> #include <math.h> int main(void) { int num; printf("Digite um numero inteiro qualquer: "); scanf("%d", &num); printf("Valor absoluto de %d: %d.\n", num, abs(num)); system("pause"); return 0;

2.12. CONSTANTES E FUNES MATEMTICAS } Digite um numero inteiro qualquer: -8 Valor absoluto de -8: 8.

45

2.12.1 Constantes Matemticas


A Tabela 2.6 apresenta diversas constantes matemticas denidas na biblioteca math.h. Todas as constantes so denidas como nmeros de ponto utuante do tipo double. Tabela 2.6: Constantes matemticas denidas em math.h Smbolo e log2 e log10 e /2 /4 2 Descrio Nmero de Euler Logaritmo de e na base 2 Logaritmo de e na base 10 Pi Meio Pi Quarto de Pi Raiz quadrada de 2 Constante M_E M_LOG2E M_LOG10E M_PI M_PI_2 M_PI_4 M_SQRT2 Valor 2.7182818284590452354 1.4426950408889634074 0.43429448190325182765 3.14159265358979323846 1.57079632679489661923 0.78539816339744830962 1.41421356237309504880

2.12.2 Funes Matemticas


As funes matemticas da biblioteca math.h retornam valores numricos do tipo double.

Funes Trigonomtricas As funes trigonomtricas recebem como argumento o ngulo em radiano. sin(double) retorna o valor do seno. cos(double) retorna o valor do cosseno. tan(double) retorna o valor da tangente.

46

CAPTULO 2. INTRODUO PROGRAMAO EM C

Funes Logaritmicas log2(double) retorna o valor do logaritmo na base 2. log10(double) retorna o valor do logaritmo na base 10. log(double) retorna o valor do logaritmo neperiano (ou natural), na base e. Potncias pow(double, double) retorna o valor da base elevada ao expoente. Recebe dois argumentos do tipo double, o primeiro a base e o segundo o expoente. sqrt(double) retorna o valor da raiz quadrada. Arredondamento ceil(double) retorna o primeiro double sem casas decimais acima do valor fornecido como argumento. Exemplo: ceil(45.98561) retorna 46. floor(double) retorna o primeiro double sem casas decimais abaixo do valor fornecido como argumento. Exemplo: floor(45.98561) retorna 45.

2.12.3

Valor Absoluto

abs(int) retorna o valor absoluto de um nmero inteiro fornecido como argumento. O retorno um nmero inteiro. fabs(double) retorna o valor absoluto de um double fornecido como argumento. O retorno um double. Exemplo 2.34 Emprego de constante e de funo matemtica da biblioteca math.h para o clculo do seno de um ngulo cujo ngulo fornecido pelo usurio em graus. #include <stdio.h> #include <math.h> int main(void) { int angulo; float radiano; printf("Digite o angulo em graus: "); scanf("%d", &angulo); radiano = angulo * M_PI / 180; printf("Seno de %d graus: %f\n", angulo,sin(radiano)); system("pause");

2.12. CONSTANTES E FUNES MATEMTICAS return 0; } Digite o angulo em graus: 30 Seno de 30 graus: 0.50000

47

Exerccio 2.18 Escreva o programa C para o calculo da area de um circulo utilizando a funao matemtica pow(). Exerccio 2.19 Escreva um programa C que solicite ao usuario em tempo de execuo o raio R e que calcule e mostre na tela a rea A e o volume V de uma esfera dados por 4R3 A = 4R2 e V = 3 Exerccio 2.20 Escreva um programa C que que solicite ao usuario em tempo de execuao as coordenadas x e y de dois pontos quaisquer do plano cartesiano e que calcule e mostre na tela a distancia entre os pontos. Exerccio 2.21 Escreva um programa C que que solicite ao usuario em tempo de execuao o valor de um angulo em graus e que calcule e mostre na tela os valores da cosecante e da cotangente. Lembre-se que 180 equivale a radianos. Exerccio 2.22 A funo exponencial usada para calcular a desintegrao do carbono 14 atravs da equao y(t) = y0 e0.00012t , onde y0 a massa inicial da substncia medida em gramas e t o tempo transcorrido, medido em anos. Escreva um programa C que solicite ao usurio a massa inicial de uma amostra de carbono 14 e que apresente na sada padro a massa aps 10, 100 e 1000 anos.

48

CAPTULO 2. INTRODUO PROGRAMAO EM C

Captulo 3 Estruturas de Seleo


Quem pouco pensa, muito erra. Leonardo da Vinci

Todos os programas apresentados ate o momento sao executados exatamente na ordem em que as instruoes sao escritas, do incio ate o m. A maioria dos algoritmos a serem implementados em uma linguagem de programaao nao seguem essa sequencia. A razao para isso e que muitas vezes e necessario tomar uma decisao e, a partir da, continuar a execuao de uma maneira ou de outra.

3.1 Operadores Relacionais


Para tomar uma deciso necessrio um mecanismo para se comparar valores. A linguagem C oferece um conjunto de operadores relacionais com esse objetivo, conforme apresentado na Tabela 3.1. Tabela 3.1: Operadores Relacionais Smbolo < <= > >= == != Descrio Menor que Menor ou igual a Maior que Maior ou igual a Igual a Diferente de

49

50

CAPTULO 3. ESTRUTURAS DE SELEO

3.1.1

Expresses Envolvendo Operadores Relacionais

A partir dos operadores relacionais apresentados na Tabela 3.1 possvel elaborar expresses lgicas ou booleanas. Tais expresses podem resultar em apenas um de dois valores possveis: verdadeiro ou falso. Na linguagem C, um valor logicamente verdadeiro representado pelo nmero 1 e um valor logicamente falso representado pelo nmero 0. O Exemplo 3.1 ilustra a aplicao dos operadores relacionais em expresses lgicas. Exemplo 3.1 Operadores relacionais em expresses lgicas. #include <stdio.h> int main(void) { printf("%d\n",5>4); printf("%d\n",1==2); printf("%d\n",'A'!='a'); system("pause"); return 0; } 1 0 1

3.2

Estruturas de Seleo da Linguagem C

As estruturas de seleo permitem que o programa possa decidir o caminho a seguir durante a execuo. Por exemplo, dependendo do valor de uma varivel, uma estrutura de deciso pode executar um conjunto de comandos ou no. As estruturas de seleo utilizam os operadores relacionais para compor expresses lgicas e decidir qual o caminho que a execuo de um programa deve seguir dependendo do resultado da expresso, ou seja, verdadeiro ou falso.

3.2.1

Estrutura de Seleo if-else

O comando if-else a estrutura de seleo mais utilizada na maioria das linguagens de programao. Basicamente, utilizada quando torna-se necessrio escolher

3.2. ESTRUTURAS DE SELEO DA LINGUAGEM C entre dois caminhos possveis para a execuo do programa. A forma geral do comando if-else dada por if (expresso lgica) bloco de comandos 1; else bloco de comandos 2;

51

Atente para o uso de parnteses para delimitar a expresso lgica a ser avaliada na estrutura de seleo if-else. O comando if-else avalia o valor da expresso lgica e, caso o resultado seja verdadeiro, o bloco de comandos 1 executado. Caso o resultado seja falso, o bloco de comandos 2, associado clusula else, executado. Entende-se por bloco de comandos um conjunto formado por um ou mais comandos da linguagem C. Observe que em uma dada execuo do programa executado apenas o bloco de comandos 1, associado ao resultado verdadeiro para a expresso lgica avaliada, ou o bloco de comandos 2, associado ao resultado falso para a expresso lgica avaliada. O Exemplo3.2 ilustra o emprego da estrutura de seleo if-else usando expresses lgicas para denir o caminho a ser seguido pela execuo do programa. Exemplo 3.2 Programa C que solicita ao usurio a digitao de um nmero inteiro qualquer e verica se igual ou diferente de 10. #include <stdio.h> int main(void) { int num; printf("Digite um numero inteiro: "); scanf("%d",&num); if(num == 10) printf("O numero %d eh igual a 10.\n",num); else printf("O numero %d eh diferente de 10.\n",num); system("pause"); return 0; } Digite um numero inteiro: 11 O numero 11 eh diferente de 10.

52

CAPTULO 3. ESTRUTURAS DE SELEO

Exerccio 3.1 Escreva um programa C que solicite ao usuario a digitaao de um nmero inteiro N em tempo de execuao. O programa deve calcular e apresentar na tela N caso N 0 ou N 2 caso N < 0. Exerccio 3.2 Escreva um programa C que solicite ao usuario a digitaao de dois nmeros inteiros em tempo de execuao. O programa deve vericar se os nmeros digitados so iguais ou diferentes. Exerccio 3.3 Escreva um programa C que solicite ao usuario a digitaao de dois nmeros quaisquer em tempo de execuao. O programa deve apresentar na tela o maior dos dois nmeros informados. Exerccio 3.4 Escreva um programa C que solicite ao usuario a digitaao das quatro notas de um aluno e que calcule e apresente na tela a media aritmetica das notas e uma mensagem de aprovado ou reprovado, considerando para aprovaao a media maior ou igual a 70. Considere as notas como sendo nmeros inteiros no intervalo [0, 100]. Uma vez que para a linguagem C todo nmero diferente de 0 considerado logicamente verdadeiro e o 0 considerado logicamente falso, o Exemplo 3.3 apresenta um comando de seleo if-else que baseia-se nessa caracterstica para denir se um nmero informado pelo usurio nulo ou no. Exemplo 3.3 Programa C que solicita ao usurio a digitao de um nmero inteiro qualquer e verica se igual ou diferente de 0. #include <stdio.h> int main(void) { int num; printf("Digite um numero inteiro: "); scanf("%d",&num); if(num) // num verdadeiro, isto , num diferente de 0? printf("Numero %d -> diferente de 0\n",num); else printf("Numero %d -> igual a 0\n",num); system("pause"); return 0; } Digite um numero inteiro: 3 Numero 3 -> diferente de 0.

3.2. ESTRUTURAS DE SELEO DA LINGUAGEM C

53

Exerccio 3.5 Escreva um programa C que solicite ao usuario a digitaao de um nmero inteiro e positivo qualquer e que verique se o nmero digitado par ou mpar. Exerccio 3.6 Escreva um programa C que solicite ao usuario a digitaao de um numerico inteiro e positivo em tempo de execuao. O programa deve informar na tela se o numero e ou no divisivel por 5. Estrutura de Seleo if Sem Clusula else A clusula else no obrigatria. O Exemplo 3.4 apresenta um programa C que emprega a estrutura de seleo if sem a clusula else. Exemplo 3.4 Programa C que solicita ao usurio a digitao de um nmero inteiro qualquer e que calcula o valor absoluto. #include <stdio.h> int main(void) { int num; printf("Digite um numero inteiro qualquer: "); scanf("%d", &num); if(num < 0) num = -num; printf("Valor absoluto: %d\n",num); system("pause"); return 0; } Digite um numero inteiro: -1 Valor absoluto: 1 Exerccio 3.7 Escreva um programa C que solicite ao usuario a digitaao de um nmero inteiro N em tempo de execuao. O programa deve calcular e exibir o logaritmo neperiano (log N ) caso N 0 ou o prprio nmero N, caso N < 0. Uso de Blocos de Cdigo em Estruturas if-else Retornando forma geral do comando if-else, dada por

54 if (expresso lgica) bloco de comandos 1; else bloco de comandos 2;

CAPTULO 3. ESTRUTURAS DE SELEO

importante observar que quando houver mais de um comando associado ao bloco de comandos 1 ou ao bloco de comandos 2, ento torna-se necessrio delimitar por chaves de abertura e de fechamento o conjunto de comandos. A esse conjunto de instrues C delimitadas por chaves de abertura e fechamento d-se o nome de bloco de cdigo. Como poder ser visto ao longo do curso, em muitas situaes um bloco de cdigo exigido por diversos comandos da linguagem C quando h mais de uma instruo a ser executada. Embora no seja necessrio, permitido delimitar-se por chaves de abertura de fechamento um bloco de cdigo que contenha apenas um nico comando. O Exemplo 3.5 ilustra a aplicao de blocos de cdigo em um comando if-else. Observe que o bloco de cdigo associado clusula else possui apenas um nico comando. Nesse caso, a delimitao do bloco por chaves opcional. Ateno: o uso incorreto de chaves de abertura e de fechamento fonte de erros ao compilar um programa C. Procure sempre vericar se para cada chave de abertura corresponde uma chave de fechamento. Exemplo 3.5 Programa C que solicita ao usurio a digitao de um nmero inteiro e positivo e que calcula e exibe a raiz quadrada e a raiz cbica. Uma mensagem de erro apresentada caso o nmero digitado no seja positivo. #include <stdio.h> #include <math.h> int main(void) { int num; printf("Digite um numero inteiro e positivo: "); scanf("%d", &num); if(num > 0) { printf("Raiz quadrada: %f\n",sqrt(num)); printf("Raiz cubica..: %f\n",pow(num,0.333)); } else { printf("Erro. Numero nao positivo.\n"); } system("pause"); return 0;

3.2. ESTRUTURAS DE SELEO DA LINGUAGEM C } Digite um numero inteiro e positivo: 9 Raiz quadrada: 3 Raiz cubica..: 2.078561

55

Exerccio 3.8 Segundo uma tabela medica, o peso ideal esta relacionado com a altura e o sexo. Fazer um programa C que receba, em tempo de execuao, a altura H e o sexo de uma pessoa e que calcule e imprima o seu peso ideal, utilizando as seguintes formulas: (a) para homens: 72.7 H58 e (b) para mulheres 62.1 H44.7. Estruturas if-else Aninhadas Para escrever muitos algoritmos torna-se necessrio empregar estruturas de seleo aninhadas, ou seja, uma dentro da outra. Uma vez que cada estrutura if-else permite apenas selecionar entre dois valores lgicos (verdadeiro ou falso), a soluo para algoritmos que envolvam mais de duas condies possveis recai no emprego de estruturas aninhadas conforme mostrado no Exemplo 3.6. Exemplo 3.6 Programa C que solicita ao usurio a digitao da idade I de uma pessoa e que verica se menor de idade (I < 18), maior de idade ou idoso (I 65). #include <stdio.h> #include <math.h> int main(void) { int idade; printf("Digite a idade: "); scanf("%d", &idade); if(idade < 18) printf("Menor de idade.\n"); else if(idade < 65) printf("Maior de idade.\n"); else printf("Idoso.\n"); system("pause"); return 0; } Digite a idade: 30 Maior de Idade.

56

CAPTULO 3. ESTRUTURAS DE SELEO

Exerccio 3.9 Escreva um programa C que receba dois numeros e execute as operaoes listadas a seguir, de acordo com a escolha do usuario. Se a opao digitada for invalida, mostrar uma mensagem de erro. Observe que no possvel calcular a diviso quando o divisor for nulo. 1. 2. 3. 4. media entre os numeros digitados; diferena do maior pelo menor; produto dos numeros digitados; divisao do maior pelo menor.

Exerccio 3.10 Escreva um programa C que solicite ao usuario a digitao de duas notas de um aluno (no intervalo [0, 100]) e que calcule e apresente na tela a media aritmetica das notas e a mensagem segundo a regra: media menor que 40 Reprovado media entre 40 e 70 Exame nal media maior que 70 Aprovado

3.3

Operadores Lgicos

Muitas vezes as expresses relacionais a serem avaliadas necessitam combinar mais de uma condio utilizando-se os operadores relacionais apresentados anteriormente na Tabela 3.1. Por exemplo, pode ser necessrio executar uma ao se um determinado nmero est um intervalo especco [a, b], ou seja, deve ser no menor que a e no maior que b. Em outra situao, uma ao deve ser executada somente se um caractere igual a 'A' ou igual a 'a'. Para compor expresses relacionais que sejam capazes de lidar adequadamente com essas situaes podem ser utilizados os operadores lgicos, apresentados na Tabela 3.2. Tabela 3.2: Operadores Lgicos Smbolo && || ! Descrio E lgico OU lgico NO lgico

3.3. OPERADORES LGICOS

57

3.3.1 Operador Lgico &&


Uma expresso relacional composta que empregue um operador E lgico (&&) ser considerada verdadeira se, e somente se, todos os componentes forem logicamente verdadeiros. Se apenas um dos componentes for logicamente falsa ento a expresso relacional ser avaliada como falsa. O Exemplo 3.7 ilustra a aplicao do operador lgico &&. Exemplo 3.7 Programa C para exemplicar o emprego do operador lgico E. #include <stdio.h> int main(void) { int num1 = 2; float num2 = 3.5; char ch = 'R'; if(num1 <= 2 && num2 > 3.4 && ch == 'T') printf("Dados validos.\n"); else printf("Dados invalidos.\n"); system("pause"); return 0; } Dados invalidos.

3.3.2 Operador Lgico ||


Uma expresso relacional composta que empregue um operador OU lgico (||) ser considerada verdadeira se, e somente se, pelo menos um dos componentes for logicamente verdadeiro. Somente se todos os componentes forem logicamente falsos que a expresso relacional ser avaliada como falsa. O Exemplo 3.8 ilustra a aplicao do operador lgico ||. Exemplo 3.8 Programa C para exemplicar o emprego do operador lgico OU. #include <stdio.h> int main(void) { int num1 = 2; float num2 = 3.5; char ch = 'R';

58

CAPTULO 3. ESTRUTURAS DE SELEO if(num1 <= 2 || num2 > 3.4 || ch == 'T') printf("Dados validos.\n"); else printf("Dados invalidos.\n"); system("pause"); return 0;

} Dados validos.

3.3.3

Operador Lgico !

O operador lgico NO, representado pelo smbolo !, um operador unrio. Se objetivo reverter o valor lgico de uma expresso relacional. Assim, se uma dada expresso for logicamente verdadeira, o operador ! torna a expresso logicamente falsa e vice-versa. O Exemplo 3.9 ilustra o uso do operador lgico !. Exemplo 3.9 Programa C para exemplicar o emprego do operador lgico NO. #include <stdio.h> int main(void) { int num; printf("Digite um numero inteiro: "); scanf("%d", &num); if(!num) printf("Nulo.\n"); else printf("Nao nulo.\n"); system("pause"); return 0; } Digite um numero inteiro: 3 O numero 3 eh diferente de 0.

3.3.4

Expresses Relacionais e Operadores Lgicos

O emprego de operadores lgicos permite a composio de expresses relacionais complexos, que podem empregar diversos operadores relacionais, conforme ilustrado no Exemplo 3.10.

3.3. OPERADORES LGICOS

59

Exemplo 3.10 Escrever um programa C que solicite ao usurio a digitao dos lados de um tringulo e que exiba na tela a classicao do tringulo quanto ao tamanho dos lados (equiltero, issceles ou escaleno). Um tringulo equiltero se possui os trs lados iguais, issceles se possui 2 lados iguais e escaleno se possui os 3 lados de tamanhos diferentes.

#include <stdio.h> int main(void) { int a; int b; int c; printf("Digite os lados de um triangulo: "); scanf("%d%d%d", &a, &b, &c); if(a == b && a == c) printf("Triangulo equilatero.\n"); else if(a == b || a == c || b == c) printf("Triangulo isosceles.\n"); else printf("Triangulo escaleno.\n"); system("pause"); return 0; } Digite os lados de um triangulo: 2 5 3 Triangulo escaleno.

Ateno: Considerando-se o Exemplo 3.10 importante observar que a linguagem C no permite a composio de expresses relacionais do tipo: if(a == b && c) ou if(a == b || == c || b == c). Em outros termos, uma expresso relacional deve ser formada por dois operandos e um operador relacional e a composio de duas ou mais expresses relacionais deve ser formada com operadores lgicos.

Exerccio 3.11 Escreva um programa C que solicite ao usuario o codigo de origem de um produto e que mostre o a procedencia, de acordo com a Tabela 3.3.

60

CAPTULO 3. ESTRUTURAS DE SELEO Cod. Origem 1 2 3 4 5 ou 6 7 ou 8 ou 9 10 a 20 21 a 30 Procedencia Sul Norte Leste Oeste Nordeste Sudeste Centro-Oeste Noroeste

Tabela 3.3: Procedncia de Produtos Categoria Infantil Juvenil Adolescente Adulto Senior Idade 5a7 8 a 10 11 a 15 16 a 30 Acima de 30

Tabela 3.4: Categorias de Nadadores

3.3.5

Problemas de Mltiplas Opes

Nos casos de problemas de mltipla opes, onde necessrio o emprego de duas ou mais estruturas if else, a sintaxe pode ser ligeiramente alterada conforme apresentado no Exemplo 3.11. Este estilo de codicao else if mais recomendado nessas situaes porque facilita a legibilidade. Exemplo 3.11 Escrever um programa C que solicite ao usurio a digitao dos lados de um tringulo e que exiba na tela a classicao do tringulo quanto ao tamanho dos lados (equiltero, issceles ou escaleno). Um tringulo equiltero se possui os trs lados iguais, issceles se possui 2 lados iguais e escaleno se possui os 3 lados de tamanhos diferentes. #include <stdio.h> int main(void) { int a; int b; int c; printf("Digite os lados de um triangulo: "); scanf("%d%d%d", &a, &b, &c);

3.3. OPERADORES LGICOS if(a == b && a == c) printf("Triangulo equilatero.\n"); else if(a == b || a == c || b == c) printf("Triangulo isosceles.\n"); else printf("Triangulo escaleno.\n"); system("pause"); return 0; } Digite os lados de um triangulo: 2 5 3 Triangulo escaleno.

61

Exerccio 3.12 Escreva um programa C que solicite ao usuario a idade de um nadador e mostre na tela a sua categoria, usando as regras apresentadas na Tabela 3.4. Exerccio 3.13 Trs valores numricos podem ser os lados de um tringulo se cada valor for menor que a soma dos outros valores. Escreva um programa C que solicite ao usurio a digitao de trs valores inteiros e verique se podem formar um tringulo. Exerccio 3.14 Escrever um programa C que solicite ao usurio a digitao dos coecientes de uma equao do segundo grau (ax2 + bx + c = 0) e que calcule e retorne as razes reais da equao. Observe que uma equao do 2o grau pode ter duas, uma ou nenhuma raiz real, dependendo do valor de , onde = b2 4ac. Exerccio 3.15 Capicua ou palndromo denido como um nmero que lido da direita para a esquerda ou da esquerda para a direita idntico. Escreva um programa C que solicite ao usuario a digitaao de um nmero inteiro e positivo no intervalo [1000, 9999] e que verique se o nmero palndromo. Exerccio 3.16 O Teorema de Pitgoras provavelmente o mais clebre dos teoremas da Matemtica. Enunciado pela primeira vez por lsofos gregos chamados de pitagricos, estabelece uma relao simples entre o comprimento dos lados de um tringulo retngulo: o quadrado da hipotenusa igual soma dos quadrados dos catetos. Escreva um programa C para vericar se os valores fornecidos pelo usurio em tempo de execuo para as medidas dos lados formam ou no um tringulo retngulo.

62

CAPTULO 3. ESTRUTURAS DE SELEO

3.4

Operador Condicional Ternrio

A linguagem C fornece um operador condicional ternrio, muito semelhante a um bloco if-else. A sintaxe do comando condio ? expresso1 : expresso2. O primeiro operando uma condio a ser logicamente avaliada, o segundo operando a expresso a ser executada caso a condio avaliada seja logicamente verdadeira. O terceiro operando a expresso a ser executada caso a condio avaliada seja logicamente falsa. Os Exemplos 3.12 e 3.13 apresentam alguns casos de uso do operador condicional ternrio. Exemplo 3.12 Operador condicional ternrio associado a um comando de atribuio. #include <stdio.h> int main(void) { int num; int res; printf("Digite um numero inteiro: "); scanf("%d", &num); res = (num >= 0) ? 1 : 0; printf("%d\n", res); system("pause"); return 0; } Digite um numero inteiro: 3 1 Exemplo 3.13 Operador condicional ternrio associado sada padro. #include <stdio.h> int main(void) { int num; printf("Quantos animais de estimacao voce possui? "); scanf("%d", &num); printf("Voce possui %d anima%s de estimacao.\n", num, (num == 1) ? "l" : "is"); system("pause");

3.5. PRECEDNCIA DE OPERADORES return 0; } Quantos animais de estimacao voce possui? 1 Voce possui 1 animal de estimacao.

63

3.5 Precedncia de Operadores


Agora que j foram apresentados diversos operadores aritmticos, relacionais e lgicos, torna-se importante observar a ordem de precedncia de execuo entre eles. Suponha que seja necessrio escrever um programa para selecionar candidatos a uma vaga de emprego com os seguintes requisitos: idade acima de 25 anos e formao em Engenharia ou Informtica. O Exemplo 3.14 tenta resolver o problema. Exemplo 3.14 Precedncia entre operadores da linguagem C. #include <stdio.h> int main(void) { int idade; int graduacao; printf("Idade: "); scanf("%d", &idade); printf("Graduacao: (1) Engenharia (2) Informatica scanf("%d", &graduacao); if(idade > 25 && graduacao == 1 || graduacao == 2) printf("Candidato aprovado.\n"); else printf("Candidato reprovado.\n"); system("pause"); return 0; } Idade: 20 Graduacao: (1) Engenharia Candidato aprovado.

(3) Outro ");

(2) Informatica

(3) Outro 2

A resposta est incorreta porque a precedncia do operador relacional && maior que do operador ||. A expresso relacional que consta do Exemplo 3.14 avaliada da seguinte forma: (idade > 25 && graduacao == 1) || graduacao == 2

64

CAPTULO 3. ESTRUTURAS DE SELEO

Para corrigir a precedncia dos operadores relacionais necessrio usar parnteses (Exemplo 3.15). Exemplo 3.15 Alterao de precedncia entre operadores com o uso de parnteses. #include <stdio.h> int main(void) { int idade; int graduacao; printf("Idade: "); scanf("%d", &idade); printf("Graduacao - (1) Engenharia (2) Informatica (3) Outro: "); scanf("%d", &graduacao); if(idade > 25 && (graduacao == 1 || graduacao == 2)) printf("Candidato aprovado.\n"); else printf("Candidato reprovado.\n"); system("pause"); return 0; } Idade: 20 Graduacao - (1) Engenharia Candidato reprovado.

(2) Informatica

(3) Outro: 2

3.5.1

Tabela de Precedncia Entre Operadores

A Tabela 3.5 apresenta a precedncia entre os operadores aritmticos, relacionais e lgicos utilizados at esse ponto do curso. Exerccio 3.17 Escrever um programa C que solicite ao usuario a digitaao do dia e do mes corrente no formato DD/MM e que verique se e uma data valida ou invlida. Por exemplo, 30/02 e 31/04 sao datas invalidas.

3.6

Comando de Desvio Condicional switch

O comando de desvio condicional switch uma alternativa ao uso de diversas estruturas if-else em problemas de mltiplas opes. A forma geral do comando switch apresentada a seguir:

3.6. COMANDO DE DESVIO CONDICIONAL SWITCH Tabela 3.5: Precedncia entre Operadores Smbolo ( ) ! * / % + < <= > >= == != && || ?: Descrio Parnteses Menos unrio No lgico Mutiplicao, diviso e mdulo Adio e subtrao Menor que, menor ou igual a, maior que, maior ou igual a Igual, diferente E lgico OU lgico Operador condicional ternrio

65

switch(expresso) { case constante1: sequncia_de_comandos; break; case constante2: sequncia_de_comandos; break; case constante3: sequncia_de_comandos; break; case ... default: sequncia_de_comandos; } Uma sequncia de comandos diferencia-se de um bloco de comandos por no ser delimitado por chaves de abertura e de fechamento. A execuo do comando switch segue os seguintes passos: A expresso avaliada. O resultado da expresso comparado com as constantes associadas s clusulas case. Quando o resultado da expresso for igual a uma das constantes, a execuo transferida para o incio da sequncia de comandos associada a esta constante.

66

CAPTULO 3. ESTRUTURAS DE SELEO A execuo continua sequencialmente at o m do comando switch a menos que um comando break seja encontrado. Nesse caso, a execuo do comando switch terminada. Caso o valor da expresso no corresponda a nenhuma das constantes associadas s clusulas case, a sequncia de comandos associada clusula default executada. A clusula default opcional. Nenhuma sequncia de comandos ser executada caso o valor da expresso no corresponda a nenhuma clusula case e no houver uma clusula default denida.

O comando break um dos comandos de desvio incondicional da linguagem C. O comando break usado no corpo do comando switch para interromper a execuo de uma sequncia de comandos e pular para a instruo seguinte ao comando switch. H ainda alguns pontos importantes que devem ser mencionados sobre o comando switch: O resultado da expresso avaliada deve ser um valor inteiro. Caso no exista um comando de desvio incondicional break, todas as instrues seguintes clusula case selecionada sero executadas, mesmo que pertenam as sequncias de comandos seguintes. O comando switch s pode testar a igualdade. Cada constante associada a uma clusula case deve possuir um valor diferente. No h uma ordem estabelecida para as diversas clusulas case de um comando switch. O Exemplo 3.16 ilustra a aplicao do comando de desvio condicional switch. Exemplo 3.16 Escrever um programa C para solicitar ao usuario a digitao de um numero inteiro correspondente a classicao em uma competio esportiva e que apresente na tela a medalha conquistada. #include <stdio.h> int main(void) { int classificacao; printf("Digite a classificacao: "); scanf("%d",&clas); switch(clas) { case 1: printf("Medalha de ouro.\n"); break;

3.6. COMANDO DE DESVIO CONDICIONAL SWITCH case 2: printf("Medalha de prata.\n"); break; case 3: printf("Medalha de bronze.\n"); break; default: printf("Nao ha medalha para essa classificacao.\n"); } system("pause"); return 0; } Digite a classificacao: 2 Medalha de prata.

67

Observe que as clusulas case de um comando switch no podem ser associadas a expresses relacionais. O Exemplo 3.17 ilustra essa restrio da estrutura. Exemplo 3.17 Escrever um programa C para solicitar ao usuario a digitao de uma resposta do tipo sim ou no a uma pergunta. O usurio pode usar letras maisculas ou minsculas ao responder. #include <stdio.h> int main(void) { char resp; printf("Digite (S)im ou (N)ao: "); scanf("%c", &resp); switch(resp) { case 'S': case 's': printf("Voce respondeu SIM.\n"); break; case 'N': case 'n': printf("Voce respondeu NAO.\n"); break; default: printf("Voce respondeu incorretamente.\n"); } system("pause");

68 return 0; }

CAPTULO 3. ESTRUTURAS DE SELEO

Exerccio 3.18 Escrever um programa C que solicite ao usuario o peso de uma pessoa na Terra e o numero correspondente a um dos demais planetas do sistema solar e que apresente na tela o peso no planeta especicado. Considere a Tabela 3.6 para os valores da gravidade relativa dos planetas tomando como base 1 o valor na Terra. Tabela 3.6: Gravidade relativa nos planetas do Sistema Solar Nmero Gravidade Planeta 1 0,37 Mercrio 2 0,88 Vnus 3 0,38 Marte 4 2,64 Jpiter 5 1,15 Saturno 6 1,17 Urano

Exerccio 3.19 Escrever um programa C que solicite ao usuario qual o prato principal, a sobremesa e a bebida escolhidos a partir do cardapio de um restaurante e que informe o total de calorias que sera consumido pelo cliente. Considere a Tabela 3.7 de calorias.

3.7

Funes para Teste de Caracteres

A biblioteca padro <ctype.h> disponibiliza diversas funes para teste de caracteres, conforme apresentado na Tabela 3.8. Em todos os casos a funo retorna verdadeiro ou falso. Alm das funes para teste de caracteres, a biblioteca padro <ctype.h> oferece as funes tolower() e toupper() que permitem a converso de uma letra maiscula para minscula e vice-versa. Exemplo 3.18 Escrever um programa C para solicitar ao usuario a digitao de um caractere em tempo de execuo. O programa deve vericar se o usurio digitou uma vogal ou uma consoante.

3.7. FUNES PARA TESTE DE CARACTERES Tabela 3.7: Calorias por item do cardpio de um restaurante Prato Vegetariano (180 cal) Peixe (230 cal) Frango (250 cal) Carne de Porco (350 cal) Sobremesa Abacaxi (75 cal) Sorvete diet (110 cal) Mousse diet (170 cal) Mousse chocolate (200 cal)

69

Bebida Cha (20 cal) Suco de Laranja (70 cal) Suco de Melao (100 cal) Refrigerante (120 cal)

Tabela 3.8: Funes para teste de caracteres Funo islower isupper isalpha isalnum isdigit isblank Teste Letra minscula Letra maiscula Letra maiscula ou minscula Letra ou dgito numrico Dgito numrico Espao em branco ou marca de tabulao

#include <stdio.h> #include <ctype.h> int main(void) { char ch; printf("Digite um caractere: "); scanf("%c",&ch); if(isalpha(ch)) { if(islower(ch)) ch = toupper(ch); if(ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') printf("Voce digitou uma vogal.\n"); else printf("Voce digitou uma consoante.\n"); } system("pause"); return 0; } Digite um caractere: a

70 Voce digitou uma vogal.

CAPTULO 3. ESTRUTURAS DE SELEO

Exerccio 3.20 Escrever um programa C para solicitar ao usuario a digitao de um caractere em tempo de execuo. O programa deve vericar se o usurio digitou letra, nmero, espao ou nenhum desses. Exerccio 3.21 Escrever um programa C para solicitar ao usuario a digitao de um caractere em tempo de execuo. O programa deve vericar se o usurio digitou letra ou nmero. Se digitou letra, informar se a letra digitada maiscula ou minscula. Exerccio 3.22 Escrever um programa C que solicite ao usurio a digitao da sigla da unidade da federao (UF) e que exiba o nome do Estado correspondente. Para simplicar o exerccio, considere apenas os Estados da regio Sudeste. Exerccio 3.23 Um nmero hexadecimal pode conter dgitos numricos (0 a 9) e letras (A a E). Escreva um programa C que solicite ao usurio a digitao de um nmero hexadecimal composto por um nico dgito e que exiba na tela o correspondente valor em decimal.

3.8

Operador Aritmtico de Atribuio

A linguagem C permite a codicao de programas-fonte concisos. Para tanto, fornece atalhos para alguns operadores. O operador aritmtico de atribuio permite reunir um comando de atribuio a um operador aritmtico. Por exemplo, a linha cdigo: num = num + 10; pode ser reescrita na forma num += 10; O operador aritmtico de atribuio pode ser empregado em conjunto com os operadores aritmticos de adio (+), subtrao (-), multiplicao (*), diviso (/) e mdulo (%).

Captulo 4 Estruturas de Repetio


A mente que se abre a uma nova ideia jamais voltara ao seu tamanho original Albert Einstein

Em diversos casos, um algoritmo necessita repetir parte do codigo diversas vezes. O mecanismo de repetio e um dos mais importantes recursos empregados em programas de computador. Atraves da iterao de lacos, um trecho denido pode ser executado quantas vezes forem necessarias para se implementar corretamente o algoritmo desejado. A linguagem C oferece tres comandos de repetio: for, while e do-while. Dependendo das caracteristicas do algoritmo a ser implementado, pode ser mais interessante empregar um ou outro dos comandos mencionados.

4.1 Operadores de Incremento e Decremento


Os operadores de incremento (++) e de decremento (--) permitem, respectivamente, adicionar ou subtrair uma unidade de uma varivel do tipo inteiro. Uma expresso aritmtica que contenha o operador de adio para somar uma unidade pode ser reescrita utilizando-se o operador de incremento ++ (Exemplo 4.1). Exemplo 4.1 Emprego do operador de incremento. #include <stdio.h> int main(void) { int a; a = 7; 71

72

CAPTULO 4. ESTRUTURAS DE REPETIO a++; /* equivale a a = a + 1; */ printf("%d\n", a); system("pause"); return 0;

} De forma anloga, uma expresso aritmtica que contenha o operador de subtrao para subtrair uma unidade pode ser reescrita utilizando-se o operador de decremento -- (Exemplo 4.2). Exemplo 4.2 Emprego do operador de decremento. #include <stdio.h> int main(void) { int a; a = 7; a--; /* equivale a a = a - 1; */ printf("%d\n", a); system("pause"); return 0; }

4.1.1

Formas Pr-xada e Ps-xada para os Operadores de Incremento e Decremento

importante observar alguns particularidades quanto ao emprego dos operadores de incremento e decremento. Quando usados no contexto de expresses, o uso incorreto pode ocasionar resultados inesperados. O operador de incremento dito pr-xado quando adiciona uma unidade varivel para depois calcular o valor da expresso (Exemplo 4.3). Ao contrrio, o operador de incremento dito ps-xado quando adiciona uma unidade varivel somente depois que o clculo do valor da expresso j foi realizado (Exemplo 4.4). A mesma considerao vlida para o operador de decremento. Exemplo 4.3 Emprego do operador de incremento pr-xado. #include <stdio.h> #include <math.h> int main(void) {

4.2. ESTRUTURA DE REPETIO FOR int num1, num2; num1 = 10; num2 = num1++; printf("%d\n",num2); system("pause"); return 0; } Exemplo 4.4 Emprego do operador de incremento ps-xado. #include <stdio.h> #include <math.h> int main(void) { int num1, num2; num1 = 10; num2 = num1++; printf("%d\n",num2); system("pause"); return 0; }

73

4.2 Estrutura de Repetio for


A estrutura de repetio for aparece em vrias linguagens de programao, mas em C apresenta uma grau maior de exibilidade. A ideia bsica da estrutura for consiste em empregar uma varivel, geralmente um contador, para controlar as repeties a serem executadas. O bloco de comandos associada estrutura for executado e ao nal a varivel de controle incrementada ou decrementada e comparada com o valor nal que deve alcanar. Caso a condio para o trmino da repetio tenha sido atingida a execuo da estrutura for interrompida.

4.2.1 Forma Geral da Estrutura for


A forma geral da estrutura de repetio for : for(valor_inicial;teste;passo) bloco_de_comandos

74 onde:

CAPTULO 4. ESTRUTURAS DE REPETIO

o valor_inicial corresponde a uma expresso utilizada para inicializar a varivel de controle da estrutura for; o teste corresponde a uma expresso cujo objetivo vericar se a estrutura for deve ser terminada; o passo permite alterar o valor da varivel de controle da estrutura for. A execuo da estrutura for segue os seguintes passos: 1. o valor_inicial atribudo varivel de controle; 2. o teste avaliado para determinar se a estrutura de repetio for deve ser executada; 3. se o resultado do teste for verdadeiro o bloco_de_comandos executado, caso contrrio a instruo for terminada; 4. o passo processado; 5. a execuo retorna ao passo 2. O Exemplo 4.5 apresenta um cdigo-fonte C que emprega a estrutura de repetio for. Exemplo 4.5 Programa para exibir na tela todos os nmeros inteiros no intervalo [1, 10]. #include <stdio.h> int main(void) { int i; /* varivel de controle */ for (i = 1; i <= 10; i++) printf("%d\n", i); /* bloco de comandos */ system("pause"); return 0; } Os Exemplos 4.6 e 4.7 apresentam outros casos de uso para a estrutura de repetio for. Exemplo 4.6 Programa para exibir na tela todos os nmeros pares no intervalo [1, 20].

4.2. ESTRUTURA DE REPETIO FOR #include <stdio.h> int main(void) { int i; /* varivel de controle*/ for (i = 2; i <= 20; i += 2) printf("%d\n", i); /* bloco de comandos */ system("pause"); return 0; }

75

O Exemplo 4.7 apresenta um algoritmo para calcular uma soma de forma iterativa, onde cada novo valor a ser adicionado gerado em uma estrutura de repetio. importante observar que em algoritmos para clculo de um somatrio necessrio a atribuio de um valor inicial para a varivel que recebe o valor da soma. Normalmente esse valor inicial corresponde ao nmero 0 por se tratar do valor neutro da adio. Exemplo 4.7 Programa para calcular e exibir na tela a soma dos nmeros inteiros no intervalo [1, 100]. #include <stdio.h> int main(void) { int i; /* varivel de controle*/ int soma = 0; for (i = 1; i < 100; i++) soma += i; printf("Soma: %d\n",soma); system("pause"); return 0; }

4.2.2 Lao Innito


importante observar que o programador inteiramente responsvel pela construo de uma estrutura de repetio for que contenha uma condio de teste que efetivamente termine a execuo do lao. Caso contrrio, a execuo do lao continuar indenidamente. Esse erro de lgica chamado lao innito (Exemplo 4.8). Exemplo 4.8 Lao innito em estrutura de repetio for.

76

CAPTULO 4. ESTRUTURAS DE REPETIO

#include <stdio.h> int main(void) { int i; for (i = 1; i >= 0 ; i++) /* Lao infinito! */ printf("%d\n", i); system("pause"); return 0; } Exerccio 4.1 Escreva um programa C para exibir na tela em ordem decrescente todos os numeros naturais no intervalo [1, 25]. Exerccio 4.2 Escreva um programa C para exibir na tela em ordem decrescente todos os numeros mpares no intervalo [1, 50]. Exerccio 4.3 Escreva um programa C para exibir na tela em ordem crescente 10 nmeros reais no intervalo [0, 1]. Exerccio 4.4 Escrever uma programa C para exibir na tela uma tabela com a temperatura em graus Celsius e a temperatura equivalente em Fahrenheit, para valores entre 15 e 35 graus Celsius. Frmula de converso: TF = 9TC /5 + 32 Exerccio 4.5 Escrever uma programa C que exiba na tela todos os nmeros inteiros compreendidos entre um limite inferior e um limite superior fornecidos pelo usurio em tempo de execuo. Exerccio 4.6 Escrever uma programa C que exiba na tela em ordem crescente todos os nmeros inteiros compreendidos entre um limite inferior e um limite superior fornecidos pelo usurio em tempo de execuo. Observe que o usurio pode digitar primeiro o limite superior. Exerccio 4.7 Escreva um programa C que solicite ao usuario a digitaao de 10 numeros inteiros e positivos e que calcule e exiba na tela a media aritmetica dos numeros fornecidos. Exerccio 4.8 Escreva um programa C que solicite ao usuario a digitaao de 10 caracteres e que calcule e exiba na tela a quantidade de letras do alfabeto que foram digitadas.

4.2. ESTRUTURA DE REPETIO FOR

77

Exerccio 4.9 Escreva um programa C que solicite ao usuario a digitaao de 10 caracteres e que calcule e exiba na tela a quantidade de letras maisculas que foram digitadas. Exerccio 4.10 Escreva um programa C que solicite ao usuario a digitaao de 10 numeros inteiros. Exibir na tela o maior valor informado pelo usurio. Exerccio 4.11 Escreva um programa C para calcular e exibir na tela o fatorial de um numero inteiro e positivo, fornecido pelo usuario em tempo de execuao. N ! = 1 2 3 . . . N , para N > 0 e N ! = 1 para N = 0. Exerccio 4.12 Escreva um programa C que solicite ao usuario a digitaao de um numero inteiro e positivo N e que calcule e mostre na tela a seguinte soma: S = 1 + 1/2 + 1/3 + 1/4 + 1/5 + . . . + 1/N . Exerccio 4.13 Escreva um programa C que solicite ao usuario a digitaao de um numero inteiro e positivo N e que calcule e mostre na tela a seguinte soma: S = 1 1/2 + 1/3 1/4 + 1/5 . . . 1/N . Exerccio 4.14 Escreva um programa C que solicite ao usuario a digitaao de um numero inteiro e positivo qualquer e que verique se o numero e primo. Um nmero inteiro e positivo dito primo se divisvel apenas por 1 e por ele prprio. Exerccio 4.15 Escrever um programa C para calcular e exibir na tela aproximaes para o numero irracional a partir da serie: = 4 4 + 4 4 + 4 . . . Exiba o resultado 3 5 7 9 para 10, 100, 1000 e 10000 termos da serie. Exerccio 4.16 Escrever um programa C que calcule e exiba na tela os N primeiros termos da serie de Fibonacci: 1, 1, 2, 3, 5, 8, 13, 21, . . ., onde N e fornecido pelo usuario em tempo de execucao.

4.2.3 Estruturas for Avanadas


A estrutura de repetio for da linguagem C bastante exvel e permite construes complexas. Na maioria dos casos, porm, essas construes devem ser evitadas porque tornam o cdigo-fonte confuso.

78

CAPTULO 4. ESTRUTURAS DE REPETIO

Estrutura for Com Mais de Uma Varivel de Controle O Exemplo 4.9 apresenta um programa-fonte C onde a estrutura for utiliza duas variveis de controle. Exemplo 4.9 Estrutura de repetio que utiliza duas variveis de controle. #include <stdio.h> int main(void) { int i; int j; for (i = 0, j = 10; i+j>0; i++,j-=2) printf("i = %d e j = %2d\n", i, j); system("pause"); return 0; } i i i i i i i i i i = = = = = = = = = = 0 1 2 3 4 5 6 7 8 9 e e e e e e e e e e j j j j j j j j j j = = = = = = = = = = 10 8 6 4 2 0 -2 -4 -6 -8

Estrutura for Sem Valor Inicial Alm disso, vale observar que no necessrio denir o valor inicial para a varivel de controle de uma estrutura for diretamente no comando (Exemplo 4.10). Exemplo 4.10 Estrutura de repetio for sem a inicializao da varivel de controle. #include <stdio.h> int main(void) { int i = 0; for ( ; i < 10; i++)

4.2. ESTRUTURA DE REPETIO FOR printf("%d\n", i); system("pause"); return 0; } Estrutura for Sem Incremento

79

De forma anloga, o incremento no necessariamente deve ser explicitado na estrutura de repetio for (Exemplo 4.11). Exemplo 4.11 Estrutura de repetio for sem a denio do incremento da varivel de controle. #include <stdio.h> int main(void) { int i = 0; for ( ; i < 10; ) printf("%d\n", i++); system("pause"); return 0; } Estrutura for Sem Condio de Teste Mesmo a condio de teste pode ser suprimida em uma estrutura de repetio for. Nesse caso, o bloco de comandos associado estrutura deve permitir que a execuo do lao for seja interrompido caso contrrio ocorrer um lao innito. O Exemplo 4.12 utiliza o comando incondicional break para terminar a execuo da estrutura de repetio for quando uma determinada condio atingida. Exemplo 4.12 Estrutura de repetio for sem a condio de teste. #include <stdio.h> int main(void) { int i = 0; for ( ; ; ) { printf("%d\n", i++); if(i == 10) break;

80 } system("pause"); return 0; }

CAPTULO 4. ESTRUTURAS DE REPETIO

Estrutura for Sem Bloco de Comandos Por m, possvel implementar uma estrutura de repetio for sem um bloco de comandos associado. Nessa situao, todo o contedo da estrutura limita-se aos parmetros informados nas condies iniciais, teste e incremento (Exemplo 4.13). Observe que nesse caso necessrio inserir as chaves de abertura e fechamento para especicar um bloco de comandos vazio. Exemplo 4.13 Estrutura de repetio for sem bloco de comandos. #include <stdio.h> int main(void) { long soma = 0; int i; for (i = 1; i <= 100; soma += i++) { } printf("Soma: %d\n", soma); system("pause"); return 0; } Soma: 5050

4.2.4

Laos Aninhados

Em alguns algoritmos necessrio inserir uma estrutura de repetio for dentro do bloco de comandos de uma outra estrutura de repetio for. Quando se tem uma estrutura de repetio no interior de outra estrutura de repetio d-se o nome de laos aninhados. O Exemplo 4.14 apresenta o funcionamento de estruturas for aninhadas. Exemplo 4.14 Programa C para exibir o processo de execuo de laos for aninhados.

4.2. ESTRUTURA DE REPETIO FOR #include <stdio.h> int main(void) { int i, j; int num; printf("Numero de inteiro: "); scanf("%d",&num); for (i = 1; i <= num; i++) for (j = 1; j <= i; j++) printf("i=%d j=%d\n",i,j); system("pause"); return 0; } Numero de inteiro: 3 i=1 j=1 i=1 j=2 i=1 j=3 i=2 j=1 i=2 j=2 i=2 j=3 i=3 j=1 i=3 j=2 i=3 j=3

81

Exerccio 4.17 Escrever um programa C exiba na tela um quadrado formado pelo caractere * repetido diversas vezes. O tamanho do quadrado, ou seja, o nmero de asteriscos na linha e na coluna deve ser informado pelo usurio. Exerccio 4.18 Escrever um programa C exiba na tela um retngulo formado pelo caractere * repetido diversas vezes. O tamanho do retngulo, ou seja, o nmero de asteriscos na linha e na coluna devem ser informados pelo usurio. Exerccio 4.19 Escrever um programa C exiba na tela um tringulo formado pelo caractere * repetido diversas vezes. O tamanho do tringulo, ou seja, o nmero de asteriscos na maior largura e maior altura devem ser informados pelo usurio. Exerccio 4.20 Escrever um programa C que solicite ao usurio a digitao de diversos valores inteiros e positivos. A entrada de dados deve terminar quando o usurio informar um valor negativo. Exibir a soma dos valores digitados pelo usurio. O valor negativo no deve ser somado.

82

CAPTULO 4. ESTRUTURAS DE REPETIO

4.3

Estrutura de Repetio while

A estrutura de repetio while permite repetir um trecho de codigo enquanto uma determinada condio for verdadeira. Em geral, uma estrutura while fornece um cdigo mais simples e fcil de ser entendido do que a estrutura for quando nao se conhece a priori o numero de repeties que serao executadas no corpo do lao.

4.3.1

Forma Geral da Estrutura while

A forma geral da estrutura de repetio while : while(condio) bloco_de_comandos onde a condio corresponde a uma expresso relacional que deve ser logicamente avaliada e bloco-de-comandos corresponde a uma ou mais instrues C que sero executadas somente enquanto a condio avaliada for verdadeira. O Exemplo 4.15 ilustra a aplicao da estrutura de repetio while. Exemplo 4.15 Programa C para exibir na tela todos os numeros naturais menores que 100. #include <stdio.h> int main(void) { int i = 1; while(i < 100) { printf("%4d",i); i++; } printf("\n"); system("pause"); return 0; } Uma soluo alternativa poderia empregar o operador unario de incremento ++. Nesse caso, como o bloco de comandos do comando while constitudo por apenas uma nica instruo C, no necessrio a delimitao atravs de chaves de abertura e fechamento (Exemplo 4.16).

4.3. ESTRUTURA DE REPETIO WHILE

83

Exemplo 4.16 Programa C para exibir na tela todos os numeros naturais menores que 100 onde o bloco de cdigos contm apenas uma nica instruo. #include <stdio.h> int main(void) { int i = 1; while(i < 100) printf("%4d",i++); printf("\n"); system("pause"); return 0; } Exemplo 4.17 Programa C para calcular e exibir na tela a soma dos numeros naturais at 100. #include <stdio.h> int main(void) { int num = 1; int soma = 0; while(num <= 100) { soma += num; num++; } printf("Soma: %d\n",soma); system("pause"); return 0; }

4.3.2 Flag ou Sentinela


Em muitos algoritmos, nao se conhece previamente o numero de iteraes que uma estrutura de repetio dever executar. Na maioria dos casos, um lao deve ser executado ate que o usuario digite um valor que determina o termino das iteraes. Esse valor informado e chamado ag ou sentinela. No Exemplo 4.18, o ag o numero 0. Exemplo 4.18 Programa C para calcular a soma dos numeros inteiros fornecidos pelo usuario em tempo de execuo. A entrada de dados termina quando o usuario digita o valor 0.

84

CAPTULO 4. ESTRUTURAS DE REPETIO

#include <stdio.h> int main(void) { int soma = 0; int num; printf("Digite um numero inteiro: "); scanf("%d", &num); while (num != 0) { soma += num; printf("Digite um numero inteiro: "); scanf("%d", &num); } printf("Soma: %d\n", soma); system("pause"); return 0; } 3 5 0 Soma: 8

4.3.3

Estrutura while Sempre Verdadeira

Uma estrutura de repetio while pode ser escrita de forma que a condio a ser avaliada seja sempre verdadeira. Nesse caso, o trmino da execuo da estrutura de repetio dever ser explicitamente implementada no corpo do lao atravs de um comando break. O Exemplo 4.19 ilustra a aplicao de uma estrutura while sempre verdadeira. Exemplo 4.19 Programa C para calcular a soma dos numeros inteiros fornecidos pelo usuario em tempo de execuo utilizando uma estrutura while sempre verdadeira. A entrada de dados termina quando o usuario digita o valor 0. #include <stdio.h> int main(void) { int soma = 0; int num; while ( 1 ) { printf("Digite um numero inteiro: "); scanf("%d", &num);

4.3. ESTRUTURA DE REPETIO WHILE if(num == 0) break; soma += num; } printf("Soma: %d\n", soma); system("pause"); return 0; } 3 5 0 Soma: 8

85

Para resolver os Exerccios 4.21 a 4.27 utilize a estrutura de repetio while. Exerccio 4.21 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de 10 nmeros inteiros quaisquer. Calcule e exiba na tela a soma somente dos nmeros positivos. Exerccio 4.22 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar um ponto. Exibir na tela o total de caracteres digitados. Exerccio 4.23 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar um ponto. Exibir na tela o total de letras e o total de dgitos numricos digitados. Exerccio 4.24 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar qualquer caractere que no for uma letra. Exibir na tela o total de letras maisculas e o total de letras minsculas digitadas. Exerccio 4.25 Dado um pais A, com 5 milhoes de habitantes e uma taxa de natalidade de 3% ao ano, e um pais B com 7 milhoes de habitantes e uma taxa de natalidade de 2% ao ano, fazer um programa C para calcular e exibir na tela o tempo necessario para que a populao do pais A ultrapasse a populao do pais B.

86

CAPTULO 4. ESTRUTURAS DE REPETIO

Exerccio 4.26 Escrever um programa C que solicite ao usuario a digitao em tempo de execuo de diversos numeros inteiros no intervalo [1, 1000]. O ag e qualquer valor fora desse intervalo. Apresentar na tela o maior e o menor valor vlido ou seja, dentro do intervalo digitado pelo usuario. Exerccio 4.27 Escrever um programa C que solicite ao usurio a digitao de diversos numeros inteiros e positivos. O programa deve vericar cada um dos numeros fornecidos e um quadrado perfeito. O ag e um nmero no-positivo. Um numero e dito quadrado perfeito quando a raiz quadrada e um numero inteiro.

4.4

Estrutura de Repetio do-while

De forma semelhante estrutura while, a estrutura de repetio do-while permite repetir um trecho de codigo enquanto uma determinada condio for verdadeira. Entretanto, guarda porem uma diferenca importante em relao estrutura while. Em um lao do-while o bloco de comandos associado estrutura de repetio e executado obrigatoriamente pelo menos uma vez, independente da expresso relacional associada ao comando. Isso acontece porque a avaliao da condio e feita no nal da estrutura de repetio do-while.

4.4.1

Forma Geral da Estrutura do-while

A forma geral da estrutura de repetio do-while : do bloco_de_comandos while(condio) onde a condio corresponde a uma expresso relacional que deve ser logicamente avaliada e bloco-de-comandos corresponde a uma ou mais instrues C que sero executadas somente enquanto a condio avaliada for verdadeira. O Exemplo 4.20 ilustra a aplicao da estrutura de repetio while. Exemplo 4.20 Programa C para exibir na tela todos os numeros naturais menores que 100 utilizando a estrutura de repetio do-while. #include <stdio.h> int main(void) {

4.4. ESTRUTURA DE REPETIO DO-WHILE int num = 1; do { printf("%4d",num); num++; } while(num < 100); printf("\n"); system("pause"); return 0; }

87

Em alguns casos, a estrutura de repetio do-while permite a construo de algoritmos relativamente mais simples e de melhor implementao em comparao estrutura while (Exemplo 4.21).

Exemplo 4.21 Programa C para calcular a soma dos numeros inteiros fornecidos pelo usuario em tempo de execucao utilizando o comando do-while. A entrada de dados termina quando o usuario informa o valor 0.

#include <stdio.h> int main(void) { int soma = 0; int num; do { printf("Digite um numero inteiro: "); scanf("%d", &num); soma += num; } while (num != 0); printf("Soma: %d\n", soma); system("pause"); return 0; } 3 5 0 Soma: 8

88

CAPTULO 4. ESTRUTURAS DE REPETIO

4.5

Comando continue

O comando continue permite ignorar o restante das instrues inseridas em uma estrutura de repetio e avanar a execuo para a avaliao da condio de teste. O Exemplo 4.22 ilustra a aplicao do comando continue. Exemplo 4.22 Programa C para calcular a soma dos numeros inteiros fornecidos pelo usuario em tempo de execucao utilizando o comando continue. A entrada de dados termina quando o usuario informa o valor 0. #include <stdio.h> int main(void) { int soma = 0; int num; do { printf("Digite um numero inteiro: "); scanf("%d", &num); if(num ==0 ) continue; soma += num; } while (num != 0); printf("Soma: %d\n", soma); system("pause"); return 0; } 3 5 0 Soma: 8 Para resolver os Exerccios 4.28 a 4.34 utilize a estrutura de repetio do-while. Exerccio 4.28 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de 10 nmeros inteiros quaisquer. Calcule e exiba na tela a soma somente dos nmeros positivos. Exerccio 4.29 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar um ponto. Exibir na tela o total de caracteres digitados.

4.6. CONSISTNCIA NA ENTRADA DE DADOS

89

Exerccio 4.30 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar um ponto. Exibir na tela o total de letras e o total de dgitos numricos digitados. Exerccio 4.31 Escrever um programa C que solicite ao usurio a digitao em tempo de execuo de diversos caracteres. A entrada de dados deve terminar quando o usurio digitar qualquer caractere que no for uma letra. Exibir na tela o total de letras maisculas e o total de letras minsculas digitadas. Exerccio 4.32 Dado um pais A, com 5 milhoes de habitantes e uma taxa de natalidade de 3% ao ano, e um pais B com 7 milhoes de habitantes e uma taxa de natalidade de 2% ao ano, fazer um programa C para calcular e exibir na tela o tempo necessario para que a populao do pais A ultrapasse a populao do pais B. Exerccio 4.33 Escrever um programa C que solicite ao usuario a digitao em tempo de execuo de diversos numeros inteiros no intervalo [1, 1000]. O ag e qualquer valor fora desse intervalo. Apresentar na tela o maior e o menor valor vlido ou seja, dentro do intervalo digitado pelo usuario. Exerccio 4.34 Escrever um programa C que solicite ao usurio a digitao de diversos numeros inteiros e positivos. O programa deve vericar cada um dos numeros fornecidos e um quadrado perfeito. O ag e um nmero no-positivo. Um numero e dito quadrado perfeito quando a raiz quadrada e um numero inteiro.

4.6 Consistncia na Entrada de Dados


Em geral, os exemplos de cdigo-fonte C apresentados solicitam ao usurio a digitao de dados a partir da entrada padro (teclado). O leitor mais atento deve ter observado que o usurio instrudo a informar um determinado tipo de informao por exemplo, um valor inteiro ou uma letra do alfabeto mas os programas-fonte no vericam se o tipo de dado solicitado foi de fato digitado. A introduo das estruturas de repetio permitem que os algoritmos construdos em linguagem C possam de alguma forma processar o tipo de dado digitado pelo usurio e vericar se esto de acordo com o esperado. Esse processo de deteco de erros na entrada de dados recebe o nome de consistncia. Especicamente, a consistncia na entrada de dados visa impedir que valores fornecidos pelo usurio em tempo de execuo sejam aceitos caso estejam em desacordo com o tipo, quantidade ou limites esperados.

90

CAPTULO 4. ESTRUTURAS DE REPETIO

O Exemplo 4.23 ilustra a aplicao da tcnica de consistncia na entrada de dados utilizando uma estrutura de repetio while. O programa impede que nmeros inteiros negativos sejam aceitos. Exemplo 4.23 Programa C que solicita ao usurio a digitao de 5 nmeros naturais e que calcula e exibe a soma dos nmeros informados. #include <stdio.h> int main(void) { int soma = 0; int i; int num; for (i = 1; i <= 5; i++) { printf("Informe um numero natural (%d/5): ",i); scanf("%d", &num); while (num<1) { // Consistncia na entrada de dados printf("Erro. Informe um numero natural (%d/5): ",i); scanf("%d", &num); } soma += num; } printf("Soma = %d\n",soma); system("pause"); return 0; } Informe um numero natural (1/5): 0 Erro. Informe um numero natural (1/5): 5 Informe um numero natural (2/5): -4 Erro. Informe um numero natural (2/5): 4 Informe um numero natural (3/5): 2 Informe um numero natural (4/5): 4 Informe um numero natural (5/5): 6 Soma = 21 Exemplo 4.24 Programa C que solicita ao usurio a digitao de diversas letras do alfabeto e que calcula e exibe o nmero de letras informadas. O ag o caractere ponto. A consistncia na entrada de dados feita a partir de uma estrutura de repetio do-while. #include <stdio.h>

4.7. NMEROS PSEUDOALEATRIOS #include <ctype.h> int main(void) { int letras = 0; char ch; do { printf("Digite uma letra: "); scanf(" %c",&ch); if(isalpha(ch)) letras++; else if(ch == '.') break; else printf("Erro! "); } while(ch != '.'); printf("Numero de letras digitadas: %d\n",letras); system("pause"); return 0; } Digite uma letra: e Digite uma letra: G Digite uma letra: 5 Erro! Digite uma letra: k Digite uma letra: @ Erro! Digite uma letra: m Digite uma letra: . Numero de letras digitadas: 4

91

Exerccio 4.35 Escrever um programa C que solicite ao usurio a digitao de 10 numeros inteiros no intervalo [1, 10]. O programa deve calcular e exibir a soma dos nmeros fornecidos pelo usurio. Faa a consistncia na entrada de dados de forma que todos os nmeros inteiros fora do intervalo sejam desprezados e o usurio seja instrudo a digitar um novo valor.

4.7 Nmeros Pseudoaleatrios


A linguagem C permite a gerao automtica de numeros pseudoaleatorios, uteis em diversos problemas computacionais, principalmente em modelagem e simulaao

92

CAPTULO 4. ESTRUTURAS DE REPETIO

probabilistica. Os nmeros gerados so ditos pseudoaleatrios porque na realidade so obtidos a partir do emprego de funes matemticas pr-denidas. A biblioteca padro <stdlib.h> contm a funo rand(), que retorna um numero inteiro pseudoaleatrio no intervalo [0, 32767]. O Exemplo 4.25 ilustra a aplicao da funo rand(). Exemplo 4.25 Programa C que gera nmeros pseudoaleatrios a partir da funo rand(). #include <stdio.h> #include <stdlib.h> int main(void) { int i; for(i = 0;i < 10;i++) printf("Numero pseudoaleatorio: %d\n",rand()); system("pause"); return 0; }

4.7.1

Semente de Randomizao

O problema do algoritmo implementado no Exemplo 4.25 que a cada nova execuo do programa executvel gerado, os mesmos nmeros sero gerados e exibidos na mesma ordem. A explicao para esse comportamento refere-se forma como o compilador processa a gerao de nmeros pseudoaleatrios, ou seja, a partir de uma funo matemtica padro. Para contornar o problema necessrio alterar a semente de randomizao. Em outros termos, preciso alterar a frmula matemtica usada pelo compilador para a gerao dos nmeros pseudoaleatrios. Para tanto, deve-se utilizar a funo srand() disponvel tambm na biblioteca <stdlib.h>. A funo srand() deve receber um nmero inteiro como argumento. Para que que seja possvel informar sempre um argumento diferente e, dessa forma, produzir uma funo geradora de nmeros pseudoaleatrios distinta, normalmente se utiliza a funo time(0), que retorna o nmero de milisegundos transcorridos desde o dia 01/01/1970. Como esse valor sempre varia no tempo, trata-se de uma boa soluo para a construo de funes gerados adequadas. O Exemplo 4.26 ilustra o emprego das funes srand() e time(0) para permitir a alterao da semente de randomizao usada pela funo rand() para a gerao de nmeros pseudoaleatrios.

4.7. NMEROS PSEUDOALEATRIOS

93

Exemplo 4.26 Programa C que permite a alterao da semente de randomizao para gerao de nmeros pseudoaleatrios. #include <stdio.h> #include <stdlib.h> int main(void) { srand(time(0)); int i; for(i = 0;i < 10;i++) printf("Numero pseudoaleatorio: %d\n",rand()); system("pause"); return 0; } Conforme apresentado no Exemplo 4.26, os algoritmos implementados em C que utilizem nmeros pseudoaleatrios devem incluir a instruo para a alterao da semente de randomizao no incio do bloco de comandos da funo main(). Dessa forma, a cada nova execuo do programa executvel, valores diferentes sero gerados.

4.7.2 Escopo dos Nmeros Pseudo-Aleatrios Gerados


A funo rand() retorna um nmero pseudo-aleatrio no intervalo [0, 32767]. Para alterar o intervalo pode-se empregar alguma manipulao algbrica, conforme apresentado no Exemplo 4.27. Exemplo 4.27 Programa C que permite a gerao de nmeros pseudoaleatrios no intervalo [0, 9]. #include <stdio.h> #include <stdlib.h> int main(void) { srand(time(0)); int i; int num; for(i = 0;i < 10;i++) { num = rand() % 10; printf("%d\n",num); } system("pause");

94 return 0; }

CAPTULO 4. ESTRUTURAS DE REPETIO

Mesmo para a gerao de caracteres pseudo-aleatrios possvel empregar-se a funo rand(). Nesse caso, utiliza-se a codicao numrica ASCII correspondente, conforme apresentado no Exemplo 4.28. Exemplo 4.28 Programa C que permite a gerao de letras maisculas pseudoaleatrios no intervalo. #include <stdio.h> #include <stdlib.h> int main(void) { srand(time(0)); int i; char letra; for(i = 0;i < 10;i++) { letra = rand() % 26 + 65; printf("%d (%c)\n",letra,letra); } system("pause"); return 0; } 67 84 72 65 68 73 87 78 82 85 (C) (T) (H) (A) (D) (I) (W) (N) (R) (U)

Exerccio 4.36 Escrever um programa C que solicite ao usurio a digitao de dois nmeros inteiros quaisquer A e B em tempo de execuo. O programa deve gerar e exibir na tela 10 nmeros inteiros aleatrios no intervalo [A, B]. Exerccio 4.37 Escrever um programa C para gerar e exibir na tela 20 nmeros de ponto utuante no intervalo 0.00, 0.99]. Os nmeros gerados devem ser exibidos com dois dgitos decimais.

4.7. NMEROS PSEUDOALEATRIOS

95

Exerccio 4.38 Escrever um programa C que simule o lanamento de uma moeda 1000 vezes e que exiba o nmero de ocorrncias de cara e de coroa. Exerccio 4.39 Escrever um programa C solicite ao usurio a digitao de um nmero inteiro no intervalo [0, 32767]. Calcular e exibir na tela quantos nmeros pseudoaleatrios necessitam ser gerados at coincidir com o valor informado pelo usurio. Exerccio 4.40 Escrever um pequeno jogo de azar em C. O usurio deve tentar acertar um nmero inteiro pseudoaleatrio escolhido pelo programa no intervalo [1, 100]. O usurio deve digitar um novo palpite at acertar. Ao nal, o programa deve informar quantos palpites o usurio digitou. Nota: nesse caso, o nmero mximo de palpites at o acerto no deve ultrapassar 7.

96

CAPTULO 4. ESTRUTURAS DE REPETIO

Captulo 5 Estruturas Homogneas


A mente que se abre a uma nova ideia jamais voltara ao seu tamanho original Albert Einstein

At o momento, todas as variveis utilizadas nos programas-fonte escritos em linguagem C receberam apenas um contedo por vez. Assim, em uma varivel do tipo int, no foi possvel alocar ao mesmo tempo dois valores inteiros diferentes. Entretanto, em muitos algoritmos computacionais necessrio empregar estruturas capazes de armazenar mais de um valor do mesmo tipo de dado em uma nica varivel de memria. Na linguagem C, uma estrutura homognea tambm chamada array permite denir uma varivel que atende a esse propsito. Teoricamente, possvel denir e manipular estruturas homogneas de qualquer dimenso. Na prtica, porm, a maioria das aplicaes requer arrays de uma ou duas dimenses apenas.

5.1 Estruturas Homogneas Unidimensionais


Uma estrutura homognea unidimensional tambm chamada vetor possui uma nica dimenso. A Figura 5.1 ilustra a representao de um vetor na memria do computador. Na Figura 5.1, a estrutura homognea compe-se de 10 elementos que ocupam posies contguas de memria. Cada elemento do vetor acessado atravs de um ndice ou subscrito. Na linguagem C, o ndice do primeiro elemento de um array sempre igual a 0. Se um vetor declarado como sendo de um tipo inteiro, por exemplo int, 97

98

CAPTULO 5. ESTRUTURAS HOMOGNEAS

Figura 5.1: Representao de um vetor na memria isso implica dizer que todos os elementos devero armazenar valores int. Por isso a estrutura chamada homognea. Se a Figura 5.1 for declarada como int, todos os elementos devero receber valores inteiros.

5.1.1

Declarao de um Array

Para declarar um array em C deve-se informar o tipo primitivo a ser armazenado nos elementos do vetor, seguido do nome da varivel e do tamanho da estrutura homognea informado entre colchetes. Por exemplo,int var[10]; dene uma varivel do tipo array de inteiros de tamanho 10 cujo nome var. O Exemplo 5.1 apresenta um programa C que declara um array unidimensional, atribui valor a dois elementos e exibe o contedo desses elementos do vetor na sada padro. Exemplo 5.1 Programa C que declara, inicializa e exibe o contedo de dois elementos de um array de tamanho 10. #include <stdio.h> int main(void) { int vet[10]; // Vetor de inteiros de tamanho 10 vet[0] = 45; // Atribui o valor 45 ao elemento de ndice 0 do vetor vet[4] = 28; // Atribui o valor 28 ao elemento de ndice 0 do vetor printf("%d\n",vet[0]); printf("%d\n",vet[4]); system("pause"); return 0; } A Figura 5.2 apresenta o contedo do vetor vet declarado no Exemplo 5.1 aps a execuo dos comandos de atribuio presentes no cdigo-fonte. Pode-se observar que o acesso a um determinado elemento do vetor se d atravs do respectivo ndice. Essa regra vale tanto para a atribuio de valor ao

5.1. ESTRUTURAS HOMOGNEAS UNIDIMENSIONAIS

99

Figura 5.2: Contedo do vetor vet na memria elemento quanto para retornar o contedo do elemento, conforme apresentado no Exemplo 5.1.

5.1.2 Arrays e Comandos de Repetio


O emprego de comandos de repetio muito eciente para acessar os elementos de um vetor, seja para atribuio de valor ou para obter o contedo armazenado em cada elemento. Em geral, a varivel de controle do lao usada como ndice para acessar os elementos do vetor. O Exemplo 5.2 ilustra a manipulao de uma estrutura homognea unidimensional a partir de um lao for. Exemplo 5.2 programa C que cria um vetor de inteiros de tamanho 10 e que inicializa cada elemento com um valor inteiro fornecido pelo usurio em tempo de execuo. #include <stdio.h> int main(void) { int i; int vet[10]; for (i = 0; i < 10; i++) { printf("Valor para o indice %d do vetor: ", i); scanf("%d",&vet[i]); } printf("\nConteudo do vetor:\n"); for (i = 0; i < 10; i++) printf("%4d",vet[i]); printf("\n"); system("pause"); return 0; } Valor para o indice 0 do vetor: 5 Valor para o indice 1 do vetor: 6

100 Valor Valor Valor Valor Valor Valor Valor Valor para para para para para para para para o o o o o o o o indice indice indice indice indice indice indice indice 2 3 4 5 6 7 8 9 do do do do do do do do

CAPTULO 5. ESTRUTURAS HOMOGNEAS vetor: vetor: vetor: vetor: vetor: vetor: vetor: vetor: 8 9 2 4 5 6 7 0

Conteudo do vetor: 5 6 8 9 2

Exerccio 5.1 Escrever um programa C para criar um vetor de float de tamanho 8 e inicializar cada elemento com um valor fornecido pelo usurio em tempo de execuo. Exerccio 5.2 Escrever um programa C para criar um vetor de caracteres de tamanho 12 e inicializar cada elemento com uma letra fornecida pelo usurio em tempo de execuo. Caso o usurio digite um caractere invlido, o elemento deve ser preenchido com um asterisco. Exerccio 5.3 Escrever um programa C para criar um vetor de inteiros de tamanho 10 e inicializar cada elemento com um valor no intervalo [1, 10] fornecido pelo usurio em tempo de execuo. Caso o usurio digite um nmero inteiro fora do intervalo, deve ser solicitado a digitar novamente. Esse processo deve se repetir at que seja fornecido um valor vlido. No necessariamente uma estrutura homognea deve ser inicializada a partir da ao do usurio. O Exemplo 5.3 apresenta um algoritmo que atribui valores a um vetor a partir do prprio ndice. Exemplo 5.3 Programa C que cria um vetor de inteiros de tamanho 10 e que inicializa cada elemento com o valor do respectivo ndice. #include <stdio.h> int main(void) { int i; int vet[10]; for (i = 0; i < 10; i++) vet[i] = i;

5.1. ESTRUTURAS HOMOGNEAS UNIDIMENSIONAIS printf("Conteudo do vetor: "); for (i = 0; i < 10; i++) printf("%4d",vet[i]); printf("\n"); system("pause"); return 0; } Conteudo do vetor: 0 1 2 3 4 5 6 7 8 9

101

Exerccio 5.4 Escrever um programa C para criar um vetor de inteiros de tamanho 15, inicializar cada elemento com nmeros crescentes e sequenciais a partir de 10 e exibir o contedo do vetor na sada padro. Exerccio 5.5 Escrever um programa C para criar um vetor de inteiros de tamanho 10, inicializar cada elemento com nmeros crescentes mpares a partir de 1 e exibir o contedo do vetor na sada padro. Exerccio 5.6 Escrever um programa C para criar um vetor de inteiros de tamanho 18, inicializar cada elemento de forma que o contedo do elemento seguinte seja igual ao contedo do elemento anterior adicionado de 2. O contedo do primeiro elemento do vetor deve ser fornecido pelo usurio em tempo de execuo. Exibir o contedo do vetor na sada padro. Exerccio 5.7 Escrever um programa C para criar um vetor de inteiros de tamanho 12, inicializar cada elemento com nmeros decrescentes mltiplos de 3 a partir de 90 e exibir o contedo do vetor na sada padro.

5.1.3 Diretiva #define


A diretiva para o pr-processador C denominada #define permite denir constantes simblicas e que sero substitudas no cdigo-fonte durante a compilao. Com o uso desta diretiva torna-se mais simples manter o cdigo envolvendo constantes correto. Ela tambm simplica a compreenso do cdigo ao usar nomes simblicos que indicam o signicado das constantes denidas. No caso de estruturas homogneas, recomendado o uso de diretivas #define para se especicar o tamanho, ou seja, o nmero de elementos do array. A vantagem em se usar constantes simblicas que qualquer modicao nessas denies por exemplo, mudar o tamanho do array de 100 para 120 elementos

102

CAPTULO 5. ESTRUTURAS HOMOGNEAS

pode ser realizada em um nico local. O restante do cdigo permanece inalterado (Exemplo 5.4). Exemplo 5.4 Programa C que cria um vetor de inteiros de tamanho 10 e que inicializa cada elemento com o valor do respectivo ndice. #include <stdio.h> #define SIZE 10 int main(void) { int i; int vet[SIZE]; for (i = 0; i < SIZE; i++) vet[i] = i; printf("Conteudo do vetor: "); for (i = 0; i < SIZE; i++) printf("%4d",vet[i]); printf("\n"); system("pause"); return 0; } Conteudo do vetor: 0 1 2 3 4 5 6 7 8 9

5.1.4

Atribuio de Valor na Declarao do Array

O contedo de um ou mais elementos de um array pode ser atribudo no momento da declarao da estrutura homognea. Nesse caso, os valores devem ser fornecidos entre parnteses e separados por vrgula (Exemplo 5.5). Exemplo 5.5 Programa C que cria um vetor de inteiros de tamanho 10 e que inicializa cada elemento na declarao do array. #include <stdio.h> #define SIZE 10 int main(void) { int i; int vet[SIZE] = {2, 5, 7, 9, 0, -1, 6, 8, -2, 4}; printf("Conteudo do vetor: "); for (i = 0; i < SIZE; i++) printf("%4d",vet[i]);

5.1. ESTRUTURAS HOMOGNEAS UNIDIMENSIONAIS printf("\n"); system("pause"); return 0; } Conteudo do vetor: 2 5 7 9 0 -1 6 8 -2 4

103

Embora no seja uma prtica recomendvel, possvel incubir o prprio compilador C em determinar o tamanho do array a partir do nmero de elementos atribudos na declarao, conforme apresentado no Exemplo 5.6. Exemplo 5.6 Programa C que cria um vetor de inteiros de tamanho no declarado e que inicializa cada elemento na declarao do array. #include <stdio.h> #define SIZE 10 int main(void) { int i; int vet[] = {2, 5, 7, 9, 0, -1, 6, 8, -2, 4}; printf("Conteudo do vetor: "); for (i = 0; i < SIZE; i++) printf("%4d",vet[i]); printf("\n"); system("pause"); return 0; } Conteudo do vetor: 2 5 7 9 0 -1 6 8 -2 4

No necessrio atribuir valor a todos os elementos de um array na declarao, conforme pode ser observado no Exemplo 5.7. Os elementos que no forem explicitamente inicializados recebem o valor 0. Exemplo 5.7 Programa C que cria um vetor de inteiros de tamanho 10 e que inicializa os 5 primeiros elementos na declarao do array. #include <stdio.h> #define SIZE 10 int main(void) { int i;

104

CAPTULO 5. ESTRUTURAS HOMOGNEAS int vet[SIZE] = {-2, 3, 4, -1, 8}; printf("Conteudo do vetor: "); for (i = 0; i < SIZE; i++) printf("%4d", vet[i]); printf("\n"); system("pause"); return 0;

} Conteudo do vetor: -2 3 4 -1 8 0 0 0 0 0

Exerccio 5.8 Escrever um programa C para criar um vetor de inteiros de tamanho 10, inicializar cada elemento com 0 (na declarao) e exibir o contedo do vetor na sada padro. Exerccio 5.9 Escrever um programa C para criar um vetor de inteiros de tamanho 10 e inicializar cada elemento com valores inteiros no intervalo [0, 9] (na declarao) e exibir o contedo do array na sada padro. Em seguida, multiplicar por 2 o contedo de cada elemento e exibir novamente o vetor na sada padro.

5.1.5

Arrays e Nmeros Pseudoaleatrios

Nmeros pseudoaleatrios representam uma forma conveniente de atribuir valor aos elementos de uma estrutura homognea. O Exemplo 5.8 apresenta um programa C que utiliza nmeros randmicos para atribuir valor a um array. Exemplo 5.8 Programa C que atribui valor a um array de inteiros de tamanho 10 a partir de nmeros pseudoaleatrios no intervalo [0, 32767]. #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 10 int main(void) { srand(time(0)); int i; int vet[SIZE]; printf("Conteudo do vetor:\n"); for (i = 0; i < SIZE; i++) { vet[i] = rand();

5.1. ESTRUTURAS HOMOGNEAS UNIDIMENSIONAIS printf("%8d", vet[i]); } printf("\n"); system("pause"); return 0; } Conteudo do vetor: 19047 28042 11130

105

203

17329

10838

2698

29696

20744

31173

Exerccio 5.10 Escrever um programa C para criar um vetor de inteiros de tamanho 20 cujo contedo seja nmeros pseudoaleatrios no intervalo [0, 9]. Exerccio 5.11 Escrever um programa C para criar e exibir na sada padro um vetor de inteiros de tamanho 20 cujo contedo seja nmeros pseudoaleatrios no intervalo [0, 99]. Exibir na sada padro o ndice correspondente ao elemento de menor valor. Exerccio 5.12 Escrever um programa C para criar e exibir na sada padro um vetor de inteiros de tamanho 50 cujo contedo seja nmeros pseudoaleatrios no intervalo [0, 9]. Exibir na sada padro a soma dos elementos do vetor. Exerccio 5.13 Escrever um programa C para criar e exibir na sada padro dois vetores de inteiros A e B de tamanho 20 cujo contedo sejam nmeros pseudoaleatrios no intervalo [0, 99]. Calcular e exibir na sada padro o vetor soma C dado por C = A + B. Exerccio 5.14 Escrever um programa C para criar e exibir na sada padro um vetor de caracteres A de tamanho 15 cujo contedo sejam letras maisculas geradas aleatoriamente. Gerar e exibir na sada padro um vetor de caracteres B cujo contedo seja idntico ao vetor A porm com letras minsculas. Exerccio 5.15 Escrever um programa C para criar e exibir na sada padro um vetor de inteiros de tamanho 20 cujo contedo seja nmeros pseudoaleatrios no intervalo [0, 99]. Calcular e exibir na sada padro o total de elementos cujo contedo seja nmeros pares e o total de elementos cujo contedo seja nmeros mpares. Exerccio 5.16 Escrever um programa C para criar e exibir na sada padro dois vetores A e B de float de tamanho 10 cujo contedo seja nmeros randmicos no intervalo [0.00, 1.00]. O programa deve concatenar os dois vetores formando um novo vetor C de 20 elementos, na forma A[0], A[1], . . . , A[9], B[0], B[1], . . . , B[9]. Exibir na sada padro o vetor resultante.

106

CAPTULO 5. ESTRUTURAS HOMOGNEAS

Exerccio 5.17 Escrever um programa C para criar e exibir na sada padro dois vetores A e B de oat de tamanho 10 cujo contedo seja nmeros randmicos no intervalo [0.00, 1.00]. O programa deve intercalar os dois vetores formando um novo vetor C de 20 elementos, na forma A[0], B[0], A[1], B[1], . . . , A[9], B[9]. Exibir na sada padro o vetor resultante. Exerccio 5.18 Escrever um programa C para criar e exibir na sada padro dois vetores A e B de inteiros de tamanho 12 cujo contedo corresponda a nmeros randmicos no intervalo [0, 999]. O programa deve localizar e exibir na sada padro os nmeros gerados que so comuns aos dois vetores. Exerccio 5.19 Escrever um programa C para criar e exibir na sada padro um vetor A de inteiros de tamanho 20 cujo contedo corresponda a nmeros randmicos no intervalo [100, 100]. Em seguida, o programa deve criar dois novos vetores B e C. B deve conter os nmeros < 0 e C deve conter os nmeros 0. Por m, o programa deve exibir na sada padro os vetores B e C gerados. Exerccio 5.20 Escrever um programa C para criar e exibir na sada padro um vetor A de inteiros de tamanho 40 cujo contedo corresponda a nmeros randmicos no intervalo [0, 99]. O programa deve gerar e exibir na sada padro um novo vetor A excluindo todas as ocorrncias de nmeros repetidos do vetor A. Por exemplo, se o vetor A comear por 45, 56, 45, 3, . . . o vetor B comear por 45, 56, 3, . . . Exerccio 5.21 Escrever um programa C que simule o lanamento de um dado 1000 vezes e que exiba na sada padro o nmero de ocorrncias de cada face do dado.

5.2

Estruturas Homogneas Bidimensionais

Uma estrutura homognea bidimensional tambm chamada matriz possui duas dimenses, representadas por linhas e colunas. A Figura 5.3 ilustra a representao de uma matriz na memria do computador. A estrutura homognea bidimensional representada na Figura 5.3 possui dimenso 55, ou seja, 5 linhas por 5 colunas. Observe que na linguagem C os ndices das linhas e das colunas inicia-se obrigatoriamente pelo valor 0. Assim, o nmero 5 em destaque na Figura 5.3 corresponde ao contedo do elemento da matriz de ndices 1 para linha e 2 para coluna. Na sintaxe da linguagem C a representao em memria da matriz representada na Figura 5.3 equivalente a int vet[5][5]; onde os valores entre colchetes

5.2. ESTRUTURAS HOMOGNEAS BIDIMENSIONAIS

107

Figura 5.3: Representao de uma matriz na memria correspondem ao nmero de linhas e de colunas da estrutura homognea bidimensional. Para acessar o elemento em destaque na Figura 5.3 necessrio informar o nome da matriz seguido dos ndices da linha e da coluna entre colchetes. Por exemplo, o comando mat[1][2] = 5; atribui o valor 5 para o elemento da matriz de ndices 1 (linha) e 2 (coluna). Observe que os ndices correspondentes linha e coluna so sempre nmeros inteiros. Uma estrutura homognea bidimensional que possui igual nmero de linhas e de colunas chamada de matriz quadrada. A estrutura homognea bidimensional representada na Figura 5.3 uma matriz quadrada de ordem 5.

5.2.1 Percorrimento de Matriz em C


Para percorrer uma matriz em C so necessrias duas estruturas de lao normalmente utiliza-se o comando for uma para o controle de linhas e outra para o controle de colunas. O Exemplo 5.9 apresenta um programa C que utiliza nmeros randmicos para atribuir valor aos elementos de uma matriz quadrada. Exemplo 5.9 Programa C que atribui valor aos elementos de uma matriz quadrada de ordem 5 com nmeros inteiros aleatrios no intervalo [0, 9]. #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 5 int main(void) { srand(time(0));

108

CAPTULO 5. ESTRUTURAS HOMOGNEAS int i; // ndice para linhas int j; // ndice para colunas int mat[SIZE][SIZE]; printf("Conteudo da matriz:\n"); for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { mat[i][j] = rand() % 10; printf("%4d",mat[i][j]); } printf("\n"); } system("pause"); return 0;

} Conteudo da matriz: 5 6 7 0 0 5 0 4 0 5 8 5 2 6 1 6 1 1 5 9 9 3 5 8 3

5.2.2

Inicializao de Matrizes

De forma semelhante aos vetores em C, uma matriz pode ser inicializada ao ser declarada. O Exemplo 5.10 apresenta um programa C que declara e inicializa os elementos de uma matriz quadrada de ordem 3. Observe que os elementos de cada linha devem ser delimitados por chaves. Exemplo 5.10 Programa C que declara e atribui valor aos elementos de uma matriz quadrada de ordem 3. #include <stdio.h> #define SIZE 3 int main(void) { int i; // ndice para linhas int j; // ndice para colunas int mat[SIZE][SIZE] = {{1, 4, 4},{5, 7, 9},{8, 2, 3}}; printf("Conteudo da matriz:\n"); for (i = 0, j= 0; i < SIZE; i++, j++) {

5.2. ESTRUTURAS HOMOGNEAS BIDIMENSIONAIS for (j = 0; j < SIZE; j++) printf("%4d",mat[i][j]); printf("\n"); } system("pause"); return 0; } Conteudo da matriz: 1 4 4 5 7 9 8 2 3

109

5.2.3 Atribuio de Valor aos Elementos de uma Matriz


Os elementos de uma matriz tambm podem ser fornecidos pelo usurio em tempo de execuo. O Exemplo 5.11 apresenta um programa C que solicita ao usurio a digitao do contedo para os elementos de uma estrutura homognea bidimensional. Exemplo 5.11 Programa C que solicita ao usurio a digitao em tempo de execuo do contedo para os elementos de uma matriz de nmeros reais de ordem 2 3. #include <stdio.h> int main(void) { int i; // ndice para linhas int j; // ndice para colunas float mat[2][3]; printf("Forneca os valores para a matriz:\n"); for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) { printf("[%d][%d] ",i,j); scanf("%f",&mat[i][j]); } } printf("\nConteudo da matriz:\n"); for (i = 0; i < 2; i++) { for (j = 0; j < 3; j++) printf("%8.2f",mat[i][j]); printf("\n");

110 } system("pause"); return 0; }

CAPTULO 5. ESTRUTURAS HOMOGNEAS

Forneca os valores para a matriz: [0][0] 4 [0][1] 5 [0][2] 1 [1][0] 8 [1][1] 5 [1][2] 8 Conteudo da matriz: 4.00 5.00 1.00 8.00 5.00 8.00 Exerccio 5.22 Escrever um programa C que inicialize randomicamente os elementos de uma matriz quadrada de ordem 10 de caracteres no intervalo [A, Z]. Exibir o contedo da matriz na sada padro. Exerccio 5.23 Escrever um programa C que inicialize randomicamente os elementos de uma matriz quadrada de ordem 8 de nmeros reais no intervalo [0.0, 9.9]. Exibir o contedo da matriz na sada padro. Exerccio 5.24 Escrever um programa C que inicialize randomicamente os elementos de uma matriz de ordem 5 10 de inteiros no intervalo [0, 9]. Exibir na sada padro a soma dos elementos da matriz gerada. Exerccio 5.25 Escrever um programa C que inicialize randomicamente os elementos de uma matriz quadrada de ordem 10 de inteiros no intervalo [0, 999]. Exibir na sada padro o ndice e o valor correspondente ao maior elemento da matriz. Exerccio 5.26 Escrever um programa C que inicialize randomicamente os elementos de uma matriz quadrada de ordem 10 de inteiros no intervalo [0, 99]. Solicitar ao usurio, em tempo de execuo, a digitao de um nmero inteiro tambm no intervalo [0, 99]. Vericar se o nmero digitado est presente na matriz. Exerccio 5.27 Escrever um programa C que inicialize randomicamente os elementos de duas matriz quadradas A e B de ordem 5 de inteiros no intervalo [0, 9]. Calcular e apresentar na sada padro a matriz soma C das matrizes geradas C = A + B.

5.2. ESTRUTURAS HOMOGNEAS BIDIMENSIONAIS

111

Exerccio 5.28 Uma matriz identidade uma matriz quadrada que possui todos os membros da diagonal principal iguais a 1. Todos os demais elementos tm contedo igual a 0. Escrever um programa C que gere e apresente na sada padro uma matriz identidade de ordem 8. Exerccio 5.29 Escrever um programa C que gere e apresente na sada padro uma matriz quadrada de ordem 8 cujos elementos da diagonal secundria possuem nmeros inteiros aleatrios no intervalo [1, 9] e os demais elementos da matriz possuem valor zero. Exerccio 5.30 Uma matriz dita triangular superior quando somente os elementos acima e na diagonal principal so diferentes de 0. Escrever um programa C que gere e apresente na sada padro uma matriz triangular superior de ordem 8 cujo contedo so nmeros aleatrios no intervalo [1, 99]. Exerccio 5.31 Escrever um programa C que inicialize randomicamente os elementos de uma matriz de ordem 5 10 de inteiros no intervalo [0, 9]. Gerar e apresentar na sada padro o vetor soma de cada linha da matriz gerada. Exerccio 5.32 Escrever um programa C que inicialize randomicamente os elementos de uma matriz quadrada de ordem 8 de inteiros no intervalo [0, 99]. Apresentar na sada padro a matriz transposta. Exerccio 5.33 Escrever um programa C para inicializar uma matriz quadrada de ordem 12 com todos os valores iguais a i + j, onde i o ndice correspondente linha e j o ndice correspondente coluna. Em seguida, exibir a matriz na sada padro. Exerccio 5.34 Considere uma matriz quadrada de ordem 10 cujos elementos so inteiros no intervalo [0, 99] gerados randomicamente. Escrever um programa C para trocar todos os nmeros pares por 0 e todos os nmeros mpares por 1. Exibir a matriz resultante na sada padro. Exerccio 5.35 Matriz esparsas so aquelas que possuem a maioria dos elementos com valor 0. Escreva um programa C para gerar e apresentar na sada padro uma matriz quadrada de ordem 12 cujo contedo corresponda a 0 e 1. Para cada ndice, considere a possibilidade de 1/6 para o preenchimento com o valor 1 e 5/6 para o preenchimento com o valor 0. Exiba a matriz gerada na sada padro.

112

CAPTULO 5. ESTRUTURAS HOMOGNEAS

Exerccio 5.36 Uma matriz A dita simtrica se At = A, ou seja, igual a sua prpria matriz transposta. Escreva um programa C para gerar e apresentar na sada padro uma matriz quadrada simtrica de ordem 8 cujos elementos so nmeros inteiros no intervalo [1, 25] gerados randomicamente.

Captulo 6 Cadeias de Caracteres


A mente que se abre a uma nova ideia jamais voltara ao seu tamanho original Albert Einstein

Cadeias de caracteres ou strings so estruturas de dados utilizadas para a manipulao de sequncias de caracteres. Existem muitas aplicaes em Algoritmos que empregam cadeias de caracteres. Conforme visto a partir do captulo 2, uma constante do tipo cadeira de caracteres delimitada por aspas duplas. Assim, "ALGORITMO" representa uma cadeia de caracteres vlida em C. Entretanto, ainda no foi apresentado como denir variveis de memria do tipo string ou como ler cadeias de caracteres a partir da entrada padro. Esse assunto ser discutido nesse captulo.

6.1 Cadeias de Caracteres em C


Na linguagem C, cadeias de caracteres so representadas por vetores do tipo char terminadas obrigatoriamente pelo caractere nulo ('\0' na tabela ASCII). Portanto, para armazenar uma cadeia de caracteres na memria, deve-se reservar uma posio adicional no vetor para o caractere de m da cadeia. A Figura 6.1 ilustra a representao de uma cadeia de caracteres na memria do computador. O Exemplo 6.1 ilustra a representao de uma cadeia de caracteres. Como queremos representar a palavra ALGORITMO, composta por 9 caracteres, declaramos um vetor com dimenso 10 (um elemento adicional para armazenarmos o caractere nulo no nal da cadeia). O programa preenche cada um dos elementos do vetor, incluindo o caractere '\0' e exibe a string na sada padro.

113

114

CAPTULO 6. CADEIAS DE CARACTERES

Figura 6.1: Representao de uma cadeia de caracteres na memria em C Exemplo 6.1 Programa C que declara uma cadeia de caracteres e atribui valor a cada elemento separadamente. #include <stdio.h> int main(void) { char string[10]; string[0] = 'A'; string[1] = 'L'; string[2] = 'G'; string[3] = 'O'; string[4] = 'R'; string[5] = 'I'; string[6] = 'T'; string[7] = 'M'; string[8] = 'O'; string[9] = '\0'; printf("%s\n",string); system("pause"); return 0; } ALGORITMO O especicador de formato %s da funo printf permite exibir na sada padro uma cadeia de caracteres. A funo printf recebe um vetor de char e exibe elemento por elemento at encontrar o caractere nulo. Ateno: se o caractere '\0' no for colocado ao nal da cadeia de caracteres, a sada na tela pode ser executada de forma incorreta, pois no possvel localizar o identicador de m de string. Uma vez que as cadeias de caracteres so representadas atravs de vetores, possvel reescrever o Exemplo 6.1 utilizando-se a inicializao dos elementos conforme apresentado na declarao de um vetor de char (Exemplo 6.2).

6.1. CADEIAS DE CARACTERES EM C

115

Exemplo 6.2 Programa C que declara e inicializa o contedo de uma cadeia de caracteres. #include <stdio.h> int main(void) { char string[10] = {'A','L','G','O','R','I','T','M','O','\0'}; printf("%s\n",string); system("pause"); return 0; } ALGORITMO A inicializao de cadeias de caracteres nas formas apresentadas nos Exemplos 6.1 e 6.2 no muito prtica. Entretanto, a linguagem C permite que o contedo de strings possa ser atribudo escrevendo-se os caracteres entre aspas duplas. Nesse caso, o caractere nulo representado implicitamente. O Exemplo 6.3 ilustra a declarao e inicializao de cadeias de caracteres utilizando-se essa abordagem. Exemplo 6.3 Programa C que atribui valor a uma cadeia de caracteres na memria. #include <stdio.h> int main(void) { char string[10] = "ALGORITMO"; printf("%s\n",string); system("pause"); return 0; } ALGORITMO Nesse caso, no necessrio tambm declarar o tamanho do vetor (Exemplo 6.4). Ao atribuir valor ao vetor de char, o tamanho determinado implicitamente pelo compilador da linguagem C. Exemplo 6.4 Programa C que atribui valor a uma cadeia de caracteres cujo tamanho denido implicitamente. #include <stdio.h> int main(void) {

116

CAPTULO 6. CADEIAS DE CARACTERES char string[] = "ALGORITMO"; printf("%s\n",string); system("pause"); return 0;

} ALGORITMO No Exemplo 6.4 a varivel string automaticamente dimensionada e inicializada com 10 elementos. Para ilustrar a inicializao de cadeias de caracteres, considere as seguintes declaraes: char char char char str1[] = ""; str2[] = "ALGORITMO"; str3[81]; str4[81] = "ALGORITMO";

Nessas declaraes, a varivel str1 armazena uma cadeia de caracteres vazia, representada por um vetor com um nico elemento, o caractere '\0'. A varivel str2 representa um vetor com 10 elementos. A varivel str3 representa uma cadeia de caracteres capaz de representar cadeias com at 80 caracteres, j que foi dimensionada com 81 elementos. Essa varivel, no entanto, no foi inicializada e seu contedo desconhecido (lixo de memria). A varivel str4 tambm foi dimensionada para armazenar cadeias com at 80 caracteres, mas apenas os dez primeiros elementos foram utilizados na declarao.

6.2

Entrada de cadeias de caracteres

Para capturar um caractere simples fornecido pelo usurio atravs da entrada padro utilizada a funo scanf com o especicador de formato %c (Exemplo 6.5). Exemplo 6.5 Programa C para entrada de dados do tipo caractere. #include <stdio.h> int main(void) { char ch; printf("Digite um caractere: "); scanf("%c",&ch); system("pause");

6.2. ENTRADA DE CADEIAS DE CARACTERES return 0; } Digite um caractere: A

117

Dessa forma, se o usurio digitar a letra A, por exemplo, o cdigo ASCII associado letra A ser armazenado na varivel ch. Vale ressaltar que, diferentemente dos especicadores %d e %f, o especicador de formato %c no pula os caracteres em branco. Portanto, se o usurio teclar um espao antes da letra A, o cdigo ASCII correspondente ao espao ser armazenado em ch e o caractere A ser capturado apenas em um prximo scanf. Se for necessrio ignorar todas as ocorrncias dos caracteres ' ', '\n' e '\t' que porventura antecederem o caractere que se deseja capturar, basta incluir um espao em branco no especicador de formato (Exemplo 6.6). Exemplo 6.6 Programa C para entrada de dados do tipo caractere que ignora ' ', '\n' e '\t'. #include <stdio.h> int main(void) { char ch; printf("Digite um caractere: "); scanf(" %c",&ch); printf("Voce digitou %c\n",ch); system("pause"); return 0; } Digite um caractere: <enter> A Voce digitou A O especicador de formato %s pode ser utilizado para a entrada de dados do tipo cadeia de caracteres em um scanf. No entanto, seu uso possui algumas restries. O especicador de formato %s termina a entrada de dados na ocorrncia de um ' ', '\n' ou '\t'. Considere o Exemplo 6.7 que solicita ao usurio a digitao do nome completo. Exemplo 6.7 Programa C para entrada de dados do tipo cadeia de caracteres com especicador de formato %s.

118

CAPTULO 6. CADEIAS DE CARACTERES

#include <stdio.h> int main(void) { char nome[81]; printf("Digite seu nome completo: "); scanf("%s",&nome); printf("Seu nome: %s\n",nome); system("pause"); return 0; } Digite seu nome completo: Wander Gaspar Seu nome: Wander Recomenda-se a entrada de dados do tipo string utilizando-se o especicador de formato %[], no qual listado entre os colchetes todos os caracteres que sero aceitos na leitura. Assim, por exemplo, o especicador de formato %[aeiou] l sequncias de vogais minsculas, isto , a leitura prossegue at se encontrar um caractere que no seja uma vogal em letras minsculas (Exemplo 6.8). Exemplo 6.8 Programa C para entrada de dados do tipo cadeia de caracteres com especicador de formato %[]. #include <stdio.h> int main(void) { char vogal[21]; printf("Digite uma sequencia de vogais minusculas: "); scanf("%[aeiou]",&vogal); printf("Vogais digitadas: %s\n",vogal); system("pause"); return 0; } Digite uma sequencia de vogais minusculas: aeouiae auie Vogais digitadas: aeouiae Se o primeiro caractere entre colchetes no especicador de formato %[] for o acento circunexo, tem-se o efeito inverso (negao). Por exemplo, o especicador de formato %[^aeiou] produz uma entrada de dados enquanto uma vogal no for encontrada. Essa construo permite capturar nomes compostos. Considere o Exemplo 6.9.

6.2. ENTRADA DE CADEIAS DE CARACTERES

119

Exemplo 6.9 Programa C para entrada de dados do tipo cadeia de caracteres com especicador de formato %[^]. #include <stdio.h> int main(void) { char nome[81]; printf("Digite seu nome completo: "); scanf(" %[^\n]",&nome); printf("Seu nome: %s\n",nome); system("pause"); return 0; } Digite seu nome completo: Wander Gaspar Seu nome: Wander Gaspar No Exemplo 6.9, o scanf l uma sequncia de caracteres enquanto no for encontrado um '\n'. Em termos prticos, captura-se a linha fornecida pelo usurio at que se tecle Enter. A incluso do espao no especicador de formato (antes do sinal %) garante que eventuais caracteres em branco que precedam o nome sejam descartados. Para concluir esse tpico, deve-se salientar que o especicador de formato %[^\n] do Exemplo 6.9 pode ser ainda aperfeioado. Se o usurio digitar uma sequncia com mais de 80 caracteres, estar invadindo um espao de memria no reservado (o vetor foi dimensionado com 81 elementos). Para evitar essa possvel invaso, possvel limitar o nmero mximo de caracteres que sero capturados incluindo-se essa informao no especicador de formato, conforme apresentado no Exemplo 6.10. Exemplo 6.10 Programa C para entrada de dados do tipo string com especicador de formato %[^] com limitao de caracteres. #include <stdio.h> int main(void) { char palavra[10]; printf("Digite uma palavra (mximo de 9 caracteres): "); scanf(" %9[^\n]",&palavra); printf("Palavra digitada: %s\n",palavra); system("pause"); return 0;

120 }

CAPTULO 6. CADEIAS DE CARACTERES

Digite uma palavra (mximo de 9 caracteres): ALGORITMOS Palavra digitada: ALGORITMO Exemplo 6.11 Programa C que retorna o nmero de caracteres em uma string fornecida pelo usurio em tempo de execuo. #include <stdio.h> int main(void) { char nome[81]; int tam = 0; printf("Digite seu nome: "); scanf(" %80[^\n]",&nome); while(nome[tam] != '\0') tam++; printf("Numero de caracteres em %s: %d\n",nome,tam); return 0; } Digite seu nome: WANDER GASPAR Numero de caracteres em WANDER GASPAR: 13 Exerccio 6.1 Escrever um programa C para substituir todos os espaos em branco de uma frase digitada pelo usurio em tempo de execuo por _. Exibir na sada padro a frase antes e depois de substitudos os espaos. Exerccio 6.2 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que exiba na sada padro uma palavra por linha. Exerccio 6.3 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que calcule e apresente na sada padro a quantidade de vogais. Exerccio 6.4 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio com todas as letras em minsculas e que substitua e apresente na sada padro a frase com a primeira letra de cada palavra substituda por sua equivalente maiscula.

6.3. CONVERSO DE CADEIAS DE CARACTERES EM TIPOS NUMRICOS121 Exerccio 6.5 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro a frase retirando-se todos os espaos em branco. Exerccio 6.6 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro a frase no sentido contrrio, ou seja, comeando pelo ltimo caractere. Exerccio 6.7 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro o total de palavras digitadas. Exerccio 6.8 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro a frase criptografada conforme a regra: ch = ch + 10. Exerccio 6.9 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro a frase descriptografada de acordo com a regra apresentada no exerccio anterior. Exerccio 6.10 Decifre o Cdigo Secreto (junho/2010) Escreva um programa C que solicite ao usurio a digitao de uma frase que deve conter at 80 caracteres. O programa deve decifrar o cdigo secreto formado pela primeira letra de cada palavra digitada. O cdigo deve ser exibido na tela em letras maisculas. Exemplo de execuo: Frase: Pode remar ou velejar amanha. Codigo: PROVA

6.3 Converso de Cadeias de Caracteres em Tipos Numricos


H situaes, como na entrada de dados, em que importante converter cadeias de caracteres em tipos numricos. A vantagem da entrada de dados sempre a partir de cadeias de caracteres consiste em evitar que o programa seja terminado caso o usurio digite um valor invlido para o tipo de dados esperado. A biblioteca padro stdlib.h dispe de funes para promover a converso de cadeias de caracteres para tipos numricos inteiros e de ponto utuante. Por exemplo, "123" pode ser convertido para um tipo inteiro com o valor 123.

122

CAPTULO 6. CADEIAS DE CARACTERES

A funo atoi() retorna um valor inteiro convertido a partir de uma string fornecida como argumento de entrada. A converso interrompida se um caractere invlido for encontrado. Se nenhum caractere for vlido ou se o primeiro caractere for invlido a funo retorna o valor 0 (zero). A Tabela 6.1 a seguir apresenta alguns exemplos de converso de cadeias de caracteres para inteiro. Tabela 6.1: Exemplos de converso de string para inteiro String Inteiro "157" 157 -1.6" -1 "+50x" 50 "um" 0 "x505" 0

Exemplo 6.12 Programa C que que solicita ao usurio a digitao de diversos valores inteiros e positivos e que retorna a soma dos valores vlidos. O ag qualquer valor negativo. #include<stdio.h> #include<stdlib.h> int main(void) { char num[11]; int val; int soma = 0; do { printf("Inteiro: "); scanf(" %10[^\n]",&num); val = atoi(num); if(val<0) break; soma+=val; } while(1); printf("Soma: %d\n",soma); system("pause"); return 0; }

6.3. CONVERSO DE CADEIAS DE CARACTERES EM TIPOS NUMRICOS123 Inteiro: 3 Inteiro: 3.6 Inteiro: -1 Soma: 6 A funo atof() retorna um valor numrico de ponto utuante convertido a partir de uma string fornecida como argumento de entrada. A converso interrompida se um caractere invlido for encontrado. Se nenhum caractere for vlido ou se o primeiro caractere for invlido a funo retorna o valor 0.000000. A Tabela 6.2 apresenta alguns exemplos de converso de cadeias de caracteres para double. Tabela 6.2: Exemplos de converso de string para ponto utuante String Ponto Flutuante "12" 12.000000 -0.123" -0.123000 "123E+3" 123000.000000 "123.1e-5" 0.001231 "x506" 0.000000

Exemplo 6.13 Programa C que solicita ao usurio a digitao de diversos valores reais e positivos e que retorna a soma dos valores vlidos. O ag qualquer valor negativo. #include<stdio.h> #include<stdlib.h> int main(void) { char num[16]; double val; double soma = 0; do { printf("Numero: "); scanf(" %15[^\n]",&num); val = atof(num); if(val<0) break; soma+=val; } while(1);

124

CAPTULO 6. CADEIAS DE CARACTERES printf("Soma: %.2f\n",soma); system("pause"); return 0;

} Numero: 3 Numero: 3.7 Numero: trs Numero: 1.5e0 Numero: -1 Soma: 8.20 Exerccio 6.11 Soma de Valores (junho/2010) Escreva um programa C que solicite ao usurio a digitao de diversos valores em tempo de execuo. A entrada de dados termina quando o usurio digitar um valor que corresponda ao nmero zero. O objetivo do programa consiste em calcular e exibir a soma dos valores numricos digitados. Mas cuidado, o problema no to simples assim! Observe que o usurio pode digitar caracteres que no correspondam a nmeros, ao ponto decimal ou ao sinal de negativo e que, obviamente, no podem ser somados. Exemplo de execuo: Valor: 10 Valor: -3A Valor: 6o. Valor: -1.5$$$ Valor: 0 Soma: 11.50

6.4

Funes de C para Cadeias de Caracteres

Uma vez que C manipula cadeias de caracteres a partir de vetores, a maioria dos procedimentos usuais como comparar strings e mover o contedo de uma string para outra requer o tratamento de ndices e comandos de lao. Entretanto, como alternativa para a realizao desses procedimentos, vrias funes teis para a manipulao de cadeias de caracteres esto disponveis na biblioteca padro string.h.

6.4.1

Cpia de Cadeias de Caracteres

A funo strcpy(string1,string2) permite copiar o contedo da cadeia de caracteres string2 para a cadeia de caracteres string1. importante observar que

6.4. FUNES DE C PARA CADEIAS DE CARACTERES

125

a funo no verica se h espao suciente em string1 para acomodar todo o contedo de string2. Portanto, esse tipo de vericao de compatibilidade deve ser executado pelo programador. Exemplo 6.14 Programa C que copia o contedo de uma cadeia de caracteres de uma varivel para outra usando a funo strcpy(). #include<stdio.h> #include<string.h> int main(void) { char string2[]="JUIZ DE FORA"; char string1[13]; if(sizeof(string1)>=sizeof(string2)) { strcpy(string1,string2); printf("%s\n",string1); } else printf("Erro.\n"); system("pause"); return 0; } JUIZ DE FORA Exemplo 6.15 Programa C que solicita ao usurio a digitao de uma sequncia de 5 caracteres e gera uma cadeia de caracteres onde a sequncia informada repetida 10 vezes. #include<stdio.h> #include<string.h> int main(void) { int i; char entrada[6]; char saida[51]; printf("Digite uma sequencia de 5 caracteres: "); scanf(" %5[^\n]",&entrada); for(i=0;i<10;i++) strcpy(saida+i*5,entrada); //Ateno!! saida[50] = '\0'; printf("%s\n",saida);

126 return 0; }

CAPTULO 6. CADEIAS DE CARACTERES

ABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCDEABCD A funo sizeof() recebe como argumento de entrada uma varivel qualquer e retorna o tamanho (nmero de bytes) alocados na memria para acomodar o contedo da varivel. A funo strncpy(string1,string2,n) permite copiar os n primeiros caracteres da cadeia string2 para a cadeia de caracteres string1. Tambm a funo strncpy() no verica se h espao suciente em string1 para acomodar o contedo de string2 a ser copiado. importante que a cadeia de caracteres de destino tenha um espao adicional para acomodar o marcador de m de string ('\0'). Exemplo 6.16 Programa C que copia parte do contedo de uma cadeia de caracteres de uma varivel para outra usando a funo strncpy(). #include<stdio.h> #include<string.h> int main(void) { char string2[]="WANDER GASPAR"; char string1[7]; strncpy(string1,string2,6); printf("%s\n",string1); system("pause"); return 0; } WANDER

6.4.2

Tamanho de Cadeias de Caracteres

A funo strlen() recebe como argumento de entrada uma cadeia de caracteres e retorna o tamanho (nmero de bytes) utilizados para acomodar a string na memria, sem considerar o espao para o marcador de m de string. Observe que o espao de fato utilizado por uma cadeia de caracteres pode ser menor que o espao reservado na memria, isto , eventualmente, o retorno da funo strlen() pode ser igual ou menor que o retorno da funo sizeof(). O Exemplo 6.17 ilustra a aplicao da funo strlen().

6.4. FUNES DE C PARA CADEIAS DE CARACTERES

127

Exemplo 6.17 Programa C que retorna o nmero de caracteres em uma string fornecida pelo usurio em tempo de execuo. #include <stdio.h> #include <string.h> int main(void) { char nome[81]; printf("Digite seu nome: "); scanf(" %80[^\n]",&nome); printf("Espaco alocado na memoria......: %d\n",sizeof(nome)); printf("Tamanho da cadeia de caracteres: %d\n",strlen(nome)); system("pause"); return 0; } Digite seu nome: WANDER GASPAR Espaco alocado na memoria......: 81 Tamanho da cadeia de caracteres: 13

6.4.3 Concatenao de Cadeias de Caracteres


A funo strcat(string1,string2) permite concatenar o contedo da cadeia de caracteres string2 para o m da cadeia de caracteres string1. Mais uma vez, responsabilidade do programador garantir que haja espao suciente em string1 para acomodar os caracteres concatenados. O Exemplo 6.18 ilustra a aplicao da funo strcat(). Exemplo 6.18 Programa C que processa a concatenao de cadeias de caracteres a partir da funo strcat(). #include <stdio.h> #include <string.h> int main(void) { char prenome[21]; char sobrenome[21]; char nome[41]="; printf("Digite seu prenome: "); scanf(" %20[^\n]",&prenome); printf("Digite seu sobrenome: "); scanf(" %20[^\n]",&sobrenome);

128

CAPTULO 6. CADEIAS DE CARACTERES strcat(nome,prenome); strcat(nome," "); strcat(nome,sobrenome); printf("Nome completo: %s\n",nome); system("pause"); return 0;

} Digite seu prenome: WANDER Digite seu sobrenome: GASPAR Nome completo: WANDER GASPAR A funo strncat(string1,string2,n) permite concatenar parte do contedo da cadeia de caracteres string2 para o m da cadeia de caracteres string1. Lembre-se que responsabilidade do programador garantir que haja espao suciente em string1 para acomodar os caracteres concatenados. O Exemplo 6.19 ilustra a aplicao da funo strncat(). Exemplo 6.19 Programa C que processa a concatenao de cadeias de caracteres a partir da funo strncat(). #include <stdio.h> #include <string.h> int main(void) { char prenome[21]; char sobrenome[21]; char nome[41]=""; printf("Digite seu prenome: "); scanf(" %20[^\n]",&prenome); printf("Digite seu sobrenome: "); scanf(" %20[^\n]",&sobrenome); strcat(nome,sobrenome); strcat(nome,", "); strncat(nome,prenome,1); strcat(nome,"."); printf("Nome: %s\n",nome); system("pause"); return 0; } Digite seu prenome: WANDER

6.4. FUNES DE C PARA CADEIAS DE CARACTERES Digite seu sobrenome: GASPAR Nome: GASPAR, W.

129

6.4.4 Comparao de Cadeias de Caracteres


A funo strcmp(string1,string2) permite comparar o contedo de duas cadeias de caracteres string1 e string2 e vericar qual delas maior ou se so iguais. O mecanismo de comparao empregado caractere a caractere, da esquerda para a direita, conforme apresentado na Figura 6.2.

Figura 6.2: Mecanismo de comparao da funo strcmp() A funo strcmp(string1,string2) retorna um nmero inteiro que pode ser: 0 (zero) caso as duas cadeias de caracteres sejam iguais; <0 (menor que zero) caso string1 seja menor que string2; >0 (maior que zero) caso string2 seja maior que string2. Para ser mais exato, o nmero inteiro retornado pela funo strcmp(string1, string2) corresponde diferena entre os cdigos ASCII dos caracteres onde foi detectado a primeira diferena mais esquerda na comparao. O Exemplo 6.20 ilustra a aplicao da funo strcmp(). Exemplo 6.20 Programa C que processa a comparao de cadeias de caracteres a partir da funo strcmp(). #include <stdio.h> #include <string.h>

130

CAPTULO 6. CADEIAS DE CARACTERES

int main(void) { char str1[6] = "Joao"; char str2[6] = "Joana"; printf("Diferenca: %d\n",strcmp(str1,str2)); system("pause"); return 0; } Diferenca: 1 A funo strncmp(string1,string2) permite comparar os n primeiros caracteres de duas cadeias string1 e string2 e vericar qual delas maior ou se so iguais. O mecanismo de comparao tambm empregado caractere a caractere, da esquerda para a direita, conforme apresentado anteriomente na Figura 6.2. O Exemplo 6.21 ilustra a aplicao da funo strcmp(). Exemplo 6.21 Programa C que processa a comparao de cadeias de caracteres a partir da funo strncmp(). #include <stdio.h> #include <string.h> int main(void) { char str1[6] = "Joao"; char str2[6] = "Joana"; printf("Diferenca: %d\n",strncmp(str1,str2,3)); system("pause"); return 0; } Diferenca: 0

6.4.5

Pesquisa em uma Cadeia de Caracteres

A funo strchr(string,char) verica se um determinado caractere char est contido em uma cadeia de caracteres string. Caso o caractere esteja contido na cadeia, a funo retorna o endereo de memria do caractere. Em caso contrrio retornado a palavra reservada NULL. O Exemplo 6.22 ilustra a aplicao da funo strchr(). Exemplo 6.22 Programa C que pesquisa por uma caractere em uma string a partir da funo strchr().

6.4. FUNES DE C PARA CADEIAS DE CARACTERES #include <stdio.h> #include <string.h> int main(void) { char str1[6] = "AEIOU"; char ch = 'I'; if(strchr(str1,ch)==NULL) printf("NAO\n"); else printf("SIM\n"); system("pause"); return 0; } SIM

131

Caso seja necessrio identicar o ndice da cadeia onde o caractere foi encontrado, torna-se necessrio empregar um recurso da linguagem C denominado ponteiro, que permite armazenar uma posio de memria. O Exemplo 6.23 apresenta um programa C que exibe na sada padro o ndice onde um determinado caractere encontra-se representado em uma cadeia. Um ponteiro declarado por um asterisco antecedido ao nome da varivel. A palavra reservada NULL signica que nenhum endereo de memria est armazenado no ponteiro. Para maiores detalhes sobre ponteiros em C consulte um livro avanado sobre a linguagem. Exemplo 6.23 Programa C que exibe o ndice de uma cadeia onde se encontra um caractere pesquisado a partir da funo strchr(). #include <stdio.h> #include <string.h> int main(void) { char str[6] = "AEIOU"; char ch = 'I'; char *pos = NULL; pos = strchr(str,ch); printf("%d\n",pos-str); return 0; } 2

132

CAPTULO 6. CADEIAS DE CARACTERES

A funo strstr(string1,str2) verica se uma determinada cadeia de caracteres str2 est contida em uma outra cadeia string1. Em caso positivo a funo retorna o endereo de memria do primeiro caractere da cadeia procurada. Em caso contrrio retornado a palavra reservada NULL. O Exemplo 6.24 ilustra a aplicao da funo strstr(). Exemplo 6.24 Programa C que exibe o ndice do primeiro caractere de uma cadeia pesquisada a partir da funo strstr(). #include <stdio.h> #include <string.h> int main(void) { char str1[6] = "AEIOU"; char str2[3] = "OU"; char *pos = NULL; pos = strstr(str1,str2); printf("%d\n",pos-str1); return 0; } 3 Exerccio 6.12 Escrever um programa C que receba na entrada padro duas palavras digitadas pelo usurio. O programa deve vericar se as palavras so iguais ou diferentes, independente dos caracteres estarem em letras minsculas ou maisculas. Exerccio 6.13 Escrever um programa C que receba na entrada padro uma frase digitada pelo usurio e que apresente na sada padro a quantidade de vezes que uma determinada palavra tambm fornecida pelo usurio se encontra presente na frase. Exerccio 6.14 Escrever um programa C que receba na entrada padro uma sequncia de 5 letras maisculas. O programa deve retornar o nmero de vezes necessrios para que seja gerado uma sequncia aleatria idntica.

6.5

Vetor de Cadeias de Caracteres

Em muitas aplicaes desejvel representar um vetor de cadeia de caracteres. Por exemplo, pode-se considerar uma aplicao que necessite armazenar os nomes de todos os alunos de uma turma em um vetor.

6.5. VETOR DE CADEIAS DE CARACTERES

133

Uma cadeia de caracteres representada por um vetor do tipo char. Para representar um vetor no qual cada elemento consiste em uma cadeia de caracteres necessrio ter um array bidimensional de char. Assumindo que nenhum nome de aluno ter mais de 80 caracteres e que o nmero mximo de alunos em uma turma 50, possvel declarar uma matriz para armazenar os nomes dos alunos com a seguinte sintaxe: char alunos[50][81]; Com essa varivel declarada, a1unos[i] acessa a cadeia de caracteres com o nome do (i+1)-simo aluno da turma e, consequentemente, alunos[i][j] acessa a (j+1)-sima letra do nome referenciado. Os Exemplos 6.25 e 6.26 ilustram a aplicao de vetores de cadeias de caracteres. Exemplo 6.25 Programa C que gera e exibe na sada padro um vetor de strings, cujo contedo fornecido pelo usurio em tempo de execuo. #include <stdio.h> int main(void) { char str[5][81]; int i; for(i = 0; i < 5; i++) { printf("Digite seu nome: "); scanf(" %80[^\n]",str[i]); } for(i = 0; i < 5; i++) printf("%s\n",str[i]); system("pause"); return 0; } Exemplo 6.26 Programa C que gera e exibe na sada padro um vetor de strings e que verica se uma determinada cadeia de caracteres informada pelo usurio na entrada padro est contida no vetor gerado. #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> int main(void) {

134

CAPTULO 6. CADEIAS DE CARACTERES srand(time(0)); char str[20][5]; char s[5]; int i, j; for(i = 0; i < 20; i++) { for(j = 0; j < 4; j++) str[i][j] = rand()%26+65; str[i][j] = '\0'; } for(i = 0; i < 20; i++) printf("%2d %s\n",i,str[i]); printf("Sequencia de 4 letras maiusculas: "); scanf(" %4[^\n]",s); for(i = 0; i < 20; i++) if(strcmp(str[i],s) == 0) printf("%d\n",i); system("pause"); return 0;

} Exerccio 6.15 Escrever um programa C que receba na entrada padro o nome e as notas de uma turma de N alunos, onde N fornecido pelo usurio. As notas devem estar no intervalo [0, 100]. Os nomes devem possuir at 30 caracteres. Exibir na sada padro a relao de nomes e notas classicados em ordem decrescente de nota. Exerccio 6.16 Gosto No Se Discute (junho/2010) Seu objetivo nessa questo consiste em gerar e exibir uma frase aleatria em uma nica linha na tela. A frase deve conter trs elementos: sujeito, verbo e predicado, nessa ordem. O sujeito deve ser escolhido randomicamente pelo programa entre 4 opes possveis: Pedro, Maria, Carlos e Ana. Analogamente, o verbo deve ser escolhido aleatoriamente pelo programa entre gosta de, no gosta de, adora e detesta. Por m, o predicado deve ser escolhido randomicamente pelo programa entre feijoada, futebol, samba e feriado. Exemplo de execuo: Ana detesta feriado. Exerccio 6.17 Quem Ganhou A Rifa? (junho/2010) Escreva um programa que simule o sorteio de uma rifa. Cada nmero no intervalo [1, 10] deve ser associado a um nome. Os nomes e respectivos nmeros devem ser exibidos na tela. Em seguida, o programa deve sortear aleatoriamente um nmero e apresentar o nome do

6.5. VETOR DE CADEIAS DE CARACTERES

135

respectivo vencedor na tela. Os 10 (dez) nomes podem ser digitados pelo usurio em tempo de execuo ou inseridos diretamente no cdigo fonte do programa. Considere cada nome com at 10 caracteres. Exemplo de execuo: [1] JOAO [2] ROSA [3] PEDRO [4] MARIA [5] ANTONIO [6] LUCAS [7] RITA [8] CARLOS [9] CLARA [10] MANUEL Sorteio: 7 Vencedor: RITA

136

CAPTULO 6. CADEIAS DE CARACTERES

Captulo 7 Funes
A mente que se abre a uma nova ideia jamais voltara ao seu tamanho original Albert Einstein

Para a construo de programas estruturados, sempre prefervel dividir as grandes tarefas de computao em tarefas menores e utilizar seus resultados parciais para compor o resultado nal desejado (CELES et al., 2004).

7.1 Modularizao
Modularizao uma tcnica de desenvolvimento de software que consiste em dividir um problema em diversas partes ou mdulos. Em C, os mdulos so implementados atravs do uso de funes. Alguns benefcios dessa estratgia: Evita que uma sequncia de comandos necessria em vrias partes do software tenha que ser reescrita; Divide o software em partes logicamente coerentes; Aumenta a legibilidade do cdigo-fonte; Facilita a manuteno do software. Exemplo 7.1 Funo que calcula e retorna o volume de um cilindro. Os argumentos so o raio da base e a altura do cilindro.

137

138 // cabealho da funo: float volumeCilindro(float r, float h) { // corpo da funo: const float PI = 3.1415926536; return (PI * r * r * h); }

CAPTULO 7. FUNES

A denio de uma funo consiste de um cabealho (ou declarao) e de um bloco de comandos. A declarao da funo deve especicar, nesta ordem: o tipo do valor de retorno (ou argumento de sada); o nome da funo; os tipos e nomes dos argumentos de entrada, especicados entre parnteses e separados por vrgulas. Deve existir tambm pelo menos um comando return no corpo de uma funo. O trmino da execuo ocorre ao se alcanar o comando return. Quando isso acontece, o uxo da execuo retorna para o ponto do programa onde a funo foi invocada. Na realidade, a execuo de um programa C sempre inicia a partir de uma funo principal, denominada main(). Portanto, o cdigo-fonte C, para ser executado aps a compilao, deve conter uma, e somente uma funo main(). Esta funo principal, por sua vez, pode chamar (ou invocar), uma ou mais funes, conforme apresentado no Exemplo 7.2). Exemplo 7.2 Programa C que solicita ao usurio a digitao na entrada padro do raio da base e da altura de um cilindro e que invoca a funo que calcula e retorna o volume do cilindro. #include <stdio.h> float volumeCilindro(float, float); int main(void) { float raio; float altura; float volume; printf("Informe o raio da base do cilindro:"); scanf("%f",&raio); printf("Informe a altura do cilindro:"); scanf("%f",&altura); volume = volumeCilindro(raio,altura); // chama a funo.

7.1. MODULARIZAO printf("Volume do cilindro: %.2f",volume); system("pause"); return 0; } float volumeCilindro(float r, float h) { const float PI = 3.1415926536; return (PI * r * r * h); }

139

Observe que, antes do cabealho da funo main(), necessrio incluir o prottipo das funes invocadas. O prottipo de uma funo semelhante declarao da funo porm, no necessrio especicar os nomes dos argumentos, apenas os tipos de dados. Como ocorre a execuo de um programa C contendo funes? A execuo inicia-se pela funo main(). Quando uma funo invocada, a execuo transferida e retorna aps o comando return ser alcanado. O m da execuo do programa acontece aps a execuo do comando return da funo principal main() (Figura 7.1).

Figura 7.1: Encadeamento entre funes durante a execuo de um programa C importante observar que no necessrio especicar o prottipo caso a funo seja declarada antes da funo principal main() (Exemplo 7.3). Entretanto, o emprego de prottipos recomendado por tratar-se de uma boa prtica de programao. Exemplo 7.3 Programa C que solicita ao usurio a digitao na entrada padro do raio da base e da altura de um cilindro e que invoca a funo que calcula e retorna o volume do cilindro (verso sem prottipo).

140

CAPTULO 7. FUNES

#include <stdio.h> float volumeCilindro(float r, float h) { const float PI = 3.1415926536; return (PI * r * r * h); } int main(void) { float raio; float altura; float volume; printf("Informe o raio da base do cilindro:"); scanf("%f",&raio); printf("Informe a altura do cilindro:"); scanf("%f",&altura); volume = volumeCilindro(raio,altura); printf("Volume do cilindro: %.2f",volume); system("pause"); return 0; }

7.2

Argumentos de Entrada e Tipos de Retorno

Uma funo em C pode ter um ou mais argumentos de entrada, fornecidos entre parnteses e separados por vrgulas, na declarao da prpria funo. Tambm possvel declarar uma funo que no tenha argumento de entrada. Nesse caso, o argumento declarado como void. O tipo de retorno ou argumento de sada de uma funo determina o tipo de dado que passado para o encadeamento do programa quando a funo termina a execuo. O tipo de retorno pode ser, inicialmente, qualquer um dos tipos bsicos da linguagem (int, float, double, char, etc.) ou void, caso a funo no retorne nenhum valor. O Exemplo 7.4 apresenta uma funo declarada pelo usurio cujo tipo de retorno void e cujo argumento de entrada tambm void. Isso signica que a funo no recebe nenhum argumento de entrada e tambm no retorna nenhum valor ao m da execuo. Exemplo 7.4 Funo para exibir uma linha de asteriscos na sada padro. #include <stdio.h> void linha(void); // Prottipo da funo.

7.2. ARGUMENTOS DE ENTRADA E TIPOS DE RETORNO int main(void) { linha(); // Invocao da Funo printf("CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA\n"); linha(); system("pause"); return 0; } void linha(void) { // Declarao da funo. int i; for(i=0;i<80;i++) printf("*"); printf("\n"); }

141

********************************************************************* CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA ********************************************************************* O Exemplo 7.5 apresenta uma funo declarada pelo usurio cujo tipo de retorno void e que possui um nico argumento de entrada cujo tipo inteiro. Observe que o argumento de entrada usado no corpo da funo para controlar o nmero de asteriscos a serem exibidos na sada padro. Em uma funo do tipo void opcional a incluso do comando return ao nal do corpo da funo. Exemplo 7.5 Funo para exibir uma linha com um nmero determinado de asteriscos na sada padro. #include <stdio.h> void linha(int); int main(void) { int num; printf("Numero de asteriscos: "); scanf("%d",&num); linha(num); printf("CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA\n"); linha(num); system("pause"); return 0; }

142 void linha(int n) { int i; for(i=0;i<n;i++) printf("*"); printf("\n"); return; } Numero de asteriscos: 41 ***************************************** CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA *****************************************

CAPTULO 7. FUNES

Pode-se observar a partir do 7.5 que o nome do argumento na funo no necessariamente deve ser igual ao nome da varivel na chamada da funo. Exerccio 7.1 Escreva uma funo que apresente na sada padro uma frase informada pelo usurio na entrada padro. A sada deve ser centralizada na linha. Considere que a frase digitada deve ter, no mximo, 80 caracteres. O Exemplo 7.6 apresenta uma funo cujo tipo de retorno void e que possui dois argumentos de entrada. O primeiro argumento int e o segundo char. Quando h mais de um argumento de entrada, a invocao da funo deve respeitar rigorosamente o nmero e o tipo de argumentos e tambm a ordem entre eles. Exemplo 7.6 Funo para exibir uma linha com um nmero determinado de caracteres na sada padro. O caractere informado pelo usurio na entrada padro. #include <stdio.h> void linha(int,char); int main(void) { int num; char car; printf("Numero de caracteres: "); scanf("%d",&num); printf("Caractere: "); scanf(" %c",&car); linha(num,car); printf("CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA\n"); linha(num,car);

7.2. ARGUMENTOS DE ENTRADA E TIPOS DE RETORNO system("pause"); return 0; } void linha(int n, char ch) { int i; for(i=0;i<n;i++) printf("%c",ch); printf("\n"); } Numero de caracteres: 41 Caractere: ----------------------------------------CENTRO DE ENSINO SUPERIOR DE JUIZ DE FORA -----------------------------------------

143

O Exemplo 7.7 apresenta uma funo cujo tipo de retorno int e que possui dois argumentos de entrada, ambos do tipo int. Observe que o valor retornado, do tipo inteiro, compatvel com o tipo de retorno esperado ao m da execuo da funo. Exemplo 7.7 Dene uma funo cujo valor de retorno o resto da diviso de dois nmeros inteiros fornecidos como argumentos de entrada. #include <stdio.h> int restoDivisao(int, int); int main(void) { int num1, num2, resto; printf("Digite o primeiro numero: "); scanf("%d",&num1); printf("Digite o segundo numero: "); scanf("%d",&num2); resto = restoDivisao(num1,num2); printf("Resto da divisao de %d por %d: %d\n",num1,num2,resto); system("pause"); return 0; } int restoDivisao(int n1, int n2) { return (n1 % n2); }

144 Digite o primeiro numero: 13 Digite o segundo numero: 3 Resto da divisao de 13 por 3: 1

CAPTULO 7. FUNES

Exerccio 7.2 Escreva uma funo que calcule e retorne a soma da sequncia 1, 2, . . . , N , onde N um nmero inteiro fornecido como argumento de entrada. Exerccio 7.3 Escreva uma funo que calcule e retorne a mdia aritmtica de 3 nmeros reais fornecidos como argumentos de entrada. Exerccio 7.4 Escreva uma funo que calcule e retorne a mdia ponderada de 3 nmeros inteiros fornecidos como argumentos de entrada. Os pesos devem ser 1, 2 e 3 respectivamente para o primeiro, segundo e terceiro nmeros. Exerccio 7.5 Escreva uma funo que calcule e retorne a mdia ponderada de 3 nmeros inteiros fornecidos como argumentos de entrada. Os pesos devem tambm ser fornecidos como argumentos de entrada. Exerccio 7.6 Escreva uma funo que receba como argumento de entrada um nmero inteiro no intervalo [1, 32767] e que retorne o nmero invertido. Por exemplo, se a entrada for o nmero 347 a sada deve ser 743. Caso seja informado um argumento de entrada invlido, o retorno deve ser 0. Exerccio 7.7 Escreva uma funo que receba como argumento de entrada um nmero inteiro no intervalo [1, 10] e que retorne o fatorial do nmero. Caso seja informado um argumento de entrada invlido, o retorno deve ser 0.

7.3

Funes e Estruturas Homogneas

A passagem de argumentos entre funes pode ser realizada de duas maneiras, por valor ou por referncia. Todos os exemplos apresentados nas sees anteriores utilizaram a abordagem de passagem por valor. Isto signica que os argumentos de entrada e sada devem ser explicitamente indicados na declarao da funo. Em geral, ao trabalhar-se com os tipos primitivos da linguagem, utiliza-se a passagem de argumentos por valor. Na passagem por referncia, ao contrrio, os argumentos so implicitamente referenciados pelas funes. A passagem de argumentos do tipo estruturas homogneas, como um vetor ou uma matriz) sempre deve ser feita por referncia (Exemplo 7.8).

7.3. FUNES E ESTRUTURAS HOMOGNEAS

145

Exemplo 7.8 Dene duas funes para tratamento de vetores. A primeira inicializa a estrutura e a segunda exibe o contedo na sada padro. #include <stdio.h> #define SIZE 10 void inicializa(int[]); void imprime(int[]); int main(void) { int vet[SIZE]; inicializa(vet); imprime(vet); system("pause"); return 0; } void inicializa(int v[]) { int i; for(i = 0; i < SIZE; i++) v[i] = i; } void imprime(int v[]) { int i; for(i = 0; i < SIZE; i++) printf("%2d",v[i]); printf("\n"); } 0 1 2 3 4 5 6 7 8 9 Como funciona a passagem por referncia? Exatamente como sugere o nome dessa abordagem. criada uma referncia da estrutura de dados criada em main() e passada para as funes declaradas. Assim, estas funes acessam e manipulam uma nica rea na memria, denida na funo principal do programa, onde encontra-se armazenados os elementos do vetor. Uma vez que a estrutura no foi passada por valor, torna-se desnecessrio um argumento de retorno na passagem por referncia, que sempre ser do tipo void. Observe no Exemplo 7.8 que existe um vnculo indesejvel entre as funes declaradas e a diretiva #define. O problema, nesse caso, que as funes precisam saber que SIZE representa o tamanho do vetor. Uma soluo mais interessante apresentada no Exemplo 7.9, onde o tamanho da estrutura de dados passada como argumento de entrada para as funes declaradas.

146

CAPTULO 7. FUNES

Exemplo 7.9 Dene duas funes para tratamento de vetores. A primeira inicializa a estrutura e a segunda exibe o contedo na sada padro (verso com passagem do tamanho do vetor como argumento de entrada). #include <stdio.h> #define SIZE 10 void inicializa(int,int[]); void imprime(int,int[]); int main(void) { int vet[SIZE]; inicializa(SIZE,vet); imprime(SIZE,vet); return 0; } void inicializa(int t,int v[]) { int i; for(i = 0; i < t; i++) v[i] = i; } void imprime(int t,int v[]) { int i; for(i = 0; i < t; i++) printf("%2d",v[i]); printf("\n"); } Exerccio 7.8 Escreva uma funo que receba como argumento de entrada um vetor de tamanho N, onde N tambm passado como argumento de entrada. A funo deve retornar a mdia aritmtica dos elementos do vetor. Escreva tambm uma funo para inicializar e exibir na sada padro um vetor com valores aleatrios no intervalo [A, B], onde A e B so nmeros inteiros quaisquer e B A. Escreva uma aplicao para gerar um vetor de tamanho 100 e exibir na sada padro a mdia aritmtica do contedo. Exerccio 7.9 Ainda considerando-se o exerccio anterior, dena uma funo para retornar o maior elemento do vetor. Exerccio 7.10 Escrever uma funo para inicializar um vetor de caracteres com valores no intervalo [A, Z]. O tamanho do vetor deve ser passado como o argumento de entrada. Escrever uma outra funo que retorne a quantidade de vogais no vetor.

7.4. FUNES E CADEIAS DE CARACTERES

147

Escrever uma aplicao para gerar um vetor de tamanho 100 e exibir na sada padro quantidade de vogais presentes no vetor. Exerccio 7.11 Escreva uma funo para inicializar uma matriz quadrada de ordem N com valores inteiros gerados randomicamente no intervalo [A, B], onde B A. O valor de N deve ser passado como argumento de entrada para a funo. Escreva tambm uma funo para exibir na sada padro uma matriz quadrada de ordem N, onde N passado como argumento de entrada. Por m, escreva uma funo para calcular a matriz C = A + B, onde A e B so matrizes quadradas de ordem N. Escreva uma aplicao que declare e inicialize 2 matrizes quadradas de ordem 20 com valores aleatrios no intervalo [9, 9]. A aplicao deve calcular C = A + B e exibir a matriz C na sada padro. Exerccio 7.12 Escreva uma funo que receba 2 vetores A e B de inteiros de tamanho N como argumentos de entrada. A funo deve calcular B = A, onde um nmero inteiro tambm passado como argumento para a funo.

7.4 Funes e Cadeias de Caracteres


Uma vez que cadeias de caracteres em C so manipuladas na forma de vetores do tipo char, o emprego de passagem por referncia para os argumentos de funes tambm deve ser observado ao se tratar strings. O Exemplo 7.10 apresenta uma funo que recebe como argumento de entrada a passagem por referncia de uma cadeia de caracteres. Exemplo 7.10 Aplicao que chama uma funo para converter os caracteres de uma string para letras maisculas. #include <stdio.h> #include <string.h> void str(char[]); int main(void) { char p[] = "Teste"; str(p); printf("%s\n",p); return 0; } void str(char ch[]) { int i;

148 for (i = 0; ch[i]!='\0'; i++) if(ch[i]>='a'&&ch[i]<='z') ch[i]-=32; } TESTE

CAPTULO 7. FUNES

Exerccio 7.13 Escrever uma funo que receba como argumento de entrada uma string e que retorne a cadeia de caracteres criptografada conforme a regra: ch = ch + 10. Escreva tambm uma outra funo para descriptografar a string. Exerccio 7.14 Escrever uma funo que receba como argumento de entrada uma string, que deve ser modicada de forma que cada palavra se inicie por letra maiscula e as demais letras sejam grafadas em letras minsculas. Exerccio 7.15 Escrever uma funo que receba como argumento de entrada uma string e que retorne o nmero de palavras existentes na cadeia de caracteres.

7.5
7.5.1

Tipos Especiais de Variveis


Variveis Globais

Uma varivel pode ser declarada fora do corpo de uma funo. Este tipo especial de varivel denominada global. Uma varivel global possui a caracterstica de ser visvel a todas as funes que se seguem sua declarao. Outro aspecto importante que uma varivel global permanece alocada na memria enquanto o programa estiver em execuo. Assim, seu contedo permanece disponvel at o trmino da aplicao. O Exemplo 7.11 exibe uma funo que emprega duas variveis globais do tipo inteiro. Exemplo 7.11 Funo para calcular e retornar a soma e o produto de dois nmeros inteiros atribudos a variveis globais. #include <stdio.h> void somaprod(int, int); int s, p; int main(void) {

7.5. TIPOS ESPECIAIS DE VARIVEIS somaprod(5,10); printf("Soma = %d\nProduto = %d\n", s, p); system("pause"); return 0; } void somaprod(int a, int b) { s = a + b; p = a * b; } Soma = 15 Produto = 50

149

O uso de variveis globais apresenta vantagens e desvantagens. Conforme apresentado at o momento, uma funo pode retornar apenas um nico valor de um dos tipos de dados primitivos da linguagem atravs do comando return. O uso de variveis globais contorna essa limitao ao permitir a manipulao direta de variveis fora do corpo da funo. Como desvantagem, o emprego de variveis globais aumenta a interdependncia entre as funes utilizadas em um programa, dicultando a reutilizao de cdigo. Exerccio 7.16 Escrever uma funo para processar o swap (troca de valores) entre duas variveis globais do tipo float. Exerccio 7.17 Escrever um programa C para exibir o maior e o menor valor contido em um vetor de inteiros de tamanho 100. O programa deve possuir os seguintes mdulos ou funes: funo para atribuio de valores randmicos ao vetor, no intervalo [0, N ], onde N passado como argumento de entrada. funo para exibio do vetor na sada padro, com M elementos por linha, onde M passado como argumento de entrada. funo para calcular o maior e o menor elemento do vetor (use variveis globais).

7.5.2 Variveis Estticas


Uma varivel esttica deve ser declarada no corpo de uma funo. Porm, seu contedo permanece disponvel mesmo aps o trmino da execuo da funo. Na declarao, uma varivel esttica deve conter o modicador static.

150

CAPTULO 7. FUNES

Variveis estticas compartilham algumas caractersticas tanto de variveis locais (s podem ser acessadas no corpo da funo que a declarou) quanto de variveis globais (tm o seu contedo disponvel mesmo aps a execuo da funo). Uma utilizao importante de variveis estticas consiste em recuperar o valor de uma varivel atribuda na ltima vez em que a funo foi executada (Exemplo 7.12). Exemplo 7.12 Funo que exibe a aplicabilidade de uma varivel esttica. #include <stdio.h> void estatica(void); // Prottipo da funo esttica int main(void) { int i; for (i = 1; i <= 5; i++) estatica(); system("pause"); return 0; } void estatica(void) { int i = 0; static int j = 0; // declara e atribui valor a uma varivel esttica printf("Local = %d\tEstatica = %d\n", i++, j++); } Local Local Local Local Local = = = = = 0 0 0 0 0 Estatica Estatica Estatica Estatica Estatica = = = = = 0 1 2 3 4

7.6

Recursividade

Funes em C podem ser usadas de forma recursiva. Isto signica que uma funo pode chamar a si prpria. Em uma analogia com o mundo real, como se voc procurasse no dicionrio a denio da palavra recurso e encontrasse a seguinte denio: Recurso: (s.f.) Veja a denio em recurso. Um exemplo de funo que pode ser escrita com chamadas recursivas o

7.6. RECURSIVIDADE

151

fatorial de um nmero inteiro no-negativo N, representado por N ! e que representa a seguinte denio: 0! = 1 e n! = (n 1)! n para n>0

Assim, 1! = 0! 1 = 1 1 = 1, 2! = 1! 2 = 1 2 = 2 e 3! = 2! 2 = 2 3 = 6. possvel resolver o problema do fatorial sem o emprego de recursividade, conforme apresentado no Exemplo 7.13, que dene uma funo para esse m. Exemplo 7.13 Funo para o clculo do fatorial de um nmero inteiro no-negativo. #include <stdio.h> int fatorial(int); int main(void) { int num; int fat; printf("Numero inteiro nao-negativo: "); scanf("%d",&num); fat = fatorial(num); printf("Fatorial: %d\n",fat); system("pause"); return 0; } int fatorial(int n) { int i; int fat = 1; for(i=1;i<=n;i++) fat*=i; return fat; } Numero inteiro nao-negativo: 6 Fatorial: 720 A partir da denio do fatorial apresentada anteriormente, pode-se pensar em uma soluo recursiva para o problema, onde o fatorial de um nmero qualquer igual ao prprio nmero multiplicado pelo fatorial do seu predecessor. O Exemplo 7.14 apresenta uma funo recursiva para o clculo do fatorial. Exemplo 7.14 Funo recursiva para o clculo do fatorial de um nmero inteiro no-negativo.

152 #include <stdio.h> int fatrec(int); int main(void) { int num; int fat; printf("Numero inteiro nao-negativo: "); scanf("%d",&num); fat = fatrec(num); printf("Fatorial: %d\n",fat); system("pause"); return 0; } int fatrec(int n) { if(n==0) return 1; else return n * fatrec(n-1); } Numero inteiro nao-negativo: 6 Fatorial: 720

CAPTULO 7. FUNES

importante observar que toda funo recursiva deve prever como o processo de recurso ser interrompido. No Exemplo 7.14, o processo termina quando o valor do nmero passado como argumento passa a valer 0. Se este teste no for includo na funo, as chamadas continuariam indenidamente com valores negativos cada vez menores sendo passados como argumento de entrada. Exerccio 7.18 Escrever uma funo recursiva para calcular o valor de xn , onde n > 0, onde x e n so passados como argumentos de entrada.

7.7

Bibliotecas de Funes

Os compiladores C permitem que um programa utilize funes armazenadas em uma biblioteca do usurio. Nesse caso, a diretiva ao pr-processador #include deve ser utilizada para informar ao programa o nome da biblioteca onde se encontra a funo. Alm disso, no caso do Dev-C++, deve ser includo no IDE o caminho completo do diretrio onde se encontra a biblioteca de funes do usurio. Este requisito pode ser feito, a partir do menu principal, selecionando-se Ferramentas Opes do

7.7. BIBLIOTECAS DE FUNES

153

Compilador Diretrios C includes. Na parte inferior direita da janela h um boto que deve ser usado para localizar a pasta na rvore de diretrios do computador. A vantagem do uso de funes previamente denidas est diretamente relacionada modularizao e ao reaproveitamento de cdigo-fonte. O Exemplo 7.15 exibe uma funo armazenada em uma biblioteca do usurio denominada wander.h. Exemplo 7.15 Funo recursiva para o clculo do fatorial. int fatrec(int n) { if(n==0) return 1; else return n * fatrec(n-1); } Uma vez armazenada na biblioteca do usurio e congurado o IDE para a busca no diretrio determinado, possvel implementar o programa-fonte para acessar a funo previamente denida. O Exemplo 7.16 apresenta um programa C para calcular o fatorial de um nmero inteiro no-negativo a partir de uma funo recursiva armazenada em uma biblioteca do usurio. Exemplo 7.16 Programa C para clculo do fatorial. #include <stdio.h> #include "wander.h" int fatrec(int); int main(void) { int num; int fat; printf("Numero inteiro nao-negativo: "); scanf("%d",&num); fat = fatrec(num); printf("Fatorial: %d\n",fat); system("pause"); return 0; }

154

CAPTULO 7. FUNES

Observe no Exemplo 7.16 que uma biblioteca do usurio delimitada por aspas duplas na diretiva ao pr-processador #include. Exerccio 7.19 Criar uma biblioteca do usurio prpria e nome-la como meunome.h. Incluir na biblioteca duas ou mais funes denidas nesse captulo. Escrever um programa C que chame as funes armazenadas na biblioteca do usurio.