Vous êtes sur la page 1sur 210

Curso de Linguagem C Em Construo ca v0.

001
Adriano Joaquim de Oliveira Cruz Instituto de Matemtica a N cleo de Computao Eletrnica u ca o UFRJ c 2009 Adriano Cruz 21 de Janeiro de 2009

Contedo u
1 Introduo ca 1.1 1.2 Sucessos e Fracassos da Computaao . . . . . . . . . . . . . . . . c Um Pouco da Histria da Computaao . . . . . . . . . . . . . . . o c 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.2 1.3.3 1.3.4 1.4 1.5 1.6 O In cio . . . . . . . . . . . . . . . . . . . . . . . . . . . . A Era Moderna . . . . . . . . . . . . . . . . . . . . . . . . O Desenvolvimento durante as Grandes Guerras . . . . . As Geraoes . . . . . . . . . . . . . . . . . . . . . . . . . . c Microcomputadores . . . . . . . . . . . . . . . . . . . . . Memrias . . . . . . . . . . . . . . . . . . . . . . . . . . . o Bits e Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . Perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . . e 19 19 21 21 22 24 27 27 29 30 32 33 33 39 40 41 41 43 44 45 45 46 48 49

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

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

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

Modelo de von Neumann . . . . . . . . . . . . . . . . . . . . . . . Estruturas Bsicas de Algoritmos . . . . . . . . . . . . . . . . . . a 3

4 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.6 2.7

CONTEUDO Comandos de leitura . . . . . . . . . . . . . . . . . . . . . Comandos de escrita . . . . . . . . . . . . . . . . . . . . . Expresses . . . . . . . . . . . . . . . . . . . . . . . . . . o Comandos de atribuiao . . . . . . . . . . . . . . . . . . . c Comandos de controle . . . . . . . . . . . . . . . . . . . . Comandos de repetiao . . . . . . . . . . . . . . . . . . . c 50 50 51 53 54 55 57 58 63 63 63 63 64 64 66 67 67 68 68 70 70 71 71 72 73 73 75 75 75 76 77 79 82

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

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

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

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

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

4 Entrada e Sa pelo Console da 4.1 4.2 4.3 4.4 4.5 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c Biblioteca Padro . . . . . . . . . . . . . . . . . . . . . . . . . . . a Sa - A Funao printf . . . . . . . . . . . . . . . . . . . . . . da c 4.3.1 Cdigos de Converso . . . . . . . . . . . . . . . . . . . . o a Entrada - A Funao scanf . . . . . . . . . . . . . . . . . . . . . . c Lendo e Imprimindo Caracteres . . . . . . . . . . . . . . . . . . .

CONTEUDO 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6 Funoes getchar e putchar . . . . . . . . . . . . . . . . . c Lendo e Imprimindo Cadeias de Caracteres . . . . . . . . Lendo e Imprimindo cadeias com scanf e printf . . . . . Lendo e Imprimindo cadeias com gets e puts . . . . . . . A Funao fgets . . . . . . . . . . . . . . . . . . . . . . . c

5 82 83 84 84 86 86 89 89 89 90 91 91 92 94 96 96 97 97 99 99 101

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

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

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

5.10 Regras de Precedncia . . . . . . . . . . . . . . . . . . . . . . . . e 5.11 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 Comandos de Controle 6.1 6.2 6.3

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 c Blocos de Comandos . . . . . . . . . . . . . . . . . . . . . . . . . 101 Comandos de Teste . . . . . . . . . . . . . . . . . . . . . . . . . . 102 6.3.1 6.3.2 6.3.3 Comando if . . . . . . . . . . . . . . . . . . . . . . . . . . 102 Comando switch . . . . . . . . . . . . . . . . . . . . . . . 103 Comando Ternrio . . . . . . . . . . . . . . . . . . . . . . 106 a Comando for . . . . . . . . . . . . . . . . . . . . . . . . . 106 Comando while . . . . . . . . . . . . . . . . . . . . . . . 111 Comando do-while . . . . . . . . . . . . . . . . . . . . . 113 Comando break . . . . . . . . . . . . . . . . . . . . . . . 113

6.4

Laos de Repetiao . . . . . . . . . . . . . . . . . . . . . . . . . . 106 c c 6.4.1 6.4.2 6.4.3

6.5

Comandos de Desvio . . . . . . . . . . . . . . . . . . . . . . . . . 113 6.5.1

6 6.5.2 6.5.3 6.5.4 6.5.5 6.6

CONTEUDO Comando continue . . . . . . . . . . . . . . . . . . . . . 114 Comando goto . . . . . . . . . . . . . . . . . . . . . . . . 114 Funao exit() . . . . . . . . . . . . . . . . . . . . . . . . 114 c Comando return . . . . . . . . . . . . . . . . . . . . . . . 115

Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 117

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

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 c Declaraao de Vetores Unidimensionais . . . . . . . . . . . . . . . 117 c Cadeias de Caracteres . . . . . . . . . . . . . . . . . . . . . . . . 120 Declaraao de Vetores Multidimensionais c . . . . . . . . . . . . . 124

Vetores de Cadeias de Caracteres . . . . . . . . . . . . . . . . . . 125 Inicializaao de Vetores e Matrizes . . . . . . . . . . . . . . . . . 127 c Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129 133

8 Funoes c 8.1 8.2 8.3 8.4

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 c Forma Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134 Prottipos de Funoes . . . . . . . . . . . . . . . . . . . . . . . . 135 o c Escopo de Variveis . . . . . . . . . . . . . . . . . . . . . . . . . 136 a 8.4.1 Variveis Locais . . . . . . . . . . . . . . . . . . . . . . . 136 a

8.5 8.6

Variveis Globais . . . . . . . . . . . . . . . . . . . . . . . . . . . 138 a Parmetros Formais . . . . . . . . . . . . . . . . . . . . . . . . . 139 a 8.6.1 8.6.2 8.6.3 Passagem de Parmetros por Valor . . . . . . . . . . . . . 139 a Passagem de Parmetros por Referncia . . . . . . . . . . 140 a e Passagem de Vetores e Matrizes . . . . . . . . . . . . . . . 141

8.7 8.8 8.9

O Comando return . . . . . . . . . . . . . . . . . . . . . . . . . 144 Recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144 a Argumentos - argc e argv . . . . . . . . . . . . . . . . . . . . . . 145

8.10 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146

CONTEUDO 9 Ponteiros 9.1 9.2

7 149

Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 c Operaoes com Ponteiros . . . . . . . . . . . . . . . . . . . . . . 151 c 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 Declaraao de Ponteiros . . . . . . . . . . . . . . . . . . . 151 c Os Operadores Especiais para Ponteiros . . . . . . . . . . 152 Atribuiao de Ponteiros . . . . . . . . . . . . . . . . . . . 152 c Incrementando e Decrementando Ponteiros . . . . . . . . 154 Comparaao de Ponteiros . . . . . . . . . . . . . . . . . . 156 c . . . . . . . . . . . . . . . . . 157

9.3 9.4 9.5 9.6 9.7 9.8 9.9

Ponteiros e Vetores . . . . . . . . . . . . . . . . . . . . . . . . . . 156 Ponteiros e Cadeias de Caracteres Alocaao Dinmica de Memria . . . . . . . . . . . . . . . . . . . 158 c a o Ponteiros e Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . 160 Vetores de Ponteiros . . . . . . . . . . . . . . . . . . . . . . . . . 163 Ponteiros para Ponteiros . . . . . . . . . . . . . . . . . . . . . . . 163 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 171

10 Estruturas

10.1 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171 c 10.2 Denioes Bsicas . . . . . . . . . . . . . . . . . . . . . . . . . . 171 c a 10.3 Atribuiao de Estruturas . . . . . . . . . . . . . . . . . . . . . . . 174 c 10.4 Matrizes de Estruturas . . . . . . . . . . . . . . . . . . . . . . . . 175 10.5 Estruturas e Funoes . . . . . . . . . . . . . . . . . . . . . . . . . 176 c 10.6 Ponteiros para Estruturas . . . . . . . . . . . . . . . . . . . . . . 177 10.7 Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 11 Entrada e Sa por Arquivos da 185

11.1 Introduao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 c 11.2 Fluxos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . 185 11.2.1 Fluxos de Texto . . . . . . . . . . . . . . . . . . . . . . . 185 11.2.2 Fluxo Binrio . . . . . . . . . . . . . . . . . . . . . . . . . 186 a 11.2.3 Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . 186 11.3 Funoes de Entrada e Sa c da . . . . . . . . . . . . . . . . . . . . . 187 11.4 In e Fim . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188 cio 11.4.1 Abrindo um Arquivo . . . . . . . . . . . . . . . . . . . . . 188 11.4.2 Fechando um Arquivo . . . . . . . . . . . . . . . . . . . . 190

CONTEUDO 11.4.3 Fim de Arquivo . . . . . . . . . . . . . . . . . . . . . . . . 190 11.4.4 Volta ao In cio . . . . . . . . . . . . . . . . . . . . . . . . 190 11.5 Lendo e Escrevendo Caracteres . . . . . . . . . . . . . . . . . . . 191 11.6 Testando Erros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193 11.7 Lendo e Escrevendo Cadeias de Caracteres . . . . . . . . . . . . . 194 11.8 Entrada e Sa Formatada . . . . . . . . . . . . . . . . . . . . . 195 da 11.9 Lendo e Escrevendo Arquivos Binrios . . . . . . . . . . . . . . . 197 a 11.10Exerc cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198

A Tabela ASCII B Palavras Reservadas

203 205

Lista de Figuras
1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 Fotograa de um circuito integrado de microprocessador Pentium. 20 Imagem de um baco. . . . . . . . . . . . . . . . . . . . . . . . . a Blaise Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Charles Babbage . . . . . . . . . . . . . . . . . . . . . . . . . . . Fotograa da Dierence Engine . . . . . . . . . . . . . . . . . . . Computador Eniac . . . . . . . . . . . . . . . . . . . . . . . . . . Diagrama Bsico de um Computador Digital . . . . . . . . . . . a N veis de hierarquia da memria de um computador. . . . . . . . o Tamanho de Bits, Bytes e Palavras . . . . . . . . . . . . . . . . . 22 22 23 23 26 28 30 32 37 45 46 49 54 56 57

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

Mapa de memria de uma matriz. . . . . . . . . . . . . . . . . . 125 o Mapa de memria com duas variveis e ponteiro. . . . . . . . . . 149 o a Ponteiro apontando para rea de memria contendo vetor. . . . . 150 a o Declaraao de ponteiros. . . . . . . . . . . . . . . . . . . . . . . . 151 c Atribuiao de endereo de uma varivel a um ponteiro. . . . . . . 152 c c a Uso de um ponteiro para copiar valor de uma varivel. . . . . . . 153 a Exemplos de atribuioes de ponteiros. . . . . . . . . . . . . . . . 154 c 9

10 9.7

LISTA DE FIGURAS Armazenamento de matrizes com vetores de ponteiros. . . . . . . 165

11.1 Fluxos de dados. . . . . . . . . . . . . . . . . . . . . . . . . . . . 187

Lista de Tabelas
1.1 1.2 1.3 1.4 1.5 2.1 3.1 3.2 3.3 3.4 3.5 3.6 3.7 4.1 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 Transistores por circuito integrado nos microprocessadores da Intel 20 Tempo de execuao das instruoes aritmticas no ENIAC . . . . c c e Exemplos de Microprocessadores . . . . . . . . . . . . . . . . . . Abreviaoes usadas em referncias `s memrias. . . . . . . . . . . c e a o Exemplos de perifricos . . . . . . . . . . . . . . . . . . . . . . . e Operadores Aritmticos. . . . . . . . . . . . . . . . . . . . . . . . e Tipos de dados denidos pelo Padro ANSI C. . . . . . . . . . . a Constantes Inteiras na Base 10 . . . . . . . . . . . . . . . . . . . Constantes octais . . . . . . . . . . . . . . . . . . . . . . . . . . . Constantes hexadecimais . . . . . . . . . . . . . . . . . . . . . . . Constantes em ponto utuante . . . . . . . . . . . . . . . . . . . Exemplos de constantes caractere . . . . . . . . . . . . . . . . . . Exemplos de caracteres invis veis. . . . . . . . . . . . . . . . . . . Cdigos de Converso para leitura e entrada de dados. . . . . . . o a Operadores aritmticos. . . . . . . . . . . . . . . . . . . . . . . . e Operadores Relacionais. . . . . . . . . . . . . . . . . . . . . . . . Operador Lgico E. . . . . . . . . . . . . . . . . . . . . . . . . . . o Operador Lgico OU. . . . . . . . . . . . . . . . . . . . . . . . . . o ~ Operador Lgico NAO. . . . . . . . . . . . . . . . . . . . . . . . . o Precedncia dos operadores lgicos e relacionais. . . . . . . . . . e o Operadores com bits. . . . . . . . . . . . . . . . . . . . . . . . . . Operador Lgico OU. . . . . . . . . . . . . . . . . . . . . . . . . . o 11 26 29 33 33 53 65 66 67 67 70 70 71 77 90 91 92 93 94 94 94 95

12 5.9 7.1

LISTA DE TABELAS Precedncia dos operadores. . . . . . . . . . . . . . . . . . . . . . e 99

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

11.1 Exemplos de funoes de Entrada e Sa c da. . . . . . . . . . . . . . 188 A.1 Conjunto de caracteres ASCII . . . . . . . . . . . . . . . . . . . . 203 A.2 Conjunto de cdigos especiais ASCII e seus signicados . . . . . 204 o

Lista de Algoritmos
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 Exemplo de Algoritmo. . . . . . . . . . . . . . . . . . . . . . . . . Algoritmo para resolver uma equaao do primeiro grau. . . . . . . c Algoritmo para calcular a mdia das notas de um aluno. . . . . . e Algoritmo para calcular a maior nota de um grupo de notas. . . . Modelo de memria e funcionamento de um algoritmo . . . . . . . o Comando se em pseudo-linguagem . . . . . . . . . . . . . . . . . . Algoritmo para decidir o que fazer no domingo. . . . . . . . . . . Algoritmo para decidir se deve levar um guarda-chuva. . . . . . . Algoritmo para ler 10 n meros e imprimir se so pares ou no. . . u a a 43 44 45 47 49 54 55 55 58 59 60 61 61 69

2.10 Algoritmo para ler n meros e imprimir se so pares ou no. . . . . u a a 2.11 Algoritmo para calcular a maior nota de uma turma de 25 alunos. 2.12 Algoritmo para calcular a nota mdia de uma turma de 25 alunos. e 2.13 Algoritmo para calcular a maior temperatura do ano. . . . . . . . 3.1 Algoritmo para converter inteiros na base 10 para uma base b. . .

13

14

LISTA DE ALGORITMOS

Listings
1.1 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 5.1 5.2 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7.1 7.2 7.3 7.4 7.5 Exemplo de Programa em C. . . . . . . . . . . . . . . . . . . . . Exemplo de impresso de resultados . . . . . . . . . . . . . . . . a Exemplo de justicaao de resultados. . . . . . . . . . . . . . . . c Exemplo de uso de especicador de preciso. . . . . . . . . . . . a Exemplo de uso de scanf. . . . . . . . . . . . . . . . . . . . . . Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . Exemplo de uso de getchar e putchar. . . . . . . . . . . . . . . Exemplo de uso de printf e scanf na leitura de cadeias. . . . . Exemplo de uso de puts e gets na leitura de cadeias. . . . . . . Exemplo de operadores de deslocamento. Exemplo do operador sizeof. Exemplo de switch. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 76 79 79 81 82 83 84 85 95 97

Programas com ifs em escada e aninhados.

. . . . . . . . . . . 104

. . . . . . . . . . . . . . . . . . . . . . . . . 107

Exemplo de comando ternrio. . . . . . . . . . . . . . . . . . . . 108 a Exemplo de comando for. . . . . . . . . . . . . . . . . . . . . . . 109 Exemplo de comando for com testes sobre outras variveis. . . . 110 a Exemplo de comando for sem alteraao da varivel de controle. c a Exemplo de comando for sem teste de m. Comando for aninhados. Comando while com uma funao. c Produto escalar de dois vetores. Ordenaao pelo mtodo da bolha. c e Leitura de uma matriz. 110 . . . . . . . . . . . . 111

. . . . . . . . . . . . . . . . . . . . . . 111 . . . . . . . . . . . . . . . . . 112 . . . . . . . . . . . . . . . . . . 119 . . . . . . . . . . . . . . . . . 121

Exemplo de vetores. . . . . . . . . . . . . . . . . . . . . . . . . . 118

Exemplos de funoes para cadeias. . . . . . . . . . . . . . . . . . 123 c . . . . . . . . . . . . . . . . . . . . . . . 124 15

16 7.6 7.7 7.8 7.9 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 Multiplicaao de duas matrizes. c

LISTINGS . . . . . . . . . . . . . . . . . . 126

Leitura de um vetor de nomes. . . . . . . . . . . . . . . . . . . . 127 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 128 Exemplos de tratamento de vetores. . . . . . . . . . . . . . . . . 129 Exemplo de prottipos. . . . . . . . . . . . . . . . . . . . . . . . 136 o Exemplos de variveis locais. . . . . . . . . . . . . . . . . . . . . 137 a Deniao de varivel dentro de um bloco. . . . . . . . . . . . . . 138 c a Deniao de varivel global. c a . . . . . . . . . . . . . . . . . . . . 139 Exemplo de passagem por valor. . . . . . . . . . . . . . . . . . . 140 Uso indevido de variveis locais. . . . . . . . . . . . . . . . . . . 141 a Passagem de vetor com dimenses. o . . . . . . . . . . . . . . . . 142 Passagem de vetores sem dimenses. . . . . . . . . . . . . . . . . 143 o Funao recursiva para calcular xn . . . . . . . . . . . . . . . . . . 146 c Exemplo de atribuiao de ponteiros. . . . . . . . . . . . . . . . . 153 c Exemplos de operaoes com ponteiros. c . . . . . . . . . . . . . . 154 Exemplo de subtraao de ponteiros. . . . . . . . . . . . . . . . . 155 c Exemplo de comparaao de ponteiros. . . . . . . . . . . . . . . . 156 c Exemplo de alteraoes invlidas sobre ponteiros. . . . . . . . . . 157 c a Exemplo de notaoes de vetores. . . . . . . . . . . . . . . . . . . 157 c Exemplo de ponteiro varivel. a . . . . . . . . . . . . . . . . . . . 158 . . . . . . . . . 158 Exemplo de ponteiro para cadeia de caracteres.

8.10 Uso de argc e argv. . . . . . . . . . . . . . . . . . . . . . . . . . 147

Exemplo de cpia de cadeias de caracteres. . . . . . . . . . . . . 159 o . . . . . . . . . . . . . . . . . 160 . . . . . . . . 162 . . . . . . . . . . . . . . . . . . . . . 161 . . . . . . . . . . . . 162 . . . . . . . . . . . 166 . . 167

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

9.12 Exemplo de matriz normal sem uso de ponteiros. 9.13 Exemplo de matriz mapeada em um vetor. 9.14 Exemplo de uso de vetor de ponteiros. 9.15 Exemplo de uso de ponteiros para ponteiros. 9.17 Continuaao do exemplo 9.16. c

. . . . . . . . . . . . . . 164

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

. . . . . . . . . . . . . . . . . . . 168

10.1 Deniao de uma estrutura. . . . . . . . . . . . . . . . . . . . . . 172 c 10.2 Atribuiao de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 174 c 10.3 Ordenaao de Estruturas. . . . . . . . . . . . . . . . . . . . . . . 175 c

LISTINGS 10.4 Passando elementos para funoes. c 10.6 Funao que ordena estruturas. c

17 . . . . . . . . . . . . . . . . . 176 . . . . . . . . . . . . . . . 177

10.5 Passagem de estruturas para funoes. c

. . . . . . . . . . . . . . . . . . . 178

10.7 Alocaao de espao para estruturas. . . . . . . . . . . . . . . . . 179 c c 10.8 Alocaao de espao para vetores de estruturas. . . . . . . . . . . 181 c c 10.9 Listagem do exercicio 3. 11.1 Uso da funao feof(). c . . . . . . . . . . . . . . . . . . . . . . 182 . . . . . . . . . . . . . . . . . . . . . . . 191 . . . . . . . . . . . . 192 . . . . . . . . . . . . 193 . . . . . . 195

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

11.4 Uso da funao ferror(). . . . . . . . . . . . . . . . . . . . . . . 194 c 11.5 Exemplo de leitura e escrita de cadeias de caracteres. 11.7 Exemplo de leitura e escrita na forma binria. a 11.8 Exemplo de leitura e escrita de estruturas. 11.6 Exemplo de leitura e escrita de dados formatados. . . . . . . . . 196 . . . . . . . . . . 197 . . . . . . . . . . . . 199

18

LISTINGS

Cap tulo 1

Introduo ca
1.1 Sucessos e Fracassos da Computao ca

Os objetivos principais deste Cap tulo so mostrar para o aluno iniciante alguns a aspectos da histria da computaao e denir, informalmente, termos e palavraso c chave que os prossionais da rea de computaao usam no seu dia a dia. Adriano a c Cruz c . A histria do desenvolvimento dos computadores tem sido impressionante. o O avano da tecnologia e a presena da computaao na nossa vida so inegveis. c c c a a Embora a histria deste fantstico desenvolvimento seja recente e bem documeno a tada, h lacunas e controvrsias impressionantes sobre diversos pontos. Neste a e cap tulo iremos ver histrias de espionagem e brigas na justia por roubo de o c idias. H oportunidades perdidas e gente que soube aproveitar a sua chance. e a H verdades estabelecidas que tiveram de ser revistas. a O avano na tecnologia dos computadores se deu em passos to largos que os c a primeiros computadores parecem to distantes no tempo quanto a Pr-Histria. a e o O aumento de velocidade, desde os anos 40, foi da ordem de vrias ordens de a grandeza, enquanto que o custo dos computadores caiu de milhes de dlares o o para valores em torno de centenas de dlares. As primeiras mquinas tinham mio a lhares de vlvulas, ocupavam reas enormes e consumiam quilowatts de energia. a a O microprocessador Pentium, lanado em 1993, tinha em torno de 3,1 milhes c o de transistores, ocupava uma rea de aproximadamente 25 cm2 e consumia a alguns watts de energia, custando aproximadamente 1000 dlares, somente o o microprocessador. A Figura 1.1 mostra a imagem de um circuito integrado de microprocessador Pentium. No entanto, esta histria de reduao de tamanho, aumento de velocidade e o c diminuiao de gasto de potncia, pode, para alguns pesquisadores, j ter uma c e a data xada para terminar. Em 1965, Gordon Moore, um dos fundadores da Intel, fabricante do Pentium e uma dos maiores fabricantes de circuitos integrados 19

20

CAP ITULO 1. INTRODUCAO

Figura 1.1: Fotograa de um circuito integrado de microprocessador Pentium.

do mundo, enunciou o que cou conhecido como a Lei de : Cada novo circuito integrado ter o dobro de transistores do anterior e ser lanado dentro de um a a c intervalo de 18 a 24 meses. Moore achava que esta lei seria vlida somente at a e 1975, no entanto, ela continua vlida at hoje. Na tabela 1.1, pode-se observar a e a evoluao dos microprocessadores usados em nossos computadores. c Ano 1971 1972 1974 1982 1985 1989 1993 1997 1999 2000 Processador 4004 8008 8080 80286 80386 80486 DX Pentium Pentium II Pentium III Pentium 4 Transistores 2.250 2.500 5.000 120.000 275.500 1.180.000 3.100.000 7.500.000 24.000.000 42.000.000

Tabela 1.1: Transistores por circuito integrado nos microprocessadores da Intel

Os transistores, que compem os circuitos eletrnicos, esto diminu de o o a do tamanho, e estamos nos aproximando da fronteira nal, os eltrons. J se houve e a falar em tamanho de transistores medidos em n meros de eltrons. Devemos nos u e lembrar que toda a tecnologia atual est baseada em uxo de eltrons, ou seja a e uma corrente eltrica. Os os conduzem correntes de eltrons e os transistores e e controlam este uxo. Se o tamanho diminuir alm dos eltrons estaremos em e e outro dom nio. No entanto, na histria da computaao, muitas promessas no foram cumo c a pridas e falhas gigantescas aconteceram. Como em diversas questes, artistas o geniais, apontam o que no conseguimos ou no queremos ver e mostram que a a o rei est nu. H uma frase de Picasso que diz: Computadores so est pidos, a a a u

1.2. UM POUCO DA HISTORIA DA COMPUTACAO

21

eles somente conseguem responder perguntas. Esta frase expe com ironia o um fracasso da comunidade de computaao que havia prometido criar rapidac mente computadores inteligentes, computadores que poderiam questionar-se e nos questionar. Muitos acreditaram nesta promessa e muitos livros de cao cic ent ca foram publicados em que este tipo de computador estaria dispon em vel um futuro muito prximo. Com notvel exemplo podemos citar o lme 2001 o a Uma Odissia no Espao, de Stanley Kubrik que estreou em 1968 e foi baseado e c no conto The Sentinel, escrito em 1950 por Arthur Clark, um dos mestres da cao cient c ca. Neste lme o enlouquecido computador HAL 9000, que era capaz de ver, falar, raciocinar etc, mata quase todos os tripulantes de uma nave espacial. Ora, j passamos por 2001 e no existe a menor possibilidade de se a a ver um computador como o HAL ou to louco de pedra como ele. a Na computaao, um exemplo fantstico de sucesso a Internet. A Internet c a e est se tornando essencial para o funcionamento do mundo moderno. Freq ena u temente ouvimos dizer que ela o meio de comunicaao que mais rapidamente se e c difundiu pelo mundo. Pode parecer verdade, j que conhecemos tantos internaua tas e as empresas esto se atropelando para fazer parte desta onda e aproveitar a as suas possibilidades. Esta corrida provocou alguns acidentes e muitos sonhos de riqueza se esva ram no ar. Hoje, pode-se fazer quase tudo pela Internet, namorar, comprar, pagar contas, fazer amigos, estudar, jogar etc. Quem sabe, em um futuro prximo, voltaremos ` Grcia Antiga e nos reuniremos em uma o a e enorme praa virtual para, democraticamente, discutir nossas leis, dispensando c intermedirios. a

