Buscar

Pré-texto.Livro programação C.FlávioVarejão

Prévia do material em texto

Suma´rio
1 Introduc¸a˜o 6
1.1 Histo´rico . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.2 Arquitetura de Computadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.1 Memo´ria . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.2.2 Processador . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
1.3 Algoritmos e Programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
1.4 Te´cnica de Desenvolvimento de Programas . . . . . . . . . . . . . . . . . . . . . 11
1.5 Partes de um Programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
1.6 Traduc¸a˜o de Programas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.6.1 Compilac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.6.2 Interpretac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
1.7 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
1.8 Exerc´ıcios Propostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
2 Conceitos Ba´sicos 18
2.1 Varia´veis e Ce´lulas de Memo´ria . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
2.2 Identificadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
2.3 Comando de Atribuic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
2.4 Tipos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.1 Declarac¸a˜o de Varia´veis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
2.4.2 Tipo Inteiro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
2.4.3 Tipo Ponto Flutuante . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
2.4.4 Tipo Booleano . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4.5 Tipo Caractere . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
2.4.6 Conversa˜o de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
2.5 Constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
2.6 Expresso˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.6.1 Expresso˜es Aritme´ticas . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
2.6.2 Expresso˜es Relacionais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.6.3 Expresso˜es Lo´gicas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
2.7 Comando de Entrada de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
1
2 SUMA´RIO
2.8 Comando de Sa´ıda de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
2.9 Comandos de Selec¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.9.1 Comando de selec¸a˜o simples . . . . . . . . . . . . . . . . . . . . . . . . . . 39
2.9.2 Comando de selec¸a˜o dupla . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
2.9.3 Comando de selec¸a˜o mu´ltipla . . . . . . . . . . . . . . . . . . . . . . . . . 46
2.10 Comandos de Repetic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
2.10.1 Comando de repetic¸a˜o com pre´-condic¸a˜o . . . . . . . . . . . . . . . . . . . 49
2.10.2 Comando de repetic¸a˜o com po´s-condic¸a˜o . . . . . . . . . . . . . . . . . . . 52
2.10.3 Comando de repetic¸a˜o condensado . . . . . . . . . . . . . . . . . . . . . . 55
2.11 Problema dos Lotes Encaixantes . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
2.12 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
2.13 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.14 Exerc´ıcios Propostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3 Modularizac¸a˜o 70
3.1 Introduc¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
3.2 Subprogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
3.3 Partes de um Subprograma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3.1 Cabec¸alho . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
3.3.2 Diciona´rio de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
3.3.3 Corpo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
3.3.4 Comenta´rios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.4 Chamada de subprogramas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
3.5 Passagem de paraˆmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
3.6 Retorno de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
3.6.1 Encerramento antecipado de execuc¸a˜o . . . . . . . . . . . . . . . . . . . . 84
3.7 Func¸o˜es sem lista de paraˆmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
3.8 Func¸o˜es sem retorno de dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
3.9 Recursividade . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
3.9.1 Implementac¸a˜o na˜o recursiva equivalente . . . . . . . . . . . . . . . . . . 90
3.10 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
3.11 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
3.12 Exerc´ıcios Propostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
3.13 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4 Tipos Abstratos de Dados 109
4.1 Te´cnicas de Programac¸a˜o Top-down e Bottom-up . . . . . . . . . . . . . . . . . . 109
4.2 Tipos Compostos Heterogeˆneos (Estruturas) . . . . . . . . . . . . . . . . . . . . . 110
4.2.1 Definic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.2.2 Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
4.3 Tipos Abstratos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
4.3.1 Definic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
SUMA´RIO 3
4.3.2 Definic¸a˜o de Atributos de um TAD . . . . . . . . . . . . . . . . . . . . . . 120
4.3.3 Definic¸a˜o de Operac¸o˜es de um TAD . . . . . . . . . . . . . . . . . . . . . 120
4.3.4 Uso do TAD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
4.3.5 Tipos de TADs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
4.4 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
4.5 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
4.6 Lista de Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
4.7 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
5 Vetores 135
5.1 Vetores e sua importaˆncia . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
5.2 Representac¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.3 Definic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.3.1 Definic¸a˜o do Tamanho do Vetor . . . . . . . . . . . . . . . . . . . . . . . . 139
5.4 Operac¸o˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
5.4.1 Acesso indevido . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
5.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 144
5.6 TAD Implementacional . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
5.6.1 Atributos . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . 147
5.6.2 Operac¸o˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
5.7 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
5.8 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
5.9 Lista de Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
5.10 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
6 Matrizes 164
6.1 Introduc¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
6.2 Definic¸a˜o e Acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
6.2.1 Definic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
6.2.2 Acesso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
6.3 O TAD implementacional tMatriz . . . . . . . . . . . . . . . . . . . . . . . . . . 168
6.3.1 Atributos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
6.3.2 Operac¸o˜es . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
6.4 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
6.5 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.6 Exerc´ıcios Propostos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.7 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.8 To´picos Avanc¸ados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
4 SUMA´RIO
7 Apontadores 187
7.1 Varia´veis Apontadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187
7.2 A Sintaxe dos Apontadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
7.2.1 Operador Enderec¸o de Memo´ria . . . . . . . . . . . . . . . . . . . . . . . 190
7.2.2 O Operador Seta . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
7.3 Acesso a` Varia´vel por Meio de Apontadores . . . . . . . . . . . . . . . . . . . . . 191
7.4 Uso de Apontadores nas Passagens de Paraˆmetros . . . . . . . . . . . . . . . . . 192
7.5 Alocac¸a˜o Dinaˆmica de Memo´ria . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
7.6 Problemas Gerados por Apontadores . . . . . . . . . . . . . . . . . . . . . . . . . 198
7.6.1 Apontadores Na˜o Inicializados . . . . . . . . . . . . . . . . . . . . . . . . 198
7.6.2 Objetos Pendentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
7.6.3 Refereˆncia Pendente . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
7.6.4 Programac¸a˜o Macarroˆnica . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
7.7 TAD Implementacional Lista Encadeada tLista . . . . . . . . . . . . . . . . . . . 200
7.7.1 Definic¸a˜o do Tipo tNo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
7.7.2 Atributos de tLista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
7.7.3 Operac¸o˜es de tLista . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
7.7.4 Uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211
7.8 Exerc´ıcios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
7.9 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223
7.10 Lista de Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
7.11 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
8 Arquivos 235
8.1 Varia´veis Transientes X Varia´veis Persistentes . . . . . . . . . . . . . . . . . . . . 235
8.2 Tipos de Arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
8.2.1 Tipos de Arquivos - Arquivos Texto . . . . . . . . . . . . . . . . . . . . . 236
8.2.2 Tipos de Arquivos - Arquivos Bina´rios . . . . . . . . . . . . . . . . . . . . 237
8.3 Definic¸a˜o de arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
8.4 Operac¸a˜o sobre arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
8.4.1 Abertura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
8.4.2 Fechamento . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 240
8.5 Operac¸o˜es sobre arquivos texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
8.5.1 Leitura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 241
8.5.2 Escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
8.6 Operac¸o˜es sobre arquivos bina´rios . . . . . . . . . . . . . . . . . . . . . . . . . . 244
8.6.1 Leitura . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244
8.6.2 Escrita . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
8.7 Outras func¸o˜es u´teis para arquivos . . . . . . . . . . . . . . . . . . . . . . . . . . 246
8.7.1 feof() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
8.7.2 fseek() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249
8.8 Exercicios Resolvidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 250
SUMA´RIO 5
8.8.1 O Tipo Abstrato de Dados TDicionario . . . . . . . . . . . . . . . . . . . 250
8.9 Resumo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
8.10 Exerc´ıcios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257
8.11 Trabalhos Sugeridos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 260
Cap´ıtulo 1
Introduc¸a˜o
Co-autor:
Andre´ Boechat
Objetivos:
• Apresentar um breve histo´rico da Computac¸a˜o;
• Apresentar noc¸o˜es sobre arquitetura de computadores, como funcionam o processador e a
memo´ria;
• Definir o que sa˜o algoritmos e programas, ale´m de apresentar algumas te´cnicas para de-
senvolveˆ-los;
• Definir as partes de um programa e a importaˆncia da documentac¸a˜o;
• Introduzir o conceito de traduc¸a˜o de programas.
Basicamente, pode-se considerar a programac¸a˜o de computadores como a forma que se da´
o relacionamento entre a ma´quina e o homem. Para programar de forma correta e eficiente,
muitas vezes na˜o basta conhecer apenas os comandos de determinadas operac¸o˜es, e´ necessa´rio
saber como a ma´quina, um ser na˜o pensante, faz para compreender e executa´-los. Assim, este
cap´ıtulo visa apresentar alguns conceitos fundamentais para o entendimento da programac¸a˜o,
desenvolvidos juntamente com a a´rea mais recente da cieˆncia, a Computac¸a˜o.
1.1 Histo´rico
Dado o alto grau tecnolo´gico dos computadores atuais, pode ser dif´ıcil imaginar que os primeiros
computadores eram totalmente mecaˆnicos. Diversos tipos foram projetados e constru´ıdos ao
longo da evoluc¸a˜o, chegando aos modernos computadores digitais; pore´m, alguns se destacam
pela inovac¸a˜o e complexidade que marcaram suas e´pocas.
6
1.1. HISTO´RICO 7
A primeira ma´quina programa´vel que se tem not´ıcia foi constru´ıda pelo professor de ma-
tema´tica da Universidade de Cambridge, Charles Babbage (1792-1871). A “ma´quina anal´ıtica”,
como ficou conhecida, era totalmente mecaˆnica, composta basicamente por engrenagens que
formavam quatro componentes: a memo´ria, a unidade de ca´lculo ou computac¸a˜o, a unidade
de entrada e a de sa´ıda. A unidade de computac¸a˜o recebia operandos da memo´ria para reali-
zar sobre eles as operac¸o˜es de soma, subtrac¸a˜o, multiplicac¸a˜o ou divisa˜o, e depois armazenar o
resultado na memo´ria.
Como a ma´quina anal´ıtica executava as instruc¸o˜es lidas pela unidade de entrada, era poss´ıvel
executar diferentes sequ¨eˆncias de ca´lculos, bastandopara isso que um programa diferente fosse
utilizado. Assim, a primeira pessoa no mundo a programar um computador foi a jovem Ada
Augusta Lovelace, contratada pelo pro´prio Babbage a fim de produzir o software necessa´rio para
o funcionamento da ma´quina.
A procura por ma´quinas calculadoras cresceu com a Segunda Guerra Mundial, estimulando
o surgimento dos primeiros computadores eletroˆnicos. O professor de f´ısica da Universidade da
Pensilvaˆnia, John Mauchley, junto com seu aluno de mestrado, J. Presper Eckert, construiu
um computador chamado ENIAC (Electronic Numerical Integrator And Computer)[2], o qual
detinava-se ao coˆmputo de trajeto´rias ta´ticas que exigissem conhecimento substancial em ma-
tema´tica. O ENIAC tinha 18.000 va´lvulas e 1.500 rele´s, pesava 30 toneladas e consumia 140
quilowatts de energia ele´trica. Para programar o ENIAC, era necessa´rio ajustar a posic¸a˜o de
6.000 chaves de va´rias posic¸o˜es e conectar um nu´mero imenso de soquetes por meio de uma ver-
dadeira floresta de cabos. Este gigantesco computador so´ ficou pronto em 1946, apo´s o te´rmino
da guerra.
Um dos pesquisadores envolvidos no projeto do ENIAC, John von Neumann, construiu para
o Instituto de Estudos Avanc¸ado de Princeton (Princeton Institute of Advanced Studies — IAS )
a ma´quina IAS[3], a qual ainda e´ a base de praticamente todas as ma´quina atuais. Ele imaginou
que os programas poderiam ser representados em formato digital na memo´ria, junto com os
dados.
A invenc¸a˜o do trans´ıstor e o desenvolvimento de circuitos integrados revolucionaram os pro-
jetos de computadores do final da de´cada de 1950, tornando obsoletos os computadores valvula-
dos. Nas de´cadas de 1960 e 1970, as famı´lias de computadores da IBM1 (International Business
Machines), System/360, e da DEC2 (Digital Equipament Corporation), PDP-11, dominavam o
mercado.
Nesse per´ıodo surgiu uma das linguagens de programac¸a˜o mais usadas para o desenvolvi-
mento de softwares e tambe´m adotada neste livro, a linguagem C[1]. Ela e´, ainda hoje, muito uti-
lizada para a criac¸a˜o de programas diversos, como processadores de texto, planilhas eletroˆnicas,
programas para a soluc¸a˜o de problemas de engenharia, e muitos outros.
Diversos fatores, como a criac¸a˜o de linguagens de programac¸a˜o mais semelhantes a` linguagem
humana3, o que facilitava a vida dos programadores, e a integrac¸a˜o de circuitos em escala muito
alta, o que aumentou o desempenho e diminu´ıu o tamanho das ma´quinas, deram in´ıcio a era
1http://www.ibm.com
2http://www.hp.com
3Essas linguagens sa˜o chamadas de “linguagens de alto n´ıvel”
8 CAPI´TULO 1. INTRODUC¸A˜O
dos computadores pessoais. E foi nesse contexto, na de´cada de 80, que a IBM construiu o
computador mais vendido de toda a histo´ria, o Personal Computer — o famoso PC.
O processador utilizado no PC foi constru´ıdo por uma promissora empresa da e´poca, a Intel4.
E a versa˜o inicial desse computador vinha com o sistema operacional MS-DOS fornecido por
outra empresa, a rece´m-criada Microsoft Corporation.
1.2 Arquitetura de Computadores
Para conhecer um pouco mais sobre o funcionamento dos computadores, e´ apresentada nesta
Sec¸a˜o uma noc¸a˜o ba´sica sobre processadores e memo´rias.
1.2.1 Memo´ria
A memo´ria e´ a parte do computador onde as operac¸o˜es a serem executadas pelo computador
(instruc¸o˜es) e as informac¸o˜es a serem processadas pelo mesmo (dados) sa˜o armazenados.
Na memo´ria, o processador leˆ e escreve informac¸o˜es ao executar as instruc¸o˜es de um pro-
grama. Existem dois tipos de memo´ria: a memo´ria principal e a secunda´ria. A principal,
conhecida tambe´m como RAM (Random Access Memory), possui as seguintes caracter´ısticas:
• Armazena dados e instruc¸o˜es do programa em execuc¸a˜o;
• Proporciona ao computador acesso ra´pido aos dados e instruc¸o˜es armazenados por ela;
• So´ mantem as informac¸o˜es armazenadas enquanto o computador estiver ligado.
A memo´ria secunda´ria geralmente possui maior capacidade de armazenamento de dados e
instruc¸o˜es, pore´m o tempo necessa´rio para acessa´-los e´ bem maior quando comparado ao da
memo´ria principal. As informac¸o˜es permanecem armazenadas mesmo apo´s o desligamento do
computador. Discos r´ıgidos e CD-ROMs sa˜o exemplos de memo´rias secunda´rias.
A unidade ba´sica da memo´ria e´ o digito bina´rio, conhecido como “bit”. Um bit pode assumir
apenas dois valores, normalmente 0 ou 1.
A memo´ria e´ formada por um conjunto de ce´lulas, ou posic¸o˜es, sendo que cada uma pode
guardar uma informac¸a˜o e possui um nu´mero de reconhecimento, conhecido como “enderec¸o
de memo´ria”. E´ por meio desse nu´mero de enderec¸o que os programas podem acessar uma
determinada ce´lula. Se uma ce´lula possuir k bits, ela podera´ armazenar qualquer uma das 2k
combinac¸o˜es poss´ıveis para os bits. A Figura 1.1 mostra um exemplo de memo´ria com seis
ce´lulas enderec¸a´veis, onde cada ce´lula possui dezesseis bits.
1.2.2 Processador
O processador e´ o “ce´rebro” do computador. Basicamente, o processador e´ responsa´vel por
buscar instruc¸o˜es na memo´ria, decodifica´-las para determinar seus operandos (dados que sera˜o
4http://www.intel.com
1.3. ALGORITMOS E PROGRAMAS 9
Figura 1.1: Exemplo de uma memo´ria de 16 bits e 6 enderec¸os.
usados ao processar a instruc¸a˜o) e quais operac¸o˜es devem ser realizadas com os mesmos, e
executar tais operac¸o˜es. Essas tarefas compo˜em o processo de execuc¸a˜o de um programa.
1.3 Algoritmos e Programas
Apesar do nome pouco comum, diversos algoritmos sa˜o executados por pessoas comuns todos os
dias. Ao escovar os dentes, fazer um bolo ou trocar o pneu de um carro, diversos procedimentos
sa˜o feitos em sequ¨eˆncia, seguindo, muitas vezes, uma certa ordem lo´gica.
Para exemplificar a execuc¸a˜o de um algoritmo, descreve-se a seguir alguns passos necessa´rios
para fazer algo simples, cotidiano, como o ato de escovar os dentes.
1. Pegar a escova e a pasta de dentes;
2. Colocar um pouco de pasta sobre as cerdas da escova;
3. Escovar os dentes do maxilar inferior;
4. Escovar os dentes do maxilar superior;
5. Expelir da boca o excesso de espuma;
6. Bochechar um pouco de a´gua;
7. Lavar a escova e guarda´-la;
8. Enxugar o rosto.
Apo´s conhecer um exemplo comum de algoritmo, torna-se mais fa´cil compreender a sua definic¸a˜o:
Algoritmo e´ uma sequ¨eˆncia de operac¸o˜es que deve ser executada em uma
ordem definida e na˜o-amb´ıgua, com o propo´sito de solucionar um deter-
minado problema.
10 CAPI´TULO 1. INTRODUC¸A˜O
Apesar de conseguirem executar operac¸o˜es muito complexas, os computadores na˜o sa˜o do-
tados da mesma capacidade de compreensa˜o que os humanos. Uma sequ¨eˆncia de tarefas consi-
derada simples e o´bvia para uma pessoa qualquer pode ser incompreens´ıvel e pouco detalhada
para um computador.
Voltando ao exemplo da escovac¸a˜o, um computador poderia considera´-lo incompleto, pois
ha´ diversas questo˜es sobre como algum passo pode ser executado, por exemplo:
1. Onde esta´ a escova a ser usada?
2. Quanto, exatamente, se deve colocar de pasta sobre as cerdas?
3. O que fazer se na˜o houver pasta? Escovar mesmo sem a pasta ou interromper o processo
de escovac¸a˜o?
Questo˜es como essas sa˜o facilmente contornadas por um humano, decididas instantaˆneamente
de acordo com o ambiente que o cerca. Enta˜o, para que uma ma´quina tambe´m possa “decidir”
o que fazer em situac¸o˜es semelhantes, e´ necessa´rio que se estabelec¸am as condic¸o˜es iniciais
(condic¸o˜es de entrada) e as finais (condic¸o˜es de sa´ıda) do problema. Dessa forma, ela sabera´
quais ferramentas podera˜o ser usadas para atingir a condic¸a˜o de sa´ıda desejada.
Assim, o problema da escovac¸a˜o seria mais bem definido da seguinte maneira:
Condic¸o˜es de Entrada: Dentes sujos com restos de alimentos, uma escova dental em condic¸o˜es
de uso, 90 gramas de creme dental e 300 mililitrosde a´gua tratada.
Condic¸o˜es de Sa´ıda: Dentes limpos (sem restos de alimentos vis´ıveis), uma escova dental em
condic¸o˜es de uso e 85 gramas de creme dental. Toda a quantidade de a´gua deve ser
utilizada.
Portanto, para um computador, os algoritmos definem o conjunto de atividades que ele deve
desempenhar para solucionar um problema.
Contudo, ta˜o importante quanto saber “o que” escrever para a ma´quina e´ saber “como”
escrever. Para que um computador possa executar um algoritmo, e´ necessa´rio que esse algoritmo
seja traduzido para uma linguagem de programac¸a˜o, geralmente incompreens´ıvel para a maioria
das pessoas. Ao se traduzir um algoritmo para uma linguagem de programac¸a˜o, obte´m-se um
programa.
“Embora os computadores modernos sejam capazes de executar operac¸o˜es dif´ıceis e
complexas, eles sa˜o ma´quinas do´ceis e de uma inteligeˆncia restrita. Eles devem ser
ensinados exatamente o que fazer, e as instruc¸o˜es devem ser feitas em uma linguagem
simples, precisa e limitada que eles possam compreender. Estas instruc¸o˜es sa˜o mais
conhecidas como programa” (Darmell,1988).
1.4. TE´CNICA DE DESENVOLVIMENTO DE PROGRAMAS 11
1.4 Te´cnica de Desenvolvimento de Programas
Na maioria das vezes, o ato de programar na˜o e´ uma tarefa simples e fa´cil. A sintaxe das
linguagens de programac¸a˜o e´ bem r´ıgida e deve ser respeitada fielmente para que o computador a
compreenda. Esquecer de um “;” no lugar onde e´ necessa´rio, por exemplo, significa comprometer
a execuc¸a˜o de todo o programa (na verdade, o computador pode nem comec¸ar a executa´-lo). Ou
pior, um programa teoricamente correto, que na˜o apresente erros de sintaxe, pode fornecer um
resultado incorreto. Encontrar o erro torna-se um enorme problema a` medida que o programa
cresce em tamanho e complexidade.
Para contornar a complexidade dos programas, os construtores de software costumam fazer
uso de uma poderosa te´cnica de programac¸a˜o, conhecida como “te´cnica dos refinamentos suces-
sivos”5. Ela consiste basicamente em dividir um processo complexo em processos-componentes
menores, especificando apenas a entrada e a sa´ıda de cada um deles. E se, mesmo assim,
alguns processos menores continuarem complexos, repete-se a divisa˜o no interior dos processos-
componentes, gerando processos cada vez mais simplificados.
Ale´m de facilitar a depurac¸a˜o de erros, essa te´cnica pode tornar um complexo programa em
uma “unia˜o” de programas menores e mais simples. A divisa˜o tambe´m possibilita outra grande
vantagem, o reu´so de co´digo, ou seja, o uso de um mesmo trecho de programa para realizar o
mesmo tipo de tarefa em diferentes ocasio˜es dentro de um programa maior.
Um exemplo pra´tico do uso dos refinamentos sucessivos segue abaixo:
=⇒ Algoritmo “Escovac¸a˜o denta´ria”:
1. Pegar a escova e a pasta de dentes;
2. Colocar um pouco de pasta sobre as cerdas da escova;
3. Escovar os dentes do maxilar inferior;
4. Escovar os dentes do maxilar superior;
5. Expelir da boca o excesso de espuma;
6. Bochechar um pouco de a´gua;
7. Lavar a escova e guarda´-la;
8. Enxugar o rosto.
=⇒ Processo-componente “pegar a escova e a pasta de dentes”:
1. Enquanto na˜o encontrar a escova e o tubo de pasta, continuar procurando por cada gaveta
do arma´rio;
5Tambe´m conhecida como “dividir para conquistar”.
12 CAPI´TULO 1. INTRODUC¸A˜O
2. Caso tenham acabado as gavetas e na˜o tenha encontrado a escova e o tubo, interromper a
tarefa.
=⇒ Processo-componente “escovar os dentes do maxilar inferior”:
1. Com as cerdas da escova na posic¸a˜o vertical, fazer movimentos de vai-e-vem na regia˜o
superior dos dentes;
2. Com as cerdas na posic¸a˜o horizontal, escovar a regia˜o frontal dos dentes;
3. Com as cerdas na posic¸a˜o horizontal, escovar a regia˜o detra´s dos dentes.
=⇒ Processo-componente “escovar a regia˜o detra´s dos dentes”:
1. Abrir bem a boca;
2. Afastar a l´ıngua da regia˜o a ser escovada;
3. Esfregar as cerdas da escova atra´s dos dentes.
O exemplo anterior mostra apenas parte do processo de refinamentos, que deve prosseguir
ate´ que cada atividade esteja suficientemente detalhada, possibilitando que o computador as
reconhec¸a e execute.
1.5 Partes de um Programa
Como dito anteriormente, os programas podem ser comparados a` diversas atividades do dia-a-
dia de qualquer pessoa. Um exemplo e´ o de receitas culina´rias. Geralmente, essas seguem uma
determinada estrutura, como abaixo:
• Nome da receita;
• Ingredientes: descreve todo o material necessa´rio para o preparo da receita;
• Modo de preparo: descreve a forma de trabalhar com os ingredientes para que se obtenha
o resultado esperado;
• Comenta´rios sobre certos procedimentos ou ingredientes a fim de detalhar alguma peculi-
aridade que o cozinheiro poderia na˜o conhecer previamente.
A estrutura de um bom programa segue um modelo semelhante. Basicamente, um programa
deve conter quatro partes:
• Cabec¸alho: conte´m informac¸o˜es sobre o programa, como o seu nome;
1.5. PARTES DE UM PROGRAMA 13
• Diciona´rio de dados: define quais sa˜o os dados manipulados pelo programa;
• Corpo: define os procedimentos que o programa deve executar;
• Documentac¸a˜o: explica certos aspectos na˜o muito claros do programa, tanto no corpo do
programa quanto no cabec¸alho ou no diciona´rio de dados.
Um dos principais objetivos deste tipo de estrutura e´ aumentar a legibilidade do programa, ou
seja, facilitar o entendimento dos diversos processos que o programa executa. Um programa deve
valorizar a formatac¸a˜o, disposic¸a˜o f´ısica das linhas de co´digo, para facilitar seu entendimento.
Colocar cada comando em uma linha e inserir uma linha em branco entre blocos de comandos
de finalidade comum sa˜o regras ba´sicas para uma boa formatac¸a˜o. Os programas devem ser
lidos e entendidos por quem os escreveu e por outras pessoas, uma vez que podem necessitar de
correc¸a˜o, manutenc¸a˜o, modificac¸a˜o ou apenas de serem compreendidos por um simples usua´rio.
Para ilustrar essa estrutura, apresenta-se a seguir um programa, Pseudoco´digo 1.1, que efetua
o ca´lculo das ra´ızes reais de uma equac¸a˜o de segundo grau. Os dados de entrada do programa
sa˜o os treˆs coeficientes da equac¸a˜o e ele devera´ apresentar ao usua´rio as ra´ızes reais da mesma,
caso existam.
Pseudoco´digo 1.1 Ca´lculo das ra´ızes reais de uma equac¸a˜o de segundo grau.
Descric¸a˜o: programa que calcula as ra´ızes reais de uma equac¸a˜o de segundo grau.
Dados de Entrada: os treˆs coeficientes da equac¸a˜o.
Sa´ıda do Programa: ra´ızes reais da equac¸a˜o.
Leitura dos coeficientes da equac¸~ao;
Ca´lculo do discriminante (delta);
Ca´lculo das raı´zes pelo processo componente "Ca´lculo das Raı´zes";
Utilizando a te´cnica dos refinamentos sucessivos, na u´ltima linha do Pseudoco´digo 1.1 ocorre
a execuc¸a˜o do processo componente Ca´lculo das Ra´ızes, que, a partir dos valores dos coeficien-
tes lidos e do discriminante calculado, encontra os valores das ra´ızes reais da equac¸a˜o. No geral,
o processo componente Ca´lculo das Ra´ızes deve conter os passos descritos no Pseudoco´digo
1.2.
Pseudoco´digo 1.2 Processo componente para o ca´lculo das ra´ızes.
Processo-componente "Ca´lculo das Raı´zes":
Verificar a existe^ncia de raı´zes reais
Se possui raı´zes reais:
Exiba para o usua´rio os valores da raı´zes;
Sen~ao:
Exiba um alerta sobre a n~ao existe^ncia de raı´zes reais;
FIM-Processo componente "Ca´lculo das Raı´zes"
14 CAPI´TULO 1. INTRODUC¸A˜O
No Exemplo 1.1, o programa para o ca´lculo das ra´ızes esta´ transcrito para a linguagem de
programac¸a˜o C. Deve-se destacar que o texto escrito entre os s´ımbolos “/*” e “*/” e´ sempre
ignorado pelo computador, na˜o alterando em nada o funcionamento do programa. Pore´m, esse
texto serve para comentar o co´digo e deixa´-lo mais claro. Pode-se fazeˆ-los tambe´m utilizando o
s´ımbolo “//”, que transformaem comenta´rio tudo aquilo que estiver a sua direita, ate´ o final
da linha.
1 /*
2 Programa para ca´lculo das raı´zes de segundo grau.
3 Dados de entrada: os coeficientes a, b e c de uma equac¸~ao
4 da forma ax^2 + bx + c = 0
5 Dados de saı´da: imprime na tela as raı´zes reais da equac¸~ao , caso existam.
6 Restric¸~ao: N~ao se considera o zero como um possı´vel valor de a.
7 */
8
9 #include <math.h>
10 #include <stdio.h>
11
12 main(){
13 float a; // Coeficiente angular.
14 float b; // Coeficiente linear.
15 float c; // Termo independente.
16 float delta; // Discriminante.
17 float raiz1; // A primeira raiz.
18 float raiz2; // A segunda raiz.
19
20 // Leitura dos coeficientes.
21 scanf("%f %f %f",&a, &b, &c);
22
23 // Ca´lculo do discriminante (delta).
24 delta = b*b - 4 * a * c;
25
26 // Ca´lculo das raı´zes.
27 if(delta < 0){
28 printf("A equac¸~ao n~ao possui raı´zes reais");
29 }else{
30 raiz1 = (-b + sqrt(delta)) / (2*a);
31 raiz2 = (-b - sqrt(delta)) / (2*a);
32 printf("As raı´zes da equac¸~ao s~ao: %f e %f",raiz1 , raiz2);
33 }
34 }
Exemplo 1.1: Programa para o ca´lculo das ra´ızes reais de uma equac¸a˜o de segundo grau.
Na linguagem C, o cabec¸alho dos programas sempre tem o nome main() e o in´ıcio do corpo
do programa e´ marcado pela chave “{”, assim como o final e´ marcado pela u´ltima chave “}”.
As linhas 9 e 10 permitem o uso dos comandos sqrt e printf (o significado desses comandos e´
explicado no pro´ximo cap´ıtulo).
1.6. TRADUC¸A˜O DE PROGRAMAS 15
De acordo com a estrutura de programa apresentada no in´ıcio desta sec¸a˜o, as linhas 13 a
18 compo˜em o diciona´rio de dados e o restante compo˜e o corpo do programa. A documentac¸a˜o
esta´ inserida no programa em forma de comenta´rios, como as linhas 1 a 7, 20, 23 e 26.
Vale destacar a importaˆncia da disposic¸a˜o f´ısica das linhas de co´digo para o fa´cil entendimento
do programa. A hierarquizac¸a˜o de elementos por meio de espac¸os em branco e´ chamada de
indentac¸a˜o. O trecho de programa relacionado ao ca´lculo das ra´ızes no Exemplo 1.1 demonstra
como a indentac¸a˜o pode facilitar a visualizac¸a˜o da mudanc¸a do fluxo do programa.
Normalmente, linhas de co´digo com mesma indentac¸a˜o sa˜o executadas de maneira cont´ınua,
uma apo´s a outra. Uma mudanc¸a na indentac¸a˜o indica uma mudanc¸a nesse fluxo de execuc¸a˜o
do programa. No pro´ximo cap´ıtulo sa˜o apresentadas diversas maneiras de mudar esse fluxo.
1.6 Traduc¸a˜o de Programas
Apesar do que foi dito na Sec¸a˜o 1.3, para ser executado pelo computador, um programa ainda
precisa ser traduzido para uma linguagem mais simples que as linguagens de alto n´ıvel: a lingua-
gem de ma´quina. Chama-se de “co´digo fonte” o arquivo que conte´m o conjunto de instruc¸o˜es
escritas em uma determinada linguagem de programac¸a˜o, normalmente familiares ao programa-
dor. Ja´ o arquivo que as conte´m traduzidas para linguagem de ma´quina e´ chamado de “co´digo
objeto”.
Para efetuar essa traduc¸a˜o, e´ necessa´rio aplicar um programa, ou conjunto de programas,
que receba o co´digo fonte e gere o co´digo objeto. A seguir, descrevem-se dois me´todos ba´sicos
para um programa tradutor efetuar essa tarefa: a compilac¸a˜o e a interpretac¸a˜o de um co´digo
fonte.
1.6.1 Compilac¸a˜o
O processo de compilac¸a˜o efetua a traduc¸a˜o integral do programa fonte para o co´digo de ma´quina.
Uma vez traduzido, o programa em linguagem de ma´quina pode ser executado diretamente. A
Figura 1.2 ilustra esse processo.
A grande vantagem desse me´todo de traduc¸a˜o e´ a rapidez na execuc¸a˜o dos programas, pois
na˜o e´ necessa´rio fazer qualquer traduc¸a˜o durante a execuc¸a˜o. Pore´m, o co´digo objeto gerado pela
compilac¸a˜o e´, geralmente, espec´ıfico para um determinado tipo de arquitetura de computador.
Assim, e´ necessa´rio uma nova compilac¸a˜o do programa para cada tipo diferente de computador.
A linguagem C, adotada neste livro, e´ um exemplo de linguagem de programac¸a˜o compilada.
1.6.2 Interpretac¸a˜o
No processo de interpretac¸a˜o, cada instruc¸a˜o do co´digo fonte e´ traduzida no instante imedia-
tamente anterior a` execuc¸a˜o dela. Desse modo, em contraste com a compilac¸a˜o, a traduc¸a˜o e
execuc¸a˜o de programas interpretados podem ser vistas como um processo u´nico (veja as Figuras
1.2 e 1.3).
16 CAPI´TULO 1. INTRODUC¸A˜O
Figura 1.2: Me´todo de compilac¸a˜o. Figura 1.3: Me´todo de interpretac¸a˜o.
Apesar de ser um processo mais lento quando comparado ao me´todo anterior, a interpretac¸a˜o
apresenta maior flexibilidade na construc¸a˜o de programas e facilidade de depurac¸a˜o de co´digo.
A presenc¸a do interpretador durante a execuc¸a˜o permite, por exemplo, a execuc¸a˜o de trechos
de programas criados, alterados ou obtidos durante a pro´pria execuc¸a˜o.
1.7 Resumo
• O processador e´ o componente do computador responsa´vel por executar os programas
armazenados na memo´ria.
• A memo´ria e´ responsa´vel por armazenar os programas e os dados. A unidade ba´sica da
memo´ria e´ o bit.
• Algoritmo e´ uma sequ¨eˆncia de operac¸o˜es que deve ser executada em uma ordem definida
e na˜o-amb´ıgua, com o propo´sito de solucionar um determinado problema. Ao traduzir-se
um algoritmo para uma linguagem de programac¸a˜o, obte´m-se um programa.
• A Te´cnica de Refinamentos Sucessivos consiste, basicamente, em dividir sucessivamente
problemas complexos em diversos problemas menores e mais simples.
• Um programa bem estruturado deve conter as seguintes partes bem definidas: cabec¸alho,
diciona´rio de dados, corpo e documentac¸a˜o.
1.8. EXERCI´CIOS PROPOSTOS 17
• Basicamente, existem dois mecanismos de traduc¸a˜o de programas para linguagem de
ma´quina: compilac¸a˜o e interpretac¸a˜o. Na compilac¸a˜o, o co´digo fonte e´ totalmente tradu-
zido antes de ser executado. Ja´ na interpretac¸a˜o, a traduc¸a˜o do co´digo fonte e a execuc¸a˜o
do programa ocorrem quase simultaneamente, como um processo u´nico.
1.8 Exerc´ıcios Propostos
1. Qual e´ o papel do processador?
2. Qual e´ o papel da memo´ria?
3. Considere uma memo´ria que possua ce´lulas de 8 bits cada uma. Qual o nu´mero de poss´ıveis
informac¸o˜es diferentes cada ce´lula pode armazenar?
4. Utilizando o conceito de algoritmo apresentado no cap´ıtulo, descreva, atrave´s de um al-
goritmo, o ato de trocar um pneu furado de um carro. Na˜o se esquec¸a de estabelecer as
condic¸o˜es iniciais do problema (por exemplo, carro com um pneu dianteiro furado, se a
chave de roda esta´ no carro, se o carro esta´ parado em uma ladeira, etc) e as condic¸o˜es de
sa´ıda (por exemplo, carro parado e frenado, etc).
5. Use a Te´cnica de Refinamentos Sucessivos para detalhar as seguintes atividades:
(a) Montagem de uma barraca de camping;
(b) Preparac¸a˜o de um bolo de aniversa´rio;
(c) Ca´lculo da distaˆncia entre dois pontos no plano cartesiano.
Cap´ıtulo 2
Conceitos Ba´sicos
Co-autores:
Andre´ Boechat
Bruno Pandolfi
Objetivos:
• Apresentar o conceito de varia´vel;
• Estudar os principais tipos de dados ba´sicos e expresso˜es va´lidas;
• Mostrar como e´ feita a definic¸a˜o de varia´veis e constantes;
• Apresentar os comandos elementares usados em programas.
A ide´ia de resolver problemas formalizando a soluc¸a˜o atrave´s do emprego de algoritmos e´ a
espinha dorsal da programac¸a˜o procedural, na qual as tarefas sa˜o prescritas ao computador por
meio de uma sequ¨eˆncia de operac¸o˜es ba´sicas.
Este cap´ıtulo trata do estudo dos conceitos e operac¸o˜es elementares da programac¸a˜o, forne-
cendo uma base so´lida que, mais adiante, serve para construir algoritmos progressivamente mais
complexos e resolver problemas cada vez mais elaborados.
2.1 Varia´veis e Ce´lulas de Memo´ria
Qualquer algoritmo tem por finalidade produzir algum resultado u´til para compor a soluc¸a˜o de
um problema. Os algoritmos computacionais,em sua maioria, operam sobre um conjunto de
dados para produzir novos resultados de acordo com a necessidade da tarefa em questa˜o.
Quando corretamente transcritos para uma linguagem de programac¸a˜o, os algoritmos sa˜o
chamados de programas e podem ser executados pelo computador. E´ necessa´rio, todavia, arma-
zenar as informac¸o˜es utilizadas pelos programas em um local organizado e seguro, para que as
consultas e alterac¸o˜es sejam efetuadas de maneira coerente e livre de erros. Os computadores
utilizam a memo´ria para armazenar os dados de um programa em execuc¸a˜o.
18
2.1. VARIA´VEIS E CE´LULAS DE MEMO´RIA 19
Como dito na Sec¸a˜o 1.2.1, a memo´ria pode ser entendida como uma sequ¨eˆncia de ce´lulas,
cada ce´lula podendo armazenar uma porc¸a˜o dos dados de um programa. Grac¸as a essa ordenac¸a˜o
sequ¨encial, cada ce´lula possui um nu´mero identificador chamado enderec¸o, que esta´ relacionado
com a posic¸a˜o que a ce´lula ocupa na sequ¨eˆncia. Por meio dos enderec¸os e´ poss´ıvel acessar
qualquer ce´lula para ler ou alterar seu conteu´do. A Figura 2.1 esboc¸a essa ide´ia, pore´m, em
contraste com a Figura 1.1, omite a representac¸a˜o dos bits.
Figura 2.1: Modelo para a estrutura da memo´ria do computador, mostrando uma frac¸a˜o de seis
ce´lulas, seus enderec¸os e conteu´dos.
As seis ce´lulas de memo´ria da Figura 2.1 podem guardar valores nume´ricos ou letras em seus
interiores. Cada ce´lula e´ apontada por um enderec¸o u´nico e sequ¨encial.
A estrutura da memo´ria favorece a execuc¸a˜o de suas duas operac¸o˜es ba´sicas: leitura e escrita.
A leitura e´ o processo de consulta do conteu´do da ce´lula. Essa operac¸a˜o na˜o altera o valor
guardado na ce´lula.
A escrita e´ o processo de armazenamento de um novo dado na ce´lula indicada por um
enderec¸o conhecido. Apo´s a execuc¸a˜o da escrita, o valor que estava anteriormente armazenado
na ce´lula e´ perdido.
Um algoritmo para o ca´lculo do valor da conta mensal de energia ele´trica e´ um bom exemplo
para compreender as operac¸o˜es ba´sicas da memo´ria. Os dados de entrada desse algoritmo sa˜o: a
leitura atual do medidor, a leitura registrada no meˆs anterior e o prec¸o do quilowatt-hora (kWh)
— unidade comercial de energia ele´trica.
Na pra´tica, o que se faz para calcular o valor da conta e´ encontrar a diferenc¸a entre a leitura
atual do medidor e a leitura do meˆs anterior e multiplicar esse valor pelo prec¸o do quilowatt-hora.
O algoritmo computacional, por sua vez, e´ descrito no Pseudoco´digo 2.1.
No Pseudoco´digo 2.1, o computador leˆ os conteu´dos das ce´lulas 43 e 46 (que guardam os
valores das leituras atual e anterior, respectivamente), realiza a subtrac¸a˜o e o resultado e´ guar-
dado na ce´lula 41. Posteriormente, essa diferenc¸a e´ lida e seu valor multiplicado pelo conteu´do
da ce´lula 44, que guarda o valor do prec¸o unita´rio do kWh. Finalmente, o valor da conta e´
guardado na ce´lula 42.
Acompanhando a descric¸a˜o acima e´ poss´ıvel chegar a` situac¸a˜o encontrada na Figura 2.2.
Nos primo´rdios da programac¸a˜o, percebeu-se que acessar a memo´ria por meio de enderec¸os
era trabalhoso demais e causa constante de erros. Isso porque o programador deveria escolher os
enderec¸os das ce´lulas com as quais iria trabalhar, tanto das ce´lulas que teriam valores a serem
lidos quanto das que seriam usadas para a escrita de resultados.
Essa situac¸a˜o confusa e´ observa´vel no exemplo da conta de energia ele´trica. Sem o comenta´rio
20 CAPI´TULO 2. CONCEITOS BA´SICOS
Pseudoco´digo 2.1 Ca´lculo da conta de energia ele´trica utilizando os enderec¸os das ce´lulas de
memo´ria.
Descric¸a˜o: programa que calcula o valor da conta de energia ele´trica.
Dados de Entrada: ce´lulas 43 e 46 contendo, respectivamente, a leitura atual e a anterior; e valor
unita´rio do kWh na ce´lula 44.
Sa´ıda do Programa: valor da conta, armazenada na ce´lula 42.
Subtrair o conteu´do da ce´lula 43 do conteu´do da ce´lula 46 e guardar na
ce´lula 41;
Multiplicar o conteu´do da ce´lula 41 pelo conteu´do da ce´lula 44 e guardar na
ce´lula 42;
Figura 2.2: Conteu´do da memo´ria apo´s execuc¸a˜o do algoritmo que calcula o valor de uma conta de
energia ele´trica.
no in´ıcio do Pseudoco´digo 2.1, seria imposs´ıvel ter a mı´nima ide´ia do que o programa faz em
cada passo. Isso torna dif´ıcil na˜o so´ a escrita, mas tambe´m a correc¸a˜o dos programas.
Para resolver essa questa˜o, o conceito de varia´vel foi criado. Uma varia´vel nada mais e´ do
que uma abstrac¸a˜o para o enderec¸o de memo´ria. Com o emprego de varia´veis, as ce´lulas de
memo´ria sa˜o referenciadas nos programas por meio de ro´tulos, definidos com ajuda do bom-
senso do programador. O compilador fica encarregado do trabalho de transformar ro´tulos em
enderec¸os para que as operac¸o˜es de acesso a` memo´ria sejam realizadas.
O Pseudoco´digo 2.2 mostra como fica o programa que calcula o valor da conta de energia
ele´trica, agora escrito utilizando varia´veis.
Pseudoco´digo 2.2 Ca´lculo da conta de energia ele´trica utilizando varia´veis.
Descric¸a˜o: programa que calcula o valor da conta de energia ele´trica.
Dados de Entrada: a leitura atual, a anterior e o prec¸o unita´rio do kWh.
Sa´ıda do Programa: valor da conta.
Subtrair o conteu´do da varia´vel ‘leituraAtual’ do conteu´do da varia´vel
‘leituraAnterior’ e guardar na varia´vel ‘diferenca’;
Multiplicar o conteu´do da varia´vel ‘diferenca’ pelo conteu´do da varia´vel
‘valorUnitario’ e guardar na varia´vel ‘valorConta’;
A partir do Pseudoco´digo 2.2, um compilador pode converter os ro´tulos para posic¸o˜es quais-
quer na memo´ria, evitando que o programador tenha que se preocupar em manipula´-las. Uma
2.2. IDENTIFICADORES 21
Figura 2.3: Uma poss´ıvel traduc¸a˜o para enderec¸os de memo´ria, a partir dos ro´tulos do co´digo que utiliza
varia´veis.
poss´ıvel traduc¸a˜o e´ exibida na Figura 2.3.
Como visto nos exemplos desta sec¸a˜o, o uso de varia´veis em um algoritmo reduz a quantidade
de comenta´rios explicativos, pois sua leitura e´ mais simples e seu entendimento e´ mais fa´cil. Em
caso de erros, a correc¸a˜o do programa e´ muito mais ra´pida e eficiente.
Apresentados os conceitos de varia´vel e ce´lulas de memo´ria, e´ va´lido abordar um outro
significado de programa. Trata-se de considerar os programas como sendo processos de mudanc¸a
de estados.
Nessa abordagem, os dados de entrada, escritos em suas respectivas varia´veis, sa˜o conside-
rados o estado inicial do programa. A partir da´ı, realiza-se uma sequ¨eˆncia de operac¸o˜es para
chegar a um estado final. A cada operac¸a˜o, diz-se que o programa esta´ em um novo estado in-
termedia´rio. O estado final e´ atingido quando a tarefa em questa˜o e´ considerada como realizada.
A transic¸a˜o do estado inicial para o estado final pode ser efetuada de diversas maneiras.
Conforme pode ser visto mais adiante neste cap´ıtulo, e´ poss´ıvel escolher entre duas ou mais
sequ¨eˆncias de comandos, bem como repeti-las, de acordo com o estado intermedia´rio em que o
programa se encontra.
2.2 Identificadores
Em geral, as linguagens de alto n´ıvel possuem dois tipos de elementos: os elementos definidos
pela pro´pria linguagem — s´ımbolos para operadores, nome de comandos etc — e os elementos
definidos pelo programador — identificadores, comenta´rios etc.
Um identificador e´ um s´ımbolo que pode representar alguma entidade criada pelo progra-
mador, como uma varia´vel, por exemplo. Cada linguagem define uma regra para formac¸a˜o de
identificadores. Em geral, sempre e´ poss´ıvel utilizar uma sequ¨eˆncia de caracteres alfanume´ricos
— letras ou d´ıgitos, sem acentos e sem cedilha — sendo que o primeiro caractere deve ser obri-
gatoriamente alfabe´tico. Os Exemplos 2.1 e 2.2 apresentam, respectivamente, nomes corretos e
nomes inva´lidos de varia´veis na linguagem C.
Algumas linguagens, como C, fazem diferenciac¸a˜o entre letras maiu´sculas eminu´sculas.
Desta forma, uma varia´vel de nome Saldo e´ considerada diferente de outra de nome saldo,
ou, ainda, de nome SALDO. E´ importante ressalvar que na˜o e´ uma boa pra´tica de programac¸a˜o
criar identificadores que apenas se diferenciem pelo formato das letras, como no exemplo do
saldo, pois isso tem impacto negativo na legibilidade dos programas.
22 CAPI´TULO 2. CONCEITOS BA´SICOS
1 abc
2 x1
3 y2
4 letra
5 SOMA_TOTAL
6 B_32
Exemplo 2.1: Nomes va´lidos de varia´veis, concordando com as regras de nomenclatura.
1 fim? // ‘‘?’’ n~ao e´ um caractere alfanume´rico
2 %percentual% // ‘‘%’’ n~ao e´ um caractere alfanume´rico
3 123 quatro // Iniciado por nu´mero
4 !hola! // ‘‘!’’ n~ao e´ um caracter alfanume´rico
5 @ARROBA // ‘‘@’’ n~ao e´ um caractere alfanume´rico
Exemplo 2.2: Nomes inva´lidos de varia´veis.
Normalmente, em grandes projetos de software, sa˜o adotados padro˜es para a escrita dos
identificadores a fim de que os programadores possam trocar seus co´digos, entendeˆ-los e altera´-
los sem grande dificuldade. Neste texto, e´ adotado como regra na escrita:
• Nomes simples: comec¸ados com letra minu´scula e demais caracteres minu´sculos;
• Nomes compostos: primeira parte e´ iniciada por letra minu´scula e as demais partes inici-
adas por letra maiu´scula. Os demais caracteres sa˜o minu´sculos.
Como dito na Sec¸a˜o 1.5, um bom programa deve necessariamente ser leg´ıvel e de fa´cil com-
preensa˜o. A escolha dos nomes dos identificadores influenciam diretamente esses dois aspectos.
Logo, e´ muito importante que os nomes sejam significativos, deixando bem clara a sua refereˆncia.
A fim de contrastar com a declarac¸a˜o de varia´veis do Exemplo 2.1, o Exemplo 2.3 ilustra
a convenc¸a˜o proposta, apresentando nomes significativos para varia´veis. Neste, o ro´tulo das
varia´veis ja´ e´ suficiente para informar a funcionalidade das mesmas, tornando ra´pida a compre-
ensa˜o do programa que as utiliza e dispensando a necessidade de comenta´rios.
1 delta
2 raiz1
3 idade
4 letra
5 percentualDeLucro
6 primeiraLetra
7 indiceBovespa
Exemplo 2.3: Nomes significativos para varia´veis.
2.3. COMANDO DE ATRIBUIC¸A˜O 23
2.3 Comando de Atribuic¸a˜o
Os pseudoco´digos da Sec¸a˜o 2.1 na˜o mostram como os conteu´dos das varia´veis de entrada sa˜o
alterados para que o ca´lculo seja efetuado coerentemente. Em outras palavras, na˜o se mostra
como as varia´veis leituraAtual, leituraAnterior e valorUnitario sa˜o inicializadas. O responsa´vel
pela alterac¸a˜o dessas varia´veis, assim como de qualquer outra, e´ o comando de atribuic¸a˜o.
O comando de atribuic¸a˜o e´ muito importante e, com certeza, e´ o mais utilizado. E´ por meio
dele que as varia´veis podem ter seus valores (conteu´dos) alterados. Por isso, o comando de
atribuic¸a˜o esta´ diretamente ligado a`s operac¸o˜es de memo´ria.
No Exemplo 2.4 e´ transcrito o algoritmo do ca´lculo da conta de energia ele´trica para o co´digo
de um programa na linguagem C.
1 main(){
2 leituraAtual = 125;
3 leituraAnterior = 25;
4 valorUnitario = 2;
5 diferenca = leituraAtual - leituraAnterior;
6 valorConta = diferenca * valorUnitario;
7 }
Exemplo 2.4: Ca´lculo do valor da conta de energia ele´trica.
No Exemplo 2.4, o s´ımbolo “=” representa o comando de atribuic¸a˜o. Em seu lado esquerdo
sempre havera´ a varia´vel destino, na qual sera´ escrito o resultado da expressa˜o do lado direito
do comando. As expresso˜es mais simples sa˜o as que conteˆm valores constantes, tais como as que
ocorrem nas linhas 1, 2 e 3 do Exemplo 2.4.
Essas treˆs linhas sa˜o omitidas propositalmente do Pseudoco´digo 2.2 para torna´-lo mais sim-
ples. Entretanto, elas na˜o sa˜o dif´ıceis de compreender, pois apenas informam ao computador
quais valores ele deve manipular para encontrar o resultado esperado: o valor da conta mensal
de energia ele´trica.
Dessa forma, o comando da linha 1 do Exemplo 2.4 simplesmente realiza a atribuic¸a˜o do valor
125 a` varia´vel leituraAtual. A partir da efetivac¸a˜o desse comando, o conteu´do dessa varia´vel
pode ser usado para os ca´lculos. O mesmo vale para as demais varia´veis.
As linhas 4 e 5 do Exemplo 2.4 sa˜o transcric¸o˜es diretas dos dois passos do algoritmo da
conta de energia. O que ocorre de diferente e´ que o valor a ser atribu´ıdo a`s varia´veis do lado
esquerdo e´ primeiramente calculado na expressa˜o para, em seguida, ser guardado na varia´vel
correspondente. A Figura 2.4 representa graficamente essa passagem.
O comando de atribuic¸a˜o e´ executado sempre da mesma maneira pelo computador. Em
primeiro lugar a expressa˜o que esta´ do lado direito do comando e´ calculada e, para isso, todas as
varia´veis que aparecem teˆm seus valores lidos e lanc¸ados na expressa˜o. Apo´s o fim dos ca´lculos na
expressa˜o, o computador escreve o resultado na varia´vel destino, no lado esquerdo. Basicamente,
a forma geral do comando de atribuic¸a˜o e´ a seguinte:
<varia´vel> = <express~ao>;
24 CAPI´TULO 2. CONCEITOS BA´SICOS
Figura 2.4: Representac¸a˜o gra´fica da linha 4 do Exemplo 2.4.
E´ muito importante compreender a diferenc¸a significativa existente entre o comando de atri-
buic¸a˜o e a igualdade matema´tica. Em muitas linguagens de programac¸a˜o (C, por exemplo) a
atribuic¸a˜o e´ tambe´m representada pelo s´ımbolo “=”, o que pode provocar interpretac¸o˜es equi-
vocadas. O Exemplo 2.5 mostra um trecho de programa que geralmente causa confusa˜o para os
programadores iniciantes.
1 contador = 10;
2 contador = contador + 1;
Exemplo 2.5: Incremento de uma varia´vel usando o comando de atribuic¸a˜o.
No Exemplo 2.5 ocorrem duas atribuic¸o˜es. A primeira ocorre na linha 1, sendo mais um
exemplo simples de inicializac¸a˜o de uma varia´vel, como ja´ discutido anteriormente. Na linha 2,
a varia´vel contador aparece em ambos os lados da expressa˜o, o que pode parecer um absurdo
matema´tico. Pore´m, e´ necessa´rio lembrar que, nesse contexto, o s´ımbolo “=” atribui o valor da
expressa˜o da direita a` varia´vel que aparece a` esquerda. Ou seja, avalia-se primeiro o resultado
da expressa˜o a` direita (10 + 1 = 11) e, posteriormente, atribui-se o valor a` varia´vel a` esquerda
(contador = 11). Isso e´ representado graficamente na Figura 2.5.
Figura 2.5: Representac¸a˜o gra´fica do incremento de uma varia´vel.
Mais uma observac¸a˜o e´ necessa´ria: O programador deve ficar atento aos tipos de dados
manipulados em um comando de atribuic¸a˜o, pois o tipo da expressa˜o a` direita deve ser compat´ıvel
com o tipo da varia´vel a` esquerda. A manipulac¸a˜o dos tipos de dados e´ detalhada na Sec¸a˜o 2.4.
2.4. TIPOS DE DADOS 25
2.4 Tipos de Dados
Um tipo de dados delimita o conjunto de valores poss´ıveis que uma determinada varia´vel pode
representar. Ale´m disso, define as operac¸o˜es ba´sicas poss´ıveis para suas varia´veis.
Sua necessidade decorre do fato de que as ce´lulas de memo´ria, sozinhas, conseguem represen-
tar apenas conjuntos de dados muito limitados. Entretanto, a maioria dos valores de interesse
pertence a conjuntos extensos, os quais na˜o podem ser representados com o uso de apenas uma
ce´lula de memo´ria.
Os programadores, enta˜o, passaram a utilizar mu´ltiplas ce´lulas para representar um u´nico
valor. Essa atitude resolveu a dificuldade de armazenar dados complexos, mas criou um outra
questa˜o: os processos de leitura e escrita para valores de mu´ltiplas ce´lulas, bem como as de-
mais operac¸o˜es sobre tais valores, exigiam co´digos que, ale´m de na˜o-triviais, fugiam do foco do
problema principal.
Na˜o demorou para que as linguagens de programac¸a˜o incorporassem a definic¸a˜o dos tipos
de dados e suas operac¸o˜es essenciais, poupando os programadores da tarefa de defini-los em seu
co´digo e tornando-o mais enxuto e leg´ıvel.
Tipos de dados, portanto, abstraem a forma de implementac¸a˜o e disponibilizam operac¸o˜es
sobre oselementos do conjunto para que o programador possa utiliza´-las sem ter que implementa´-
las.
Os tipos ba´sicos mais importantes sa˜o o tipo inteiro, o ponto flutuante, o booleano e o tipo
caractere. Cada linguagem de programac¸a˜o possui certas particularidades em relac¸a˜o aos tipos
de dados.
Primeiramente, e´ preciso abordar um conceito imprescind´ıvel da escrita de programas em
linguagem C: a declarac¸a˜o de varia´veis. Em seguida, sa˜o descritas as caracter´ısticas mais comuns
dos tipos ba´sicos principais.
2.4.1 Declarac¸a˜o de Varia´veis
De acordo com o problema abordado, diferentes conjuntos de dados sa˜o necessa´rios. Conforme
visto, os tipos de dados representam os conjuntos de valores poss´ıveis para suas varia´veis, assim
como as operac¸o˜es va´lidas sobre elas. Tambe´m ja´ foram abordadas a necessidade e as vantagens
do uso de varia´veis em um programa. Entretanto, ainda na˜o foi mencionado como as varia´veis
sa˜o criadas, ou seja, como o programador declara formalmente uma varia´vel em seu co´digo.
Na linguagem C, o ato de declarar uma varia´vel e´ simples e imprescind´ıvel. Afinal, sem
esse procedimento, na˜o e´ poss´ıvel usa´-la. Quando a declarac¸a˜o de varia´veis e´ esquecida, uma
mensagem de erro e´ apresentada ao programador, e a compilac¸a˜o do co´digo e´ interrompida. Por
isso, toda varia´vel deve ser declarada antes de ser utilizada.
A declarac¸a˜o de varia´veis tem uma estrutura simples e algumas regras ba´sicas. Em primeiro
lugar, escreve-se o nome do tipo de dados ao qual a varia´vel pertence. Em seguida, separado
por um espac¸o em branco, escreve-se o identificador da varia´vel.
<tipo> <identificador>;
26 CAPI´TULO 2. CONCEITOS BA´SICOS
E´ poss´ıvel declarar mais de uma varia´vel em uma mesma linha, desde que todas sejam do mesmo
tipo, conforme o Exemplo 2.6.
1 float valorFracionado , saldo , salarioMinimo;
2 char letra , ultimaLetra;
3 int entrada1 , entrada2 , entrada3;
Exemplo 2.6: Declarac¸a˜o mu´ltipla de varia´veis em uma mesma linha de co´digo.
2.4.2 Tipo Inteiro
O tipo inteiro, como o pro´prio nome sugere, representa um intervalo finito do conjunto ma-
tema´tico dos nu´meros inteiros.
De fato, uma linguagem de programac¸a˜o pode definir va´rios tipos inteiros, cada um com
intervalo diferente. Na linguagem C, por exemplo, existem va´rios tipos inteiros, tais como o int,
long int, unsigned int, short int. Neste livro, para bem da simplicidade, usa-se apenas o tipo
int.
O intervalo de valores para o tipo int depende do compilador que esta´ sendo empregado.
Assumimos aqui que o intervalo do tipo int sempre varia de entre −32768 a 32767.
Em C, como na maioria das linguagens, as operac¸o˜es sobre as varia´veis do tipo inteiro ja´
esta˜o implementadas e a` disposic¸a˜o do programador. As operac¸o˜es dispon´ıveis sa˜o as de soma,
subtrac¸a˜o, multiplicac¸a˜o, divisa˜o e resto de divisa˜o, conforme o Exemplo 2.7.
O uso dessas func¸o˜es e´ bastante simples e intuitivo, pois ha´ ate´ certa relac¸a˜o com os s´ımbolos
da escrita matema´tica. No Exemplo 2.7, as varia´veis x e y sa˜o relacionadas entre si e os resultados
sa˜o armazenados nas varia´veis de a a f.
Os operadores de soma e subtrac¸a˜o funcionam tal qual na aritme´tica. O operador de sub-
trac¸a˜o pode ser aplicado para um u´nico valor quando se deseja inverter seu sinal. A linha 12 do
Exemplo 2.7 mostra essa situac¸a˜o.
Um destaque deve ser dado ao operador de multiplicac¸a˜o. Seu u´nico s´ımbolo e´ “*” (na˜o ha´
o s´ımbolo “×” ou o “·”). Ale´m disso, em oposic¸a˜o ao que ocorre na aritme´tica, a escrita do “*”
na˜o pode ser omitida. Logo, a operac¸a˜o da linha 13 do Exemplo 2.7 geraria erro se na˜o estivesse
comentada, pois o compilador trataria xy como uma varia´vel na˜o declarada.
1 main(){
2 int x, y, a, b, c, d, e, f;
3
4 x = 10;
5 y = 3;
6
7 a = x + y; // a armazena 13
8 b = x - y; // b armazena 7
9 c = x * y; // c armazena 30
10 d = x / y; // d armazena 3
11 e = x % y; // e armazena 1
2.4. TIPOS DE DADOS 27
12 f = -a; // f armazena -13
13 // c = xy;
14 }
Exemplo 2.7: Operac¸o˜es ba´sicas com o tipo inteiro int.
Tambe´m e´ importante destacar o resultado da operac¸a˜o de divisa˜o. No caso do Exemplo
2.7, o resultado correto da divisa˜o de x — que armazena o valor 10 — por y — cujo valor e´ 3
— e´ a d´ızima perio´dica 3, 333 . . . Entretanto, como as varia´veis envolvidas na linha 10 sa˜o todas
do tipo inteiro, o compilador trata de truncar o resultado, desconsiderando a parte decimal e
fornecendo 3 como resultado da operac¸a˜o.
Ainda no Exemplo 2.7, deve-se notar o uso do operador de resto de divisa˜o inteira. Seu
s´ımbolo — “%” — deve ficar entre os valores do dividendo e do divisor. A linha 11 mostra a
obtenc¸a˜o do resto da divisa˜o de x por y. Apo´s a execuc¸a˜o dessa operac¸a˜o, a varia´vel e guardara´
o valor 1, que e´ o resto da divisa˜o de 10 por 3.
2.4.3 Tipo Ponto Flutuante
Esse tipo de dados representa um intervalo dos nu´meros racionais. Assim como o tipo inteiro,
ha´ mais do que um intervalo poss´ıvel, dependendo da precisa˜o escolhida.
Na linguagem C, os tipos de ponto flutuante sa˜o o float e o double. Neste livro, apenas o
tipo float e´ empregado.
Dependendo do compilador utilizado, os tipos de dados de ponto flutuante apresentam dife-
rentes preciso˜es. Aqui se considera que o tipo float proveˆ seis casas decimais de precisa˜o.
As operac¸o˜es pre´-definidas sa˜o as mesmas que as dispon´ıveis para o tipo int, exceto, e´ claro,
pela inexisteˆncia do operador de resto de divisa˜o. O Exemplo 2.8 mostra o uso de varia´veis do
tipo float em um programa.
1 main(){
2 float p, q, x, z;
3 int y;
4
5 x = 10;
6 y = 4;
7
8 p = 50 / 30; // p guardara´ 1
9 q = 10.0 / 4; // q guardara´ 2.5
10
11 z = x / y; // z guardara´ 2.5
12 }
Exemplo 2.8: Operac¸o˜es com varia´veis do tipo float.
As operac¸o˜es entre varia´veis do tipo float sa˜o escritas com os mesmos s´ımbolos das operac¸o˜es
do tipo int. O Exemplo 2.8 mostra particularidades do processo de compilac¸a˜o que podem gerar
erros nos programas.
28 CAPI´TULO 2. CONCEITOS BA´SICOS
A linha 8 do Exemplo 2.8 possui um comenta´rio explicando que a varia´vel p recebe 1 como
resultado da operac¸a˜o de divisa˜o. Tal erro na˜o ocorre para a divisa˜o da linha seguinte. A
justificativa para essa situac¸a˜o e´ que, conforme e´ mostrado na Sec¸a˜o 2.3, o computador primeiro
calcula o resultado da expressa˜o do lado direito do comando de atribuic¸a˜o para, em seguida,
escrever esse valor na correspondente varia´vel de destino.
Durante a compilac¸a˜o, o compilador checa os tipos das varia´veis envolvidas nos ca´lculos
para realizar as operac¸o˜es correspondentes. Entretanto, quando ha´ apenas valores nume´ricos
envolvidos, o compilador considera os nu´meros escritos sem ponto decimal como sendo do tipo
inteiro. E´ por isso que a divisa˜o realizada na linha 8 do Exemplo 2.8 resulta em 1. O computador
entende a operac¸a˜o 50/30 como uma divisa˜o inteira, descartando a parte decimal do resultado.
Ja´ na linha 9, o compilador enxerga o valor 10.0 como sendo do tipo float devido a` presenc¸a
expl´ıcita do ponto decimal, e realiza a divisa˜o, resultando no valor esperado.
No caso da u´ltima linha do Exemplo 2.8, nenhum resultado inesperado ocorre porque o
tipo mais abrangente — tipo float da varia´vel x — encontrado na expressa˜o e´ considerado nas
operac¸o˜es, garantindo o resultado esperado. Caso a varia´vel x tambe´m fosse do tipo int, enta˜o
o mesmo incoveniente da linha 8 ocorreria.
2.4.4 Tipo Booleano
O tipo booleano e´ o tipo de dados mais simples. Ele conte´m apenas dois valores poss´ıveis:
verdadeiro e falso. E´ usado principalmente quando se precisa verificar condic¸o˜es no programa,
em expresso˜es lo´gicas (Sec¸a˜o 2.6.3) e relacionais (Sec¸a˜o 2.6.2).
Na linguagem C na˜o ha´ uma representac¸a˜o espec´ıficapara esse tipo de dados e sa˜o utilizados
valores inteiros para codifica´-lo. Desta forma, todo valor inteiro diferente de zero e´ considerado
valor “verdadeiro”. O valor zero e´ considerado “falso”.
2.4.5 Tipo Caractere
Como o pro´prio nome indica, o tipo caractere registra os co´digos para letras, nu´meros e caracteres
especiais ($, &, #, @ etc). Normalmente, esses co´digos e caracteres variam para as diversas
regio˜es do planeta, conforme suas particularidades lingu´ısticas. Um padra˜o largamente utilizado
atualmente, pricipalmente no Ocidente, e´ o ASCII (American Standard Code of Information
Interchange — Padra˜o Americano para Intercaˆmbio de Informac¸o˜es), especificado pelo ANSI
(American National Standars Institute — Instituto Americano Nacional de Padro˜es).
O padra˜o ASCII e´ uma tabela. Cada posic¸a˜o da tabela simboliza um caractere. Na linguagem
C, o tipo char e´ empregado para conter o ı´ndice para a posic¸a˜o da tabela que codifica um
determinado caractere.
Originalmente, essa tabela era composta por apenas 128 s´ımbolos, os quais inclu´ıam todos os
caracteres alfanume´ricos do Ingleˆs, sinais de pontuac¸a˜o e alguns outros s´ımbolos. Os primeiros 32
caracteres eram utilizados para controle de fluxo de dados (em comunicac¸o˜es entre o computador
e seus perife´ricos) e na˜o imprimı´veis. Atualmente, esses caracteres ca´ıram em desuso. A Tabela
2.1 mostra os 128 caracteres da tabela ASCII original.
2.4. TIPOS DE DADOS 29
Co´digo Caractere Co´digo Caractere Co´digo Caractere Co´digo Caractere
0 NUL (null) 32 SPACE 64 @ 96 `
1 SOH (start of heading) 33 ! 65 A 97 a
2 STX (start of text) 34 ” 66 B 98 b
3 ETX (end of text) 35 # 67 C 99 c
4 EOT (end of transmission) 36 $ 68 D 100 d
5 ENQ (enquiry) 37 % 69 E 101 e
6 ACK (acknowledge) 38 & 70 F 102 f
7 BEL (bell) 39 ’ 71 G 103 g
8 BS (backspace) 40 ( 72 H 104 h
9 HT (horizontal tab) 41 ) 73 I 105 i
10 LF (NL line feed,new line) 42 * 74 J 106 j
11 VT (vertical tab) 43 + 75 K 107 k
12 FF (NP from feed,new page) 44 , 76 L 108 l
13 CR (carriage return) 45 - 77 M 109 m
14 SO (shift out) 46 . 78 N 110 n
15 SI (shift in) 47 / 79 O 111 o
16 DLE (data link escape) 48 0 80 P 112 p
17 DC1 (device control 1) 49 1 81 Q 113 q
18 DC2 (device control 2) 50 2 82 R 114 r
19 DC3 (device control 3) 51 3 83 S 115 s
20 DC4 (device control 4) 52 4 84 T 116 t
21 NAK (negative acknowledge) 53 5 85 U 117 u
22 SYN (synchronous idle) 54 6 86 V 118 v
23 ETB (end of trans. block) 55 7 87 W 119 w
24 CAN (cancel) 56 8 88 X 120 x
25 EM (end of medium) 57 9 89 Y 121 y
26 SUB (substitute) 58 : 90 Z 122 z
27 ESC (escape) 59 ; 91 [ 123 {
28 FS (file separator) 60 < 92 \ 124 |
29 GS (group separator) 61 = 93 ] 125 }
30 RS (record separator) 62 > 94 ˆ 126 ˜
31 US (unit separator) 63 ? 95 127 DEL
Tabela 2.1: Os 128 caracteres da tabela ASCII original.
Com o passar do tempo, a tabela ASCII sofreu modificac¸o˜es. Ela foi atualizada e incorporou
mais 128 novos s´ımbolos, os quais incluem, por exemplo, os caracteres acentuados e o cedilha,
do Portugueˆs. Essa nova versa˜o e´ conhecida como tabela ASCII estendida.
Para fazer com que uma varia´vel do tipo char aponte para um s´ımbolo de interesse, o
programador precisa apenas atribuir a essa varia´vel o caractere desejado, colocando-o entre
aspas simples. O Exemplo 2.9 exibe essa situac¸a˜o.
1 main(){
2 char letraA , letraFMaiuscula , simboloSoma;
3
4 letraA = ‘a’;
30 CAPI´TULO 2. CONCEITOS BA´SICOS
5 letraFMaiuscula = ‘F’;
6 simboloSoma = ‘+’;
7 }
Exemplo 2.9: Uso de varia´veis do tipo caractere.
2.4.6 Conversa˜o de Tipos
Agora, conhecidas algumas informac¸o˜es sobre os tipos de dados ba´sicos, torna-se mais simples
compreender o problema existente na atribuic¸a˜o entre tipos diferentes, mencionada na Sec¸a˜o
2.3.
Considera-se que os tipos int, float e char ocupam a quantidade de memo´ria representada
na Figura 2.6.
Figura 2.6: Tamanho da memo´ria utilizada pelos tipos de dados ba´sicos.
As diferenc¸as nos tamanhos sa˜o justifica´veis, uma vez que, quanto maior o conjunto a ser
representado, mais ce´lulas de memo´ria sa˜o necessa´rias para acomodar uma varia´vel. Desta
forma, sendo o conjunto dos caracteres o menor, e´ preciso apenas um byte (uma ce´lula) para
representa´-lo. Ja´ o conjunto do tipo float, que e´ o maior dos treˆs, precisa de 4 bytes (4 ce´lulas)
para uma representac¸a˜o coerente de seus valores.
E´ preciso ter em mente que, devido a essas restric¸o˜es de implementac¸a˜o, na˜o se deve utili-
zar operac¸o˜es de atribuic¸a˜o entre varia´veis sem tomar algum cuidado. Se elas forem de tipos
diferentes, problemas podem acontecer.
Na˜o ha´ problemas em atribuir uma varia´vel do tipo int a outra do tipo float. Tal qual ocorre
na matema´tica, toda varia´vel do tipo int e´ poss´ıvel de ser representada por outra do tipo float,
pois o conjunto dos nu´meros racionais conte´m o conjunto dos inteiros. Um racioc´ınio similar
pode ser empregado para justificar as atribuic¸o˜es de varia´veis char a varia´veis de tipo int ou
float, que tambe´m ocorrem sem erros.
O problema e´ quando se tenta atribuir uma varia´vel de um conjunto mais amplo a uma de
um conjunto mais restrito. Veja o Exemplo 2.10.
Observando o Exemplo 2.10, um programador distra´ıdo pode pensar que houve uma atri-
buic¸a˜o correta. Entretanto, o valor armazenado pela varia´vel teste e´ 125. Na˜o havendo condic¸o˜es
de armazenar corretamente (um co´digo de 4 bytes na˜o pode ser escrito num espac¸o de apenas
2 bytes), o compilador simplesmente descarta a parte decimal do nu´mero, armazenando apenas
2.5. CONSTANTES 31
sua parte inteira na varia´vel. Logo, e´ preciso permanecer atento a`s atribuic¸o˜es desse tipo para
na˜o se equivocar sobre o valor armazenado por uma varia´vel.
1 main(){
2 int teste;
3
4 teste = 125.568;
5 }
Exemplo 2.10: Atribuic¸a˜o entre tipos diferentes com perda de informac¸a˜o.
2.5 Constantes
Em algumas situac¸o˜es surge a necessidade de se utilizar um determinado valor constante em
diversas partes do co´digo. Para simplificar a alterac¸a˜o dessas constantes e facilitar a leitura do
co´digo, e´ poss´ıvel definir um nome signicativo para elas de maneira simples, por meio de uma
estrutura espec´ıfica.
Essa estrutura e´ iniciada pela diretiva #define, seguida pelo identificador da constante e
pelo seu respectivo valor, todos separados por um espac¸o em branco.
#define <identificador> <valor>
Na linguagem C, a declarac¸a˜o de constantes deve ser feita no in´ıcio do co´digo, antes da func¸a˜o
main . O Exemplo 2.11 apresenta declarac¸o˜es va´lidas de constantes.
1 #define PI 3.141593
2 #define FALSO 0
3 #define VERDADEIRO 1
4 #define RAIZDEDOIS 1.414214
5
6 main(){
7 float raio , comprimento , area;
8
9 raio = 10;
10 area = PI * raio * raio;
11 comprimento = 2 * PI * raio;
12 }
Exemplo 2.11: Definic¸a˜o de constantes.
Na declarac¸a˜o de constantes, a escolha dos nomes segue as mesmas regras para a escrita dos
nomes de varia´veis. Geralmente, para diferenciar as constantes no co´digo, opta-se por escrever
seus nomes com todas as letras maiu´sculas.
O Exemplo 2.11 mostra um exemplo simples onde diversas constantes sa˜o declaradas de
acordo com a convenc¸a˜o proposta. Durante a compilac¸a˜o do co´digo, o compilador troca tocas
as ocorreˆncias da constante PI por seu respectivo valor, definido na linha 1.
32 CAPI´TULO 2. CONCEITOS BA´SICOS
2.6 Expresso˜es
As varia´veis e constantes podem ser combinadas com os operadores associados a cada tipo de
dados, gerando expresso˜es.
2.6.1 Expresso˜es Aritme´ticas
A expressa˜o aritme´tica e´ aquela cujos operadores e operandos sa˜o de tipos nume´ricos (int ou
float, por exemplo).
Nas operac¸o˜es aritme´ticas, e´ guardada sempre a seguinte relac¸a˜o de prioridade:
1. Multiplicac¸a˜o, divisa˜oe resto de divisa˜o;
2. Adic¸a˜o e subtrac¸a˜o.
Para se obter uma sequ¨eˆncia diferente de ca´lculos, va´rios n´ıveis de pareˆnteses podem ser
usados para quebrar as prioridades definidas. Na˜o e´ permitido o uso de colchetes e chaves, uma
vez que estes s´ımbolos ja´ sa˜o utilizados com outras finalidades. O Exemplo 2.12 exibe uma se´rie
de expresso˜es aritme´ticas va´lidas.
1 main(){
2 int x, y, z;
3
4 x = 10 * 10 + 25; // x = 125
5 y = 5 * (7 + 3); // y = 50
6 z = 10 * ((x - 25) / y + (x - 25) * 2); // z = 2020
7 }
Exemplo 2.12: Expresso˜es aritme´ticas e o uso de pareˆnteses para determinar a precedeˆncia das
operac¸o˜es.
No Exemplo 2.12, e´ importante notar que, no comando de atribuic¸a˜o a` varia´vel x, a multi-
plicac¸a˜o 10 × 10 e´ executada primeiro. Na linha seguinte, a soma 7 + 3 e´ executada primeiro
e seu valor e´, em seguida, multiplicado por 5 e atribu´ıdo a` varia´vel y. A ana´lise da linha 6 e´
deixada para o leitor.
Ale´m das operac¸o˜es ba´sicas ja´ citadas, e´ poss´ıvel usar, nas expresso˜es aritme´ticas, outras
operac¸o˜es bastante comuns na matema´tica, definidas dentro da linguagem na forma de func¸o˜es.
A sintaxe geral para o uso dessas func¸o˜es e´ a seguinte:
<nome da func¸~ao>(<valor>)
Algumas func¸o˜es matema´ticas sa˜o mostradas na Tabela 2.2.
O Exemplo 2.13 exibe va´rios usos de func¸o˜es matema´ticas e expresso˜es aritme´ticas.
2.6. EXPRESSO˜ES 33
Nome Descric¸a˜o
abs Mo´dulo ou valor absoluto de um valor inteiro
fabs Mo´dulo ou valor absoluto de um valor racional
sin Seno de um aˆngulo em radianos
cos Cosseno de um aˆngulo em radianos
sqrt Raiz quadrada de um nu´mero
pow Potenciac¸a˜o
floor Maior inteiro na˜o maior que o nu´mero de entrada
ceil Menor inteiro na˜o menor que o nu´mero de entrada
log Logaritmo neperiano
exp Exponencial
Tabela 2.2: Principais func¸o˜es matema´ticas ja´ definidas na linguagem C.
1 #include <math.h>
2
3 #define PI 3.1415
4
5 main(){
6 float a, b, c, delta , raiz1 , raiz2;
7 float x, y, z;
8
9 a = 10;
10 b = 50;
11 c = 30;
12
13 delta = b * b - 4 * a * c;
14 raiz1 = -b + sqrt(delta) / (2 * a);
15 raiz2 = -b - sqrt(delta) / (2 * a);
16
17 x = sin(-PI / 2);
18 y = fabs(x);
19 z = pow(y,2); // y elevado a` pote^ncia 2
20 }
Exemplo 2.13: Uso de func¸o˜es matema´ticas pre´-definidas.
Para o uso das func¸o˜es matema´ticas apresentadas no Exemplo 2.13 e´ necessa´rio a inclusa˜o
da biblioteca math.h, como na linha 1. Os mesmos ca´lculos para a procura das ra´ızes de uma
equac¸a˜o de segundo grau sa˜o executados nas linhas 13 a 15, onde a func¸a˜o sqrt calcula a raiz
quadrada do seu operando — a varia´vel delta. Ja´ as linhas 15 a 17 apresentam ca´lculos avulsos:
a linha 17 executa o ca´lculo do seno de −pi/2 e armazena o resultado na varia´vel x; a linha
18 armazena, na varia´vel y, o mo´dulo do valor armazenado em x; e a linha 19 calcula o valor
armazenado em y elevado a` poteˆncia de 2 e armazena o resultado na varia´vel z.
34 CAPI´TULO 2. CONCEITOS BA´SICOS
2.6.2 Expresso˜es Relacionais
As expresso˜es relacionais comparam valores entre si. Tal qual se faz na pra´tica, o operador
relacional trabalha com dois valores: o da expressa˜o que esta´ a sua direita e o da expressa˜o que
esta´ a sua esquerda. E´ importante destacar que uma varia´vel ou uma constante isolada, por si
so´, pode ser considerada uma expressa˜o.
A Tabela 2.3 mostra exemplos de operadores relacionais da linguagem C e alguns casos de
uso.
S´ımbolo Nome Exemplo
< menor que a < 10
<= menor ou igual a x <= y
== igual a 4 == 2*2
> maior que t > 0
>= maior ou igual a delta >= 0
!= diferente de x != 9+8*8
Tabela 2.3: Operadores relacionais.
As expresso˜es relacionais resultam sempre em 0 (zero) para uma comparac¸a˜o falsa ou 1 para
uma comparac¸a˜o verdadeira.
As varia´veis do tipo char tambe´m podem ser comparadas entre si, respeitando a ordenac¸a˜o
do padra˜o de codificac¸a˜o utilizado.
E´ importante atentar que, embora sejam escritos de maneira parecida, ha´ uma grande dife-
renc¸a entre o operador de comparac¸a˜o “==” e o comando de atribuic¸a˜o “=”. Essa semelhanc¸a e´
uma fonte comum de erros de programac¸a˜o, geralmente dif´ıceis de detectar.
2.6.3 Expresso˜es Lo´gicas
As expresso˜es lo´gicas sa˜o utilizadas para relacionar os resultados de um conjunto de operac¸o˜es
relacionais. Elas realizam as principais operac¸o˜es da lo´gica booleana e, na linguagem C, teˆm
como operadores:
• “&&” (AND): Realiza o “E” lo´gico;
• “||” (OR): Realiza o “OU” lo´gico;
• “!” (NOT): Realiza a negac¸a˜o.
Os resultados obtidos das expresso˜es lo´gicas tambe´m sa˜o valores do tipo inteiro: 0 para falso
e 1 para verdadeiro.
Para melhor entender o que cada operador realiza, sa˜o levados em conta dois valores P e Q
de entrada, que podem ser verdadeiros (V) ou falsos (F). A Tabela 2.4 resume todos os casos
poss´ıveis.
2.7. COMANDO DE ENTRADA DE DADOS 35
P Q P && Q P || Q !P !Q
V V V V F F
V F F V F V
F V F V V F
F F F F V V
Tabela 2.4: Todas as combinac¸o˜es poss´ıveis para os operadores lo´gicos.
O uso dos operadores relacionais e lo´gicos fica bem mais claro adiante, neste cap´ıtulo, quando
os comandos de selec¸a˜o e repetic¸a˜o sa˜o estudados.
2.7 Comando de Entrada de Dados
O comando de entrada de dados serve para captar do usua´rio do programa um ou mais valores
necessa´rios para a execuc¸a˜o das tarefas. Na verdade, o que se faz e´ ler os dados de uma fonte
externa, normalmente do teclado, para depois usa´-los de alguma maneira dentro do programa.
Por meio desse comando de leitura de dados, uma ou mais varia´veis podem ter seus valores
lidos durante a execuc¸a˜o do programa. Essa caracter´ıstica permite criar programas mais flex´ıveis.
Na linguagem C, a sintaxe para o uso do comando e´ a seguinte:
scanf("<formato1> <formato2> ... <formatoN>", &var1, &var2, ..., &varN);
Essa estrutura e´ dividida em duas partes distintas. A primeira, colocada entre aspas duplas,
conte´m os formatos, os quais sa˜o relacionados diretamente com os tipos das varia´veis a serem
lidas. A segunda parte e´ uma lista dos nomes dessas varia´veis, com uma relac¸a˜o direta entre
a posic¸a˜o nessa lista e o respectivo formato descrito na primeira parte do comando. Conforme
mostra a descric¸a˜o da sintaxe, os nomes das varia´veis devem ser precedidos pelo caractere “&”.
A Tabela 2.5 mostra alguns dos poss´ıveis formatos.
Co´digo Significado
%c Leˆ um u´nico caracter
%d Leˆ um inteiro decimal
%f Leˆ um nu´mero em ponto flutuante
Tabela 2.5: Co´digos para formatos de dados do comando de entrada scanf .
Um exemplo claro da utilidade do comando de entrada de dados e´ o ca´lculo da conta de
energia ele´trica. O exemplo apresentado ate´ agora tinha os valores de consumo e do prec¸o do
quilowatt-hora escritos diretamente no co´digo. Isso e´ bastante incoˆmodo, pois, quando se quer
calcular o valor de uma conta diferente, o co´digo deve ser alterado e recompilado.
Uma maneira de tornar o programa mais flex´ıvel e´ utilizar o comando de entrada de dados.
Com ele, e´ poss´ıvel digitar os valores desejados para as varia´veis e efetuar os ca´lculos para
36 CAPI´TULO 2. CONCEITOS BA´SICOS
diferentes contas, bastando, para isso, executar novamente o programa. O co´digo modificado e´
exibido no Exemplo 2.14.
De acordo com o formato descrito no comando de leitura, os valores das varia´veis leituraA-
tual, leituraAnterior e valorUnitario devem ser digitados pelo usua´rio, nesta ordem, separados
por espac¸os em branco.
1 #include <stdio.h>
2 main(){
3 int leituraAtual , leituraAnterior , diferenca;
4 float valorUnitario , valorConta;
5
6 scanf("%d %d %f", &leituraAtual , &leituraAnterior , &valorUnitario);
7 diferenca = leituraAtual - leituraAnterior;
8 valorConta = diferenca * valorUnitario;
9 }
Exemplo 2.14: Emprego do comando

Continue navegando