Anda di halaman 1dari 145

r

in
a
el
im

C para no Computeiros: uma introduo ao


raciocnio computacional
Paulo R. Coelho

Pr

Lsaro Camargos

Ve
r

s
o

12 de maro de 2013

s
o

Ve
r

in
a

el
im

Pr

Bsico

11

O computador uma mquina burra


1.1 Algoritmo . . . . . . . . . . . . . . . . .
1.2 Linguagem de Programao . . . . . . .
1.3 A linguagem C(++) . . . . . . . . . . . .
1.3.1 Meu Primeiro Programa . . . . .
1.3.2 rea de um Retngulo . . . . . .
1.3.3 Tipos Primitivos da Linguagem C
1.3.4 Organizao do Cdigo . . . . . .
1.4 A Funo main . . . . . . . . . . . . . .
1.5 Concluso . . . . . . . . . . . . . . . . .
1.6 Exerccios . . . . . . . . . . . . . . . . .
1.6.1
. . . . . . . . . . . . . . . . . .
1.6.2
. . . . . . . . . . . . . . . . . .

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

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

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

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

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

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

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

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

Compilao e Execuo
2.1 O processo de compilao
2.2 A IDE Code::Blocks . . .
2.2.1 Criando um Projeto
2.2.2 Depurao . . . .
2.3 O Arquivo Executvel . . .
2.4 Exerccios . . . . . . . . .
2.4.1
. . . . . . . . . .
2.4.2
. . . . . . . . . .

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

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

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

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

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

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

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

13
13
13
14
14
15
16
16
17
18
18
18
18

Pr

el
im

in
a

Sumrio

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

19
19
20
20
21
22
23
23
23

Variveis, Entrada / Sada e Operadores


3.1 Declarao de Variveis . . . . . . .
3.1.1 Atribuio e Uso . . . . . .
3.1.2 Parmetros so Variveis . .
3.2 Entrada / Sada . . . . . . . . . . .
3.2.1 Impresso . . . . . . . . . .
3.2.2 Leitura . . . . . . . . . . .
3.3 Operadores . . . . . . . . . . . . .
3.3.1 Construes Especiais . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

25
25
26
28
28
28
29
30
30

s
o

.
.
.
.
.
.
.
.

Ve
r

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

SUMRIO

.
.
.
.

.
.
.
.

.
.
.
.

Seleo Simples
5.1 Operadores Relacionais .
5.2 if-else . . . . . . . .
5.3 Funes e Procedimentos
5.4 O Tipo Primitivo bool .
5.5 Exerccios . . . . . . . .
5.5.1
. . . . . . . . .
5.5.2
. . . . . . . . .
5.5.3
. . . . . . . . .
5.5.4
. . . . . . . . .
5.5.5
. . . . . . . . .
5.6 Laboratrio . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

31
31
31
31
32

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

33
33
36
36
36

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

37
39
40
43
44
44
44
45
46
46
46
46

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

47
47
49
50
50
50
51

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

53
53
56
57
57
59
59
59

Repetio (I)
8.1 Motivao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.2 O comando while . . . . . . . . . . . . . . . . . . . . . . . . . . . .
8.3 O comando do-while . . . . . . . . . . . . . . . . . . . . . . . . . .

61
61
62
63

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.

Seleo Simples (II)


6.1 if-else e Operadores Lgicos
6.2 Prioridade dos Operadores .
6.3 Exerccios . . . . . . . . . .
6.3.1
. . . . . . . . . . .
6.3.2
. . . . . . . . . . .
6.3.3
. . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

Switch
7.1 switch-case-default
7.2 break . . . . . . . .
7.3 Exerccios . . . . . . .
7.3.1
. . . . . . . .
7.3.2
. . . . . . . .
7.3.3
. . . . . . . .
7.4 Laboratrio . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

s
o

Pr

el
im

Variveis (II)
4.1 Escopo de Variveis
4.2 Faixas de Valores .
4.3 Exerccios . . . . .
4.4 Laboratrio . . . .

.
.
.
.
.

Ve
r

3.3.2 Precedncia de Operadores


Exerccios . . . . . . . . . . . . .
3.4.1
. . . . . . . . . . . . . .
3.4.2
. . . . . . . . . . . . . .
3.4.3
. . . . . . . . . . . . . .

in
a

3.4

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

SUMRIO
.
.
.
.
.
.
.
.
.
.
.
.
.
.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Repetio (II)
9.1 for . . . . . . . . . . . . . . . . . . . . . . . .
9.2 Mais Exemplos . . . . . . . . . . . . . . . . .
9.3 Declaraes especiais . . . . . . . . . . . . . .
9.4 Alterando a repetio com o break e continue
9.5 Exerccios . . . . . . . . . . . . . . . . . . . .
9.6 Laboratrio . . . . . . . . . . . . . . . . . . .
9.6.1
. . . . . . . . . . . . . . . . . . . . .
9.6.2
. . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

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

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

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

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

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

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

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

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

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

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

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

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

Ve
r

s
o

10 Tipos de Dados e Suas Representaes


10.1 Bit & Byte . . . . . . . . . . . . . . . .
10.1.1 Base Binria . . . . . . . . . .
10.1.2 Base Hexadecimal . . . . . . .
10.2 Converso entre bases numricas . . . .
10.3 Tipos Numricos Inteiros . . . . . . . .
10.3.1 Nmeros Binrios Negativos . .
10.4 Aritmtica Inteira Binria . . . . . . . .
10.4.1 Nmeros positivos . . . . . . .
10.4.2 Nmeros em Complemento de 2
10.4.3 E a subtrao? . . . . . . . . .
10.5 Tipos Numricos Reais . . . . . . . . .
10.6 Representao de caracteres . . . . . .
10.7 Exerccios . . . . . . . . . . . . . . . .
10.7.1 . . . . . . . . . . . . . . . . .
10.7.2 . . . . . . . . . . . . . . . . .
10.7.3 . . . . . . . . . . . . . . . . .
10.7.4 . . . . . . . . . . . . . . . . .
10.7.5 . . . . . . . . . . . . . . . . .
10.7.6 . . . . . . . . . . . . . . . . .
10.8 Laboratrio . . . . . . . . . . . . . . .

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

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

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

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

64
66
66
66
66
66
67
67
67
67
67
67
68
68

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

69
69
71
71
72
73
73
73
73

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

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

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

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

75
75
75
76
76
77
77
79
80
80
81
81
81
82
82
82
82
83
84
84
84

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

Pr

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

in
a

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

8.6

Mais exemplos
Exerccios . . .
8.5.1
. . . .
8.5.2
. . . .
8.5.3
. . . .
8.5.4
. . . .
Laboratrio . .
8.6.1
. . . .
8.6.2
. . . .
8.6.3
. . . .
8.6.4
. . . .
8.6.5
. . . .
8.6.6
. . . .
8.6.7
. . . .

el
im

8.4
8.5

SUMRIO
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

84
84
85
85

11 Arranjos Unidimensionais
11.1 Vetores . . . . . . . . . . . . . . . . . . .
11.2 Vetores de Caracteres . . . . . . . . . . . .
11.2.1 Vetores de Caracteres como Strings
11.3 Exerccios . . . . . . . . . . . . . . . . . .
11.4 Laboratrio . . . . . . . . . . . . . . . . .

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

.
.
.
.
.

87
87
88
90
91
91

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

13 Funes teis I
13.1 Funes Matemticas
13.2 Exerccios . . . . . .
13.2.1 . . . . . . .
13.2.2 . . . . . . .

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

93
93
94
96
96
96
96
96
96
96
96

.
.
.
.
.
.
.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

97
97
99
99
99

14 Arranjos Multidimensionais (I)


14.1 Declarao e Iniciao . . . .
14.1.1 Acesso aos elementos
14.2 Matrizes de Caracteres . . . .
14.3 Mais Dimenses . . . . . . . .
14.4 Multiplicao de Matrizes . .
14.5 Exercicios . . . . . . . . . . .
14.5.1 . . . . . . . . . . . .
14.5.2 . . . . . . . . . . . .
14.5.3 . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

101
101
102
102
103
103
104
104
104
105

15 Arranjos Multidimensionais (II)


15.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15.2 Passagem de matriz como parmetro em funes . . . . . . .
15.3 Matrizes Bidimensionais Como Unidimensionais e Vice-Versa
15.4 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

107
. 107
. 107
. 108
. 110

Ve
r

s
o

Pr

el
im

12 Strings e Funes
12.1 Funes para manipulao Strings . .
12.2 Funes com vetores como parmetros
12.3 Exerccios . . . . . . . . . . . . . . .
12.3.1 . . . . . . . . . . . . . . . .
12.3.2 . . . . . . . . . . . . . . . .
12.3.3 . . . . . . . . . . . . . . . .
12.3.4 . . . . . . . . . . . . . . . .
12.3.5 . . . . . . . . . . . . . . . .
12.3.6 . . . . . . . . . . . . . . . .
12.3.7 . . . . . . . . . . . . . . . .

.
.
.
.

in
a

10.8.1
10.8.2
10.8.3
10.8.4

.
.
.
.

.
.
.
.

.
.
.
.

7
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

II

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

el
im

16 Ordenao de Arranjos
16.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . .
16.2 Algoritmos de Ordenao . . . . . . . . . . . . . . . . .
16.2.1 Algoritmo de Insero (Insertion Sort) . . . . . .
16.2.2 Algoritmo de Seleo (Selection Sort) . . . . . .
16.2.3 Algoritmo de Ordenao por Troca (Bubble Sort)
16.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . .
16.3.1 . . . . . . . . . . . . . . . . . . . . . . . . . .
16.3.2 . . . . . . . . . . . . . . . . . . . . . . . . . .
16.3.3 . . . . . . . . . . . . . . . . . . . . . . . . . .

Intermedirio

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

111
111
111
111
112
113
114
114
114
114

115

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

117
117
117
118
119
119
120
120
120
120

18 Referncias
18.1 A memria um grande vetor . . . . . . .
18.2 Variveis do Tipo Referncia . . . . . . . .
18.3 Passagem de Referncias como Parmetros
18.4 Laboratrio . . . . . . . . . . . . . . . . .
18.4.1 . . . . . . . . . . . . . . . . . . .
18.4.2 . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

121
121
121
123
124
124
124

19 Referncias II
19.1 Ponteiros para Structs . . . . . . . . . . . .
19.2 Arranjos e Ponteiros . . . . . . . . . . . .
19.2.1 Percorrendo vetores com ponteiros .
19.3 Laboratrio . . . . . . . . . . . . . . . . .
19.3.1 . . . . . . . . . . . . . . . . . . .
19.3.2 . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

.
.
.
.
.
.

125
125
126
127
128
128
129

.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.

Ve
r

s
o

Pr

17 Estruturas No-Homogneas
17.1 Introduo . . . . . . . . . . . . . . .
17.2 Declarao . . . . . . . . . . . . . .
17.2.1 typedef . . . . . . . . . . . .
17.3 Acesso aos Campos de Uma Estrutura
17.4 Exemplo . . . . . . . . . . . . . . . .
17.5 Exerccios . . . . . . . . . . . . . . .
17.5.1 . . . . . . . . . . . . . . . .
17.5.2 . . . . . . . . . . . . . . . .
17.6 Laboratrio . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.

110
110

in
a

15.4.1
15.4.2

SUMRIO

SUMRIO

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

21 Arquivos
21.1 Arquivos de texto . . . . . . . . . . . . . . . .
21.1.1 Abertura e Fechamendo de Arquivos . .
21.1.2 Criao de Arquivos . . . . . . . . . .
21.1.3 Cuidados com a Formatao dos Dados
21.2 Laboratrio . . . . . . . . . . . . . . . . . . .
21.2.1 . . . . . . . . . . . . . . . . . . . . .
21.2.2 . . . . . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.

131
131
132
133
133
134
134
134
134
134
134

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

135
135
135
137
138
139
139
139

in
a

.
.
.
.
.
.
.
.
.
.

el
im

.
.
.
.
.
.
.
.
.
.

20 Alocao Dinmica
20.1 Alocao Dinmica de Tipos Simples
20.2 Alocao Dinmica de Vetores . . . .
20.3 Liberao de memria . . . . . . . .
20.4 Alocao Dinmica de Estruturas . . .
20.5 Exerccios . . . . . . . . . . . . . . .
20.5.1 . . . . . . . . . . . . . . . .
20.5.2 . . . . . . . . . . . . . . . .
20.6 Laboratrio . . . . . . . . . . . . . .
20.6.1 . . . . . . . . . . . . . . . .
20.6.2 . . . . . . . . . . . . . . . .

Ve
r

s
o

Pr

22 Navegao dentro do arquivo


141
22.1 Posicionmento no arquivo . . . . . . . . . . . . . . . . . . . . . . . 141
22.2 Arquivos formatados . . . . . . . . . . . . . . . . . . . . . . . . . . 142

in
a

Introduo

Ve
r

s
o

Pr

el
im

A habilidade de olhar para um problema complexo e extrair do mesmo um conjunto


de problemas mais simples e, portanto, mais facilmente resolvveis, essencial aos
profissionais da computao, pois na automatizao de tarefas por um computador,
necessrio quebr-las em unidades mnimas, que sejam compreensveis pela mquina.
Acontece que esta habilidade tambm til profissionais das mais diversas reas. A
esta habilidade, chamamos de raciocnio computacional.
Este material uma tentativa de organizar um curso de raciocnio computacional,
via aprendizado de tcnicas bsicas de programao. Nosso pblico alvo so os estudantes cujo tpico principal de estudo no a Cincia da Computao ou reas afins,
embora estes tambm possam se beneficiar deste material como uma introduo aos
estudos mais aprofundados que faro.
Este tipo de curso tradicional nos estudos de engenharia e mesmo outras reas e,
provavelmente por razes histricas, dado usando-se como ferramenta a linguagem
de programao C. Aqui usaremos C, mas no toda ela e no somente ela. Em vez
disso, usaremos parte da linguagem C, extendida com partes da linguagem C++. A
esta combinao, chamaremos C(++).
O material dividido em captulos correspondendo a aproximadamente uma aula
de 100 minutos. So apresentadas mais lies do que provavelmente comporiam um
curso deste tipo dando, assim, opes para que os professores usando livro variem a
estrutura de seus cursos.
Sugere-se que a primeira parte do livro, mais bsica, seja seguida na ntegra e na
ordem em que apresentada. A segunda parte contm tpicos mais (mas no completamente) independentes. A terceira parte apresenta tpicos mais avanados, que podero
ser usadas em turmas com melhor rendimento.
Cada captulo iniciado com uma motivao para o tpico apresentado, seguido de
sees com a teoria e exemplos. O captulo termina, ento, com exerccios propostos e
problemas para serem resolvidos em laboratrio.

s
o

Ve
r

in
a

el
im

Pr

10
SUMRIO

s
o

Ve
r
Bsico

11

in
a

el
im

Pr
Parte I

s
o

Ve
r

in
a

el
im

Pr

el
im

in
a

O computador uma mquina


burra

Captulo 1

1.1

Algoritmo

Pr

Computadores so mquinas burras que no fazem nada alm de seguir instrues.


Sendo assim, eles precisam de instrues precisas e detalhadas sobre o que fazer.
Para montar a sequncia de instrues que resolvam determinado problema precisamos, antes de qualquer outra coisa, entender o problema e sermos capazes de resolv-lo
na mo. Uma vez que tenhamos uma soluo teremos o que chamamos de um algoritmo.

s
o

Um algoritmo nada mais que um conjunto de instrues para se resolver um problema. Por exemplo, para se destrancar uma porta temos o seguinte algoritmo:
Coloque a chave na fechadura
Gire a chave

Ve
r

claro que este algoritmo est em um nvel de abstrao muito alto e que poderia
ser muito mais detalhado. Por exemplo, no h por qu destrancar a porta se ela j estiver destrancada e no h como destranc-la se no estiver de posse da chave. Quanto
mais detalhada sua sequncia de passos, mais prximo de algo inteligvel ao computador ela ser. Para isto ocorra, isto , para que o computador entenda suas intrues,
alm de detalhadas, eles precisam ser escritas em uma linguagem de programao.

1.2

Linguagem de Programao

De acordo com a fontes altamente confiveis


A programming language is an artificial language designed to communicate instructions to a machine, particularly a computer. Programming
13

14

CAPTULO 1. O COMPUTADOR UMA MQUINA BURRA


languages can be used to create programs that control the behavior of a
machine and/or to express algorithms precisely.

1.3

A linguagem C(++)

in
a

De forma simplificada, uma liguagem de programao um conjunto de palavras e


regras para o uso destas palavras na descrio de algoritmos interpretveis por um
computador.
Existem diversas linguagens de programao, tendo cada uma seus pontos fortes e
fracos. Neste curso, usaremos as linguagens C e C++, por razes que no discutiremos
aqui.

s
o

Pr

el
im

A primeira encarnao da linguagem de programao C foi desenvolvida no fim da


dcada de 60, tendo sido extendida, melhorada e padronizada vrias vezes depois. A
linguagem C++, que extende a linguagem C com diversos features como classes e streams, comeou a ser desenvolvida na dcada de 70 e, como a linguagem C, tambm
passou por vrias reformas. Como resultado, hoje temos uma linguagem C++ padronizada que pode ser usada, alas com certa dificuldade, para se programar em vrios
sistemas operacionais de forma portvel. Alm disso, a linguagem C++ um super
conjunto da linguagem C. Ou seja, todo e qualquer programa em C tambm um programa em C++, mesmo que o oposto no seja verdade.
Uma vez que o objetivo deste curso introduzir o uso do racioccio computacional,
no estudaremos todos os aspectos da linguagem C, mas somente aqueles essenciais.
Alm disso, usaremos partes da linguagem C++ para simplificar o desenvolvimento
dos nossos programas. Assim, nos referiremos linguagem usada como C(++), pois
nem toda a C, e nem somente C, mas no chega a ser C++. Mas chega de ladainha;
vamos ao nosso primeiro programa em linguagem C(++)!

1.3.1

Meu Primeiro Programa

Ve
r

O algoritmo em linguagem C(++)1 , abaixo, descreve para o computador os passos


necessrios para se escrever a mensagem Ol Mundo! na tela do computador. No
se preocupe com os detalhes de como isso feito agora, mas foque-se nos seguintes
aspectos:
existem vrias formas de se dizer Ol Mundo!, por exemplo se pode saltar
antes de faz-lo, agaixar, ou fechar os olhos. Todas estas formas so corretas,
embora algumas possam lhe causar certo constrangimento.
um cdigo de computador deve ser entendido, alm de pelos computadores, tambm por humanos. Sendo assim, imprescindvel que voc mantenha o cdigo
organizado.
usar acentos em um programa fonte de dores de cabea; melhor simplesmente
ignor-los aqui.
1 Usaremos

tambm os termos programa e cdigo para nos referirmos a tais algoritmos.

1.3. A LINGUAGEM C(++)

15

programar no uma arte mas, sim, magia!!!


#include <iostream>
2

using namespace std;


4

in
a

int main()
{
cout << "Ola Mundo!" << endl;
return 0;
}

1.3.2

rea de um Retngulo

el
im

Analisando o programa anterior, podemos facilmente identificar a linha que contm


a frase Ola Mundo!. Esta linha a que efetivamente escreve na tela do computador.
Altere esta linha para que contenha, por exemplo, seu nome em vez da palavra Mundo.
Digamos que seu nome seja Feissibukson. Este programa agora escreve na tela do
computador os dizeres Ola Feissibukson!.
Para entendermos o que as demais linhas fazem, precisamos passar para o nosso
prxmo problema/programa.

int f(int a, int b)


{
return a * b;
}

A linha 1 do cdigo define a funo f como uma funo que aceita dois parmetros
e b. Alm disso, esta funo tambm define que cada um destes parmetros um
nmero inteiro ao preceder cada parmetro pela palavra int. Finalmente, esta linha
tambm define que o resultado da funo ser um nmero inteiro ao preceder o nome
da funo (f) pela palavra int. Isto quer dizer que se voc no pode usar esta funo
para calcular a rea de retngulos cujos lados no sejam inteiros. Mas no se preocupe,
corrigiremos esta deficincia daqui a pouco.
As linhas 2 e 4 definem o corpo da funo, isto , quais outras linhas so partes da
funo f. Toda funo na linguagem C precisa ter definido seu comeo e fim usando {
e }, respectivamente.
A linha 3 do cdigo onde o clculo da rea efetivamente executado: a*b. Alm
disso, esta linha define tambm qual o resultado da funo ao preceder o resultado da
multiplicao por return.

Ve
r

s
o

Pr

A rea de um retngulo pode ser facilmente calculada caso voc saiba o comprimento
de sua base e de sua altura. Matematicamente, seja b o comprimento da base e a a
altura. A funo f equivalente rea do retngulo pode ser definda como: f (a, b) =
a b. Isto , a funo f tem dois parmetros (a altura a e base b do retngulo) e calcula
a rea como sendo a multiplicao de a e b. Em linguagem C(++) pode-se escrever esta
funo como mostrado no prximo segmento de cdigo, que analisaremos em seguida.

16

CAPTULO 1. O COMPUTADOR UMA MQUINA BURRA

1.3.3

Tipos Primitivos da Linguagem C

O cdigo apresentado acima, como mencionado, tem a limitao de s calcular a rea


de retngulos cujos lados tenham tamanhos inteiros. Para corrigir esta deficincia, vamos alter-lo para que aceite nmeros reais. Em computao, nmeros reais so tambm chamados de nmeros com pontos flutuantes e, em linguagem C, simplesmente
de float. Sendo assim, podemos corrigir o programa simplesmente substituindo as
ocorrncias da palavra int por float.

float f(float a, float b)


{
return a * b;
}

in
a

1.3.4

el
im

Pronto, a funo agora recebe dois parmetros do tipo float e retorna um resultado tambm deste tipo. Juntamente com outros tipos que sero vistos adiante no curso,
int e float so chamados de tipos de dados primitivos da linguagem. Isto sugere,
obviamente, que h tambm tipos no primitivos, e nada poderia ser mais verdade.
Estes tipos, contudo, no sero estudados por enquanto.

Organizao do Cdigo

Pr

possvel facilmente perceber um padro nos exemplos de cdigo apresentados at


