Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Em Construo
v0.003.11
18 de fevereiro de 2016
Sumrio
1 Introduo
13
1.1
13
1.2
15
1.2.1
O Incio . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
1.2.2
A Era Moderna . . . . . . . . . . . . . . . . . . . . . . . .
16
1.2.3
18
1.2.4
As Geraes . . . . . . . . . . . . . . . . . . . . . . . . . .
20
O Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
1.3.1
Microcomputadores . . . . . . . . . . . . . . . . . . . . .
22
1.3.2
Memrias . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
1.3.3
Bits e Bytes . . . . . . . . . . . . . . . . . . . . . . . . . .
25
1.3.4
Perifricos . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
1.4
O Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
1.5
Um programa em C . . . . . . . . . . . . . . . . . . . . . . . . .
32
1.3
2 Algoritmos
35
2.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
35
2.2
Primeiros Passos . . . . . . . . . . . . . . . . . . . . . . . . . . .
36
2.3
Representao . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
38
2.3.1
Linguagem Natural . . . . . . . . . . . . . . . . . . . . . .
38
2.3.2
Fluxogramas . . . . . . . . . . . . . . . . . . . . . . . . .
38
2.3.3
Pseudo-Linguagem . . . . . . . . . . . . . . . . . . . . . .
39
2.4
41
2.5
42
2.5.1
Comandos de leitura . . . . . . . . . . . . . . . . . . . . .
43
2.5.2
Comandos de escrita . . . . . . . . . . . . . . . . . . . . .
43
2.5.3
Expresses . . . . . . . . . . . . . . . . . . . . . . . . . .
44
2.5.4
Comandos de atribuio . . . . . . . . . . . . . . . . . . .
46
2.6
2.5.5
Comandos de controle . . . . . . . . . . . . . . . . . . . .
47
2.5.6
Comandos de repetio . . . . . . . . . . . . . . . . . . .
48
Exemplos de Algoritmos . . . . . . . . . . . . . . . . . . . . . . .
49
56
3.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
3.2
Tipos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
3.2.1
Tipos Bsicos . . . . . . . . . . . . . . . . . . . . . . . . .
56
3.2.2
Modificadores de tipos . . . . . . . . . . . . . . . . . . . .
57
Constantes Numricas . . . . . . . . . . . . . . . . . . . . . . . .
57
3.3.1
58
3.3.2
59
3.3.3
60
3.3.4
60
3.3.5
61
Constantes Caracteres . . . . . . . . . . . . . . . . . . . . . . . .
62
3.4.1
63
Variveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
3.5.1
64
3.5.2
Declarao de variveis . . . . . . . . . . . . . . . . . . .
64
3.5.3
Atribuio de valores . . . . . . . . . . . . . . . . . . . . .
65
3.3
3.4
3.5
68
4.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
4.2
Biblioteca Padro . . . . . . . . . . . . . . . . . . . . . . . . . . .
68
4.3
69
4.3.1
Cdigos de Converso . . . . . . . . . . . . . . . . . . . .
70
4.4
72
4.5
74
4.5.1
74
4.5.2
75
4.5.3
76
4.5.4
77
4.5.5
A Funo fgets . . . . . . . . . . . . . . . . . . . . . . .
78
5 Operadores e Expresses
80
5.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
5.2
Operador de Atribuio . . . . . . . . . . . . . . . . . . . . . . .
80
5.3
Operadores Aritmticos . . . . . . . . . . . . . . . . . . . . . . .
81
5.4
82
5.4.1
Operadores Relacionais . . . . . . . . . . . . . . . . . . .
82
5.4.2
Operadores Lgicos
. . . . . . . . . . . . . . . . . . . . .
82
5.5
85
5.6
86
5.7
Operador vrgula . . . . . . . . . . . . . . . . . . . . . . . . . . .
87
5.8
Operador sizeof() . . . . . . . . . . . . . . . . . . . . . . . . . .
87
5.9
Converso de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . .
87
89
6 Comandos de Controle
92
6.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
92
6.2
Blocos de Comandos . . . . . . . . . . . . . . . . . . . . . . . . .
92
6.3
Comandos de Teste . . . . . . . . . . . . . . . . . . . . . . . . . .
92
6.3.1
Comando if . . . . . . . . . . . . . . . . . . . . . . . . . .
93
6.3.2
Comando switch . . . . . . . . . . . . . . . . . . . . . . .
94
6.3.3
Comando Ternrio . . . . . . . . . . . . . . . . . . . . . .
97
6.4
6.5
Laos de Repetio . . . . . . . . . . . . . . . . . . . . . . . . . .
97
6.4.1
Comando for . . . . . . . . . . . . . . . . . . . . . . . . .
97
6.4.2
6.4.3
6.5.2
6.5.3
6.5.4
6.5.5
109
7.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
7.2
7.3
7.4
7.5
7.6
8 Funes
125
8.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
8.2
8.3
8.4
8.5
8.4.1
Variveis Locais
. . . . . . . . . . . . . . . . . . . . . . . 128
8.4.2
8.5.2
8.5.3
8.6
8.7
Recurso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
8.8
8.7.1
8.7.2
9 Ponteiros
145
9.1
Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
9.2
9.2.2
9.2.3
9.2.4
9.2.5
9.3
9.4
9.5
9.6
9.7
9.8
10 Estruturas
. . . . . . . . . . . . . . . . . 153
168
181
. . . . . . . . . . . . . . . . . . . . . . . . . . . 182
199
A Tabela ASCII
210
B Palavras Reservadas
212
Lista de Figuras
1.1
1.2
Imagem de um baco. . . . . . . . . . . . . . . . . . . . . . . . .
15
1.3
Blaise Pascal . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
16
1.4
Charles Babbage . . . . . . . . . . . . . . . . . . . . . . . . . . .
17
1.5
17
1.6
Computador Eniac . . . . . . . . . . . . . . . . . . . . . . . . . .
19
1.7
22
1.8
23
1.9
25
30
2.1
39
2.2
40
2.3
Modelo de memria . . . . . . . . . . . . . . . . . . . . . . . . .
43
2.4
seno. . . . . . .
47
2.5
49
2.6
51
7.1
9.1
9.2
9.3
9.4
9.5
9.6
9.7
ento ...
Lista de Tabelas
1.1
15
1.2
20
1.3
Exemplos de Microprocessadores . . . . . . . . . . . . . . . . . .
23
1.4
26
1.5
Exemplos de perifricos . . . . . . . . . . . . . . . . . . . . . . .
26
2.1
Operadores Aritmticos. . . . . . . . . . . . . . . . . . . . . . . .
46
3.1
58
3.2
59
3.3
Constantes octais . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
3.4
Constantes hexadecimais . . . . . . . . . . . . . . . . . . . . . . .
60
3.5
62
3.6
63
3.7
63
3.8
Tabela do exercicio 6 . . . . . . . . . . . . . . . . . . . . . . . . .
67
4.1
70
5.1
Operadores aritmticos. . . . . . . . . . . . . . . . . . . . . . . .
81
5.2
Operadores Relacionais. . . . . . . . . . . . . . . . . . . . . . . .
82
5.3
Operador Lgico E. . . . . . . . . . . . . . . . . . . . . . . . . . .
83
5.4
84
5.5
84
5.6
84
5.7
85
5.8
85
5.9
89
7.1
Lista de Algoritmos
2.1
Exemplo de Algoritmo. . . . . . . . . . . . . . . . . . . . . . . . .
37
2.2
37
2.3
. . . . .
39
2.4
41
2.5
42
2.6
Comando se em pseudo-linguagem . . . . . . . . . . . . . . . . . .
47
2.7
. . . . . . . . . .
48
2.8
48
2.9
50
2.10 Algoritmo para ler nmeros e imprimir se so pares ou no. A quantidade de nmeros a ser lida de
2.11 Algoritmo para calcular a maior nota de uma turma de 25 alunos.
52
52
53
55
55
3.1
61
Listings
1.1
Exemplo de Programa em C. . . . . . . . . . . . . . . . . . . . .
32
4.1
69
4.2
71
4.3
72
4.4
. . . . . . . . . . . . . . . . . . . . .
74
4.5
75
4.6
76
4.7
76
4.8
. . . . . .
78
5.1
. . . . . . . . . . . . .
86
5.2
. . . . . . . . . . . . . . . . . . .
88
5.3
Variveis da questo 9.
. . . . . . . . . . . . . . . . . . . . . . .
91
6.1
. . . . . . . . . . . . . . . . . . . . . .
94
6.2
95
6.3
Exemplo de switch.
. . . . . . . . . . . . . . . . . . . . . . . . .
98
6.4
99
6.5
6.6
6.7
6.8
6.9
101
. . . . . . . . . . . . 101
. . . . . . . . . . . . . . . . . . . . . . 102
. . . . . . . . . . . . . . . . . 103
. . . . . . . . . . . . . . . . . . . . . 108
7.1
7.2
7.3
7.4
7.5
. . . . . . . . . . . . . . . . . . 111
. . . . . . . . . . . . . . . . . 113
. . . . . . . . . . . . . . . . . . . . . . . 116
10
7.6
7.7
7.8
7.9
. . . . . . . . . . . . . . . . . . 118
. . . . . . . . . . . . . . . . . . . . . 124
8.1
8.2
8.3
8.4
8.5
8.6
8.7
8.8
8.9
. . . . . . . . . . . . . . . . . . . . 130
. . . . . . . . . . . . . . . . 133
. . . . . . . . . . . . . . . 135
. . . . . . . . . . . . . . 136
. . . . . . . . . . . . . . . . . . . . . 137
. . . . . . . . . . . . . . . . . . . . 137
. . . . . . . . . . . . . . . . . . 138
. . . . . . . . . . . . . . . . . . . . . . 139
. . . . . . . . . . . . . . . . . . . . . . 143
9.2
9.3
9.4
9.5
9.6
9.7
9.8
9.9
. . . . . . . . . . . . . . . . . . . 153
. . . . . . . . . . . . . . 150
. . . . . . . . . 154
. . . . . . . . . . . . . . . . . 155
. . . . . . . . . . . . . . . . . . . . . 156
. . . . . . . . 157
. . . . . . . . . . . . 157
. . . . . . . . . . . . . . 158
. . . . . . . . . . . 160
. . 161
. . . . . . . . . . . . . . . . . . . 162
. . . . . . . . . . . . . . . . . . . . . 164
. . . . . . . . . . . . . . . . . . . . . 165
. . . . . . . . . . . . . . . . . . . . . 167
. . . . . . . . . . . . . . . . . 174
. . . . . . . . . . . . . . . 174
. . . . . . . . . . . . . . . . . . . 175
. . . . . . . . . . . . . . . . . . . . . . 179
. . . . . . . . . . . . . . . . . . . . . . . 186
. . . . . . . . . . . . 188
. . . . . . . . . . . . 189
. . . . . . 191
. . . . . . . . . . 193
. . . . . . . . . . . . 195
. . . . . . . . . . . . . 198
12
Captulo 1
Introduo
1.1 Su
essos e Fra
assos da Computao
Os objetivos principais deste captulo so mostrar para o aluno iniciante alguns
aspectos da histria da computao e definir, informalmente, termos e palavraschave que os profissionais da rea de computao usam no seu dia a dia. Adriano
Cruz .
A histria do desenvolvimento dos computadores tem sido impressionante.
O avano da tecnologia e a presena da computao na nossa vida so inegveis. Embora a histria deste fantstico desenvolvimento seja recente e bem
documentada, h lacunas e controvrsias impressionantes sobre diversos pontos.
Neste captulo iremos ver histrias de espionagem e brigas na justia por roubo
de ideias. H oportunidades perdidas e gente que soube aproveitar a sua chance.
H verdades estabelecidas que tiveram de ser revistas.
O avano na tecnologia dos computadores se deu em passos to largos que os
primeiros computadores parecem to distantes no tempo quanto a Pr-Histria.
O aumento de velocidade, desde os anos 40, foi da vrias ordens de grandeza,
enquanto que o custo dos computadores caiu de milhes de dlares para valores em torno de centenas de dlares. As primeiras mquinas tinham milhares
de vlvulas, ocupavam reas enormes e consumiam quilowatts de energia. O
microprocessador Pentium, lanado em 1993, tinha em torno de 3,1 milhes
de transistores, ocupava uma rea de aproximadamente 25 cm2 e consumia
alguns watts de energia, custando aproximadamente 1000 dlares, somente o
microprocessador. A Figura 1.1 mostra a imagem de um circuito integrado de
microprocessador Pentium.
No entanto, esta histria de reduo de tamanho, aumento de velocidade e
diminuio de gasto de potncia, pode, para alguns pesquisadores, j ter uma
data fixada para terminar. Em 1965, Gordon Moore, um dos fundadores da Intel, fabricante do Pentium e uma dos maiores fabricantes de circuitos integrados
do mundo, enunciou o que ficou conhecido como a Lei de Moore: Cada novo
circuito integrado ter o dobro de transistores do anterior e ser lanado dentro
de um intervalo de 18 a 24 meses. Moore achava que esta lei seria vlida somente at 1975, no entanto, ela continua vlida at hoje. Na tabela 1.1, pode-se
observar a evoluo dos microprocessadores usados em nossos computadores.
13
14
Ano
1971
1972
1974
1974
1982
1984
1985
1989
1993
1997
1997
1999
2000
2009
2011
2012
2014
2015
Processador
Intel 4004
Intel 8008
Motorola 6800
Intel 8080
Intel 80286
Motorola 68020
Intel 80386
Intel 80486 DX
Intel Pentium
Intel Pentium II
AMD K6
Intel Pentium III
Intel Pentium 4
AMD Six-core Opteron 2400
Intel Quad-core + GPU Core i7
AMD Quad-core + GPU Trinity
Intel 18-core Xeon Haswell-E5
IBM z13 Storage Controller
Transistores
2.250
2.500
4,100
5.000
120.000
190,000
275.500
1.180.000
3.100.000
7.500.000
8,800,000
24.000.000
42.000.000
904,000,000
1,160,000,000
1,303,000,000
5,560,000,000
7,100,000,000
encontraram os restos de um mecanismo, parecido com um relgio, com aproximadamente 2000 anos de idade. O mecanismo, de grande complexidade, parece
ser um dispositivo para calcular os movimentos de estrelas e planetas.
Em 1823, ele iniciou o projeto de construir uma outra mquina mais avanada e capaz de calcular polinmios de at sexta ordem. Ele esperava terminar
esta mquina em trs anos, mas a construo se arrastou at 1834. Este projeto
que no foi completado, usou dinheiro do governo ingls e possivelmente a maior
parte da fortuna pessoal de Babbage. A mquina, inteiramente mecnica, teria
as seguintes caractersticas:
Arredondamento automtico;
Preciso dupla;
Alarmes para avisar fim de clculo;
Impresso automtica de resultados em placas de cobre.
Em 1834 ele tinha completado os primeiros desenhos da mquina que denominou Analytical Engine que tinha as seguintes caractersticas:
50 dgitos decimais de preciso;
17
18
Operao
soma
multiplicao
diviso
Tempo
200 s
2,8 ms
6,0 ms
assinou uma deciso, em seguida a uma longa batalha judicial, que declarava
a patente do ENIAC de Mauchly e Eckert invlida e atribua a Atanasoff a
inveno computador eletrnico digital, o ABC ou Atanasoff-Berry Computer.
Na Inglaterra
Jnos von Neumann, emigrante hngaro que vivia nos EUA, sugeriu que a
memria do computador deveria ser usada para armazenar as instrues do
computador de maneira codificada, o conceito de programa armazenado. Esta
idia foi fundamental para o progresso da computao. Os primeiros computadores, como o ENIAC, eram programados por fios que os cientistas usavam para
conectar as diversas partes. Quando um programa terminava, estes cientistas
trocavam os fios de posio de acordo com a nova tarefa a ser executada. Com o
programa armazenado na memria, juntamente com os dados, no era mais necessrio interromper as atividades. Carregava-se o programa na memria, uma
tarefa extremamente rpida, junto com os dados e dava-se partida no programa.
Ao trmino da execuo do programa passava-se imediatamente para a prxima
tarefa sem interrupes para troca de fios.
Em 1949, na Inglaterra, dois computadores que usavam a memria para
armazenar tanto programas como dados foram lanados. Na Universidade de
Cambridge foi lanado o EDSAC, (Electronic Delay Storage Automatic Calculator) e em Manchester o computador chamado de Manchester Mark I. O EDSAC
considerado o primeiro computador de programa armazenado a ser lanado.
Curiosamente, a Universidade de Manchester reivindica que o primeiro computador de programa armazenado foi o chamado Baby, um prottipo do Mark I,
que comeou a operar onze meses antes do EDSAC.
Outro fato curioso em relao Inglaterra e que foi divulgado recentemente
relata que um computador chamado COLOSSUS entrou em operao secretamente na Inglaterra em 1943. Este computador foi usado para auxiliar na
quebra dos cdigos de criptografia alemes durante a segunda grande guerra.
1.2.4 As Geraes
Costumava-se dividir os projetos de computadores em geraes. Hoje em dia
como a taxa de evoluo muito grande no se usa mais este tipo de terminologia. No entanto interessante mencionar estas divises.
Primeira Gerao: Os computadores construdos com rels e vlvulas so os
da primeira gerao. Estes computadores consumiam muita energia e
espao.
20
1.3 O Hardware
O hardware corresponde aos circuitos eletrnicos e componentes mecnicos que
compem o computador. Um tpico diagrama em blocos de um computador
digital monoprocessado esta mostrado na Figura 1.7. A Unidade Central
de Processamento (UCP), em ingls Central Processing Unit (CPU), como o
prprio nome diz, a unidade onde os dados so processados, ou seja alterados,
no computador. Ou seja, dentro das UCPs os dados so somados, subtrados
etc. A UCP tambm controla a movimentao dos dados dentro de todo o
sistema. Os mdulos que constituem a UCP so os seguintes:
Unidade de Controle (UC): comanda a operao do computador. Esta unidade l da memria tanto as instrues como os dados e comanda todos
os circuitos para executar cada instruo lida da memria. Atualmente as
unidades de controle so capazes de executar mais de uma instruo por
ciclo de mquina, o que caracteriza o processamento paralelo. A tcnica
mais comum para conseguir este paralelismo conhecida como pipelining,
que ser detalhada mais adiante.
Unidade Aritmtica e Lgica (UAL): local onde as transformaes sobre
os dados acontecem. Atualmente esta unidade bastante sofisticada e
diversos mtodos so empregadas para acelerar a execuo das instrues.
Alguns processadores duplicam circuitos para permitir que mais de uma
operao aritmtica seja executada por vez. muito comum, por exemplo, a existncia de uma unidade aritmtica para executar instrues que
operam sobre nmeros inteiros e outra sobre nmeros reais, chamada de
unidade de ponto flutuante. As vezes a UCP conta com mais de uma de
cada uma destas unidades.
Unidade de Entrada e Sada (UES): controla a comunicao com os usurios do computador e os equipamentos perifricos tais como discos e impressoras. Em alguns computadores mais simples esta unidade no existe
independentemente, sendo distribuda pela Unidade Central de Processamento. Em computadores mais poderosos ao contrrio as Unidades de
Entrada e Sada so computadores completos que foram programados para
controlar a comunicao com os perifricos.
21
Unidade
de
Controle
Unidade
de
Entrada
e
Sada
Memria
Unidade
Arimtica
Discos
Vdeo
Unidade
Central
de
Processamento
1.3.1 Mi
ro
omputadores
Uma UCP integrada em um nico circuito (chip) comumente chamada de
microprocessador . Os microprocessadores atuais incluem outros circuitos que
normalmente ficavam fora da UCP, tais como processadores de ponto flutuante
e memrias cache. Alguns exemplos de microprocessadores so mostrados na
Tabela 1.3
Usualmente se chama de computador, o processador mais os seus perifricos
e os sistemas para controlar estes perifricos, ou seja todo o sistema de processamento de dados. Os perifricos so os dispositivos usados para fazer a entrada
e sada dos dados que sero processados.
Os microcomputadores so computadores baseados em microprocessadores. As assim chamadas placas me dos microprocessadores atuais incluem
diversos componentes que formam o microcomputador. Por exemplo, uma placa
me pode incluir o microprocessador e seus circuitos de suporte, que, no conjunto so conhecidos como o chipset. Alm disso a placa me pode incluir tambm a memria principal e as placas de controle de perifricos, como a placa de
22
Microprocessador
Arquitetura Intel X86
PowerPC
Power
MIPS
ARM
SPARC
Empresa
Intel, AMD
Consrcio Apple/IBM/Motorola
IBM
MIPS Technologies
ARM Technologies
SUN
1.3.2 Memrias
Os dados no computador podem ser armazenados em diversos nveis de memria
semicondutoras ou em perifricos (discos, fitas, etc). Quanto mais rpida a
memria, usualmente mais cara ela . A idia por traz da separao em nveis
colocar mais perto do processador, em memrias rpidas e mais caras, os
dados que o processador ir precisar mais freqentemente. A medida que vamos
nos afastando do processador as memrias vo, ao mesmo tempo, ficando mais
baratas, aumentando de capacidade e diminuindo de velocidade. A Figura 1.8
ilustra esta hierarquia.
PROCESSADOR
MEMRIA
DISCO
CACHE
REGISTRADORES
BYTE
8 BITS
PALAVRA
32 BITS
4 BYTES
Smbolo
Kb
MB
GB
TB
PB
EB
Multiplicador
210 = 1024
220
230
240
250
260
1.3.4 Perifri
os
Como j mencionamos antes, os dados no ficam guardados somente na memria, h tambm os perifricos . H perifricos de entrada, outros de sada
e alguns que servem tanto para entrada como sada de dados. Perifricos no
servem somente para armazenar dados. H perifricos que so usados para permitir a interao entre os usurios e o computador. A tabela 1.5 ilustra alguns
destes perifricos.
Entrada
Teclados
Mouse
CD-ROM
Scanner
Sada
Impressoras
Vdeo
Plotter
Alto-falantes
Ambos
Discos Rgidos
Fitas Magnticas
Disquetes
Discos Zip
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
no software, o que no se v nem se toca, mas tambm est l.
26
Incio
Ligao
Criao de
Algoritmo
Depurao e
Testes
Sim
Codificao do
Algoritmo
Erros de
Execuo?
No
Compilacao do
Programa
Uso do programa
Sim
Sim
Erros de
Compilao?
Erros de
Execuo?
No
30
usurios, espao em discos, uso de memria, tempo que cada programa pode rodar etc. Alguns dos sistemas operacionais conhecidos so os baseados no padro
UNIX, por exemplo o LINUX. Outros sistemas muito usados so os da famlia
Windows.
Compilando Programas Simples em C
Para resolver os exerccios deste livro voc ir precisar de um compilador para a
linguagem C e de um editor de textos simples (no processador como o Word).
O editor pode ser to simples quanto o Notepad, na verdade recomendamos
fortemente que o editor seja simples para que voc possa ter contato com todas
as etapas do processo de desenvolvimento de um programa. Para compilar
empregaremos o compilador gcc que gratuito e pode ser obtido na Internet
como veremos adiante. No ser necessrio nenhum ambiente mais complexo,
tal como um Integrated Development Environment (IDE).
A coleo de compiladores da GNU (GNU Compiler Collection) usualmente
abreviada por gcc, uma coleo de compiladores produzidos pelo projeto GNU.
A abreviao gcc, originalmente, significava GNU C Compiler. Este aplicativo
distribudo gratuitamente pela Free Software Foundation (FSF) sob a licena
GNU GPL e GNU LGPL. Este o compilador padro para os sistemas operacionais livres do tipo Unix, como o LINUX, e diversos sistemas operacionais
proprietrios como o Apple Mac OS X. Atualmente o gcc pode compilar C++,
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
gcc -o teste teste.c -Wall
em uma janela de comandos no sistema Windows ou em um terminal nos sistemas Unix. O sufixo .c no nome do programa normalmente usado para indicar
que o arquivo de um programa C. Este comando deve ser digitado no diretrio
onde est o arquivo fonte teste.c. O arquivo executvel ser armazenado no
mesmo diretrio.
Nos sistemas Unix normalmente o gcc faz parte da distribuio padro e
nada precisa ser feito. No Windows uma maneira fcil de obter uma verso
do gcc instalar o MinGW (Minimalist GNU for Windows). MinGW uma
coleo de arquivos e bibliotecas distribudas livremente as quais combinadas
com outras ferramentas da GNU permitem que programas para Windows sejam
produzidos sem a necessidade de bibliotecas extras e pagas. O MinGW dispe
de um programa instalador que facilita enormemente o processo. Este programa
pode ser obtido no stio oficial do MinGW. Caso aps a instalao, o comando
indicado no funcione uma das razes para a falha pode ser que o sistema operacional no sabe onde se encontra o compilador gcc. Suponha que o programa
gcc foi instalado no diretrio C:\MinGW\bin. Uma soluo digitar o caminho
completo do compilador. Neste caso o comando se torna
C:\MinGW\bin\gcc -o teste teste.c -Wall
Para que no seja necessrio digitar o caminho completo, preciso adicionar este caminho varivel PATH do Windows. Consulte o manual para obter
informaes de como fazer este passo no seu sistema Windows.
31
1.5 Um programa em C
Vamos terminar este captulo mostrando um exemplo simples de programa escrito em C(Listagem 1.1). A nica coisa que este programa faz imprimir Alo
Mundo! e terminar [Kernighan e Ritchie 1978, Schildt 1997, Oliveira 2008].
A primeira linha do programa avisa ao compilador que ir usar funes de
entrada e sada de dados guardadas na biblioteca stdio. Neste caso a funo
usada printf. A segunda linha o incio real do programa. A linha indica que
esta a funo main que todo programa C deve conter, pois nesta funo que
o programa obrigatoriamente comea sua execuo. A funo vai retornar um
valor inteiro (int) ao final de sua execuo e no vai precisar receber nenhum
argumento para sua execuo (void). As chaves ({ e }) marcam o incio e o
fim da funo. Para imprimir o texto Alo Mundo! o programa usa a funo
printf. O incio e o fim do texto a ser impresso so marcados pelo caractere ".
A funo termina com o comando return 0, que avisa ao sistema operacional,
que foi quem iniciou a execuo do programa, que o programa terminou sem
problemas. Este programa simples ilustra alguns das estruturas bsicas que
sero usadas nos programas C que sero apresentados neste livro.
#in
lude
int main
{
}
return
32
Exer
ios
1.1: O que o hardware do computador?
1.2: Quais os principais componentes de um computador?
1.3: Quais as diferenas entre um microprocessador e o microcomputador?
1.4: D exemplos de microprocessadores e de microcomputadores.
1.5: Qual o nmero exato de bytes em 64 Kbytes?
1.6: Se voc j usa computadores, liste alguns aplicativos que voc normalmente
usa.
1.7: Defina Sistema Operacional.
1.8: Qual a diferena bsica entre memrias ROM e RAM?
1.9: Procure em manuais, internet e outras fontes quais so os tempos de acesso
das memrias RAMs atuais.
1.10: Faa trs listas, uma de perifricos de entrada, outra de perifricos de
sada e finalmente uma de perifricos de entrada e sada.
1.11: Explique o que faz um compilador.
1.12: Discuta as vantagens e desvantagens das linguagens interpretadas e as
compiladas.
1.13: O que so erros de compilao e de execuo.
1.14: Procure nomes de linguagens de programao no listadas no texto e diga
quais so as suas caractersticas principais.
1.15: Segundo a Wikipedia, a norma ABNT NBR 14724:2011, sugere que uma
pgina de texto pode conter mais de 3000 caracteres. Nesta questo considere
que uma pgina de texto sempre contm 3000 caracteres e que cada caractere
ocupa 32 bits. Precisamos armazenar 1000 livros e cada um deles contm 200
pginas de texto. Marque o MENOR dos tamanhos de memria abaixo capaz
de conter todos os 1000 livros, ou seja, se mais de um tamanho puder conter os
livros escolha o menor.
(a) 1 Kilo bytes
(b) 1 Mega bytes
(c) 1 Giga bytes
(d) 1 Tera bytes
(e) Nenhuma das respostas anteriores
1.16: Responda as seguintes questes:
33
(a) Um anncio de computadores informa que a velocidade do processador igual a 3.5 Gigahertz. Qual a quantidade exata de Hertz do
processador anunciado?
(b) H duas maneiras de calcular a capacidade de armazenamento de
discos rgidos em termos de 1 Gigabyte de memria. Uma alternativa
usa a base 10 e outra a base 2. Qual a quantidade exata de 1
Gigabyte nas duas maneiras?
1.17: BIOS um software que vem junto com os PCs e o primeiro cdigo executado pelo computador quando ele ligado. A sua principal funo carregar
na memria do computador o sistema operacional e dar incio a sua execuo.
Discuta porque o BIOS fica armazenado em uma memria conhecida como flash,
e que basicamente funciona como uma memria EPROM, enquanto que os programas comuns ficam armazenados na memria principal que composta de
memrias RAM.
1.18: Computadores internamente executam operaes aritmticas na base 2 e
no na base 10 como a que normalmente usamos. Uma representao binria,
muito comum, para nmeros inteiros usa 32 bits ou 4 bytes. Por exemplo, o
nmero inteiro 25 quando convertido para binrio representado por 32 bits
com o seguinte cdigo
00000000000000000000000000011001
No entanto, quando processando texto computadores usam cdigos binrios
diferentes. Por exemplo, o cdigo ASCII muito popular para representar
caracteres que devem ser armazenados na memria. Neste cdigo cada caractere
representado por um cdigo binrio com 8 bits. Encontre uma referncia que
contenha a tabela ASCII e responda como seriam representados os caracteres
2 e 5 usando os cdigos desta tabela.
1.19: Qual a diferena entre um endereo de memria e o contedo de memria?
Explique o conceito de contedo de memria e o de endereo de memria. Se
possvel mostre com figuras ou diagramas.
34
Captulo 2
Algoritmos
2.1 Introduo
O objetivo deste captulo fazer uma breve introduo ao conceito de algoritmos e apresentar algumas formas mais comuns de representar algoritmos para
facilitar o entendimento dos demais captulos deste livro. Iremos apresentar as
construes mais comuns empregadas no desenvolvimento de algoritmos e apresentaremos exemplos bsicos de algoritmos usando algumas destas formas de
representao e construes.
Para resolver um problema no computador necessrio que seja primeiramente encontrada uma maneira de descrever este problema de uma forma clara
e precisa. preciso que encontremos uma seqncia de passos que permitam
que o problema possa ser resolvido de maneira automtica e repetitiva. Alm
disto preciso definir como os dados que sero processados sero armazenados no computador. Portanto, a soluo de um problema por computador
baseada em dois pontos: a seqncia de passos e a forma como os dados sero
armazenados no computador. Esta seqncia de passos chamada de algoritmo.
Usamos algoritmos em diversas atividades que realizamos diariamente. Uma
grande parte destas atividades no esto relacionadas com computao. Um
exemplo simples e prosaico, de como um problema pode ser resolvido caso forneamos uma seqncia de passos que mostrem a maneira de obter a soluo,
uma receita para preparar um bolo.
Uma vez que foi criado um algoritmo para resolver um determinado problema usando computadores passamos para a prxima fase que a escrita deste
algoritmo em alguma linguagem de programao.
A noo de algoritmo central para toda a computao. A criao de algoritmos para resolver os problemas uma das maiores dificuldades dos iniciantes
em programao em computadores. Isto porque no existe um conjunto de regras, ou seja um algoritmo, que nos permita criar algoritmos. Caso isto fosse
possvel a funo de criador de algoritmos desapareceria. Claro que existem
linhas mestras e estruturas bsicas, a partir das quais podemos criar algoritmos, mas a soluo completa depende em grande parte do criador do algoritmo.
35
2.3 Representao
As formas mais comuns de representao de algoritmos so as seguintes:
Linguagem Natural: Os algoritmos so expressos diretamente em linguagem
natural, como nos exemplos anteriores.
Fluxograma Convencional: Esta um representao grfica que emprega
formas geomtricas padronizadas para indicar as diversas aes e decises
que devem ser executadas para resolver o problema.
Pseudo-linguagem: Emprega uma linguagem intermediria entre a linguagem
natural e uma linguagem de programao para descrever os algoritmos.
No existe consenso entre os especialistas sobre qual seria a melhor maneira de representar um algoritmo. Atualmente a maneira mais comum de
representar-se algoritmos atravs de uma pseudo-linguagem ou pseudo-cdigo.
Esta forma de representao tem a vantagem de fazer com que o algoritmo seja
escrito de uma forma que est mais prxima de uma linguagem de programao
de computadores.
2.3.2 Fluxogramas
Esta forma de representao de algoritmos emprega vrias formas geomtricas
para descrever cada uma das possveis aes durante a execuo do algoritmos.
38
Existem algumas formas geomtricas que usualmente so empregadas neste mtodo. Estas formas esto mostradas na Figura 2.1. Cada uma destas formas se
aplica a uma determinada ao como est indicado na figura. Estas formas so
apenas alguns exemplos, existindo outras, no entanto, nesta apostila estas sero
suficientes para os exemplos que sero mostrados.
Incio e Fim de Fluxograma
Processamento
Ponto de Deciso
Impresso de Resultados
2.3.3 Pseudo-Linguagem
Este modo de representar algoritmos procura empregar uma linguagem que esteja o mais prximo possvel de uma linguagem de programao de computadores de alto nvel, mas evitando de definir regras de construo gramatical muito
rgidas. A idia usar as vantagens do emprego da linguagem natural, mas
restringindo o escopo da linguagem. Normalmente estas linguagens so verses
ultra reduzidas de linguagens de alto nvel do tipo Pascal ou C. O algoritmo 2.2
foi escrito em uma pseudo-linguagem. A maioria destas linguagens so muito
39
Incio
Obter a
Obter b
Sim
a =0
No
No h razes
reais
x=-b/a
Imprime x
Fim
3. Executa instruo;
4. Volta para o passo 1 buscando a instruo seguinte na memria.
Portanto, aps a instruo do endereo 0 ser lida da memria e trazida para
a UCP, ela decodificada pela UC, que descobre que a instruo manda carregar
o valor inteiro 2 na posio de memria 10, que chamada de a para facilitar.
A instruo seguinte ordena a carga do valor inteiro 8 na posio de memria
chamada de b, que a posio 11. A ltima instruo ordena a soma dos valores
armazenados em a e b e que o resultado seja armazenado na posio 12, que
chamada c.
Algoritmo 2.5: Modelo de memria e funcionamento de um algoritmo
Armazena 2 na memria no lugar chamado a
a2
Armazena 8 na memria no lugar chamado b
b8
Soma a com b e armazena no lugar chamado c
ca+b
Observe que no modelo de von Neumann instrues e dados ficam na memria. Considere a ltima instruo do programa que pede para que os dados
da posio 10 (a) e 11 (b) sejam somados e o resultado armazenado na posio
12 (c). Para executar esta instruo, o computador faz as seguintes operaes
na memria:
1. ler a instruo no endereo 2;
2. ler o dado a na posio 10;
3. ler o dado b na posio 11;
4. escrever o resultado da soma no endereo 12.
Portanto, temos 3 leituras e uma escrita. Destas operaes, a primeira
uma leitura de instruo e as restantes operaes com dados.
a<-2
b<-8
12
13
14
15
c<-a+b
9
10
11
10
16
17
18
19
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
imprimir x
imprime o valor atual que est na memria representada pelo nome x.
Da mesma forma que nos comandos de leitura possvel colocar uma lista
de nomes de variveis aps o comando. Por exemplo, o comando
imprimir x1, x2
imprime os valores das variveis x1 e x2. O meio de apresentao dos resultados,
normalmente, um monitor de vdeo.
O comando imprimir pode ser usado para mandar mensagens de texto
para o usurio do algoritmo das formas mais variadas. Alguns exemplos de
comandos de impresso so os seguintes:
2.5.3 Expresses
Expresses so usadas para definir os clculos requeridos pelo algoritmo, por
exemplo b/a. Iremos discutir dois tipos bsicos de expresses: expresses aritmticas e expresses lgicas.
Expresses manipulam dados dentro dos algoritmos. Uma pergunta importante neste momento : que tipo de dados poderemos manipular? As linguagens
de programao normalmente estabelecem regras precisas para definir que tipos
de dados elas iro manipular. Nesta discusso vamos estabelecer, ainda que
informalmente, algumas regras que limitam os conjuntos de dados existentes na
Matemtica e estabelecem que dados podero ser manipulados pelos algoritmos.
Isto ocorre porque os computadores possuem limitaes que os impedem de manipular todos os tipos de dados que um ser humano pode tratar. Mais adiante,
quando formos estudar a linguagem C iremos apresentar mais formalmente as
regras desta linguagem para estas representaes. Existem trs tipos bsicos de
dados que iremos discutir:
Dados numricos: como o nome indica so os nmeros que sero operados.
Dados alfa-numricos: so os dados representados por caracteres. Como caracteres podem ser letras, algarismos e sinais diversos estes dados recebem
este nome.
44
Dados Lgicos: estes dados podem assumir dois valores verdadeiro e falso.
Estes dados resultam de expresses do tipo x > 0.
Os dados numricos que os algoritmos que iremos construir podem manipular
so de dois tipos: inteiros e reais. So exemplos de nmeros inteiros:
+3
3
-324
-50
So exemplos de nmeros reais:
+0.5
0.5
-8.175
2.0
Dados alfa-numricos servem para tratamento de textos e normalmente so
compostos por uma seqncia de caracteres contendo letras, algarismos e caracteres de pontuao. Nos algoritmos so normalmente representados por uma
seqncia de caracteres entre aspas, por exemplo:
Linguagem de programao
Qual o seu nome?
12345
Dados lgicos so intensamente aplicados durante o processo de tomada
de decises que o computador frequentemente obrigado a fazer. Em muitos
textos este tipo de dados tambm chamado de tipo de dados booleanos, devido
a George Boole, matemtico que deu ao nome lgebra (lgebra booleana) que
manipula este tipo de dados. Os dados deste tipo somente podem assumir
dois valores: verdadeiro e falso. Computadores tomam decises, durante o
processamento de um algoritmo, baseados nestes dois valores. Por exemplo,
considere a deciso abaixo:
se a = 0 ento
imprimir A equao nao tem soluo
seno
x b/a
imprimir A raiz da equao vale , x
fim se
Neste algoritmo aparece a expresso a = 0, que procura descobrir se o valor
de raiz igual a 0. Esta expresso somente pode ter como resultado os valores:
verdadeiro ou falso. Nos nossos algoritmos estes valores sero representados por
verdadeiro e falso.
45
Expresses Aritmticas
Para os nossos exemplos iniciais iremos adotar os operadores aritmticos binrios mostrados na Tabela 2.1. A coluna prioridade indica a prioridade relativa
dos operandos. O menor nmero indica a maior prioridade. Quando temos
dois operandos de mesma prioridade o computador ir executar primeiro a operao mais esquerda. Em computao, as expresses devem ser escritas em
linhas e para alterar a prioridade deve-se usar parnteses. Maiores detalhes
sobre expresses sero apresentados no Captulo 5. No momento, estamos apenas apresentando alguns conceitos bsicos para facilitar a discusso de alguns
algoritmos.
Operador
/
*
%
+
-
Descrio
Diviso
Multiplicao
Mdulo (resto da diviso de
operandos inteiros)
Soma
Subtrao
Prioridade
0
0
0
1
1
b 4ac
1
1
1+ a+b
Expresso em
Pseudo-linguagem
a/(b+c)
(a+b)/(c+d)
b*b-4*a*c
1/(1 + 1/(a+b))
da seta. A direo da seta no pode ser alterada. No caso da ltima expresso temos que o valor atual de i incrementado e depois substitui este valor,
portanto, se ele valia 10, ao final da instruo ele vale 11.
Algoritmando
Falso
Condio
Verdadeiro
Faa isto
Faa aquilo
Continuo
algoritmando
ento ...
seno.
Vestir para
ir ao cinema
Falso
Chovendo?
Verdadeiro
Pegar
guarda-chuva
Ir ao
cinema
vamos considerar que caso o resto da diviso seja igual a zero o nmero par.
Neste algoritmo sabemos a quantidade de nmeros a serem lidos e portanto o
nmero de repeties pr-determinado. O Algoritmo 2.9 mostra como seria
implementada uma soluo para este problema.
Vamos mostrar um exemplo onde o nmero de repeties no conhecido.
Considere no exemplo anterior que o total de nmeros a ser lido no conhecido.
Mas ento, como o algoritmo ir terminar de ler nmeros? Usaremos o que
costuma-se chamar de sentinela em computao. O algoritmo ir se manter
lendo nmeros enquanto os nmeros forem positivos. No momento que for
lido um nmero negativo o algoritmo pra. A sentinela que indica o final da
lista de nmeros um nmero negativo. O Algoritmo 2.10 mostra como fica
em pseudo-linguagem o algoritmo modificado. Observe que neste algoritmo o
primeiro nmero tem de ser lido antes do comando enquanto. Isto porque
assumimos que o primeiro nmero que for digitado pode ser negativo e portanto
a lista de nmeros no tem nenhum nmero.
50
Algoritmando
Falso
Testa
Condio
Verdadeiro
Bloco de comandos
do enquanto
Continuo
algoritmando
caso ela seja maior substitui o valor anterior pelo novo valor. Observar que
criamos uma varivel para armazenar a quantidade de alunos. Voc poderia
perguntar porque no usar o nmero 25 toda vez que for necessrio. A razo
simples. Suponha que voc gostaria de usar este algoritmo para calcular a maior
nota de uma turma de 40 alunos. Neste algoritmo bastaria substituir o nmero
25 por 40. No entanto, existe uma soluo mais geral ainda que permite que
o algoritmo possa ser usado para qualquer tamanho de turma. Este problema
est apresentado na lista de exerccios deste captulo.
Exemplo 2.2: Vamos mostrar outro exemplo de algoritmo muito usado. Precisamos ler as notas de uma turma de alunos e calcular a mdia destas notas.
Vamos assumir que a turma tem 25 alunos e as notas esto entre 0 e 10. O
algoritmo est mostrado em Algoritmo 2.12.
Exemplo 2.3: Neste exemplo considere o seguinte problema. Um escritrio de
previso do tempo armazena diariamente a temperatura mdia de uma determinada regio. A tarefa descobrir qual a maior temperatura do ano passado.
Assuma que foram armazenadas 365 temperaturas, uma para cada dia do ano.
Neste caso no podemos aplicar o algoritmo 2.11 usado para descobrir a maior
nota da turma. Antes de continuar procure encontrar a razo. Como dica,
considere que estamos no plo sul e portanto todas as temperaturas lidas so
negativas.
Uma soluo possvel para este exemplo est mostrada no algoritmo 2.13.
Este algoritmo faz o seguinte. Pega a primeira temperatura e a anota como a
maior j encontrada. A partir da o algoritmo fica repetidamente lendo tem51
52
53
Exer
ios
2.1: Uma empresa paga R$10.00 por hora normal trabalhada e R$ 15.00 por
hora extra. Escreva um algoritmo que leia o total de horas normais e o total
de horas extras trabalhadas por um empregado em um ano e calcule o salrio
anual deste trabalhador.
2.2: Assuma que o trabalhador do exerccio anterior deve pagar 10% de imposto
se o seu salrio anual for menor ou igual a R$ 12000.00. Caso o salrio seja maior
que este valor o imposto devido igual a 10% sobre R$ 12000.00 mais 25% sobre
o que passar de R$ 12000.00. Escreva um programa que calcule o imposto devido
pelo trabalhador.
2.3: Escreva um algoritmo que descubra a maior nota de uma turma de alunos.
O tamanho da turma deve ser o primeiro dado pedido ao usurio.
2.4: Modifique o algoritmo anterior de modo que ele imprima tambm quantas
vezes a maior nota aparece.
2.5: Nos exerccios anteriores assumimos que os usurios sempre digitam uma
nota entre 0 e 10. Vamos assumir agora que o usurio sempre digita um nmero,
mas este nmero pode estar fora do intervalo 0 a 10. Ou seja, poderemos ter
uma nota menor que zero ou maior que 10. Modifique o algoritmo anterior
para que ele verifique a nota digitada e, caso o aluno tenha digitado uma nota
invlida, uma mensagem avisando o usurio seja impressa e uma nova nota seja
pedida. O algoritmo deve insistir at que o usurio digite um valor vlido.
2.6: Escreva um programa que leia um conjunto de 100 temperaturas e imprima
a menor temperatura lida. Observe que temperaturas podem assumir valores
menores do que zero.
2.7: Escreva um algoritmo que leia trs nmeros e os imprima em ordem crescente.
2.8: Escreva um algoritmo que leia um nmero inteiro entre 100 e 999 e imprima
na sada cada um dos algarismos que compem o nmero. Observe que o nmero
lido com um valor inteiro, e, portanto, ele tem de ser decomposto em trs
nmeros: os algarismos das centenas, dezenas e unidades.
2.9: Escreva um algoritmo que leia uma hora em horas, minutos e segundos e
some um segundo a hora lida.
2.10: Escreva um algoritmo que leia duas datas em dia, ms e ano e imprima
a data mais recente.
2.11: Um aluno est escrevendo um programa que l uma nota no intervalo
entre 0 e 100, inclusive. Foi pedido ao aluno que o programa aceite as notas
vlidas e rejeite as invlidas. Marque a letra que mostra a expresso que falta
no trecho pontilhado do algoritmo mostrado em 2.14.
(a) (nota < 0) e (nota > 100)
(b) (nota <= 0) e (nota >= 100)
54
55
Captulo 3
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
float
double
long double
Bytes
1
1
1
4
4
4
2
2
2
4
4
4
Faixa Mnima
-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
8
4
8
12
0 a 18.446.744.073.709.551.615
oito dgitos de preciso
16 dgitos de preciso
16 dgitos de preciso
ponto_decimal: .
sufixo: sufixo_sem_sinal, sufixo_longo
sufixo_sem_sinal: u, U
sufixo_longo: l, L
sufixo_flutuante: f, F, l, L
O uso destas caracteres ser mostrado com exemplos nas sees seguintes.
1997
1997U
1234L
1997UL
134LL
1997ULL
Constantes
-3
+5
45u 12345U
1997L
-3l
45Lu
23Ul
1997Ll
-3ll
45LLu
23Ull
7
0U
+0L
0LU
+0LL
0LLU
59
Base 8
025
077
011
010ul
0175
Base 10
21
63
9
8
125
Base 10
15
37
171
48879
(3.1)
Esta equao est escrita na base 10. Por exemplo, aplicando a equao 3.1
para converter o nmero 0175 da base 8 para a base 10 ficamos com
(0175)8 = 1 82 + 7 81 + 5 80 = (125)10
60
(3.2)
Vamos considerar a contante inteira (3AF )16 . Aplicando a frmula 3.2 temos
(3AF )16 = 3 162 + 10 161 + 15 160 = (943)10
O algoritmo para converter um nmero inteiro da base 10 para uma determinada base b feito por um conjunto de divises sucessivas do nmero pela base
at que o resultado da diviso seja 0. O Algoritmo 3.1 mostra como converter
um nmero (N )10 para uma base b. importante notar que os algarismos na
base b vo sendo impressos na ordem inversa, do menos significativo para o mais
significativo. Por exemplo, caso forneamos para o algoritmo o nmero (943)10
e a base 16, o algoritmo iria imprimir os resultados 15, 10 e 3 nesta ordem. Isto
corresponderia aos seguintes dgitos da base 16: F, A e 3 e, portanto, a resposta
seria (3AF )16 .
Algoritmo 3.1: Algoritmo para converter inteiros na base 10 para uma
base b.
Entrada: nmero, (numero) e base b (baseb).
Sada: Dgitos do nmero na base b
inicio
ler numero
ler base
enquanto numero > 0 faa
resto numero % base
numero numero / base
imprimir resto
fim enqto
fin
Nmero
+23.45e-10
123.45
123.45E+10
123.45F
123.
Caractere
a
A
\0141
(
9
\n
Significado
caractere a
caractere A
Constante octal correspondente ao caractere a
caractere abre parnteses
algarismo 9
Nova linha, posiciona o cursor no incio da nova linha.
Tabela 3.6: Exemplos de constantes caractere
Caractere
\n
\t
\b
\f
\r
\a
\0
Significado
Passa para uma nova linha.
Tabulao horizontal, move o cursor
para a prxima parada de tabulao.
Retorna um caractere.
Salta uma pgina.
Carriage return, posiciona o cursor
no incio da linha atual.
Alerta, faz soar a campainha do sistema.
Null, caractere que em C termina
uma cadeia de caracteres.
63
3.5 Variveis
Variveis so nomes dados para posies de memria a fim de facilitar o manuseio dos dados durante a criao dos programas. Os dados podem ser de
qualquer dos tipos definidos para a linguagem C.
total
salarioMensal
nome
taxa_imposto
raio
_inicio
tipo lista_de_variveis;
onde uma lista_de_variveis uma lista de nomes de variveis separadas
por vrgulas. Por exemplo:
int i ;
unsigned int a , b ,
;
unsigned short int dia ,
f l o a t raio , diametro ;
double salario ;
mes , ano ;
int i = 0 , j = 10;
f l o a t raio = 2.54;
har
= 'd ';
double pre
isao = 0.00001 L ;
A seguir mostramos um trecho de programa com exemplos de atribuio de
valores aps a definio das variveis.
int i , j ;
f l o a t raio ;
har
;
i = 0;
j = 10;
raio = 2.54;
= 'd ';
65
Exer
ios
3.1: Indique os nomes de variveis que so vlidos. Justifique os nomes invlidos.
(a) tempo
(e) 2dias
(b) nota_final (f) teste 1
(c) us$
(g) raio.do.circulo
(d) char
(h) DiaHoje
3.2: Marque a letra que contm pelo menos um nome de varivel invlido.
(a)
(b)
(c)
(d)
(e)
3.3: Indique quais dos nmeros abaixo so constantes inteiras (longas ou no)
vlidas. Justifique suas respostas.
(a) 100
(e) - 234
(b) 2 345 123 (f) 0L
(c) 3.0
(g) 21
(d) -35
(h) 0xF1
3.4: Qual o valor na base 10 das constantes abaixo?
(a)
(b)
(c)
(d)
025
0123
0xD
0x1D
66
Descrio
total de alunos em uma sala
a nota de aluno em Computao I
Primeira letra de um nome
pontos de um jogador de voleibol ao final do ano;
o raio de um crculo.
Tabela 3.8: Tabela do exercicio 6
67
Tipo da varivel
Captulo 4
#in lude
<stdio.h>
no incio do programa.
A diretiva #in
lude instrui o compilador a ler o arquivo indicado entre <
e >, e process-lo como se ele fosse parte do arquivo original e seu contedo
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
um diretrio especfico de localizao pr-definida, onde esto os arquivos de
68
int
69
Comentrio
Caracter simples
Inteiro decimal com sinal
Inteiro decimal com sinal
Real em notao cientfica com E
Real em notao cientfica com e
Real em ponto flutuante
%E ou %f, o que for mais curto
%g ou %f, o que for mais curto
Inteiro em base octal
Cadeia Caracteres
Inteiro decimal sem sinal
Inteiro em base hexadecimal (letras minsculas)
Inteiro em base hexadecimal (letras maisculas)
Endereo de memria
Imprime o caractere %
70
return
0;
return
0;
O resultado e = 0.333
.
Alo
Nos exemplos anteriores verifique que \n no impresso. A barra inclinada
chamada de seqencia de escape, indicando que o prximo caractere no para
ser impresso mas representa caracteres invisveis ou caracteres que no esto
representados no teclado. Esta seqncia de escape indica que o programa deve
passar a imprimir na prxima linha.
Uma diferena fundamental que existe entre esta funo e a funo printf
est nos argumentos que vm depois do controle. No caso de s
anf os argumentos so os endereos das variveis que iro receber os valores lidos e no,
como em printf, as prprias variveis. A indicao que estamos referenciando
um endereo e no a varivel se faz pelo operador &. Por exemplo, o comando
s
anf("%d %d", &a, &b);
espera que dois valores inteiros sejam digitados no teclado. O primeiro armazenado na varivel a e o segundo em b. Os valores sero armazenados diretamente
nos endereos indicados por &a e &b respectivamente.
Um outro exemplo incluindo variveis reais :
int i ;
float x;
72
73
int
int
74
return
0;
har
nome [41;
#define DIM 40
#in
lude < stdio .h >
int main ( void ) {
har nome [ DIM ;
76
Considere que este programa se chama util. Uma possvel interao entre
este programa e um usurio poderia ser da seguinte maneira.
$ util
Por favor, qual o seu nome?
Ze Sa
Sou um computador. Posso ajuda-lo Ze?
O smbolo $ o prompt tpico dos sistemas Unix. Aparentemente o computador se tornou ntimo do usurio Ze Sa e o tratou apenas pelo primeiro nome. A
explicao para esta intimidade est no modo de leitura. Quando se usa scanf
para ler uma cadeia deve-se empregar o cdigo de converso %s. Este comando
no l o nome todo, mas encerra a leitura dos caracteres quando encontra um
caractere espao (ou branco), ou seja o separador de cadeias no comando s
anf
o caractere espao. Mas como ler para um vetor um nome inteiro, ou um
cadeia que contenha brancos? Para isto deve-se usar a funo gets que ser
nosso prximo assunto.
* str ) ;
77
#define DIM 41
#in
lude < stdio .h >
int main ( void ) {
har nome [ DIM ;
* str ,
int
A funo fgets l no mximo um caractere a menos que o nmero de caracteres especificado no parmetro tam a partir do fluxo de entrada de dados
definido por fluxo. No caso de leitura do teclado, como temos feito, fluxo
igual a stdin. A leitura interrompida quando um caractere <enter> encontrado ou o final do arquivo foi atingido. Diferentemente do que ocorre na
funo gets, aqui o caractere <enter> armazenado no vetor onde os demais
caracteres esto sendo guardados. O caractere nulo adicionado aps o ltimo
caractere lido.
A funo retorna str caso seja bem sucedida. Se o final do arquivo for
atingido e nenhum caractere tiver sido lido, o vetor str permanece inalterado
e um ponteiro nulo retornado. Caso ocorra um erro de leitura o contedo do
vetor fica indeterminado e um ponteiro nulo retornado.
78
Exer
ios
4.1: Escreva um programa que declare variveis do tipo int, char e float,
inicialize-as, e imprima os seus valores.
4.2: Escreva um programa que defina variveis do tipo int e armazene nelas
constantes octais e hexadecimais e imprima o seu contedo no formato original
e em formato decimal.
4.3: Faa um programa que leia um valor inteiro no formato decimal e escreva,
na tela, este mesmo valor nas bases hexadecimal e octal.
Exemplo de Entrada e Sada:
Entre com o valor:
10
Hexadecimal: A
Octal: 12
4.4: Faa um programa capaz de ler um valor real e escrev-lo com apenas uma
casa decimal.
4.5: Faa um programa que leia trs palavras de at 10 letras e reescreva estas
palavras alinhadas direita da tela.
4.6: Sabendo que os argumentos da funo printf podem ser expresses (a+b,
a/b, a*b, 3*a...), e no somente argumentos, faa um programa capaz de ler
um valor inteiro e escrever seu triplo, seu quadrado, e a sua metade.
Exemplo de Entrada e Sada:
Valor:
6
Triplo: 18
Quadrado: 36
Meio: 3
4.7: Escreva um programa que leia 3 nmeros reais e imprima a mdia aritmtica destes nmeros.
4.8: Escreva um programa que pegue o valor de uma conta de restaurante e
imprima o valor total a ser pago, considerando que o restaurante cobra 10% de
taxa para os atendentes.
4.9: Faa um programa que pea ao usurio a quilometragem atual, a quilometragem anterior, os litros consumidos e informe a taxa de consumo (quilmetros
por litro) de um automvel.
4.10: Escreva um programa que converta uma temperatura de Farenheit para
Celsius.
4.11: Escreva um programa que, dado o permetro de um crculo, calcule sua
rea.
4.12: Faa um programa que utilize a funo gets para ler duas cadeias de
tamanho at 20 e em seguia s reescreva na linha de baixo, uma ao lado da
outra e separadas por "/-/ ";
79
Captulo 5
Operadores e Expresses
5.1 Introduo
O objetivo deste captulo apresentar os operadores existentes na linguagem
C e a forma correta de construir expresses que envolvam estes operadores,
constantes e variveis.
*
/
%
+
-
Descrio
Mais unrio
Menos unrio
Incremento
Decremento
Multiplicao
Diviso
Resto da diviso
Soma
Subtrao
Prioridade
0
0
1
1
2
2
2
3
3
b
b+c
= a + b/(b+c)
2. b2 + c2 = b*b + c*c
3.
x
a+ cb
= x/(a+b/c)
Descrio
Maior ou igual a
Maior que
Menor ou igual a
Menor que
Igual a
Diferente de
Prioridade
0
0
0
0
1
1
int i = 3 , j =
f l o a t z = 3.0;
int resultado ;
-5;
q
0
1
0
1
p && q
0
0
0
1
OU lgico
O smbolo usado para representar o operador OU lgico ||. A Tabela 5.4
mostra a tabela verdade do operador. Para que o resultado da expresso seja
verdade basta que uma das variveis seja verdade. Por exemplo, considere o
seguinte trecho de programa:
f l o a t x = 3.0;
int n = 55 , i =
int resultado ;
0;
p
0
0
1
1
q
0
1
0
1
p || q
0
1
1
1
No lgico
O smbolo usado para representar o operador NO lgico !. A Tabela 5.5
mostra a tabela verdade do operador. Este operador unrio e quando aplicado
uma varivel ele troca seu valor. Por exemplo, considere o seguinte trecho de
programa:
int
int
!p
1
0
Prioridade
0
1
2
3
4
84
~
&
^
|
Descrio
Desloca para direita
Desloca para esquerda
No
E
Ou exclusivo
OU
Prioridade
0
0
1
2
3
4
q
0
1
0
1
p ^ q
0
1
1
0
Um deslocamento para a direita equivalente a uma diviso por 2. Deslocamento para a esquerda equivalente a uma multiplicao por 2. Assim
a = a * 2; e a = a 1; so equivalentes.
O exemplo 5.1 ilustra o uso dos operandos de deslocamento:
= 7;
return
0;
=
=
=
=
0000000E
00000007
FFFFFFF2
FFFFFFF9
raiz = raiz * 4;
raiz *= 4;
soma = soma / ( a + b);
soma /= (a + b);
a = a 1;
a = 1;
i = i % 2;
i %= 2;
em
de
do
do
do
do
87
#define DIM 10
#in
lude < stdio .h >
#in
lude <
onio .h >
int main () {
int i =0;
f l o a t f =3.0;
har
= 'a ';
int v [ DIM ;
5.10
A Tabela 5.9 mostra, em ordem decrescente de prioridade, as regras de precedncia dos operadores em C. Os operadores que esto na mesma linha da tabela
e com a mesma ordem tm a mesma prioridade. Alguns dos operadores listados
na Tabela somente sero mostrados nos captulos seguintes.
Pri
0
1
1
2
3
4
5
6
7
8
9
10
11
12
13
13
14
Operador
() [] -> .
! ++ * &
(tipo) sizeof()
* / %
+
< <= >= >
== !=
&
^
|
&&
||
? () : ()
= += -= *= /= %=
= = &= |=
,
Descrio
Agrupamento; acesso vetor; acesso membro
Unrias lgicas, aritmticas e com ponteiros;
Conformao de tipo; tamanho
Multiplicao, diviso e mdulo
soma e subtrao
Deslocamento de bits direita e esquerda
Operadores relacionais
Igualdade e diferena
E bit a bit
Ou exclusivo bit a bit
Ou bit a bit
E
Ou
Ternrio
Atribuies
Atribuies
Separador de expresses
89
Exer
ios
5.1: Escreva as expresses C abaixo na sua forma matemtica usual:
1. (a/b)*(c/d)
2. (a/b*c/d)
3. (a/(b*c)/d)
4. a*x*x+b*x+c
5.2: Escreva as expresses matemticas na linguagem C.
1. b2 4 b c
2.
3.
1
1+
1+
1
1
1+x
a+b
c+d
4. a
x
c+d
f l o a t salario ;
int tempo ;
(a) (salario <= 400.00) && (salario >= 1000.00) && (tempo > 5)
(b) (salario <= 400.00) || (salario >= 1000.00) && (tempo > 5)
(c) ((salario <= 400.00) || (salario >= 1000.00)) || (tempo >
5)
(d) ((salario <= 400.00) || (salario >= 1000.00)) && (tempo >
5)
(e) ((salario <= 400.00) && (salario >= 1000.00)) || (tempo >
5)
91
Captulo 6
Comandos de Controle
6.1 Introduo
Este captulo tem por objetivo apresentar os comandos de controle da linguagem
C. Estes comandos servem para controlar o fluxo de execuo das instrues
de um programa. Estes comandos permitem que o computador tome decises
independentemente do usurio que est rodando o programa.
6.3.1 Comando if
O comando if utilizado quando for necessrio escolher entre dois caminhos.
A forma geral do comando if a seguinte:
if
( expresso )
blo
o_de_
o ma n do s 1 ;
else
blo o_de_ o ma n do s 2 ;
if
( expresso )
blo
o_de_
om a nd o s ;
if
( expresso )
blo
o_de_
o ma nd o s
e l s e i f ( expresso1 )
blo
o_de_
o m an d os 1
e l s e i f ( expresso2 )
blo
o_de_
o ma nd o s2
...
else
blo o_de_ o ma nd o sn
93
else
if
( expresso )
blo
o_de_
om a nd o s ;
e l s e i f ( expresso )
blo
o_de_
om a nd o s ;
e l s e i f ( expresso )
blo
o_de_
om a nd o s ;
...
e l s e blo
o_de_
o ma n do s ;
94
/* primeiro operando */
num2 ,
/* segundo operando */
res ; /* resultado da opera
ao */
oper ;
/*
ara
tere que define a opera
ao */
95
a escrita de trechos de programa em que a seleo deve ser feita entre vrias
alternativas.
A forma geral do comando switch a seguinte:
swit
h ( expresso ) {
ase
onstante1 :
seqn ia_ d e _ o ma n d os ;
ase
break ;
onstante2 :
seqn
ia_ d e _
o ma n d os ;
break ;
ase
onstante3 :
seqn
ia_ d e _
o ma n d os ;
break ;
...
default :
seqn
ia_ d e_
om a n do s ;
expresso2 :
expresso3
Para avaliar o resultado total da expresso, primeiro a expresso1 avaliada. Caso este resultado seja correspondente ao valor verdadeiro ento o
resultado da expresso ser igual ao resultado da expresso2. Caso contrrio
a expresso3 avaliada e se torna o resultado. O programa 6.4 mostra um
exemplo de uso de comando ternrio.
for
97
/* primeiro operando */
/* segundo operando */
/* resultado da opera
ao */
/*
ara
ter que define a opera
ao
98
/* primeiro operando */
/* segundo operando */
/* resultado da opera
ao */
for
}
99
main () {
int numero , fat =1 , i ;
printf ( " \ nEntre
om um numero positivo . " ) ;
s
anf ( " % d " , & numero ) ;
for ( i = numero ; i >1; i - -) fat = fat * i ;
printf ( " O fatorial de % u vale % u . " , numero , fat ) ;
return 0;
int
for
}
i,j;
( i =1 , j = 10; i <= 10; i ++ , j += 10) {
printf ( " i = %d , j = % d \ n " , i , j ) ;
Listagem 6.6: Exemplo de comando for com testes sobre outras variveis.
return
0;
!= -1 ; ) {
printf ( " % d \ n " ,i ) ;
s
anf ( " % d " , & i ) ;
return
0;
i ++) {
printf ( " numero % d \ n " , i ) ;
i f ( i == 5) break ;
return
0;
Lao infinito
Uma construo muito utilizada o lao infinito. No lao infinito o programa
pra quando se executa o comando break. O trecho de programa a seguir
somente pra quando for digitada a tecla s ou S .
for
( ; ; ) {
printf ( " \ nVo
e quer parar ?\ n " ) ;
= get
har () ;
i f (
== 'S ' ||
== 's ') break ;
101
while
( expresso )
blo
o_de_
o ma nd o s
102
i = 1;
while
( i <= 100) {
printf ( " Numero % d \ n " , i ) ;
i ++;
while
do
blo
o_de_
o ma nd o s
( expresso ) ;
while
i = 1;
{
printf ( " Numero % d \ n " , i ) ;
i ++;
} while ( i <= 100) ;
do
for
for
105
Exer
ios
6.1: Escreva um programa que calcule x elevado a n. Assuma que n um valor
inteiro.
6.2: Escreva um programa que exiba as opes
1-multiplicar e 2-somar
de um menu, leia a opo desejada, leia dois valores, execute a operao (utilizando o comando if) e exiba o resultado.
6.3: Utilizando ifs em escada, inclua, no programa do exerccio anterior, as
opes 3-Subtrair e 4-Dividir.
6.4: Simplifique os programas anteriores da seguinte forma:
Reescreva o programa do exerccio 1 substituindo o comando if pelo comando ternrio.
Reescreva o programa do exerccio 2 substituindo os ifs em escada pelo
comando switch.
6.5: Utilizando um lao for dentro de outro, escreva um programa que exiba
as tabuadas de multiplicao dos nmeros de 1 9.
6.6: Escreva um programa com menu de 5 opes que utilize o comando de
desvio goto para executar a opo desejada e s saia do programa caso a opo
5-Sair seja selecionada.
6.7:Escreva um programa que tenha um nmero (inteiro) como entrada do
usurio e escreva como sada a seqencia de bits que forma esse numero. Por
exemplo, aps digitado o nmero 10, a sada deve ser 0000000000001010.
6.8:Escreva um programa que imprima todos os pares entre 0 e 50 e em seguida
imprima todos os impares. Deixar um espao entre os nmeros.
6.9: Escreva um programa que leia 10 nmeros. O programa deve imprimir a
media, o maior e o menor deles.
Obs: Os nmeros devem ser entre 0 e 10.
6.10: Escreva um programa que leia 10 nmeros. O programa deve imprimir a
media, o maior e o menor deles.
Obs: Considere agora que os nmeros podem ser quaisquer.
6.11: Escreva um programa que exibe a tabela ascii.
6.12: Crie um programa para verificar se um nmero dado primo.
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
987654321876543217654321654321543214321321211
106
9*9*9=729
Faa seu programa dar uma pausa a cada 20 linhas para que seja possvel
ver todos os nmeros pouco a pouco. Solicite que seja pressionada alguma tecla
para ver a prxima seqncia de nmeros.
6.16:
Escreva um programa que imprima uma figura como a mostrada abaixo. O
nmero de linhas da figura deve ser pedido ao usurio.
******
*****
****
***
**
*
6.17: O que ser impresso pelo programa 6.11. Indique os nmeros que voc
ir digitar para o programa. Os nmeros devem ser todos diferentes.
107
}
}
< 6; i ++) {
s
anf ( " % d " , & m ) ;
i f ( m % 2) {
for ( j = 0; j < m ; j ++) {
printf ( " # " ) ;
}
}
else {
for ( j = m ; j > 0; j - -) {
printf ( " * " ) ;
}
}
printf ( " \ n " ) ;
return
0;
108
Captulo 7
Vetores e Cadeias de
Cara
teres
7.1 Introduo
Vetores so usados para tratamento de conjuntos de dados que possuem as
mesmas caractersticas. Uma das vantagens de usar vetores que o conjunto
recebe um nome comum e elementos deste conjunto so referenciados atravs
de ndices. Pelo nome vetor estaremos referenciando estruturas que podem
ter mais de uma dimenso, como por exemplo matrizes de duas dimenses.
Neste captulo estaremos mostrando vetores de tamanhos fixos. Somente aps
apresentarmos ponteiros iremos abordar alocao de memria para vetores.
onde tipo um tipo qualquer de dados, nome o nome pelo qual o vetor vai
ser referenciado e tamanho o nmero de elementos que o vetor vai conter.
Observar que em C o primeiro elemento tem ndice 0 e o ltimo tamanho - 1.
Exemplos de declaraes de vetores so:
sizeof(tipo)
#define DIM 5
#in
lude < stdio .h >
int main ( void ) {
int vetor [ DIM ;
unsigned int i ,
num ;
return
0;
110
#define DIM 5
#in
lude < stdio .h >
int
main ( void ) {
int vetor1 [ DIM , vetor2 [ DIM , i , prod =0;
printf ( " Entre
om um vetor de % d elementos \ n " , DIM ) ;
for ( i = 0; i < DIM ; i ++) {
printf ( " Elemento % d " , i ) ;
s
anf ( " % d " , & vetor1 [ i ) ;
}
printf ( " Entre
om outro vetor de % d elementos \ n " , DIM )
;
for ( i = 0; i < DIM ; i ++) {
printf ( " Elemento % d " , i ) ;
s
anf ( " % d " , & vetor2 [ i ) ;
}
for ( i = 0; i < DIM ; i ++)
prod += vetor1 [ i * vetor2 [ i ;
printf ( " O produto vale % d " , prod ) ;
return
0;
111
Operao
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]
v[1]
v[2]
v[3]
v[4]
20
15
15
15
15
15
15
15
15
20
20
8
8
8
8
8
8
8
8
20
20
12
12
12
12
12
12
12
12
20
20
5
5
5
5
5
5
5
5
20
v[3]
15
8
8
8
8
8
8
15
15
12
12
12
12
12
12
15
15
5
5
5
5
5
5
15
20
20
20
20
20
20
v[2]
8
8
8
12
12
5
5
5
12
15
15
15
20
20
20
v[1]?
8
5
5
8
12
12
15
15
20
20
v[1]
v[2]
v[3]
v[4]
v[1]
v[2]
112
#define
#define
#define
DIM 5
FALSO 0
VERDADE 1
#in
lude
int main
int
int
do
tro
ou = FALSO ;
for ( i =0; i < fim -1; i ++) {
i f ( vetor [ i > vetor [ i +1) {
temp = vetor [ i ;
vetor [ i = vetor [ i +1;
vetor [ i +1 = temp ;
tro
ou = VERDADE ;
}
}
fim - -;
} while ( tro
ou ) ;
for
}
return
0;
113
114
strcat, e esta razo das aspas, ou seja, uma cadeia de um caractere apenas.
A seguir mostramos um resultado da execuo do programa 7.4.
Entre com um nome Ze
Ze
Entre com um sobrenome Sa
Sa
Ze Sa
Qual caracter? a
O caractere aparece na posicao 4
void ) {
har
, nome [81 ,
int i ;
main (
sobrenome [41;
for
}
}
return
0;
115
sizeof(tipo)*dim1*dim2*dim3*...*dimN
Por exemplo a declarao
int
matriz[10[20;
armazena o dobro do elemento que est na quarta linha e nona coluna na varivel
c. Observar que o primeiro ndice indica a linha e o segundo a coluna. Lembrar
que o nmero da primeira linha (coluna) igual a 0. O programa 7.5 l uma
matriz de trs linhas e cinco colunas e imprime os valores lidos.
#define DIML 3
#define DIMC 5
#in
lude < stdio .h >
int main ( void ) {
int i , j ;
int matriz [ DIML [ DIMC ;
for
for
}
}
return
0;
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]
M Rij =
C1
X
M 1ik M 2kj
(7.1)
k=1
117
3
3
3
3
void ) {
f l o a t m1 [ L1 [ C1 ,
f l o a t mr [ L1 [ C2 ,
int i , j , k ;
main (
for
for
for
for
}
}
L1
L2
C1
C2
m2 [ L2 [ C2 ;
m;
return
0;
118
#define DIML 5
#define DIMC 41
#in
lude < stdio .h >
#in
lude < string .h >
int main ( void ) {
int i ;
har nomes [ DIML [ DIMC ;
for
for
}
}
return
0;
#define DIM 5
#in
lude < stdio .h >
int
main () {
int vetor [ DIM = {10 , 15 , 20 , 25 , 30};
int vetor1 [ = {10 , 20 , 30 , 40 , 50 , 60 , -1};
int vetor2 [ = {3 , 6 , 9 , 12 , 15 , 18 , 21 , 24};
unsigned int i , tam ;
printf ( " Este programa imprime vetores " ) ;
printf ( "
ontendo numeros inteiros e \ n " ) ;
printf ( " que foram ini
ializado s durante " ) ;
printf ( " a sua de
lara
ao .\ n " ) ;
/* Impressao dos
onjuntos */
printf ( " \ nVetor
om tamanho pre - definido \ n " ) ;
for ( i =0; i < DIM ; i ++)
printf ( " Elemento % d = % d \ n " , i , vetor [ i ) ;
printf ( " \ nVetor terminando por -1\ n " ) ;
for ( i =0; vetor1 [ i >0; i ++)
printf ( " Elemento % d = % d \ n " , i , vetor1 [ i ) ;
tam = s i z e o f ( vetor2 )
printf ( " \ nDes
obrindo
for ( i =0; i < tam ;
printf ( " Elemento
return
/ s i z e o f ( int ) ;
o tamanho do Vetor \ n " ) ;
i ++)
% d = % d \ n " , i , vetor2 [ i ) ;
0;
120
float
#define DIM 5
#in
lude < stdio .h >
int
main (
har
};
int
void
) {
dis
iplinas [[40 = {
" dis
0: Computa
ao para Informati
a " ,
" dis
1: Ban
o de Dados I " ,
" dis
2: Ban
o de Dados II " ,
" dis
3: Arquitetura de Computadores I "
i;
printf ( " Qual a dis
iplina ? " ) ; s
anf ( " % d " , & i ) ;
puts ( dis
iplinas [ i ) ;
}
return
0;
121
Exer
ios
7.1: Escreva um programa que leia uma linha de at 80 caracteres do teclado e
imprima quantos caracteres foram lidos.
7.2: Escreva um programa que leia uma linha de caracteres do teclado e imprima
quantas vezes um caractere, tambm fornecido pelo teclado, aparece nesta linha.
O programa tambm deve imprimir em que posies o caractere foi encontrado.
7.3: Escreva um programa que leia uma linha do teclado e em seguida um par
de caracteres. O programa deve procurar este par na linha e imprimir em que
posies o par foi encontrado. Obs. No use funes da biblioteca de strings
do C
7.4: Escreva um programa que leia uma linha do teclado e imprima todas as
vogais encontradas no texto e o total de vezes que elas aparecem.
Obs: Tamanho mximo da linha deve ser 40 caracteres.
7.5: O imperador romano Csar usava um sistema simples para codificar as
mensagens que enviava aos seus generais. Neste sistema cada letra era substituda por trs letras frente no alfabeto. A sua misso mais simples ainda,
escrever um programa que converta cada letra, e somente as letras, de uma
mensagem de at 80 caracteres para a letra imediatamente posterior. Note que
a letra z deve ser convertida para a letra a, e a letra Z para A.
7.6: Escreva um programa que leia uma frase de 80 caracteres e a imprime
retirando os espaos em branco.
7.7: Escreva um programa que leia uma linha de caracteres do teclado de
tamanho 80. A linha somente contm letras. Divida a linha em blocos de 5
letras. Dentro de cada bloco o seu programa deve trocar a primeira letra pela
letra seguinte no alfabeto, a segunda letra por duas letras adiante no alfabeto,
a terceira por trs letras adiante e assim at a quinta. Os espaos em branco
devem ser retirados da frase. Considere o seguinte exemplo.
1. Frase lida:
EVA VIU A UVA
2. Retirada dos espaos em branco:
EVAVIUAUVA
3. Diviso em blocos de 5 (blocos indicados por tipos diferentes):
EVAVIUAUVA
4. Criptografia:
FYDANVCYAF
Portanto, o que ser impresso pelo programa :
FYDANVCYAF
7.8: Escreva um programa que leia uma matriz de 3x3 que contm somente
caracteres 0 e X e procure linhas que contenham somente um dos dois caracteres.
O caractere a ser procurado deve ser lido do teclado.
122
7.9: Escreva um programa que leia uma linha de caracteres do teclado e converta
o primeiro caractere de cada palavra para maisculas. Assuma que as palavras
so sempre separadas por um branco.
7.10: Escreva um programa que leia para um vetor um conjunto de nmeros
inteiros. Assuma que o conjunto de nmeros lidos menor que o tamanho do
vetor. O programa deve inserir no vetor, em uma posio especificada pelo
usurio, um nmero lido do teclado. Assuma que a posio especificada pelo
usurio corresponde ao ndice do vetor.
7.11: Faa um programa que inverta uma cadeia de caracteres. O programa
deve ler a cadeia com gets e armazen-la invertida em outra cadeia. Use o
comando for para varrer a cadeia at o seu final.
7.12: Escreva um programa que leia um conjunto de nomes para uma matriz
e imprima estes nomes em ordem alfabtica. Assuma que os nomes sero lidos
somente em letras maisculas. Assuma tambm que os nomes tm no mximo
40 caracteres e sero lidos 10 nomes ao todo.
7.13: Escreva um programa que leia um conjunto N (1 N 1000000000) de
nmeros inteiros e imprima os seguintes resultados:
media dos nmeros;
maior dos nmeros;
menor dos nmeros;
produto de todos os nmeros.
7.14: Considere que voc digitou o seu nome para o programa mostrado na
listagem 7.10. O que ser impresso? Indique o que voc digitou. Justifique
sua resposta com detalhes.
123
temp ;
gets ( texto ) ;
tam = strlen ( texto ) ;
for ( i = 0; i < tam ; i ++) {
temp = texto [ i ;
texto [ i = texto [ tam -1 - i ;
texto [ strlen ( texto ) -1 - i = temp ;
}
puts ( texto ) ;
return 0;
124
Captulo 8
Funes
8.1 Introduo
Em C, diferentemente de outras linguagens como Pascal, todas as aes ocorrem
dentro de funes. Na linguagem C no h conceito de um programa principal, o
que existe uma funo chamada main que sempre a primeira a ser executada.
Um programa pode ser escrito apenas com a funo main e mais as funes
existentes nas bibliotecas da linguagem C. No entanto o uso de funes pode
facilitar o desenvolvimento de programas de diversas maneiras.
Em primeiro lugar temos as vantagens do reuso de cdigo desenvolvido por
outros programadores. As funes de entrada e sada so o exemplo mais direto
deste reuso. Em C no existem estes tipos de comandos como na maioria das
linguagens. Programas escritos em C usam funes de entrada e sada escritas
e testadas por outros programadores. Este reuso de cdigo apresenta vrias
vantagens. Primeiro, diminui o tempo de desenvolvimento do programas. Em
segundo lugar, como estas funes foram testadas por diversos usurios, a quantidade de erros bastante reduzida. Estes fatores contribuem para a reduo
dos custos de desenvolvimento dos projetos.
Uma outra vantagem do uso de funes e a maior facilidade na diviso do
trabalho necessrio para construir um aplicativo. Funes podem ser desenvolvidas por programadores trabalhando independentemente. Para isto basta que
alguns acordos sejam feitos entre os programadores que iro programar a funo
e os que iro us-las. Estes acordos precisam definir que parmetros a funo
ir receber, que resultados ir fornecer e que operaes ela deve realizar sobre
estes parmetros para obter os resultados necessrios. Esta diviso do trabalho
concorre para acelerar o desenvolvimento dos programas e na reduo dos custos
deste desenvolvimento.
A diviso de um programa em funes tambm permite que os testes do
sistema completo sejam feitos mais facilmente e com mais garantia de correo.
Os programadores podem testar suas funes separadamente em testes menos
complexos, j que as funes normalmente so simples e tm requisitos menos
complicados de serem avaliados. Isto permite que muitos erros do sistema completo possam ser retirados antes que ele esteja completo. Normalmente testar
um programa complexo requer testes complexos.
125
Uma funo recebe uma lista de argumentos (nome1, nome2, ..., nomeN),
executa comandos com estes argumentos e pode retornar ou no um resultado
para a funo que chamou esta funo. A lista de argumentos, tambm chamados de parmetros, uma lista, separada por vrgulas, de variveis com seus
tipos associados. No possvel usar uma nica definio de tipo para vrias
variveis. A lista de argumentos pode ser vazia, ou seja, a funo no recebe
nenhum argumento. O nome da funo pode ser qualquer identificador vlido.
O tipo que aparece antes do nome da funo especifica o tipo do resultado que
ser devolvido ao final da execuo da funo. Caso nenhum tipo seja especificado o compilador assume que um tipo inteiro retornado. O tipo void pode
ser usado para declarar funes que no retornam valor algum.
H basicamente duas maneiras de terminar a execuo de uma funo. Normalmente usa-se o comando return para retornar o resultado da funo. Portanto, quando o comando
return
expresso;
int
a, dia, mes, i;
oat
oat
n2,
oat
n3);
Neste exemplo, uma funo chamada media que do tipo oat , isto retorna
um resultado oat , recebe trs argumentos (n1, n2, n3) tambm do tipo oat .
126
int
soma (int,
int)
128
#in
lude
void
pares ( void ) {
int i ;
for ( i = 2; i <= 10; i += 2) {
printf ( " % d : " , i ) ;
}
void
int
impares ( void ) {
int i ;
for ( i = 3; i <= 11; i += 2) {
printf ( " % d : " , i ) ;
}
main ( int arg
,
pares () ;
printf ( " \ n " ) ;
impares () ;
return
har
* argv [) {
0;
i ++) {
return
0;
#in
lude
int
void
}
void
int
i;
soma1 ( void ) {
i += 1;
printf ( " Fun
ao soma1 : i = % d \ n " , i ) ;
sub1 ( void ) {
int i = 10;
i -= 1;
printf ( " Fun
ao sub1 : i = % d \ n " , i ) ;
main ( int arg
,
har * argv [) {
i = 0;
soma1 () ;
sub1 () ;
printf ( " Fun
ao main : i = % d \ n " , i ) ;
return 0;
130
int
Eleva ( f l o a t a , int b ) {
res = 1.0;
float
for ( ; b >0;
return res ;
b - -) res *= a ;
main () {
f l o a t numero ;
int poten
ia ;
har linha [80;
puts ( " Entre
om um numero " ) ;
gets ( linha ) ; numero = atof ( linha ) ;
puts ( " Entre
om a poten
ia " ) ;
gets ( linha ) ; poten
ia = atoi ( linha ) ;
printf ( " \ n % f Elevado a % d e igual a % f \ n " ,
numero , poten
ia , Eleva ( numero , poten
ia ) ) ;
return
0;
131
Para ilustrar o fato de que somente o valor passado vamos usar o exemplo
8.6. Neste programa as variveis a e b recebem os valores 10 e 20 respectivamente. Na funo tro
ar estes valores so recebidos e so trocados localmente.
Aps o retorno da funo, o programa imprime os valores originais das variveis,
j que estes no sofreram nenhuma alterao. O resultado da execuo deste
programa o seguinte:
a = 10, b = 20
int
b) {
temp = a ; a = b ; b = temp ;
return
0;
har
onta ( har v [ ,
har
);
main () {
har
, linha [ DIM ;
int maius
ulas [26 , minus
ulas [26;
puts ( " Entre
om uma linha " ) ;
gets ( linha ) ;
for (
= 'a ';
<= 'z ';
++)
minus
ulas [
- 'a ' =
onta ( linha ,
) ;
for (
= 'A ';
<= 'Z ';
++)
maius
ulas [
- 'A ' =
onta ( linha ,
) ;
for (
= 'a ';
<= 'z ';
++)
i f ( minus
ulas [
- 'a ' )
printf ( " %
apare
eu % d vezes \ n " ,
, minus
ulas [
- 'a ' ) ;
for (
= 'A ';
<= 'Z ';
++)
i f ( maius
ulas [
- 'A ' )
printf ( " %
apare
eu % d vezes \ n " ,
, maius
ulas [
- 'A ' ) ;
return 0;
onta (
har v [ DIM ,
int i =0 , vezes =0;
har
) {
while
}
( v [ i != ' \0 ' )
i f ( v [ i ++ ==
) vezes ++;
return vezes ;
133
return
expresso
A funo que chamou livre para ignorar o valor retornado. Alm disso a
funo pode no conter o comando e portanto nenhum valor retornado e neste
caso a funo termina quando o ltimo comando da funo executado. Quando
o comando return no existe o valor de retorno considerado indefinido. As
funes que no retornam valores devem ser declaradas como do tipo void.
importante observar que funes que so declaradas com um tipo vlido podem
ser includas em qualquer expresso vlida em C.
8.7 Re
urso
Funes em C podem ser usadas recursivamente, isto uma funo pode chamar
a si mesmo. como se procurssemos no dicionrio a definio da palavra
recurso e encontrssemos o seguinte texto:
recurso: s.f. Veja a definio em recurso
Um exemplo simples de funo que pode ser escrita com chamadas recursivas
o fatorial de um nmero inteiro. O fatorial de um nmero, sem recurso,
definido como
n! = n (n 1) (n 2) 2 1
A partir desta definio podemos escrever a funo fatorial como mostrado
na listagem 8.9.
Alternativamente, o fatorial pode ser definido como o produto deste nmero
pelo fatorial de seu predecessor, ou seja
n! = n (n 1)!
Deste modo podemos escrever uma funo recursiva em que cada chamada
da funo que calcula o fatorial chama a prpria funo fatorial. O exemplo,
mostrado na listagem 8.10 ilustra como a funo pode ser escrita recursivamente.
134
void
main () {
int v [ DIM ;
Le_vetor (v , DIM ) ;
Imprime_vetor (v , DIM ) ;
Inverte_vetor (v , DIM ) ;
Imprime_vetor (v , DIM ) ;
return 0;
Le_vetor ( int v [ ,
int i ;
for
void
tam ) {
int
tam ) {
Inverte_vetor ( int v [ ,
int i , temp ;
for
int
Imprime_vetor ( int v [ ,
int i ;
for
void
v [ , int tam ) ;
( int v [ , int tam ) ;
( int v [ , int tam ) ;
int
135
tam ) {
( unsigned long
fato =1 , i ;
int
num ) {
return
fato ;
num ) {
136
void
f () {
/* ... */
f ()
/* ... */
void
f () {
/* ... */
g ()
/* ... */
void
g () {
... f () ...
como
xn = x x(n1)
float
Elevar ( f l o a t x ,
( n <= 1) {
return x ;
if
}
else
return
int
n) {
x * Elevar (x , b -1) ;
Para facilitar pode-se pensar que quando uma chamada recursiva feita, a
funo faz uma cpia de si mesmo, das variveis locais, com seus valores iniciais,
e dos parmetros.
Cada cpia da funo inclui uma marcao indicando o ponto atual onde a
funo est sendo executada. Quando uma chamada recursiva feita, o marcador na funo que chamou fica logo aps a chamada. O marcador na funo
chamada vai para o incio da funo.
Quando a funo retorna, a cpia some, e a funo que chamou continua aps
a chamada, posio indicada pela marcao. As cpias anteriores continuam
sabendo de onde continuar porque as marcaes esto em suas posies.
137
Funes podem ser recursivas com cauda ou no. Em uma funo recursiva
com cauda, nenhuma das chamadas recursivas executam algo aps a chamada
recursiva completar, exceto para retornar o valor da funo.
A listagem 8.14 mostra o return de uma tpica funo recursiva com cauda e
a listagem 8.15 mostra uma sem cauda. A chamada sem cauda caracterizada
porque primeiro f feita e depois soma 5, portanto, algo executado aps a
chamada.
int
}
f ( int x , int y ) {
return f (x , y ) ;
int
}
f ( int x , int y ) {
return f (x , y ) + 5;
Quando a chamada soma( vetor, 10 ); for executada sabemos que os primeiros 10 elementos do vetor vetor sero somados.
Em seguida, repita vrias vezes para si mesmo o seguinte raciocnio:
recurso resolve um grande problema (de tamanho n, por
exemplo), resolvendo um ou mais problemas de tamanho
menor, e usando as solues destes pequenos problemas
para resolver o grande problema.
Caso bsico
Portanto, recurso um processo que quebra um problema em problemas
menores que sero quebrados em problemas menores at que chegamos no menor
problema possvel e na sua soluo (caso bsico) e retornamos esta soluo.
Uma vez que voc escreveu o prottipo, pense em como resolver o prximo
problema menor. Ento se a chamada
138
soma(vetor, n),
Suponha que algum lhe daria a resposta para esta segunda soma. O que
voc teria? Voc teria a soma dos n1 primeiros elementos do vetor. Agora que
voc tem esta soluo (por hiptese), o que falta para resolver todo o problema?
Achar a soluo do caso base, que o menor problema. Neste exemplo seria:
sum(vetor, 1 );
Quanto falta apenas um elemento a soma a ser calculada o prprio elemento. Deste modo a soluo para este problema fica como mostrado na listagem 8.16.
int
soma (
vetor [ ,
int menor ;
i f ( n == 1 )
return v [0
else
int
int
n )
{ /*
aso base */
/* sem
hamada re
ursiva */
{
menor = soma ( vetor , n - 1 ) ; /* resolve problema
menor */
/* usa solu
ao do menor para resolver o maior */
return menor + vetor [ n - 1 ;
Todavia, pela mesma razo, deve ser difcil resolver usar laos para resolver
o problema. Laos tambm dependem de fazer a mesma coisa diversas vezes,
em diferentes ndices.
Se voc conseguir resolver um problema por meio de um lao, deve ser possvel resolve-lo por meio de recurso.
void
har
*argv[)
140
int
har * argv [) {
unsigned long int numero , fatorial ,
if
for
}
}
num ) {
i;
( arg
< 2) {
printf ( " Para rodar : % s num1 num2 ... .\ n " , argv
[0) ;
return 1;
( i =1; i < arg
; i ++) {
numero = ( unsigned long int ) ( atoi ( argv [ i ) ) ;
fatorial = fat ( numero ) ;
printf ( " O fatorial de % lu vale % lu .\ n " , numero ,
fatorial ) ;
return
0;
141
Exer
ios
8.1: Escrever um programa que declare, inicialize e imprima um vetor de 10
inteiros. O vetor deve conter os 10 primeiros mltiplos de 5. A inicializao do
vetor e a sua impresso devem ser feitas por funes.
8.2: Escreva um programa para declarar um vetor de caracteres de tamanho 26 e
imprimir o seu contedo. O vetor deve ser inicializado com as letras minsculas
do alfabeto. A inicializao do vetor e a sua impresso devem ser feitas por
funes.
8.3: Escreva um programa que armazene em uma matriz trs nomes de pessoas
e em seguida os imprima. Assuma que o tamanho mximo de cada nome 40
caracteres. Neste programa a leitura dos nomes dever ser feita por uma funo
e a impresso dos nomes por outra.
8.4: Escreva um programa que imprima o cdigo ASCII de todos os caracteres,
das seguintes maneiras:
1. caractere a caractere, a escolha do usurio;
2. a tabela inteira, a partir de um determinado valor decimal.
Cada item deste exerccio deve corresponder a uma funo.
8.5: Escreva um programa que crie uma tabela de temperaturas Celsius - Fahrenheit. O programa deve usar uma funo que converta de Celsius para Fahrenheit. A tabela deve iniciar na temperatura 0 graus Celsius e terminar na
temperatura 100 graus Celsius.
8.6: Escreva um programa, usando funes, que gere um vetor a partir de uma
matriz. Cada elemento do vetor igual a soma dos elementos de uma das linhas
da matriz. Considere que a matriz tenha tamanho 10 por 10.
8.7: Escreva um programa usando recursividade para gerar a seqncia do
Fibonacci. A seqncia de Fibonacci definida como:
f (0) =
f (1) =
0
1
f (n) =
f (n 1) + f (n 2)
8.8: O que o programa mostrado na listagem 8.18 imprime, caso sejam fornecidos os valores 48 e 256. Justifique a sua resposta.
int
ab
( int x , int y ) {
printf ( " % d % d \ n " , x , y ) ;
i f ( y == 0) {
return x ;
}
else {
return ab
(y , x % y ) ;
}
main ( void ) {
int a , b ;
s
anf ( " % d % d " , &a , & b ) ;
printf ( " % d \ n " , ab
(a , b ) ) ;
return 0;
143
[) ;
main ( void ) {
har numeroC [80;
fgets ( numeroC , 80 , stdin ) ;
{
numeroC [ strlen ( numeroC ) -1 = ' \0 ';
printf ( " % s = % d \ n " , numeroC , fromHexatoD e
i ma l (
numeroC ) ) ;
fgets ( numeroC , 80 , stdin ) ;
}
return 0;
int
toLower (
har
) {
i f (
>= 'A ' &&
<= 'Z ') {
=
- 'A ' + 'a ';
}
return
;
toNumero (
har
) {
int resultado ;
if
}
else i f
}
}
return
resultado ;
144
Captulo 9
Ponteiros
9.1 Introduo
Ponteiros so usados em situaes em que necessrio conhecer o endereo
onde est armazenada a varivel e no o seu contedo. Um ponteiro uma
varivel que contm um endereo de uma posio de memria e no o contedo
da posio. A memria de um computador pode ser vista como uma seqncia
de bytes cada um com seu prprio e nico endereo. No h dois bytes com
o mesmo endereo. O primeiro endereo sempre 0 e o ltimo geralmente
uma potncia de 2. Por exemplo um computador com memria igual a 512
Mbytes tem 512x1024x1024 bytes. A Figura 9.1 mostra o mapa de um trecho
de memria que contm duas variveis inteiras (num, res) ocupando 4 bytes
cada uma e mais um ponteiro (pint), que tambm ocupa 4 bytes. Observar que
os endereos esto pulando de quatro em quatro bytes devido ao espao que
cada um destas variveis ocupa.
0
4
10
num
120
res
*pint
12
16
destas variveis, que aps o fim da funo estaro disponveis para a funo que
chamou. Neste caso os argumentos podem funcionar como entrada e sada de
dados da funo.
Uma outra aplicao importante de ponteiros apontar para reas de memria que devem ser gerenciadas durante a execuo do programa. Com ponteiros,
possvel reservar as posies de memria necessrias para armazenamento
destas reas somente quando for necessrio e no quando as variveis so declaradas. Neste esquema o programador pode reservar o nmero exato de posies
que o programa requer. A Figura 9.2 ilustra como um ponteiro faz referncia
para uma rea de memria. Na figura a varivel ponteiro pi aponta para a rea
de memria que contm um vetor de 10 inteiros. Com ponteiros, o programador
precisa, no incio, definir a varivel ponteiro e seu tipo. Durante a execuo do
programa, aps descobrir o tamanho do vetor, reserva a rea necessria para
guardar os dados. Observe a diferena do que ocorre quando se usa vetores de
tamanho fixo. Neste caso a definio do tamanho do vetor dada na declarao
do vetor e mantida at o final da execuo do programa.
0
pi ponteiro
para vetor
1000
4
8
120
1000
Vetor de
10 inteiros
1036
97
146
*/
flutuante */
Como as variveis, os ponteiros devem ser inicializados antes de serem usados. Esta inicializao pode ser feita na declarao ou atravs de uma atribuio.
Aps a declarao o que temos um espao na memria reservado para armazenamento de endereos. O valor inicial da memria indefinido como acontece
com variveis. A Figura 9.3 ilustra esta situao. Um ponteiro pode ser inicializado com um endereo ou com o valor NULL. O valor NULL, que equivalente a
0, uma constante definida no arquivo <stdio.h> e significa que o ponteiro no
aponta para lugar nenhum. A atribuio de inteiros a ponteiros no faz sentido a no ser em aplicaes muito especiais e o nico valor inteiro que se pode
atribuir a um ponteiro o 0. Este tipo de atribuio no faz sentido porque na
maioria das aplicaes o sistema operacional que aloca e gerencia a posio
dos programas na memria e, portanto, o usurio no tem controle sobre estes
endereos.
996
1000
endereo indefinido
*res
1004
endereo indefinido
*div
a varivel ponteiro pint termina com o valor 4, como est mostrado na Figura
9.4. Lembre-se que o valor 4 no tem sentido prtico na maioria das aplicaes.
O fato importante que o ponteiro pint passou a apontar para a varivel num.
O operador * o complemento de &. O operador * devolve o valor da varivel
localizada no endereo apontado pelo ponteiro. Por exemplo, considere que o
147
0
4
10
num
120
12
res
*pint
16
comando res = *pint; foi executado logo aps pint = #. Isto significa que
a varivel res recebe o valor apontado por pint, ou seja a varivel res recebe o
valor 10, como est mostrado na Figura 9.5.
0
4
10
120 10
12
num
res = *pint
*pint
16
Figura 9.6 a situao da memria aps estas operaes. Alm disso no final o
endereo apontado por p1 carregado em p2. Os comandos printf imprimem os
valores apontados pelos ponteiros respectivos, mostrando os seguintes valores:
30
100
30
{ 10 , 20 , 30 , 40 , 50 };
* p1 , * p2 ;
i = 100;
0
4
10
v[0]
20
v[1]
12
30
v[2]
16
40
v[3]
20
50
v[4]
24
12
*p1
28
32
100
*p2
32
p1 = &v[2];
p2 = &i;
i
149
int
main ( void ) {
int vetor [ = { 10 , 20 , 30 , 40 , 50 };
int * 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 nmero inteiro, que armazenado em quatro bytes, seja incrementado por um e passe para apontar para
o prximo nmero inteiro. A primeira vista, para que passasse a apontar para
o prximo endereo, seria necessrio aumentar o endereo em quatro. Ou seja,
sempre que um ponteiro incrementado (decrementado) ele passa a apontar
para a posio do elemento seguinte (anterior). O compilador interpreta o comando p1++ como: passe a apontar para o prximo nmero inteiro e, portanto,
aumenta o endereo do nmero de bytes correto. Este ajuste feito de acordo
com o tipo do operando que o ponteiro est apontando. Do mesmo modo, somar
trs a um ponteiro faz com que ele passe apontar para o terceiro elemento aps o
atual. Portanto, um incremento em um ponteiro que aponta para um valor que
armazenado em n bytes faz que n seja somado ao endereo. ento possvel
somar-se e subtrair-se inteiros de ponteiros. A operao abaixo faz com que o
ponteiro p passe a apontar para o terceiro elemento aps o atual.
p = p + 3;
a, b;
if
(
== v )
printf ( " As variveis estao na mesma posi
ao . " ) ;
else
return
0;
151
int
list [5 , i ;
152
Para percorrer um vetor alm da maneira mostrada no programa 9.6 possvel usar um ponteiro varivel como ilustrado no Programa 9.7. Observe como
o ponteiro p recebe seu valor inicial e a maneira como ele incrementado.
Quando uma cadeia de caracteres como esta enviada para a funo, o que
passado o ponteiro para a cadeia. possvel ento carregar o endereo da
cadeia em um ponteiro do tipo
har, como no exemplo 9.8. Neste programa
contado o nmero de caracteres de uma cadeia. Observe o ponteiro *(s+tam++)
apontando caractere a caractere.
Um outro exemplo (Programa 9.9) mostra uma funo que copia um cadeia
de caracteres para outra.
s = lista ;
while (*( s + tam ++) != ' \0 ') ;
tam - -;
printf ( " O tamanho do string \"% s \" e % d
ara
teres .\ n "
,
lista , tam ) ;
return 0;
int
de origem " ;
void *mallo
(size_t size); Reserva espao na memria para algum item
de um programa. O tamanho em bytes reservado definido pela varivel size.
O valor armazenado no espao indefinido. A funo retorna um ponteiro de
tipo void para o espao reservado ou NULL no caso de algum erro ocorrer.
void *
allo
(size_t num, size_t size); Reserva espao na memria para
um vetor de num itens do programa. Cada item tem tamanho size e todos os
bits do espao so inicializados com 0. A funo retorna um ponteiro de tipo
void para o espao reservado ou NULL no caso de algum erro ocorrer.
void free(void *pont); O espao apontado por pont devolvido ao sistema
para uso. Caso pont seja um ponteiro nulo nenhuma ao executada. No caso
do ponteiro no ter sido resultado de uma reserva feita por meio de uma das
funes
allo
, reallo
ou mallo
o resultado indefinido.
void reallo
(void *pont, size_t size); A funo altera o tamanho do objeto na memria apontado por pont para o tamanho especificado por size. O
154
contedo do objeto ser mantido at um tamanho igual ao menor dos dois tamanhos, novo e antigo. Se o novo tamanho requerer movimento, o espao reservado
anteriormente liberado. Caso o novo tamanho for maior, o contedo da poro de memria reservada a mais ficar com um valor sem especificao. Se o
tamanho size for igual a 0 e pont no um ponteiro nulo o objeto previamente
reservado liberado.
Estas funes podem ser encontradas na biblioteca stdlib.h. O Programa
9.10 ilustra o uso das funo
allo
e free.
void
float
tam ,
int
* vezes ) ;
int i ;
f l o a t maior ;
int
tam ,
int
* vezes ) {
156
#define
#define
LIN 3
COL 4
{
printf ( " Elemento % d % d = " , i , j ) ;
s
anf ( " % d " , & matriz [ i [ j ) ;
#define
#define
int
int
LIN 3
COL 4
* matriz ;
i, j;
157
main ( void ) {
har * linha [ LINHAS ;
int i ;
for
for
}
for
}
}
return
0;
158
linha 0
*(matriz+0)
*(matriz+1)
linha 1
*(matriz+2)
linha 2
*(matriz+n)
linha n
sizeof(int
*));
foi usado pelo programa para reservar espao para armazenar lin linhas de
ponteiros para ponteiros. Observe que o comando sizeof(int *) calcula o espao
para armazenar um ponteiro na memria. Note tambm que o valor retornado
pela funo mallo
foi conformado ao tipo ponteiro para ponteiro pela operao
(int **). O interessante do programa que a troca de linhas da matriz envolve
simplesmente a troca de dois ponteiros e no a troca de todos os elementos das
linhas. Esta soluo muito mais rpida do que trocar elemento a elemento,
especialmente para matrizes grandes.
A seguir mostramos o programa nas listagens 9.16 e 9.17 que o exemplo
anterior modificado para utilizar funes. O propsito mostrar como ficam as
chamadas e as definies das funes que utilizam ponteiros para ponteiros.
159
*/
160
int
void
161
void
void
void
162
int
linha2 ) {
Exer
ios
9.1: Escreva um programa que gere um vetor de trs dimenses (X, Y e Z) em
que cada posio guarda a soma de suas coordenadas. As dimenses da matriz
devero ser determinadas em tempo de execuo e o programa dever informar
os valores gerados.
9.2: Escreva um programa que leia uma frase de at 80 caracteres do teclado
e imprima a freqncia com que aparece cada uma das letras do alfabeto na
frase.
9.3: Escreva um programa que leia uma frase de at 80 caracteres e a imprima
em ordem reversa convertendo todos os caracteres minsculos para maisculos.
9.4: Escreva um programa que leia uma matriz e a imprima. O programa deve
ler o numero de colunas e linhas do teclado. O programa deve ainda trocar duas
linhas da matriz de posio. Os nmeros das linhas a serem trocadas devem ser
lidos do teclado.
9.5: Escreva um programa que simule uma pilha usando vetores. O programa
deve implementar as seguintes operaes na pilha:
Inserir
Remover
Listar
9.6: Escreva uma funo que receba um ponteiro para uma cadeia de caractere
e troque todo o caracter aps um branco pelo seu equivalente maisculo.
9.7: Escreva um programa que leia seu nome completo e pergunte quantas letras
tem o seu primeiro nome. Assuma que a letra a tem ndice 0, a letra b ndice
1 e assim por diante. O programa deve imprimir quantas letras iguais a letra
cujo ndice o nmero de letras do seu primeiro nome existem no seu nome
completo.
9.8: Escreva um programa que leia seu nome completo e pergunte quantas letras
tem o seu primeiro nome. O seu programa deve usar a funo posi
ao que tem
o seguinte prottipo:
int
har
*str);
Esta funo deve verificar se a cadeia apontada por substr est presente na
cadeia apontada por str e retornar a posio em que a sub-cadeia aparece em
cadeia.
9.9: Escreva um programa que procure em uma matriz elementos que sejam
ao mesmo tempo o maior da linha e o menor coluna. As dimenses da matriz
devem ser pedidas ao usurio.
9.10: Escreva um programa que leia duas cadeias de caracteres e concatene a
segunda cadeia ao final da primeira.
163
MAX 80
misterio ( har * p1 ,
har
* p2 ) ;
main ( void ) {
har palavra1 [ MAX ;
har palavra2 [ MAX ;
puts ( " Palavra 1? " ) ;
fgets ( palavra1 , MAX , stdin ) ;
palavra1 [ strlen ( palavra1 ) -1 = ' \0 ' ;
puts ( " Palavra 2? " ) ;
fgets ( palavra2 , MAX , stdin ) ;
palavra2 [ strlen ( palavra2 ) -1 = ' \0 ' ;
misterio ( palavra1 , palavra2 ) ;
return
void
while
if
if
0;
(* p1 != ' \0 ') {
(* p1 != ' \0 ') {
put
har (* p1 ) ;
p1 = p1 + 1;
}
while
(* p2 != ' \0 ') {
(* p2 != ' \0 ') {
put
har (* p2 ) ;
p2 = p2 + 1;
}
while
164
9.11: O que ser impresso pelo programa mostrado na listagem 9.18 caso a
primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ltimo
sobrenome.
9.12: O que ser impresso pelo programa mostrado na listagem 9.19 caso a
primeira palavra fornecida seja o seu primeiro nome e a segunda o seu ltimo
sobrenome. Indique os nomes que usou e justifique a sua resposta.
MAX 80
nMisterio (
har * p1 ,
(* p1 != ' \0 ') {
p1 = p1 + 1;
while
}
har
* p2 ) {
while
(* p2 != ' \0 ') {
* p1 = * p2 ;
p1 = p1 + 1;
p2 = p2 + 1;
int
}
* p1 = ' \0 ';
main ( void ) {
palavra1 [ MAX ;
palavra2 [ MAX ;
har
har
9.13: O que ser impresso pelo programa 9.20. Justifique sua resposta.
9.14: O que ser impresso pelo programa mostrado na listagem 9.21. Justifique
sua resposta.
165
166
void
int
int
f1 ( int v ) {
v = v + 1;
printf ( " f1 = % d \ n " , v ) ;
f2 ( int * v ) {
* v = * v + 1;
printf ( " f2 = % d \ n " , * v ) ;
f3 ( int v ) {
v = v + 1;
printf ( " f3 = % d \ n " , v ) ;
return v ;
main ( void ) {
int v = 1;
f1 ( v ) ;
f2 (& v ) ;
v = f3 ( v ) ;
printf ( " main = % d \ n " , v ) ;
return 0;
167
Captulo 10
Estruturas
10.1 Introduo
Uma estrutura um conjunto de uma ou mais variveis, que podem ser de tipos diferentes, agrupadas sob um nico nome. O fato de variveis agrupadas
em uma estrutura poderem ser referenciadas por um nico nome facilita a manipulao dos dados armazenados nestas estruturas. Um exemplo poderia ser
uma estrutura que armazenasse as diversas informaes sobre os alunos de uma
Universidade. Nesta estrutura estariam armazenadas, sob o mesmo nome, informaes do tipo: nome, registro, data de nascimento, data de ingresso, CPF,
etc. Uma estrutura pode incluir outras estruturas alm de variveis simples.
As estruturas facilitam manipular estes agrupamentos complexos de dados. Por
exemplo, considere o problema de ordenar as informaes sobre os alunos da
Universidade exemplo. A ordenao pode ser efetuada como se todos os dados
que compem a estrutura fossem uma entidade nica.
168
stru
t ALUNO {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
};
stru t
Nesta declarao trs estruturas do tipo ALUNO foram criadas. Esta declarao alocou espao para armazenar os dados dos trs alunos. A declarao acima
idntica, na forma, a declarao de variveis de um tipo pr-definido, como
por exemplo:
int
a, b, ;
stru
t ALUNO {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
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.
urso);
stru
t DATA {
int dia ,
};
mes , ano ;
Agora vamos modificar a estrutura aluno de modo que ela inclua a data de
nascimento do aluno. A estrutura fica com a seguinte definio:
169
stru
t aluno {
har nome [40;
int registro ;
int ano_entrada ;
har
urso [20;
stru
t DATA data_nas
im en to ;
};
paulo.data_nas imento.mes
typedef int
typedef int
typedef int
ores ;
laranja ;
manga ;
...
laranja lima ;
manga espada ;
ores = AMARELO ;
...
espada ++;
Ao mesmo tempo que typedef tem a vantagem de tornar mais claro a finalidade de cada varivel ele pode trazer problemas na medida em que esconde o
real tipo da varivel.
comum o uso de typedef em conjunto com stru
t. Considere a definio
de uma estrutura para guardar tempos gastos em tarefas. Esta estrutura deve
guardar horas, minutos e segundos. Usando esta combinao, a definio
usualmente feita da seguinte maneira:
stru
t _TEMPO {
int hora , minuto ,
};
typedef stru
t
...
TEMPO t1 ;
segundo ;
_TEMPO TEMPO ;
Uma forma ainda mais abreviada, junta as duas definies, ficando a definio da estrutura da seguinte maneira:
typedef stru
t
int hora ,
} TEMPO ;
_TEMPO {
minuto , segundo ;
170
...
TEMPO t1 ;
typedef stru
t
int hora ,
} TEMPO ;
...
TEMPO t1 ;
{
minuto , segundo ;
} EMPREGADO ;
int
main () {
EMPREGADO temp , emp1 ;
puts ( " Entre
om nome . " ) ;
gets ( emp1 . nome ) ;
puts ( " Qual o salario ? " ) ; s
anf ( " % f " , & emp1 . salario ) ;
temp = emp1 ;
printf ( " O salario de % s e %.2 f \ n " ,
temp . nome , temp . salario ) ;
return 0;
stru
t aluno {
har nome [40;
172
#in
lude
#in
lude
} ALUNO ;
int
main ( void ) {
ALUNO turma [4 , temp ;
int jaOrdenados = 0 , foraOrdem , i ;
for
do
( i = 0; i < 4; i ++) {
gets ( turma [ i . nome ) ;
s
anf ( " % f " , & turma [ i . n1 ) ;
do {} while ( get
har () != '\ n ') ;
s
anf ( " % f " , & turma [ i . n2 ) ;
do {} while ( get
har () != '\ n ') ;
turma [ i . media =( turma [ i . n1 + turma [ i . n2 ) /2.0;
{
foraOrdem = 0;
for ( i = 0; i < 4 - 1 - jaOrdenados ; i ++) {
i f ( turma [ i . media > turma [ i +1. media ) {
temp = turma [ i ;
turma [ i = turma [ i +1;
turma [ i +1 = temp ; foraOrdem = 1;
}
}
jaOrdenados ++;
} while ( foraOrdem ) ;
for ( 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;
173
} CIRCULO ;
float
}
int
Area ( f l o a t r ) {
3.141516 * r * r ;
return
main ( void ) {
CIRCULO
;
. x =
. y =
. raio = 1.0;
printf ( " % f \ n " , Area (
. raio ) ) ;
return 0;
} PONTO ;
f l o a t
omp ( PONTO p1 , PONTO p2 ) {
return sqrt ( pow ( p2 .x - p1 .x ,2) + pow ( p2 .y - p1 .y ,2) ) ;
}
int main ( void ) {
PONTO p1 , p2 ;
174
void
int ano_entrada ;
f l o a t n1 , n2 , media ;
} * maria ;
Para alocar espao para estruturas apontadas por ponteiros necessrio usar
o operador unrio sizeof, isto porque o tamanho de uma estrutura sempre
igual ou maior que a soma dos tamanhos dos seu componentes. Para explicar
esta fato devemos considerar como os dados so armazenados na memria dos
computadores.
Algumas arquiteturas de computadores endeream os dados na memria por
bytes, isto cada endereo de memria se refere a um byte. No entanto, estas
arquiteturas lem sempre uma palavra inteira da memria. Usualmente, palavras podem ser compostas de dois bytes e comeam em endereos pares, como
est mostrado na figura abaixo. Sabemos que existem variveis que ocupam
mais de um byte, por exemplo inteiros que so compostos de dois bytes.
175
Imagine ento uma estrutura composta de um caractere (1 byte) e um nmero inteiro (4 bytes). Caso a memria do computador fosse organizada em
palavras de 32 bits ou 4 bytes, e os dados fosse alocados sequencialmente byte a
byte, a estrutura acima ocuparia 5 bytes ou duas palavras, conforme esta mostrado na Figura 10.1a. Para ler o nmero inteiro o programa deveria ler duas
palavras. Para facilitar o acesso s variveis, alguns compiladores armazenam as
variveis de acordo com o que est indicado na Figura 10.1b. Observar que agora
a estrutura ocupa oito bytes e trs so perdidos. Neste caso o acesso ao nmero
inteiro ser sempre feito em um passo e portanto ganhou-se em tempo de acesso
ao custo de gasto de memria. Este uma troca constante em computao.
0
char int
int
int
int
char
int
12
12
16
16
int
int
int
Vimos ento que embora o total de bytes dos elementos da estrutura fosse
trs o compilador pode armazenar a estrutura em quatro bytes, da a necessidade
de sempre usar o operador sizeof quando alocar espao.
O programa 10.7 mostra como alocar espao para uma varivel simples e
como usar esta varivel em diversos tipos de comandos.
O programa 10.8 mostra como utilizar ponteiros para vetores de estruturas
e a forma mais segura de alocar espao para os dados. Observar as notaes
usadas na funo que l os dados dos funcionrios. Notar que (
adastro+i)
->salario o valor da salrio.
fgets ((
adastro + i ) -> nome , 39 , stdin ) ;
ss
anf ( linha , " % f " , &((
adastro + i ) -> salario ) ) ;
176
int
main ( void ) {
ALUNO * maria ;
maria = ( ALUNO *) mallo
( s i z e o f ( ALUNO ) ) ;
i f (! maria ) exit (1) ;
gets ( maria - > nome ) ;
s
anf ( " % 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;
Exer
ios
10.1: Considere que uma empresa precisa armazenar os seguintes dados de um
cliente:
Nome completo com no mximo 50 caracteres;
renda mensal do do cliente;
ano de nascimento;
possui ou no carro.
Defina 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
imprima.
10.2: Considerando a mesma estrutura do exerccio anterior, escreva um programa que leia os dados de 100 clientes e imprima:
quantos clientes tm renda mensal acima da mdia;
quantos clientes tm carro;
quantos clientes nasceram entre 1960 (inclusive) e 1980 (exclusive).
177
} Tfun ;
void
float
f l o a t media =0.0;
int i ;
for
}
int
int
fun ionarios ) {
return
main ( void ) {
Tfun
*
adastro ;
int fun
ionarios ;
har linha [40;
puts ( " Quantos fun
ionarios ? " ) ; fgets ( linha , 39 , stdin )
;
ss
anf ( linha , " % d " , & fun
ionarios ) ;
if
}
le (
adastro , fun
ionarios ) ;
printf ( " Salario medio = %.2 f \ n " ,
media (
adastro , fun
ionarios ) ) ;
return 0;
178
int
main ( void ) {
stru
t aluno turma [ MAX ;
le ( turma ) ;
puts ( " Imprimindo dados lidos da turma . " ) ;
puts ( " Digite qualquer
oisa para
ontinuar . " ) ;
get
har () ;
imprime ( turma ) ;
ordena_medias ( turma ) ;
puts ( " Imprimindo dados ordenados da turma . " ) ;
puts ( " Digite qualquer
oisa para
ontinuar . " ) ;
get
har () ;
imprime ( turma ) ;
get
har () ;
} FRACAO ;
180
Captulo 11
impressora que espera final de linha no modo DOS surge o que comumente
chamado de efeito escada. A impresso continua na linha seguinte mas sem
voltar para o incio da linha porque em UNIX o caractere de retorno de carro
no inserido no fluxo de texto.
At agora temos trabalhado com os fluxos de dados padro: stdin, para
entrada de dados e stdout para sada de dados. Ao iniciar todo programa em
C automaticamente associado a estes dois fluxos de dados sem necessitar de
nenhuma interveno do programador. A definio de que perifricos estaro
associados a estes fluxos depende do sistema operacional. Normalmente o fluxo
de entrada (stdin) est associado ao teclado e o fluxo de sada (stdout) ao
monitor.
fluxo binrio
000...01100
32 bits
12
32 bits
113
8 bits 8 bits
a
b
11.2.3 Arquivos
Um arquivo pode estar associado qualquer dispositivo de entrada e sada
como, por exemplo: impressora, teclado, disquete, disco rgido etc. No entanto,
os programas vem os arquivos atravs de fluxos. Para que um determinado
182
onde arq o ponteiro que ser usado para executar as operaes no arquivo.
11.4 In
io e Fim
As operaes mostradas a seguir mostram operaes que devem ser realizadas
antes e depois de usar um arquivo (fopen() e f
lose()). As outras duas funes
servem para que o usurio possa detectar o fim de um arquivo ou voltar para
seu incio.
183
Funo
fopen()
f
lose()
fput
()
get
(), fget
()
fprintf()
ss
anf()
fs
anf()
fseek()
rewind()
feof()
ferror()
fflush()
fread()
fwrite()
Descrio
Abre um arquivo
Fecha um arquivo
Escreve um caractere em um arquivo
L um caractere de um arquivo
Equivalente a printf()
Equivalente a s
anf(). L de uma cadeia de caracteres
Equivalente a s
anf()
Posiciona o arquivo em um ponto especfico
Posiciona o arquivo no incio
Retorna verdade se chegou ao fim do arquivo
Verifica a ocorrncia de um erro
Descarrega o buffer associado ao arquivo
Leitura de dados no modo binrio
Escrita de dados no modo binrio
har
*parq,
onst har
*modo)
Observar que se um arquivo for aberto com permisso de escrita todo o seu
contedo anterior ser apagado. Caso o arquivo no exista ele ser criado.
O trecho de programa abaixo ilustra os passos necessrios para abrir um
arquivo para escrita. Primeiro declarado o ponteiro pa para o arquivo. Em
seguida a funo fopen chamada para associar o nome externo do programa
(arquivo.txt) no modo escrita ao ponteiro pa. Um teste para ponteiro nulo
feito para verificar se ocorreu algum problema com a operao de abertura do
arquivo.
Lembrar que abrir, para escrita, um arquivo que j existe, implica em apagar
todo o contedo anterior e a preparao do arquivo para receber dados a partir
de seu ponto inicial. Se o programador deseja acrescentar dados ao final de um
arquivo j existente o modo de abertura deve ser a.
int
onde parq um ponteiro de arquivo para o arquivo que deve ser fechado. Todos
os buffers internos associados com o fluxo de dados do arquivo so descarregados. O contedo de qualquer buffer no escrito escrito e dados no lidos
de buffers so perdidos. Este ponto importante de ser considerado porque
em muitos sistemas operacionais uma operao de escrita em um arquivo no
ocorre imediatamente a emisso da ordem de escrita. O sistema operacional
pode executar a ordem no momento que achar mais conveniente. Um valor zero
de retorno significa que a operao foi executada com xito, qualquer outro valor
implica em erro.
int
feof(FILE *parq)
= get
har () ;
while (
!= EOF ) {
put
har (
) ;
= get
har () ;
}
return 0;
11.4.4 Volta ao In
io
A funo rewind() recoloca o indicador de posio de arquivo no incio do arquivo. Uma operao semelhante ao que fazemos em uma fita cassete de msica
ou vdeo. O prottipo da funo o seguinte:
void
rewind(FILE *parq)
int
int
As funes get () e fget () so equivalentes e muitos compiladores implementam get () como uma macro do seguinte modo:
#dene
int
int
onde parq um ponteiro de arquivo para o arquivo que foi previamente aberto
por meio da funo fopen() e
h o caractere a ser escrito.
O programa 11.2 mostra como um arquivo pode ser criado para leitura e
escrita. Em seguida um conjunto de caracteres lido do teclado escrito no arquivo. O prximo passo a leitura do arquivo que iniciada aps uma chamada
a funo rewind(), fazendo com que o indicador de posio do arquivo volte a
apontar para seu incio.
Uma outra alternativa mostrada em 11.3 mostra um exemplo onde o arquivo criado para escrita em seguida fechado e reaberto para leitura ficando
automaticamente posicionado no incio para a leitura.
int
187
FILE * pa ;
* nome = " texto . txt " ;
har
return
0;
188
FILE * pa ;
* nome = " texto . txt " ;
har
if
}
= get
har () ;
while (! feof ( stdin ) ) {
fput
(
, pa ) ;
= get
har () ;
}
f
lose ( pa ) ;
printf ( " \ nTerminei de es
rever , agora vou ler .\ n " ) ;
i f (( pa = fopen ( nome , " r " ) ) == NULL ) {
printf ( " \ n \ nErro ao abrir o arquivo - leitura .\ n "
);
exit (1) ;
}
= fget
( pa ) ;
while (! feof ( pa ) ) {
put
har (
) ;
= fget
( pa ) ;
}
f
lose ( pa ) ;
return 0;
189
#in
lude
int main
if
}
( pArq == NULL ) {
printf ( " Erro abrindo arquivo . " );
return 1;
else
}
}
{
fput
( 'x ' , pArq ) ;
i f ( ferror ( pArq ) ) {
printf ( " Erro es
revendo arquivo \ n " ) ;
f
lose ( pArq ) ;
return 1;
}
return
0;
int
int
190
FILE * pa ;
* nome = " texto . txt " ;
har
if
}
fgets ( linha , MAX , stdin ) ;
while (! feof ( stdin ) ) {
fputs ( linha , pa ) ;
fgets ( linha , MAX , stdin ) ;
}
rewind ( pa ) ; /* volta ao ini
io do arquivo */
printf ( " \ nTerminei de es
rever , agora vou ler .\ n \ n " );
fgets ( linha , MAX , pa ) ;
while (! feof ( pa ) ) {
puts ( linha ) ;
fgets ( linha , MAX , pa ) ;
}
f
lose ( pa ) ;
return 0;
191
har * nome
i f (( pa =
}
puts ( " Entre
om uma palavra . " ) ; s
anf ( " % s " , palavra )
;
puts ( " Entre
om um numero inteiro . " ) ; s
anf ( " % d " , & i )
;
puts ( " Entre
om um numero flutuante . " ) ; s
anf ( " % f " , &
f);
/* Es
reve os dados no arquivo */
fprintf ( pa , " % s % d % f " , palavra , i , f ) ;
rewind ( pa ) ; /* volta ao ini
io do arquivo */
printf ( " \ nTerminei de es
rever , agora vou ler .\ n " ) ;
fs
anf ( 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 ) ;
f
lose ( pa ) ;
return 0;
192
}
fwrite (& inum , s i z e o f ( int ) , 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 (&
, s i z e o f (
har ) , 1 , pa ) ;
rewind ( pa ) ;
fread (& inum , s i z e o f ( int ) , 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 (&
, s i z e o f (
har ) , 1 , pa ) ;
printf ( " %d , %f , %f , %
\ n " , inum , fnum , pi ,
) ;
f
lose ( pa ) ;
return 0;
Uma das principais aplicaes destas funes a leitura e escrita de estruturas criadas pelos usurios. A gravao em binrio da estrutura permite que o
193
sizeof (stru t
Para testar erro basta verificar o valor retornado pela funo. Caso ela tenha
retornado um valor diferente de MAX ocorreu um erro.
194
int
main () {
FILE * pa ;
har nome [40 , linha [80;
PESSOA turma [4 , ba
k [4;
int i ;
for ( i =0; i <4; i ++) {
puts ( " Nome ? " );
fgets ( turma [ i . nome , 40 , stdin ) ;
turma [ i . nome [ strlen ( turma [ i . nome ) -1= ' \0 ';
puts ( " Ano ? " ); fgets ( linha , 80 , stdin ) ;
ss
anf ( linha , " % d " , & turma [ i . ano ) ;
}
puts ( " \ nGravando \ n " );
puts ( " Qual o nome do arquivo ? " ) ; fgets ( nome , 40 , stdin
);
nome [ strlen ( nome ) -1= ' \0 ';
i f (( pa = fopen ( nome , " w + " ) ) == NULL ) {
puts ( " Arquivo nao pode ser aberto " ) ;
return 1;
}
for ( i =0; i <4; i ++) {
i f ( fwrite ( & turma [ i , s i z e o f ( PESSOA ) , 1 , pa ) !=
1)
puts ( " Erro na es
rita . " ) ;
}
rewind ( pa ) ;
for ( i =0; i <4; i ++) {
i f ( fread ( & ba
k [ i , s i z e o f ( PESSOA ) , 1 , pa ) !=
1) {
i f ( feof ( pa ) ) break ;
puts ( " Erro na leitura . " ) ;
}
}
for ( i =0; i <4; i ++) {
printf ( " Nome = % s \ n " , ba
k [ i . nome ) ;
printf ( " Ano = % d \ n \ n " , ba
k [ i . ano ) ;
}
return 0;
195
Exer
ios
11.1: Escreva um programa que abra um arquivo texto e conte o nmero de
caracteres presentes nele. Imprima o nmero de caracteres na tela.
11.2: Considere um arquivo de dados do tipo texto com o seguinte contedo:
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
primeira linha contm o nmero de alunos no arquivo. As linhas seguintes
contm os seguintes dados:
nome do aluno com no mximo 50 caracteres;
nota da primeira prova;
nota da segunda prova.
Escreva um programa que imprima os nomes de todos os alunos que tm a mdia
das duas notas menor que 7.0
11.3: Escreva um programa que grave os dados lidos no exerccio anterior em
um arquivo do tipo binrio de acesso aleatrio. O nmero que indica quantos
alunos devem ser lidos (primeira linha do arquivo) no deve ser gravado no
arquivo binrio. Nesta questo o programa deve obrigatoriamente usar um
vetor de estruturas do seguinte tipo:
} ALUNO ;
11.4: Escreva um programa que leia de um arquivo, cujo nome sera fornecido
pelo usurio, um conjunto de nmeros reais e armazena em um vetor. O tamanho mximo do vetor e dado pela constante TAM_MAX. A quantidade de nmeros
no arquivo varia entre 0 e TAM_MAX. O programa ao final calcula a media dos
nmeros lidos.
11.5: Faa um programa que leia 10 caracteres e armazene em um arquivo 10
cpias de cada um. Exiba o contedo
196
11.6: Crie uma funo que receba duas strings como parmetros, uma com um
endereo de arquivo e outra com um texto qualquer, e adicione o texto no fim
do arquivo.
11.7: Utilizando a funo do exerccio anterior faa um programa que gere 10
arquivos com o nome "Teste"e extenses "01", ..., "10". Cada um contendo o
texto "Texto do arquivo [NMERO DO ARQUIVO]".
11.8: Escreva um programa para armazenar o telefone de 5 amigos. O programa
deve obrigatoriamente usar a estrutura
197
1 - O
11 - a
indicando que os primeiros caracteres dos arquivos so iguais (O) bem como o
dcimo primeiro (a)
11.13: Um arquivo do tipo texto, chamado numeros.txt contm uma quantidade desconhecida de nmeros reais. Escreva um programa que leia estes nmeros, os coloque em ordem crescente e depois os grave em um arquivo binrio
chamado numeros.bin.
Observaes:
(a) Neste exerccio a quantidade de dados gravados no arquivo do tipo
texto desconhecida, portanto, obrigatrio usar um vetor definido
com ponteiro. A definio de um vetor com um nmero constante
de elementos, mesmo que seja um nmero grande, considerado um
erro.
(b) Para testar o programa crie o arquivo com um editor simples.
11.14: Um programador escreveu os trechos de programas (I) e (II), mostrados
nas listagens 11.9 e 11.10, para ler dados inteiros de um arquivo. O nmero de
dados armazenados no arquivo desconhecido.
while
(1)
fs
anf (p , " % d " , & i ) ;
i f ( feof ( p ) ) break ;
printf ( " % d \ n " , i ) ;
while
198
Captulo 12
Problemas Extras
1a Problema:
199
PN 1
xi
N
v
u N 1
u1 X
(xi x)2
= t
N i=0
i=0
(12.1)
(12.2)
Tarefa
A sua tarefa ler um conjunto de dados armazenado em um arquivo do tipo
texto, chamado estatistica.txt e calcular a mdia e depois o desvio padro
deste conjunto. Observe que o tamanho do conjunto desconhecido e s pode
ser descoberto aps a leitura de todos os dados.
Neste exerccio obrigatrio o uso de ponteiros para armazenar o
vetor.
Sada
A sada deve informar os valores obtidos para a mdia e o desvio padro.
Exemplo de Arquivo de Entrada e da sada
Arquivo estatistica.txt:
1
2
3
4
5
6
7
8
9
10
Sada na tela:
A media vale 5.500000
O desvio padrao vale 2.872281
3a Problema:
Tarefa
Z S est planejando a sua prxima viagem por Pindorama. No momento
ele gostaria de saber qual so as cidades mais distante e as mais perto da sua.
Para fazer estes clculos ele dispe de um arquivo com as coordenadas de sua
cidade e das vrias cidades que ele ir visitar
Entrada
A entrada ser feita a partir de um arquivo texto chamado cidades.txt.
A primeira linha deste arquivo um nmero inteiro n dizendo quantas cidades
h no arquivo. Considere que o nmero mximo de cidades igual a 50. As n
201
#in
lude
#in
lude
#in
lude
#define
#define
#define
int
int
int
int
int
pfs (
har *) ;
verifi
aCPF (
har *) ;
digito1 (
har *) ;
digito2 (
har * , int ) ;
leCPF (
har *) ;
* argv [) {
int
int
int
int
*/
linhas seguintes contm pares de nmeros com as coordenadas de cada uma das
cidades que Z S ir visitar. O primeiro par de coordenadas pertence a cidade
onde Z S vive.
Sada
A sada composta de trs tipos de linhas e deve ser feita no vdeo. A
primeira linha informa as coordenadas da cidade onde Z S vive. Em seguida
deve(m) vir as coordenadas da(s) cidade(s) que fica(m) mais perto da cidade
de Z S. Aps devem vir a(s) linha(s) que mostra(m) as coordenadas da(s)
cidade(s) que fica(m) mais longe da cidade de Z S. O exemplo abaixo mostra
o formato do arquivo de entrada e o formato da sada na tela.
Exemplo de entrada e sada
Arquivo :
8
2.0 2.0
0.0 0.0
1.0 1.0
3.0 3.0
4.0 4.0
0.0 4.0
4.0 0.0
7.0 7.0
5a Problema:
Sada na tela:
Origem: (2.000000, 2.000000)
Mais perto: (1.000000, 1.000000)
Mais perto: (3.000000, 3.000000)
Mais longe: (7.000000, 7.000000)
Produto Es alar
(12.3)
Tarefa
Escreva um programa que calcule o produto escalar de M pares de vetores,
todos em um espao de n dimenses. Neste problema no preciso saber
vetores em C.
Entrada
A entrada consiste das seguintes linhas de dados:
1. A primeira linha contm um nmero inteiro M que informa o nmero de
pares de vetores a serem lidos.
2. A segunda linha contm um nmero n que indica a dimenso de cada um
dos vetores.
3. As linhas restantes contm as coordenadas dos pares de vetores. Primeiro
n linhas com as coordenadas do primeiro par, em seguida n linhas com as
coordenadas do segundo par e assim sucessivamente.
203
Exemplo de sada:
32.000000
22.000000
204
Exemplo de entrada
12
8
21
14
5
36
21
43
14
6
21
24
43
7a Problema:
205
Exemplo de entrada
6
25
123456
14
-1
8a Problema:
typedef stru t
_CIRCULO
int x , y , raio ;
} CIRCULO ;
Entrada
Os dados estaro organizados da seguinte maneira. Primeiro, a quantidade
N de crculos, em seguida os dados dos N crculos, na seguinte ordem: coordenada x, coordenada y, raio raio.
Obs. No possvel assumir um valor mximo para N , aloque o espao de
memria necessrio.
Sada
O programa de imprimir se um dado crculo tem rea maior que a mdia
ou rea menor ou igual a mdia. Considerando que o primeiro crculo recebe o
nmero um, o segundo o nmero 2 e assim at o crculo N , o formato de sada
o seguinte: a palavra Circulo seguida do nmero do crculo e se ele tem rea
maior ou menor ou igual.
206
Exemplo de Entrada:
5
1 1 1
1 2 2
3 1 2
2 2 4
1 1 3
Exemplo de Sada:
Circulo 1 area menor ou igual
Circulo 2 area menor ou igual
Circulo 3 area menor ou igual
Circulo 4 area maior
Circulo 5 area maior
9a Problema:
Lu
rando
om Aes
Voc foi contratado, pela bolsa de valores de Pindorama, para escrever um
programa que imprima as aes com o melhor e o pior desempenho durante o
ano de 2325.
Entrada
A entrada ser lida de um arquivo texto com o nome de acoes.txt. O
arquivo consiste de uma srie de linhas. Em cada linha h o nome da ao
seguido pelas cotaes no dia 01 de janeiro de 2325 e no do dia 31 de dezembro
de 2325.
Nenhum nome de empresa ter mais de 20 caracteres. Observe que pode
haver mais de uma pior (melhor) ao.
Sada
A sada dever ser um arquivo do tipo texto, com o nome saida.txt. Neste
arquivo voc deve indicar a melhor ao e seu rendimento e a pior ao com sua
perda. Observe que pode haver mais de uma melhor (pior) ao.
Exemplo de Entrada:
Exemplo Sada:
10a Problema:
Somando Linhas
Escreva um programa que leia de um arquivo texto uma matriz quadrada de
nmeros reais. O tamanho mximo da matriz 10001000. O nome do arquivo
de entrada matrizin.txt. O seu programa deve calcular a soma de todos
os elementos de cada linha. Em seguida o seu programa deve descobrir qual a
maior soma e que linha tem soma igual a maior soma. O programa deve gravar
207
a maior soma e o(s) nmero(s) da(s) linha(s) com soma igual a maior em um
arquivo texto chamado matrizout.txt.
Entrada
Os dados no arquivo de entrada tem o seguinte formato. A primeira linha
do arquivo contm o tamanho da matriz (1 N 1000). Em seguida o arquivo
contm N N nmeros inteiros em um formato livre, ou seja quantidade de
nmeros por linha do arquivo varivel.
Sada
O arquivo de sada tem o seguinte formato. Primeiro o valor da maior soma
das linhas. Em seguida as linhas com soma igual a maior soma.
Exemplo de
5
1.0 2.0 3.0
2.0 1.0 2.0
3.0 0.0 0.0
5.0 1.0 0.0
1.0 1.0 1.0
Entrada:
4.0
1.0
0.0
2.0
1.0
Exemplo de Sada:
14.000000
1
2
3
2.0
8.0
11.0
6.0
1.0
11a Problema:
Misturando Dados
Uma tarefa muito comum em computao misturar dois vetores dados j
ordenados para criar um terceiro tambm ordenado.
A sua tarefa escrever um programa que leia os dados de dois vetores e os
misture em um terceiro.
Considere que o tamanho mximo de cada um dos dois vetores originais
desconhecido.
Entrada
A leitura dos dados vai ser feita da seguinte maneira. Primeiro o programa
deve ler o tamanho do primeiro vetor (tam1). Em seguida o programa deve ler
tam1 nmeros reais. Aps estas leituras o programa l o tamanho do segundo
vetor (tam2). Finalmente, o programa l tam2 nmeros reais. Considerar que
os dados do primeiro e do segundo vetor esto em ordem crescente.
Sada
Aps misturar os dois vetores em um terceiro o programa deve imprimir os
tam1 + tam2 nmeros reais armazenados no terceiro vetor. Estes dados devem
208
Exemplo de Sada:
1.0
1.0
2.0
4.0
7.0
9.0
10.0
12.0
209
Apndi e A
Tabela ASCII
A tabela ASCII (American Standard for Information Interchange) usada por
grande parte da indstria de computadores para a troca de informaes e armazenamento de caracteres. Cada caractere representado por um cdigo de
8 bits. A Tabela A.1 mostra os cdigos para a tabela ASCII de 7 bits. Existe
uma table estendida para 8 bits que inclui os caracteres acentuados.
Para saber qual o cdigo de um caractere na base 10 junte o dgito da
primeira coluna da tabela com o dgito da primeira linha da tabela. Por exemplo,
o cdigo da letra a minscula 97 na base 10.
0
1
2
3
4
5
6
7
8
9
10
11
12
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
ff
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
210
Carac
nul
stx
eot
ack
bs
lf
ff
so
dle
dc2
dc4
syn
can
sub
fs
rs
sp
Descrio
Caractere nulo
Comeo de texto
Fim de transmisso
Confirmao
Volta um caractere
Passa para prxima linha
Passa para prxima pgina
Shift-out
Data line escape
Controle de dispositivo
Controle de dispositivo
Synchronous idle
Cancela
Substitui
Separador de arquivo
Separador de registro
Espao em branco
Carac
soh
etx
enq
bel
ht
vt
cr
si
dc1
dc3
nak
etb
em
esc
gs
us
Descrio
Comeo de cabealho de transmisso
Fim de texto
Interroga
Sinal sonoro
Tabulao horizontal
Tabulao vertical
Passa para incio da linha
Shift-in
Controle de dispositivo
Controle de dispositivo
Negativa de confirmao
Fim de transmisso de um bloco
Fim de meio de transmisso
Escape
Separador de grupo
Separador de unidade
211
Apndi e B
Palavras Reservadas
Palavras reservadas, tambm as vezes chamadas de palavra chave, servem para
propsitos especiais nas linguagens de programao. Servem para declarar tipos
de dados ou propriedades de um objeto da linguagem, indicar um comando alm
de vrias outras funes. Palavras reservadas no podem ser usadas como nomes
de variveis ou funes.
asm: Indica que cdigo escrito em assembly ser inserido junto comandos C.
auto: Modificador que define a classe de armazenamento padro.
break: Comando usado para sair incondicionalmente dos comandos for, while,
switch, and do...while.
case: Comando usado dentro do comando switch.
char: O tipo de dados mais simples em C, normalmente usado para armazenar
caracteres.
const: Modificados de dados que impede que uma varivel seja modificada.
Esta palavra no existia nas primeiras verses da linguagem C e foi introduzida pelo comit ANSI C. Veja volatile.
continue: Comando que interrompe os comandos de repetio for , while ,
ou do...while e faz que eles passem para a prxima iterao.
default: usado dentro do comando switch para aceitar qualquer valor no
definido previamente com um comando case.
do: Comando de repetio usado em conjunto com o comando while . Pela
definio do comando o lao sempre executado pelo menos uma vez.
double: Tipo de dados usado para armazenar valores de ponto flutuante em
preciso dupla.
else: Comando que indica um bloco de comandos alternativo que deve ser executado quando a condio testada pelo comando if foi avaliada como
FALSA.
212
enum: Tipo definido pelo usurio que permite a definio de variveis que iro
aceitar somente certos valores.
extern: Modificador de dados que indica que uma varivel ir ser declarada em
outra rea do programa.
float: Tipo usado para armazenar valores de ponto flutuante.
for: Comando de repetio que contm inicializao de variveis, incremento e
sees condicionais. Em C o comando for um comando de repetio
extremamente flexvel, permitindo inmeras possibilidades.
goto: Comando que causa um pulo para uma posio do programa marcada
com um rtulo.
if: Comando de testes usado para mudar o fluxo do programa baseada em uma
deciso VERDADEIRO/FALSO.
int: Tipo de dados usado para armazenar valores inteiros.
long: Tipo de dados usado para armazenar valores inteiros com preciso maior
do que o tipo int. Nos computadores modernos o tipo long tem a mesma
preciso que o tipo int e so usados 4 bytes.
register: Especificador de classe de armazenamento que pede que, caso seja
possvel, uma varivel deve ser armazenada nos registradores do processador.
return: Comando que causa o fluxo de instrues do programa abandonar a
funo em execuo e retornar para a funo que chamou. Tambm pode
ser usado para retornar um nico valor.
short: Tipo de dados usado para armazenar valores inteiros em preciso menor
do que o tipo int. Neste tipo 2 bytes so usados para armazenar os dados.
signed: Modificador usado para indicar que uma varivel pode armazenar tanto
valores positivos como negativos.
sizeof: Operador que retorna o tamanho em bytes do item fornecido.
static: Modificador usado para significar que o compilador deve preparar o
cdigo de forma a reter o valor da varivel.
struct: Usado para combinar C variveis de tipos diferentes na mesma estrutura.
switch: Comando de desvio usado para permitir que o fluxo do programa possa
ser mudado para vrias direes diferentes. Usado em conjunto com o
comando case.
typedef: Modificador usado para criar novos nomes para tipos j existentes.
union: Palavra chave usada para permitir mltiplas variveis partilharem o
mesmo espao na memria.
213
unsigned: Modificador usado para significar que uma varivel conter somente
valores positivos.
void: Palavra usada para significar que ou a funo no retorna nada ou que
um ponteiro deve ser considerado genrico ou ser capaz de apontar para
qualquer tipo de dados.
volatile: Modificador que significa que uma varivel pode ser alterada.
while: Comando de teste que executa uma seo de cdigo enquanto uma condio retorna VERDADEIRO.
Em adio a estas as seguintes palavras so reservadas em C++:
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.
214
215