1.2
1.2.1

Um Pouco da Histria da Computao o ca


O In cio

A primeira tentativa de se criar uma mquina de contar foi o abaco. A palavra a vem do rabe e signica p. Os primeiros bacos eram bandejas de areia sobre a o a as quais se faziam guras para representar as operaoes. Aparentemente, os c chineses foram os inventores do baco de calcular. No entanto, h controvrsias, a a e e os japoneses tambm reivindicam esta invenao, que eles chamam de soroban. e c Alm disso h os russos, que inventaram um tipo mais simples, chamado de e a tschoty So conhecidos exemplares de baco datados de 2500 A.C. A Figura 1.2 a a ilustra um exemplar com as suas contas e varetas. Em 1901 mergulhadores, trabalhando perto da ilha grega de Antikythera, encontraram os restos de um mecanismo, parecido com um relgio, com aproxio madamente 2000 anos de idade. O mecanismo, de grande complexidade, parece ser um dispositivo para calcular os movimentos de estrelas e planetas.

22

CAP ITULO 1. INTRODUCAO

Figura 1.2: Imagem de um baco. a

1.2.2

A Era Moderna

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

Figura 1.3: Blaise Pascal Pascal recebeu uma patente do rei da Frana, o que lhe possibilitou o c lanamento de sua mquina no mercado. A comercializaao das calculadoras c a c no foi satisfatria devido a seu funcionamento pouco convel, apesar dele ter a o a constru cerca de 50 verses. As mquinas de calcular, derivadas da Pascado o a lina, como cou conhecida sua mquina, ainda podiam ser encontradas em lojas a at alguns poucos anos atrs. Antes de morrer, aos 39 anos, em 1662, Pascal e a que contribu em vrios campos da Cincia, ainda teve tempo de criar uma ra a e variante de sua mquina, a caixa registradora. a

1.2. UM POUCO DA HISTORIA DA COMPUTACAO

23

Em 1666, Samuel Morland adaptou a calculadora de Pascal para resolver multiplicaoes por meio de uma srie de somas sucessivas. Independentemente, c e em 1671 Leibniz projetou uma outra calculadora que somava e multiplicava. Esta calculadora s foi conclu em 1694. o da O primeiro computador de uso espec co comeou a ser projetado em 1819 c e terminou em 1822, ou seja, h mais de 180 anos atrs, pelo britnico Charles a a a Babbage (1791-1871, Figura 1.4), que o batizou de Dierence Engine (Figura 1.5). A motivaao de Babbage era resolver polinmios pelo mtodo das difec o e renas. Naquele tempo as tbuas astronmicas e outras tabelas eram calculadas c a o por humanos, em mtodos tediosos e repetitivos. e

Figura 1.4: Charles Babbage

Figura 1.5: Fotograa da Dierence Engine

Em 1823, ele iniciou o projeto de construir uma outra mquina mais avanada a c e capaz de calcular polinmios de at sexta ordem. Ele esperava terminar esta o e

24

CAP ITULO 1. INTRODUCAO

mquina em trs anos, mas a construao se arrastou at 1834. Este projeto que a e c e no foi completado, usou dinheiro do governo ingls e possivelmente a maior a e parte da fortuna pessoal de Babbage. A mquina, inteiramente mecnica, teria a a as seguintes caracter sticas: Arredondamento automtico; a Preciso dupla; a Alarmes para avisar m de clculo; a Impresso automtica de resultados em placas de cobre. a a Em 1834 ele tinha completado os primeiros desenhos da mquina que denoa minou Analytical Engine que tinha as seguintes caracter sticas: 50 d gitos decimais de preciso; a Memria para 1000 destes n meros (165000 bits); o u Controle por meio de cartes perfurados das operaoes e endereos dos o c c dados; Tempo de soma e subtraao igual a 1 segundo; tempo de multiplicaao e c c diviso igual a 1 minuto; a Sub-rotinas; Arredondamento automtico e detecao de transbordo (overow ); a c Babagge nunca conseguiu terminar este ambicioso projeto. No entanto, os mais importantes conceitos de computaao, que somente vieram a tona nos anos c 40 do sculo vinte, j tinham sido considerados por Charles Babbage em o seu e a projeto. Um fato curioso que entre os auxiliares de Babagge estava Augusta Ada e Byron, Countess of Lovelace. Considera-se, hoje, que ela escreveu para Charles Babbage o primeiro programa para computadores. Ada que mudou seu nome para Augusta Ada King, aps seu casamento, estudava Matemtica com Deo a Morgan que provou um dos teoremas bsicos da Algebra Booleana, que a base a e matemtica sobre a qual foram desenvolvidos os projetos dos modernos compua tadores. No entanto, no havia nenhuma ligaao entre o trabalho do projetista a c dos primeiros computadores e o do matemtico que estudava o que viria a ser a o fundamento terico de todo a computaao que conhecemos hoje. o c

1.2.3

O Desenvolvimento durante as Grandes Guerras

Antes da Segunda Grande Guerra, em vrios pa a ses, cientistas estavam trabalhando em projetos que visavam construir computadores eletro-mecnicos, ou a sejam usavam rels. Alguns destes computadores eram de uso geral, outros e tinha nalidades espec cas. Alguns destes projetos esto listados a seguir. a

1.2. UM POUCO DA HISTORIA DA COMPUTACAO Na Alemanha

25

Em 1934 na Alemanha Konrad Zuze, engenheiro projetista de avies, concebeu o uma mquina de somar para resolver os clculos que deveria realizar em seus a a projetos. Em 1938, ele concluiu o Z1, um calculador mecnico com uma unidade a aritmtica que usava a base 2 para representar os n meros, base que hoje os e u computadores modernos empregam. Em 1938 ele melhorou o desempenho do Z1, graas aos rels. c e O governo alemo patrocinou os trabalhos de Zuze e em 1941 estava pronto a o Z2, uma mquina eletromecnica capaz de receber instruoes por meio de uma a a c ta de papel. Em 1941 foi introduzido o Z3, que calculava trs a quatro adioes e c por segundo, uma multiplicaao em 4 ou 5 segundos e era capaz de extrair a c raiz quadrada. Nos Estados Unidos Em 1944 a IBM e H. Haiken da Universidade de Harvard, conclu am a construcao de um verdadeiro computador: o Harvard Mark I, que operava em base 10. O Mark I efetuava as quatro operaoes fundamentais, mais o clculo de funoes c a c trigonomtricas, exponenciais e logar e tmicas. As instruoes eram fornecidas por c meio de tas de papel e os dados lidos de cartes perfurados. Os resultados eram o fornecidos em forma de cartes perfurados ou impressos por meio de mquinas o a de escrever. Em 1943 na Universidade da Pensilvnia, J. Eckert e J. Mauchly iniciaram a a construao de um computador a vlvulas, ou seja eletrnico. O projeto foi c ` a o conclu em 1946 e usado na segunda guerra mundial. O ENIAC podia ser do reprogramado para executar diversas operaoes diferentes atravs de ligaoes c e c por meio de os e conectores. Durante muitos anos o computador ENIAC foi considerado o primeiro computador eletrnico constru o do. A mquina projetada pelos Drs. Eckert and a Mauchly era gigantesca quando comparada com os computadores pessoais atuais. Quando foi terminado, o ENIAC (Figura 1.6) enchia um laboratrio inteiro, o pesava trinta toneladas, e consumia duzentos quilowatts de potncia. e Ele gerava tanto calor que teve de ser instalado em um dos poucos espaos c da Universidade que possu sistemas de refrigeraao forada. Mais de 19000 a c c vlvulas, eram os elementos principais dos circuitos do computador. Ele tambm a e tinha quinze mil rels e centenas de milhares de resistores, capacitores e indue tores. Toda esta parafernlia eletrnica foi montada em quarenta e dois painis a o e com mais 2,70 metros de altura, 60 cent metros de largura e 30 cent metros de comprimento, montados na forma da letra U. Uma leitora de cartes perfurados o e uma perfuradora de cartes eram usados para entrada e sa de dados. o da Os tempos de execuao do ENIAC so mostrados na Tabela 1.2. Compare c a estes tempos com os tempos dos computadores atuais que esto na ordem de a nano segundos, ou 109 segundos.

26

CAP ITULO 1. INTRODUCAO

Figura 1.6: Computador Eniac

Operao ca soma multiplicaao c diviso a

Tempo 200 s 2,8 ms 6,0 ms

Tabela 1.2: Tempo de execuao das instruoes aritmticas no ENIAC c c e

Em 1939 John Vincent Atanaso e Cliord E. Berry, na Universidade Estadual de Iowa constru ram um prottipo de computador digital eletrnico, que o o usa aritmtica binria. Em 19 de outubro de 1973, o juiz federal Earl R. Larson e a assinou uma deciso, em seguida a uma longa batalha judicial, que declarava a a patente do ENIAC de Mauchly e Eckert invlida e atribu a Atanaso a a a invenao computador eletrnico digital, o ABC ou Atanaso-Berry Computer. c o Na Inglaterra Jnos von Neuman, emigrante h ngaro que vivia nos EUA, sugeriu que a a u memria do computador deveria ser usada para armazenar as instruoes do o c computador de maneira codicada, o conceito de programa armazenado. Esta idia foi fundamental para o progresso da computaao. Os primeiros computae c dores, como o ENIAC, eram programados por os que os cientistas usavam para conectar as diversas partes. Quando um programa terminava, estes cientistas trocavam os os de posiao de acordo com a nova tarefa a ser executada. Com o c programa armazenado na memria, juntamente com os dados, no era mais neo a cessrio interromper as atividades. Carregava-se o programa na memria, uma a o tarefa extremamente rpida, junto com os dados e dava-se partida no programa. a Ao trmino da execuao do programa passava-se imediatamente para a prxima e c o tarefa sem interrupoes para troca de os. c Em 1949, na Inglaterra, dois computadores que usavam a memria para o armazenar tanto programas como dados foram lanados. Na Universidade de c

1.3. O HARDWARE

27

Cambridge foi lanado o EDSAC, (Electronic Delay Storage Automatic Calculac tor) e em Manchester o computador chamado de Manchester Mark I. O EDSAC considerado o primeiro computador de programa armazenado a ser lanado. e c Curiosamente, a Universidade de Manchester reivindica que o primeiro computador de programa armazenado foi o chamado Baby, um prottipo do Mark o I, que comeou a operar onze meses antes do EDSAC. c Outro fato curioso em relaao a Inglaterra e que foi divulgado recentemente c ` relata que um computador chamado COLOSSUS entrou em operaao secrec tamente na Inglaterra em 1943. Este computador foi usado para auxiliar na quebra dos cdigos de criptograa alemes durante a segunda grande guerra. o a

1.2.4

As Geraes co

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

1.3

O Hardware

O hardware corresponde aos circuitos eletrnicos e componentes mecnicos que o a compem o computador. Um t o pico diagrama em blocos de um computador digital monoprocessado esta mostrado na Figura 1.7. A Unidade Central de Processamento (UCP) , em ingls Central Processing Unit (CPU), como o e prprio nome diz, a unidade onde os dados so processados, ou seja alterados, o e a no computador. Ou seja, dentro das UCPs os dados so somados, subtra a dos

28

CAP ITULO 1. INTRODUCAO

etc. A UCP tambm controla a movimentaao dos dados dentro de todo o e c sistema. Os mdulos que constituem a UCP so os seguintes: o a Unidade de Controle (UC): comanda a operaao do computador. Esta unic dade l da memria tanto as instruoes como os dados e comanda todos e o c os circuitos para executar cada instruao lida da memria. Atualmente as c o unidades de controle so capazes de executar mais de uma instruao por a c ciclo de mquina, o que caracteriza o processamento paralelo. A tcnica a e mais comum para conseguir este paralelismo conhecida como pipelining, e que ser detalhada mais adiante. a Unidade Aritmtica e Lgica (UAL): local onde as transformaoes sobre e o c os dados acontecem. Atualmente esta unidade bastante sosticada e e diversos mtodos so empregadas para acelerar a execuo das instruoes. e a ca c Alguns processadores duplicam circuitos para permitir que mais de uma operaao aritmtica seja executada por vez. E muito comum, por exemc e plo, a existncia de uma unidade aritmtica para executar instruoes que e e c operam sobre n meros inteiros e outra sobre n meros reais, chamada de u u unidade de ponto utuante. As vezes a UCP conta com mais de uma de cada uma destas unidades. Unidade de Entrada e Sa (UES): controla a comunicaao com os usuda c a rios do computador e os equipamentos perifricos tais como discos e ime pressoras. Em alguns computadores mais simples esta unidade no existe a independentemente, sendo distribu pela Unidade Central de Procesda samento. Em computadores mais poderosos ao contrrio as Unidades de a Entrada e Sa so computadores completos que foram programados para da a controlar a comunicaao com os perifricos. c e

Unidade de Controle

Unidade de Entrada e Sada Memria Discos Vdeo

Unidade Arimtica

Unidade Central de Processamento

Figura 1.7: Diagrama Bsico de um Computador Digital a O termo pipelining que mencionamos acima se refere a um dos modos de como o processador pode paralelizar a execuao de instruoes. Este termo pode c c

1.3. O HARDWARE

29

ser traduzido por linha de montagem, porque exatamente isto que a tcnica e e faz, uma linha de montagem de instruoes. Por exemplo, em uma linha de c montagem de uma fbrica de automveis, mais de um automvel montado a o o e ao mesmo tempo. No in cio da linha o carro no existe. Em cada estgio da a a linha de montagem os operrios vo adicionando partes e ao m da linha sai a a um carro novo. Se voc olhar a linha poder ver carros em diversos estgios da e a a montagem. Repare que a linha no pra, e a montagem de um carro no espera a a a que o que comeou a ser montado antes dele esteja terminado. Nas linhas de c montagem muitos carros so montados ao mesmo tempo. O efeito nal que a e cada carro continua levando bastante tempo para ser montado, mas como vrios a vo sendo montados ao mesmo tempo, algum que se colocasse no nal da linha a e de montagem teria a impresso que cada carro leva muito pouco tempo para a ser montado. Isto porque no nal da linha de montagem sai um carro a cada poucos minutos. O mesmo acontece com a linha de montagem de instruoes. c

1.3.1

Microcomputadores

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

Tabela 1.3: Exemplos de Microprocessadores

Usualmente se chama de computador, o processador mais os seus perifricos e e os sistemas para controlar estes perifricos, ou seja todo o sistema de procese samento de dados. Os perifricos so os dispositivos usados para fazer a entrada e a e sa dos dados que sero processados. da a Os microcomputadores so computadores baseados em microprocessaa dores. As assim chamadas placas me dos microprocessadores atuais incluem a diversos componentes que formam o microcomputador. Por exemplo, uma placa me pode incluir o microprocessador e seus circuitos de suporte, que, no cona junto so conhecidos como o chipset. Alm disso a placa me pode incluir a e a tambm a memria principal e as placas de controle de perifricos, como a e o e placa de v deo, e os conectores para os perifricos, enm, quase todo o sistema. e

30

CAP ITULO 1. INTRODUCAO

1.3.2

Memrias o

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

PROCESSADOR

MEMRIA
CACHE
REGISTRADORES

DISCO

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

1.3. O HARDWARE

31

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

32

CAP ITULO 1. INTRODUCAO

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

1.3.3

Bits e Bytes

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

BYTE 8 BITS

PALAVRA 32 BITS 4 BYTES

Figura 1.9: Tamanho de Bits, Bytes e Palavras

Observar que estamos falando de dados na memria e no do tamanho dos o a dados que o computador pode processar. Considere que este tamanho relacioe nado com a quantidade mxima de algarismos que um n mero pode ter para ser a u processado. Um computador pode ter capacidade de processar 64 bits de cada vez. Caso sua memria tenha palavras de 32 bits o processador dever, ento, o a a ler duas palavras da memria para poder processar um n mero. Lembre-se que o u as duas leituras so atendidas uma de cada vez. Da mesma forma o computador a pode processar 32 bits de cada vez e a memria ter largura 64 bits. Isto pode o acelerar o processamento, j que o processador est se adiantando e recebendo a a

1.4. O SOFTWARE

33

o que poder ser o prximo dado a ser processado, ou seja economizando uma a o leitura. Devido a base 2 o fator kilo tem um signicado diferente em computaao. c Por exemplo 1 Kbyte de memria corresponde a 2 elevado a 10 (210 ), ou seja o 1024 bytes. Da mesma forma 1 Megabyte corresponde a 1024 x 1024 bytes e 1 Gigabyte igual a 1024 x 1024 x 1024 bytes. Na Tabela 1.4 esto mostradas as e a diversas abreviaoes usadas quando se fazem referncias `s memrias. c e a o Nome Kilobyte Megabyte Gigabyte Terabyte Petabyte Exabyte S mbolo Kb MB GB TB PB PB Multiplicador 210 = 1024 220 230 240 250 260

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

1.3.4

Perifricos e

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

Tabela 1.5: Exemplos de perifricos e

1.4

O Software

Tudo isto que sobre o que acabamos de escrever constitui o hardware do computador, o que se v e o que se toca. A partir de agora falaremos brevemente e no software, o que no se v nem se toca, mas tambm est l. a e e a a

34

CAP ITULO 1. INTRODUCAO

Para que um computador execute alguma tarefa primeiro se desenvolve um algoritmo , que uma espcie de receita que diz precisamente, ao computae e dor, como o problema deve ser resolvido. Esta deniao informal de algoritmo c enganosamente simples, e a chave para entender o engano est nas palavras e a dizer precisamente ao computador. Por exemplo, uma receita em gastronomia normalmente no um algoritmo. Receitas so entendidas pela comunidade a e a de cozinheiros, que as seguem facilmente durante o preparo do prato. No entanto, receitas esto cheias de expresses como, por exemplo, mexer at car a o e no ponto e colocar sal a gosto. Fora da comunidade de cozinheiros estas expresses so pass o a veis de vrias interpretaoes. Para escrever algoritmos prea c cisamos de uma linguagem matematicamente precisa e sem ambig idades. u A escrita de um algoritmo consta de uma deniao do estado inicial do c problema a ser resolvido e de regras precisas que estabelecem a cada instante os passos a serem seguidos. Como em um jogo, alm de denir os passos, so e a necessrias regras que denam se aps a execuao de um passo do algoritmo o a o c novo estado do problema vlido. As regras do xadrez denem o estado inicial e a do tabuleiro, os movimentos poss veis de cada pea e se aps um movimento c o de uma pea a conguraao atingida vlida. Ou seja precisamos vericar em c c e a cada instante qual dos movimentos (instruoes) pode ser usado. c Algoritmos podem ser chamados de procedimentos efetivos e devem obedecer aos seguintes limites: sempre dar alguma resposta; sempre dar a resposta correta e nunca uma resposta incorreta; terminar em um n mero nito de passos; u trabalhar em todos os exemplos da classe de problemas que o algoritmo se prope a resolver. o Em seguida este algoritmo deve ser traduzido para uma linguagem que possa ser entendida pelo computador ou que possa ser traduzida para esta linguagem. No in cio da computaao eletrnica com programas armazenados, estes eram c o escritos diretamente em linguagem de mquina que a linguagem que o coma e putador realmente entende. Estas instruoes so conjuntos de bits indicando c a a operaao que deve ser executada e, caso necessrio, onde como achar os os c a dados que sero operados. Por esta razo tambm costuma-se dizer que so a a e a programas escritos em binrio. a Com a evoluao da computaao os programas passaram a ser escritos em c c assembly , que uma representaao em mnemnicos das instruoes de mquina. e c o c a Deste modo era mais fcil escrever os algoritmos. Por exemplo, um fragmento e a de um programa escrito em assembly do processador PowerPC : e li r3,4 li r4,8 * O primeiro numero a ser somado e 4. * 8 e o segundo numero

1.4. O SOFTWARE add r5,r4,r3 * Some os contedos de r3 (4) e r4 (8) u * e armazene o resultado em r5

35

Este pequeno trecho de programa armazena os n meros 4 e 5 em registradou res internos do processador em seguida os soma e armazena o resultado em um terceiro registrador. As informaoes aps os asteriscos so comentrios usados c o a a para explicar o que o programa est fazendo naquela instruao. a c O PowerPC um microprocessador criado em 1991 por um consrcio fore o mado pela IBM, Apple e Motorola Os microprocessadores PowerPC podem ser usados para equipar desde sistemas embutidos at computadores de alto deseme penho. A Apple usou este microprocessador para equipar suas mquinas at a e 2006. Um programa escrito em assembly deve ser traduzido para a representaao c binria, tarefa que normalmente se chama de montar o programa. A palavra a assembler frequentemente usada erradamente para signicar a linguagem e e no o programa que traduz o programa de assembly para linguagem binria de a a mquina. Este tipo de programaao pode levar a se escrever programas muito a c ecientes, devido ao controle quase que total do programador sobre a mquina. a No entanto devido ao fato de ser uma linguagem prxima do computador e afaso tada da maneira de raciocinar do ser humano mais dif de ser usada. Alm e cil e deste fato h outros problemas tais como: diculdade de leitura por humanos, a diculdade de manutenao dos programas, maior tempo de desenvolvimento etc. c Para evitar estes problemas foram desenvolvidas as linguagens de programaao chamadas de linguagens de alto n c vel, por estarem mais prximas da o linguagem natural empregada pelos serem humanos. Alguns exemplos de linguagens de programaao so: c a Fortran: Usada em programaao cient c ca e engenharia; Pascal: Usada em ensino de linguagens e desenvolvimento de sistemas; COBOL: Usada em ambientes comerciais; Basic: O nome diz tudo, bsica; a C: Mesmas caracter sticas do Pascal com facilidades que permitem mais controle do computador; C++: Linguagem originria do C com metodologia de orientaao ` objetos; a c a Java: Linguagem tambm baseada na sintaxe do C e tambm seguindo o moe e delo de orientaao ` objetos. c a Delphi: Linguagem originria do Pascal com metodologia de orientaao ` oba c a jetos; Lisp e Prolog: Linguagens usadas para desenvolver programas de Inteligncia e Articial.

36

CAP ITULO 1. INTRODUCAO

Aplicativos importantes para os programadores so os compiladores. Esa tes programas traduzem programas escritos em linguagens de alto n vel para a linguagem de mquina, de modo que o computador possa execut-los. De a a maneira geral um compilador um programa que traduz um programa de uma e linguagem para outra. Podemos resumir os passos necessrios para criar um programa em uma a linguagem de programaao, por exemplo C, nos passos descritos a seguir. A c Figura 1.10 ilustra a ordem em que se desenvolvem estes passos. Criao do Algoritmo: neste passo criado o algoritmo que ir resolver o ca e a problema. As diversas maneiras de descrever um algoritmo sero apresena tadas no prximo cap o tulo. Codicao do Algoritmo: O algoritmo preparado no passo anterior esca e crito em uma linguagem de programaao. Neste passo o programador c conta, normalmente, com a ajuda de um editor de textos (no processaa dor de textos). Para esta ediao qualquer editor pode ser usado. Hoje c em dia muitos ambientes de desenvolvimento integram todas as ferramentas necessrias para criar um programa, inclusive o editor, em um unico a aplicativo. Compilao do Programa: O arquivo texto contendo o programa passa por ca um programa especial chamado compilador que gera, caso no hajam era ros, uma sa que quase o programa executvel, ou seja o programa em da e a cdigo binrio do processador em que ser executado. Os erros mais coo a a muns nesta etapa so erros de uso correto da linguagem de programaao. a c Estes erros so chamados de erros de compilaao. As linguagens de proa c gramaao so baseadas em regras gramaticais muito r c a gidas e qualquer violaao destas regras pode implicar em erro. No caso de erros serem c encontrados o programador deve voltar ao passo de codicaao para a c correao dos erros. c Ligao: Em ingls este passo conhecido por link edition. Um programa ca e e completo composto por vrios mdulos que podem ter sido criados pelo e a o prprio programador ou por outras programadores. Por exemplo, em C o os trechos de programa que interagem com os usurios, os comandos de a entrada e sa de dados, normalmente vm com o programa compilador. da e Estes trechos podem estar guardados em bibliotecas de programas e so a ligados ao programa do usurio para completar o programa. a Depurao e Testes: Nesta etapa o programa ser testado para a retirada ca a dos poss veis erros de lgica que o programador cometeu. Caso algum o erro seja encontrado o programador deve reelaborar o que estiver errado no algoritmo e em seguida ir para a etapa de codicaao do algoritmo. c Este ciclo pode repetir-se in meras vezes at que o desenvolvedor acredite u e que os erros foram corrigidos.

1.4. O SOFTWARE

37

Uso do Programa: O programa foi entregue aos seus usurios para ser usaa do. Durante o uso, erros que no foram encontrados durante o desenvola vimento do programa podem ser descobertos e precisam ser corrigidos. A correao pode ser feita pelos mesmos programadores que desenvolveram o c programa ou por outro grupo devidamente treinado. Costuma-se chamar esta correao de manutenao do programa. c c

Incio Ligao

Criao de Algoritmo

Depurao e Testes

Codificao do Algoritmo

Sim

Erros de Execuo? No

Compilacao do Programa

Uso do programa

Sim Erros de Compilao? No

Sim Erros de Execuo?