agora:
A linha definindo a funo seguida por uma linha contendo apenas um { que
alinhado com o incio da linha acima.

s
o

A ltima linha da funo contm apenas um }, alinhado com o { do incio da


funo.

Todas as linhas entre { e } esto alinhas e mais avanadas em relao s chaves.

Ve
r

Esta organizao do cdigo serve para facilitar a leitura do cdigo, uma vez que torna
extremamente bvio onde a funo comea e termina.
Algo que faltou nestes exemplos e que tambm serve ao propsito de facilitar o
entendimento do cdigo so os chamados comentrios. O exemplo a seguir mostra
como a funo f poderia ser comentada.

10

/*
* A funcao a seguir calcula a area de um retangulo de base
* b e altura b. Os parametros e resultado da funcao sao do
* tipo float.
*/
float f(float a, float b)
{
//Calcula e retorna a area do retangulo.
return a * b;
}

1.4. A FUNO MAIN

17

10

in
a

/*
* A funcao a seguir calcula a area de um retangulo de base
* base e altura altura. Os parametros e resultado da funcao
* sao do tipo float.
*/
float area_retangulo(float altura, float base)
{
//Calcula e retorna a area do retangulo.
return altura * base;
}

1.4

el
im

Observe que h dois tipos de comentrios no cdigo. O primeiro comea com \*


e termina com *\ e o segundo comea com \\ e termina no final da linha. Todos
os comentrios servem somente ao programador e so completamente ignorados pelo
computador.
Finalmente, muito importante nomear suas funes e parmetros com nomes intuitivos. Seguindo esta orientao, escreveremos a ltima verso de nossa funo.

A Funo main

#include <iostream>

Pr

Que o computador uma mquina burra e executa somente o que voc manda voc j
deve ter entendido, mas como mand-lo executar algo? Em linguagem C, o computador
sempre comea a execuo de um programa pela funo main. Sendo assim, se voc
quer dizer ao computador que calcule a rea de um retngulo, ento esta ordem dever
partir, de alguma forma, da funo main. Por exemplo, veja o cdigo abaixo.

s
o

using namespace std;


4

Ve
r

/*
* A funcao a seguir calcula a area de um retangulo de base
* base e altura altura. Os parametros e resultado da funcao
* sao do tipo float.
*/
float area_retangulo(float altura, float base)
{
//Calcula e retorna a area do retangulo.
return altura * base;
}

10

12

14

16

18

20

22

int main()
{
//Calculemos a area de alguns retangulos.
cout << area_retangulo(3.3, 2.0) << endl;
cout << area_retangulo(2.0, 2.0) << endl;
//Lembre-se, todo numero inteiro tambem e um numero real.
cout << area_retangulo(4, 2) << endl;

24

return 0;

18
26

CAPTULO 1. O COMPUTADOR UMA MQUINA BURRA

Algumas observaes importantes sobre a funo main:


1. A funo main tem um resultado do tipo inteiro e seu resultado sempre 0
(return 0;). Bom, nem sempre 0, mas por enquanto definiremos sempre
assim.

in
a

2. Funo main como um highlander: s pode haver uma! Isto , cada programa
s pode conter a definio de uma funo com este nome.
3. Finalmente, a funo area_retangulo aparece antes da fuo main no programa. Isto deve ser verdade para todas as funes do seu programa. Isto ocorre
por qu, antes de executar a funo main, o computador precisa aprender sobre
a existncia das outras funes.

Concluso

Pr

1.5

el
im

O cdigo como est, includindo as duas linhas iniciais que ainda no sabem para
que serverm, est pronto para ser executado no seu computador. Por que voce no
experimenta faz-lo? Para tal, crie um projeto do tipo Console Application, usando a
linguagem C++.

Os cdigos apresentados neste captulo, apesar de simples, ilustraram vrios pontos


importantes da programao em de computadores em geral e da linguagem C em especfico. Estes pontos podem ser sumarizados assim:

s
o

Em C se pode definir funes que executem computaes bem definidas e especficas.


C tem vrios tipos de dados, como int (nmeros inteiros) e float (nmeros
reais).

Ve
r

importante manter o cdigo organizado, comentado e indentado. Isso facilita


seu entendimento e manuteno.

1.6

Exerccios

1.6.1

Escreva um funo que calcule a rea de um tringulo.

1.6.2
Escreva um funo que calcule a rea de um crculo. Observe que a linguagem C
baseada na lngua inglesa, na qual se separa casas decimais por . e no por ,. Logo,
igual 3.14 e no 3,14.

in
a

Compilao e Execuo

Captulo 2

2.1

Pr

el
im

Para colocarmos nossos algoritmos em execuo, o primeiro passo escrev-los, usando


um editor de textos qualquer que salve arquivos em texto puro, como o notepad, vim,
gedit, etc. Relembrando, o arquivo com o cdigo do programa conhecido como cdigo fonte ou simplesmente fonte. Uma vez de posse do fonte, preciso submet-lo a
um processos com vrios passos que gera, ao final, um arquivo executvel. O processo
como um todo conhecido como compilao, apesar de compilao ser apenas um dos
passos do processo. Este processo descrito na prxima seo.

O processo de compilao

Ve
r

s
o

A sequncia de passos que compem a compilao a seguinte:


Cdigo Fonte Pr-processador Fonte Expandido Compilador Arquivo
Objeto Ligador Executvel
De forma simplificada, a pr-compilao um passo que modifica o cdigo fonte
substituindo certas palavras chave encontradas ao longo do texto por suas definies.
Por exemplo, pode-se definir que, no programa, toda vez que o pr-processador encontrar a palavra PI, ele a substituir por 3.141649. Se voc est perdido, no se preocupe.
A funo da pr-compilao ficar mais clara mais adiante no curso.
Uma vez termina a pr-compilao, acontece a compilao do seu programa. A
compilao traduz o cdigo que voc escreveu para uma linguagem inteligvel ao computador, salvando-o em um arquivo chamado arquivo objeto. Por exemplo, a compilao transformaria o cdigo Ol Mundo! escrito acima em algo como
...
CALL
GIO
RET
...

write(0x1,0x400623,0xe)
fd 1 "Ol Mundo!"

Aps a compilao vem a linkedio, o passo que junta o seu arquivo objeto a
outros arquivos objetos interessantes, como por exemplo um que contenha cdigo de
19

20

CAPTULO 2. COMPILAO E EXECUO

funes matemticas, manipulao de arquivos, ou interao grfica com o usurio.1

2.2

A IDE Code::Blocks

2.2.1

el
im

in
a

Embora a edio de um programa pode ser feita em praticamente qualquer editor de


textos, h certos editores que so mais adequados a esta tarefa. Tais editores fazem,
dentre outras, a colorizao das palavras de seu cdigo de forma a ajud-lo a detectar
erros e tentam alinhar automaticamente as linhas do seu cdigo. A inteno destes
editores aumenentar sua produtividade como programador. Outros editores vo ainda
mais longe e lhe permitem fazer todo o processo de compilao com um simples click
do mouse ou apertar de uma tecla. Estes editores mais completos so conhecidos como
Integrated Development Environment, ou simplesmente IDE.
No decorrer deste curso consideraremos que o aluno estar usando a IDE que
gratuita e com verses para Windows, Linux e OSX. Entretanto, qualquer outra IDE
ou mesmo a compilao manual podem ser usados em substituio ao Code::Blocks.

Criando um Projeto

Ve
r

s
o

Pr

Para comear a programa no Code::Blocks, precisamos criar um projeto. Este projeto


conter seu cdigo fonte e, no caso de uma programao mais avanada, arquivos de
imagens, definies de personalizao do processo de compilao, etc. Para criar um
projeto no Code::Blocks, clique em File e, em seguida, New, Project.
Na tela que se apresenta, voc deve escolher o tipo de projeto a ser criado. No se
perca nos tipos; escolha Console Application e ento clique em Go.

Na tela seguinte voc dever escolher a linguagem de programao usada; escolha


C++ e clique em Next para passar para a tela onde dever nomear o seu projeto. Em
project title escreva algo como aula6_1; em folder to create the project in, clique no
1 Embora a explicao dada aqui no seja estritamente correta, ela prxima o suficiente da realidade
para o escopo deste curso.

2.2. A IDE CODE::BLOCKS

21

el
im

in
a

botao com ... e escolha uma pasta para salvar o projeto; esta pode ser, por exemplo, a
pasta Meus Documentos ou uma pasta qualquer em um pen drive.2 Clique ento Next
e, na tela seguinte, clique em Finish.

s
o

Pr

Pronto, seu projeto foi criado. Mas e agora? Agora abra o arquivo main.cpp, que
est na pasta sources, dando um clique duplo no nome do arquivo.

Ve
r

Finalmente, clique em build e ento em build and run. Parabns, voc acaba de
executar seu primeiro programa.

2.2.2

Depurao

Todo programa de tamanho considervel, e mesmo aqueles de tamanho diminuto, possuiro, ao menos em suas verses iniciais, erros. Por razes histricas, nos referimos
a estes erros por bugs. Uma das formas de achar os bugs do seu programa fazer
com que o computador execute seu programa passo a passo, isto , linha a linha, e
acompanhar esta execuo verificando se o programa faz o que voc espera.
Para experimentarmos a depurao, processo pelo qual removemos bugs, modifique a mensagem "Hello world!"do seu programa para "Ol <seu nome>!"e execute
novamente o programa (build and run). Se o programa executou normalmente, voc
2O

importante aqui salvar o arquivo em um lugar em que voc possa voltar mais tarde para reler.

22

CAPTULO 2. COMPILAO E EXECUO

est no caminho certo. Agora, copie a toda a linha contendo a mensagem e cole-a
vrias vezes, substituindo o nome em cada linha. Seu programa deve ficar assim:
#include <iostream>
2

using namespace std;

10

Joao!" << endl;


Jose!" << endl;
Joaquim!" << endl;
Joselino!" << endl;
Asdrubal!" << endl;

el
im

12

int main()
{
cout << "Hello
cout << "Hello
cout << "Hello
cout << "Hello
cout << "Hello
return 0;
}

in
a

s
o

Pr

Mais uma vez, compile e execute seu programa. Se a execuo foi bem sucedida,
voc est pronto para a depurao. Para depurar, clique ao lado direito do nmero 7
(stima linha do programa), at que uma bolinha vermelha aparea, como na figura a
seguir.

Ve
r

A bolinha vermelha , na verdade, um sinal de pare, e diz ao computador que deve


executar seu programa parar ali durante a execuo. Se voc for adiante e executar o
programa como fizemos at agora, ver que o pare no funcionou. Isto por que o
sinal ignorado a no ser que voc inicie a execuo em modo de depurao. Para
fazer isso, clique no menu Debug e ento em Start ou, alternativamente, pressione a
tecla F8. Observe que a execuo parou onde voc esperava. Agora, clique em Debug
e Next Line (ou simplesmente em F7) sucessivamente para ver o que acontece. Pronto,
voc j quase um profissional no Code::Blocks.

2.3

O Arquivo Executvel

Agora que voc j escreveu programas super interessantes, compilou e executou-os,


imagine como faria para enviar tais programas a um amigo que no tenha qualquer
interesse e/ou aptido em programao. A soluo simples: mandaremos a este amigo
o arquivo executvel do programa. Para faz-lo, abra a pasta na qual salvou seu projeto

2.4. EXERCCIOS

23

Code::Blocks. Nesta pasta voc encontrar um arquivo com extenso .exe; este o
arquivo executvel que deveria enviar para seu amigo.

2.4

Exerccios

2.4.1

in
a

Escreva o programa completo que calcula a rea de vrios retngulos do captulo anterior e execute-o.

2.4.2

Ve
r

s
o

Pr

el
im

Altere seu programa para usar, alm da funo de clculo de rea de um quadrado, as
funes definidas nos exerccios do captulo anterior.

CAPTULO 2. COMPILAO E EXECUO

Ve
r

s
o

Pr

el
im

in
a

24

el
im

in
a

Variveis, Entrada / Sada e


Operadores

Captulo 3

Declarao de Variveis

Ve
r

3.1

s
o

Pr

A todo momento precisamos representar informao do mundo a nossa volta em nossos


programas. Essas informaes, tais como nome, nmero de matrcula, nota final, so
armazenadas em entidades chamadas variveis.
Uma varivel nada mais do que um pedao de memria, no qual se pode ler ou
gravar alguma informao, com um nome bonitinho associado. Damos um nome a
certas partes da memria quando seu contedo ser acessado (lido e/ou escrito) com
grande frequncia durante a execuo do programa.
As alteraes em uma varivel resultam da interao com o usurio ,isto , quando
o usurio informa valores para as mesmas em uma operao de leitura, ou da avaliao
de expresses lgico-aritmticas.
Neste captulo veremos como criar nossas primeiras variveis e como alterar seus
valores por meio da leitura direta do teclado e da utilizao de operadores.

Na linguagem C, toda varivel deve ser declarada (isto , criada) logo depois da declarao da funo (aqueles blocos que vimos no Captulo 1). A declarao/criao de
uma varivel tem, pelo menos, duas partes:
Nome: atravs do qual ela pode ser acessada e atualizada no seu programa;
Tipo: para que o computador saiba como tratar a informao, ele precisa saber de que
tipo ela , ou seja, se um nmero, ou uma palavra, ou uma caractere, etc.
Existem algumas regrinhas bsicas para se nomear uma variveis:
o nome s pode conter os caracteres [a-z], [A-Z], [0-9] e o "_"; e,
o nome no pode comear com nmeros.
25

26

CAPTULO 3. VARIVEIS, ENTRADA / SADA E OPERADORES


Quanto aos tipos usaremos, por enquanto, os seguintes tipos bsicos:

int: representando um nmero inteiro;


float: representando um nmero real, com casas decimais separadas por ponto (e.g.,
3.1416); e
char: representando um caractere (letra, dgito, sinal de pontuao, etc).

int nota1, nota2;


float media;
char _caractere;

int 1nota, 2nota;


float #media;
char nome completo;

3.1.1

Atribuio e Uso

el
im

So exemplos de declaraes invlidas:

in
a

So exemplos de declaraes de variveis vlidas:

int inteiro1, inteiro2;


float real;
inteiro1 = 0;
inteiro2 = 10;
real = 10.0;

Ve
r

s
o

Pr

Como j dito, uma varivel um pedao da memria do computador no qual se pode


escrever e ler dados. Em vez de escrever, contudo, no mundo da computao
usamos a expresso atribuir um valor a uma varivel para significar a a mudana do
valor da varivel. Esta operao executada pelo operador de atribuio =. Por exemplo, o seguinte cdigo declara trs variveis numricas, duas inteiras e uma real, e, em
seguida, lhes atribui os valores 0, 10 e 10.0.

A memria do computador sempre tem algum dado, tenha ele sido colocado por
voc ou no, seja ele relevante ou no. Logo, para se usar o contedo de uma varivel,
necessrio ter certeza de que a mesma contm um valor que faa sentido. Isto ,
algo que tenha sido atribudo pelo seu programa quela varivel, via uma operao
de leitura, via uma computao qualquer, ou via uma atribuio como a do exemplo
anterior.
Denominamos a primeira atribuio de um valor a uma varivel de iniciao (ou
inicializao). E j que qualquer varivel s pode ser usada se tiver sido iniciada, o C
permite que as variveis sejam iniciadas j em sua declarao. Por exemplo, o cdigo
abaixo faz exatamente o que fazia o exemplo anterior, mas de forma mais compacta.

3.1. DECLARAO DE VARIVEIS

27

int inteiro1 = 0,
inteiro2 = 10;
float real = 10.0;

#include <iostream>

using namespace std;

float area_circulo(float raio)


{
float PI = 3.14,
area;
area = PI * raio * raio;
return area;
}

11

13

15

17

char proxima_letra(char c1)


{
char c2;
c2 = c1 + 1;
return c2;
}

19

21

23

proximo de " << _c << " eh " << proxima_letra(_c) << endl;

Ve
r

25

int main() {
int r1;
float r2;
char _c;
_c = a;
cout << "O
r1 = 2;
r2 = 9.7;
cout << "r
cout << "r
r1 = 12;
r2 = 0.4;
cout << "r
cout << "r
return 0;
}

s
o

Pr

el
im

in
a

Observe que se pode iniciar vrias variveis do mesmo tipo, declaradas na mesma
linha, com valores distintos. Neste caso, note quebra de linha entre as declaraes de
inteiro1 e inteiro2; ela somente esttica, mas ajuda a separar a declarao e
iniciao das vrias variveis.
Agora que voc viu como declarar e iniciar uma varivel vem a parte fcil, us-la.
Veja como no seguinte exemplo.

27

29

31

33

35

= " << r1 << ", area = " << area_circulo(r1) << endl;
= " << r2 << ", area = " << area_circulo(r2) << endl;

= " << r1 << ", area = " << area_circulo(r1) << endl;
= " << r2 << ", area = " << area_circulo(r2) << endl;

simples assim: para se usar uma varivel, basta colocar seu nome na expresso a ser
computada.

28

CAPTULO 3. VARIVEIS, ENTRADA / SADA E OPERADORES

3.1.2

Parmetros so Variveis

11

int main()
{
float area;
area = area_retangulo(2.0, 2.0);
cout << area;
return 0;

13

in
a

float area_retangulo(float altura, float base)


{
//Calcula e retorna a area do retangulo.
return altura * base;
}

el
im

Nos exemplos de programas dos captulos anteriores, voc viu como o contedo de uma
parmetro definido e usado. Por exemplo, os dois parmetros da funo area_retangulo,
reproduzida abaixo, so declarados dizendo-se de que tipo eles so e quais so seus nomes. Em seguida, no corpo da funo, os parmetros so usados no clculo da rea
simplesmente multiplicando-se o nome de um pelo nome do outro; os valores dos
parmetros so aqueles passados na chamada da funo.

Entrada / Sada

s
o

3.2

Pr

Esta semelhana com a declarao e uso de variveis no coincidental: parmetros no so mais do que variveis declaradas e iniciadas de uma forma especial.

Duas das tarefas mais comuns em programao so a leitura de valores informados


pelo usurio e a impresso na tela de resultados calculados pelos nossos programas. A
seguir veremos os comandos que nos permitem executar tais tarefas.

Impresso

Ve
r

3.2.1

O comando de impresso em tela que usaremos ser o cout, do qual j vimos diversos
exemplos. Seu uso bem simples e intuitivo: textos devem aparecer entre aspas duplas,
caracteres entre aspas simples e nmeros, variveis e chamadas de funes aparecem
diretamente. Todas as informaes impressas pelo mesmo comando cout devem ser
conectadas pelos caracteres <<. A seguir, podemos ver alguns exemplos:

...
char letra = a;
int num = 2;
cout << "letra = " << letra << endl << "num = " << num << endl;

3.2. ENTRADA / SADA

29

Como pode ser observado no exemplo anterior, a palavra endl aparece algumas
vezes. Sua funo a de pular uma linha na tela (endl a contrao end line).
Sendo assim, o comando anterior teria a seguinte sada:
letra = a
num = 2

3.2.2

Leitura

cout << "Informe a letra inicial de seu nome e sua idade: ";
// a seguir eh feita a leitura
cin >> letra >> idade;
cout << "A letra eh " << letra;
cout << " e sua idade eh " << idade << endl;

Pr

char letra;
int idade;

el
im

in
a

De forma semelhante ao cout, h tambm um comando para leitura denominado cin.


Este comando permite ler valores digitados pelo usurio atualizando a(s) varivel(is)
passada(s) para o cin por meio do conector >>.
A seguir temos um exemplo de entrada de dados:

Agora que voc consegue ler do teclado e escrever para a tela, veja como fcil fazer um programa que calcule a rea de retngulo cujos lados so digitados pelo
usurio.

float area_retangulo(float altura, float base)


{
//Calcula e retorna a area do retangulo.
return altura * base;
}

s
o

int main()
{
float area,
b,
a;
cout << "Qual a altura do retangulo?" << endl;
cin >> a;

Ve
r

10

12

14

cout << "Qual a base do retangulo?" << endl;


cin >> b;

16

area = area_retangulo(b, a);


cout << area;

18

20

return 0;
22

30

CAPTULO 3. VARIVEIS, ENTRADA / SADA E OPERADORES

3.3

Operadores

in
a

Os operadores so os mecanismos por meio dos quais os computadores realizam os


clculos aritmticos e lgicos, atualizando valores das variveis e executando as tarefas
a que se destinam.
Os operadores matemticos so os mais utilizados na maioria dos programas que
sero desenvolvidos. Os principais operadores aritmticos so: +, , , / e o %, indicando, respectivamente, as operaes de soma, subtrao, multiplicao, diviso e
resto da diviso.
Considere o exemplo a seguir:
#include<iostream>
2

using namespace std;


4

10

12

el
im

int main()
{
int n, dobro_de_n;
cout << "Entre um inteiro: ";
cin >> n;
dobro_de_n = 2*n;
cout << "O dobro de " << n << " eh " << dobro_de_n << endl;
return 0;
}

3.3.1

Pr

Construes Especiais

int
...
a =
b =
a =

a, b;

a + b;
b * 2;
a / 7;

Ve
r

s
o

Com a finalidade de agilizar o desenvolvimento e simplificar algumas operaes aritmticas mais comuns, a linguagem C permite algumas construes especiais envolvendo operadores. Considere o seguinte trecho de cdigo::

Observe que nas trs atribuies (indicadas pelo sinal de igualdade), as variveis
que so atualizadas tambm aparecem como primeiro elemento da operao aritmtica
esquerda. Nestas situaes, podemos reescrever as atribuies assim:

int a, b;
...
a += b;
b *= 2;
a /= 7;

3.4. EXERCCIOS

31

As operaes de incremento (aumento de uma unidade) e o decremento (diminuio de uma unidade) de uma varivel so muito comuns em programao. Sendo assim,
a linguagem C define dois operadores para as mesmas: ++ e --, respectivamente. Veja
o exemplo.

0;
1;
"a = " << a << endl;
"a = " << a << endl;

int a =
a = a +
cout <<
a += 1;
cout <<
a++;
cout <<
a--;
cout <<

"a = " << a << endl;

in
a

"a = " << a << endl;

3.3.2

Precedncia de Operadores

el
im

O trecho acima deve imprimir os valores de a, ou seja, 1, 2, 3 e 2.

3.4

Exerccios

3.4.1

Pr

Em uma expresso onde aparecem diversos operadores, a seguinte ordem de precedncia deve ser obedecida: primeiramente os operadores de incremento/decremento; em
seguida os operadores %, e /; e por ltimo os operadores + e

int a, b = 0, c
a = ++b + ++c;
cout << a << ",
a = b++ + c++;
cout << a << ",
a = ++b + c++;
cout << a << ",
a = b-- + --c;
cout << a << ",

= 0;

" << b << ", " << c << endl;


" << b << ", " << c << endl;

Ve
r

s
o

Diga o que ser escrito na tela durante a execuo do seguinte trecho de cdigo:

" << b << ", " << c << endl;


" << b << ", " << c << endl;

3.4.2
Escreva uma funo em C que, dado uma temperatura em graus Clsius (do tipo float),
retorne a temperatura equivalente em Farenheit. Escreva tambm a funo main que
leia a temperatura em Clsius do teclado, invoque a funo de converso, e imprima o
resultado.
Dado: F = 9C
5 + 32

32

CAPTULO 3. VARIVEIS, ENTRADA / SADA E OPERADORES

3.4.3

s
o

Pr

el
im

in
a

Escreva uma

Ve
r

o qu?

Captulo 4

Escopo de Variveis

el
im

4.1

in
a

Variveis (II)

No captulo anterior estudamos como declarar e utilizar variveis em nossos programas. Fizemos, por exemplo, um programa como o seguinte, que pede ao usurio que
entre com as medidas da base e altura de um retngulo e ento imprime na tela do
computador a rea deste retngulo.

11

13

Pr

float area_retangulo(float altura, float base)


{
//Calcula e retorna a area do retangulo.
return altura * base;
}

int main()
{
float area,
b,
a;
cout << "Qual a altura do retangulo?" << endl;
cin >> a;

s
o

cout << "Qual a base do retangulo?" << endl;


cin >> b;

Ve
r

15

17

area = area_retangulo(b, a);


cout << "A area do retangulo de base " << b << " e altura "
<< a << " eh " << area << endl;

19

21

return 0;

23

O que aconteceria se em vez de chamarmos as variveis na funo main de a e b


as tivssemos chamado de base e altura? Veja que estes so exatamente os nomes
dos parmetros da funo area_retangulo. Melhor ainda, e se a funo tivesse
alterado os valores dos parmetros?
33

34

CAPTULO 4. VARIVEIS (II)


Para descobrir as respostas a estas perguntas, faa o seguinte experimento:
digite o programa tal qual acima em seu computador e execute-o.

int main()
{
float area,
base,
altura;
cout << "Qual a altura do retangulo?" << endl;
cin >> altura;

in
a

cout << "Qual a base do retangulo?" << endl;


cin >> base;

11

15

return 0;
}

e execute-o.

el
im

area = area_retangulo(base, altura);


cout << "A area do retangulo de base " << base << " e altura "
<< altura << " eh " << area << endl;

13

17

modifique somente a funo main do seu programa para que fique assim

Pr

Note quais as diferenas na execuo.

Finalmente, altere a funo area_retangulo para que fique assim


1

s
o

float area_retangulo(float altura, float base)


{
//Calcula e retorna a area do retangulo.
altura *= base;
return altura;
}

Ve
r

e execute novamente o programa.

Note se houve alguma alterao do valor da varivel altura.

Como se pde notar, estas mudanas no afetaram a execuo do programa. Isto


acontece por qu as variveis tem escopos bem definidos em C. A varivel altura da
funo main no a mesma varivel/parmetro altura da funo area_retangulo;
cada uma s existe dentro do corpo da funo em que foi declarada. Quando a funo
area_retangulo invocada passando-se como parmetro a varivel altura da
funo main, seu valor desta varivel copiado para o parmetro altura da funo
invocada. Sendo assim, quaisquer alteraes ao valor do parmetro dentro da funo
afetam apenas a cpia, no o valor da varivel de onde foi copiado.
A variveis definidas at agora possuem o que chamamos escopo local. Isto ,
elas so visiveis somente localmente funo em que foram definidas. Outro tipo de

4.1. ESCOPO DE VARIVEIS

35

float PI = 3.1416;

float resposta = 0;

float area_retangulo(float altura, float base)


{
//Calcula e retorna a area do retangulo.
resposta = base * altura;
return resposta;
}

11

17

19

21

23

int main()
{
float area,
base,
altura,
raio;

25

el
im

15

float area_circulo(float raio)


{
//Calcula e retorna a area do circulo.
resposta = PI * raio * raio;
return resposta;
}

Pr

13

in
a

escopo presente possvel em C o escopo global. Uma varivel tem escopo global
se for definida fora de qualquer funo. Uma variel com escopo global poder ser
acessada de (quase) qualquer parte do seu cdigo. Para um exemplo de varivel de
escopo global, veja o cdigo a seguir.

cout << "Qual a altura do retangulo?" << endl;


cin >> altura;

27

cout << "Qual a base do retangulo?" << endl;


cin >> base;

s
o

29

31

area = area_retangulo(base, altura);


cout << "A area do retangulo de base " << base << " e altura "
<< altura << " eh " << area << endl;

33

35

Ve
r

cout << "Resposta da chamada de funcao " << resposta << endl;
37

cout << "Qual o raio do circulo?" << endl;


cin >> raio;

39

area = area_circlo(raio);
cout << "A area do circulo de raio " << raio
<< " e PI arredondado para " << PI <<" eh " << area << endl;

41

43

cout << "Resposta da chamada de funcao " << resposta << endl;
return 0;

45

47

Observe a varivel PI. Esta varivel foi declarada fora de qualquer funo e, sendo
assim, visvel em qualque delas, como demonstrado pelo seu uso na funo main e

36

CAPTULO 4. VARIVEIS (II)

Faixas de Valores

in
a

4.2

area_circulo.
Observe tambm que a mesma varivel aread foi utilizada mais de uma vez. Isto
comum em programao pois, com a quantidade limitada de recursos, pode no fazer
sentido criar uma varivel para cada novo uso. Observe que a varivel resposta
foi alterada dentro das duas funes de clculo de rea e que estas mudanas foram
visveis funo main.
Verifique de forma experimental (copiando e executando )que o programa acima
funciona como esperado.

Colocar

4.3

Exerccios

4.4

Laboratrio

Ve
r

Colocar

s
o

Pr

el
im

Voc j aprendeu que variveis so espaos (clulas) da memria do computador para


o qual damos nomes. Estes espaos, por serem limitados, podem armazenar uma quantidade limitada de valores. Pense, por exemplo, em quais os nmeros, positivos e
negativos, se pode representar com trs dgitos: 99, 98, . . . , 0, 1, 2, . . . , 998, 999.
Tentemos descobrir qual a faixa de valores que cabem em uma varivel int.
Escreva um programa que declare uma varivel do tipo int, inicie esta varivel com
um nmero (digamos, 10000), e imprima este nmero na tela do computador. Veja que
o nmero impresso na tela como deveria: 10000.
Agora altere seu programa para que imprima 20000 e execute-o. Refaa este passo
(adicionando 10000 a cada passo) at que a impresso fuja do que voc esperava. Neste
ponto, trabalhe com incrementos menores at determinar qual o maior nmero que
impresso como esperado. Fepita o processo para identificar qual o menor nmero que
cabe em um int. Quais so estes valores?
Finalmente, tente identificar a faixa de valores que cabem em um float. Dica: os
incrementos iniciais deveriam ser na faixa de milhes e no dezenas de milhares.

Captulo 5

in
a

Seleo Simples

float delta(float a, float b, float c)


{
return b*b - 4*a*c;
}

s
o

Pr

el
im

Nossos programas at agora foram extremamente simples, contendo apenas algumas


pequenas funes alm da main. Isto acontece em parte por qu nossos programas so
apenas sequncias diretas de comandos, sem execuo condicional. Isto , at agora
no aprendemos a dizer para o computador Se for assim, ento faa assado! Seno,
faa cozido!. Esta deficincia ser corrigida neste captulo.
Como exemplo de programao mais interessante, implementemos uma funo que
calcule as raizes de uma equao de segundo grau. Para faz-lo, relembremos a frmula
de Bhaskara:

x = b
, sendo = b2 4ac.
2a
Comecemos ento definindo uma funo para o clculo do .

Ve
r

Para testar o clculo do precisamos da funo main, juntamente com o restante


do esqueleto de programa aprendido at agora.
#include <iostream>

using namespace std;

10

12

14

16

float delta(float a, float b, float c)


{
return b*b - 4*a*c;
}
int main()
{
float a, b, c;
cout << "Equacao do segundo grau: axx + bx + c = 0" << endl;
cout << "Digite o valor de a: ";
cin >> a;

37

38
cout << "Digite o valor de b: ";
cin >> b;
cout << "Digite o valor de c: ";
cin >> c;

18

20

cout << "Delta: " << delta(a,b,c) << endl;


return 0;

22

24

CAPTULO 5. SELEO SIMPLES

in
a

Agora, para clculo das razes! Comecemos por alterar o programa para imprimir
o nmero de razes da equao. O clculo do nmero de razes ser feito na funo
raizes. A equao tem ou 0 razes reais (se o < 0), ou duas razes iguais (se
= 0), ou duas raizes distintas (se > 0).
#include <iostream>
using namespace std;
4

10

12

float delta(float a, float b, float c)


{
return b*b - 4*a*c;
}
int raizes(float a, float b, float c)
{
float d = delta(a,b,c);
int qtd;

Pr

14

se d menor que 0
{
qtd = 0;
}
senao e se d igual a 0
{
qtd = 1;
}
senao
{
qtd = 2;
}

16

22

Ve
r

24

s
o

18

20

el
im

26

return qtd;

28

30

32

34

36

38

40

int main()
{
float a, b, c;
cout << "Equacao do segundo grau: axx + bx + c = 0" << endl;
cout << "Digite o valor de a: ";
cin >> a;
cout << "Digite o valor de b: ";
cin >> b;
cout << "Digite o valor de c: ";

5.1. OPERADORES RELACIONAIS

39

42

cin >> c;

44

cout << "Delta: " << delta(a,b,c) << endl;


return 0;

46

5.1

in
a

Acontece que o computador no entende nem o se e nem o menor que. Mas


ento como faremos as verificaes necessrias para determinar a quantidade raizes?
A resposta tem duas partes.

Operadores Relacionais

s
o

Pr

el
im

As linguagens de programao provem sempre formas de se comparar dados. Em


C(++) os operadores relacionais, usados para comparar, so os seguintes:
== igual a
!= diferente de
> maior que
< menor que
>= maior ou igual a
<= menor ou igual a
Observe que o primeiro operador tem dois sinais de igual. Isto para diferenciar
este operador do operador de atribuio =, visto anteriormente. O segundo operador
tem um sinal de exclamao (!) que, em linguagem C, significa emph. Logo, !=
significa no igual ou, simplesmente, diferente. Os demais operadores devem ter significados bvios.
Usando estes operadores, podemos re-escrever a funo raizes do nosso programa
assim:
int raizes(float a, float b, float c)
{
float d = delta(a,b,c);
int qtd;
se d < 0
{
qtd = 0;
}
senao e se d == 0
{
qtd = 1;
}
senao
{
qtd = 2;
}

Ve
r

10

12

14

16

18

return qtd;
20

40

CAPTULO 5. SELEO SIMPLES


Melhorou, mas ainda no pode ser executado pelo computador. Vamos ento ao se.

5.2

if-else

Em C, testes simples (tudo o que voc realmente precisa) podem ser feitos com a estrutura if, que tem uma das seguintes sintaxes:

if( expresso lgica ) bloco de comandos 1

in
a

if( expresso lgica ) bloco de comandos 1 else bloco de comandos 2

#include <iostream>

Pr

el
im

Uma expresso lgica uma expresso cuja avaliao resulte em verdadeiro ou


falso como, por exemplo, as expresses que usam os operadores relacionais apenas
apresentados.
Um bloco de comandos ou uma instruo ou um conjunto de instrues dentro de
{ }.
Quando a expresso lgica avaliada, se seu resultado for verdadeiro, ento o bloco
de comandos 1 ser executado. Se o resultado for falso, o bloco de comandos 1 no
ser executado e o bloco 2, se existir, ser executado em seu lugar.
Observe que o segundo bloco pode ser, por sua vez, outro if. Por exemplo, nosso
programa pode ser reescrito assim:

using namespace std;


4

10

12

int raizes(float a, float b, float c)


{
float d = delta(a,b,c);
int qtd;
if(d < 0)
{
qtd =
}
else if(d
{
qtd =
}
else
{
qtd =
}

Ve
r

14

float delta(float a, float b, float c)


{
return b*b - 4*a*c;
}

s
o

16

18

20

22

24

26

0;
== 0)
1;

2;

return qtd;

28

}
30

int main()

5.2. IF-ELSE
32

41

{
float a, b, c;

34

cout << "Equacao do segundo grau: axx + bx + c = 0" << endl;


cout << "Digite o valor de a: ";
cin >> a;
cout << "Digite o valor de b: ";
cin >> b;
cout << "Digite o valor de c: ";
cin >> c;

36

38

40

46

in
a

cout << "Delta: " << delta(a,b,c) << endl;


cout << "A equacao tem " << raizes(a,b,c) << " raizes.";
return 0;

44

42

el
im

O ltimo passo no desenvolvimento do nosso programa imprimir na tela as raizes


da equao, o que faremos em uma nova funo: imprime_raizes.
#include <iostream>
#include <math.h>

using namespace std;


5

11

13

Pr

float delta(float a, float b, float c)


{
return pow(b,2) - 4*a*c;
}
int raizes(float a, float b, float c)
{
float d = delta(a,b,c);
int qtd;

s
o

15

if(d < 0)
{
qtd =
}
else if(d
{
qtd =
}
else
{
qtd =
}

17

0;

== 0)

Ve
r

19

21

23

25

27

1;

2;

return qtd;

29

}
31

33

35

int imprime_raizes(float a, float b, float c)


{
float d = delta(a,b,c);
int qtd;

42

CAPTULO 5. SELEO SIMPLES


if(d < 0)
{
cout << "A equacao tem zero raizes reais." << endl;
}
else if(d == 0)
{
cout << "A equacao tem duas raizes iguais a " << -b;
}
else
{
cout << "A equacao tem duas raizes iguais distintas " << endl
<<
"x = " << (-b + sqrt(d))/(2*a) << endl <<
"x = " << (-b - sqrt(d))/(2*a) << endl;
}

37

39

41

43

45

49

in
a

47

51

return qtd;
}

55

57

int main()
{
float a, b, c;

59

cout << "Equacao do segundo grau: axx + bx + c = 0" << endl;


cout << "Digite o valor de a: ";
cin >> a;
cout << "Digite o valor de b: ";
cin >> b;
cout << "Digite o valor de c: ";
cin >> c;

61

Pr

63

65

67

cout << "Delta: " << delta(a,b,c) << endl;


cout << "A equacao tem " << raizes(a,b,c) << " raizes." << endl;
imprime_raizes(a,b,c);
return 0;

Ve
r

73

s
o

69

71

el
im

53

Note que a nova funo usa a funo sqrt para calcular a raz de . Esta funo
uma das muitas disponveis na linguagem C. Para usar esta funo preciso dizer ao
computador sua inteno. No nosso programa, isto feito na linha 2, isto ,
#include <math.h>
em que dizemos ao computador que queremos usar as funes da biblioteca matemtica da linguagem. Aproveitando a incluso desta biblioteca tambm alteramos a linha
8 para usar a funo pow para o clculo do b2 . Vrias outras funes esto disponveis e podem ser consultadas em http://www.cplusplus.com/reference/
clibrary/cmath/.

A seo seguinte deveria


virar um captulo e a parte
if else vistos at agora se
juntar ao prximo captulo

5.3. FUNES E PROCEDIMENTOS

5.3

43

Funes e Procedimentos

el
im

tipo_resultado o tipo do valor que a funo est calculando.

in
a

A funo imprime_raizes, definida na seo anterior, tem por objetivo imprimir


na tela as raizes da equao de segundo grau, se existirem. Esta funo no tem, pela
nossa definio, o objetivo de calcular a quantidade de razes (que era o objetivo da
funo raizes). Em imprime_raizes no faz sentido, ento, a funo ter um
resultado. Funes sem resultado so denominadas procedimentos e, em C, so declaradas como qualquer outra funo, apenas com uma particularidade: o tipo do resultado
void. Antes de vermos alguns exemplos, precisamos ver a sintaxe de funes em geral, que estivemos usando nas sees e captulos anteriores mas no havamos definido
formalmente.
tipo_resultado
identificador_funo(tipo_parmetro 1 identificador_do_parmetro 1, . . . ) bloco_de_comandos

identificador_funo o nome usado para invocar a funo.


tipo_parmetro 1 tipo do primeiro parmetro da funo.

identificador_parmetro 1 identificador do primeiro parmetro da funo.


. . . tipo e identificador dos demais parmetros.

Pr

bloco_de_comandos instrues que compem o corpo da funo.

int ler_idade()
{
int id;
cout << "Qual sua idade? " <<endl;
cin >> id;
return id;
}

Ve
r

s
o

Como mencionado, procedimentos so funes sem um resultado e, em C, so


declarados como tendo resultado do tipo void. Em funes com normais, o resultado
dado pela instruo return; em procedimentos, que no tem resultado, return
no utilizado. Alm disso, procedimentos no podem ser usados em atribuies.
Alm de funes sem resultado, C permite a definio de funes sem parmetros.
Um exemplo deste tipo de funo seria uma que lesse algum dado do usurio.

Finalmente, importante relembrar que as funes precisam ser definidas antes de


serem usadas. Sendo assim, voc deve incluir a definio das funes antes da definio
da funo main em seu cdigo. 1 . Ainda, relembrando a primeira aula, sobre a funo
main:
1 possvel escrever o cdigo de suas funes aps a funo main ou mesmo em outros arquivos. Fazer
isso, contudo, requer conhecer um pouco mais do funcionamento dos compiladores do que o escopo deste
livro.

44

CAPTULO 5. SELEO SIMPLES


1. A funo main tem um resultado do tipo inteiro e seu resultado sempre 0
(return 0; )2 .
2. Funo main como um highlander: s pode haver uma! Isto , cada programa
s pode conter a definio de uma funo com este nome.

O Tipo Primitivo bool

in
a

5.4

3. Finalmente, todas as funes devem ser declaradas antes da serem usadas, pois
quando o computador tenta execut-la, j deve saber de usa existncia.

0 corresponde a falso.

el
im

Como vimos neste captulo, o if avalia uma expresso lgica para decidir-se por executar ou no um bloco de comandos. Expresses lgicas, como tambm j tido, so
aquelas que so avaliadas em verdadeiro ou falso. Na linguagem C(++), quaisquer
nmeros inteiros podem tambm ser avaliados como verdadeiro ou falso, seguindo a
seguinte regra:

qualquer outro nmero corresponde a verdadeiro.

Exerccios

s
o

5.5

Pr

Em C++, tambm possvel utilizar os valores true e false, que correspondem,


respectivamente, a 1 e 0. Estes dois valores compem o conjuntos dos booleanos, ou
melhor, o tipo primitivo bool. Isto , true e false esto para bool assim como -100,
10, 12, . . . esto para int.

5.5.1

Muitas pessoas acreditam que um ano bissexto se for mltiplo de 4. Contudo, a regra
um pouco mais complexa do que esta:

Ve
r

Um ano bissexto se for mltiplo de 4 mas no de 100, ou


se for mltiplo de 100, ento for mltiplo de 400.

Escreva um programa que leia um ano, chame uma funo para calcular se o ano
bissexto e imprima sim ou no de acordo.
#include <iostream>

using namespace std;


4

bool bissexto(int ano)


{
if(ano % 4 == 0)
{
2 Pelo

menos nos programas simples que faremos.

5.5. EXERCCIOS

45

14

16

18

20

22

26

28

el
im

}
else
{
return false;
}

24

}
30

32

in
a

12

if(ano % 100 == 0)
{
if (ano % 400 == 0)
{
return true;
}
else
{
return false;
}
}
else
{
return true;
}

10

int main()
{
int ano;

34

cout << "Digite o ano que deseja verificar se e bissexto: ";


cin >> ano;

38

cout << "O ano " << ano;

40

if(bissexto(ano))
cout << " e bissexto" << endl;
else
cout << " nao e bissexto" << endl;

s
o

42

Pr

36

44

return 0;
}

Ve
r

46

5.5.2

Este exerccio dividido em vrias partes:


1. Escreva uma funo que receba 3 nmeros reais e retorne a mdia dos trs nmeros.
2. Escreva uma funo que receba 3 nmeros reais e retorne o menor dentre eles.
3. Escreva uma funo que receba 3 nmeros reais e retorne o maior dentre eles.
4. Escreva a funo main de forma a ler trs nmeros reais, calcular a mdia dos
mesmos e, caso a mdia seja menor que 0, imprima o menor dentre os trs, ou,
caso a mdia seja maior ou igual a zero, imprima o maior dentre os trs. Sua

46

CAPTULO 5. SELEO SIMPLES


funo main deve usar as funes escritas nos itens anteriores para clculo da
mdia e impresso dos nmeros.

5.5.3
Escreva um programa que contenha

1. Uma funo celsius_fahrenheit que receba uma temperatura em graus


celsius e converta para fahrenheit.

in
a

2. Uma funo fahrenheit_celsius que receba uma temperatura em fahrenheit e converta para graus celsius.

el
im

3. Funo main que leia uma temperatura do teclado, pergunte ao usurio se a


temperatura em celsius ou fahrenheit, e imprima a temperatura convertida para
a outra medida.

5.5.4

Faa uma funo denominada ehPar que receba um nmero inteiro como argumento
e retorne verdadeiro se este nmero for par ou falso, caso contrrio. A funo main
deve ser o nmero e imprimir o valor retornado pela funo auxiliar.

Pr

5.5.5

Elabore um programa com as seguinte descrio:

s
o

Uma funo que retorna verdadeiro se trs nmeros reais recebidos como argumentos formam um tringulo ou falso, caso contrrio.
Uma funo que recebe trs nmeros reais como argumento representado os lados de um tringulo e retorna 0 caso os nmeros formem um tringulo equiltero,
1 caso formem um tringulo issceles, ou 2 caso sejam os lados de um tringulo
escaleno.

Ve
r

Por fim, a funo main deve ler os 3 nmeros que representam os lados, e caso
formem um tringulo, imprimir se o tringulo formado equilatero, issceles ou
escaleno.

5.6

Laboratrio

Refaa no computador os exerccios do captulo anterior.

in
a

Seleo Simples (II)

Captulo 6

6.1

el
im

Uma vez apresentado a estrutura condicional if-else, veremos agora como realizar testes mais complexos utilizando operadores lgicos.

if-else e Operadores Lgicos

10

Ve
r

12

...
/*
* esta funcao retorna verdadeiro se a pessoa de sexo
* (1=Masculino, 2=Feminino) e idade passados como argumentos
* for maior que idade ou falso, caso contrario
*/
bool ehMaior(int sexo, int idade)
{
if(sexo == 1)
// masculino
{
if(idade == 18)
{
return true;
}
else
{
return false;
}
else if(sexo == 2) // feminino
{
if(idade == 21)
{
return true;
else
{
return false;
}
}
else
// sexo informado errado

s
o

Pr

At o ponto atual fizemos apenas testes simples dentro da condio dos nossos if, por
exemplo:

14

16

18

20

22

24

26

28

47

48

CAPTULO 6. SELEO SIMPLES (II)

30

32

return false;
}

in
a

Observe que na funo ehMaior temos if aninhados, ou seja, if dentro de if.


Isto porque um pessoa deve ser do sexo masculino E possuir idade maior ou igual a 18
anos para ser considerada maior de idade. OU ainda, ela pode ser do sexo feminino E
possuir idade igual ou maior a 21 anos.
Quando esta situao ocorre, as condies podem ser combinadas em um nico if
utilizando-se operadores lgicos. Os operadores lgicos que usaremos so o E, o OU
e a NO (negao).
Na linguagem C, eles so representados pelos smbolos a seguir:

el
im

Tabela 6.1: Operadores lgicos e seus smbolos na linguagem C.


Operador Lgico Smbolo
E
&&
OU
||
NO
!

Ve
r

s
o

Pr

Os operadores lgicos podem ser resumidos nas tabelas a seguir:


Tabela 6.2: NO lgico.
A !A
V F
F V

Tabela 6.3: E lgico.


A B A && B
V V
V
V F
F
F V
F
F F
F

Voltando ao nosso exemplo, a funo anterior pode ser reescrita da seguinte forma:
2

...
/*
* esta funcao retorna verdadeiro se a pessoa de sexo
* (1=Masculino, 2=Feminino) e idade passados como argumentos

6.2. PRIORIDADE DOS OPERADORES

49

10

12

14

16

in
a

* for maior de idade ou falso, caso contrario


*/
bool ehMaior(int sexo, int idade)
{
if((sexo == 1 && idade >=18) || (sexo == 2 && !(idade < 21))
{
return true;
}
else
// sexo errado ou idade errada
{
return false;
}
}

el
im

Tabela 6.4: OU lgico.


A B A || B
V V
V
V F
V
F V
V
F F
F

Pr

Perceba que em apenas um if colocamos a condio completa, ou seja, se sexo


igual a 1 E idade maior ou igual a 18 OU sexo igual a 2 e idade NO menor do que 21
ento maior de idade.

Prioridade dos Operadores

s
o

6.2

Ve
r

Quando mais de um operador lgico aparece em uma expresso, a precedncia pode ser
expressa da seguinte maneira: primeiro o NO, depois o E, por ltimo o OU. Quando
houver parnteses, primeiro avalia-se o que estiver dentro dos mesmos.
Em diversas expresses e testes, diversos operadores dos vrios tipos podem aparecer. A avaliao dessa expresso deve obedecer seguinte ordem de prioridade em
relao aos operadores:
1. Parnteses, incremento e decremento (++, )
2. Negao (!)

3. Multiplicao, diviso e mdulo (o que aparecer primeiro);


4. Soma e subtrao;
5. Operadores relacionais (<, <=, >, >=)
6. Operadores relacionais (==, !=)

50

CAPTULO 6. SELEO SIMPLES (II)


7. OU-Exclusivo ()
8. E (&&)
9. OU (||)

10. Atribuio (=, +=, -=, *=, /=, %=)

6.3

Exerccios

6.3.1

el
im

in
a

Embora os operadores lgicos faam sentido somente para operandos bool, importante relembrar que, para o computador, verdadeiro e falso so apenas formas de
interpretar nmeros na memria. Na linguagem C, qualquer nmero diferente de 0
tratado como true e 0 tratado como false. Sendo assim, possvel aplicar operadores lgicos tambm nmeros. Contudo, sempre que requisitado a representar o
valor true como nmero, o computador usar o valor 1, o que faz com que nem todas
as computaes tenham resultados bvios. Por exemplo, o cdigo cout<<(2||0); imprime, na tela, o valor 1. Isto por qu 2 tratado como verdadeiro e 0 como falso, e o
resultado de verdadeiro OU falso verdadeiro, que ento convertido para 1.
Da mesma forma, !!3 1, pois !3 falso e sua negao verdadeiro, que 1.

Pr

Avalie o resultado de cada expresso a seguir (verdadeiro ou falso):


2 < 5 && 15/3 == 5

pow(3,2)- 5 > 0 && 5/2 == 3 - 4

s
o

F || 20 18/3 != 21/3 / 2
!V || 3*3/3 < 15 - 35%7

!(5 != 10/2)|| V && 2 - 5 > 5 - 2 || V


pow(2,4)!= 4 + 2 || 2 + 3 * 5/3%5 < 0

Ve
r

!1+1
!2+1
!0+1

6.3.2

Faa um programa que:


1. contenha uma funo que retorna verdadeiro se um nmero for divisvel por 3
ou 5, mas no simultaneamente pelos dois, e;
2. na funo principal sejam lidos dois nmeros inteiros, que devero ser passados
para a funo criada, tendo seu resultado impresso.

6.3. EXERCCIOS

51

6.3.3
Faa uma funo que receba 3 nmeros reais (float) correspondentes aos lados de um
tringulo e retorne true caso esse tringulo seja retngulo ou false caso no o seja.
A funo principal deve ler os valores dos lados do tringulo e imprimir se ou no
retngulo.

Ve
r

s
o

Pr

el
im

in
a

Exerccio que deixe bvio a


necessidade do switch-case

CAPTULO 6. SELEO SIMPLES (II)

Ve
r

s
o

Pr

el
im

in
a

52

Captulo 7

in
a

Switch

7.1

el
im

Em diversas situaes em programao, necessrio testar se uma determinada varivel tem um dentre diversos possveis valores. Nesta situao, embora seja possvel usar
vrios if, outra soluo nos dada em linguagem C: o uso de switch.

switch-case-default

#include <iostream>

Pr

Considere o problema de transformar o ms de uma representao numrica de uma


data em sua representao textual. Isto , transformar, por exemplo, 25/12/2012 em
25 de Dezembro de 2012. Uma possvel soluo para este problema, em C(++), o
seguinte.

s
o

using namespace std;


4

cout << "Dia? " <<endl;


cin >> dia;

Ve
r

int main()
{
int dia, mes, ano;

10

12

cout << "Mes? " <<endl;


cin >> mes;

14

16

cout << "Ano? " <<endl;


cin >> ano;

18

cout << dia << " de ";

20

if(mes == 1)
cout << "Janeiro";
else if(mes == 2)
cout << "Fevereiro";
else if(mes == 3)
cout << "Marco";

22

24

53

30

32

34

36

38

40

42

44

46

in
a

28

el
im

else if(mes == 4)
cout << "Abril";
else if(mes == 5)
cout << "Maio";
else if(mes == 6)
cout << "Junho";
else if(mes == 7)
cout << "Julho";
else if(mes == 8)
cout << "Agosto";
else if(mes == 9)
cout << "Setembro";
else if(mes == 10)
cout << "Outubro";
else if(mes == 11)
cout << "Novembro";
else if(mes == 12)
cout << "Dezembro";
else
cout << "Hein?-zembro";
cout << " de " << ano << endl;
return 0;

26

48

CAPTULO 7. SWITCH

54

s
o

Pr

Em vez de usar vrios if e else-if, uma soluo melhor seria usar switch, criado
exatamente para tratar estas situaes. A sintaxe do uso do switch a seguinte.
switch (identificador)
{
case valor1: bloco_comandos1
case valor2: bloco_comandos2
...
case valorN: bloco_comandosN
default: bloco_comandos_default
}

Ve
r

identificador: Identificador da varivel a ser testada


valor1: primeiro caso a ser testado
bloco_comandos1: bloco de comandos a ser executado caso a varivel tenha
valor igual a valor1
valor2: segundo caso a ser testado
bloco_comandos2: bloco de comandos a ser executado caso a varivel tenha
valor igual a valor2
. . . outros casos a serem testados
valor n: ltimo caso a ser testado

7.1. SWITCH-CASE-DEFAULT

55

bloco_comandosN: bloco de comandos a ser executado caso a varivel tenha


valor igual a valorN
default: um valor especial, que sempre casa com o valor da varivel
bloco_comandos_default: bloco de comandos a ser executado caso a varivel
case com default.
Usando switch-case-default, o exemplo acima pode ser reescrito assim.

#include <iostream>

in
a

using namespace std;


4

int main()
{
int dia, mes, ano;

el
im

cout << "Dia? " <<endl;


cin >> dia;

10

cout << "Mes? " <<endl;


cin >> mes;

12

16

cout << "Ano? " <<endl;


cin >> ano;

18

cout << dia << " de ";

20

switch(mes)
{
case 1:
cout <<
case 2:
cout <<
case 3:
cout <<
case 4:
cout <<
case 5:
cout <<
case 6:
cout <<
case 7:

22

"Janeiro";

s
o

24

Pr

14

26

28

"Marco";
"Abril";
"Maio";

Ve
r

30

"Fevereiro";

32

34

"Junho";

...

case 11:
cout << "Novembro";
case 12:
cout << "Dezembro";
default:
cout << "Hein?-zembro";
}
cout << " de " << ano << endl;
return 0;

36

38

40

42

44

56

CAPTULO 7. SWITCH

Execute este cdigo e digite, por exemplo, a data 1/1/2012 para ver que ele funciona quase corretamente. O problema, voc deve ter observado, que alm de
imprimir o nome do ms correto, o programa imprime tambm o nome de todos os meses subsequentes e o valor default. Isso ocorre por que, na verdade, o switch comea
a executar o bloco correspondente ao case com o valor da varivel mas, a partir da,
executa todos os blocos a no ser que seja instrudo a fazer diferente, o que feito via
a instruo break.

7.2

in
a

break

A instruo break diz ao computador que pare de executar o switch no ponto em que
invocada.1 Sendo assim, podemos reescrever o programa mais uma vez para obter
exatamente o comportamento da verso usando if.

using namespace std;


4

int main()
{
int dia, mes, ano;

12

cout << "Dia? " <<endl;


cin >> dia;

Pr

10

cout << "Mes? " <<endl;


cin >> mes;

14

18

20

22

cout << dia << " de ";


switch(mes)
{
case 1:
cout <<
break;
case 2:
cout <<
break;
case 3:
cout <<
break;
case 4:
cout <<
break;
case 5:
cout <<
break;
case 6:
cout <<

Ve
r

24

cout << "Ano? " <<endl;


cin >> ano;

s
o

16

26

28

30

32

34

36

38

el
im

#include <iostream>
2

1 Mais

"Janeiro";

"Fevereiro";

"Marco";

"Abril";

"Maio";

"Junho";

tarde veremos outros blocos no qual o break pode ser utilizado.

7.3. EXERCCIOS

46

48

50

52

54

56

58

60

"Agosto";

"Setembro";

44

"Julho";

"Outubro";

in
a

42

"Novembro";

"Dezembro";

"Hein?-zembro";

62

cout << " de " << ano << endl;


return 0;

64

Exerccios

7.3.1

s
o

7.3

Pr

el
im

break;
case 7:
cout <<
break;
case 8:
cout <<
break;
case 9:
cout <<
break;
case 10:
cout <<
break;
case 11:
cout <<
break;
case 12:
cout <<
break;
default:
cout <<
break;
}

40

57

Implemente uma funo chamada menu imprima o seguinte menu na tela:


1. Soma

Ve
r

2. Mdia

3. Menor
4. Maior

Leia e que retorne o nmero da opo escolhida.


Implemente a funo main de forma a ler trs nmeros e, ento, invocar a funo
definida acima para decidir o que fazer. O resultado da funo deve ser armazenando
em uma varivel e seu contedo testado com switch. Cada opo deve invocara a
funo respectiva, que calcular e retornar o que se pede. A funo main imprimir
ento o resultado.

#include <iostream>
#include <stdio.h>

58

10

int menu()
{
int opcao;
cout << "1 Soma" << endl << "2 Media" << endl << "3 Menor" << endl
<< "4 Maior" << endl;
cout << "Qual sua opcao? ";
cin >> opcao;
return opcao;

12

#include <math.h>
using namespace std;

14

16

int menor(int x, int y, int z)


{
if(x <= y && x <= z)
return x;

18

if(y <= x && y <= z)


return y;

22

return z;

24

}
26

32

34

36

38

40

int soma(int x, int y, int z)


{
return x+y+z;
}
float media(int x, int y, int z)
{
float somatorio = soma(x,y,z);
return somatorio / 3.0;
}

Ve
r

42

Pr

30

int maior(int x, int y, int z)


{
if(x >= y && x >= z)
return x;
else if(y >= x && y<= z)
return y;
else
return z;
}

s
o

28

el
im

20

in
a

CAPTULO 7. SWITCH

44

46

48

50

int main()
{
int a, b, c;
int opcao;

52

cout << "digite tres numero inteiros" <<endl;


54

cin >> a >> b >> c;


56

opcao = menu();
58

7.4. LABORATRIO

59

switch(opcao)
{
case 1:
cout << "A soma dos tres numeros eh " << soma(a,b,c);
break;
case 2:
cout << "A media dos tres numeros eh " << media(a,b,c);
break;
case 3:
cout << "O menor dentre os tres numeros eh " << menor(a,b,c
);
break;
case 4:
cout << "O maior dentre os tres numeros eh " << maior(a,b,c
);
break;
default:
cout << "Opcao invalida. Execute o programa novamente e
leia direito as opcoes.";
}

60

62

64

66

68

72

74

el
im

in
a

70

76

return 0;
78

Pr

7.3.2

7.3.3

s
o

Escreva um programa com uma funo que receba um inteiro entre 1 e 7, inclusive, e
escreva o dia correspondente da semana (1 para domingo e 7 para sbado).

Ve
r

Escreva um programa com uma funo que receba um inteiro de 1 a 12 e retorne a


quantidade de dias no ms correspondente (assuma que o ano no bisexto).
Para este exerccio, a soluo mais simples envolve no colocar break em alguns
dos case.

7.4

Laboratrio

Faa os exerccios da lista de exerccios 1.

CAPTULO 7. SWITCH

Ve
r

s
o

Pr

el
im

in
a

60

Captulo 8

in
a

Repetio (I)

Motivao

Pr

8.1

el
im

Existem situaes em que a repetio de um conjunto de comandos inevitvel. Em


situaes como esta, temos duas opes: ou copiamos e colamos todo o trecho que
desejamos repetir, fazendo os ajustes necessrios; ou utilizamos uma sada mais inteligente por meio de comandos especiais que permitem automatizar a repetio. Neste
captulo veremos o comando de repetio while e alguns exemplos de seu uso.

Suponha de voc deseja fazer um programa para ler duas notas, calcular e imprimir a
mdia de dez alunos da disciplina. A maneira menos prtica de fazer isso seria:

Ve
r

...
float nota1, nota2, media;
cout << "Entre nota 1 e nota 2 do aluno 1: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 2: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 3: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 4: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 5: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 6: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;

s
o

10

12

14

16

18

20

22

24

61

28

30

32

34

36

38

40

el
im

42

cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 7: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 8: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 9: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
cout << "Entre nota 1 e nota 2 do aluno 10: " << endl;
cin >> nota1 >> nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
...

in
a

26

CAPTULO 8. REPETIO (I)

62

Pr

Este cdigo tem vrios problemas. Primeiro, ele mais propenso a erros. Se, por
exemplo, voc resolve renomear a varivel nota2 para notab, voc ter que faz-lo
em diversos pontos do programa, aumentando a possibilidade de esquecer algum. Em
segundo lugar, o cdigo exigiu grande retrabalho, isto , a repetio de uma mesma
tarefa por parte do programador. Finalmente, se voc precisar aumentar a quantidade
de repeties para, digamos, 100 alunos, ter que estender o cdigo por pginas e
pginas.
Para evitar tais problemas, para estas situaes a linguagem C fornece estruturas de
repeties, as quais permitem repetir um determinado conjunto de comandos.

O comando while

s
o

8.2

Um destes comandos o comando while (enquanto, em portugus). Sua forma geral


muito simples:
while (<condicao>)
{
// bloco de comandos
// a ser repetido
}

Ve
r

O bloco de comandos entre as chaves ser repetido enquanto a condio dentro dos
parnteses for verdadeira.
Utilizando o while, o exemplo anterior pode ser reescrito de maneira bem mais
adequada:

...
float nota1, nota2, media;
int i = 1; // valor inicial do identificador do aluno

8.3. O COMANDO DO-WHILE

10

12

while (i <= 10)


{
cout << "Entre nota 1 e nota 2 do aluno " << i << ": " << endl;
cin << nota1 << nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
i++; // aumentamos o valor de i no final de cada calculo da media
}
...

63

in
a

Observe as seguintes modificaes:


Uma nova varivel i foi criada para contabilizar o nmero de alunos.

Esta varivel inicializada com o valor 1, representando o primeiro aluno.

el
im

A condio dentro do comando de repetio ser verdadeira enquanto o valor de


i for menor ou igual a 10.
Por este motivo, devemos incrementar o valor de i no fim de cada ciclo.

8.3

O comando do-while

do
{
\\ bloco de comandos
\\ a ser repetido

s
o

Pr

Uma variao do comando while fornecida pela linguagem C. Trata-se do comando


do-while (faa-enquanto ou repita-enquanto, em portugus). Sua forma geral dada
por:

}
while (<condicao>);

Ve
r

O mesmo exemplo anterior pode ser reescrito utilizando este comando:


2

...
float nota1, nota2, media;
int i = 1; // valor inicial do identificador do aluno

10

12

14

do
{

cout << "Entre nota 1 e nota 2 do aluno " << i << ": " << endl;
cin << nota1 << nota2;
media = (nota1 + nota2) / 2;
cout << "A media das notas eh " << media << endl;
i++; // aumentamos o valor de i no final de cada calculo da media

}
while (i <= 10);
...

64

CAPTULO 8. REPETIO (I)

Em comparao ao comando while, a nica diferena existente o fato do teste da


condio ser feito aps a execuo do bloco de comandos que se deseja repetir. Uma
implicao disto que, em casos em que a condio falsa logo no primeiro teste, o
bloco de comandos executado com do-while, mas no executado com while. Isto
aconteceria para a varivel i com valor inicial de 11, por exemplo.

Mais exemplos

8.4

Pr

10

...
int n = 2, // primeiro par maior do que 1
soma = 0; // soma inicialmente zerada
while (n < 999)
{
soma = soma + n;
n += 2;
}
cout << "O valor da soma eh " << soma << endl;
...

el
im

in
a

Considere que deseja-se somar todos os nmeros pares entre 1 e 999. Ou fazemos uma
soma com todos os valores em uma linha enorme, ou utlizamos o que apresendemos
sobre comandos de repetio. Utilizando o while, teramos:

...
int i = 0, // contador da qtde de numeros lidos
maior,
n;
do
{
cout << "Entre um numero: ";
cin >> n;
if (i == 0) // se for o primeiro numero lido
{
// ele serah o menor
maior = n;
}
else
// a partir do segundo
{
if(n > maior) // atualizo o maior
{
maior = n;
}
}
i++;
}
while (i < 10);
...

Ve
r

s
o

Observe que a cada iterao o valor de soma acrescido do prximo nmero par, o
qual obtido somando-se 2 ao valor de n.
Imagine que se deseja obter o maior entre 10 nmeros inteiros lidos. Utilizando o
do-while, uma possvel soluo seria:

10

12

14

16

18

20

22

8.4. MAIS EXEMPLOS

65

Ve
r

s
o

Pr

in
a

...
int num;
do
{
cout << "Entre um numero: ";
cin >> num;
}
while (! num > 100);
...

el
im

Neste exemplo temos uma situao especial em que, no primeiro caso (i = 0), o
maior valor o nico valor lido. A partir do segundo nmero, se o nmero lido for
maior do que o valor armazenado na varivel maior, esta ser atualizada.
Em outro exemplo, imagine que queira ler nmeros at que leia um nmero maior
que 100. Neste caso, o seguinte programa resolveria nosso problema.

66

8.5

CAPTULO 8. REPETIO (I)

Exerccios

Faa os exerccios a seguir mo.

8.5.1

Faa uma funo que recebe um nmero inteiro positivo e retorna o fatorial deste nmero. A funo principal deve ler o nmero do qual se deseja calcular o fatorial e
imprimir o resultado.

in
a

8.5.2

el
im

Faa uma funo que recebe um nmero inteiro positivo e retorna true se o nmero
for primo ou false, caso contrrio. A funo principal (main) deve ler o nmero e
imprimir o resultado.

8.5.3

Modifique o programa anterior para imprimir todos os nmeros primos abaixo de dois
milhes.

8.5.4

Ve
r

s
o

Pr

Faa um programa que leia um nmero inteiro positivo e imprima esse nmero de trs
pra frente. A impresso deve ser feita pela funo auxiliar inverteNumero.

8.6. LABORATRIO

8.6

67

Laboratrio

8.6.1
Implemente os exerccios acima no Code::Blocks.

8.6.2

in
a

O exerccio 7.3.1 pedia que voc escrevesse uma funo que gerasse um menu na tela.
A funo que voc escreveu tinha um problema: ela aceitava qualquer valor, mesmo
algum no correspondendo a nenhuma opo do menu.
Usando do-while, altere sua funo para que continue exibindo o menu e lendo
uma opo at que uma opo vlida seja digitada pelo usurio.

el
im

8.6.3

Implemente uma funo chamada pot que receba dois nmeros reais base e expoente
como parmetro e que calcule baseexpoente . A funo pot deve usar multiplicaes
sucessivas para calcular seu resultado (isto , proibido o uso da funo pow).

8.6.4

propsito, para terminar um programa basta digitar a combinao de teclas ctrl+c.

Ve
r

...
int num = 10;
do
{
cout << num;
num *= 2;
}
while (1);
...

s
o

Pr

Execute o seguinte programa em seu computador e observe o que acontece.

8.6.5

Escreva um programa que leia um numero inteiro positivo n e em seguida imprima n linhas do
chamado Tringulo de Floyd:

1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21

68

CAPTULO 8. REPETIO (I)

8.6.6
Faa um programa que gera um nmero inteiro aleatrio de 1 a 1000 em uma funo denominada
geraNumero. Na funo principal, o usurio deve tentar acertar qual o nmero foi gerado. A
cada tentativa o programa dever informar se o chute menor ou maior que o nmero gerado.
O programa acaba quando o usurio acerta o nmero gerado. O programa deve informar em
quantas tentativas o nmero foi descoberto.

8.6.7

Ve
r

s
o

Pr

el
im

in
a

Escreva um programa que receba como entrada o valor do saque realizado pelo cliente de um
banco e retorne quantas notas de cada valor sero necessrias para atender ao saque com a
menor quantidade de notas possvel. Sero utilizadas notas de 100, 50, 20, 10, 5, 2 e 1 reais. O clculo e impresso do resultado deve ser efetuado por uma funo auxiliar denominada
imprimeNotas.

Captulo 9

in
a

Repetio (II)

el
im

Voc deve ter percebido que no uso de do-while e while quase sempre seguimos os mesmos
passos:
declarar uma varivel que sirva de controle para a iterao;
iniciar a varivel de controle (e possivelmente outras);
verificar a condio para iterao
executar iterao

Pr

executar incremento/decremento (mudana da varivel de controle)

A linguagem C tem um comando iterao que agrega todos estes passos, chamado for.

for

s
o

9.1

Sua forma geral do comando for a seguinte:


2

Ve
r

for(DI; C; I)
{
\\bloco de comandos a ser repetido
}

O comando for tem trs partes em sua declarao, alm dos comandos a serem repetidos.
DI em DI variveis podem ser Declaradas e Iniciadas. Variveis j existentes tambm
podem ter seus valores ajustados em DI;
C C define a Condio necessria execuo do bloco de comandos. Enquanto a
condio for verdadeira, o bloco ser executado.
I comandos de modificao de variveis, como Incremento e decremento, so colocados
diretamente na declarao do for. O comando executado ao final de cada iterao.
A execuo do for segue os seguintes passos:

1. Iniciao (execuo de DI)


2. Avaliao (teste da condio em C)

69

70

CAPTULO 9. REPETIO (II)


3. Execuo do bloco de comandos
4. Incremento
5. De volta ao passo 2

10

in
a

...
int n = 2, // primeiro par maior do que 1
soma = 0; // soma inicialmente zerada
while (n < 999)
{
soma = soma + n;
n += 2;
}
cout << "O valor da soma eh " << soma << endl;
...

el
im

Considere o exemplo do captulo anterior em que deseja-se somar todos os nmeros pares
entre 1 e 999. O cdigo pode ser escrito, como vimos, usando while.

O cdigo equivalente, usando for essencialmente o mesmo.

...
int n, // primeiro par maior do que 1
soma = 0; // soma inicialmente zerada
for (n = 1; n < 999; n += 2)
{
soma = soma + n;
}
cout << "O valor da soma eh " << soma << endl;
...

Pr

...
int soma =
for (int n
{
soma =
}
cout << "O
...

Ve
r

s
o

O cdigo, contudo, pode ser simplificado colocando-se a declarao da varivel de controle


no prprio for.

0; // soma inicialmente zerada


= 1; n < 999; n += 2)

soma + n;
valor da soma eh " << soma << endl;

possvel declarar e iniciar mais de uma varivel no DI, mas no possvel definir novas
variveis e iniciar outras j definidas. No exemplo abaixo, errado, a varivel soma sendo iniciada
no for diferente da varivel definida antes do comando, apesar do nome ser igual.

...
int soma = 0; // soma inicialmente zerada
for (int n = 1, soma = 0; n < 999; n += 2)
{
soma = soma + n;

9.2. MAIS EXEMPLOS


6

71

}
cout << "O valor da soma eh " << soma << endl;
...

9.2

Mais Exemplos

10

12

14

16

18

cout << "Entre um numero: ";


cin >> n;
maior = n;
for(i = 0; i < 9; i++)
{
cout << "Entre um numero: ";
cin >> n;
if(n > maior) // atualizo o maior
{
maior = n;
}
}
...

el
im

Pr

...
int i, // contador da qtde de numeros lidos
maior,
n;

s
o

in
a

Tambm do captulo anterior, imagine o exemplo em que se deseja obter o maior entre 10 nmeros inteiros lidos. Utilizando o for, uma possvel soluo seria:

Observe que a primeira leitura aconteceu fora do for.

9.3

Declaraes especiais

Ve
r

Em certas situaes pode ser desejvel omitir partes da declarao do for. Por exemplo, se as
variveis de controle j tiverem sido iniciadas ou, simplesmente, se no existirem, ou se no
houver incremento a ser feito, ento estas partes da declarao podem ser deixadas em branco.
Por exemplo,

int menu()
{
int opcao = 0;

10

12

for( ; opcao <


{
cout << "1
<< "2
<< "3
<< "4

1 || opcao > 4 ; )
Soma" << endl
Media" << endl
Menor" << endl
Maior" << endl;

cout << "Qual sua opcao? ";

72

CAPTULO 9. REPETIO (II)

cin >> opcao;


}
return opcao;

14

16

in
a

Observe que embora neste exemplo tanto DI quanto I esto vazias, isso no necessrio. Isto
, qualquer das partes da declarao podem estar vazias independentemente, inclusive a segunda
parte.

9.4

Alterando a repetio com o break e continue

int menu()
{
int opcao;

10

"1
"2
"3
"4

Soma" << endl


Media" << endl
Menor" << endl
Maior" << endl;

Pr

for(;;)
{
cout <<
<<
<<
<<

el
im

Caso a segunda parte do comando esteja vazia, a repetio ser executada ad infinitum ou at que
seja interrompida. A interrupo de uma iterao pode ser feita usando-se o comando break.
Veja o exemplo anterior reescrito para usar tal comando.

cout << "Qual sua opcao? ";

14

cin >> opcao;

16

18

20

if(opcao > 0 && opcao < 5)


break;
else
cout << "Opcao invalida" << endl << endl;

return opcao;

Ve
r

22

s
o

12

Outra forma de se alterar o fluxo via o comando continue, que faz com que a o restante do bloco de comandos seja ignorado e, conseqentemente, incremento e condio sejam
reavaliados. Por exemplo, reescrevendo o cdigo acima para o usar o continue.

int menu()
{
int opcao;

for(;;)
{
cout << "1 Soma" << endl
<< "2 Media" << endl

9.5. EXERCCIOS

73

<< "3 Menor" << endl


<< "4 Maior" << endl;

10

12

cout << "Qual sua opcao? ";

14

cin >> opcao;

16

if(opcao < 1 || opcao > 4)


continue;

18

cout << "A opcao escolhida foi " << opcao;


break;

20

in
a

}
22

return opcao;
}

9.5

el
im

24

Exerccios

Refaa os execcios do captulo anterior usando for.

Laboratrio

Pr

9.6

Refaa o laboratrio do captulo anterior usando for.

9.6.1

Ve
r

..
..
..

s
o

Escreva uma funo que receba dois parmetros inteiros, X e Y, e imprima X linhas na tela, cada
uma com Y .. Por exemplo, se sua funo for invocada com X igual 3 e Y igual 2, o resultado
deveria ser o seguinte

9.6.2

Escreva uma funo que receba dois parmetros inteiros, X e Y, e imprima de forma decrescente
os nmeros de X*Y at 1, em X linhas de Y nmeros. Por exemplo, se sua funo for invocada
com X igual 4 e Y igual 3, o resultado deveria ser o seguinte
12 11 10
9 8 7
6 5 4
3 2 1

CAPTULO 9. REPETIO (II)

Ve
r

s
o

Pr

el
im

in
a

74

in
a

el
im

Tipos de Dados e Suas


Representaes

Captulo 10

At agora temos trabalhado essencialmente com os tipos numricos, inteiros e reais, e booleanos. Para que possamos usar outros tipos, essencial que antes entendamos como os dados so
representados na memria do computador.

Bit & Byte

Pr

10.1

10.1.1

s
o

Como dito anteriormente, a memria do computador pode ser entendida como uma grande planilha eletrnica, podendo cada clula ser endereada (atribuda, lida, nomeada) individualmente.
Na memria do computador no existem nmeros ou caracteres, mas vrias lampdas que podem estar ligadas ou desligadas. Ns humanos atribumos significado a tais estados como sendo
0s e 1s. Cada posio da memria, que pode armazenar 0 ou 1, denominado um bit. Por
serem mnimos, normalmente trabalhamos com conjuntos de 8 bits por vez, o que denominamos
bytes.

Base Binria

Ve
r

Os bits de um byte podem assumir todas as combinaes de ligado e desligado (0 e 1). Dado
um contexto, cada combinao corresponde a um certo valor. Por exemplo, se estiver usando um
byte para representar nmeros inteiros, ento provavelmente a correspondncia na Tabela 10.1
se aplica.
Talvez isso seja novidade para voc, mas voc representa nmeros na base decimal usando
10 dgitos (de 0 a 9). Contudo, outras bases existem. Como os bits s possuem dois estados,
natural na computao usar a base binria, que usa 2 dgitos (0 e 1). Os valores esquerda na
tabela podem ser entendidos como nmeros nesta base.1
Para conseguir converter nmeros de uma base para a outra, basta entender o que exatamente
significa a representao de um nmero em uma base genrica X. Nesta base, ABCDX significa
AX 3 +BX 2 +CX 1 +DX 0 . O nmero 123410 , por exemplo, significa 1X 3 +2X 2 +3
X 1 +4X 0 = 11000+2100+310+41 que igual a, t d, 123410 . Para um exemplo mais
1 sempre que no for colocada a base, considera-se a base 10, mais natural aos seres de vida baseada em
carbono do nosso planeta, A.K.A., voc.

75

76

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES

el
im

in
a

Tabela 10.1: Exemplos de valores em binrio e decimal correspondente.


bits
Nmero
00000000
0
1
00000001
00000010
2
3
00000011
00000100
4
00000101
5
6
00000110
00000111
7
8
00001000
00001001
9
00001010
10
...
11111101
253
11111110
254
11111111
255
00000000
0
...

Base Hexadecimal

s
o

10.1.2

Pr

interessante, o nmero 101010102 = 127 +026 +125 +024 +123 +022 +121 +020 =
128 + 0 + 32 + 8 + 2 = 170.
Observe que, pela tabela, o maior nmero que se pode representar com 8 bits 111111112 =
25510 . Via de regra, com X bits pode se representar 2X na base binria, de 0 a 2X 1.

Ve
r

Embora se possa usar qualquer base numrica, as que fazem mais sentido no mundo computacional so as binria e hexadecimal. A base hexadecimal usa 16 dgitos em cada posio
representando valores de 0 a 15. Para isto, usa os valores de 0 a 9 iguais aos da base decimal e
tambm as letras de A a F representado os valores de 10 a 15. Por exemplo, o nmero 1A2F16
equivale a 1 163 + 10 162 + 2 161 + 15 160 = 4096 + 2560 + 32 + 15 = 6703.

10.2

Converso entre bases numricas

Enquanto ns trabalhamos com base decimal, o computador armazena informao e realiza operaes na base binria. Por isso, a todo momento ocorre a converso entre um decimal que
informamos como entrada em um programa, por exemplo, para a base binria (para efetuar o
clculo), bem como da base binria (resultado do clculo) para a base decimal exibida na tela.

Converso de Binrio para Decimal


A converso de binrio (e qualquer outra base) para decimal pode ser feita facilmente usando a
notao da base genrica apresentada acima. Isto , para realizar a converso basta multiplicar o
valor de cada posio pelo seu peso (base elevada posio). Por exemplo, o nmero 11110112
equivale a 126 +125 +124 +123 +022 +121 +120 = 64+32+16+8+0+2+1 = 12310 .

10.3. TIPOS NUMRICOS INTEIROS

77

Converso de Decimal para Binrio

el
im

in
a

A converso de decimal para binrio feita realizando-se divises sucessivas pela base de interesse (2, no nosso caso) at que o resultado seja zero. Os restos das divises, na ordem inversa,
correspondem ao nmero convertido.
Por exemplo, considere a converso do nmero 169 para a base binria. O processo de
converso o seguinte:
169/2 = 84, Resto = 1
84/2 = 42, Resto = 0
42/2 = 21, Resto = 0
21/2 = 10, Resto = 1
10/2 = 5, Resto = 0
5/2 = 2, Resto = 1
2/2 = 1, Resto = 0
1/2 = 0, Resto = 1
O nmero binrio equivalente , portanto, 101010012 .

Converso entre Binrio e Hexadecimal

Tipos Numricos Inteiros

s
o

10.3

Pr

Sabendo-se que com 4 bits possvel representar at 16 nmeros (de 0 a 15) e que a base hexadecimal tem exatamente 16 dgitos, conclumos que possvel representar cada dgito hexadecimal
com 4 dgitos binrios. Sendo assim, a converso binrio/hexadecimal pode ser feita facilmente
substituindo conjuntos de 4 bits binrios por um dgito hexadecimal e vice-versa.
Por exemplo, para convertermos 111010102 convertemos 11102 para E16 e 10102 para A16 ,
obtendo o nmero EA16 . Na direo inversa, para convertermos o nmero 7B16 para binrio
convertemos 716 para 01112 e B16 para 10112 , obtendo o nmero 011110112 .

Ve
r

Na linguagem C, os principais tipos, a quantidade de bits utilizada para sua representao e o


intervalo de valores aceitos so resumidos na tabela a seguir: 2
Observe que o tipo caractere tambm armazenado internamente como um nmero inteiro
de 8 bits. Com 8 bits podemos representar 28 nmeros. Se considerarmos nmeros sem sinal
(unsigned) teremos de 0 a 255; se considerarmos nmeros com sinal, teremos metade para positivos e metade para negativos, ou seja, de -128 a 127. O mesmo raciocnio se aplica para os
outros tipos de dados da tabela.
A partir desta tabela podemos observar a importncia da escolha adequada do tipo correto
de acordo com sua aplicao. Se utilizarmos um inteiro para somarmos 20.000 e 50.000, por
exemplo, o resultado ser inesperado, uma vez que o maior valor que um inteiro aceita 32.767.
Quando isto ocorre, dizemos que houve um overflow.

10.3.1

Nmeros Binrios Negativos

Os exemplos que vimos at agora de converso no contemplam nmeros negativos. Na base


decimal, o sinal de menos (-) antes do valor do nmero tem a finalidade de representar nmeros
negativos.
2A

quantidade de bits pode variar de acordo com o compilador e a arquitetura do sistema

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES

in
a

78

Ve
r

s
o

Pr

el
im

Tabela 10.2: Exemplos de valores em binrio, decimal e hexadecimal correspondentes.


Binrio
Decimal Hexadecimal
00000000
0
0
00000001
1
1
00000010
2
2
00000011
3
3
00000100
4
4
00000101
5
5
00000110
6
6
00000111
7
7
00001000
8
8
00001001
9
9
00001010
10
A
00001011
11
B
00001100
12
C
13
D
00001101
00001110
14
E
00001111
15
F
00010000
16
10
...
11111101
253
FD
11111110
254
FE
11111111
255
FF
0
0
00000000
...

10.4. ARITMTICA INTEIRA BINRIA

79

in
a

Tabela 10.3: Intervalo de representao dos tipos numricos inteiros.


Tipo
Quantidade de Bits
Intervalo
char
8
-128 a 127
8
0 a 255
unsigned char
int
16
-32.768 a 32.767
16
0 a 65.535
unsigned int
long
32
-2.147.483.648 a 2.147.483.647
unsignet long
32
0 a 4.294.967.295

Como a memria do computador armazena apenas 0s e 1s, uma possvel estratgia desperdiar um dos bits do nmero para o sinal. Adota-se, por padro, o zero para representar um
nmero positivo e o um para negativo. O bit do sinal armazenado na posio mais esquerda.

el
im

Para representar o valor de um nmero negativo h duas principais abordagens: sinalmagnitude e complemento de 2.
Na representao sinal-magnitude, o nmero negativo tem seu valor absoluto (magnitude)
representado da mesma forma que um nmero positivo e o bit mais significativo, que representa
o sinal, ser igual a um. A tabela a seguir mostra alguns exemplos de nmeros na base decimal
e na representao sinal-magnitude.

s
o

Pr

Tabela 10.4: Exemplos de valores na representao sinal-magnitude.


Decimal Binrio Sinal-Magnitude
+20
00010100
-20
10010100
+115
01110011
-115
11110011
Com 8 bits, temos, ento nmeros de 111111112 a 011111112 (-127 a +127). Um problema que aparece com esta representao o zero. Qual a representao correta, 00000000 ou
10000000? E por que precisaramos de duas representaes?

Ve
r

A representao complemento de 2 utiliza uma maneira um pouco diferente de representar


nmeros negativos. Para express-los devemos inverter cada bit do nmero positivo e somar 1
ao resultado. Por exemplo, o nmero -15 representado em complemento de 2 com 5 bits como
10001, ou seja, calcula-se o valor de +15 = 011112 , e, em seguida invertemos e somamos 1:
100002 + 12 = 100012 . Se a representao usar 8 bits, ento 1510 = 000011112 e 1510 =
111100012 .

10.4

Aritmtica Inteira Binria

Aritmtica binria to simples como 1 + 1 = 10. Srio, assim que se faz: 0 + 0 = 0, 0 + 1 =


1 + 0 = 1, 1 + 1 = 102 . Logo, em sistemas computacionais as somas e subtraes geralmente
so realizadas aos pares, da mesma forma que na base binria.

80

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES

10.4.1

Nmeros positivos

A adio de nmeros positivos muito simples. Para faz-la, basta somar os valores na mesma
posio, do menos significativo para o mais significativo. O vai-um funciona da mesma forma
como fazemos na base decimal. Por exemplo, para somarmos 5 e 9, fazemos:

in
a

1
0101 +
1001
---1110

1 111
0111 +
1001
---1 0000 <-- overflow!

el
im

Como a quantidade de bits para determinado tipo de dados limitado, durante uma soma pode
ocorrer de o resultado ultrapassar o maior valor permitido para aquela quantidade de bits, quando
isto ocorre, temos um overflow (derramamento). Considere a soma de 7 e 9, ambos com 4 bits.

Houve um vai-um alm do bit mais significativo, caracterizando um overflow. Neste caso,
o resultado da operao est errado.

Nmeros em Complemento de 2

Pr

10.4.2

s
o

Como vimos anteriormente, o computador usa duas principais representaes para nmeros negativos. A representao complemento de 2 a mais utilizada porque permite que a soma de
nmeros negativos seja feita da mesma maneira que a soma de nmeros positivos. Por exemplo
considere as soma de -2 + 5 e -1+(-1), em complemento de 2:
1 1
1110 +
0101
---1 0011 <-- No overflow! Esse "vai-um" deve ser desprezado!

Ve
r

(-2)
(+5)

(-1)
(-1)

1 111
1111 +
1111
---1 1110 <-- No overflow! Esse "vai-um" deve ser desprezado!

Observe que nestes exemplos tivemos um vai-um alm do bit mais significativo. Em soma de
nmeros em complemento de 2 isto no suficiente para caracterizar um overflow. Um overflow
apenas ocorrer quando, ao somarmos dois nmeros de mesmo sinal, obtivermos um nmero de
sinal diferente. Desta maneira, no exemplo apresentado, este vai-um a mais deve simplesmente
ser ignorado.
J os exemplos a seguir mostram operaes problemticas.

10.5. TIPOS NUMRICOS REAIS

(+7)
(+7)

81

111
0111 +
0111
---1110 <-- O resultado comea com 1, logo negativo. Absurdo!

10.4.3

in
a

1
(-3) 1101 +
(-6) 1010
---1 0111 <-- O resultado comea com 0, logo positivo. Absurdo!

E a subtrao?

10.5

Tipos Numricos Reais

el
im

Na verdade, a maioria dos computadores no sabe fazer subtrao. O que eles fazem utilizar
um truque para transformar uma subtrao em uma soma.
Por exemplo, a operao 7 5 pode ser reescrita como 7 + (5), ou seja, para realizar a
subtrao basta inverter o segundo nmero (em complemento de 2) e som-lo ao primeiro da
maneira usual.

Ve
r

s
o

Pr

Para representarmos nmeros reais no computador, definimos que uma quantidade de bits do
nmero ser usada para representar a mantissa e o restante o expoente do nmero. Por exemplo,
se dispusermos de 8 bits, podemos definir que os quatro primeiros bits sero a mantissa e os
quatro ltimos sero o expoente, em notao cientfica. Assim, 101010102 = 1, 0 1011 e
101110102 = 1, 1 1011 .
Antes que voc saia dizendo por a que o ideal usar tais nmeros pois podemos representar
nmeros to grandes como 111111112 = 15 1015 , que muito mais que os 216 1 da notao
binria convencional, pense em como representaria o nmero 16110 , j que a maior mantissa
representvel 1,5. Alm disso, como representar 1,1111, j que s dispomos de 4 dgitos na
mantissa?
Alm disso, se representaes de nmeros reais pecam em sua preciso, tambm pecam na
velocidade de processamento. A aritmtica de nmeros binrios muito mais simples que a de
nmeros reais (ou de ponto flutuante, como costumamos dizer na computao). Para manipular
nmeros reais, computadores normalmente precisam de componentes dedicados a este fim e que
tem alto tempo de execuo.
Para saber mais sobre representaes de nmeros em pontos flutuantes visite a URL http:
//en.wikipedia.org/wiki/Floating_point

10.6

Representao de caracteres

A converso de nmeros para o sistema binrio bem simples e intuitiva. No entanto, o computador no trabalha exclusivamente com nmeros. Como por exemplo, iremos armazenar uma
frase do tipo "eu amo programar em C"no nosso pen-drive?
Uma pessoa pode decidir que o a ser o 1, o b ser o 2 e assim por diante. Mas como
outra pessoa que receber a informao saber disso? Para evitar este problema a representao

82

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES

de caracteres como nmeros foi padronizada. Os principais padres existentes so: ASCII,
EBCDIC e Unicode.

ASCII

Outras representaes

el
im

in
a

ASCII, ou American Standard Code for Information Interchange, o padro mais utilizado,
presente em todos os nossos computadores pessoais. Trata-se de uma codificao de caracteres
de oito bits baseada no alfabeto ingls.
A codificao define 256 caracteres (28 ). Desses, 33 no so imprimveis, como caracteres
de controle atualmente no utilizveis para edio de texto, porm amplamente utilizados em
dispositivos de comunicao, que afetam o processamento do texto. Exceto pelo caractere de
espao, o restante composto por caracteres imprimveis.
A Figura 10.1 exibe a tabela ASCII.
A linguagem C prov um atalho para que voc no tenha que recorrer tabela ASCII sempre
que precisar do valor de um caractere: para obter o valor de um caractere qualquer, basta coloclo entre aspas simples. Isto , para verificar se um caracter c uma letra maiscula, por exemplo,
basta efetuar o teste if(c >= A&& c <= Z).

10.7

Pr

As representaes EBCDIC (Extended Binary Coded Decimal Interchange Code) e Unicode


tambm mapeiam os caracteres em nmeros de 8 e 16 bits, respectivamente.
EBCDIC utilizado principalmente em mainframes IBM. O padro Unicode foi criado para
acomodar alfabetos com mais de 256 caracteres.

Exerccios

10.7.1

s
o

Quantos nmeros se pode representar, na base binria, com 1, 8, 16, 32 e 64 bits?

10.7.2

Escreva os seguintes nmeros nas bases binria e hexadecimal:

Ve
r

1. 16
2. 45

3. 129
4. 23

5. 1290

10.7.3
Converta os nmeros a seguir para a base decimal:
1. 1616
2. D516
3. 11001011012

83

Ve
r

s
o

Pr

el
im

in
a

10.7. EXERCCIOS

Figura 10.1: Tabela ASCII

4. 2C0416
5. 111012

10.7.4
Escreva os nmeros a seguir nas representaes sinal-magnitude e complemento de 2 com 8 bits:

84

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES


1. -19
2. +47
3. -29
4. -37
5. -105

10.7.5

Realize as seguintes operaes aritmticas em complemento de 2 com nmeros de 8 bits:

in
a

1. 16 - 9
2. -45 - 7
3. -12 + 12

el
im

10.7.6
Escreva seu nome na codificao ASCII.

10.8

Laboratrio

Acompanhe as atividades a seguir:

Pr

10.8.1

No laboratrio veremos como utilizar a tabela ASCII para imprimir caracteres. Execute o seguinte programa e observe o que ser impresso. Atente para as atribuies!
#include<iostream>
2

int main()
{
int a;
char c;
for(a = 65; a < 91; a++)
{
c = a;
cout << c << endl;
}
return 0;
}

Ve
r

10

s
o

using namespace std;


4

12

14

Voc deve ter observado que os nmeros no foram impressos, e sim as letras de A a Z.
Olhe a tabela na Figura 10.1 e descubra o porqu.

10.8.2
Modifique o programa a seguir para imprimir as letras de a a z, ou seja, as letras minsculas
do alfabeto ingls.

10.8. LABORATRIO

85

10.8.3
Agora faa um programa que leia caracteres informados pelo usurio enquanto ele no pressionar
a tecla ESC. Para cada caractere informado pelo usurio, escreva o nmero correspondente na
tabela ASCII.

10.8.4

Ve
r

s
o

Pr

el
im

in
a

Modifique o programa anterior para que solicite que o usurio entre com letras minsculas de a
a z e imprima na tela, para cada letra, a maiscula correspondente.

CAPTULO 10. TIPOS DE DADOS E SUAS REPRESENTAES

Ve
r

s
o

Pr

el
im

in
a

86

in
a

Arranjos Unidimensionais

Captulo 11

el
im

Tente resolver o seguinte problema:


1. ler um conjunto de 6 nmeros inteiros
2. calcular sua mdia

3. imprimir todos os nmeros maiores que a mdia na tela do computador

Pr

Fcil, certo? Basta declarar 6 variveis do tipo int, ler seus valores, somar seus valores e dividir
por 6.
Mas e se alterssemos o problema para que, em vez de 6, precisasse ler 10 nmeros? E 100?
Ter muitas variveis distintas com a mesma finalidade no vivel por duas razes:

s
o

difcil de manter: e se voc precisar renomear uma varivel, ter que faz-lo em todas as
variveis;
se precisar aumentar ou diminuir o nmero de variveis, ter que apagar/copiar e renomear.
evita reuso de cdigo: se uma mesma operao precisa ser aplicada a cada varivel, fica
difcil reusar o cdigo desta operao.
A soluo para esta situao o uso de vetores (ou variveis indexadas ou arranjo ou array).

Vetores

Ve
r

11.1

Continuando com nossa analogia da memria do computador com uma planilha eletrnica, um
vetor uma varivel que nomeia diversas clulas contguas da memria do computador. Isto
, de certa forma, enquanto uma varivel int corresponde a uma rea da memria que cabe 1
inteiro, um vetor de 10 int uma varivel que cabe 10 inteiros.
A sintaxe para a declarao esttica de vetores bem simples (em captulos futuros veremos
como declarar vetores dinmicos, isto , que podem variar seus tamanhos).
tipo identificador[tamanho];
Onde
tipo o tipo do dado a ser armazenado em cada posio do vetor;
identificador o nome do vetor;

87

88

CAPTULO 11. ARRANJOS UNIDIMENSIONAIS


tamanho a quantidade de clulas no vetor;

O acesso a uma clula, para leitura ou atribuio, feito usando se o identificador seguido
pela posio a ser acessada, entre colchetes ([]). Por exemplo, x[3] = 0 atribui o valor 0
posio de ndice 3 do vetor x. Algo importante a ser observado aqui que a primeira posio
de um vetor de tamanho n tem ndice 0 e a ltima tem ndice n 1.
O exemplo a seguir resolve o problema apresentado na seo anterior usando vetores.
#include<iostream>
2

using namespace std;


4

in
a

#define TAMANHO 10
6

10

int main()
{
int num[TAMANHO];
int soma = 0;
int media;

12

el
im

18

for(int i = 0; i < TAMANHO; i++)


{
cout << "Digite o " << i << "-esimo valor: ";
cin >> num[i];
soma += num[i];
}

20

media = soma/TAMANHO;

22

cout << "Os valores acima da media " << media << " sao" << endl;
for(int i = 0; i < TAMANHO; i++)
{
if(num[i] > media)
cout << num[i] << endl;
}

14

Pr

16

24

28

s
o

26

return 0;

30

Ve
r

Observe a definio e o uso da palavra TAMANHO no programa. Uma vez definido que
TAMANHO tem o valor 10, o computador substituir toda ocorrncia desta palavra no programa
pelo valor correspondente, antes da compilao.

11.2

Vetores de Caracteres

Vetores podem conter dados de quaisquer tipos. Isto , voc pode declarar vetores de nmeros
reais ou inteiros, caracteres ou booleanos, e at tipos definidos por voc, uma vez que aprenda
como definir novos tipos. Por exemplo, vamos definir um programa que leia um vetor de 10
caracteres e depois o escreva de volta tela.
#include<iostream>

using namespace std;


4

11.2. VETORES DE CARACTERES

89

#define TAMANHO 10
6

int main()
{
char nome[TAMANHO];

10

cout << "Digite " << TAMANHO << " caracteres: ";
12

24

cout << endl;

20

el
im

22

cout << "Os caracteres digitados foram: ";


for(int i = 0; i < TAMANHO; i++)
{
cout << nome[i];
}

18

return 0;

26

in
a

16

for(int i = 0; i < TAMANHO; i++)


{
cin >> nome[i];
}

14

#include<iostream>

using namespace std;

#define TAMANHO 100

int main()
{
char nome[TAMANHO];
int i = 0;

s
o

Pr

Agora, s para tornar as coisas mais interessantes, alteremos o programa para que leia at
100 caracteres, mas que pare de l-los to logo um . seja digitado.

11

Ve
r

cout << "Digite ate " << TAMANHO << " caracteres. Para terminar antes
, digite . ";
13

15

17

do
{

cin >> nome[i];


i++;
}while( i < TAMANHO && nome[i-1] != .);

19

21

23

cout << "Os caracteres digitados foram: "


for(int i = 0; i < TAMANHO && nome[i] != .; i++)
{
cout << nome[i];
}

25

cout << endl;


27

return 0;

90
29

CAPTULO 11. ARRANJOS UNIDIMENSIONAIS

11.2.1

Vetores de Caracteres como Strings

in
a

Um vetor de caracteres essencialmente uma palavra ou uma frase. Assim, durante a leitura
de um vetor de caracteres dificilmente sabe-se quantos caracteres sero digitados pelo usurio,
por exemplo, quando deseja-se ler o nome de um indivduo. Por este motivo, a maioria das linguagem de programao fornece mtodos especiais de leitura, impresso e manipulao desses
vetores de caracteres, ou como chamaremos agora, strings.
Na linguagem C++, os comandos cout e cin permite imprimir e ler strings de maneira
direta:
#include<iostream>
2

#define TAMANHO 100


6

int main()
{
char nome[TAMANHO];

10

el
im

using namespace std;


4

12

Pr

cout << "Digite ate " << TAMANHO << " caracteres. Para terminar
pressione ENTER:";
cin >> nome;
cout << "Os caracteres digitados foram: " << nome << endl;

14

return 0;

16

s
o

Ve
r

Entretanto, o comando cin, no permite, da forma como vimos at agora, a leitura de uma
string que contenha espaos (uma frase, por exemplo). Para que isso seja possvel precisamos
utilizar a funo cin.getline(). Esta funo necessita de dois argumentos: o vetor de caracteres representando a string e o tamanho mximo de caracteres que ser lido. A leitura realizada
at que seja atingido ou nmero mximo de caracteres ou o usurio pressione a tecla ENTER. A
seguir uma modificao do exemplo anterior:
#include<iostream>

using namespace std;

#define TAMANHO 100

int main()
{
char nome[TAMANHO];

10

cout << "Digite seu nome completo. Para terminar pressione ENTER:";
12

cin.getline(nome, TAMANHO);

11.3. EXERCCIOS

91

cout << "Seu nome eh: " << nome << endl;

14

return 0;

16

Exerccios

in
a

11.3

Escreva um programa que leia 10 caracteres e os imprima na ordem inversa quela em que foram
digitados.

el
im

Escreva um programa que leia 10 caracteres e os imprima na ordem inversa quela em que foram
digitados, trocando maisculas e por minsculas e vice-versa.

Pr

Escreva um programa que leia 10 nmeros e calcule e imprima a mdia e desvio padro dos
mesmos. Lembre-se que o desvio padro definido como a raiz quadrada dos quadrados das
diferenas dos valores para a mdia dos valores.

11.4

s
o

Escreva um programa que leia 11 nmeros reais e imprima os valores dos 10 primeiros multiplicados pelo 11-simo. Por exemplo, se os valores digitados foram 1, 2, 3 ,4 ,5 ,6, 7, 8, 9, 10 e 1.1,
ento seu programa deve imprimir 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 e 11.0.

Laboratrio

Ve
r

Repita os exerccios acima no computador.

Escreva um programa que leia 10 caracteres e os imprima na ordem inversa quela em que foram
digitados, trocando maisculas por minsculas e vice-versa.

Escreva um programa que leia 100 caracteres ou at que # seja digitado e os imprima na ordem
inversa quela em que foram digitados.

Escreva um programa que leia um nmero de 2 dgitos na base decimal e imprima o mesmo
nmero na base binria.

92

CAPTULO 11. ARRANJOS UNIDIMENSIONAIS

Escreva um programa que leia e imprima strings at que o usurio digite a palavra fim. Considere que cada string no possui espaos.

Ve
r

s
o

Pr

el
im

in
a

Escreva um programa que leia e imprima strings at que o usurio digite a palavra fim. As
strings podem conter espaos.

in
a

Strings e Funes

Captulo 12

12.1

el
im

Neste captulo veremos algumas funes muito usadas na manipulao de (strings) assim como
definir suas prprias funes que recebem vetores como parmetros.

Funes para manipulao Strings

s
o

Descrio
retorna o tamanho (em caracteres) da palavra passada como argumento.
copia o contedo da segunda string para a primeira.
concatena o texto da segunda string na primeira.
compara duas strings (vide exemplo a seguir).
compara duas strings sem diferenciar maisculas e minsculas.
converte uma string para o inteiro correspondente.
converte uma string para o nmero real correspondente.

Ve
r

Funo
strlen
strcpy
strcat
strcmp
stricmp
atoi
atof

Pr

Quando trabalhamos com strings muito comum a realizao de algumas tarefas como descobrir
o tamanho da palavra digitada pelo usurio, comparar duas palavras para saber a ordem, ou ainda,
concatenar duas palavras em uma nica.
Para isso, a biblioteca string.h fornece algumas funes prontas, como pode ser visto na
tabela 12.1

Tabela 12.1: Algumas funes para trabalhar com strings.

O exemplo a seguir mostra a utilizao destas funes:

#include<string.h>
#include<iostream>

using namespace std;

int main()
{
char str1[50], str2[50];
int i;
float f;

10

93

94

CAPTULO 12. STRINGS E FUNES

cout << Entre primeiro nome:;


cin >> str1;
cout << Entre ultimo nome:;
cin >> str2;
strcat(str1, ); //junto espaco com str1
strcat(str1, str2);
cout << Seu nome completo eh << str1 << endl;
cout << Ele possui << strlen(str1) << caracteres. << endl
;

12

14

16

18

cout << Entre outro nome:.


cin >> str2;

in
a

22

26

28

30

32

34

36

el
im

//comparacao de strings
if(strcmp(str1, str2) == 0)
{
cout << os dois nomes sao iguais. << endl;
}
else if(strcmp(str1, str2) < 0)
{
cout << str1 << vem antes de << str2 << endl;
}
else
{
cout << str2 << vem antes de << str1 << endl;
}
return 0;

24

Pr

38

20

s
o

No uso destas funes, importante manter-se em mente que o espao adequado deve ser
alocado para a string resultante das operaes. Por exemplo, ao se concatenar duas strings de no
mximo 100 caracteres, o resultado ter, no mximo, 200 caracteres.

12.2

Funes com vetores como parmetros

Ve
r

As funes descritas acima recebem strings como parmetros. Agora, veremos como definir
suas funes prprias funes que recebem no somente strings, mas vetores de outros tipos de
dados.
A declarao de uma varivel do tipo vetor segue, como j visto, a seguinte forma.
tipo identificador[tamanho];
A declarao de parmetros segue uma sintaxe parecida, no qual o tamanho do vetor no
aparece
tipo identificador[]
Isto ocorre por que, para que a funo seja genrica e opere em qualquer vetor passado, o parmetro no pode ser especificado em cdigo. Assim, a declarao de uma funo que recebe um
vetor como parmetro segue a seguinte receita:

12.2. FUNES COM VETORES COMO PARMETROS

95

tipo identificadorDaFuncao(tipo identificador1[], int tamanho1, ...)


{
Corpo da Funcao
}
Por exemplo, veja como definir uma funo que transforme todos os caracteres de uma string
para letras mausculas.
#include<string.h>
#include<iostream>

using namespace std;

void maiusculas(char str[], int tam)


{
for(int i = 0; i < tam && i < strlen(str); i++)
if(str[i] >= a && str[i] <= z)
str[i] = str[i] - a + A;
}

12

14

16

in
a

10

el
im

int main()
{
char str[50];
cout << Digite seu primeiro nome:;
cin >> str;

18

cout << str << endl;


return 0;

22

s
o

Pr

maiusculas(str, 50)
20

Ve
r

Observe que a funo altera a string passada como parmetro, um comportamento diferente
do que acontecei quando uma varivel que no um vetor passada. Este comportamento ser
estudado mais a fundo em captulos posteriores.
Da mesma forma que uma string, um vetor de outro tipo de dados pode ser passado como
parmetro. A funo a seguir, por exemplo, calcula qual o maior inteiro em um vetor de inteiros.
1

#include<iostream>

using namespace std;

int maior(int v[], int tam)


{
int maior = -1;
for(int i = 0; i < tam ; i++)
if(v[i] > maior)
maior = v[i];

11

return maior;
13

96

12.3

CAPTULO 12. STRINGS E FUNES

Exerccios

12.3.1

in
a

O cdigo de Csar uma das mais simples e conhecidas tcnicas de criptografia. um tipo
de substituio na qual cada letra do texto substituda por outra, que se apresenta no alfabeto
abaixo dela um nmero fixo de vezes. Por exemplo, com uma troca de trs posies, A seria
substitudo por D, B se tornaria E, e assim por diante. Implemente um programa que faa uso
desse Cdigo de Csar (3 posies),entre com uma string e retorne a string codificada.
String orig.: a ligeira raposa marrom saltou sobre o cachorro cansado
Nova string : D OLJHLUD UDSRVD PDUURP VDOWRX VREUH R FDFKRUUR FDQVDGR

12.3.2

el
im

Faa um programa que dado uma string, retorne 1 se ela for palndromo e 0 se ela no for
palndromo. Lembrando que:Um palndromo uma palavra que tenha a propriedade de poder ser
lida tanto da direita para a esquerda como da esquerda para a direita. Deve-se obrigatoriamente
utilizar uma string auxiliar e a funo strcmp para fazer a resoluo.
Ex: SUBI NO ONIBUS
ARARA
ANOTARAM A DATA DA MARATONA

12.3.3

12.3.4

Pr

Faa um programa em que troque todas as ocorrncias de uma letra L1 pela letra L2 em uma
string. A string e as letras L1 e L2 devem ser fornecidas pelo usurio.

s
o

Altere os programas anteriores para que contenham funes que resolvam os problemas propostos.

12.3.5

Ve
r

Faa um programa que leia 3 strings e as imprima em ordem alfabtica.

12.3.6

Faa um programa com uma funo que receba um vetor de inteiros e um inteiro X, e que retorne
como resultado o maior inteiro do vetor que menor que o inteiro X.

12.3.7

Usando a resposta do problema anterior, faa um programa com uma funo que receba dois
vetores de inteiros, e que faa com que o segundo torne-se uma cpia do primeiro, ordenado de
forma decrescente.

Captulo 13

Funes Matemticas

el
im

13.1

in
a

Funes teis I

A biblioteca math.h fornece algumas funes aritmticas muito teis no desenvolvimento de


programas. A Tabela 13.1 apresenta algumas destas funes.

s
o

Pr

Descrio/Exemplo
valor absoluto do argumento. Ex: int x = abs(-9);
seno do argumento (em radianos). Ex: double x = sin(3.14159);
cosseno do argumento (em radianos). Ex: double x = cos(3.14159);
tangente do argumento (em radianos). Ex: double x = tan(3.14159);
arco cujo seno passado como argumento. Ex: double x = asin(1);
arco cujo cosseno passado como argumento. Ex: double x = acos(1);
arco cuja tangente passada como argumento. Ex: double x = atan(sqrt(2)/2);
piso do valor passado como argumento. Ex: double x = floor(3.2); //=3
teto do valor passado como argumento. Ex: double x = floor(3.2); //=4
arredonda o argumento para o inteiro mais prximo. Ex: double x = round(9.9); //=10
eleva o primeiro argumento ao expoente no segundo. Ex: double x = pow(2,3); //=8
retorna a raiz quadrada do argumento. Ex: double x = sqrt(169); //=13
retorna logaritmo natural do argumento.
retorna log. do argumento na base 10.
retornar log do argumento na base 2

Ve
r

Funo
abs
sin
cos
tan
asin
acos
atan
floor
ceil
round
pow
sqrt
log
log10
log2

Tabela 13.1: Algumas funes aritmticas.

Alm das funes em math.h, duas outras funes, da biblioteca stdlib.h, so particularmente interessantes na manipulao de nmeros. Estas funes so apresentadas na Tabela 13.2.
A funo rand() utiliza para gerar nmeros aleatrios. Um nmero aleatrio gerado
internamente pelo computador aplicando-se operaes aritmticas que o usurio desconhece a
partir de um valor inicial chamado de semente. O valor dessa semente definido com a funo
srand(). O exemplo a seguir imprime na tela 30 nmeros aleatrios.

97

98

CAPTULO 13. FUNES TEIS I

Funo
rand
srand

Descrio/Exemplo
retorna um nmero aleatrio (biblioteca stdlib.h)
define a semente para a gerao de nmeros aleatrios por rand (biblioteca stdlib.h)

#include<stdlib.h>
#include<time.h>
. . .
int main()
{
for (int i = 0; i < 10; i++)
{
cout << rand() << endl;
}

10

el
im

for (int i = 0; i < 10; i++)


{
cout << rand() << endl;
}

in
a

Tabela 13.2: Funes para gerao de nmeros aleatrios.

12

14

18

20

22

24

Pr

//Configuracao da semente
//com valor que depende da hora atual.
//Isto garante maior aleatoriedade
srand(time(NULL));
for (int i = 0; i < 10; i++)
{
cout << rand() << endl;
}
return 0;

16

s
o

O codigo a seguir para um jogo de adivinhao. O programa gera um nmero aleatrio


entre 1 e 10, e o usurio deve descobrir qual este nmero1 .
/* rand example: guess the number */
#include <iostream>
#include <stdlib.h>
#include <time.h>

Ve
r

using namespace std;

int main ()
{
int iSecret, iGuess;

11

13

15

/* initialize random seed: */


srand ( time(NULL) );
/* generate secret number: */
iSecret = rand() % 10 + 1;
1 http://www.cplusplus.com/reference/clibrary/cstdlib/rand/

13.2. EXERCCIOS

99

17

do {
printf ("Guess the number (1 to 10): ");
cin >> iGuess;
if (iSecret<iGuess) puts ("The secret number is lower");
else if (iSecret>iGuess) puts ("The secret number is higher");
} while (iSecret!=iGuess);

19

21

23

puts ("Congratulations!");
return 0;

25

13.2

in
a

27

Exerccios

el
im

13.2.1

Faa um programa que leia os catetos de um tringulo e imprima o valor de sua hipotenusa.
Utiliza as funes aritmticas.

13.2.2

Ve
r

s
o

Pr

O valor de
pela srie:
Ppode ser dado
4
= n=0 (1)n 2n+1
Faa uma funo chamada pi que recebe o valor de n e retorna o valor calculado de acordo
com a funo informada. A funo principal deve ler o valor de n, invocar a funo pi e
imprimir o resultado.

CAPTULO 13. FUNES TEIS I

Ve
r

s
o

Pr

el
im

in
a

100

Captulo 14

in
a

Arranjos Multidimensionais (I)

14.1

Declarao e Iniciao

el
im

Embora os arranjos unidimensionais sejam teis em vrias situaes, eles no so suficientes


para resolver todos os problemas relacionados a arranjos. Em certas situaes, vrias dimenses
precisam ser representadas. Um exemplo simples o problema de mltiplicao de matrizes.1

Como j visto, a declarao de arranjos tem a seguinte sintaxe,

Pr

tipo identificador[tamanho];

A declarao de uma varivel do tipo matriz tem uma forma semelhante, apenas aumentando
uma segunda dimenso ao arranjo, como a seguir.

s
o

tipo identificador[tamanho1][tamanho2];
Assim, uma declarao como
1

int matriz[10][20];

Ve
r

declara uma matriz de 10 linhas por 10 colunas, cujas clulas so nmeros inteiros.
A matriz pode ser iniciada como em arranjos unidimensionais, colocando-se os valores do
elemento dentro de chaves aps a declarao da matriz. Os valores para cada linha devem ficar
dentro de chaves prprias e so separados por vrgula:

{int matriz[2][3] = {{1, 2, 3}, {4, 5, 6}};

A matriz criada pode ser visualizada da seguinte maneira:


1
4

2
5

3
6

1 A bem da verdade, possvel representar qualquer matriz finita como um arranjo unidimensional, mas
a complexidade muito maior em relao ao uso de arranjos multidimensionais.

101

102

CAPTULO 14. ARRANJOS MULTIDIMENSIONAIS (I)

14.1.1

Acesso aos elementos

O acesso s clulas feito tambm como em arrajos unidimensionais, exceto que ambas as coordenadas devem ser especificadas. O exemplo seguir mostra a criao, iniciao, e impresso
dos elementos de uma matriz bidimensional.
1

#include<iostream>

#define M 5
#define N 10

using namespace std;

in
a

int main()
{
int m[M][N];

11

cout << "Digite o valor dos elementos de uma matriz " << M << " por
" << N;
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
{
cout << i << "," << j;
cin >> m[i][j];
}

el
im

13

15

17

19

cout << "A matriz lida foi a seguinte "<< endl;


21

Pr

for(int i = 0; i < M; i++)


{
for(int j = 0; j < N; j++)
{
cout << m[i][j] << " ";
}

23

25

29

s
o

27

cout << endl;

Observe que tanto na leitura como impresso da matriz, o lao mais externo percorre as
linhas. Para cada valor da varivel i, a varivel j, dentro do lao interno percorre os valores de
0 a N. Desta maneira, a matriz lida e impressa linha a linha.
Observe a impresso. Para que serve o comando cout<<endl;?

Ve
r

31

14.2

Matrizes de Caracteres

Da mesma forma que vetores de caracteres podem ser manipuladas de forma especial no C(++),
tambm podem as matrizes de caractere. Na verdade, se um vetor de caracteres o que chama-se
de uma string, ento uma matriz bidimensional de caracteres , na verdade, um vetor de strings.
Por exemplo,
char nomes[10][20];

14.3. MAIS DIMENSES

103

pode ser visto como um vetor de 10 strings, cada uma com 20 caracteres, e cada string pode ser
manipulada como tal, como no exemplo a seguir.
1

#include<iostream>

#define M 10
#define N 11

using namespace std;


7

int main()
{
char m[M][N];

in
a

11

17

cout << "Digite " << M << " palavras de no maximo " << N-1 << "
caracteres" << endl;
for(int i = 0; i < M; i++)
{
cout << i << ": ";
cin >> m[i];
}

19

cout << "As palavras lidas foram as seguintes "<< endl;

21

for(int i = 0; i < M; i++)


{
cout << m[i] << " (com tamanho = " << strlen(m[i]) << ")" <<
endl;
}

13

23

14.3

s
o

25

Pr

el
im

15

Mais Dimenses

Ve
r

Agora voc j deve ter deduzido que para adicionar mais dimenses aos seus arranjos, basta
colocar esta dimenso na declarao dos mesmos. Por exemplo, o seguinte trecho de cdigo
declara um arranjo com trs dimenses, em que cada clula um inteiro.
char matriz[100][100][100];

Outra forma de ver tal arranjo como um livro com vrias pginas, em que cada uma
uma matriz bidimensional.

14.4

Multiplicao de Matrizes

Agora que voc viu alguns exemplos de declaraes de arranjos multidimensionais, vejamos
alguns usos reais, como a j mencionada multiplicao de matrizes.
Sejam duas matrizes A e B, tal
A tem dimenses m n e B, n o; ento, a matriz AB
Pque
m
tem dimenses m o, e Ci , j = k=1 Am,n Bn,o .

104

CAPTULO 14. ARRANJOS MULTIDIMENSIONAIS (I)

Observe que na matemtica os ndices comeam, normalmente, em 1. Na computao,


contudo, os arranjos tem seu menor ndice igual a zero. Logo, o cdigo para multiplicar as duas
matrizes fica assim.
1

int main()
{
int soma = 0, m, n, o;
int a[100][100], b[100][100], ab[100][100]; //m,n e 0 precisam ser
menores que 100.

for(int i = 0; i < m; i++)


for(int j = 0; j < n; j++)
cin >> a[i][j];

11

13

el
im

for(int j = 0; j < m; j++)


for(int k = 0; k < n; k++)
cin >> a[j][k];

in
a

//ler as dimensoes
cout << "Quais as dimensoes das matrizes?";
cin >> m >> n >> o;

15

17

19

for(int i = 0 ; i < m ; i++ )


{
for(int j = 0 ; j < o ; j++ )
{
for(int k = 0 ; k < n ; k++ )
{
sum = sum + a[i][k] * b[k][j];
}

21

Pr

23

25

27

29

ab[i][j] = sum;
sum = 0;

s
o

31

33

Ve
r

Observe que fizemos nosso cdigo de manipulao da matriz dentro da funo main. Fizemos isso por que usar matrizes como parmetro bem mais complicado do que vetores unidimensionais. Contudo, no se aflija, pois veremos isso logo a seguir.

14.5

Exercicios

14.5.1
Escreva uma programa que leia e some duas matrizes, e imprima o resultado.

14.5.2
Escreva um programa que leia uma matriz e diga se ela a matriz identidade ou no.

14.5. EXERCICIOS

105

14.5.3

Ve
r

s
o

Pr

el
im

in
a

Escreva um programa que leia uma matriz e imprima sua transposta.

CAPTULO 14. ARRANJOS MULTIDIMENSIONAIS (I)

Ve
r

s
o

Pr

el
im

in
a

106

Captulo 15

Introduo

el
im

15.1

in
a

Arranjos Multidimensionais (II)

Como voc j percebeu, arranjos multimensionais so muito divertidos. Neste captulo, veremos
alguns tpicos mais avanados em seu uso.

15.2

Passagem de matriz como parmetro em funes

Pr

Vimos que, ao passar vetores para uma funo, no era necessrio especificar o nmero de elementos no vetor. Em matrizes bidimensionais, no necessrio especificar o nmero de linhas
na matriz, apenas o nmero de colunas. O programa a seguir usa a funo exibeMatriz para
exibir o contedo de matrizes bidimensionais:
#include <iostream>
#define ncol 10

using namespace std;

void exibeMatriz(int matriz[][ncol], int linhas)


{
int i, j;
for (i = 0; i < linhas; i++)
{
for (j = 0; j < 10; j++)
{
cout << matriz[i][j] << \t;
}
cout << endl;
}
}

Ve
r

s
o

10

12

14

16

18

20

int main()
{
int a[1][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}};

22

24

int b[2][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},


{11, 12, 13, 14, 15, 16, 17, 18, 19,20}};

107

108

CAPTULO 15. ARRANJOS MULTIDIMENSIONAIS (II)

int c[3][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},


{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}};

26

28

exibeMatriz(a, 1);
exibeMatriz(b, 2);
exibeMatriz(c, 3);
return 0;

30

32

34

in
a

15.3

el
im

Via de regra, no necessrio especificar a primeira dimenso da matriz. Isto , em vetores,


voc no passava qualquer dimenso. Em matrizes bidimensionais, no precisa especificar a
quantidade de linhas. Em uma matriz tridimensional, no precisaria especificar a quantidade de
pginas, e assim por diante.
Lembre-se, semelhante ao que acontece com vetores, matrizes alteradas em funes auxiliares implicam em alterao na matriz original.

Matrizes Bidimensionais Como Unidimensionais e


Vice-Versa

#include <iostream>
#define ncol 10

s
o

Pr

Uma matriz bidimensional pode ser utilizada sem precisar acessar os elementos em suas posies
de linha ou coluna. Ela pode ser tratada como se tivesse uma nica dimenso. O programa a
seguir calcula a soma dos valores em uma matriz bidimensional, inicialmente utilizando as duas
dimenses e em seguida da mesma forma que com vetores.

using namespace std;


5

Ve
r

int somaMatrizBi(int matriz[][ncol], int linhas)


{
int soma = 0;
for (int i = 0; i < linhas; i++)
for (int j = 0; j < ncol; j++)
soma += matriz[i][j];

11

return soma;

13

15

17

19

21

int somaMatrizUni(int matriz[], int elementos)


{
int soma = 0;
int i;
for (i = 0; i < elementos; i++)
soma += matriz[i];
return soma;

23

}
25

15.3. MATRIZES BIDIMENSIONAIS COMO UNIDIMENSIONAIS E VICE-VERSA109

27

int main()
{
int a[10] =

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

29

int b[2][10]={{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},


{11, 12, 13, 14, 15, 16, 17, 18, 19,20}};

31

37

39

cout <<
<<
cout <<
<<

"Soma dos elementos da primeira matriz: "


somaMatrizUni(a, 10);
"Soma dos elementos da primeira matriz de novo: "
somaMatrizBi(a, 1);

cout <<
<<
cout <<
<<

"Soma dos elementos da segunda matriz: "


somaMatrizUni(b, 20);
"Soma dos elementos da segunda matriz de novo: "
somaMatrizBi(b, 2);

cout <<
<<
cout <<
<<

"Soma dos elementos da terceira matriz: "


somaMatrizUni(c, 30);
"Soma dos elementos da terceira matriz de novo: "
somaMatrizBi(c, 3);

in
a

35

45

47

49

el
im

41

43

51

return 0;
}

Pr

53

int c[3][10]={{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},


{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29,30}};

33

s
o

Observe que a funo somaMatrizUni recebe como argumento o total de elementos e percorre a matriz da mesma forma que um vetor. Isto pode ser feito porque na memria do computador a matriz armazenada como um vetor de nlinha ncolunas elementos. A funo
somaMatrizBi recebe o nmero de linhas e faz a mesma soma utilizando as duas dimenses.
Uma vez que a matriz multidimensional pode ser acessada como unidimensional, voc pode
criar funes que recebam uma matriz unidimensional e passar, como parmetro, todas as suas
dimenses. Internamente a esta funo, a matriz pode ser percorrida usando-se as dimenses e
um pouco de aritmtica bsica.

Ve
r

#include <iostream>
2

using namespace std;

10

int somaMatrizBiDisfarcadaDeUni(int matriz[], int linhas, int colunas)


{
int soma = 0;
for (int i = 0; i < linhas; i++)
for (int j = 0; j < colunas; j++)
soma += matriz[i * colunas + j];
return soma;

12

}
14

16

int main()
{
int a[10] =

{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

110

CAPTULO 15. ARRANJOS MULTIDIMENSIONAIS (II)

18

int b[2][8]={{1, 2, 3, 4, 5, 6, 7, 8},


{11, 12, 13, 14, 15, 16, 17, 18}};

20

int c[3][7]={{1, 2, 3, 4, 5, 6, 7},


{11, 12, 13, 14, 15, 16, 17},
{21, 22, 23, 24, 25, 26, 27}};

22

24

cout << "Soma dos elementos da primeira matriz: "


<< somaMatrizBiDisfarcadaDeUni(a, 1, 10);

26

in
a

cout << "Soma dos elementos da segunda matriz: "


<< somaMatrizBiDisfarcadaDeUni(b, 2, 8);

30

cout << "Soma dos elementos da terceira matriz: "


<< somaMatrizBiDisfarcadaDeUni(c, 3, 7);

32

34

return 0;
}

15.4

Exerccios

15.4.1

el
im

36

28

15.4.2

Pr

Escreva uma funo que receba como parmetro uma matriz bidimensional e suas dimenses, e
que incremente cada elemento da matriz em 10%.

Ve
r

s
o

Altere a funo do exerccio anterior para que receba como parmetro uma matriz tridimensional
e suas dimenses, e que incremente cada elemento da matriz em 10%.

Introduo

el
im

16.1

in
a

Ordenao de Arranjos

Captulo 16

Pr

Uma das aplicaes mais estudadas e realizadas sobre arranjos a ordenao. Ordenar um
arranjo significa permutar seus elementos de tal forma que eles fiquem em ordem crescente, ou
seja, v[0] <= v[1] <= v[2] <= . . . <= v[n 1]. Por exemplo, suponha o vetor
v = 5, 6, 9, 9, 0, 4.
Uma ordenao desse vetor resultaria em um rearranjo de seus elementos:
v = 9, 0, 4, 5, 6, 9.
Exitem diversos algoritmos de ordenao para vetores. Eles variam em relao dificuldade
de implementao e desempenho. Usualmente algoritmos mais fceis de serem implementados
apresentam desempenho inferior. Veremos 3 algoritmos diferentes de ordenao:
1. Algoritmo de Insero (Insertion Sort);

s
o

2. Algoritmo de Seleo (Selection Sort); e


3. Algoritmo de Ordenao por Troca (Bubble Sort).

Algoritmos de Ordenao

Ve
r

16.2
16.2.1

Algoritmo de Insero (Insertion Sort)

Trata-se de um dos algoritmos de implementao mais simples. Seu mtodo de ordenao semelhante ao que usamos para ordenar as cartas de um baralho. A idia bsica do algoritmo
descrita a seguir:
Compare a chave (x) com os elementos sua esquerda, deslocando para direita cada
elemento maior do que a chave;
Insira a chave na posio correta sua esquerda, onde os elementos j esto ordenados;
Repita os passos anteriores atualizando a chave para a prxima posio direita at o fim
do vetor.
A figura 16.1 apresenta um exemplo de uma etapa da execuo do algoritmo.
O cdigo a seguir implementa o algoritmo em C, considerando um vetor v de tamanho n.

111

112

CAPTULO 16. ORDENAO DE ARRANJOS

10

12

14

in
a

el
im

void insertionSort(int v[], int n)


{
int i, j, x;
for(i = 1; i < n; i++)
{
x = v[i];
j = i - 1;
while(j >= 0 && v[j] > x)
{
v[j+1] = v[j];
j--;
}
v[j+1] = x;
}
}

16.2.2

Pr

Figura 16.1: Exemplo do algoritmo Insertion Sort.

Algoritmo de Seleo (Selection Sort)

A implementao deste mtodo de ordenao muito simples. A idia bsica descrita a seguir:

s
o

Selecione o menor elemento do vetor de tamanho n;


Troque esse elemento com o elemento da primeira posio do vetor;
Repita as duas operaes anteriores considerando apenas os n-1 elementos restantes,
em seguida repita com os n-2 elementos restantes; e assim sucessivamente at que reste
apenas um elemento no vetor a ser considerado.

Ve
r

A figura 16.2 apresenta um exemplo da execuo do algoritmo.

Figura 16.2: Exemplo do algoritmo Selection Sort.

O cdigo a seguir implementa o algoritmo em C, considerando um vetor v de tamanho n.


1

void selectionSort(int v[], int n)


{
int i, j, aux, min;
for(i = 0; i < n-1; i++)
{

16.2. ALGORITMOS DE ORDENAO

113

min = i;
for(j = i+1; j < n; j++)
{
if(v[j] < v[min])
{
min = j;
}
}
aux = v[i]; v[i] = v[min]; v[min] = aux; //troca

11

13

15

Algoritmo de Ordenao por Troca (Bubble Sort)

el
im

16.2.3

in
a

Outro algoritmo simples, muito til para ordenao de vetores pequenos, mas no indicado para
vetores maiores devido ao seu baixo desempenho computacional. Sua dia bsica apresentada
a seguir:

Pr

Compare o primeiro elemento com o segundo. Se estiverem desordenados, ento efetue a


troca de posio. Compare o segundo elemento com o terceiro e efetue a troca de posio,
se necessrio;
Repita a operao anterior at que o penltimo elemento seja comparado com o ltimo.
Ao final desta repetio o elemento de maior valor estar em sua posio correta, a nsima posio do vetor;

s
o

Continue a ordenao posicionando o segundo maior elemento, o terceiro,..., at que todo


o vetor esteja ordenado.
A figura 16.3 apresenta um exemplo de um vetor sendo ordenado pelo algoritmo.
O cdigo a seguir implementa o algoritmo em C, considerando um vetor v de tamanho n.
void bubbleSort(int v[], int n)
{
int i, j, aux;
for(i = n-1; i > 0; i--)
{
for(j = 0; j < i; j++)
{
if(v[j] > v[j+1])
{
aux = v[j]; v[j] = v[j+1]; v[j+1] = aux; //troca
}
}
}
}

Ve
r

10

12

14

CAPTULO 16. ORDENAO DE ARRANJOS

el
im

in
a

114

Figura 16.3: Exemplo de ordenao usando o algoritmo Bubble Sort.

Exerccios

16.3.1

Pr

16.3

s
o

Implemente na linguagem C o algoritmo de ordenao insertion sort. Utilize funes auxiliares


para implementar a ordenao, a leitura do vetor desordenado e a impresso do vetor ordenado.

16.3.2

Ve
r

Implemente na linguagem C o algoritmo de ordenao selection sort. Utilize funes auxiliares


para implementar a ordenao, a leitura do vetor desordenado e a impresso do vetor ordenado.

16.3.3

Implemente na linguagem C o algoritmo de ordenao bubble sort. Utilize funes auxiliares


para implementar a ordenao, a leitura do vetor desordenado e a impresso do vetor ordenado.

r
in
a

el
im

Parte II

Ve
r

s
o

Pr

Intermedirio

115

s
o

Ve
r

in
a

el
im

Pr

Introduo

el
im

17.1

in
a

Estruturas No-Homogneas

Captulo 17

Declarao

Ve
r

17.2

s
o

Pr

Imagine que voc deseje armazenar informaes sobre um funcionrio de uma empresa. Entre
estas informaes podemos ter, por exemplo, nome, endereo, telefone, sexo, estado civil, cargo,
setor e salrio. Em um programa, isto seria representado por oito variveis apenas para um funcionrio. Se voc desejar incluir mais informaes, isto implicar em mais variveis, aumentando
a complexidade do programa.
Por esta razo, em muitas aplicaes, importante a capacidade de se tratar todas as informaes de uma entidade (uma pessoa, por exemplo), como sendo uma nica unidade de armazenamento, ou seja, uma nica varivel. Por outro lado, deve ser possvel, que esta nica varivel
permita acesso a cada informao em separado. Outros exemplos de informao com esta caracterstica o endereo, que pode ser decomposto em: logradouro, nmero, complemento, CEP,
cidade, estado, pas.
Neste tipo de informao possvel observar que, diferentemente de variveis indexadas
(vetores e matrizes), no h homogeneidade quanto ao tipo de dados tratado. Por isso, deve haver um mecanismo para trabalhar com variveis estruturadas heterogneas, tambm conhecidas
simplesmente como estruturas ou structs.

Na linguagem C, a palavra reservada struct destinada declarao de variveis no-homogneas,


e seu uso segue a seguinte sintaxe:
struct identificador{
tipo_campo_1 nome_campo_1;
...
tipo_campo_n nome_campo_n;
};
Em primeiro lugar, cada estrututura tem um identificador, usado na declarao de variveis
do tipo desta estrutura. Em seguida, so declarados os campos da estrutura, especificadas entre
as chaves. Os campos podem ter qualquer tipo, inclusive ser outra estrutura. O exemplo a seguir
declara uma estrutura para o armazenamento de endereos e vrias variveis deste tipo.

117

118

struct endereco {
char logradouro[15];
int numero;
char complemento[6], bairro[10];
char cidade[10], estado[3], pais[10];
};
...
struct endereco e1, e2, e3;

CAPTULO 17. ESTRUTURAS NO-HOMOGNEAS

17.2.1

in
a

O uso da palavra reservada struct obrigatrio na declarao de variveis, pois ela faz
parte do tipo da varivel. O uso repetido desta palavra reservada pode poluir o cdigo, e por
essa razo recomenda-se a definio de novos tipos baseados na estrutura.
typedef

el
im

A palavra chave typedef permite que se defina novos tipos de dados a partir de tipos j existentes. Por exemplo, possvel definir um tipo numero_real ou um tipo caractere. A sintaxe
para o uso typedef a seguinte:
typedef tipo_antigo tipo_novo;

Os exemplos apenas dados so implementados assim:


typedef float numero_real;
typedef char caractere;

Pr

struct end{
char logradouro[15];
int numero;
char complemento[6], bairro[10];
char cidade[10], estado[3], pais[10];
};
...
typedef end endereco;

Ve
r

s
o

Mais importante, possvel definir um tipo basedo na estrutura. Neste caso, h duas formas
de faz-lo. O exemplo a seguir mostra a mais verborrgica.

10

endereco e1, e2, e3;

Embora mais explcita, esta forma no usada normalmente, em funo forma mais compacta a seguir.

typedef struct{
char logradouro[15];
int numero;
char complemento[6], bairro[10];
char cidade[10], estado[3], pais[10];
} endereco;
...

17.3. ACESSO AOS CAMPOS DE UMA ESTRUTURA


8

119

endereco e1, e2, e3;

17.3

Acesso aos Campos de Uma Estrutura

10

12

14

17.4

el
im

//Atribuicao na iniciacao.

//Atribuicao...
//... campo a ...
//... campo.
//Copia de valores de todos os campos.

Pr

typedef struct st1 st1;


struct st1 {
char l;
int i;
float b;
};
...
st1 s1 = {c, -9, 4.76},
s1Copia, s2;
s2.l = z;
s2.i = -4;
s2.b = 0.89;
s1Copia = s1;
...

Exemplo

s
o

in
a

Embora as estruturas agreguem vrios campos, com raras excees, o manuseio da mesma deve
ser feito campo a campo, como variveis normais. Para acessar um dos campos de uma estrutura,
usa-se o operador . (ponto). Diferentemente de variveis indexadas, variveis do tipo estrutura
podem receber o valor de outra do mesmo tipo (desde que nenhum dos campos seja vetor). Por
exemplo:

Ve
r

Considere a estrutura complexo, a qual representa um nmero imaginrio na forma a + b i,


em que o valor de a armazenado na varivel real e o valor de b armazenado na varivel
imag. O exemplo a seguir apresenta uma matriz de 3 3 em que cada elemento do tipo
complexo.
#include <iostream>

using namespace std;

typedef struct{
float real, imag;
} complexo;

10

12

14

16

int main() {
int i, j;
complexo A[3][3] = {
{ {1.0, -0.1}, {2.0, -0.2}, {2.0, -0.2} }, //real
{ {4.0, -3.4}, {5.0, 4.1}, {6.0, -2.6} }
//imag
};
for ( i= 0; i < 3; i++) {
for (j = 0; j < 3; j++)

120

CAPTULO 17. ESTRUTURAS NO-HOMOGNEAS


cout << A[i][j].real << " + " A[i][j].imag << "*i" << \t;
cout << endl;

18

}
return 0;

20

Exerccios

17.5.1

in
a

17.5

Faa um programa que leia informaes sobre 15 pessoas. Essa informao deve ficar em um
vetor de variveis do tipo estruturado pessoa, o qual deve conter as seguintes informaes:
Nome: string de tamanho 30;
Idade: valor inteiro;

el
im

Sexo: tipo enumerativo com os valores masc, fem;

Estado Civil: tipo enumerativo com os valores solteiro, casado, separado, vivo.
Salrio: valor real.

Pr

Em seguida, imprima o nmero de homens, nmero de mulheres e informaes da pessoa com


maior salrio.

17.5.2

s
o

Faa um programa que leia o nome, duas notas e nmero de faltas de 10 alunos. As informaes
desses alunos devem ser armazenadas em um vetor de variveis do tipo estruturado aluno, o
qual deve conter as seguintes informaes de cada aluno:
Nome: string de tamanho 30;
Mdia: nmero real resultado da mdia das duas notas lidas;
Situao: caractere representando situao, isto , A (Aprovado), se mdia maior ou
igual a 6 e nmero de faltas menor que 10, e R (Reprovado), caso contrrio.

Ve
r

Faltas: nmero de faltas (valor inteiro).

Por fim, devem ser impressas as informaes de cada aluno.

17.6

Laboratrio

Primeiramente, implemente sua soluo para o exerccio anterior. Em seguida, implemente duas
funes, que ordenem os dados das pessoas por Nome e Idade, e imprimam todos os dados na
tela. Finalmente, demonstre o uso destas funes.

Captulo 18

in
a

Referncias

18.1

el
im

O uso da analogia da memria do computador com uma planilha eletrnica nos permitiu entender como variveis simples e tambm arranjos so alocados em nossos programas. Agora que
j conhecemos vetores, usaremos uma analogia mais precisa para entendermos referncias, ou
como so mais popularmente conhecidas, os famigerados ponteiros.

A memria um grande vetor

Ve
r

s
o

Pr

A memria de um computador pode ser vista como um grande vetor de bytes. O primeiro byte
denominado byte 0, o segundo, byte 1 e assim por diante at o tamanho da memria disponvel
ao seu programa.
Quando em seu programa voc, por exemplo, declara uma varivel do tipo caractere (char)
com o nome c, o compilador separa um byte da memria, digamos o byte 7542, e passa a chamlo de c. Assim, toda vez que se referir varivel c em seu programa, o computador sabe que
est se referindo ao byte 7542. Neste caso, dizemos que o endereo da varivel c 7542.
Similarmente, quando voc aloca uma varivel do tipo inteiro, o compilador reserva quatro
bytes para voc, digamos, os bytes 8012, 8013, 8014 e 8015. Tal varivel tem o endereo 8012
(como os tipos tem sempre tamanho fixo, o endereo do primeiro byte mais a informao sobre
o tipo da varivel suficiente para o computador determinar de onde at onde na memria cada
varivel fica armazenada).
Finalmente, quando voc aloca um vetor de tamanho n de algum tipo qualquer, o compilador
reserva um espao de tamanho n t, onde t o tamanho do tipo em questo. Se so 10 inteiros,
por exemplo, ento o vetor ter tamanho 40 bytes. O endereo desta varivel o endereo do
primeiro byte da primeira clula. Assim, quando voc, por exemplo, acessa a posio 5 de um
vetor de inteiros cujo endereo 1000, o computador faz o seguinte clculo para determinar a
posio de memria que voc est acessando, sabendo que cada inteiro ocupa 4 bytes: 1000 +
5 4.

18.2

Variveis do Tipo Referncia

Em certas situaes, o poder de se referir a posies de memria pelo seus endereos em vez de
por um nome de varivel muito til. Por exemplo, imagine que precisemos calcular uma srie
de estatsticas sobre os dados em um vetor. Neste caso, gostaramos de definir uma funo que

121

122

CAPTULO 18. REFERNCIAS

*identificador;

in
a

tipo

analisasse o vetor e desse como resultados as vrias estatsticas, como mdia, desvio padro, varincia, intervalo de confiana etc. Entretanto, como bem sabemos, funes em C(++) retornam
um nico resultado. Se, contudo, pudssemos passar como parmetro para a funo as referncias de onde gostaramos que os resultados fossem colocados, ento a funo poderia coloc-los
diretamente nestas posies de memria. Esse mecanismo o que chamamos de passagem de
parmetro por referncia.
Antes de se poder exercitar a passagem de parmetros por referncia, contudo, precisamos
aprender a declar-las, a obter referncias para posies de memria, e a usar tais referncias.
Estas operaes so feitas pelos operadores * e &. A declarao de variveis segue a seguinte
sintaxe:

Assim, para se declarar variveis de referncia para uma posies de memria que armazenam um inteiro, um caractere, e um float, voc usaria as seguintes declaraes:
int *ref_int;
char *ref_char;
float *zabumba;

el
im

Observe que o * sempre considerado como ligado ao identificador e no ao tipo da varivel.


Assim, a linha de cdigo

Pr

int *a, b, *c;

s
o

declara duas referncias para inteiro (a e c), e um inteiro (b). Para se evitar confuses, sugere-se
que no se declare variveis do tipo referncia e no referncia em conjunto. Ou seja, a cdigo
acima deveria ser reescrito como
int *a, *c;
int b;

Ve
r

O operador & permite que se extraia o endereo (ou uma referncia) de uma varivel. No
cdigo,

int *a;
int b;

a = &b;

a recebe o endereo da varivel b. Logo, se b est nos bytes 2012, 2013, 2014 e 2015, a varivel

a recebe o valor 2012.


Aqui, gostaramos de chamar a ateno para o seguinte fato: em rarssimas situaes
necessrio saber o endereo de uma varivel. Na maior parte dos casos, basta saber que uma
varivel tem tal endereo..
Finalmente, o operador * tambm nos permite acessar o contedo de uma varivel referenciada, em do valor da referncia. No cdigo,

18.3. PASSAGEM DE REFERNCIAS COMO PARMETROS

123

int *a;
int b;
int c;

a = &b;
*a = 20;
c = *a;
c++;

Passagem de Referncias como Parmetros

el
im

18.3

in
a

a varivel b termina com o valor 20, enquanto que a varivel c termina com o valor 21.

Variveis do tipo referncia, como outros tipos de variveis, podem ser passadas como parmetro
em chamadas de funo. A grande vantagem desta tcnica, tambm conhecida como passagem
de parmetros por referncia, a possibilidade de modificao da memria para qual a referncia
foi passada. Por exemplo, analise o seguinte cdigo.
#include<iostream>
#include<cmath>

using namespace std;

void sen_cos_tan(float val, float *seno, float *cosseno, float *


tangente)
{
*seno = sin(val);
*cosseno = cos(val);
*tangente = tan(val);
}

10

s
o

12

14

Pr

int main()
{
float v = 0, s, c, t;

Ve
r

16

sen_cos_tan(v, &s, &c, &t);

18

cout << "seno: " << s << " cosseno: " << c << " tangente: "<< t;

20

return 0;

22

Esse programa calcula em uma nica chamada, os valores do seno, cosseno e tangente da
varivel v. Enquanto o feito no parece muito impressionante, pense no caso em que voc precisa
calcular diversas estatsticas de um vetor de nmeros. Neste caso, devido forte dependncia do
clculo de uma estatstica no clculo de outras, esta funo poderia simplificar em muito o seu
cdigo.

124

18.4

CAPTULO 18. REFERNCIAS

Laboratrio

18.4.1
Escreva um programa que contenha funes que calculam a mdia, varincia e desvio padro de
um vetor de nmeros reais (uma funo por dado estatstico).

18.4.2

Ve
r

s
o

Pr

el
im

in
a

Altere o programa do exerccio anterior para que calcule as trs estatsticas em uma funo
apenas, reaproveitado os clculos uns dos outros.

Captulo 19

in
a

Referncias II

19.1

Ponteiros para Structs

el
im

Continuando com o estudo de ponteiros, vamos ver como utiliz-los para referenciar estruturas
e arranjos.

typedef struct
{
int i;
char c;
float j;
} exemplo1;

s
o

Pr

Se voc recordar-se da anologia apresentada na seo 18.1, em que a memria comparada a


um grande vetor e cada tipo de dados tem um tamanho pr-definido, fcil entender como uma
estrutura representada na memria.
Considere a seguinte estrutura e responda: qual o tamanho desta estrutura na memria do
computador?

Ve
r

Para responder a esta pergunta precisamos entender que uma estrutura ocupa espao equivalente soma do espao ocupado por cada um de seus campos. Desta forma, o espao total
ocupado por uma varivel do tipo exemplo1 ser a soma dos tamanhos de 1 int, 1 char e 1
float, ou seja, 4 + 1 + 4 = 9 bytes.
Assim, e voc cria uma varivel exemplo1 v[10], o compilador deve reservar um espao
de 10 9 = 90 bytes.
Assim como nos referimos a variveis dos tipos primitivos (inteiro, real, caractere) utilizando
ponteiros, podemos tambm utilizar ponteiros para acessar uma varivel do tipo struct e seus
campos. Veja o exemplo para a estrutura declarada anteriormente.

exemplo1 a = {-5, z, 0.89}, b;


exemplo1 *p;
p = &a;
cout << (*p).i << endl;
p = &b;
cin >> (*p).c;

125

126

CAPTULO 19. REFERNCIAS II

exemplo1 a = {-5, z, 0.89}, b;


exemplo1 *p;
p = &a;
cout << p->i << endl;
p = &b;
cin >> p->c;

el
im

in
a

Este trecho mostra na linha 1 a criao de duas variveis do tipo exemplo1 e na linha 2 a
criao de uma varivel do tipo ponteiro para exemplo1. As linhas 3 e 5 atualizando o ponteiro,
fazendo com que referencie as variveis a e b, respectivamente. Desta maneira, a linha 4 ir
imprimir o valor de a.i, enquanto a linha 6 ir ler a partir do teclado um valor para b.c.
Quando usamos ponteiros e estruturas, aparece o incoveniente de termos que digitar toda vez
entre parnteses a varivel do tipo ponteiro ((*p).c). Para simplificar a utilizao de ponteiros
no acesso a campos de uma estrutura, a linguagem C permite escrever esta mesma instruo de
uma maneira mais fcil de digitar: p->c. O cdigo anterior pode ser reescrito como:

Por fim, a passagem de estruturas por referncia em funes auxiliares feita da mesma
forma que vimos no captulo anterior:

10

12

14

16

int main()
{
exemplo1 a = {1, a, 1.0}, b = {2, b, 2.0};
inverte_structs(&a, &b);
cout << a.i << ", " << a.c << "," << a.j << endl;
cout << b.i << ", " << b.c << "," << b.j << endl;
return 0;
}

Ve
r

18

Pr

void inverte_structs(exemplo1 *s1, exemplo2 *s2) {


exemplo1 aux
aux.i = s2->i;
s2->i = s1->i;
s1->i = aux.i;
aux.c = s2->c;
s2->c = s1->c;
s1->c = aux.c;
aux.j = s2->j;
s2->j = s1->j;
s1->j = aux.j;
}

s
o

20

A funo auxiliar troca os valores de duas variveis do tipo exemplo1 passadas por referncia. Aps a invocao da funo auxiliar a partir da main os valores iniciais das variveis a e b
sero trocados.

19.2

Arranjos e Ponteiros

At agora vimos vetores sem nenhuma relao com ponteiros. No fundo, quando criamos um
vetor com a instruo int a[10], estamos dizendo ao compilador para reservar na memria

19.2. ARRANJOS E PONTEIROS

127

espao para 10 inteiros (40 bytes) e armazenar o endereo em que comea o vetor na varivel a.
Em outras palavras, a varivel a um ponteiro para o primeiro elemento do vetor.
Por esta razo, a relao entre vetores e ponteiros mais direta e mais fcil de utilizar. Uma
vez que a varivel que usamos contm o endereo do comeo do vetor, um ponteiro pode receber
diretamente seu valor, sem necessidade do operador &. Considere o exemplo a seguir:

float a[10];
float *p;
p = a;
cout << "Digite 10 numeros reais: ";
for(int i = 0; i < 10; i++)
cin >> a[i];
cout << "Num. digitados: ";
for(int i = 0; i < 10; i++)
cout << p[i];

in
a

Percorrendo vetores com ponteiros

Pr

19.2.1

el
im

Observe a linha 3 e perceba como a atualizao da referncia do ponteiro p para o vetor a


no utilizou o &. Isto porque a tambm um ponteiro. A diferena entre p e a que a primeira
pode ter sua referncia atualizada, enquanto a segunda no. A partir da linha 3, o vetor pode ser
acessado tanto pela varivel a (linha 6) quanto pela varivel p (linha 9).
por este motivo que vetores sempre so passados por referncia em funes auxiliares,
sem a necessidade do & e do *.

J sabemos a relao entre ponteiros e vetores. Veremos a seguir algumas maneiras diferentes
de acessar os elementos de um vetor utilizando ponteiros. Considere o trecho de um programa a
seguir:

Ve
r

char str[100];
char *s;
int totalletras = 0;
s = str;
cout << "entre uma frase com letras minusculas" << endl;
cin.getline(s,100);
for(int i = 0; i < strlen(s); i++)
{
if(s[i] >= a && s[i] <= z)
{
totalletras++;
}
}
cout << "O total de letras da frase eh " << totalletras;

s
o

10

12

14

Neste trecho utilizamos o ponteiro s como o vetor str, pois a partir da linha 3 ele aponta
para o vetor. Este mesmo trecho pode ser reescrito:
2

char str[100];
char *s;
int totalletras = 0;
s = str;
cout << "entre uma frase com letras minusculas" << endl;

128
6

10

12

cin.getline(s,100);
for(int i = 0; i < strlen(s); i++)
{
if( *(s+i) >= a && *(s+i) <= z )
{
totalletras++;
}
}
cout << "O total de letras da frase eh " << totalletras;

14

CAPTULO 19. REFERNCIAS II

in
a

Observe a linha 9 de cada um dos dois trechos anteriores e veja a diferena na notao.
Quando utilizamos ponteiro, podemos acessar um vetor pelo ndice (colchetes) ou por um deslocamento sobre o valor do endereo inicial do vetor armazenado em s, ou seja, a notao *(s+i),
significa o caractere localizado i caracteres a partir do caractere na primeira posio do vetor.
O mesmo trecho pode ser reescrito ainda de uma terceira forma:

10

12

s
o

14

el
im

char str[100];
char *s;
int totalletras = 0;
s = str;
cout << "entre uma frase com letras minusculas" << endl;
cin.getline(s,100);
for(int i = 0; i < strlen(str); i++) //Observe que aqui usamos str e
nao s. Por que?
{
if( *s >= a && *s <= z )
{
totalletras++;
}
s++;
}
cout << "O total de letras da frase eh " << totalletras;

Pr

Qual a diferena entre esta verso e as verses anteriores? Qual a diferena entre s++ e

Ve
r

(*s)++? Qual o valor de s[0] em cada verso? E de *s? E de str[0]?

19.3

Laboratrio

19.3.1

Crie uma estrutura com os campos nome, idade e salario dos tipos string, inteiro e real, respectivamente.
Em seguida, crie uma funo que receba referncias para duas variveis de tal tipo e uma
varivel correspondente a uma porcentagem de aumento que deve ser aplicada sobre o campo
salrio de cada estrutura. A funo principal deve ler cada campo das duas variveis e imprimir
o novo salrio.
Finalmente, crie uma funo que recebe duas variveis de tal tipo e que troque os valores de
todos os campos das duas estruturas. A funo principal deve agora imprimir as estruturas antes
e depois da troca.

19.3. LABORATRIO

129

19.3.2

Ve
r

s
o

Pr

el
im

in
a

Execute as trs verses do programa da seo 19.2.1 e veja se h diferena no resultado. Responda s perguntas no final da seo.

CAPTULO 19. REFERNCIAS II

Ve
r

s
o

Pr

el
im

in
a

130

in
a

Alocao Dinmica

Captulo 20

Alocao Dinmica de Tipos Simples

Pr

20.1

el
im

Por mais interessante que seja poder criar ponteiros para variveis j existentes e passar parmetros por referncia, o poder dos ponteiros s fica mesmo evidente quando se trabalha com
alocao dinmica de memria.
Alocao dinmica a habilidade de se criar novas variveis durante a execuo do programa, sem que elas tenham sido declaradas antes. Justamente por no terem sido declaradas
antes da compilao, estas variveis alocadas dinamicamente no tm nomes e, assim, s podem
ser acessadas por meio de referncias.

char *s1;
int *i1;
float *f1;

Ve
r

s
o

Existem vrias formas de se alocar memria dinamicamente, todas elas via funes que retornam
como resultado uma referncia para o comeo da memria alocada, na forma de uma referncia
genrica.
A funo mais simples para alocao de memria a malloc. Esta funo recebe como
nico parmetro o tamanho da memria a ser alocada, em bytes. Observe o seguinte cdigo para
alguns exemplos.

s1 = (char *) malloc(1);
i1 = (int *) malloc(4);
f1 = (float *) malloc(4);

No exemplo acima voc percebe que antes de cada malloc h, entre parnteses, o tipo da
varivel que guardar a referncia. Isso o que chamamos de casting, e serve para transformar
a referncia genrica retornada pela funo para o tipo de referncia da varivel. Este casting
obrigatrio em seu cdigo.
Voc tambm percebe que cada alocao especifica exatamente o tamanho do tipo para o
qual estamos alocando a memria. Isto , 1 para caracteres e 4 para inteiros e nmeros reais.
Estes tamanhos, contudo, podem variar de uma mquina/sistema operacional para outra, o que
tornaria complicado especificar tais tamanhos em cada invocao malloc. por isso que a

131

132

CAPTULO 20. ALOCAO DINMICA

linguagem C(++) especifica o construto sizeof, que descobre o tamanho do tipo para voc,
conforme o seguinte exemplo.

s1
i1
f1
d1

=
=
=
=

(char *) malloc(sizeof(char));
(int *) malloc(sizeof(int));
(float *) malloc(sizeof(float));
(double *) malloc(sizeof(double));

20.2

char *s1;
int *i1;
float *f1;
double *d1;

in
a

Alocao Dinmica de Vetores

el
im

Como visto nos captulos anteriores, a diferena entre referncias para tipos simples e vetores
... nenhuma! Isso quer dizer que podemos alocar vetores usando um cdigo similar ao anterior,
alterando apenas a quantidade de memria alocada, como no seguinte exemplo.
char *s2;
int *i2;
float *f2;
double *d2;

11

13

15

17

(char *) malloc(sizeof(char) * 100);


(int *) malloc(sizeof(int) * 10);
(float *) malloc(sizeof(float) * 6);
(double *) malloc(sizeof(double) * 8);

cin.getline(s2,100);
cout << s2;

for(int i = 0; i < 10; i++)


cin >> i2[i];
for(int i = 0; i < 10; i++)
cout << i2[i] << endl;

Ve
r

19

=
=
=
=

Pr

s2
i2
f2
d2

s
o

21

for(int i = 0; i < 6; i++)


cin >> f2[i];

23

25

for(int i = 0; i < 6; i++)


cout << f2[i] << endl;

27

29

31

for(int i = 0; i < 8; i++)


cin >> d2[i];
for(int i = 0; i < 8; i++)
cout << d2[i] << endl;

20.3. LIBERAO DE MEMRIA

20.3

133

Liberao de memria

Todos os exemplos mostrados at agora neste captulo so incompletos. Isso por qu nenhum
programa que faa alocao dinmica em C(++) pode ser completo sem que se faa a liberao
da memria alocada. Liberar ou desalocar a memria consiste simplesmente na invocao da
funo free, passando-se como parmetro a referncia a ser desalocada. O uso de free ser
exemplificado na prxima seo.

Alocao Dinmica de Estruturas

in
a

20.4

10

12

14

#define NUM_PESSOAS 10
typedef struct
{
char prim_nome[20],
char ult_nome[20],
int idade,
float salario,
char regiao,
char sexo
} pessoa_t;
int main()
{
pessoa_t *pessoas;

Pr

el
im

Assim como declarar uma referncia para uma estrutura to simples quanto declarar uma referncia para um tipo primitivo(simples), alocar um vetor de estruturas dinamicamente to
simples quanto alocar um vetor de tipos primitivos dinamicamente. O exemplo a seguir mostra
exatamente como alocar um vetor com 10 estruturas do tipo definido.

pessoas = (pessoa_t *) malloc(sizeof(pessoa) * NUM_PESSOAS);

18

for(int
{
cin
cin
cin
cin
cin
cin
}

20

i = 0; i < NUM_PESSOAS; i++)


>>
>>
>>
>>
>>
>>

pessoas[i].prim_nome;
pessoas[i].ult_nome;
pessoas[i].idade;
pessoas[i].salario;
pessoas[i].sexo;
pessoas[i].regiao;

Ve
r

22

s
o

16

24

26

//Uso dos dados


...

28

30

//Liberacao da memoria
free(pessoas);

32

return 0;

34

134

20.5

CAPTULO 20. ALOCAO DINMICA

Exerccios

20.5.1
Escreva um programa que leia um numero inteiro N, aloque dinamicamente um vetor de N
inteiros, leia cada um dos N inteiros, e imprima os N inteiros na tela.

20.5.2

Laboratrio

20.6.1
Implemente os exerccios acima.

20.6.2

el
im

20.6

in
a

Escreva um programa que repita o seguinte procedimento X vezes: leia um numero inteiro N,
aloque dinamicamente um vetor de N carateres, leia uma palavra de N caracteres, transforme
todas as maisculas em minsculas e vice-versa na palara e imprima o resultado na tela. X deve
ser lido no incio da execuo do programa.

Ve
r

s
o

Pr

Escreva um programa que aloque um vetor de 100000 float e imprima os 10 primeiros e os 10


ltimos (o lixo que estiver na memria). 1

1 Se tudo funcionar, aumente o vetor para 1000000 e assim por diante. O objetivo neste laboratrio
mostrar que a quantidade de memria disponvel para seu programa limitada, e que se extrapolada, seu
programa incorrer em um erro.

Captulo 21

el
im

in
a

Arquivos

Pr

Muitas vezes desejamos guardar o resultado de alguma computao para consulta posterior.
Imagine, por exemplo, que voc fez um programa que calcula a mdia final e situao de toda
a turma. Se o resultado deste processamento no puder ser armazenado, toda vez que for necessrio consultar a situao de algum aluno, o programa dever ser executado e todos os dados
inseridos novamente. Para solucionar este problema, o usurio pode salvar resultados de computao em uma estrutura persistente. Esta estrutura de dados manipulada fora do ambiente do
programa (memria principal) conhecida como arquivo.
Um arquivo armazenado em um dispositivo de memria secundria (CD, DVD, disco
rgido, pendrive) e pode ser lido ou escrito por um programa. Em C, um arquivo pode representar
diversas coisas, como documentos, uma impressora, um teclado, ou qualquer dispositivo de
entrada ou sada. Consideraremos apenas dados em disco, iniciando por dados na forma textual.

Arquivos de texto

s
o

21.1

Ve
r

Nesta seo estudaremos apenas arquivos texto, ou seja, arquivos que contm apenas caracteres
e podem ser visualizados em editores de textos como Notepad, Gedit, Vim, etc.
A linguagem C++ d suporte utilizao de arquivos por meio da biblioteca fstream. Esta
biblioteca fornece vrias funes para manipulao de arquivos e define alguns tipos de dados
para serem usados especificamente com arquivos. O principal tipo definido nessa biblioteca que
ser usado o tipo fstream. Um varivel do tipo fstream capaz de identificar um arquivo no
disco, direcionando-lhe todas as operaes. Essas variveis so declaradas da seguinte maneira:
fstream arq;

21.1.1

Abertura e Fechamendo de Arquivos

Antes que o arquivo seja manipulado, preciso abr-lo, o que feito via funo open do
arquivo. Uma vez aberto, o arquivo funciona como o cin e cout, com os quais voc j est
acostumado a usar << e >>, como no exemplo a seguir. Ao terminar o uso do arquivo, importante fech-lo, para garantir que tudo que, em teoria, est escrito no arquivo, realmente foi
colocado no disco.
2

#include <iostream>
#include <fstream>

135

Mover para 4 ou 5 captulo. Alunos vem mais


exemplos prticos de aplicabilidade

136

CAPTULO 21. ARQUIVOS

using namespace std;


4

10

int main () {
fstream arquivo;
arquivo.open ("arquivo.txt");
arquivo << "O que eu deveria escrever neste arquivo?" << endl;
arquivo.close();
return 0;
}

#include <iostream>
#include <fstream>
using namespace std;

el
im

in
a

Nem sempre possvel abrir o arquivo como no exemplo, o que ser explicado adiante. Para
testar se o arquivo foi aberto ou no, use a funo is_open(). importante que voc teste se o
arquivo realmente est aberto, antes de tentar us-lo.

int main () {
fstream arquivo;
arquivo.open("arquivo.txt");

if(arquivo.is_open())
{
arquivo << "O que eu deveria escrever neste arquivo?" << endl;
arquivo.close();
cout << "tudo escrito";
}
else
cout << "falhou";

10

Pr

12

14

16

return 0;

18

s
o

Ve
r

Se voc tentou executar o cdigo acima, percebeu que a mensagem "falhou"foi escrita na
tela. O problema que o cdigo abre um arquivo e escreve no mesmo, mas somente se ele j
existir, o que no o caso. Por enquanto, v at a pasta onde est o seu projeto e crie o arquivo
manualmente. Na seo seguinte veremos como criar um arquivo de dentro do programa. J
no cdigo a seguir, veja como os dados do arquivo podem ser lidos.

11

13

#include <iostream>
#include <fstream>
using namespace std;
int main () {
fstream arquivo;
arquivo.open ("arquivo.txt");
if(arquivo.is_open())
{
cout << "yeah";
arquivo << "Sera que isso foi escrito?" << endl;
arquivo.close();

21.1. ARQUIVOS DE TEXTO

137

arquivo.open ("arquivo.txt");
char str[1000];
arquivo.getline(str,1000);
arquivo.close();

15

17

19

23

cout << str;


}
else
cout << "O arquivo nao foi aberto";

21

return 0;

25

Criao de Arquivos

el
im

21.1.2

in
a

Para abrir um arquivo que no existe, ou seja, criar o arquivo, necessrio passar um conjunto
especial de instrues para a funo de abertura. Infelizmente, o nico jeito de passar estas
instrues bem mais complicado do que o que vimos at agora. Veja o seguinte cdigo, em
especial a linha que abre o arquivo.
2

#include <iostream>
#include <fstream>
using namespace std;

Pr

int main () {
fstream arquivo;
arquivo.open ("arquivo.txt", ios::out | ios::in | ios::trunc);

if(arquivo.is_open())
cout << "yeah";
else
cout << "nope";

s
o

10

12

arquivo << "O que eu deveria escrever neste arquivo?" << endl;
arquivo.close();

14

16

22

cout << str;

Ve
r
20

arquivo.open ("arquivo.txt");
char str[1000];
arquivo.getline(str,1000);
arquivo.close();

18

return 0;

24

Na frente do parmetro com o nome do arquivo, na funo open, foram passadas trs opes
para o modo de abertura do arquivo, que especifica o tipo de operaes que se intende fazer no
arquivo (o caractere | combina as opes passadas). Algumas das opes possveis so:
ios::in Operaes de escrita.

138

CAPTULO 21. ARQUIVOS


ios::out Operaes de leitura.
ios::app Posiciona no fim do arquivo. No pode ser reposicionado. No pode ser usado
com ios::in.
ios::trunc Posiciona no incio do arquivo. Se o arquivo j existe, ento seu contedo
anterior perdido.

21.1.3

in
a

As opes para leitura e escrita do arquivo, e somente estas, so implcitas, quando nenhuma
opo especificada. Se voc quiser, pode usar apenas uma destas por questes de segurana (o
arquivo pode ser lido mas no escrito, ou o arquivo pode ser aumentado mas no lido). Usando
somente as opes de leitura e escrita, contudo, o arquivo no criado caso no exista. Para que
seja criado, necessrio que se especifique ou ios::trunc ou ios::app, que faro com que o
arquivo seja ou truncado ou que toda modificao seja adicionada ao fim do arquivo (append).

Cuidados com a Formatao dos Dados

#include <iostream>
#include <fstream>
using namespace std;

Pr

10

12

if(arquivo.is_open())
{
cout << "O arquivo foi aberto!";
arquivo << "Escrevendo um numero pequeno:" << endl;
arquivo << 10 <<endl;
arquivo << "Numero pequeno escrito." << endl;

Ve
r

14

int main () {
fstream arquivo;
arquivo.open ("arquivo.txt", ios::out | ios::in | ios::trunc);
char str[1000];

s
o

el
im

Quando se escreve um dado em um arquivo de texto, precisa-se entender que o dado ocupa
somente o espao que voc especificar. Isto , se voc escrever a sequncia de caracteres C(++)
bom!!!, 14 caracteres sero escritos, e pronto. Se escrever algo na linha seguinte depois
resolver mudar a string acima para C(++) no bom!!!, ento a diviso entre as linhas (o endl
) ter sido sobrescrito e as duas linhas se tornaro uma. Estes cuidados no precisam ser tomados
agora, com os exemplos simples com os quais estamos lidando, mas nos prximos capitulos voc
ter que tom-los. Assim, melhor que voc j saiba sobre estes problemas desde agora.

16

18

cout << "Fechando o arquivo.";


arquivo.close();

20

cout << "Reabrindo o arquivo.";

22

arquivo.open ("arquivo.txt");

24

arquivo << "Escrevendo um numero pequeno:" << endl;


arquivo << 10000 <<endl;

26

28

30

cout << "Fechando o arquivo.";


arquivo.close();
cout << "Reabrindo o arquivo.";
arquivo.open ("arquivo.txt");

21.2. LABORATRIO

139

32

arquivo.getline(str,1000);
cout << str;
arquivo.getline(str,1000);
cout << str;
arquivo.getline(str,1000);
cout << str;

34

36

38

arquivo.close();

40

42

in
a

else
cout << "nope";

44

return 0;

46

21.2

el
im

Laboratrio

21.2.1

Pr

Faa um programa que leia o nome e sobrenome de 30 alunos e armazene em um arquivo, de


tal forma que o arquivo tenha um aluno por linha. Abra o arquivo usando um editor de textos
qualuer, como o Notepad.

21.2.2

Ve
r

s
o

Faa um programa que tente abrir um arquivo e, caso no consiga, tente cri-lo e abr-lo. Com
arquivo aberto, leia um vetor A de inteiros de tamanho 20 e guarde seus valores em um arquivo,
um por linha. Em seguida, reabra o arquivo e leia os elementos para o vetor B, verificando se os
valores foram gravados corretamente.

CAPTULO 21. ARQUIVOS

Ve
r

s
o

Pr

el
im

in
a

140

in
a

Navegao dentro do arquivo

Captulo 22

el
im

Embora seja possivel trabalhar com arquivos usando apenas as ferramentas apresentadas at
agora, alguns problemas so de difcil resoluo, a no ser que extendamos nosso conhecimento.
Suponha por exemplo que voc tenha o seguinte arquivo

Pr

O rato roeu a roupa do


rei de Roma e a rainha
Ruinha resolveu rir-se
pois o rei que remente
suas rodas roupagens.

22.1

s
o

Observe que todas as linhas tem o mesmo tamanho (22 caracteres) e que a palavra remende
est escrita de forma incorreta. Para corrigir esta palavra, podemos reescrever toda a frase, ou
posicionar o cursor do arquivo examante sobre o caractere errado e corrig-lo. A vrias formas
de se fazer isso, como veremos agora.

Posicionmento no arquivo

Ve
r

Como visto no captulo anterior, operaes de leitura e escrita no arquivo vo mudando a posio
em que as prximas operaes sero executadas. Isto , se considerarmos que h um cursor
dentro do arquivo, na posio em escreveremos, caso uma escrita seja feita, ou leremos, caso
uma leitura seja executada, ento se lermos ou escrevermos 3 caracteres, ento o cursor andar
3 caracteres. Se quisermos colocar o cursor no fim do arquivo, podemos reabr-lo usando ios
::app. Caso queiramos colocar o cursor no comeo do arquivo, podemos podemos reabr-lo
simplesmente reabr-lo sem especificar qualquer opo ou usando ios::trunc (e com isso
tambm zerarmos nosso arquivo).
Caso precisemos posicionar o cursor no meio do arquivo, podemos usar a funo seekg,
que pode ser usada duas formas:
seekg(nova posio [em bytes])
seekg(diferena [em bytes] em relao ao marco, marco)
Na primeira forma voc pode especificar onde o cursor deve ser posicionado em relao ao
incio do arquivo, em nmero de bytes. Por exemplo, arq.seekg(10) posiciona o cursor no

141

142

CAPTULO 22. NAVEGAO DENTRO DO ARQUIVO

dcimo byte do arquivo arq. J pela segunda forma, voc especifica onde posicionar o cursor em
relao a um marco no arquivo, que pode ser seu incio (ios_base::beg), fim (ios_base::
end), ou posio atual (ios_base::cur). A diferena em relao ao marco especificada como
um inteiro com sinal. Por exemplo, arq.seekg(-10,ios_base::end) posiciona o cursor no
dcimo caractere antes do fim do arquivo arq.
Para resolver o problema apresentado acima, podemos ento usar as seguintes solues.
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
fstream arq;
arq.open("arquivo.txt"); //Posicionando o cursor no inicio.
arq.seekg(23*3+20);
arq << d;
arq.close();

12

in
a

10

el
im

14

arq.open("arquivo.txt"); //Buscando a partir do fim.


arq.seekg(-23-3, ios_base::end);
arq << d;
arq.close();

16

18

arq.open("arquivo.txt", ios::out |
arquivo.
arq << "O rato roeu a roupa do" <<
<< "rei de Roma e a rainha" <<
<< "Ruinha resolveu rir-se" <<
<< "pois o rei que remende" <<
<< "suas roidas roupagens.";
arq.close();

Pr

20

22

24

endl
endl
endl
endl

return 0;

}
"

Ve
r

30

ios::trunc); //Recriando o

s
o

26

28

22.2

Arquivos formatados

Para que se possa movimentar o cursor dentro de um arquivo, importante que se conhea a
estrutura do mesmo, principalmente se pretender sobrescrev-lo sem destru-lo. Por exemplo,
considere o seguinte problema.
Escrever um programa que leia matrcula e nome de alunos do curso de Engenharia Qumica
e armazene estas informaes em um arquivo. Em seguida, seu programa deve escrever todas
as informaes na tela, precedidas por um nmero identificando cada aluno. Finalmente, o
programa deve ler nmeros correspondentes a alunos e sobrescrever os dados do aluno com
novas informaes.

#include <iostream>

22.2. ARQUIVOS FORMATADOS

143

#include <fstream>
3

#define NOME_ARQ "arquivo.txt"


5

using namespace std;


7

11

bool mais_info()
{
char resp = x;
cout << "Entrar com mais informacoes? (s/n)";

13

in
a

while(true)
{
cin >> resp;

15

17

21

23

25

el
im

switch(resp)
{
case s:
case S:
return true;
case n:
case N:
return false;
}

19

27

}
29

35

37

39

41

int main()
{
fstream arq;

Ve
r

43

Pr

33

void ler_aluno(char mat[], int tmat, char nome[], int tnome)


{
cin.ignore(1000,\n);
cin.clear();
cout << "Digite a matricula (max " << tmat-1 << " caracteres:)";
cin.getline(mat,tmat);
cout << "Digite o nome (max " << tnome-1 << " caracteres";
cin.getline(nome,tnome);
}

s
o

31

45

int totalcount = 0;
int count;
char linha[1000];

47

49

51

53

char mat[15];
char nome[100];

arq.open(NOME_ARQ);
if(! arq.is_open())
arq.open(NOME_ARQ, ios::in | ios::out | ios::trunc);

55

57

while(mais_info())
{
ler_aluno(mat, 15, nome, 100);

144

CAPTULO 22. NAVEGAO DENTRO DO ARQUIVO


arq << mat << " " << nome << endl;

59

}
61

count = 1;
arq.clear();
arq.seekg(0);

63

65

cout << "Dados atuais" << endl;


while(arq.getline(linha,1000))
{

67

}
73

while(mais_info())
{
cout << "Sobrescrever qual linha?";
cin >> count;
if(count > totalcount)
{
cout << "Linha nao existente";
}
else
{
ler_aluno(mat, 15, nome, 100);

75

el
im

77

79

81

83

85

arq.clear();
arq.seekg(0);
while(count > 1)
{
arq.getline(linha,1000);
count--;
}
arq << mat << " " << nome << endl;

Pr

87

89

s
o

91

93

in
a

cout << count++ << " - "<< linha << endl;


totalcount++;

71

69

95

97

arq.clear();
count = 1;
arq.seekg(0, arq.beg);
cout << "Dados atuais" << endl;
while(arq.getline(linha,1000))
{
cout << count++ << " - "<< linha << endl;
}

Ve
r

99

101

103

105

107

return 0;

109

Este cdigo possui duas particularidades. Primeiro, ele usa a funo arq.clear(), ainda
no mencionada e, segundo, ele est errado.

22.3. EXERCCIOS

145

Toda vez que o arquivo lido at o seu fim, seu estado interno mudado para identificar
o fato. Isto verificvel pela funo arq.eof(), que testa se o arquivo chegou ao end of file.
Quando isso verdade, as funes de reposicionamento no funcionaro, a no ser que este
status seja reiniciado, o que feito com a funo clear(). No cdigo simplesmente usamos
esta funo sempre que formos fazer um seek, por simplicidade.
Sobre o cdigo no funcionar como esperado, execute-o e insira um aluno apenas, com
matrcula "aaaaaaaaaa"e nome "bbbbbbbbbb". Em seguida, altere os dados da linha 1 e insira
matrcula "cc"e nome "dd". Ao final, os dados impressos sero os seguintes:

in
a

22.3

Dados atuais
1 - cc dd
2 - aaaa bbbbbbbbbb

Exerccios

el
im

22.3.1

Ve
r

s
o

Pr

Corrija o programa exemplo mostrado acima para que escreva sempre linhas de um mesmo
tamanho e que, portanto, no tenha o problema de fragmentao de registros.

Anda mungkin juga menyukai