Em Construo
v0.003.11
18 de fevereiro de 2016
Sumrio
1 Introduo 13
1.1 Sucessos e Fracassos da Computao . . . . . . . . . . . . . . . . 13
1.2 Um Pouco da Histria da Computao . . . . . . . . . . . . . . . 15
1.2.1 O Incio . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.2.2 A Era Moderna . . . . . . . . . . . . . . . . . . . . . . . . 16
1.2.3 O Desenvolvimento durante as Grandes Guerras . . . . . 18
1.2.4 As Geraes . . . . . . . . . . . . . . . . . . . . . . . . . . 20
1.3 O Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.3.1 Microcomputadores . . . . . . . . . . . . . . . . . . . . . 22
1.3.2 Memrias . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
1.3.3 Bits e Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . 25
1.3.4 Perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.4 O Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
1.5 Um programa em C . . . . . . . . . . . . . . . . . . . . . . . . . 32
2 Algoritmos 35
2.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
2.2 Primeiros Passos . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.3 Representao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.3.1 Linguagem Natural . . . . . . . . . . . . . . . . . . . . . . 38
2.3.2 Fluxogramas . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.3.3 Pseudo-Linguagem . . . . . . . . . . . . . . . . . . . . . . 39
2.4 Modelo de von Neumann . . . . . . . . . . . . . . . . . . . . . . . 41
2.5 Estruturas Bsicas de Algoritmos . . . . . . . . . . . . . . . . . . 42
2.5.1 Comandos de leitura . . . . . . . . . . . . . . . . . . . . . 43
2.5.2 Comandos de escrita . . . . . . . . . . . . . . . . . . . . . 43
2.5.3 Expresses . . . . . . . . . . . . . . . . . . . . . . . . . . 44
2.5.4 Comandos de atribuio . . . . . . . . . . . . . . . . . . . 46
1
2.5.5 Comandos de controle . . . . . . . . . . . . . . . . . . . . 47
2.5.6 Comandos de repetio . . . . . . . . . . . . . . . . . . . 48
2.6 Exemplos de Algoritmos . . . . . . . . . . . . . . . . . . . . . . . 49
2
5 Operadores e Expresses 80
5.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
5.2 Operador de Atribuio . . . . . . . . . . . . . . . . . . . . . . . 80
5.3 Operadores Aritmticos . . . . . . . . . . . . . . . . . . . . . . . 81
5.4 Operadores Relacionais e Lgicos . . . . . . . . . . . . . . . . . . 82
5.4.1 Operadores Relacionais . . . . . . . . . . . . . . . . . . . 82
5.4.2 Operadores Lgicos . . . . . . . . . . . . . . . . . . . . . 82
5.5 Operadores com Bits . . . . . . . . . . . . . . . . . . . . . . . . . 85
5.6 Operadores de Atribuio Composta . . . . . . . . . . . . . . . . 86
5.7 Operador vrgula . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.8 Operador sizeof() . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.9 Converso de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . 87
5.10 Regras de Precedncia . . . . . . . . . . . . . . . . . . . . . . . . 89
6 Comandos de Controle 92
6.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.2 Blocos de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.3 Comandos de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . 92
6.3.1 Comando if . . . . . . . . . . . . . . . . . . . . . . . . . . 93
6.3.2 Comando switch . . . . . . . . . . . . . . . . . . . . . . . 94
6.3.3 Comando Ternrio . . . . . . . . . . . . . . . . . . . . . . 97
6.4 Laos de Repetio . . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.4.1 Comando for . . . . . . . . . . . . . . . . . . . . . . . . . 97
6.4.2 Comando while . . . . . . . . . . . . . . . . . . . . . . . 102
6.4.3 Comando do-while . . . . . . . . . . . . . . . . . . . . . 103
6.5 Comandos de Desvio . . . . . . . . . . . . . . . . . . . . . . . . . 104
6.5.1 Comando break . . . . . . . . . . . . . . . . . . . . . . . 104
6.5.2 Comando continue . . . . . . . . . . . . . . . . . . . . . 104
6.5.3 Comando goto . . . . . . . . . . . . . . . . . . . . . . . . 104
6.5.4 Funo exit() . . . . . . . . . . . . . . . . . . . . . . . . 105
6.5.5 Comando return . . . . . . . . . . . . . . . . . . . . . . . 105
3
8 Funes 125
8.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
8.2 Forma Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
8.3 Prottipos de Funes . . . . . . . . . . . . . . . . . . . . . . . . 127
8.4 Escopo de Variveis . . . . . . . . . . . . . . . . . . . . . . . . . 127
8.4.1 Variveis Locais . . . . . . . . . . . . . . . . . . . . . . . 128
8.4.2 Variveis Globais . . . . . . . . . . . . . . . . . . . . . . . 130
8.5 Parmetros Formais . . . . . . . . . . . . . . . . . . . . . . . . . 131
8.5.1 Passagem de Parmetros por Valor . . . . . . . . . . . . . 131
8.5.2 Passagem de Parmetros por Referncia . . . . . . . . . . 132
8.5.3 Passagem de Vetores e Matrizes . . . . . . . . . . . . . . . 132
8.6 O Comando return . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.7 Recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.7.1 Como pensar recursivamente? . . . . . . . . . . . . . . . . 138
8.7.2 O que faz recurso trabalhar? . . . . . . . . . . . . . . . . 139
8.8 Argumentos - argc e argv . . . . . . . . . . . . . . . . . . . . . . 140
9 Ponteiros 145
9.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9.2 Operaes com Ponteiros . . . . . . . . . . . . . . . . . . . . . . 146
9.2.1 Declarao de Ponteiros . . . . . . . . . . . . . . . . . . . 146
9.2.2 Os Operadores Especiais para Ponteiros . . . . . . . . . . 147
9.2.3 Atribuio de Ponteiros . . . . . . . . . . . . . . . . . . . 148
9.2.4 Incrementando e Decrementando Ponteiros . . . . . . . . 150
9.2.5 Comparao de Ponteiros . . . . . . . . . . . . . . . . . . 151
9.3 Ponteiros e Vetores . . . . . . . . . . . . . . . . . . . . . . . . . . 152
9.4 Ponteiros e Cadeias de Caracteres . . . . . . . . . . . . . . . . . 153
9.5 Alocao Dinmica de Memria . . . . . . . . . . . . . . . . . . . 153
9.6 Ponteiros e Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . 155
9.7 Vetores de Ponteiros . . . . . . . . . . . . . . . . . . . . . . . . . 158
9.8 Ponteiros para Ponteiros . . . . . . . . . . . . . . . . . . . . . . . 159
10 Estruturas 168
10.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
10.2 Definies Bsicas . . . . . . . . . . . . . . . . . . . . . . . . . . 168
10.3 Atribuio de Estruturas . . . . . . . . . . . . . . . . . . . . . . . 171
10.4 Matrizes de Estruturas . . . . . . . . . . . . . . . . . . . . . . . . 171
10.5 Estruturas e Funes . . . . . . . . . . . . . . . . . . . . . . . . . 172
10.6 Ponteiros para Estruturas . . . . . . . . . . . . . . . . . . . . . . 172
4
11 Entrada e Sada por Arquivos 181
11.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
11.2 Fluxos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
11.2.1 Fluxos de Texto . . . . . . . . . . . . . . . . . . . . . . . 181
11.2.2 Fluxo Binrio . . . . . . . . . . . . . . . . . . . . . . . . . 182
11.2.3 Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . 182
11.3 Funes de Entrada e Sada . . . . . . . . . . . . . . . . . . . . . 183
11.4 Incio e Fim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183
11.4.1 Abrindo um Arquivo . . . . . . . . . . . . . . . . . . . . . 184
11.4.2 Fechando um Arquivo . . . . . . . . . . . . . . . . . . . . 185
11.4.3 Fim de Arquivo . . . . . . . . . . . . . . . . . . . . . . . . 185
11.4.4 Volta ao Incio . . . . . . . . . . . . . . . . . . . . . . . . 186
11.5 Lendo e Escrevendo Caracteres . . . . . . . . . . . . . . . . . . . 186
11.6 Testando Erros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
11.7 Lendo e Escrevendo Cadeias de Caracteres . . . . . . . . . . . . . 187
11.8 Entrada e Sada Formatada . . . . . . . . . . . . . . . . . . . . . 190
11.9 Lendo e Escrevendo Arquivos Binrios . . . . . . . . . . . . . . . 193
5
Lista de Figuras
1.1 Fotografia de um circuito integrado de microprocessador Pentium. 14
1.2 Imagem de um baco. . . . . . . . . . . . . . . . . . . . . . . . . 15
1.3 Blaise Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.4 Charles Babbage . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.5 Fotografia da Difference Engine . . . . . . . . . . . . . . . . . . . 17
1.6 Computador Eniac . . . . . . . . . . . . . . . . . . . . . . . . . . 19
1.7 Diagrama Bsico de um Computador Digital . . . . . . . . . . . 22
1.8 Nveis de hierarquia da memria de um computador. . . . . . . . 23
1.9 Tamanho de Bits, Bytes e Palavras . . . . . . . . . . . . . . . . . 25
1.10 Ciclo de desenvolvimento de um programa. . . . . . . . . . . . . 30
6
Lista de Tabelas
1.1 Transistores por circuito integrado em microprocessadores . . . . 15
1.2 Tempo de execuo das instrues aritmticas no ENIAC . . . . 20
1.3 Exemplos de Microprocessadores . . . . . . . . . . . . . . . . . . 23
1.4 Abreviaes usadas em referncias s memrias. . . . . . . . . . . 26
1.5 Exemplos de perifricos . . . . . . . . . . . . . . . . . . . . . . . 26
7
11.1 Exemplos de funes de Entrada e Sada. . . . . . . . . . . . . . 184
8
Lista de Algoritmos
2.1 Exemplo de Algoritmo. . . . . . . . . . . . . . . . . . . . . . . . . 37
2.2 Algoritmo para resolver uma equao do primeiro grau. . . . . . . 37
2.3 Algoritmo para calcular a mdia das notas de um aluno. . . . . . 39
2.4 Algoritmo para calcular a maior nota de um grupo de notas. . . . 41
2.5 Modelo de memria e funcionamento de um algoritmo . . . . . . . 42
2.6 Comando se em pseudo-linguagem . . . . . . . . . . . . . . . . . . 47
2.7 Algoritmo para decidir o que fazer no domingo. . . . . . . . . . . 48
2.8 Algoritmo para decidir se deve levar um guarda-chuva. . . . . . . 48
2.9 Algoritmo para ler 10 nmeros e imprimir se so pares ou no. . . 50
2.10 Algoritmo para ler nmeros e imprimir se so pares ou no. A quantidade de nmeros a ser lida de
2.11 Algoritmo para calcular a maior nota de uma turma de 25 alunos. 52
2.12 Algoritmo para calcular a nota mdia de uma turma de 25 alunos. 52
2.13 Algoritmo para calcular a maior temperatura do ano. . . . . . . . 53
2.14 Algoritmo do exerccio 11. . . . . . . . . . . . . . . . . . . . . . . 55
2.15 Algoritmo do exerccio 11. . . . . . . . . . . . . . . . . . . . . . . 55
9
Listings
1.1 Exemplo de Programa em C. . . . . . . . . . . . . . . . . . . . . 32
4.1 Exemplo de impresso de resultados . . . . . . . . . . . . . . . . 69
4.2 Exemplo de justificao de resultados. . . . . . . . . . . . . . . . 71
4.3 Exemplo de uso de especificador de preciso. . . . . . . . . . . . 72
4.4 Exemplo de uso de scanf. . . . . . . . . . . . . . . . . . . . . . 74
4.5 Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . 75
4.6 Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . 76
4.7 Exemplo de uso de printf e scanf na leitura de cadeias. . . . . 76
4.8 Exemplo de uso de puts e gets na leitura de cadeias. . . . . . . 78
5.1 Exemplo de operadores de deslocamento. . . . . . . . . . . . . . 86
5.2 Exemplo do operador sizeof. . . . . . . . . . . . . . . . . . . . 88
5.3 Variveis da questo 9. . . . . . . . . . . . . . . . . . . . . . . . 91
6.1 Exemplo de comandos if. . . . . . . . . . . . . . . . . . . . . . . 94
6.2 Programas com ifs em escada e aninhados. . . . . . . . . . . . . 95
6.3 Exemplo de switch. . . . . . . . . . . . . . . . . . . . . . . . . . 98
6.4 Exemplo de comando ternrio. . . . . . . . . . . . . . . . . . . . 99
6.5 Exemplo de comando for. . . . . . . . . . . . . . . . . . . . . . . 100
6.6 Exemplo de comando for com testes sobre outras variveis. . . . 100
6.7 Exemplo de comando for sem alterao da varivel de controle. 101
6.8 Exemplo de comando for sem teste de fim. . . . . . . . . . . . . 101
6.9 Comando for aninhados. . . . . . . . . . . . . . . . . . . . . . . 102
6.10 Comando while com uma funo. . . . . . . . . . . . . . . . . . 103
6.11 Programa do exercicio 17. . . . . . . . . . . . . . . . . . . . . . 108
7.1 Exemplo de vetores. . . . . . . . . . . . . . . . . . . . . . . . . . 110
7.2 Produto escalar de dois vetores. . . . . . . . . . . . . . . . . . . 111
7.3 Ordenao pelo mtodo da bolha. . . . . . . . . . . . . . . . . . 113
7.4 Exemplos de funes para cadeias. . . . . . . . . . . . . . . . . . 115
7.5 Leitura de uma matriz. . . . . . . . . . . . . . . . . . . . . . . . 116
10
7.6 Multiplicao de duas matrizes. . . . . . . . . . . . . . . . . . . 118
7.7 Leitura de um vetor de nomes. . . . . . . . . . . . . . . . . . . . 119
7.8 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 120
7.9 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 121
7.10 Programa do exercicio 14. . . . . . . . . . . . . . . . . . . . . . 124
8.1 Exemplo de prottipos. . . . . . . . . . . . . . . . . . . . . . . . 128
8.2 Exemplos de variveis locais. . . . . . . . . . . . . . . . . . . . . 129
8.3 Definio de varivel dentro de um bloco. . . . . . . . . . . . . . 129
8.4 Definio de varivel global. . . . . . . . . . . . . . . . . . . . . 130
8.5 Exemplo de passagem por valor. . . . . . . . . . . . . . . . . . . 131
8.6 Uso indevido de variveis locais. . . . . . . . . . . . . . . . . . . 132
8.7 Passagem de vetor com dimenses. . . . . . . . . . . . . . . . . 133
8.8 Passagem de vetores sem dimenses. . . . . . . . . . . . . . . . 135
8.9 Fatorial calculado no recursivamente. . . . . . . . . . . . . . . 136
8.10 Fatorial calculado recursivamente. . . . . . . . . . . . . . . . . . 136
8.11 Chamada recursiva direta. . . . . . . . . . . . . . . . . . . . . . 137
8.12 Chamada recursiva indireta. . . . . . . . . . . . . . . . . . . . . 137
8.13 Funo recursiva para calcular xn . . . . . . . . . . . . . . . . . . 137
8.14 Chamada recursiva com cauda. . . . . . . . . . . . . . . . . . . 138
8.15 Chamada recursiva sem cauda. . . . . . . . . . . . . . . . . . . . 138
8.16 Soma de vetor recursiva. . . . . . . . . . . . . . . . . . . . . . . 139
8.17 Uso de argc e argv. . . . . . . . . . . . . . . . . . . . . . . . . . 141
8.18 Programa do exerccio 8. . . . . . . . . . . . . . . . . . . . . . . 143
8.19 Programa do problema 9. . . . . . . . . . . . . . . . . . . . . . . 144
9.1 Exemplo de atribuio de ponteiros. . . . . . . . . . . . . . . . . 149
9.2 Exemplos de operaes com ponteiros. . . . . . . . . . . . . . . 150
9.3 Exemplo de subtrao de ponteiros. . . . . . . . . . . . . . . . . 151
9.4 Exemplo de comparao de ponteiros. . . . . . . . . . . . . . . . 151
9.5 Exemplo de alteraes invlidas sobre ponteiros. . . . . . . . . . 152
9.6 Exemplo de notaes de vetores. . . . . . . . . . . . . . . . . . . 152
9.7 Exemplo de ponteiro varivel. . . . . . . . . . . . . . . . . . . . 153
9.8 Exemplo de ponteiro para cadeia de caracteres. . . . . . . . . . 154
9.9 Exemplo de cpia de cadeias de caracteres. . . . . . . . . . . . . 154
9.10 Exemplo de uso de
allo
e free. . . . . . . . . . . . . . . . . . 155
9.11 Exemplo de uso de mallo
. . . . . . . . . . . . . . . . . . . . . . 156
9.12 Exemplo de matriz normal sem uso de ponteiros. . . . . . . . . 157
9.13 Exemplo de matriz mapeada em um vetor. . . . . . . . . . . . . 157
11
9.14 Exemplo de uso de vetor de ponteiros. . . . . . . . . . . . . . . 158
9.15 Exemplo de uso de ponteiros para ponteiros. . . . . . . . . . . . 160
9.16 Exemplo de uso de ponteiros para ponteiros usando funes. . . 161
9.17 Continuao do exemplo 9.16. . . . . . . . . . . . . . . . . . . . 162
9.18 Programa do exercicio 11. . . . . . . . . . . . . . . . . . . . . . 164
9.19 Programa do exercicio 12. . . . . . . . . . . . . . . . . . . . . . 165
9.20 Listagem do exerccio 13. . . . . . . . . . . . . . . . . . . . . . . 166
9.21 Programa do exerccio 14. . . . . . . . . . . . . . . . . . . . . . 167
10.1 Definio de uma estrutura. . . . . . . . . . . . . . . . . . . . . . 169
10.2 Atribuio de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 171
10.3 Ordenao de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 173
10.4 Passando elementos para funes. . . . . . . . . . . . . . . . . . 174
10.5 Passagem de estruturas para funes. . . . . . . . . . . . . . . . 174
10.6 Funo que ordena estruturas. . . . . . . . . . . . . . . . . . . . 175
10.7 Alocao de espao para estruturas. . . . . . . . . . . . . . . . . 177
10.8 Alocao de espao para vetores de estruturas. . . . . . . . . . . 178
10.9 Listagem do exercicio 3. . . . . . . . . . . . . . . . . . . . . . . 179
11.1 Uso da funo feof(). . . . . . . . . . . . . . . . . . . . . . . . 186
11.2 Exemplo de leitura e escrita de caracteres. . . . . . . . . . . . . 188
11.3 Exemplo de leitura e escrita de caracteres. . . . . . . . . . . . . 189
11.4 Uso da funo ferror(). . . . . . . . . . . . . . . . . . . . . . . 190
11.5 Exemplo de leitura e escrita de cadeias de caracteres. . . . . . . 191
11.6 Exemplo de leitura e escrita de dados formatados. . . . . . . . . 192
11.7 Exemplo de leitura e escrita na forma binria. . . . . . . . . . . 193
11.8 Exemplo de leitura e escrita de estruturas. . . . . . . . . . . . . 195
11.9 (I) Trecho de programa do problema 14. . . . . . . . . . . . . . 198
11.10(II) Trecho de programa do problema 14. . . . . . . . . . . . . . 198
12.1 Processando o CPF. . . . . . . . . . . . . . . . . . . . . . . . . . 202
12.2 Estrutura do problema 8. . . . . . . . . . . . . . . . . . . . . . . 206
12
Captulo 1
Introduo
13
Figura 1.1: Fotografia de um circuito integrado de microprocessador Pentium.
14
Ano Processador Transistores
1971 Intel 4004 2.250
1972 Intel 8008 2.500
1974 Motorola 6800 4,100
1974 Intel 8080 5.000
1982 Intel 80286 120.000
1984 Motorola 68020 190,000
1985 Intel 80386 275.500
1989 Intel 80486 DX 1.180.000
1993 Intel Pentium 3.100.000
1997 Intel Pentium II 7.500.000
1997 AMD K6 8,800,000
1999 Intel Pentium III 24.000.000
2000 Intel Pentium 4 42.000.000
2009 AMD Six-core Opteron 2400 904,000,000
2011 Intel Quad-core + GPU Core i7 1,160,000,000
2012 AMD Quad-core + GPU Trinity 1,303,000,000
2014 Intel 18-core Xeon Haswell-E5 5,560,000,000
2015 IBM z13 Storage Controller 7,100,000,000
15
encontraram os restos de um mecanismo, parecido com um relgio, com aproxi-
madamente 2000 anos de idade. O mecanismo, de grande complexidade, parece
ser um dispositivo para calcular os movimentos de estrelas e planetas.
Pascal recebeu uma patente do rei da Frana, o que lhe possibilitou o lana-
mento de sua mquina no mercado. A comercializao das calculadoras no foi
satisfatria devido a seu funcionamento pouco confivel, apesar dele ter cons-
trudo cerca de 50 verses. As mquinas de calcular, derivadas da Pascalina,
como ficou conhecida sua mquina, ainda podiam ser encontradas em lojas at
alguns poucos anos atrs. Antes de morrer, aos 39 anos, em 1662, Pascal que
contribura em vrios campos da Cincia, ainda teve tempo de criar uma vari-
ante de sua mquina, a caixa registradora.
Em 1666, Samuel Morland adaptou a calculadora de Pascal para resolver
multiplicaes por meio de uma srie de somas sucessivas. Independentemente,
em 1671 Leibniz projetou uma outra calculadora que somava e multiplicava.
Esta calculadora s foi concluda em 1694.
O primeiro computador de uso especfico comeou a ser projetado em 1819
e terminou em 1822, ou seja, h mais de 180 anos atrs, pelo britnico Char-
les (1791-1871, Figura 1.4), que o batizou de Difference Engine (Figura 1.5).
A motivao de Babbage era resolver polinmios pelo mtodo das diferenas.
Naquele tempo as tbuas astronmicas e outras tabelas eram calculadas por
humanos, em mtodos tediosos e repetitivos.
16
Figura 1.4: Charles Babbage
Em 1823, ele iniciou o projeto de construir uma outra mquina mais avan-
ada e capaz de calcular polinmios de at sexta ordem. Ele esperava terminar
esta mquina em trs anos, mas a construo se arrastou at 1834. Este projeto
que no foi completado, usou dinheiro do governo ingls e possivelmente a maior
parte da fortuna pessoal de Babbage. A mquina, inteiramente mecnica, teria
as seguintes caractersticas:
Arredondamento automtico;
Preciso dupla;
Alarmes para avisar fim de clculo;
Impresso automtica de resultados em placas de cobre.
17
Memria para 1000 destes nmeros (165000 bits);
Controle por meio de cartes perfurados das operaes e endereos dos
dados;
Tempo de soma e subtrao igual a 1 segundo; tempo de multiplicao e
diviso igual a 1 minuto;
Sub-rotinas;
Arredondamento automtico e deteco de transbordo (overflow );
Na Alemanha
18
Nos Estados Unidos
Ele gerava tanto calor que teve de ser instalado em um dos poucos espaos
da Universidade que possua sistemas de refrigerao forada. Mais de 19000
vlvulas, eram os elementos principais dos circuitos do computador. Ele tam-
bm tinha quinze mil rels e centenas de milhares de resistores, capacitores e
indutores. Toda esta parafernlia eletrnica foi montada em quarenta e dois
painis com mais 2,70 metros de altura, 60 centmetros de largura e 30 cent-
metros de comprimento, montados na forma da letra U. Uma leitora de cartes
perfurados e uma perfuradora de cartes eram usados para entrada e sada de
dados.
Os tempos de execuo do ENIAC so mostrados na Tabela 1.2. Compare
estes tempos com os tempos dos computadores atuais que esto na ordem de
nano segundos, ou 109 segundos.
Em 1939 John Vincent Atanasoff e Clifford E. Berry, na Universidade Esta-
dual de Iowa construram um prottipo de computador digital eletrnico, que
usa aritmtica binria. Em 19 de outubro de 1973, o juiz federal Earl R. Larson
19
Operao Tempo
soma 200 s
multiplicao 2,8 ms
diviso 6,0 ms
assinou uma deciso, em seguida a uma longa batalha judicial, que declarava
a patente do ENIAC de Mauchly e Eckert invlida e atribua a Atanasoff a
inveno computador eletrnico digital, o ABC ou Atanasoff-Berry Computer.
Na Inglaterra
Jnos von Neumann, emigrante hngaro que vivia nos EUA, sugeriu que a
memria do computador deveria ser usada para armazenar as instrues do
computador de maneira codificada, o conceito de programa armazenado. Esta
idia foi fundamental para o progresso da computao. Os primeiros computa-
dores, como o ENIAC, eram programados por fios que os cientistas usavam para
conectar as diversas partes. Quando um programa terminava, estes cientistas
trocavam os fios de posio de acordo com a nova tarefa a ser executada. Com o
programa armazenado na memria, juntamente com os dados, no era mais ne-
cessrio interromper as atividades. Carregava-se o programa na memria, uma
tarefa extremamente rpida, junto com os dados e dava-se partida no programa.
Ao trmino da execuo do programa passava-se imediatamente para a prxima
tarefa sem interrupes para troca de fios.
Em 1949, na Inglaterra, dois computadores que usavam a memria para
armazenar tanto programas como dados foram lanados. Na Universidade de
Cambridge foi lanado o EDSAC, (Electronic Delay Storage Automatic Calcula-
tor) e em Manchester o computador chamado de Manchester Mark I. O EDSAC
considerado o primeiro computador de programa armazenado a ser lanado.
Curiosamente, a Universidade de Manchester reivindica que o primeiro compu-
tador de programa armazenado foi o chamado Baby, um prottipo do Mark I,
que comeou a operar onze meses antes do EDSAC.
Outro fato curioso em relao Inglaterra e que foi divulgado recentemente
relata que um computador chamado COLOSSUS entrou em operao secre-
tamente na Inglaterra em 1943. Este computador foi usado para auxiliar na
quebra dos cdigos de criptografia alemes durante a segunda grande guerra.
1.2.4 As Geraes
Costumava-se dividir os projetos de computadores em geraes. Hoje em dia
como a taxa de evoluo muito grande no se usa mais este tipo de termino-
logia. No entanto interessante mencionar estas divises.
20
Segunda Gerao: Os computadores da segunda gerao foram construdos
com transistores, os quais tinham a vantagem de serem mais compactos e
consumirem muito menos energia. Por gerarem menos calor eram mqui-
nas mais confiveis.
Terceira Gerao: Com o advento dos circuitos integrados, que so compo-
nentes em que vrios transistores so construdos em uma mesma base
de semicondutor, chegamos aos computadores de terceira gerao. Com
a integrao o tamanho dos computadores e seu consumo diminuiu ainda
mais e aumentou a capacidade de processamento.
Quarta Gerao: Os computadores de quarta gerao utilizavam circuitos
com a tecnologia (Very Large Scale Integration), que permitia uma escala
de integrao de transistores muito grande.
1.3 O Hardware
O hardware corresponde aos circuitos eletrnicos e componentes mecnicos que
compem o computador. Um tpico 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
prprio nome diz, a unidade onde os dados so processados, ou seja alterados,
no computador. Ou seja, dentro das UCPs os dados so somados, subtrados
etc. A UCP tambm controla a movimentao dos dados dentro de todo o
sistema. Os mdulos que constituem a UCP so os seguintes:
21
Unidade
Unidade de
de Entrada
Controle e
Sada
Unidade
Arimtica Unidade
Central
de
Processamento
1.3.1 Mi
ro
omputadores
Uma UCP integrada em um nico circuito (chip) comumente chamada de
microprocessador . Os microprocessadores atuais incluem outros circuitos que
normalmente ficavam fora da UCP, tais como processadores de ponto flutuante
e memrias cache. Alguns exemplos de microprocessadores so mostrados na
Tabela 1.3
Usualmente se chama de computador, o processador mais os seus perifricos
e os sistemas para controlar estes perifricos, ou seja todo o sistema de proces-
samento de dados. Os perifricos so os dispositivos usados para fazer a entrada
e sada dos dados que sero processados.
Os microcomputadores so computadores baseados em microprocessa-
dores. As assim chamadas placas me dos microprocessadores atuais incluem
diversos componentes que formam o microcomputador. Por exemplo, uma placa
me pode incluir o microprocessador e seus circuitos de suporte, que, no con-
junto so conhecidos como o chipset. Alm disso a placa me pode incluir tam-
bm a memria principal e as placas de controle de perifricos, como a placa de
22
Microprocessador Empresa
Arquitetura Intel X86 Intel, AMD
PowerPC Consrcio Apple/IBM/Motorola
Power IBM
MIPS MIPS Technologies
ARM ARM Technologies
SPARC SUN
1.3.2 Memrias
Os dados no computador podem ser armazenados em diversos nveis de memria
semicondutoras ou em perifricos (discos, fitas, etc). Quanto mais rpida a
memria, usualmente mais cara ela . A idia por traz da separao em nveis
colocar mais perto do processador, em memrias rpidas e mais caras, os
dados que o processador ir precisar mais freqentemente. A medida que vamos
nos afastando do processador as memrias vo, ao mesmo tempo, ficando mais
baratas, aumentando de capacidade e diminuindo de velocidade. A Figura 1.8
ilustra esta hierarquia.
PROCESSADOR
MEMRIA
DISCO
CACHE
REGISTRADORES
23
Em alguns computadores os discos esto sendo substitudos por memrias se-
micondutoras.
Para acelerar o acesso aos dados freqentemente usados, os computadores
dispem de memrias mais rpidas, porm de menor capacidade, que ficam en-
tre os registradores e a memria principal. Estas funcionam como as bolsas ou
carteiras em que carregamos documentos e outros itens que precisamos freqen-
temente. Este tipo de memria conhecido como memria cache. O cache
opera de forma invisvel para o processador. Ao pedir um dado para memria,
circuitos especiais verificam se este dado est no cache, caso esteja, ele repas-
sado para o processador. Para o processador o que aconteceu que a memria
entregou o dado com uma rapidez maior do que o normal.
Uma memria como se fosse uma srie de cofres numerados capazes de
armazenar os dados, como est ilustrado na Figura 2.3. Os dados e instrues
na memria so apontados ou referenciados por estes nmeros, conhecidos como
endereos. Ou seja, para ler um dado da memria necessrio fornecer um
endereo para que a memria possa encontrar e devolver o contedo pedido. Isto
similar ao o que ocorre quando enviamos uma carta, o endereo faz com que o
carteiro saiba onde ele deve entregar a correspondncia. Em operao normal,
toda vez que o processador precisa de um dado ele envia um pedido de leitura
memria junto com o endereo da memria onde o dado est. Nas escritas
o processador envia o endereo, o dado e pedido de escrita. Normalmente a
memria somente pode atender um pedido de cada vez. Portanto, para ler 1000
nmeros o processador ter de fazer 1000 acessos seqencialmente.
Os dois tipos bsicos de memria mais comuns so ROM e RAM. Estas
siglas tm diversas variaes (PROM, EPROM, DRAM, etc), mas os princpios
bsicos so os mesmos. Estas siglas indicam os dois tipos bsicos de memria
que so usadas em computadores. A sigla bsica ROM significa Read Only
Memory, ou seja, memria de somente de leitura. A outra sigla RAM (Random
Access Memory) significa memria de acesso randmico, portanto, memria que
se pode ler em qualquer endereo.
A sigla RAM muito confusa porque em uma memria ROM tambm se
pode ler em qualquer endereo. A diferena real que nas RAMs se pode ler e
escrever com a mesma velocidade em qualquer endereo, enquanto que na ROM,
o acesso rpido somente para leituras, a escrita uma histria mais complicada.
A ROM normalmente contm dados que no podem ser modificados durante o
funcionamento do computador. Outro tipo de dados armazenados em ROMs so
os que no devem ser perdidos quando o computador desligado. Exemplos de
uso de ROM so as memrias que armazenam os programas que so executados
quando os computadores so ligados, os famosos BIOS (Basic Input Output
System). Um computador ao ser ligado deve ter um programa mnimo capaz
de iniciar o seu funcionamento normal, caso contrrio seria como uma pessoa
que perdeu totalmente a memria. Para isto so escritos programas simples que
fazem acesso aos perifricos em busca do Sistema Operacional da mquina.
As primeiras memrias do tipo ROM eram gravadas nas fbricas e nunca
mais eram modificadas. Isto trazia algumas dificuldades, por exemplo, quando
um programa precisava ser atualizado. Para resolver este tipo de problemas
surgiram as PROMs, que so ROMs programveis. Ou seja possvel desgravar
o contedo antigo e gravar novos programas nesta memria. Antigamente este
24
era um processo complicado e exigia que a memria fosse retirada fisicamente
do circuito e colocada em dispositivos especiais capazes de apagar o contedo
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.
O computador ficava literalmente sem a memria dos programas iniciais. Hoje
em dia existem PROMs que podem ser apagadas e regravadas muito facilmente.
Por exemplo, as EEPROMs (Eletricaly Erasable PROMs), que so memrias
que podem ser apagadas eletricamente sem a necessidade de serem retiradas
dos circuitos. Flash memory uma forma de memria no voltil que pode
ser apagada e reprogramada eletricamente. Diferentemente das EEPROMs, ela
deve ser apagada em blocos de endereos. Este tipo de memria custa menos
do que EEPROMs e portanto so preferidas quando necessrio usar memria
no voltil em forma de circuitos integrados.
As memrias RAMs so as memrias onde os nossos programas comuns
rodam. Elas so modificveis e de acesso rpido tanto na leitura quanto na
gravao. Muitas siglas aparecem e desaparecem quando falamos de memrias
RAM. Existem as DRAM, memrias EDO, SIMM, etc. Tudo isto ou se refere ao
mtodo de acesso dos dados na memria ou a tecnologia de construo ou a outra
caracterstica acessria. O certo que todas elas tem como caracterstica bsica
o fato dos acessos de leitura e escrita poderem ser feitos na mesma velocidade.
BIT
BYTE
8 BITS
PALAVRA
32 BITS
4 BYTES
25
as duas leituras so atendidas uma de cada vez. Da mesma forma o computador
pode processar 32 bits de cada vez e a memria ter largura 64 bits. Isto pode
acelerar o processamento, j que o processador est se adiantando e recebendo
o que poder ser o prximo dado a ser processado, ou seja economizando uma
leitura.
Devido a base 2 o fator kilo tem um significado diferente em computao.
Por exemplo 1 Kbyte de memria corresponde a 2 elevado a 10 (210 ), ou seja
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
diversas abreviaes usadas quando se fazem referncias s memrias.
1.3.4 Perifri
os
Como j mencionamos antes, os dados no ficam guardados somente na me-
mria, h tambm os perifricos . H perifricos de entrada, outros de sada
e alguns que servem tanto para entrada como sada de dados. Perifricos no
servem somente para armazenar dados. H perifricos que so usados para per-
mitir a interao entre os usurios e o computador. A tabela 1.5 ilustra alguns
destes perifricos.
1.4 O Software
Tudo isto que sobre o que acabamos de escrever constitui o hardware do com-
putador, o que se v e o que se toca. A partir de agora falaremos brevemente
no software, o que no se v nem se toca, mas tambm est l.
26
Para que um computador execute alguma tarefa primeiro se desenvolve um
algoritmo , que uma espcie de receita que diz precisamente, ao computador,
como o problema deve ser resolvido. Esta definio informal de algoritmo
enganosamente simples, e a chave para entender o engano est nas palavras
dizer precisamente ao computador. Por exemplo, uma receita em gastronomia
normalmente no um algoritmo. Receitas so entendidas pela comunidade de
cozinheiros, que as seguem facilmente durante o preparo do prato. No entanto,
receitas esto cheias de expresses como, por exemplo, mexer at ficar no ponto
e colocar sal a gosto. Fora da comunidade de cozinheiros estas expresses so
passveis de vrias interpretaes. Para escrever algoritmos precisamos de uma
linguagem matematicamente precisa e sem ambigidades.
A escrita de um algoritmo consta de uma definio do estado inicial do
problema a ser resolvido e de regras precisas que estabelecem a cada instante
os passos a serem seguidos. Como em um jogo, alm de definir os passos, so
necessrias regras que definam se aps a execuo de um passo do algoritmo o
novo estado do problema vlido. As regras do xadrez definem o estado inicial
do tabuleiro, os movimentos possveis de cada pea e se aps um movimento
de uma pea a configurao atingida vlida. Ou seja precisamos verificar em
cada instante qual dos movimentos (instrues) pode ser usado.
Algoritmos podem ser chamados de procedimentos efetivos e devem obedecer
aos seguintes limites:
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 incio da computao eletrnica com programas armazenados, estes eram
escritos diretamente em linguagem de mquina que a linguagem que o com-
putador realmente entende. Estas instrues so conjuntos de bits indicando
a operao que deve ser executada e, caso necessrio, onde como achar os dados
que sero operados. Por esta razo tambm costuma-se dizer que so programas
escritos em binrio.
Com a evoluo da computao os programas passaram a ser escritos em
assembly , que uma representao em mnemnicos das instrues de mquina.
Deste modo era mais fcil escrever os algoritmos. Por exemplo, um fragmento
de um programa escrito em assembly do processador PowerPC :
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)
* e armazene o resultado em r5
Este pequeno trecho de programa armazena os nmeros 4 e 5 em registrado-
res internos do processador em seguida os soma e armazena o resultado em um
27
terceiro registrador. As informaes aps os asteriscos so comentrios usados
para explicar o que o programa est fazendo naquela instruo.
O PowerPC um microprocessador criado em 1991 por um consrcio for-
mado pela IBM, Apple e Motorola Os microprocessadores PowerPC podem ser
usados para equipar desde sistemas embutidos at computadores de alto desem-
penho. A Apple usou este microprocessador para equipar suas mquinas at
2006.
Um programa escrito em assembly deve ser traduzido para a representao
binria, tarefa que normalmente se chama de montar o programa. A palavra
assembler frequentemente usada erradamente para significar a linguagem e
no o programa que traduz o programa de assembly para linguagem binria de
mquina. Este tipo de programao pode levar a se escrever programas muito
eficientes, devido ao controle quase que total do programador sobre a mquina.
No entanto devido ao fato de ser uma linguagem prxima do computador e afas-
tada da maneira de raciocinar do ser humano mais difcil de ser usada. Alm
deste fato h outros problemas tais como: dificuldade de leitura por humanos,
dificuldade de manuteno dos programas, maior tempo de desenvolvimento etc.
Para evitar estes problemas foram desenvolvidas as linguagens de progra-
mao chamadas de linguagens de alto nvel, por estarem mais prximas da
linguagem natural empregada pelos serem humanos. Alguns exemplos de lin-
guagens de programao so:
28
Criao do Algoritmo: neste passo criado o algoritmo que ir resolver o
problema. As diversas maneiras de descrever um algoritmo sero apresen-
tadas no prximo captulo.
Codificao do Algoritmo: O algoritmo preparado no passo anterior es-
crito em uma linguagem de programao. Neste passo o programador
conta, normalmente, com a ajuda de um editor de textos (no processa-
dor de textos). Para esta edio qualquer editor pode ser usado. Hoje
em dia muitos ambientes de desenvolvimento integram todas as ferramen-
tas necessrias para criar um programa, inclusive o editor, em um nico
aplicativo.
Compilao do Programa: O arquivo texto contendo o programa passa por
um programa especial chamado compilador que gera, caso no hajam er-
ros, uma sada que quase o programa executvel, ou seja o programa
em cdigo binrio do processador em que ser executado. Os erros mais
comuns nesta etapa so erros de uso correto da linguagem de programa-
o. Estes erros so chamados de erros de compilao. As linguagens de
programao so baseadas em regras gramaticais muito rgidas e qualquer
violao destas regras pode implicar em erro. No caso de erros serem
encontrados o programador deve voltar ao passo de codificao para a
correo dos erros.
Ligao: Em ingls este passo conhecido por link edition. Um programa
completo composto por vrios mdulos que podem ter sido criados pelo
prprio programador ou por outras programadores. Por exemplo, em C
os trechos de programa que interagem com os usurios, os comandos de
entrada e sada de dados, normalmente vm com o programa compilador.
Estes trechos podem estar guardados em bibliotecas de programas e so
ligados ao programa do usurio para completar o programa.
Depurao e Testes: Nesta etapa o programa ser testado para a retirada
dos possveis erros de lgica que o programador cometeu. Caso algum
erro de execuo seja encontrado o programador deve reelaborar o que
estiver errado no algoritmo e em seguida ir para a etapa de codificao do
algoritmo. Este ciclo pode repetir-se inmeras vezes at que o desenvol-
vedor acredite que os erros foram corrigidos.
Uso do Programa: O programa foi entregue aos seus usurios para ser usa-
do. Durante o uso, erros que no foram encontrados durante o desenvol-
vimento do programa podem ser descobertos e precisam ser corrigidos. A
correo pode ser feita pelos mesmos programadores que desenvolveram o
programa ou por outro grupo devidamente treinado. Costuma-se chamar
esta correo de manuteno do programa.
29
Incio
Ligao
Criao de
Algoritmo Depurao e
Testes
Sim
Codificao do Erros de
Algoritmo Execuo?
No
Compilacao do
Programa Uso do programa
Sim Sim
Erros de Erros de
Compilao? Execuo?
No
30
usurios, espao em discos, uso de memria, tempo que cada programa pode ro-
dar etc. Alguns dos sistemas operacionais conhecidos so os baseados no padro
UNIX, por exemplo o LINUX. Outros sistemas muito usados so os da famlia
Windows.
31
1.5 Um programa em C
Vamos terminar este captulo mostrando um exemplo simples de programa es-
crito em C(Listagem 1.1). A nica coisa que este programa faz imprimir Alo
Mundo! e terminar [Kernighan e Ritchie 1978, Schildt 1997, Oliveira 2008].
A primeira linha do programa avisa ao compilador que ir usar funes de
entrada e sada de dados guardadas na biblioteca stdio. Neste caso a funo
usada printf. A segunda linha o incio real do programa. A linha indica que
esta a funo main que todo programa C deve conter, pois nesta funo que
o programa obrigatoriamente comea sua execuo. A funo vai retornar um
valor inteiro (int) ao final de sua execuo e no vai precisar receber nenhum
argumento para sua execuo (void). As chaves ({ e }) marcam o incio e o
fim da funo. Para imprimir o texto Alo Mundo! o programa usa a funo
printf. O incio e o fim do texto a ser impresso so marcados pelo caractere ".
A funo termina com o comando return 0, que avisa ao sistema operacional,
que foi quem iniciou a execuo do programa, que o programa terminou sem
problemas. Este programa simples ilustra alguns das estruturas bsicas que
sero usadas nos programas C que sero apresentados neste livro.
32
Exer
ios
1.1: O que o hardware do computador?
1.6: Se voc j usa computadores, liste alguns aplicativos que voc normalmente
usa.
1.15: Segundo a Wikipedia, a norma ABNT NBR 14724:2011, sugere que uma
pgina de texto pode conter mais de 3000 caracteres. Nesta questo considere
que uma pgina de texto sempre contm 3000 caracteres e que cada caractere
ocupa 32 bits. Precisamos armazenar 1000 livros e cada um deles contm 200
pginas de texto. Marque o MENOR dos tamanhos de memria abaixo capaz
de conter todos os 1000 livros, ou seja, se mais de um tamanho puder conter os
livros escolha o menor.
33
(a) Um anncio de computadores informa que a velocidade do processa-
dor igual a 3.5 Gigahertz. Qual a quantidade exata de Hertz do
processador anunciado?
(b) H duas maneiras de calcular a capacidade de armazenamento de
discos rgidos em termos de 1 Gigabyte de memria. Uma alternativa
usa a base 10 e outra a base 2. Qual a quantidade exata de 1
Gigabyte nas duas maneiras?
1.17: BIOS um software que vem junto com os PCs e o primeiro cdigo exe-
cutado pelo computador quando ele ligado. A sua principal funo carregar
na memria do computador o sistema operacional e dar incio a sua execuo.
Discuta porque o BIOS fica armazenado em uma memria conhecida como flash,
e que basicamente funciona como uma memria EPROM, enquanto que os pro-
gramas comuns ficam armazenados na memria principal que composta de
memrias RAM.
34
Captulo 2
Algoritmos
2.1 Introduo
O objetivo deste captulo fazer uma breve introduo ao conceito de algorit-
mos e apresentar algumas formas mais comuns de representar algoritmos para
facilitar o entendimento dos demais captulos deste livro. Iremos apresentar as
construes mais comuns empregadas no desenvolvimento de algoritmos e apre-
sentaremos exemplos bsicos de algoritmos usando algumas destas formas de
representao e construes.
Para resolver um problema no computador necessrio que seja primeira-
mente encontrada uma maneira de descrever este problema de uma forma clara
e precisa. preciso que encontremos uma seqncia de passos que permitam
que o problema possa ser resolvido de maneira automtica e repetitiva. Alm
disto preciso definir como os dados que sero processados sero armazena-
dos no computador. Portanto, a soluo de um problema por computador
baseada em dois pontos: a seqncia de passos e a forma como os dados sero
armazenados no computador. Esta seqncia de passos chamada de algoritmo.
Usamos algoritmos em diversas atividades que realizamos diariamente. Uma
grande parte destas atividades no esto relacionadas com computao. Um
exemplo simples e prosaico, de como um problema pode ser resolvido caso for-
neamos uma seqncia de passos que mostrem a maneira de obter a soluo,
uma receita para preparar um bolo.
Uma vez que foi criado um algoritmo para resolver um determinado pro-
blema usando computadores passamos para a prxima fase que a escrita deste
algoritmo em alguma linguagem de programao.
A noo de algoritmo central para toda a computao. A criao de algo-
ritmos para resolver os problemas uma das maiores dificuldades dos iniciantes
em programao em computadores. Isto porque no existe um conjunto de re-
gras, ou seja um algoritmo, que nos permita criar algoritmos. Caso isto fosse
possvel a funo de criador de algoritmos desapareceria. Claro que existem
linhas mestras e estruturas bsicas, a partir das quais podemos criar algorit-
mos, mas a soluo completa depende em grande parte do criador do algoritmo.
35
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 [Knuth 1973]
apresenta uma verso para a origem desta palavra. Ela seria derivada do nome
de um famoso matemtico persa chamado Abu Jafar Maom ibn Ms al-
Khowrism (825) que traduzido literalmente quer dizer Pai de Jafar, Maom,
filho de Moiss, de Khowrizm. Khowrizm hoje a cidade de Khiva, na ex
Unio Sovitica. Este autor escreveu um livro chamado Kitab al jabr wal-
muqabala (Regras de Restaurao e Reduo). O ttulo do livro deu origem
tambm a palavra lgebra.
O significado da palavra muito similar ao de uma receita, procedimento,
tcnica, rotina. Um algoritmo um conjunto finito de regras que for-
nece uma seqncia de operaes para resolver um problema espec-
fico. Segundo o dicionrio do prof. Aurlio Buarque de Holanda um algoritmo
um:
36
sair de casa, qual o melhor meio de transporte etc. Um fator importante
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
transporte em funo do preo, conforto, rapidez, etc. A escolha ser feita em
funo do critrio que melhor se adequar as nossas necessidades. Um exemplo
de algoritmo pode ser as instrues que um professor passa aos seus alunos em
uma academia de ginstica, mostrado no Algoritmo 2.1. Observar que nesta
representao do algoritmo cada linha contm uma instruo.
37
passos do algoritmo servem para o algoritmo obter os valores dos coeficientes a e
b. Os valores podem, por exemplo, serem digitados em um teclado pelo usurio
que est usando o algoritmo. O valor digitado vai para uma posio da memria
do computador, que para facilitar o manuseio do dado, recebe um nome. Neste
exemplo demos os nomes a, b e x as posies de memria usadas pelo programa
para armazenar dados. Aps os dois primeiros passos o algoritmo executa uma
instruo de teste para verificar se o valor de a diferente de 0. Neste caso
podemos ter duas respostas e o computador ir escolher entre dois caminhos
independentes e exclusivos. Caso a seja igual a zero, o algoritmo executa as
instrues entre a palavra ento e seno, e portanto, imprime uma mensagem
de aviso para o usurio e termina. Esta mensagem normalmente aparece em
um monitor de vdeo. No caso de a ser diferente de zero, o algoritmo executa as
instrues entre seno e fim se. Isto significa calcular o resultado da equao
e atribuir este resultado x. O ltimo passo, desta opo a impresso do
resultado da equao.
2.3 Representao
As formas mais comuns de representao de algoritmos so as seguintes:
2.3.2 Fluxogramas
Esta forma de representao de algoritmos emprega vrias formas geomtricas
para descrever cada uma das possveis aes durante a execuo do algoritmos.
38
Algoritmo 2.3: Algoritmo para calcular a mdia das notas de um aluno.
Entrada: Notas n1 , n2 e n3 .
Sada: Resultado media do aluno e se ele foi aprovado ou no.
inicio
Obter as notas n1 , n2 e n3
Calcular mdia. Usar a frmula ((n1 + n2 + n3 )/3.0).
Se a mdia for maior que 5.0 imprimir que o aluno foi aprovado
Caso contrrio imprimir que o aluno foi reprovado.
Imprimir a mdia.
fin
2.3.3 Pseudo-Linguagem
Este modo de representar algoritmos procura empregar uma linguagem que es-
teja o mais prximo possvel de uma linguagem de programao de computado-
res de alto nvel, mas evitando de definir regras de construo gramatical muito
rgidas. A idia usar as vantagens do emprego da linguagem natural, mas
restringindo o escopo da linguagem. Normalmente estas linguagens so verses
ultra reduzidas de linguagens de alto nvel do tipo Pascal ou C. O algoritmo 2.2
foi escrito em uma pseudo-linguagem. A maioria destas linguagens so muito
39
Incio
Obter a
Obter b
Sim
a =0
No
No h razes
x=-b/a reais
Imprime x
Fim
40
Algoritmo 2.4: Algoritmo para calcular a maior nota de um grupo de
notas.
Entrada: Trs notas de um aluno, (notaAluno).
Sada: Maior das notas do aluno, (maiorN ota)
inicio
L primeira nota
ler notaAluno
maiorN ota notaAluno
L segunda nota
ler notaAluno
se notaAluno > maiorN ota ento
maiorN ota notaAluno
fim se
L terceira nota
ler notaAluno
se notaAluno > maiorN ota ento
maiorN ota notaAluno
fim se
imprimir A maior nota das notas , maiorN ota
fin
1. Busca instruo;
2. Decodifica instruo;
41
3. Executa instruo;
4. Volta para o passo 1 buscando a instruo seguinte na memria.
42
0 1 2 3 4 5 6 7
2 8 10
16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
43
imprimir x
imprime o valor atual que est na memria representada pelo nome x.
Da mesma forma que nos comandos de leitura possvel colocar uma lista
de nomes de variveis aps o comando. Por exemplo, o comando
imprimir x1, x2
imprime os valores das variveis x1 e x2. O meio de apresentao dos resultados,
normalmente, um monitor de vdeo.
O comando imprimir pode ser usado para mandar mensagens de texto
para o usurio do algoritmo das formas mais variadas. Alguns exemplos de
comandos de impresso so os seguintes:
Notar que os textos entre aspas indicam um texto que deve ser impresso no
perifrico de sada sem nenhuma modificao. Vamos considerar que as variveis
destes exemplos valem x = 10, x1 = 5 e x2 = 8. Os trs comandos mostrariam
no perifrico de sada os seguintes resultados:
2.5.3 Expresses
Expresses so usadas para definir os clculos requeridos pelo algoritmo, por
exemplo b/a. Iremos discutir dois tipos bsicos de expresses: expresses arit-
mticas e expresses lgicas.
Expresses manipulam dados dentro dos algoritmos. Uma pergunta impor-
tante neste momento : que tipo de dados poderemos manipular? As linguagens
de programao normalmente estabelecem regras precisas para definir que tipos
de dados elas iro manipular. Nesta discusso vamos estabelecer, ainda que
informalmente, algumas regras que limitam os conjuntos de dados existentes na
Matemtica e estabelecem que dados podero ser manipulados pelos algoritmos.
Isto ocorre porque os computadores possuem limitaes que os impedem de ma-
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 representaes. Existem trs tipos bsicos de
dados que iremos discutir:
44
Dados Lgicos: estes dados podem assumir dois valores verdadeiro e falso.
Estes dados resultam de expresses do tipo x > 0.
+3
3
-324
-50
+0.5
0.5
-8.175
2.0
Linguagem de programao
Qual o seu nome?
12345
se a = 0 ento
imprimir A equao nao tem soluo
seno
x b/a
imprimir A raiz da equao vale , x
fim se
45
Expresses Aritmticas
Expresso Expresso em
Matemtica Pseudo-linguagem
a
b+c a/(b+c)
a+b
c+d (a+b)/(c+d)
2
b 4ac b*b-4*a*c
1
1
1+ a+b
1/(1 + 1/(a+b))
46
da seta. A direo da seta no pode ser alterada. No caso da ltima expres-
so temos que o valor atual de i incrementado e depois substitui este valor,
portanto, se ele valia 10, ao final da instruo ele vale 11.
Algoritmando
Falso
Condio
Verdadeiro
Continuo
algoritmando
47
feito. Esta deciso em forma de pseudo-linguagem fica da maneira mostrada no
Algoritmo 2.7.
48
Vestir para
ir ao cinema
Falso
Chovendo?
Verdadeiro
Pegar
guarda-chuva
Ir ao
cinema
vamos considerar que caso o resto da diviso seja igual a zero o nmero par.
Neste algoritmo sabemos a quantidade de nmeros a serem lidos e portanto o
nmero de repeties pr-determinado. O Algoritmo 2.9 mostra como seria
implementada uma soluo para este problema.
Vamos mostrar um exemplo onde o nmero de repeties no conhecido.
Considere no exemplo anterior que o total de nmeros a ser lido no conhecido.
Mas ento, como o algoritmo ir terminar de ler nmeros? Usaremos o que
costuma-se chamar de sentinela em computao. O algoritmo ir se manter
lendo nmeros enquanto os nmeros forem positivos. No momento que for
lido um nmero negativo o algoritmo pra. A sentinela que indica o final da
lista de nmeros um nmero negativo. O Algoritmo 2.10 mostra como fica
em pseudo-linguagem o algoritmo modificado. Observe que neste algoritmo o
primeiro nmero tem de ser lido antes do comando enquanto. Isto porque
assumimos que o primeiro nmero que for digitado pode ser negativo e portanto
a lista de nmeros no tem nenhum nmero.
49
Algoritmo 2.9: Algoritmo para ler 10 nmeros e imprimir se so pares
ou no.
Entrada: 10 nmeros, (numero).
Sada: Se o nmero par ou no
inicio
totalN umeros 10
enquanto totalN umeros > 0 faa
ler numero
se numero%2 = 0 ento
imprimir numero, par
seno
imprimir numero, impar
fim se
totalN umeros totalN umeros 1
fim enqto
fin
50
Algoritmando
Falso
Testa
Condio
Verdadeiro
Bloco de comandos
do enquanto
Continuo
algoritmando
caso ela seja maior substitui o valor anterior pelo novo valor. Observar que
criamos uma varivel para armazenar a quantidade de alunos. Voc poderia
perguntar porque no usar o nmero 25 toda vez que for necessrio. A razo
simples. Suponha que voc gostaria de usar este algoritmo para calcular a maior
nota de uma turma de 40 alunos. Neste algoritmo bastaria substituir o nmero
25 por 40. No entanto, existe uma soluo mais geral ainda que permite que
o algoritmo possa ser usado para qualquer tamanho de turma. Este problema
est apresentado na lista de exerccios deste captulo.
Exemplo 2.2: Vamos mostrar outro exemplo de algoritmo muito usado. Pre-
cisamos ler as notas de uma turma de alunos e calcular a mdia destas notas.
Vamos assumir que a turma tem 25 alunos e as notas esto entre 0 e 10. O
algoritmo est mostrado em Algoritmo 2.12.
Exemplo 2.3: Neste exemplo considere o seguinte problema. Um escritrio de
previso do tempo armazena diariamente a temperatura mdia de uma deter-
minada regio. A tarefa descobrir qual a maior temperatura do ano passado.
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
nota da turma. Antes de continuar procure encontrar a razo. Como dica,
considere que estamos no plo sul e portanto todas as temperaturas lidas so
negativas.
Uma soluo possvel para este exemplo est mostrada no algoritmo 2.13.
Este algoritmo faz o seguinte. Pega a primeira temperatura e a anota como a
maior j encontrada. A partir da o algoritmo fica repetidamente lendo tem-
51
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).
Sada: Maior das notas dos alunos, (maiorN ota)
inicio
totalAlunos 25
maiorN ota 0.0
enquanto totalAlunos > 0 faa
ler notaAluno
se notaAluno > maiorN ota ento
maiorN ota notaAluno
fim se
totalAlunos totalAlunos 1
fim enqto
imprimir A maior nota das notas , maiorN ota
fin
52
peraturas dos registros do escritrio comparando com a temperatura que no
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
temperaturas para ler a que estiver anotada como a maior a maior verdadei-
ramente.
53
Exer
ios
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
anual deste trabalhador.
2.2: Assuma que o trabalhador do exerccio anterior deve pagar 10% de imposto
se o seu salrio anual for menor ou igual a R$ 12000.00. Caso o salrio seja maior
que este valor o imposto devido igual a 10% sobre R$ 12000.00 mais 25% sobre
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.
2.4: Modifique o algoritmo anterior de modo que ele imprima tambm quantas
vezes a maior nota aparece.
2.5: Nos exerccios anteriores assumimos que os usurios sempre digitam uma
nota entre 0 e 10. Vamos assumir agora que o usurio sempre digita um nmero,
mas este nmero pode estar fora do intervalo 0 a 10. Ou seja, poderemos ter
uma nota menor que zero ou maior que 10. Modifique o algoritmo anterior
para que ele verifique a nota digitada e, caso o aluno tenha digitado uma nota
invlida, uma mensagem avisando o usurio seja impressa e uma nova nota seja
pedida. O algoritmo deve insistir at que o usurio digite um valor vlido.
2.7: Escreva um algoritmo que leia trs nmeros e os imprima em ordem cres-
cente.
2.8: Escreva um algoritmo que leia um nmero inteiro entre 100 e 999 e imprima
na sada cada um dos algarismos que compem o nmero. Observe que o nmero
lido com um valor inteiro, e, portanto, ele tem de ser decomposto em trs
nmeros: os algarismos das centenas, dezenas e unidades.
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
a data mais recente.
54
(c) (nota < 0) ou (nota > 100)
(d) (nota <= 0) ou (nota >= 100)
(e) (nota >= 0) e (nota <= 100)
2.11: Considere que os valores -3, -4 e -5, nesta ordem, foram fornecidos ao
algoritmo 2.15:
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.
55
Captulo 3
3.1 Introduo
Variveis e constantes so os elementos bsicos que um programa manipula.
Uma varivel corresponde a um espao reservado na memria do computador
para armazenar um determinado tipo de dado. Variveis devem receber no-
mes para poderem ser mais facilmente referenciadas e modificadas sempre que
necessrio. Muitas linguagens de programao exigem que os programas de-
clarem todas as variveis antes que elas possam ser usadas. Estas declaraes
especificam de que tipo so as variveis usadas pelos programas e as vezes um
valor inicial. Tipos podem ser por exemplo: inteiros, reais, caracteres, etc. As
expresses combinam variveis e constantes para calcular novos valores.
56
double: Nmero em ponto flutuante de preciso dupla, com isto a preciso e
as vezes a excurso dos nmeros aumenta. Este tipo armazenado em 64
bits.
void: Este tipo serve para indicar que um resultado no tem um tipo defi-
nido. Uma das aplicaes deste tipo em C criar um tipo vazio que pode
posteriormente ser modificado para um dos tipos anteriores.
unsigned: Este modificador 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.
signed: Este modificador tambm pode ser aplicado aos tipos int e char. O
uso de signed com int redundante.
long: Modificador que pode ser aplicado aos tipos int e double aumentando o
nmero de bytes reservado para armazenamento de dados.
dgito: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
dgito_sem_zero: 1, 2, 3, 4, 5, 6, 7, 8, 9
dgito_octal: 0, 1, 2, 3, 4, 5, 6, 7
dgito_hexa: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D,
e, E, f, F
sinal: +, -
57
Tipo Bytes Faixa Mnima
char 1 -127 a 127
unsigned char 1 0 a 255
signed char 1 -127 a 127
int 4 -2.147.483.648 a 2.147.483.647
unsigned int 4 0 a 4.294.967.295
signed int 4 -2.147.483.648 a 2.147.483.647
short int, short 2 -32.768 a 32.767
unsigned short int 2 0 a 65.535
signed short int 2 -32.768 a 32.767
long int, long 4 -2.147.483.648 a 2.147.483.647
signed long int 4 -2.147.483.648 a 2.147.483.647
unsigned long int 4 0 a 4.294.967.295
long long int -9.223.372.036.854.775.808 a
long long 8 9.223.372.036.854.775.807
signed long long int -9.223.372.036.854.775.808 a
signed long long 8 9.223.372.036.854.775.807
unsigned long long int
unsigned long long 8 0 a 18.446.744.073.709.551.615
float 4 oito dgitos de preciso
double 8 16 dgitos de preciso
long double 12 16 dgitos de preciso
ponto_decimal: .
O uso destas caracteres ser mostrado com exemplos nas sees seguintes.
[sinal]dgito_sem_zero{dgito}[sufixo_sem_sinal|sufixo_longo]
58
um dgito_sem_zero que obrigatrio. Isto dados inteiros devem comear
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,
pode ser seguido por uma seqncia de zero ou mais algarismos. Como sufixo
podemos ter opcionalmente as letras u (U) ou l (L) ou uma mistura, em qualquer
ordem, das duas. Para constantes inteiras o sufixo U (u) representa o modificador
unsigned. O sufixo L (l) representa o modificador long. Um par de Ls (ls)
indica que a constante do tipo long long. A tabela 3.2 mostra exemplos de
nmeros inteiros:
Tipo Constantes
int 1997 -3 +5 7
unsigned int 1997U 45u 12345U 0U
long int 1234L 1997L -3l +0L
unsigned long int 1997UL 45Lu 23Ul 0LU
long long 134LL 1997Ll -3ll +0LL
unsigned long long 1997ULL 45LLu 23Ull 0LLU
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
e 7 inclusive.
59
Base 8 Base 10
025 21
077 63
011 9
010ul 8
0175 125
[0x|0X]dgito_hexa{dgito_hexa}[sufixo_sem_sinal|sufixo_longo]
Base 16 Base 10
0xF 15
0X25 37
0XAB 171
0XBEEF 48879
Esta equao est escrita na base 10. Por exemplo, aplicando a equao 3.1
para converter o nmero 0175 da base 8 para a base 10 ficamos com
(0175)8 = 1 82 + 7 81 + 5 80 = (125)10
60
A frmula para converso da base 8 para a base 10 pode se estendida para
uma base qualquer com a substituio do algarismo 8. Considere uma base
qualquer representada por b. Nesta base os dgitos di ficam no intervalo b 1
di 0. A equao 3.2 mostra a frmula para converter um nmero em uma
base b qualquer para a base 10.
Vamos considerar a contante inteira (3AF )16 . Aplicando a frmula 3.2 temos
61
igual a 0.15 101 . possvel omitir ou os dgitos antes do ponto (a parte
inteira) ou aps (a parte fracionria), mas nunca os dois grupos. possvel
escrever um nmero em ponto flutuante sem ponto, desde que um expoente seja
usado. Portanto, os nmeros .8, 1234., 1E1 so nmeros de ponto flutuante.
Para mostrar mais formalmente como se deve escrever as constantes de ponto
flutuante vamos usar a mesma notao usada at aqui, mas usando uma hierar-
quia de definies para facilitar o entendimento. Primeiro damos uma definio
mais geral que vai sendo mais detalhada a medida que avanamos. Lembrar
que termos entre chaves podem ser repetidos 0 ou mais vezes e termos entre
colchetes so opcionais.
Portanto, usando a forma hierrquica, uma constante de ponto flutuante
(CPF) pode ser definida das seguintes maneiras:
CPF = [sinal]frao[expoente][sufixo_flutuante]
CPF = [sinal]seq_dgitos expoente[sufixo_flutuante]
A seguir definimos cada um dos componentes. Uma frao definida como:
frao = [seq_digitos] ponto_decimal seq_dgitos ou
frao = seq_dgitos ponto_decimal
Descrio Nmero
sinal frao expoente +23.45e-10
frao 123.45
frao expoente 123.45E+10
frao sufixo 123.45F
seq_dgitos ponto_decimal 123.
62
Caractere Significado
a caractere a
A caractere A
\0141 Constante octal correspondente ao caractere a
( caractere abre parnteses
9 algarismo 9
\n Nova linha, posiciona o cursor no incio da nova linha.
Caractere Significado
\n Passa para uma nova linha.
\t Tabulao horizontal, move o cursor
para a prxima parada de tabulao.
\b Retorna um caractere.
\f Salta uma pgina.
\r Carriage return, posiciona o cursor
no incio da linha atual.
\a Alerta, faz soar a campainha do sistema.
\0 Null, caractere que em C termina
uma cadeia de caracteres.
63
3.5 Variveis
Variveis so nomes dados para posies de memria a fim de facilitar o ma-
nuseio dos dados durante a criao dos programas. Os dados podem ser de
qualquer dos tipos definidos para a linguagem C.
boa poltica escolher nomes que indiquem a funo da varivel. Por exem-
plo:
soma total nome raio
mediaNotas salarioMensal taxa_imposto _inicio
Em C nomes como raio, Raio e RAIO referem-se a diferentes variveis. No
entanto, para afastar confuses, evite diferenciar nomes de variveis por letras
maisculas e minsculas. Normalmente, os programadores usam letras mais-
culas para representar constantes.
Observe que em alguns nomes combinamos duas palavras para melhor indi-
car o dado armazenado na varivel. Note tambm que o caractere espao no
pode ser usado em nomes de variveis. Os programadores ao longo do tempo
desenvolveram algumas regras informais para fazer esta combinao. Por exem-
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
comea uma palavra, como em mediaNotas. Alguns programadores usam a con-
veno de no comear nomes de variveis por letras maisculas. No existem
regras formais para definir como nomes devem ser criados. O melhor analisar
as regras que programadores mais experientes usam ou os padres que empresas
adotam, para ento escolher o que mais lhe agrada e segui-lo. Uma vez adotado
um padro ele deve ser seguido para evitar incoerncias.
64
tipo lista_de_variveis;
onde uma lista_de_variveis uma lista de nomes de variveis separadas
por vrgulas. Por exemplo:
int i ;
unsigned int a , b ,
;
unsigned short int dia , mes , ano ;
f l o a t raio , diametro ;
double salario ;
int i = 0 , j = 10;
f l o a t raio = 2.54;
har
= 'd ';
double pre
isao = 0.00001 L ;
int i , j ;
f l o a t raio ;
har
;
i = 0;
j = 10;
raio = 2.54;
= 'd ';
65
Exer
ios
3.1: Indique os nomes de variveis que so vlidos. Justifique os nomes invli-
dos.
(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.
3.3: Indique quais dos nmeros abaixo so constantes inteiras (longas ou no)
vlidas. Justifique suas respostas.
(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) 025
(b) 0123
(c) 0xD
(d) 0x1D
(a) Caso um bit seja reservado para o sinal diga qual o menor nmero
inteiro negativo que este computador pode armazenar?
(b) Para os nmeros sem sinal, qual o maior nmero positivo?
3.6: Indique na tabela 3.8 os tipos que voc usaria para armazenar os dados
indicados.
3.7: Marque a opo que indica quantos dos nmeros abaixo representam re-
sultados da operao (175)8 + (AB)16 .
(602)7 , (100101000)2, (128)16 , (450)8
(a) 0
(b) 1
(c) 2
(d) 3
(e) 4
66
Descrio Tipo da varivel
total de alunos em uma sala
a nota de aluno em Computao I
Primeira letra de um nome
pontos de um jogador de voleibol ao final do ano;
o raio de um crculo.
67
Captulo 4
4.1 Introduo
Neste captulo vamos apresentar conceitos bsicos de entrada e sada de dados
para que os exemplos e exerccios iniciais possam ser construdos. Um programa
que no fornece resultados nem pede valores para operar no deve ter grande
utilidade. A entrada de dados ser feita pelo teclado e a sada poder ser vista
na tela do computador. Em C, quando um programa se inicia, normalmente trs
fluxos (arquivos) de dados so abertos para operaes de entrada e sada: um
para entrada, um para sada e um para imprimir mensagens de erro ou diagns-
tico. Normalmente o fluxo de entrada est conectado ao teclado, enquanto que
o fluxo de sada e o de mensagens de erro, para serem visualizados, esto conec-
tados ao monitor. Estas configuraes podem ser alteradas de acordo com as
necessidades dos usurios e estas operaes so chamadas de redirecionamento.
O fluxo de entrada chamado de entrada padro (standard input); o fluxo de
sada chamado de sada padro (standard output) e o fluxo de erros chamado
de sada padro de erros (standard error output). Estes termos so substitudos
pelas suas formas abreviadas: stdin, stdout e stderr.
68
incluso. Quando se usa aspas o arquivo procurado de maneira definida pela
implementao, isso pode significar procurar no diretrio de trabalho atual,
ou em um diretrio indicado no comando usado para compilar o programa.
Normalmente os programadores usam maior e menor para incluir os arquivos
de cabealho padro e aspas para a incluso de arquivos do prprio projeto.
69
4.3.1 Cdigos de Converso
Os cdigos de converso esto mostrados na tabela 4.1.
Cdigo Comentrio
%c Caracter simples
%d Inteiro decimal com sinal
%i Inteiro decimal com sinal
%E Real em notao cientfica com E
%e Real em notao cientfica com e
%f Real em ponto flutuante
%G %E ou %f, o que for mais curto
%g %g ou %f, o que for mais curto
%o Inteiro em base octal
%s Cadeia Caracteres
%u Inteiro decimal sem sinal
%x Inteiro em base hexadecimal (letras minsculas)
%X Inteiro em base hexadecimal (letras maisculas)
%p Endereo de memria
%% Imprime o caractere %
%[modificadores][largura][.preciso][comprimento]cdigo
70
0 Completa o campo, pela esquerda, com zeros (0) ao invs de espaos,
sempre que a opo para completar seja especificada (ver especifica-
dor de largura do campo).
largura: Caso seja usado um nmero inteiro, este especifica o tamanho mnimo
do campo onde o argumento ser impresso. Na listagem 4.2 o nmero
especifica que 8 espaos so reservados para imprimir o resultado. Os
espaos livres sero completados com espaos em branco. Se o argumento
precisar de mais espao que o especificado ele ser escrito normalmente e
o tamanho mnimo ignorado.
.preciso Este nmero tem diferentes significados dependendo do cdigo usado.
caracteres: No caso de impresso de cadeia de caracteres (s), este n-
mero especifica o nmero mximo de caracteres de uma cadeia de
caracteres a serem impressos.
ponto flutuante: No caso de formato (e, E, f) o nmero de dgitos a
serem impressos a direita do ponto, ou seja o nmero de casas deci-
mais. Para o formato g ou G o nmero mximo dgitos significativos.
inteiros: No formatos inteiros (d, i, o, u, x, X) a preciso especifi-
cou o nmero mximo de dgitos a serem impressos. Se o nmero de
caracteres a serem impressos menor que este o resultado comple-
tado com brancos. O valor no truncado
comprimento: Modifica os formatos da seguinte maneira:
l Aplicado aos formatos de tipo d, i, o, u, x e X indicando que o dado
do tipo long int e no int.
h Modifica 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 modificado para long double.
return 0;
}
71
Listagem 4.3: Exemplo de uso de especificador de preciso.
#in
lude < stdio .h >
int main () {
f l o a t r = 1.0/3.0;
har s [ = " Alo Mundo " ;
printf ( " O resultado e = %9.3 f \ n " , r ) ;
printf ( " %9.3 s \ n " , s ) ;
return 0;
}
O resultado e = 0.333
. Alo
Nos exemplos anteriores verifique que \n no impresso. A barra inclinada
chamada de seqencia de escape, indicando que o prximo caractere no para
ser impresso mas representa caracteres invisveis ou caracteres que no esto
representados no teclado. Esta seqncia de escape indica que o programa deve
passar a imprimir na prxima linha.
int i ;
float x;
s
anf ( " % d % f " , &i , & x ) ;
72
a execuo do exemplo iria terminar com o valor inteiro 34 sendo armazenado
na varivel i e o valor real 56.43 em x.
Usualmente o campo de controle s contm especificaes de converso, como
os listados na Tabela 4.1, que so utilizadas para interpretar os dados que sero
lidos, no entanto, como em printf, outros caracteres podem aparecer. O campo
de controle pode conter:
O modelo o seguinte:
%{*}{largura}{modificadores}tipo
O caracteres entre chaves so opcionais. O asterisco indica que o dado ser lido
de stdin mas ignorado. A largura especifica o nmero mximo de caracteres a
serem lidos.
Os modificadores alteram o tamanho do especificadores de tipo que vm logo
a seguir. Existem os seguintes modificadores:
Por exemplo, para que os valores digitados sejam separados por vrgulas, o
comando deveria ser escrito da seguinte maneira:
s
anf("%d, %f", &i, &x);
Observar que deve haver uma correspondncia exata entre os caracteres no
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 funo s
anf.
O resultado da execuo deste programa :
73
Listagem 4.4: Exemplo de uso de scanf.
#in
lude < stdio .h >
int main () {
har
;
int num1 , num2 ;
printf ( " Entre
om um
ara
tere qualquer .\ n " ) ;
s
anf ( " %
" , &
) ;
printf ( " Codigo ASCII do
ara
tere %
vale % d .\ n " ,
,
);
printf ( " Agora dois inteiros separados por espa
o .\ n " ) ;
s
anf ( " % d % d " , & num1 , & num2 ) ;
printf ( " A soma destes numeros vale % d .\ n " , num1 + num2 ) ;
return 0;
}
74
Entre com um algarismo entre 0 e 9.
7
O caractere lido foi o 7
return 0;
}
75
Listagem 4.6: Exemplo de uso de getchar e putchar.
#in
lude < stdio .h >
int main ( void ) {
har
;
int i ;
printf ( " Entre
om um numero inteiro .\ n " ) ;
s
anf ( " % d " , & i ) ;
76
Considere que este programa se chama util. Uma possvel interao entre
este programa e um usurio poderia ser da seguinte maneira.
$ util
Por favor, qual o seu nome?
Ze Sa
Sou um computador. Posso ajuda-lo Ze?
O smbolo $ o prompt tpico dos sistemas Unix. Aparentemente o computa-
dor se tornou ntimo do usurio Ze Sa e o tratou apenas pelo primeiro nome. A
explicao para esta intimidade est no modo de leitura. Quando se usa scanf
para ler uma cadeia deve-se empregar o cdigo de converso %s. Este comando
no l o nome todo, mas encerra a leitura dos caracteres quando encontra um
caractere espao (ou branco), ou seja o separador de cadeias no comando s
anf
o caractere espao. Mas como ler para um vetor um nome inteiro, ou um
cadeia que contenha brancos? Para isto deve-se usar a funo gets que ser
nosso prximo assunto.
A funo gets retorna str caso nenhum erro ocorra. Caso o final do ar-
quivo seja encontrado antes de qualquer caractere ser lido, o vetor permanece
inalterado e um ponteiro nulo retornado. Caso um erro ocorra durante a lei-
tura, o contedo do array fica indeterminado e novamente um ponteiro nulo
retornado.
A funo puts tem o seguinte prottipo:
77
Entre com o seu nome, por favor.
Ze Sa
Alo
Ze Sa
Eu sou um computador, em que posso ajuda-lo?
78
Exer
ios
4.1: Escreva um programa que declare variveis do tipo int, char e float,
inicialize-as, e imprima os seus valores.
4.2: Escreva um programa que defina variveis do tipo int e armazene nelas
constantes octais e hexadecimais e imprima o seu contedo no formato original
e em formato decimal.
4.3: Faa um programa que leia um valor inteiro no formato decimal e escreva,
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
casa decimal.
4.5: Faa um programa que leia trs palavras de at 10 letras e reescreva estas
palavras alinhadas direita da tela.
4.6: Sabendo que os argumentos da funo printf podem ser expresses (a+b,
a/b, a*b, 3*a...), e no somente argumentos, faa um programa capaz de ler
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 aritm-
tica destes nmeros.
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 quilome-
tragem anterior, os litros consumidos e informe a taxa de consumo (quilmetros
por litro) de um automvel.
4.10: Escreva um programa que converta uma temperatura de Farenheit para
Celsius.
4.11: Escreva um programa que, dado o permetro de um crculo, calcule sua
rea.
4.12: Faa um programa que utilize a funo gets para ler duas cadeias de
tamanho at 20 e em seguia s reescreva na linha de baixo, uma ao lado da
outra e separadas por "/-/ ";
79
Captulo 5
Operadores e Expresses
5.1 Introduo
O objetivo deste captulo apresentar os operadores existentes na linguagem
C e a forma correta de construir expresses que envolvam estes operadores,
constantes e variveis.
80
5.3 Operadores Aritmti
os
A Tabela 5.1 mostra os operadores aritmticos e as suas ordens de precedncia.
81
notao da linguagem C. Observe o uso de parnteses para evitar ambigidades
que poderiam fazer com que a expresso fosse calculada erradamente.
Exemplo 5.4:
b
1. a + b+c = a + b/(b+c)
2. b2 + c2 = b*b + c*c
x
3. a+ cb
= x/(a+b/c)
82
comum representar verdadeiro por true e falso por false. Em C o valor
falso representado por 0 e verdadeiro por qualquer valor diferente de 0. A
seguir iremos mostrar os operadores lgicos existentes na linguagem C.
E lgico
int i = 3 , j = -5;
f l o a t z = 3.0;
int resultado ;
resultado = (10 > 5) && ( i > -5) && ( z != 0) ;
printf ( " O resultado e vale % d . " , resultado ) ;
p q p && q
0 0 0
0 1 0
1 0 0
1 1 1
OU lgico
f l o a t x = 3.0;
int n = 55 , i = 0;
int resultado ;
resultado = ( i != 0) || ( x == 0) || ( n < 100) ;
printf ( " O resultado e % d " , resultado ) ;
83
p q p || q
0 0 0
0 1 1
1 0 1
1 1 1
No lgico
p !p
0 1
1 0
Operador Prioridade
! 0
>, >=, <, <= 1
==, != 2
&& 3
|| 4
84
5.5 Operadores
om Bits
Para operaes com bits, a linguagem C dispe de alguns operadores que podem
ser usados nos tipos char, int, long e long long mas no podem ser usados
em float, double, long double e void. A diferena entre estes operadores
e os lgicos que estes operam em pares de bits enquanto que os operadores
lgicos anteriores consideram a palavra toda. Por exemplo, para um valor int
ser falso necessrio que todos os 32 bits sejam iguais a zero. Os operadores
em bits esto mostrados na Tabela 5.7.
[fragile]Operadores com bits
p q p ^ q
0 0 0
0 1 1
1 0 1
1 1 0
Observaes:
85
Um deslocamento para a direita equivalente a uma diviso por 2. Deslo-
camento para a esquerda equivalente a uma multiplicao por 2. Assim
a = a * 2; e a = a 1; so equivalentes.
return 0;
}
86
raiz = raiz * 4;
raiz *= 4;
soma = soma / ( a + b);
soma /= (a + b);
a = a 1;
a = 1;
i = i % 2;
i %= 2;
y = ( x =5 , x +2) ;
87
Listagem 5.2: Exemplo do operador sizeof.
#define DIM 10
#in
lude < stdio .h >
#in
lude <
onio .h >
int main () {
int i =0;
f l o a t f =3.0;
har
= 'a ';
int 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
har % d \ n " , s i z e o f
) ;
printf ( " Tamanho do vetor de % d inteiros % d \ n " ,
DIM , s i z e o f ( v ) ) ;
return 0;
}
88
outro convertido para long e o resultado long. Caso contrrio, se algum
dos operandos unsigned, o outro convertido para unsigned e o resultado
deste tipo. Caso contrrio os operandos so int e o resultado int. Note que
todos os floats em uma expresso so convertidos para double e a expresso
avaliada em double.
O resultado de uma expresso convertido para o tipo da varivel onde o re-
sultado ser armazenado. Um resultado float ao ser carregado em uma varivel
do tipo int causa o truncamento da parte fracionria, porventura existente.
A converso de inteiro para caractere bem comportada, mas o contrrio
nem sempre ocorre convenientemente. A linguagem no especifica se o tipo
char um tipo com sinal ou no. Quando um caractere armazenado em uma
varivel do tipo inteiro podem ocorrer problemas com caracteres que tm o bit
mais esquerda igual a 1. Isto porque algumas arquiteturas podem estender
este bit e outras no.
89
Exer
ios
5.1: Escreva as expresses C abaixo na sua forma matemtica usual:
1. (a/b)*(c/d)
2. (a/b*c/d)
3. (a/(b*c)/d)
4. a*x*x+b*x+c
1. b2 4 b c
1
2. 1+ 1
1+ 1
1+x
a+b
3. c+d
x
4. a c+d
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));
90
Listagem 5.3: Variveis da questo 9.
f l o a t salario ;
int 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)
91
Captulo 6
Comandos de Controle
6.1 Introduo
Este captulo tem por objetivo apresentar os comandos de controle da linguagem
C. Estes comandos servem para controlar o fluxo de execuo das instrues
de um programa. Estes comandos permitem que o computador tome decises
independentemente do usurio que est rodando o programa.
/* blo
o_de_
o ma nd o s */
{
i = 0;
j = j + 1;
printf ( " % d % d \ n " , i , j ) ;
}
92
so baseados em estados internos disponveis ao processador. Estes estados
podem ser resultantes de uma operao aritmtica anterior, de uma operao
anterior etc.
6.3.1 Comando if
O comando if utilizado quando for necessrio escolher entre dois caminhos.
A forma geral do comando if a seguinte:
if ( expresso )
blo
o_de_
o ma n do s 1 ;
else
blo
o_de_
o ma n do s 2 ;
if ( expresso )
blo
o_de_
om a nd o s ;
if ( expresso )
blo
o_de_
o ma nd o s
e l s e i f ( expresso1 )
blo
o_de_
o m an d os 1
e l s e i f ( expresso2 )
blo
o_de_
o ma nd o s2
...
else
blo
o_de_
o ma nd o sn
93
Listagem 6.1: Exemplo de comandos if.
s
anf ( " % d " , & dia ) ;
i f ( dia > 31 || dia < 1 )
printf ( " Dia invalido \ n " ) ;
if ( expresso )
blo
o_de_
om a nd o s ;
e l s e i f ( expresso )
blo
o_de_
om a nd o s ;
e l s e i f ( expresso )
blo
o_de_
om a nd o s ;
...
e l s e blo
o_de_
o ma n do s ;
94
Listagem 6.2: Programas com ifs em escada e aninhados.
#in
lude < stdio .h >
int main ( void ) {
f l o a t num1 , /* primeiro operando */
num2 , /* segundo operando */
res ; /* resultado da opera
ao */
har oper ; /*
ara
tere que define a opera
ao */
95
a escrita de trechos de programa em que a seleo deve ser feita entre vrias
alternativas.
A forma geral do comando switch a seguinte:
swit
h ( expresso ) {
ase
onstante1 :
seqn
ia_ d e _
o ma n d os ;
break ;
ase
onstante2 :
seqn
ia_ d e _
o ma n d os ;
break ;
ase
onstante3 :
seqn
ia_ d e _
o ma n d os ;
break ;
...
default :
seqn
ia_ d e_
om a n do s ;
}
1. A expresso avaliada;
2. O resultado da expresso comparado com os valores das constantes que
aparecem nos comandos case;
3. Quando o resultado da expresso for igual a uma das constantes, a e-
xecuo se inicia a partir do comando associado com esta constante. A
execuo continua at o fim do comando switch, ou at que um comando
break seja encontrado;
4. Caso no ocorra nenhuma coincidncia os comandos associados ao co-
mando default so executados. O comando default opcional, e se ele
no aparecer nenhum comando ser executado.
96
Notar que caso no aparea um comando de desvio, todas as instrues
seguintes ao teste case que teve sucesso sero executadas, mesmo as que
estejam relacionadas com outros testes case;
O comando switch s pode testar igualdade;
No podem aparecer duas constantes iguais em um case;
97
Listagem 6.3: Exemplo de switch.
#in
lude < stdio .h >
int main ( void ) {
float num1 , /* primeiro operando */
num2 , /* segundo operando */
res ; /* resultado da opera
ao */
har oper ; /*
ara
ter que define a opera
ao
*/
98
Listagem 6.4: Exemplo de comando ternrio.
#in
lude < stdio .h >
int main ( void ) {
float num1 , /* primeiro operando */
num2 , /* segundo operando */
max ; /* resultado da opera
ao */
1. A expresso1 avaliada;
2. A expresso2 avaliada para determinar se o comando deve ser execu-
tado;
3. Se o resultado da expresso2 for verdadeiro o bloco de comandos
executado, caso contrrio o lao terminado;
4. A expresso3 avaliada;
5. Voltar para o passo 2.
99
Listagem 6.5: Exemplo de comando for.
#in
lude < stdio .h >
#in
lude < stdlib .h >
int main () {
int numero , fat =1 , i ;
printf ( " \ nEntre
om um numero positivo . " ) ;
s
anf ( " % d " , & numero ) ;
for ( i = numero ; i >1; i - -) fat = fat * i ;
printf ( " O fatorial de % u vale % u . " , numero , fat ) ;
return 0;
}
int i,j;
for ( i =1 , j = 10; i <= 10; i ++ , j += 10) {
printf ( " i = %d , j = % d \ n " , i , j ) ;
}
Listagem 6.6: Exemplo de comando for com testes sobre outras variveis.
#in
lude < stdio .h >
int main () {
har
= ' ';
int i ;
for ( i =0 ; (i <5) && (
!= '* ') ; i ++ ) {
printf ( " %
\ n " ,
) ;
= get
har () ;
}
return 0;
}
Um outro ponto importante do for que nem todas as expresses precisam estar
presentes. No exemplo 6.7 a varivel de controle no incrementada. A nica
100
maneira do programa terminar o usurio bater o nmero -1.
Lao infinito
for ( ; ; ) {
printf ( " \ nVo
e quer parar ?\ n " ) ;
= get
har () ;
i f (
== 'S ' ||
== 's ') break ;
}
101
Laos for aninhados
Uma importante construo aparece quando colocamos como comando a ser re-
petido um outro comando for. Esta construo pode aparecer quando estamos
trabalhando com matrizes. O exemplo 6.9 mostra um programa que imprime
uma tabuada.
while ( expresso )
blo
o_de_
o ma nd o s
1. A expresso avaliada;
2. Se o resultado for verdadeiro ento o bloco de comandos executado,
caso contrrio a execuo do bloco terminada;
3. Voltar para o passo 1.
Uma caracterstica do comando while, como pode ser visto dos passos acima,
que o bloco de comandos pode no ser executado caso a condio seja igual a
falso logo no primeiro teste.
O trecho de abaixo imprime os 100 primeiros nmeros usando um comando
while.
102
i = 1;
while ( i <= 100) {
printf ( " Numero % d \ n " , i ) ;
i ++;
}
do
blo
o_de_
o ma nd o s
while ( expresso ) ;
1. Executa o comando;
2. Avalia a expresso;
3. Se o resultado da expresso for verdadeiro ento volta para o passo 1,
caso contrrio interrompe o do-while
103
i = 1;
do {
printf ( " Numero % d \ n " , i ) ;
i ++;
} while ( i <= 100) ;
104
desvio indicado por um rtulo, que um identificador vlido em C seguido por
dois pontos. importante notar que o comando goto e o ponto para onde ser
feito o desvio pode estar em qualquer ponto dentro da mesma funo. A forma
geral deste comando :
goto rtulo;
...
rtulo:
Este comando durante muito tempo foi associado a programas ilegveis. O
argumento para esta afirmao se baseia no fato de que programas com coman-
dos goto perdem a organizao e estrutura porque o fluxo de execuo pode
ficar saltando erraticamente de um ponto para outro. Atualmente as restries
ao uso do comando tem diminudo e seu uso pode ser admitido em alguns casos.
105
Exer
ios
6.1: Escreva um programa que calcule x elevado a n. Assuma que n um valor
inteiro.
6.5: Utilizando um lao for dentro de outro, escreva um programa que exiba
as tabuadas de multiplicao dos nmeros de 1 9.
6.13: Escreva um programa que leia um numero do teclado e ache todos os seus
divisores.
106
No use nenhuma constante, use apenas variveis. Em outra linha imprima
as letras maisculas de A at Z (ABCD...).
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 possvel
ver todos os nmeros pouco a pouco. Solicite que seja pressionada alguma tecla
para ver a prxima seqncia de nmeros.
6.16:
Escreva um programa que imprima uma figura como a mostrada abaixo. O
nmero de linhas da figura deve ser pedido ao usurio.
******
*****
****
***
**
*
6.17: O que ser impresso pelo programa 6.11. Indique os nmeros que voc
ir digitar para o programa. Os nmeros devem ser todos diferentes.
107
Listagem 6.11: Programa do exercicio 17.
#in
lude < stdio .h >
int main ( void ) {
int i , j , m ;
for ( i = 0; i < 6; i ++) {
s
anf ( " % d " , & m ) ;
i f ( m % 2) {
for ( j = 0; j < m ; j ++) {
printf ( " # " ) ;
}
}
else {
for ( j = m ; j > 0; j - -) {
printf ( " * " ) ;
}
}
printf ( " \ n " ) ;
}
return 0;
}
108
Captulo 7
Vetores e Cadeias de
Cara
teres
7.1 Introduo
Vetores so usados para tratamento de conjuntos de dados que possuem as
mesmas caractersticas. Uma das vantagens de usar vetores que o conjunto
recebe um nome comum e elementos deste conjunto so referenciados atravs
de ndices. Pelo nome vetor estaremos referenciando estruturas que podem
ter mais de uma dimenso, como por exemplo matrizes de duas dimenses.
Neste captulo estaremos mostrando vetores de tamanhos fixos. Somente aps
apresentarmos ponteiros iremos abordar alocao de memria para vetores.
109
variveis, ou mesmo em trechos de cdigo. tarefa do programador fazer com
que os ndices dos vetores estejam sempre dentro dos limites estabelecidos pela
declarao do vetor.
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 definir
uma constante, que posteriormente foi usada para estabelecer o tamanho do
vetor. Esta constante passa a ser usada nas referncias ao vetor, por exem-
plo no comando de gerao do conjunto de dados armazenado no vetor. Caso
seja necessrio trocar o tamanho do vetor basta alterar o valor da constante e
recompilar o programa.
/* Gera
ao do
onjunto */
for ( i = 0 ; i < DIM ; i ++) vetor [ i = num ++;
/* Impressao do
onjunto */
for ( i = 0; i < DIM ; i ++)
printf ( " Elemento % d = % d \ n " , i , vetor [ i ) ;
return 0;
}
110
Listagem 7.2: Produto escalar de dois vetores.
#define DIM 5
#in
lude < stdio .h >
int main ( void ) {
int vetor1 [ DIM , vetor2 [ DIM , i , prod =0;
printf ( " Entre
om um vetor de % d elementos \ n " , DIM ) ;
for ( i = 0; i < DIM ; i ++) {
printf ( " Elemento % d " , i ) ;
s
anf ( " % d " , & vetor1 [ i ) ;
}
printf ( " Entre
om outro vetor de % d elementos \ n " , DIM )
;
for ( i = 0; i < DIM ; i ++) {
printf ( " Elemento % d " , i ) ;
s
anf ( " % d " , & vetor2 [ i ) ;
}
for ( i = 0; i < DIM ; i ++)
prod += vetor1 [ i * vetor2 [ i ;
printf ( " O produto vale % d " , prod ) ;
return 0;
}
111
Operao v[0] v[1] v[2] v[3] v[4]
Passo 1
v[0] > v[1]? 20 15 8 12 5
Trocar v[0] e v[1] 15 20 8 12 5
v[1] > v[2]? 15 20 8 12 5
Trocar v[1] e v[2] 15 8 20 12 5
v[2] > v[3]? 15 8 20 12 5
Trocar v[2] e v[3] 15 8 12 20 5
v[3] > v[4]? 15 8 12 20 5
Trocar v[3] e v[4] 15 8 12 5 20
Passo 2
v[0] > v[1]? 15 8 12 5 20
Trocar v[0] e v[1] 8 15 12 5 20
v[1] > v[2]? 8 15 12 5 20
Trocar v[1] e v[2] 8 12 15 5 20
v[2] > v[3]? 8 12 15 5 20
Trocar v[2] e v[3] 8 12 5 15 20
Passo 3
v[0] > v[1]? 8 12 5 15 20
v[1] > v[2]? 8 12 5 15 20
Trocar v[1] e v[2] 8 5 12 15 20
Passo 4
v[0] > v[1]? 8 5 12 15 20
Trocar v[0] e v[1]? 5 8 12 15 20
112
Listagem 7.3: Ordenao pelo mtodo da bolha.
#define DIM 5
#define FALSO 0
#define VERDADE 1
do {
tro
ou = FALSO ;
for ( 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 ;
tro
ou = VERDADE ;
}
}
fim - -;
} while ( tro
ou ) ;
return 0;
}
113
7.3 Cadeias de Cara
teres
Um cadeia de caracteres (string) um conjunto de caracteres terminado por um
caractere nulo, que representado como \0. Para especificar um vetor para
armazenar um cadeia deve-se sempre reservar um espao para este caractere.
Por exemplo, para armazenar um cadeia de 40 caracteres deve-se reservar um
vetor de 41 de caracteres. Em C possvel haver constantes cadeia, que so
definidas como uma lista de caracteres entre aspas. Por exemplo,
"programando em C"
No necessrio a colocao do caractere nulo ao final da cadeia. Em C
no h o tipo cadeia (string) e, portanto, conjuntos de caracteres teriam de
ser tratados como conjuntos de nmeros inteiros, por exemplo. Para facilitar a
programao foram criadas algumas funes para manipular cadeias. Algumas
das funes mais comuns esto resumidamente descritas a seguir:
Nas definies a seguir, size_t o tipo inteiro sem sinal que volta como
resultado do operador sizeof.
har *str
at(
har *dest,
onst
har *orig): Concatena cadeia orig ao
final de dest. O primeiro caractere de orig substitui o caractere nulo de
dest. A funo retorna o valor de dest.
har *strn
at (
har *dest,
onst
har *orig, size_t n): Concatena ca-
deia orig ao final de dest, usando no mximo n caracteres de orig. O
primeiro caractere de orig substitui o caractere nulo de dest. A funo
retorna o valor de dest.
har *str
mp (
onst
har *
ad1,
onst
har *
ad2): Compara lexico-
graficamente as duas cadeias. Retorna zero se as cadeias so iguais, menor
que 0 se
ad1 <
ad2, maior que 0 se
ad1 >
ad2.
har *strn
mp (
onst
har *
ad1,
onst
har *
ad2, size_t n): Com-
para lexicograficamente at n caracteres das duas cadeias. Retorna zero se
as cadeias so iguais, menor que 0 se
ad1 <
ad2, maior que 0 se
ad1
>
ad2.
114
strcat, e esta razo das aspas, ou seja, uma cadeia de um caractere apenas.
A seguir mostramos um resultado da execuo do programa 7.4.
Entre com um nome Ze
Ze
Entre com um sobrenome Sa
Sa
Ze Sa
Qual caracter? a
O caractere aparece na posicao 4
115
7.4 De
larao de Vetores Multidimensionais
Em C existe a possibilidade de declararmos vetores de mais de uma dimenso.
A forma geral da declarao a seguinte:
tipo nome [dim1][dim2][dim3]...[dimN];
onde dimI o tamanho da dimenso I. Deve-se tomar cuidado com armaze-
namento de matrizes multidimensionais, por que a memria necessria para
guardar estes dados igual a
sizeof(tipo)*dim1*dim2*dim3*...*dimN
Por exemplo a declarao
int matriz[10[20;
define uma matriz quadrada de 10 linhas por 20 colunas, enquanto o comando
= 2 * matriz[3[8;
armazena o dobro do elemento que est na quarta linha e nona coluna na varivel
c. Observar que o primeiro ndice indica a linha e o segundo a coluna. Lembrar
que o nmero da primeira linha (coluna) igual a 0. O programa 7.5 l uma
matriz de trs linhas e cinco colunas e imprime os valores lidos.
116
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]
C1
X
M Rij = M 1ik M 2kj (7.1)
k=1
117
Listagem 7.6: Multiplicao de duas matrizes.
#in
lude < stdio .h >
#define L1 3
#define L2 3
#define C1 3
#define C2 3
118
Listagem 7.7: Leitura de um vetor de nomes.
#define DIML 5
#define DIMC 41
#in
lude < stdio .h >
#in
lude < string .h >
int main ( void ) {
int i ;
har nomes [ DIML [ DIMC ;
for ( i =0; i < DIML ; i ++) {
printf ( " Entre
om a linha % d " , i ) ;
fgets ( nomes [ i , DIMC -1 , stdin ) ;
nomes [ i [ strlen ( nomes [ i ) -1 = ' \0 ';
}
return 0;
}
119
Listagem 7.8: Exemplos de tratamento de vetores.
#define DIM 5
#in
lude < stdio .h >
int main () {
int vetor [ DIM = {10 , 15 , 20 , 25 , 30};
int vetor1 [ = {10 , 20 , 30 , 40 , 50 , 60 , -1};
int vetor2 [ = {3 , 6 , 9 , 12 , 15 , 18 , 21 , 24};
unsigned int i , tam ;
printf ( " Este programa imprime vetores " ) ;
printf ( "
ontendo numeros inteiros e \ n " ) ;
printf ( " que foram ini
ializado s durante " ) ;
printf ( " a sua de
lara
ao .\ n " ) ;
return 0;
}
120
reservar memria de maneira adequada. A primeira dimenso somente especifica
quantos elementos o vetor ir armazenar e isto lendo a inicializao o compilador
pode descobrir.
A declarao a seguir ilustra como declarar e inicializar uma matriz de trs
linhas por quatro colunas de nmeros reais.
printf ( " Qual a dis
iplina ? " ) ; s
anf ( " % d " , & i ) ;
puts ( dis
iplinas [ i ) ;
return 0;
}
121
Exer
ios
7.1: Escreva um programa que leia uma linha de at 80 caracteres do teclado 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.
O programa tambm deve imprimir em que posies o caractere foi encontrado.
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
posies o par foi encontrado. Obs. No use funes da biblioteca de strings
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.
7.5: O imperador romano Csar usava um sistema simples para codificar as
mensagens que enviava aos seus generais. Neste sistema cada letra era substi-
tuda por trs letras frente no alfabeto. A sua misso mais simples ainda,
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
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.
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
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
devem ser retirados da frase. Considere o seguinte exemplo.
1. Frase lida:
EVA VIU A UVA
2. Retirada dos espaos em branco:
EVAVIUAUVA
3. Diviso em blocos de 5 (blocos indicados por tipos diferentes):
EVAVIUAUVA
4. Criptografia:
FYDANVCYAF
122
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
so sempre separadas por um branco.
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
somente em letras maisculas. Assuma tambm que os nomes tm no mximo
40 caracteres e sero lidos 10 nomes ao todo.
7.14: Considere que voc digitou o seu nome para o programa mostrado na
listagem 7.10. O que ser impresso? Indique o que voc digitou. Justifique
sua resposta com detalhes.
123
Listagem 7.10: Programa do exercicio 14.
#in
lude < stdio .h >
#in
lude < string .h >
#define MAX 50
int main ( void ) {
har texto [ MAX +2 , temp ;
int tam , i ;
gets ( texto ) ;
tam = strlen ( texto ) ;
for ( i = 0; i < tam ; i ++) {
temp = texto [ i ;
texto [ i = texto [ tam -1 - i ;
texto [ strlen ( texto ) -1 - i = temp ;
}
puts ( texto ) ;
return 0;
}
124
Captulo 8
Funes
8.1 Introduo
Em C, diferentemente de outras linguagens como Pascal, todas as aes ocorrem
dentro de funes. Na linguagem C no h conceito de um programa principal, o
que existe uma funo chamada main que sempre a primeira a ser executada.
Um programa pode ser escrito apenas com a funo main e mais as funes
existentes nas bibliotecas da linguagem C. No entanto o uso de funes pode
facilitar o desenvolvimento de programas de diversas maneiras.
Em primeiro lugar temos as vantagens do reuso de cdigo desenvolvido por
outros programadores. As funes de entrada e sada so o exemplo mais direto
deste reuso. Em C no existem estes tipos de comandos como na maioria das
linguagens. Programas escritos em C usam funes de entrada e sada escritas
e testadas por outros programadores. Este reuso de cdigo apresenta vrias
vantagens. Primeiro, diminui o tempo de desenvolvimento do programas. Em
segundo lugar, como estas funes foram testadas por diversos usurios, a quan-
tidade de erros bastante reduzida. Estes fatores contribuem para a reduo
dos custos de desenvolvimento dos projetos.
Uma outra vantagem do uso de funes e a maior facilidade na diviso do
trabalho necessrio para construir um aplicativo. Funes podem ser desenvol-
vidas por programadores trabalhando independentemente. Para isto basta que
alguns acordos sejam feitos entre os programadores que iro programar a funo
e os que iro us-las. Estes acordos precisam definir que parmetros a funo
ir receber, que resultados ir fornecer e que operaes ela deve realizar sobre
estes parmetros para obter os resultados necessrios. Esta diviso do trabalho
concorre para acelerar o desenvolvimento dos programas e na reduo dos custos
deste desenvolvimento.
A diviso de um programa em funes tambm permite que os testes do
sistema completo sejam feitos mais facilmente e com mais garantia de correo.
Os programadores podem testar suas funes separadamente em testes menos
complexos, j que as funes normalmente so simples e tm requisitos menos
complicados de serem avaliados. Isto permite que muitos erros do sistema com-
pleto possam ser retirados antes que ele esteja completo. Normalmente testar
um programa complexo requer testes complexos.
125
Mesmo quando um programa desenvolvido por um nico programador a
sua diviso em funes traz vantagens, por dividir um trabalho complexo em
diversas fatias menores permitindo ao programador se concentrar a cada vez em
problemas mais simples.
Uma funo recebe uma lista de argumentos (nome1, nome2, ..., nomeN),
executa comandos com estes argumentos e pode retornar ou no um resultado
para a funo que chamou esta funo. A lista de argumentos, tambm cha-
mados de parmetros, uma lista, separada por vrgulas, de variveis com seus
tipos associados. No possvel usar uma nica definio de tipo para vrias
variveis. A lista de argumentos pode ser vazia, ou seja, a funo no recebe
nenhum argumento. O nome da funo pode ser qualquer identificador vlido.
O tipo que aparece antes do nome da funo especifica o tipo do resultado que
ser devolvido ao final da execuo da funo. Caso nenhum tipo seja especifi-
cado o compilador assume que um tipo inteiro retornado. O tipo void pode
ser usado para declarar funes que no retornam valor algum.
H basicamente duas maneiras de terminar a execuo de uma funo. Nor-
malmente usa-se o comando return para retornar o resultado da funo. Por-
tanto, quando o comando
return expresso;
for executado, o valor da expresso devolvido para a funo que chamou.
Quando no h valor para retornar o comando return no precisa ser usado e
a funo termina quando a chave que indica o trmino do corpo da funo
atingido.
Os parmetros so valores que a funo recebe para realizar as tarefas para
as quais foi programada. Por exemplo, uma funo que calcule a raiz quadrada
de um nmero do tipo oat , deve declarar como parmetro uma varivel deste
tipo para receber o valor.
importante notar que diferentemente de declaraes de variveis onde
podemos associar vrios nomes de variveis a uma declarao como em
int a, dia, mes, i;
na lista de parmetros necessrio associar um tipo a cada varivel como
no exemplo a seguir:
oat media (oat n1, oat n2, oat n3);
Neste exemplo, uma funo chamada media que do tipo oat , isto retorna
um resultado oat , recebe trs argumentos (n1, n2, n3) tambm do tipo oat .
126
Um ponto importante como usar a funo. Suponha que uma determinada
funo, A, deseje usar uma outra funo, B. A funo A deve colocar no local
desejado o nome da funo (B) e a lista de valores que deseja passar. Por
exemplo, um programador que deseje usar a funo media em seu programa
para calcular a mdia de trs valores, nota1, nota2 e nota3, deve escrever no
local onde quer que a mdia seja calculada o seguinte comando:
resultado = media(nota1, nota2, nota3);
onde resultado a varivel que vai receber a mdia calculada.
importante notar que o nome da funo pode aparecer em qualquer lugar
onde o nome de uma varivel apareceria. Alm disso os tipos e o nmero de
parmetros que aparecem na declarao da funo e na sua chamada devem
estar na mesma ordem e ser tipos equivalentes. Se os tipos so incompatveis,
o compilador no gera um erro, mas podem ser gerados avisos na compilao e
resultados estranhos.
Outro ponto importante a ser notado e que ser detalhado mais adiante
que os nomes das variveis nos programas que usam a funo media podem ser
diferentes dos nomes usados na definio da funo.
dentro de funes,
fora de todas as funes,
127
Listagem 8.1: Exemplo de prottipos.
#in
lude < stdio .h >
/* Prototipo da fun
ao */
int soma ( int a , int b ) ;
/* Fun
ao Prin
ipal */
int main () {
int a =5 , b =9;
printf ( " % d \ n " , soma (a , b ) ) ;
return 0;
}
/* Defini
ao da fun
ao */
int soma ( int a , int b ) {
return a + b ;
}
128
Listagem 8.2: Exemplos de variveis locais.
#in
lude < stdio .h >
return 0;
}
129
varivel somente existe dentro do bloco, pode-se controlar melhor o uso da
varivel, evitando erros de uso indevido da varivel.
int i;
130
8.5 Parmetros Formais
As variveis que aparecem na lista de parmetros da funo so chamadas de
parmetros formais da funo. Eles so criados no incio da execuo da funo
e destrudos no final. Parmetros so valores que as funes recebem da funo
que a chamou. Portanto, os parmetros permitem que uma funo passe valores
para outra. Normalmente os parmetros so inicializados durante a chamada da
funo, pois para isto foram criados. No entanto, as variveis que atuam como
parmetros so iguais a todas as outras e podem ser modificadas, operadas, etc,
sem nenhuma restrio. Parmetros podem ser passados para funes de duas
maneiras: passagem por valor ou passagem por referncia.
int main () {
f l o a t numero ;
int poten
ia ;
har linha [80;
puts ( " Entre
om um numero " ) ;
gets ( linha ) ; numero = atof ( linha ) ;
puts ( " Entre
om a poten
ia " ) ;
gets ( linha ) ; poten
ia = atoi ( linha ) ;
printf ( " \ n % f Elevado a % d e igual a % f \ n " ,
numero , poten
ia , Eleva ( numero , poten
ia ) ) ;
return 0;
}
131
Para ilustrar o fato de que somente o valor passado vamos usar o exemplo
8.6. Neste programa as variveis a e b recebem os valores 10 e 20 respectiva-
mente. Na funo tro
ar estes valores so recebidos e so trocados localmente.
Aps o retorno da funo, o programa imprime os valores originais das variveis,
j que estes no sofreram nenhuma alterao. O resultado da execuo deste
programa o seguinte:
a = 10, b = 20
return 0;
}
132
Listagem 8.7: Passagem de vetor com dimenses.
#in
lude < stdio .h >
#in
lude <
onio .h >
#define DIM 80
har
onta (
har v [ ,
har
);
int main () {
har
, linha [ DIM ;
int maius
ulas [26 , minus
ulas [26;
puts ( " Entre
om uma linha " ) ;
gets ( linha ) ;
for (
= 'a ';
<= 'z ';
++)
minus
ulas [
- 'a ' =
onta ( linha ,
) ;
for (
= 'A ';
<= 'Z ';
++)
maius
ulas [
- 'A ' =
onta ( linha ,
) ;
for (
= 'a ';
<= 'z ';
++)
i f ( minus
ulas [
- 'a ' )
printf ( " %
apare
eu % d vezes \ n " ,
, minus
ulas [
- 'a ' ) ;
for (
= 'A ';
<= 'Z ';
++)
i f ( maius
ulas [
- 'A ' )
printf ( " %
apare
eu % d vezes \ n " ,
, maius
ulas [
- 'A ' ) ;
return 0;
}
133
perfeitamente possvel porque a funo somente precisa receber o endereo onde
se encontra o vetor. Alm disso C no confere limites de vetores e portanto a
funo precisa do endereo inicial do vetor e uma maneira de descobrir o final
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.
A terceira maneira de passagem de parmetros implica no uso de ponteiros,
o que somente iremos ver no prximo captulo.
8.7 Re
urso
Funes em C podem ser usadas recursivamente, isto uma funo pode chamar
a si mesmo. como se procurssemos no dicionrio a definio da palavra
recurso e encontrssemos o seguinte texto:
recurso: s.f. Veja a definio em recurso
Um exemplo simples de funo que pode ser escrita com chamadas recursivas
o fatorial de um nmero inteiro. O fatorial de um nmero, sem recurso,
definido como
n! = n (n 1) (n 2) 2 1
n! = n (n 1)!
Deste modo podemos escrever uma funo recursiva em que cada chamada
da funo que calcula o fatorial chama a prpria funo fatorial. O exemplo,
mostrado na listagem 8.10 ilustra como a funo pode ser escrita recursivamente.
134
Listagem 8.8: Passagem de vetores sem dimenses.
#in
lude < stdio .h >
#in
lude <
onio .h >
#define DIM 6
void Le_vetor ( int v [ , int tam ) ;
void Imprime_vetor ( int v [ , int tam ) ;
void Inverte_vetor ( int v [ , int tam ) ;
int main () {
int v [ DIM ;
Le_vetor (v , DIM ) ;
Imprime_vetor (v , DIM ) ;
Inverte_vetor (v , DIM ) ;
Imprime_vetor (v , DIM ) ;
return 0;
}
135
Listagem 8.9: Fatorial calculado no recursivamente.
unsigned long int fat ( unsigned long int num ) {
unsigned long int fato =1 , i ;
return fato ;
}
136
Listagem 8.11: Chamada recursiva direta.
void f () {
/* ... */
f ()
/* ... */
}
como
xn = x x(n1)
que nos leva a escrever a funo da maneira mostrada no exemplo 8.13. Na
funo consideramos que x do tipo oat .
Para facilitar pode-se pensar que quando uma chamada recursiva feita, a
funo faz uma cpia de si mesmo, das variveis locais, com seus valores iniciais,
e dos parmetros.
Cada cpia da funo inclui uma marcao indicando o ponto atual onde a
funo est sendo executada. Quando uma chamada recursiva feita, o mar-
cador na funo que chamou fica logo aps a chamada. O marcador na funo
chamada vai para o incio da funo.
Quando a funo retorna, a cpia some, e a funo que chamou continua aps
a chamada, posio indicada pela marcao. As cpias anteriores continuam
sabendo de onde continuar porque as marcaes esto em suas posies.
137
Funes podem ser recursivas com cauda ou no. Em uma funo recursiva
com cauda, nenhuma das chamadas recursivas executam algo aps a chamada
recursiva completar, exceto para retornar o valor da funo.
A listagem 8.14 mostra o return de uma tpica funo recursiva com cauda e
a listagem 8.15 mostra uma sem cauda. A chamada sem cauda caracterizada
porque primeiro f feita e depois soma 5, portanto, algo executado aps a
chamada.
Caso bsico
Portanto, recurso um processo que quebra um problema em problemas
menores que sero quebrados em problemas menores at que chegamos no menor
problema possvel e na sua soluo (caso bsico) e retornamos esta soluo.
Uma vez que voc escreveu o prottipo, pense em como resolver o prximo
problema menor. Ento se a chamada
138
soma(vetor, n),
o prximo caso menor
soma(vetor, n-1)
Suponha que algum lhe daria a resposta para esta segunda soma. O que
voc teria? Voc teria a soma dos n1 primeiros elementos do vetor. Agora que
voc tem esta soluo (por hiptese), o que falta para resolver todo o problema?
Achar a soluo do caso base, que o menor problema. Neste exemplo seria:
sum(vetor, 1 );
Quanto falta apenas um elemento a soma a ser calculada o prprio ele-
mento. Deste modo a soluo para este problema fica como mostrado na lista-
gem 8.16.
139
Todavia, pela mesma razo, deve ser difcil resolver usar laos para resolver
o problema. Laos tambm dependem de fazer a mesma coisa diversas vezes,
em diferentes ndices.
Se voc conseguir resolver um problema por meio de um lao, deve ser pos-
svel resolve-lo por meio de recurso.
140
Listagem 8.17: Uso de argc e argv.
#in
lude < stdio .h >
#in
lude < stdlib .h >
unsigned long int fat ( unsigned long int num ) {
i f ( num == 0)
return 1;
else
return num * fat ( num -1) ;
}
int main ( int arg
,
har * argv [) {
unsigned long int numero , fatorial , i;
if ( arg
< 2) {
printf ( " Para rodar : % s num1 num2 ... .\ n " , argv
[0) ;
return 1;
}
for ( i =1; i < arg
; i ++) {
numero = ( unsigned long int ) ( atoi ( argv [ i ) ) ;
fatorial = fat ( numero ) ;
printf ( " O fatorial de % lu vale % lu .\ n " , numero ,
fatorial ) ;
}
return 0;
}
141
Exer
ios
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 inicializao do
vetor e a sua impresso devem ser feitas por funes.
8.3: Escreva um programa que armazene em uma matriz trs nomes de pessoas
e em seguida os imprima. Assuma que o tamanho mximo de cada nome 40
caracteres. Neste programa a leitura dos nomes dever ser feita por uma funo
e a impresso dos nomes por outra.
8.5: Escreva um programa que crie uma tabela de temperaturas Celsius - Fah-
renheit. O programa deve usar uma funo que converta de Celsius para Fah-
renheit. A tabela deve iniciar na temperatura 0 graus Celsius e terminar na
temperatura 100 graus Celsius.
8.6: Escreva um programa, usando funes, que gere um vetor a partir de uma
matriz. Cada elemento do vetor igual a soma dos elementos de uma das linhas
da matriz. Considere que a matriz tenha tamanho 10 por 10.
f (0) = 0
f (1) = 1
f (n) = f (n 1) + f (n 2)
142
Entre com um numero inteiro: 6
Fibonacci (6) = 8
8.8: O que o programa mostrado na listagem 8.18 imprime, caso sejam forne-
cidos os valores 48 e 256. Justifique a sua resposta.
143
Listagem 8.19: Programa do problema 9.
#in
lude < stdio .h >
#in
lude < string .h >
#in
lude < stdlib .h >
int fromHexatoD e
im a l (
har
[) ;
int toNumero (
har ) ;
har toLower (
har ) ;
int main ( void ) {
har numeroC [80;
fgets ( numeroC , 80 , stdin ) ;
while (! feof ( stdin ) ) {
numeroC [ strlen ( numeroC ) -1 = ' \0 ';
printf ( " % s = % d \ n " , numeroC , fromHexatoD e
i ma l (
numeroC ) ) ;
fgets ( numeroC , 80 , stdin ) ;
}
return 0;
}
int fromHexatoD e
im a l (
har numeroC [)
{ /* Aqui falta
odigo */ }
144
Captulo 9
Ponteiros
9.1 Introduo
Ponteiros so usados em situaes em que necessrio conhecer o endereo
onde est armazenada a varivel e no o seu contedo. Um ponteiro uma
varivel que contm um endereo de uma posio de memria e no o contedo
da posio. A memria de um computador pode ser vista como uma seqncia
de bytes cada um com seu prprio e nico endereo. No h dois bytes com
o mesmo endereo. O primeiro endereo sempre 0 e o ltimo geralmente
uma potncia de 2. Por exemplo um computador com memria igual a 512
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
cada uma e mais um ponteiro (pint), que tambm ocupa 4 bytes. Observar que
os endereos esto pulando de quatro em quatro bytes devido ao espao que
cada um destas variveis ocupa.
0
4 10 num
8 120 res
12 *pint
16
145
destas variveis, que aps o fim da funo estaro disponveis para a funo que
chamou. Neste caso os argumentos podem funcionar como entrada e sada de
dados da funo.
Uma outra aplicao importante de ponteiros apontar para reas de mem-
ria que devem ser gerenciadas durante a execuo do programa. Com ponteiros,
possvel reservar as posies de memria necessrias para armazenamento
destas reas somente quando for necessrio e no quando as variveis so decla-
radas. Neste esquema o programador pode reservar o nmero exato de posies
que o programa requer. A Figura 9.2 ilustra como um ponteiro faz referncia
para uma rea de memria. Na figura a varivel ponteiro pi aponta para a rea
de memria que contm um vetor de 10 inteiros. Com ponteiros, o programador
precisa, no incio, definir a varivel ponteiro e seu tipo. Durante a execuo do
programa, aps descobrir o tamanho do vetor, reserva a rea necessria para
guardar os dados. Observe a diferena do que ocorre quando se usa vetores de
tamanho fixo. Neste caso a definio do tamanho do vetor dada na declarao
do vetor e mantida at o final da execuo do programa.
0
1000 pi ponteiro
4 para vetor
8
1000 120
Vetor de
10 inteiros
1036 97
146
int * res ; /* ponteiro para inteiro */
f l o a t * div ; /* ponteiro para ponto flutuante */
996
147
0
4 10 num
8 120 res
12 4 *pint
16
comando res = *pint; foi executado logo aps pint = #. Isto significa que
a varivel res recebe o valor apontado por pint, ou seja a varivel res recebe o
valor 10, como est mostrado na Figura 9.5.
0
4 10 num
8 120 10 res = *pint
12 4 *pint
16
148
Figura 9.6 a situao da memria aps estas operaes. Alm disso no final o
endereo apontado por p1 carregado em p2. Os comandos printf imprimem os
valores apontados pelos ponteiros respectivos, mostrando os seguintes valores:
30
100
30
int * p1 , * p2 ;
int i = 100;
0
4 10 v[0]
8 20 v[1]
12 30 v[2]
16 40 v[3]
p1 = &v[2];
20 50 v[4]
24 12 *p1
28 32 *p2
p2 = &i;
32 100 i
149
9.2.4 In
rementando e De
rementando Ponteiros
O exemplo 9.2 mostra que operaes de incremento e decremento podem ser
aplicadas em operandos. O primeiro printf imprime 30, que o elemento de
ndice igual a 2 no vetor vetor. Aps o incremento do ponteiro o segundo
printf imprime 40 e o mesmo acontece com o terceiro printf que imprime 50.
Pode parecer estranho que um ponteiro para um nmero inteiro, que arma-
zenado em quatro bytes, seja incrementado por um e passe para apontar para
o prximo nmero inteiro. A primeira vista, para que passasse a apontar para
o prximo endereo, seria necessrio aumentar o endereo em quatro. Ou seja,
sempre que um ponteiro incrementado (decrementado) ele passa a apontar
para a posio do elemento seguinte (anterior). O compilador interpreta o co-
mando p1++ como: passe a apontar para o prximo nmero inteiro e, portanto,
aumenta o endereo do nmero de bytes correto. Este ajuste feito de acordo
com o tipo do operando que o ponteiro est apontando. Do mesmo modo, somar
trs a um ponteiro faz com que ele passe apontar para o terceiro elemento aps 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. ento possvel
somar-se e subtrair-se inteiros de ponteiros. A operao abaixo faz com que o
ponteiro p passe a apontar para o terceiro elemento aps o atual.
p = p + 3;
Tambm possvel usar-se o seguinte comando
*(p+1)=10;
Este comando armazena o valor 10 na posio seguinte quela apontada por
p. A operao realizada nos seguintes passos:
150
A diferena entre ponteiros fornece quantos elementos do tipo do ponteiro
existem entre os dois ponteiros. No exemplo 9.3 impresso o valor 2.
if (
== v )
printf ( " As variveis estao na mesma posi
ao . " ) ;
else
printf ( " As variaveis nao estao na mesma posi
ao . "
);
return 0;
}
151
9.3 Ponteiros e Vetores
Ponteiros e Vetores esto fortemente relacionados na linguagem C. O nome de
um vetor um ponteiro que aponta para a primeira posio do vetor. A decla-
rao int vetor[100 cria um vetor de inteiros de 100 posies e permite que
algumas operaes com ponteiros possam ser realizadas com a varivel vetor.
No entanto, existe uma diferena fundamental entre declarar um conjunto
de dados como um vetor ou atravs de um ponteiro. Na declarao de vetor,
o compilador automaticamente reserva um bloco de memria para que o vetor
seja armazenado. Quando apenas um ponteiro declarado a nica coisa que
o compilador faz alocar um ponteiro para apontar para a memria, sem que
espao seja reservado. O nome de um vetor chamado de ponteiro constante
e, portanto, no pode ter o seu valor alterado. O nome de um ponteiro cons-
tante no pode aparecer em expresses no lado esquerdo do sinal de igual, ou
seja, no pode receber valores diferentes do valor inicial atribudo na declarao
da varivel. Assim, os comandos que alteram o ponteiro list, mostrados no
exemplo 9.5, no so vlidos:
152
Para percorrer um vetor alm da maneira mostrada no programa 9.6 pos-
svel usar um ponteiro varivel como ilustrado no Programa 9.7. Observe como
o ponteiro p recebe seu valor inicial e a maneira como ele incrementado.
153
Listagem 9.8: Exemplo de ponteiro para cadeia de caracteres.
#in
lude < stdio .h >
int main ( void ) {
har *s , * lista = " 1234567890 " ;
int tam =0;
s = lista ;
while (*( s + tam ++) != ' \0 ') ;
tam - -;
printf ( " O tamanho do string \"% s \" e % d
ara
teres .\ n "
,
lista , tam ) ;
return 0;
}
void *mallo
(size_t size); Reserva espao na memria para algum item
de um programa. O tamanho em bytes reservado definido pela varivel size.
O valor armazenado no espao indefinido. A funo retorna um ponteiro de
tipo void para o espao reservado ou NULL no caso de algum erro ocorrer.
void *
allo
(size_t num, size_t size); Reserva espao na memria para
um vetor de num itens do programa. Cada item tem tamanho size e todos os
bits do espao so inicializados com 0. A funo retorna um ponteiro de tipo
void para o espao reservado ou NULL no caso de algum erro ocorrer.
void free(void *pont); O espao apontado por pont devolvido ao sistema
para uso. Caso pont seja um ponteiro nulo nenhuma ao executada. No caso
do ponteiro no ter sido resultado de uma reserva feita por meio de uma das
funes
allo
, reallo
ou mallo
o resultado indefinido.
void reallo
(void *pont, size_t size); A funo altera o tamanho do ob-
jeto na memria apontado por pont para o tamanho especificado por size. O
154
contedo do objeto ser mantido at um tamanho igual ao menor dos dois tama-
nhos, novo e antigo. Se o novo tamanho requerer movimento, o espao reservado
anteriormente liberado. Caso o novo tamanho for maior, o contedo da por-
o de memria reservada a mais ficar com um valor sem especificao. Se o
tamanho size for igual a 0 e pont no um ponteiro nulo o objeto previamente
reservado liberado.
Estas funes podem ser encontradas na biblioteca stdlib.h. O Programa
9.10 ilustra o uso das funo
allo
e free.
155
Listagem 9.11: Exemplo de uso de mallo
.
#in
lude < stdio .h >
#in
lude < stdlib .h >
void LeVetor ( f l o a t *v , int tam ) ;
f l o a t Pro
uraMaior ( f l o a t *v , int tam , int * vezes ) ;
int main ( void ) {
f l o a t *v , maior ;
int i , tam , vezes ;
printf ( " Qual o tamanho do vetor ? " ) ;
s
anf ( " % d " , & tam ) ;
v = ( f l o a t *) mallo
( tam * s i z e o f ( f l o a t ) ) ;
i f (v) {
LeVetor (v , tam ) ;
maior = Pro
uraMaior (v , tam , & vezes ) ;
printf ( " Maior = % f e apare
e % d vezes .\ n . " ,
maior , vezes ) ;
free ( v ) ;
}
else {
printf ( " Nao
onsegui alo
ar memoria . " ) ;
return 1;
}
return 0;
}
void LeVetor ( f l o a t *v , int tam ) {
int i ;
for ( i =0; i < tam ; i ++) {
printf ( " Elemento % d ? " , i ) ;
s
anf ( " % f " , v + i ) ;
printf ( " Li valor % f \ n " , *( v + i ) ) ;
}
}
float Pro
uraMaior ( f l o a t *v , int tam , int * vezes ) {
int i ;
f l o a t maior ;
maior = v [0; * vezes = 1;
for ( i =1; i < tam ; i ++) {
i f ( v [ i & gt ; maior ) {
maior = v [ i ;
* vezes = 1;
}
e l s e i f ( maior == v [ i ) * vezes =* vezes +1;
}
return maior ;
}
156
programa listado em 9.12. Caso o programa utilizasse ponteiros ao invs de
notao de matrizes, poderamos usar uma soluo que mapeasse a matriz que
um objeto de duas dimenses em um vetor que tem apenas uma. Neste caso
o programa deve fazer a translao de endereos toda vez que precisar ler ou
escrever na matriz. O trecho de programa ficaria como mostrado no exemplo
9.13. A expresso matriz+(i*COL+j) calcula a posio do elemento matriz
[i[j a partir do primeiro elemento da matriz que est no endereo inicial
matriz.
int * matriz ;
int i, j;
157
9.7 Vetores de Ponteiros
Uma possibilidade mais interessante utilizar vetores de ponteiros. Esta no
a notao ideal, mas um passo na direo da notao mais efetiva. Neste caso
cada linha da matriz corresponde a um vetor que apontado por um ponteiro
armazenado no vetor de ponteiros. Como ponteiros tambm so variveis
possvel ento criar vetores de ponteiros e utiliz-los. O exemplo mostrado em
9.14 mostra um programa onde utilizado um vetor de ponteiros para vrias
linhas de caracteres. Observe na funo main a declarao
har *linha[LINHAS
; que define um vetor de tamanho LINHAS. Este vetor contem ponteiros e no
valores. At este momento do programa temos apenas posies reservadas para
armazenar ponteiros. A alocao de espao e a inicializao dos ponteiros feito
no primeiro comando for. Como cada elemento do vetor linha um ponteiro
temos que o endereo retornado pela funo mallo
armazenado em cada
um dos elementos deste vetor. A leitura das linhas de caracteres feita pela
funo gets(linha[i) que passa o elemento do vetor onde os caracteres sero
armazenados.
158
9.8 Ponteiros para Ponteiros
No exemplo anterior podemos observar que o nmero de linhas da matriz
fixa, e portanto, h uma mistura de notao de ponteiros com matrizes. Va-
mos considerar um exemplo onde tanto o nmero de linhas como o de colunas
desconhecido. Neste exemplo iremos criar um vetor de ponteiros que ir ar-
mazenar o endereo inicial de cada linha. Portanto, para obter um elemento da
matriz primeiro devemos descobrir onde est a linha no vetor que armazena os
endereos das linhas, em seguida procuramos na linha o elemento. A Figura 9.7
ilustra como ser feito o armazenamento desta matriz.
Vetor de ponteiros linha 0
**matriz *(matriz+0)
*(matriz+1) linha 1
*(matriz+2)
linha 2
*(matriz+n)
linha n
159
Listagem 9.15: Exemplo de uso de ponteiros para ponteiros.
#in
lude < stdio .h >
#in
lude < stdlib .h >
int main ( void ) {
int ** matriz ; /* ponteiro para os ponteiros */
int lin ,
ol ; /* nmero de linhas e
olunas */
int i , j ;
int linha1 , linha2 ; /* linhas que serao tro
adas */
har linha [80; /* linha de
ara
teres
om os dados */
int * temp ;
puts ( " Qual o numero de linhas ? " ) ;
gets ( linha ) ; lin = atoi ( linha ) ;
matriz = ( int **) mallo
( lin * s i z e o f ( int *) ) ;
i f (! matriz ) {
puts ( " Nao h espao para alo
ar memria " ) ;
return 1;
}
puts ( " Qual o numero de
olunas ? " ) ;
gets ( linha ) ;
ol = atoi ( linha ) ;
for ( i =0; i < lin ; i ++) {
*( matriz + i ) = ( int *) mallo
(
ol * s i z e o f ( int ) )
;
i f (! *( matriz + i ) ) {
printf ( " Sem espao para alo
ar a linha % d " ,
i);
return 1;
}
}
puts ( " Entre
om os dados " ) ;}
for ( i =0; i < lin ; i ++) {
printf ( " Entre
om a linha % d \ n " , i ) ;
for ( j =0; j <
ol ; j ++) {
printf ( " Elemento % d % d \ n " , i , j ) ;
s
anf ( " % d " , *( matriz + i ) + j ) ;
}
}
puts ( " Qual a primeira linha a ser tro
ada ? " ) ;
gets ( linha ) ; linha1 = atoi ( linha ) ;
puts ( " Qual a segunda linha a ser tro
ada ? " ) ;
gets ( linha ) ; linha2 = atoi ( linha ) ;
temp = *( matriz + linha1 ) ;
*( matriz + linha1 ) = *( matriz + linha2 ) ;
*( matriz + linha2 ) = temp ;
puts ( " Dados tro
ados . " ) ;
for ( i =0; i < lin ; i ++) {
for ( j =0; j <
ol ; j ++) {
printf ( " %7 d " , *(*( matriz + i ) + j ) ) ;
}
printf ( " \ n " ) ;
}
return 0;
}
160
Listagem 9.16: Exemplo de uso de ponteiros para ponteiros usando funes.
#in
lude < stdio .h >
#in
lude < stdlib .h >}
int ** alo
a_linhas ( int ) ;
void alo
a_
olunas ( int ** , int , int ) ;
void le_dados ( int ** , int , int ) ;
void imprime_matri z ( int ** , int , int ) ;
void tro
a_linhas ( int ** , int , int ) ;
int main ( void ) {
int ** matriz ;
int lin ,
ol ;& nbsp ;& nbsp ;
int linha1 , linha2 ;
har linha [80;
puts ( " Qual o numero de linhas ? " ) ;
gets ( linha ) ; lin = atoi ( linha ) ;
matriz = alo
a_linhas ( lin ) ;
puts ( " Qual o numero de
olunas ? " ) ;
gets ( linha ) ;
ol = atoi ( linha ) ;
161
Listagem 9.17: Continuao do exemplo 9.16.
void le_dados ( int ** matriz , int lin , int
ol ) {
int i , j ;
puts ( " Entre
om os dados " ) ;
for ( i =0; i < lin ; i ++) {
printf ( " Entre
om a linha % d \ n " , i ) ;
for ( j =0; j <
ol ; j ++) {
printf ( " Elemento % d % d \ n " , i , j ) ;
s
anf ( " % d " , *( matriz + i ) + j ) ;
}
}
}
void imprime_matri z ( int ** matriz , int lin , int
ol ) {
int i , j ;
for ( i =0; i < lin ; i ++) {
for ( j =0; j <
ol ; j ++) {
printf ( " %7 d " , *(*( matriz + i ) + j ) ) ;
}
printf ( " \ n " ) ;
}
}
void tro
a_linhas ( int ** matriz , int linha1 , int linha2 ) {
int * temp ;
temp = *( matriz + linha1 ) ;
*( matriz + linha1 ) = *( matriz + linha2 ) ;
*( matriz + linha2 ) = temp ;
}
162
Exer
ios
9.1: Escreva um programa que gere um vetor de trs dimenses (X, Y e Z) em
que cada posio guarda a soma de suas coordenadas. As dimenses da matriz
devero ser determinadas em tempo de execuo e o programa dever informar
os valores gerados.
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 posio. Os nmeros das linhas a serem trocadas devem ser
lidos do teclado.
9.5: Escreva um programa que simule uma pilha usando vetores. O programa
deve implementar as seguintes operaes na pilha:
Inserir
Remover
Listar
9.6: Escreva uma funo que receba um ponteiro para uma cadeia de caractere
e troque todo o caracter aps um branco pelo seu equivalente maisculo.
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 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 funo posi
ao que tem
o seguinte prottipo:
int posi
ao(
har *substr,
har *str);
Esta funo deve verificar se a cadeia apontada por substr est presente na
cadeia apontada por str e retornar a posio em que a sub-cadeia aparece em
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
devem ser pedidas ao usurio.
163
Listagem 9.18: Programa do exercicio 11.
#in
lude < string .h >
#in
lude < stdio .h >
#define MAX 80
return 0;
}
if (* p1 != ' \0 ') {
while (* p1 != ' \0 ') {
put
har (* p1 ) ;
p1 = p1 + 1;
}
}
if (* p2 != ' \0 ') {
while (* p2 != ' \0 ') {
put
har (* p2 ) ;
p2 = p2 + 1;
}
}
}
164
9.11: O que ser impresso pelo programa mostrado na listagem 9.18 caso a
primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ltimo
sobrenome.
9.12: O que ser impresso pelo programa mostrado na listagem 9.19 caso a
primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ltimo
sobrenome. Indique os nomes que usou e justifique a sua resposta.
9.13: O que ser impresso pelo programa 9.20. Justifique sua resposta.
9.14: O que ser impresso pelo programa mostrado na listagem 9.21. Justifique
sua resposta.
165
Listagem 9.20: Listagem do exerccio 13.
#in
lude < stdio .h >
#in
lude < string .h >
int main ( void ) {
har * frase = " Otimo teste " ;
har *p , misterio [80;
int i = 0;
int j = 0;
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;
}
166
Listagem 9.21: Programa do exerccio 14.
#in
lude < stdio .h >
void f1 ( int v ) {
v = v + 1;
printf ( " f1 = % d \ n " , v ) ;
}
void f2 ( int * v ) {
* v = * v + 1;
printf ( " f2 = % d \ n " , * v ) ;
}
int f3 ( int v ) {
v = v + 1;
printf ( " f3 = % d \ n " , v ) ;
return v ;
}
int main ( void ) {
int v = 1;
f1 ( v ) ;
f2 (& v ) ;
v = f3 ( v ) ;
printf ( " main = % d \ n " , v ) ;
return 0;
}
167
Captulo 10
Estruturas
10.1 Introduo
Uma estrutura um conjunto de uma ou mais variveis, que podem ser de ti-
pos diferentes, agrupadas sob um nico nome. O fato de variveis agrupadas
em uma estrutura poderem ser referenciadas por um nico nome facilita a ma-
nipulao dos dados armazenados nestas estruturas. Um exemplo poderia ser
uma estrutura que armazenasse as diversas informaes sobre os alunos de uma
Universidade. Nesta estrutura estariam armazenadas, sob o mesmo nome, in-
formaes do tipo: nome, registro, data de nascimento, data de ingresso, CPF,
etc. Uma estrutura pode incluir outras estruturas alm de variveis simples.
As estruturas facilitam manipular estes agrupamentos complexos de dados. Por
exemplo, considere o problema de ordenar as informaes sobre os alunos da
Universidade exemplo. A ordenao pode ser efetuada como se todos os dados
que compem a estrutura fossem uma entidade nica.
168
Listagem 10.1: Definio de uma estrutura.
stru
t ALUNO {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
};
stru
t ALUNO {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
} paulo ,
arlos , ana ;
stru
t DATA {
int dia , mes , ano ;
};
Agora vamos modificar a estrutura aluno de modo que ela inclua a data de
nascimento do aluno. A estrutura fica com a seguinte definio:
169
stru
t aluno {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
stru
t DATA data_nas
im en to ;
};
Ao mesmo tempo que typedef tem a vantagem de tornar mais claro a fina-
lidade de cada varivel ele pode trazer problemas na medida em que esconde o
real tipo da varivel.
comum o uso de typedef em conjunto com stru
t. Considere a definio
de uma estrutura para guardar tempos gastos em tarefas. Esta estrutura deve
guardar horas, minutos e segundos. Usando esta combinao, a definio
usualmente feita da seguinte maneira:
stru
t _TEMPO {
int hora , minuto , segundo ;
};
typedef stru
t _TEMPO TEMPO ;
...
TEMPO t1 ;
Uma forma ainda mais abreviada, junta as duas definies, ficando a defini-
o da estrutura da seguinte maneira:
170
...
TEMPO t1 ;
typedef stru
t {
int hora , minuto , segundo ;
} TEMPO ;
...
TEMPO t1 ;
int main () {
EMPREGADO temp , emp1 ;
171
tipo stru
t ALUNO.
O exemplo 10.3 mostra atribuies entre estruturas e operaes aritmticas
envolvendo membros de estruturas. O programa coloca um vetor de estrutu-
ras em ordem crescente usando como chave de ordenao um dos membros da
estrutura (media).
stru
t aluno {
har nome [40;
172
Listagem 10.3: Ordenao de Estruturas.
#in
lude < stdio .h >
#in
lude < string .h >
173
Listagem 10.4: Passando elementos para funes.
#in
lude < stdio .h >
typedef stru
t _CIRCULO {
f l o a t x , y , raio ;
} CIRCULO ;
float Area ( f l o a t r ) {
return 3.141516 * r * r ;
}
174
Listagem 10.6: Funo que ordena estruturas.
void Ordena ( ALUNO turma [ , int tam ) {
int i , foraOrdem , jaOrdenados = 0;
ALUNO temp ;
do {
foraOrdem = 0;
for ( 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 ) ;
}
int ano_entrada ;
f l o a t n1 , n2 , media ;
} * maria ;
Para alocar espao para estruturas apontadas por ponteiros necessrio usar
o operador unrio sizeof, isto porque o tamanho de uma estrutura sempre
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
computadores.
Algumas arquiteturas de computadores endeream os dados na memria por
bytes, isto cada endereo de memria se refere a um byte. No entanto, estas
arquiteturas lem sempre uma palavra inteira da memria. Usualmente, pala-
vras podem ser compostas de dois bytes e comeam em endereos pares, como
est mostrado na figura abaixo. Sabemos que existem variveis que ocupam
mais de um byte, por exemplo inteiros que so compostos de dois bytes.
175
Imagine ento uma estrutura composta de um caractere (1 byte) e um n-
mero inteiro (4 bytes). Caso a memria do computador fosse organizada em
palavras de 32 bits ou 4 bytes, e os dados fosse alocados sequencialmente byte a
byte, a estrutura acima ocuparia 5 bytes ou duas palavras, conforme esta mos-
trado na Figura 10.1a. Para ler o nmero inteiro o programa deveria ler duas
palavras. Para facilitar o acesso s variveis, alguns compiladores armazenam as
variveis de acordo com o que est indicado na Figura 10.1b. Observar que agora
a estrutura ocupa oito bytes e trs so perdidos. Neste caso o acesso ao nmero
inteiro ser sempre feito em um passo e portanto ganhou-se em tempo de acesso
ao custo de gasto de memria. Este uma troca constante em computao.
8 8
12 12
16 16
N N
Vimos ento que embora o total de bytes dos elementos da estrutura fosse
trs o compilador pode armazenar a estrutura em quatro bytes, da a necessidade
de sempre usar o operador sizeof quando alocar espao.
O programa 10.7 mostra como alocar espao para uma varivel simples e
como usar esta varivel em diversos tipos de comandos.
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 notaes
usadas na funo que l os dados dos funcionrios. Notar que (
adastro+i)
->salario o valor da salrio.
176
Listagem 10.7: Alocao de espao para estruturas.
#in
lude < stdio .h >
#in
lude < string .h >
#in
lude < stdlib .h >
typedef stru
t _ALUNO {
har nome [40;
f l o a t n1 , n2 , media ;
} ALUNO ;
Exer
ios
10.1: Considere que uma empresa precisa armazenar os seguintes dados de um
cliente:
177
Listagem 10.8: Alocao de espao para vetores de estruturas.
#in
lude < stdio .h >
#in
lude < stdlib .h >
typedef stru
t _fun
{
har nome [40;
f l o a t salario ;
} Tfun
;
178
Listagem 10.9: Listagem do exercicio 3.
int main ( void ) {
stru
t aluno turma [ MAX ;
le ( turma ) ;
puts ( " Imprimindo dados lidos da turma . " ) ;
puts ( " Digite qualquer
oisa para
ontinuar . " ) ;
get
har () ;
imprime ( turma ) ;
ordena_medias ( turma ) ;
puts ( " Imprimindo dados ordenados da turma . " ) ;
puts ( " Digite qualquer
oisa para
ontinuar . " ) ;
get
har () ;
imprime ( turma ) ;
get
har () ;
}
10.4: Escrever um programa que utilize stru
ts e ponteiro para stru
t e im-
prima o contedo das variveis da stru
t.
10.7: Fazer um programa que simule as operaes de uma pilha push e pop,
usando stru
ts. 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 informaes num vetor de uma estrutura que contem esses dados (nome e
telefone). O programa deve ter trs opes apenas: uma que adiciona um novo
dado, outra que lista todos os dados atualmente armazenados na memria e
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
que este mximo permitido.
179
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 funes str
py e str
at para strings nesse formato.
10.11: Crie uma estrutura chamada retngulo, que possua duas estruturas
ponto (o ponto superior esquerdo e o ponto inferior direito). Faa um programa
que receba as informaes acerca de um retngulo (as coordenadas dos dois
pontos), e informe a rea, o comprimento da diagonal e o comprimento de cada
aresta
180
Captulo 11
11.1 Introduo
Em C no existem instrues especiais de entrada e sada como em outras lin-
guagens de programao. Estas tarefas, em C so executadas por funes espe-
cialmente criadas para esta finalidade e armazenadas em bibliotecas especficas.
Por esta razo todos programas em C que precisam de entrada e/ou sada de
dados necessitam incluir a diretiva #in
lude<stdio.h> no incio do programa,
para permitir o uso da biblioteca padro stdio de funes de entrada e sada.
181
impressora que espera final de linha no modo DOS surge o que comumente
chamado de efeito escada. A impresso continua na linha seguinte mas sem
voltar para o incio da linha porque em UNIX o caractere de retorno de carro
no inserido no fluxo de texto.
At agora temos trabalhado com os fluxos de dados padro: stdin, para
entrada de dados e stdout para sada de dados. Ao iniciar todo programa em
C automaticamente associado a estes dois fluxos de dados sem necessitar de
nenhuma interveno do programador. A definio de que perifricos estaro
associados a estes fluxos depende do sistema operacional. Normalmente o fluxo
de entrada (stdin) est associado ao teclado e o fluxo de sada (stdout) ao
monitor.
fluxo de texto
1 2 b 1 1 3 b a b
fluxo binrio
11.2.3 Arquivos
Um arquivo pode estar associado qualquer dispositivo de entrada e sada
como, por exemplo: impressora, teclado, disquete, disco rgido etc. No entanto,
os programas vem os arquivos atravs de fluxos. Para que um determinado
182
arquivo em um perifrico seja associado a um fluxo necessrio que o arquivo
seja aberto e somente aps esta operao, o programa pode manipular os
dados. Normalmente a interao entre o programa e os arquivos feita por
meio de buffers que intermediam a transferncia dos dados entre os programas
e os perifricos. Isto serve para facilitar a operao do sistema operacional.
Operaes comuns em arquivos so:
FILE *arq;
onde arq o ponteiro que ser usado para executar as operaes no arquivo.
11.4 In
io e Fim
As operaes mostradas a seguir mostram operaes que devem ser realizadas
antes e depois de usar um arquivo (fopen() e f
lose()). As outras duas funes
servem para que o usurio possa detectar o fim de um arquivo ou voltar para
seu incio.
183
Funo Descrio
fopen() Abre um arquivo
f
lose() Fecha um arquivo
fput
() Escreve um caractere em um arquivo
get
(), fget
() L um caractere de um arquivo
fprintf() Equivalente a printf()
ss
anf() Equivalente a s
anf(). L de uma cadeia de caracteres
fs
anf() Equivalente a s
anf()
fseek() Posiciona o arquivo em um ponto especfico
rewind() Posiciona o arquivo no incio
feof() Retorna verdade se chegou ao fim do arquivo
ferror() Verifica a ocorrncia de um erro
fflush() Descarrega o buffer associado ao arquivo
fread() Leitura de dados no modo binrio
fwrite() Escrita de dados no modo binrio
184
Observar que se um arquivo for aberto com permisso de escrita todo o seu
contedo anterior ser apagado. Caso o arquivo no exista ele ser criado.
O trecho de programa abaixo ilustra os passos necessrios para abrir um
arquivo para escrita. Primeiro declarado o ponteiro pa para o arquivo. Em
seguida a funo fopen chamada para associar o nome externo do programa
(arquivo.txt) no modo escrita ao ponteiro pa. Um teste para ponteiro nulo
feito para verificar se ocorreu algum problema com a operao de abertura do
arquivo.
Lembrar que abrir, para escrita, um arquivo que j existe, implica em apagar
todo o contedo anterior e a preparao do arquivo para receber dados a partir
de seu ponto inicial. Se o programador deseja acrescentar dados ao final de um
arquivo j existente o modo de abertura deve ser a.
onde parq um ponteiro de arquivo para o arquivo que deve ser fechado. Todos
os buffers internos associados com o fluxo de dados do arquivo so descarre-
gados. O contedo de qualquer buffer no escrito escrito e dados no lidos
de buffers so perdidos. Este ponto importante de ser considerado porque
em muitos sistemas operacionais uma operao de escrita em um arquivo no
ocorre imediatamente a emisso da ordem de escrita. O sistema operacional
pode executar a ordem no momento que achar mais conveniente. Um valor zero
de retorno significa que a operao foi executada com xito, qualquer outro valor
implica em erro.
185
que o final de um arquivo binrio foi encontrado. Naturalmente esta funo
pode ser aplicada tambm a arquivos texto. O prottipo da funo o seguinte:
11.4.4 Volta ao In
io
A funo rewind() recoloca o indicador de posio de arquivo no incio do ar-
quivo. Uma operao semelhante ao que fazemos em uma fita cassete de msica
ou vdeo. O prottipo da funo o seguinte:
186
int fget
(FILE *parq); int get
(FILE *parq);
int put (int h, FILE *parq); int fput (int h, FILE *parq)
onde parq um ponteiro de arquivo para o arquivo que foi previamente aberto
por meio da funo fopen() e
h o caractere a ser escrito.
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 ar-
quivo. O prximo passo a leitura do arquivo que iniciada aps uma chamada
a funo rewind(), fazendo com que o indicador de posio do arquivo volte a
apontar para seu incio.
Uma outra alternativa mostrada em 11.3 mostra um exemplo onde o ar-
quivo criado para escrita em seguida fechado e reaberto para leitura ficando
automaticamente posicionado no incio para a leitura.
187
Listagem 11.2: Exemplo de leitura e escrita de caracteres.
#in
lude < stdio .h >
#in
lude < stdlib .h >
int main ( void ) {
int
;
FILE * pa ;
har * nome = " texto . txt " ;
return 0;
}
188
Listagem 11.3: Exemplo de leitura e escrita de caracteres.
#in
lude < stdio .h >
int main ( void ) {
int
;
FILE * pa ;
har * nome = " texto . txt " ;
189
Listagem 11.4: Uso da funo ferror().
#in
lude < stdio .h >
int main ( void ) {
FILE * pArq ;
pArq = fopen ( " MeusDados . txt " ," r " ) ;
if ( pArq == NULL ) {
printf ( " Erro abrindo arquivo . " );
return 1;
}
else {
fput
( 'x ' , pArq ) ;
i f ( ferror ( pArq ) ) {
printf ( " Erro es
revendo arquivo \ n " ) ;
f
lose ( pArq ) ;
return 1;
}
}
return 0;
}
190
Listagem 11.5: Exemplo de leitura e escrita de cadeias de caracteres.
#in
lude < stdio .h >
#define MAX 80
int main ( void ) {
har linha [ MAX ;
FILE * pa ;
har * nome = " texto . txt " ;
191
onde parq um ponteiro de arquivo recebido aps uma chamada a fopen().
Em leituras, a funo retorna o nmero de itens lidos com sucesso. Esta
contagem pode igualar o nmero esperado de leituras ou ser menor no caso de
falha. Caso ocorra uma falha antes de que uma leitura possa ser feita com
sucesso, EOF retornado.
Em escritas, caso a operao de escrita tenha sucesso, o nmero total de
caracteres escrito retornado. Um nmero negativo retornado em caso de
falha.
Embora estas duas funes, por sua semelhana com printf() e s
anf()
, sejam maneiras convenientes de escrever e ler dados de arquivos, elas tm a
desvantagem de serem mais lentas do que uso de arquivos binrios. A perda
de tempo devido ao fato dos dados serem gravados em ASCII, o que obriga
a uma converso dos dados a cada operao realizada. Em alguns casos o fato
dos dados serem gravados em ASCII pode ser considerado um vantagem que se
sobrepe a desvantagem da reduo de velocidade. Dados gravados em ASCII
podem ser facilmente verificados pelos usurios, o que no acontece com dados
em binrio. O exemplo 11.6 mostra o uso destas funes para ler e escrever
vrios tipos de dados em um arquivo.
192
11.9 Lendo e Es
revendo Arquivos Binrios
As funes fread e fwrite so empregadas para leitura e escrita de dados em
modo binrio. Os prottipos das funes so:
size_t fread (void *ptr, size_t size, size_t nmemb, FILE *parq);
size_t fwrite(
onst void *ptr, size_t size, size_t nmemb, FILE *parq);
193
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
um exemplo onde estruturas so gravadas e lidas de um arquivo. Neste exemplo
usado um lao para gravar uma estrutura de cada vez. No entanto, tambm
possvel gravar todas as estruturas de uma vez mudando o terceiro parmetro
da funo fwrite(). O lao seria substitudo por
fwrite( &turma[i, sizeof (stru
t pessoa), MAX, pa);
Para testar erro basta verificar o valor retornado pela funo. Caso ela tenha
retornado um valor diferente de MAX ocorreu um erro.
194
Listagem 11.8: Exemplo de leitura e escrita de estruturas.
#in
lude < stdio .h >
#in
lude < string .h >
typedef stru
t _PESSOA {
har nome [40; int ano ;
} PESSOA ;
int main () {
FILE * pa ;
har nome [40 , linha [80;
PESSOA turma [4 , ba
k [4;
int i ;
for ( 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 ) ;
ss
anf ( 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;
}
for ( i =0; i <4; i ++) {
i f ( fwrite ( & turma [ i , s i z e o f ( PESSOA ) , 1 , pa ) !=
1)
puts ( " Erro na es
rita . " ) ;
}
rewind ( pa ) ;
for ( i =0; i <4; i ++) {
i f ( fread ( & ba
k [ i , s i z e o f ( PESSOA ) , 1 , pa ) !=
1) {
i f ( feof ( pa ) ) break ;
puts ( " Erro na leitura . " ) ;
}
}
for ( i =0; i <4; i ++) {
printf ( " Nome = % s \ n " , ba
k [ i . nome ) ;
printf ( " Ano = % d \ n \ n " , ba
k [ i . ano ) ;
}
return 0;
}
195
Exer
ios
11.1: Escreva um programa que abra um arquivo texto e conte o nmero de
caracteres presentes nele. Imprima o nmero de caracteres na tela.
3
ZE SA
8.5
10.0
ANTONIO SANTOS
7.5
8.5
SEBASTIAO OLIVEIRA
5.0
6.0
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 tama-
nho mximo do vetor e dado pela constante TAM_MAX. A quantidade de nmeros
no arquivo varia entre 0 e TAM_MAX. O programa ao final calcula a media dos
nmeros lidos.
196
11.6: Crie uma funo que receba duas strings como parmetros, uma com um
endereo de arquivo e outra com um texto qualquer, e adicione o texto no fim
do arquivo.
11.11: Faa um programa que receba o nome de um arquivo e gere uma cpia.
197
1 - O
11 - a
indicando que os primeiros caracteres dos arquivos so iguais (O) bem como o
dcimo primeiro (a)
11.13: Um arquivo do tipo texto, chamado numeros.txt contm uma quan-
tidade desconhecida de nmeros reais. Escreva um programa que leia estes n-
meros, os coloque em ordem crescente e depois os grave em um arquivo binrio
chamado numeros.bin.
Observaes:
198
Captulo 12
Problemas Extras
1a Problema:
Forasteiro infeliz, para chegar at a fonte voc deve ter muita paci-
ncia e faa o seguinte: a cada 5 minutos caminhe metade da dis-
tncia que ainda falta para chegar at a fonte. Desobedea qualquer
uma destas instrues e a morte ser o seu destino.
Tarefa
A sua tarefa descobrir em quantos minutos Zeno ir chegar a uma distncia
da fonte menor do que 103 m.
Entrada
Este programa no tem entradas.
Sada
O seu programa deve imprimir em quantos minutos Zeno ir chegar na dis-
tncia desejada.
2a Problema:
Estatsti a?
199
Uma medida importante em Estatstica o desvio padro representado na
equao 12.2 por . Ele d a medida da variabilidade ou disperso de um
conjunto de dados. Alm de ser bastante til muito fcil de ser calculado.
Considere um conjunto de N nmeros S = {x0 , x1 , x2 , . . . , xN 1 } cuja mdia
vale x. Para este conjunto de dados o desvio padro pode ser calculado pela
equao 12.2.
PN 1
xi
i=0
x = (12.1)
v N
u N 1
u1 X
= t (xi x)2 (12.2)
N i=0
Tarefa
A sua tarefa ler um conjunto de dados armazenado em um arquivo do tipo
texto, chamado estatistica.txt e calcular a mdia e depois o desvio padro
deste conjunto. Observe que o tamanho do conjunto desconhecido e s pode
ser descoberto aps a leitura de todos os dados.
Neste exerccio obrigatrio o uso de ponteiros para armazenar o
vetor.
Sada
A sada deve informar os valores obtidos para a mdia e o desvio padro.
Exemplo de Arquivo de Entrada e da sada
Arquivo estatistica.txt: Sada na tela:
1 A media vale 5.500000
2 O desvio padrao vale 2.872281
3
4
5
6
7
8
9
10
3a Problema:
Definies
O CPF o nmero usado pela Receita Federal no Brasil para identificar
os Contribuintes Pessoas Fsicas. O CPF composto por 11 algarismos. Des-
tes 11 algarismos os dois ltimos so usados para verificar se os primeiros 9
foram digitados corretamente. Eles so chamados de algarismos verificadores.
Por exemplo, considere o CPF exemplo 12345678909. Este CPF na realidade
200
123456789, os algarismos 09 servem para que os programas da Receita Federal
verifiquem se os 9 primeiros esto corretos e so gerados automaticamente pelos
computadores da Receita quando algum se inscreve. O algoritmo de gerao
dos dois ltimos algarismos descrito a seguir.
Para o primeiro dgito verificador (v1 ), o 0, no nosso exemplo, o algoritmo
o seguinte: multiplique o primeiro algarismo por 10, o segundo por 9, e assim
sucessivamente at o nono algarismo do cdigo e some todos estes resultados.
Neste exemplo teramos
soma1 = (1 10) + (2 9) + (3 8) + + (9 2)
4a Problema:
Tarefa
Z S est planejando a sua prxima viagem por Pindorama. No momento
ele gostaria de saber qual so as cidades mais distante e as mais perto da sua.
Para fazer estes clculos ele dispe de um arquivo com as coordenadas de sua
cidade e das vrias cidades que ele ir visitar
Entrada
A entrada ser feita a partir de um arquivo texto chamado cidades.txt.
A primeira linha deste arquivo um nmero inteiro n dizendo quantas cidades
h no arquivo. Considere que o nmero mximo de cidades igual a 50. As n
201
Listagem 12.1: Processando o CPF.
#in
lude < stdio .h >
#in
lude < stdlib .h >
#in
lude < string .h >
#define TAMCPF 11
#define CERTO 1
#define ERRADO 0
5a Problema:
Produto Es
alar
O produto escalar de dois vetores de n dimenses A = (a1 , a2 , . . . , an ) e
A B = a1 b 1 + a2 b 2 + + an b n (12.3)
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
vetores em C.
Entrada
A entrada consiste das seguintes linhas de dados:
203
As coordenadas de cada par de vetores so fornecidas da seguinte maneira.
Primeiro so fornecidos dois nmeros a1 b1 depois a2 b2 e assim sucessivamente
at an bn .
Sada
Imprimir os M produtos escalares calculados.
Exemplo de entrada: Exemplo de sada:
2 32.000000
4 22.000000
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:
Des
onando do sorteio
H pessoas que desconfiam de tudo, como h pessoas que acreditam em tudo.
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 nmeros entre
1 e 60. O jogador que acertar os nmeros sorteados ganha uma frao mnima
do total que o governo arrecadou. Um jogador desconfiado acha que o sorteio
viciado e contratou voc para descobrir se isto verdade ou no.
Voc deve escrever um programa que leia os N ltimos nmeros inteiros
sorteados e conte a frequncia com que cada um dos nmeros foi sorteado.
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.
Sada:
Imprimir a frequncia com que cada um dos nmeros apareceu. Nmeros
com frequncia zero no devem ser impressos.
Exemplos de entrada e sada:
204
Exemplo de entrada Sada para o exemplo de en-
12 trada
8 5 = 1
21 6 = 1
14 8 = 1
5 14 = 2
36 21 = 3
21 24 = 1
43 36 = 1
14 43 = 2
6
21
24
43
7a Problema:
Convertendo para base 2
Escreva um programa que leia uma sequncia de nmeros inteiros na base
10 e imprima o nmero convertido para base 2 e a maior sequncia de bits 1
que o nmero binrio contm.
Considere que o nmero na base 10 menor que 232 1.
Entrada:
A entrada contm vrios casos de teste. Cada linha de um caso de teste
contm um nmero inteiro menor que 232 1 O programa termina quando o
usurio fornecer um nmero negativo.
Sada:
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
nmero convertido para base 2. Zeros esquerda no devem ser impressos. Na
terceira linha o seu programa deve imprimir a maior sequncia de 1s do nmero
em binrio. A quarta linha deve ser deixada em branco.
Exemplos de entrada e sada:
205
Exemplo de entrada Sada para o exemplo de en-
6 trada
25 Teste 1
123456 110
14 2
-1
Teste 2
11001
2
Teste 3
11110001001000000
4
Teste 4
1110
3
8a Problema:
Voc foi contratado para escrever um programa que calcula reas de crculos.
O programa deve imprimir se um crculo tem rea maior que a rea mdia ou
rea menor ou igual a mdia.
O seu programa deve usar a estrutura (12.2) para representar cada crculo.
Entrada
Os dados estaro organizados da seguinte maneira. Primeiro, a quantidade
N de crculos, em seguida os dados dos N crculos, na seguinte ordem: coorde-
nada x, coordenada y, raio raio.
Obs. No possvel assumir um valor mximo para N , aloque o espao de
memria necessrio.
Sada
O programa de imprimir se um dado crculo tem rea maior que a mdia
ou rea menor ou igual a mdia. Considerando que o primeiro crculo recebe o
nmero um, o segundo o nmero 2 e assim at o crculo N , o formato de sada
o seguinte: a palavra Circulo seguida do nmero do crculo e se ele tem rea
maior ou menor ou igual.
206
Exemplo de Entrada: Exemplo de Sada:
5 Circulo 1 area menor ou igual
1 1 1 Circulo 2 area menor ou igual
1 2 2 Circulo 3 area menor ou igual
3 1 2 Circulo 4 area maior
2 2 4 Circulo 5 area maior
1 1 3
9a Problema:
Lu rando om Aes
10a Problema:
Somando Linhas
207
a maior soma e o(s) nmero(s) da(s) linha(s) com soma igual a maior em 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
contm N N nmeros inteiros em um formato livre, ou seja quantidade de
nmeros por linha do arquivo varivel.
Sada
O arquivo de sada tem o seguinte formato. Primeiro o valor da maior soma
das linhas. Em seguida as linhas com soma igual a maior soma.
11a Problema:
Misturando Dados
208
estar em ordem crescente.
209
Apndi
e A
Tabela ASCII
A tabela ASCII (American Standard for Information Interchange) usada por
grande parte da indstria de computadores para a troca de informaes e ar-
mazenamento de caracteres. Cada caractere representado por um cdigo de
8 bits. A Tabela A.1 mostra os cdigos para a tabela ASCII de 7 bits. Existe
uma table estendida para 8 bits que inclui os caracteres acentuados.
Para saber qual o cdigo de um caractere na base 10 junte o dgito da
primeira coluna da tabela com o dgito da primeira linha da tabela. Por exemplo,
o cdigo da letra a minscula 97 na base 10.
0 1 2 3 4 5 6 7 8 9
0 nul soh stx etx eot enq ack bel bs ht
1 nl vt ff cr so si dle dc1 dc2 dc3
2 dc4 nak syn etb can em sub esc fs gs
3 rs us sp ! " # $ % &
4 ( ) * + , - . / 0 1
5 2 3 4 5 6 7 8 9 : ;
6 < = > ? @ A B C D E
7 F G H I J K L M N O
8 P Q R S T U V W X Y
9 Z [ \ ] ^ _ a b c
10 d e f g h i j k l m
11 n o p q r s t u v w
12 x y z { | } ~ del
210
Carac Descrio Carac Descrio
nul Caractere nulo soh Comeo de cabealho de transmisso
stx Comeo de texto etx Fim de texto
eot Fim de transmisso enq Interroga
ack Confirmao bel Sinal sonoro
bs Volta um caractere ht Tabulao horizontal
lf Passa para prxima linha vt Tabulao vertical
ff Passa para prxima pgina cr Passa para incio da linha
so Shift-out si Shift-in
dle Data line escape dc1 Controle de dispositivo
dc2 Controle de dispositivo dc3 Controle de dispositivo
dc4 Controle de dispositivo nak Negativa de confirmao
syn Synchronous idle etb Fim de transmisso de um bloco
can Cancela em Fim de meio de transmisso
sub Substitui esc Escape
fs Separador de arquivo gs Separador de grupo
rs Separador de registro us Separador de unidade
sp Espao em branco
211
Apndi
e B
Palavras Reservadas
Palavras reservadas, tambm as vezes chamadas de palavra chave, servem para
propsitos especiais nas linguagens de programao. Servem para declarar tipos
de dados ou propriedades de um objeto da linguagem, indicar um comando alm
de vrias outras funes. Palavras reservadas no podem ser usadas como nomes
de variveis ou funes.
asm: Indica que cdigo escrito em assembly ser inserido junto comandos C.
auto: Modificador que define a classe de armazenamento padro.
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: Modificados de dados que impede que uma varivel seja modificada.
Esta palavra no existia nas primeiras verses da linguagem C e foi intro-
duzida pelo comit ANSI C. Veja volatile.
continue: Comando que interrompe os comandos de repetio for , while ,
ou do...while e faz que eles passem para a prxima iterao.
default: usado dentro do comando switch para aceitar qualquer valor no
definido previamente com um comando case.
do: Comando de repetio usado em conjunto com o comando while . Pela
definio do comando o lao sempre executado pelo menos uma vez.
double: Tipo de dados usado para armazenar valores de ponto flutuante em
preciso dupla.
else: Comando que indica um bloco de comandos alternativo que deve ser exe-
cutado quando a condio testada pelo comando if foi avaliada como
FALSA.
212
enum: Tipo definido pelo usurio que permite a definio de variveis que iro
aceitar somente certos valores.
extern: Modificador de dados que indica que uma varivel ir ser declarada em
outra rea do programa.
float: Tipo usado para armazenar valores de ponto flutuante.
for: Comando de repetio que contm inicializao de variveis, incremento e
sees condicionais. Em C o comando for um comando de repetio
extremamente flexvel, permitindo inmeras possibilidades.
goto: Comando que causa um pulo para uma posio do programa marcada
com um rtulo.
if: Comando de testes usado para mudar o fluxo do programa baseada em uma
deciso VERDADEIRO/FALSO.
int: Tipo de dados usado para armazenar valores inteiros.
long: Tipo de dados usado para armazenar valores inteiros com preciso maior
do que o tipo int. Nos computadores modernos o tipo long tem a mesma
preciso que o tipo int e so usados 4 bytes.
register: Especificador de classe de armazenamento que pede que, caso seja
possvel, uma varivel deve ser armazenada nos registradores do processa-
dor.
return: Comando que causa o fluxo de instrues do programa abandonar a
funo em execuo e retornar para a funo que chamou. Tambm pode
ser usado para retornar um nico valor.
short: Tipo de dados usado para armazenar valores inteiros em preciso menor
do que o tipo int. Neste tipo 2 bytes so usados para armazenar os dados.
signed: Modificador usado para indicar que uma varivel pode armazenar tanto
valores positivos como negativos.
sizeof: Operador que retorna o tamanho em bytes do item fornecido.
static: Modificador usado para significar que o compilador deve preparar o
cdigo de forma a reter o valor da varivel.
struct: Usado para combinar C variveis de tipos diferentes na mesma estru-
tura.
switch: Comando de desvio usado para permitir que o fluxo do programa possa
ser mudado para vrias direes diferentes. Usado em conjunto com o
comando case.
typedef: Modificador usado para criar novos nomes para tipos j existentes.
union: Palavra chave usada para permitir mltiplas variveis partilharem o
mesmo espao na memria.
213
unsigned: Modificador usado para significar que uma varivel conter somente
valores positivos.
void: Palavra usada para significar que ou a funo no retorna nada ou que
um ponteiro deve ser considerado genrico ou ser capaz de apontar para
qualquer tipo de dados.
volatile: Modificador que significa que uma varivel pode ser alterada.
while: Comando de teste que executa uma seo de cdigo enquanto uma con-
dio retorna VERDADEIRO.
214
Refern
ias Bibliogr
as
[Kernighan e Ritchie 1978]KERNIGHAN, B. W.; RITCHIE, D. M. The C Pro-
gramming Language. Englewood Cliffs, NJ, USA: Prentice-Hall, Inc, 1978.
[Knuth 1973]KNUTH, D. E. The Art of Computer Programming: Fundamental
Algorithms - vol. 1. Massachusetts, USA: Addison-Wesley Publishing Com-
pany, Inc, 1973.
[Oliveira 2008]OLIVEIRA, U. de. Programando em C: Fundamentos. 1. ed. Bra-
sil: Editora Cincia Moderna, 2008.
[Schildt 1997]SCHILDT, H. C Completo e Total. So Paulo, Brasil: Makron
Books do Brasil Editora, 1997.
215