Anda di halaman 1dari 207

Curso de Linguagem C Em Construo ca v0.

001
Adriano Joaquim de Oliveira Cruz Instituto de Matemtica a N cleo de Computao Eletrnica u ca o UFRJ c 2009 Adriano Cruz 14 de Setembro de 2010

Contedo u
1 Introduo ca 1.1 1.2 Sucessos e Fracassos da Computaao . . . . . . . . . . . . . . . . c Um Pouco da Histria da Computaao . . . . . . . . . . . . . . . o c 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.4 1.5 1.6 O In cio . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Era Moderna . . . . . . . . . . . . . . . . . . . . . . . . O Desenvolvimento durante as Grandes Guerras . . . . . As Geraoes . . . . . . . . . . . . . . . . . . . . . . . . . . c Microcomputadores . . . . . . . . . . . . . . . . . . . . . Memrias . . . . . . . . . . . . . . . . . . . . . . . . . . . o Bits e Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . Perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . . e 13 13 15 15 15 18 20 21 22 23 25 26 26 32 33 34 34 35 37 37 37 38 40 41 42 42 43

O Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

O Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Um programa em C . . . . . . . . . . . . . . . . . . . . . . . . . Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

2 Algoritmos 2.1 2.2 2.3 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Primeiros Passos . . . . . . . . . . . . . . . . . . . . . . . . . . . Representaao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c 2.3.1 2.3.2 2.3.3 2.4 2.5 Linguagem Natural . . . . . . . . . . . . . . . . . . . . . . Fluxogramas . . . . . . . . . . . . . . . . . . . . . . . . . Pseudo-Linguagem . . . . . . . . . . . . . . . . . . . . . .

Modelo de von Neumann . . . . . . . . . . . . . . . . . . . . . . . Estruturas Bsicas de Algoritmos . . . . . . . . . . . . . . . . . . a 2.5.1 2.5.2 2.5.3 Comandos de leitura . . . . . . . . . . . . . . . . . . . . . Comandos de escrita . . . . . . . . . . . . . . . . . . . . . Expresses . . . . . . . . . . . . . . . . . . . . . . . . . . o 1

2.5.4 2.5.5 2.5.6 2.6 2.7

Comandos de atribuiao . . . . . . . . . . . . . . . . . . . c Comandos de controle . . . . . . . . . . . . . . . . . . . . Comandos de repetiao . . . . . . . . . . . . . . . . . . . c

45 46 47 48 53 55 55 55 55 56 56 57 58 59 59 60 61 62 62 63 63 64 65 67 67 67 68 69 71 73 73 74 75 75 76 78

Exemplos de Algoritmos . . . . . . . . . . . . . . . . . . . . . . . Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Tipos de Dados, Constantes e Variveis a 3.1 3.2 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Tipos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.4 3.5 3.4.1 3.5.1 3.5.2 3.5.3 3.6 Tipos Bsicos . . . . . . . . . . . . . . . . . . . . . . . . . a Modicadores de tipos . . . . . . . . . . . . . . . . . . . . Constantes Inteiras na base 10 . . . . . . . . . . . . . . . Constantes Inteiras Octais . . . . . . . . . . . . . . . . . . Constantes Inteiras Hexadecimais . . . . . . . . . . . . . . Converso entre Bases . . . . . . . . . . . . . . . . . . . . a Constantes em Ponto Flutuante . . . . . . . . . . . . . . . Constantes Cadeias de Caracteres . . . . . . . . . . . . . Nomes das Variveis . . . . . . . . . . . . . . . . . . . . . a Declaraao de variveis . . . . . . . . . . . . . . . . . . . c a Atribuiao de valores . . . . . . . . . . . . . . . . . . . . . c

Constantes Numricas . . . . . . . . . . . . . . . . . . . . . . . . e

Constantes Caracteres . . . . . . . . . . . . . . . . . . . . . . . . Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a

Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

4 Entrada e Sa pelo Console da 4.1 4.2 4.3 4.4 4.5 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Biblioteca Padro . . . . . . . . . . . . . . . . . . . . . . . . . . . a Sa - A Funao printf . . . . . . . . . . . . . . . . . . . . . . . da c 4.3.1 Cdigos de Converso . . . . . . . . . . . . . . . . . . . . o a Entrada - A Funao scanf . . . . . . . . . . . . . . . . . . . . . . c Lendo e Imprimindo Caracteres . . . . . . . . . . . . . . . . . . . 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6 Funoes getchar e putchar . . . . . . . . . . . . . . . . . c Lendo e Imprimindo Cadeias de Caracteres . . . . . . . . Lendo e Imprimindo cadeias com scanf e printf . . . . . Lendo e Imprimindo cadeias com gets e puts . . . . . . . A Funao fgets . . . . . . . . . . . . . . . . . . . . . . . c

Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

5 Operadores e Expresses o 5.1 5.2 5.3 5.4 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Operador de Atribuiao . . . . . . . . . . . . . . . . . . . . . . . c Operadores Aritmticos . . . . . . . . . . . . . . . . . . . . . . . e Operadores Relacionais e Lgicos . . . . . . . . . . . . . . . . . . o 5.4.1 5.4.2 5.5 5.6 5.7 5.8 5.9 Operadores Relacionais . . . . . . . . . . . . . . . . . . . Operadores Lgicos o . . . . . . . . . . . . . . . . . . . . .

79 79 79 80 81 81 81 83 85 86 86 87 88 89 91 91 91 91 92 93 95 97 97

Operadores com Bits . . . . . . . . . . . . . . . . . . . . . . . . . Operadores de Atribuiao Composta . . . . . . . . . . . . . . . . c Operador v rgula . . . . . . . . . . . . . . . . . . . . . . . . . . . Operador sizeof() . . . . . . . . . . . . . . . . . . . . . . . . . . Converso de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . a

5.10 Regras de Precedncia . . . . . . . . . . . . . . . . . . . . . . . . e 5.11 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Comandos de Controle 6.1 6.2 6.3 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Blocos de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . Comandos de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3.1 6.3.2 6.3.3 6.4 6.4.1 6.4.2 6.4.3 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.6 Comando if . . . . . . . . . . . . . . . . . . . . . . . . . . Comando switch . . . . . . . . . . . . . . . . . . . . . . . Comando Ternrio . . . . . . . . . . . . . . . . . . . . . . a Comando for . . . . . . . . . . . . . . . . . . . . . . . . .

Laos de Repetiao . . . . . . . . . . . . . . . . . . . . . . . . . . c c

Comando while . . . . . . . . . . . . . . . . . . . . . . . 100 Comando do-while . . . . . . . . . . . . . . . . . . . . . 101 Comando break . . . . . . . . . . . . . . . . . . . . . . . 102 Comando continue . . . . . . . . . . . . . . . . . . . . . 102 Comando goto . . . . . . . . . . . . . . . . . . . . . . . . 103 Funao exit() . . . . . . . . . . . . . . . . . . . . . . . . 103 c Comando return . . . . . . . . . . . . . . . . . . . . . . . 103

Comandos de Desvio . . . . . . . . . . . . . . . . . . . . . . . . . 102

Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

7 Vetores e Cadeias de Caracteres 7.1 7.2 7.3 7.4 7.5 7.6 7.7

107

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107 c Declaraao de Vetores Unidimensionais . . . . . . . . . . . . . . . 107 c Cadeias de Caracteres . . . . . . . . . . . . . . . . . . . . . . . . 108 Declaraao de Vetores Multidimensionais c . . . . . . . . . . . . . 112 Vetores de Cadeias de Caracteres . . . . . . . . . . . . . . . . . . 114 Inicializaao de Vetores e Matrizes . . . . . . . . . . . . . . . . . 116 c Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119 122

8 Funoes c 8.1 8.2 8.3 8.4

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122 c Forma Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 Prottipos de Funoes . . . . . . . . . . . . . . . . . . . . . . . . 124 o c Escopo de Variveis . . . . . . . . . . . . . . . . . . . . . . . . . 125 a 8.4.1 8.4.2 Variveis Locais . . . . . . . . . . . . . . . . . . . . . . . 125 a Variveis Globais . . . . . . . . . . . . . . . . . . . . . . . 127 a Passagem de Parmetros por Valor . . . . . . . . . . . . . 128 a Passagem de Parmetros por Referncia . . . . . . . . . . 129 a e Passagem de Vetores e Matrizes . . . . . . . . . . . . . . . 129

8.5

Parmetros Formais . . . . . . . . . . . . . . . . . . . . . . . . . 127 a 8.5.1 8.5.2 8.5.3

8.6 8.7 8.8 8.9

O Comando return . . . . . . . . . . . . . . . . . . . . . . . . . 132 Recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132 a Argumentos - argc e argv . . . . . . . . . . . . . . . . . . . . . . 133 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 138

9 Ponteiros 9.1 9.2

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 c Operaoes com Ponteiros . . . . . . . . . . . . . . . . . . . . . . 139 c 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 Declaraao de Ponteiros . . . . . . . . . . . . . . . . . . . 139 c Os Operadores Especiais para Ponteiros . . . . . . . . . . 140 Atribuiao de Ponteiros . . . . . . . . . . . . . . . . . . . 141 c Incrementando e Decrementando Ponteiros . . . . . . . . 142 Comparaao de Ponteiros . . . . . . . . . . . . . . . . . . 144 c . . . . . . . . . . . . . . . . . 145

9.3 9.4 9.5 9.6 9.7 9.8 9.9

Ponteiros e Vetores . . . . . . . . . . . . . . . . . . . . . . . . . . 144 Ponteiros e Cadeias de Caracteres Alocaao Dinmica de Memria . . . . . . . . . . . . . . . . . . . 146 c a o Ponteiros e Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . 147 Vetores de Ponteiros . . . . . . . . . . . . . . . . . . . . . . . . . 148 Ponteiros para Ponteiros . . . . . . . . . . . . . . . . . . . . . . . 151 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 156 4

10 Estruturas

160

10.1 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160 c 10.2 Denioes Bsicas . . . . . . . . . . . . . . . . . . . . . . . . . . 160 c a 10.3 Atribuiao de Estruturas . . . . . . . . . . . . . . . . . . . . . . . 163 c 10.4 Matrizes de Estruturas . . . . . . . . . . . . . . . . . . . . . . . . 163 10.5 Estruturas e Funoes . . . . . . . . . . . . . . . . . . . . . . . . . 164 c 10.6 Ponteiros para Estruturas . . . . . . . . . . . . . . . . . . . . . . 166 10.7 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169 11 Entrada e Sa por Arquivos da 171

11.1 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 c 11.2 Fluxos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 11.2.1 Fluxos de Texto . . . . . . . . . . . . . . . . . . . . . . . 171 11.2.2 Fluxo Binrio . . . . . . . . . . . . . . . . . . . . . . . . . 172 a 11.2.3 Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 11.3 Funoes de Entrada e Sa c da . . . . . . . . . . . . . . . . . . . . . 173 11.4 In e Fim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174 cio 11.4.1 Abrindo um Arquivo . . . . . . . . . . . . . . . . . . . . . 174 11.4.2 Fechando um Arquivo . . . . . . . . . . . . . . . . . . . . 175 11.4.3 Fim de Arquivo . . . . . . . . . . . . . . . . . . . . . . . . 176 11.4.4 Volta ao In cio . . . . . . . . . . . . . . . . . . . . . . . . 176 11.5 Lendo e Escrevendo Caracteres . . . . . . . . . . . . . . . . . . . 177 11.6 Testando Erros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177 11.7 Lendo e Escrevendo Cadeias de Caracteres . . . . . . . . . . . . . 180 11.8 Entrada e Sa Formatada . . . . . . . . . . . . . . . . . . . . . 181 da 11.9 Lendo e Escrevendo Arquivos Binrios . . . . . . . . . . . . . . . 182 a 11.10Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 12 Problemas Extras A Tabela ASCII B Palavras Reservadas 188 199 201

Lista de Figuras
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 Fotograa de um circuito integrado de microprocessador Pentium. 14 Imagem de um baco. . . . . . . . . . . . . . . . . . . . . . . . . a Blaise Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Charles Babbage . . . . . . . . . . . . . . . . . . . . . . . . . . . Fotograa da Dierence Engine . . . . . . . . . . . . . . . . . . . Computador Eniac . . . . . . . . . . . . . . . . . . . . . . . . . . Diagrama Bsico de um Computador Digital . . . . . . . . . . . a N veis de hierarquia da memria de um computador. . . . . . . . o Tamanho de Bits, Bytes e Palavras . . . . . . . . . . . . . . . . . 15 16 17 17 19 22 23 25 30 38 39 42 46 48 50

1.10 Ciclo de desenvolvimento de um programa. . . . . . . . . . . . . 2.1 2.2 2.3 2.4 2.5 2.6 7.1 9.1 9.2 9.3 9.4 9.5 9.6 9.7 S mbolos mais comumente usados em uxogramas. . . . . . . . . Fluxograma para resolver uma equaao do primeiro grau. . . . . c Modelo de memria . . . . . . . . . . . . . . . . . . . . . . . . . o Fluxograma do comando se ... ent~o ... a sen~o. . . . . . . a Fluxograma para decidir se deve levar um guarda-chuva. . . . . . Fluxograma do comando enquanto. . . . . . . . . . . . . . . . .

Mapa de memria de uma matriz. . . . . . . . . . . . . . . . . . 116 o Mapa de memria com duas variveis e ponteiro. . . . . . . . . . 138 o a Ponteiro apontando para rea de memria contendo vetor. . . . . 139 a o Declaraao de ponteiros. . . . . . . . . . . . . . . . . . . . . . . . 140 c Atribuiao de endereo de uma varivel a um ponteiro. . . . . . . 141 c c a Uso de um ponteiro para copiar valor de uma varivel. . . . . . . 141 a Exemplos de atribuioes de ponteiros. . . . . . . . . . . . . . . . 142 c Armazenamento de matrizes com vetores de ponteiros. . . . . . . 152

11.1 Fluxos de dados. . . . . . . . . . . . . . . . . . . . . . . . . . . . 172

Lista de Tabelas
1.1 1.2 1.3 1.4 1.5 2.1 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 4.1 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 7.1 Transistores por circuito integrado nos microprocessadores da Intel 14 Tempo de execuao das instruoes aritmticas no ENIAC . . . . c c e Exemplos de Microprocessadores . . . . . . . . . . . . . . . . . . Abreviaoes usadas em referncias `s memrias. . . . . . . . . . . c e a o Exemplos de perifricos . . . . . . . . . . . . . . . . . . . . . . . e Operadores Aritmticos. . . . . . . . . . . . . . . . . . . . . . . . e Tipos de dados denidos pelo Padro ANSI C. . . . . . . . . . . a Constantes Inteiras na Base 10 . . . . . . . . . . . . . . . . . . . Constantes octais . . . . . . . . . . . . . . . . . . . . . . . . . . . Constantes hexadecimais . . . . . . . . . . . . . . . . . . . . . . . Constantes em ponto utuante . . . . . . . . . . . . . . . . . . . Exemplos de constantes caractere . . . . . . . . . . . . . . . . . . Exemplos de caracteres invis veis. . . . . . . . . . . . . . . . . . . Tabela do exercicio 6 . . . . . . . . . . . . . . . . . . . . . . . . . Cdigos de Converso para leitura e entrada de dados. . . . . . . o a Operadores aritmticos. . . . . . . . . . . . . . . . . . . . . . . . e Operadores Relacionais. . . . . . . . . . . . . . . . . . . . . . . . Operador Lgico E. . . . . . . . . . . . . . . . . . . . . . . . . . . o Operador Lgico OU. . . . . . . . . . . . . . . . . . . . . . . . . . o Operador Lgico N~O. . . . . . . . . . . . . . . . . . . . . . . . . o A Precedncia dos operadores lgicos e relacionais. . . . . . . . . . e o Operadores com bits. . . . . . . . . . . . . . . . . . . . . . . . . . Operador Lgico OU. . . . . . . . . . . . . . . . . . . . . . . . . . o Precedncia dos operadores. . . . . . . . . . . . . . . . . . . . . . e 19 22 26 26 45 57 58 59 59 61 62 62 66 69 80 81 82 83 83 83 84 84 88

Passos executados durante o algoritmo da bolha. . . . . . . . . . 109

11.1 Exemplos de funoes de Entrada e Sa c da. . . . . . . . . . . . . . 174 A.1 Conjunto de caracteres ASCII . . . . . . . . . . . . . . . . . . . . 199 A.2 Conjunto de cdigos especiais ASCII e seus signicados . . . . . 200 o

Lista de Algoritmos
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 Exemplo de Algoritmo. . . . . . . . . . . . . . . . . . . . . . . . . Algoritmo para resolver uma equaao do primeiro grau. . . . . . . c Algoritmo para calcular a mdia das notas de um aluno. e . . . . . Algoritmo para calcular a maior nota de um grupo de notas. . . . Modelo de memria e funcionamento de um algoritmo . . . . . . . o Comando se em pseudo-linguagem . . . . . . . . . . . . . . . . . . Algoritmo para decidir o que fazer no domingo. . . . . . . . . . . Algoritmo para decidir se deve levar um guarda-chuva. . . . . . . Algoritmo para ler 10 nmeros e imprimir se so pares ou no. . . u a a 36 36 38 40 41 46 47 47 49 51 51 52 54 54 60

2.10 Algoritmo para ler nmeros e imprimir se so pares ou no. A quantidade de n meros a ser lida de u a a u e 2.11 Algoritmo para calcular a maior nota de uma turma de 25 alunos. 2.12 Algoritmo para calcular a nota mdia de uma turma de 25 alunos. e 2.13 Algoritmo para calcular a maior temperatura do ano. . . . . . . . 2.14 Algoritmo do exerc 11. . . . . . . . . . . . . . . . . . . . . . . cio 2.15 Algoritmo do exerc 11. . . . . . . . . . . . . . . . . . . . . . . cio 3.1 Algoritmo para converter inteiros na base 10 para uma base b. . .

Listings
1.1 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 5.1 5.2 5.3 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 Exemplo de Programa em C. . . . . . . . . . . . . . . . . . . . . Exemplo de impresso de resultados . . . . . . . . . . . . . . . . a Exemplo de justicaao de resultados. . . . . . . . . . . . . . . . c Exemplo de uso de especicador de preciso. . . . . . . . . . . . a Exemplo de uso de scanf. . . . . . . . . . . . . . . . . . . . . . Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . Exemplo de uso de printf e scanf na leitura de cadeias. . . . . Exemplo de uso de puts e gets na leitura de cadeias. Exemplo de operadores de deslocamento. Exemplo do operador sizeof. Variveis da questo 9. a a Exemplo de comandos if. Exemplo de switch. . . . . . . . . . . . . . . . . . . . 32 68 70 71 73 74 74 75 76 85 86 90 92 94 96 97 98 99 99

. . . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Programas com ifs em escada e aninhados. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Exemplo de comando ternrio. . . . . . . . . . . . . . . . . . . . a Exemplo de comando for. . . . . . . . . . . . . . . . . . . . . . . Exemplo de comando for com testes sobre outras variveis. . . . a Exemplo de comando for sem alteraao da varivel de controle. c a Exemplo de comando for sem teste de m. Comando for aninhados.

. . . . . . . . . . . . 100

. . . . . . . . . . . . . . . . . . . . . . 100 . . . . . . . . . . . . . . . . . 101 . . . . . . . . . . . . . . . . . . . . . 106 . . . . . . . . . . . . . . . . . . 110 . . . . . . . . . . . . . . . . . 111

6.10 Comando while com uma funao. c 6.11 Programa do exercicio 17. 7.1 7.2 7.3 7.4 7.5

Exemplo de vetores. . . . . . . . . . . . . . . . . . . . . . . . . . 108 Produto escalar de dois vetores. Ordenaao pelo mtodo da bolha. c e Leitura de uma matriz.

Exemplos de funoes para cadeias. . . . . . . . . . . . . . . . . . 113 c . . . . . . . . . . . . . . . . . . . . . . . 114

10

7.6 7.7 7.8 7.9 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9

Multiplicaao de duas matrizes. c

. . . . . . . . . . . . . . . . . . 115

Leitura de um vetor de nomes. . . . . . . . . . . . . . . . . . . . 117 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 118 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 118 . . . . . . . . . . . . . . . . . . . . . 121 Exemplo de prottipos. . . . . . . . . . . . . . . . . . . . . . . . 124 o Exemplos de variveis locais. . . . . . . . . . . . . . . . . . . . . 126 a Deniao de varivel dentro de um bloco. . . . . . . . . . . . . . 126 c a Deniao de varivel global. c a . . . . . . . . . . . . . . . . . . . . 127 Exemplo de passagem por valor. . . . . . . . . . . . . . . . . . . 128 Uso indevido de variveis locais. . . . . . . . . . . . . . . . . . . 129 a Passagem de vetor com dimenses. o . . . . . . . . . . . . . . . . 130 Passagem de vetores sem dimenses. . . . . . . . . . . . . . . . . 131 o Funao recursiva para calcular xn . . . . . . . . . . . . . . . . . . 133 c . . . . . . . . . . . . . . . . . . . . . . 136

7.10 Programa do exercicio 14.

8.10 Uso de argc e argv. . . . . . . . . . . . . . . . . . . . . . . . . . 134 8.11 Programa do exerc 8. cio 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 8.12 Programa do problema 9. . . . . . . . . . . . . . . . . . . . . . . 136 Exemplo de atribuiao de ponteiros. . . . . . . . . . . . . . . . . 142 c Exemplos de operaoes com ponteiros. c . . . . . . . . . . . . . . 143 Exemplo de subtraao de ponteiros. . . . . . . . . . . . . . . . . 144 c Exemplo de comparaao de ponteiros. . . . . . . . . . . . . . . . 144 c Exemplo de alteraoes invlidas sobre ponteiros. . . . . . . . . . 145 c a Exemplo de notaoes de vetores. . . . . . . . . . . . . . . . . . . 145 c Exemplo de ponteiro varivel. a . . . . . . . . . . . . . . . . . . . 146 . . . . . . . . . 146 Exemplo de ponteiro para cadeia de caracteres.

Exemplo de cpia de cadeias de caracteres. . . . . . . . . . . . . 147 o . . . . . . . . . . . . . . . . . 148 . . . . . . . . 150 . . . . . . . . . . . . . . . . . . . . . 149 . . . . . . . . . . . . 150 . . . . . . . . . . . 153 . . 154

9.10 Exemplo de uso de calloc e free. 9.11 Exemplo de uso de malloc.

9.12 Exemplo de matriz normal sem uso de ponteiros. 9.13 Exemplo de matriz mapeada em um vetor. 9.14 Exemplo de uso de vetor de ponteiros. 9.15 Exemplo de uso de ponteiros para ponteiros. 9.17 Continuaao do exemplo 9.16. c 9.18 Programa do exercicio 11. 9.19 Programa do exercicio 12.

. . . . . . . . . . . . . . 151

9.16 Exemplo de uso de ponteiros para ponteiros usando funoes. c

. . . . . . . . . . . . . . . . . . . 155

. . . . . . . . . . . . . . . . . . . . . 157 . . . . . . . . . . . . . . . . . . . . . 158

9.20 Listagem do exerc 13. . . . . . . . . . . . . . . . . . . . . . . 158 cio 11

9.21 Programa do exerc 14. cio

. . . . . . . . . . . . . . . . . . . . . 159

10.1 Deniao de uma estrutura. . . . . . . . . . . . . . . . . . . . . . 161 c 10.2 Atribuiao de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 163 c 10.3 Ordenaao de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 163 c 10.4 Passando elementos para funoes. c 10.6 Funao que ordena estruturas. c . . . . . . . . . . . . . . . . . 164 . . . . . . . . . . . . . . . 165 10.5 Passagem de estruturas para funoes. c

. . . . . . . . . . . . . . . . . . . 166

10.7 Alocaao de espao para estruturas. . . . . . . . . . . . . . . . . 167 c c 10.8 Alocaao de espao para vetores de estruturas. . . . . . . . . . . 168 c c 10.9 Listagem do exercicio 3. 11.1 Uso da funao feof(). c . . . . . . . . . . . . . . . . . . . . . . 169 . . . . . . . . . . . . . . . . . . . . . . . 176 . . . . . . . . . . . . 178 . . . . . . . . . . . . 179 . . . . . . 180

11.2 Exemplo de leitura e escrita de caracteres. 11.3 Exemplo de leitura e escrita de caracteres.

11.4 Uso da funao ferror(). . . . . . . . . . . . . . . . . . . . . . . 180 c 11.5 Exemplo de leitura e escrita de cadeias de caracteres. 11.7 Exemplo de leitura e escrita na forma binria. a 11.8 Exemplo de leitura e escrita de estruturas. 11.9 (I) Trecho de programa do problema 14. 11.6 Exemplo de leitura e escrita de dados formatados. . . . . . . . . 182 . . . . . . . . . . 183 . . . . . . . . . . . . 184 . . . . . . . . . . . . . 187

11.10(II) Trecho de programa do problema 14. . . . . . . . . . . . . . 187 12.1 Processando o CPF. . . . . . . . . . . . . . . . . . . . . . . . . . 191 12.2 Estrutura do problema 8. . . . . . . . . . . . . . . . . . . . . . . 195

12

Cap tulo 1

Introduo ca
1.1 Sucessos e Fracassos da Computao ca

Os objetivos principais deste cap tulo so mostrar para o aluno iniciante alguns a aspectos da histria da computaao e denir, informalmente, termos e palavraso c chave que os prossionais da rea de computaao usam no seu dia a dia. Adriano a c Cruz c . A histria do desenvolvimento dos computadores tem sido impressionante. o O avano da tecnologia e a presena da computaao na nossa vida so inegveis. c c c a a Embora a histria deste fantstico desenvolvimento seja recente e bem documeno a tada, h lacunas e controvrsias impressionantes sobre diversos pontos. Neste a e cap tulo iremos ver histrias de espionagem e brigas na justia por roubo de o c ideias. H oportunidades perdidas e gente que soube aproveitar a sua chance. a H verdades estabelecidas que tiveram de ser revistas. a O avano na tecnologia dos computadores se deu em passos to largos que os c a primeiros computadores parecem to distantes no tempo quanto a Pr-Histria. a e o O aumento de velocidade, desde os anos 40, foi da vrias ordens de grandeza, a enquanto que o custo dos computadores caiu de milhes de dlares para valo o ores em torno de centenas de dlares. As primeiras mquinas tinham milhares o a de vlvulas, ocupavam reas enormes e consumiam quilowatts de energia. O a a microprocessador Pentium, lanado em 1993, tinha em torno de 3,1 milhes c o de transistores, ocupava uma rea de aproximadamente 25 cm2 e consumia a alguns watts de energia, custando aproximadamente 1000 dlares, somente o o microprocessador. A Figura 1.1 mostra a imagem de um circuito integrado de microprocessador Pentium. No entanto, esta histria de reduao de tamanho, aumento de velocidade e o c diminuiao de gasto de potncia, pode, para alguns pesquisadores, j ter uma c e a data xada para terminar. Em 1965, Gordon Moore, um dos fundadores da Intel, fabricante do Pentium e uma dos maiores fabricantes de circuitos integrados do mundo, enunciou o que cou conhecido como a Lei de Moore: Cada novo circuito integrado ter o dobro de transistores do anterior e ser lanado dentro a a c de um intervalo de 18 a 24 meses. Moore achava que esta lei seria vlida soa mente at 1975, no entanto, ela continua vlida at hoje. Na tabela 1.1, pode-se e a e observar a evoluao dos microprocessadores usados em nossos computadores. c 13

Figura 1.1: Fotograa de um circuito integrado de microprocessador Pentium. Ano 1971 1972 1974 1982 1985 1989 1993 1997 1999 2000 Processador 4004 8008 8080 80286 80386 80486 DX Pentium Pentium II Pentium III Pentium 4 Transistores 2.250 2.500 5.000 120.000 275.500 1.180.000 3.100.000 7.500.000 24.000.000 42.000.000

Tabela 1.1: Transistores por circuito integrado nos microprocessadores da Intel

Os transistores, que compem os circuitos eletrnicos, esto diminuindo de o o a tamanho, e estamos nos aproximando da fronteira nal, os eltrons. J se houve e a falar em tamanho de transistores medidos em nmeros de eltrons. Devemos nos u e lembrar que toda a tecnologia atual est baseada em uxo de eltrons, ou seja a e uma corrente eltrica. Os os conduzem correntes de eltrons e os transistores e e controlam este uxo. Se o tamanho diminuir alm dos eltrons estaremos em e e outro dom nio. No entanto, na histria da computaao, muitas promessas no foram cumprio c a das e falhas gigantescas aconteceram. Como em diversas questes, artistas geo niais, apontam o que no conseguimos ou no queremos ver e mostram que o a a rei est nu. H uma frase de Picasso que diz: Computadores so est pidos, a a a u eles somente conseguem responder perguntas. Esta frase expe com ironia o um fracasso da comunidade de computaao que havia prometido criar rapidac mente computadores inteligentes, computadores que poderiam questionar-se e nos questionar. Muitos acreditaram nesta promessa e muitos livros de cao c cient ca foram publicados em que este tipo de computador estaria dispon vel em um futuro muito prximo. Com notvel exemplo podemos citar o lme o a 2001 - Uma Odissia no Espao, de Stanley Kubrik que estreou em 1968 e e c foi baseado no conto The Sentinel, escrito em 1950 por Arthur Clark, um dos mestres da cao cient c ca. Neste lme o enlouquecido computador HAL 9000, que era capaz de ver, falar, raciocinar etc, mata quase todos os tripulantes de

14

uma nave espacial. Ora, j passamos por 2001 e no existe a menor possibilidade a a de se ver um computador como o HAL ou to louco de pedra como ele. a Na computaao, um exemplo fantstico de sucesso a Internet. A Internet c a e est se tornando essencial para o funcionamento do mundo moderno. Freq ena u temente ouvimos dizer que ela o meio de comunicaao que mais rapidamente se e c difundiu pelo mundo. Pode parecer verdade, j que conhecemos tantos internaua tas e as empresas esto se atropelando para fazer parte desta onda e aproveitar a as suas possibilidades. Esta corrida provocou alguns acidentes e muitos sonhos de riqueza se esva ram no ar. Hoje, pode-se fazer quase tudo pela Internet, namorar, comprar, pagar contas, fazer amigos, estudar, jogar etc. Quem sabe, em um futuro prximo, voltaremos ` Grcia Antiga e nos reuniremos em uma o a e enorme praa virtual para, democraticamente, discutir nossas leis, dispensando c intermedirios. a

1.2
1.2.1

Um Pouco da Histria da Computao o ca


O In cio

A primeira tentativa de se criar uma mquina de contar foi o baco. A palavra a a vem do rabe e signica p. Os primeiros bacos eram bandejas de areia sobre a o a as quais se faziam guras para representar as operaoes. Aparentemente, os c chineses foram os inventores do baco de calcular. No entanto, h controvrsias, a a e e os japoneses tambm reivindicam esta invenao, que eles chamam de soroban. e c Alm disso h os russos, que inventaram um tipo mais simples, chamado de e a tschoty. So conhecidos exemplares de baco datados de 2500 A.C. A Figura a a 1.2 ilustra um exemplar com as suas contas e varetas.

Figura 1.2: Imagem de um baco. a Em 1901 mergulhadores, trabalhando perto da ilha grega de Antikythera, encontraram os restos de um mecanismo, parecido com um relgio, com aproxio madamente 2000 anos de idade. O mecanismo, de grande complexidade, parece ser um dispositivo para calcular os movimentos de estrelas e planetas.

1.2.2

A Era Moderna

Em 1614 John Napier, matemtico escocs, inventou um dispositivo feito de a e marm para demonstrar a diviso por meio de subtraoes e a multiplicaao por a c c 15

meio de somas. A semelhana entre marm e ossos, fez com que o dispositivo c fosse conhecido como os ossos de Napier. Um dos primeiros instrumentos modernos de calcular, do tipo mecnico, foi a constru pelo lsofo, matemtico e f do o a sico francs Blaise Pascal (Figura 1.3). e Em 1642 aos 19 anos, na cidade de Rouen, Pascal desenvolveu uma mquina de a calcular, para auxiliar seu trabalho de contabilidade. A engenhoca era baseada em 2 conjuntos de discos interligados por engrenagens: um para a introduao c dos dados e outro para armazenar os resultados. A mquina utilizava o sistema a decimal para calcular, de maneira que quando um disco ultrapassava o valor 9, retornava ao 0 e aumentava uma unidade no disco imediatamente superior.

Figura 1.3: Blaise Pascal Pascal recebeu uma patente do rei da Frana, o que lhe possibilitou o c lanamento de sua mquina no mercado. A comercializaao das calculadoras c a c no foi satisfatria devido a seu funcionamento pouco convel, apesar dele ter a o a constru cerca de 50 verses. As mquinas de calcular, derivadas da Pasdo o a calina, como cou conhecida sua mquina, ainda podiam ser encontradas em a lojas at alguns poucos anos atrs. Antes de morrer, aos 39 anos, em 1662, e a Pascal que contribu em vrios campos da Cincia, ainda teve tempo de criar ra a e uma variante de sua mquina, a caixa registradora. a Em 1666, Samuel Morland adaptou a calculadora de Pascal para resolver multiplicaoes por meio de uma srie de somas sucessivas. Independentemente, c e em 1671 Leibniz projetou uma outra calculadora que somava e multiplicava. Esta calculadora s foi conclu em 1694. o da O primeiro computador de uso espec co comeou a ser projetado em 1819 c e terminou em 1822, ou seja, h mais de 180 anos atrs, pelo britnico Charles a a a (1791-1871, Figura 1.4), que o batizou de Dierence Engine (Figura 1.5). A motivaao de Babbage era resolver polinmios pelo mtodo das diferenas. Naquele c o e c tempo as tbuas astronmicas e outras tabelas eram calculadas por humanos, a o em mtodos tediosos e repetitivos. e Em 1823, ele iniciou o projeto de construir uma outra mquina mais avanada a c e capaz de calcular polinmios de at sexta ordem. Ele esperava terminar esta o e mquina em trs anos, mas a construao se arrastou at 1834. Este projeto que a e c e no foi completado, usou dinheiro do governo ingls e possivelmente a maior a e parte da fortuna pessoal de Babbage. A mquina, inteiramente mecnica, teria a a as seguintes caracter sticas: Arredondamento automtico; a 16

Figura 1.4: Charles Babbage

Figura 1.5: Fotograa da Dierence Engine

Preciso dupla; a Alarmes para avisar m de clculo; a Impresso automtica de resultados em placas de cobre. a a Em 1834 ele tinha completado os primeiros desenhos da mquina que dea nominou Analytical Engine que tinha as seguintes caracter sticas: 50 d gitos decimais de preciso; a Memria para 1000 destes nmeros (165000 bits); o u Controle por meio de cartes perfurados das operaoes e endereos dos o c c dados; Tempo de soma e subtraao igual a 1 segundo; tempo de multiplicaao e c c diviso igual a 1 minuto; a Sub-rotinas; 17

Arredondamento automtico e detecao de transbordo (overow ); a c Babagge nunca conseguiu terminar este ambicioso projeto. No entanto, os mais importantes conceitos de computaao, que somente vieram a tona nos anos c 40 do sculo vinte, j tinham sido considerados por Charles Babbage em o seu e a projeto. Um fato curioso que entre os auxiliares de Babagge estava Augusta Ada e Byron, Countess of Lovelace. Considera-se, hoje, que ela escreveu para Charles Babbage o primeiro programa para computadores. Ada que mudou seu nome para Augusta Ada King, aps seu casamento, estudava Matemtica com Deo a Morgan que provou um dos teoremas bsicos da Algebra Booleana, que a a e base matemtica sobre a qual foram desenvolvidos os projetos dos modernos a computadores. No entanto, no havia nenhuma ligaao entre o trabalho do proa c jetista dos primeiros computadores e o do matemtico que estudava o que viria a a ser o fundamento terico de todo a computaao que conhecemos hoje. o c

1.2.3

O Desenvolvimento durante as Grandes Guerras

Antes da Segunda Grande Guerra, em vrios pa a ses, cientistas trabalhavam em projetos que visavam construir computadores com rels, que so disposie a tivos eletromecnicos usados para ligar ou desligar circuitos eltricos. Rels a e e so os dispositivos que antecederam os transistores na construao de computaa c dores. Alguns destes computadores eram de uso geral, outros tinha nalidades espec cas. Alguns destes projetos esto listados a seguir. a Na Alemanha Em 1934 na Alemanha Konrad Zuze, engenheiro projetista de avies, concebeu o uma mquina de somar para resolver os clculos que deveria realizar em seus a a projetos. Em 1938, ele concluiu o Z1, um calculador mecnico com uma unidade a aritmtica que usava a base 2 para representar os nmeros, base que hoje os e u computadores modernos empregam. Em 1938 ele melhorou o desempenho do Z1, graas aos rels. c e O governo alemo patrocinou os trabalhos de Zuze e em 1941 estava pronto a o Z2, uma mquina eletromecnica capaz de receber instruoes por meio de uma a a c ta de papel. Em 1941 foi introduzido o Z3, que calculava trs a quatro adioes e c por segundo, uma multiplicaao em 4 ou 5 segundos e era capaz de extrair a c raiz quadrada. Nos Estados Unidos Em 1944 a IBM e H. Haiken da Universidade de Harvard, conclu am a construc ao de um verdadeiro computador: o Harvard Mark I, que operava em base 10. O Mark I efetuava as quatro operaoes fundamentais, mais o clculo de funoes c a c trigonomtricas, exponenciais e logar e tmicas. As instruoes eram fornecidas por c meio de tas de papel e os dados lidos de cartes perfurados. Os resultados eram o fornecidos em forma de cartes perfurados ou impressos por meio de mquinas o a de escrever. 18

Em 1943 na Universidade da Pensilvnia, J. Eckert e J. Mauchly iniciaram a a construao de um computador ` vlvulas, ou seja eletrnico que foi chamado de c a a o ENIAC. O projeto foi conclu em 1946 e usado na segunda guerra mundial. do O ENIAC podia ser reprogramado para executar diversas operaoes diferentes c atravs de ligaoes por meio de os e conectores. e c Durante muitos anos o computador ENIAC foi considerado o primeiro computador eletrnico constru o do. A mquina projetada pelos Drs. Eckert and a Mauchly era gigantesca quando comparada com os computadores pessoais atuais. Quando foi terminado, o ENIAC (Figura 1.6) enchia um laboratrio inteiro, o pesava trinta toneladas, e consumia duzentos quilowatts de potncia. e

Figura 1.6: Computador Eniac Ele gerava tanto calor que teve de ser instalado em um dos poucos espaos c da Universidade que possu sistemas de refrigeraao forada. Mais de 19000 a c c vlvulas, eram os elementos principais dos circuitos do computador. Ele tambm a e tinha quinze mil rels e centenas de milhares de resistores, capacitores e indue tores. Toda esta parafernlia eletrnica foi montada em quarenta e dois painis a o e com mais 2,70 metros de altura, 60 cent metros de largura e 30 cent metros de comprimento, montados na forma da letra U. Uma leitora de cartes perfurados o e uma perfuradora de cartes eram usados para entrada e sa de dados. o da Os tempos de execuao do ENIAC so mostrados na Tabela 1.2. Compare c a estes tempos com os tempos dos computadores atuais que esto na ordem de a nano segundos, ou 109 segundos. Operao ca soma multiplicaao c diviso a Tempo 200 s 2,8 ms 6,0 ms

Tabela 1.2: Tempo de execuao das instruoes aritmticas no ENIAC c c e Em 1939 John Vincent Atanaso e Cliord E. Berry, na Universidade Estadual de Iowa constru ram um prottipo de computador digital eletrnico, que o o usa aritmtica binria. Em 19 de outubro de 1973, o juiz federal Earl R. Larson e a assinou uma deciso, em seguida a uma longa batalha judicial, que declarava a

19

a patente do ENIAC de Mauchly e Eckert invlida e atribu a Atanaso a a a invenao computador eletrnico digital, o ABC ou Atanaso-Berry Computer. c o Na Inglaterra Jnos von Neumann, emigrante hngaro que vivia nos EUA, sugeriu que a a u memria do computador deveria ser usada para armazenar as instruoes do o c computador de maneira codicada, o conceito de programa armazenado. Esta idia foi fundamental para o progresso da computaao. Os primeiros computae c dores, como o ENIAC, eram programados por os que os cientistas usavam para conectar as diversas partes. Quando um programa terminava, estes cientistas trocavam os os de posiao de acordo com a nova tarefa a ser executada. Com c o programa armazenado na memria, juntamente com os dados, no era mais o a necessrio interromper as atividades. Carregava-se o programa na memria, a o uma tarefa extremamente rpida, junto com os dados e dava-se partida no proa grama. Ao trmino da execuao do programa passava-se imediatamente para a e c prxima tarefa sem interrupoes para troca de os. o c Em 1949, na Inglaterra, dois computadores que usavam a memria para o armazenar tanto programas como dados foram lanados. Na Universidade de c Cambridge foi lanado o EDSAC, (Electronic Delay Storage Automatic Calc culator) e em Manchester o computador chamado de Manchester Mark I. O EDSAC considerado o primeiro computador de programa armazenado a ser e lanado. Curiosamente, a Universidade de Manchester reivindica que o primeiro c computador de programa armazenado foi o chamado Baby, um prottipo do o Mark I, que comeou a operar onze meses antes do EDSAC. c Outro fato curioso em relaao ` Inglaterra e que foi divulgado recentemente c a relata que um computador chamado COLOSSUS entrou em operaao secrec tamente na Inglaterra em 1943. Este computador foi usado para auxiliar na quebra dos cdigos de criptograa alemes durante a segunda grande guerra. o a

1.2.4

As Geraes co

Costumava-se dividir os projetos de computadores em geraoes. Hoje em dia c como a taxa de evoluao muito grande no se usa mais este tipo de terminoloc e a gia. No entanto interessante mencionar estas divises. e o Primeira Gerao: Os computadores constru ca dos com rels e vlvulas so os e a a da primeira geraao. Estes computadores consumiam muita energia e c espao. c Segunda Gerao: Os computadores da segunda geraao foram constru ca c dos com transistores, os quais tinham a vantagem de serem mais compactos e consumirem muito menos energia. Por gerarem menos calor eram mquinas a mais conveis. a Terceira Gerao: Com o advento dos circuitos integrados, que so compoca a nentes em que vrios transistores so constru a a dos em uma mesma base de semicondutor, chegamos aos computadores de terceira geraao. Com c a integraao o tamanho dos computadores e seu consumo diminuiu ainda c mais e aumentou a capacidade de processamento. 20

Quarta Gerao: Os computadores de quarta geraao utilizavam circuitos ca c com a tecnologia (Very Large Scale Integration), que permitia uma escala de integraao de transistores muito grande. c

1.3

O Hardware

O hardware corresponde aos circuitos eletrnicos e componentes mecnicos que o a compem o computador. Um t o pico diagrama em blocos de um computador digital monoprocessado esta mostrado na Figura 1.7. A Unidade Central de Processamento (UCP), em ingls Central Processing Unit (CPU), como o e prprio nome diz, a unidade onde os dados so processados, ou seja alterados, o e a no computador. Ou seja, dentro das UCPs os dados so somados, subtra a dos etc. A UCP tambm controla a movimentaao dos dados dentro de todo o e c sistema. Os mdulos que constituem a UCP so os seguintes: o a Unidade de Controle (UC): comanda a operaao do computador. Esta unic dade l da memria tanto as instruoes como os dados e comanda todos e o c os circuitos para executar cada instruao lida da memria. Atualmente as c o unidades de controle so capazes de executar mais de uma instruao por a c ciclo de mquina, o que caracteriza o processamento paralelo. A tcnica a e mais comum para conseguir este paralelismo conhecida como pipelining, e que ser detalhada mais adiante. a Unidade Aritmtica e Lgica (UAL): local onde as transformaoes sobre e o c os dados acontecem. Atualmente esta unidade bastante sosticada e e diversos mtodos so empregadas para acelerar a execuao das instruoes. e a c c Alguns processadores duplicam circuitos para permitir que mais de uma operaao aritmtica seja executada por vez. E muito comum, por exemc e plo, a existncia de uma unidade aritmtica para executar instruoes que e e c operam sobre nmeros inteiros e outra sobre nmeros reais, chamada de u u unidade de ponto utuante. As vezes a UCP conta com mais de uma de cada uma destas unidades. Unidade de Entrada e Sa (UES): controla a comunicaao com os usuda c a rios do computador e os equipamentos perifricos tais como discos e ime pressoras. Em alguns computadores mais simples esta unidade no existe a independentemente, sendo distribu pela Unidade Central de Procesda samento. Em computadores mais poderosos ao contrrio as Unidades de a Entrada e Sa so computadores completos que foram programados para da a controlar a comunicaao com os perifricos. c e O termo pipelining que mencionamos acima se refere a um dos modos de como o processador pode paralelizar a execuao de instruoes. Este termo pode c c ser traduzido por linha de montagem, porque exatamente isto que a tcnica e e faz, uma linha de montagem de instruoes. Por exemplo, em uma linha de c montagem de uma fbrica de automveis, mais de um automvel montado a o o e ao mesmo tempo. No in da linha o carro no existe. Em cada estgio da cio a a linha de montagem os operrios vo adicionando partes e ao m da linha sai a a um carro novo. Se voc olhar a linha poder ver carros em diversos estgios da e a a 21

Unidade de Controle

Unidade de Entrada e Sada Memria Discos Vdeo

Unidade Arimtica

Unidade Central de Processamento

Figura 1.7: Diagrama Bsico de um Computador Digital a

montagem. Repare que a linha no pra, e a montagem de um carro no espera a a a que o que comeou a ser montado antes dele esteja terminado. Nas linhas de c montagem muitos carros so montados ao mesmo tempo. O efeito nal que a e cada carro continua levando bastante tempo para ser montado, mas como vrios a vo sendo montados ao mesmo tempo, algum que se colocasse no nal da linha a e de montagem teria a impresso que cada carro leva muito pouco tempo para a ser montado. Isto porque no nal da linha de montagem sai um carro a cada poucos minutos. O mesmo acontece com a linha de montagem de instruoes. c

1.3.1

Microcomputadores

Uma UCP integrada em um unico circuito (chip) comumente chamada de e microprocessador . Os microprocessadores atuais incluem outros circuitos que normalmente cavam fora da UCP, tais como processadores de ponto utuante e memrias cache. Alguns exemplos de microprocessadores so mostrados na o a Tabela 1.3 Microprocessador Arquitetura Intel X86 PowerPC Power MIPS ARM SPARC Empresa Intel, AMD Consrcio Apple/IBM/Motorola o IBM MIPS Technologies ARM Technologies SUN

Tabela 1.3: Exemplos de Microprocessadores

Usualmente se chama de computador, o processador mais os seus perifricos e e os sistemas para controlar estes perifricos, ou seja todo o sistema de procese samento de dados. Os perifricos so os dispositivos usados para fazer a entrada e a e sa dos dados que sero processados. da a Os microcomputadores so computadores baseados em microprocesa sadores. As assim chamadas placas me dos microprocessadores atuais ina 22

cluem diversos componentes que formam o microcomputador. Por exemplo, uma placa me pode incluir o microprocessador e seus circuitos de suporte, que, a no conjunto so conhecidos como o chipset. Alm disso a placa me pode incluir a e a tambm a memria principal e as placas de controle de perifricos, como a placa e o e de v deo, e os conectores para os perifricos, enm, quase todo o sistema. e

1.3.2

Memrias o

Os dados no computador podem ser armazenados em diversos n veis de memria o semicondutoras ou em perifricos (discos, tas, etc). Quanto mais rpida a e a memria, usualmente mais cara ela . A idia por traz da separaao em n o e e c veis colocar mais perto do processador, em memrias rpidas e mais caras, os e o a dados que o processador ir precisar mais freqentemente. A medida que vamos a u nos afastando do processador as memrias vo, ao mesmo tempo, cando mais o a baratas, aumentando de capacidade e diminuindo de velocidade. A Figura 1.8 ilustra esta hierarquia.

PROCESSADOR

MEMRIA
CACHE
REGISTRADORES

DISCO

Figura 1.8: N veis de hierarquia da memria de um computador. o No n mais prximo do processador esto os registradores , que, na vervel o a dade, cam internamente ao processador. So poucos e extremamente rpidos a a e, portanto, no podem armazenar grandes quantidades de dados. Somente os a dados que so necessrios ao processador com rapidez extraordinria devem ser a a a colocados nos registradores. Durante o processamento normal, na memria principal onde o processador e o busca instruoes e dados de um programa para executar. Alm da memria c e o principal esto os discos. Devido a sua velocidade menor que a da memria a o principal e a sua grande capacidade, os discos so considerados dispositivos de a armazenamento secundrio. Os discos tambm so memrias de armazenamento a e a o permanente, isto , quando os computadores so desligados o seu conte do se e a u mantm. Ao contrrio, a memria principal e os registradores so memrias e a o a o semicondutoras e perdem seus contedos quando a energia eltrica desligada. u e e Em alguns computadores os discos esto sendo substitu a dos por memrias semio condutoras. Para acelerar o acesso aos dados freqentemente usados, os computadores u dispem de memrias mais rpidas, porm de menor capacidade, que cam eno o a e tre os registradores e a memria principal. Estas funcionam como as bolsas ou o carteiras em que carregamos documentos e outros itens que precisamos freq enu temente. Este tipo de memria conhecido como memria cache. O cache o e o opera de forma invis para o processador. Ao pedir um dado para memria, vel o 23

circuitos especiais vericam se este dado est no cache, caso esteja, ele repasa e sado para o processador. Para o processador o que aconteceu que a memria e o entregou o dado com uma rapidez maior do que o normal. Uma memria como se fosse uma srie de cofres numerados capazes de o e e armazenar os dados, como est ilustrado na Figura 2.3. Os dados e instruoes a c na memria so apontados ou referenciados por estes nmeros, conhecidos como o a u endereos. Ou seja, para ler um dado da memria necessrio fornecer um c o e a endereo para que a memria possa encontrar e devolver o contedo pedido. Isto c o u similar ao o que ocorre quando enviamos uma carta, o endereo faz com que o e c carteiro saiba onde ele deve entregar a correspondncia. Em operaao normal, e c toda vez que o processador precisa de um dado ele envia um pedido de leitura a ` memria junto com o endereo da memria onde o dado est. Nas escritas o c o a o processador envia o endereo, o dado e pedido de escrita. Normalmente a c memria somente pode atender um pedido de cada vez. Portanto, para ler 1000 o nmeros o processador ter de fazer 1000 acessos seqencialmente. u a u Os dois tipos bsicos de memria mais comuns so ROM e RAM. Estas a o a siglas tm diversas variaoes (PROM, EPROM, DRAM, etc), mas os princ e c pios bsicos so os mesmos. Estas siglas indicam os dois tipos bsicos de memria a a a o que so usadas em computadores. A sigla bsica ROM signica Read Only a a Memory, ou seja, memria de somente de leitura. A outra sigla RAM (Random o Access Memory) signica memria de acesso randmico, portanto, memria que o o o se pode ler em qualquer endereo. c A sigla RAM muito confusa porque em uma memria ROM tambm se e o e pode ler em qualquer endereo. A diferena real que nas RAMs se pode ler e c c e escrever com a mesma velocidade em qualquer endereo, enquanto que na ROM, c o acesso rpido somente para leituras, a escrita uma histria mais complicada. e a e o A ROM normalmente contm dados que no podem ser modicados durante o e a funcionamento do computador. Outro tipo de dados armazenados em ROMs so a os que no devem ser perdidos quando o computador desligado. Exemplos de a e uso de ROM so as memrias que armazenam os programas que so executados a o a quando os computadores so ligados, os famosos BIOS (Basic Input Output a System). Um computador ao ser ligado deve ter um programa m nimo capaz de iniciar o seu funcionamento normal, caso contrrio seria como uma pessoa a que perdeu totalmente a memria. Para isto so escritos programas simples que o a fazem acesso aos perifricos em busca do Sistema Operacional da mquina. e a As primeiras memrias do tipo ROM eram gravadas nas fbricas e nunca o a mais eram modicadas. Isto trazia algumas diculdades, por exemplo, quando um programa precisava ser atualizado. Para resolver este tipo de problemas surgiram as PROMs, que so ROMs programveis. Ou seja poss desgravar a a e vel o contedo antigo e gravar novos programas nesta memria. Antigamente este u o era um processo complicado e exigia que a memria fosse retirada sicamente o do circuito e colocada em dispositivos especiais capazes de apagar o conte do u antigo. Em seguida um circuito programador de PROMs era usado para gravar o novo contedo e somente aps tudo isto a memria era recolocada no local. u o o O computador cava literalmente sem a memria dos programas iniciais. Hoje o em dia existem PROMs que podem ser apagadas e regravadas muito facilmente. Por exemplo, as EEPROMs (Eletricaly Erasable PROMs), que so memrias a o que podem ser apagadas eletricamente sem a necessidade de serem retiradas

24

dos circuitos. Flash memory uma forma de memria no voltil que pode e o a a ser apagada e reprogramada eletricamente. Diferentemente das EEPROMs, ela deve ser apagada em blocos de endereos. Este tipo de memria custa menos c o do que EEPROMs e portanto so preferidas quando necessrio usar memria a e a o no voltil em forma de circuitos integrados. a a As memrias RAMs so as memrias onde os nossos programas comuns o a o rodam. Elas so modicveis e de acesso rpido tanto na leitura quanto na a a a gravaao. Muitas siglas aparecem e desaparecem quando falamos de memrias c o RAM. Existem as DRAM, memrias EDO, SIMM, etc. Tudo isto ou se refere ao o mtodo de acesso dos dados na memria ou a tecnologia de construao ou a outra e o c caracter stica acessria. O certo que todas elas tem como caracter o e stica bsica a o fato dos acessos de leitura e escrita poderem ser feitos na mesma velocidade.

1.3.3

Bits e Bytes

A memria do computador composta de bits, a menor unidade de informaao o e c que o computador armazena. Um bit pode conter o valor 0 ou 1, que so os a d gitos usados na base dois, a base usada nos computadores. Um conjunto de 8 bits forma o byte. Uma palavra de memria um conjunto de bytes. o e Atualmente a maioria dos computadores tem palavras de memria com largura o de 32 (4 bytes) ou 64 (8 bytes) bits. Na Figura 1.9 mostramos os diversos tamanhos dos dados.
BIT

BYTE 8 BITS

PALAVRA 32 BITS 4 BYTES

Figura 1.9: Tamanho de Bits, Bytes e Palavras

Observar que estamos falando de dados na memria e no do tamanho dos o a dados que o computador pode processar. Considere que este tamanho relae cionado com a quantidade mxima de algarismos que um nmero pode ter para a u ser processado. Um computador pode ter capacidade de processar 64 bits de cada vez. Caso sua memria tenha palavras de 32 bits o processador dever, o a ento, ler duas palavras da memria para poder processar um n mero. Lembrea o u se que as duas leituras so atendidas uma de cada vez. Da mesma forma o a computador pode processar 32 bits de cada vez e a memria ter largura 64 bits. o Isto pode acelerar o processamento, j que o processador est se adiantando e a a recebendo o que poder ser o prximo dado a ser processado, ou seja econoa o mizando uma leitura. Devido a base 2 o fator kilo tem um signicado diferente em computaao. c Por exemplo 1 Kbyte de memria corresponde a 2 elevado a 10 (210 ), ou seja o

25

1024 bytes. Da mesma forma 1 Megabyte corresponde a 1024 x 1024 bytes e 1 Gigabyte igual a 1024 x 1024 x 1024 bytes. Na Tabela 1.4 esto mostradas as e a diversas abreviaoes usadas quando se fazem referncias `s memrias. c e a o Nome Kilobyte Megabyte Gigabyte Terabyte Petabyte Exabyte S mbolo Kb MB GB TB PB EB Multiplicador 210 = 1024 220 230 240 250 260

Tabela 1.4: Abreviaoes usadas em referncias `s memrias. c e a o

1.3.4

Perifricos e

Como j mencionamos antes, os dados no cam guardados somente na memria, a a o h tambm os perifricos . H perifricos de entrada, outros de sa e alguns a e e a e da que servem tanto para entrada como sa de dados. Perifricos no servem da e a somente para armazenar dados. H perifricos que so usados para permitir a a e a interaao entre os usurios e o computador. A tabela 1.5 ilustra alguns destes c a perifricos. e Entrada Teclados Mouse CD-ROM Scanner Sa da Impressoras V deo Plotter Alto-falantes Ambos Discos R gidos Fitas Magnticas e Disquetes Discos Zip

Tabela 1.5: Exemplos de perifricos e

1.4

O Software

Tudo isto que sobre o que acabamos de escrever constitui o hardware do computador, o que se v e o que se toca. A partir de agora falaremos brevemente e no software, o que no se v nem se toca, mas tambm est l. a e e a a Para que um computador execute alguma tarefa primeiro se desenvolve um algoritmo , que uma espcie de receita que diz precisamente, ao computae e dor, como o problema deve ser resolvido. Esta deniao informal de algoritmo c enganosamente simples, e a chave para entender o engano est nas palavras e a dizer precisamente ao computador. Por exemplo, uma receita em gastronomia normalmente no um algoritmo. Receitas so entendidas pela comunidade a e a de cozinheiros, que as seguem facilmente durante o preparo do prato. No entanto, receitas esto cheias de expresses como, por exemplo, mexer at car a o e 26

no ponto e colocar sal a gosto. Fora da comunidade de cozinheiros estas expresses so pass o a veis de vrias interpretaoes. Para escrever algoritmos prea c cisamos de uma linguagem matematicamente precisa e sem ambig idades. u A escrita de um algoritmo consta de uma deniao do estado inicial do c problema a ser resolvido e de regras precisas que estabelecem a cada instante os passos a serem seguidos. Como em um jogo, alm de denir os passos, so e a necessrias regras que denam se aps a execuao de um passo do algoritmo o a o c novo estado do problema vlido. As regras do xadrez denem o estado inicial e a do tabuleiro, os movimentos poss veis de cada pea e se aps um movimento c o de uma pea a conguraao atingida vlida. Ou seja precisamos vericar em c c e a cada instante qual dos movimentos (instruoes) pode ser usado. c Algoritmos podem ser chamados de procedimentos efetivos e devem obedecer aos seguintes limites: sempre dar alguma resposta; sempre dar a resposta correta e nunca uma resposta incorreta; terminar em um nmero nito de passos; u trabalhar em todos os exemplos da classe de problemas que o algoritmo se prope a resolver. o Em seguida este algoritmo deve ser traduzido para uma linguagem que possa ser entendida pelo computador ou que possa ser traduzida para esta linguagem. No in cio da computaao eletrnica com programas armazenados, estes eram c o escritos diretamente em linguagem de mquina que a linguagem que o coma e putador realmente entende. Estas instruoes so conjuntos de bits indicando c a a operaao que deve ser executada e, caso necessrio, onde como achar os dados c a que sero operados. Por esta razo tambm costuma-se dizer que so programas a a e a escritos em binrio. a Com a evoluao da computaao os programas passaram a ser escritos em c c assembly , que uma representaao em mnemnicos das instruoes de mquina. e c o c a Deste modo era mais fcil escrever os algoritmos. Por exemplo, um fragmento e a de um programa escrito em assembly do processador PowerPC : e li r3,4 * O primeiro numero a ser somado e 4. li r4,8 * 8 e o segundo numero add r5,r4,r3 * Some os contedos de r3 (4) e r4 (8) u * e armazene o resultado em r5 Este pequeno trecho de programa armazena os nmeros 4 e 5 em registradou res internos do processador em seguida os soma e armazena o resultado em um terceiro registrador. As informaoes aps os asteriscos so comentrios usados c o a a para explicar o que o programa est fazendo naquela instruao. a c O PowerPC um microprocessador criado em 1991 por um consrcio fore o mado pela IBM, Apple e Motorola Os microprocessadores PowerPC podem ser usados para equipar desde sistemas embutidos at computadores de alto deseme penho. A Apple usou este microprocessador para equipar suas mquinas at a e 2006.

27

Um programa escrito em assembly deve ser traduzido para a representaao c binria, tarefa que normalmente se chama de montar o programa. A palavra a assembler frequentemente usada erradamente para signicar a linguagem e e no o programa que traduz o programa de assembly para linguagem binria de a a mquina. Este tipo de programaao pode levar a se escrever programas muito a c ecientes, devido ao controle quase que total do programador sobre a mquina. a No entanto devido ao fato de ser uma linguagem prxima do computador e afaso tada da maneira de raciocinar do ser humano mais dif de ser usada. Alm e cil e deste fato h outros problemas tais como: diculdade de leitura por humanos, a diculdade de manutenao dos programas, maior tempo de desenvolvimento etc. c Para evitar estes problemas foram desenvolvidas as linguagens de programaao chamadas de linguagens de alto n c vel, por estarem mais prximas da o linguagem natural empregada pelos serem humanos. Alguns exemplos de linguagens de programaao so: c a Fortran: Usada em programaao cient c ca e engenharia; Pascal: Usada em ensino de linguagens e desenvolvimento de sistemas; COBOL: Usada em ambientes comerciais; Basic: O nome diz tudo, bsica; a C: Mesmas caracter sticas do Pascal com facilidades que permitem mais controle do computador; C++: Linguagem originria do C com metodologia de orientaao ` objetos; a c a Java: Linguagem tambm baseada na sintaxe do C e tambm seguindo o moe e delo de orientaao ` objetos. c a Delphi: Linguagem originria do Pascal com metodologia de orientaao ` oba c a jetos; Lisp e Prolog: Linguagens usadas para desenvolver programas de Inteligncia e Articial. Aplicativos importantes para os programadores so os compiladores. Estes a programas traduzem programas escritos em linguagens de alto n para a linvel guagem de mquina, de modo que o computador possa execut-los. De maneira a a geral um compilador um programa que traduz um programa de uma linguagem e para outra. Podemos resumir os passos necessrios para criar um programa em uma a linguagem de programaao, por exemplo C, nos passos descritos a seguir. A c Figura 1.10 ilustra a ordem em que se desenvolvem estes passos. Criao do Algoritmo: neste passo criado o algoritmo que ir resolver o ca e a problema. As diversas maneiras de descrever um algoritmo sero apresena tadas no prximo cap o tulo.

28

Codicao do Algoritmo: O algoritmo preparado no passo anterior esca e crito em uma linguagem de programaao. Neste passo o programador c conta, normalmente, com a ajuda de um editor de textos (no procesa sador de textos). Para esta ediao qualquer editor pode ser usado. Hoje c em dia muitos ambientes de desenvolvimento integram todas as ferramentas necessrias para criar um programa, inclusive o editor, em um unico a aplicativo. Compilao do Programa: O arquivo texto contendo o programa passa por ca um programa especial chamado compilador que gera, caso no hajam era ros, uma sa que quase o programa executvel, ou seja o programa em da e a cdigo binrio do processador em que ser executado. Os erros mais coo a a muns nesta etapa so erros de uso correto da linguagem de programaao. a c Estes erros so chamados de erros de compilaao. As linguagens de proa c gramaao so baseadas em regras gramaticais muito r c a gidas e qualquer violaao destas regras pode implicar em erro. No caso de erros serem c encontrados o programador deve voltar ao passo de codicaao para a c correao dos erros. c Ligao: Em ingls este passo conhecido por link edition. Um programa ca e e completo composto por vrios mdulos que podem ter sido criados pelo e a o prprio programador ou por outras programadores. Por exemplo, em C o os trechos de programa que interagem com os usurios, os comandos de a entrada e sa de dados, normalmente vm com o programa compilador. da e Estes trechos podem estar guardados em bibliotecas de programas e so a ligados ao programa do usurio para completar o programa. a Depurao e Testes: Nesta etapa o programa ser testado para a retirada ca a dos poss veis erros de lgica que o programador cometeu. Caso algum o erro de execuao seja encontrado o programador deve reelaborar o que c estiver errado no algoritmo e em seguida ir para a etapa de codicaao do c algoritmo. Este ciclo pode repetir-se inmeras vezes at que o desenvolveu e dor acredite que os erros foram corrigidos. Uso do Programa: O programa foi entregue aos seus usurios para ser usaa do. Durante o uso, erros que no foram encontrados durante o desenvolvia mento do programa podem ser descobertos e precisam ser corrigidos. A correao pode ser feita pelos mesmos programadores que desenvolveram o c programa ou por outro grupo devidamente treinado. Costuma-se chamar esta correao de manutenao do programa. c c Algumas linguagens de programaao no so compiladas e sim interpretadas. c a a Isto signica que o programa para ser executado no precisa ser traduzido direa tamente para linguagem de mquina, gerando um arquivo executvel. Este ara a quivo nal, se torna independente do programa fonte. Para executar o programa podemos usar somente o arquivo executvel. Em um programa interpretado a um aplicativo l o programa instruao por instruao, diretamente na prpria e c c o linguagem de alto n vel, traduz cada uma destas instruoes para linguagem de c mquina e as executa. No h, portanto, o processo de traduao antecipada a a a c do programa. A interpretaao de um programa funciona como o processo de c traduao simultnea do discurso de um orador. A medida que ele pronuncia seu c a 29

Incio Ligao

Criao de Algoritmo

Depurao e Testes

Codificao do Algoritmo

Sim

Erros de Execuo? No

Compilacao do Programa

Uso do programa

Sim Erros de Compilao? No

Sim Erros de Execuo?

Figura 1.10: Ciclo de desenvolvimento de um programa.

discurso um tradutor repete as frases na linguagem destino. Um programa compilado funciona como se primeiro, o tradutor traduzisse todo o discurso e depois o lesse. A linguagem Basic uma linguagem interpretada. Em Java ocorre um e processo um pouco diferente. Um programa em Java traduzido para uma line guagem intermediria e depois interpretado por meio de uma chamada mquina a a virtual. No h efetivamente uma compilaao para linguagem de mquina. A a a c a execuao de um programa escrito em uma linguagem interpretada mais lenta, c e j que o processo de interpretaao e execuao ao mesmo tempo mais lento do a c c e que a simples execuao de um programa traduzido antecipadamente. c Hoje em dia a maior parte dos usurios de computadores no so prograa a a madores e sim pessoas que usam programas para resolver seus problemas do dia a dia. Aplicativos t picos que rodam nos computadores so: editores de texto, a processadores de texto, planilhas eletrnicas, compiladores, bancos de dados, o jogos, etc. Para gerenciar os recursos do computador existe um programa especial normalmente chamado de Sistema Operacional (S. O.). Por exemplo, considere o problema de gerenciar como os diversos programas que um usurio normalmente a utiliza partilharo o processador do computador. Um usurio pode estar oua a vindo msica, digitando um texto e imprimindo um outro documento ao mesmo u tempo. Portanto, os computadores so capazes de executar um n mero de tarea u fas muito maior do que o nmero de processadores dispon u veis. Atualmente a maior parte dos computadores possui somente um processador. O Sistema Operacional controla a alocaao de recursos tais como: comunicaao com os c c usurios, espao em discos, uso de memria, tempo que cada programa pode roa c o dar etc. Alguns dos sistemas operacionais conhecidos so os baseados no padro a a UNIX, por exemplo o LINUX. Outros sistemas muito usados so os da fam a lia

30

Windows. Compilando Programas Simples em C Para resolver os exerc cios deste livro voc ir precisar de um compilador para a e a linguagem C e de um editor de textos simples (no processador como o Word). a O editor pode ser to simples quanto o Notepad, na verdade recomendamos a fortemente que o editor seja simples para que voc possa ter contato com todas e as etapas do processo de desenvolvimento de um programa. Para compilar empregaremos o compilador gcc que gratuito e pode ser obtido na Internet e como veremos adiante. No ser necessrio nenhum ambiente mais complexo, a a a tal como um Integrated Development Environment (IDE). A coleao de compiladores da GNU (GNU Compiler Collection) usualmente c abreviada por gcc, uma coleao de compiladores produzidos pelo projeto GNU. e c A abreviaao gcc, originalmente, signicava GNU C Compiler. Este aplicativo c distribu gratuitamente pela Free Software Foundation (FSF) sob a licena e do c GNU GPL e GNU LGPL. Este o compilador padro para os sistemas operae a cionais livres do tipo Unix, como o LINUX, e diversos sistemas operacionais proprietrios como o Apple Mac OS X. Atualmente o gcc pode compilar C++, a Objective-C, Java, Fortran e ADA, entre outras linguagens. Vamos considerar, como exemplo, um programa chamado teste.c. Para compilar e gerar o executvel para este programa digitamos o comando a gcc -o teste teste.c -Wall em uma janela de comandos no sistema Windows ou em um terminal nos sistemas Unix. O suxo .c no nome do programa normalmente usado para e indicar que o arquivo de um programa C. Este comando deve ser digitado e no diretrio onde est o arquivo fonte teste.c. O arquivo executvel ser aro a a a mazenado no mesmo diretrio. o Nos sistemas Unix normalmente o gcc faz parte da distribuiao padro e c a nada precisa ser feito. No Windows uma maneira fcil de obter uma verso a a do gcc instalar o MinGW (Minimalist GNU for Windows). MinGW uma e e coleao de arquivos e bibliotecas distribu c das livremente as quais combinadas com outras ferramentas da GNU permitem que programas para Windows sejam produzidos sem a necessidade de bibliotecas extras e pagas. O MinGW dispe de um programa instalador que facilita enormemente o processo. Este o programa pode ser obtido no s ocial do MinGW. Caso aps a instalaao, tio o c o comando indicado no funcione uma das razes para a falha pode ser que o a o sistema operacional no sabe onde se encontra o compilador gcc. Suponha que a o programa gcc foi instalado no diretrio C:\MinGW\bin. Uma soluao digitar o c e o caminho completo do compilador. Neste caso o comando se torna C:\MinGW\bin\gcc -o teste teste.c -Wall Para que no seja necessrio digitar o caminho completo, preciso adicionar a a e este caminho ` varivel PATH do Windows. Consulte o manual para obter ina a formaoes de como fazer este passo no seu sistema Windows. c

31

1.5

Um programa em C

Vamos terminar este cap tulo mostrando um exemplo simples de programa escrito em C(Listagem 1.1). A unica coisa que este programa faz imprimir Alo e Mundo! e terminar [1, 2, 3]. A primeira linha do programa avisa ao compilador que ir usar funoes de a c entrada e sa de dados guardadas na biblioteca stdio. Neste caso a funao da c usada printf. A segunda linha o in real do programa. A linha indica que e e cio esta a funao main que todo programa C deve conter, pois nesta funao que e c e c o programa obrigatoriamente comea sua execuao. A funo vai retornar um c c ca valor inteiro (int) ao nal de sua execuao e no vai precisar receber nenhum c a argumento para sua execuao (void). As chaves ({ e }) marcam o in e o c cio m da funao. Para imprimir o texto Alo Mundo! o programa usa a funao c c printf. O in e o m do texto a ser impresso so marcados pelo caractere ". cio a A funao termina com o comando return 0, que avisa ao sistema operacional, c que foi quem iniciou a execuao do programa, que o programa terminou sem c problemas. Este programa simples ilustra alguns das estruturas bsicas que a sero usadas nos programas C que sero apresentados neste livro. a a Listing 1.1: Exemplo de Programa em C.
#i ncl ude < stdio .h > i n t main ( void ) { printf ( " Alo Mundo !\ n " ); return 0; }

32

1.6

Exerc cios

1.1: O que o hardware do computador? e 1.2: Quais os principais componentes de um computador? 1.3: Quais as diferenas entre um microprocessador e o microcomputador? c 1.4: D exemplos de microprocessadores e de microcomputadores. e 1.5: Qual o nmero exato de bytes em 64 Kbytes? u 1.6: Se voc j usa computadores, liste alguns aplicativos que voc normalmente e a e usa. 1.7: Dena Sistema Operacional. 1.8: Qual a diferena bsica entre memrias ROM e RAM? c a o 1.9: Procure em manuais, internet e outras fontes quais so os tempos de acesso a das memrias RAMs atuais. o 1.10: Faa trs listas, uma de perifricos de entrada, outra de perifricos de c e e e sa e nalmente uma de perifricos de entrada e sa da e da. 1.11: Explique o que faz um compilador. 1.12: Discuta as vantagens e desvantagens das linguagens interpretadas e as compiladas. 1.13: O que so erros de compilaao e de execuao. a c c 1.14: Procure nomes de linguagens de programaao no listadas no texto e diga c a quais so as suas caracter a sticas principais.

33

Cap tulo 2

Algoritmos
2.1 Introduo ca

O objetivo deste cap tulo fazer uma breve introduao ao conceito de algorite c mos e apresentar algumas formas mais comuns de representar algoritmos para facilitar o entendimento dos demais cap tulos deste livro. Iremos apresentar as construoes mais comuns empregadas no desenvolvimento de algoritmos e aprec sentaremos exemplos bsicos de algoritmos usando algumas destas formas de a representaao e construoes. c c Para resolver um problema no computador necessrio que seja primeirae a mente encontrada uma maneira de descrever este problema de uma forma clara e precisa. E preciso que encontremos uma seqncia de passos que permitam ue que o problema possa ser resolvido de maneira automtica e repetitiva. Alm a e disto preciso denir como os dados que sero processados sero armazenae a a dos no computador. Portanto, a soluao de um problema por computador c e baseada em dois pontos: a seqncia de passos e a forma como os dados sero ue a armazenados no computador. Esta seqncia de passos chamada de algoritmo. ue e Usamos algoritmos em diversas atividades que realizamos diariamente. Uma grande parte destas atividades no esto relacionadas com computaao. Um a a c exemplo simples e prosaico, de como um problema pode ser resolvido caso forneamos uma seqncia de passos que mostrem a maneira de obter a soluao, c ue c uma receita para preparar um bolo. e Uma vez que foi criado um algoritmo para resolver um determinado problema usando computadores passamos para a prxima fase que a escrita deste o e algoritmo em alguma linguagem de programaao. c A noao de algoritmo central para toda a computaao. A criaao de algoc e c c ritmos para resolver os problemas uma das maiores diculdades dos iniciantes e em programaao em computadores. Isto porque no existe um conjunto de rec a gras, ou seja um algoritmo, que nos permita criar algoritmos. Caso isto fosse poss vel a funao de criador de algoritmos desapareceria. Claro que existem c linhas mestras e estruturas bsicas, a partir das quais podemos criar algorita mos, mas a soluao completa depende em grande parte do criador do algoritmo. c

34

Geralmente existem diversos algoritmos para resolver o mesmo problema, cada um segundo o ponto de vista do seu criador. No seu livro Fundamental Algorithms vol. 1 Donald Knuth [4] apresenta uma verso para a origem desta palavra. Ela seria derivada do nome de um a famoso matemtico persa chamado Abu Jafar Maom ibn Ms al-Khowrism a e ua a (825) que traduzido literalmente quer dizer Pai de Jafar, Maom, lho de e Moiss, de Khowrizm. Khowrizm hoje a cidade de Khiva, na ex Unio e a a e a Sovitica. Este autor escreveu um livro chamado Kitab al jabr wal-muqabala e (Regras de Restauraao e Reduao). O t c c tulo do livro deu origem tambm a e palavra Algebra. O signicado da palavra muito similar ao de uma receita, procedimento, e tcnica, rotina. Um algoritmo um conjunto nito de regras que e e fornece uma seqncia de operaoes para resolver um problema esue c pec co. Segundo o dicionrio do prof. Aurlio Buarque de Holanda um algoa e ritmo um: e Processo de clculo, ou de resoluao de um grupo de problemas a c semelhantes, em que se estipulam, com generalidade e sem restries, co regras formais para a obtenao de resultado ou de soluao de probc c lema. Um algoritmo opera sobre um conjunto de entradas (no caso do bolo, farinha ovos, fermento, etc.) de modo a gerar uma sa que seja util (ou agradvel) da a para o usurio (o bolo pronto). a Um algoritmo computacional tem cinco caracter sticas importantes: Finitude: Um algoritmo deve sempre terminar aps um nmero nito de paso u sos. Denio: Cada passo de um algoritmo deve ser precisamente denido. As ca aoes devem ser denidas rigorosamente e sem ambiguidades. c Entradas: Um algoritmo deve ter zero ou mais entradas. Entradas so as a quantidades que so lhe so fornecidas para processamento. a a Sa das: Um algoritmo deve ter uma ou mais sa das, isto quantidades que tem e uma relaao espec c ca com as entradas. Efetividade: Um algoritmo deve ser efetivo. Isto signica que todas as operac oes devem ser sucientemente bsicas de modo que possam ser, em princ a pio, executadas com preciso em um tempo nito por um humano usando a papel e lpis. a

2.2

Primeiros Passos

E claro que todos ns sabemos construir algoritmos. Se isto no fosse verdade, o a no conseguir a amos sair de casa pela manh, ir ao trabalho, decidir qual o melhor a caminho para chegar a um lugar, voltar para casa, etc. Para que tudo isto seja feito necessrio uma srie de entradas do tipo: a que hora acordar, que hora e a e 35

sair de casa, qual o melhor meio de transporte etc. Um fator importante e que pode haver mais de um algoritmo para resolver um determinado problema. Por exemplo, para ir de casa at o trabalho, posso escolher diversos meios de e transporte em funao do preo, conforto, rapidez, etc. A escolha ser feita em c c a funao do critrio que melhor se adequar as nossas necessidades. Um exemplo c e de algoritmo pode ser as instruoes que um professor passa aos seus alunos em c uma academia de ginstica, mostrado no Algoritmo 2.1. Observar que nesta a representaao do algoritmo cada linha contm uma instruao. c e c Algoritmo 2.1: Exemplo de Algoritmo. in cio enquanto no fez 10 vezes faa a c Levantar e abaixar brao direito c Levantar e abaixar brao esquerdo c Levantar e abaixar perna esquerda Levantar e abaixar perna direita m enqto m Computadores so mquinas muito ecientes na resoluao de problemas a a c matemticos ou que envolvam nmeros. Como exemplo de um algoritmo matea u mtico, vamos considerar o problema de resolver uma equaao do primeiro grau a c da forma ax + b = 0 A soluao desta equaao c c e x = b/a se o valor de a for diferente de 0. Caso a seja igual a 0, a equaao no possui c a soluao, j que no poss dividir por 0. Este algoritmo escrito (Algoritmo c a a e vel 2.2) em uma pseudo-linguagem de programaao caria da seguinte maneira: c Algoritmo 2.2: Algoritmo para resolver uma equaao do primeiro grau. c Entrada: Coecientes a e b da equaao ax + b = 0 c Sa da: Resultado x da Equaao c in cio ler a ler b se a = 0 ento a imprimir A equa~o nao tem solu~o ca ca seno a x b/a imprimir A raiz da equa~o vale , x ca m se m As instruoes do algoritmo so executadas passo a passo e uma instruao c a c somente executada quando a anterior terminou sua tarefa. Os dois primeiros e passos do algoritmo servem para o algoritmo obter os valores dos coecientes a e

36

b. Os valores podem, por exemplo, serem digitados em um teclado pelo usurio a que est usando o algoritmo. O valor digitado vai para uma posiao da memria a c o do computador, que para facilitar o manuseio do dado, recebe um nome. Neste exemplo demos os nomes a, b e x as posioes de memria usadas pelo programa c o para armazenar dados. Aps os dois primeiros passos o algoritmo executa uma o instruao de teste para vericar se o valor de a diferente de 0. Neste caso c e podemos ter duas respostas e o computador ir escolher entre dois caminhos a independentes e exclusivos. Caso a seja igual a zero, o algoritmo executa as instruoes entre a palavra ent~o e sen~o, e portanto, imprime uma mensagem c a a de aviso para o usurio e termina. Esta mensagem normalmente aparece em a um monitor de v deo. No caso de a ser diferente de zero, o algoritmo executa as instruoes entre sen~o e fim se. Isto signica calcular o resultado da equaao c a c e atribuir este resultado ` x. O ultimo passo, desta opao a impresso do a c e a resultado da equaao. c

2.3

Representao ca

As formas mais comuns de representaao de algoritmos so as seguintes: c a Linguagem Natural: Os algoritmos so expressos diretamente em linguagem a natural, como nos exemplos anteriores. Fluxograma Convencional: Esta um representaao grca que emprega e c a formas geomtricas padronizadas para indicar as diversas aoes e decises e c o que devem ser executadas para resolver o problema. Pseudo-linguagem: Emprega uma linguagem intermediria entre a linguagem a natural e uma linguagem de programaao para descrever os algoritmos. c No existe consenso entre os especialistas sobre qual seria a melhor maneira a de representar um algoritmo. Atualmente a maneira mais comum de representarse algoritmos atravs de uma pseudo-linguagem ou pseudo-cdigo. Esta forma e e o de representaao tem a vantagem de fazer com que o algoritmo seja escrito de c uma forma que est mais prxima de uma linguagem de programao de coma o ca putadores.

2.3.1

Linguagem Natural

A representaao em linguagem natural tem a desvantagem de colocar uma c grande distncia entre a soluao encontrada e o resultado nal do processo a c que um programa em linguagem de programaao. O Algoritmo 2.3 mostra e c um algoritmo, escrito em linguagem natural, para calcular a mdia de um aluno e que faz trs provas e precisa de obter mdia acima de 5.0 para ser aprovado. e e

2.3.2

Fluxogramas

Esta forma de representaao de algoritmos emprega vrias formas geomtricas c a e para descrever cada uma das poss veis aoes durante a execuao do algoritc c mos. Existem algumas formas geomtricas que usualmente so empregadas e a 37

Algoritmo 2.3: Algoritmo para calcular a mdia das notas de um aluno. e Entrada: Notas n1 , n2 e n3 . Sa da: Resultado media do aluno e se ele foi aprovado ou no. a in cio Obter as notas n1 , n2 e n3 Calcular mdia. Usar a frmula ((n1 + n2 + n3 )/3.0). e o Se a mdia for maior que 5.0 imprimir que o aluno foi aprovado e Caso contrrio imprimir que o aluno foi reprovado. a Imprimir a mdia. e m neste mtodo. Estas formas esto mostradas na Figura 2.1. Cada uma destas e a formas se aplica a uma determinada aao como est indicado na gura. Estas c a formas so apenas alguns exemplos, existindo outras, no entanto, nesta apostila a estas sero sucientes para os exemplos que sero mostrados. a a
Incio e Fim de Fluxograma Processamento

Ponto de Deciso

Entrada de Dados Manual

Impresso de Resultados

Conector para mesma pgina

Figura 2.1: S mbolos mais comumente usados em uxogramas. Como exemplo de um algoritmo escrito em forma de uxograma, vamos considerar o algoritmo 2.2 para resolver uma equaao do primeiro grau da forma c ax + b = 0. A Figura 2.2 mostra um uxograma para resolver este problema. Os dois primeiros passos do algoritmo lem os valores dos coecientes a e e b da equaao. Em seguida h um teste para descobrir se o valor de a igual c a e a zero. Se o valor de a for igual a zero o algoritmo manda que seja impressa uma mensagem informando que a equaao no tem soluao. Caso o valor de c a c a seja diferente os prximos passos calculam o valor da soluao e em seguida o c imprimem este resultado

2.3.3

Pseudo-Linguagem

Este modo de representar algoritmos procura empregar uma linguagem que esteja o mais prximo poss de uma linguagem de programaao de computao vel c dores de alto n vel, mas evitando de denir regras de construao gramatical c muito r gidas. A idia usar as vantagens do emprego da linguagem natural, e e mas restringindo o escopo da linguagem. Normalmente estas linguagens so a verses ultra reduzidas de linguagens de alto n do tipo Pascal ou C. O algoo vel ritmo 2.2 foi escrito em uma pseudo-linguagem. A maioria destas linguagens so a muito parecidas e tm a vantagem de serem facilmente entendidas. Vamos ape resentar agora um outro exemplo (Algoritmo 2.4) escrito em pseudo-linguagem. 38

Incio

Obter a

Obter b

Sim a =0 No x=-b/a No h razes reais

Imprime x

Fim

Figura 2.2: Fluxograma para resolver uma equaao do primeiro grau. c

Este algoritmo serve para descobrir qual a maior nota de um grupo de trs e e notas de um aluno. O algoritmo inicialmente l a primeira nota e guarda esta e nota como a maior nota. Em seguida, l cada uma das outras notas e compara e com a nota guardada como a maior nota. Caso a nota lida seja maior substitui o valor anterior pelo novo valor. Apesar destas pseudo-linguagens terem poucas regras existem algumas que normalmente so usadas para facilitar o entendimento entre os programadores. a Vamos detalhar algumas delas. As palavras in cio e m indicam onde comea c e termina o algoritmo. As palavras em negrito indicam instruoes que devem c ser executadas pelo computador onde o algoritmo ser rodado. Por exemplo, a ler notaAluno uma instruao do algoritmo que ordena ao computador para e c obter a nota de um aluno para ser processada. Em algoritmos esta nota normalmente ser obtida de um perifrico de entrada de dados, sendo mais comum a e o teclado. As palavras em itlico so normalmente chamadas de variveis e a a a representam locais na memria do computador onde os valores a serem usados o durante o processamento esto armazenados. Os programadores podem incluir a nos algoritmos explicaoes que facilitem o entendimento do seu funcionamento. c Estes comentrios no so executados pelos computadores e somente so lidos a a a a pelos programadores. Existem diversas maneiras de indicar que o texto no algoritmo apenas um comentrio. Neste exemplo usamos dois caracteres -- para e a indicar que o restante da linha apenas um comentrio. Mais adiante outras e a explicaoes sero apresentadas. c a

39

Algoritmo 2.4: Algoritmo para calcular a maior nota de um grupo de notas. Entrada: Trs notas de um aluno, (notaAluno). e Sa da: Maior das notas do aluno, (maiorN ota) in cio -- L^ primeira nota e ler notaAluno maiorN ota notaAluno -- L^ segunda nota e ler notaAluno se notaAluno > maiorN ota ento a maiorN ota notaAluno m se -- L^ terceira nota e ler notaAluno se notaAluno > maiorN ota ento a maiorN ota notaAluno m se imprimir A maior nota das notas , maiorN ota e m

2.4

Modelo de von Neumann

Algoritmos para computadores se baseiam em alguns conceitos bsicos e em um a modelo de computador, os quais devem ser bem entendidos para que se possa criar algoritmos ecientes. Este modelo foi proposto pelo matemtico h ngaro a u Neumann Jnos Lajos Margittai. Em hngaro o nome de fam aparece antes. a u lia Assim em portugus o seu nome seria Jnos Lajos Margittai Neumann. O seu e a pai, que era rico, comprou um t tulo de nobreza e ele passou a se chamar Jnos a Lajos Margittai von Neumann. No modelo de computador proposto por von Neumann as instruoes e os dados cam juntos na memria. O processador c o busca na memria e executa uma instruao de cada vez. o c Para ilustrar como este modelo funciona vamos analisar passo a passo a execuao de um algoritmo simples. Na Figura 2.3 mostramos nos endereos c c 0, 1 e 2, de uma memria, um grupo de instruoes formando parte de um o c algoritmo. As instruoes tambm podem ser acompanhadas no Algoritmo 2.5. c e Vamos assumir que o computador inicie executando o algoritmo a partir da instruao que est no endereo 0. O procedimento normal a Unidade de c a c e Controle (UC) do computador continuar buscando e executando uma instruao c de cada vez nos endereos seguintes, a no ser que haja uma ordem para desviar c a o uxo das instruoes. E importante observar que o computador executa uma c instruao de cada vez, e como veremos adiante, tambm um dado buscado de c e e cada vez. Portanto, as transferncias entre a memria e o processador so feitas e o a passo a passo. O ciclo normal da execuao de um programa ento: c e a 1. Busca instruao; c 2. Decodica instruao; c

40

3. Executa instruao; c 4. Volta para o passo 1 buscando a instruao seguinte na memria. c o Portanto, aps a instruao do endereo 0 ser lida da memria e trazida para o c c o a UCP, ela decodicada pela UC, que descobre que a instruao manda carregar e c o valor inteiro 2 na posiao de memria 10, que chamada de a para facilitar. c o e A instruao seguinte ordena a carga do valor inteiro 8 na posiao de memria c c o chamada de b, que a posiao 11. A ultima instruao ordena a soma dos valores e c c armazenados em a e b e que o resultado seja armazenado na posiao 12, que c e chamada c. Algoritmo 2.5: Modelo de memria e funcionamento de um algoritmo o -- Armazena 2 na memria no lugar chamado a o a2 -- Armazena 8 na memria no lugar chamado b o b8 -- Soma a com b e armazena no lugar chamado c ca+b Observe que no modelo de von Neumann instruoes e dados cam na memria. c o Considere a ultima instruao do programa que pede para que os dados da posiao c c 10 (a) e 11 (b) sejam somados e o resultado armazenado na posiao 12 (c). Para c executar esta instruao, o computador faz as seguintes operaoes na memria: c c o 1. ler a instruao no endereo 2; c c 2. ler o dado a na posiao 10; c 3. ler o dado b na posiao 11; c 4. escrever o resultado da soma no endereo 12. c Portanto, temos 3 leituras e uma escrita. Destas operaoes, a primeira c e uma leitura de instruao e as restantes operaoes com dados. c c

2.5

Estruturas Bsicas de Algoritmos a

Com a nalidade de ilustrar como criar algoritmos para computadores usando este modelo, vamos discutir alguns tipos bsicos de estruturas usados nesta a tarefa. Para isto, iremos usar a representaao que for apropriada no momento. c No iremos neste livro discutir em detalhes estes tpicos, nem apresentar de uma a o maneira formal qualquer uma destas formas. O interesse apenas apresentar e e discutir algumas estruturas bsicas para ilustrar o pensamento usado pelos proa gramadores quando criam um algoritmo para resolver um problema espec co. Estas estruturas so importantes e sero reapresentadas quando formos aprea a sentar a linguagem C. Para o programador iniciante esta discusso serve como a introduao. c

41

a<-2
8

b<-8
9

c<-a+b
10 11 12 13 14 15

2
16 17 18

8
19

10
20 21 22 23

24

25

26

27

28

29

30

31

Endereo Endereo Endereo Endereo Endereo Endereo

0: Instruo a <--2 1: Instruo b <--8 2: Instruo c <--a+b 10: Dado a 11: Dado b 12: Dado c

Figura 2.3: Modelo de memria o

2.5.1

Comandos de leitura

Estes comandos servem para obter dados do mundo exterior, normalmente digitados por um usurio em um teclado. Outros exemplos de lugares de onde a podem ser obtidos dados so os arquivos em discos r a gidos, disquetes e tas magnticas. Estes dados so lidos e guardados na memria para posterior uso. e a o Normalmente os lugares para onde vo estes dados recebem um nome para a facilitar o seu manuseio durante a execuao do algoritmo. c Por exemplo, o comando ler a signica que o algoritmo ir obter um dado do teclado e ir armazen-lo em uma a a a posiao de memria que passar a ser conhecida pelo nome a. Estas posioes c o a c so conhecidas por variveis em computaao. Costuma-se dizer ento que a a a c a e uma varivel do algoritmo. Apesar de a no algoritmo 2.2 representar uma das a constantes da equaao do primeiro grau no algoritmo ela uma das variveis. c e a Observe que cada vez que o algoritmo executado a pode assumir um valor e diferente, portanto varia de acordo com a execuao do algoritmo. c O comando pode ser seguido por uma lista de nomes separados por v rgulas. Por exemplo o comando ler a, b l dois valores do teclado e os atribui as variveis a e b. Observe que a ordem em e a que os valores foram digitados determina como os valores sero atribu a dos. O primeiro valor lido atribu a primeira varivel, no caso a. O segundo valor e do a lido atribu a segunda varivel (b). Os valores normalmente so digitados e do a a separados por um ou mais espaos em branco ou em linhas diferentes. c

2.5.2

Comandos de escrita

Aps a obtenao dos resultados do algoritmo, estes devem ser apresentados ao o c usurio, e para isto usamos os comandos de escrita. Por exemplo o comando a 42

imprimir x imprime o valor atual que est na memria representada pelo nome x. a o Da mesma forma que nos comandos de leitura poss colocar uma lista e vel de nomes de variveis aps o comando. Por exemplo, o comando a o imprimir x1, x2 imprime os valores das variveis x1 e x2. O meio de apresentaao dos resultados, a c normalmente, um monitor de v e deo. O comando imprimir pode ser usado para mandar mensagens de texto para o usurio do algoritmo das formas mais variadas. Alguns exemplos de a comandos de impresso so os seguintes: a a

imprimir Entre com o valor do coeciente imprimir O valor de x , x e imprimir O valor de x1 , x1, e o de x2 , x2 e e Notar que os textos entre aspas indicam um texto que deve ser impresso no perifrico de sa sem nenhuma modicaao. Vamos considerar que as variveis e da c a destes exemplos valem x = 10, x1 = 5 e x2 = 8. Os trs comandos mostrariam e no perifrico de sa os seguintes resultados: e da Entre com o valor do coeficiente. O valor de x 10 e O valor de x1 5 e o de x2 8 e e

2.5.3

Expresses o

Expresses so usadas para denir os clculos requeridos pelo algoritmo, por o a a exemplo b/a. Iremos discutir dois tipos bsicos de expresses: expresses arita o o mticas e expresses lgicas. e o o Expresses manipulam dados dentro dos algoritmos. Uma pergunta imporo tante neste momento : que tipo de dados poderemos manipular? As linguagens e de programaao normalmente estabelecem regras precisas para denir que tipos c de dados elas iro manipular. Nesta discusso vamos estabelecer, ainda que a a informalmente, algumas regras que limitam os conjuntos de dados existentes na Matemtica e estabelecem que dados podero ser manipulados pelos algoritmos. a a Isto ocorre porque os computadores possuem limitaoes que os impedem de mac nipular todos os tipos de dados que um ser humano pode tratar. Mais adiante, quando formos estudar a linguagem C iremos apresentar mais formalmente as regras desta linguagem para estas representaoes. Existem trs tipos bsicos de c e a dados que iremos discutir: Dados numricos: como o nome indica so os nmeros que sero operados. e a u a Dados alfa-numricos: so os dados representados por caracteres. Como care a acteres podem ser letras, algarismos e sinais diversos estes dados recebem este nome. 43

Dados Lgicos: estes dados podem assumir dois valores verdadeiro e falso. o Estes dados resultam de expresses do tipo x > 0. o Os dados numricos que os algoritmos que iremos construir podem manipular e so de dois tipos: inteiros e reais. So exemplos de nmeros inteiros: a a u +3 3 -324 -50 So exemplos de nmeros reais: a u +0.5 0.5 -8.175 2.0 Dados alfa-numricos servem para tratamento de textos e normalmente so e a compostos por uma seqncia de caracteres contendo letras, algarismos e caue racteres de pontuaao. Nos algoritmos so normalmente representados por uma c a seqncia de caracteres entre aspas, por exemplo: ue Linguagem de programa~o ca Qual o seu nome? e 12345 Dados lgicos so intensamente aplicados durante o processo de tomada o a de decises que o computador frequentemente obrigado a fazer. Em muitos o e textos este tipo de dados tambm chamado de tipo de dados booleanos, devido e e a George Boole, matemtico que deu ao nome ` lgebra (lgebra booleana) que a aa a manipula este tipo de dados. Os dados deste tipo somente podem assumir dois valores: verdadeiro e falso. Computadores tomam decises, durante o o processamento de um algoritmo, baseados nestes dois valores. Por exemplo, considere a deciso abaixo: a

se a = 0 ento a imprimir A equa~o nao tem solu~o ca ca seno a x b/a imprimir A raiz da equa~o vale , x ca m se Neste algoritmo aparece a expresso a = 0, que procura descobrir se o valor a de raiz igual a 0. Esta expresso somente pode ter como resultado os valores: e a verdadeiro ou falso. Nos nossos algoritmos estes valores sero representados por a verdadeiro e falso.

44

Expresses Aritmticas o e Para os nossos exemplos iniciais iremos adotar os operadores aritmticos binrios e a mostrados na Tabela 2.1. A coluna prioridade indica a prioridade relativa dos operandos. O menor nmero indica a maior prioridade. Quando temos dois u operandos de mesma prioridade o computador ir executar primeiro a operaao a c mais ` esquerda. Em computaao, as expresses devem ser escritas em lina c o has e para alterar a prioridade deve-se usar parnteses. Maiores detalhes sobre e expresses sero apresentados no Cap o a tulo 5. No momento, estamos apenas apresentando alguns conceitos bsicos para facilitar a discusso de alguns algoa a ritmos. Operador / * % + Descrio ca Diviso a Multiplicaao c Mdulo (resto da diviso de o a operandos inteiros) Soma Subtraao c Prioridade 0 0 0 1 1

Tabela 2.1: Operadores Aritmticos. e Para ilustrar o uso de operadores aritmticos vamos considerar alguns exe emplos de expresses. Os exemplos a seguir mostram como converter uma exo presso matemtica para a forma que usaremos em pseudo-linguagem. Observer a a o uso de parnteses para alterar a prioridade das operaoes. e c Expresso a Matemtica a
a b+c a+b c+d 2

b 4ac
1 1 1+ a+b

Expresso em a Pseudo-linguagem a/(b+c) (a+b)/(c+d) b*b-4*a*c 1/(1 + 1/(a+b))

2.5.4

Comandos de atribuio ca

Servem para atribuir valores ` posioes de memria. Normalmente estes valores a c o podem ser constantes ou resultados de expresses dos diversos tipos. Exemplos o de comandos de atribuiao so mostrados a seguir. c a x b/a media (n1 + n2)/2 inicio 0 nome Ze Sa ii+1 A seta aponta sempre da direita para a esquerda. O valor ou o resultado da expresso a direita da seta armazenado na varivel que est no lado esa e a a querdo da seta. A direao da seta no pode ser alterada. No caso da ultima c a 45

expresso temos que o valor atual de i incrementado e depois substitui este a e valor, portanto, se ele valia 10, ao nal da instruao ele vale 11. c

2.5.5

Comandos de controle

So usados para controlar o uxo de execuao das instruoes. Nas linguagens a c c de programaao existem diversos tipos de comandos de controle. Para estes exc emplos iniciais vamos mostrar somente o comando mais bsico que serve para o a computador escolher entre dois poss veis caminhos qual o algoritmo deve seguir. Este comando, representado em uxograma, pode ser visto na Figura 2.4 e em pseudo linguagem tem a forma mostrada no algoritmo 2.6.

Algoritmando

Falso Condio

Verdadeiro

Faa isto

Faa aquilo

Continuo algoritmando

Figura 2.4: Fluxograma do comando se ...

ent~o ... a

sen~o. a

Algoritmo 2.6: Comando se em pseudo-linguagem se Condio sendo testada ento ca a Faa isto c seno a Faa aquilo c m se Um exemplo de uso desta construao, escolhido a partir da vida real, pode c ser o seguinte. Tenho que decidir o que fazer em um domingo de folga. Se estiver chovendo irei ao cinema, caso contrrio irei ` praia. Observe que para a a ir para a praia basta apenas que no esteja chovendo, nenhum outro teste foi a

46

feito. Esta deciso em forma de pseudo-linguagem ca da maneira mostrada no a Algoritmo 2.7. Algoritmo 2.7: Algoritmo para decidir o que fazer no domingo. se est chovendo ento a a vou ao cinema seno a vou ` praia a m se Nem sempre nos algoritmos precisamos de duas alternativas. As vezes precisamos somente de decidir se devemos fazer algo ou no Por exemplo, vamos a assumir que decidimos ir ao cinema no domingo chova ou faa sol. No enc tanto, preciso decidir se levo um guarda-chuva. O algoritmo para este caso est a mostrado no Algoritmo 2.8. Observe que no caso de no estar chovendo nada a precisa ser feito. A Figura 2.5 mostra esta deciso em forma de uxograma. a Algoritmo 2.8: Algoritmo para decidir se deve levar um guarda-chuva. Vestir para ir ao cinena se est chovendo ento a a pego guarda-chuva m se Vou ao cinema

2.5.6

Comandos de repetio ca

As linguagens de programaao normalmente possuem diversos comandos que c permitem que um trecho de algoritmo seja repetido um nmero de vezes. Para u estes exemplos iniciais iremos apresentar um comando de repetiao que suc e cientemente geral para substituir todos os outros. Este comando, que chamaremos de comando enquanto tem a forma mostrada na Figura 2.6. O comando funciona da seguinte maneira: Passo 1: Testar se a condiao verdadeira. Caso seja verdade executar o bloco c e de comandos situados entre o in do comando e o nal do comando. O cio nal do comando enquanto normalmente marcado de alguma forma. Em e nossa pseudo-linguagem marcaremos o m pelas palavras fim enquanto ou fim eqto. Passo 2: Executar o bloco de comandos at o m do enquanto. Quando chegar e ao m retornar automaticamente para o in cio do comando e refazer o passo 1. Como exemplo consideremos o caso em que precisamos ler um conjunto de 10 nmeros e imprimir se cada um dos nmeros lidos par ou no. Para descobrir u u e a se o nmero par vamos dividi-lo por 2 e testar o resto. Para simplicar, u e vamos considerar que caso o resto da diviso seja igual a zero o n mero par. a u e 47

Vestir para ir ao cinema

Falso Chovendo?

Verdadeiro

Pegar guarda-chuva

Ir ao cinema

Figura 2.5: Fluxograma para decidir se deve levar um guarda-chuva.

Neste algoritmo sabemos a quantidade de nmeros a serem lidos e portanto o u nmero de repetioes pr-determinado. O Algoritmo 2.9 mostra como seria u c e e implementada uma soluao para este problema. c Vamos mostrar um exemplo onde o nmero de repetioes no conhecido. u c a e Considere no exemplo anterior que o total de nmeros a ser lido no conhecido. u a e Mas ento, como o algoritmo ir terminar de ler nmeros? Usaremos o que a a u costuma-se chamar de sentinela em computaao. O algoritmo ir se manter c a lendo nmeros enquanto os nmeros forem positivos. No momento que for u u lido um nmero negativo o algoritmo pra. A sentinela que indica o nal da u a lista de nmeros um nmero negativo. O Algoritmo 2.10 mostra como ca u e u em pseudo-linguagem o algoritmo modicado. Observe que neste algoritmo o primeiro nmero tem de ser lido antes do comando enquanto. Isto porque u assumimos que o primeiro nmero que for digitado pode ser negativo e portanto u a lista de nmeros no tem nenhum nmero. u a u

2.6

Exemplos de Algoritmos

Nesta seao iremos apresentar uma srie de algoritmos escritos na pseudoc e linguagem que acabamos de apresentar. Exemplo 2.1: Este algoritmo serve para descobrir qual a maior nota de uma e turma de alunos. Neste algoritmo iremos considerar que as notas podem variar entre 0.0 e 10.0 e que a turma tem 25 alunos. O algoritmo 2.11 inicialmente inicia a maiorN ota com zero, depois compara cada nota com esta maiorN ota caso ela seja maior substitui o valor anterior pelo novo valor. Observar que 48

Algoritmo 2.9: Algoritmo para ler 10 nmeros e imprimir se so pares u a ou no. a Entrada: 10 nmeros, (numero). u Sa da: Se o nmero par ou no u e a in cio totalN umeros 10 enquanto totalN umeros > 0 faa c ler numero se numero%2 = 0 ento a imprimir numero, par seno a imprimir numero, impar m se totalN umeros totalN umeros 1 m enqto m

Algoritmo 2.10: Algoritmo para ler nmeros e imprimir se so pares ou u a no. A quantidade de nmeros a ser lida desconhecida. a u e Entrada: nmeros, (numero). O algoritmo para quando um n mero u u negativo lido e Sa da: Se o nmero par ou no u e a in cio ler numero enquanto numero > 0 faa c se numero % 2 = 0 ento a imprimir numero, par seno a imprimir numero, impar m se ler numero m enqto m

49

Algoritmando

Falso Testa Condio

Verdadeiro

Bloco de comandos do enquanto

Continuo algoritmando

Figura 2.6: Fluxograma do comando enquanto.

criamos uma varivel para armazenar a quantidade de alunos. Voc poderia a e perguntar porque no usar o nmero 25 toda vez que for necessrio. A razo a u a a e simples. Suponha que voc gostaria de usar este algoritmo para calcular a maior e nota de uma turma de 40 alunos. Neste algoritmo bastaria substituir o n mero u 25 por 40. No entanto, existe uma soluao mais geral ainda que permite que c o algoritmo possa ser usado para qualquer tamanho de turma. Este problema est apresentado na lista de exerc a cios deste cap tulo. Exemplo 2.2: Vamos mostrar outro exemplo de algoritmo muito usado. Precisamos ler as notas de uma turma de alunos e calcular a mdia destas notas. e Vamos assumir que a turma tem 25 alunos e as notas esto entre 0 e 10. O a algoritmo est mostrado em Algoritmo 2.12. a Exemplo 2.3: Neste exemplo considere o seguinte problema. Um escritrio de o previso do tempo armazena diariamente a temperatura mdia de uma detera e minada regio. A tarefa descobrir qual a maior temperatura do ano passado. a e e Assuma que foram armazenadas 365 temperaturas, uma para cada dia do ano. Neste caso no podemos aplicar o algoritmo 2.11 usado para descobrir a maior a nota da turma. Antes de continuar procure encontrar a razo. Como dica, a considere que estamos no plo sul e portanto todas as temperaturas lidas so o a negativas. Uma soluao poss c vel para este exemplo est mostrada no algoritmo 2.13. a Este algoritmo faz o seguinte. Pega a primeira temperatura e a anota como a maior j encontrada. A partir da o algoritmo ca repetidamente lendo tema peraturas dos registros do escritrio comparando com a temperatura que no o 50

Algoritmo 2.11: Algoritmo para calcular a maior nota de uma turma de 25 alunos. Entrada: Nota de cada um dos dos 25 alunos da turma, (notaAluno). Sa da: Maior das notas dos alunos, (maiorN ota) in cio totalAlunos 25 maiorN ota 0.0 enquanto totalAlunos > 0 faa c ler notaAluno se notaAluno > maiorN ota ento a maiorN ota notaAluno m se totalAlunos totalAlunos 1 m enqto imprimir A maior nota das notas , maiorN ota e m

Algoritmo 2.12: Algoritmo para calcular a nota mdia de uma turma de e 25 alunos. Entrada: Nota de cada um dos dos 25 alunos da turma, (notaAluno). Sa da: Mdia das notas dos alunos, (mediaN otas) e in cio totalAlunos 25 i0 somaN otas 0.0 enquanto i < totalAlunos faa c ler notaAluno somaN otas somaN otas + notaAluno ii+1 m enqto mediaN otas somaN otas/totalAlunos imprimir A mdia das notas , mediaN otas e e m

51

momento consta como a maior de todas. Se a temperatura tirada dos arquivos for maior que a menor atual, o algoritmo joga fora a temperatura anotada e guarda a que foi lida como a nova maior temperatura. Quando no houver mais a temperaturas para ler a que estiver anotada como a maior a maior verdadeirae mente. Algoritmo 2.13: Algoritmo para calcular a maior temperatura do ano. Entrada: Temperaturas registradas em ano, (temperatura). Sa da: Maior das temperaturas, (maiorT emperatura) in cio totalT emperaturas 365 ler temperatura -- J li uma temperatura a totalT emperaturas totalT emperaturas 1 -- A primeira temperatura a maior temperatura e maiorT emperatura temperatura enquanto totalT emperaturas > 0 faa c ler temperatura se temperatura > maiorT emperatura ento a maiorT emperatura temperatura m se totalT emperaturas totalT emperaturas 1 m enqto imprimir A maior nota das temperaturas , maiorT emperatura e m

52

2.7

Exerc cios

2.1: Uma empresa paga R$10.00 por hora normal trabalhada e R$ 15.00 por hora extra. Escreva um algoritmo que leia o total de horas normais e o total de horas extras trabalhadas por um empregado em um ano e calcule o salrio a anual deste trabalhador. 2.2: Assuma que o trabalhador do exerc anterior deve pagar 10% de imposto cio se o seu salrio anual for menor ou igual a R$ 12000.00. Caso o salrio seja maior a a que este valor o imposto devido igual a 10% sobre R$ 12000.00 mais 25% sobre e o que passar de R$ 12000.00. Escreva um programa que calcule o imposto devido pelo trabalhador. 2.3: Escreva um algoritmo que descubra a maior nota de uma turma de alunos. O tamanho da turma deve ser o primeiro dado pedido ao usurio. a 2.4: Modique o algoritmo anterior de modo que ele imprima tambm quantas e vezes a maior nota aparece. 2.5: Nos exerc cios anteriores assumimos que os usurios sempre digitam uma a nota entre 0 e 10. Vamos assumir agora que o usurio sempre digita um n mero, a u mas este nmero pode estar fora do intervalo 0 a 10. Ou seja, poderemos ter u uma nota menor que zero ou maior que 10. Modique o algoritmo anterior para que ele verique a nota digitada e, caso o aluno tenha digitado uma nota invlida, uma mensagem avisando o usurio seja impressa e uma nova nota seja a a pedida. O algoritmo deve insistir at que o usurio digite um valor vlido. e a a 2.6: Escreva um programa que leia um conjunto de 100 temperaturas e imprima a menor temperatura lida. Observe que temperaturas podem assumir valores menores do que zero. 2.7: Escreva um algoritmo que leia trs nmeros e os imprima em ordem crese u cente. 2.8: Escreva um algoritmo que leia um nmero inteiro entre 100 e 999 e imprima u na sa cada um dos algarismos que compem o nmero. Observe que o n mero da o u u lido com um valor inteiro, e, portanto, ele tem de ser decomposto em trs e e nmeros: os algarismos das centenas, dezenas e unidades. u 2.9: Escreva um algoritmo que leia uma hora em horas, minutos e segundos e some um segundo a hora lida. 2.10: Escreva um algoritmo que leia duas datas em dia, ms e ano e imprima e a data mais recente. 2.11: Um aluno est escrevendo um programa que l uma nota no intervalo a e entre 0 e 100, inclusive. Foi pedido ao aluno que o programa aceite as notas vlidas e rejeite as invlidas. Marque a letra que mostra a expresso que falta a a a no trecho pontilhado do algoritmo mostrado em 2.14. (a) (nota < 0) e (nota > 100) (b) (nota <= 0) e (nota >= 100) 53

(c) (nota < 0) ou (nota > 100) (d) (nota <= 0) ou (nota >= 100) (e) (nota >= 0) e (nota <= 100)

Algoritmo 2.14: Algoritmo do exerc 11. cio in cio imprimir Entre com a nota ler nota se .............. ento a imprimir Nota invlida a seno a imprimir Nota vlida a m se m 2.11: Considere que os valores -3, -4 e -5, nesta ordem, foram fornecidos ao algoritmo 2.15: Algoritmo 2.15: Algoritmo do exerc 11. cio Dados: t1, t2, t3, maior in cio ler (t1, t2, t3) maior 0 se t1 > maior ento a maior t1 m se se t2 > maior ento a maior t2 m se se t3 > maior ento a maior t3 m se imprimir (maior) m Marque a letra que indica o que foi impresso em cada vez que o programa foi executado. (a) 0 (b) -3 (c) -4 (d) -5 (e) nenhuma das respostas anteriores.

54

Cap tulo 3

Tipos de Dados, Constantes e Variveis a


3.1 Introduo ca

Variveis e constantes so os elementos bsicos que um programa manipula. a a a Uma varivel corresponde a um espao reservado na memria do computaa c o dor para armazenar um determinado tipo de dado. Variveis devem receber a nomes para poderem ser mais facilmente referenciadas e modicadas sempre que necessrio. Muitas linguagens de programaao exigem que os programas a c declarem todas as variveis antes que elas possam ser usadas. Estas declaraoes a c especicam de que tipo so as variveis usadas pelos programas e as vezes um a a valor inicial. Tipos podem ser por exemplo: inteiros, reais, caracteres, etc. As expresses combinam variveis e constantes para calcular novos valores. o a

3.2
3.2.1

Tipos de Dados
Tipos Bsicos a

Os dados em C podem assumir cinco tipos bsicos que so os seguintes: a a char: O valor armazenado um caractere. Caracteres geralmente so are a mazenados em cdigos (usualmente o cdigo ASCII). A Tabela A.1 mostra o o este cdigo. Caracteres so armazenados em um byte. o a int: O valor armazenado um nmero inteiro e o tamanho do subconjunto que e u pode ser representado pelo computador normalmente depende da mquina a em que o programa est rodando. Atualmente em C os nmeros inteiros a u so armazenados em 32 bits. a oat: Nmero em ponto utuante de preciso simples, normalmente 32 bits. u a So conhecidos como nmeros reais, no entanto, os computadores somente a u podem armazenar e trabalhar com uma pequena parte do conjunto dos nmeros reais. u 55

double: Nmero em ponto utuante de preciso dupla, com isto a preciso e u a a as vezes a excurso dos nmeros aumenta. Este tipo armazenado em 64 a u e bits. void: Este tipo serve para indicar que um resultado no tem um tipo denido. a Uma das aplicaoes deste tipo em C criar um tipo vazio que pode postec e riormente ser modicado para um dos tipos anteriores.

3.2.2

Modicadores de tipos

Modicadores podem ser aplicados a estes tipos. Estes modicadores so palaa vras que alteram o tamanho do conjunto de valores que o tipo pode representar. Por exemplo, um modicador permite que possam ser usados mais bits para armazenar nmeros inteiros. Um outro modicador obriga que s n meros u o u inteiros sem sinal possam ser armazenados pela varivel. Deste modo no a a e necessrio guardar o bit de sinal do nmero e somente nmeros positivos so a u u a armazenados. O resultado prtico que o conjunto praticamente dobra de a e tamanho. Os modicadores de tipos so os seguintes: a unsigned: Este modicador pode ser aplicado aos tipos int e char e faz com que o bit de sinal no seja usado, ou seja o tipo passa a ter um bit a mais. a signed: Este modicado tambm pode ser aplicado aos tipos int e char. O e uso de signed com int redundante. e long: Modicador que pode ser aplicado aos tipos int e double aumentando o nmero de bytes reservado para armazenamento de dados. u E poss vel combinar estes modicadores de diversas maneiras como est a mostrado na Tabela 3.1 que lista os tipos bsicos denidos no padro ANSI a a e a sua excurso. a

3.3

Constantes Numricas e

Constantes so valores que o programa no pode modicar durante a execuao a a c de um programa. Elas so usadas em expresses para representar vrios tipos de a o a valores. Em C existem regras r gidas para determinar como devem ser escritos estes valores. A seguir iremos mostrar estas regras. Para escrever constantes numricas vamos usar as seguintes denioes: e c d gito: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 d gito sem zero: 1, 2, 3, 4, 5, 6, 7, 8, 9 d gito octal: 0, 1, 2, 3, 4, 5, 6, 7 d gito hexa: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D, e, E, f, F 56

Tipo char unsigned char signed char int unsigned int signed int short int, short unsigned short int signed short int long int, long signed long int unsigned long int long long int long long signed long long int signed long long unsigned long long int unsigned long long oat double long double

Bytes 1 1 1 4 4 4 2 2 2 4 4 4 8 8 8 4 8 12

Faixa M nima -127 a 127 0 a 255 -127 a 127 -2.147.483.648 a 2.147.483.647 0 a 4.294.967.295 -2.147.483.648 a 2.147.483.647 -32.768 a 32.767 0 a 65.535 -32.768 a 32.767 -2.147.483.648 a 2.147.483.647 -2.147.483.648 a 2.147.483.647 0 a 4.294.967.295 -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 0 a 18.446.744.073.709.551.615 oito d gitos de preciso a 16 d gitos de preciso a 16 d gitos de preciso a

Tabela 3.1: Tipos de dados denidos pelo Padro ANSI C. a

sinal: +, ponto decimal: . suxo: sufixo sem sinal, sufixo longo suxo sem sinal: u, U suxo longo: l, L suxo utuante: f, F, l, L O uso destas caracteres ser mostrado com exemplos nas sees seguintes. a co

3.3.1

Constantes Inteiras na base 10

So valores numricos sem ponto decimal, precedidos ou no por um sinal. No a e a a poss separar, por espaos em branco, o sinal do valor numrico. Podemos e vel c e descrever este formato com uma notaao simplicada da seguinte maneira: c [sinal]dgito sem zero{dgito}[sufixo sem sinal|sufixo longo] Esta notaao deve ser entendida da seguinte maneira. Colchetes indicam c opao, portanto, o fato de sinal (+ ou -) estar entre colchetes signica que um c 57

nmero inteiro pode ou no ter sinal, isto o sinal opcional. Em seguida temos u a e e um dgito sem zero que obrigatrio. Isto dados inteiros devem comear e o e c por, pelo menos, um algarismo entre 1 e 9. A seguir temos a palavra dgito entre chaves. As chaves indicam que o fator entre elas pode ser repetido zero ou mais vezes. Portanto, um nmero inteiro, aps o algarismo inicial obrigatrio, u o o pode ser seguido por uma seqncia de zero ou mais algarismos. Como suxo ue podemos ter opcionalmente as letras u (U) ou l (L) ou uma mistura, em qualquer ordem, das duas. Para constantes inteiras o suxo U (u) representa o modicador unsigned. O suxo L (l) representa o modicador long. Um par de Ls (ls) indica que a constante do tipo long long. A tabela 3.2 mostra exemplos de e nmeros inteiros: u Tipo int unsigned int long int unsigned long int long long unsigned long long Constantes -3 +5 45u 12345U 1997L -3l 45Lu 23Ul 1997Ll -3ll 45LLu 23Ull

1997 1997U 1234L 1997UL 134LL 1997ULL

7 0U +0L 0LU +0LL 0LLU

Tabela 3.2: Constantes Inteiras na Base 10 Alguns exemplos de erros na escrita de constantes inteiras so: a 1.0 (No poss usar ponto decimal.) a e vel - 345 (No poss colocar um espao entre o sinal e o valor numrico.) a e vel c e 23 (No poss usar notaao de expoentes.) a e vel c Nos compiladores modernos o nmero de bytes usados para armazenar os u valores inteiros o mesmo tanto para tipos inteiros (int) quanto para tipos e inteiros longos (long int), como est mostrado na Tabela 3.1. Por esta razo, a a a diferena entre estes dois tipos de constantes perdeu a razo de ser. Alguns c a exemplos de constantes inteira longas esto mostrados na Tabela 3.2. a

3.3.2

Constantes Inteiras Octais

So constantes representadas na base 8. Normalmente so representadas sem a a sinal e devem comear com um 0. Usando a notaao apresentada na seao c c c anterior podemos denir a forma que deve ter uma constante octal como: 0 {dgito octal}[sufixo sem sinal|sufixo longo] Na Tabela 3.3 mostramos exemplos de constantes octais e o seu valor na base 10. Nmeros escritos na base 8 somente podem ser escritos com algarismos entre 0 u e 7 inclusive.

58

Base 8 025 077 011 010ul 0175

Base 10 21 63 9 8 125

Tabela 3.3: Constantes octais

3.3.3

Constantes Inteiras Hexadecimais

So constantes representadas na base 16. So iniciadas com um 0x ou 0X. Usando a a a notaao podemos denir uma contante hexadecimal como: c [0x|0X]dgito hexa{dgito hexa}[sufixo sem sinal|sufixo longo] Na Tabela 3.4 mostramos exemplos de constantes hexadecimais e o seu valor na base 10. Para escrever constantes na base 16 usamos todos os algarismos e ainda as letras A (ou a), B (ou b), C (ou c), D (ou d), E (ou e), F (ou f), que representam respectivamente os seguintes valores 10, 11, 12, 13, 14 e 15. Base 16 0xF 0X25 0XAB 0XBEEF Base 10 15 37 171 48879

Tabela 3.4: Constantes hexadecimais

3.3.4

Converso entre Bases a

A converso de nmeros inteiros entre a base 8 e a base 10 tem uma frmula a u o simples, que pode ser estendida para converter nmeros entre qualquer base e u a base 10. Vamos considerar que um nmero (N )8 escrito na base 8 tenha a u seguinte forma (N )8 = dn1 dn2 . . . d1 d0 onde 7 di 0 A frmula para converter um nmero da base 8 para a base 10 a seguinte o u e N10 = dn1 8n1 + dn2 8n2 + + d1 81 + d0 80 (3.1)

Esta equaao est escrita na base 10. Por exemplo, aplicando a equaao 3.1 c a c para converter o nmero 0175 da base 8 para a base 10 camos com u (0175)8 = 1 82 + 7 81 + 5 80 = (125)10

59

A frmula para converso da base 8 para a base 10 pode se estendida para o a uma base qualquer com a substituiao do algarismo 8. Considere uma base c qualquer representada por b. Nesta base os d gitos di cam no intervalo b 1 di 0. A equaao 3.2 mostra a frmula para converter um nmero em uma c o u base b qualquer para a base 10. N10 = dn1 bn1 + dn2 bn2 + + d1 b1 + d0 b0 (3.2)

Vamos considerar a contante inteira (3AB)16 . Aplicando a frmula 3.2 temos o (3AF )16 = 3 162 + 10 161 + 15 160 = (943)10 O algoritmo para converter um nmero inteiro da base 10 para uma determiu nada base b feito por um conjunto de divises sucessivas do nmero pela base e o u at que o resultado da diviso seja 0. O Algoritmo 3.1 mostra como converter e a um nmero (N )10 para uma base b. E importante notar que os algarismos na u base b vo sendo impressos na ordem inversa, do menos signicativo para o mais a signicativo. Por exemplo, caso forneamos para o algoritmo o n mero (943)10 c u e a base 16, o algoritmo iria imprimir os resultados 15, 10 e 3 nesta ordem. Isto corresponderia aos seguintes d gitos da base 16: F, A e 3 e, portanto, a resposta seria (3AF )16 . Algoritmo 3.1: Algoritmo para converter inteiros na base 10 para uma base b. Entrada: nmero, (numero) e base b (baseb). u Sa da: D gitos do nmero na base b u in cio ler numero ler base enquanto numero > 0 faa c resto numero % base numero numero / base imprimir resto m enqto m

3.3.5

Constantes em Ponto Flutuante

Constantes em ponto utuante so usadas para representar nmeros reais. O a u nome ponto utuante devido ao modo como os valores so armazenados pelo e a computador. Constantes de ponto utuante podem ser do tipo oat, double, long ou long double. Constantes sem nenhum suxo so consideradas do tipo double. a Caso seja usado o suxo F ou o f a constante ser considerada como do tipo a oat . O suxo L ou o l torna a constante long double. Uma constante em ponto utuante pode ser denida de duas maneiras. Voc pode escrever um nmero com ponto decimal (1.5) ou na chamada forma e u cient ca, em que um expoente usado (0.15E1). Na segunda forma o n mero e u igual a 0.15 101 . E poss e vel omitir ou os d gitos antes do ponto (a parte 60

inteira) ou aps (a parte fracionria), mas nunca os dois grupos. E poss o a vel escrever um nmero em ponto utuante sem ponto, desde que um expoente seja u usado. Portanto, os nmeros .8, 1234., 1E1 so nmeros de ponto utuante. u a u Para mostrar mais formalmente como se deve escrever as constantes de ponto utuante vamos usar a mesma notaao usada at aqui, mas usando uma hierarc e quia de denioes para facilitar o entendimento. Primeiro damos uma deniao c c mais geral que vai sendo mais detalhada a medida que avanamos. Lembrar c que termos entre chaves podem ser repetidos 0 ou mais vezes e termos entre colchetes so opcionais. a Portanto, usando a forma hierrquica, uma constante de ponto utuante a (CPF) pode ser denida das seguintes maneiras: CPF = [sinal]fra~o[expoente][sufixo flutuante] ca CPF = [sinal]seq dgitos expoente[sufixo flutuante] A seguir denimos cada um dos componentes. Uma fra~o denida como: ca e fra~o = [seq digitos] ponto decimal seq dgitos ou ca fra~o = seq dgitos ponto decimal ca O expoente e a seqencia de d u gitos so denidos como: a expoente = [e | E][sinal]seq dgitos seq dgitos = dgito{dgito} A Tabela 3.5 mostra exemplos de constantes em ponto utuante. Descrio ca sinal fra~o expoente ca fra~o ca fra~o expoente ca fra~o sufixo ca seq dgitos ponto decimal N mero u +23.45e-10 123.45 123.45E+10 123.45F 123.

Tabela 3.5: Constantes em ponto utuante

3.4

Constantes Caracteres

Uma constante caractere um unico caractere escrito entre , como em a. Alm e e disso, uma constante de tamanho igual a um byte pode ser usada para denir um caractere, escrevendo-se, por exemplo, \ddd, onde ddd uma constante com e entre um e trs d e gitos octais. Em C, caracteres podem participar normalmente de expresses aritmticas. O valor que entra na expresso o do cdigo usado o e a e o para representar o caractere. Exemplos de constantes do tipo caractere so a mostrados na Tabela 3.6. Certos caracteres que no so vis a a veis podem ser representados antepondo-se o caractere \ (barra invertida), como no exemplo nova linha da Tabela 3.6. Este caractere tambm conhecido como caractere de escape. Exemplos so e e a mostrados na Tabela 3.7. 61

Caractere a A \0141 ( 9 \n

Signicado caractere a caractere A Constante octal correspondente ao caractere a caractere abre parnteses e algarismo 9 Nova linha, posiciona o cursor no in da nova linha. cio Tabela 3.6: Exemplos de constantes caractere

Caractere \n \t \b \f \r \a \0

Signicado Passa para uma nova linha. Tabulaao horizontal, move o cursor c para a prxima parada de tabulaao. o c Retorna um caractere. Salta uma pgina. a Carriage return, posiciona o cursor no in da linha atual. cio Alerta, faz soar a campainha do sistema. Null, caractere que em C termina uma cadeia de caracteres.

Tabela 3.7: Exemplos de caracteres invis veis.

3.4.1

Constantes Cadeias de Caracteres

Neste livro vamos usar em alguns casos a palavra cadeia para signicar cadeia de caracteres (string em ingls). Uma constante do tipo cadeia de caracteres e uma seqncia de qualquer nmero de caracteres entre " como no exemplo: e ue u "alo mundo!!!". E importante notar que a linguagem C insere automaticamente ao nal de uma cadeia de caracteres um caractere null (\0). Este caractere ser usado a em diversos algoritmos como sinal de m de cadeia. Os caracteres \ (caractere escape) e " (in e m de cadeia) tm signicados especiais em cadeias de cio e caracteres e para serem representados precisam ser antecedidos pelo caractere escape. Portanto, \\ e \" devem ser usados dentro de cadeias de caracteres para representar \ e " respectivamente. Por exemplo, "Estas s~o \" (aspas) dentro de cadeias." a As aspas no meio da cadeia no indicam o m, j que elas esto precedidas a a a do caractere de escape.

3.5

Variveis a

Variveis so nomes dados para posioes de memria a m de facilitar o manua a c o seio dos dados durante a criaao dos programas. Os dados podem ser de qualquer c 62

dos tipos denidos para a linguagem C.

3.5.1

Nomes das Variveis a

Existem algumas regras bsicas que regulam o batismo de variveis. Estas regras a a so as seguintes: a Nomes de varivel s podem conter letras, d a o gitos e o caractere _; Todo primeiro caractere deve ser sempre uma letra ou o caractere _; Letras maisculas e minsculas so consideradas caracteres diferentes, isto u u a , C diferencia a caixa das letras; e Palavras reservadas no podem ser usadas como nome de variveis. Palavras a a reservadas so palavras usadas para indicar os comandos da linguagem, a tipos de dados ou outras funoes. O Anexo B mostra as palavras reserc vadas da linguagem C. E boa pol tica escolher nomes que indiquem a funao da varivel. Por exc a emplo: soma mediaNotas total salarioMensal nome taxa imposto raio inicio

Em C nomes como raio, Raio e RAIO referem-se a diferentes variveis. No a entanto, para afastar confuses, evite diferenciar nomes de variveis por leo a tras maisculas e minsculas. Normalmente, os programadores usam letras u u maisculas para representar constantes. u Observe que em alguns nomes combinamos duas palavras para melhor indicar o dado armazenado na varivel. Note tambm que o caractere espao no a e c a pode ser usado em nomes de variveis. Os programadores ao longo do tempo a desenvolveram algumas regras informais para fazer esta combinaao. Por exemc o plo, usa-se o caractere para separar as palavras que compem o nome, como em taxa_imposto . Outra maneira usar letras maisculas para indicar quando e u comea uma palavra, como em mediaNotas. Alguns programadores usam a conc venao de no comear nomes de variveis por letras maisculas. No existem c a c a u a regras formais para denir como nomes devem ser criados. O melhor analisar e as regras que programadores mais experientes usam ou os padres que empresas o adotam, para ento escolher o que mais lhe agrada e segui-lo. Uma vez adotado a um padro ele deve ser seguido para evitar incoerncias. a e

3.5.2

Declarao de variveis ca a

Para serem usadas, as variveis precisam ser declaradas de modo que o compia lador possa reservar espao na memria para o valor a ser armazenado. A forma c o geral de uma declaraao : c e a tipo lista de variveis; onde uma lista de variveis uma lista de nomes de variveis separadas por a e a v rgulas. Por exemplo: 63

int i; unsigned i n t a , b , c ; unsigned short i n t dia , mes , ano ; f l o a t raio , diametro ; double salario ;

3.5.3

Atribuio de valores ca

Aps ser declarada, uma varivel pode receber valores. O operador de atribuiao o a c = indica que o resultado da expresso ` direita do operador ser atribu ` a a a do a varivel. Nada se pode armar sobre o contedo de uma uma varivel que j a u a a foi declarada mas ainda no recebeu um valor. a A seguir so mostrados exemplos de atribuioes de valores `s variveis dua c a a rante as declaraoes. c
i n t i = 0 , j = 10; f l o a t raio = 2.54; char c = d ; double precisao = 0.00001 L ;

A seguir mostramos um trecho de programa com exemplos de atribuiao de c valores aps a deniao das variveis. o c a
int i, j; f l o a t raio ; char c ; i = 0; j = 10; raio = 2.54; c = d ;

64

3.6

Exerc cios

3.1: Indique os nomes de variveis que so vlidos. Justique os nomes invlidos. a a a a (a) tempo (e) 2dias (b) nota final (f) teste 1 (c) us$ (g) raio.do.circulo (d) char (h) DiaHoje 3.2: Marque a letra que contm pelo menos um nome de varivel invlido. e a a (a) (b) (c) (d) (e) raio, nome, hoje, provaFinal 2dia, aluno, real, podeSer = 2dia Alo, ALO, alo, aLO errado, certo, ok, dia2 nome , prova final, raio, nao sei nao

3.3: Indique quais dos nmeros abaixo so constantes inteiras (longas ou no) u a a vlidas. Justique suas respostas. a (a) 100 (e) - 234 (b) 2 345 123 (f) 0L (c) 3.0 (g) 21 (d) -35 (h) 0xF1 3.4: Qual o valor na base 10 das constantes abaixo? (a) (b) (c) (d) 025 0123 0xD 0x1D

3.5: Considere um computador que armazene nmeros inteiros em 32 bits. u (a) Caso um bit seja reservado para o sinal diga qual o menor n mero e u inteiro negativo que este computador pode armazenar? (b) Para os nmeros sem sinal, qual o maior nmero positivo? u e u 3.6: Indique na tabela 3.8 os tipos que voc usaria para armazenar os dados e indicados. 3.7: Marque a opao que indica quantos dos nmeros abaixo representam rec u sultados da operaao (175)8 + (AB)16 . c (602)7 , (100101000)2, (128)16 , (450)8 (a) (b) (c) (d) (e) 0 1 2 3 4

65

Descrio ca total de alunos em uma sala a nota de aluno em Computaao I c Primeira letra de um nome pontos de um jogador de voleibol ao nal do ano; o raio de um c rculo. Tabela 3.8: Tabela do exercicio 6

Tipo da varivel a

66

Cap tulo 4

Entrada e Sa pelo da Console


4.1 Introduo ca

Neste cap tulo vamos apresentar conceitos bsicos de entrada e sa de dados a da para que os exemplos e exerc cios iniciais possam ser constru dos. Um programa que no fornece resultados nem pede valores para operar no deve ter grande a a utilidade. A entrada de dados ser feita pelo teclado e a sa poder ser vista a da a na tela do computador. Em C, quando um programa se inicia, normalmente trs uxos (arquivos) de dados so abertos para operaoes de entrada e sa e a c da: um para entrada, um para sa e um para imprimir mensagens de erro ou dida agnstico. Normalmente o uxo de entrada est conectado ao teclado, enquanto o a que o uxo de sa e o de mensagens de erro, para serem visualizados, esto da a conectados ao monitor. Estas conguraoes podem ser alteradas de acordo com c as necessidades dos usurios e estas operaoes so chamadas de redirecionaa c a mento. O uxo de entrada chamado de entrada padro (standard input); o e a uxo de sa chamado de sa padro (standard output) e o uxo de erros da e da a chamado de sa padro de erros (standard error output). Estes termos so e da a a substitu dos pelas suas formas abreviadas: stdin, stdout e stderr.

4.2

Biblioteca Padro a

Na linguagem C no existem comandos de entrada e sa a da. As operaoes de c entrada e sa so executadas com aux de variveis, macros e funoes espeda a lio a c ciais. Para termos acesso ` biblioteca que contm estas ferramentas o programa a e deve conter a declaraao c
#include <stdio.h>

no in do programa. cio A diretiva #include instrui o compilador a ler o arquivo indicado entre < e >, e process-lo como se ele fosse parte do arquivo original e seu conte do a u

67

estivesse no ponto onde a diretiva foi escrita. Se o nome do arquivo estiver entre os sinais de maior e menor, como no exemplo, ele ser procurado em a um diretrio espec o co de localizaao pr-denida, onde esto os arquivos de c e a incluso. Quando se usa aspas o arquivo procurado de maneira denida pela a e implementaao, isso pode signicar procurar no diretrio de trabalho atual, c o ou em um diretrio indicado no comando usado para compilar o programa. o Normalmente os programadores usam maior e menor para incluir os arquivos de cabealho padro e aspas para a incluso de arquivos do prprio projeto. c a a o

4.3

Sa - A Funo printf da ca

A funao printf faz com que dados sejam escritos na sa padro, que normalc da a mente a tela do computador. O prottipo da funao : e o c e
int printf(controle, arg1, arg2, ...);

onde os argumentos arg1, arg2, ... so impressos de acordo com o formato a indicado pela cadeia de caracteres que compe controle. O formato ao mesmo o e tempo de uso simples e bastante ex vel, permitindo que os resultados possam ser apresentados de diversas maneiras. A funao retorna o n mero de caracteres c u impressos, no incluindo o nulo em vetores de caracteres. No caso de um erro a de sa um valor negativo retornado. da e Um exemplo simples pode tornar a explicaao mais clara. O programa 4.1 c imprime o valor da varivel ano. a Listing 4.1: Exemplo de impresso de resultados a
#i ncl ude < stdio .h > i n t main ( void ) { i n t ano = 1997; /* Imprime o valor do ano */ printf ( " Estamos no ano % d " , ano ); return 0; }

Este programa ir imprimir na tela do computador: a Estamos no ano 1997 Como controle uma cadeia ele aparece entre " ". Ele dene como sero e a impressos os valores representados pelos argumentos. No controle podem existir dois tipos de informaoes: caracteres comuns e cdigos de formataao. Os c o c caracteres comuns, como no exemplo o texto Estamos no ano, so escritos na a tela sem nenhuma modicaao. Os cdigos de formataao, aparecem precedidos c o c por um caractere% e so aplicados aos argumentos na ordem em que aparea cem. Deve haver um cdigo de formataao para cada argumento. O cdigo o c o %d indica que o valor armazenado em ano deve ser impresso na notaao inteiro c decimal. E importante notar que o campo de controle aparece somente uma vez na funao printf e sempre no in c cio.

68

4.3.1

Cdigos de Converso o a

Os cdigos de converso esto mostrados na tabela 4.3.1. o a a Cdigo o %c %d %i %E %e %f %G %g %o %s %u %x %X %p %% Comentrio a Caracter simples Inteiro decimal com sinal Inteiro decimal com sinal Real em notaao cient c ca com E Real em notaao cient c ca com e Real em ponto utuante %E ou %f, o que for mais curto %g ou %f, o que for mais curto Inteiro em base octal Cadeia Caracteres Inteiro decimal sem sinal Inteiro em base hexadecimal (letras minsculas) u Inteiro em base hexadecimal (letras maisculas) u Endereo de memria c o Imprime o caractere %

Tabela 4.1: Cdigos de Converso para leitura e entrada de dados. o a Entre o caractere % e o cdigo de convers~o podem ser inseridos caracteres o a que alteram o formato. A seguir so mostrados a ordem de inserao destes a c caracteres e o seu signicado: %[modificadores][largura][.precis~o][comprimento]cdigo a o modificadores: Usados logo aps o caractere %. o - Um sinal de menos serve para especicar que o argumento deve ser justicado ` esquerda no seu campo de impresso. Caso nenhum a a sinal seja usado o argumento ser ajustado ` direita. O programa a a 4.2 ilustra os dois tipos de justicaao. c + Fora que o resultado seja precedido por sinal de menos ou de mais, c mesmo para nmeros positivos. O padro que somente negativos u a e sejam precedidos por sinal de menos. espao Caso nenhum sinal v ser escrito, um espao inserido antes do c a c e valor. # Usado com o, x ou X precede o valor com 0, 0x ou 0X respectivamente para valores diferentes de zero. Usado com e, E e f, fora c que a sa contenha um ponto decimal mesmo que no haja parte da a fracionria. Por padro, se no h parte fracionria o ponto decimal a a a a a no escrito. Usado com g ou G o resultado o mesmo que com e a e e ou E, mas os zeros nais no so retirados. a a 0 Completa o campo, pela esquerda, com zeros (0) ao invs de espaos, e c sempre que a opao para completar seja especicada (ver especic cador de largura do campo). 69

largura: Caso seja usado um nmero inteiro, este especica o tamanho m u nimo do campo onde o argumento ser impresso. Na listagem 4.2 o n mero a u especica que 8 espaos so reservados para imprimir o resultado. Os c a espaos livres sero completados com espaos em branco. Se o argumento c a c precisar de mais espao que o especicado ele ser escrito normalmente e c a o tamanho m nimo ignorado. e .precis~o Este nmero tem diferentes signicados dependendo do cdigo usa u o ado. caracteres: No caso de impresso de cadeia de caracteres (s), este a nmero especica o nmero mximo de caracteres de uma cadeia u u a de caracteres a serem impressos. ponto utuante: No caso de formato (e, E, f) o nmero de d e u gitos a serem impressos a direita do ponto, ou seja o nmero de casas u decimais. Para o formato g ou G o nmero mximo d e u a gitos signicativos. inteiros: No formatos inteiros (d, i, o, u, x, X) a preciso especia cou o nmero mximo de d u a gitos a serem impressos. Se o n mero de u caracteres a serem impressos menor que este o resultado complee e tado com brancos. O valor no truncado a e comprimento: Modica os formatos da seguinte maneira: l Aplicado aos formatos de tipo d, i, o, u, x e X indicando que o dado e do tipo long int e no int. a h Modica o dado, nos formatos d, i, o, u, x e X para tipo short int. L Nos formatos e, E, f, g e G o argumento modicado para long double. e O programa 4.2 ir imprimir o seguinte resultado: a Justificado para direita Ano = 1997 Justificado para esquerda Ano = 1997 Listing 4.2: Exemplo de justicaao de resultados. c
#i ncl ude < stdio .h > i n t main ( void ) { i n t ano = 1997; printf ( " Justificado para direita Ano = %8 d \ n " , ano ); printf ( " Justificado para esquerda Ano = % -8 d \ n " , ano ); return 0; }

O programa exemplo 4.3 imprimir o seguinte resultado: a O resultado e = 0.333 . Alo

70

Listing 4.3: Exemplo de uso de especicador de preciso. a


#i ncl ude < stdio .h > i n t main () { f l o a t r = 1.0/3.0; char s [] = " Alo Mundo " ; printf ( " O resultado e = %9.3 f \ n " , r ); printf ( " %9.3 s \ n " , s ); return 0; }

Nos exemplos anteriores verique que \n no impresso. A barra inclinada a e chamada de seqencia de escape, indicando que o prximo caractere no para e u o a e ser impresso mas representa caracteres invis veis ou caracteres que no esto a a representados no teclado. Esta seqncia de escape indica que o programa deve ue passar a imprimir na prxima linha. o

4.4

Entrada - A Funo scanf ca

A funao scanf pode ser utilizada para entrada de dados a partir do teclado e c seu prottipo : o e
scanf(controle, arg1, arg2, ...);

Uma diferena fundamental que existe entre esta funao e a funao printf c c c est nos argumentos que vm depois do controle. No caso de scanf os argua e mentos so os endereos das variveis que iro receber os valores lidos e no, a c a a a como em printf, as prprias variveis. A indicaao que estamos referenciando o a c um endereo e no a varivel se faz pelo operador &. Por exemplo, o comando c a a
scanf("%d %d", &a, &b);

espera que dois valores inteiros sejam digitados no teclado. O primeiro are mazenado na varivel a e o segundo em b. Os valores sero armazenados direa a tamente nos endereos indicados por &a e &b respectivamente. c Um outro exemplo incluindo variveis reais : a e
int i; fl oat x; scanf ( " % d % f " , &i , & x );

Assumindo que a linha de entrada no teclado fosse 34 56.43 a execuao do exemplo iria terminar com o valor inteiro 34 sendo armazenado c na varivel i e o valor real 56.43 em x. a Usualmente o campo de controle s contm especicaoes de converso, como o e c a os listados na Tabela 4.3.1, que so utilizadas para interpretar os dados que sero a a lidos, no entanto, como em printf, outros caracteres podem aparecer. O campo de controle pode conter: 71

Caracteres branco: A funao l e ignora todos os caracteres branco e/ou c e <enter> e/ou tab que aparecerem antes de qualquer caractere diferente destes. Caracteres comuns: (no %) que devem casar com o prximo caractere difea o rente de branco da entrada. Isto signica que qualquer caractere que no a for igual a branco e/ou <enter> e/ou tab ou parte de um especicador de formato faz com que a funao leia o prximo caractere da entrada (stdin) c o e se for igual a este ele descartado. Caso os caracteres sejam diferentes e a funao falha e retorna deixando os caracteres seguintes no lidos. c a Especicaoes de converso: Um especicador de converso de formato sec a a guindo um modelo similar ao da funao printf. c O modelo o seguinte: e %{*}{largura}{modificadores}tipo O caracteres entre chaves so opcionais. O asterisco indica que o dado ser lido a a de stdin mas ignorado. A largura especica o nmero mximo de caracteres a u a serem lidos. Os modicadores alteram o tamanho do especicadores de tipo que vm logo e a seguir. Existem os seguintes modicadores: h: Os tipos d, i e n, que so int passam a ser short int e os tipos o, u e x, a tambm int passam a ser unsigned short int. e l: Os tipos d, i e n passam a ser long int e os tipos o, u e x passam a unsigned long int. Os tipos e, f e g passam de oat para double. L: Os tipos e, f e g passam de oat para long double. Por exemplo, para que os valores digitados sejam separados por v rgulas, o comando deveria ser escrito da seguinte maneira:
scanf("%d, %f", &i, &x);

Observar que deve haver uma correspondncia exata entre os caracteres no e a brancos do controle e os caracteres digitados. Neste caso a entrada deveria ser: 35, 46.3 O programa 4.4 mostra exemplos de uso da funao scanf. c O resultado da execuao deste programa : c e Entre com um caractere qualquer. d Codigo ASCII do caractere d vale 100. Agora dois inteiros separados por espaco. 2 4 A soma destes numeros vale 6. A funao scanf retorna o nmero de itens lidos com sucesso. Este n mero c u u pode ser usado para vericar se todos os valores pedidos foram lidos. No caso de ocorrer uma falha antes da leitura se iniciar a constante EOF retornada. e 72

Listing 4.4: Exemplo de uso de scanf.


#i ncl ude < stdio .h > i n t main () { char c ; i n t num1 , num2 ; printf ( " Entre com um caractere qualquer .\ n " ); scanf ( " % c " , & c ); printf ( " Codigo ASCII do caractere % c vale % d .\ n " , c , c ); printf ( " Agora dois inteiros separados por espaco .\ n " ); scanf ( " % d % d " , & num1 , & num2 ); printf ( " A soma destes numeros vale % d .\ n " , num1 + num2 ); return 0; }

4.5
4.5.1

Lendo e Imprimindo Caracteres


Funes getchar e putchar co

Para ler e escrever caracteres do teclado as funoes de entrada e sa mais c da simples so getchar e putchar, que esto na biblioteca stdio.h e cujos prottipos a a o so os seguintes: a
i n t getchar ( void ); i n t putchar ( i n t c );

Apesar da funao getchar retornar um parmetro inteiro poss atribuir c a e vel este valor a uma varivel do tipo char porque o cdigo do caractere est ara o a mazenado no byte ordem mais baixa. O mesmo acontece com a funo putchar ca que recebe um inteiro, mas somente o byte de ordem mais baixa passado para e a tela do computador. A funao putchar retorna o caractere que foi escrito e EOF c em caso de erro. O programa da listagem 4.5 mostra exemplos de uso destas funoes, e o seu resultado : c e Entre com um algarismo entre 0 e 9. 7 O caractere lido foi o 7 Observar que, normalmente, quando algum dado fornecido pelo teclado e termina-se a digitaao com a tecla <enter>. No entanto, o <enter> um c e caractere tambm, e isto pode causar problemas. Vamos analisar o que acontece e quando antes do comando getchar, se l um dado do tipo inteiro, por exemplo. e O comando scanf l o nmero inteiro mas no o <enter> digitado. Deste modo, e u a quando logo em seguida o programa executar a funao getchar, o que ser lido c a o <enter> digitado ao nal do nmero. A listagem 4.6 um exemplo de e u e programa onde isto pode ocorrer. Considere que o usurio digitou 35<enter> a como resposta ao comando scanf. O comando getchar ir ler o <enter> e em a seguida o programa ir imprimir o nmero 35, lido no scanf, e apenas uma linha a u em branco correspondente ao caractere <enter>, lido pelo getchar, como est a indicado a seguir. Mais adiante mostraremos como resolver este problema.

73

Listing 4.5: Exemplo de uso de getchar e putchar.


#include < stdio .h > i n t main ( void ) { char c ; printf ( " Entre com um algarismo entre 0 e 9.\ n " ); c = getchar (); printf ( " O caractere lido foi o " ); putchar ( c ); return 0; }

Entre com um numero inteiro. 35 Agora um caractere. Numero lido 35 Caractere lido

Listing 4.6: Exemplo de uso de getchar e putchar.


#i ncl ude < stdio .h > i n t main ( void ) { char c ; int i; printf ( " Entre com um numero inteiro .\ n " ); scanf ( " % d " , & i ); printf ( " Agora um caractere .\ n " ); c = getchar (); printf ( " Numero lido % d \ n " , i ); printf ( " Caractere lido % c \ n " , c ); return 0; }

4.5.2

Lendo e Imprimindo Cadeias de Caracteres

Uma cadeia de caracteres (string) em C um vetor de caracteres. Vetores, que e sero vistos mais adiante no Cap a tulo 7, so conjuntos de caracteres em que a cada um deles pode ser acessado independentemente dos outros por meio de um endereo. Nesta etapa iremos apresentar rapidamente alguns conceitos que c nos permitiro criar alguns exemplos simples com cadeias de caracteres. Para a usar cadeias preciso primeiro denir um espao para armazen-las. Para isto e c a preciso declarar o nome, o tamanho e o tipo do vetor. Considere que pree cisamos armazenar uma cadeia de caracteres chamada nome com 40 caracteres. 74

A deniao desta cadeia caria da seguinte maneira: c


char nome [41];

Quando denir o tamanho do vetor de caracteres, observar que toda cadeia em C termina com o caractere NULL (\0), que automaticamente inserido e pelo compilador. Portanto o vetor nome deve ser denido com um espao a c mais. Aps este passo, o vetor nome pode ser usado durante a execuao do o c programa.

4.5.3

Lendo e Imprimindo cadeias com scanf e printf

O programa 4.7 mostra como ler e imprimir um cadeia usando os comandos scanf e printf respectivamente. Listing 4.7: Exemplo de uso de printf e scanf na leitura de cadeias.
#de fi ne DIM 40 #include < stdio .h > i n t main ( void ) { char nome [ DIM ]; /* linha de caracteres lidos */ /* Entrada de dados do vetor */ printf ( " Por favor , qual o seu nome ?\ n " ); scanf ( " % s " , nome ); printf ( " Sou um computador . Posso ajuda - lo % s ?\ n " , nome ); return 0; }

Considere que este programa se chama util. Uma poss interaao entre vel c este programa e um usurio poderia ser da seguinte maneira. a $ util Por favor, qual o seu nome? Ze Sa Sou um computador. Posso ajuda-lo Ze? O s mbolo $ o prompt t e pico dos sistemas Unix. Aparentemente o computador se tornou ntimo do usurio Ze Sa e o tratou apenas pelo primeiro nome. A a explicaao para esta intimidade est no modo de leitura. Quando se usa scanf c a para ler uma cadeia deve-se empregar o cdigo de converso %s. Este comando o a no l o nome todo, mas encerra a leitura dos caracteres quando encontra um a e caractere espao (ou branco), ou seja o separador de cadeias no comando scanf c o caractere espao. Mas como ler para um vetor um nome inteiro, ou um e c cadeia que contenha brancos? Para isto deve-se usar a funao gets que ser c a nosso prximo assunto. o

4.5.4

Lendo e Imprimindo cadeias com gets e puts

Diferentemente do comando scanf a funao gets l toda a cadeia at que a tecla c e e <enter> seja digitada. No vetor so colocados todos os cdigos dos caracteres a o 75

lidos excetuando-se o da tecla <enter>, que no armazenado sendo substitu a e do pelo cdigo NULL. Caso a funao scanf do exemplo anterior fosse substitu pela o c da gets o programa imprimiria Posso ajuda-lo Ze Sa? O comando que substitui o scanf gets(nome). O prottipo da funao gets e o c o seguinte: e
#include < stdio .h > char * gets ( char * str );

A funao gets retorna str caso nenhum erro ocorra. Caso o nal do arc quivo seja encontrado antes de qualquer caractere ser lido, o vetor permanece inalterado e um ponteiro nulo retornado. Caso um erro ocorra durante a e leitura, o contedo do array ca indeterminado e novamente um ponteiro nulo u retornado. e A funao puts tem o seguinte prottipo: c o
#include < stdio .h > i n t puts ( const char * str );

Ela imprime a cadeia apontado por str. O programa 4.8 semelhante ao e exemplo anterior com as funoes printf substitu c das por puts. Observe que a impresso sempre termina e passa para a prxima linha. A funao puts retorna a o c um valor positivo caso nenhum erro ocorra. Em caso de erro retornado um e valor negativo. Entre com o seu nome, por favor. Ze Sa Alo Ze Sa Eu sou um computador, em que posso ajuda-lo?

Listing 4.8: Exemplo de uso de puts e gets na leitura de cadeias.


#de fi ne DIM 41 #i ncl ude < stdio .h > i n t main ( void ) { char nome [ DIM ]; /* linha de caracteres lidos */ /* Entrada de dados do vetor */ puts ( " Entre com o seu nome , por favor . " ); gets ( nome ); puts ( " Alo " ); puts ( nome ); puts ( " Eu sou um computador , em que posso ajuda - lo ? " ); return 0; }

4.5.5

A Funo fgets ca

A funao gets pode abrir porta para invases de computadores pelo fato dela c o no controlar o nmero de caracteres lido de stdin. Apesar do usurio denir a u a 76

um tamanho mximo para o vetor que ir armazenar os caracteres a funao a a c ignora o limite e continua lendo valores at que o usurio digite o caractere e a <enter>. Para evitar este problema recomenda-se o emprego da funao fgets cujo c prottipo o e
#include < stdio .h > i n t * fgets ( const char * str , i n t tam , FILE * fluxo );

A funao fgets l no mximo um caractere a menos que o n mero de carc e a u acteres especicado no parmetro tam a partir do uxo de entrada de dados a denido por fluxo. No caso de leitura do teclado, como temos feito, uxo e igual a stdin. A leitura interrompida quando um caractere <enter> ene e contrado ou o nal do arquivo foi atingido. Diferentemente do que ocorre na funao gets, aqui o caractere <enter> armazenado no vetor onde os demais c e caracteres esto sendo guardados. O caractere nulo adicionado aps o ultimo a e o caractere lido. A funao retorna str caso seja bem sucedida. Se o nal do arquivo for c atingido e nenhum caractere tiver sido lido, o vetor str permanece inalterado e um ponteiro nulo retornado. Caso ocorra um erro de leitura o conte do do e u vetor ca indeterminado e um ponteiro nulo retornado. e

77

4.6

Exerc cios

4.1: Escreva um programa que declare variveis do tipo int, char e float, a inicialize-as, e imprima os seus valores. 4.2: Escreva um programa que dena variveis do tipo int e armazene nelas a constantes octais e hexadecimais e imprima o seu contedo no formato original u e em formato decimal. 4.3: Faa um programa que leia um valor inteiro no formato decimal e escreva, c na tela, este mesmo valor nas bases hexadecimal e octal. Exemplo de Entrada e Sada: Entre com o valor: 10 Hexadecimal: A Octal: 12 4.4: Faa um programa capaz de ler um valor real e escrev-lo com apenas uma c e casa decimal. 4.5: Faa um programa que leia trs palavras de at 10 letras e reescreva estas c e e palavras alinhadas ` direita da tela. a 4.6: Sabendo que os argumentos da funao printf podem ser expresses (a+b, c o a/b, a*b, 3*a...), e no somente argumentos, faa um programa capaz de ler a c um valor inteiro e escrever seu triplo, seu quadrado, e a sua metade. Exemplo de Entrada e Sada: Valor: 6 Triplo: 18 Quadrado: 36 Meio: 3 4.7: Escreva um programa que leia 3 nmeros reais e imprima a mdia aru e itmtica destes nmeros. e u 4.8: Escreva um programa que pegue o valor de uma conta de restaurante e imprima o valor total a ser pago, considerando que o restaurante cobra 10% de taxa para os atendentes. 4.9: Faa um programa que pea ao usurio a quilometragem atual, a quilomec c a tragem anterior, os litros consumidos e informe a taxa de consumo (quilmetros o por litro) de um automvel. o 4.10: Escreva um programa que converta uma temperatura de Farenheit para Celsius. 4.11: Escreva um programa que, dado o per metro de um c rculo, calcule sua a rea. 4.12: Faa um programa que utilize a funao gets para ler duas cadeias de c c tamanho at 20 e em seguia `s reescreva na linha de baixo, uma ao lado da e a outra e separadas por /-/ ; 78

Cap tulo 5

Operadores e Expresses o
5.1 Introduo ca

O objetivo deste cap tulo apresentar os operadores existentes na linguagem e C e a forma correta de construir expresses que envolvam estes operadores, o constantes e variveis. a

5.2

Operador de Atribuio ca

Este o operador usado para transferir o resultado de uma expresso para uma e a varivel. Em C este operador o sinal de igual (=). Esta escolha do sinal de a e igual para servir de operador de atribuiao pode causar problemas. Isto porque c este sinal no est representando que o resultado da expresso do lado direito a a a igual ao resultado do lado esquerdo e sim uma atribuiao. Observe que o e c comando de atribuiao termina em ponto e v c rgula. Isto faz parte das regras da linguagem C, que determina que comandos terminam com este caractere. Por exemplo: soma = a + b; pi = 3.1415; E poss fazer-se vrias atribuioes em uma unica linha, como no exemplo vel a c a seguir: a = b = c = 1.0; as trs variveis recebem o mesmo valor. As atribuioes so feitas na seguinte e a c a ordem: 1. c = 1.0; c recebe o valor 1.0. 2. b recebe o resultado da expresso ` sua direita, que o valor atribu ` a a e do a c, ou seja 1.0. 3. a recebe o resultado da expresso ` sua direita, que o valor atribu ` a a e do a b, ou seja 1.0. 79

5.3

Operadores Aritmticos e

A Tabela 5.3 mostra os operadores aritmticos e as suas ordens de precedncia. e e Operador + ++ -* / % + Descri~o ca Mais unrio a Menos unrio a Incremento Decremento Multiplicaao c Diviso a Resto da diviso a Soma Subtraao c Prioridade 0 0 1 1 2 2 2 3 3

Tabela 5.1: Operadores aritmticos. e Os s mbolos mostrados na Tabela 5.3 so os unicos que podem ser usados a para representar as operaoes acima listadas. Expresses aritmticas em C dec o e vem ser escritas no formato linear para facilitar a digitaao dos programas e c tambm porque alguns s e mbolos usados em Matemtica no existem nos teclaa a dos. O exemplo mais comum deste formato a operaao de diviso que deve e c a ser escrita a/b. Parnteses tm um papel importante nas expresses e permitem que a ordem e e o das operaoes seja alterada. Expresses entre parnteses so calculadas em c o e a primeiro lugar, portanto eles conferem o maior grau de prioridade as expresses o que eles envolvem. Podemos ter pares de parnteses envolvendo outros pares. e Dizemos que os parnteses esto aninhados. Neste caso as expresses dentro dos e a o parnteses mais internos so avaliadas primeiro. e a Outro ponto importante so as regras de precedncia que determinam que a e operaao deve ser executada primeiro. Na tabela os operadores esto listados c a em ordem decrescente de prioridade. Para os operadores aritmticos a operaao e c de mais alta precedncia o - unrio, vindo em seguida ++, -- com a mesma e e a prioridade. Os operadores de multiplicaao, diviso e mdulo tem a mesma c a o prioridade. O operador menos unrio multiplica seu operador por -1. Quando a duas operaoes de mesmo n de prioridade tm de ser avaliadas, a operaao c vel e c mais ` esquerda ser avaliada primeiro. a a Um ponto importante que deve ser sempre levado em consideraao quando c uma expresso for calculada so os tipos das variveis, porque eles alteram radia a a calmente os resultados das expresses. Por exemplo, a diviso entre operandos o a do tipo inteiro tem como resultado um valor inteiro. Portanto, se o resultado possuir uma parte fracionria ela ser truncada. No poss a a a e vel aplicar a operaao de mdulo a operandos do tipo float e double. Algumas regras c o de converso simples existem e sero discutidas em detalhes mais adiante. Por a a exemplo a operaao 1/3 em C fornece como resultado o valor 0, enquanto que c 1 % 3 igual a 1. e A seguir mostramos alguns exemplos de expresses aritmticas escritas na o e 80

notaao da linguagem C. Observe o uso de parnteses para evitar ambig idades c e u que poderiam fazer com que a expresso fosse calculada erradamente. a Exemplo 5.4: 1. a +
b b+c

= a + b/(b+c)

2. b2 + c2 = b*b + c*c 3.
x b a+ c

= x/(a+b/c)

5.4
5.4.1

Operadores Relacionais e Lgicos o


Operadores Relacionais

Os operadores relacionais esto mostrados na Tabela 5.2. Nesta tabela mostramos a somente a ordem de precedncia destes operadores. A ordem de precedncia que e e inclui todos os operadores est mostrada na Tabela 5.10. a Operador >= > <= < == != Descrio ca Maior ou igual a Maior que Menor ou igual a Menor que Igual a Diferente de Prioridade 0 0 0 0 1 1

Tabela 5.2: Operadores Relacionais. Os operadores >, >=, < e <= tm a mesma precedncia e esto acima de == e e a e !=. Estes operadores tm precedncia menor que os aritmticos, portanto e e e expresses como ( i < limite - 1) e i < (limite -1) tm o mesmo signio e cado.

5.4.2

Operadores Lgicos o

Os operadores lgicos denem as maneiras como as relaoes acima podem ser o c conectadas. Por exemplo podemos querer testar se ao mesmo tempo uma nota maior ou igual a 5.0 e a taxa de presena maior que 75%. e c e Para simplicar a apresentaao destes operadores sero usadas variveis para c a a substituir as relaoes. Neste caso a expresso acima seria representada como p c a e q, onde p est representando nota maior ou igual a 5.0 e q taxa de prea sena maior que 75%. Estas expresses podem ter dois resultados verdadeiro c o e falso. Observar que, assim como em operaoes aritmticas, podemos ter c e combinaoes de mais de duas relaoes em uma unica expresso. Por exemplo, c c a podemos ter a seguinte combinaao: ano maior que 2000 e ms menor que 6 c e e dia maior que 15. Nas linguagens de programaao os valores verdadeiro e c falso podem ser representados de diversas maneiras. Uma das maneiras mais 81

comum representar verdadeiro por true e falso por false. Em C o valor e falso representado por 0 e verdadeiro por qualquer valor diferente de 0. A e seguir iremos mostrar os operadores lgicos existentes na linguagem C. o E lgico o O s mbolo usado para representar o operador E lgico &&. A Tabela 5.3 o e mostra a tabela verdade do operador. O resultado da expresso verdadeiro a e se e somente se todas as variveis forem iguais a verdadeiro. Por exemplo, a considere o seguinte trecho de programa:
i n t i = 3 , j = -5; f l o a t z = 3.0; i n t resultado ; resultado = (10 > 5) && ( i > -5) && ( z != 0); printf ( " O resultado e vale % d . " , resultado );

O resultado deste trecho a impresso de um valor diferente de 0, ou seja o e a valor correspondente a verdadeiro. Isto porque 10 maior que 5 E i maior e e que -5 E z diferente de 0. e p 0 0 1 1 q 0 1 0 1 p && q 0 0 0 1

Tabela 5.3: Operador Lgico E. o

OU lgico o O s mbolo usado para representar o operador OU lgico ||. A Tabela 5.4 o e mostra a tabela verdade do operador. Para que o resultado da expresso seja a verdade basta que uma das variveis seja verdade. Por exemplo, considere o a seguinte trecho de programa:
f l o a t x = 3.0; i n t n = 55 , i = 0; i n t resultado ; resultado = ( i != 0) || ( x == 0) || ( n < 100); printf ( " O resultado e % d " , resultado );

O resultado deste trecho a impresso do valor 1. Isto porque, apesar de i e a no ser diferente de 0 e x no ser diferente de zero, temos que n menor que a a e 100. Como basta um dos testes ser verdade para o resultado ser verdade ser a impresso um valor diferente de 0.

82

p 0 0 1 1

q 0 1 0 1

p || q 0 1 1 1

Tabela 5.4: Operador Lgico OU. o

No lgico a o O s mbolo usado para representar o operador N~O lgico !. A Tabela 5.5 A o e mostra a tabela verdade do operador. Este operador unrio e quando aplicado e a ` uma varivel ele troca seu valor. Por exemplo, considere o seguinte trecho de a a programa:
i n t dia = 25 , ano = 1959; i n t resultado ; resultado = ! ( ( dia < 30) && ( ano > 1950) ) printf ( " O resultado vale \% d . " , resultado );

Este trecho de programa imprime 0 (falso), porque dia menor que 30 E e ano maior que 1950. Portanto, o resultado do parnteses vale 1 (verdadeiro). e e No entanto, o operador ! nega este valor que vira 0. p 0 1 !p 1 0

Tabela 5.5: Operador Lgico N~O. o A A tabela 5.6 mostra, em ordem decrescente, a precedncia dos operadores e lgicos e relacionais. o Operador ! >, >=, <, <= ==, != && || Prioridade 0 1 2 3 4

Tabela 5.6: Precedncia dos operadores lgicos e relacionais. e o

5.5

Operadores com Bits

Para operaoes com bits, a linguagem C dispe de alguns operadores que podem c o ser usados nos tipos char, int, long e long long mas no podem ser usados a 83

em float, double, long double e void. A diferena entre estes operadores c e os lgicos que estes operam em pares de bits enquanto que os operadores o e lgicos anteriores consideram a palavra toda. Por exemplo, para um valor int o ser falso necessrio que todos os 32 bits sejam iguais a zero. Os operadores e a em bits esto mostrados na Tabela 5.7. a Operador & | ^ ~ >> << Descrio ca E OU Ou exclusivo No a Desloca para direita Desloca para esquerda Prioridade

Tabela 5.7: Operadores com bits.

Os operadores &, | e ~ tm a mesma tabela verdade que os operadores &&, || e e ! respectivamente. O operador ^ (OU Exclusivo) est descrito pela Tabela a 5.8. O resultado da operaao verdadeiro se e somente se os dois operandos c e so diferentes. a p 0 0 1 1 q 0 1 0 1 p ^ q 0 1 1 0

Tabela 5.8: Operador Lgico OU. o

Os operandos de deslocamento tm os seguintes modos de operaao: e c operando >> vezes: o operando deslocado vezes bits para a direita. e operando << vezes: o operando deslocado vezes bits para a esquerda. e Observaoes: c Nos deslocamentos ` direita em variveis unsigned e nos deslocamentos a a a ` esquerda, os bits que entram so zeros; a Nos deslocamentos ` direita em variveis signed, os bits que entram cora a respondem ao sinal do nmero (1= sinal negativo, 0 = sinal positivo). u Um deslocamento para a direita equivalente a uma diviso por 2. Desloe a camento para a esquerda equivalente a uma multiplicaao por 2. Assim e c a = a * 2; e a = a << 1; so equivalentes. a O exemplo 5.1 ilustra o uso dos operandos de deslocamento: Este programa teria como resposta os seguintes resultados. 84

Listing 5.1: Exemplo de operadores de deslocamento.


#include < stdio .h > i n t main ( void ) { unsigned i n t c = 7; i n t d = -7; c = c < <1; printf ( " %3 d = %08 X \ n " , c , c ); c = c > >1; printf ( " %3 d = %08 X \ n " , c , c ); d = d < <1; printf ( " %3 d = %08 X \ n " , d , d ); d = d > >1; printf ( " %3 d = %08 X \ n " , d , d ); return 0; }

14 7 -14 -7

= = = =

0000000E 00000007 FFFFFFF2 FFFFFFF9

Os resultados mostram que o nmero 7 aps o primeiro deslocamento de 1 u o bit para a esquerda cou igual a 14, portanto um 0 entrou no nmero. Quando u o nmero foi deslocado para direita 1 bit, ele retornou ao valor original. Observe u que quando o nmero -14 foi deslocado para a direita entrou um bit 1, que u e igual ao sinal negativo.

5.6

Operadores de Atribuio Composta ca

Em C qualquer expresso da forma: a variavel = variavel operador expressao pode ser escrita como: variavel operador= expressao Por exemplo: ano = ano + 10; equivalente a e ano += 10; Outros exemplos so: a raiz = raiz * 4; raiz *= 4; soma = soma / ( a + b); soma /= (a + b); a = a >> 1; a >>= 1; i = i % 2; i %= 2; 85

5.7

Operador v rgula

O operador v rgula (,) usado para separar duas ou mais expresses que so e o a escritas onde somente uma esperada. Quando o conjunto de expresses tem e o de ser reduzido a somente um valor, somente a expresso mais ` direita cona a e siderada. Por exemplo, considere o seguinte trecho de cdigo: o
y = ( x =5 , x +2);

A expresso comea a ser avaliada da esquerda para a direita. Portanto, a c primeiro seria atribu o valor 5 a varivel x. Em seguida atribui x+2 para a do a varivel y. Ao nal a varivel x contm o valor 5 e y o valor 7. a a e

5.8

Operador sizeof()

O operador sizeof() um operador unrio que retorna o tamanho em bytes e a da expresso ou tipo fornecido entre parnteses. Por exemplo, suponha que o a e tipo float tenha quatro bytes ento o operador sizeof(float) retorna o valor a 4. Para se calcular o tamanho de bytes de uma expresso no necessrio o uso a a e a de parnteses. No exemplo 5.2 ilustramos alguns exemplos de uso do operador e sizeof(). Listing 5.2: Exemplo do operador sizeof.
#de fi ne DIM 10 #include < stdio .h > #include < conio .h > i n t main () { i n t i =0; f l o a t f =3.0; char c = a ; i n t v [ DIM ]; printf ( " Tamanho em bytes de alguns tipos \ n " ); printf ( " Tamanho de int % d \ n " , s i z e o f i ); printf ( " Tamanho do float % d \ n " , s i z e o f f ); printf ( " Tamanho do double % d \ n " , s i z e o f ( double )); printf ( " Tamanho do char % d \ n " , s i z e o f c ); printf ( " Tamanho do vetor de % d inteiros % d \ n " , DIM , s i z e o f ( v )); return 0; }

Este programa imprime os seguintes resultados: Tamanho Tamanho Tamanho Tamanho Tamanho Tamanho em de do do do do bytes de alguns tipos int 4 float 4 double 8 char 1 vetor de 10 inteiros 40 86

5.9

Converso de Tipos a

Quando operandos de tipos diferentes aparecem em expresses so convertidos o a para um tipo comum, que permita o clculo da expresso da forma mais eciente. a a Por exemplo, uma operaao que envolva um tipo int e um float, o valor int c convertido para float. e Observar que converses ocorrem somente quando necessrio. Por exemplo, o a em uma diviso de inteiros o resultado do tipo inteiro. Isto pode causar a e surpresas desagradveis para programadores iniciantes. A expresso 1/3*3 tem a a como resultado o valor inteiro 0. J que a primeira expresso executada 1/3 a a tem como resultado 0. Operandos do tipo char e int podem ser livremente misturados em expresses aritmticas. Os tipos char so convertidos para int. Caso o conjunto o e a de caracteres esteja codicado segundo a tabela ASCII, esta facilidade permite a realizaao de algumas transformaoes interessantes. Por exemplo, a converso c c a de uma letra maiscula para minscula pode ser facilmente implementada com u u o comando: l = l - A + a; A letra maiscula armazenada na varivel l subtra do cdigo da letra u a e da o maiscula A, fornecendo a posiao desta letra no alfabeto. Em seguida este u c valor somado ao cdigo da letra minscula a, resultando da converso para e o u a minscula. u Portanto, converses aritmticas ocorrem de maneira quase que natural. Em o e operaoes binrias as seguintes converses ocorrem quando diferentes tipos esto c a o a envolvidos: char convertido para int; e float convertido para double. e Ento, se algum dos operandos double o outro convertido para double a e e e o resultado double. Caso contrrio, se algum dos operandos long, o e a e outro convertido para long e o resultado long. Caso contrrio, se algum e e a dos operandos unsigned, o outro convertido para unsigned e o resultado e e e deste tipo. Caso contrrio os operandos so int e o resultado int. Note que a a e todos os floats em uma expresso so convertidos para double e a expresso a a a avaliada em double. e O resultado de uma expresso convertido para o tipo da varivel onde o rea e a sultado ser armazenado. Um resultado float ao ser carregado em uma varivel a a do tipo int causa o truncamento da parte fracionria, porventura existente. a A converso de inteiro para caractere bem comportada, mas o contrrio a e a nem sempre ocorre convenientemente. A linguagem no especica se o tipo a char um tipo com sinal ou no. Quando um caractere armazenado em uma e a e varivel do tipo inteiro podem ocorrer problemas com caracteres que tm o bit a e mais ` esquerda igual a 1. Isto porque algumas arquiteturas podem estender a este bit e outras no. a

87

5.10

Regras de Precedncia e

A Tabela 5.10 mostra, em ordem decrescente de prioridade, as regras de precedncia e dos operadores em C. Os operadores que esto na mesma linha da tabela e com a a mesma ordem tm a mesma prioridade. Alguns dos operadores listados na e Tabela somente sero mostrados nos cap a tulos seguintes. Pri 0 1 1 2 3 4 5 6 7 8 9 10 11 12 13 13 14 Operador () [] -> . ! ~ ++ -- * & (tipo) sizeof() * / % + >> << < <= >= > == != & ^ | && || ? () : () = += -= *= /= %= >>= <<= &= |= , Descrio ca Agrupamento; acesso vetor; acesso membro Unrias lgicas, aritmticas e com ponteiros; a o e Conformaao de tipo; tamanho c Multiplicaao, diviso e mdulo c a o soma e subtraao c Deslocamento de bits ` direita e esquerda a Operadores relacionais Igualdade e diferena c E bit a bit Ou exclusivo bit a bit Ou bit a bit E Ou Ternrio a Atribuioes c Atribuioes c Separador de expresses o

Tabela 5.9: Precedncia dos operadores. e

88

5.11

Exerc cios

5.1: Escreva as expresses C abaixo na sua forma matemtica usual: o a 1. (a/b)*(c/d) 2. (a/b*c/d) 3. (a/(b*c)/d) 4. a*x*x+b*x+c 5.2: Escreva as expresses matemticas na linguagem C. o a 1. b2 4 b c 2. 3.
1 1+
1+ 1 1 1+x

a+b c+d x c+d

4. a

5.3: Diga a ordem de clculo e o resultado das expresses abaixo: a o 1. x = 5 * 4 / 6 + 7; 2. x = 5 * 4.0 / 6 + 7; 3. x = 5 * 4 % 6 + 7; 4. x = ((4 / 2) + (3.0 * 5)); 5.4: Escreva um programa que imprima a tabela verdade da funao ou excluc sivo. 5.5: Escreva um programa que calcule o produto entre um valor x e 2n , onde n e x so inteiros. Utilize operadores binrios. a a 5.6: Escreva um programa que leia um ngulo em segundos e imprima quantos a graus, minutos e segundos h neste ngulo. a a 5.7: Escreva um programa que leia um tempo em segundos e imprima quantas horas, minutos e segundos h neste tempo. a 5.8: Escreva um programa que leia um comprimento em cent metros e imprima quantos metros, dec metros e cent metros h neste comprimento. a 5.9: Uma empresa est selecionando entre seus empregados os que iro fazer um a a treinamento especial. O funcionrio selecionado deve satisfazer a dois critrios. a e O primeiro critrio para que um funcionrio seja pr-selecionado que ele deve e a e e ter um salrio menor ou igual a R$ 400,00 ou maior ou igual a R$ 1.000,00. a O segundo critrio leva em conta o tempo de trabalho e o funcionrio deve ter e a mais de 5 anos na empresa. Marque a resposta que indica a expresso lgica a o que representa este critrio. Considere que existem as seguintes variveis. e a 89

Listing 5.3: Variveis da questo 9. a a


f l o a t salario ; i n t tempo ;

(a) (salario <= 400.00) && (salario >= 1000.00) && (tempo > 5) (b) (salario <= 400.00) || (salario >= 1000.00) && (tempo > 5) (c) ((salario <= 400.00) || (salario >= 1000.00)) || (tempo > 5) (d) ((salario <= 400.00) || (salario >= 1000.00)) && (tempo > 5) (e) ((salario <= 400.00) && (salario >= 1000.00)) || (tempo > 5)

90

Cap tulo 6

Comandos de Controle
6.1 Introduo ca

Este cap tulo tem por objetivo apresentar os comandos de controle da linguagem C. Estes comandos servem para controlar o uxo de execuao das instruoes c c de um programa. Estes comandos permitem que o computador tome decises o independentemente do usurio que est rodando o programa. a a

6.2

Blocos de Comandos

Blocos de comando so grupos de comandos que devem ser tratados como uma a unidade lgica. O in de um bloco em C marcado por uma chave de abertura o cio e ({) e o trmino por uma chave de fechamento (}). O bloco de comandos serve e para agrupar comandos que devem ser executados juntos. Por exemplo, usase bloco de comandos quando em comandos de teste deve-se escolher entre executar dois blocos de comandos. Um bloco de comandos pode ser utilizado em qualquer trecho de programa onde se pode usar um comando C. E interessante observar que um bloco de comandos pode ter zero comandos C. Um bloco de comandos com 0 ou 1 comando pode dispensar as chaves. Um bloco de comandos mostrado a seguir. e
/* bloco_de_co ma n do s */ { i = 0; j = j + 1; printf ( " % d % d \ n " , i , j ); }

6.3

Comandos de Teste

Os comandos de teste permitem ao computador decidir o caminho a seguir, durante a execuao do programa, independentemente do usurio. Estes testes c a 91

so baseados em estados internos dispon a veis ao processador. Estes estados podem ser resultantes de uma operaao aritmtica anterior, de uma operaao c e c anterior etc.

6.3.1

Comando if

O comando if utilizado quando for necessrio escolher entre dois caminhos. e a A forma geral do comando if a seguinte: e
i f ( express~ o ) a bloco_de_co m an d os 1 ; else bloco_de_co m an d os 2 ;

Neste comando a expresso avaliada, e caso o resultado seja verdadeiro a e (qualquer resultado diferente de zero) o bloco de comandos1 executado, caso e contrrio o bloco de comandos2 executado. Pela deniao do comando a exa e c presso deve ter como resultado um valor diferente de zero para ser considerada a verdade. Observar que somente um dos dois blocos ser executado. Como a a clusula else opcional a forma abaixo do comando if perfeitamente vlida. a e e a
i f ( express~ o ) a bloco_de_co ma nd o s ;

Lembrar que os blocos de comandos devem ser delimitados pelas chaves, a no ser quando o bloco composto por 0 ou 1 comando. Na listagem 6.1 a e mostramos alguns exemplos de uso de comando if. Listing 6.1: Exemplo de comandos if.
scanf ( " % d " , & dia ); i f ( dia > 31 || dia < 1 ) printf ( " Dia invalido \ n " ); scanf ( " % d " , & numero ); i f ( numero > 0 ) printf ( " Numero positivo \ n " ); else printf ( " Numero negativo \ n " ); scanf ( " % f " , & salario ); i f ( salario < 800.00) { printf ( " Aliquota de imposto = 0.1\ n " ); imposto = salario * 0.1; } else { printf ( " Aliquota de imposto = 0.25\ n " ); imposto = salario * 0.25; }

Uma construao que pode aparecer so os comandos ifs em escada, cuja c a forma geral a seguinte: e

92

i f ( express~ o ) a bloco_de_co ma n do s e l s e i f ( express~ o1 ) a bloco_de_c om a nd o s1 e l s e i f ( express~ o2 ) a bloco_de_co ma n do s 2 ... else bloco_de_co ma n do s n

O programa 6.2 mostra um exemplo com ifs em escada e aninhados. Um exemplo de uso deste programa o seguinte: e Este programa simula uma calculadora simples. Por favor entre com os dois operandos. 3 5 Qual a operacao + O resultado da + vale 8.000000. Para evitar que o recuo da escada seja muito profundo o comando if em escada foi escrito da seguinte maneira:
i f ( express~ o ) a bloco_de_co ma nd o s ; e l s e i f ( express~ o ) a bloco_de_co ma nd o s ; e l s e i f ( express~ o ) a bloco_de_co ma nd o s ; ... e l s e bloco_de_co ma n do s ;

6.3.2

Comando switch

O comando if, em todas suas formas, suciente resolver problemas de seleao e c de comandos. Porm em alguns casos, como no exemplo 6.2 o programa se e torna mais trabalhoso para ser escrito e entendido. O comando switch facilita a escrita de trechos de programa em que a seleao deve ser feita entre vrias c a alternativas. A forma geral do comando switch a seguinte: e
switch ( express~ o ) { a case constante1 : seq ^ ncia _d e _ co m an d o s ; ue break ; case constante2 : seq ^ ncia _d e _ co m an d o s ; ue break ; case constante3 : seq ^ ncia _d e _ co m an d o s ; ue break ; ...

93

Listing 6.2: Programas com ifs em escada e aninhados.


#i ncl ude < stdio .h > i n t main ( void ) { f l o a t num1 , /* primeiro operando */ num2 , /* segundo operando */ res ; /* resultado da operacao */ char oper ; /* caractere que define a operacao */ printf ( " \ nPrograma que simula calculadora simples .\ n " ); printf ( " Entre com os dois operandos .\ n " ); scanf ( " % f % f " , & num1 , & num2 ); getchar (); /* tirar o cr */ printf ( " Qual a operacao ? \ n " ); oper = getchar (); i f ( oper == + ) res = num1 + num2 ; e l s e i f ( oper == - ) res = num1 - num2 ; e l s e i f ( oper == * ) res = num1 * num2 ; e l s e i f ( oper == / ) { i f ( num2 == 0.0) { printf ( " Operacao de divisao por 0 invalida !\ n " ); return 1; } e l s e res = num1 / num2 ; } else { printf ( " Operacao invalida !\ n " ); return 1; } printf ( " O resultado da % c vale % f .\ n " , oper , res ); return 0; }

94

default: seq ^ ncia_ d e_ c o ma n do s ; ue }

Uma seqncia de comandos diferente de um bloco de comandos. Um ue e bloco de comandos inicia com uma chave e termina com uma chave, enquanto que uma seqncia apenas uma srie de comandos. Por exemplo, uma vez que ue e e um bloco de comandos foi selecionado por um comando if ele ser executado a at a ultima instruao do bloco, a menos que haja um comando de desvio. Uma e c srie de comandos so apenas comandos colocados um aps outro. A execuao e a o c do comando switch segue os seguintes passos: 1. A expresso avaliada; a e 2. O resultado da expresso comparado com os valores das constantes que a e aparecem nos comandos case; 3. Quando o resultado da expresso for igual a uma das constantes, a ea xecuao se inicia a partir do comando associado com esta constante. A c execuao continua at o m do comando switch, ou at que um comando c e e break seja encontrado; 4. Caso no ocorra nenhuma coincidncia os comandos associados ao coa e mando default so executados. O comando default opcional, e se ele a e no aparecer nenhum comando ser executado. a a O comando break um dos comandos de desvio da linguagem C. O break e usado dentro do comando switch para interromper a execuao da seqncia e c ue de comandos e pular para o comando seguinte ao comando switch. H alguns pontos importantes que devem ser mencionados sobre o comando a switch. O resultado da expresso deve ser um tipo enumervel, por exemplo o a a tipo int. Tambm podem ser usados tipos compat e veis com int, isto , e expresses com resultados tipo char podem ser usadas; o Notar que caso no aparea um comando de desvio, todas as instruoes a c c seguintes ao teste case que teve sucesso sero executadas, mesmo as que a estejam relacionadas com outros testes case; O comando switch s pode testar igualdade; o No podem aparecer duas constantes iguais em um case; a O programa 6.3 mostra um exemplo de uso de comandos switch.

6.3.3

Comando Ternrio a

O comando ternrio tem este nome porque necessita de trs operandos para ser a e avaliado. O comando ternrio tem a seguinte forma: a express~o1 ? a express~o2 : a express~o3 a 95

Listing 6.3: Exemplo de switch.


#i ncl ude < stdio .h > i n t main ( void ) { float num1 , /* primeiro operando */ num2 , /* segundo operando */ res ; /* resultado da operacao */ char oper ; /* caracter que define a operacao */ printf ( " \ nEste programa simula uma calculadora simples .\ n " ); printf ( " Por favor entre com os dois operandos .\ n " ); scanf ( " % f % f " , & num1 , & num2 ); getchar (); printf ( " Qual a operacao \ n " ); oper = getchar (); printf ( " A operacao e % c \ n " , oper ); switch ( oper ) { case + : res = num1 + num2 ; break ; case - : res = num1 - num2 ; break ; case * : res = num1 * num2 ; break ; case / : i f ( num2 == 0.0){ printf ( " Divisao por zero e uma opcao invalida .\ n " ); return 1; } else { res = num1 / num2 ; break ; } default: printf ( " Operacao invalida !\ n " ); return 2; } printf ( " O resultado da % c vale % f .\ n " , oper , res ); return 0; }

96

Para avaliar o resultado total da expresso, primeiro a express~o1 avalia a e ada. Caso este resultado seja correspondente ao valor verdadeiro ento o a resultado da expresso ser igual ao resultado da express~o2. Caso contrrio a a a a a express~o3 avaliada e se torna o resultado. O programa 6.4 mostra um a e exemplo de uso de comando ternrio. a Listing 6.4: Exemplo de comando ternrio. a
#i ncl ude < stdio .h > i n t main ( void ) { float num1 , /* primeiro operando */ num2 , /* segundo operando */ max ; /* resultado da operacao */ printf ( " Imprime o maior valor de dois numeros .\ n " ); printf ( " Por favor entre com os dois mumeros .\ n " ); scanf ( " % f % f " , & num1 , & num2 ); max = ( num1 > num2 )? num1 : num2 ; printf ( " O maior dos numeros lidos e % f .\ n " , max ); return 0; }

6.4

Laos de Repetio c ca

Estes comandos permitem que trechos de programa sejam repetidos um certo nmero de vezes controlado pelo programa. O nmero de vezes que um lao u u c ser executado pode ser xo ou depender de condioes que mudam durante a a c execuao do lao. c c

6.4.1

Comando for

Este comando aparece em vrias linguagens de programaao, mas na linguagem a c C ele apresenta um grau maior de exibilidade. A idia bsica do comando for e a e a seguinte. Uma varivel de controle, geralmente um contador, recebe um valor a inicial. O trecho de programa que pertence ao lao executado e ao nal a c e varivel de controle incrementada ou decrementada e comparada com o valor a e nal que ela deve alcanar. Caso a condiao de trmino tenha sido atingida o c c e lao interrompido. A forma geral do comando for a seguinte: c e e
f o r ( express~ o1 ; express~ o2 ; express~ o3 ) a a a blocodecoman do s ;

As trs expresses geralmente tm os seguintes signicados: e o e 1. A express~o1 utilizada para inicializar a varivel de controle do lao; a e a c 2. A express~o2 um teste que controla o m do lao; a e c 3. A express~o3 normalmente faz um incremento ou decremento da varivel a a de controle. 97

A execuao do comando for segue os seguintes passos: c 1. A express~o1 avaliada; a e 2. A express~o2 avaliada para determinar se o comando deve ser execua e tado; 3. Se o resultado da express~o2 for verdadeiro o bloco de comandos a e executado, caso contrrio o lao terminado; a c e 4. A expresso3 avaliada; a e 5. Voltar para o passo 2. O trecho a seguir imprime todos os nmeros entre 1 e 100. u
f o r ( i = 1; i <= 100; i ++) { printf ( " Numero % d \ n " , i ); }

O programa 6.5 mostra como se pode calcular o fatorial de um n mero u usando-se o comando for. Listing 6.5: Exemplo de comando for.
#i ncl ude < stdio .h > #include < stdlib .h > i n t main () { i n t numero , fat =1 , i ; printf ( " \ nEntre com um numero positivo . " ); scanf ( " % d " , & numero ); f o r ( i = numero ; i >1; i - -) fat = fat * i ; printf ( " O fatorial de % u vale % u . " , numero , fat ); return 0; }

Laos for com mais de um comando por expresso c a Outra possibilidade que o comando for em C permite a incluso de vrios e a a comandos, separados por v rgulas, nas expresses. O trecho de programa a o seguir mostra um exemplo de uso de comando for com vrios comandos nas a expresses. o
int i,j; f o r ( i =1 , j = 10; i <= 10; i ++ , j += 10) { printf ( " i = %d , j = % d \ n " , i , j ); }

98

Laos for com testes usando outras variveis c a A expresso de controle no precisa necessariamente envolver somente um teste a a com a varivel que controla o lao. O teste de nal do lao pode ser qualquer a c c expresso relacional ou lgica. No programa 6.6 o lao pode terminar porque a o c a varivel de controle j chegou ao seu valor limite ou foi batida a tecla *, e a a neste caso o lao termina antecipadamente. c Listing 6.6: Exemplo de comando for com testes sobre outras variveis. a
#include < stdio .h > i n t main () { char c = ; int i; f o r ( i =0 ; (i <5) && ( c != * ); i ++ ) { printf ( " % c \ n " , c ); c = getchar (); } return 0; }

Laos for com expresses faltando c o Um outro ponto importante do for que nem todas as expresses precisam estar e o presentes. No exemplo 6.7 a varivel de controle no incrementada. A unica a a e maneira do programa terminar o usurio bater o nmero -1. e a u Listing 6.7: Exemplo de comando for sem alteraao da varivel de controle. c a
#include < stdio .h > i n t main () { int i; f o r ( i =0 ; i != -1 ; ) { printf ( " % d \ n " ,i ); scanf ( " % d " , & i ); } return 0; }

E poss omitir qualquer uma das expresses. Por exemplo, se a express~o2 vel o a for omitida o programa assume que ela sempre verdade de modo que o lao e c s termina com um comando de desvio como o break. O programa do exemplo o 6.8 pra quando o valor da varivel de controle for igual a 5. Neste caso o teste a a ser verdade o lao termina por meio do break. a c Lao innito c Uma construao muito utilizada o lao innito. No lao innito o programa c e c c pra quando se executa o comando break. O trecho de programa a seguir a somente pra quando for digitada a tecla s ou S . a 99

Listing 6.8: Exemplo de comando for sem teste de m.


#include < stdio .h > i n t main () { int i; f o r ( i = 0; ; i ++) { printf ( " numero % d \ n " , i ); i f ( i == 5) break ; } return 0; }

for ( ; ; ) { printf ( " \ nVoce quer parar ?\ n " ); c = getchar (); i f ( c == S || c == s ) break ; }

Laos for aninhados c Uma importante construao aparece quando colocamos como comando a ser c repetido um outro comando for. Esta construao pode aparecer quando esc tamos trabalhando com matrizes. O exemplo 6.9 mostra um programa que imprime uma tabuada. Listing 6.9: Comando for aninhados.
#include < stdio .h > i n t main ( void ) { int i, j; printf ( " Imprime tabuada de multiplicacao .\ n " ); f o r ( i =1 ; i <10 ; i ++) { printf ( " Tabuada de % d \ n " , i ); f o r ( j =1; j <10; j ++) { printf ( " % d x % d = % d \ n " , i , j , i * j ); } } return 0; }

6.4.2

Comando while

O comando while tem a seguinte forma geral:


while ( express~ o ) a bloco_de_co ma n do s

A expresso pode assumir o valor falso (igual a 0) ou verdade (diferente a de 0). Os passos para execuao do comando so os seguintes: c a 100

1. A expresso avaliada; a e 2. Se o resultado for verdadeiro ento o bloco de comandos executado, a e caso contrrio a execuao do bloco terminada; a c e 3. Voltar para o passo 1. Uma caracter stica do comando while, como pode ser visto dos passos acima, que o bloco de comandos pode no ser executado caso a condiao seja igual a e a c falso logo no primeiro teste. O trecho de abaixo imprime os 100 primeiros nmeros usando um comando u while.
i = 1; while ( i <= 100) { printf ( " Numero % d \ n " , i ); i ++; }

A expresso do comando pode incluir chamadas de funao. Lembrar que a c qualquer atribuiao entre parnteses considerada como uma expresso que c e e a tem como resultado o valor da atribuiao sendo feita. Por exemplo, o programa c 6.10 repete um bloco de comandos enquanto o usurio usar a tecla c para a continuar, qualquer outra tecla o bloco interrompido. e Listing 6.10: Comando while com uma funao. c
#i ncl ude < stdio .h > i n t main ( void ) { int c; puts ( " Tecle c para continuar .\ n " ); while (( c = getchar ()) == c ) { puts ( " Nao Acabou .\ n " ); getchar (); /* tira o enter */ } puts ( " Acabou .\ n " ); return 0; }

6.4.3

Comando do-while

A forma genrica do comando a seguinte: e e


do bloco_de_co ma n do s while ( express~ o ); a

Observar que neste comando a expresso de teste est aps a execuao do a a o c comando, portanto o bloco de comandos executado pelo menos uma vez. A e execuao do comando segue os seguintes passos: c

101

1. Executa o comando; 2. Avalia a expresso; a 3. Se o resultado da expresso for verdadeiro ento volta para o passo 1, a a caso contrrio interrompe o do-while a O exemplo de comando for para imprimir os 100 primeiros n meros escrito u com comando do-while ca da seguinte maneira:
i = 1; do { printf ( " Numero % d \ n " , i ); i ++; } while ( i <= 100);

6.5
6.5.1

Comandos de Desvio
Comando break

O comando break pode ser tanto usado para terminar um teste case dentro de um comando switch quanto interromper a execuao de um lao. Quando o c c comando utilizado dentro de um comando for o lao imediatamente intere c e rompido e o programa continua a execuao no comando seguinte ao comando c for. No trecho de programa abaixo o comando for deve ler 100 nmeros inteiros u positivos. No entanto, se for digitado um nmero negativo o comando for u e interrompido imediatamente sem que o nmero seja impresso. u
f o r ( i = 0; i < 100; i ++) { scanf ( " % d " , & num ); i f ( num < 0) break ; printf ( " % d \ n " , num ); }

6.5.2

Comando continue

O comando continue parecido com o comando break. A diferena que o e c e comando continue simplesmente interrompe a execuao da iteraao corrente c c passando para a prxima iteraao do lao, se houver uma. No comando for o o c c controle passa a execuao da express~o3. Nos comandos while e do-while o c a controle passa para a fase de testes. No trecho de programa abaixo o lao l 100 nmeros inteiros, caso o n mero c e u u seja negativo, um novo nmero lido. u e
f o r ( i = 0; i < 100; i ++) { scanf ( " % d " , & num ); i f ( num < 0) continue ; printf ( " % d \ n " , num ); }

102

6.5.3

Comando goto

O comando goto causa um desvio incondicional para um outro ponto da funao c em que o comando est sendo usado. O comando para onde deve ser feito o a desvio indicado por um rtulo, que um identicador vlido em C seguido por e o e a dois pontos. E importante notar que o comando goto e o ponto para onde ser a feito o desvio pode estar em qualquer ponto dentro da mesma funao. A forma c geral deste comando : e goto rtulo; o ... rtulo: o Este comando durante muito tempo foi associado a programas ileg veis. O argumento para esta armaao se baseia no fato de que programas com comanc dos goto perdem a organizaao e estrutura porque o uxo de execuao pode c c car saltando erraticamente de um ponto para outro. Atualmente as restrioes c ao uso do comando tem diminu e seu uso pode ser admitido em alguns casos. do

6.5.4

Funo exit() ca

A funao exit provoca a terminaao de um programa, retornando o controle ao c c sistema operacional. O prottipo da funao a seguinte: o c e void exit (int codigo); Observar que esta funao interrompe o programa como um todo. O cdigo c o usado para indicar qual condiao causou a interrupao do programa. Usuale c c mente o valor 0 indica que o programa terminou sem problemas. Um valor diferente de 0 indica um erro.

6.5.5

Comando return

O comando return usado para interromper a execuao de uma funao e ree c c tornar um valor ao programa que chamou esta funao. Caso haja algum valor c associado ao comando return este devolvido para a funao, caso contrrio um e c a valor qualquer retornado. A forma geral do comando : e e return express~o; a Notar que a expresso opcional. A chave que termina uma funao equiva e c e alente a um comando return sem a expresso correspondente. E poss haver a vel mais de um comando return dentro de uma funao. O primeiro que for enc contrado durante a execuao causar o m da execuao. Uma funao declarada c a c c como do tipo void no pode ter um comando return que retorne um valor. a Isto no faz sentido, j que funoes deste tipo no podem retornar valores. a a c a

103

6.6

Exerc cios

6.1: Escreva um programa que calcule x elevado a n. Assuma que n um valor e inteiro. 6.2: Escreva um programa que exiba as opoes c 1-multiplicar e 2-somar de um menu, leia a opao desejada, leia dois valores, execute a operaao (utic c lizando o comando if) e exiba o resultado. 6.3: Utilizando ifs em escada, inclua, no programa do exerc anterior, as cio opoes 3-Subtrair e 4-Dividir. c 6.4: Simplique os programas anteriores da seguinte forma: Reescreva o programa do exerc 1 substituindo o comando if pelo cocio mando ternrio. a Reescreva o programa do exerc 2 substituindo os ifs em escada pelo cio comando switch. 6.5: Utilizando um lao for dentro de outro, escreva um programa que exiba c as tabuadas de multiplicaao dos nmeros de 1 ` 9. c u a 6.6: Escreva um programa com menu de 5 opoes que utilize o comando de c desvio goto para executar a opao desejada e s saia do programa caso a opao c o c 5-Sair seja selecionada. 6.7:Escreva um programa que tenha um nmero (inteiro) como entrada do u usurio e escreva como sa a seqencia de bits que forma esse numero. Por a da u exemplo, aps digitado o nmero 10, a sa deve ser 0000000000001010. o u da 6.8:Escreva um programa que imprima todos os pares entre 0 e 50 e em seguida imprima todos os impares. Deixar um espao entre os nmeros. c u 6.9: Escreva um programa que leia 10 nmeros. O programa deve imprimir a u media, o maior e o menor deles. Obs: Os nmeros devem ser entre 0 e 10. u 6.10: Escreva um programa que leia 10 nmeros. O programa deve imprimir a u media, o maior e o menor deles. Obs: Considere agora que os nmeros podem ser quaisquer. u 6.11: Escreva um programa que exibe a tabela ascii. 6.12: Crie um programa para vericar se um nmero dado primo. u e 6.13: Escreva um programa que leia um numero do teclado e ache todos os seus divisores. 6.14: Escreva um programa que imprima a seqncia ue 987654321876543217654321654321543214321321211

104

No use nenhuma constante, use apenas variveis. Em outra linha imprima a a as letras maisculas de A at Z (ABCD...). u e 6.15: Escreva um programa que conte de 100 a 999 (inclusive) e exiba, um por linha, o produto dos trs d e gitos dos nmeros. Por exemplo, inicialmente o u programa ir exibir: a 0 (1*0*0) 0 (1*0*1) 0 (1*0*2) (...) 0 (1*1*0) 1 (1*1*1) 2 (1*1*2) 9*9*9=729 Faa seu programa dar uma pausa a cada 20 linhas para que seja poss c vel ver todos os nmeros pouco a pouco. Solicite que seja pressionada alguma tecla u para ver a prxima seqncia de nmeros. o ue u 6.16: Escreva um programa que imprima uma gura como a mostrada abaixo. O nmero de linhas da gura deve ser pedido ao usurio. u a ****** ***** **** *** ** *

6.17: O que ser impresso pelo programa 6.11. Indique os nmeros que voc a u e ir digitar para o programa. Os nmeros devem ser todos diferentes. a u

105

Listing 6.11: Programa do exercicio 17.


#include < stdio .h > i n t main ( void ) { int i, j, m; f o r ( i = 0; i < 6; i ++) { scanf ( " % d " , & m ); i f ( m % 2) { f o r ( j = 0; j < m ; j ++) { printf ( " # " ); } } else { f o r ( j = m ; j > 0; j - -) { printf ( " * " ); } } printf ( " \ n " ); } return 0; }

106

Cap tulo 7

Vetores e Cadeias de Caracteres


7.1 Introduo ca

Vetores so usados para tratamento de conjuntos de dados que possuem as a mesmas caracter sticas. Uma das vantagens de usar vetores que o conjunto e recebe um nome comum e elementos deste conjunto so referenciados atravs de a e ndices. Pelo nome vetor estaremos referenciando estruturas que podem ter mais de uma dimenso, como por exemplo matrizes de duas dimenses. Neste cap a o tulo estaremos mostrando vetores de tamanhos xos. Somente aps apresentarmos o ponteiros iremos abordar alocaao de memria para vetores. c o

7.2

Declarao de Vetores Unidimensionais ca

A forma geral da declaraao de vetores de uma dimenso : c a e


tipo nome [tamanho];

onde tipo um tipo qualquer de dados, nome o nome pelo qual o vetor vai e e ser referenciado e tamanho o nmero de elementos que o vetor vai conter. e u Observar que em C o primeiro elemento tem ndice 0 e o ultimo tamanho - 1. Exemplos de declaraoes de vetores so: c a
i n t numeros [1000]; f l o a t notas [65]; char nome [40]; /* vetor de 1000 inteiros */ /* conjunto de 65 numeros reais */ /* conjunto de 40 caracteres */

O espao de memria, em bytes, ocupado por um vetor de tipo qualquer c o e igual a:


espao = tamanho * sizeof(tipo) c

E importante notar que em C no h vericaao de limites em vetores. Isto a a c signica que poss e vel ultrapassar o m de um vetor e escrever em outras variveis, ou mesmo em trechos de cdigo. E tarefa do programador fazer com a o 107

que os ndices dos vetores estejam sempre dentro dos limites estabelecidos pela declaraao do vetor. c O programa 7.1 ilustra como se declara um vetor, inicializa seus valores e imprime o contedo. Notar o uso da diretiva #define DIM 5 para denir u uma constante, que posteriormente foi usada para estabelecer o tamanho do vetor. Esta constante passa a ser usada nas referncias ao vetor, por exeme plo no comando de geraao do conjunto de dados armazenado no vetor. Caso c seja necessrio trocar o tamanho do vetor basta alterar o valor da constante e a recompilar o programa. Listing 7.1: Exemplo de vetores.
#de fi ne DIM 5 #i ncl ude < stdio .h > i n t main ( void ) { i n t vetor [ DIM ]; unsigned i n t i , num ; puts ( " Este programa gera um vetor de inteiros .\ n " ); puts ( " Entre com o numero inicial do conjunto . " ); scanf ( " % d " , & num ); /* Geracao do conjunto */ f o r ( i = 0 ; i < DIM ; i ++) vetor [ i ] = num ++; /* Impressao do conjunto */ f o r ( i = 0; i < DIM ; i ++) printf ( " Elemento % d = % d \ n " , i , vetor [ i ]); return 0; }

O programa 7.2 calcula o produto escalar de dois vetores inteiros. Observar como na leitura dos elementos do vetor usa-se o operador de endereo & antes c do nome de cada elemento. O programa 7.3 ilustra o mtodo da bolha para ordenaao em ordem crese c cente de um vetor de inteiros. Neste mtodo a cada etapa o maior elemento e e movido para a sua posiao. A cada iteraao os elementos do vetor so comparac c a dos dois a dois, sendo trocados caso seja necessrio. Ao trmino da primeira a e passada pelo vetor, o maior elemento levado para a sua posiao, no nal do e c vetor. Portanto, ele no precisa ser mais considerado, da o valor da varivel a a que aponta para o nal do vetor (fim) diminu de 1. O processo repetido e da e at que todos os elementos sejam levados para as suas posioes ou que nenhuma e c troca seja realizada. Quando nenhuma troca realizada o vetor est ordenado. e a A Tabela 7.1 mostra os passos executados pelo algoritmo at ordenar o vetor. e

7.3

Cadeias de Caracteres

Um cadeia de caracteres (string) um conjunto de caracteres terminado por um e caractere nulo, que representado como \0. Para especicar um vetor para e 108

Operao ca Passo 1 v[0] > v[1]? Trocar v[0] e v[1] > v[2]? Trocar v[1] e v[2] > v[3]? Trocar v[2] e v[3] > v[4]? Trocar v[3] e Passo 2 v[0] > v[1]? Trocar v[0] e v[1] > v[2]? Trocar v[1] e v[2] > v[3]? Trocar v[2] e Passo 3 v[0] > v[1]? v[1] > v[2]? Trocar v[1] e Passo 4 v[0] > v[1]? Trocar v[0] e

v[0] 20 15 15 15 15 15 15 15 15 8 8 8 8 8 8 8 8 8 5

v[1] 15 20 20 8 8 8 8 8 8 15 15 12 12 12 12 12 5 5 8

v[2] 8 8 8 20 20 12 12 12 12 12 12 15 15 5 5 5 12 12 12

v[3] 12 12 12 12 12 20 20 5 5 5 5 5 5 15 15 15 15 15 15

v[4] 5 5 5 5 5 5 5 20 20 20 20 20 20 20 20 20 20 20 20

v[1] v[2] v[3] v[4]

v[1] v[2] v[3]

v[2]

v[1]?

Tabela 7.1: Passos executados durante o algoritmo da bolha.

109

Listing 7.2: Produto escalar de dois vetores.


#de fi ne DIM 5 #i ncl ude < stdio .h > i n t main ( void ) { i n t vetor1 [ DIM ] , vetor2 [ DIM ] , i , prod =0; printf ( " Entre com um vetor de % d elementos \ n " , DIM ); f o r ( i = 0; i < DIM ; i ++) { printf ( " Elemento % d " , i ); scanf ( " % d " , & vetor1 [ i ]); } printf ( " Entre com outro vetor de % d elementos \ n " , DIM ); f o r ( i = 0; i < DIM ; i ++) { printf ( " Elemento % d " , i ); scanf ( " % d " , & vetor2 [ i ]); } f o r ( i = 0; i < DIM ; i ++) prod += vetor1 [ i ] * vetor2 [ i ]; printf ( " O produto vale % d " , prod ); return 0; }

armazenar um cadeia deve-se sempre reservar um espao para este caractere. c Por exemplo, para armazenar um cadeia de 40 caracteres deve-se reservar um vetor de 41 de caracteres. Em C poss e vel haver constantes cadeia, que so a denidas como uma lista de caracteres entre aspas. Por exemplo, "programando em C" No necessrio a colocaao do caractere nulo ao nal da cadeia. Em C a e a c no h o tipo cadeia (string) e, portanto, conjuntos de caracteres teriam de a a ser tratados como conjuntos de nmeros inteiros, por exemplo. Para facilitar a u programaao foram criadas algumas funoes para manipular cadeias. Algumas c c das funoes mais comuns esto resumidamente descritas a seguir: c a Nas denioes a seguir, size_t o tipo inteiro sem sinal que volta como c e resultado do operador sizeof. char *strcat(char *dest, const char *orig): Concatena cadeia orig ao nal de dest. O primeiro caractere de orig substitui o caractere nulo de dest. A funao retorna o valor de dest. c char *strncat (char *dest, const char *orig, size_t n): Concatena cadeia orig ao nal de dest, usando no mximo n caracteres de orig. O a primeiro caractere de orig substitui o caractere nulo de dest. A funao c retorna o valor de dest. char *strcmp (const char *cad1, const char *cad2): Compara lexicogracamente as duas cadeias. Retorna zero se as cadeias so iguais, menor a que 0 se cad1 < cad2, maior que 0 se cad1 > cad2. 110

Listing 7.3: Ordenaao pelo mtodo da bolha. c e


#de fi ne DIM 5 #de fi ne FALSO 0 #de fi ne VERDADE 1 #i ncl ude < stdio .h > i n t main ( void ) { i n t vetor [ DIM ] , i ; i n t trocou = FALSO , fim = DIM , temp ; printf ( " Entre com um vetor de % d elementos \ n " , DIM ); f o r ( i = 0; i < DIM ; i ++) { printf ( " Elemento % d " , i ); scanf ( " % d " , & vetor [ i ]); } do { trocou = FALSO ; f o r ( i =0; i < fim -1; i ++) { i f ( vetor [ i ] > vetor [ i +1]) { temp = vetor [ i ]; vetor [ i ] = vetor [ i +1]; vetor [ i +1] = temp ; trocou = VERDADE ; } } fim - -; } while ( trocou ); f o r ( i =0; i < DIM ; i ++) printf ( " % d \ n " , vetor [ i ]); return 0; }

111

char *strncmp (const char *cad1, const char *cad2, size_t n): Compara lexicogracamente at n caracteres das duas cadeias. Retorna zero e se as cadeias so iguais, menor que 0 se cad1 < cad2, maior que 0 se a cad1 > cad2. size_t strlen(const char *cad): Calcula o comprimento da cadeia sem contar o caraca ter nulo. O comprimento da cadeia determinado pelo e caractere nulo. No confundir o tamanho da cadeia com o tamanho do a vetor que armazena a cadeia. char *strcpy(char *dest, const char *orig): Copia cadeia orig para dest. A cadeia destino deve ter espao suciente para armazenar orig. c O valor de dest retornado. e Estas funoes esto na biblioteca string.h. O programa 7.4 mostra exemc a plos de uso de algumas das funoes de cadeia. Neste exemplo, o programa c primeiro l um nome e em seguida um sobrenome. O programa ir ento cone a a catenar as duas cadeias. Observe que sempre colocado um branco ao nal e do nome para separ-lo do sobrenome. Este branco inserido usando a funao a e c strcat, e esta razo das aspas, ou seja, uma cadeia de um caractere apenas. e a A seguir mostramos um resultado da execuao do programa 7.4. c Entre com um nome Ze Ze Entre com um sobrenome Sa Sa Ze Sa Qual caracter? a O caractere aparece na posicao 4

7.4

Declarao de Vetores Multidimensionais ca

Em C existe a possibilidade de declararmos vetores de mais de uma dimenso. a A forma geral da declaraao a seguinte: c e tipo nome [dim1][dim2][dim3]...[dimN]; onde dimI o tamanho da dimenso I. Deve-se tomar cuidado com armazenae a mento de matrizes multidimensionais, por que a memria necessria para guardar o a estes dados igual a e
sizeof(tipo)*dim1*dim2*dim3*...*dimN

Por exemplo a declaraao c


int matriz[10][20];

dene uma matriz quadrada de 10 linhas por 20 colunas, enquanto o comando


c = 2 * matriz[3][8];

armazena o dobro do elemento que est na quarta linha e nona coluna na varivel a a c. Observar que o primeiro ndice indica a linha e o segundo a coluna. Lembrar 112

Listing 7.4: Exemplos de funoes para cadeias. c


#include < string .h > #include < stdio .h > i n t main ( void ) { char c , nome [81] , sobrenome [41]; int i; printf ( " Entre com um nome " ); fgets ( nome , 41 , stdin ); nome [ strlen ( nome ) -1] = \0 ; /* tira cr do fim */ puts ( nome ); printf ( " Entre com um sobrenome " ); fgets ( sobrenome , 41 , stdin ); sobrenome [ strlen ( sobrenome ) -1] = \0 ; puts ( sobrenome ); strcat ( nome , " " ); strcat ( nome , sobrenome ); puts ( nome ); printf ( " Qual caracter ? " ); c = getchar (); f o r ( i =0; i < strlen ( nome ); i ++) { i f ( c == nome [ i ]) { printf ( " O caractere aparece na posicao % d \ n " , i ); } } return 0; }

113

que o nmero da primeira linha (coluna) igual a 0. O programa 7.5 l uma u e e matriz de trs linhas e cinco colunas e imprime os valores lidos. e Listing 7.5: Leitura de uma matriz.
#de fi ne DIML 3 #de fi ne DIMC 5 #i ncl ude < stdio .h > i n t main ( void ) { int i, j; i n t matriz [ DIML ][ DIMC ]; f o r ( i =0; i < DIML ; i ++) f o r ( j =0; j < DIMC ; j ++) scanf ( " % d " , & matriz [ i ][ j ]); f o r ( i =0; i < DIML ; i ++) { f o r ( j =0; j < DIMC ; j ++) printf ( " %4 d " , matriz [ i ][ j ]); printf ( " \ n " ); } return 0; }

A matriz armazenada na memria linha a linha e a Figura 7.4 ilustra esta e o idia com uma matriz de nmeros inteiros de trs por trs. Estamos assumindo e u e e que cada nmero inteiro ocupa quatro bytes, o endereo aponta um byte e a u c matriz est armazenada a partir do endereo 1000. a c Uma operaao muito comum em matemtica a multiplicaao de matrizes. c a e c Considere a matriz M 1 com L1 linhas e C1 colunas e a matriz M 2 com L2 linhas e C2 colunas. O nmero de colunas C1 de M 1 deve ser igual ao n mero u u de linhas L2 de M 2. O elemento M Rij da matriz resultado M R do produto destas matrizes denido pela equaao 7.1. O programa 7.6 multiplica duas e c matrizes de acordo com a frmula. o
C1

M Rij =
k=1

M 1ik M 2kj

(7.1)

7.5

Vetores de Cadeias de Caracteres

A declaraao abaixo mostra uma matriz de cadeias de caracteres com 30 linhas c de 80 caracteres. char nome turma[30][80]; O Programa 7.7 mostra um programa que l uma matriz de nomes e imprime e os seus contedos. E importante notar que para ler um nome o programa no u a l um caracter de cada vez mas usa a funao fgets. Como cada linha da matriz e c uma cadeia de caracteres, o programa l o nome que est na linha i como e e a fgets(nomes[i], DIMC-1, stdin). 114

Listing 7.6: Multiplicaao de duas matrizes. c


#include < stdio .h > #de fi ne #de fi ne #de fi ne #de fi ne L1 L2 C1 C2 3 3 3 3

i n t main ( void ) { f l o a t m1 [ L1 ][ C1 ] , m2 [ L2 ][ C2 ]; f l o a t mr [ L1 ][ C2 ] , m ; int i, j, k; f o r ( i =0; i < L1 ; i ++) { f o r ( j =0; j < C1 ; j ++) { printf ( " %d , % d " , i , j ); scanf ( " % f " , & m1 [ i ][ j ]); } } f o r ( i =0; i < L2 ; i ++) { f o r ( j =0; j < C2 ; j ++) { printf ( " %d , % d " , i , j ); scanf ( " % f " , & m2 [ i ][ j ]); } } f o r ( i =0; i < L1 ; i ++) { f o r ( j =0; j < C2 ; j ++) { m = 0; f o r ( k =0; k < C1 ; k ++) { m += m1 [ i ][ k ]* m2 [ k ][ j ]; } mr [ i ][ j ] = m ; } } f o r ( i =0; i < L1 ; i ++ ) { f o r ( j =0; j < C2 ; j ++) { printf ( " %.3 f " , mr [ i ][ j ]); } printf ( " \ n " ); } return 0; }

115

1000

m[0][0]

1004

m[0][1]

1008

m[0][2]

1012

m[1][0]

1016

m[1][1]

1020

m[1][2]

1024

m[2][0]

1028

m[2][1]

1032

m[2][2]

Figura 7.1: Mapa de memria de uma matriz. o

7.6

Inicializao de Vetores e Matrizes ca

Em C poss e vel inicializar vetores da mesma forma que variveis, isto , no a e momento em que so declarados. A forma de fazer isto a seguinte: a e tipo nome[dim] = {lista de valores}; onde lista de valores um conjunto de valores separados por v e rgulas. Por exemplo, a declaraao abaixo inicializa um vetor inteiro de cinco posioes. c c int vetor[5] = { 10, 15, 20, 25, 30 }; Observe que nesta declaraao necessrio que o tamanho do conjunto seja c e a conhecido antecipadamente. No entanto, tambm poss inicializar vetores e e vel em que no se conhece o seu tamanho. Neste caso, ento, importante que o a a e programador preveja um modo de indicar o m do vetor. O Programa 7.8 mostra os casos ilustrados acima. No primeiro exemplo o tamanho do vetor conhecido e foi denido pela constante DIM. Para descobrir o e como parar de processar o vetor, quando desconhecemos seu tamanho, apresentamos duas soluoes poss c veis. No primeiro caso a condiao de m do vetor o c e nmero negativo -1. Neste caso uma posiao do vetor perdida para armazenar u c e esta condiao. No segundo caso usado o operador sizeof para descobrir o c e tamanho do vetor. Observe que sizeof calcula o tamanho do vetor em bytes e por esta razo necessrio uma diviso pelo tamanho em bytes do tipo de cada a e a a elemento. 116

Listing 7.7: Leitura de um vetor de nomes.


#de fi ne DIML 5 #de fi ne DIMC 41 #i ncl ude < stdio .h > #i ncl ude < string .h > i n t main ( void ) { int i; char nomes [ DIML ][ DIMC ]; f o r ( i =0; i < DIML ; i ++) { printf ( " Entre com a linha % d " , i ); fgets ( nomes [ i ] , DIMC -1 , stdin ); nomes [ i ][ strlen ( nomes [ i ]) -1] = \0 ; } f o r ( i =0; i < DIML ; i ++) { printf ( " O nome % d e " , i ); puts ( nomes [ i ]); } return 0; }

E poss vel inicializar matrizes multidimensionais e neste caso necessrio e a especicar todas as dimenses menos a primeira, para que o compilador possa o reservar memria de maneira adequada. A primeira dimenso somente especica o a quantos elementos o vetor ir armazenar e isto lendo a inicializaao o compilador a c pode descobrir. A declaraao a seguir ilustra como declarar e inicializar uma matriz de trs c e linhas por quatro colunas de nmeros reais. u
f l o a t mat [][4] = { {1.0 , 2.0 , 3.0 , 4.0} , // linha 0 {8.0 , 9.0 , 7.5 , 6.0} , // linha 1 {0.0 , 0.1 , 0.5 , 0.4} }; // linha 2

O Programa 7.9 ilustra a deniao de um vetor de cadeia de caracteres, que c nada mais do que uma matriz de caracteres. Note que as cadeias so separadas e a uma das outras por v rgulas.

117

Listing 7.8: Exemplos de tratamento de vetores.


#de fi ne DIM 5 #include < stdio .h > i n t main () { i n t vetor [ DIM ] = {10 , 15 , 20 , 25 , 30}; i n t vetor1 [] = {10 , 20 , 30 , 40 , 50 , 60 , -1}; i n t vetor2 [] = {3 , 6 , 9 , 12 , 15 , 18 , 21 , 24}; unsigned i n t i , tam ; printf ( " Este programa imprime vetores " ); printf ( " contendo numeros inteiros e \ n " ); printf ( " que foram inicializados durante " ); printf ( " a sua declaracao .\ n " ); /* Impressao dos conjuntos */ printf ( " \ nVetor com tamanho pre - definido \ n " ); f o r ( i =0; i < DIM ; i ++) printf ( " Elemento % d = % d \ n " , i , vetor [ i ]); printf ( " \ nVetor terminando por -1\ n " ); f o r ( i =0; vetor1 [ i ] >0; i ++) printf ( " Elemento % d = % d \ n " , i , vetor1 [ i ]); tam = s i z e o f ( vetor2 ) printf ( " \ nDescobrindo f o r ( i =0; i < tam ; printf ( " Elemento return 0; } / s i z e o f ( i n t ); o tamanho do Vetor \ n " ); i ++) % d = % d \ n " , i , vetor2 [ i ]);

Listing 7.9: Exemplos de tratamento de vetores.


#de fi ne DIM 5 #include < stdio .h > i n t main ( void ) { char disciplinas [][40] = { " disc 0: Computacao para Informatica " , " disc 1: Banco de Dados I " , " disc 2: Banco de Dados II " , " disc 3: Arquitetura de Computadores I " }; int i; printf ( " Qual a disciplina ? " ); scanf ( " % d " , & i ); puts ( disciplinas [ i ]); return 0; }

118

7.7

Exerc cios

7.1: Escreva um programa que leia uma linha de at 80 caracteres do teclado e e imprima quantos caracteres foram lidos. 7.2: Escreva um programa que leia uma linha de caracteres do teclado e imprima quantas vezes um caractere, tambm fornecido pelo teclado, aparece nesta linha. e O programa tambm deve imprimir em que posioes o caractere foi encontrado. e c 7.3: Escreva um programa que leia uma linha do teclado e em seguida um par de caracteres. O programa deve procurar este par na linha e imprimir em que posioes o par foi encontrado. Obs. No use funoes da biblioteca de strings c a c do C 7.4: Escreva um programa que leia uma linha do teclado e imprima todas as vogais encontradas no texto e o total de vezes que elas aparecem. Obs: Tamanho mximo da linha deve ser 40 caracteres. a 7.5: O imperador romano Csar usava um sistema simples para codicar as e mensagens que enviava aos seus generais. Neste sistema cada letra era substitu por trs letras ` frente no alfabeto. A sua misso mais simples ainda, da e a a e escrever um programa que converta cada letra, e somente as letras, de uma mensagem de at 80 caracteres para a letra imediatamente posterior. Note que e a letra z deve ser convertida para a letra a, e a letra Z para A. 7.6: Escreva um programa que leia uma frase de 80 caracteres e a imprime retirando os espaos em branco. c 7.7: Escreva um programa que leia uma linha de caracteres do teclado de tamanho 80. A linha somente contm letras. Divida a linha em blocos de 5 e letras. Dentro de cada bloco o seu programa deve trocar a primeira letra pela letra seguinte no alfabeto, a segunda letra por duas letras adiante no alfabeto, a terceira por trs letras adiante e assim at a quinta. Os espaos em branco e e c devem ser retirados da frase. Considere o seguinte exemplo. 1. Frase lida: EVA VIU A UVA 2. Retirada dos espaos em branco: c EVAVIUAUVA 3. Diviso em blocos de 5 (blocos indicados por tipos diferentes): a EVAVIUAUVA 4. Criptograa: FYDANVCYAF Portanto, o que ser impresso pelo programa : a e FYDANVCYAF 7.8: Escreva um programa que leia uma matriz de 3x3 que contm somente e caracteres 0 e X e procure linhas que contenham somente um dos dois caracteres. O caractere a ser procurado deve ser lido do teclado. 119

7.9: Escreva um programa que leia uma linha de caracteres do teclado e converta o primeiro caractere de cada palavra para maisculas. Assuma que as palavras u so sempre separadas por um branco. a 7.10: Escreva um programa que leia para um vetor um conjunto de n meros u inteiros. Assuma que o conjunto de nmeros lidos menor que o tamanho do u e vetor. O programa deve inserir no vetor, em uma posiao especicada pelo c usurio, um nmero lido do teclado. Assuma que a posiao especicada pelo a u c usurio corresponde ao a ndice do vetor. 7.11: Faa um programa que inverta uma cadeia de caracteres. O programa c deve ler a cadeia com gets e armazen-la invertida em outra cadeia. Use o a comando for para varrer a cadeia at o seu nal. e 7.12: Escreva um programa que leia um conjunto de nomes para uma matriz e imprima estes nomes em ordem alfabtica. Assuma que os nomes sero lidos e a somente em letras maisculas. Assuma tambm que os nomes tm no mximo u e e a 40 caracteres e sero lidos 10 nomes ao todo. a 7.13: Escreva um programa que leia um conjunto N (1 N 1000000000) de nmeros inteiros e imprima os seguintes resultados: u media dos nmeros; u maior dos nmeros; u menor dos nmeros; u produto de todos os nmeros. u 7.14: Considere que voc digitou o seu nome para o programa mostrado na e listagem 7.10. O que ser impresso? Indique o que voc digitou. Justique a e sua resposta com detalhes.

120

Listing 7.10: Programa do exercicio 14.


#include < stdio .h > #include < string .h > #de fi ne MAX 50 i n t main ( void ) { char texto [ MAX +2] , temp ; i n t tam , i ; gets ( texto ); tam = strlen ( texto ); f o r ( i = 0; i < tam ; i ++) { temp = texto [ i ]; texto [ i ] = texto [ tam -1 - i ]; texto [ strlen ( texto ) -1 - i ] = temp ; } puts ( texto ); return 0; }

121

Cap tulo 8

Funes co
8.1 Introduo ca

Em C, diferentemente de outras linguagens como Pascal, todas as aes ocorrem co dentro de funoes. Na linguagem C no h conceito de um programa principal, o c a a que existe uma funao chamada main que sempre a primeira a ser executada. e c e Um programa pode ser escrito apenas com a funao main e mais as funoes c c existentes nas bibliotecas da linguagem C. No entanto o uso de funoes pode c facilitar o desenvolvimento de programas de diversas maneiras. Em primeiro lugar temos as vantagens do reuso de cdigo desenvolvido por o outros programadores. As funoes de entrada e sa so o exemplo mais direto c da a deste reuso. Em C no existem estes tipos de comandos como na maioria das a linguagens. Programas escritos em C usam funoes de entrada e sa escritas c da e testadas por outros programadores. Este reuso de cdigo apresenta vrias o a vantagens. Primeiro, diminui o tempo de desenvolvimento do programas. Em segundo lugar, como estas funoes foram testadas por diversos usurios, a quanc a tidade de erros bastante reduzida. Estes fatores contribuem para a reduao e c dos custos de desenvolvimento dos projetos. Uma outra vantagem do uso de funoes e a maior facilidade na diviso do c a trabalho necessrio para construir um aplicativo. Funoes podem ser desena c volvidas por programadores trabalhando independentemente. Para isto basta que alguns acordos sejam feitos entre os programadores que iro programar a a funao e os que iro us-las. Estes acordos precisam denir que parmetros a c a a a funao ir receber, que resultados ir fornecer e que operaoes ela deve realizar c a a c sobre estes parmetros para obter os resultados necessrios. Esta diviso do a a a trabalho concorre para acelerar o desenvolvimento dos programas e na reduao c dos custos deste desenvolvimento. A diviso de um programa em funoes tambm permite que os testes do a c e sistema completo sejam feitos mais facilmente e com mais garantia de correao. c Os programadores podem testar suas funoes separadamente em testes menos c complexos, j que as funoes normalmente so simples e tm requisitos menos a c a e complicados de serem avaliados. Isto permite que muitos erros do sistema completo possam ser retirados antes que ele esteja completo. Normalmente testar um programa complexo requer testes complexos. 122

Mesmo quando um programa desenvolvido por um unico programador a e sua diviso em funoes traz vantagens, por dividir um trabalho complexo em a c diversas fatias menores permitindo ao programador se concentrar a cada vez em problemas mais simples.

8.2

Forma Geral

A forma geral de uma funao em C a seguinte: c e


tipo nome ( tipo nome1 , tipo nome2 , ... , tipo nomeN ){ declara ~ o das vari veis ca a corpo da fun ~ o ca }

Uma funao recebe uma lista de argumentos (nome1, nome2, ..., nomeN), c executa comandos com estes argumentos e pode retornar ou no um resultado a para a funao que chamou esta funao. A lista de argumentos, tambm chamac c e dos de parmetros, uma lista, separada por v a e rgulas, de variveis com seus a tipos associados. No poss usar uma unica deniao de tipo para vrias a e vel c a variveis. A lista de argumentos pode ser vazia, ou seja, a funo no recebe a ca a nenhum argumento. O nome da funao pode ser qualquer identicador vlido. c a O tipo que aparece antes do nome da funao especica o tipo do resultado que c ser devolvido ao nal da execuao da funao. Caso nenhum tipo seja especia c c cado o compilador assume que um tipo inteiro retornado. O tipo void pode e ser usado para declarar funoes que no retornam valor algum. c a H basicamente duas maneiras de terminar a execuao de uma funao. Nora c c malmente usa-se o comando return para retornar o resultado da funao. Porc tanto, quando o comando
return express~o; a

for executado, o valor da express~o devolvido para a funao que chamou. a e c Quando no h valor para retornar o comando return no precisa ser usado e a a a a funao termina quando a chave que indica o trmino do corpo da funao c e c e atingido. Os parmetros so valores que a funao recebe para realizar as tarefas para a a c as quais foi programada. Por exemplo, uma funao que calcule a raiz quadrada c de um nmero do tipo oat , deve declarar como parmetro uma varivel deste u a a tipo para receber o valor. E importante notar que diferentemente de declaraoes de variveis onde c a podemos associar vrios nomes de variveis a uma declaraao como em a a c
int a, dia, mes, i;

na lista de parmetros necessrio associar um tipo a cada varivel como a e a a no exemplo a seguir:
oat media (oat n1, oat n2, oat n3);

Neste exemplo, uma funao chamada media que do tipo oat , isto retorna c e e um resultado oat , recebe trs argumentos (n1, n2, n3) tambm do tipo oat . e e

123

Um ponto importante como usar a funao. Suponha que uma determinada e c funao, A, deseje usar uma outra funao, B. A funao A deve colocar no local c c c desejado o nome da funao (B) e a lista de valores que deseja passar. Por c exemplo, um programador que deseje usar a funao media em seu programa c para calcular a mdia de trs valores, nota1, nota2 e nota3, deve escrever no e e local onde quer que a mdia seja calculada o seguinte comando: e
resultado = media(nota1, nota2, nota3);

onde resultado a varivel que vai receber a mdia calculada. e a e importante notar que o nome da funao pode aparecer em qualquer lugar E c onde o nome de uma varivel apareceria. Alm disso os tipos e o n mero de a e u parmetros que aparecem na declaraao da funao e na sua chamada devem a c c estar na mesma ordem e ser tipos equivalentes. Se os tipos so incompat a veis, o compilador no gera um erro, mas podem ser gerados avisos na compilaao e a c resultados estranhos. Outro ponto importante a ser notado e que ser detalhado mais adiante a e que os nomes das variveis nos programas que usam a funao media podem ser a c diferentes dos nomes usados na deniao da funao. c c

8.3

Prottipos de Funes o co

O padro ANSI estendeu a declaraao da funao para permitir que o compilador a c c faa uma vericaao mais r c c gida da compatibilidade entre os tipos que a funao c espera receber e `queles que so fornecidos. Prottipos de funoes ajudam a a a o c detectar erros antes que eles ocorram, impedindo que funoes sejam chamadas c com argumentos inconsistentes. A forma geral de deniao de um prottipo c o e a seguinte:
tipo nome (tipo nome1, tipo nome2, ..., tipo nomeN);

O exemplo 8.1 mostra a declaraao de uma funao e seu prottipo. c c o Listing 8.1: Exemplo de prottipos. o
#include < stdio .h > /* Prototipo da funcao */ i n t soma ( i n t a , i n t b ); /* Funcao Principal */ i n t main () { i n t a =5 , b =9; printf ( " % d \ n " , soma (a , b )); return 0; } /* Definicao da funcao */ i n t soma ( i n t a , i n t b ) { return a + b ; }

124

Tambm poss declarar um prottipo sem dar os nomes das variveis e e vel o a somente os tipos das funoes. No exemplo 8.1 o prottipo da funao soma pode c o c ser declarada da seguinte maneira
int soma (int, int)

8.4

Escopo de Variveis a

Variveis podem ser denidas para serem usadas somente dentro de uma funao a c particular, ou pode ocorrer que variveis precisem ser acess a veis ` diversas a funoes diferentes. Por esta razo, temos que apresentar os locais onde as c a variveis de um programa podem ser denidas e a partir destes locais podera mos inferir onde elas estaro dispon a veis. As variveis podem ser declaradas a basicamente em trs lugares: e dentro de funoes, c fora de todas as funoes, c na lista de parmetros das funoes. a c As variveis denidas dentro das funoes so chamadas de variveis locais, as a c a a que aparecem fora de todas as funoes chamamos de variveis globais e aquelas c a que aparecem na lista de parmetros so os parmetros formais. E importante a a a notar que em C todas as funoes esto no mesmo n c a vel, por esta razo no a a e poss denir uma funao dentro de outra funao. vel c c

8.4.1

Variveis Locais a

As variveis locais so aquelas declaradas dentro de uma funao ou um bloco a a c de comandos. Elas passam a existir quando do in da execuao do bloco de cio c comandos ou funao onde foram denidas e so destru c a das ao nal da execuao c do bloco. Uma varivel local s pode ser referenciada, ou seja usada, dentro a o da funao (ou bloco) onde foi declarada. Outro ponto muito importante que c e como as variveis locais deixam de existir ao nal da execuao da funao (ou a c c bloco), elas so invis a veis para outras funoes do mesmo programa. O cdigo c o que dene uma funao e os seus dados so particulares da funao (do bloco). c a c No programa 8.2 podemos ver o uso de variveis locais. A varivel i a a e denida em cada uma das funoes do programa (pares, impares). Os valores c da varivel no podem ser acessados a partir de nenhuma outra funao e as a a c modicaoes feitas dentro da funao somente valem enquanto a funao est c c c a sendo executada. Alguns autores usam o termo variveis automticas para se referir as variveis a a a locais. Em C existe a palavra chave auto que pode ser usada para declarar que variveis pertencem ` classe de armazenamento padro. No entanto, como todas a a a as variveis locais so por deniao automticas raramente se usa esta palavra a a c a chave. Observe que um bloco de comandos se inicia em um { e termina em um }. O bloco de comandos, dentro do qual mais comumente se dene 125

Listing 8.2: Exemplos de variveis locais. a


#i ncl ude < stdio .h > void pares ( void) { int i; f o r ( i = 2; i <= 10; i += 2) { printf ( " % d : " , i ); } } void impares ( void) { int i; f o r ( i = 3; i <= 11; i += 2) { printf ( " % d : " , i ); } } i n t main ( i n t argc , char * argv []) { pares (); printf ( " \ n " ); impares (); return 0; }

uma varivel a funao. Todas as variveis que sero usadas dentro de um a e c a a bloco de comandos precisam ser declaradas antes do primeiro comando do bloco. Declaraoes de variveis, incluindo sua inicializaao, podem vir logo aps o abre c a c o chaves que inicia um bloco de comandos, no somente o que comea uma funao. a c c O programa 8.3 ilustra este tipo de declaraao. c Listing 8.3: Deniao de varivel dentro de um bloco. c a
#include < stdio .h > i n t main () { int i; f o r ( i =0; i <10; i ++) { i n t t = 2; printf ( " % d \ n " , i * t ); } return 0; }

Existem algumas vantagens em se declarar variveis dentro de blocos. Como a as variveis somente existem durante a execuao do bloco, o programa pode a c ocupar menos espao de memria. Por exemplo, se a execuao do bloco for c o c condicional a varivel pode nem ser alocada. Outra vantagem que como a a e varivel somente existe dentro do bloco, pode-se controlar melhor o uso da a varivel, evitando erros de uso indevido da varivel. a a

126

8.4.2

Variveis Globais a

As variveis globais so denidas fora de qualquer funao e so portanto dispoa a c a n veis para qualquer funao. Este tipo de varivel pode servir como uma canal c a de comunicaao entre funoes, uma maneira de transferir valores entre elas. Por c c exemplo, se duas funoes tem de partilhar dados, mais uma no chama a outra, c a uma varivel global tem de ser usada. a O programa 8.4 ilustra este tipo de declaraao. O resultado da execuao c c deste programa o seguinte: e Funcao soma1: i = 1 Funcao sub1: i = 9 Funcao main: i = 1 Observe que a varivel global i recebe o valor 0 no in da funao main. A a cio c funao soma1 ao executar um comando que aumenta o valor de i em uma unidade c est aumentando a varivel global. Em seguida vemos que a funao sub1 dene a a c uma varivel local tambm chamada i e, portanto, a alteraao feita por esta a e c funao somente modica esta varivel. Finalmente, a funao main imprime o c a c valor nal da varivel global. a Listing 8.4: Deniao de varivel global. c a
#i ncl ude < stdio .h > int i; void soma1 ( void) { i += 1; printf ( " Funcao soma1 : i = % d \ n " , i ); } void sub1 ( void ) { i n t i = 10; i -= 1; printf ( " Funcao sub1 : i = % d \ n " , i ); } i n t main ( i n t argc , char * argv []) { i = 0; soma1 (); sub1 (); printf ( " Funcao main : i = % d \ n " , i ); return 0; }

8.5

Parmetros Formais a

As variveis que aparecem na lista de parmetros da funao so chamadas de a a c a parmetros formais da funao. Eles so criados no in da execuao da funao a c a cio c c e destru dos no nal. Parmetros so valores que as funoes recebem da funao a a c c que a chamou. Portanto, os parmetros permitem que uma funao passe valores a c para outra. Normalmente os parmetros so inicializados durante a chamada da a a 127

funao, pois para isto foram criados. No entanto, as variveis que atuam como c a parmetros so iguais a todas as outras e podem ser modicadas, operadas, etc, a a sem nenhuma restriao. Parmetros podem ser passados para funoes de duas c a c maneiras: passagem por valor ou passagem por referncia. e

8.5.1

Passagem de Parmetros por Valor a

Na passagem por valor uma cpia do valor do argumento passado para a o e funao. Neste caso a funao que recebe este valor, ao fazer modicaoes no c c c parmetro, no estar alterando o valor original que somente existe na funao a a a c que chamou. O exemplo 8.5 mostra o uso de passagem de parmetros por valor. Observe a que as funao Eleva recebe dois parmetros (a,b) e opera usando os valores c a recebidos. O resultado da funao retornado por meio da varivel local res. c e a Listing 8.5: Exemplo de passagem por valor.
#include < stdio .h > #include < stdlib .h > f l o a t Eleva ( f l o a t a , i n t b ) { f l o a t res = 1.0; f o r ( ; b >0; b - -) res *= a ; return res ; } i n t main () { f l o a t numero ; i n t potencia ; char linha [80]; puts ( " Entre com um numero " ); gets ( linha ); numero = atof ( linha ); puts ( " Entre com a potencia " ); gets ( linha ); potencia = atoi ( linha ); printf ( " \ n % f Elevado a % d e igual a % f \ n " , numero , potencia , Eleva ( numero , potencia )); return 0; }

Para ilustrar o fato de que somente o valor passado vamos usar o exemplo e 8.6. Neste programa as variveis a e b recebem os valores 10 e 20 respectivaa mente. Na funao trocar estes valores so recebidos e so trocados localmente. c a a Aps o retorno da funao, o programa imprime os valores originais das variveis, o c a j que estes no sofreram nenhuma alteraao. O resultado da execuao deste a a c c programa o seguinte: e a = 10, b = 20

128

Listing 8.6: Uso indevido de variveis locais. a


#i ncl ude < stdio .h > void trocar ( i n t a , i n t b ) { i n t temp ; temp = a ; a = b ; b = temp ; } i n t main ( i n t argc , char * argv []) { i n t a = 10 , b = 20; trocar (a , b ); printf ( " a = %d , b = % d \ n " , a , b ); return 0; }

8.5.2

Passagem de Parmetros por Referncia a e

Na passagem por referncia o que passado para a funao o endereo do e e c e c parmetro e, portanto, a funao que recebe pode, atravs do endereo, modicar a c e c o valor do argumento diretamente na funao que chamou. Para a passagem de c parmetros por referncia necessrio o uso de ponteiros. Este assunto ser a e e a a discutido no prximo cap o tulo e portanto, por agora, usaremos somente funoes c com passagem por valor.

8.5.3

Passagem de Vetores e Matrizes

Matrizes so um caso especial e exceao a regra que parmetros so passados a c a a sempre por valor. Como veremos mais adiante, o nome de um vetor corresponde ao endereo do primeiro elemento do array, Quando um vetor passado como c e parmetro, apenas o endereo do primeiro elemento passado. a c e Existem basicamente trs maneiras de declarar um vetor como um parmetro e a de uma funao. Na primeira ele declarado como tem sido apresentado em todos c e os exemplos at agora. O exemplo 8.7 mostra um programa que usa uma funao e c para descobrir quantas vezes um caractere ocorre em um vetor. Observe que na deniao da funao a dimenso do vetor foi declarada explicitamente. c c a Uma outra maneira, leva em conta que apenas o endereo do vetor passado. c e Neste modo o parmetro declarado como um vetor sem dimenso. Isto a e a e perfeitamente poss porque a funao somente precisa receber o endereo onde vel c c se encontra o vetor. Alm disso C no confere limites de vetores e portanto a e a funao precisa do endereo inicial do vetor e uma maneira de descobrir o nal c c do vetor. Esta maneira pode ser, por exemplo, uma constante, ou o caractere \0 em um vetor de caracteres. O exemplo 8.8 mostra este modo de passar vetores com um programa que inverte o contedo de um vetor. u A terceira maneira de passagem de parmetros implica no uso de ponteiros, a o que somente iremos ver no prximo cap o tulo.

129

Listing 8.7: Passagem de vetor com dimenses. o


#include < stdio .h > #include < conio .h > #de fi ne DIM 80 char conta ( char v [] , char c ); i n t main () { char c , linha [ DIM ]; i n t maiusculas [26] , minusculas [26]; puts ( " Entre com uma linha " ); gets ( linha ); f o r ( c = a ; c <= z ; c ++) minusculas [c - a ] = conta ( linha , c ); f o r ( c = A ; c <= Z ; c ++) maiusculas [c - A ] = conta ( linha , c ); f o r ( c = a ; c <= z ; c ++) i f ( minusculas [c - a ]) printf ( " % c apareceu % d vezes \ n " , c , minusculas [c - a ]); f o r ( c = A ; c <= Z ; c ++) i f ( maiusculas [c - A ]) printf ( " % c apareceu % d vezes \ n " , c , maiusculas [c - A ]); return 0; } char conta ( char v [ DIM ] , char c ) { i n t i =0 , vezes =0; while ( v [ i ] != \0 ) i f ( v [ i ++] == c ) vezes ++; return vezes ; }

130

Listing 8.8: Passagem de vetores sem dimenses. o


#include < stdio .h > #include < conio .h > #de fi ne DIM 6 void Le_vetor ( i n t v [] , i n t tam ); void Imprime_vetor ( i n t v [] , i n t tam ); void Inverte_vetor ( i n t v [] , i n t tam ); i n t main () { i n t v [ DIM ]; Le_vetor (v , DIM ); Imprime_vetor (v , DIM ); Inverte_vetor (v , DIM ); Imprime_vetor (v , DIM ); return 0; } void Le_vetor ( i n t v [] , i n t tam ) { int i; f o r ( i = 0; i < tam ; i ++) { printf ( " % d = ? " , i ); scanf ( " % d " , & v [ i ]); } } void Imprime_vetor ( i n t v [] , i n t tam ) { int i; f o r ( i = 0; i < tam ; i ++) printf ( " % d = % d \ n " , i , v [ i ]); } void Inverte_vetor ( i n t v [] , i n t tam ) { i n t i , temp ; f o r ( i = 0; i < tam /2; i ++){ temp = v [ i ]; v [ i ] = v [ tam -i -1]; v [ tam -i -1] = temp ; } }

131

8.6

O Comando return

O comando return usado para retornar o valor calculado para a funao que e c chamou. Qualquer expresso pode aparecer no comando, que tem a a seguinte a forma geral:
return express~o a

A funao que chamou livre para ignorar o valor retornado. Alm disso a c e e funao pode no conter o comando e portanto nenhum valor retornado e neste c a e caso a funao termina quando o ultimo comando da funao executado. Quando c c e o comando return no existe o valor de retorno considerado indenido. As a e funoes que no retornam valores devem ser declaradas como do tipo void. E c a importante observar que funoes que so declaradas com um tipo vlido podem c a a ser inclu das em qualquer expresso vlida em C. a a

8.7

Recurso a

Funoes em C podem ser usadas recursivamente, isto uma funao pode chamar c e c a si mesmo. E como se procurssemos no dicionrio a deniao da palavra a a c recurso e encontrssemos o seguinte texto: a a recurso: s.f. Veja a deniao em recurso a c a Um exemplo simples de funao que pode ser escrita com chamadas recursivas c o fatorial de um nmero inteiro. O fatorial de um nmero, sem recurso, e u u a e denido como n! = n (n 1) (n 2) 2 1 A partir desta deniao podemos escrever a funao fatorial como c c
unsigned long i n t fat ( unsigned long i n t num ) { unsigned long i n t fato =1 , i ; f o r ( i = num ; i >1; i - -) fato = fato * i ; return fato ; }

Alternativamente, o fatorial pode ser denido como o produto deste n mero u pelo fatorial de seu predecessor, ou seja n! = n (n 1)! Deste modo podemos escrever uma funao recursiva em que cada chamada c da funao que calcula o fatorial chama a prpria funao fatorial. O exemplo, c o c mostrado a seguir, mostra como a funao pode ser escrita recursivamente. c
unsigned long i n t fat ( unsigned long i n t num ) { i f ( num == 0) return 1; else

132

return num * fat ( num -1); }

Quando a funao fatorial recursiva chamada, primeiro vericado se o c e e nmero recebido como parmetro vale 0 e neste caso a funao retorna o valor 1. u a c No caso contrrio ela devolve o valor da expresso num * fat(num-1), ou seja o a a produto do nmero pelo valor do fatorial do nmero predecessor. Ou seja para u u retornar um valor a funao precisa chamar ela mesma passando como parmetro c a o valor do nmero menos 1. Este processo continua se repetindo at que o valor u e passado igual a 0, o que indica o nal da recurso. Neste ponto o processo se e a reverte e as chamadas comeam a ser respondidas. c Um ponto importante que toda funao recursiva deve prever cuidadosae c mente como o processo de recurso deve ser interrompido. No caso da funao fat a c o processo interrompido quando o valor do nmero passado como parmetro e u a vale 0. Se este teste no tivesse sido inclu na funao as chamadas contina do c uariam indenidamente com valores negativos cada vez menores sendo passados como parmetro. a Quando uma funao chama a si mesmo recursivamente ela recebe um conc junto novo de variveis na pilha que usada para transferncia de valores entre a e e funoes. E importante notar que recurso no traz obrigatoriamente economia c a a de memria porque os valores sendo processados tem de ser mantidos em pilhas. o Nem ser mais rpido, e as vezes pode ser at mais lento porque temos o custo a a e de chamada as funoes. As principais vantagens da recurso so cdigos mais c a a o compactos e provavelmente mais fceis de serem lidos. a Um outro exemplo simples de funao que pode ser resolvida por recurso c a xn , assumindo que n 0. Esta funao pode escrita na sua forma recursiva e c como xn = x x(n1) que nos leva a escrever a funao da maneira mostrada no exemplo 8.9. Na c funao consideramos que x do tipo oat . c e Listing 8.9: Funao recursiva para calcular xn . c
f l o a t Elevar ( f l o a t x , i n t n ) { i f ( n <= 1) { return x ; } else { return x * Elevar (x , b -1); } }

8.8

Argumentos - argc e argv

A funao main como todas as funoes podem ter parmetros. Como a funao main c c a c sempre a primeira a ser executada, os parmetros que ela recebe so fornecidos e a a

133

pela linha de comando ou pelo programa que iniciou a sua execuao. No caso c da funao main so usados dois argumentos especiais int argc e char **argv. c a O primeiro argumento, argc, uma varivel inteira que indica quantos are a gumentos foram fornecidos para a funao. Observar que argc vale sempre pelo c menos 1, porque o nome do programa sempre o primeiro argumento fornecido e ao programa. A partir do segundo argumento em diante que aparecem os e outros argumentos. O outro parmetro um vetor de cadeias de caracteres, e portanto, caso a e sejam fornecidos nmeros, estes devem ser convertidos para o formato requerido. u Cada um dos argumentos do programa um elemento deste vetor. A primeira e linha da funao main pode ter a seguinte forma c
void main (int argc, char *argv[])

O programa exemplo 8.10 calcula o fatorial dos nmeros fornecidos como u argumentos. Listing 8.10: Uso de argc e argv.
#i ncl ude < stdio .h > #i ncl ude < stdlib .h > unsigned long i n t fat ( unsigned long i n t num ) { i f ( num == 0) return 1; else return num * fat ( num -1); } i n t main ( i n t argc , char * argv []) { unsigned long i n t numero , fatorial , i ; i f ( argc < 2) { printf ( " Para rodar : % s num1 num2 ... .\ n " , argv [0]); return 1; } f o r ( i =1; i < argc ; i ++) { numero = ( unsigned long i n t ) ( atoi ( argv [ i ])); fatorial = fat ( numero ); printf ( " O fatorial de % lu vale % lu .\ n " , numero , fatorial ); } return 0; }

Os nomes argc e argv so comumente usados mas o programador livre para a e escolher os nomes mais apropriados.

134

8.9

Exerc cios

8.1: Escrever um programa que declare, inicialize e imprima um vetor de 10 inteiros. O vetor deve conter os 10 primeiros mltiplos de 5. A inicializaao do u c vetor e a sua impresso devem ser feitas por funoes. a c 8.2: Escreva um programa para declarar um vetor de caracteres de tamanho 26 e imprimir o seu contedo. O vetor deve ser inicializado com as letras min sculas u u do alfabeto. A inicializaao do vetor e a sua impresso devem ser feitas por c a funoes. c 8.3: Escreva um programa que armazene em uma matriz trs nomes de pessoas e e em seguida os imprima. Assuma que o tamanho mximo de cada nome 40 a e caracteres. Neste programa a leitura dos nomes dever ser feita por uma funao c e a impresso dos nomes por outra. a 8.4: Escreva um programa que imprima o cdigo ASCII de todos os caracteres, o das seguintes maneiras: 1. caractere a caractere, a escolha do usurio; a 2. a tabela inteira, a partir de um determinado valor decimal. Cada item deste exerc deve corresponder a uma funao. cio c 8.5: Escreva um programa que crie uma tabela de temperaturas Celsius Fahrenheit. O programa deve usar uma funao que converta de Celsius para c Fahrenheit. A tabela deve iniciar na temperatura 0 graus Celsius e terminar na temperatura 100 graus Celsius. 8.6: Escreva um programa, usando funoes, que gere um vetor a partir de uma c matriz. Cada elemento do vetor igual a soma dos elementos de uma das linhas e da matriz. Considere que a matriz tenha tamanho 10 por 10. 8.7: Escreva um programa usando recursividade para gerar a seqncia do ue Fibonacci. A seqncia de Fibonacci denida como: ue e f (0) = f (1) = f (n) = 0 1 f (n 1) + f (n 2)

O programa deve ler um numero e exibir o valor dele na seqncia de Fibonacci. ue Exemplos de entrada e sa do programa so mostrados abaixo. da a Entre com um numero inteiro: 0 Fibonacci (0) = 0 Entre com um numero inteiro: 1 Fibonacci (1) = 1 Entre com um numero inteiro: 2 Fibonacci (2) = 1 Entre com um numero inteiro: 3 Fibonacci (3) = 2 135

Entre com um numero inteiro: Fibonacci (6) = 8

8.8: O que o programa mostrado na listagem 8.11 imprime, caso sejam fornecidos os valores 48 e 256. Justique a sua resposta. Listing 8.11: Programa do exerc 8. cio
#include < stdio .h > #de fi ne MAX 1000 i n t abc ( i n t x , i n t y ) { printf ( " % d % d \ n " , x , y ); i f ( y == 0) { return x ; } else { return abc (y , x % y ); } } i n t main ( void ) { int a, b; scanf ( " % d % d " , &a , & b ); printf ( " % d \ n " , abc (a , b )); return 0; }

8.9: O programa mostrado na listagem 8.12 converte cadeias de caracteres contendo nmeros na base 16 para a base 10. Neste programa est faltando um u a trecho. A sua tarefa e completar o trecho que est faltando. a Listing 8.12: Programa do problema 9.
#include < stdio .h > #include < string .h > #include < stdlib .h > i n t fromHexatoD ec i ma l ( char c []); i n t toNumero ( char ); char toLower ( char ); i n t main ( void ) { char numeroC [80]; fgets ( numeroC , 80 , stdin ); while (! feof ( stdin )) { numeroC [ strlen ( numeroC ) -1] = \0 ; printf ( " % s = % d \ n " , numeroC , fromHexato De c im al ( numeroC )); fgets ( numeroC , 80 , stdin ); } return 0; } i n t fromHexatoD ec i ma l ( char numeroC []) { /* Aqui falta codigo */ }

136

char toLower ( char c ) { i f ( c >= A && c <= Z ) { c = c - A + a ; } return c ; } i n t toNumero ( char c ) { i n t resultado ; i f ( c >= 0 && c <= 9 ) { resultado = c - 0 ; } e l s e i f ( toLower ( c ) >= a && toLower ( c ) <= f ) { resultado = toLower ( c ) - a + 10; } return resultado ; }

137

Cap tulo 9

Ponteiros
9.1 Introduo ca

Ponteiros so usados em situaoes em que necessrio conhecer o endereo a c e a c onde est armazenada a varivel e no o seu contedo. Um ponteiro uma a a a u e varivel que contm um endereo de uma posiao de memria e no o conte do a e c c o a u da posiao. A memria de um computador pode ser vista como uma seqncia c o ue de bytes cada um com seu prprio e unico endereo. No h dois bytes com o c a a o mesmo endereo. O primeiro endereo sempre 0 e o ultimo geralmente c c e e uma potncia de 2. Por exemplo um computador com memria igual a 512 e o Mbytes tem 512x1024x1024 bytes. A Figura 9.1 mostra o mapa de um trecho de memria que contm duas variveis inteiras (num, res) ocupando 4 bytes o e a cada uma e mais um ponteiro (pint), que tambm ocupa 4 bytes. Observar que e os endereos esto pulando de quatro em quatro bytes devido ao espao que c a c cada um destas variveis ocupa. a
0 4 8 12 16 10 120 num res *pint

Figura 9.1: Mapa de memria com duas variveis e ponteiro. o a Ponteiros so importantes, por exemplo, quando se deseja que uma funao a c retorne mais de um valor. Neste caso uma soluao a funao receber como c e c argumentos no os valores dos parmetros mas sim ponteiros que apontem para a a seus endereos. Assim esta funao pode modicar diretamente os conte dos c c u 138

destas variveis, que aps o m da funao estaro dispon a o c a veis para a funao que c chamou. Neste caso os argumentos podem funcionar como entrada e sa de da dados da funao. c Uma outra aplicaao importante de ponteiros apontar para reas de mec e a mria que devem ser gerenciadas durante a execuao do programa. Com pono c teiros, poss e vel reservar as posioes de memria necessrias para armazenac o a mento destas reas somente quando for necessrio e no quando as variveis a a a a so declaradas. Neste esquema o programador pode reservar o n mero exato a u de posioes que o programa requer. A Figura 9.2 ilustra como um ponteiro faz c referncia para uma rea de memria. Na gura a varivel ponteiro pi aponta e a o a para a rea de memria que contm um vetor de 10 inteiros. Com ponteiros, o a o e programador precisa, no in cio, denir a varivel ponteiro e seu tipo. Durante a a execuao do programa, aps descobrir o tamanho do vetor, reserva a rea c o a necessria para guardar os dados. Observe a diferena do que ocorre quando a c se usa vetores de tamanho xo. Neste caso a deniao do tamanho do vetor c e dada na declaraao do vetor e mantida at o nal da execuao do programa. c e e c
0 4 8 1000 pi ponteiro para vetor

1000

120 Vetor de 10 inteiros

1036

97

Figura 9.2: Ponteiro apontando para rea de memria contendo vetor. a o

9.2
9.2.1

Operaes com Ponteiros co


Declarao de Ponteiros ca

Antes de serem usados os ponteiros, como as variveis, precisam ser declarados. a A forma geral da declaraao de um ponteiro a seguinte: c e tipo *nome; Onde tipo qualquer tipo vlido em C e nome o nome da varivel ponteiro. e a e a Por exemplo:
i n t * res ; /* ponteiro para inteiro */ f l o a t * div ; /* ponteiro para ponto flutuante */

139

Como as variveis, os ponteiros devem ser inicializados antes de serem usaa dos. Esta inicializaao pode ser feita na declaraao ou atravs de uma atribuiao. c c e c Aps a declaraao o que temos um espao na memria reservado para aro c e c o mazenamento de endereos. O valor inicial da memria indenido como aconc o e tece com variveis. A Figura 9.3 ilustra esta situaao. Um ponteiro pode ser a c inicializado com um endereo ou com o valor NULL. O valor NULL, que equivc e alente a 0, uma constante denida no arquivo <stdio.h> e signica que o e ponteiro no aponta para lugar nenhum. A atribuiao de inteiros a ponteiros a c no faz sentido a no ser em aplicaoes muito especiais e o unico valor inteiro a a c que se pode atribuir a um ponteiro o 0. Este tipo de atribuiao no faz sentido e c a porque na maioria das aplicaoes o sistema operacional que aloca e gerencia c e a posiao dos programas na memria e, portanto, o usurio no tem controle c o a a sobre estes endereos. c
996

1000

endereo indefinido

*res

1004

endereo indefinido

*div

Figura 9.3: Declaraao de ponteiros. c

9.2.2

Os Operadores Especiais para Ponteiros

Existem dois operadores especiais para ponteiros: * e &. Os dois operadores so unrios, isto requerem somente um operando. O operador & devolve o a a e endereo de memria do seu operando. Considere a Figura 9.1. Aps a execuao c o o c da instruao c
pint = &num; /*o endereco de num e carregado em pint */

a varivel ponteiro pint termina com o valor 4, como est mostrado na Figura a a 9.4. Lembre-se que o valor 4 no tem sentido prtico na maioria das aplicaoes. a a c O fato importante que o ponteiro pint passou a apontar para a varivel num. e a O operador * o complemento de &. O operador * devolve o valor da varivel e a localizada no endereo apontado pelo ponteiro. Por exemplo, considere que o c comando res = *pint; foi executado logo aps pint = &num;. Isto signica que o a varivel res recebe o valor apontado por pint, ou seja a varivel res recebe o a a valor 10, como est mostrado na Figura 9.5. a

140

0 4 8 12 16 10 120 4 num res *pint

Figura 9.4: Atribuiao de endereo de uma varivel a um ponteiro. c c a

0 4 8 12 16 10 120 10 4 num res = *pint *pint

Figura 9.5: Uso de um ponteiro para copiar valor de uma varivel. a

Estes operadores no devem ser confundidos com os j estudados em cap a a tulos anteriores. O operador * para ponteiros no tem nada a ver com o operador a multiplicaao *. O operador ponteiro * unrio e, como o operador &, tem c e a precedncia maior que do que todos os operadores aritmticos. e e

9.2.3

Atribuio de Ponteiros ca

Da mesma maneira que ocorre com uma varivel comum, o conte do de um a u ponteiro pode ser passado para outro ponteiro do mesmo tipo. Por exemplo, uma varivel ponteiro declarada como apontador de dados inteiros deve sempre a apontar para dados deste tipo. Observar que em C poss atribuir qualquer e vel endereo a uma varivel ponteiro. Deste modo poss atribuir o endereo de c a e vel c uma varivel do tipo oat a um ponteiro do tipo int. No entanto, o programa a no ir funcionar da maneira correta. O programa 9.1 mostra exemplos de a a atribuioes de ponteiros. Neste exemplo o endereo do terceiro elemento do c c vetor v carregado em p1 e o endereo da varivel i carregado em p2. A e c a e Figura 9.6 a situaao da memria aps estas operaoes. Alm disso no nal o c o o c e endereo apontado por p1 carregado em p2. Os comandos printf imprimem os c e valores apontados pelos ponteiros respectivos, mostrando os seguintes valores:

141

30 100 30 Listing 9.1: Exemplo de atribuiao de ponteiros. c


#i ncl ude < stdio .h > i n t main ( void ) { i n t vetor [] = { 10 , 20 , 30 , 40 , 50 }; i n t * p1 , * p2 ; i n t i = 100; p1 = & vetor [2]; printf ( " % d \ n " , * p1 ); p2 = & i ; printf ( " % d \ n " , * p2 ); p2 = p1 ; printf ( " % d \ n " , * p2 ); return 0; }

0 4 8 12 16 20 24 28 32 10 20 30 40 50 12 32 100 v[0] v[1] v[2] v[3] v[4] *p1 *p2 p2 = &i; i p1 = &v[2];

Figura 9.6: Exemplos de atribuioes de ponteiros. c

9.2.4

Incrementando e Decrementando Ponteiros

O exemplo 9.2 mostra que operaoes de incremento e decremento podem ser c aplicadas em operandos. O primeiro printf imprime 30, que o elemento de e ndice igual a 2 no vetor vetor. Aps o incremento do ponteiro o segundo printf o imprime 40 e o mesmo acontece com o terceiro printf que imprime 50. Pode parecer estranho que um ponteiro para um nmero inteiro, que aru e mazenado em quatro bytes, seja incrementado por um e passe para apontar para 142

Listing 9.2: Exemplos de operaoes com ponteiros. c


i n t main ( void ) { i n t vetor [] = { 10 , 20 , 30 , 40 , 50 }; i n t * p1 ; p1 = & vetor [2]; printf ( " % d \ n " , * p1 ); p1 ++; printf ( " % d \ n " , * p1 ); p1 = p1 + 1; printf ( " % d \ n " , * p1 ); return 0; }

o prximo nmero inteiro. A primeira vista, para que passasse a apontar para o u o prximo endereo, seria necessrio aumentar o endereo em quatro. Ou seja, o c a c sempre que um ponteiro incrementado (decrementado) ele passa a apontar e para a posiao do elemento seguinte (anterior). O compilador interpreta o coc mando p1++ como: passe a apontar para o prximo nmero inteiro e, portanto, o u aumenta o endereo do nmero de bytes correto. Este ajuste feito de acordo c u e com o tipo do operando que o ponteiro est apontando. Do mesmo modo, somar a trs a um ponteiro faz com que ele passe apontar para o terceiro elemento aps o e o atual. Portanto, um incremento em um ponteiro que aponta para um valor que armazenado em n bytes faz que n seja somado ao endereo. E ento poss e c a vel somar-se e subtrair-se inteiros de ponteiros. A operaao abaixo faz com que o c ponteiro p passe a apontar para o terceiro elemento aps o atual. o
p = p + 3;

Tambm poss usar-se o seguinte comando e e vel


*(p+1)=10;

Este comando armazena o valor 10 na posiao seguinte `quela apontada por c a


p. A operaao realizada nos seguintes passos: c e

1. A expresso p+1 calculada e o seu resultado aponta para o prximo a e o endereo de dado inteiro; c 2. A expresso do lado direito do sinal de atribuiao, calculada e fornece a c e como resultado o valor 10; 3. Este resultado atribu ao endereo calculado no primeiro passo. e do c A diferena entre ponteiros fornece quantos elementos do tipo do ponteiro c existem entre os dois ponteiros. No exemplo 9.3 impresso o valor 2. e No poss multiplicar ou dividir ponteiros, e no se pode adicionar ou a e vel a subtrair o tipo oat ou o tipo double a ponteiros.

143

Listing 9.3: Exemplo de subtraao de ponteiros. c


#i ncl ude < stdio .h > i n t main ( void ) { f l o a t vetor [] = { 1.0 , 2.0 , 3.0 , 4.0 , 5.0 }; f l o a t * p1 , * p2 ; p1 = & vetor [2]; /* endereco do terceiro elemento */ p2 = vetor ; /* endereco do primeiro elemento */ printf ( " Diferenca entre ponteiros % d \ n " , p1 - p2 ); return 0; }

9.2.5

Comparao de Ponteiros ca

E poss comparar ponteiros em uma expresso relacional. No entanto, s vel a oe poss comparar ponteiros de mesmo tipo. O Programa 9.4 ilustra um exemplo vel deste tipo de operaao. c Listing 9.4: Exemplo de comparaao de ponteiros. c
#include < stdio .h > i n t main ( void ) { char *c , *v , a , b ; scanf ( " % c % c " , &a , & b ); c = &a; v = &b; i f ( c == v ) printf ( " As vari veis estao na mesma posicao . " ); a else printf ( " As variaveis nao estao na mesma posicao . " ); return 0; }

9.3

Ponteiros e Vetores

Ponteiros e Vetores esto fortemente relacionados na linguagem C. O nome a de um vetor um ponteiro que aponta para a primeira posiao do vetor. A e c declaraao int vetor[100] cria um vetor de inteiros de 100 posioes e permite c c que algumas operaoes com ponteiros possam ser realizadas com a varivel c a vetor. No entanto, existe uma diferena fundamental entre declarar um conjunto c de dados como um vetor ou atravs de um ponteiro. Na declarao de vetor, e ca o compilador automaticamente reserva um bloco de memria para que o vetor o seja armazenado. Quando apenas um ponteiro declarado a unica coisa que e

144

o compilador faz alocar um ponteiro para apontar para a memria, sem que e o espao seja reservado. O nome de um vetor chamado de ponteiro constante c e e, portanto, no pode ter o seu valor alterado. O nome de um ponteiro cona stante no pode aparecer em expresses no lado esquerdo do sinal de igual, ou a o seja, no pode receber valores diferentes do valor inicial atribu na declaraao a do c da varivel. Assim, os comandos que alteram o ponteiro list, mostrados no a exemplo 9.5, no so vlidos: a a a Listing 9.5: Exemplo de alteraoes invlidas sobre ponteiros. c a
i n t list [5] , i ; /* O ponteiro list nao pode ser modificado recebendo o endereco de i */ list = & i /* O ponteiro list nao pode ser incrementado */ list ++;

O contedo de vetores pode ser acessado usando-se o operador * para obter u o contedo do vetor. O Programa 9.6 mostra a notaao que usa u c ndices para buscar o elemento de um vetor e o uso do operador * de ponteiros. Neste programa o contedo do vetor impresso usando-se estas duas notaoes. u e c Listing 9.6: Exemplo de notaoes de vetores. c
#include < stdio .h > i n t main ( void ) { f l o a t v [] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0}; int i; f o r ( i = 0; i < 7; i ++) printf ( " %.1 f " , v [ i ]); printf ( " \ n " ); f o r ( i = 0; i < 7; i ++) printf ( " %.1 f " , *( v + i )); return 0; }

Para percorrer um vetor alm da maneira mostrada no programa 9.6 e e poss vel usar um ponteiro varivel como ilustrado no Programa 9.7. Observe a como o ponteiro p recebe seu valor inicial e a maneira como ele incrementado. e

9.4

Ponteiros e Cadeias de Caracteres

Uma cadeia de caracteres constante escrita como no exemplo: e


"Esta e uma cadeia de caracteres."

At agora um dos usos mais comuns de cadeias de caracteres constantes tem e sido na funao printf, como no exemplo abaixo c
printf("Acabou o programa.\n");

145

Listing 9.7: Exemplo de ponteiro varivel. a


#i ncl ude < stdio .h > i n t main ( void ) { f l o a t v [] = {1.0 , 2.0 , 3.0 , 4.0 , 5.0 , 6.0 , 7.0}; int i; fl oat *p; f o r ( i = 0; i < 7; i ++) printf ( " %.1 f " , v [ i ]); printf ( " \ n " ); f o r ( i = 0; i < 7; i ++) printf ( " %.1 f " , *( v + i )); printf ( " \ n " ); f o r ( i = 0 , p = v ; i < 7; i ++ , p ++) printf ( " %.1 f " , * p ); return 0; }

Quando uma cadeia de caracteres como esta enviada para a funao, o que e c passado o ponteiro para a cadeia. E poss ento carregar o endereo da e e vel a c cadeia em um ponteiro do tipo char, como no exemplo 9.8. Neste programa e contado o nmero de caracteres de uma cadeia. Observe o ponteiro *(s+tam++) u apontando caractere a caractere. Listing 9.8: Exemplo de ponteiro para cadeia de caracteres.
#i ncl ude < stdio .h > i n t main ( void ) { char *s , * lista = " 1234567890 " ; i n t tam =0; s = lista ; while (*( s + tam ++) != \0 ); tam - -; printf ( " O tamanho do string \"% s \" e % d caracteres .\ n " , lista , tam ); return 0; }

Um outro exemplo (Programa 9.9) mostra uma funao que copia um cadeia c de caracteres para outra.

9.5

Alocao Dinmica de Memria ca a o

O uso de ponteiros e vetores exige que aps a deniao da varivel ponteiro uma o c a rea de memria deve ser reservada para armazenar os dados do vetor. Para a o obter esta rea o programa deve usar funoes existentes na biblioteca stdlib. a c Estas funoes pedem ao sistema operacional para separar pedaos da memria c c o e devolvem ao programa que pediu o endereo inicial deste local. As funoes c c bsicas de alocaao de memria que iremos discutir so: a c o a
void *malloc(size_t size); Reserva espao na memria para algum item c o

146

Listing 9.9: Exemplo de cpia de cadeias de caracteres. o


#include < stdio .h > i n t strcop ( char *d , char * o ); i n t main ( void ) { char destino [20]; char * origem = " cadeia de caractere de origem " ; strcop ( destino , origem ); printf ( " % s \ n " , origem ); printf ( " % s \ n " , destino ); return 0; } i n t strcop ( char *d , char * o ) { while ((* d ++ = * o ++) != \0 ); return 0; }

de um programa. O tamanho em bytes reservado denido pela varivel size. e a O valor armazenado no espao indenido. A funao retorna um ponteiro de c e c tipo void para o espao reservado ou NULL no caso de algum erro ocorrer. c
void *calloc(size_t num, size_t size); Reserva espao na memria para c o um vetor de num itens do programa. Cada item tem tamanho size e todos os bits do espao so inicializados com 0. A funao retorna um ponteiro de tipo c a c void para o espao reservado ou NULL no caso de algum erro ocorrer. c void free(void *pont); O espao apontado por pont devolvido ao sistema c e para uso. Caso pont seja um ponteiro nulo nenhuma aao executada. No caso c e do ponteiro no ter sido resultado de uma reserva feita por meio de uma das a funoes calloc, realloc ou malloc o resultado indenido. c e void realloc(void *pont, size_t size); A funao altera o tamanho do obc jeto na memria apontado por pont para o tamanho especicado por size. O o contedo do objeto ser mantido at um tamanho igual ao menor dos dois u a e tamanhos, novo e antigo. Se o novo tamanho requerer movimento, o espao c reservado anteriormente liberado. Caso o novo tamanho for maior, o conte do e u da porao de memria reservada a mais car com um valor sem especicaao. c o a c Se o tamanho size for igual a 0 e pont no um ponteiro nulo o objeto previaa e mente reservado liberado. e

Estas funoes podem ser encontradas na biblioteca stdlib.h. O Programa c 9.10 ilustra o uso das funao calloc e free. c Um outro exemplo, agora empregando a funao malloc() est mostrado no c a Programa 9.11. Observe que neste programa tambm mostramos exemplos onde e um endereo de varivel foi passado para uma funao de modo que a funao main c a c c possa receber um valor (vezes).

9.6

Ponteiros e Matrizes

Um ponteiro aponta para uma rea de memria que endereada de maneira a o e c linear. Portanto, vetores podem ser facilmente manipulados com ponteiros. No 147

Listing 9.10: Exemplo de uso de calloc e free.


#i ncl ude < stdio .h > #i ncl ude < stdlib .h > i n t main ( void ) { fl oat *v; i n t i , tam ; printf ( " Qual o tamanho do vetor ? " ); scanf ( " % d " , & tam ); v = calloc ( tam , s i z e o f ( f l o a t )); i f (! v ) { printf ( " Nao consegui alocar memoria . " ); return 1; } f o r ( i =0; i < tam ; i ++) { printf ( " Elemento % d ? " , i ); scanf ( " % f " , v + i ); printf ( " Li valor % f \ n " , *( v + i )); } free ( v ); return 0; }

entanto, quando usamos estruturas de dados com maior dimensionalidade, como matrizes, por exemplo, que so arranjos bidimensionais de dados, necessrio a e a mapear o espao bidimensional (ou de maior ordem) para uma dimenso. No c a caso das matrizes necessrio mapear o endereo de cada elemento na matriz, e a c que denido por um par (linha, coluna) em um endereo linear. e c Considere uma matriz chamada matriz de tamanho LIN,COL que poderia ser declarada e ter um de seus elementos lidos da maneira mostrada no trecho de programa listado em 9.12. Caso o programa utilizasse ponteiros ao invs de e notaao de matrizes, poder c amos usar uma soluao que mapeasse a matriz que c um objeto de duas dimenses em um vetor que tem apenas uma. Neste caso e o o programa deve fazer a translaao de endereos toda vez que precisar ler ou c c escrever na matriz. O trecho de programa caria como mostrado no exemplo 9.13. A expresso matriz+(i*COL+j) calcula a posiao do elemento matriz[i][j] a c a partir do primeiro elemento da matriz que est no endereo inicial matriz. a c No entanto, esta soluao ainda no a melhor j que o usurio necessita c a e a a escrever diretamente uma expresso para mapear o endereo bidimensional da a c matriz matriz[i][j] em um endereo linear. O ideal usar uma notaao que c e c use somente ponteiros. Esta notaao ser discutida nas seoes seguintes. c a c

9.7

Vetores de Ponteiros

Uma possibilidade mais interessante utilizar vetores de ponteiros. Esta no e a e a notaao ideal, mas um passo na direao da notaao mais efetiva. Neste caso c e c c cada linha da matriz corresponde a um vetor que apontado por um ponteiro e armazenado no vetor de ponteiros. Como ponteiros tambm so variveis e a a e

148

Listing 9.11: Exemplo de uso de malloc.


#i ncl ude < stdio .h > #i ncl ude < stdlib .h > void LeVetor ( f l o a t *v , i n t tam ); float ProcuraMaior ( f l o a t *v , i n t tam , i n t * vezes ); i n t main ( void ) { f l o a t *v , maior ; i n t i , tam , vezes ; printf ( " Qual o tamanho do vetor ? " ); scanf ( " % d " , & tam ); v = ( f l o a t *) malloc ( tam * s i z e o f ( f l o a t )); i f (v) { LeVetor (v , tam ); maior = ProcuraMaior (v , tam , & vezes ); printf ( Maior = % f e aparece % d vezes .\ n . " , maior , vezes ); free ( v ); } else { printf ( " Nao consegui alocar memoria . " ); return 1; } return 0; } void LeVetor ( float *v , int tam ) { int i ; for ( i =0; i < tam ; i ++) { printf ( " Elemento % d ? " , i ); scanf ( " % f " , v + i ); printf ( " Li valor % f \ n " , *( v + i )); } } float ProcuraMaior ( float *v , int tam , int * vezes ) { int i ; float maior ; maior = v [0]; * vezes = 1; for ( i =1; i < tam ; i ++) { if ( v [ i ] & gt ; maior ) { maior = v [ i ]; * vezes = 1; } else if ( maior == v [ i ]) * vezes =* vezes +1; } return maior ; }

149

Listing 9.12: Exemplo de matriz normal sem uso de ponteiros.


#de fi ne LIN 3 #de fi ne COL 4 i n t matriz [ LIN ][ COL ]; f o r ( i =0; i < LIN ; i ++) { f o r ( j =0; j < COL ; j ++) { printf ( " Elemento % d % d = " , i , j ); scanf ( " % d " , & matriz [ i ][ j ]); } }

Listing 9.13: Exemplo de matriz mapeada em um vetor.


#de fi ne LIN 3 #de fi ne COL 4 i n t * matriz ; int i, j; matriz = malloc ( LIN * COL * s i z e o f ( i n t )); i f (! matriz ) { printf ( " Erro .\ n " ); return 1; } f o r ( i = 0; i < LIN ; i ++) { f o r ( j = 0; j < COL ; j ++) { printf ( " Elemento % d % d = " , i , j ); scanf ( " % d " , matriz +( i * COL + j )); } }

150

poss ento criar vetores de ponteiros e utiliz-los. O exemplo mostrado em vel a a 9.14 mostra um programa onde utilizado um vetor de ponteiros para vrias e a linhas de caracteres. Observe na funao main a declaraao char *linha[LINHAS]; c c que dene um vetor de tamanho LINHAS. Este vetor contem ponteiros e no a valores. At este momento do programa temos apenas posioes reservadas para e c armazenar ponteiros. A alocaao de espao e a inicializaao dos ponteiros feito c c c e no primeiro comando for. Como cada elemento do vetor linha um ponteiro e temos que o endereo retornado pela funao malloc armazenado em cada c c e um dos elementos deste vetor. A leitura das linhas de caracteres feita pela e funao gets(linha[i]) que passa o elemento do vetor onde os caracteres sero c a armazenados. Listing 9.14: Exemplo de uso de vetor de ponteiros.
#include < stdio .h > #include < stdlib .h > #de fi ne LINHAS 10 #de fi ne COLUNAS 60 i n t main ( void ) { char * linha [ LINHAS ]; int i; f o r ( i = 0; i < LINHAS ; i ++) { i f (!( linha [ i ] = malloc ( COLUNAS * s i z e o f ( char )))) { printf ( " Sem mem ria para vetor % d .\ n " , i ); o return i ; } } f o r ( i = 0; i < LINHAS ; i ++) { printf ( " Entre com a linha % d .\ n " , i ); gets ( linha [ i ]); } f o r ( i = 0; i < LINHAS ; i ++) { printf ( " Linha % d % s .\ n " , i , linha [ i ]); } return 0; }

9.8

Ponteiros para Ponteiros

No exemplo anterior podemos observar que o nmero de linhas da matriz u e xa, e portanto, h uma mistura de notaao de ponteiros com matrizes. Vaa c mos considerar um exemplo onde tanto o nmero de linhas como o de colunas u desconhecido. Neste exemplo iremos criar um vetor de ponteiros que ir are a mazenar o endereo inicial de cada linha. Portanto, para obter um elemento da c matriz primeiro devemos descobrir onde est a linha no vetor que armazena os a

151

endereos das linhas, em seguida procuramos na linha o elemento. A Figura 9.7 c ilustra como ser feito o armazenamento desta matriz. a
Vetor de ponteiros **matriz *(matriz+0) *(matriz+1) *(matriz+2) linha 2 linha 1 linha 0

*(matriz+n) linha n

Figura 9.7: Armazenamento de matrizes com vetores de ponteiros.

O Programa 9.15, listado a seguir, ir pedir ao usurio que digite o n mero a a u de linhas e colunas da matriz. Em seguida ler todos os elementos da matriz e a por ultimo ir trocar duas linhas da matriz de posiao. Observe que agora foi a c criado um ponteiro para ponteiro chamado de **matriz. O programa primeiro pergunta o nmero de linhas da matriz para poder alocar espao para armazenar u c os ponteiros para cada uma das linhas. Em seguida alocado espao para e c armazenar cada uma das linhas. O comando
matriz = (int **) malloc (lin * sizeof(int *));

foi usado pelo programa para reservar espao para armazenar lin linhas de c ponteiros para ponteiros. Observe que o comando sizeof(int *) calcula o espao c para armazenar um ponteiro na memria. Note tambm que o valor retornado o e pela funao malloc foi conformado ao tipo ponteiro para ponteiro pela operaao c c (int **). O interessante do programa que a troca de linhas da matriz envolve e simplesmente a troca de dois ponteiros e no a troca de todos os elementos das a linhas. Esta soluao muito mais rpida do que trocar elemento a elemento, c e a especialmente para matrizes grandes. A seguir mostramos o programa nas listagens 9.16 e 9.17 que o exemplo e anterior modicado para utilizar funoes. O propsito mostrar como cam as c o e chamadas e as denioes das funoes que utilizam ponteiros para ponteiros. c c

152

Listing 9.15: Exemplo de uso de ponteiros para ponteiros.


#include < stdio .h > #include < stdlib .h > i n t main ( void ) { i n t ** matriz ; /* ponteiro para os ponteiros */ i n t lin , col ; /* n mero de linhas e colunas */ u int i, j; i n t linha1 , linha2 ; /* linhas que serao trocadas */ char linha [80]; /* linha de caracteres com os dados */ i n t * temp ; puts ( " Qual o numero de linhas ? " ); gets ( linha ); lin = atoi ( linha ); matriz = ( i n t **) malloc ( lin * s i z e o f ( i n t *)); i f (! matriz ) { puts ( " Nao h espa o para alocar mem ria " ); a c o return 1; } puts ( " Qual o numero de colunas ? " ); gets ( linha ); col = atoi ( linha ); f o r ( i =0; i < lin ; i ++) { *( matriz + i ) = ( i n t *) malloc ( col * s i z e o f ( i n t )); i f (! *( matriz + i ) ) { printf ( " Sem espa o para alocar a linha % d " , i ); c return 1; } } puts ( " Entre com os dados " );} f o r ( i =0; i < lin ; i ++) { printf ( " Entre com a linha % d \ n " , i ); f o r ( j =0; j < col ; j ++) { printf ( " Elemento % d % d \ n " , i , j ); scanf ( " % d " , *( matriz + i ) + j ); } } puts ( " Qual a primeira linha a ser trocada ? " ); gets ( linha ); linha1 = atoi ( linha ); puts ( " Qual a segunda linha a ser trocada ? " ); gets ( linha ); linha2 = atoi ( linha ); temp = *( matriz + linha1 ); *( matriz + linha1 ) = *( matriz + linha2 ); *( matriz + linha2 ) = temp ; puts ( " Dados trocados . " ); f o r ( i =0; i < lin ; i ++) { f o r ( j =0; j < col ; j ++) { printf ( " %7 d " , *(*( matriz + i ) + j )); } printf ( " \ n " ); } return 0; }

153

Listing 9.16: Exemplo de uso de ponteiros para ponteiros usando funoes. c


#include < stdio .h > #include < stdlib .h >} i n t ** aloca_linhas ( i n t ); void aloca_colunas ( i n t ** , i nt , i n t ); void le_dados ( i n t ** , i nt , i n t ); void imprime_matri z ( i n t ** , i nt , i n t ); void troca_linhas ( i n t ** , i nt , i n t ); i n t main ( void ) { i n t ** matriz ; i n t lin , col ;& nbsp ;& nbsp ; i n t linha1 , linha2 ; char linha [80]; puts ( " Qual o numero de linhas ? " ); gets ( linha ); lin = atoi ( linha ); matriz = aloca_linhas ( lin ); puts ( " Qual o numero de colunas ? " ); gets ( linha ); col = atoi ( linha ); printf ( " Alocando espa o para linhas .\ n " ); c aloca_colunas ( matriz , lin , col ); le_dados ( matriz , lin , col ); imprime_matri z ( matriz , lin , col ); puts ( " Qual a primeira linha a ser trocada ? " ); gets ( linha ); linha1 = atoi ( linha ); puts ( " Qual a segunda linha a ser trocada ? " ); gets ( linha ); linha2 = atoi ( linha ); troca_linhas ( matriz , linha1 , linha2 ); imprime_matri z ( matriz , lin , col ); return 0; } i n t ** aloca_linhas ( i n t lin ) { i n t ** m ;} m = ( i n t **) malloc ( lin * s i z e o f ( i n t *)); i f (! m ) { puts ( " Sem espa o para alocar mem ria " ); c o return 1; } return m ; } void aloca_colunas ( i n t ** matriz , i n t lin , i n t col ) { int i; f o r ( i =0; i < lin ; i ++) { *( matriz + i ) = ( i n t *) malloc ( col * s i z e o f ( i n t )); i f (! *( matriz + i ) ) { printf ( " Sem espa o para linha % d " , i ); c return 1; } } }

154

Listing 9.17: Continuaao do exemplo 9.16. c


void le_dados ( i n t ** matriz , i n t lin , i n t col ) { int i, j; puts ( " Entre com os dados " ); f o r ( i =0; i < lin ; i ++) { printf ( " Entre com a linha % d \ n " , i ); f o r ( j =0; j < col ; j ++) { printf ( " Elemento % d % d \ n " , i , j ); scanf ( " % d " , *( matriz + i ) + j ); } } } void imprime_matri z ( i n t ** matriz , i n t lin , i n t col ) { int i, j; f o r ( i =0; i < lin ; i ++) { f o r ( j =0; j < col ; j ++) { printf ( " %7 d " , *(*( matriz + i ) + j )); } printf ( " \ n " ); } } void troca_linhas ( i n t ** matriz , i n t linha1 , i n t linha2 ) { i n t * temp ; temp = *( matriz + linha1 ); *( matriz + linha1 ) = *( matriz + linha2 ); *( matriz + linha2 ) = temp ; }

155

9.9

Exerc cios

9.1: Escreva um programa que gere um vetor de trs dimenses (X, Y e Z) em e o que cada posiao guarda a soma de suas coordenadas. As dimenses da matriz c o devero ser determinadas em tempo de execuao e o programa dever informar a c a os valores gerados. 9.2: Escreva um programa que leia uma frase de at 80 caracteres do teclado e e imprima a freqncia com que aparece cada uma das letras do alfabeto na ue frase. 9.3: Escreva um programa que leia uma frase de at 80 caracteres e a imprima e em ordem reversa convertendo todos os caracteres minsculos para mai sculos. u u 9.4: Escreva um programa que leia uma matriz e a imprima. O programa deve ler o numero de colunas e linhas do teclado. O programa deve ainda trocar duas linhas da matriz de posiao. Os nmeros das linhas a serem trocadas devem ser c u lidos do teclado. 9.5: Escreva um programa que simule uma pilha usando vetores. O programa deve implementar as seguintes operaoes na pilha: c Inserir Remover Listar 9.6: Escreva uma funao que receba um ponteiro para uma cadeia de caractere c e troque todo o caracter aps um branco pelo seu equivalente mai sculo. o u 9.7: Escreva um programa que leia seu nome completo e pergunte quantas letras tem o seu primeiro nome. Assuma que a letra a tem ndice 0, a letra b ndice 1 e assim por diante. O programa deve imprimir quantas letras iguais a letra cujo ndice o nmero de letras do seu primeiro nome existem no seu e u nome completo. 9.8: Escreva um programa que leia seu nome completo e pergunte quantas letras tem o seu primeiro nome. O seu programa deve usar a funao posicao que tem c o seguinte prottipo: o
int posicao(char *substr, char *str);

Esta funao deve vericar se a cadeia apontada por substr est presente na c a cadeia apontada por str e retornar a posiao em que a sub-cadeia aparece em c cadeia. 9.9: Escreva um programa que procure em uma matriz elementos que sejam ao mesmo tempo o maior da linha e o menor coluna. As dimenses da matriz o devem ser pedidas ao usurio. a 9.10: Escreva um programa que leia duas cadeias de caracteres e concatene a segunda cadeia ao nal da primeira. 156

Listing 9.18: Programa do exercicio 11.


#include < string .h > #include < stdio .h > #de fi ne MAX 80 void misterio ( char * p1 , char * p2 ); i n t main ( void ) { char palavra1 [ MAX ]; char palavra2 [ MAX ]; puts ( " Palavra 1? " ); fgets ( palavra1 , MAX , stdin ); palavra1 [ strlen ( palavra1 ) -1] = \0 ; puts ( " Palavra 2? " ); fgets ( palavra2 , MAX , stdin ); palavra2 [ strlen ( palavra2 ) -1] = \0 ; misterio ( palavra1 , palavra2 ); return 0; } void misterio ( char * p1 , char * p2 ) { while (* p1 != \0 && * p2 != \0 ) { putchar (* p1 ); putchar (* p2 ); p1 = p1 + 1; p2 = p2 + 1; } i f (* p1 != \0 ) { while (* p1 != \0 ) { putchar (* p1 ); p1 = p1 + 1; } } i f (* p2 != \0 ) { while (* p2 != \0 ) { putchar (* p2 ); p2 = p2 + 1; } } }

157

9.11: O que ser impresso pelo programa mostrado na listagem 9.18 caso a a primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ultimo sobrenome. 9.12: O que ser impresso pelo programa mostrado na listagem 9.19 caso a a primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ultimo sobrenome. Indique os nomes que usou e justique a sua resposta. Listing 9.19: Programa do exercicio 12.
#include < string .h > #include < stdio .h > #de fi ne MAX 80 void nMisterio ( char * p1 , char * p2 ) { while (* p1 != \0 ) { p1 = p1 + 1; } while (* p2 != \0 ) { * p1 = * p2 ; p1 = p1 + 1; p2 = p2 + 1; } * p1 = \0 ; } i n t main ( void ) { char palavra1 [ MAX ]; char palavra2 [ MAX ]; puts ( " Palavra 1? " ); fgets ( palavra1 , MAX , stdin ); palavra1 [ strlen ( palavra1 ) -1]= \0 ; puts ( " Palavra 2? " ); fgets ( palavra2 , MAX , stdin ); palavra2 [ strlen ( palavra2 ) -1]= \0 ; nMisterio ( palavra1 , palavra2 ); puts ( palavra1 ); return 0; }

9.13: O que ser impresso pelo programa 9.20. Justique sua resposta. a Listing 9.20: Listagem do exerc 13. cio
#i ncl ude < stdio .h > #i ncl ude < string .h > i n t main ( void ) { char * frase = " Otimo teste " ; char *p , misterio [80]; i n t i = 0; i n t j = 0;

158

p = frase + strlen ( frase ) - 1; while (* p != ) { misterio [ i ] = * p ; i ++; p - -; } misterio [ i ] = ; i ++; while ( frase [ j ] != ) { misterio [ i ] = frase [ j ]; j ++; i ++; } misterio [ i ] = \0 ; puts ( misterio ); return 0; }

9.14: O que ser impresso pelo programa mostrado na listagem 9.21. Justique a sua resposta. Listing 9.21: Programa do exerc 14. cio
#include < stdio .h > void f1 ( i n t v ) { v = v + 1; printf ( " f1 = % d \ n " , v ); } void f2 ( i n t * v ) { * v = * v + 1; printf ( " f2 = % d \ n " , * v ); } i n t f3 ( i n t v ) { v = v + 1; printf ( " f3 = % d \ n " , v ); return v ; } i n t main ( void ) { i n t v = 1; f1 ( v ); f2 (& v ); v = f3 ( v ); printf ( " main = % d \ n " , v ); return 0; }

159

Cap tulo 10

Estruturas
10.1 Introduo ca

Uma estrutura um conjunto de uma ou mais variveis, que podem ser de e a tipos diferentes, agrupadas sob um unico nome. O fato de variveis agrupadas a em uma estrutura poderem ser referenciadas por um unico nome facilita a ma nipulaao dos dados armazenados nestas estruturas. Um exemplo poderia ser c uma estrutura que armazenasse as diversas informaoes sobre os alunos de uma c Universidade. Nesta estrutura estariam armazenadas, sob o mesmo nome, informaoes do tipo: nome, registro, data de nascimento, data de ingresso, CPF, c etc. Uma estrutura pode incluir outras estruturas alm de variveis simples. e a As estruturas facilitam manipular estes agrupamentos complexos de dados. Por exemplo, considere o problema de ordenar as informaoes sobre os alunos da c Universidade exemplo. A ordenaao pode ser efetuada como se todos os dados c que compem a estrutura fossem uma entidade unica. o

10.2

Denies Bsicas co a

Uma estrutura, ento, uma coleao de variveis, de tipos diversos ou no, a e c a a agrupadas sob um unico nome. As variveis que compem a estrutura so os a o a seus membros, elementos ou campos. Normalmente os elementos da estrutura tem alguma relaao semntica. Por exemplo: alunos de uma universidade, discos c a de uma coleao, elementos de uma gura geomtrica, etc. Vamos considerar o c e exemplo do aluno e assumir que estaremos armazenando o seu nome, registro, ano de entrada e curso. Para este m podemos criar uma estrutura como a descrita no trecho de programa 10.1. A palavra chave struct inicia a declaraao da estrutura, em seguida pode c aparecer um identicador (ALUNO), que subseqentemente pode ser usado como u abreviaao da deniao da estrutura. A declaraao continua com a lista de c c c declaraoes entre chaves e termina com um ;. Um membro da estrutura e c uma varivel no membro da estrutura podem ter o mesmo nome, j que a a a e poss distingui-las por contexto. vel

160

Listing 10.1: Deniao de uma estrutura. c


s t r u c t ALUNO { char nome [40]; i n t registro ; i n t ano_entrada ; char curso [20]; };

A declaraao acima ainda no alocou espao de memria j que nenhuma c a c o a varivel foi realmente denida. Esta declaraao apenas um modelo de como a c e estruturas do tipo ALUNO devem ser constru das. Para denir estruturas deste tipo podemos usar a seguinte declaraao. c
struct ALUNO paulo, carlos, ana;

Nesta declaraao trs estruturas do tipo ALUNO foram criadas. Esta declaraao c e c alocou espao para armazenar os dados dos trs alunos. A declaraao acima c e c e idntica, na forma, a declaraao de variveis de um tipo pr-denido, como por e c a e exemplo:
int a, b, c;

E poss declarar ao mesmo tempo o modelo da estrutura e as variveis do vel a programa. Por exemplo,
s t r u c t ALUNO { char nome [40]; i n t registro ; i n t ano_entrada ; char curso [20]; } paulo , carlos , ana ;

Para referenciar um elemento da estrutura usa-se o nome da varivel do tipo a da estrutura seguida de um ponto e do nome do elemento. Por exemplo,
paulo.ano_entrada = 1999;

armazena o ano em que aluno paulo entrou na universidade. Para ler o nome do curso que paulo cursa pode-se usar o comando
gets(paulo.curso);

Estruturas podem conter outras estruturas como membros. Por exemplo, vamos denir uma estrutura para armazenar uma data com a seguinte deniao: c
s t r u c t DATA { i n t dia , mes , ano ; };

Agora vamos modicar a estrutura aluno de modo que ela inclua a data de nascimento do aluno. A estrutura ca com a seguinte deniao: c
s t r u c t aluno { char nome [40]; i n t registro ; i n t ano_entrada ; char curso [20];

161

s t r u c t DATA data_nascime nt o ; };

Para se referir ao ms de nascimento de uma varivel paulo do tipo estrutura e a


aluno usamos a declaraao c paulo.data_nascimento.mes

Note que o operador ponto (.) associa da esquerda para a direita. Uma forma mais conveniente de deniao de estruturas poss c e vel com o uso do comando typedef. Este comando permite dar a um tipo de dados um novo nome. A intenao aumentar a legibilidade do programa. Por exemplo, c e e poss usar o seguinte cdigo vel o
typedef i n t cores ; typedef i n t laranja ; typedef i n t manga ; ... laranja lima ; manga espada ; cores = AMARELO ; ... espada ++;

Ao mesmo tempo que typedef tem a vantagem de tornar mais claro a nalidade de cada varivel ele pode trazer problemas na medida em que esconde o a real tipo da varivel. a E comum o uso de typedef em conjunto com struct. Considere a deniao c de uma estrutura para guardar tempos gastos em tarefas. Esta estrutura deve guardar horas, minutos e segundos. Usando esta combinaao, a deniao c c e usualmente feita da seguinte maneira:
s t r u c t _TEMPO { i n t hora , minuto , segundo ; }; typedef s t r u c t _TEMPO TEMPO ; ... TEMPO t1 ;

Uma forma ainda mais abreviada, junta as duas denioes, cando a deniao c c da estrutura da seguinte maneira:
typedef s t r u c t _TEMPO { i n t hora , minuto , segundo ; } TEMPO ; ... TEMPO t1 ;

E poss dispensar o nome da estrutura (_TEMPO) e a deniao ca ainda vel c mais simples, com a seguinte forma:
typedef s t r u c t { i n t hora , minuto , segundo ; } TEMPO ; ... TEMPO t1 ;

162

10.3

Atribuio de Estruturas ca

E poss vel atribuir o contedo de uma estrutura a outra estrutura do mesmo u tipo, no sendo necessrio atribuir elemento por elemento da estrutura. Esta a a e uma das grandes vantagens de estruturas j que o tamanho do cdigo reduzido a o e e a clareza dos programas aumenta. O programa 10.2 ilustra como podemos atribuir uma estrutura a outra. O comando temp = emp1; faz com que todos os dados armazenados na estrutura emp1 sejam transferidos para a estrutura temp. Listing 10.2: Atribuiao de Estruturas. c
#include < stdio .h > typedef s t r u c t _EMPREGADO { char nome [40]; f l o a t salario ; } EMPREGADO ; i n t main () { EMPREGADO temp , emp1 ; puts ( " Entre com nome . " ); gets ( emp1 . nome ); puts ( " Qual o salario ? " ); scanf ( " % f " , & emp1 . salario ); temp = emp1 ; printf ( " O salario de % s e %.2 f \ n " , temp . nome , temp . salario ); return 0; }

10.4

Matrizes de Estruturas

Estruturas aparecem freqentemente na forma de matrizes. Por exemplo, a u declaraao struct ALUNO turma[100]; dene uma matriz de 100 estruturas do c tipo struct ALUNO. O exemplo 10.3 mostra atribuioes entre estruturas e operaes aritmticas c co e envolvendo membros de estruturas. O programa coloca um vetor de estruturas em ordem crescente usando como chave de ordenaao um dos membros da esc trutura (media). Listing 10.3: Ordenaao de Estruturas. c
#i ncl ude < stdio .h > #i ncl ude < string .h > typedef s t r u c t _ALUNO { char nome [40]; f l o a t n1 , n2 , media ; } ALUNO ; i n t main ( void ) { ALUNO turma [4] , temp ;

163

i n t jaOrdenados = 0 , foraOrdem , i ; f o r ( i = 0; i < 4; i ++) { gets ( turma [ i ]. nome ); scanf ( " % f " , & turma [ i ]. n1 ); do {} while ( getchar ()!= \ n ); scanf ( " % f " , & turma [ i ]. n2 ); do {} while ( getchar ()!= \ n ); turma [ i ]. media =( turma [ i ]. n1 + turma [ i ]. n2 )/2.0; } do { foraOrdem = 0; f o r ( i = 0; i < 4 - 1 - jaOrdenados ; i ++) { i f ( turma [ i ]. media > turma [ i +1]. media ) { temp = turma [ i ]; turma [ i ] = turma [ i +1]; turma [ i +1] = temp ; foraOrdem = 1; } } jaOrdenados ++; } while ( foraOrdem ); f o r ( i =0; i <4; i ++) { printf ( " \ nDados do aluno % d \ n " , i ); printf ( " % s : %0.1 f , %0.1 f , %0.1 f \ n " , turma [ i ]. nome , turma [ i ]. n1 , turma [ i ]. n2 , turma [ i ]. media ); } return 0; }

10.5

Estruturas e Funes co

Primeiro vamos considerar o caso de passar elementos da estrutura para funoes. c Caso os elementos da estrutura sejam variveis de um dos tipos j vistos, a a a passagem efetuada da maneira normal. O exemplo 10.4 mostra como passar e um elemento (c.raio) de uma estrutura para uma funao. c Listing 10.4: Passando elementos para funoes. c
#include < stdio .h > typedef s t r u c t _CIRCULO { f l o a t x , y , raio ; } CIRCULO ; f l o a t Area ( f l o a t r ) { return 3.141516 * r * r ; } i n t main ( void ) { CIRCULO c ; c . x = c . y = c . raio = 1.0; printf ( " % f \ n " , Area ( c . raio )); return 0;

164

A funao que recebe este parmetro est preparada para receber uma varivel c a a a de ponto utuante simples. Caso seja necessrio passar o endereo de um dos a c membros ou elementos da estrutura basta colocar o operador & antes do nome da estrutura. Por exemplo, para trocar os valores das coordenadas x dos centros de dois c rculos c1 e c2 usar amos chamadas da seguinte forma.
troca_x (& c1 .x , & c2 . x );

Para trabalhar com endereos necessrio usar ponteiros dentro da funao c e a c Antes vamos vericar como e poss passar uma estrutura inteira para uma funao. vel c
troca_x, mas isto veremos no prximo item. o

Estruturas, quando passadas para funoes, se comportam da mesma maneira c que as variveis dos tipos que j estudamos. Ao passar uma estrutura para uma a a funao estaremos passando os valores armazenados nos membros da estrutura. c Como este tipo de passagem feito por valor, alteraoes nos membros da estrue c tura no modicam os valores da estrutura na funao que chamou. A passagem a c de estruturas para funoes ilustrada no exemplo 10.5 onde o comprimento da c e reta que liga dois pontos p1 e p2 calculado e impresso. e Listing 10.5: Passagem de estruturas para funoes. c
#include < stdio .h > #include < math .h > typedef s t r u c t _PONTO { fl oat x, y; } PONTO ; f l o a t comp ( PONTO p1 , PONTO p2 ) { return sqrt ( pow ( p2 .x - p1 .x ,2)+ pow ( p2 .y - p1 .y ,2)); } i n t main ( void ) { PONTO p1 , p2 ; puts ( " Coordenadas do ponto 1 " ); printf ( " x1 = ? " ); scanf ( " % f " , & p1 . x ); printf ( " y1 = ? " ); scanf ( " % f " , & p1 . y ); puts ( " Coordenadas do ponto 2 " ); printf ( " x2 = ? " ); scanf ( " % f " , & p2 . x ); printf ( " y2 = ? " ); scanf ( " % f " , & p2 . y ); printf ( " \ nComprimento da reta = % f \ n " , comp ( p1 , p2 )); return 0; }

Para ilustrar a passagem de vetores de estruturas para funoes considere o c programa 10.3. Neste programa iremos substituir o trecho que ordena o vetor de alunos por uma funao, cujo cdigo mostrado na listagem 10.6. No programa c o e o trecho que chama a funao tem a seguinte forma c
Ordena(turma, 4);

165

Listing 10.6: Funao que ordena estruturas. c


void Ordena ( ALUNO turma [] , i n t tam ) { i n t i , foraOrdem , jaOrdenados = 0; ALUNO temp ; do { foraOrdem = 0; f o r ( i = 0; i < 4 - 1 - jaOrdenados ; i ++) { i f ( turma [ i ]. media > turma [ i +1]. media ) { temp = turma [ i ]; turma [ i ] = turma [ i +1]; turma [ i +1] = temp ; foraOrdem = 1; } } jaOrdenados ++; } while ( foraOrdem ); }

10.6

Ponteiros para Estruturas

Para denir ponteiros para estruturas a declaraao similar a declaraao de um c e c ponteiro normal. O exemplo abaixo mostra a deniao de um ponteiro chamado c maria para uma estrutura chamada aluno.
s t r u c t aluno { char nome [40]; i n t ano_entrada ; f l o a t n1 , n2 , media ; } * maria ;

Ponteiros so uteis quando passamos estruturas para funoes. Ao passar a c apenas o ponteiro para estrutura economizamos tempo e memria. O espao o c de memria, economizado por que se evita passar os dados que compem a o e o estrutura um por um. O tempo economizado porque no necessrio gastar o e a e a tempo de empilhar e desempilhar todos os elementos da estrutura no processo de passagem para a funao. Empilhar e desempilhar se referem a pilha de dados c usada para transferir os dados entre funoes. c Para acessar elementos da estrutura apontada por um ponteiro usa-se o chamado operador seta (->). Por exemplo para imprimir a mdia da aluna e maria usar amos o comando
printf ( " A media vale %.1 f " , maria - > media );

Para alocar espao para estruturas apontadas por ponteiros necessrio usar c e a o operador unrio sizeof, isto porque o tamanho de uma estrutura sempre a e igual ou maior que a soma dos tamanhos dos seu componentes. Para explicar esta fato devemos considerar como os dados so armazenados na memria dos a o computadores. Algumas arquiteturas de computadores endeream os dados na memria por c o bytes, isto cada endereo de memria se refere a um byte. No entanto, estas are c o quiteturas lem sempre uma palavra inteira da memria. Usualmente, palavras e o 166

podem ser compostas de dois bytes e comeam em endereos pares, como est c c a mostrado na gura abaixo. Sabemos que existem variveis que ocupam mais de a um byte, por exemplo inteiros que so compostos de dois bytes. a Imagine ento uma estrutura composta de um caractere (1 byte) e um a nmero de inteiro (2 bytes). Caso a memria do computador seja organizada u o em palavras de 16 bits ou 2 bytes a estrutura acima ocuparia 3 bytes ou uma palavra e meia. Para ler o nmero inteiro o programa deveria ler duas palavras. u Lembrar que se os dados fossem sempre armazenados seqencialmente, metade u do nmero inteiro estaria em uma palavra e a metade restante na outra, como u est indicado na gura abaixo (parte a). Para facilitar o acesso `s variveis, a a a alguns compiladores armazenam as variveis de acordo com o que est india a cado na gura (parte b). Observar que agora a estrutura ocupa quatro bytes. Neste caso o acesso ao nmero inteiro ser sempre feito em um passo e portanto u a ganhou-se em tempo de acesso ao custo de gasto de memria. Este uma troca o e constante em computaao. c Vimos ento que embora o total de bytes dos elementos da estrutura fosse a trs o compilador pode armazenar a estrutura em quatro bytes, da a necessidade e de sempre usar o operador sizeof quando alocar espao. c O programa 10.7 mostra como alocar espao para uma varivel simples e c a como usar esta varivel em diversos tipos de comandos. a Listing 10.7: Alocaao de espao para estruturas. c c
#i ncl ude < stdio .h > #i ncl ude < string .h > #i ncl ude < stdlib .h > typedef s t r u c t _ALUNO { char nome [40]; f l o a t n1 , n2 , media ; } ALUNO ; i n t main ( void ) { ALUNO * maria ; maria = ( ALUNO *) malloc ( s i z e o f ( ALUNO )); i f (! maria ) exit (1); gets ( maria - > nome ); scanf ( " % f % f " , &( maria - > n1 ) , &( maria - > n2 )); maria - > media = ( maria - > n1 + maria - > n2 ) / 2; printf ( " A media de % s vale %0.2 f \ n " , maria - > nome , maria - > media ); return 0; }

O programa 10.8 mostra como utilizar ponteiros para vetores de estruturas e a forma mais segura de alocar espao para os dados. Observar as notaoes usadas c c na funao que l os dados dos funcionrios. Notar que (cadastro+i)->salario c e a e o valor da salrio. a
fgets (( cadastro + i ) - > nome , 39 , stdin ); sscanf ( linha , " % f " , &(( cadastro + i ) - > salario ));

167

Listing 10.8: Alocaao de espao para vetores de estruturas. c c


#include < stdio .h > #include < stdlib .h > typedef s t r u c t _func { char nome [40]; f l o a t salario ; } Tfunc ; void le ( Tfunc * cadastro , i n t funcionarios ) { int i; char linha [40]; f o r ( i =0; i < funcionarios ; i ++) { puts ( " Nome ? " ); fgets (( cadastro + i ) - > nome , 39 , stdin ); puts ( " Salario ? " ); fgets ( linha , 39 , stdin ); sscanf ( linha , " % f " , &(( cadastro + i ) - > salario )); } } f l o a t media ( Tfunc * cadastro , i n t funcionarios ) { f l o a t media =0.0; int i; f o r ( i =0; i < funcionarios ; i ++) { media += ( cadastro + i ) - > salario ; } return media /= funcionarios ; } i n t main ( void ) { Tfunc * cadastro ; i n t funcionarios ; char linha [40]; puts ( " Quantos funcionarios ? " ); fgets ( linha , 39 , stdin ); sscanf ( linha , " % d " , & funcionarios ); i f (!( cadastro = ( Tfunc *) malloc ( funcionarios * s i z e o f ( Tfunc )))) { exit (1); } le ( cadastro , funcionarios ); printf ( " Salario medio = %.2 f \ n " , media ( cadastro , funcionarios )); return 0; }

168

10.7

Exerc cios

10.1: Considere que uma empresa precisa armazenar os seguintes dados de um cliente: Nome completo com no mximo 50 caracteres; a renda mensal do do cliente; ano de nascimento; possui ou no carro. a Dena um tipo e uma estrutura para armazenarem estes dados e escreva um programa que leia estes dados armazene-os em uma varivel e em seguida os a imprima. 10.2: Considerando a mesma estrutura do exerc anterior, escreva um procio grama que leia os dados de 100 clientes e imprima: quantos clientes tm renda mensal acima da mdia; e e quantos clientes tm carro; e quantos clientes nasceram entre 1960 (inclusive) e 1980 (exclusive). 10.3: Reescreva o programa 10.3 empregando funoes para implementar as c diversas tarefas do programa. A funao main deve car da maneira indicada na c Listagem 10.9. Listing 10.9: Listagem do exercicio 3.
i n t main ( void ) { s t r u c t aluno turma [ MAX ]; le ( turma ); puts ( " Imprimindo dados lidos da turma . " ); puts ( " Digite qualquer coisa para continuar . " ); getchar (); imprime ( turma ); ordena_medias ( turma ); puts ( " Imprimindo dados ordenados da turma . " ); puts ( " Digite qualquer coisa para continuar . " ); getchar (); imprime ( turma ); getchar (); }

10.4: Escrever um programa que utilize structs e ponteiro para struct e imprima o contedo das variveis da struct. u a

169

10.5: Escrever um programa que utilize enumeradores com as matrias do seu e per odo. Inicialize cada matria com um numero. Depois imprime os valores e das variveis enumeradas. a 10.6: Escrever um programa que utilize union. Inicialize as variveis com a valores diferentes e imprima o contedo delas. u 10.7: Fazer um programa que simule as operaoes de uma pilha push e pop, c usando structs. Um exemplo de entrada poderia ser o seguinte: empilha C empilha B empilha A desempilha A desempilha B desempilha C 10.8: Escreva um programa que solicite o nome e telefone de uma pessoa e grave essas informaoes num vetor de uma estrutura que contem esses dados (nome e c telefone). O programa deve ter trs opoes apenas: uma que adiciona um novo e c dado, outra que lista todos os dados atualmente armazenados na memria e o outra que sai do programa. Esse vetor de estrutura deve ter apenas 10 elementos e fornecer uma mensagem de erro caso o usurio tente adicionar mais pessoas a que este mximo permitido. a 10.9: Escreva uma estrutura similar as strings do Delphi (possuem um campo armazenando o tamanho da string e um ponteiro para o primeiro caractere da string) e crie as funoes strcpy e strcat para strings nesse formato. c 10.10: Escreva um programa fazendo o uso de estruturas. Voc dever criar e a uma estrutura chamada Ponto, contendo apenas a posiao x e y (inteiros) do c ponto. Declare 2 pontos, leia a posiao (coordenadas x e y) de cada um e calcule c a distncia entre eles. Apresente no nal a distncia entre os dois pontos. a a 10.11: Crie uma estrutura chamada ret^ngulo, que possua duas estruturas a ponto (o ponto superior esquerdo e o ponto inferior direito). Faa um programa c que receba as informaoes acerca de um retngulo (as coordenadas dos dois c a pontos), e informe a rea, o comprimento da diagonal e o comprimento de cada a aresta 10.12: Escreva um programa que use as mesmas estruturas do exerc anterior cio para descobrir se um ponto est dentro de um retngulo. a a 10.13: Considere que foi denida a seguinte estrutura:
typedef s t r u c t _frac { i n t numerador , denominador ; } FRACAO ;

Escreva um programa em C que calcule as quatro operaoes usando fraoes c c denidas com estruturas do tipo FRACAO. O programa deve ler duas fraoes e c imprimir o resultado de cada uma das quatro operaoes. c

170

Cap tulo 11

Entrada e Sa por da Arquivos


11.1 Introduo ca

Em C no existem instruoes especiais de entrada e sa como em outras lina c da guagens de programaao. Estas tarefas, em C so executadas por funoes espec a c cialmente criadas para esta nalidade e armazenadas em bibliotecas espec cas. Por esta razo todos programas em C que precisam de entrada e/ou sa de a da dados necessitam incluir a diretiva #include<stdio.h> no in do programa, cio para permitir o uso da biblioteca padro stdio de funoes de entrada e sa a c da.

11.2

Fluxos de Dados

Para isolar os programadores dos problemas de manipular os vrios tipos de a dispositivos de armazenamento e seus diferentes formatos a linguagem C utiliza o conceito de uxo de dados (stream). Todos os diferentes sistemas de arquivos se comportam da mesma maneira que foi denida como semelhante a um uxo cont nuo de dados (stream). Dados podem ser manipulados em dois diferentes tipos de uxos: uxos de texto e uxos binrios. a

11.2.1

Fluxos de Texto

Um uxo de texto (text stream) composto por uma seqncia de caracteres, e ue que pode ou no ser dividida em linhas terminadas por um caractere de nal de a linha. Um detalhe que deve ser considerado ao escrever um programa que na e ultima linha no obrigatrio o caractere de m de linha. a e o Nem sempre a traduao entre a representaao do caractere no uxo de texto c c e no sistema de arquivos do computador hospedeiro um para um byte. Por e exemplo, entre UNIX e DOS h uma diferena na representaao de nal de a c c linha (linefeed ) que causa problemas na impresso de arquivos. Em UNIX um a nal de linha representado pelo caractere de alimentaao de linha (LF). Em e c 171

DOS um nal de linha representado pelo par retorno de carro/alimentaao de e c linha (CR/LF). Deste modo quando um arquivo gerado em UNIX vai para uma impressora que espera nal de linha no modo DOS surge o que comumente e chamado de efeito escada. A impresso continua na linha seguinte mas sem a voltar para o in da linha porque em UNIX o caractere de retorno de carro cio no inserido no uxo de texto. a e At agora temos trabalhado com os uxos de dados padro: stdin, para e a entrada de dados e stdout para sa de dados. Ao iniciar todo programa em da C automaticamente associado a estes dois uxos de dados sem necessitar de e nenhuma intervenao do programador. A deniao de que perifricos estaro c c e a associados a estes uxos depende do sistema operacional. Normalmente o uxo de entrada (stdin) est associado ao teclado e o uxo de sa (stdout) ao a da monitor.

11.2.2

Fluxo Binrio a

Um uxo binrio composto por uma seqncia de bytes lidos, sem traduao, a e ue c diretamente do dispositivo externo. Existe uma correspondncia um para um e entre os dados do dispositivo e os que esto no uxo que o programa manipula. a A Figura 11.1 ilustra estes dois tipos de uxos. No uxo de texto os dados so a armazenados como caracteres sem converso para representaao binria. Cada a c a um dos caracteres ocupa um byte. O numero 12 ocupa dois bytes e o n mero u 113 ocupa 3. Um caractere em branco foi inserido entre cada um dos n meros u para separ-los, de modo que a funao de entrada e sa possa descobrir que a c da so dois nmeros inteiros (12 e 113) e no o nmero 12113. a u a u No uxo binrio cada nmero inteiro ocupa 32 bits e armazenado na forma a u e binria. Os caracteres do exemplo esto armazenados seguindo a tabela ASCII. a a Observe que, em arquivos binrios, no h necessidade de separar os n meros a a a u j que eles sempre ocupam 32 bits. a

fluxo de texto 1 2 b 1 1 3 b a b

fluxo binrio
000...01100 000...01110001 01100001 01100010

32 bits 12

32 bits 113

8 bits 8 bits a b

Figura 11.1: Fluxos de dados.

172

11.2.3

Arquivos

Um arquivo pode estar associado ` qualquer dispositivo de entrada e sa a da como, por exemplo: impressora, teclado, disquete, disco r gido etc. No entanto, os programas vem os arquivos atravs de uxos. Para que um determinado e e arquivo em um perifrico seja associado a um uxo necessrio que o arquivo e e a seja aberto e somente aps esta operaao, o programa pode manipular os o c dados. Normalmente a interaao entre o programa e os arquivos feita por c e meio de buers que intermediam a transferncia dos dados entre os programas e e os perifricos. Isto serve para facilitar a operaao do sistema operacional. e c Operaoes comuns em arquivos so: c a abertura e fechamento de arquivos; remover um arquivo; leitura e escrita de um caractere ou byte; procurar saber se o m do arquivo foi atingido; posicionar o arquivo em um ponto determinado. Obviamente algumas dessas funoes no se aplicam a todos os tipos de disc a positivos. Por exemplo, para uma impressora pode no ser poss a vel usar a funao que reposiciona o arquivo no in c cio. Um arquivo em disco permite acesso aleatrio enquanto um teclado no. o a Ao nal das operaoes nos arquivos o programa deve fech-los. Caso o c a programador esquea de executar esta operaao, ao nal do programa todos os c c arquivos associados so fechados automaticamente e os conte dos dos buers a u so descarregados para o dispositivo externo. Caso o arquivo seja de entrada o a contedo do buer esvaziado. u e

11.3

Funes de Entrada e Sa co da

As funoes de Entrada e Sa normalmente utilizadas pelos programadores c da esto armazenadas na biblioteca stdio.h. As funoes mais comuns esto mostradas a c a na tabela 11.1. Para ter acesso aos dados em um arquivo necessrio a denio de um e a ca ponteiro do tipo especial FILE. Este tipo tambm est denido na biblioteca e a stdio.h. Um ponteiro deste tipo permite que o programa tenha acesso a uma estrutura que armazena informaoes importantes sobre o arquivo. Para denir c uma varivel deste tipo o programa deve conter a seguinte declaraao a c
FILE *arq;

onde arq o ponteiro que ser usado para executar as operaoes no arquivo. e a c

173

Funo ca
fopen() fclose() fputc() getc(), fgetc() fprintf() sscanf() fscanf() fseek() rewind() feof() ferror() fflush() fread() fwrite()

Descrio ca Abre um arquivo Fecha um arquivo Escreve um caractere em um arquivo L um caractere de um arquivo e Equivalente a printf() Equivalente a scanf(). L de uma cadeia de caracteres e Equivalente a scanf() Posiciona o arquivo em um ponto espec co Posiciona o arquivo no in cio Retorna verdade se chegou ao m do arquivo Verica a ocorrncia de um erro e Descarrega o buer associado ao arquivo Leitura de dados no modo binrio a Escrita de dados no modo binrio a

Tabela 11.1: Exemplos de funoes de Entrada e Sa c da.

11.4

In cio e Fim

As operaoes mostradas a seguir mostram operaoes que devem ser realizadas c c antes e depois de usar um arquivo (fopen() e fclose()). As outras duas funoes c servem para que o usurio possa detectar o m de um arquivo ou voltar para a seu in cio.

11.4.1

Abrindo um Arquivo

Antes de qualquer operaao ser executada com o arquivo, ele deve ser aberto. c Esta operaao associa um uxo de dados a um arquivo. Um arquivo pode ser c aberto de diversas maneiras, de acordo com as operaoes que devero ser exec a cutadas: leitura, escrita, leitura/escrita, adiao de texto etc. A funao utilizada c c para abrir o arquivo chamada fopen() e tem o seguinte prottipo: e o
FILE *fopen (const char *parq, const char *modo)

onde parq um ponteiro de arquivo para o arquivo a ser manipulado e modo e e um ponteiro para uma cadeia de caracteres que dene a maneira como o arquivo vai ser aberto. Este ponteiro no deve ser modicado e a funo retorna um a ca ponteiro nulo (NULL) se o arquivo no puder ser aberto. A seguir listamos os a diversos modos que podem ser usados para abrir um arquivo. r: Abre um arquivo para leitura, o arquivo deve existir ou um erro ocorre. w: Cria um arquivo vazio para escrita, caso um arquivo com o mesmo nome exista o seu contedo apagado. u e a: Adiciona ao nal de um arquivo. O arquivo criado caso ele no exista. e a

174

r+: Abre um arquivo para leitura e escrita. O arquivo deve existir ou um erro ocorre. w+: Cria um arquivo vazio para leitura e escrita. Se um arquivo com o mesmo nome existe o contedo apagado. u e a+: Abre um arquivo para leitura e adiao. Todas as operaoes de escrita c c so feitas no nal do arquivo. E poss reposicionar o ponteiro do arquivo a vel para qualquer lugar em leituras, mas as escritas movero o ponteiro para a o nal do arquivo. O arquivo criado caso no exista. e a Observar que se um arquivo for aberto com permisso de escrita todo o seu a contedo anterior ser apagado. Caso o arquivo no exista ele ser criado. u a a a O trecho de programa abaixo ilustra os passos necessrios para abrir um a arquivo para escrita. Primeiro declarado o ponteiro pa para o arquivo. Em e seguida a funao fopen chamada para associar o nome externo do programa c e (arquivo.txt) no modo escrita ao ponteiro pa. Um teste para ponteiro nulo feito para vericar se ocorreu algum problema com a operaao de abertura do e c arquivo.
FILE * pa ; /* declaracao do ponteiro para arquivo */ /* nome externo associado ao interno */ pa = fopen ( " arquivo . txt " , " w " ); i f ( pa == NULL ) { /* verifica erro na abertura */ printf ( " Arquivo nao pode ser aberto . " ); return 1; }

Lembrar que abrir, para escrita, um arquivo que j existe, implica em apagar a todo o contedo anterior e a preparaao do arquivo para receber dados a partir u c de seu ponto inicial. Se o programador deseja acrescentar dados ao nal de um arquivo j existente o modo de abertura deve ser a. a

11.4.2

Fechando um Arquivo

Um arquivo aberto por meio da funao fopen() deve ser fechado com a funao c c
fclose() cujo prottipo o e int fclose (FILE *parq);

onde parq um ponteiro de arquivo para o arquivo que deve ser fechado. Todos e os buers internos associados com o uxo de dados do arquivo so descarregaa dos. O contedo de qualquer buer no escrito escrito e dados no lidos de u a e a buers so perdidos. Este ponto importante de ser considerado porque em a e muitos sistemas operacionais uma operaao de escrita em um arquivo no ocorre c a imediatamente a emisso da ordem de escrita. O sistema operacional pode exa ecutar a ordem no momento que achar mais conveniente. Um valor zero de retorno signica que a operaao foi executada com xito, qualquer outro valor c e implica em erro. 175

11.4.3

Fim de Arquivo

A funao feof() indica que um arquivo chegou ao seu nal. A pergunta que c pode surgir a seguinte - Se j existe o valor EOF para indicar o nal de arquivo, e a por que precisamos de uma funo extra do tipo feof()? O problema que EOF ca e um valor inteiro e ao ler arquivos binrios este valor pode ser lido como parte e a do arquivo e no por ser o nal do arquivo. A funao feof() serve para indicar a c que o nal de um arquivo binrio foi encontrado. Naturalmente esta funao a c pode ser aplicada tambm a arquivos texto. O prottipo da funao o seguinte: e o c e
int feof(FILE *parq)

Um valor diferente de zero retornado no caso de ter sido atingido o nal e do arquivo. O valor zero indica que ainda no se chegou ao nal do arquivo. a O exemplo 11.1 mostra um programa que l um caractere do teclado e o e mostra na tela. Neste exemplo a leitura termina quando o usurio digita o a caractere <ctl>+D, que indica nal de arquivo pelo teclado em Unix (no outro sistema <ctl>+Z). e Listing 11.1: Uso da funao feof(). c
#include < stdio .h > i n t main ( void ) { char c ; c = getchar (); while ( c != EOF ) { putchar ( c ); c = getchar (); } return 0; }

11.4.4

Volta ao In cio

A funao rewind() recoloca o indicador de posiao de arquivo no in do arc c cio quivo. Uma operaao semelhante ao que fazemos em uma ta cassete de m sica c u ou v deo. O prottipo da funao o seguinte: o c e
void rewind(FILE *parq)

E importante observar que o arquivo deve estar aberto em um modo que permita a execuao das operaoes desejadas. Por exemplo, um arquivo aberto c c somente para escrita e em seguida reposicionado para o in cio, no ir permitir a a outra operaao que no seja escrita. c a

176

11.5

Lendo e Escrevendo Caracteres

As operaoes mais simples em arquivos so a leitura e escrita de caracteres. c a Para ler um caractere de um arquivo, que foi previamente aberto, pode-se usar as funoes getc() e fgetc(), que so equivalentes. Os prottipos destas funoes c a o c so os seguintes: a
int fgetc (FILE *parq); int getc (FILE *parq);

As funoes getc() e fgetc() so equivalentes e muitos compiladores implec a mentam getc() como uma macro do seguinte modo:
#dene getc(parq) fgetc(parq)

A funao l o caractere como um unsigned char mas retorna o valor como c e um inteiro, onde o byte mais signicativo vale zero. O apontador do arquivo avana um caractere e passa a apontar para o prximo caractere a ser lido. c o A funao devolve o cdigo EOF ao chegar ao nal do arquivo ou caso um erro c o ocorra. O valor EOF tambm um inteiro vlido e portanto ao usar arquivos e e a binrios necessrio que a funao feof() seja utilizada para vericar o nal do a e a c arquivo. A funao ferror() pode ser usada para determinar se um erro ocorreu. c Para escrever caracteres h duas funoes denidas putc() e fputc(). Os a c prottipos das funoes so os seguintes: o c a
int putc(int ch, FILE *parq); int fputc(int ch, FILE *parq)

onde parq um ponteiro de arquivo para o arquivo que foi previamente aberto e por meio da funao fopen() e ch o caractere a ser escrito. c e O programa 11.2 mostra como um arquivo pode ser criado para leitura e escrita. Em seguida um conjunto de caracteres lido do teclado escrito no are quivo. O prximo passo a leitura do arquivo que iniciada aps uma chamada o e e o a funao rewind(), fazendo com que o indicador de posiao do arquivo volte a c c apontar para seu in cio. Uma outra alternativa mostrada em 11.3 mostra um exemplo onde o arquivo criado para escrita em seguida fechado e reaberto para leitura cando e e automaticamente posicionado no in para a leitura. cio

11.6

Testando Erros

A funao ferror(FILE *parq) serve para vericar se ocorreu um erro associado c ao uxo de dados sendo usado. Um valor diferente de zero a indicaao do e c erro, que ocorre geralmente quando a operaao previamente executada no uxo c falhou. O parmetro parq um ponteiro para o uxo a ser testado. O programa a e 11.4 abre um arquivo para leitura, mas tenta escrever um caractere o que provoca um erro que testado pela funao ferror. e c

177

Listing 11.2: Exemplo de leitura e escrita de caracteres.


#include < stdio .h > #include < stdlib .h > i n t main ( void ) { int c; FILE * pa ; char * nome = " texto . txt " ; /* Abre o arquivo para leitura e escrita */ i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); exit (1); } /* Cada caractere digitado sera gravado no arquivo */ c = getchar (); while (! feof ( stdin )) { fputc (c , pa ); c = getchar (); } rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); c = fgetc ( pa ); while (! feof ( pa )) { putchar ( c ); c = fgetc ( pa ); } fclose ( pa ); return 0; }

178

Listing 11.3: Exemplo de leitura e escrita de caracteres.


#include < stdio .h > i n t main ( void) { int c; FILE * pa ; char * nome = " texto . txt " ; i f (( pa = fopen ( nome , " w " )) == NULL ) { printf ( " \ n \ nErro ao abrir o arquivo - escrita .\ n " ); return 1; } c = getchar (); while (! feof ( stdin )) { fputc (c , pa ); c = getchar (); } fclose ( pa ); printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); i f (( pa = fopen ( nome , " r " )) == NULL ) { printf ( " \ n \ nErro ao abrir o arquivo - leitura .\ n " ); exit (1); } c = fgetc ( pa ); while (! feof ( pa )) { putchar ( c ); c = fgetc ( pa ); } fclose ( pa ); return 0; }

179

Listing 11.4: Uso da funao ferror(). c


#i ncl ude < stdio .h > i n t main ( void ) { FILE * pArq ; pArq = fopen ( " MeusDados . txt " ," r " ); i f ( pArq == NULL ) { printf ( " Erro abrindo arquivo . " ); return 1; } else { fputc ( x , pArq ); i f ( ferror ( pArq )) { printf ( " Erro escrevendo arquivo \ n " ); fclose ( pArq ); return 1; } } return 0; }

11.7

Lendo e Escrevendo Cadeias de Caracteres

As funoes fgets() e fputs() servem para ler e escrever cadeias de caracteres c em arquivos. Os prottipos das funoes so: o c a
int fputs(char *str, FILE *parq); int fgets(char *str, int comp, FILE *parq);

A funao fputs() escreve a cadeia de caracteres apontada por str no uxo c apontado por parq. O cdigo nulo ao nal da cadeia no copiado para o uxo. o a e O cdigo correspondente ` EOF ser retornado se ocorrer um erro e um valor no o a a a negativo em caso de sucesso. A funao fgets() l uma cadeia de caracteres do uxo especicado por parq c e at que um caractere de nova linha seja encontrado ou comp-1 caracteres sejam e lidos. O caractere de nova linha interrompe a leitura. Observar que diferentemente de gets() o caractere de nova linha encontrado passa a fazer parte da cadeia que recebe um caractere nulo ao seu nal. O ponteiro str retornado e caso a leitura ocorra sem erro. No caso de erro o ponteiro str recebe o valor NULL. Se o m do arquivo for encontrado e nenhum caractere foi lido, o conte do u de str mantido e um NULL retornado. O exemplo 11.5 mostra um exemplo e e de uso destas funoes para ler e escrever cadeias de caracteres em um arquivo. c Listing 11.5: Exemplo de leitura e escrita de cadeias de caracteres.
#include < stdio .h > #de fi ne MAX 80 i n t main ( void ) { char linha [ MAX ];

180

FILE * pa ; char * nome = " texto . txt " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); return 1; } fgets ( linha , MAX , stdin ); while (! feof ( stdin )) { fputs ( linha , pa ); fgets ( linha , MAX , stdin ); } rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n \ n " ); fgets ( linha , MAX , pa ); while (! feof ( pa )) { puts ( linha ); fgets ( linha , MAX , pa ); } fclose ( pa ); return 0; }

11.8

Entrada e Sa Formatada da

As funoes fprintf() e fscanf() so equivalentes as funoes printf() e scanf() c a c usadas at agora, sendo a unica modicaao o fato de que elas trabalham com e c uxos de dados (arquivos). Os prottipos das duas funoes so os seguintes: o c a
int fprintf(FILE *parq, const char *formatacao, ...); int fscanf(FILE *parq, const char *formatacao, ...);

onde parq um ponteiro de arquivo recebido aps uma chamada a fopen(). e o Em leituras, a funao retorna o nmero de itens lidos com sucesso. Esta c u contagem pode igualar o nmero esperado de leituras ou ser menor no caso u de falha. Caso ocorra uma falha antes de que uma leitura possa ser feita com sucesso, EOF retornado. e Em escritas, caso a operaao de escrita tenha sucesso, o nmero total de c u caracteres escrito retornado. Um nmero negativo retornado em caso de e u e falha. Embora estas duas funoes, por sua semelhana com printf() e scanf(), c c sejam maneiras convenientes de escrever e ler dados de arquivos, elas tm a e desvantagem de serem mais lentas do que uso de arquivos binrios. A perda a de tempo devido ao fato dos dados serem gravados em ASCII, o que obriga e a uma converso dos dados a cada operaao realizada. Em alguns casos o fato a c dos dados serem gravados em ASCII pode ser considerado um vantagem que se sobrepe a desvantagem da reduao de velocidade. Dados gravados em ASCII o c podem ser facilmente vericados pelos usurios, o que no acontece com dados a a

181

em binrio. O exemplo 11.6 mostra o uso destas funoes para ler e escrever a c vrios tipos de dados em um arquivo. a Listing 11.6: Exemplo de leitura e escrita de dados formatados.
#include < stdio .h > i n t main ( void ) { char palavra [20]; int i; fl oat f; FILE * pa ; char * nome = " format . txt " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); return 1; } puts ( " Entre com uma palavra . " ); scanf ( " % s " , palavra ); puts ( " Entre com um numero inteiro . " ); scanf ( " % d " , & i ); puts ( " Entre com um numero flutuante . " ); scanf ( " % f " , & f ); /* Escreve os dados no arquivo */ fprintf ( pa , " % s % d % f " , palavra , i , f ); rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); fscanf ( pa , " % s % d % f " , palavra , &i , & f ); printf ( " Palavra lida : % s \ n " , palavra ); printf ( " Inteiro lido : % d \ n " , i ); printf ( " Float lido : % f \ n " , f ); fclose ( pa ); return 0; }

11.9

Lendo e Escrevendo Arquivos Binrios a

As funoes fread e fwrite so empregadas para leitura e escrita de dados em c a modo binrio. Os prottipos das funoes so: a o c a
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *parq); size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *parq);

A funao fread l nmemb objetos, cada um com size bytes de comprimento, c e do uxo apontado por stream e os coloca na localizaao apontada por ptr. A c funao retorna o nmero de itens que foram lidos com sucesso. Caso ocorra um c u erro, ou o m do arquivo foi atingido o valor de retorno menor do que nmemb e ou zero. Esta funao no distingue entre um m de arquivo e erro, portanto c a e aconselhvel o uso de feof() ou ferror() para determinar que erro ocorreu. a A funao fwrite escreve nmemb elementos de dados, cada um com size bytes c de comprimento, para o uxo apontado por stream obtendo-os da localizaao c apontada por ptr. fwrite retorna o nmero de itens que foram lidos com sucesso. u Caso ocorra um erro, ou o m do arquivo foi atingido o valor de retorno menor e do que nmemb ou zero. O programa 11.7 ilustra como podemos escrever e ler dados binrios de diferentes tipos em arquivos. Como um dos parmetros da a a funao o nmero de bytes do dado a ser lido, recomendado o uso de sizeof. c e u e 182

Listing 11.7: Exemplo de leitura e escrita na forma binria. a


#include < stdio .h > i n t main ( void ) { i n t inum =10; f l o a t fnum =2.5; double pi =3.141516; char c = Z ; FILE * pa ; char * nome = " texto . bin " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { perror ( " fopen : " ); return 1; } fwrite (& inum , s i z e o f ( i n t ) , 1 , pa ); fwrite (& fnum , s i z e o f ( f l o a t ) , 1 , pa ); fwrite (& pi , s i z e o f (double) , 1 , pa ); fwrite (& c , s i z e o f ( char ) , 1 , pa ); rewind ( pa ); fread (& inum , s i z e o f ( i n t ) , 1 , pa ); fread (& fnum , s i z e o f ( f l o a t ) , 1 , pa ); fread (& pi , s i z e o f (double) , 1 , pa ); fread (& c , s i z e o f ( char ) , 1 , pa ); printf ( " %d , %f , %f , % c \ n " , inum , fnum , pi , c ); fclose ( pa ); return 0; }

Uma das principais aplicaoes destas funoes a leitura e escrita de estruc c e turas criadas pelos usurios. A gravaao em binrio da estrutura permite que o a c a programador ao escrever ou ler do arquivo se preocupe somente com a estrutura como um todo e no com cada elemento que a compe. O programa 11.8 mostra a o um exemplo onde estruturas so gravadas e lidas de um arquivo. Neste exemplo a usado um lao para gravar uma estrutura de cada vez. No entanto, tambm e c e poss gravar todas as estruturas de uma vez mudando o terceiro parmetro e vel a da funao fwrite(). O lao seria substitu por c c do
fwrite( &turma[i], sizeof (struct pessoa), MAX, pa);

Para testar erro basta vericar o valor retornado pela funao. Caso ela tenha c retornado um valor diferente de MAX ocorreu um erro.

183

Listing 11.8: Exemplo de leitura e escrita de estruturas.


#include < stdio .h > #include < string .h > typedef s t r u c t _PESSOA { char nome [40]; i n t ano ; } PESSOA ; i n t main () { FILE * pa ; char nome [40] , linha [80]; PESSOA turma [4] , back [4]; int i; f o r ( i =0; i <4; i ++) { puts ( " Nome ? " ); fgets ( turma [ i ]. nome , 40 , stdin ); turma [ i ]. nome [ strlen ( turma [ i ]. nome ) -1]= \0 ; puts ( " Ano ? " ); fgets ( linha , 80 , stdin ); sscanf ( linha , " % d " , & turma [ i ]. ano ); } puts ( " \ nGravando \ n " ); puts ( " Qual o nome do arquivo ? " ); fgets ( nome , 40 , stdin ); nome [ strlen ( nome ) -1]= \0 ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { puts ( " Arquivo nao pode ser aberto " ); return 1; } f o r ( i =0; i <4; i ++) { i f ( fwrite ( & turma [ i ] , s i z e o f ( PESSOA ) , 1 , pa ) != 1) puts ( " Erro na escrita . " ); } rewind ( pa ); f o r ( i =0; i <4; i ++) { i f ( fread ( & back [ i ] , s i z e o f ( PESSOA ) , 1 , pa ) != 1) { i f ( feof ( pa )) break ; puts ( " Erro na leitura . " ); } } f o r ( i =0; i <4; i ++) { printf ( " Nome = % s \ n " , back [ i ]. nome ); printf ( " Ano = % d \ n \ n " , back [ i ]. ano ); } return 0; }

184

11.10

Exerc cios

11.1: Escreva um programa que abra um arquivo texto e conte o n mero de u caracteres presentes nele. Imprima o nmero de caracteres na tela. u 11.2: Considere um arquivo de dados do tipo texto com o seguinte conte do: u 3 ZE SA 8.5 10.0 ANTONIO SANTOS 7.5 8.5 SEBASTIAO OLIVEIRA 5.0 6.0 O arquivo acima um exemplo. Considere ento que nestes arquivos a e a primeira linha contm o nmero de alunos no arquivo. As linhas seguintes e u contm os seguintes dados: e nome do aluno com no mximo 50 caracteres; a nota da primeira prova; nota da segunda prova. Escreva um programa que imprima os nomes de todos os alunos que tm a mdia e e das duas notas menor que 7.0 11.3: Escreva um programa que grave os dados lidos no exerc anterior em cio um arquivo do tipo binrio de acesso aleatrio. O nmero que indica quantos a o u alunos devem ser lidos (primeira linha do arquivo) no deve ser gravado no a arquivo binrio. Nesta questo o programa deve obrigatoriamente usar um a a vetor de estruturas do seguinte tipo:
typedef s t r u c t _ALUNO { char nome [81]; f l o a t n1 , n2 ; } ALUNO ;

11.4: Escreva um programa que leia de um arquivo, cujo nome sera fornecido pelo usurio, um conjunto de nmeros reais e armazena em um vetor. O a u tamanho mximo do vetor e dado pela constante TAM_MAX. A quantidade de a nmeros no arquivo varia entre 0 e TAM_MAX. O programa ao nal calcula a u media dos nmeros lidos. u 11.5: Faa um programa que leia 10 caracteres e armazene em um arquivo 10 c cpias de cada um. Exiba o contedo o u

185

11.6: Crie uma funao que receba duas strings como parmetros, uma com um c a endereo de arquivo e outra com um texto qualquer, e adicione o texto no m c do arquivo. 11.7: Utilizando a funao do exerc anterior faa um programa que gere 10 c cio c arquivos com o nome Testee extenses 01, ..., 10. Cada um contendo o o texto Texto do arquivo [NUMERO DO ARQUIVO]. 11.8: Escreva um programa para armazenar o telefone de 5 amigos. O programa deve obrigatoriamente usar a estrutura
typedef s t r u c t _PESSOA { char nome [50]; i n t idade ; f l o a t altura ; char telefone [10]; } PESSOA ;

a ser preenchida pelo usurio antes do armazenamento de cada registro. a 11.9: Faa um programa que leia os dados do arquivo gerado no exerc c cio anterior e salve-os num novo arquivo utilizando uma sa formatada como da indicado abaixo. FORMATO: [nome] tem [idade] anos e [altura] de altura Tel.: [telefone] 11.10: Escreva um programa que leia um arquivo texto contendo linhas de dados. Em cada linha do arquivo h o nome de um aluno e duas notas. Estes a dados esto separados por ponto e v a rgula. Existe um ponto e v rgula ao nal de cada linha. O formato dos dados e o seguinte: ze sa; 10.0; 9.0; antonio silva: 9.0; 7.0; O programa deve ler estes dados e imprimir os valores lidos, a mdia das e duas notas e se o aluno foi aprovado ou no (media 5). O formato de sa : a da e ze sa 10.0 8.0 9.0 aprovado antonio silva 9.0 7.0 8.0 aprovado 11.11: Faa um programa que receba o nome de um arquivo e gere uma cpia. c o 11.12: Escreva um programa que compare dois arquivos especicados pelo usurio e imprima sempre que os caracteres dos dois arquivos coincidirem. Por a exemplo: arquivo1.c Ol, pessoal! a arquivo2.c Oi, como vai? Neste caso, os caracteres na primeira e dcima primeira posiao so iguais e c a nos dois arquivos. A sa do seu programa deve ser algo como: da 1 - O 11 - a 186

indicando que os primeiros caracteres dos arquivos so iguais (O) bem como o a dcimo primeiro (a) e 11.13: Um arquivo do tipo texto, chamado numeros.txt contm uma e quantidade desconhecida de nmeros reais. Escreva um programa que leia estes u nmeros, os coloque em ordem crescente e depois os grave em um arquivo binrio u a chamado numeros.bin. Observaoes: c (a) Neste exerc a quantidade de dados gravados no arquivo do tipo cio texto desconhecida, portanto, obrigatrio usar um vetor denido e e o com ponteiro. A deniao de um vetor com um nmero constante c u de elementos, mesmo que seja um nmero grande, considerado um u e erro. (b) Para testar o programa crie o arquivo com um editor simples. 11.14: Um programador escreveu os trechos de programas (I) e (II), mostrados nas listagens 11.9 e 11.10, para ler dados inteiros de um arquivo. O n mero de u dados armazenados no arquivo desconhecido. e Listing 11.9: (I) Trecho de programa do problema 14.
while (1) { fscanf (p , " % d " , & i ); i f ( feof ( p )) break ; printf ( " % d \ n " , i ); }

Listing 11.10: (II) Trecho de programa do problema 14.


fscanf (p , " % d " , & i ); while (! feof ( p )) { printf ( " % d \ n " , i ); fscanf (p , " % d " , & i ); }

Qual das opoes abaixo verdadeira? c e (a) Somente o trecho I funciona. (b) Somente o trecho II funciona. (c) Os dois trechos funcionam. (d) Nenhum dos dois trechos funcionam.

187

Cap tulo 12

Problemas Extras
1a Problema:

Ser que Zeno chega l? a a a


Zeno estava perdido em uma regio desrtica da Terra Mdia, ao norte de a a e e Nrnia e a leste do famoso Castelo de Hogwarts. A cidade mais prxima, Forks, a o cava a vrios dias de caminhada. Sedento e faminto ele j perdia as esperanas, a a c quando avistou, a 1000 metros de onde estava, uma fonte jorrando gua. a Zeno comeou a correr, mas chocou-se contra uma barreira mgica que a c a circundava a fonte. No instante em que se chocou contra a barreira ouviu a seguinte mensagem: Forasteiro infeliz, para chegar at a fonte voc deve ter muita pacincia e e e e faa o seguinte: a cada 5 minutos caminhe metade da distncia c a que ainda falta para chegar at a fonte. Desobedea qualquer uma e c destas instrues e a morte ser o seu destino. co a Tarefa A sua tarefa descobrir em quantos minutos Zeno ir chegar a uma distncia e a a da fonte menor do que 103 m. Entrada Este programa no tem entradas. a Sa da O seu programa deve imprimir em quantos minutos Zeno ir chegar na a distncia desejada. a 2a Problema:

Estat stica?

188

Uma medida importante em Estat stica o desvio padro representado na e a equaao 12.2 por . Ele d a medida da variabilidade ou disperso de um c a a conjunto de dados. Alm de ser bastante util muito fcil de ser calculado. e e a Considere um conjunto de N nmeros S = {x0 , x1 , x2 , . . . , xN 1 } cuja mdia u e a vale x. Para este conjunto de dados o desvio padro pode ser calculado pela equaao 12.2. c
N 1 i=0

= =

xi

N 1 N
N 1

(12.1) (xi x)2 (12.2)

i=0

Tarefa A sua tarefa ler um conjunto de dados armazenado em um arquivo do tipo e texto, chamado estatistica.txt e calcular a mdia e depois o desvio e padro deste conjunto. Observe que o tamanho do conjunto desconhecido e a e s pode ser descoberto aps a leitura de todos os dados. o o Neste exerc cio obrigatrio o uso de ponteiros para armazenar o e o vetor. Sa da A sa deve informar os valores obtidos para a mdia e o desvio padro. da e a Exemplo de Arquivo de Entrada e da sa da Arquivo estatistica.txt: 1 2 3 4 5 6 7 8 9 10 3a Problema: Sa na tela: da A media vale 5.500000 O desvio padrao vale 2.872281

Vericando o CPF
Denioes c O CPF o nmero usado pela Receita Federal no Brasil para identicar os e u Contribuintes Pessoas F sicas. O CPF composto por 11 algarismos. Destes 11 e algarismos os dois ultimos so usados para vericar se os primeiros 9 foram dig a itados corretamente. Eles so chamados de algarismos vericadores. Por exema plo, considere o CPF exemplo 12345678909. Este CPF na realidade 123456789, e

189

os algarismos 09 servem para que os programas da Receita Federal veriquem se os 9 primeiros esto corretos e so gerados automaticamente pelos computaa a dores da Receita quando algum se inscreve. O algoritmo de geraao dos dois e c ultimos algarismos descrito a seguir. e Para o primeiro d gito vericador (v1 ), o 0, no nosso exemplo, o algoritmo o seguinte: multiplique o primeiro algarismo por 10, o segundo por 9, e assim e sucessivamente at o nono algarismo do cdigo e some todos estes resultados. e o Neste exemplo ter amos soma1 = (1 10) + (2 9) + (3 8) + + (9 2) Calcule o valor do mdulo 11 de soma1 . Se este valor for 0 ou 1 ento o algarismo o a v1 0, caso contrrio o algarismo v1 o resultado da subtraao 11soma1 % 11. e a e c Para o segundo d gito vericador (v2 ), no nosso caso o 9, o algoritmo o e seguinte: multiplique o primeiro algarismo por 11, o segundo por 10, e assim sucessivamente at o nono algarismo do cdigo e some todos estes resultados. e o Neste exemplo ter amos soma2 = (1 11) + (2 10) + (3 9) + + (9 3) Some este resultado ao dobro do primeiro d gito vericador (soma2 = soma2 + 2 v1 ). Calcule o valor do mdulo 11 desta nova soma2 . Se este valor for 0 o ou 1 ento o algarismo v2 0, caso contrrio o algarismo v2 o resultado da a e a e subtraao 11 soma2 % 11. c Tarefa O programa mostrado na listagem 12.1 faz a vericaao de um CPF fornecido c pelo usurio. Complete as partes que faltam do programa. Observe que o a CPF lido como um vetor de caracteres. Um exemplo de interaao do e c programa com um usurio o seguinte: a e Entre com o cpf. 12345678909 CPF lido: 12345678909 CPF valido. 4a Problema:

Mais perto, mais longe


Tarefa Z S est planejando a sua prxima viagem por Pindorama. No momento e a a o ele gostaria de saber qual so as cidades mais distante e as mais perto da sua. a Para fazer estes clculos ele dispe de um arquivo com as coordenadas de sua a o cidade e das vrias cidades que ele ir visitar a a Entrada A entrada ser feita a partir de um arquivo texto chamado cidades.txt. a A primeira linha deste arquivo um nmero inteiro n dizendo quantas cidades e u h no arquivo. Considere que o nmero mximo de cidades igual a 50. As n a u a e 190

Listing 12.1: Processando o CPF.


#i ncl ude < stdio .h > #i ncl ude < stdlib .h > #i ncl ude < string .h > #de fi ne TAMCPF 11 #de fi ne CERTO 1 #de fi ne ERRADO 0 int int int int int cpfs ( char *); verificaCPF ( char *); digito1 ( char *); digito2 ( char * , i n t ); leCPF ( char *);

i n t main ( i n t argc , char * argv []){ char cpfs [ TAMCPF +1]; i n t tam ; tam = leCPF ( cpfs ); i f ( tam != TAMCPF ) { puts ( " CPF deve ter 11 digitos . " ); return 1; } else { i f ( verificaCPF ( cpfs )) { puts ( " CPF valido . " ); return 0; } else { puts ( " CPF invalido . " ); return 1; } } return 0; } i n t leCPF ( char * cpfs ) { puts ( " Entre com o cpf . " ); fgets ( cpfs , TAMCPF +2 , stdin ); cpfs [ strlen ( cpfs ) -1] = \0 ; printf ( " CPF lido : % s \ n " , cpfs ); return strlen ( cpfs ); } i n t verificaCPF ( char * cpfs ) { i n t dig1 , dig2 ; dig1 = digito1 ( cpfs ); dig2 = digito2 ( cpfs , dig1 ); /* AQUI FALTA O FINAL */ } i n t digito1 ( char * cpfs ) /* AQUI FALTA TODA A } i n t digito2 ( char * cpfs , /* AQUI TAMBEM FALTA } { FUNCAO

*/

i n t dig1 ) { TODA A FUNCAO */

191

linhas seguintes contm pares de nmeros com as coordenadas de cada uma das e u cidades que Z S ir visitar. O primeiro par de coordenadas pertence a cidade e a a onde Z S vive. e a Sa da A sa composta de trs tipos de linhas e deve ser feita no v da e e deo. A primeira linha informa as coordenadas da cidade onde Z S vive. Em seguida e a deve(m) vir as coordenadas da(s) cidade(s) que ca(m) mais perto da cidade de Z S. Aps devem vir a(s) linha(s) que mostra(m) as coordenadas da(s) e a o cidade(s) que ca(m) mais longe da cidade de Z S. O exemplo abaixo mostra e a o formato do arquivo de entrada e o formato da sa na tela. da Exemplo de entrada e sa da Arquivo : 8 2.0 2.0 0.0 0.0 1.0 1.0 3.0 3.0 4.0 4.0 0.0 4.0 4.0 0.0 7.0 7.0 5a Problema: Sa na tela: da Origem: (2.000000, 2.000000) Mais perto: (1.000000, 1.000000) Mais perto: (3.000000, 3.000000) Mais longe: (7.000000, 7.000000)

Produto Escalar

O produto escalar de dois vetores de n dimenses A = (a1 , a2 , . . . , an ) e o B = (b1 , b2 , . . . , bn ), onde (ai , bi ) dado pela equaao 12.3 e c A B = a1 b 1 + a2 b 2 + + an b n Tarefa Escreva um programa que calcule o produto escalar de M pares de vetores, todos em um espao de n dimenses. Neste problema no preciso saber c o a e vetores em C. Entrada A entrada consiste das seguintes linhas de dados: 1. A primeira linha contm um nmero inteiro M que informa o n mero de e u u pares de vetores a serem lidos. 2. A segunda linha contm um nmero n que indica a dimenso de cada um e u a dos vetores. 3. As linhas restantes contm as coordenadas dos pares de vetores. Primeiro e n linhas com as coordenadas do primeiro par, em seguida n linhas com as coordenadas do segundo par e assim sucessivamente. (12.3)

192

As coordenadas de cada par de vetores so fornecidas da seguinte maneira. a Primeiro so fornecidos dois nmeros a1 b1 depois a2 b2 e assim sucessivamente a u at an bn . e Sa da Imprimir os M produtos escalares calculados. Exemplo de entrada: 2 4 1 1.5 2 2 3 3.5 4 4 2.0 1.0 2.0 2.0 2.0 3.0 4.0 2.5 6a Problema: Exemplo de sa da: 32.000000 22.000000

Desconando do sorteio

H pessoas que desconam de tudo, como h pessoas que acreditam em tudo. a a Em Pindorama se joga em tudo, Ultrasena, Maxisena, Lotoesportiva etc, desde que seja o governo que recebe todos os lucros. Um dos jogos a Ultrasena, onde os jogadores devem escolher n meros entre e u 1 e 60. O jogador que acertar os nmeros sorteados ganha uma fraao m u c nima do total que o governo arrecadou. Um jogador desconado acha que o sorteio e viciado e contratou voc para descobrir se isto verdade ou no. e e a Voc deve escrever um programa que leia os N ultimos nmeros inteiros e u sorteados e conte a frequncia com que cada um dos nmeros foi sorteado. e u Entrada: Primeiro o programa deve ler o valor de N . Em seguida o programa deve ler a lista de N nmeros inteiros entre 1 e 60. u Sa da: Imprimir a frequncia com que cada um dos nmeros apareceu. N meros e u u com frequncia zero no devem ser impressos. e a Exemplos de entrada e sa da:

193

Exemplo de entrada 12 8 21 14 5 36 21 43 14 6 21 24 43 7a Problema:

Sa da para o exemplo de entrada 5 = 1 6 = 1 8 = 1 14 = 2 21 = 3 24 = 1 36 = 1 43 = 2

Convertendo para base 2

Escreva um programa que leia uma sequncia de nmeros inteiros na base e u 10 e imprima o nmero convertido para base 2 e a maior sequncia de bits 1 u e que o nmero binrio contm. u a e Considere que o nmero na base 10 menor que 232 1. u e Entrada: A entrada contm vrios casos de teste. Cada linha de um caso de teste e a contm um nmero inteiro menor que 232 1 O programa termina quando o e u usurio fornecer um nmero negativo. a u Sa da: Para cada caso de teste da entrada seu programa deve produzir quatro linhas. Na primeira linha o programa deve imprimir o caso de teste no formato Teste n, onde n nmero do caso de teste comeando em 1. Na segunda linha o e u c nmero convertido para base 2. Zeros ` esquerda no devem ser impressos. Na u a a terceira linha o seu programa deve imprimir a maior sequncia de 1s do n mero e u em binrio. A quarta linha deve ser deixada em branco. a Exemplos de entrada e sa da:

194

Exemplo de entrada 6 25 123456 14 -1

Sa da para o exemplo de entrada Teste 1 110 2 Teste 2 11001 2 Teste 3 11110001001000000 4 Teste 4 1110 3

8a Problema:

Calculando Areas
Voc foi contratado para escrever um programa que calcula reas de c e a rculos. O programa deve imprimir se um c rculo tem rea maior que a rea mdia ou a a e a rea menor ou igual a mdia. e O seu programa deve usar a estrutura (12.2) para representar cada c rculo. Listing 12.2: Estrutura do problema 8.
typedef s t r u c t _CIRCULO { i n t x , y , raio ; } CIRCULO ;

Entrada Os dados estaro organizados da seguinte maneira. Primeiro, a quantidade a N de c rculos, em seguida os dados dos N c rculos, na seguinte ordem: coordenada x, coordenada y, raio raio. Obs. No poss assumir um valor mximo para N , aloque o espao de a e vel a c memria necessrio. o a Sa da O programa de imprimir se um dado c rculo tem rea maior que a mdia a e ou rea menor ou igual a mdia. Considerando que o primeiro c a e rculo recebe o nmero um, o segundo o nmero 2 e assim at o c u u e rculo N , o formato de sa da o seguinte: a palavra Circulo seguida do nmero do c e u rculo e se ele tem rea a maior ou menor ou igual.

195

Exemplo de Entrada: 5 1 1 1 1 2 2 3 1 2 2 2 4 1 1 3

Exemplo de Sa da: Circulo 1 area menor ou igual Circulo 2 area menor ou igual Circulo 3 area menor ou igual Circulo 4 area maior Circulo 5 area maior

9a Problema:

Lucrando com Aes co


Voc foi contratado, pela bolsa de valores de Pindorama, para escrever um e programa que imprima as aoes com o melhor e o pior desempenho durante o c ano de 2325. Entrada A entrada ser lida de um arquivo texto com o nome de acoes.txt. O a arquivo consiste de uma srie de linhas. Em cada linha h o nome da aao e a c seguido pelas cotaoes no dia 01 de janeiro de 2325 e no do dia 31 de dezembro c de 2325. Nenhum nome de empresa ter mais de 20 caracteres. Observe que pode a haver mais de uma pior (melhor) aao. c Sa da A sa dever ser um arquivo do tipo texto, com o nome saida.txt. Neste da a arquivo voc deve indicar a melhor aao e seu rendimento e a pior aao com sua e c c perda. Observe que pode haver mais de uma melhor (pior) aao. c Exemplo de Entrada: lixo 56.00 23.00 bb 100.00 125.00 etai 125.00 110.00 embrair 78.00 156.00 estavel 88.00 88.00 maislixo 56.00 23.00 Exemplo Sa da: Pior acao = lixo, variacao -0.59 Melhor acao = embrair, variacao 1.00 Pior acao = maislixo, variacao -0.59

10a Problema:

Somando Linhas
Escreva um programa que leia de um arquivo texto uma matriz quadrada de nmeros reais. O tamanho mximo da matriz 1000 1000. O nome do u a e arquivo de entrada matrizin.txt. O seu programa deve calcular a soma e de todos os elementos de cada linha. Em seguida o seu programa deve descobrir qual a maior soma e que linha tem soma igual a maior soma. O programa deve e 196

gravar a maior soma e o(s) nmero(s) da(s) linha(s) com soma igual a maior em u um arquivo texto chamado matrizout.txt. Entrada Os dados no arquivo de entrada tem o seguinte formato. A primeira linha do arquivo contm o tamanho da matriz (1 N 1000). Em seguida o arquivo e contm N N nmeros inteiros em um formato livre, ou seja quantidade de e u nmeros por linha do arquivo varivel. u e a Sa da O arquivo de sa tem o seguinte formato. Primeiro o valor da maior soma da das linhas. Em seguida as linhas com soma igual a maior soma. Exemplo de 5 1.0 2.0 3.0 2.0 1.0 2.0 3.0 0.0 0.0 5.0 1.0 0.0 1.0 1.0 1.0 11a Problema: Entrada: 4.0 1.0 0.0 2.0 1.0 2.0 8.0 11.0 6.0 1.0 Exemplo de Sa da: 14.000000 1 2 3

Misturando Dados
Uma tarefa muito comum em computaao misturar dois vetores dados j c e a ordenados para criar um terceiro tambm ordenado. e A sua tarefa escrever um programa que leia os dados de dois vetores e os e misture em um terceiro. Considere que o tamanho mximo de cada um dos dois vetores originais a e desconhecido. Entrada A leitura dos dados vai ser feita da seguinte maneira. Primeiro o programa deve ler o tamanho do primeiro vetor (tam1). Em seguida o programa deve ler tam1 nmeros reais. Aps estas leituras o programa l o tamanho do segundo u o e vetor (tam2). Finalmente, o programa l tam2 nmeros reais. Considerar que e u os dados do primeiro e do segundo vetor esto em ordem crescente. a Sa da Aps misturar os dois vetores em um terceiro o programa deve imprimir os o tam1 + tam2 nmeros reais armazenados no terceiro vetor. Estes dados devem u

197

estar em ordem crescente. Exemplo de Entrada: 5 1.0 4.0 7.0 10.0 12.0 3 1.0 2.0 9.0 Exemplo de Sa da: 1.0 1.0 2.0 4.0 7.0 9.0 10.0 12.0

198

Apndice A e

Tabela ASCII
A tabela ASCII (American Standard for Information Interchange) usada por e grande parte da indstria de computadores para a troca de informaoes e aru c mazenamento de caracteres. Cada caractere representado por um cdigo de e o 8 bits. A Tabela A.1 mostra os cdigos para a tabela ASCII de 7 bits. Existe o uma table estendida para 8 bits que inclui os caracteres acentuados. Para saber qual o cdigo de um caractere na base 10 junte o d e o gito da primeira coluna da tabela com o d gito da primeira linha da tabela. Por exemplo, o cdigo da letra a minscula 97 na base 10. o u e 0 nul nl dc4 rs ( 2 F P Z d n x 1 soh vt nak us ) 3 = G Q [ e o y 2 stx syn sp * 4 H R \ f p z 3 etx cr etb ! + 5 ? I S ] g q { 4 eot so can , 6 @ J T ^ h r 5 enq si em # 7 A K U _ i s } 6 ack dle sub $ . 8 B L V j t ~ 7 bel dc1 esc % / 9 C M W a k u del 8 bs dc2 fs & 0 : D N X b l v 9 ht dc3 gs 1 ; E O Y c m w

0 1 2 3 4 5 6 7 8 9 10 11 12

Tabela A.1: Conjunto de caracteres ASCII Os caracteres de controle listados acima, servem para comunicaao com c perifricos e controlar a troca de dados entre computadores. Eles tm o sige e nicado mostrado na Tabela A.2.

199

Carac nul stx eot ack bs lf so dle dc2 dc4 syn can sub fs rs sp

Descrio ca Caractere nulo Comeo de texto c Fim de transmisso a Conrmaao c Volta um caractere Passa para prxima linha o Passa para prxima pgina o a Shift-out Data line escape Controle de dispositivo Controle de dispositivo Synchronous idle Cancela Substitui Separador de arquivo Separador de registro Espao em branco c

Carac soh etx enq bel ht vt cr si dc1 dc3 nak etb em esc gs us

Descrio ca Comeo de cabealho de transmisso c c a Fim de texto Interroga Sinal sonoro Tabulaao horizontal c Tabulaao vertical c Passa para in da linha cio Shift-in Controle de dispositivo Controle de dispositivo Negativa de conrmaao c Fim de transmisso de um bloco a Fim de meio de transmisso a Escape Separador de grupo Separador de unidade

Tabela A.2: Conjunto de cdigos especiais ASCII e seus signicados o

200

Apndice B e

Palavras Reservadas
Palavras reservadas, tambm as vezes chamadas de palavra chave, servem para e propsitos especiais nas linguagens de programaao. Servem para declarar tipos o c de dados ou propriedades de um objeto da linguagem, indicar um comando alm e de vrias outras funoes. Palavras reservadas no podem ser usadas como nomes a c a de variveis ou funoes. a c asm: Indica que cdigo escrito em assembly ser inserido junto comandos C. o a auto: Modicador que dene a classe de armazenamento padro. a break: Comando usado para sair incondicionalmente dos comandos for, while, switch, and do...while. case: Comando usado dentro do comando switch. char: O tipo de dados mais simples em C, normalmente usado para armazenar caracteres. const: Modicados de dados que impede que uma varivel seja modicada. a Esta palavra no existia nas primeiras verses da linguagem C e foi introa o duzida pelo comit ANSI C. Veja volatile. e continue: Comando que interrompe os comandos de repetiao for , while , c ou do...while e faz que eles passem para a prxima iteraao. o c default: E usado dentro do comando switch para aceitar qualquer valor no a denido previamente com um comando case. do: Comando de repetiao usado em conjunto com o comando while . Pela c deniao do comando o lao sempre executado pelo menos uma vez. c c e double: Tipo de dados usado para armazenar valores de ponto utuante em preciso dupla. a else: Comando que indica um bloco de comandos alternativo que deve ser executado quando a condiao testada pelo comando if foi avaliada como c FALSA. 201

enum: Tipo denido pelo usurio que permite a deniao de variveis que iro a c a a aceitar somente certos valores. extern: Modicador de dados que indica que uma varivel ir ser declarada a a em outra rea do programa. a oat: Tipo usado para armazenar valores de ponto utuante. for: Comando de repetiao que contm inicializaao de variveis, incremento e c e c a seoes condicionais. Em C o comando for um comando de repetiao c e c extremamente ex vel, permitindo inmeras possibilidades. u goto: Comando que causa um pulo para uma posiao do programa marcada c com um rtulo. o if: Comando de testes usado para mudar o uxo do programa baseada em uma deciso VERDADEIRO/FALSO. a int: Tipo de dados usado para armazenar valores inteiros. long: Tipo de dados usado para armazenar valores inteiros com preciso maior a do que o tipo int. Nos computadores modernos o tipo long tem a mesma preciso que o tipo int e so usados 4 bytes. a a register: Especicador de classe de armazenamento que pede que, caso seja poss vel, uma varivel deve ser armazenada nos registradores do procesa sador. return: Comando que causa o uxo de instruoes do programa abandonar a c funao em execuao e retornar para a funao que chamou. Tambm pode c c c e ser usado para retornar um unico valor. short: Tipo de dados usado para armazenar valores inteiros em preciso menor a do que o tipo int. Neste tipo 2 bytes so usados para armazenar os dados. a signed: Modicador usado para indicar que uma varivel pode armazenar tanto a valores positivos como negativos. sizeof: Operador que retorna o tamanho em bytes do item fornecido. static: Modicador usado para signicar que o compilador deve preparar o cdigo de forma a reter o valor da varivel. o a struct: Usado para combinar C variveis de tipos diferentes na mesma estrua tura. switch: Comando de desvio usado para permitir que o uxo do programa possa ser mudado para vrias direoes diferentes. Usado em conjunto com o a c comando case. typedef: Modicador usado para criar novos nomes para tipos j existentes. a union: Palavra chave usada para permitir mltiplas variveis partilharem o u a mesmo espao na memria. c o

202

unsigned: Modicador usado para signicar que uma varivel conter somente a a valores positivos. void: Palavra usada para signicar que ou a funao no retorna nada ou que c a um ponteiro deve ser considerado genrico ou ser capaz de apontar para e qualquer tipo de dados. volatile: Modicador que signica que uma varivel pode ser alterada. a while: Comando de teste que executa uma seao de cdigo enquanto uma c o condiao retorna VERDADEIRO. c Em adiao a estas as seguintes palavras so reservadas em C++: c a catch, inline, template, class, new, this, delete, operator, throw, except, private, try, finally, protected, virtual, friend, public. Caso queira escrever programas que possam ser convertidas para a linguagem C++ aconselhvel no us-las. e a a a

203

Bibliograa
[1] KERNIGHAN, B. W.; RITCHIE, D. M. The C Programming Language. Englewood Clis, NJ, USA: Prentice-Hall, Inc, 1978. [2] SCHILDT, H. C Completo e Total. So Paulo, Brasil: Makron Books do a Brasil Editora, 1997. [3] OLIVEIRA, U. de. Programando em C, Fundamentos. Rio de Janeiro, Brasil: Editora Cincia Moderna, 2009. e [4] KNUTH, D. E. The Art of Computer Programming: Fundamental Algorithms - vol. 1. Massachusetts, USA: Addison-Wesley Publishing Company, Inc, 1973.

204

Indice
a baco, 21 a lgebra booleana, 51 C, 34 abertura de arquivo, 179 algoritmo, 32, 41 Analytical Engine, 23 arquivo, 179 abrir arquivo, 180 fechar arquivo, 181 m de arquivo, 182 assembler, 34 assembly, 33 atribuiao, 70 c atribuioes, 52 c Babbage, 22 base 2, 31 Basic, 34 BIOS, 30 bit, 31 byte, 31 C++, 34 cadeia de caractere, 68 char, 61 chipset, 29 circuitos integrados, 26 Cobol, 34 comandos de controle, 53 comandos de repetiao, 54 c compilador, 35 compiladores, 34 constante caractere, 67 constante em ponto-utuante, 66 constante hexadecimal, 65 constante octal, 64 constantes, 61, 62 declaraao de variveis, 69 c a Delphi, 34 depuraao, 35 c Dierence Engine, 22 double, 62 DRAM, 30 EDSAC, 26 EEPROM, 30 endereos de memria, 30 c o ENIAC, 25 EPROM, 30 erros de compilaao, 35 c Exabyte, 32 nal de linha, 177 Flash memory, 31 uxo de dados, 177 uxo binrio, 178 a uxo de texto, 177 Fluxograma, 44, 45 Fortran, 34 gcc, 37 George Boole, 51 Gigabyte, 32 hardware, 27 Harvard Mark I, 24 IDE, 37 int, 61 Integrated Development Environment, 37 Java, 34 Kilobyte, 32 linguagem de alto n vel, 34 linguagem de mquina, 33 a linguagem intermediria, 36 a Linguagem Natural, 44 linguagem natural, 44 205

linguagens interpretadas, 35 link edition, 35 Lisp, 34 long, 62 Megabyte, 32 memria, 29 o memria cache, 29 o memria principal, 29 o microcomputadores, 28 microprocessador, 28 MINGW, 37 montar, 34 Moore, 19 null, 68 palavra de memria, 31 o Pascal, 34 Pascalina, 22 perifricos, 28, 32 e Petabyte, 32 pipelining, 27 Prolog, 34 PROM, 30 pseudo-cdigo, 44 o Pseudo-linguagem, 44 pseudo-linguagem, 45 RAM, 30 registradores, 29 ROM, 30 signed, 62 sistema operacional, 36 software, 32 soroban, 21 string, 68 Terabyte, 32 text stream, 177 tipos de dados, 61 UCP, 27 Unidade Central de Processamento, 27 Unidade de Controle, 27 Unidade de Entrada e Sa da, 27 Unidade Lgica e Aritmtica, 27 o e unsigned, 62 variveis, 61 a

varivel, 68 a VLSI, 27 void, 62 von Neumann, 26, 47 Z1, 24 Zuze, 24

206

Anda mungkin juga menyukai