Figura 1.10: Ciclo de desenvolvimento de um programa. Algumas linguagens de programaao no so compiladas e sim interpretac a a das. Isto signica que o programa para ser executado no precisa ser tradua zido diretamente para linguagem de mquina, gerando um arquivo executvel. a a Este arquivo nal, se torna independente do programa fonte. Para executar o programa podemos usar somente o arquivo executvel. Em um programa intera pretado um aplicativo l o programa instruao por instruao, diretamente na e c c prpria linguagem de alto n o vel, traduz cada uma destas instruoes para linc guagem de mquina e as executa. No h, portanto, o processo de traduao a a a c antecipada do programa. A interpretaao de um programa funciona como o c processo de traduao simultnea do discurso de um orador. A medida que ele c a pronuncia seu discurso um tradutor repete as frases na linguagem destino. Um programa compilado funciona como se primeiro, o tradutor traduzisse todo o discurso e depois o lesse. A linguagem Basic uma linguagem interpretada. e Em Java ocorre um processo um pouco diferente. Um programa em Java e traduzido para uma linguagem intermediria e depois interpretado por meio a de uma chamada mquina virtual. No h efetivamente uma compilaao para a a a c

38

CAP ITULO 1. INTRODUCAO

linguagem de mquina. A execuao de um programa escrito em uma linguaa c gem interpretada mais lenta, j que o processo de interpretaao e execuao ao e a c c mesmo tempo mais lento do que a simples execuao de um programa traduzido e c antecipadamente. Hoje em dia a maior parte dos usurios de computadores no so programaa a a dores e sim pessoas que usam programas para resolver seus problemas do dia a dia. Aplicativos t picos que rodam nos computadores so: editores de texto, a processadores de texto, planilhas eletrnicas, compiladores, bancos de dados, o jogos, etc. Para gerenciar os recursos do computador existe um programa especial normalmente chamado de Sistema Operacional (S. O.). Por exemplo, considere o problema de gerenciar como os diversos programas que um usurio normalmente a utiliza partilharo o processador do computador. Um usurio pode estar oua a vindo m sica, digitando um texto e imprimindo um outro documento ao mesmo u tempo. Portanto, os computadores so capazes de executar um n mero de taa u refas muito maior do que o n mero de processadores dispon u veis. Atualmente a maior parte dos computadores possui somente um processador. O Sistema Operacional controla a alocaao de recursos tais como: comunicaao com os c c usurios, espao em discos, uso de memria, tempo que cada programa pode roa c o dar etc. Alguns dos sistemas operacionais conhecidos so os baseados no padro a a UNIX, por exemplo o LINUX. Outros sistemas muito usados so os da fam a lia Windows. Compilando Programas Simples em C Para resolver os exerc cios deste livro voc ir precisar de um compilador para a e a linguagem C e de um editor de textos simples (no processador do como o Word). a O editor pode ser to simples quanto o Notepad, na verdade recomendamos a fortemente que o editor seja simples para que voc possa ter contacto com e todas as etapas do processo de desenvolvimento de um programa. Para compilar empregaremos o compilador gcc que gratuito e pode ser obtido na Internet e como veremos adiante. No ser necessrio nenhum ambiente mais complexo, a a a tal como um Integrated Development Environment (IDE). A coleao de compiladores da GNU (GNU Compiler Collection) usualmente c abreviada por gcc, uma coleao de compiladores produzidos pelo projeto GNU. e c A abreviaao gcc, originalmente, signicava GNU C Compiler. Este aplicativo c distribu gratuitamente pela Free Software Foundation (FSF) sob a licena e do c GNU GPL e GNU LGPL. Este o compilador padro para os sistemas opee a racionais livres do tipo Unix, como o LINUX, e diversos sistemas operacionais proprietrios como o Apple Mac OS X. Atualmente o gcc pode compilar C++, a Objective-C, Java, Fortran e ADA, entre outras linguagens. Vamos considerar, como exemplo, um programa chamado teste.c. Para compilar e gerar o executvel para este programa digitamos o comando a gcc -o teste teste.c -Wall

1.5. UM PROGRAMA EM C

39

em uma janela de comandos no sistema Windows ou em um terminal nos sistemas Unix. O suxo .c no nome do programa normalmente usado para indicar e que o arquivo de um programa C. Este comando deve ser digitado no diretrio e o onde est o arquivo fonte teste.c. O arquivo executvel ser armazenado no a a a mesmo diretrio. o Nos sistemas Unix normalmente o gcc faz parte da distribuiao padro e c a nada precisa ser feito. No Windows uma maneira fcil de obter uma verso a a do gcc instalar o MinGW (Minimalist GNU for Windows). MinGW uma e e coleao de arquivos e bibliotecas distribu c das livremente as quais combinadas com outras ferramentas da GNU permitem que programas para Windows sejam produzidos sem a necessidade de bibliotecas extras e pagas. O MinGW dispe o de um programa instalador que facilita enormemente o processo. Este programa pode ser obtido no s ocial do MinGW. Caso aps a instalaao, o comando tio o c indicado no funcione uma das razes para a falha pode ser que o sistema opea o racional no sabe onde se encontra o compilador gcc. Suponha que o programa a gcc foi instalado no diretrio C:\MinGW\bin. Uma soluao digitar o caminho o c e completo do compilador. Neste caso o comando se torna C:\MinGW\bin\gcc -o teste teste.c -Wall Para que no seja necessrio digitar o caminho completo, preciso adicioa a e nar este caminho ` varivel PATH do Windows. Consulte o manual para obter a a informaoes de como fazer este passo no seu sistema Windows. c

1.5

Um programa em C

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

40

CAP ITULO 1. INTRODUCAO Listagem 1.1: Exemplo de Programa em C.

#include < stdio .h > i n t main ( void ) { printf ( " Alo Mundo !\ n " ); return 0; }

1.6

Exerc cios

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

Cap tulo 2

Algoritmos
2.1 Introduo ca

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

42

CAP ITULO 2. ALGORITMOS

poss vel a funao de criador de algoritmos desapareceria. Claro que existem c linhas mestras e estruturas bsicas, a partir das quais podemos criar algorita mos, mas a soluao completa depende em grande parte do criador do algoritmo. c 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 apresenta uma verso para a origem desta palavra. Ela seria derivada do nome de um famoso a matemtico persa chamado Abu Jafar Maom ibn M s al-Khowrism (825) a e ua a que traduzido literalmente quer dizer Pai de Jafar, Maom, lho de Moiss, e e de Khowrizm. Khowrizm hoje a cidade de Khiva, na ex Unio Sovitica. a a e a e Este autor escreveu um livro chamado Kitab al jabr wal-muqabala (Regras de Restauraao e Reduao). O t c c tulo do livro deu origem tambm a palavra e Algebra. O signicado da palavra muito similar ao de uma receita, procedimento, e tcnica, rotina. Um algoritmo um conjunto nito de regras que e e fornece uma seqncia de operaoes para resolver um problema esue c pec co. Segundo o dicionrio do prof. Aurlio Buarque de Holanda um algoa e ritmo um: e Processo de clculo, ou de resoluao de um grupo de problemas sea c melhantes, em que se estipulam, com generalidade e sem restrioes, c regras formais para a obtenao de resultado ou de soluao de proc c blema. Um algoritmo opera sobre um conjunto de entradas (no caso do bolo, farinha ovos, fermento, etc.) de modo a gerar uma sa que seja util (ou agradvel) da a para o usurio (o bolo pronto). a Um algoritmo computacional tem cinco caracter sticas importantes: Finitude: Um algoritmo deve sempre terminar aps um n mero nito de paso u sos. Denio: Cada passo de um algoritmo deve ser precisamente denido. As ca aoes devem ser denidas rigorosamente e sem ambiguidades. c Entradas: Um algoritmo deve ter zero ou mais entradas, isto quantidades e que so lhe so fornecidas antes do algoritmo iniciar. a a Sa das: Um algoritmo deve ter uma ou mais sa das, isto quantidades que tem e uma relaao espec c ca com as entradas. Efetividade: Um algoritmo deve ser efetivo. Isto signica que todas as operacoes devem ser sucientemente bsicas de modo que possam ser, em princ a pio, executadas com preciso em um tempo nito por um humano usando a papel e lpis. a

2.2. PRIMEIROS PASSOS

43

2.2

Primeiros Passos

E claro que todos ns sabemos construir algoritmos. Se isto no fosse verdade, o a no conseguir a amos sair de casa pela manh, ir ao trabalho, decidir qual o melhor a caminho para chegar a um lugar, voltar para casa, etc. Para que tudo isto seja feito necessrio uma srie de entradas do tipo: a que hora acordar, que hora e a e sair de casa, qual o melhor meio de transporte etc. Um fator importante e que pode haver mais de um algoritmo para resolver um determinado problema. Por exemplo, para ir de casa at o trabalho, posso escolher diversos meios de e transporte em funao do preo, conforto, rapidez, etc. A escolha ser feita em c c a funao do critrio que melhor se adequar as nossas necessidades. Um exemplo c e de algoritmo pode ser as instruoes que um professor passa aos seus alunos em c uma academia de ginstica, mostrado no Algoritmo 2.1. Observar que nesta a representaao do algoritmo cada linha contm uma instruao. c e c Algoritmo 2.1: Exemplo de Algoritmo. in cio enquanto no fez 10 vezes faa a c Levantar e abaixar brao direito c Levantar e abaixar brao esquerdo c Levantar e abaixar perna esquerda Levantar e abaixar perna direita m enqto m Computadores so mquinas muito ecientes na resoluao de problemas maa a c temticos ou que envolvam n meros. Como exemplo de um algoritmo matema u a tico, vamos considerar o problema de resolver uma equaao do primeiro grau da c forma ax + b = 0 A soluao desta equaao c c e x = b/a se o valor de a for diferente de 0. Caso a seja igual a 0, a equaao no possui c a soluao, j que no poss dividir por 0. Este algoritmo escrito (Algoritmo c a a e vel 2.2) em uma pseudo-linguagem de programaao caria da seguinte maneira: c As instruoes do algoritmo so executadas passo a passo e uma intruao c a c somente executada quando a anterior terminou sua tarefa. Os dois primeiros e passos do algoritmo servem para o algoritmo obter os valores dos coecientes a e b. Os valores podem, por exemplo, serem digitados em um teclado pelo usurio a que est usando o algoritmo. O valor digitado vai para uma posiao da memria a c o do computador, que para facilitar o manuseio do dado, recebe um nome. Neste exemplo demos os nomes a, b e x as posioes de memria usadas pelo programa c o para armazenar dados. Aps os dois primeiros passos o algoritmo executa uma o

44

CAP ITULO 2. ALGORITMOS

Algoritmo 2.2: Algoritmo para resolver uma equaao do primeiro grau. c Entrada: Coecientes a e b da equaao ax + b = 0 c Sa da: Resultado x da Equaao c in cio ler a ler b se a = 0 ento a imprimir A equa~o nao tem solu~o ca ca seno a x b/a imprimir A raiz da equa~o vale , x ca m se m

instruao de teste para vericar se o valor de a diferente de 0. Neste caso c e podemos ter duas respostas e o computador ir escolher entre dois caminhos a independentes e exclusivos. Caso a seja igual a zero, o algoritmo executa as instruoes entre a palavra ent~o e sen~o, e portanto, imprime uma mensagem c a a de aviso para o usurio e termina. Esta mensagem normalmente aparece em a um monitor de v deo. No caso de a ser diferente de zero, o algoritmo executa as instruoes entre sen~o e fim se. Isto signica calcular o resultado da equaao c a c e atribuir este resultado ` x. O ultimo passo, desta opao a impresso do a c e a resultado da equaao. c

2.3

Representao ca

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

2.3. REPRESENTACAO

45

2.3.1

Linguagem Natural

A representaao em linguagem natural tem a desvantagem de colocar uma c grande distncia entre a soluao encontrada e o resultado nal do processo a c que um programa em linguagem de programaao. O Algoritmo 2.3 mostra e c um algoritmo, escrito em linguagem natural, para calcular a mdia de um aluno e que faz trs provas e precisa de obter mdia acima de 5.0 para ser aprovado. e e Algoritmo 2.3: Algoritmo para calcular a mdia das notas de um aluno. e Entrada: Notas n1 , n2 e n3 . Sa da: Resultado media do aluno e se ele foi aprovado ou no. a in cio Obter as notas n1 , n2 e n3 Calcular mdia. Usar a frmula ((n1 + n2 + n3 )/3.0). e o Se a mdia for maior que 5.0 imprimir que o aluno foi aprovado e Caso contrrio imprimir que o aluno foi reprovado. a Imprimir a mdia. e m

2.3.2

Fluxogramas

Esta forma de representaao de algoritmos emprega vrias formas geomtricas c a e para descrever cada uma das poss veis aoes durante a execuao do algoritc c mos. Existem algumas formas geomtricas que usualmente so empregadas e a neste mtodo. Estas formas esto mostradas na Figura 2.1. Cada uma destas e a formas se aplica a uma determinada aao como est indicado na gura. Estas c a formas so apenas alguns exemplos, existindo outras, no entanto, nesta apostila a estas sero sucientes para os exemplos que sero mostrados. a a
Incio e Fim de Fluxograma Processamento

Ponto de Deciso

Entrada de Dados Manual

Impresso de Resultados

Conector para mesma pgina

Figura 2.1: S mbolos mais comumente usados em uxogramas.

Como exemplo de um algoritmo escrito em forma de uxograma, vamos considerar o algoritmo 2.2 para resolver uma equaao do primeiro grau da forma c ax + b = 0. A Figura 2.2 mostra um uxograma para resolver este problema.

46
Incio

CAP ITULO 2. ALGORITMOS

Obter a

Obter b

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

Imprime x

Fim

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

Os dois primeiros passos do algoritmo lem os valores dos coecientes a e e b da equaao. Em seguida h um teste para descobrir se o valor de a igual c a e a zero. Se o valor de a for igual a zero o algoritmo manda que seja impressa uma mensagem informando que a equaao no tem soluao. Caso o valor de c a c a seja diferente os prximos passos calculam o valor da soluao e em seguida o c imprimem este resultado

2.3.3

Pseudo-Linguagem

Este modo de representar algoritmos procura empregar uma linguagem que esteja o mais prximo poss de uma linguagem de programaao de computadoo vel c res de alto n vel, mas evitando de denir regras de construao gramatical muito c r gidas. A idia usar as vantagens do emprego da linguagem natural, mas e e restringindo o escopo da linguagem. Normalmente estas linguagens so verses a o ultra reduzidas de linguagens de alto n do tipo Pascal ou C. O algoritmo 2.2 vel foi escrito em uma pseudo-linguagem. A maioria destas linguagens so muito a parecidas e tm a vantagem de serem facilmente entendidas. Vamos apresentar e agora um outro exemplo (Algoritmo 2.4) escrito em pseudo-linguagem. Este algoritmo serve para descobrir qual a maior nota de um grupo de trs notas e e de um aluno. O algoritmo inicialmente l a primeira nota e guarda esta nota e

2.3. REPRESENTACAO

47

como a maior nota. Em seguida, l cada uma das outras notas e compara com e a nota guardada como a maior nota. Caso a nota lida seja maior substitui o valor anterior pelo novo valor.

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

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

48

CAP ITULO 2. ALGORITMOS

2.4

Modelo de von Neumann

Algoritmos para computadores se baseiam em alguns conceitos bsicos e em um a modelo de computador, os quais devem ser bem entendidos para que se possa criar algoritmos ecientes. Este modelo foi proposto pelo matemtico h ngaro a u Neumann Jnos Lajos Margittai. Em h ngaro o nome de fam aparece antes. a u lia Assim em portugus o seu nome seria Jnos Lajos Margittai Neumann. O seu e a pai, que era rico, comprou um t tulo de nobreza e ele passou a se chamar Jnos a Lajos Margittai von Neumann. No modelo de computador proposto por von Neumann as instruoes e os dados cam juntos na memria. O processador c o busca na memria e executa uma instruao de cada vez. o c Para ilustrar como este modelo funciona vamos analisar passo a passo a execuao de um algoritmo simples. Na Figura 2.3 mostramos nos endereos c c 0, 1 e 2, de uma memria, um grupo de instruoes formando parte de um o c algoritmo. As instruoes tambm podem ser acompanhadas no Algoritmo 2.5. c e Vamos assumir que o computador comee executando o algoritmo a partir da c instruao que est no endereo 0. O procedimento normal a Unidade de c a c e Controle (UC) do computador continuar buscando e executando uma instruao c de cada vez nos endereos seguintes, a no ser que haja uma ordem para desviar c a o uxo das instruoes. E importante observar que o computador executa uma c instruao de cada vez, e como veremos adiante, tambm um dado buscado de c e e cada vez. Portanto, as transferncias entre a memria e o processador so feitas e o a passo a passo. O ciclo normal da execuao de um programa ento: c e a 1. Busca instruao; c 2. Decodica instruao; c 3. Executa instruao; c 4. Volta para o passo 1 buscando a instruao seguinte na memria. c o Portanto, aps a instruao do endereo 0 ser lida da memria e trazida para o c c o a UCP, ela decodicada pela UC, que descobre que a instruao manda carregar e c o valor inteiro 2 na posiao de memria 10, que chamada de a para facilitar. c o e A instruao seguinte ordena a carga do valor inteiro 8 na posiao de memria c c o chamada de b, que a posiao 11. A ultima instruao ordena a soma dos valores e c c armazenados em a e b e que o resultado seja armazenado na posiao 12, que c e chamada c. Observe que no modelo de von Neumann instruoes e dados cam na memria. c o Considere a ultima instruao do programa que pede para que os dados da posiao c c 10 (a) e 11 (b) sejam somados e o resultado armazenado na posiao 12 (c). Para c executar esta instruao, o computador faz as seguintes operaoes na memria: c c o 1. ler a instruao no endereo 2; c c 2. ler o dado a na posiao 10; c

2.5. ESTRUTURAS BASICAS DE ALGORITMOS Algoritmo 2.5: Modelo de memria e funcionamento de um algoritmo o -- Armazena 2 na memria no lugar chamado a o a2 -- Armazena 8 na memria no lugar chamado b o b8 -- Soma a com b e armazena no lugar chamado c ca+b

49

3. ler o dado b na posiao 11; c 4. escrever o resultado da soma no endereo 12. c Portanto, temos 3 leituras e uma escrita. Destas operaoes, a primeira c e uma leitura de instruao e as restantes operaoes com dados. c c
0 1 2 3 4 5 6 7

a<-2
8

b<-8
9

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

2
16 17 18

8
19

10
20 21 22 23

24

25

26

27

28

29

30

31

Endereo Endereo Endereo Endereo Endereo Endereo

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

Figura 2.3: Modelo de memria o

2.5

Estruturas Bsicas de Algoritmos a

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

50

CAP ITULO 2. ALGORITMOS

sentar a linguagem C. Para o programador iniciante esta discusso serve como a introduao. c

2.5.1

Comandos de leitura

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

2.5.2

Comandos de escrita

Aps a obtenao dos resultados do algoritmo, estes devem ser apresentados ao o c usurio, e para isto usamos os comandos de escrita. Por exemplo o comando a imprimir x imprime o valor atual que est na memria representada pelo nome x. a o Da mesma forma que nos comandos de leitura poss colocar uma lista e vel de nomes de variveis aps o comando. Por exemplo, o comando a o imprimir x1, x2 imprime os valores das variveis x1 e x2. O meio de apresentaao dos resultados, a c normalmente, um monitor de v e deo.

2.5. ESTRUTURAS BASICAS DE ALGORITMOS

51

O comando imprimir pode ser usado para mandar mensagens de texto para o usurio do algoritmo das formas mais variadas. Alguns exemplos de a comandos de impresso so os seguintes: a a imprimir Entre com o valor do coeciente imprimir O valor de x , x e imprimir O valor de x1 , x1, e o de x2 , x2 e e Notar que os textos entre aspas indicam um texto que deve ser impresso no perifrico de sa sem nenhuma modicaao. Vamos considerar que as variveis e da c a destes exemplos valem x = 10, x1 = 5 e x2 = 8. Os trs comandos mostrariam e no perifrico de sa os seguintes resultados: e da Entre com o valor do coeficiente. O valor de x 10 e O valor de x1 5 e o de x2 8 e e

2.5.3

Expresses o

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

52 +3 3 -324 -50 So exemplos de n meros reais: a u +0.5 0.5 -8.175 2.0

CAP ITULO 2. ALGORITMOS

Dados alfa-numricos servem para tratamento de textos e normalmente so e a compostos por uma seqncia de caracteres contendo letras, algarismos e caue racteres de pontuaao. Nos algoritmos so normalmente representados por uma c a seqncia de caracteres entre aspas, por exemplo: ue Linguagem de programa~o ca Qual o seu nome? e 12345 Dados lgicos so intensamente aplicados durante o processo de tomada o a de decises que o computador frequentemente obrigado a fazer. Em muitos o e textos este tipo de dados tambm chamado de tipo de dados booleanos, devido e e a George Boole, matemtico que deu ao nome ` lgebra (lgebra booleana) que a aa a manipula este tipo de dados. Os dados deste tipo somente podem assumir dois valores: verdadeiro e falso. Computadores tomam decises, durante o o processamento de um algoritmo, baseados nestes dois valores. Por exemplo, considere a deciso abaixo: a se a = 0 ento a imprimir A equa~o nao tem solu~o ca ca seno a x b/a imprimir A raiz da equa~o vale , x ca m se Neste algoritmo aparece a expresso a = 0, que procura descobrir se o valor a de raiz igual a 0. Esta expresso somente pode ter como resultado os valores: e a verdadeiro ou falso. Nos nossos algoritmos estes valores sero representados por a verdadeiro e falso. Expresses Aritmticas o e Para os nossos exemplos iniciais iremos adotar os operadores aritmticos binrios e a mostrados na Tabela 2.5.3. A coluna prioridade indica a prioridade relativa dos

2.5. ESTRUTURAS BASICAS DE ALGORITMOS

53

operandos. O menor n mero indica a maior prioridade. Quando temos dois opeu randos de mesma prioridade o computador ir executar primeiro a operaao mais a c a ` esquerda. Em computaao, as expresses devem ser escritas em linhas e para c o alterar a prioridade deve-se usar parnteses. Maiores detalhes sobre expresses e o sero apresentados no Cap a tulo 5. No momento, estamos apenas apresentando alguns conceitos bsicos para facilitar a discusso de alguns algoritmos. a a Operador / * % + Descrio ca Diviso a Multiplicaao c Mdulo (resto da diviso de o a operandos inteiros) Soma Subtraao c Prioridade 0 0 0 1 1

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

b 4ac
1 1 1+ a+b

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

2.5.4

Comandos de atribuio ca

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

54

CAP ITULO 2. ALGORITMOS

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

2.5.5

Comandos de controle

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

Algoritmando

Falso Condio

Verdadeiro

Faa isto

Faa aquilo

Continuo algoritmando

Figura 2.4: Fluxograma do comando se ...

ent~o ... a

sen~o. a

Algoritmo 2.6: Comando se em pseudo-linguagem se Condiao sendo testada ento c a Faa isto c seno a Faa aquilo c m se Um exemplo de uso desta contruao, escolhido a partir da vida real, pode ser c

2.5. ESTRUTURAS BASICAS DE ALGORITMOS

55

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

2.5.6

Comandos de repetio ca

As linguagens de programaao normalmente possuem diversos comandos que c permitem que um trecho de algoritmo seja repetido um n mero de vezes. Para u estes exemplos iniciais iremos apresentar um comando de repetiao que sucic e entemente geral para substituir todos os outros. Este comando, que chamaremos de comando enquanto tem a forma mostrada na Figura 2.6. O comando funciona da seguinte maneira: Passo 1: Testar se a condiao verdadeira. Caso seja verdade executar o bloco c e de comandos situados entre o in do comando e o nal do comando. O cio nal do comando enquanto normalmente marcado de alguma forma. Em e nossa pseudo-linguagem marcaremos o m pelas palavras fim enquanto ou fim eqto.

56

CAP ITULO 2. ALGORITMOS

Vestir para ir ao cinema

Falso Chovendo?

Verdadeiro

Pegar guarda-chuva

Ir ao cinema

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

Passo 2: Executar o bloco de comandos at o m do enquanto. Quando chegar e ao m retornar automaticamente para o in cio do comando e refazer o passo 1. Como exemplo consideremos o caso em que precisamos ler um conjunto de 10 n meros e imprimir se cada um dos n meros lidos par ou no. Para descobrir u u e a se o n mero par vamos dividi-lo por 2 e testar o resto. Lembrar que caso o u e resto da diviso seja igual a zero o n mero par. Neste algoritmo sabemos a a u e quantidade de n meros a serem lidos e portanto o n mero de repetioes pru u c e e determinado. O Algoritmo 2.9 mostra como seria implementada uma soluao c para este problema. Vamos mostrar um exemplo onde o n mero de repetioes no conhecido. u c a e Considere no exemplo anterior que o total de n meros a ser lido no conhecido. u a e Mas ento, como o algoritmo ir terminar de ler n meros? Usaremos o que a a u costuma-se chamar de sentinela em computaao. O algoritmo ir se manter c a lendo n meros enquanto os n meros forem positivos. No momento que for u u lido um n mero negativo o algoritmo pra. A sentinela que indica o nal da u a lista de n meros um n mero negativo. O Algoritmo 2.10 mostra como ca u e u em pseudo-linguagem o algoritmo modicado. Observe que neste algoritmo o primeiro n mero tem de ser lido antes do comando enquanto. Isto porque u assumimos que o primeiro n mero que for digitado pode ser negativo e portanto u a lista de n meros no tem nenhum n mero. u a u

2.6. EXEMPLOS DE ALGORITMOS

57

Algoritmando

Falso Testa Condio

Verdadeiro

Bloco de comandos do enquanto

Continuo algoritmando

Figura 2.6: Fluxograma do comando enquanto.

2.6

Exemplos de Algoritmos

Nesta seao iremos apresentar uma srie de algoritmos escritos na pseudoc e linguagem que acabamos de apresentar. Exemplo 2.1: Este algoritmo serve para descobrir qual a maior nota de uma e turma de alunos. Neste algoritmo iremos considerar que as notas podem variar entre 0.0 e 10.0 e que a turma tem 25 alunos. O algoritmo 2.11 inicialmente inicia a maiorN ota com zero, depois compara cada nota com esta maiorN ota caso ela seja maior substitui o valor anterior pelo novo valor. Observar que criamos uma varivel para armazenar a quantidade de alunos. Voc poderia a e perguntar porque no usar o n mero 25 toda vez que for necessrio. A razo a u a a e simples. Suponha que voc gostaria de usar este algoritmo para calcular a maior e nota de uma turma de 40 alunos. Neste algoritmo bastaria substituir o n mero u 25 por 40. No entanto, existe uma soluao mais geral ainda que permite que c o algoritmo possa ser usado para qualquer tamanho de turma. Este problema est apresentado na lista de exerc a cios deste cap tulo. Exemplo 2.2: Vamos mostrar outro exemplo de algoritmo muito usado. Precisamos ler as notas de uma turma de alunos e calcular a mdia destas notas. e Vamos assumir que a turma tem 25 alunos e as notas esto entre 0 e 10. O a

58

CAP ITULO 2. ALGORITMOS

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

algoritmo est mostrado em Algoritmo 2.12. a Exemplo 2.3: Neste exemplo considere o seguinte problema. Um escritrio de o previso do tempo armazena diariamente a temperatura mdia de uma detera e minada regio. A tarefa descobrir qual a maior temperatura do ano passado. a e e Assuma que foram armazenadas 365 temperaturas, uma para cada dia do ano. Neste caso no podemos aplicar o algoritmo 2.11 usado para descobrir a maior a nota da turma. Antes de continuar procure encontrar a razo. Como dica, a considere que estamos no polo sul e portanto todas as temperaturas lidas so a negativas. Uma soluao poss c vel para este exemplo est mostrada no algoritmo 2.13. a Este algoritmo faz o seguinte. Pega a primeira temperatura e a anota como a menor j encontrada. A partir da o algoritmo ca repetidamente lendo tema peraturas dos registros do escritrio comparando com a temperatura que no o momento consta como a menor de todas. Se a temperatura tirada dos arquivos for menor que a menor atual, o algoritmo joga fora a temperatura anotada e guarda a que foi lida como a nova menor temperatura. Quando no houver a mais temperaturas para ler a que estiver anotada como a menor a menor e verdadeiramente.

2.7

Exerc cios

2.1: Uma empresa paga R$10.00 por hora normal trabalhada e R$ 15.00 por hora extra. Escreva um algoritmo que leia o total de horas normais e o total de horas extras trabalhadas por um empregado em um ano e calcule o salrio a anual deste trabalhador.

2.7. EXERC ICIOS Algoritmo 2.10: Algoritmo para ler n meros e imprimir se so pares ou u a no. a Entrada: n meros, (numero). O algoritmo pra quando um n mero u a u negativo lido e Sa da: Se o n mero par ou no u e a in cio ler numero enquanto numero > 0 faa c se numero % 2 = 0 ento a imprimir numero, par m se imprimir numero, impar ler numero m enqto m

59

2.2: Assuma que o trabalhador do exerc anterior deve pagar 10% de imposto cio se o seu salrio anual for menor ou igual a R$ 12000.00. Caso o salrio seja maior a a que este valor o imposto devido igual a 10% sobre R$ 12000.00 mais 25% sobre e o que passar de R$ 12000.00. Escreva um programa que calcule o imposto devido pelo trabalhador. 2.3: Escreva um algoritmo que descubra a maior nota de uma turma de alunos. O tamanho da turma deve ser o primeiro dado pedido ao usurio. a 2.4: Modique o algoritmo anterior de modo que ele imprima tambm quantas e vezes a maior nota aparece. 2.5: Nos exerc cios anteriores assumimos que os usurios sempre digitam uma a nota entre 0 e 10. Vamos assumir agora que o usurio sempre digita um n mero, a u mas este n mero pode estar fora do intervalo 0 a 10. Ou seja, poderemos ter u uma nota menor que zero ou maior que 10. Modique o algoritmo anterior para que ele verique a nota digitada e, caso o aluno tenha digitado uma nota invlida, uma mensagem avisando o usurio seja impressa e uma nova nota seja a a pedida. O algoritmo deve insistir at que o usurio digite um valor vlido. e a a 2.6: Escreva um algoritmo que leia trs n meros e os imprima em ordem crese u cente. 2.7: Escreva um algoritmo que leia um n mero inteiro entre 100 e 999 e imprima u na sa cada um dos algarismos que compem o n mero. Observe que o n mero da o u u lido com um valor inteiro, e, portanto, ele tem de ser decomposto em trs e e n meros: os algarismos das centenas, dezenas e unidades. u 2.8: Escreva um algoritmo que leia uma hora em horas, minutos e segundos e some um segundo a hora lida.

60

CAP ITULO 2. ALGORITMOS

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

2.9: Escreva um algoritmo que leia duas datas em dia, mes e ano e imprima a data mais recente.

2.7. EXERC ICIOS

61

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

Algoritmo 2.13: Algoritmo para calcular a maior temperatura do ano. Entrada: Temperaturas registrada em ano, (temperatura). Sa da: Maior das temperaturas, (maiorT emperatura) in cio totalT emperaturas 365 ler temperatura J li uma temperatura a totalT emperaturas totalT emperaturas 1 -- A primeira temperatura a maior temperatura e maiorT emperatura temperatura enquanto totalT emperaturas > 0 faa c ler temperatura se temperatura > maiorT emperatura ento a maiorT emperatura temperatura m se totalT emperaturas totalT emperaturas 1 m enqto imprimir A maior nota das notas , maiorT emperatura e m

62

CAP ITULO 2. ALGORITMOS

Cap tulo 3

Tipos de Dados, Constantes e Variveis a


3.1 Introduo ca

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

3.2
3.2.1

Tipos de Dados
Tipos Bsicos a

Os dados em C podem assumir cinco tipos bsicos que so os seguintes: a a char: O valor armazenado um caracter. Caracateres geralmente so armae a zenados em cdigos (usualmente o cdigo ASCII). A Tabela A.1 mostra o o este cdigo. Caracteres so armazenados em um byte. o a int: O valor armazenado um n mero inteiro e o tamanho do subconjunto que e u pode ser representado pelo computador normalmente depende da mquina a em que o programa est rodando. Atualmente em C os n meros inteiros a u so armazenados em 32 bits. a 63

64

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS

oat: N mero em ponto utuante de preciso simples, normalmente 32 bits. u a So conhecidos como n meros reais, no entanto, os computadores somente a u podem armazenar e trabalhar com uma pequena parte do conjunto dos n meros reais. u double: N mero em ponto utuante de preciso dupla, com isto a preciso e u a a as vezes a excurso dos n meros aumenta. Este tipo armazenado em 64 a u e bits. void: Este tipo serve para indicar que um resultado no tem um tipo dea nido. Uma das aplicaoes deste tipo em C criar um tipo vazio que pode c e posteriormente ser modicado para um dos tipos anteriores.

3.2.2

Modicadores de tipos

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

3.3

Constantes Numricas e

Constantes so valores que o programa no pode modicar durante a execuao a a c de um programa. Elas so usadas em expresses para representar vrios tipos de a o a valores. Em C existem regras r gidas para determinar como devem ser escritos estes valores. A seguir iremos mostrar estas regras. Para escrever constantes numricas vamos usar as seguintes denioes: e c

3.3. CONSTANTES NUMERICAS Tipo char unsigned char signed char int unsigned int signed int short int, short unsigned short int signed short int long int, long signed long int unsigned long int long long int long long signed long long int signed long long unsigned long long int unsigned long long oat double long double Bytes 1 1 1 4 4 4 2 2 2 4 4 4 8 8 8 4 8 12 Faixa M nima -127 a 127 0 a 255 -127 a 127 -2.147.483.648 a 2.147.483.647 0 a 4.294.967.295 -2.147.483.648 a 2.147.483.647 -32.768 a 32.767 0 a 65.535 -32.768 a 32.767 -2.147.483.648 a 2.147.483.647 -2.147.483.648 a 2.147.483.647 0 a 4.294.967.295 -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807 0 a 18.446.744.073.709.551.615 oito d gitos de preciso a 16 d gitos de preciso a 16 d gitos de preciso a

65

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

d gito: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 d gito sem zero: 1, 2, 3, 4, 5, 6, 7, 8, 9 d gito octal: 0, 1, 2, 3, 4, 5, 6, 7 d gito hexa: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, A, b, B, c, C, d, D, e, E, f, F sinal: +, ponto decimal: . suxo: sufixo sem sinal, sufixo longo suxo sem sinal: u, U suxo longo: l, L suxo utuante: f, F, l, L O uso destas caracteres ser mostrado com exemplos nas seoes seguintes. a c

66

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS

3.3.1

Constantes Inteiras na base 10

So valores numricos sem ponto decimal, precedidos ou no por um sinal. No a e a a poss separar, por espaos em branco, o sinal do valor numrico. Podemos e vel c e descrever este formato com uma notaao simplicada da seguinte maneira: c [sinal]dgito sem zero{dgito}[sufixo sem sinal|sufixo longo] Esta notaao deve ser entendida da seguinte maneira. Colchetes indicam c opao, portanto, o fato de sinal (+ ou -) estar entre colchetes signica que um c n mero inteiro pode ou no ter sinal, isto o sinal opcional. Em seguida temos u a e e um dgito sem zero que obrigatrio. Isto dados inteiros devem comear e o e c por, pelo menos, um algarismo entre 1 e 9. A seguir temos a palavra dgito entre chaves. As chaves indicam que o fator entre elas pode ser repetido zero ou mais vezes. Portanto, um n mero inteiro, aps o algarismo inicial obrigatrio, u o o pode ser seguido por uma seqncia de zero ou mais algarismos. Como suxo ue podemos ter opcionalmente as letras u (U) ou l (L) ou uma mistura, em qualquer ordem, das duas. Para constantes inteiras o suxo U (u) representa o modicador unsigned. O suxo L (l) representa o modicador long. Um par de Ls (ls) indica que a constante do tipo long long. A tabela 3.2 mostra exemplos de e n meros inteiros: u Tipo int unsigned int long int unsigned long int long long unsigned long long Constantes -3 +5 45u 12345U 1997L -3l 45Lu 23Ul 1997Ll -3ll 45LLu 23Ull

1997 1997U 1234L 1997UL 134LL 1997ULL

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

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

3.3. CONSTANTES NUMERICAS

67

3.3.2

Constantes Inteiras Octais

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

Tabela 3.3: Constantes octais

3.3.3

Constantes Inteiras Hexadecimais

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

Tabela 3.4: Constantes hexadecimais

68

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS

3.3.4

Converso entre Bases a

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

Esta equaao est escrita na base 10. Por exemplo, aplicando a equaao 3.1 c a c para converter o n mero 0175 da base 8 para a base 10 camos com u (0175)8 = 1 82 + 7 81 + 5 80 = (125)10 A frmula para converso da base 8 para a base 10 pode se estendida para o a uma base qualquer com a substituiao do algarismo 8. Considere uma base c qualquer representada por b. Nesta base os d gitos di cam no intervalo b 1 di 0. A equaao 3.2 mostra a frmula para converter um n mero em uma c o u base b qualquer para a base 10. N10 = dn1 bn1 + dn2 bn2 + + d1 b1 + d0 b0 (3.2)

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

3.3.5

Constantes em Ponto Flutuante

Constantes em ponto utuante so usadas para representar n meros reais. O a u nome ponto utuante devido ao modo como os valores so armazenados pelo e a computador. Constantes de ponto utuante podem ser do tipo oat, double, long ou long double. Constantes sem nenhum suxo so consideradas do tipo a

3.3. CONSTANTES NUMERICAS Algoritmo 3.1: Algoritmo para converter inteiros na base 10 para uma base b. Entrada: n mero, (numero) e base b (baseb). u Sa da: D gitos do n mero na base b u in cio ler numero ler base enquanto numero > 0 faa c resto numero % base numero numero / base imprimir resto m enqto m

69

double. Caso seja usado o suxo F ou o f a constante ser considerada como a do tipo oat. O suxo L ou o l torna a constante long double. Uma constante em ponto utuante pode ser denida de duas maneiras. Voc e pode escrever um n mero com ponto decimal (1.5) ou na chamada forma ciu ent ca, em que um expoente usado (0.15E1). Na segunda forma o n mero e u igual a 0.15 101 . E poss e vel omitir ou os d gitos antes do ponto (a parte inteira) ou aps (a parte fracionria), mas nunca os dois grupos. E poss o a vel escrever um n mero em ponto utuante sem ponto, desde que um expoente seja u usado. Portanto, os n meros .8, 1234., 1E1 so n meros de ponto utuante. u a u Para mostrar mais formalmente como se deve escrever as constantes de ponto utuante vamos usar a mesma notaao usada at aqui, mas usando uma hierarc e quia de denioes para facilitar o entendimento. Primeiro damos uma deniao c c mais geral que vai sendo mais detalhada a medida que avanamos. Lembrar c que termos entre chaves podem ser repetidos 0 ou mais vezes e termos entre colchetes so opcionais. a Portanto, usando a forma hierrquica, uma constante de ponto utuante a (CPF) pode ser denida das seguintes maneiras: CPF = [sinal]fra~o[expoente][sufixo flutuante] ca CPF = [sinal]seq dgitos expoente[sufixo flutuante] A seguir denimos cada um dos componentes. Uma fra~o denida como: ca e fra~o = [seq digitos] ponto decimal seq dgitos ou ca fra~o = seq dgitos ponto decimal ca O expoente e a sequncia de d e gitos so denidos como: a expoente = [e | E][sinal]seq dgitos seq dgitos = dgito{dgito} A Tabela 3.5 mostra exemplos de constantes em ponto utuante.

70

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS Descrio ca sinal fra~o expoente ca fra~o ca fra~o expoente ca fra~o sufixo ca seq dgitos ponto decimal N mero u +23.45e-10 123.45 123.45E+10 123.45F 123.

Tabela 3.5: Constantes em ponto utuante

3.4

Constantes Caracteres

Uma constante caractere um unico caractere escrito entre , como em a. Alm e e disso, uma constante de tamanho igual a um byte pode ser usada para denir um caracter, escrevendo-se, por exemplo, \ddd, onde ddd uma constante com e entre um e trs d e gitos octais. Em C, caracteres podem participar normalmente de expresses aritmticas. O valor que entra na expresso o do cdigo usado o e a e o para representar o caractere. Exemplos de constantes do tipo caractere so a mostrados na Tabela 3.6. Caractere a A \0141 ( 9 \n Signicado caractere a caractere A Constante octal correspondente ao caractere a caractere abre parnteses e algarismo 9 Nova linha, posiciona o cursor no nicio da nova linha. Tabela 3.6: Exemplos de constantes caractere

Certos caracteres que no so vis a a veis podem ser representados antepondo-se o caractere \ (barra invertida), como no exemplo nova linha da Tabela 3.6. Este caractere tambm conhecido como caractere de escape. Exemplos so e e a mostrados na Tabela 3.7.

3.4.1

Constantes Cadeias de Caracteres

Neste livro vamos usar em alguns casos a palavra cadeia para signicar cadeia de caracteres (string em ingls). Uma constante do tipo cadeia de caracteres e uma seqncia de qualquer n mero de caracteres entre " como no exemplo: e ue u "alo mundo!!!". E importante notar que a linguagem C insere automaticamente ao nal de uma cadeia de caracteres um caractere null (\0). Este caractere ser usado a

3.5. VARIAVEIS Caractere \n \t \b \f \r \a \0 Signicado Passa para uma nova linha. Tabulaao horizontal, move o cursor c para a prxima parada de tabulaao. o c Retorna um caractere. Salta uma pgina. a Carriage return, posiciona o cursor no nicio da linha atual. Alerta, faz soar a campainha do sistema. Null, caractere que em C termina uma cadeia de caracteres.

71

Tabela 3.7: Exemplos de caracteres invis veis.

em diversos algoritmos como sinal de m de cadeia. Os caracteres \ (caractere escape) e " (in e m de cadeia) tm signicados especiais em cadeias de cio e caracteres e para serem representados precisam ser antecedidos pelo caractere escape. Portanto, \\ e \" devem ser usados dentro de cadeias de caracteres para representar \ e " respectivamente. Por exemplo, "Estas s~o \" (aspas) dentro de cadeias." a As aspas no meio da cadeia no indicam o m, j que elas esto precedidas a a a do caractere de escape.

3.5

Variveis a

Variveis so nomes dados para posioes de memria a m de facilitar o maa a c o nuseio dos dados durante a criaao dos programas. Os dados podem ser de c qualquer dos tipos denidos para a linguagem C.

3.5.1

Nomes das Variveis a

Existem algumas regras bsicas que regulam o batismo de variveis. Estas regras a a so as seguintes: a Nomes de varivel s podem conter letras, d a o gitos e o caractere _; Todo primeiro caractere deve ser sempre uma letra ou o caractere _; Letras mai sculas e min sculas so consideradas caracteres diferentes, isto u u a , C diferencia a caixa das letras; e

72

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS Palavras reservadas no podem ser usadas como nome de variveis. Palaa a vras reservadas so palavras usadas para indicar os comandos da linguaa gem, tipos de dados ou outras funoes. O Anexo B mostra as palavras c reservadas da linguagem C.

E boa pol tica escolher nomes que indiquem a funao da varivel. Por exemc a plo: soma mediaNotas total salarioMensal nome taxa imposto raio inicio

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

3.5.2

Declarao de variveis ca a

Para serem usadas, as variveis precisam ser declaradas de modo que o compilaa dor possa reservar espao na memria para o valor a ser armazenado. A forma c o geral de uma declaraao : c e a tipo lista de variveis; onde uma lista de variveis uma lista de nomes de variveis separadas por a e a v rgulas. Por exemplo:
int i; unsigned i n t a , b , c ; unsigned short i n t dia , mes , ano ; f l o a t raio , diametro ; double salario ;

3.6. EXERC ICIOS

73

3.5.3

Atribuio de valores ca

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

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

3.6
(a) (b) (c) (d)

Exerc cios
tempo nota final us$ char (e) (f) (g) (h) 2dias teste 1 raio.do.circulo DiaHoje

3.1: Indique os nomes de vriaveis que so vlidos. Justique os nomes invlidos. a a a a

3.2: Indique quais dos n meros abaixo so constantes inteiras (longas ou no) u a a vlidas. Justique suas respostas. a (a) (b) (c) (d) 100 2 345 123 3.0 -35 (e) (f) (g) (h) - 234 0L 21 0xF1

3.3: Qual o valor na base 10 das constantes abaixo? (a) 025 (b) 0123 (c) 0xD

74

CAP ITULO 3. TIPOS DE DADOS, CONSTANTES E VARIAVEIS (d) 0x1D

3.4: Considere um computador que armazene n meros inteiros em 32 bits. u (a) Caso um bit seja reservado para o sinal diga qual o menor n mero e u inteiro negativo que este computador pode armazenar? (b) Para os n meros sem sinal, qual o maior n mero positivo? u e u

Cap tulo 4

Entrada e Sa pelo da Console


4.1 Introduo ca

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

4.2

Biblioteca Padro a

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

75

76

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE no in do programa. cio

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

4.3

Sa - A Funo printf da ca

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

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

Este programa ir imprimir na tela do computador: a Estamos no ano 1997 Como controle uma cadeia ele aparece entre " ". Ele dene como sero e a impressos os valores representados pelos argumentos. No controle podem existir dois tipos de informaoes: caracteres comuns e cdigos de formataao. Os c o c

4.3. SA IDA - A FUNCAO PRINTF

77

caracteres comuns, como no exemplo o texto Estamos no ano, so escritos na a tela sem nenhuma modicaao. Os cdigos de formataao, aparecem precedidos c o c por um caractere% e so aplicados aos argumentos na ordem em que aparea cem. Deve haver um cdigo de formataao para cada argumento. O cdigo o c o %d indica que o valor armazenado em ano deve ser impresso na notaao inteiro c decimal. E importante notar que o campo de controle aparece somente uma vez na funao printf e sempre no in c cio.

4.3.1

Cdigos de Converso o a

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

Tabela 4.1: Cdigos de Converso para leitura e entrada de dados. o a Entre o caractere % e o cdigo de convers~o podem ser inseridos caracteres o a que alteram o formato. A seguir so mostrados a ordem de inserao destes a c caracteres e o seu signicado: %[modificadores][largura][.precis~o][comprimento]cdigo a o modificadores: Usados logo aps o caractere %. o - Um sinal de menos serve para especicar que o argumento deve ser justicado ` esquerda no seu campo de impresso. Caso nenhum a a sinal seja usado o argumento ser ajustado ` direita. O programa a a 4.2 ilustra os dois tipos de justicaao. c

78

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE + Fora que o resultado seja precedido por sinal de menos ou de mais, c mesmo para n meros positivos. O padro que somente negativos u a e sejam precedidos por sinal de menos. espao Caso nenhum sinal v ser escrito, um espao inserido antes do c a c e valor. # Usado com o, x ou X precede o valor com 0, 0x ou 0X respectivamente para valores diferentes de zero. Usado com e, E e f, fora c que a sa contenha um ponto decimal mesmo que no haja parte da a fracionria. Por padro, se no h parte fracionria o ponto decimal a a a a a no escrito. Usado com g ou G o resultado o mesmo que com e a e e ou E, mas os zeros nais no so retirados. a a 0 Completa o campo, pela esquerda, com zeros (0) ao invs de espaos, e c sempre que a opao para completar seja especicada (ver especicac dor de largura do campo).

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

4.4. ENTRADA - A FUNCAO SCANF Listagem 4.2: Exemplo de justicaao de resultados. c


#include < stdio .h > i n t main ( void ) { i n t ano = 1997; printf ( " Justificado para direita Ano = %8 d \ n " , ano ); printf ( " Justificado para esquerda Ano = % -8 d \ n " , ano ); return 0; }

79

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


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

Justificado para direita Ano = 1997 Justificado para esquerda Ano = 1997 O programa exemplo 4.3 imprimir o seguinte resultado: a O resultado e = 0.333 . Alo Nos exemplos anteriores verique que \n no impresso. A barra inclinada a e chamada de sequncia de escape, indicando que o prximo caractere no para e e o a e ser impresso mas representa caracteres invis veis ou caracteres que no esto a a representados no teclado. Esta seqncia de escape indica que o programa deve ue passar a imprimir na prxima linha. o

4.4

Entrada - A Funo scanf ca

A funao scanf pode ser utilizada para entrada de dados a partir do teclado e c seu prottipo : o e

80

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE int scanf(controle, arg1, arg2, ...);

Uma diferena fundamental que existe entre esta funao e a funao printf c c c est nos argumentos que vm depois do controle. No caso de scanf os argua e mentos so os endereos das variveis que iro receber os valores lidos e no, a c a a a como em printf, as prprias variveis. A indicaao que estamos referenciando o a c um endereo e no a varivel se faz pelo operador &. Por exemplo, o comando c a a scanf(%d %d, &a, &b); espera que dois valores inteiros sejam digitados no teclado. O primeiro armazee nado na varivel a e o segundo em b. Os valores sero armazenados diretamente a a nos endereos indicados por &a e &b respectivamente. c Um outro exemplo incluindo variveis reais : a e
int i; fl oat x; scanf ( " % d % f " , &i , & x );

Assumindo que a linha de entrada no teclado fosse 34 56.43 a execuao do exemplo iria terminar com o valor inteiro 34 sendo armazenado c na varivel i e o valor real 56.43 em x. a Usualmente o campo de controle s contm especicaoes de converso, como o e c a os listados na Tabela 4.3.1, que so utilizadas para interpretar os dados que sero a a lidos, no entanto, como em printf, outros caracteres podem aparecer. O campo de controle pode conter: Caracteres branco: A funao l e ignora todos os caracteres branco e/ou c e <enter> e/ou tab que aparecerem antes de qualquer caractere diferente destes. Caracteres comuns: (no %) que devem casar com o prximo caractere difea o rente de branco da entrada. Isto signica que qualquer caractere que no a for igual a branco e/ou <enter> e/ou tab ou parte de um especicador de formato faz com que a funao leia o prximo caractere da entrada (stdin) c o e se for igual a este ele descartado. Caso os caracteres sejam diferentes e a funao falha e retorna deixando os caracteres seguintes no lidos. c a Especicaoes de converso: Um especicador de converso de formato sec a a guindo um modelo similar ao da funao printf. c O modelo o seguinte: e %{*}{largura}{modificadores}tipo O caracteres entre chaves so opcionais. O asterisco indica que o dado ser lido a a de stdin mas ignorado. A largura especica o n mero mximo de caracteres a u a serem lidos.

4.4. ENTRADA - A FUNCAO SCANF

81

Os modicadores alteram o tamanho do especicadores de tipo que vm logo e a seguir. Existem os seguintes modicadores: h: Os tipos d, i e n, que so int passam a ser short int e os tipos o, u e x, a tambm int passam a ser unsigned short int. e l: Os tipos d, i e n passam a ser long int e os tipos o, u e x passam a unsigned long int. Os tipos e, f e g passam de oat para double. L: Os tipos e, f e g passam de oat para long double. Por exemplo, para que os valores digitados sejam separados por v rgulas, o comando deveria ser escrito da seguinte maneira: scanf("%d, %f", &i, &x); Observar que deve haver uma correspondncia exata entre os caracteres no e a brancos do controle e os caracteres digitados. Neste caso a entrada deveria ser: 35, 46.3 O programa 4.4 mostra exemplos de uso da funao scanf. c Listagem 4.4: Exemplo de uso de scanf.
#include < stdio .h > i n t main () { char c ; i n t num1 , num2 ; printf ( " Entre com um caractere qualquer .\ n " ); scanf ( " % c " , & c ); printf ( " Codigo ASCII do caractere % c vale % d .\ n " , c , c ); printf ( " Agora dois inteiros separados por espaco .\ n " ); scanf ( " % d % d " , & num1 , & num2 ); printf ( " A soma destes numeros vale % d .\ n " , num1 + num2 ); return 0; }

O resultado da execuao deste programa : c e Entre com um caractere qualquer. d Codigo ASCII do caractere d vale 100. Agora dois inteiros separados por espaco. 2 4 A soma destes numeros vale 6. A funao scanf retorna o n mero de itens lidos com sucesso. Este n mero c u u pode ser usado para vericar se todos os valores pedidos foram lidos. No caso de ocorrer uma falha antes da leitura se iniciar a constante EOF retornada. e

82

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE

4.5
4.5.1

Lendo e Imprimindo Caracteres


Funes getchar e putchar co

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

Apesar da funao getchar retornar um parmetro inteiro poss atribuir c a e vel este valor a uma varivel do tipo char porque o cdigo do caractere est armaa o a zenado no byte ordem mais baixa. O mesmo acontece com a funo putchar ca que recebe um inteiro, mas somente o byte de ordem mais baixa passado para e a tela do computador. A funao putchar retorna o caractere que foi escrito e c EOF em caso de erro. O programa da listagem 4.5 mostra exemplos de uso destas funoes, e o seu resultado : c e Entre com um algarismo entre 0 e 9. 7 O caractere lido foi o 7 Listagem 4.5: Exemplo de uso de getchar e putchar.
#include < stdio .h > i n t main ( void ) { char c ; printf ( " Entre com um algarismo entre 0 e 9.\ n " ); c = getchar (); printf ( " O caractere lido foi o " ); putchar ( c ); return 0; }

Observar que, normalmente, quando algum dado fornecido pelo teclado e termina-se a digitaao com a tecla <enter>. No entanto, o <enter> um c e caractere tambm, e isto pode causar problemas. Vamos analisar o que acontece e quando antes do comando getchar, se l um dado do tipo inteiro, por exemplo. e O comando scanf l o n mero inteiro mas no o <enter> digitado. Deste modo, e u a quando logo em seguida o programa executar a funao getchar, o que ser lido c a o <enter> digitado ao nal do n mero. A listagem 4.6 um exemplo de e u e programa onde isto pode ocorrer. Considere que o usurio digitou 35<enter> a como resposta ao comando scanf. O comando getchar ir ler o <enter> e em a

4.5. LENDO E IMPRIMINDO CARACTERES

83

seguida o programa ir imprimir o n mero 35, lido no scanf, e apenas uma a u linha em branco correspondente ao caractere <enter>, lido pelo getchar, como est indicado a seguir. Mais adiante mostraremos como resolver este problema. a Entre com um numero inteiro. 35 Agora um caractere. Numero lido 35 Caractere lido

Listagem 4.6: Exemplo de uso de getchar e putchar.


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

4.5.2

Lendo e Imprimindo Cadeias de Caracteres

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

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

84

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE

mais. Aps este passo, o vetor nome pode ser usado durante a execuao do o c programa.

4.5.3

Lendo e Imprimindo cadeias com scanf e printf

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

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

4.5.4

Lendo e Imprimindo cadeias com gets e puts

Diferentemente do comando scanf a funao gets l toda a cadeia at que a tecla c e e <enter> seja digitada. No vetor so colocados todos os cdigos dos caracteres a o lidos excetuando-se o da tecla <enter>, que no armazenado sendo substitu a e do

4.5. LENDO E IMPRIMINDO CARACTERES

85

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

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

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

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


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

86

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE

4.5.5

A Funo fgets ca

A funao gets pode abrir porta para invases de computadores pelo fato dela c o no controlar o n mero de caracteres lido de stdin. Apesar do usurio denir a u a um tamanho mximo para o vetor que ir armazenar os caracteres a funao a a c ignora o limite e continua lendo valores at que o usurio digite o caractere e a <enter>. Para evitar este problema recomenda-se o emprego da funao fgets cujo c prottipo o e
#include < stdio .h > i n t * fgets ( const char * str , i n t tam , FILE * fluxo );

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

4.6

Exerc cios

4.1: Escreva um programa que declare variaveis do tipo int, char e float, inicialize-as, e imprima os seus valores. 4.2: Escreva um programa que dena variveis do tipo int e armazene nelas a constantes octais e hexadecimais e imprima o seu conte do no formato original u e em formato decimal. 4.3: Faa um programa que leia um valor inteiro no formato decimal e escreva, c na tela, este mesmo valor nas bases hexadecimal e octal. Exemplo de Entrada e Sada: Entre com o valor: 10 Hexadecimal: A Octal: 12 4.4: Faa um programa capaz de ler um valor real e escrev-lo com apenas uma c e casa decimal.

4.6. EXERC ICIOS

87

4.5: Faa um programa que leia trs palavras de at 10 letras e reescreva estas c e e palavras alinhadas ` direita da tela. a 4.6: Sabendo que os argumentos da funao printf podem ser expresses (a+b, c o a/b, a*b, 3*a...), e no somente argumentos, faa um programa capaz de ler a c um valor inteiro e escrever seu triplo, seu quadrado, e a sua metade. Exemplo de Entrada e Sada: Valor: 6 Triplo: 18 Quadrado: 36 Meio: 3 4.7: Escreva um programa que leia 3 n meros reais e imprima a mdia aritmtica u e e destes n meros. u 4.8: Escreva um programa que pegue o valor de uma conta de restaurante e imprima o valor total a ser pago, considerando que o restaurante cobra 10% de taxa para os atendentes. 4.9: Faa um programa que pea ao usurio a quilometragem atual, a quilomec c a tragem anterior, os litros consumidos e informe a taxa de consumo (quilmetros o por litro) de um automvel. o 4.10: Escreva um programa que converta uma temperatura de Farenheit para Celsius. 4.11: Escreva um programa que, dado o per metro de um c rculo, calcule sua a rea. 4.12: Faa um programa que utilize a funao gets para ler duas cadeias de c c tamanho at 20 e em seguia `s reescreva na linha de baixo, uma ao lado da e a outra e separadas por /-/ ;

88

CAP ITULO 4. ENTRADA E SA IDA PELO CONSOLE

Cap tulo 5

Operadores e Expresses o
5.1 Introduo ca

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

5.2

Operador de Atribuio ca

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

90

CAP ITULO 5. OPERADORES E EXPRESSOES 3. a recebe o resultado da expresso ` sua direita, que o valor atribu ` a a e do a b, ou seja 1.0.

5.3

Operadores Aritmticos e

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

Tabela 5.1: Operadores aritmticos. e Os s mbolos mostrados na Tabela 5.3 so os unicos que podem ser usados a para representar as operaoes acima listadas. Expresses aritmticas em C dec o e vem ser escritas no formato linear para facilitar a digitaao dos programas e c tambm porque alguns s e mbolos usados em Matemtica no existem nos teclaa a dos. O exemplo mais comum deste formato a operaao de diviso que deve e c a ser escrita a/b. Parnteses tm um papel importante nas expresses e permitem que a ordem e e o das operaoes seja alterada. Expresses entre parnteses so calculadas em c o e a primeiro lugar, portanto eles conferem o maior grau de prioridade as expresses o que eles envolvem. Podemos ter pares de parnteses envolvendo outros pares. e Dizemos que os parnteses esto aninhados. Neste caso as expresses dentro dos e a o parnteses mais internos so avaliadas primeiro. e a Outro ponto importante so as regras de precedncia que determinam que a e operaao deve ser executada primeiro. Na tabela os operadores esto listados c a em ordem decrescente de prioridade. Para os operadores aritmticos a operaao e c de mais alta precedncia o - unrio, vindo em seguida ++, -- com a mesma e e a prioridade. Os operadores de multiplicaao, diviso e mdulo tem a mesma c a o prioridade. O operador menos unrio multiplica seu operador por -1. Quando a duas operaoes de mesmo n de prioridade tm de ser avaliadas, a operaao c vel e c mais ` esquerda ser avaliada primeiro. a a Um ponto importante que deve ser sempre levado em consideraao quando c uma expresso for calculada so os tipos das variveis, porque eles alteram a a a

5.4. OPERADORES RELACIONAIS E LOGICOS

91

radicalmente os resultados das expresses. Por exemplo, a diviso entre opeo a randos do tipo inteiro tem como resultado um valor inteiro. Portanto, se o resultado possuir uma parte fracionria ela ser truncada. No poss aplia a a e vel car a operaao de mdulo a operandos do tipo float e double. Algumas regras c o de converso simples existem e sero discutidas em detalhes mais adiante. Por a a exemplo a operaao 1/3 em C fornece como resultado o valor 0, enquanto que 1 c % 3 igual a 3. e A seguir mostramos alguns exemplos de expresses aritmticas escritas na o e notaao da linguagem C. Observe o uso de parnteses para evitar ambiguidades c e que poderiam fazer com que a expresso fosse calculada erradamente. a Exemplo 5.4: 1. a +
b b+c

= a + b/(b+c)

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

= x/(a+b/c)

5.4
5.4.1

Operadores Relacionais e Lgicos o


Operadores Relacionais

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

Tabela 5.2: Operadores Relacionais.

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

92

CAP ITULO 5. OPERADORES E EXPRESSOES

5.4.2

Operadores Lgicos o

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

E lgico o O s mbolo usado para representar o operador E lgico &&. A Tabela 5.3 o e mostra a tabela verdade do operador. O resultado da expresso verdadeiro a e se e somente se todas as variveis forem iguais a verdadeiro. Por exemplo, a considere o seguinte trecho de programa:
i n t i = 3 , j = -5; f l o a t z = 3.0; i n t resultado ; resultado = (10 > 5) && ( i > -5) && ( z != 0); printf ( " O resultado e vale % d . " , resultado );

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

Tabela 5.3: Operador Lgico E. o

5.4. OPERADORES RELACIONAIS E LOGICOS OU lgico o

93

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

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

Tabela 5.4: Operador Lgico OU. o

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

Este trecho de programa imprime 0 (falso), porque dia menor que 30 E e ano maior que 1950. Portanto, o resultado do parnteses vale 1 (verdadeiro). e e No entanto, o operador ! nega este valor que vira 0. A tabela 5.6 mostra, em ordem decrescente, a precedncia dos operadores e lgicos e relacionais. o

94

CAP ITULO 5. OPERADORES E EXPRESSOES p 0 1 !p 1 0

Tabela 5.5: Operador Lgico N~O. o A Operador ! >, >=, <, <= ==, != && ||

Prioridade 0 1 2 3 4

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

5.5

Operadores com Bits

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

Tabela 5.7: Operadores com bits.

Os operadores &, | e ~ tm a mesma tabela verdade que os operadores &&, || e e ! respectivamente. O operador ^ (OU Exclusivo) est descrito pela Tabela a 5.8. O resultado da operaao verdadeiro se e somente se os dois operandos c e so diferentes. a Os operandos de deslocamento tm os seguintes modos de operaao: e c operando >> vezes: o operando deslocado vezes bits para a direita. e

5.5. OPERADORES COM BITS p 0 0 1 1 q 0 1 0 1 p ^ q 0 1 1 0

95

Tabela 5.8: Operador Lgico OU. o

operando << vezes: o operando deslocado vezes bits para a esquerda. e Observaoes: c Nos deslocamentos ` direita em variveis unsigned e nos deslocamentos a a a ` esquerda, os bits que entram so zeros; a Nos deslocamentos ` direita em variveis signed, os bits que entram cora a respondem ao sinal do n mero (1= sinal negativo, 0 = sinal positivo). u Um deslocamento para a direita equivalente a uma diviso por 2. Desloe a camento para a esquerda equivalente a uma multiplicaao por 2. Assim e c a = a * 2; e a = a << 1; so equivalentes. a O exemplo 5.1 ilustra o uso dos operandos de deslocamento: Listagem 5.1: Exemplo de operadores de deslocamento.
#include < stdio .h > i n t main ( void ) { unsigned i n t c = 7; i n t d = -7; c = c < <1; printf ( " %3 d = %08 X \ n " , c , c ); c = c > >1; printf ( " %3 d = %08 X \ n " , c , c ); d = d < <1; printf ( " %3 d = %08 X \ n " , d , d ); d = d > >1; printf ( " %3 d = %08 X \ n " , d , d ); return 0; }

Este programa teria como resposta os seguintes resultados. 14 7 -14 -7 = = = = 0000000E 00000007 FFFFFFF2 FFFFFFF9

96

CAP ITULO 5. OPERADORES E EXPRESSOES

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

5.6

Operadores de Atribuio Composta ca

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

5.7

Operador v rgula

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

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

5.8. OPERADOR SIZEOF()

97

5.8

Operador sizeof()

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

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

5.9

Converso de Tipos a

Quando operandos de tipos diferentes aparecem em expresses so convertidos o a para um tipo comum, que permita o clculo da expresso da forma mais eciente. a a Por exemplo, uma operaao que envolva um tipo int e um float, o valor int c convertido para float. e

98

CAP ITULO 5. OPERADORES E EXPRESSOES

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

5.10.

REGRAS DE PRECEDENCIA

99

5.10

Regras de Precedncia e

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

Tabela 5.9: Precedncia dos operadores. e

5.11

Exerc cios

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

100 2. 3.
1 1+
1+ 1 1 1+x

CAP ITULO 5. OPERADORES E EXPRESSOES

a+b c+d x c+d

4. a

5.3: Diga a ordem de clculo e o resultado das expresses abaixo: a o 1. x = 5 * 4 / 6 + 7; 2. x = 5 * 4.0 / 6 + 7; 3. x = 5 * 4 % 6 + 7; 4. x = ((4 / 2) + (3.0 * 5)); 5.4: Escreva um programa que imprima a tabela verdade da funao ou excluc sivo. 5.5: Escreva um programa que calcule o produto entre um valor x e 2n , onde n e x so inteiros. Utilize operadores binrios. a a 5.6: Escreva um programa que leia um ngulo em segundos e imprima quantos a graus, minutos e segundos h neste ngulo. a a 5.7: Escreva um programa que leia um tempo em segundos e imprima quantas horas, minutos e segundos h neste tempo. a 5.8: Escreva um programa que leia um comprimento em cent metros e imprima quantos metros, dec metros e cent metros h neste comprimento. a

Cap tulo 6

Comandos de Controle
6.1 Introduo ca

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

6.2

Blocos de Comandos

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

101

102

CAP ITULO 6. COMANDOS DE CONTROLE

6.3

Comandos de Teste

Os comandos de teste permitem ao computador decidir o caminho a seguir, durante a execuao do programa, indepentemente do usurio. Estes testes so c a a baseados em estados internos dispon veis ao processador. Estes estados podem ser resultantes de uma operaao aritmtica anterior, de uma operaao anterior c e c etc.

6.3.1

Comando if

O comando if utilizado quando for necessrio escolher entre dois caminhos. e a A forma geral do comando if a seguinte: e
i f ( express~ o ) a bloco_de_c o ma n do s 1 ; else bloco_de_c o ma n do s 2 ;

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

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

6.3. COMANDOS DE TESTE


{ printf ( " Aliquota de imposto = 0.25\ n " ); imposto = salario * 0.25; }

103

Uma construao que pode aparecer so os comandos ifs em escada, cuja c a forma geral a seguinte: e
i f ( express~ o ) a bloco_de_c om a nd o s else i f ( express~ o1 ) a bloco_de_co m an d os 1 else i f ( express~ o2 ) a bloco_de_c om a nd o s2 ... e l s e bloco_de_c om a nd o sn

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

6.3.2

Comando switch

O comando if, em todas suas formas, suciente resolver problemas de seleao e c de comandos. Porm em alguns casos, como no exemplo 6.1 o programa se e torna mais trabalhoso para ser escrito e entendido. O comando switch facilita a escrita de trechos de programa em que a seleao deve ser feita entre vrias c a alternativas. A forma geral do comando switch a seguinte: e

104

CAP ITULO 6. COMANDOS DE CONTROLE

Listagem 6.1: Programas com ifs em escada e aninhados.


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

6.3. COMANDOS DE TESTE


switch ( express~ o ) a { case constante1 : seq ^ ncia_ d e_ c o ma n do s ; ue break ; case constante2 : seq ^ ncia_ d e_ c o ma n do s ; ue break ; case constante3 : seq ^ ncia_ d e_ c o ma n do s ; ue break ; ... default: seq ^ ncia _ de _ co m a nd o s ; ue }

105

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

106

CAP ITULO 6. COMANDOS DE CONTROLE

Notar que caso no aparea um comando de desvio, todas as instruoes a c c seguintes ao teste case que teve sucesso sero executadas, mesmo as que a estejam relacionadas com outros testes case; O comando switch s pode testar igualdade; o No podem aparecer duas constantes iguais em um case; a O programa 6.2 mostra um exemplo de uso de comandos switch.

6.3.3

Comando Ternrio a

O comando ternrio tem este nome porque necessita de trs operandos para ser a e avaliado. O comando ternrio tem a seguinte forma: a express~o1 ? a express~o2 : a express~o3 a Para avaliar o resultado total da expresso, primeiro avexpress~o1 avaa a e liada. Caso este resultado seja correspondente ao valor verdadeiro ento o a resultado da expresso ser igual ao resultado da express~o2. Caso contrrio a a a a a express~o3 avaliada e se torna o resultado. O programa 6.3 mostra um a e exemplo de uso de comando ternrio. a

6.4

Laos de Repetio c ca

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

6.4.1

Comando for

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

As trs expresses geralmente tm os seguintes signicados: e o e 1. A express~o1 utilizada para inicializar a varivel de controle do lao; a e a c

6.4. LACOS DE REPETICAO

107

Listagem 6.2: Exemplo de switch.


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

108

CAP ITULO 6. COMANDOS DE CONTROLE Listagem 6.3: Exemplo de comando ternrio. a

#include < stdio .h > i n t main ( void ) { float num1 , /* primeiro operando */ num2 , /* segundo operando */ max ; /* resultado da operacao */ printf ( " Imprime o maior valor de dois numeros .\ n " ); printf ( " Por favor entre com os dois mumeros .\ n " ); scanf ( " % f % f " , & num1 , & num2 ); max = ( num1 > num2 )? num1 : num2 ; printf ( " O maior dos numeros lidos e % f .\ n " , max ); return 0; }

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

O programa 6.4 mostra como se pode calcular o fatorial de um nmero u usando-se o comando for.

6.4. LACOS DE REPETICAO Listagem 6.4: Exemplo de comando for.


#include < stdio .h > #include < stdlib .h > i n t main () { i n t numero , fat =1 , i ; printf ( " \ nEntre com um numero positivo . " ); scanf ( " % d " , & numero ); f o r ( i = numero ; i >1; i - -) fat = fat * i ; printf ( " O fatorial de % u vale % u . " , numero , fat ); return 0; }

109

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

Laos for com testes usando outras variveis c a A expresso de controle no precisa necessriamente envolver somente um teste a a a com a varivel que controla o lao. O teste de nal do lao pode ser qualquer a c c expresso relacional ou lgica. No programa 6.5 o lao pode terminar porque a o c a varivel de controle j chegou ao seu valor limite ou foi batida a tecla *, e a a neste caso o lao termina antecipadamente. c Laos for com expresses faltando c o Um outro ponto importante do for que nem todas as expresses precisam estar e o presentes. No exemplo 6.6 a varivel de controle no incrementada. A unica a a e maneira do programa terminar o usurio bater o n mero -1. e a u E poss omitir qualquer uma das expresses. Por exemplo, se a express~o2 vel o a for omitida o programa assume que ela sempre verdade de modo que o lao e c s termina com um comando de desvio como o break. O programa do exemplo o

110

CAP ITULO 6. COMANDOS DE CONTROLE

Listagem 6.5: Exemplo de comando for com testes sobre outras variveis. a
#include < stdio .h > i n t main () { char c = ; int i; f o r ( i =0 ; (i <5) && ( c != * ); i ++ ) { printf ( " % c \ n " , c ); c = getchar (); } return 0; }

Listagem 6.6: Exemplo de comando for sem alteraao da varivel de controle. c a


#include < stdio .h > i n t main () { int i; f o r ( i =0 ; i != -1 ; ) { printf ( " % d \ n " ,i ); scanf ( " % d " , & i ); } return 0; }

6.7 para quando o valor da varivel de controle for igual a 5. Neste caso o teste a ser verdade o lao termina por meio do break. a c

Lao innito c Uma construao muito utilizada o lao innito. No lao innito o programa c e c c pra quando se executa o comando break. O trecho de programa a seguir a somente pra quando for digitada a tecla s ou S . a
for ( ; ; ) { printf ( " \ nVoce quer parar ?\ n " ); c = getchar (); i f ( c == S || c == s ) break ; }

6.4. LACOS DE REPETICAO Listagem 6.7: Exemplo de comando for sem teste de m.
#include < stdio .h > i n t main () { int i; f o r ( i = 0; ; i ++) { printf ( " numero % d \ n " , i ); i f ( i == 5) break ; } return 0; }

111

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

6.4.2

Comando while

O comando while tem a seguinte forma geral:


while ( express~ o ) a bloco_de_c om a nd os

112

CAP ITULO 6. COMANDOS DE CONTROLE

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

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

6.5. COMANDOS DE DESVIO

113

6.4.3

Comando do-while

A forma genrica do comando a seguinte: e e


do bloco_de_c om a nd os while ( express~ o ); a

Observar que neste comando a expresso de teste est aps a execuao do a a o c comando, portanto o bloco de comandos executado pelo menos uma vez. A e execuao do comando segue os seguintes passos: c 1. Executa o comando; 2. Avalia a expresso; a 3. Se o resultado da expresso for verdadeiro ento volta para o passo 1, a a caso contrrio interrompe o do-while a O exemplo de comando for para imprimir os 100 primeiros n meros escrito u com comando do-while ca da seguinte maneira:
i = 1; do { printf ( " Numero % d \ n " , i ); i ++; } while ( i <= 100);

6.5
6.5.1

Comandos de Desvio
Comando break

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

114

CAP ITULO 6. COMANDOS DE CONTROLE

6.5.2

Comando continue

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

6.5.3

Comando goto

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

6.5.4

Funo exit() ca

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

6.6. EXERC ICIOS

115

6.5.5

Comando return

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

6.6

Exerc cios

6.1: Escreva um programa que calcule x elevado a n. Assuma que n um valor e inteiro. 6.2: Escreva um programa que exiba as opoes c 1-multiplicar e 2-somar de um menu, leia a opao desejada, leia dois valores, execute a operaao (utilic c zando o comando if) e exiba o resultado. 6.3: Utilizando ifs em escada, inclua, no programa do exerc anterior, as cio opoes 3-Subtrair e 4-Dividir. c 6.4: Simplique os programas anteriores da seguinte forma: Reescreva o programa do exerc 1 substituindo o comando if pelo cocio mando ternrio. a Reescreva o programa do exerc 2 substituindo os ifs em escada pelo cio comando switch. 6.5: Utilizando um lao for dentro de outro, escreva um programa que exiba c as tabuadas de multiplicaao dos n meros de 1 ` 9. c u a 6.6: Escreva um programa com menu de 5 opoes que utilize o comando de c desvio goto para executar a opao desejada e s saia do programa caso a opao c o c 5-Sair seja selecionada. 6.7:Escreva um programa que tenha um n mero (inteiro) como entrada do u usurio e escreva como sa a sequencia de bits que forma esse numero. Por a da exemplo, aps digitado o n mero 10, a saida deve ser 0000000000001010. o u

116

CAP ITULO 6. COMANDOS DE CONTROLE

6.8:Escreva um programa que imprima todos os numeros pares entre 0 e 50 e em seguida imprima todos os impares. Deixar um espaco entre os numeros. 6.9: Escreva um programa que leia 10 numeros. O programa deve imprimir a media, o maior e o menor deles. Obs: Os numeros devem ser entre 0 e 10. 6.10: Escreva um programa que leia 10 numeros. O programa deve imprimir a media, o maior e o menor deles. Obs: Considere agora que os n meros podem ser quaisquer. u 6.11: Escreva um programa que exibe a tabela ascii. 6.12: Crie um programa para vericar se um n mero dado primo. u e 6.13: Escreva um programa que leia um numero do teclado e ache todos os seus divisores. 6.14: Escreva um programa que imprima a seqncia ue 987654321876543217654321654321543214321321211 No use nenhuma constante, use apenas variveis. Em outra linha imprima a a as letras mai sculas de A at Z (ABCD...). u e 6.15: Escreva um programa que conte de 100 a 999 (inclusive) e exiba, um por linha, o produto dos trs digitos dos numeros. Por exemplo, inicialmente o e programa ir exibir: a 0 (1*0*0) 0 (1*0*1) 0 (1*0*2) (...) 0 (1*1*0) 1 (1*1*1) 2 (1*1*2) 9*9*9=729 Faa seu programa dar uma pausa a cada 20 linhas para que seja poss c vel ver todos os n meros pouco a pouco. Solicite que seja pressionada alguma tecla u para ver a prxima sequencia de n meros. o u

Cap tulo 7

Vetores e Cadeias de Caracteres


7.1 Introduo ca

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

7.2

Declarao de Vetores Unidimensionais ca

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


tipo nome [tamanho];

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

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

118

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

espao = tamanho * sizeof(tipo) c

E importante notar que em C no h vericaao de limites em vetores. Isto a a c signica que poss e vel ultrapassar o m de um vetor e escrever em outras variveis, ou mesmo em trechos de cdigo. E tarefa do programador fazer com a o que os ndices dos vetores estejam sempre dentro dos limites estabelecidos pela declaraao do vetor. c O programa 7.1 ilustra como se declara um vetor, inicializa seus valores e imprime o conte do. Notar o uso da diretiva #define DIM 5 para denir u uma constante, que posteriormente foi usada para estabelecer o tamanho do vetor. Esta constante passa a ser usada nas referncias ao vetor, por exeme plo no comando de geraao do conjunto de dados armazenado no vetor. Caso c seja necessrio trocar o tamanho do vetor basta alterar o valor da constante e a recompilar o programa. Listagem 7.1: Exemplo de vetores.
#define DIM 5 #include < stdio .h > i n t main ( void ) { i n t vetor [ DIM ]; unsigned i n t i , num ; puts ( " Este programa gera um vetor de inteiros .\ n " ); puts ( " Entre com o numero inicial do conjunto . " ); scanf ( " % d " , & num ); /* Geracao do conjunto */ f o r ( i = 0 ; i < DIM ; i ++) vetor [ i ] = num ++; /* Impressao do conjunto */ f o r ( i = 0; i < DIM ; i ++) printf ( " Elemento % d = % d \ n " , i , vetor [ i ]); return 0; }

O programa 7.2 calcula o produto escalar de dois vetores inteiros. Observar como na leitura dos elementos do vetor usa-se o operador de endereo & antes c do nome de cada elemento. O programa 7.3 ilustra o mtodo da bolha para ordenaao em ordem crese c cente de um vetor de inteiros. Neste mtodo a cada etapa o maior elemento e e movido para a sua posiao. A cada iteraao os elementos do vetor so compac c a rados dois a dois, sendo trocados caso seja necessrio. Ao trmino da primeira a e passada pelo vetor, o maior elemento levado para a sua posiao, no nal do e c vetor. Portanto, ele no precisa ser mais considerado, da o valor da varivel a a

7.2. DECLARACAO DE VETORES UNIDIMENSIONAIS

119

Listagem 7.2: Produto escalar de dois vetores.


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

120

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES Operao ca Passo 1 v[0] > v[1]? Trocar v[0] e v[1] > v[2]? Trocar v[1] e v[2] > v[3]? Trocar v[2] e v[3] > v[4]? Trocar v[3] e Passo 2 v[0] > v[1]? Trocar v[0] e v[1] > v[2]? Trocar v[1] e v[2] > v[3]? Trocar v[2] e Passo 3 v[0] > v[1]? v[1] > v[2]? Trocar v[1] e Passo 4 v[0] > v[1]? Trocar v[0] e v[0] 20 15 15 15 15 15 15 15 15 8 8 8 8 8 8 8 8 8 5 v[1] 15 20 20 8 8 8 8 8 8 15 15 12 12 12 12 12 5 5 8 v[2] 8 8 8 20 20 12 12 12 12 12 12 15 15 5 5 5 12 12 12 v[3] 12 12 12 12 12 20 20 5 5 5 5 5 5 15 15 15 15 15 15 v[4] 5 5 5 5 5 5 5 20 20 20 20 20 20 20 20 20 20 20 20

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

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

v[2]

v[1]?

Tabela 7.1: Passos executados durante o algoritmo da bolha.

que aponta para o nal do vetor (fim) diminu de 1. O processo repetido e da e at que todos os elementos sejam levados para as suas posioes ou que nenhuma e c troca seja realizada. Quando nenhuma troca realizada o vetor est ordenado. e a A Tabela 7.1 mostra os passos executados pelo algoritmo at ordenar o vetor. e

7.3

Cadeias de Caracteres

Um cadeia de caracteres (string) um conjunto de caracteres terminado por um e caractere nulo, que representado como \0. Para especicar um vetor para e armazenar um cadeia deve-se sempre reservar um espao para este caracter. Por c exemplo, para armazenar um cadeia de 40 caracteres deve-se reservar um vetor de 41 de caracteres. Em C poss haver constantes cadeia, que so denidas e vel a como uma lista de caracteres entre aspas. Por exemplo,

7.3. CADEIAS DE CARACTERES

121

Listagem 7.3: Ordenaao pelo mtodo da bolha. c e


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

122

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

"programando em C" No necessrio a colocaao do caracter nulo ao nal da cadeia. Em C no h a e a c a a o tipo cadeia (string) e, portanto, conjuntos de caracteres teriam de ser tratados como conjuntos de n meros inteiros, por exemplo. Para facilitar a programaao u c foram criadas algumas funoes para manipular cadeias. Algumas das funoes c c mais comuns esto resumidamente descritas a seguir: a Nas denioes a seguir, size_t o tipo inteiro sem sinal que volta como c e resultado do operador sizeof. char *strcat(char *dest, const char *orig): Concatena cadeia orig ao nal de dest. O primeiro caracter de orig substitui o caracter nulo de dest. A funao retorna o valor de dest. c char *strncat (char *dest, const char *orig, size_t n): Concatena cadeia orig ao nal de dest, usando no mximo n caracteres de orig. O pria meiro caracter de orig substitui o caracter nulo de dest. A funao retorna c o valor de dest. char *strcmp (const char *cad1, const char *cad2): Compara lexicogracamente as duas cadeias. Retorna zero se as cadeias so iguais, menor a que 0 se cad1 < cad2, maior que 0 se cad1 > cad2. char *strncmp (const char *cad1, const char *cad2, size_t n): Compara lexicogracamente at n caracteres das duas cadeias. Retorna zero e se as cadeias so iguais, menor que 0 se cad1 < cad2, maior que 0 se a cad1 > cad2. size_t strlen(const char *cad): Calcula o comprimento da cadeia sem contar o caracater nulo. O comprimento da cadeia determinado pelo e caractere nulo. No confundir o tamanho da cadeia com o tamanho do a vetor que armazena a cadeia. char *strcpy(char *dest, const char *orig): Copia cadeia orig para dest. A cadeia destino deve ter espao suciente para armazenar orig. c O valor de dest retornado. e Estas funoes esto na biblioteca string.h. O programa 7.4 mostra exemc a plos de uso de algumas das funoes de cadeia. Neste exemplo, o programa c primeiro l um nome e em seguida um sobrenome. O programa ir ento cone a a catenar as duas cadeias. Observe que sempre colocado um branco ao nal e do nome para separ-lo do sobrenome. Este branco inserido usando a funao a e c strcat, e esta razo das aspas, ou seja, uma cadeia de um caractere apenas. e a A seguir mostramos um resultado da execuao do programa 7.4. c

7.3. CADEIAS DE CARACTERES Entre com um nome Ze Ze Entre com um sobrenome Sa Sa Ze Sa Qual caracter? a O caractere aparece na posicao 4

123

Listagem 7.4: Exemplos de funoes para cadeias. c


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

124

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

7.4

Declarao de Vetores Multidimensionais ca

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

Por exemplo a declaraao c


int matriz[10][20];

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


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

armazena o dobro do elemento que est na quarta linha e nona coluna na varivel a a c. Observar que o primeiro ndice indica a linha e o segundo a coluna. Lembrar que o n mero da primeira linha (coluna) igual a 0. O programa 7.5 l uma u e e matriz de trs linhas e cinco colunas e imprime os valores lidos. e Listagem 7.5: Leitura de uma matriz.
#define DIML 3 #define DIMC 5 #include < stdio .h > i n t main ( void ) { int i, j; i n t matriz [ DIML ][ DIMC ]; f o r ( i =0; i < DIML ; i ++) f o r ( j =0; j < DIMC ; j ++) scanf ( " % d " , & matriz [ i ][ j ]); f o r ( i =0; i < DIML ; i ++) { f o r ( j =0; j < DIMC ; j ++) printf ( " %4 d " , matriz [ i ][ j ]); printf ( " \ n " ); } return 0; }

A matriz armazenada na memria linha a linha e a Figura 7.4 ilustra esta e o idia com uma matriz de n meros inteiros de trs por trs. Estamos assumindo e u e e que cada n mero inteiro ocupa quatro bytes, o endereo aponta um byte e a u c matriz est armazenada a partir do endereo 1000. a c

7.5. VETORES DE CADEIAS DE CARACTERES

125

1000

m[0][0]

1004

m[0][1]

1008

m[0][2]

1012

m[1][0]

1016

m[1][1]

1020

m[1][2]

1024

m[2][0]

1028

m[2][1]

1032

m[2][2]

Figura 7.1: Mapa de memria de uma matriz. o

Uma operaao muito comum em matemtica a multiplicaao de matrizes. c a e c Considere a matriz M 1 com L1 linhas e C1 colunas e a matriz M 2 com L2 linhas e C2 colunas. O n mero de colunas C1 de M 1 deve ser igual ao n mero u u de linhas L2 de M 2. O elemento M Rij da matriz resultado M R do produto destas matrizes denido pela equaao 7.1. O programa 7.6 multiplica duas e c matrizes de acordo com a frmula. o
C1

M Rij =
k=1

M 1ik M 2kj

(7.1)

7.5

Vetores de Cadeias de Caracteres

A declaraao abaixo mostra uma matriz de cadeias de caracteres com 30 linhas c de 80 caracteres. char nome turma[30][80];

126

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES Listagem 7.6: Multiplicaao de duas matrizes. c

#include < stdio .h > #define #define #define #define L1 L2 C1 C2 3 3 3 3

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

7.6. INICIALIZACAO DE VETORES E MATRIZES

127

O Programa 7.7 mostra um programa que l uma matriz de nomes e imprime e os seus conteudos. E importante notar que para ler um nome o programa no a l um caracter de cada vez mas usa a funao fgets. Como cada linha da matriz e c uma cadeia de caracteres, o programa l o nome que est na linha i como e e a fgets(nomes[i], DIMC-1, stdin). Listagem 7.7: Leitura de um vetor de nomes.
#define DIML 5 #define DIMC 41 #include < stdio .h > #include < string .h > i n t main ( void ) { int i; char nomes [ DIML ][ DIMC ]; f o r ( i =0; i < DIML ; i ++) { printf ( " Entre com a linha % d " , i ); fgets ( nomes [ i ] , DIMC -1 , stdin ); nomes [ i ][ strlen ( nomes [ i ]) -1] = \0 ; } f o r ( i =0; i < DIML ; i ++) { printf ( " O nome % d e " , i ); puts ( nomes [ i ]); } return 0; }

7.6

Inicializao de Vetores e Matrizes ca

Em C poss e vel inicializar vetores da mesma forma que variveis, isto , no a e momento em que so declarados. A forma de fazer isto a seguinte: a e tipo nome[dim] = {lista de valores}; e rgulas. Por onde lista de valores um conjunto de valores separados por v exemplo, a declaraao abaixo inicializa um vetor inteiro de cinco posioes. c c int vetor[5] = { 10, 15, 20, 25, 30 }; Observe que nesta declaraao necessrio que o tamanho do conjunto seja c e a conhecido antecipadamente. No entanto, tambm poss inicializar vetores e e vel

128

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

em que no se conhece o seu tamanho. Neste caso, ento, importante que o a a e programador preveja um modo de indicar o m do vetor. O Programa 7.8 mostra os casos ilustrados acima. No primeiro exemplo o tamanho do vetor conhecido e foi denido pela constante DIM. Para descoe brir o como parar de processar o vetor, quando desconhecemos seu tamanho, apresentamos duas soluoes poss c veis. No primeiro caso a condiao de m do c vetor o n mero negativo -1. Neste caso uma posiao do vetor perdida para e u c e armazenar esta condiao. No segundo caso usado o operador sizeof para c e descobir o tamanho do vetor. Observe que sizeof calcula o tamanho do vetor em bytes e por esta razo necessrio uma diviso pelo tamanho em bytes do a e a a tipo de cada elemento. Listagem 7.8: Exemplos de tratamento de vetores.
#define DIM 5 #include < stdio .h > i n t main () { i n t vetor [ DIM ] = {10 , 15 , 20 , 25 , 30}; i n t vetor1 [] = {10 , 20 , 30 , 40 , 50 , 60 , -1}; i n t vetor2 [] = {3 , 6 , 9 , 12 , 15 , 18 , 21 , 24}; unsigned i n t i , tam ; printf ( " Este programa imprime vetores " ); printf ( " contendo numeros inteiros e \ n " ); printf ( " que foram inicializados durante " ); printf ( " a sua declaracao .\ n " ); /* Impressao dos conjuntos */ printf ( " \ nVetor com tamanho pre - definido \ n " ); f o r ( i =0; i < DIM ; i ++) printf ( " Elemento % d = % d \ n " , i , vetor [ i ]); printf ( " \ nVetor terminando por -1\ n " ); f o r ( i =0; vetor1 [ i ] >0; i ++) printf ( " Elemento % d = % d \ n " , i , vetor1 [ i ]); tam = s i z e o f ( vetor2 ) printf ( " \ nDescobrindo f o r ( i =0; i < tam ; printf ( " Elemento return 0; } / s i z e o f ( i n t ); o tamanho do Vetor \ n " ); i ++) % d = % d \ n " , i , vetor2 [ i ]);

E poss vel inicializar matrizes multidimensionais e neste caso necessrio e a especicar todas as dimenses menos a primeira, para que o compilador possa o

7.7. EXERC ICIOS

129

reservar memria de maneira adequada. A primeira dimenso somente especica o a quantos elementos o vetor ir armazenar e isto lendo a inicializaao o compilador a c pode descobrir. A declaraao a seguir ilustra como declarar e inicializar uma matriz de trs c e linhas por quatro colunas de n meros reais. u
f l o a t mat [][4] = { {1.0 , 2.0 , 3.0 , 4.0} , // linha 0 {8.0 , 9.0 , 7.5 , 6.0} , // linha 1 {0.0 , 0.1 , 0.5 , 0.4} }; // linha 2

O Programa 7.9 ilustra a deniao de um vetor de cadeia de caracteres, que c nada mais do que uma matriz de caracteres. Note que as cadeias so separadas e a uma das outras por v rgulas. Listagem 7.9: Exemplos de tratamento de vetores.
#define DIM 5 #include < stdio .h > i n t main ( void ) { char disciplinas [][40] = { " disc 0: Computacao para Informatica " , " disc 1: Banco de Dados I " , " disc 2: Banco de Dados II " , " disc 3: Arquitetura de Computadores I " }; int i; printf ( " Qual a disciplina ? " ); scanf ( " % d " , & i ); puts ( disciplinas [ i ]); return 0; }

7.7

Exerc cios

7.1: Escreva um programa que leia uma linha de at 80 caracteres do teclado e e imprima quantos caracteres foram lidos. 7.2: Escreva um programa que leia uma linha de caracteres do teclado e imprima quantas vezes um caracter, tambm fornecido pelo teclado, aparece nesta linha. e O programa tambm deve imprimir em que posioes o caracter foi encontrado. e c 7.3: Escreva um programa que leia uma linha do teclado e em seguida um par de caracteres. O programa deve procurar este par na linha e imprimir em que

130

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

posioes o par foi encontrado. Obs. No use funoes da biblioteca de strings c a c do C 7.4: Escreva um programa que leia uma linha do teclado e imprima todas as vogais encontradas no texto e o total de vezes que elas aparecem. Obs: Tamanho maximo da linha deve ser 40 caracteres. 7.5: Oimperador romano Cesar usava um sistema simples para codicar as mensagens que enviava aos seus generais. Neste sistema cada letra era substitu da por trs letras ` frente no alfabeto. A sua misso mais simples ainda, escrever e a a e 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 e deve ser convertida para a letra a, e a letra Z para A. 7.6: Escreva um programa que leia uma frase de 80 caracteres e a imprime retirando os espaos em branco. c 7.7: Escreva um programa que leia uma linha de caracteresdo teclado de tamanho 80. A linha somente contm letras. Divida a linha em blocos de 5 letras. e 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 e e c ser retirados da frase. Considere o seguinte exemplo. 1. Frase lida: EVA VIU A UVA 2. Retirada dos espaos em branco: c EVAVIUAUVA 3. Diviso em blocos de 5 (blocos indicados por tipos diferentes): a EVAVIUAUVA 4. Criptograa: FYDANVCYAF Portanto, o que ser impresso pelo programa : a e FYDANVCYAF 7.8: Escreva um programa que leia uma matriz de 3x3 que contm somente e caracteres 0 e X e procure linhas que contenham somente um dos dois caracteres. O caracter a ser procurado deve ser lido do teclado. 7.9: Escreva um programa que leia uma linha de caracteres do teclado e converta o primeiro caracter de cada palavra para mai sculas. Assuma que as palavras u so sempre separadas por um branco. a 7.10: Escreva um programa que leia para um vetor um conjunto de n meros u inteiros. Assuma que o conjunto de n meros lidos menor que o tamanho do u e

7.7. EXERC ICIOS

131

vetor. O programa deve inserir no vetor, em uma posiao especicada pelo c usurio, um n mero lido do teclado. Assuma que a posiao especicada pelo a u c usurio corresponde ao a ndice do vetor. 7.11: Faa um programa que inverta uma cadeia de caracteres. O programa c deve ler a cadeia com gets e armazen-la invertida em outra cadeia. Use o a comando for para varrer a cadeia at o seu nal. e 7.12: Escreva um programa que leia um conjunto de nomes para uma matriz e imprima estes nomes em ordem alfabtica. Assuma que os nomes sero lidos e a somente em letras mai sculas. Assuma tambm que os nomes tm no mximo u e e a 40 caracteres e sero lidos 10 nomes ao todo. a

132

CAP ITULO 7. VETORES E CADEIAS DE CARACTERES

Cap tulo 8

Funes co
8.1 Introduo ca

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

134

CAP ITULO 8. FUNCOES

Os programadores podem testar suas funoes separadamente em testes menos c complexos, j que as funoes normalmente so simples e tm requisitos menos a c a e complicados de serem avaliados. Isto permite que muitos erros do sistema completo possam ser retirados antes que ele esteja completo. Normalmente testar um programa complexo requer testes complexos. Mesmo quando um programa desenvolvido por um unico programador a e sua diviso em funoes traz vantagens, por dividir um trabalho complexo em a c diversas fatias menores permitindo ao programador se concentrar a cada vez em problemas mais simples.

8.2

Forma Geral

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


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

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

for executado, o valor da express~o devolvido para a funao que chamou. a e c Quando no h valor para retornar o comando return no precisa ser usado e a a a a funao termina quando a chave que indica o trmino do corpo da funao c e c e atingido. Os parmetros so valores que a funao recebe para realizar as tarefas para a a c as quais foi programada. Por exemplo, uma funao que calcule a raiz quadrada c de um n mero do tipo oat , deve declarar como parmetro uma varivel deste u a a tipo para receber o valor.

8.3. PROTOTIPOS DE FUNCOES

135

E importante notar que diferentemente de declaraoes de variveis onde c a podemos associar vrios nomes de variveis a uma declaraao como em a a c
int a, dia, mes, i;

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

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

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

8.3

Prottipos de Funes o co

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

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

136

CAP ITULO 8. FUNCOES Listagem 8.1: Exemplo de prottipos. o

#include < stdio .h > /* Prototipo da funcao */ i n t soma ( i n t a , i n t b ); /* Funcao Principal */ i n t main () { i n t a =5 , b =9; printf ( " % d \ n " , soma (a , b )); return 0; } /* Definicao da funcao */ i n t soma ( i n t a , i n t b ) { return a + b ; }

8.4

Escopo de Variveis a

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

8.4.1

Variveis Locais a

As variveis locais so aquelas declaradas dentro de uma funao ou um bloco a a c de comandos. Elas passam a existir quando do in da execuao do bloco de cio c

8.4. ESCOPO DE VARIAVEIS

137

comandos ou funao onde foram denidas e so destru c a das ao nal da execuao c do bloco. Uma varivel local s pode ser referenciada, ou seja usada, dentro a o da funao (ou bloco) onde foi declarada. Outro ponto muito importante que c e como as variveis locais deixam de existir ao nal da execuao da funao (ou a c c bloco), elas so invis a veis para outras funoes do mesmo programa. O cdigo c o que dene uma funao e os seus dados so particulares da funao (do bloco). c a c No programa 8.2 podemos ver o uso de variveis locais. A varivel i a a e denida em cada uma das funoes do programa (pares, impares). Os valores c da varivel no podem ser acessados a partir de nenhuma outra funao e as a a c modicaoes feitas dentro da funao somente valem enquanto a funao est c c c a sendo executada. Listagem 8.2: Exemplos de variveis locais. a
#include < stdio .h > void pares ( void ) { int i; f o r ( i = 2; i <= 10; i += 2) { printf ( " % d : " , i ); } } void impares ( void ) { int i; f o r ( i = 3; i <= 11; i += 2) { printf ( " % d : " , i ); } } i n t main ( i n t argc , char * argv []) { pares (); printf ( " \ n " ); impares (); return 0; }

Alguns autores usam o termo variveis automticas para se referir as variveis a a a locais. Em C existe a palavra chave auto que pode ser usada para declarar que variveis pertencem ` classe de armazenamento padro. No entanto, como todas a a a as variveis locais so por deniao automticas raramente se usa esta palavra a a c a chave. Observe que um bloco de comandos se inicia em um { e termina em

138

CAP ITULO 8. FUNCOES

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

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

8.5

Variveis Globais a

As variveis globais so denidas fora de qualquer funao e so portanto dispoa a c a n veis para qualquer funao. Este tipo de varivel pode servir como uma canal c a de comunicaao entre funoes, uma maneira de transferir valores entre elas. Por c c exemplo, se duas funoes tem de partilhar dados, mais uma no chama a outra, c a uma varivel global tem de ser usada. a O programa 8.4 ilustra este tipo de declaraao. O resultado da execuao c c deste programa o seguinte: e Funcao soma1: i = 1 Funcao sub1: i = 9 Funcao main: i = 1 Observe que a varivel global i recebe o valor 0 no in da funao main. A a cio c funao soma1 ao executar um comando que aumenta o valor de i em uma unidade c est aumentando a varivel global. Em seguida vemos que a funao sub1 dene a a c uma varivel local tambm chamada i e, portanto, a alteraao feita por esta a e c

8.6. PARAMETROS FORMAIS

139

funao somente modica esta varivel. Finalmente, a funao main imprime o c a c valor nal da varivel global. a Listagem 8.4: Deniao de varivel global. c a
#include < stdio .h > int i; void soma1 ( void ) { i += 1; printf ( " Funcao soma1 : i = % d \ n " , i ); } void sub1 ( void ) { i n t i = 10; i -= 1; printf ( " Funcao sub1 : i = % d \ n " , i ); } i n t main ( i n t argc , char * argv []) { i = 0; soma1 (); sub1 (); printf ( " Funcao main : i = % d \ n " , i ); return 0; }

8.6

Parmetros Formais a

As variveis que aparecem na lista de parmetros da funao so chamadas de a a c a parmetros formais da funao. Eles so criados no in da execuao da funao a c a cio c c e destru dos no nal. Parmetros so valores que as funoes recebem da funao a a c c que a chamou. Portanto, os parmetros permitem que uma funao passe valores a c para outra. Normalmente os parmetros so inicializados durante a chamada da a a funao, pois para isto foram criados. No entanto, as variveis que atuam como c a parmetros so iguais a todas as outras e podem ser modicadas, operadas, etc, a a sem nenhuma restriao. Parmetros podem ser passados para funoes de duas c a c maneiras: passagem por valor ou passagem por referncia. e

8.6.1

Passagem de Parmetros por Valor a

Na passagem por valor uma cpia do valor do argumento passado para a o e funao. Neste caso a funao que recebe este valor, ao fazer modicaoes no c c c

140

CAP ITULO 8. FUNCOES

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

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

8.6.2

Passagem de Parmetros por Referncia a e

Na passagem por referncia o que passado para a funao o endereo do e e c e c parmetro e, portanto, a funao que recebe pode, atravs do endereo, modicar a c e c

8.6. PARAMETROS FORMAIS Listagem 8.6: Uso indevido de variveis locais. a


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

141

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

8.6.3

Passagem de Vetores e Matrizes

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

142

CAP ITULO 8. FUNCOES

Listagem 8.7: Passagem de vetor com dimenses. o


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

8.6. PARAMETROS FORMAIS

143

Listagem 8.8: Passagem de vetores sem dimenses. o


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

144

CAP ITULO 8. FUNCOES

8.7

O Comando return

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

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

8.8

Recurso a

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

Alternativamente, o fatorial pode ser dendo como o produto deste n mero u pelo fatorial de seu predecessor, ou seja n! = n (n 1)! Deste modo podemos escrever uma funao recursiva em que cada chamada c da funao que calcula o fatorial chama a prpria funao fatorial. O exemplo, c o c mostrado a seguir, mostra como a funao pode ser escrita recursivamente. c

8.9. ARGUMENTOS - ARGC E ARGV


unsigned long i n t fat ( unsigned long i n t num ) { i f ( num == 0) return 1; else return num * fat ( num -1); }

145

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

8.9

Argumentos - argc e argv

A funao main como todas as funoes podem ter parmetros. Como a funo main c c a ca sempre a primeira a ser executada, os parmetros que ela recebe so fornecidos e a a pela linha de comando ou pelo programa que iniciou a sua execuao. No caso c da funao main so usados dois argumentos especiais int argc e char **argv. c a O primeiro argumento, argc, uma varivel inteira que indica quantos are a gumentos foram fornecidos para a funao. Observar que argc vale sempre pelo c

146

CAP ITULO 8. FUNCOES Listagem 8.9: Funao recursiva para calcular xn . c

f l o a t Elevar ( f l o a t x , i n t n ) { i f ( n <= 1) { return x ; } else { return x * Elevar (x , b -1); } }

menos 1, porque o nome do programa sempre o primeiro argumento fornecido e ao programa. A partir do segundo argumento em diante que aparecem os e outros argumentos. O outro parmetro um vetor de cadeias de caracteres, e portanto, caso a e sejam fornecidos n meros, estes devem ser convertidos para o formato requerido. u Cada um dos argumentos do programa um elemento deste vetor. A primeira e linha da funao main pode ter a seguinte forma c
void main (int argc, char *argv[])

O programa exemplo 8.10 calcula o fatorial dos n meros fornecidos como u argumentos. Os nomes argc e argv so comumente usados mas o programador livre para a e escolher os nomes mais apropriados.

8.10

Exerc cios

8.1: Escrever um programa que declare, inicialize e imprima um vetor de 10 inteiros. O vetor deve conter os 10 primeiros m ltiplos de 5. A inicializaao do u c vetor e a sua impresso devem ser feitas por funoes. a c 8.2: Escreva um programa para declarar um vetor de caracteres de tamanho 26 e imprimir o seu conte do. O vetor deve ser inicializado com as letras min sculas u u do alfabeto. A inicializaao do vetor e a sua impresso devem ser feitas por c a funoes. c 8.3: Escreva um programa que armazene em uma matriz trs nomes de pessoas e e em seguida os imprima. Assuma que o tamanho mximo de cada nome 40 a e caracteres. Neste programa a leitura dos nomes dever ser feita por uma funao c e a impresso dos nomes por outra. a

8.10. EXERC ICIOS

147

Listagem 8.10: Uso de argc e argv.


#include < stdio .h > #include < stdlib .h > unsigned long i n t fat ( unsigned long i n t num ) { i f ( num == 0) return 1; else return num * fat ( num -1); } i n t main ( i n t argc , char * argv []) { unsigned long i n t numero , fatorial , i ; i f ( argc < 2) { printf ( " Para rodar : % s num1 num2 ... .\ n " , argv [0]); return 1; } f o r ( i =1; i < argc ; i ++) { numero = ( unsigned long i n t ) ( atoi ( argv [ i ])); fatorial = fat ( numero ); printf ( " O fatorial de % lu vale % lu .\ n " , numero , fatorial ); } return 0; }

148

CAP ITULO 8. FUNCOES

8.4: Escreva um programa que imprima o codigo ASCII de todos os caracteres, das seguintes maneiras: 1. caractere a caractere, a escolha do usuario; 2. a tabela inteira, a partir de um determinado valor decimal. Cada item deste exerc deve corresponder a uma funao. cio c 8.5: Escreva um programa que crie uma tabela de temperaturas Celsius - Fahrenheit. O programa deve usar uma funao que converta de Celsius para Fahc renheit. A tabela deve iniciar na temperatura 0 graus Celsius e terminar na temperatura 100 graus Celsius. 8.6: Escreva um programa, usando funoes, que gere um vetor a partir de uma c matriz. Cada elemento do vetor igual a soma dos elementos de uma das linhas e da matriz. Considere que a matriz tenha tamanho 10 por 10. 8.7: Escreva um programa usando recursividade para gerar a seqncia do ue Fibonacci. A seqncia de Fibonacci denida como: ue e f (0) = f (1) = f (n) = 0 1 f (n 1) + f (n 2)

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

Cap tulo 9

Ponteiros
9.1 Introduo ca

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

Figura 9.1: Mapa de memria com duas variveis e ponteiro. o a

149

150

CAP ITULO 9. PONTEIROS

Ponteiros so importantes, por exemplo, quando se deseja que uma funao a c retorne mais de um valor. Neste caso uma soluao a funo receber como c e ca argumentos no os valores dos parmetros mas sim ponteiros que apontem para a a seus endereos. Assim esta funao pode modicar diretamente os conte dos c c u destas variveis, que aps o m da funao estaro dispon a o c a veis para a funao que c chamou. Neste caso os argumentos podem funcionar como entrada e sa de da dados da funao. c

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

0 4 8 1000 pi ponteiro para vetor

1000

120 Vetor de 10 inteiros

1036

97

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

9.2. OPERACOES COM PONTEIROS

151

9.2
9.2.1

Operaes com Ponteiros co


Declarao de Ponteiros ca

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

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

996

1000

endereo indefinido

*res

1004

endereo indefinido

*div

Figura 9.3: Declaraao de ponteiros. c

152

CAP ITULO 9. PONTEIROS

9.2.2

Os Operadores Especiais para Ponteiros

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

a varivel ponteiro pint termina com o valor 4, como est mostrado na Figura a a 9.4. Lembre-se que o valor 4 no tem sentido prtico na maioria das aplicaoes. a a c O fato importante que o ponteiro pint passou a apontar para a varivel num e a
0 4 8 12 16 10 120 4 num res *pint

Figura 9.4: Atribuiao de endereo de uma varivel a um ponteiro. c c a O operador * o complemento de &. O operador * devolve o valor da varivel e a localizada no endereo apontado pelo ponteiro. Por exemplo, considere que o c comando res = *pint; foi executado logo aps pint = &num;. Isto signica que o a varivel res recebe o valor apontado por pint, ou seja a varivel res recebe o a a valor 10, como est mostrado na Figura 9.5. a Estes operadores no devem ser confundidos com os j estudados em cap a a tulos anteriores. O operador * para ponteiros no tem nada a ver com o operador a multiplicaao *. O operador ponteiro * unrio e, como o operador &, tem c e a precedncia maior que do que todos os operadores aritmticos. e e

9.2.3

Atribuio de Ponteiros ca

Da mesma maneira que ocorre com uma varivel comum, o conte do de um a u ponteiro pode ser passado para outro ponteiro do mesmo tipo. Por exemplo, uma varivel ponteiro declarada como apontador de dados inteiros deve sempre a apontar para dados deste tipo. Observar que em C poss atribuir qualquer e vel endereo a uma varivel ponteiro. Deste modo poss atribuir o endereo de c a e vel c uma varivel do tipo oat a um ponteiro do tipo int. No entanto, o programa a no ir funcionar da maneira correta. O programa 9.1 mostra exemplos de a a

9.2. OPERACOES COM PONTEIROS


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

153

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

atribuioes de ponteiros. Neste exemplo o endereo do terceiro elemento do c c vetor v carregado em p1 e o endereo da varivel i carregado em p2. A e c a e Figura 9.6 a situaao da memria aps estas operaoes. Alm disso no nal o c o o c e endereo apontado por p1 carregado em p2. Os comandos printf imprimem os c e valores apontados pelos ponteiros respectivos, mostrando os seguintes valores: 30 100 30

Listagem 9.1: Exemplo de atribuiao de ponteiros. c


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

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

CAP ITULO 9. PONTEIROS

p1 = &v[2];

p2 = &i; i

Figura 9.6: Exemplos de atribuioes de ponteiros. c

9.2.4

Incrementando e Decrementando Ponteiros

O exemplo 9.2 mostra que operaoes de incremento e decremento podem ser c aplicadas em operandos. O primeiro printf imprime 30, que o elemento de e ndice igual a 2 no vetor vetor. Aps o incremento do ponteiro o segundo printf o imprime 40 e o mesmo acontece com o terceiro printf que imprime 50. Listagem 9.2: Exemplos de operaoes com ponteiros. c
i n t main ( void ) { i n t vetor [] = { 10 , 20 , 30 , 40 , 50 }; i n t * p1 ; p1 = & vetor [2]; printf ( " % d \ n " , * p1 ); p1 ++; printf ( " % d \ n " , * p1 ); p1 = p1 + 1; printf ( " % d \ n " , * p1 ); return 0; }

Pode parecer estranho que um ponteiro para um n mero inteiro, que armau e zenado em quatro bytes, seja incrementado por um e passe para apontar para o prximo n mero inteiro. A primeira vista, para que passasse a apontar para o u o prximo endereo, seria necessrio aumentar o endereo em quatro. Ou seja, o c a c

9.2. OPERACOES COM PONTEIROS

155

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

Tambm poss usar-se o seguinte comando e e vel


*(p+1)=10;

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


p. A operaao realizada nos seguintes passos: c e

1. A expresso p+1 calculada e o seu resultado aponta para o prximo a e o endereo de dado inteiro; c 2. A expresso do lado direito do sinal de atribuiao, calculada e fornece a c e como resultado o valor 10; 3. Este resultado atribu ao endereo calculado no primeiro passo. e do c A diferena entre ponteiros fornece quantos elementos do tipo do ponteiro c existem entre os dois ponteiros. No exemplo 9.3 impresso o valor 2. e Listagem 9.3: Exemplo de subtraao de ponteiros. c
#include < stdio .h > i n t main ( void) { f l o a t vetor [] = { 1.0 , 2.0 , 3.0 , 4.0 , 5.0 }; f l o a t * p1 , * p2 ; p1 = & vetor [2]; /* endereco do terceiro elemento */ p2 = vetor ; /* endereco do primeiro elemento */ printf ( " Diferenca entre ponteiros % d \ n " , p1 - p2 ); return 0; }

No poss multiplicar ou dividir ponteiros, e no se pode adicionar ou a e vel a subtrair o tipo oat ou o tipo double a ponteiros.

156

CAP ITULO 9. PONTEIROS

9.2.5

Comparao de Ponteiros ca

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

9.3

Ponteiros e Vetores

Ponteiros e Vetores esto fortemente relacionados na linguagem C. O nome de a um vetor um ponteiro que aponta para a primeira posiao do vetor. A dee c claraao int vetor[100] cria um vetor de inteiros de 100 posioes e permite que c c algumas operaoes com ponteiros possam ser realizadas com a varivel vetor. c a No entanto, existe uma diferena fundamental entre declarar um conjunto c de dados como um vetor ou atravs de um ponteiro. Na declaraao de vetor, e c o compilador automaticamente reserva um bloco de memria para que o vetor o seja armazenado. Quando apenas um ponteiro declarado a unica coisa que e o compilador faz alocar um ponteiro para apontar para a memria, sem que e o espao seja reservado. O nome de um vetor chamado de ponteiro constante c e e, portanto, no pode ter o seu valor alterado. O nome de um ponteiro consa tante no pode aparecer em expresses no lado esquerdo do sinal de igual, ou a o seja, no pode receber valores diferentes do valor inicial atribu na declaraao a do c da varivel. Assim, os comandos que alteram o ponteiro list, mostrados no a exemplo 9.5, no so vlidos: a a a O conte do de vetores pode ser acessado usando-se o operador * para obter u o conte do do vetor. O Programa 9.6 mostra a notaao que usa u c ndices para

9.4. PONTEIROS E CADEIAS DE CARACTERES Listagem 9.5: Exemplo de alteraoes invlidas sobre ponteiros. c a
i n t list [5] , i ; /* O ponteiro list nao pode ser modificado recebendo o endereco de i */ list = & i /* O ponteiro list nao pode ser incrementado */ list ++;

157

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

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

9.4

Ponteiros e Cadeias de Caracteres

Uma cadeia de caracteres constante escrita como no exemplo: e


"Esta e uma cadeia de caracteres."

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

Quando uma cadeia de caracteres como esta enviada para a funao, o que e c passado o ponteiro para a cadeia. E poss ento carregar o endereo da e e vel a c cadeia em um ponteiro do tipo char, como no exemplo 9.8. Neste programa e contado o n mero de caracteres de uma cadeia. Observe o ponteiro *(s+tam++) u apontando caracter a caracter.

158

CAP ITULO 9. PONTEIROS Listagem 9.7: Exemplo de ponteiro varivel. a

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

Listagem 9.8: Exemplo de ponteiro para cadeia de caracteres.


#include < stdio .h > i n t main ( void ) { char *s , * lista = " 1234567890 " ; i n t tam =0; s = lista ; while (*( s + tam ++) != \0 ); tam - -; printf ( " O tamanho do string \"% s \" e % d caracteres .\ n " , lista , tam ); return 0; }

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

9.5

Alocao Dinmica de Memria ca a o

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

9.5. ALOCACAO DINAMICA DE MEMORIA Listagem 9.9: Exemplo de cpia de cadeias de caracteres. o
#include < stdio .h > i n t strcop ( char *d , char * o ); i n t main ( void) { char destino [20]; char * origem = " cadeia de caractere de origem " ; strcop ( destino , origem ); printf ( " % s \ n " , origem ); printf ( " % s \ n " , destino ); return 0; } i n t strcop ( char *d , char * o ) { while ((* d ++ = * o ++) != \0 ); return 0; }

159

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

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

160

CAP ITULO 9. PONTEIROS Listagem 9.10: Exemplo de uso de calloc e free.

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

9.6

Ponteiros e Matrizes

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

9.6. PONTEIROS E MATRIZES Listagem 9.11: Exemplo de uso de malloc.


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

161

162

CAP ITULO 9. PONTEIROS

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


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

Listagem 9.13: Exemplo de matriz mapeada em um vetor.


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

9.7. VETORES DE PONTEIROS

163

matriz matriz[i][j] em um endereo linear. O ideal usar uma notaao que c e c use somente ponteiros. Esta notaao ser discutida nas seoes seguintes. c a c

9.7

Vetores de Ponteiros

Uma possibilidade mais interessante utilizar vetores de ponteiros. Esta no e a e a notaao ideal, mas um passo na direao da notaao mais efetiva. Neste caso c e c c cada linha da matriz corresponde a um vetor que apontado por um ponteiro e armazenado no vetor de ponteiros. Como ponteiros tambm so variveis e a a e poss ento criar vetores de ponteiros e utiliz-los. O exemplo mostrado em vel a a 9.14 mostra um programa onde utilizado um vetor de ponteiros para vrias e a linhas de caracteres. Observe na funao main a declaraao char *linha[LINHAS]; c c que dene um vetor de tamanho LINHAS. Este vetor contem ponteiros e no a valores. At este momento do programa temos apenas posies reservadas para e co armazenar ponteiros. A alocaao de espao e a inicializaao dos ponteiros feito c c c e no primeiro comando for. Como cada elemento do vetor linha um ponteiro e temos que o endereo retornado pela funao malloc armazenado em cada c c e um dos elementos deste vetor. A leitura das linhas de caracteres feita pela e funao gets(linha[i]) que passa o elemento do vetor onde os caracteres sero c a armazenados.

9.8

Ponteiros para Ponteiros

No exemplo anterior podemos observar que o n mero de linhas da matriz u e xa, e portanto, h uma mistura de notaao de ponteiros com matrizes. Vamos a c considerar um exemplo onde tanto o n mero de linhas como o de colunas u e desconhecido. Neste exemplo iremos criar um vetor de ponteiros que ir armaa zenar o endereo inicial de cada linha. Portanto, para obter um elemento da c matriz primeiro devemos descobrir onde est a linha no vetor que armazena os a endereos das linhas, em seguida procuramos na linha o elemento. A Figura 9.7 c ilustra como ser feito o armazenamento desta matriz. a O Programa 9.15, listado a seguir, ir pedir ao usurio que digite o n mero a a u de linhas e colunas da matriz. Em seguida ler todos os elementos da matriz e a por ultimo ir trocar duas linhas da matriz de posiao. Observe que agora foi a c criado um ponteiro para ponteiro chamado de **matriz. O programa primeiro pergunta o n mero de linhas da matriz para poder alocar espao para armazenar u c os ponteiros para cada uma das linhas. Em seguida alocado espao para e c armazenar cada uma das linhas. O comando
matriz = (int **) malloc (lin * sizeof(int *));

foi usado pelo programa para reservar espao para armazenar lin linhas de c ponteiros para ponteiros. Observe que o comando sizeof(int *) calcula o espao c para armazenar um ponteiro na memria. Note tambm que o valor retornado o e

164

CAP ITULO 9. PONTEIROS

Listagem 9.14: Exemplo de uso de vetor de ponteiros.


#include < stdio .h > #include < stdlib .h > #define LINHAS 10 #define COLUNAS 60 i n t main ( void ) { char * linha [ LINHAS ]; int i; f o r ( i = 0; i < LINHAS ; i ++) { i f (!( linha [ i ] = malloc ( COLUNAS * s i z e o f ( char )))) { printf ( " Sem mem ria para vetor % d .\ n " , i ); o return i ; } } f o r ( i = 0; i < LINHAS ; i ++) { printf ( " Entre com a linha % d .\ n " , i ); gets ( linha [ i ]); } f o r ( i = 0; i < LINHAS ; i ++) { printf ( " Linha % d % s .\ n " , i , linha [ i ]); } return 0; }

9.9. EXERC ICIOS


Vetor de ponteiros **matriz *(matriz+0) *(matriz+1) *(matriz+2) linha 2 linha 1 linha 0

165

*(matriz+n) linha n

Figura 9.7: Armazenamento de matrizes com vetores de ponteiros.

pela funao malloc foi conformado ao tipo ponteiro para ponteiro pela operaao c c (int **). O interessante do programa que a troca de linhas da matriz involve e simplesmente a troca de dois ponteiros e no a troca de todos os elementos das a linhas. Esta soluao muito mais rpida do que trocar elemento a elemento, c e a especialmente para matrizes grandes. A seguir mostramos o programa nas listagens 9.16 e 9.17 que o exemplo e anterior modicado para utilizar funoes. O propsito mostrar como cam as c o e chamadas e as denioes das funoes que utilizam ponteiros para ponteiros. c c

9.9

Exerc cios

9.1: Escreva um programa que gere um vetor de trs dimenses (X, Y e Z) em e o que cada posiao guarda a soma de suas coordenadas. As dimenses da matriz c o devero ser determinadas em tempo de execuao e o programa dever informar a c a os valores gerados. 9.2: Escreva um programa que leia uma frase de at 80 caracteres do teclado e e imprima a frequncia com que aparece cada uma das letras do alfabeto na e frase. 9.3: Escreva um programa que leia uma frase de at 80 caracteres e a imprima e em ordem reversa convertendo todos os caracteres min sculos para mai sculos. u u 9.4: Escreva um programa que leia uma matriz e a imprima. O programa deve ler o numero de colunas e linhas do teclado. O programa deve ainda trocar duas

166

CAP ITULO 9. PONTEIROS Listagem 9.15: Exemplo de uso de ponteiros para ponteiros.

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

9.9. EXERC ICIOS

167

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


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

168

CAP ITULO 9. PONTEIROS

Listagem 9.17: Continuaao do exemplo 9.16. c


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

9.9. EXERC ICIOS

169

linhas da matriz de posiao. Os n meros das linhas a serem trocadas devem ser c u lidos do teclado. 9.5: Escreva um programa que simule uma pilha usando vetores. O programa deve implementar as seguintes operaoes na pilha: c Inserir Remover Listar 9.6: Escreva uma funao que receba um ponteiro para uma cadeia de caractere c e troque todo o caracter aps um branco pelo seu equivalente mai sculo. o u 9.7: Escreva um programa que leia seu nome completo e pergunte quantas letras tem o seu primeiro nome. Assuma que a letra a tem ndice 0, a letra b ndice 1 e assim por diante. O programa deve imprimir quantas letras iguais a letra cujo ndice o n mero de letras do seu primeiro nome existem no seu e u nome completo. 9.8: Escreva um programa que leia seu nome completo e pergunte quantas letras tem o seu primeiro nome. Faa uma funao que verique se a expresso apontada c c a por substr est presente na cadeia apontada por str. A funao possui o prottipo a c o abaixo:br int posicao(char *substr, char *str); e retorna a posiao em que c 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 o devem ser pedidas ao usurio. a 9.10: Escreva um programa que leia duas cadeias de caracteres e concatene a segunda cadeia ao nal da primeira.

170

CAP ITULO 9. PONTEIROS

Cap tulo 10

Estruturas
10.1 Introduo ca

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

10.2

Denies Bsicas co a

Uma estrutura, ento, uma coleao de variveis, de tipos diversos ou no, a e c a a agrupadas sob um unico nome. As variveis que compem a estrutura so os a o a seus membros, elementos ou campos. Normalmente os elementos da estrutura tem alguma relaao semntica. Por exemplo: alunos de uma universidade, discos c a de uma coleao, elementos de uma gura geomtrica, etc. Vamos considerar o c e exemplo do aluno e assumir que estaremos armazenando o seu nome, registro, ano de entrada e curso. Para este m podemos criar uma estrutura como a descrita no trecho de programa 10.1. A palavra chave struct inicia a declaraao da estrutura, em seguida pode c aparecer um identicador (ALUNO), que subsequentemente pode ser usado como abreviaao da deniao da estrutura. A declaraao continua com a lista de c c c 171

172

CAP ITULO 10. ESTRUTURAS Listagem 10.1: Deniao de uma estrutura. c

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

declaraoes entre chaves e termina com um ;. Um membro da estrutura e c uma vriavel no membro da estrutura podem ter o mesmo nome, j que a a a e poss distingui-las por contexto. vel A declaraao acima ainda no alocou espao de memria j que nenhuma c a c o a varivel foi realmente denida. Esta declaraao apenas um modelo de como a c e estruturas do tipo ALUNO devem ser constru das. Para denir estruturas deste tipo podemos usar a seguinte declaraao. c
struct ALUNO paulo, carlos, ana;

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

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

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

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

Estruturas podem conter outras estruturas como membros. Por exemplo, vamos denir uma estrutura para armazenar uma data com a seguinte deniao: c

10.2. DEFINICOES BASICAS


s t r u c t DATA { i n t dia , mes , ano ; };

173

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

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


aluno usamos a declaraao c paulo.data_nascimento.mes

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

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

174
... TEMPO t1 ;

CAP ITULO 10. ESTRUTURAS

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

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

10.3

Atribuio de Estruturas ca

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

10.4. MATRIZES DE ESTRUTURAS


temp = emp1 ; printf ( " O salario de % s e %.2 f \ n " , temp . nome , temp . salario ); return 0; }

175

10.4

Matrizes de Estruturas

Estruturas aparecem freq entemente na forma de matrizes. Por exemplo, a u declaraao struct ALUNO turma[100]; dene uma matriz de 100 estruturas do c tipo struct ALUNO. O exemplo 10.3 mostra atribuioes entre estruturas e operaoes aritmticas c c e envolvendo membros de estruturas. O programa coloca um vetor de estruturas em ordem crescente usando como chave de ordenaao um dos membros da c estrutura (media). Listagem 10.3: Ordenaao de Estruturas. c
#include < stdio .h > #include < string .h > typedef s t r u c t _ALUNO { char nome [40]; f l o a t n1 , n2 , media ; } ALUNO ; i n t main ( void ) { ALUNO turma [4] , temp ; i n t jaOrdenados = 0 , foraOrdem , i ; f o r ( i = 0; i < 4; i ++) { gets ( turma [ i ]. nome ); scanf ( " % f " , & turma [ i ]. n1 ); do {} while ( getchar ()!= \ n ); scanf ( " % f " , & turma [ i ]. n2 ); do {} while ( getchar ()!= \ n ); turma [ i ]. media =( turma [ i ]. n1 + turma [ i ]. n2 )/2.0; } do { foraOrdem = 0; f o r ( i = 0; i < 4 - 1 - jaOrdenados ; i ++) { i f ( turma [ i ]. media > turma [ i +1]. media ) { temp = turma [ i ]; turma [ i ] = turma [ i +1]; turma [ i +1] = temp ; foraOrdem = 1; } } jaOrdenados ++;

176

CAP ITULO 10. ESTRUTURAS


} while ( foraOrdem ); f o r ( i =0; i <4; i ++) { printf ( " \ nDados do aluno % d \ n " , i ); printf ( " % s : %0.1 f , %0.1 f , %0.1 f \ n " , turma [ i ]. nome , turma [ i ]. n1 , turma [ i ]. n2 , turma [ i ]. media ); } return 0;

10.5

Estruturas e Funes co

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

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

troca_x, mas isto veremos no prximo item. o

Para trabalhar com endereos necessrio usar ponteiros dentro da funao c e a c Antes vamos vericar como e poss passar uma estrutura inteira para uma funao. vel c

10.6. PONTEIROS PARA ESTRUTURAS

177

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

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

10.6

Ponteiros para Estruturas

Para denir ponteiros para estruturas a declaraao similar a declaraao de um c e c ponteiro normal. O exemplo abaixo mostra a deniao de um ponteiro chamado c maria para uma estrutura chamada aluno.

178

CAP ITULO 10. ESTRUTURAS Listagem 10.6: Funao que ordena estruturas. c

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

s t r u c t aluno { char nome [40]; i n t ano_entrada ; f l o a t n1 , n2 , media ; } * maria ;

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

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

10.6. PONTEIROS PARA ESTRUTURAS

179

arquiteturas lem sempre uma palavra inteira da memria. Usualmente, palae o vras podem ser compostas de dois bytes e comeam em endereos pares, como c c est mostrado na gura abaixo. Sabemos que existem variveis que ocupam a a mais de um byte, por exemplo inteiros que so compostos de dois bytes. a Imagine ento uma estrutura composta de um caracter (1 byte) e um n mero a u de inteiro (2 bytes). Caso a memria do computador seja organizada em palao vras de 16 bits ou 2 bytes a estrutura acima ocuparia 3 bytes ou uma palavra e meia. Para ler o n mero inteiro o programa deveria ler duas palavras. Lemu brar que se os dados fossem sempre armazenados sequencialmente, metade do n mero inteiro estaria em uma palavra e a metade restante na outra, como est u a indicado na gura abaixo (parte a). Para facilitar o acesso as variveis, alguns ` a compiladores armazenam as variveis de acordo com o que est indicado na a a gura (parte b). Observar que agora a estrutura ocupa quatro bytes. Neste caso o acesso ao n mero inteiro ser sempre feito em um passo e portanto ganhou-se u a em tempo de acesso ao custo de gasto de memria. Este uma troca constante o e em computaao. c Vimos ento que embora o total de bytes dos elementos da estrutura fosse a trs o compilador pode armazenar a estrutura em quatro bytes, da a necessidade e de sempre usar o operador sizeof quando alocar espao. c O programa 10.7 mostra como alocar espao para uma varivel simples e c a como usar esta varivel em diversos tipos de comandos. a

Listagem 10.7: Alocaao de espao para estruturas. c c


#include < stdio .h > #include < string .h > #include < stdlib .h > typedef s t r u c t _ALUNO { char nome [40]; f l o a t n1 , n2 , media ; } ALUNO ; i n t main ( void ) { ALUNO * maria ; maria = ( ALUNO *) malloc ( s i z e o f ( ALUNO )); i f (! maria ) exit (1); gets ( maria - > nome ); scanf ( " % f % f " , &( maria - > n1 ) , &( maria - > n2 )); maria - > media = ( maria - > n1 + maria - > n2 ) / 2; printf ( " A media de % s vale %0.2 f \ n " , maria - > nome , maria - > media ); return 0; }

180

CAP ITULO 10. ESTRUTURAS

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

10.7

Exerc cios

10.1: Considere que uma empresa precisa armazenar os seguintes dados de um cliente: Nome completo com no mximo 50 caracteres; a renda mensal do do cliente; ano de nascimento; possui ou no carro. a Dena um tipo e uma estrutura para armazenarem estes dados e escreva um programa que leia estes dados armazene-os em uma varivel e em seguida os a imprima. 10.2: Considerando a mesma estrutura do exerc anterior, escreva um procio grama que leia os dados de 100 clientes e imprima: quantos clientes tm renda mensal acima da mdia; e e quantos clientes tm carro; e quantos clientes nasceram entre 1960 (inclusive) e 1980 (exclusive). 10.3: Reescreva o programa 10.3 empregando funoes para implementar as c diversas tarefas do programa. A funao main deve car da maneira indicada na c Listagem 10.9. 10.4: Escrever um programa que utilize structs e ponteiro para struct e imprima o conteudo das variaveis da struct. 10.5: Escrever um programa que utilize enumeradores com as materias do seu periodo. Inicialize cada materia com um numero. Depois imprime os valores das variaveis enumeradas. 10.6: Escrever um programa que utilize union. Inicialize as variaveis com valores diferentes e imprima o conteudo delas.

10.7. EXERC ICIOS

181

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


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

182

CAP ITULO 10. ESTRUTURAS Listagem 10.9: Listagem do exercicio 3.

i n t main ( void ) { s t r u c t aluno turma [ MAX ]; le ( turma ); puts ( " Imprimindo dados lidos da turma . " ); puts ( " Digite qualquer coisa para continuar . " ); getchar (); imprime ( turma ); ordena_medias ( turma ); puts ( " Imprimindo dados ordenados da turma . " ); puts ( " Digite qualquer coisa para continuar . " ); getchar (); imprime ( turma ); getchar (); }

10.7: Fazer um programa que simule uma pilha push pop, usando structs. Um exemplo de entrada poderia ser o seguinte: empilha C empilha B empilha A desempilha A desempilha B desempilha C

10.8: Escreva um programa que solicite o nome e telefone de uma pessoa e grave essas informaoes num vetor de uma estrutura que contem esses dados (nome e c telefone). O programa deve ter trs opcoes apenas: uma que adiciona um novo e dado, outra que lista todos os dados atualmente armazenados na memria e o outra que sai do programa. Esse vetor de estrutura deve ter apenas 10 elementos e fornecer uma mensagem de erro caso o usurio tente adicionar mais pessoas a que este mximo permitido. a 10.9: Escreva uma estrutura similar as strings do Delphi (possuem um campo armazenando o tamanho da string e um ponteiro para o primeiro caracter da string) e crie as funces strcpy e strcat para strings nesse formato. o 10.10: Escreva um programa fazendo o uso de estruturas. Voc dever criar e a uma estrutura chamada Ponto, contendo apenas a posiao x e y (inteiros) do c ponto. Declare 2 pontos, leia a posiao (coordenadas x e y) de cada um e calcule c a distncia entre eles. Apresente no nal a distncia entre os dois pontos. a a

10.7. EXERC ICIOS

183

10.11: Crie uma estrutura chamada retangulo, que possua duas estruturas ponto (o ponto superior esquerdo e o ponto inferior direito). Faa um programa c que receba as informaoes acerca de um retngulo (as coordenadas dos dois c a pontos), e informe a rea, o comprimento da diagonal e o comprimento de cada a aresta 10.12: Escreva um programa que use as mesmas estruturas do exerc anterior cio para descobrir se um ponto est dentro de um retngulo. a a 10.13: Considere que foi denida a seguinte estrutura:
typedef s t r u c t _frac { i n t numerador , denominador ; } FRACAO ;

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

184

CAP ITULO 10. ESTRUTURAS

Cap tulo 11

Entrada e Sa por da Arquivos


11.1 Introduo ca

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

11.2

Fluxos de Dados

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

11.2.1

Fluxos de Texto

Um uxo de texto (text stream) composto por uma seqncia de caracteres, e ue que pode ou no ser dividida em linhas terminadas por um caractere de nal de a linha. Um detalhe que deve ser considerado ao escrever um programa que na e ultima linha no obrigatrio o caracter de m de linha. a e o 185

186

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

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

11.2.2

Fluxo Binrio a

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

11.2.3

Arquivos

Um arquivo pode estar associado ` qualquer dispositivo de entrada e sa a da como, por exemplo: impressora, teclado, disquete, disco r gido etc. No entanto, os programas vem os arquivos atravs de uxos. Para que um determinado e e arquivo em um perifrico seja associado a um uxo necessrio que o arquivo e e a seja aberto e somente aps esta operaao, o programa pode manipular os o c dados. Normalmente a interaao entre o programa e os arquivos feita por c e meio de buers que intermediam a transferncia dos dados entre os programas e

11.3. FUNCOES DE ENTRADA E SA IDA

187

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

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

32 bits 12

32 bits 113

8 bits 8 bits a b

Figura 11.1: Fluxos de dados.

e os perifricos. Isto serve para facilitar a operaao do sistema operacional. e c Operaoes comuns em arquivos so: c a abertura e fechamento de arquivos; remover um arquivo; leitura e escrita de um caracter ou byte; procurar saber se o m do arquivo foi atingido; posicionar o arquivo em um ponto determinado. Obviamente algumas dessas funoes no se aplicam a todos os tipos de disc a positivos. Por exemplo, para uma impressora pode no ser poss a vel usar a funao que reposiciona o arquivo no in c cio. Um arquivo em disco permite acesso aleatrio enquanto um teclado no. o a Ao nal das operaoes nos arquivos o programa deve fech-los. Caso o c a programador esquea de executar esta operaao, ao nal do programa todos os c c arquivos associados so fechados automaticamente e os conte dos dos buers a u so descarregados para o dispositivo externo. Caso o arquivo seja de entrada o a conte do do buer esvaziado. u e

11.3

Funes de Entrada e Sa co da

As funoes de Entrada e Sa normalmente utilizadas pelos programadores c da esto armazenadas na biblioteca stdio.h. As funoes mais comuns esto mosa c a tradas na tabela 11.1. Para ter acesso aos dados em um arquivo necessrio a deniao de um e a c ponteiro do tipo especial FILE. Este tipo tambm est denido na biblioteca e a

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

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS Descrio ca Abre um arquivo Escreve um caracter em um arquivo L um caracter de um arquivo e Equivalente a printf() Equivalente a scanf(). L de uma cadeia de caracteres e Equivalente a scanf() Posiciona o arquivo em um ponto espec co Posiona o arquivo no in cio Retorna verdade se chegou ao m do arquivo Verica a ocorrncia de um erro e Descarrega o buer associado ao arquivo Leitura de dados no modo binrio a Escrita de dados no modo binrio a

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

stdio.h. Um ponteiro deste tipo permite que o programa tenha acesso a uma

estrutura que armazena informaoes importantes sobre o arquivo. Para denir c uma varivel deste tipo o programa deve conter a seguinte declaraao a c
FILE *arq;

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

11.4

In cio e Fim

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

11.4.1

Abrindo um Arquivo

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

11.4. IN ICIO E FIM

189

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

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

190

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

11.4.2

Fechando um Arquivo

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

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

11.4.3

Fim de Arquivo

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

Um valor diferente de zero retornado no caso de ter sido atingido o nal e do arquivo. O valor zero indica que ainda no se chegou ao nal do arquivo. a O exemplo 11.1 mostra um programa que l um caractere do teclado e o e mostra na tela. Neste exemplo a leitura termina quando o usurio digita o a caracter <ctl>+D, que indica nal de arquivo pelo teclado em Unix (no outro sistema <ctl>+Z). e

11.4.4

Volta ao In cio

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

11.5. LENDO E ESCREVENDO CARACTERES Listagem 11.1: Uso da funao feof(). c


#include < stdio .h > i n t main ( void ) { char c ; c = getchar (); while ( c != EOF ) { putchar ( c ); c = getchar (); } return 0; }

191

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

11.5

Lendo e Escrevendo Caracteres

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

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

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

192

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS


int putc(int ch, FILE *parq); int fputc(int ch, FILE *parq)

onde parq um ponteiro de arquivo para o arquivo que foi previamente aberto e por meio da funao fopen() e ch o caracter a ser escrito. c e O programa 11.2 mostra como um arquivo pode ser criado para leitura e escrita. Em seguida um conjunto de caracteres lido do teclado escrito no are quivo. O prximo passo a leitura do arquivo que iniciada aps uma chamada o e e o a funao rewind(), fazendo com que o indicador de posiao do arquivo volte a c c apontar para seu in cio. Listagem 11.2: Exemplo de leitura e escrita de caracteres.
#include < stdio .h > #include < stdlib .h > i n t main ( void ) { int c; FILE * pa ; char * nome = " texto . txt " ; /* Abre o arquivo para leitura e escrita */ i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); exit (1); } /* Cada caracter digitado sera gravado no arquivo */ c = getchar (); while (! feof ( stdin )) { fputc (c , pa ); c = getchar (); } rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); c = fgetc ( pa ); while (! feof ( pa )) { putchar ( c ); c = fgetc ( pa ); } fclose ( pa ); return 0; }

11.6. TESTANDO ERROS

193

Uma outra alternativa mostrada em 11.3 mostra um exemplo onde o arquivo criado para escrita em seguida fechado e reaberto para leitura cando e e automaticamente posicionado no in para a leitura. cio Listagem 11.3: Exemplo de leitura e escrita de caracteres.
#include < stdio .h > i n t main ( void ) { int c; FILE * pa ; char * nome = " texto . txt " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nErro ao abrir o arquivo - escrita .\ n " ); return 1; } c = getchar (); while (! feof ( stdin )) { fputc (c , pa ); c = getchar (); } fclose ( pa ); printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); i f (( pa = fopen ( nome , " r " )) == NULL ) { printf ( " \ n \ nErro ao abrir o arquivo - leitura .\ n " ); exit (1); } c = fgetc ( pa ); while (! feof ( pa )) { putchar ( c ); c = fgetc ( pa ); } fclose ( pa ); return 0; }

11.6

Testando Erros

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

194

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

11.4 abre um arquivo para leitura, mas tenta escrever um caractere o que provoca um erro que testado pela funao ferror. e c Listagem 11.4: Uso da funao ferror(). c
#include < stdio .h > i n t main () { FILE * pArq ; pArq = fopen ( " MeusDados . txt " ," r " ); i f ( pArq == NULL ) { printf ( " Erro abrindo arquivo . " ); return 1; } else { fputc ( x , pArq ); i f ( ferror ( pArq )) { printf ( " Erro escrevendo arquivo \ n " ); fclose ( pArq ); return 1; } } return 0; }

11.7

Lendo e Escrevendo Cadeias de Caracteres

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

A funao fputs() escreve a cadeia de caracteres apontada por str no uxo c apontado por parq. O cdigo nulo ao nal da cadeia no copiado para o uxo. o a e O cdigo correspondente ` EOF ser retornado se ocorrer um erro e um valor no o a a a negativo em caso de sucesso. A funao fgets() l uma cadeia de caracteres do uxo especicado por parq c e at que um caracter de nova linha seja encontrado ou comp-1 caracteres sejam e lidos. O caractere de nova linha interrompe a leitura. Observar que diferentemente de gets() o caracter de nova linha encontrado passa a fazer parte da

11.8. ENTRADA E SA IDA FORMATADA

195

cadeia que recebe um caracter nulo ao seu nal. O ponteiro str retornado caso e a leitura ocorra sem erro. No caso de erro o ponteiro str recebe o valor NULL. Se o m do arquivo for encontrado e nenhum caractere foi lido, o conte do de u str mantido e um NULL retornado. O exemplo 11.5 mostra um exemplo de e e uso destas funoes para ler e escrever cadeias de caracteres em um arquivo. c Listagem 11.5: Exemplo de leitura e escrita de cadeias de caracteres.
#include < stdio .h > #define MAX 80 i n t main ( void ) { char linha [ MAX ]; FILE * pa ; char * nome = " texto . txt " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); return 1; } fgets ( linha , MAX , stdin ); while (! feof ( stdin )) { fputs ( linha , pa ); fgets ( linha , MAX , stdin ); } rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n \ n " ); fgets ( linha , MAX , pa ); while (! feof ( pa )) { puts ( linha ); fgets ( linha , MAX , pa ); } fclose ( pa ); return 0; }

11.8

Entrada e Sa Formatada da

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

196

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

onde parq um ponteiro de arquivo recebido aps uma chamada a fopen(). e o Em leituras, a funao retorna o n mero de itens lidos com sucesso. Esta c u contagem pode igualar o n mero esperado de leituras ou ser menor no caso u de falha. Caso ocorra uma falha antes de que uma leitura possa ser feita com sucesso, EOF retornado. e Em escritas, caso a operaao de escrita tenha sucesso, o n mero total de c u caracteres escrito retornado. Um n mero negativo retornado em caso de e u e falha. Embora estas duas funoes, por sua semelhana com printf() e scanf(), c c sejam maneiras convenientes de escrever e ler dados de arquivos, elas tm a e desvantagem de serem mais lentas do que uso de arquivos binrios. A perda a de tempo devido ao fato dos dados serem gravados em ASCII, o que obriga e a uma converso dos dados a cada operaao realizada. Em alguns casos o fato a c dos dados serem gravados em ASCII pode ser considerado um vantagem que se sobrepe a desvantagem da reduao de velocidade. Dados gravados em ASCII o c podem ser facilmente vericados pelos usurios, o que no acontece com dados a a em binrio. O exemplo 11.6 mostra o uso destas funoes para ler e escrever a c vrios tipos de dados em um arquivo. a Listagem 11.6: Exemplo de leitura e escrita de dados formatados.
#include < stdio .h > i n t main ( void ) { char palavra [20]; int i; fl oat f; FILE * pa ; char * nome = " format . txt " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { printf ( " \ n \ nNao foi possivel abrir o arquivo .\ n " ); return 1; } puts ( " Entre com uma palavra . " ); scanf ( " % s " , palavra ); puts ( " Entre com um numero inteiro . " ); scanf ( " % d " , & i ); puts ( " Entre com um numero flutuante . " ); scanf ( " % f " , & f ); /* Escreve os dados no arquivo */ fprintf ( pa , " % s % d % f " , palavra , i , f ); rewind ( pa ); /* volta ao inicio do arquivo */ printf ( " \ nTerminei de escrever , agora vou ler .\ n " ); fscanf ( pa , " % s % d % f " , palavra , &i , & f ); printf ( " Palavra lida : % s \ n " , palavra ); printf ( " Inteiro lido : % d \ n " , i ); printf ( " Float lido : % f \ n " , f ); fclose ( pa ); return 0; }

11.9. LENDO E ESCREVENDO ARQUIVOS BINARIOS

197

11.9

Lendo e Escrevendo Arquivos Binrios a

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

A funao fread l nmemb objetos, cada um com size bytes de comprimento, c e do uxo apontado por stream e os coloca na localizaao apontada por ptr. A c funao retorna o n mero de itens que foram lidos com sucesso. Caso ocorra um c u erro, ou o m do arquivo foi atingido o valor de retorno menor do que nmemb e ou zero. Esta funao no distingue entre um m de arquivo e erro, portanto c a e aconselhvel o uso de feof() ou ferror() para determinar que erro ocorreu. a A funao fwrite escreve nmemb elementos de dados, cada um com size bytes c de comprimento, para o uxo apontado por stream obtendo-os da localizaao c apontada por ptr. fwrite retorna o n mero de itens que foram lidos com sucesso. u Caso ocorra um erro, ou o m do arquivo foi atingido o valor de retorno menor e do que nmemb ou zero. O programa 11.7 ilustra como podemos escrever e ler dados binrios de diferentes tipos em arquivos. Como um dos parmetros da a a funao o n mero de bytes do dado a ser lido, recomendado o uso de sizeof. c e u e Listagem 11.7: Exemplo de leitura e escrita na forma binria. a
#include < stdio .h > i n t main ( void ) { i n t inum =10; f l o a t fnum =2.5; double pi =3.141516; char c = Z ; FILE * pa ; char * nome = " texto . bin " ; i f (( pa = fopen ( nome , " w + " )) == NULL ) { perror ( " fopen : " ); return 1; } fwrite (& inum , s i z e o f ( i n t ) , 1 , pa ); fwrite (& fnum , s i z e o f ( f l o a t ) , 1 , pa ); fwrite (& pi , s i z e o f ( double) , 1 , pa ); fwrite (& c , s i z e o f ( char ) , 1 , pa ); rewind ( pa ); fread (& inum , s i z e o f ( i n t ) , 1 , pa ); fread (& fnum , s i z e o f ( f l o a t ) , 1 , pa ); fread (& pi , s i z e o f ( double) , 1 , pa ); fread (& c , s i z e o f ( char ) , 1 , pa ); printf ( " %d , %f , %f , % c \ n " , inum , fnum , pi , c ); fclose ( pa ); return 0; }

198

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

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

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

11.10

Exerc cios

11.1: Escreva um programa que abra um arquivo texto e conte o n mero de u caracteres presentes nele. Imprima o n mero de caracteres na tela. u 11.2: Considere um arquivo de dados do tipo texto com o seguinte conte do: u 3 ZE SA 8.5 10.0 ANTONIO SANTOS 7.5 8.5 SEBASTIAO OLIVEIRA 5.0 6.0 O arquivo acima um exemplo. Considere ento que nestes arquivos a e a primeira linha contm o n mero de alunos no arquivo. As linhas seguintes e u contm os seguintes dados: e nome do aluno com no mximo 50 caracteres; a nota da primeira prova; nota da segunda prova. Escreva um programa que imprima os nomes de todos os alunos que tm a mdia e e das duas notas menor que 7.0 11.3: Escreva um programa que grave os dados lidos no exerc anterior em cio um arquivo do tipo binrio de acesso aleatrio. O n mero que indica quantos a o u

11.10. EXERC ICIOS Listagem 11.8: Exemplo de leitura e escrita de estruturas.


#include < stdio .h > #include < string .h > typedef s t r u c t _PESSOA { char nome [40]; i n t ano ; } PESSOA ;

199

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

200

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

alunos devem ser lidos (primeira linha do arquivo) no deve ser gravado no a arquivo binrio. Nesta questo o programa deve obrigatoriamente usar um a a vetor de estruturas do seguinte tipo:
typedef s t r u c t _ALUNO { char nome [81]; f l o a t n1 , n2 ; } ALUNO ;

11.4: Escreva um programa que leia de um arquivo, cujo nome sera fornecido pelo usurio, um conjunto de n meros reais e armazena em um vetor. O tamaa u nho mximo do vetor e dado pela constante TAM_MAX. A quantidade de n meros a u no arquivo varia entre 0 e TAM_MAX. O programa ao nal calcula a media dos n meros lidos. u 11.5: Faa um programa que leia 10 caracteres e armazene em um arquivo 10 c cpias de cada um. Exiba o conte do o u 11.6: Crie uma funao que receba duas strings como parmetros, uma com um c a endereo de arquivo e outra com um texto qualquer, e adicione o texto no m c do arquivo. 11.7: Utilizando a funao do exerc anterior faa um programa que gere 10 c cio c arquivos com o nome Testee extenses 01, ..., 10. Cada um contendo o o texto Texto do arquivo [NUMERO DO ARQUIVO]. 11.8: Escreva um programa para armazenar o telefone de 5 amigos. O programa deve obrigatoriamente usar a estrutura
typedef s t r u c t _PESSOA { char nome [50]; i n t idade ; f l o a t altura ; char telefone [10]; } PESSOA ;

a ser preenchida pelo usurio antes do armazenamento de cada registro. a 11.9: Faa um programa que leia os dados do arquivo gerado no exerc c cio anterior e salve-os num novo arquivo utilizando uma sa formatada como da indicado abaixo. FORMATO: [nome] tem [idade] anos e [altura] de altura Tel.: [telefone] 11.10: Escreva um programa que leia um arquivo texto contendo linhas de dados. Em cada linha do arquivo h o nome de um aluno e duas notas. Estes a

11.10. EXERC ICIOS

201

dados esto separados por ponto e v a rgula. Existe um ponto e v rgula ao nal de cada linha. O formato dos dados e o seguinte: ze sa; 10.0; 9.0; antonio silva: 9.0; 7.0; O programa deve ler estes dados e imprimir os valores lidos, a mdia das e duas notas e se o aluno foi aprovado ou no (media 5). O formato de saida : a e ze sa 10.0 8.0 9.0 aprovado antonio silva 9.0 7.0 8.0 aprovado 11.11: Faa um programa que receba o nome de um arquivo e gere uma cpia. c o 11.12: Escreva um programa que compare dois arquivos especicados pelo usurio e imprima sempre que os caracteres dos dois arquivos coincidirem. Por a exemplo: arquivo1.c Ol, pessoal! a arquivo2.c Oi, como vai? Neste caso, os caracteres na primeira e dcima primeira posiao so iguais e c a nos dois arquivos. A sa do seu programa deve ser algo como: da 1 - O 11 - a indicando que os primeiros caracteres dos arquivos so iguais (O) bem como o a dcimo primeiro (a) e

202

CAP ITULO 11. ENTRADA E SA IDA POR ARQUIVOS

Apndice A e

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

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

Tabela A.1: Conjunto de caracteres ASCII Os caracteres de controle listados acima, servem para comunicaao com pec rifricos e controlar a troca de dados entre computadores. Eles tm o signicado e e mostrado na Tabela A.2. 203

204

APENDICE A. TABELA ASCII

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

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

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

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

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

Apndice B e

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

206

APENDICE B. PALAVRAS RESERVADAS

else: Comando que indica um bloco de comandos alternativo que deve ser executado quando a condiao testada pelo comando if foi avaliada como c FALSA. enum: Tipo denido pelo usurio que permite a deniao de variveis que iro a c a a aceitar somente certos valores. extern: Modicador de dados que indica que uma varivel ir ser declarada a a em outra rea do programa. a oat: Tipo usado para armazenar valores de ponto utuante. for: Comando de repetiao que contm inicializaao de variveis, incremento e c e c a seoes condicionais. Em C o comando for um comando de repetiao c e c extremamente ex vel, permitindo in meras possibilidades. u goto: Comando que causa um pulo para uma posiao do programa marcada c com um rtulo. o if: Comando de testes usado para mudar o uxo do programa baseada em uma deciso VERDADE/FALSO. a int: Tipo de dados usado para armazenar valores inteiros. long: Tipo de dados usado para armazenar valores inteiros com preciso maior a do que o tipo int. Nos computadores modernos o tipo long tem a mesma preciso que o tipo int e so usados 4 bytes. a a register: Especicador de classe de armazenamento que pede que, caso seja poss vel, uma varivel deve ser armazenada nos registradores do procesa sador. return: Comando que causa o uxo de instruoes do programa abandonar a c funao em execuao e retornar para a funao que chamou. Tambm pode c c c e ser usado para retornar um unico valor. short: Tipo de dados usado para armazenar valores inteiros em preciso menor a do que o tipo int. Neste tipo 2 bytes so usados para armazenar os dados. a signed: Modicador usado para indicar que uma varivel pode armazenar tanto a valores positivos como negativos. sizeof: Operador que retorna o tamanho em bytes do item fornecido. static: Modicador usado para signicar que o compilador deve preparar o cdigo de forma a reter o valor da varivel. o a struct: Usado para combinar C variveis de tipos diferentes na mesma estrua tura.

207 switch: Comando de desvio usado para permitir que o uxo do programa possa ser mudado para vrias direoes diferentes. Usado em conjunto com o a c comando case. typedef: Modicador usado para criar novos nomes para tipos j existentes. a union: Palavra chave usada para permitir m ltiplas variveis partilharem o u a mesmo espao na memria. c o unsigned: Modicador usado para signicar que uma varivel conter somente a a valores positivos. void: Palavra usada para signicar que ou a funao no retorna nada ou que c a um ponteiro deve ser considerado genrico ou ser capaz de apontar para e qualquer tipo de dados. volatile: Modicador que signica que uma varivel pode ser alterada. a while: Comando de teste que executa uma seao de cdigo enquanto uma c o condiao retorna VERDADE. c Em adiao a estas as seguintes palavras so reservadas em C++: c a catch, inline, template, class, new, this, delete, operator, throw, except, private, try, finally, protected, virtual, friend, public. Caso queira escrever programas que possam ser convertidas para a linguagem C++ aconselhvel no us-las. e a a a

208

APENDICE B. PALAVRAS RESERVADAS

Bibliograa

209

Indice
abertura de arquivo, 186 algoritmo, 34 arquivo, 186 abrir arquivo, 188 fechar arquivo, 190 assembler, 35 assembly, 34 base 2, 32 BIOS, 31 bit, 32 byte, 32 chipset, 29 circuitos integrados, 27 compiladores, 36 EEPROM, 31 endereos de memria, 31 c o nal de linha, 186 Flash memory, 32 uxo de dados, 185 uxo binrio, 186 a uxo de texto, 185 gcc, 38 hardware, 27 linguagem de alto n vel, 35 linguagem de mquina, 34 a memria, 30 o memria cache, 30 o microcomputadores, 29 microprocessador, 29 MINGW, 39 210 Moore, 20 palavra de memria, 32 o perifricos, 29, 33 e pipelining, 28 RAM, 31 registradores, 30 ROM, 31 sistema operacional, 38 software, 33 text stream, 185 Unidade Central de Processamento, 27 Unidade de Controle, 28 Unidade de Entrada e Sa da, 28 Unidade Lgica e Aritmtica, 28 o e VLSI, 27

Vous aimerez peut-être aussi