Você está na página 1de 1030

http://blocofontes.blogspot.com.

br/

Convertido para PDF por: Daniel dos Santos


K r is J a m s a , P h .D.
La r s K l a n d e r

http://blocofontes.blogspot.com.br/

Traduo e Reviso Tcnica


Jeremias Ren D. Pereira dos Santos
Analista de Software

Daniel dos Santos Pinheiro

MAKRON Books do Brasil Editora Ltda.


Rua Tabapu, 1.348, Itaim-Bibi
CEP 04533-004 So Paulo SP
(011) 829-8604 e (011) 820-6622
makron@book.com.br Tipo: PDF
Tamanho: 34,21MB
So Paulo Rio de Janeiro Ribeiro Preto Belm Belo H orizonte Braslia Campo Grande Cuiab Curitiba Florianpolis Fortaleza
Goinia M anaus N atal Porto Alegre Recife Salvador

Barcelona Bogot Buenos Aires Caracas Ciudad dei Mxico Frankfurt Guadalajara Lisboa Londres Madrid Montevideo
New York Paris Porto Santiago
Do Original Jamsas C/C++ Programmer's Bible

Copyright 1998 by Jamsa Press


Copyright 1999 MAKRON Books do Brasil Editora Ltda.

Todos os direitos para a lngua portuguesa reservados pela MAKRON Books do


Brasil Editora Ltda. Nenhuma parte desta publicao poder ser reproduzida,
guardada pelo sistema retrieval ou transmitida de qualquer modo ou por
qualquer outro meio, seja este eletrnico, mecnico, de fotocpia, de gravao, ou
outros, sem prvia autorizao, por escrito, da Editora.

EDITOR: MILTON MIRA DE ASSUMPO FILHO

Gerente de Produo
Silas Camargo

Editora Assistente
Eugnia Pessotti

Produtora Editorial
Salete Del Guerra

Design de Capa
Marianne Helm
James Rehrauer

Editorao Eletrnica: ER J Informtica Ltda.

Dados de Catalogao na Publicao

Programando em C/C+ + A Bblia; Kris Jamsa e Lars Klander


traduo: e reviso tcnica: Jeremias Ren D. Pereira dos Santos
So Paulo: MAKRON Books, 1999.
Ttulo original: Jamsas C/C+ + Programmers Bible

ISBN: 85.346.1025-8
S u m r io

Exibindo Valores de Ponto Flutuante em um Formato


E x p o n en cial..................................................................................................60
In t r o d u o L i n g u a g e m C
Exibindo Valores em Ponto F lu tu a n te ..................................................... 61
U m a Introduo P rogram ao............................................................... 1 Exibindo uma String de Caracteres Usando p r i n t f ............................. 62
Criando um Arquivo-Fonte em A S C II......................................................2 Exibindo um Endereo de Ponteiro Usando p rin tf ........................... 63
Com pilando Seu P ro g ram a.......................................................................... 3 Precedendo um Valor com um Sinal de Adio ou de
Com preendendo os Erros de Sintaxe ........................................................4 S u b tra o ...................................................................................................... 64
Estrutura de um Tpico Programa em C ................................................. 5 Form atando um Valor Inteiro Usando p r i n t f ....................................... 65
Acrescentando Comandos aos Seus P rogram as........................................6 Sada de Inteiros Preenchida com Zeros ................................................66
Exibindo Sada em um a Nova L in h a ........................................................7 Exibindo um Prefixo Antes dos Valores Octais ou
Considera as Letras Maisculas e Minsculas D ife re n te s......................8 H exadecim ais............................................................................................... 67
Compreendendo os Erros Lgicos ............................................................ 9 Form atando um Valor em Ponto Flutuante Usando p r in tf ................ 68
Compreendendo o Processo de Desenvolvimento de um Form atando a Sada E xponencial............................................................. 69
P rogram a.....................................................................................................10 Justificando Esquerda a Sada de p r i n t f ............................................. 70
Compreendendo os Tipos de Arquivo ................................................ 11 C om binando os Especificadores de Formato de p r i n t f ....................... 71
Compreendendo M elhor o L in k e d ito r................................................ 12 Q uebrando um a String de Caracteres em Duas L in h as.......................72
Compreendendo os Arquivos de C a b e a lh o ....................................... 13 Exibindo Strings do T ipo near e far .......................................................73
Ajudando o Compilador a Localizar os Arquivos de Cabealho . . . 14 Trabalhando com os Caracteres Escape de p r i n t f ................................74
Agilizando as C o m p ila es.....................................................................15 Determinando o Nm ero de Caracteres Q ue p rin tf Exibiu ..............75
Com entando Seus P ro g ram as................................................................ 16 Usando o Valor de Retorno de p r i n t f .................................................... 76
M elhorando a Legibilidade do Seu P ro g ram a.....................................17 Usando o Controlador de Dispositivo A N S I................................ 77
Prestando Ateno s Mensagens de Advertncia do Compilador . 18 Usando o C ontrolador ANSI para Limpar Sua T e l a .......................... 78
Controlando as Advertncias do C o m p ilad o r.....................................19 Usando o C ontrolador ANSI para Exibir as Cores da T e la ................ 79
Usando Comentrios para Excluir Comandos do Programa ......... 20 Usando o C ontrolador ANSI para Posicionar o Cursor ....................80
Com preendendo a Im portncia dos N o m e s ....................................... 21 Executando Operaes Matemticas Bsicas em C .............................. 81
Compreendendo o P o n to -e -V rg u la.....................................................22 Com preendendo a Aritmtica do M d u lo ..............................................82
Apresentando as V ariveis....................................................................... 23 Com preendendo a Precedncia e a Associatividade dos
Atribuindo um Valor a uma V ariv el...................................................24 O peradores.................................................................................................... 83
Compreendendo os Tipos de Variveis................................................ 25 Forando a O rdem de Avaliao dos Operadores ................................84
Declarando Mltiplas Variveis do Mesmo T i p o ..............................26 Compreendendo o O perador de Incremento de C ..............................85
Com entando Suas Variveis na Declarao ....................................... 27 Compreendendo o Operador de Decremento de C ........................... 86
Atribuindo Valores s Variveis na D eclarao.................................. 28 Com preendendo um a Operao O U Bit a B i t .................................... 87
Inicializando M ltiplas Variveis durante a Declarao .................. 29 Com preendendo um a Operao E Bit a B i t ......................................... 88
Usando Nom es Representativos para as Variveis..............................30 Compreendendo uma Operao O U Exclusivo Bit a B i t .................. 89
Compreendendo as Palavras-chave de C .............................................. 31 Com preendendo a Operao Inverso Bit a B i t .................................... 90
Compreendendo as Variveis do T ipo int ......................................... 32 Aplicando um a Operao ao Valor de um a V arivel............................91
Com preendendo as Variveis do T ipo c h a r ....................................... 33 Com preendendo o Operador Condicional de C .................................. 92
Compreendendo as Variveis do T ipo f l o a t ....................................... 34 Com preendendo o O perador sizeof de C ............................................. 93
Compreendendo as Variveis do T ipo double .................................. 35 Efetuando um Deslocamento Bit a Bit .................................................. 94
Atribuindo Valores aos Valores em Ponto F lu tu a n te ....................... 36 Efetuando uma Rotao Bit a B i t ........................................................... 95
Com preendendo os Modificadores de T i p o ....................................... 37 Compreendendo os Operadores C ondicionais.......................................96
Compreendendo o Modificador de T ipo unsigned ......................... 38 Compreendendo o Processamento Iterativ o ........................................... 97
Com preendendo o M odificador de T ipo l o n g .................................. 39 Compreendendo Com o C Representa Verdadeiro e Falso ................98
Com binando os Modificadores de T ipo unsigned e lo n g ................ 40 Testando um a Condio com i f ............................................................. 99
Trabalhando com os Valores Grandes ................................................ 41 Compreendendo os Comandos Simples e C om postos....................... 100
Compreendendo o Modificador de T ipo reg ister............................. 42 Testando a Ig u ald ad e................................................................................ 101
Com preendendo o M odificador de T ipo s h o rt.................................. 43 Efetuando Testes Relacionais.................................................................. 102
O m itindo in t das Declaraes Modificadas ....................................... 44 Executando um a Operao Lgica E para Testar Duas
Compreendendo o Modificador de T ipo sig n e d ................................ 45 Condies ...................................................................................................103
Mltiplas Operaes de A trib u io ....................................................... 46 Executando uma Operao Lgica O U para Testar Duas
Atribuindo o Valor de um T ipo de Varivel a um T ipo Condies .................................................................................................. 104
D ifere n te.....................................................................................................47 Executando uma Operao Lgica N O ( N O T ) ........................... 105
Criando Seus Prprios T i p o s ................................................................ 48 Atribuindo o Resultado de um a Condio ...................................... 106
Atribuindo um Valor Hexadecimal ou O c t a l .....................................49 Declarando Variveis D entro de Comandos C om postos................107
Compreendendo o Extravasamento....................................................... 50 Usando Recuos para Melhorar a L egibilidade..................................108
Compreendendo a Preciso.....................................................................51 Usando a Verificao Estendida de Ctrl+Break ................................ 109
Atribuindo Apstrofos e O utros Caracteres ....................................... 52 Testando Valores de Ponto F lu tu a n te .................................................. 110
Introduo ao Com ando p r in tf ..............................................................53 Lao de Repetio Infinito ........................................................................111
Exibindo Valores do T ipo int Usando p r i n tf .....................................54 Testando um a A tribuio......................................................................... 112
Im prim indo um Valor Inteiro Octal ou H ex ad e cim a l.....................55 Cuidado com os Comandos if-if-else..................................................... 113
Exibindo Valores do T ipo unsigned int Usando p r i n t f ................. 56 Executando Comandos um Nmero Especfico de V e z e s ................ 114
Exibindo Valores do T ipo long int Usando p r i n tf .......................... 57 Partes do C om ando for So O p c io n a is ................................................ 115
Exibindo Valores do T ipo float Usando p r in tf ................................. 58 Decrementando os Valores em um C om ando f o r ..............................116
Exibindo Valores do T ipo char Usando p r i n tf .................................59 Controlando o Incremento do Lao f o r ................ ............................... 117
Usando Laos for com Valores char e f l o a t ......................................... 118

V
VI P rogram and o em C/C++ A B b l ia

Com preendendo um Lao N ull ......................................................... 119 Retornando um ndice ltim a Ocorrncia de uma S trin g ......... 179
Com preendendo o Lao Infinito .......................................................120 Trabalhando com Strings do T ipo f a r ................................................180
Usando o O perador Vrgula de C D entro de um Escrevendo Funes String para as Strings f a r .................................. 181
Lao f o r .................................................................................................... 121 Contando o Nm ero de Ocorrncias de um Caractere em uma
Evite M odificar o Valor de uma Varivel de Controle em um Lao S trin g ........................................................................................................ 182
f o r ........................... ' ................................................................................122 Invertendo o C ontedo de uma S tr in g ............................................. 183
Repetindo um ou Mais Comandos Usando um Lao w h ile ......... 123 Atribuindo um Caractere Especfico a um a String In te ira ..............184
Compreendendo as Partes de um Lao w h ile .................................. 124 Com parando Duas Strings de Caracteres .........................................185
Repetindo um ou Mais Com andos Usando do ..............................125 Comparando os Primeiros n Caracteres de Duas Strings ..............186
Compreendendo o Com ando continue de C .................................. 126 Comparando Strings sem Considerar a C a ix a ..................................187
Finalizando um Lao U sando o C om ando break de C ................ 127 Convertendo a Representao em String de Caracteres de um
Desvios com o C om ando g o t o ............................................................128 N m e r o ....................................................................................................188
Testando M ltiplas C o n d i e s............................................................129 Duplicando o Contedo de uma String ...........................................189
Com preendendo break D entro de sw itc h ......................................... 130 Encontrando um Caractere da Primeira Ocorrncia de um
Usando o Case default do Com ando sw itc h .....................................131 Determinado C o n ju n to ........................................................................... 190
Definindo Constantes no Seu P rogram a........................................... 132 Localizando uma Substring D entro de uma S trin g ............................191
Com preendendo a Expanso de Macros e de C o n stan tes..............133 Contando o Nm ero de Ocorrncias da S u b strin g ............................192
Nom eando as Constantes e as M a c r o s ..............................................134 O btendo um ndice para uma S u b strin g ..............................................193
Usando a Constante de Pr-processador _ F I L E _ ............................135 O btendo a Ocorrncia Mais Direita de uma S u b strin g ................ 194
Usando a C onstante de Pr-processador__LINE.... .........................136 Exibindo um a String sem o Especficador de Form ato % s .............195
Alterando a Contagem de Linha do P r-processador.....................137 Removendo um a Substring de D entro de uma String ................... 196
Gerando um Erro Incondicional do P r-processador.....................138 Substituindo um a Substring por O u t r a ................................................ 197
Outras Constantes do P r-processador..............................................139 Convertendo uma Representao Numrica A S C II............................198
Registrando a Data e a H ora do Pr-processador............................140 Determ inando Se um Caractere Alfanumrico .............................. 199
Testando a Adeso ao Padro A N S I.................................................. 141 Determ inando Se um Caractere uma L e tr a .................................... 200
Testando C++ versus C ....................................................................... 142 D eterm inando Se um Caractere C ontm um Valor A S C II.............. 201
Anulando a Definio de uma M acro ou C o n s ta n te .....................143 Determ inando Se um Caractere um Caractere de Controle . . . 202
Com parando Macros e F u n e s......................................................... 144 Determ inando Se um Caractere um D g ito .................................... 203
Compreendendo Pragmas do C o m p ila d o r....................................... 145 Determ inando Se um Caractere um Caractere G r fic o ................ 204
Aprendendo sobre os Valores e Macros P red efin id o s.....................146 D eterm inando Se um Caractere Maisculo ou Minsculo . . . . 205
Criando Seus Prprios Arquivos de C abealho................................ 147 D eterm inando Se um Caractere Imprimvel ..................................206
Usando #include <nomearq.h> ou #include "n o m e a rq .h " ........... 148 Determinando Se um Caractere um Sinal de P o n tu ao ..............207
Testando Se um Smbolo Est D efinido........................................... 149 Determinando Se um Caractere C ontm Espao em Branco . . . . 208
Efetuando o Processamento if-else .....................................................150 Determinando Se um Caractere um Valor H exadecim al..............209
Efetuando um Teste de Condio de Pr-processador Mais Convertendo um Caractere para M aiscula...................................... 210
P o d e ro so .................................................................................................. 151 Convertendo um Caractere para Minsculo .................................... 211
Realizando Processamento if-else e e ls e -if......................................... 152 Trabalhando com Caracteres ASCII ..................................................212
Definindo Macros e Constantes Q ue Requerem Mltiplas Escrevendo Sada Formatada em uma Varivel S trin g .................... 213
L in h a s ....................................................................................................... 153 Lendo a Entrada de um a String de Caracteres ..................................214
Criando Suas Prprias M a c r o s ............................................................154 "Tokenizando" as Strings para Poupar Espao ............................... 215
N o Coloque Ponto-e-Vrgula nas Definies de Macros ........... 155 Inicializando um a S t r i n g ...................................................................... 216
C riando Macros M in e M a x ................................................................ 156
Fu n es
C riando Macros Q U A D R A D O e C U B O .......................................157
Cuidado com os Espaos nas Definies das M a c ro s.....................158 Com preendendo as Funes ............................................................... 217
Com preendendo Com o Usar os Parnteses .....................................159 Usando Variveis D entro das Funes ............................................. 218
As Macros No Tm T i p o .................................................................. 160 Compreendendo main Com o uma F u n o ...................................... 219
Co m p r e e n d e n d o a s S t r in g s Introduo aos P arm etros.................................................................... 220
Usando Parmetros M ltip lo s ................................................................221
Visualizando uma String de C ............................................................161 Com preendendo as Declaraes de Parmetros em Programas
C om o o Compilador Representa uma String de C a racteres......... 162 C Mais A n tig o s .........................................................................................222
Com o C Armazena as Strings de C aracteres.....................................163 Retornando um Valor de um a Funo ................................................ 223
A prendendo Com o A Difere de A ................................................ 164 Com preendendo o C om ando r e t u r n .....................................................224
Representando um Apstrofo D entro de uma Constante Com preendendo os Prottipos de F u n o ............................................225
de S trin g .................................................................................................. 165 Com preendendo a Biblioteca de Execuo ......................................... 226
Determ inando o Tam anho de uma S trin g ....................................... 166 Compreendendo os Parmetros Formais e R e a is................................ 227
Usando a Funo strlen ....................................................................... 167 Solucionando os Conflitos nos N o m e s ................................................ 228
Copiando os Caracteres de uma String em O utra S trin g ..............168 Funes Q ue N o Retornam i n t ........................................................... 229
Anexando o Contedo de uma String em O u t r a ............................169 Compreendendo as Variveis Locais .....................................................230
Anexando n Caracteres em um a S trin g ..............................................170 Com o as Funes Usam a Pilha ............................................................231
Transform ando um a String em O u t r a ..............................................171 Compreendendo a Sobrecarga da F u n o ............................................232
N o Ultrapasse o Tam anho de um a String .....................................172 Compreendendo O nde C Coloca as Variveis L o c a is....................... 233
Determ inando Se Duas Strings So ou No Iguais .....................173 Declarando Variveis Globais ................................................................ 234
Ignorando a Caixa ao D eterm inar Se as Strings So I g u a is ......... 174 Evite Usar Variveis G lo b a is ...................................................................235
Convertendo um a String de Caracteres para Maisculas ou Solucionando os Conflitos de Nomes de Variveis Locais e
Minsculas .............................................................................................. 175 G lo b ais......................................................................................................... 236
O btendo a Primeira O corrncia de um Caractere em uma Definindo M elhor o Escopo de um a Varivel G lo b a l.......................237
String .......................................................................................................176 Com preendendo a Chamada por V a lo r................................................ 238
Retornando um ndice Primeira Ocorrncia de um a String . . . 177 Evitando a Alterao no Valor do Parmetro com a Chamada
E ncontrando a U ltim a Ocorrncia de um Caractere em uma por V a lo r ..................................................................................................239
String ....................................................................................................... 178 Compreendendo a Chamada por R eferncia.................................... 240
S umrio VII

O btendo um E n d e re o ......................................................................... 241 Posicionando o Cursor para Sada na Tela ........................................ 307
Usando um Endereo de M e m ria .....................................................242 Determinando a Posio de Linha e de Coluna ...............................308
Alterando o Valor de um P arm etro.................................................. 243 Inserindo uma Linha em Branco na T e l a ...........................................309
Alterando Somente Parmetros Especficos.......................................244 Copiando Texto da Tela para um Buffer ...........................................310
A Chamada por Referncia Ainda Usa a P ilh a ................................ 245 Escrevendo um Buffer de Texto em um a Posio Especfica
Introduzindo as Variveis de Funes que L e m b ra m .....................246 da T e l a ........................................................................................................ 311
Compreendendo Com o C Inicializa Variveis E stticas................ 247 Determ inando as Definies do M odo T e x to ....................................312
Usando a Seqncia de Cham ada Pascal ......................................... 248 Controlando as Cores da T e l a ...............................................................313
Com preendendo o Efeito da Palavra-Chave P ascal......................... 249 Atribuindo Cores de F u n d o ................................................................... 314
Escrevendo um Exemplo de Linguagem M is ta ................................ 250 Definindo a Cor de Frente Usando T e x tC o lo r..................................315
Com preendendo a Palavra-Chave cdecl ............................................251 Definindo a Cor de Fundo Usando textbackground........................ 316
Com preendendo a R e cu rso ................................................................ 252 Controlando a Intensidade do T e x to ...................................................317
Com preendendo a Funo Recursiva F atorial.................................. 253 Determ inando o M odo Atual do Texto ............................................ 318
Programando O utro Exemplo Recursivo ......................................... 254 Movendo Texto da Tela de um Local para O utro ...........................319
Exibindo Valores para Com preender M elhor a R ecurso..............255 D efinindo um a Janela de T e x to ............................................................ 320
Com preendendo a Recurso Direta e I n d ir e ta ................................ 256 Usando o Valor Absoluto de uma ExpressoIn te ira .......................... 321
Decidindo Usar ou No a R ecu rso ..............................................' . . 257 Usando o Arco C o-seno.......................................................................... 322
Com preendendo Por Q ue as Funes Recursivas So Lentas . . . . 258 Usando o Arco Seno ...............................................................................323
Com preendendo Com o Remover a R ecurso.................................. 259 Usando o Arco T a n g e n te ........................................................................324
Passando Strings para as F u n e s....................................................... 260 O btendo o Valor Absoluto de um Nm ero C o m p lex o ...................325
Passando Elementos Especficos da M a tr iz .......................................261 Arredondando para Cima um Valor em Ponto F lu tu a n te ............... 326
Com preendendo const em Parmetros F o rm a is ..............................262 Usando o Co-seno de um n g u lo ........................................................327
Usar const No Impede a Modificao do Parmetro .................. 263 Usando o Co-seno Hiperblico de um n g u lo ................................. 328
Com preendendo as Declaraes de Strings No-Limitadas ......... 264 Usando o Seno de um ngulo ............................................................ 329
Usando Ponteiros versus Declaraes de S trin g ................................ 265 Usando o Seno Hiperblico de um ngulo .................................. 330
Com o C Usa a Pilha para os Parmetros S trin g ..............................266 Usando a Tangente de um n g u lo ...................................................... 331
Compreendendo as Variveis E x te rn a s..............................................267 Usando a Tangente Hiperblica de um ngulo ............................... 332
Colocando extern em Uso .................................................................. 268 Realizando a Diviso Inteira ................................................................. 333
Compreendendo a Varivel Esttica Externa .................................. 269 Trabalhando com Exponencial ............................................................ 334
Com preendendo a Palavra-chave volatile ......................................... 270 Usando o Valor Absoluto de uma Expresso em Ponto
Com preendendo a Estrutura de Chamada e o Ponteiro de F lu tu a n te ................................................................................................... 335
B ase............................................................................................................271 Usando o Resto em Ponto F lu tu an te................................................... 336
C ham ando um a Funo em Linguagem A ssem bly......................... 272 Usando a Mantissa e o Expoente de um Valor em Ponto
Retornando um Valor a partir de um a Funo em Linguagem F lu tu a n te ................................................................................................... 337
A ssem bly.................................................................................................. 273 Calculando o Resultado de x * 2 e ........................................................338
Introduzindo Funes Q ue No Retornam V a lo re s....................... 274 Calculando o Logaritmo N a tu ra l.......................................................... 339
Com preendendo as Funes Q ue No Usam Parmetros ............275 Calculando o Resultado de loglO x........................................................340
Com preendendo a Palavra-chave auto ..............................................276 Determinando os Valores Mximo e M n im o ....................................341
Com preendendo o E s c o p o .................................................................. 277 Quebrando um Double em Seus Com ponentes Inteiro e Real . . . 342
Compreendendo as Categorias de Escopo de C ..............................278 Calculando o Resultado de xn ...............................................................343
Compreendendo o Espao do Nome e os Identificadores ........... 279 Calculando o Resultado de 10 * ............................................................ 344
Com preendendo a Visibilidade do Identificador ........................... 280 Gerando um Nm ero A leatrio.............................................................345
Com preendendo a Durao ................................................................ 281 Mapeando Valores Aleatrios para um Intervalo Especfico ......... 346
Funes Q ue Suportam um N m ero Varivel de Parmetros . . . 282 Inicializando o Gerador de Nmeros Aleatrios ...............................347
Suportando um N m ero Varivel de P arm etro s........................... 283 Calculando a Raiz Q uadrada de um Valor ..........................................348
Com o va_start, va_arg e va_end Funcionam .................................. 284 Criando uma Rotina de Tratam ento de Erro M atemtico .............349
Criando Funes Q ue Suportam M uitos Parmetros e Tipos . . . 285
Arquivos, Diretrios e Discos
O pe r a e s d e Teclado
Determ inando a Unidade de Disco A tu a l ...........................................350
Lendo um Caractere do Teclado .......................................................286 Selecionando a Unidade A tu a l............................................................... 351
Exibindo um Caractere de S ad a......................................................... 287 Determinando o Espao Disponvel no D isc o ....................................352
Compreendendo a Entrada Bufferizada ........................................... 288 Cuidado com o d b lsp a c e ........................................................................353
Atribuindo Entrada do Teclado a um a String ................................ 289 Lendo as Informaes de uma Tabela de Alocao de
C om binando getchar e putchar ......................................................... 290 A rquivos...................................................................................................354
Lembre-se, getchar e putchar So M acros......................................... 291 Compreendendo a Identificao do D isc o ........................................ 355
Lendo um Caractere Usando E/S Direta ......................................... 292 Efetuando uma Leitura ou Gravao Absoluta de Setor ..................356
Entrada Direta no Teclado sem a Exibio do C a ractere..............293 Efetuando E/S no Disco Baseada no B I O S ........................................357
Sabendo Q uando Usar \r* e \n .......................................................294 Testando a Prontido de uma Unidade de D isquete.........................358
Executando Sada D ire ta .......................................................................295 Abrindo um Arquivo Usando fopen ................................................... 359
Colando uma Tecla Digitada de Volta no Buffer do Teclado . . . 296 Compreendendo a Estrutura F IL E ........................................................360
Sada Formatada Rpida Usando c p r i n t f ......................................... 297 Fechando um Arquivo A b e r to ............................................................... 361
Entrada Rpida Formatada a partir do T e c la d o ..............................298 Lendo e Gravando Informaes no Arquivo um Caractere de
Escrevendo uma String de C aracteres................................................299 Cada V e z ................................................................................................... 362
Escrita Mais Rpida de String Usando E/S D ire ta ......................... 300 Compreendendo o Ponteiro de Posio do Ponteiro de
Lendo uma String de Caracteres do T e c la d o .................................. 301 Arquivo ..................................................................................................... 363
Executando Entrada de String Mais Rpida peJo T e c la d o ......... .. 302 Determ inando a Posio Atual no A rq u iv o ........................................ 364
Exibindo Sada em C o r e s .................................................................... 303 Com preendendo os Canais de Arquivos ............................................. 365
Limpando a Tela do V d e o .................................................................. 304 Compreendendo as Tradues de A rquivos........................................ 366
Apagando at o Final da Linha A tu a l................................................ 305 Compreendendo a Linha FILES=valor no C onfig.Sys......................367
Apagando a Linha Atual da Tela .......................................................306 Usando E/S em Arquivos de Baixo Nvel e de Alto Nvel .............368
VIII P rogram and o em C/C++ A B b l ia

Com preendendo os Indicativos de A rquivos.....................................369 Bloqueando o C ontedo de um Arquivo .........................................428


Com preendendo a Tabela de Arquivos do P rocesso....................... 370 G anhando Controle Mais Refinado do Bloqueio de Arquivo . . . . 429
Visualizando as Entradas da Tabela de Arquivos do Processo . . . 371 Trabalhando com Diretrios do D O S ................................................430
Com preendendo a Tabela de Arquivos do Sistema ....................... 372 Abrindo um D ire t rio ...........................................................................431
Exibindo a Tabela do Sistema de Arquivos .....................................373 Lendo um a Entrada do Diretrio .......................................................432
Derivando Indicativos de Arquivos a partir de Ponteiros Usando Servios de Diretrio para Ler C:\W indows .................... 433
Stream (de Canais) ................................................................................ 374 Voltando para o Incio de um D ire t rio ........................................... 434
Executando Sada Formatada em Arquivo .......................................375 Lendo Recursivamente os Arquivos de um Disco .........................435
Renomeando um A rq u iv o .....................................................................376 Determ inando a Posio Atual no A rq u iv o .......................................436
Excluindo um A rq u iv o ......................................................................... 377 Abrindo um Canal de Arquivo C om partilhado................................437
Determinando Como um Programa Pode Acessar um Criando um Arquivo Exclusivo em um Diretrio Especfico . . . . 438
A rq u iv o .....................................................................................................378 Criando um Novo A rq u iv o ..................................................................439
Definindo o M odo de Acesso de um A rq u iv o ................................ 379 Usando os Servios do DOS para Acessar um Arquivo ................440
G anhando M elhor Controle dos Atributos do A rq u iv o ................ 380 Forando a Abertura de um Arquivo no M odo Binrio ou
Testando o Erro no Canal de um A rq u iv o .......................................381 T e x t o .........................................................................................................441
D eterm inando o T am anho de um A r q u iv o .....................................382 Lendo Linhas de T e x t o .........................................................................442
Esvaziando um Canal de E/S ..............................................................383 Gravando Linhas de Texto ..................................................................443
Fechando Todos os Arquivos Abertos de uma S V e z .................. 384 Colocando fgets e fputs em Uso .........................................................444
O btendo o Indicativo de Arquivo de um Canal de Arquivo . . . . 385 Forando a Traduo de Arquivo B in rio .........................................445
Criando um Nom e de Arquivo Temporrio Usando P_tm pdir . . 386 Compreendendo Por Q ue o Programa copiatxt No Pode
Criando um N om e de Arquivo Tem porrio Usando T M P ou Copiar Arquivos B inrios...................................................................... 446
T E M P ...................................................................................................... 387 Testando o Final do Arquivo ............................................................. 447
Criando um Arquivo Verdadeiramente T em p o rrio ....................... 388 Devolvendo um C a ra c te re ....................................................................448
Removendo Arquivos T em p orrios.....................................................389 Lendo Dados Formatados de A rq u iv o ................................................449
Pesquisando o Cam inho de Com andos para um Arquivo ........... 390 Posicionamento do Ponteiro de Arquivo com Base em Sua Posio
Pesquisando um Arquivo na Lista de Subdiretrio de um Atual ........................................................................................................ 450
Item do A m b ien te.................................................................................. 391 O btendo Informaes do Indicativo de A rq u iv o ............................. 451
Abrindo Arquivos no Diretrio T EM P ............................................392 Reabrindo um Canal de A rquivo.........................................................452
M inimizando as Operaes de E/S em A rq u iv o ..............................393
Ma t r iz e s , P o n t e ir o s e Es t r u t u r a s
Escrevendo Cdigo Que Usa Barras Invertidas nos Nomes de
D ire t rio .................................................................................................. 394 Com preendendo as M a triz e s................................................................453
Modificando o Diretrio A tu a l............................................................395 Declarando um a M a triz .........................................................................454
Criando um D iret rio ........................................................................... 396 Visualizando um a M a triz ...................................................................... 455
Removendo um D iret rio .....................................................................397 Compreendendo os Requisitos de Armazenamento de uma
Removendo uma rvore de Diretrio ..............................................398 Matriz ......................................................................................................456
Construindo o Nom e de Caminho C o m p le to ................................ 399 Inicializando uma M a triz ...................................................................... 457
Subdividindo um Caminho de D ire t rio ......................................... 400 Acessando Elementos da Matriz ........................................................ 458
Construindo um N om e de C a m in h o ................................................ 401 Percorrendo em um Lao os Elementos da M a tr iz ........................ 459
Abrindo e Fechando um Arquivo Usando Funes de Baixo Usando Constantes para Definir as M atrizes....................................460
N v e l......................................................................................................... 402 Passando uma Matriz a uma F u n o ................................................. 461
Criando um Arquivo ............................................................................403 Revisitando as Matrizes Com o Funes ...........................................462
Efetuando Operaes de Leitura e Gravao de Baixo Nvel . . . . 404 Compreendendo Com o as Matrizes de String D iferem ..................463
Testando o Final de um A rq u iv o ...........................................................405 Passando Matrizes para a Pilha ...........................................................464
Colocando as Rotinas de Arquivo de Baixo Nvel para Determ inando Q uantos Elementos uma Matriz Pode
T rabalhar.................................................................................................. 406 A rm a z e n a r............................................................................................... 465
Especificando o M odo para uma Traduo Arquivo-Indicativo . . 407 Usando o Modelo de M emria Huge para as Matrizes
Posicionando o Ponteiro de Arquivo Usando lseek ...........................408 G ra n d e s ....................................................................................................466
Abrindo Mais de 20 Arquivos .................. ................................... .... 409 A Barganha entre Matrizes e Memria D in m ic a ...........................467
Usando servios de arquivo baseados no D O S ..................................... 410 Compreendendo as Matrizes M ultidim ensionais.............................468
O btendo a Data e a H ora de Criao de um A rq u iv o ...................... 411 Compreendendo as Linhas e C o lu n a s ............................................... 469
O btendo a Data e a H ora de um Arquivo Usando Campos de Acessando Elementos em uma Matriz B id im en sio n al....................470
B i t .................................................................................................................412 Inicializando Elementos em uma Matriz B idim ensional............... 471
D efinindo a Data e a H ora de um A rq u iv o ........................................ 413 Determ inando o Consum o de Memria de uma Matriz
Definindo a Data e a H ora de um Arquivo com a Data e a M ultidim ensional................................................................................... 472
H ora A tu ais................................................................................................. 414 Percorrendo em um Lao uma M atriz B idim ensional....................473
Lendo e Gravando Dados uma Palavra de Cada V e z ........................ 415 Percorrendo uma Matriz T ridim ensional.......................................... 474
Alterando o Tam anho de um A rq u iv o ................................................. 416 Inicializando Matrizes M ultidim ensionais........................................ 475
Controlando as Operaes de Leitura e Gravao em Passando uma Matriz Bidimensional para uma Funo ............... 476
Arquivos A bertos........................................................................................ 417 Tratando as Matrizes M ultidimensionais Com o uma Dimenso . 477
Atribuindo um Buffer de Arquivo ........................................................ 418 Com preendendo Com o C Armazena Matrizes
Alocando um Buffer de A rq u iv o .............................................................419 M ultidim ensionais................................................................................. 478
Criando um Nom e de Arquivo Exclusivo Usando m k te m p ......... 420 Com preendendo a O rdem Linha por Linha versus Coluna por
Lendo e Gravando E stru tu ra s..................................................................421 C o lu n a ..................................................................................................... 479
Lendo Dados de um a Estrutura a partir de um Canal de Matrizes de Estruturas de Matrizes ................................................... 480
A rq u iv o ........................................................................................................422 Com preendendo as Unies .................................................................481
Duplicando o Indicativo de um A rq u iv o ............................................ 423 Economizando Memria com as U n i e s .......................................... 482
Forando a Definio de um Indicativo de Arquivo ........................424 Usando REGS - U m a Unio C lssica...............................................483
Associando o Indicativo de um Arquivo com um Canal ................. 425 Colocando a Unio REGS em U s o ................................................... 484
Com preendendo o Com partilham ento de Arquivo .......................... 426 Com preendendo as Estruturas de Campos de B i t .......................... 485
Abrindo um Arquivo para o Acesso C om partilhado .......................... 427 Visualizando um a Estrutura de Campos de B i t ...............................486
S um rio IX

Com preendendo o Intervalo de Valores de um a Estrutura Compreendendo os Registradores ..........................................................551


Bit a Bit .................................................................................................. 487 Compreendendo o Registrador de Flags ..............................................552
Procurando um Valor Especfico em uma Matriz ......................... 488 Compreendendo as Interrupes de S o ftw a re .....................................553
Com preendendo um a Pesquisa B inria..............................................489 Usando a BIOS para Acessar a Impressora ......................................... 554
Usando um a Pesquisa B in ria..............................................................490 Informao de C trl+ B reak .......................................................................555
Classificando um a M a t r i z .....................................................................491 Compreendendo Possveis Efeitos Colaterais do D O S .................... 556
Com preendendo o M todo da B o lh a ................................................ 492 Suspendendo um Programa T em p o rariam en te.................................. 557
Colocando o Algoritmo da Bolha em U s o .......................................493 Divertindo-se com S o m ........................................................................... 558
Compreendendo o Algoritmo da S e le o ......................................... 494 O btendo Informaes Especficas do P a s ............................................559
Colocando em Uso o M todo da Seleo......................................... 495 Com preendendo o Endereo de Transferncia do Disco ................ 560
Com preendendo o Algoritmo Shell .................................................. 496 Acessando e Controlando a rea de Transferncia do Disco . . . . 561
Colocando em Uso o Algoritmo Shell ..............................................497 Usando os Servios de Teclado da B IO S .......................................... 562
Com preendendo o Q uick S o r t ............................................................498 O btendo a Lista de Equipamentos da B I O S ....................................563
Colocando o Q uick Sort em U s o ....................................................... 499 Controlando a E/S da Porta Serial......................................................564
Problemas com as Solues de Classificao A n te rio re s ................ 500 Acessando os Servios do D O S Usando b d o s ................................. 565
Classificando um a Matriz de Strings de Caracteres ....................... 501 O btendo Informaes Estendidas de Erro do D O S ...................... 566
Pesquisando uma Matriz com lfind .................................................. 502 Determ inando a Quantidade de Memria Convencional da
Procurando Valores com lse arch ......................................................... 503 B I O S ...........................................................................................................567
Pesquisando uma Matriz Classificada com bsearch......................... 504 Construindo um Ponteiro far ................................................................568
Classificando Matrizes com q s o r t ....................................................... 505 Dividindo um Endereo far em um Segmento e Deslocamento . . 569
Determ inando o N m ero de Elementos na Matriz .......................506 Determ inando a M emria do Ncleo Livre .......................................570
Compreendendo Ponteiros como Endereos .................................. 507 Lendo as Configuraes do Registrador de S eg m en to ....................... 571
Determ inando o Endereo de um a V arivel.....................................508
G e r e n c ia m e n t o d e M e m r ia
Com preendendo como C Trata Matrizes como P o n te iro s............509
Aplicando o Operador de Endereo (&) a um a M a t r iz ................ 510 Com preendendo os Tipos de M e m ria ................................................ 572
Declarando Variveis Ponteiro ............................................................511 Com preendendo a Memria C onvencional......................................... 573
Desreferenciando um P o n te iro ............................................................512 Compreendendo o Layout da Memria C o n v e n cio n al.....................574
Usando Valores de P o n te iro ................................................................ 513 Acessando a Memria C o n v en cio n al.................................................... 575
Usando Ponteiros com Parmetros de F u n o ................................ 514 Compreendendo Por Que o PC e o DOS Esto Restritos a
Com preendendo a Aritmtica de Ponteiros .....................................515 1 M b ............................................................................................................. 576
Incrementando e Decrem entando um P o n te iro ..............................516 Produzindo um Endereo a partir de Segmentos e
C om binando um a Referncia e Incremento de P o n te ir o ..............517 D eslocam entos...........................................................................................577
Percorrendo um a String Usando um P o n te iro ................................ 518 Compreendendo a Memria Expandida ............................................. 578
Usando Funes Q ue Retornam P onteiros....................................... 519 Usando a Memria Expandida ............................................................. 579
Criando uma Funo Q ue Retorna um P o n te iro ............................520 Compreendendo a Memria E ste n d id a ................................................580
Compreendendo um a Matriz de P o n teiro s.......................................521 Compreendendo os Modos Real e Protegido.......................................581
Visualizando uma Matriz de Strings de C aracteres......................... 522 Acessando a Memria E ste n d id a ...........................................................582
Percorrendo em um Lao um a Matriz de Strings de Compreendendo a rea de Memria A lta ........................................... 583
C a ra c te re s................................................................................................ 523 Compreendendo a Pilha ........................................................................ 584
T ratando um a M atriz de String de Caracteres Com o um Compreendendo Diferentes Configuraes da P i l h a .........................585
Ponteiro .................................................................................................. 524 Determinando o Tam anho da Pilha Atual do Seu Programa . . . . 586
Usando um Ponteiro para um Ponteiro para Strings de Controlando o Espao na Pilha com _ stk le n .......................................587
C a ra c te re s................................................................................................ 525 Atribuindo um Valor a um Intervalo de Memria ........................... 588
Declarando um a Constante String Usando um P o n te iro ..............526 Copiando um Intervalo de M emria para O utro ..............................589
Com preendendo o Ponteiro do T ipo v o i d .......................................527 Copiando um Intervalo de M emria at um Byte Especfico . . . . 590
Criando Ponteiros para as F unes.....................................................528 Com parando Duas Matrizes de unsigned char .................................. 591
Usando um Ponteiro para um a F u n o ........................................... 529 Perm utando Bytes de Strings de Caracteres A djacentes.................... 592
Usando um Ponteiro para um Ponteiro para um Ponteiro ......... 530 Alocando Memria D in m ic a ................................................................593
Com preendendo as Estruturas ............................................................531 Revisitando a Converso .........................................................................594
U m a Estrutura um Gabarito para a Declarao de Variveis . . 532 Liberando a Memria Q uando Ela No Mais N ecessria.........595
O Descritor de um a Estrutura o N om e da E s tru tu ra ................533 Alocando Memria Usando a Funo c a llo c ...................................... 596
Declarando uma Varivel Estrutura de M odos D ife re n te s........... 534 Compreendendo o H e a p ........................................................................ 597
Com preendendo os M embros da Estrutura .....................................535 Contornando o Limite de 64Kb para o H e a p .................................... 598
Visualizando um a Estrutura ................................................................ 536 Alocando Memria a partir da P i l h a ....................................................599
Pondo uma Estrutura em Uso ............................................................... 537 Alocando Dados H u g e .............................................................................600
Passando um a Estrutura a um a Funo ............................................538 Alterando o Tam anho de um Bloco Alocado .................................... 601
Alterando uma Estrutura D entro de um a Funo ......................... 539 Com preendendo b r k ............................................................................... 602
Com preendendo a Indireo (* p o nteiro).m em bro ......................... 540 Validando o H e a p ................................................................................... 603
Usando o Form ato ponteiro->m em bro ........................................... 541 Efetuando uma Verificao Rpida do H e a p ...................................... 604
Usando um a Estrutura sem N o m e .....................................................542 Preenchendo o Espao Livre do H e a p ..................................................605
C om preendendo o Escopo de Definio de um a E s tr u tu r a ......... 543 Verificando um a Entrada Especfica no H e a p .................................... 606
Inicializando uma Estrutura ....................................................................544 Percorrendo as Entradas do H e a p ........................................................ 607
Efetuando E/S em E s tru tu ra s ..............................................................545 Examinando o Contedo de uma Posio de Memria
Usando um a Estrutura D entro de O u t r a .............................................546 E specfica...................................................................................................608
Estruturas Q ue C ontm M a triz e s.......................................................... 547 Colocando Valores na M emria ...........................................................609
Criando um a Matriz de E stru tu ra s.....................................................548 Com preendendo as Portas do P C ........................................................ 610
S e r v i o s D O S e B IO S
Acessando os Valores das Portas ........................................................... 611
Com preendendo a C M O S ...................................................................... 612
Com preendendo os Servios do Sistema do D O S ......................... 549 Com preendendo os Modelos de M e m ria...........................................613
Com preendendo os Servios da BIOS ..............................................550 Com preendendo o Modelo de Memria T iny ................................. 614
X P ro g ram a n d o em C/C++ A B b l ia

Com preendendo o Modelo de Memria Small ..............................615 A s p a s .......................................................................................................... 672


Com preendendo o Modelo de M emria M e d iu m ......................... 616 Exibindo o Contedo de um Arquivo a partir da Linha de
Com preendendo o Modelo de Memria C o m p ac t......................... 617 C o m a n d o ................................................................................................... 673
Com preendendo o Modelo de M emria L arge................................ 618 Tratando argv Com o um Ponteiro ...................................................... 674
Com preendendo o Modelo de M emria Huge ..............................619 Compreendendo Com o C Sabe sobre a Linha de Comando . . . . 675
Determinando o Modelo de Memria Atual .................................. 620 Compreendendo o A m b ien te................................................................. 676
Tratando env Com o um Ponteiro ......................................................677
Da t a e h o r a
Use void para os Parmetros de m a i n ..................................................678
Obtendo a Data e a Hora Atuais Como Segundos desde 1/1/1970 . . 621 Trabalhando com Nmeros da Linha de C o m a n d o .........................679
Convertendo uma D ata e um a H ora de Segundos Compreendendo os Valores de Status da S a d a ..................................680
para ASCII ..............................................................................................622 Usando return para o Processamento do Status da S a d a ................ 681
Ajuste do Horrio de Vero ..............................................................623 Determ inando Se main Deve ou No Ser Declarada Como
Retardando durante um D eterm inado N m ero de void .............................................................................................................682
M ilissegundos......................................................................................... 624 Pesquisando o Item Especfico no A m b ien te...................................... 683
Determ inando o T em po de Processamento do Seu Programa . . . 625 Com o o D O S T rata o Ambiente ........................................................ 684
Com parando Dois H o r rio s ................................................................ 626 Usando a Varivel Global e n v iro n ........................................................ 685
O btendo um a String de D a t a ..............................................................627 Acrescentando um Item ao Ambiente Atual ...................................... 686
O btendo um a String com o H o r r i o ................................................ 628 Acrescentando Elementos no Ambiente D O S ....................................687
Lendo o Temporizador da BIOS .......................................................629 Abortando o Programa A tu a l..................................................................688
Trabalhando com o Horrio L o c a l.....................................................630 Definindo Funes Q ue Executam ao Trmino do Programa . . . 689
Trabalhando com o Horrio de G re e n w ic h .....................................631 Compreendendo as Bibliotecas ............................................................. 690
Obtendo o Horrio do Sistema D O S ................................................ 632 Reutilizando o Cdigo-Objeto ................................................................ 691
O btendo a Data do Sistema do D O S ................................................ 633 Problemas com a Compilao de Arquivos C e OBJ .......................692
Definindo o Horrio do Sistema D O S ..............................................634 Criando um Arquivo de B ib lio te c a ...................................................... 693
Definindo a Data do Sistema do D O S ........................................... 635 Compreendendo as Operaes da Biblioteca C o m u m ...................... 694
Convertendo um a Data do D O S para o Formato do U N IX . . . . 636 Listando as Rotinas em um Arquivo de B ib lio teca ........................... 695
Usando timezone para Calcular a Diferena entre a Zona Use Bibliotecas para Reduzir Seu T em po de C om pilao................ 696
H o r r ia .....................................................................................................637 Aprendendo Mais sobre as Capacidades da Sua B ib lio teca..............697
Determ inando a Zona Horria A tu a l ................................................ 638 Com preendendo o L in k e d ito r............................................................... 698
Definindo Campos de Zona Horria com tz s e t..............................639 Vendo as Capacidades do Linkeditor ..................................................699
Usando a Varivel de Ambiente T Z .............................................. . 640 Usando um M apa do L in k e d ito r...........................................................700
Definindo a Entrada de Ambiente T Z a partir de D entro de Usando Arquivos de Resposta do L inkeditor.......................................701
Seu P ro g ra m a ......................................................................................... 641 Simplificando a Criao de Aplicativos com o M A K E .....................702
O btendo as Informaes de Zona H o r ria .......................................642 Criando um Arquivo Simples do MAKE ........................................... 703
Definindo a Hora do Sistema em Segundos desde a Meia-noite Usando Mltiplos Arquivos de Dependncia com o MAKE . . . . 704
de 1/1/1970 ............................................................................................ 643 Com entando Seus Arquivos do M A K E ................................................705
Convertendo uma D ata para Segundos desde a M eia-noite de Linhas de Com ando e M A K E ............................................................... 706
1/1/1970 .................................................................................................. 644 Colocando Mltiplas Dependncias em um Arquivo do
Determinando a D ata Juliana de uma D a t a .....................................645 M A K E ........................................................................................................ 707
Criando uma String Formatada de Data e H o r a ............................646 Regras Implcitas e Explcitas do M A K E ............................................. 708
Compreendendo os Tipos de Relgio do P C .................................. 647 Usando Macros do MAKE .................................................................... 709
Macros Predefinidas do M A K E ............................................................. 710
Re d ir e c io n a n d o a E /S e P r o c e s s a n d o U n h a s d e Co m a n d o
Executando Processamento Condicional com o MAKE ...................711
Aguardando a Digitao de um a T e c la ..............................................648 Testando um N om e de Macro ............................................................. 712
Pedindo um a Senha ao U s u rio ......................................................... 649 Incluindo um Segundo Arquivo do MAKE ...................................... 713
Escrevendo Sua Prpria Funo de Senha .......................................650 Usando os Modificadores de M acro do MAKE ............................... 714
Com preendendo o Redirecionamento da Sada ..............................651 Finalizando, um Arquivo do MAKE com um E r r o ........................... 715
Com preendendo o Redirecionamento da E n tr a d a ......................... 652 Desabilitando a Exibio do N om e do C o m a n d o ............................. 716
Com binando o Redirecionamento da Entrada e da Sada ........... 653 Usando o Arquivo BUILTINS.M AK ..................................................717
Usando stdout e s td in ........................................................................... 654 Executando Processamento de Status de Sada no MAKE ..............718
Compreendendo o Operador de C analizao.................................. 655 C ham ando e Alterando um a Macro ao Mesmo T e m p o .................. 719
Com preendendo getchar e p u tc h a r.....................................................656 Executando um Com ando MAKE para Mltiplos Arquivos
N um erando a Entrada R edirecionada................................................ 657 Dependentes ............................................................................................. 720
G arantindo Q ue uma Mensagem Aparea na T e la ......................... 658 C Avanado
Escrevendo Seu Prprio Com ando more ......................................... 659
Exibindo um C ontador de Linhas R edirecionadas......................... 660 Determ inando Se o Co-Processador Matemtico Est Presente . . 721
Exibindo um C ontador de Caracteres R edirecionados.................. 661 Com preendendo as Macros ctype.h e is ty p e ...................................... 722
Criando um Com ando M ore com Controle de T e m p o ................662 Controlando o Vdeo D ir e to ..................................................................723
Im pedindo o Redirecionamento da E / S ........................................... 663 Detectando Erros Matemticos e do Sistema .................................... 724
Usando o Indicativo de Arquivo s td p r n ........................................... 664 Exibindo Mensagens de Erro Predefinidas........................................... 725
Desviando a Sada Redirecionada para um A rq u iv o ....................... 665 Determ inando o N m ero de Verso do Sistema Operacional . . . 726
Usando o Indicativo de Arquivo s td a u x ........................................... 666 Com preendendo a P o rta b ilid ad e...........................................................727
Encontrando Ocorrncias de Substring Dentro da Entrada Efetuando um G oto No-local ............................................................. 728
R edirecionada......................................................................................... 667 O btendo a Identificao do Processo.................................................... 729
Exibindo as Primeiras n Linhas da Entrada Redirecionada ......... 668 Chamando um Comando Interno do DOS .......................................730
Com preendendo os Argumentos da Linha de C o m a n d o ..............669 Usando a Varivel Global _ p s p ..............................................................731
Exibindo um C ontador de Argumentos da Linha de Com andos . 670 Usando o Modificador const nas Declaraes de V ariveis..............732
Exibindo a Linha de C om ando ......................................................... 671 Usando Tipos E n u m e ra d o s.................................................................... 733
Trabalhando com Argumentos da Linha de Comando entre Colocando um T ipo Enumerado em U s o ........................................... 734
S umrio XI

Com preendendo um Valor E n u m e ra d o ............................................735 In t r o d u o C + +


Atribuindo um Valor Especfico a um T ipo E n u m e ra d o ..............736
Salvando e Restaurando os R e gistradores......................................... 737 Introduzindo C++ .................................................................................. 803
Introduo s Listas Dinmicas ......................................................... 738 C om o os Arquivos-Fonte de C++ So D ife re n te s .............................. 804
Declarando uma Estrutura de Lista L igada.......................................739 Iniciando com um Programa Simples em C + + ...................................805
Criando uma Lista L igada.....................................................................740 Com preendendo o Canal de Enrrada/Sa/da c o u r ................................ 806
Exemplo de uma Lista Ligada S im p le s..............................................741 Escrevendo Valores e Variveis com cout ............................................ 807
Compreendendo como Percorrer uma Lista L ig a d a ....................... 742 Com binando Diferentes Tipos de Valores com c o u t..........................808
Criando uma Lista Mais t i l ..............................................................743 Exibindo Valores Hexadecimais e O c ta is.............................................. 809
Anexando um Elemento na L is t a ....................................................... 744 Redirecionando cout ................................................................................810
Inserindo um Elemento na L ista......................................................... 745 Se Voc Gosta de printf, Use p r i n t f ..................................................... 811
Exibindo um Diretrio C lassificado...................................................746 Escrevendo Sada em cerr ...................................................................... 812
Excluindo um Elemento de uma L is ta ..............................................747 Recebendo Entrada com cin .................................................................. 813
Usando uma Lista Duplam ente L igada.............................................. 748 cin No Usa P o n teiro s............................................................................. 814
Criando uma Lista Duplam ente Ligada Simples ............................749 Compreendendo Com o cin Seleciona os Campos de D a d o s.............815
Compreendendo nodo-> anterior->prxim o.....................................750 Compreendendo Com o os Canais de E/S Conhecem os Tipos
Removendo um Elemento de uma Lista Duplam ente Ligada . . . 751 dos V alores..................................................................................................816
Inserindo um Elemento em uma Lista Duplam ente L ig a d a ......... 752 Efetuando Sada Usando clog ................................................................817
Com preendendo os Processos-F ilho...................................................753 cin, cout, cerr e clog So Ocorrncias de C la sse ................................ 818
Gerando um P ro cesso -F ilh o................................................................ 754 Descarregando a Sada com flush .........................................................819
Usando Outras Funes spawnlxx .....................................................755 Com preendendo o Q ue iostream.h C o n t m .......................................820
Usando as Funes spaw nvxx..............................................................756 C++ Requer Prottipos de F u n e s.......................................................821
Executando um P rocesso-Filho....................... ....................................757 C++ Acrescenta Novas Palavras-Chave ................................................822
Usando Outras Funes execlxx......................................................... 758 C++ Suporta as Unies A n n in ias.........................................................823
Usando as Funes execvxx ................................................................ 759 Resolvendo o Escopo G lo b a l.................................................................. 824
Compreendendo os Overlays ..............................................................760 Fornecendo Valores Padro de Parmetros ......................................... 825
Compreendendo as Interrupes......................................................... 761 Controlando a Largura da Sada de c o u t ..............................................826
As Interrupes do P C ......................................................................... 762 Usando setw para Definir a Largura para c o u t .................................. 827
Usando a Palavra-Chave interrupt .....................................................763 Especificando um Caractere de Preenchimento em c o u t ...................828
Determinando o Vetor de uma In terru p o .....................................764 Justificando D ireita e Esquerda a Sada de cout ......................... 829
Definindo um Vetor de Interrupo...................................................765 Controlando o N m ero de Dgitos em Ponto Flutuante
Habilitando e Desabilitando as Interrupes .................................. 766 Exibidos por c o u t.......................................................................................830
Criando um a Rotina Simples de T ratam ento de Interrupo . . . . 767 Exibindo Valores nos Formatos Fixo ou C ien tfico ............................831
Encadeando um a Segunda In terru p o ..............................................768 Restaurando cout para o Padro ........................................................... 832
Gerando um a In terru p o .....................................................................769 D efinindo a Base da E / S .........................................................................833
Interceptando o Tem porizador do P C ..............................................770 Declarando Variveis O nde Voc Precisa Delas ................................834
Com preendendo os Erros Crticos .....................................................771 Colocando Valores de Parmetro Padro em Prottipos de
Tratam ento de Erro Crtico em C .....................................................772 F u n o .........................................................................................................835
Um a Rotina de Tratam ento de Erro Crtico C o m p le ta ................ 773 Usando Operadores Bit a Bit e c o u t .................................................... 836
Restaurando as Interrupes A lte ra d a s..............................................774 Compreendendo a Avaliao Preguiosa (ou Curto- Circuito) . . . 837
Criando um a Rotina de Tratam ento de C trl+ B reak ....................... 775 Usando a Palavra-Chave const em C + + ................................................838
Usando os Servios do D O S na Sua Rotina de Tratam ento Usando a Palavra-Chave enum em C++ ............................................. 839
de Erro C r t i c o ....................................................................................... 776 Com preendendo o Espao Livre ........................................................... 840
A um entando o Desempenho com o Uso da Seleo do Alocando Memria com n e w ...................................................................841
C onjunto de Instrues......................................................................... 777 Alocando Mltiplas M a triz e s.................................................................. 842
Funes Intrnsecas I n -lin e .................................................................. 778 Testando a Falta de Espao Livre ......................................................... 843
Habilitando e Desabilitando as Funes Intrnsecas....................... 779 Consideraes sobre o Espao no H e a p ................................................844
Compreendendo as Chamadas Rpidas de F u n e s ......... .............780 Usando Ponteiros far e o Operador n e w ..............................................845
Regras para a Passagem de Parmetros _ fa stc a ll..............................781 Liberando Memria de Volta ao Espao Livre .................................. 846
Com preendendo o Cdigo Invariante ..............................................782 Com preendendo as Referncias de C + + ................................................847
Com preendendo a Supresso de Carga R e d u n d an te.......................783 Passando um a Referncia a um a F u n o ..............................................848
Compreendendo a Compactao do Cdigo .................................. 784 A tentando para os O bjetos O c u lto s .......................................................849
Com preendendo a Compactao do Lao ....................................... 785 Usando Trs M odos de Passar Parmetros ......................................... 850
Compreendendo a Induo do Lao e a Reduo da F o r a ......... 786 Regras para Trabalhar com R eferncias................................................ 851
Com preendendo a Eliminao de Subexpresso C o m u m ..............787 As Funes Podem Retornar Referncias............................................. 852
Com preendendo as Converses Com uns de C P a d r o .................. 788 Usando a Palavra-Chave inline de C + + ............................................... 853
Com preendendo os Q uatro Tipos Bsicos de C ..............................789 Usando a Palavra-chave asm de C + + .................................................... 854
Com preendendo os Tipos Fundam entais versus os Derivados . . . 790 Lndo um Caractere Usando c i n ........................................................... 855
Com preendendo os Inicializadores.....................................................791 Escrevendo um Caractere com c o u t...................................................... 856
Com preendendo o Sistema de Ligao (L inkage)............................792 Escrevendo um Programa Simples de Filtro ......................................857
Com preendendo as Declaraes Experimentais ..............................793 Escrevendo um Com ando Tee S im p le s...............................................858
Contrastando Declaraes e Definies ............................................794 Escrevendo um Com ando First Simples ............................................ 859
Compreendendo lvalues .......................................................................795 Escrevendo um C om ando First M e lh o r...............................................860
Compreendendo rv a lu e s.......................................................................796 Testando o Final do A rquivo .................................................................. 861
Usando Palavras-chave de Registradores de Segmento ......................797 Gerando uma Nova Linha com e n d l.................................................... 862
Use os Ponteiros far com C u id a d o .....................................................798 Compreendendo as Especificaes de L ig ao .................................... 863
Compreendendo os Ponteiros Normalizados ......................................799 Com preendendo a S obrecarga................................................................864
Comandos do Co-Processador Matemtico ........................................ 800 Sobrecarregando as F unes.................................................................... 865
Compreendendo cdecl e pascal nas V ariv eis...................................... 801 Sobrecarregando Funes: um Segundo E x e m p lo ............................. 866
Im pedindo as Incluses C irc u la re s........................................................ 802 Evitando a Ambigidade da Sobrecarga............................................... 867
Lendo um a Linha de Cada Vez com cin ..............................................868
XII P ro g ram a n d o em C/C+ + A B b l ia

U sando cin.gedine em um L a o ........................................................ 869 Sobrecarregando as Funes C o n stru to ra s.........................................930


Alterando o Tratam ento Normal do Operador n e w ....................... 870 E ncontrando o Endereo de um a Funo Sobrecarregada................ 931
D efinindo um a Nova Rotina de Tratamento com set_new Usando Funes Construtoras com um nico Parmetro ............. 932
_ h a n d le r ................................................................................................. 871 Com preendendo as Funes Destrutoras,............................................. 933
Determ inando uma Compilao C + + ................................................872 Usando um a Funo D e s tru to r a ........................................................... 934
Compreendendo as Estruturas em C++ ............................................873 Com preendendo Por Q ue Voc Deve Usar as Funes
Introduzindo Funes Como M embros da E stru tu ra .....................874 D estrutoras.................................................................................................. 935
Definindo uma Funo-membro D entro de uma E stru tu ra ......... 875 Com preendendo Q uando um Programa Cham a um a Funo
Declarando uma Funo-membro Fora de um a E s tru tu ra ............876 D e s tru to r a ..................................................................................................936
Passando Parmetros para um a F u n o -m e m b ro ............................877 Usando uma Construtora de C p ia .......................................................937
Mltiplas Variveis da M esma Estrutura ......................................... 878 Usando Construtoras E xplcitas..............................................................938
Diferentes Estruturas com os Mesmos Nomes de Funo- Com preendendo o Escopo da C lasse.................................................... 939
membro .....................................................................................................879 Com preendendo as Classes Inseridas D entro de O u t r a s ....................940
Diferentes Funes com os Mesmos Nom es de M e m b ro ..............880 Com preendendo as Classes L o cais......................................................... 941
Resolvendo os Conflitos de N om e de M embro e de Parmetro . . 942
O b je t o s
Criando uma Matriz de Variveis de Classe .......................................943
Com preendendo os O b je to s ................................................................ 881 Construtoras e Matrizes de Classes .......................................................944
Com preendendo a Programao O rientada a O b j e t o s .................. 882 Sobrecarregando um Operador ............................................................. 945
Com preendendo Por Q ue Voc Deve Usar Objetos .....................883 Criando uma Funo de Operador de M e m b ro ................................946
Quebrando os Programas em Objetos ..............................................884 Sobrecarregando o O perador de Adio ............................................. 947
Com preendendo O bjetos e C lasses.....................................................885 Sobrecarregando o O perador do Sinal de S u b tra o ......................... 948
Com preendendo as Classes de C++ .................................................. 886 Sobrecarregando os Operadores de Incremento de Prefixo e
Com preendendo o E n cap su lam ento ................................ ..................887 de Sufixo .................................................................................................... 949
Com preendendo o Polimorfismo .......................................................888 Sobrecarregando os Operadores de Decremento de Prefixo e
Com preendendo a Herana ................................................................ 889 de Sufixo .................................................................................................... 950
Decidindo entre Classes e Estruturas ................................................ 890 Revisitando as Restries na Sobrecarga de O p e ra d o r....................... 951
Criando um Modelo Simples de C la s s e ............................................891 Usando um a Funo amiga para Sobrecarregar os Operadores . . . 952
Implementando o Programa da Classe Simples ..............................892 Restries na Sobrecarga de O perador de Funo A m ig a ................953
Definindo os Componentes de uma Classe .....................................893 Usando um a Funo amiga para Sobrecarregar os
Compreendendo o O perador de Definio de E sc o p o .................. 894 Operadores ++ ou ................................................................................954
Usando ou O m itindo o N om e da Classe das D eclaraes............895 Razes para Sobrecarregar os Operadores com as Funes
Com preendendo o Rtulo public: .....................................................896 amigas ......................................................................................................... 955
Com preendendo a Ocultao de Informaes ................................ 897 Sobrecarregando o O perador n e w ......................................................... 956
Com preendendo o Rtulo p riv a te :.....................................................898 Sobrecarregando o Operador d e le te .......................................................957
Usando o Rtulo protected: ................................................................ 899 Sobrecarregando new e delete para as M a triz e s.................................. 958
Usando Dados Pblicos e Privados.....................................................900 Sobrecarregando o Operador de M atriz [ ] ........................................... 959
Determ inando o Q ue O cultar e o Q ue T ornar Pblico .............. 901 Sobrecarregando o Operador de Chamada de Funo ( ) .................. 960
Os M todos Pblicos So Freqentemente Chamados de Sobrecarregando o Operador de Ponteiro > .....................................961
Funes de In te rfa c e ..............................................................................902 Sobrecarregando o O perador Vrgula , ................................................962
Definindo Funes de Classe Fora da C la s s e ...................................903 Com preendendo a A b strao .................................................................. 963
Definindo M todos D entro e Fora das Classes ..............................904 Alocando um Ponteiro para um a Classe ............................................. 964
Com preendendo as Ocorrncias do O bjeto .....................................905 Descartando um Ponteiro para um a C la sse ......................................... 965
As Ocorrncias de O bjetos Devem Com partilhar o C d ig o ......... 906 Descartando o Espao em Branco Preliminar na E n tra d a ................966
Acessando os M embros da C la s se .......................................................907 Com preendendo as Bibliotecas de C lasses........................................... 967
Revisando o O perador de Definio G lo b a l.....................................908 Coloque Suas Definies de Classe em um Arquivo de
Inicializando os Valores da C lasse.......................................................909 Cabealho .................................................................................................. 968
Usando O utro M todo para Inicializar os Valores de Classe . . . . 910 Usando a Palavra-Chave inline com Funes-membro da
Com preendendo os M em bros de Classe E s t tic a ........................... 911 C lasse........................................................................................................... 969
Usando Dados-M em bro E stticos.......................................................912 Inicializando uma Matriz de C la sse .......................................................970
Usando Funes-Membro Estticas .................................................. 913 Destruindo a Matriz de Classe .............................................................. 971
Com preendendo as Declaraes das Funes-Membro ................914 Criando Matrizes de Classe Inicializadas..............................................972
Usando Declaraes de Funo In -lin e ..............................................915 Inicializando uma Matriz com uma Construtora de Mltiplos
D eterm inando Q uando Usar Funes In-line ou N o .................. 916 A rg u m e n to s................................................................................................973
C om preendendo as Classes e as U n i e s ........................................... 917 Criando Matrizes Inicializadas versus No-inicializadas.....................974
Introduzindo as Unies A n n im a s.................................................... 918 Trabalhando com Matrizes de Classe .................................................. 975
Introduzindo as Funes Amigas .......................................................919 Compreendendo Como as Matrizes de Classe Usam a
Introduzindo as Classes Amigas ......................................................... 920 Memria .................................................................................................... 976
O Cdigo de Classe in-line Permite Modificaes ............................977
Fu n e s d e Cl a s s e s Co m u n s
Compreendendo o Armazenamento E st tic o .......................................978
Com preendendo as Funes C o n s tru to ra s.......................................921 E/S COM C + +
Usando Funes Construtoras com P a r m e tro s..............................922
Usando uma Funo C o n stru to ra....................................................... 923 Sincronizando as Operaes de Canal de E/S com std io ...................979
Compreendendo Q uando um Programa Executa uma Compreendendo os Canais de E/S de C + + ...................................... 980
C o n stru to ra..............................................................................................924 Com preendendo os Canais de Sada de C + + .................................... 981
Usando Funes Construtoras com P a r m e tro s..............................925 Com preendendo os Canais de Entrada de C + + ................................982
Resolvendo os Conflitos de Nomes em uma Funo Usando os M embros ios para Formatar a Entrada e a S a d a ......... 983
C o n stru to ra..............................................................................................926 Definindo os Sinalizadores de F o rm a to ............................................. 984
Usando uma Construtora para Alocar M e m ria..............................927 Lim pando os Sinalizadores de F o rm a to ............................................. 985
Tratando a Alocao de Memria de um M odo Mais Claro . . . . 928 Usando a Funo setf S obrecarregada.................................................. 986
Valores de Parmetro Padro para as C onstrutoras......................... 929 Examinando os Sinalizadores de Formatao A tu a is ......................... 987
S um rio XIII

Definindo Todos os Sinalizadores.......................................................... 988 Derivando uma C la s se ............................................................................ 1050


Usando a Funo precisio n ......................................................................989 Com preendendo as Construtoras Base e Derivada ..........................1051
Usando a Funo f il................................................................................. 990 Pondo os Membros Protegidos em Uso ............................................1052
Com preendendo os Manipuladores ...................................................... 991 Compreendendo Q uando Usar os M embros P ro te g id o s................ 1053
Usando Manipuladores para Formatar a E/S ..................................... 992 Revisando a Herana de Classe-base Pblica ou P riv a d a................ 1054
Com parando os M anipuladores e as F u n es-M em b ro ................... 993 Com preendendo a Herana de Classe-base P ro te g id a .....................1055
Criando Suas Prprias Funes In se r o ra s.......................................... 994 Compreendendo a Herana Mltipla ................................................ 1056
Sobrecarregando o Operador de E xtrao............................................ 995 U m a Herana Mltipla Simples ..........................................................1057
O utro M odo de Sobrecarregar o O perador de Insero de Compreendendo a Ordem das Construtoras e as Classes-base . . 1058
c o u t ...............................................................................................................996 Declarando uma Classe-base Como Privada ..................................... 1059
Criando Suas Prprias Funes E x tra to ra s.......................................... 997 Funes Destrutoras e Herana M ltipla............................................1060
Criando um Exemplo de E x trato ra........................................................ 998 Conflitos de Nomes entre as Classes Base e D eriv ad a.................. 1061
Criando Sua Prpria Funo M a n ip u la d o ra........................................999 Resolvendo Conflitos de Nome de Classe e de B a s e .....................1062
Criando M anipuladores sem Parmetros ....................................... 1000 Com preendendo Q uando as Classes Herdadas Executam as
Usando Parmetros com M anipuladores......................................... 1001 C onstrutoras............................................................................................. 1063
Com preendendo a Antiga Biblioteca de Classes de Canais . . . . 1002 Exemplo de um a Construtora de Classe H e rd a d a ............................ 1064
Abrindo um Canal de A rq u iv o ......................................................... 1003 Com o Passar Parmetros para as Construtoras de Classe-base . . . 1065
Fechando um Canal de A rq u iv o ....................................................... 1004 Com preendendo as Declaraes de Acesso com as Classes
Lendo e Gravando Dados do Canal de Arquivo ......................... 1005 D eriv ad as.................................................................................................. 1066
Verificando o Status de um a Operao de A rq u iv o .....................1006 Usando Declaraes de Acesso com as Classes D erivadas........... 1067
Juntando as Operaes de Canal de A rq u iv o ................................ 1007 Evitando Ambigidade com as Classes-base V irtuais.................... 1068
Efetuando um a Operao de Cpia B in ria .................................. 1008 Com preendendo as Classes-base V irtu ais........................................... 1069
Com preendendo a Classe stream b u f................................................ 1009 Amigas M tuas .......................................................................................1070
Escrevendo um Exemplo Simples com stream buf......................... 1010 Como um a Classe Derivada Pode Tornar-se uma Classe-base . . 1071
Lendo Dados Binrios Usando r e a d ................................................ 1011 Usando M embros Protegidos nas Classes D eriv ad as.......................1072
Escrevendo Dados Binrios Usando write .....................................1012 Definindo Dados de Classe Esttica .................................................. 1073
Usando a Funo-membro g c o u n t.................................................. 1013 Inicializando um Dado-M embro E s t tic o ...................................... 1074
Usando as Funes get Sobrecarregadas......................................... 1014 Acesso Direto de um Dado-M embro E sttico ...................................1075
Usando o M todo g e tlin e .................................................................. 1015 Compreendendo os Dados-M embro Privados Estticos ................ 1076
Detectando o Final do Arquivo ....................................................... 1016 Com preendendo as Funes-M embro E stticas................................ 1077
Usando a Funo ig n o re .....................................................................1017 Acesso Direto de uma Funo Esttica P b lic a ................................ 1078
Usando a Funo p e e k ....................................................................... 1018 Usando Tipos Expandidos Com o M embros da C la s s e .................. 1079
Usando a Funo putback ................................................................ 1019 E m butindo um a Classe D entro de O utra . . . .'................................ 1080
Encontrando a Posio Atual no Canalde A rq u iv o ......................1020 Com preendendo Subclasses e Superclasses......................................... 1081
Controlando o Ponteiro de Canal de A rq u iv o ............................... 1021 Com andos em Linguagem Assembly In-line em uma Funo
Usando seekg e seekp para Acesso A leatrio .................................. 1022 M todo .................................................................................................... 1082
M anipulando a Posio do Ponteiro de Arquivo D entro de Os M embros de Classe Podem Ser Recursivos ................................1083
um A rquivo............................................................................................1023 Compreendendo o Ponteiro t h i s .........................................................1084
Determ inando o Status Atual de um Canal de E / S .....................1024 Como o Ponteiro this Difere dos Outros Ponteiros .......................1085
Com preendendo as Classes de E/S de M a triz ................................ 1025 Compreendendo a Amarrao Precoce ou T a r d ia ........................... 1086
Com preendendo os Canais de String de C a racteres.....................1026 Ponteiros para Classes ........................................................................... 1087
Usando istrstream para Escrever um a String de Caracteres . . . . 1027 Usando o Mesmo Ponteiro para Diferentes Classes......................... 1088
Com preendendo M elhor o strstre a m ................................................ 1028 Conflitos de N om e Derivado e Base com P o n te iro s........................ 1089
Usando as Formas istrstream Sobrecarregadas ..............................1029 Com preendendo as Funes V irtu ais.................................................. 1090
Usando pcount com Matrizes de Sada ......................................... 1030 H erdando o Atributo V irtu a l................................................................ 1091
Manipulando Matrizes de Canais com as Funes- As Funes Virtuais So H ierrq u ic as................................................1092
M embro ios ......................................................................................... 1031 Implementando o Polimorfismo ......................................................... 1093
Usando strstream ................................................................................ 1032 Compreendendo as Funes Virtuais P u ra s.......................................1094
Efetuando Acesso Aleatrio D entro de uma Matriz stream . . . . 1033 Compreendendo as Classes A bstratas.................................................. 1095
Usando Manipuladores com Matrizes s tre a m ................................ 1034 Usando Funes V irtu a is.......................................................................1096
Usando um O perador de Insero Personalizado com as Mais sobre Amarrao Precoce ou T a r d i a ......................................... 1097
Matrizes S t r i n g ................................ .................................................... 1035 Decidindo entre a Amarrao Precoce e T a rd ia ................................ 1098
Usando Operadores de Extrao Personalizados com as U m Exemplo de Amarrao Precoce e Amarrao T a rd ia .............. 1099
Matrizes stre a m .....................................................................................1036 Definindo um M anipulador de Canal de S ada................................ 1100
Usando Matrizes Dinmicas com Canais de E / S ......................... 1037 H ora de Dar um a O lhada em iostream.h ..................................1101
Com preendendo os Usos para a Formatao da Matriz Usando sizeof com um a Classe ........................................................ 1102
s tr e a m .....................................................................................................1038 As Palavras-chave Private, Public e Protected Tambm
Com preendendo o M anipulador ends ............................................1039 Podem Ser Aplicadas s Estruturas .................................................... 1103
Cham ando um O bjeto a partir de O u t r o .......................................1040 Compreendendo as Converses de Classes .......................................1104
Falando ao Com pilador sobre um a Classe .....................................1041 Convertendo Dados em uma C o n stru to ra......................................... 1105
Revisitando as A m igas......................................................................... 1042 Atribuindo uma Classe a O u tr a ........................................................... 1106
Declarando a Classe Leitor Como uma A m ig a..............................1043 Use Amigas para a C o n v e rs o ..............................................................1107
O utro Exemplo de Classe A m ig a .....................................................1044 Determinando Q uando os Operadores Aumentam ou
Eliminando a Necessidade do Com ando class nome_classe . . . . 1045 Reduzem a Legibilidade.........................................................................1108
Restringindo o Acesso a uma Amiga ..............................................1046 F u n e s G e n r ic a s e G a b a r it o s
Conflito de Nomes e A m ig a s............................................................1047
Herana e Polimorfismo Compreendendo os G a b a rito s..............................................................1109
Colocando um Gabarito Simples em U s o .........................................1110
Herana em C + + .................................................................................. 1048 Compreendendo M elhor as Funes G enricas................................ 1111
Compreendendo as Classes Base e D erivada.................................. 1049 Gabaritos Q ue Suportam Mltiplos Tipos ...................................... 1112
XIV P ro g r am a n d o em C/C++ A B b l ia

Mais sobre Gabaritos com Mltiplos Tipos G enricos................1113 Sobrecarregando os Operadores Relacionais .....................................1171
Sobrecarregando Explicitamente uma Funo G e n ric a ..............1114 Determinando o Tam anho de um Objeto Strings .........................1172
Com preendendo as Restries nas Funes G en ric a s................ 1115 Convertendo um O bjeto Strings para uma Matriz de
Usando um a Funo G e n ric a .........................................................1116 Caracteres..................................................................................................1173
Usando uma Funo Genrica do Algoritmo da B o l h a .............. 1117 Usando um Objeto Strings Com o uma Matriz de Caracteres . . . 1174
Usando Funes Genricas para Compactar um a M a triz ........... 1118 Demonstrando o O bjeto S trin g s .........................................................1175
O nde Colocar os Gabaritos ..............................................................1119 Criando um Cabealho para a Classe Strings ..................................1176
Os Gabaritos Tambm Eliminam as Classes D u p lic a d a s........... 1120 O utro Exemplo de S trin g s.................................................................... 1177
Compreendendo as Classes G enricas..............................................1121 Usando uma Classe de C++ para Criar uma Lista
Usando Classes G en ricas.................................................................. 1122 Duplam ente L ig a d a ................................................................................1178
Criando uma Classe Genrica com Dois Tipos de Dados Compreendendo os M embros da Classe d b llin k o b ...................... 1179
Genricos ..............................................................................................1123 Com preendendo as Funes pegaproximo e pegaanterior........... 1180
Criando um M anipulador P aram etrizado.......................................1124 Com preendendo as Funes de Sobrecarga o p e ra to r.................... 1181
Criando um a Classe de Matriz Genrica .......................................1125 H erdando a Classe L ista_ O b jeto .........................................................1182
Com preendendo a Classe lista_ligada ............................................. 1183
Tratamento das Excees e Portabilidade de Tipo
Compreendendo a Funo armazena da lista_ligada.................... 1184
Com preendendo o Tratam ento das E xcees................................ 1126 Com preendendo a Funo remove de lista_ligada.........................1185
Com preendendo a Forma de Tratam ento Bsico da Exceo . . . 1127 Com preendendo as Funes pegainicio e pegafim ...................... 1186
Escrevendo um a Rotina de Tratam ento de Exceo Simples . . . 1128 Exibindo a lista_ligada na O rdem do Comeo para o F i m .........1187
Com preendendo o Com ando th r o w ................................................ 1129 Exibindo a lista_ligada em O rdem Inversa ...................................... 1188
As Excees So de um T ipo Especfico......................................... 1130 Pesquisando a Lista ................................................................................1189
Lanando Excees a partir de uma Funo D entro de um Im plementando um Programa Iista_Ligada Simples .......................1190
Bloco t r y ................................................................................................1131 Criando um a Classe de Lista Duplam ente Ligada Genrica . . . . 1191
Localizanda um Bloco try para uma Funo ................................ 1132 Com preendendo os M embros Genricos da Classe
Compreendendo Q uando o Programa Executa c a tc h .................. 1133 lista_objeto................................................................................................1192
Usando M ltiplos Com andos catch com um nico Bloco try . 1134 Com preendendo a Classe lista_ligada G e n ric a .............................1193
Usando o Operador Reticncias (...) com as E xcees................ 1135 Usando as ClassesGenricas com um a Lista c h a r ............................ 1194
Pegando Todas as Excees D entro de um nico Bloco try . . . 1136 Usando as ClassesGenricas com um a Lista D u p l a ........................1195
Pegando Excees Explcitas e Genricas em um nico Usando as ClassesGenricas com uma E s tr u tu r a ............................ 1196
Bloco t r y ................................................................................................1137 Sobrecarregando o Operador de Comparao == ......................... 1197
Restringindo as Excees .................................................................. 1138 O utras Melhorias na Lista Genrica .................................................. 1198
Relanando um a E x c e o .................................................................. 1139 Usando Objetos com a Funo a rm a z e n a ......................................... 1199
Aplicando o Tratam ento da Exceo ..............................................1140 Escrevendo uma Funo para Determinar o Comprimento
Usando Argumentos Padro de F u n o ......................................... 1141 da Lista ......................................................................... .......................... 1200
Evitando Erros com Argumentos de Funo Padro .................. 1142 B ib l io t e c a d e G a b a r it o s p a d r e s
Argumentos Padro versus Sobrecarga de F u n o ......................... 1143
Criando Funes de Converso .......................................................1144 Introduzindo a Biblioteca de Gabaritos P a d r e s ..............................1201
Usando Funes de Converso para Aum entar a Compreendendo os Arquivos de Cabealho da Biblioteca de
Portabilidade de T i p o ......................................................................... 1145 Gabaritos Padres ..................................................................................1202
Funes de Converso versus Operadores Sobrecarregados......... 1146 Compreendendo os R ep o sit rio s.........................................................1203
Com preendendo os Novos Operadores de Converso de C++ . . 1147 Usando um Exemplo de R epositrio..................................................1204
Usando o Operador co n st_ cast......................................................... 1148 Apresentando os Repositrios da Biblioteca de Gabaritos
Usando o O perador d y n am ic_ cast.................................................. 1149 P adres...................................................................................................... 1205
Usando o O perador reinterpret_cast................................................1150 Compreendendo os Repositrios Forward e Reversible................1206
Usando o O perador static_ cast.........................................................1151 Compreendendo os Repositrios de Seqncia da Biblioteca
Compreendendo os N am espaces.......................................................1152 de Gabaritos P a d r e s...........................................................................1207
Usando N am esp aces........................................................................... 1153 Compreendendo o Com ando using namespace s t d .........................1208
Usando o Com ando using com namespace .................................. 1154 Compreendendo os Repositrios Associativos da Biblioteca
Com preendendo a Identificao de T ipo em T em po de de Gabaritos P a d r e s...........................................................................1209
E x ecu o ............................................................................................... 1155 Compreendendo os Iterad o res............................................................. 1210
Usando typeid para a Identificao de Tipo em Tem po de Usando um Exemplo de Iterador .......................................................1211
E xecuo................................................................................................1156 Compreendendo M elhor os Tipos de Iterador de Entrada
Compreendendo a Classe ty p e _ in fo ................................................1157 e Sada da Biblioteca de Gabaritos Padres (ST L ).........................1212
Compreendendo a Palavra-chave m u tab le.......................................1158 Compreendendo os O utros Tipos de Iteradores da Biblioteca
Usando a Palavra-chave mutable D entro de uma Classe ........... 1159 de Gabaritos P a d r e s...........................................................................1213
Consideraes sobre a Palavra-chave m u ta b le ................................ 1160 Compreendendo os C o n c eito s............................................................. 1214
Introduzindo o T ipo de Dados bool ..............................................1161 Compreendendo os M o d e lo s............................................................. 1215
Usando o T ipo de Dados b o o l ......................................................... 1162 Compreendendo os A lg o ritm o s........................................................ 1216
Criando exemplos de classes reutilizveis
Usando O utro Exemplo de Algoritmo da Biblioteca de
Gabaritos Padres ............................................................................... 1217
Criando um T ipo S trin g .....................................................................1163 Descrevendo os Algoritmos Q ue a STL Inclui ............................. 1218
Definindo as Caractersticas do T ipo S trin g .................................. 1164 Estudando o Algoritmo for_each da S T L ...................................... 1219
Criando a Classe S trin g s.....................................................................1165 Estudando o Algoritmo generate_n da STL ..................................1220
Escrevendo as Construtoras para a Classe S trin g s......................... 1166 Compreendendo o Algoritmo random _shuffle da S T L .................1221
Efetuando E/S com a Classe S trin g s................................................ 1167 Usando o Algoritmo partial_sort_copy ...........................................1222
Escrevendo as Funes de Atribuio para a Classe Strings . . . . 1168 Compreendendo o Algoritmo m e rg e ............................................... 1223
Sobrecarregando o Operador + para Concatenar Objetos Compreendendo o Algoritmo inner_product .................................. 1224
S trin g s.....................................................................................................1169 Compreendendo M elhor os Vetores ............................................... 1225
Removendo uma String a partir de D entro de um Objeto Usando O utro Programa Simples de V e to r .......................................1226
S trin g s.................................................................................................... 1170 Com parando os Vetores com as Matrizes de C ............................. 1227
S umrio XV

Com preendendo o Repositrio de Seqncia bit_vector ........... 1228 Compreendendo o Fluxo de Mensagens ........................................... 1289
Usando um Exemplo bvector sim ples..............................................1229 Compreendendo M elhor os Com ponentes da Estrutura
Com preendendo o T ipo l i s t ..............................................................1230 MSG .........................................................................................................1290
Com preendendo os Com ponentes Genricos do Compreendendo a Funo PeekM essage........................................... 1291
Repositrio list .....................................................................................1231 Compreendendo a Funo PostMessage ...........................................1292
Construindo um O bjeto l i s t ..............................................................1232 Compreendendo a Funo SendM essage...........................................1293
Inserindo Objetos na L is t a ................................................................ 1233 Usando a Funo ReplyMessage .........................................................1294
Usando a Funo-M em bro assign.....................................................1234 Ganchos de M e n sag en s.......................................................................1295
Usando as Funes-M embro remove e em pty ..............................1235 Usando a Funo SetW indow sH ookEx........................................... 1296
Percorrendo o O bjeto l i s t .................................................................. 1236 Compreendendo a Funo ExitWindowsEx ..................................1297
Compreendendo o T ipo slist ........................................................... 1237 Compreendendo os Tipos de M enu ................................................1298
Compreendendo as Inseres D entro de um Repositrio de Compreendendo a Estrutura de um M e n u .................................... 1299
Seqncia s lis t....................................................................................... 1238 Criando um M enu Dentro de um Arquivo de Recurso ............. 1300
Compreendendo o Repositrio deque ............................................1239 Com preendendo os Descritores PO PU P e M E N U IT E M ........... 1301
Usando o Repositrio d e q u e ..............................................................1240 Acrescentando um M enu Janela de um A p licativ o .................... 1302
Usando as Funes-membro erase e c le a r....................................... 1241 Alterando os M enus D entro de um A p licativ o ..............................1303
Usando o Operador de Matriz [] com um d e q u e ......................... 1242 Com preendendo as Mensagens Geradas por M e n u s ....................... 1304
Usando os Iteradores reverse com um d e q u e ................................ 1243 Com preendendo a Funo LoadMenu ..............................................1305
Gerenciando o Tam anho do deque ................................................ 1244 Usando a Funo M odifyM enu...........................................................1306
Compreendendo o Objeto map ....................................................... 1245 Usando EnableM enuItem para Controlar os M e n u s.....................1307
Um Exemplo Simples de map ......................................................... 1246 Usando AppendM enu para Expandir um M e n u ............................. 1308
Usando Funes M embro para Gerenciar o M ap .......................1247 Usando DeleteM enu para Excluir Selees do M e n u .................. 1309
Controlando o Tam anho e o Contedo do M a p ......................... 1248 Usando Teclas Aceleradoras com Itens de M e n u ........................... 1310
Com preendendo os sets .....................................................................1249 Criando um a Tabela Aceleradora de E xem plo ............................... 1311
Um Exemplo Simples de s e t ..............................................................1250 Com preendendo M elhor a Estrutura do Arquivo de Recurso . . . 1312
Apresentando as Tabelas de String ................................................. 1313
In t r o d u o P r o g r a m a o W i n d o w s
Com preendendo os Recursos Personalizados..................................1314
Introduzindo a Programao em W in32 ....................................... 1251 Carregando Tabelas de String nos Programas com LoadString .. 1315
Mais Diferenas entre os Programas W indows e D O S ..............1252 Listando o Contedo de um Arquivo de R ecu rso .........................1316
Introduzindo os E ncadeam entos.......................................................1253 Usando EnumResourceTypes com Arquivos de R ecursos..............1317
Com preendendo as M ensagens......................................................... 1254 Carregando Recursos em Programas com F indR esource................1318
Compreendendo os Componentes de uma Janela ....................... 1255 C a ix a s d e D i l o g o
Compreendendo as Janelas-me e as Janelas-filha......................... 1256
Criando um Programa W indows Genrico .................................. 1257 Com preendendo as Caixas de Dilogo ..............................................1319
Com preendendo os Arquivos de R e c u rs o s.....................................1258 Definindo os Tipos de D i lo g o ........................................................... 1320
Com preendendo os Indicativos do W in d o w s................................ 1259 Usando o Teclado com Caixas de Dilogo ....................................... 1321
Definindo os Tipos de Indicativo do W in d o w s ........................... 1260 Compreendendo os Com ponentes do Gabarito da Caixa
Com preendendo o Arquivo de Cabealho G enrico.....................1261 de D i lo g o ................................................................................................1322
Com preendendo as Funes Callback ........................................... 1262 Criando um Gabarito de Caixa de Dilogo E sp ecfico .................. 1323
Apresentando a Interface de Programao de Aplicativos Com preendendo os Com ponentes da Definio da Caixa de
do W in d o w s ......................................................................................... 1263 Dilogo .................................................................................................... 1324
Examinando M elhor o Programa generico.C P P ............................1264 Definindo os Controles da Caixa de Dilogo .................................. 1325
Com preendendo a Funo W in M a in ..............................................1265 Usando a Macro DialogBox para Exibir uma Caixa de Dilogo . . 1326
Com preendendo a Criao de J a n e l a ..............................................1266 Com preendendo o Lao de Mensagem da Caixa de Dilogo . . . 1327
Com preendendo a Funo C reateW indow .....................................1267 Mais sobre a Manipulao de Controles ........................................... 1328
Com preendendo a Funo ShowW indow .....................................1268 Com preendendo a Macro CreateDialog ........................................... 1329
Com preendendo a Funo RegisterClass .......................................1269 Com preendendo a Funo C reateD ialogParam ................................1330
Aprendendo Mais sobre as M en sag en s............................................1270 Processamento de Mensagem Padro D entro de uma Caixa
Usando TranslateMessage para Processar as M ensagens..............1271 de D i lo g o ................................................................................................ 1331
Usando DispatchMessage para Processar as M e n sag en s..............1272 Usando a Funo DlgDirList para Criar uma Caixa de
Com preendendo os Com ponentes de um Programa Lista de D ilo g o .......................................................................................1332
W indows S im p le s................................................................................ 1273 Respondendo s Selees do Usurio D entro da Caixa
Com preendendo o T ipo L P C T S T R ................................................ 1274 de Lista .................................................................................................... 1333
Compreendendo o Tipo D W O R D ................................................ 1275 Fechando a Caixa de Dilogo ..............................................................1334
Compreendendo as Classes Predefinidas do W in d o w s................ 1276 Compreendendo a Entrada do U s u rio ..............................................1335
Usando Classes Predefinidas para Criar um a Janela Simples . . . 1277 Respondendo aos Eventos do M o u se ..................................................1336
O W indows Envia W M _CREA TE Q uando Cria um a Janela . . 1278 Usando a Mensagem W M _M O U S E M O V E .................................... 1337
Com preendendo os Estilos W indow e Control ........................... 1279 Lendo os Botes do M o u s e ..................................................................1338
Criando Janelas com Estilos E ste n d id o s......................................... 1280 Respondendo aos Eventos do T e c la d o ................................................1339
D estruindo Janelas ..............................................................................1281 Compreendendo as Teclas V ir tu a is .................................................... 1340
Com preendendo a Funo da API R egisterC lassEx.....................1282 Usando as Teclas V ir tu a is .....................................................................1341
Anexando Informaes em um a Janela com S e tP ro p .................. 1283 Mais sobre o Uso da Mensagem W M _K EY D O W N .....................1342
Usando EnumProps para Listar as Propriedades de uma Definindo e Retornando o T em po do Clique Duplo no
Janela .....................................................................................................1284 Mouse ...................................................................................................... 1343
Com preendendo as Funes de C a llb a c k ....................................... 1285 Perm utando os Botes do Mouse ...................................................... 1344
Compreendendo a Funo M essageB ox......................................... 1286 Determ inando se o Usurio Pressionou um a T e c la .........................1345
Com preendendo a Funo MessageBeep .......................................1287 Apresentando as Barras de Rolagem .................................................. 1346
Compreendendo os Diferentes Tipos de Barra de Rolagem . . . . 1347
Mensa gen s e Menu s
Usando a Funo ShowScroIIBar......................................................... 1348
Revisitando as M ensagens.................................................................. 1288 Compreendendo a Posio e a Faixa da Barra de R olagem ......... 1349
XVI P ro g ram a n d o em C/C+ + A B b l ia

Com preendendo as Mensagens da Barra de R olagem .................. 1350 Usando um a Seo Crtica S im p le s..................................................... 1407
O b ten d o as Definies Atuais da Barra de Rolagem .................. 1351 Usando W aitForSingleObject para Sincronizar Dois
Rolando o Contedo da Ja n e la .........................................................1352 Encadeamentos ....................................................................................... 1408
C om preendendo a Mensagem W M _ S IZ E .....................................1353 Usando W aitForM ultipleObject para Sincronizar Muitos
Com preendendo a Mensagem W M _ P A IN T ................................ 1354 Encadeamentos ....................................................................................... 1409
O utras Mensagens da Barra de Rolagem Q ue Seus Criando um M u t e x ..............................................................................1410
Programas Podem Capturar ..............................................................1355 Usando um M utex D entro de um Programa de Exemplo ......... 1411
Habilitando e Desabilitando as Barras de Rolagem .....................1356 Usando S em foros................................................................................1412
Usando a Funo ScrollDC ..............................................................1357 Usando um Processador de Evento Simples .................................. 1413
Com preendendo a Interface de Dispositivo G r fic o .................... 1414
G e r e n c ia m e n t o d a M e m r ia n o W in d o w s
Razes para Usar a Interface de Dispositivo G r fic o .................... 1415
Com preendendo o Modelo de Memria W in32 ......................... 1358 Com preendendo M elhor os Dispositivos do C o n te x to ................1416
Com preendendo a M em ria Global e a L o c a l..............................1359 Usando Dispositivos do Contexto P rivados.....................................1417
Com preendendo a M em ria V irtu a l................................................ 1360 Com preendendo as Origens e as E xtenses.....................................1418
Revisitando os H e a p s ......................................................................... 1361 O btendo o Dispositivo de Contexto para um a J a n e la .................. 1419
Alocando um Bloco de M emria a partir do Heap Global . . . . 1362 Criando um Dispositivo do Contexto para um a Impressora . . . . 1420
Usando GlobalRealloc para Alterar Dinamicamente os Usando CreateC om patibleD C para Criar um Dispositivo do
Tamanhos do Heap ............................................................................1363 Contexto em Memria .......................................................................1421
Descartando um Bloco de Memria A lo cad o ................................ 1364 Com preendendo os Perigos de C r e a te D C .......................................1422
Usando a Funo G Io b alF ree............................................................1365 Usando a Funo CreateFont ........................................................... 1423
Usando GlobalLock e GlobalHandle ..............................................1366 Usando a Funo E n u m F o n tF am ilies..............................................1424
Verificando a Memria do C om putador .......................................1367 Exibindo Mltiplas Fontes com C reateF o n tln d ire ct.................... 1425
Criando um Heap Dentro de um Processo .................................. 1368 Recuperando as Capacidades de um D ispositivo ........................... 1426
Usando as Funes do Heap para Gerenciar a M emria Usando a Funo GetSystemMetrics para Analisar uma
Especfica do Processo......................................................................... 1369 J a n e la .......................................................................................................1427
Verificando o Tam anho da Memria Alocada a partir Com preendendo os Usos para G etSystem M etrics......................... 1428
de um Heap ......................................................................................... 1370 O btendo um Dispositivo do Contexto para um a Janela
Alocando um Bloco de Memria V ir tu a l.......................................1371 Inteira .................................................................................................... 1429
Com preendendo as Pginas de Guarda ......................................... 1372 Liberando os Dispositivos do C o n te x to ........................................... 1430
Com preendendo M elhor os Blocos de M em ria V irtuais........... 1373 BlTMAPS, META-ARQUIVOS E CONES
Liberando Memria Virtual ..............................................................1374
Gerenciando as Pginas de Memria V ir tu a l................................ 1375 O btendo um Indicativo de uma Janela a partir do Dispositivo do
Contexto ...................................................................................................1431
P r o c e s s o s e En ca d ea m en to s
Compreendendo os Mapas de Bits Dependentes do
Com preendendo M elhor os Processos ........................................... 1376 D ispositivo................................................................................................ 1432
Criando um P ro c e ss o .........................................................................1377 Compreendendo os Mapas de Bits Independentes do
Term inando os P ro c esso s.................................................................. 1378 D ispositivo................................................................................................ 1433
G erando Processos-filho .................................................................... 1379 Criando Mapas de Bits ......................................................................... 1434
Trabalhando Mais com os Processos-filho .....................................1380 Exibindo Mapas de B its......................................................................... 1435
Rodando Processos-filho D estacados................................................1381 Criando Mapas de Bits na M e m ria .................................................. 1436
Compreendendo M elhor os Encadeam entos.................................. 1382 Preenchendo um Retngulo com um Padro .................................. 1437
Avaliando a Necessidade de E ncadeam entos.................................. 1383 Usando SetDIBits ...................................................................................1438
Determ inando Q uando N o Criar um E ncadeam ento................ 1384 Usando SetDIBitsToDevice para Exibir um Mapa de Bits
Criando um a Funo Simples de E n cad eam en to ......................... 1385 em um D eterm inado Dispositivo ....................................................... 1439
Visualizando a Iniciao do Encadeamento .................................. 1386 Com preendendo os Meta-arquivos .....................................................1440
Passos Q ue o Sistema Operacional Efetua na Criao do Criando e Exibindo M eta-arq u iv o s..................................................... 1441
E ncadeam ento.......................................................................................1387 Enumerando os Meta-arquivos E xpandidos....................................... 1442
D eterm inando o Tam anho da Pilha do E n cad eam en to ..............1388 Usando a Funo G etW inM etaFileB its..............................................1443
O btendo um Indicativo para o Processo ou o Encadeamento Compreendendo os c o n e s.....................................................................1444
A t u a l ...................................................................................................... 1389 Criando cones ....................................................................................... 1445
T ratando o T em po de Processamento do E ncadeam ento........... 1390 Criando cones a partir de um R ecurso.............................................. 1446
Gerenciando o Tem po de Processamento de Mltiplos Usando a Funo Createlconlndirect ................................................ 1447
E n cad eam en to s.................................................................................... 1391 Usando a Funo L o ad lco n ...................................................................1448
C om preendendo M elhor a Funo GetQueueStatus .................. 1392 Usando Loadlmage para Carregar Mltiplos Tipos Grficos . . . 1449
T ratando as Excees N o -tratadas.................................................. 1393 E /S n o W in d o w s
Term inando os Encadeamentos .......................................................1394
Determ inando a Identificao de um Encadeamento ou de Compreendendo a E/S em Arquivos no W in d o w s ....................... 1450
um Processo .........................................................................................1395 Apresentando as Canalizaes, Recursos, Dispositivos e
Compreendendo Com o o Sistema Operacional Escalona os A rquivos.................................................................................................. 1451
E ncadeam entos.................................................................................... 1396 Usando a Funo CreateFile para Abrir A rq u iv o s......................... 1452
Apresentando os Nveis de Prioridade ........................................... 1397 Usando CreateFile com Diferentes D isp o sitiv o s............................1453
Compreendendo as Classes de Prioridade do W in d o w s..............1398 Usando Indicativos de A rq u iv o ......................................................... 1454
Alterando a Classe de Prioridade de um Processo ....................... 1399 Revisitando os Ponteiros de A rq u iv o ................................................1455
Definindo a Prioridade Relativa de um Encadeamento ..............1400 Usando WriteFile para Escrever em um Arquivo ......................... 1456
O btendo o Nvel de Prioridade Atual de um Encadeamento . . . 1401 Usando ReadFile para Ler a partir de um A rq u iv o .......................1457
O btendo o Contexto de um E ncadeam ento .................................. 1402 Fechando o Arquivo ........................................................................... 1458
Fazendo um a Pausa e Reiniciando os E ncad eam en to s................ 1403 Com partilhando Dados com o M apeamento de Arquivos ......... 1459
Com preendendo a Sincronizao de E ncadeam entos.................. 1404 M apeando um Arquivo com a Memria V irtu a l............................1460
Definindo os Cinco Principais Objetos de Sincronizao ......... 1405 M apeando um a Exibio de um Arquivo no Processo Atual . . . 1461
Criando um a Seo C rtic a ................................................................ 1406 Abrindo um O bjeto de Mapeamento de Arquivo Nom eado . . . . 1462
S um rio XVII

Com preendendo os Atributos de Arquivo .....................................1463 Conectando uma Canalizao N o m e a d a ............................................ 1482
O btendo e Alterando os Atributos de um Arquivo .....................1464 Chamando uma Canalizao N o m e a d a .............................................. 1483
O btendo o Tam anho de um A rquivo..............................................1465 Desconectando uma Canalizao N o m e a d a ....................................... 1484
O btendo a D ata e a H ora de um A rq u iv o .....................................1466 Compreendendo M elhor o Processamento A ssn cro n o ...................1485
Criando D ire t rio s ..............................................................................1467 Usando Entrada e Sada A ssncrona.....................................................1486
O btendo e D efinindo o D iretrio A tu a l......................................... 1468 Compreendendo a Estrutura O V E R L A P P E D ...................................1487
O btendo os Diretrios W indows e System .....................................1469 E/S Assncrona com um Objeto de Ncleo do Dispositivo . . . . 1488
Removendo Diretrios ....................................................................... 1470 Compreendendo as Quotas de Tam anho do W orking S e t ............ 1489
Copiando A rq u iv o s..............................................................................1471 Definindo Quotas Maiores e M enores................................................ 1490
Movendo e Renomeando A rquivos.................................................. 1472 Com preendendo a Funo G etL astE rro r............................................ 1491
Apagando A rq u iv o s..............................................................................1473 Formatando as Mensagens de Erro com FormatMessage ........... 1492
Usando FindFirstFile para Localizar Arquivos ..............................1474 E/S Assncrona com um Objeto Evento do Ncleo .................... 1493
Usando F in d N e x tF ile ......................................................................... 1475 Usando W aitForM ultipleObjects com E/S A s sn c ro n a ................1494
Fechando o Indicativo de Pesquisa com F in d C lo s e .....................1476 Apresentando as Portas de Finalizao de E / S ................................... 1495
Pesquisando por Atributos com as Funes F in d F ile .................. 1477 Usando E/S Alertvel Para o Processamento A ssn cro n o ................ 1496
Usando SearchPath em Vez de Find para L o calizar.....................1478 A E/S Alertvel Somente Funciona no W indows N T ..................... 1497
O btendo um Cam inho T e m p o r rio ................................................ 1479 Usando ReadFileEx e W riteFileE x....................................................... 1498
Criando Arquivos Temporrios ....................................................... 1480 Usando uma Rotina de Callback de F inalizao...............................1499
Introduzindo a Funo C reateN a m e d P ip e.....................................1481 Usando um Programa de E/S A lertvel.............................................. 1500
S o bre o CD-ROM

Alm do cdigo do programa para todas as dicas deste livro, o CD -RO M que acompanha este livro tam
bm inclui o compilador Borland Turbo C++ Lite, que voc pode usar para comear a escrever programas C++
imediatamente.

T u r b o C + + L it e
Para lhe ajudar a iniciar com a programao em C++, a Borland International permitiu que inclussemos o com
pilador Turbo C++ Lite no CD-ROM .
Como voc aprender, esse compilador um programa baseado no MS-DOS. Se voc estiver usando o
Windows, poder rodar o compilador Turbo C++ Lite dentro de uma janela do DOS.
O Turbo C++ Lite um compilador completo que voc pode usar para comear a escrever programas C
e C++. Na verdade, voc ter condies de escrever seu primeiro programa 10 minutos depois de comear a ler
este livro. O Turbo C++ Lite um compilador baseado no MS-DOS que lhe permite:
Criar e editar seus programas C++, salvando os comandos em um arquivo-fonte no disco.
Compilar os comandos do seu programa e gerar um arquivo executvel.
Compilar a maior parte dos programas que este livro apresenta em suas primeiras 1200 dicas.
O CD -RO M que acompanha este livro inclui instrues completas sobre como instalar e comear a usar
o compilador Turbo C++ Lite, esteja voc usando o Windows 3.1, Windows 95/98 ou o Windows NT.

A r q u i v o s -Fo n t e EM C E C + +
O CD-ROM inclui tambm o cdigo-fonte para todos os programas apresentados ou referenciados no livro. O disco
est dividido em 15 diretrios de cdigo, cada um na forma DicaXXXX, em que XXXX representa o nmero
da ltima dica apresentada dentro do diretrio. Alm disso, cada diretrio est dividido em um subdiretrio para
cada dica para que voc possa fcil e rapidamente localizar o cdigo-fonte para qualquer dica.

Para os programas referenciados mas no apresentados no livro, o cdigo-fonte contm comentrios para
conduzi-lo ao processamento de cada programa. Muitos diretrios de dicas tambm incluem arquivos MAKE
para simplificar seu acesso ao contedo do programa dentro desse diretrio.
I n tro duo lin g u a g em C 1

U m a In tr o d u o Pr o g r a m a o 1
Os programas de computador, tambm conhecidos como software, so formados por uma srie de instrues que
o computador executa. Quando voc cria um programa, precisa especificar as instrues que o computador pre
cisar executar para realizar as operaes desejadas. O processo de definir as instrues que o computador deve
executar conhecido como programao. Ao criar um programa, voc armazena as instrues em um arquivo ASCII
cujo nome normalmente contm a extenso C para um programa C, e CPP para um programa C++. Por exemplo,
caso voc crie um programa C que executa operaes de folha de pagamento, poderia chamar o arquivo que contm
as instrues do programa de folha. c. Quando voc cria programas, especifica as instrues desejadas usando uma lin
guagem de programao. C e C++ so somente duas dentre as muitas linguagens de programao que existem. Muitos
programadores usam linguagens de programao, tais como BASIC, Pascal e FORTRAN. Cada linguagem de pro
gramao oferece certos recursos exclusivos, e tem seus pontos fortes e fracos. Em todos os casos, as linguagens de pro
gramao existem para permitir que definamos as instrues que queremos que o computador execute.
As instrues que o computador executa so, na verdade, sries de ls e Os, (dgitos binrios) que represen
tam os sinais eletrnicos que ocorrem dentro do computador. Para programar os primeiros computadores (nos
anos 40 e 50), os programadores tinham que compreender como o computador interpretava diferentes combi
naes de ls e Os pois os programadores escreviam seus programas usando dgitos binrios. medida que os pro
gramas se tornaram maiores, tornou-se invivel trabalhar em termos de ls e Os do computador. Em vez disso,
os pesquisadores criaram as linguagens de programao, que permitem que as pessoas expressem as instrues do
computador de uma forma mais clara para os humanos. Aps os programadores colocarem suas instrues em
um arquivo (chamado arquivo-font), um segundo programa (chamado compilador) converte as instrues da lin
guagem de programao em ls e Os (conhecidas como linguagem de mquina) que o computador compreende.
Os arquivos no seu disco com as extenses EXE e C O M contm o cdigo de mquina (ls e Os) que o compu
tador executar. A Figura 1 ilustra o processo de compilar um arquivo de cdigo-fonte em um programa executvel.

Figura l 1 Um compilador converte instrues de cdigo-fonte em cdigo de mquina.

Aps voc criar um arquivo em cdigo-fonte, roda um compilador para converter as instrues em um for
mato que o computador possa executar. Por exemplo, se voc estiver usando o Borland Turbo C++ Lite1M (in
cludo no CD -RO M que acompanha este livro), voc usar a opo Compile to OBJ do menu Compile para
chamar o compilador (isto , instru-lo a compilar o cdigo-fonte). As dicas a seguir lhe conduziro nos passos
necessrios para criar e compilar um programa em C.

C r ia n d o u m A r q u iv o - F o n t e e m ASCII 2
Quando voc cria um programa, precisa colocar os comandos de programa que voc quer que o computador exe
cute em um arquivo chamado arquivo-fonte. Se voc no estiver usando o Turbo C++ Lite ou um compilador
completo com editor, dever criar seus arquivos de programas usando um editor ASCII, tal qual o programa
EDIT, fornecido junto com o DOS. Voc no dever criar os programas usando um editor de textos (tal qual o Mi
crosoft W ortP, ou o W ordPerfect da Corel). Como voc sabe, os processadores de texto permitem que voc for
mate os documentos atribuindo margens, italizando ou sublinhando as palavras, e assim por diante. Para
executar essas operaes, os processadores de texto incorporam caracteres especiais dentro de seus documentos.
Embora esses caracteres sejam compreensveis para o processador de texto, eles confundiro o compilador que

1. As figuras e tabelas deste livro esto num eradas de acordo com o nm ero da dica. No segue, portanto, um a
seqncia de numerao.
2 Programando em C/C++ A B b l ia

converte, o seu arquivo-fonte para cdigo de mquina e essa confuso provocar erros. Quando voc criar seu
arquivo-fonte, certifique-se de atribuir um nome significativo que descreva com exatido a funo do programa
para o arquivo. Por exemplo, voc poderia nomear o cdigo-fonte para um programa de faturamento como fa
tura. c, e o arquivo-fonte para um programa de jogo como futebol.c.
Por outro lado, se voc estiver usando um compilador que inclua um editor interno, dever criar seus pro
gramas dentro desse editor. Por exemplo, se voc estiver usando o Turbo C++ Lite, usar a opo New do menu
File para criar um novo arquivo de programa. Para criar seu primeiro programa dentro do Turbo C++ Lite,
acompanhe os seguintes passos:
t. Selecione a opo New no m enu File. O Turbo C++ Lite criar o arquivo nonameOO.cpp.
2. Digite o seguinte cdigo na janela nonameOO.cpp-.
#include <stdio.h>

void main(void)
{
printf ("Bblia do Programador C/C++, do Jamsa!");
}
3. Selecione a opo Save As no menu File. O Turbo C++ Lite exibir a caixa de dilogo Save File As.
4. Dentro da caixa de dilogo Save File As, digite o nome primeiro.c e pressione Enter. O Turbo
C++ Lite salvar o arquivo de programa primeiro.c.
Embora o programa primeiro.c contenha seis linhas, somente o comando p rin tf na verdade executa algum
trabalho. Quando voc executar esse programa, printfex.ibir a mensagem Bblia do Programador C/C++, do Jam
sa! na sua tela. Toda linguagem de programao (exatamente como as linguagens humanas, tais como portugus,
ingls, francs e alemo) tem um conjunto de regras, chamadas regras de sintaxe, s quais voc precisa obedecer
quando usar a linguagem. Ao criar programas C, voc deve obedecer s regras de sintaxe da linguagem C. Exem
plos de regras de sintaxe incluem os parnteses que seguem o nome main e o ponto-e-vrgula no final da instru
o p r in tf Quando voc digitar seu programa, precisa ter muito cuidado para no omitir algum desses
elementos. Confira sua digitao para garantir que voc tenha digitado as instrues do programa C exatamente
como j mostrado. Se as instrues estiverem corretas, salve o contedo do arquivo no seu disco. Na prxima
dica, voc aprender a compilar seu arquivo-fonte e a converter suas instrues de programao C na linguagem
de mquina que seu computador pode compreender e executar.

3 C o m p il a n d o S e u P r o g r a m a
N a dica anterior, voc criou o arquivo-fonte, primeiro.c, que contm o comando p rin tf que exibir a mensagem
Bblia do Programador C/C+ +, do Jamsa! na sua tela quando voc executar o programa. Um arquivo-fonte con
tm instrues em um formato que voc pode compreender (ou pelo menos poder compreender aps aprender
C). Um programa executvel, por outro lado, contm instrues expressas como ls e Os que o computador compreen
de. O processo de converter seu arquivo-fonte C em cdigo de mquina chamado compilao. Dependendo do com
pilador C que voc estiver usando, diferir o comando que voc precisa executar para compilar seu arquivo-fonte.
Assumindo que voc esteja usando o Turbo C++ Lite, da Borland, possvel compilar o programa {primeiro, c) que
voc criou na Dica 2, usando a seguinte seqncia de comandos:
1. Selecione a opo Build Ali no menu Compile. O Turbo C++ Lite exibir a caixa de dilogo
Compiling.
2. Se o compilador completar com sucesso a compilao, ele pedir que voc pressione qualquer
tecla. Se o compilador no criar o arquivo primeiro.exe, mas, em vez disso exibir mensagens de
erro na sua tela, provavelmente porque voc violou uma regra de sintaxe de C, como discutido
na prxima dica.
3. Se voc digitou sem erros os comandos C, como mostrado na Dica 2, o compilador C criar um
arquivo executvel chamado primeiro.exe. Para executar o programa primeiro.exe, voc pode sele
cionar a opo Run no menu Run ou pressionar o atalho de teclado Ctrl+F9.
Quando voc executar o programa, sua tela exibir a seguinte sada:
Bblia do Programador C/C++, do Jamsa!
C:\>
I n tro duo lin g u a g em C 3

Nota: Em algumas instalaes, o Turbo C++ Lite gerar a sada e retomar imediatamente janela de edio. Nesses
casos, selecione a opo DOS Shell no menu File para ver a sada gerada pelo programa.

Co m p r e e n d e n d o os Erros de S in t a x e 4
C omo voc leu na Dica 2, roda linguagem de programao tem um conjunto de regras, chamadas regras de sin
taxe, s quais voc precisa obedecer quando especificar os comandos do programa. Se voc violar uma regra de
sintaxe, seu programa no ser compilado com sucesso. Em vez disso, o compilador exibir mensagens de erro
na sua tela que especificam a linha do seu programa que contm o erro e uma breve descrio do erro. Usando
seu editor, crie o arquivo sintaxe, c, que contm um erro de sintaxe. No exemplo a seguir, o programa deixou de
incluir as aspas finais na mensagem Bblia do Programador C/C++, do Jamsa!:
#include <stdio.h>

void main(void)
{
printf("Bblia do Programador C/C++, do Jamsal);
>

Quando voc compilar este programa, seu compilador exibir uma mensagem de erro de sintaxe ao encon
trar a linha 5. Dependendo do seu compilador, a mensagem de erro real diferir. No caso do Turbo C++ Lite\
sua tela exibir as seguintes mensagens:
Error sintaxe.c 5: nterminated string or character constant in function main
Error sintaxe.c 6: Function call missing ) in function main()
Error sintaxe.c 6: Statement missing ; in function main()
Embora o cdigo-fonte sintaxe.c contenha somente um erro, o compilador C exibir trs mensagens de erros.
A falta das aspas finais provoca uma srie de erros em cascata (um erro que leva a outro) dentro do compilador.
Para corrigir os erros de sintaxe dentro de seus programas, acompanhe os seguintes passos:
1. Escreva o nmero da linha de cada erro e um a breve descrio.
2. Edite seu arquivo-fonte, movendo o cursor para o nmero da primeira linha que o compilador exibir.
3. D entro do arquivo-fonte, corrija o erro e mova o cursor para o nmero da prxima linha. A
maioria dos editores exibe o nmero da linha atual para lhe ajudar a localizar linhas especficas
dentro do arquivo.
No caso do arquivo sintaxe.c, edite o arquivo e acrescente as aspas que faltaram. Salve o arquivo no disco
e compile-o novamente. Aps voc corrigir o erro de sintaxe, o compilador criar o arquivo sintaxe.c. Para exe
cutar sintaxe.exe, selecione a opo Run no menu Run. O programa executar e produzir a sada mostrada aqui:
A Bblia do Programador C/C++ A Bblia, do Jamsa!
C:\>

Estrutura de um T p ic o P r o g r a m a em C 5
Na Dica 2, voc criou o arquivo-fonte primeiro.c, que continha os seguintes comandos:
#include <stdio.h>

void main(void)
{
printf("Bblia do Programador C/C++, do Jamsa!");
>

Esses comandos so similares aos que voc encontrar na maioria dos programas C. Em muitos casos, um
arquivo-fonte C pode comear com um ou mais comandos #include. O comando #include instrui o compilador
C a usar o contedo de um arquivo especfico.
4 P rog ram and o em Q/C++ A B b l ia

No caso do arquivo primeiro, c, o comando #include instrui o compilador C a usar um arquivo chamado
stdio.h. Os arquivos especificados por um comando #include so arquivos ASCII, que contm cdigo-fonte em
C. Voc pode imprimir ou exibir o contedo de cada arquivo seguindo os passos discutidos na Dica 13, mais
frente. Os arquivos que voc nomeia dentro de um comando #include, os quais normalmente usam a extenso h,
so chamados arquivos de incluso ou arquivos de cabealho. A maioria dos arquivos de cabealho contm comandos
que seus programas usam comumente, embora voc aprender mais tarde, neste livro, sobre outros usos para os arquivos
de cabealho. Quando voc instrui o compilador C a incluir o contedo do arquivo, no precisa digitar os comandos nos
seus programas. Aps os comandos ffinclude, voc normalmente encontrar um comando similar ao seguinte:
void main(void)
Cada programa C que voc criar incluir uma linha similar ao comando void main. Como j foi escrito
na Dica 1, um programa C contm uma lista de instrues que voc quer que o compilador execute. medida
que a complexidade de seus programas aumentar, divida-os em partes menores que sejam mais fceis para voc
(e para outros que vierem a ler seu programa) compreender. O grupo de instrues que voc quer que o pro
grama execute primeiro chama-se programa main (principal). O comando void main identifica esses comandos
(o programa main) para o compilador.
E claro que, como o compilador C determinar quais comandos formam o programa main e quais coman
dos so suplementares, voc precisa ter um modo de dizer ao compilador C quais instrues correspondem a
cada seo do seu programa. Para atribuir comandos do programa a uma seo especfica do seu programa, co
loque o comando dentro de abre e fecha chaves ({ e }). As chaves fazem parte da sintaxe de C. Para todo abre
chaves, voc precisa ter um fecha chaves correspondente que encerra o grupo de comandos.

6 A c r e s c e n t a n d o Co m a n d o s aos S eu s P ro gram as
Como voc leu, o programa primeiro.c usou o comando p r in tf para exibir uma mensagem na sua tela. O pro
grama a seguir, 3_msgs.c, usa trs comandos p rin tf para exibir a mesma mensagem. Cada comando est contido
dentro do abre e fecha chaves:
#include <stdio.h>

void main(void)
{
printf(Programando");
printf("em C/C++, ");
printf("a Bblia!");
}

Observe o caractere de espao em branco dentro dos comandos printf. O caractere de espao importante
porque garante que o programa exibir corretamente o texto na sua tela (colocando um espao entre as palavras).
A medida que o nmero de comandos nos seus programas aumentar, assim tambm aumentar a probabilidade
de erros de sintaxe. Confira seu programa para garantir que voc digitou corretamente cada comando e depois
salve o arquivo no disco. Quando voc compilar e executar o programa 3_msgs.c, sua tela exibir a seguinte sada:
Bblia do Programador C/C++
C:\>

7 E x i b in d o S a d a em uma N o v a L in h a
Vrios dos programas anteriores exibiram a mensagem Bblia do Programador C/C++, do Jamsa! na tela. A me
dida que seus programas se tornarm mais complexos, voc pode querer que eles exibam sua sada em duas ou mais linhas.
Na Dica 6, voc criou o programa 3_msgs.c, que usou trs comandos printf para exibir uma mensagem na tela.

printf("Bblia);
printf("do Programador C/C++, ");
printf("do Jamsa!");
A no ser que voc instrua p r in tf a fazer de forma diferente, continuar sua sada na linha atual.
O objetivo do programa a seguir, uma_lin.c, exibir sada em duas linhas sucessivas:
I ntroduo lin g u a g em c 5

#include <stdio.h>

void main(void)
{
printf ("Esta a linha um.");
printf ("Esta a linha dois.");
}
Quando voc compilar e executar o programa uma_lin.c, sua tela exibir a seguinte sada:
Esta a linha um.Esta a linha dois.
C:\>
Quando voc quiser que printfm icie sua sada em uma nova linha, preciso incluir o caractere de nova li
nha especial (\n) dentro do texto que voc pede para p rin tfe \ ibir. Quando p r in tf encontrar o caractere \n, avan
ar o cursor para o incio da prxima linha. O programa a seguir, duas_lin.c, usa o caractere de nova linha para
exibir a segunda linha de texto em uma nova linha, como desejado:
#include <stdio.h>

void main(void)
{
printf ("Esta a linha um.\n");
printf ("Esta a linha dois.");
}
Quando voc compilar e executar o programa duas_lin.c, sua tela exibir a seguinte sada:
Esta a linha um.
Esta a linha dois.
C:\>
Muitos dos programas apresentados neste livro usam o caractere de nova linha. Na verdade, quase todo
programa que voc escrever normalmente usar o caractere de nova linha em um ou mais lugares.

C o n s id e r a as L e t r a s Ma i s c u l a s e M in s c u l a s
Dif e r e n t e s 8
medida que voc vai digitando seus programas, lembre-se de que C considera as letras maisculas e minsculas
como diferentes. Como regra, a maioria dos comandos C usa minsculas; a maioria das constantes C usa todas
maisculas; e quase todas as variveis C misturam a caixa das letras. Os programas C fazem muito uso de letras
minsculas. Como o programa a seguir, erro_mai.c, usa a letra M maiscula no nome Main quando C espera
o nome main, o programa no passa pela compilao.
#include <stdio.h>

void Main(void)
{
printf ("Este programa no passa na compilao.);
>

Quando voc compilar o programa erro_mai.c, o compilador Turbo C++ Lite exibir a seguinte mensagem:
Linker error: Undefined symbol _jnain in module TURBO_CNCOS.ASM
Essa mensagem quase incompreensvel que o compilador Turbo C++ Lite exibe conseqncia do erro na caixa
da letra M na palavra Main. Para corrigir o erro, voc simplesmente altera M ain para main. Aps fazer a cor
reo, recompile e execute o programa.
6 P ro g ram a nd o em C/C+ + A B b l ia

9 Co m p r e e n d e n d o os E r r o s L g ic o s
N a Dica 4, voc aprendeu que caso viole uma das regras da linguagem C, o compilador exibir uma mensagem
de erro de sintaxe e seu programa no ser compilado com sucesso. medida que seus programas se tornarem
mais complexos, algumas vezes eles passaro na compilao mas sem realizar corretamente a tarefa que voc que
ria que eles executassem. Por exemplo, assuma que voc quer que o programa a seguir, uma_lin. C, exiba sua sada
em duas linhas:
#include <stdio.h>

void main(void)
{
printf ("Esta a linha um.");
printf ("Esta a linha dois.");
>

Como o programa no viola nenhuma das regras de sintaxe de C, ele ser compilado sem erros. No en
tanto, quando voc executar o programa, ele no exibir a sada em duas linhas; em vez disso, exibir a sada em
uma nica linha, como mostrado aqui:
Esta a linha um.Esta a linha dois.
C:\>
Quando seu programa no funciona como voc deseja, porque ele contm erros lgicos, ou bugs. Quando
seu programa contiver um erro lgico (e algum dia isso ocorrer), ser preciso descobrir e corrigir a causa do erro.
O processo de remover os erros lgicos do seu programa chamado depurao. Posteriormente, neste livro, voc
aprender vrias tcnicas diferentes que poder usar para localizar os erros lgicos dentro de seu programa. Por
enquanto, porm, o melhor modo de localizar esses erros imprimir uma cpia do seu programa e examin-la
linha por linha at localizar o erro. O exame linha a linha de um programa chamado verificao de mesa. No
caso do programa umajlin.c, sua verificao de mesa deve revelar que o primeiro comando p rin tf no contm
o caractere de nova linha (\n).

10 Co m p r e e n d e n d o o P ro c esso de D e s e n v o l v im e n t o de

um P ro gram a
Quando voc cria programas, normalmente segue os mesmos passos. Para comear, use um editor para criar seu
arquivo-fonte. Em seguida, compile o programa. Se o programa contiver erros de sintaxe, voc precisar editar
o arquivo-fonte e corrigir os erros. Aps o programa passar pela compilao sem apresentar erros, tente execu
t-lo. Se o programa rodar com sucesso e operar como voc espera, o processo de criao do programa estar ter
minado. Por outro lado, se o programa no funcionar como planejado, voc precisar analisar o cdigo-fonte e
tentar localizar o erro lgico (como discutido na Dica 9). Aps voc corrigir o erro, precisar compilar o cdi
go-fonte para criar um novo arquivo executvel. Voc poder ento testar o novo programa para se certificar de
que ele executar a tarefa desejada. A Figura 10 ilustra o processo de desenvolvimento de um programa.

Figura 10 O processo de desenvolvimento de um programa.


I ntroduo lin g u a g em c 7

Co m p r e e n d e n d o os T ip o s de A r q u iv o 11
Ao criar um programa C, voc coloca seus comandos em um arquivo-fonte que tem a extenso C. Se seu pro
grama for compilado com sucesso, o compilador criar um arquivo de programa executvel com a extenso EXE.
Como voc j leu na Dica 5, muitos programas usam arquivos de cabealho (que tm a extenso .b) que contm
comandos usados comumente. Se voc examinar seu diretrio aps compilar um programa, provavelmente en
contrar um ou mais arquivos com a extenso .OBJ. Esses arquivos, chamados arquivos-objetos, contm instru
es na forma de ls e Os que o computador compreende. No entanto, voc no pode executar esses arquivos,
pois o contedo deles no est completo.
O compilador C fornece rotinas (tais como printf) que executam operaes comumente usadas e reduzem
o nmero de comandos que voc precisa incluir nos seus programas. Aps examinar a sintaxe do seu programa,
o compilador criar um arquivo-objeto. No caso do programa primeiro.c, o compilador criaria um arquivo-ob-
jeto chamado primeiro.obj. Em seguida, um programa chamado linkeditor (ou ligador) combina os comandos do
programa no seu arquivo-objeto com as funes (tais como printf) que o compilador fornece para criar o pro
grama executvel. Na maioria dos casos, quando voc chama o compilador para examinar seu cdigo-fonte, ele
automaticamente chamar o linkeditor st o programa passar na compilao. A Figura 11 ilustra o processo de
compilar e ligar um programa.

Figura 11 O processo de compilar e ligar um programa.

Co m p r e e n d e n d o M e l h o r o L in k e d it o r 12
Na Dica 11 voc aprendeu que quando compila seu programa C, um segundo programa, chamado linkeditor,
combina os comandos do seu programa com rotinas predefinidas (que o compilador fornece) para converter um
arquivo-objeto em um programa executvel. Assim como o caso com o processo de compilao, que pode de
tectar erros de sintaxe, o processo de ligao tambm pode encontrar erros. Por exemplo, considere o seguinte
programa, sem_prin.c, que erroneamente usa p rin te m vez de printf:
ttinclude <stdio.h>

void main(void)
{
print("Este programa no passa na ligao");
}

Como o programa sem_prin.c no viola nenhuma regra de sintaxe de C, ele ser compilado com sucesso,
produzindo um arquivo-objeto. No entanto, o linkeditor do Turbo C++ Lite exibir a seguinte mensagem de
erro, pois o comando print no est definido:
Error: Function 'print' should have a prototype in function main()
Como o compilador C no fornece uma funo chamada print, o linkeditor no pode criar o programa
executvel sem_prin.c. Em vez disso, o linkeditor exibir a mensagem de erro mostrada anteriormente. Para so
lucionar o problema, edite o arquivo, mudando print para printf, e, depois, recompile e ligue seu programa.
8 P ro g ram a nd o em C/C++ A B b l ia

13 Co m p r e e n d e n d o os A r q u iv o s de Ca b e a l h o
Cada programa apresentado neste livro usa um ou mais comandos #include para instruir o compilador C a usar
os comandos que um arquivo de cabealho contm. Um arquivo de cabealho um arquivo ASCII cujo con
tedo voc pode imprimir ou exibir na sua tela. Se voc examinar o diretrio que contm seu compilador (o di
retrio tclite, no caso do Turbo C++ Lite), encontrar um subdiretrio chamado include. O subdiretrio include
contm os arquivos de cabealho do compilador. Separe um tempo para localizar os arquivos de cabealho do
seu compilador. Se desejar, imprima o contedo de um arquivo de cabealho usado freqentemente, tal como
stdio.h. Voc encontrar comandos de programao C dentro de um arquivo de incluso. Quando o compilador
C encontra um comando #include no seu programa, ele compila o cdigo que o cabealho contm exatamente
como se voc tivesse digitado o contedo do arquivo de cabealho no cdigo-fonte do seu programa. Os arquivos
de cabealho contm definies comumente usadas e fornecem ao compilador informaes sobre certas funes,
tais como printf. Por ora, voc pode achar o contedo de um arquivo de cabealho difcil de compreender. No
entanto, medida que se tornar mais fluente em C e C++, dever imprimir uma cpia e examinar todo arquivo
de cabealho que usar. Os arquivos de cabealho contm informaes valiosas e apresentam tcnicas de progra
mao que faro de voc um programador C melhor.

14 A ju d a n d o o C o m p i l a d o r a L o c a liz a r o s A r q u i v o s de

C a b e a lh o
Na Dica 13 voc aprendeu que, quando o compilador C encontra um comando #include, ele acrescenta o con
tedo do arquivo de cabealho ao seu programa, exatamente como se voc tivesse digitado o contedo do arqui
vo de cabealho no seu cdigo-fonte. Dependendo do seu compilador, as variveis do ambiente podem conter
uma linha INCLUDE que diz ao compilador o nome do subdiretrio que contm os arquivos de cabealho. Se
quando voc compilar um programa seu compilador exibir uma mensagem de erro dizendo que no pode abrir
um determinado arquivo de cabealho, verifique primeiro o subdiretrio que contm os arquivos de cabealho
de seu programa para garantir que o arquivo existe. Se voc encontrar o arquivo, pea um comando SET no
prompt do DOS, como mostrado aqui:
C:\> SET <Enter>
COMSPEC=C:\DOS\COMMAND.COM
PATH=C:\DOS;C :\WINDOWS;C :\BORLANDC\BIN
PROMPT=$ P $G
TEMP=C:\TEMP
Se o seu ambiente no contiver uma linha INCLUDE, verifique a documentao que acompanhou seu
compilador para determinar se seu compilador requer essa linha. Normalmente, a instalao do compilador co
locar dentro do arquivo autoexec.bat um comando SET que atribui a entrada INCLUDE ao subdiretrio que
contm os arquivos de cabealho, como mostrado aqui:
SET INCLDE=C:\BORLANDC\INCLUDE
Se o seu compilador usa a entrada INCLUDE, e seu arquivo auto exec. bat no a define, voc mesmo pode
inclu-la no arquivo autoexec.bat.
Nota: O compilador Turbo C++ Lite procura os arquivos de incluso somente no subdiretrio include.

15 A g il iz a n d o as Co m p il a e s
Quando voc compilar um arquivo-fonte, o compilador C poder criar um ou mais arquivos temporrios que
existiro somente enquanto o compilador e linkeditor estiverem trabalhando. Dependendo do seu compilador,
voc poder usar a varivel do ambiente TEM P para especificar onde o compilador criar esses arquivos tempo
rrios. Se o seu computador tiver vrios discos rgidos, alguns dos quais com mais espao disponvel que os outros
(especialmente se seu compilador rodar dentro do Windows e, portanto, usar memria virtual e arquivos de
transferncia), voc poder fazer a varivel TEM P apontar para o disco que tiver mais espao disponvel. Desse
modo, o compilador criar seus arquivos temporrios no disco rgido mais rpido, o que agilizar o processo de
I ntroduo lin g u a g em C 9

compilao. Assumindo que sua unidade D tenha esse espao extra, voc poder colocar um comando SET den
tro de seu autoexec. bat para atribuir a varivel TEM P unidade D, como mostrado aqui:
SET TEMP=D:

Co m e n t a n d o S e u s P r o g r a m a s 16
Como regra, cada vez que voc cria um programa, precisa incluir comentrios que expliquem o processamento
que o programa realiza. Basicamente, um comentrio uma mensagem que o ajuda a ler e compreender o pro
grama. medida que seus programas aumentarem de tamanho, eles se tornaro mais difceis de compreender.
Como voc criar centenas e talvez at milhares de programas, no conseguir lembrar o propsito de cada co
mando dentro de cada programa. Se voc incluir comentrios no seu programa, no precisar lembrar os detalhes
de cada programa. Em vez disso, os comentrios explicaro o processamento.
A maioria dos compiladores C e C++ oferece dois modos para voc colocar comentrios dentro do seu ar
quivo-fonte. Primeiro, voc coloca dois caracteres de barras inclinadas para a direita (//), como mostrado aqui:
// Isto um comentrio
Quando o compilador C encontra as barras duplas, ele ignora o texto que segue at o final da linha atual.
O programa a seguir, comenta.c, ilustra o uso de comentrios:
// Programa: comenta.c
// Escrito por: Kris Jamsa e Lars Klander
// Data de criao: 22-12-97
// Propsito: Ilustrar o uso de comentrios em um programa C.

ttinclude <stdio.h>

void main(void)
(
printf ("Bblia do Programador C/C++, do Jamsa!"); // Exibe uma mensagem
}

Neste exemplo, voc imediatamente sabe, lendo esses simples comentrios, quando, por que e quem escre
veu o programa. Adquira o hbito de colocar comentrios similares no incio dos seus programas. Se outros pro
gramadores que precisarem ler ou modificar o programa tiverem dvidas, eles sabero rapidamente quem foi o
autor original do programa.
Quando o compilador C encontra as barras duplas (II), ele ignora o texto at o final daquela linha. A maio
ria dos novos arquivos-fonte C usam as barras duplas para designar um comentrio. Se voc estiver lendo pro
gramas C antigos, poder encontrar comentrios escritos de uma segunda forma. Na segunda forma aceitvel de
comentrios, esses aparecem entre um conjunto de barras e asteriscos, como mostrado aqui:
/* Isto um comentrio */
Q uando o compilador encontra o smbolo de abertura de comentrio (/*), ele ignora todo o texto at e in
cluindo o smbolo de encerramento de comentrio (*/). Usando o formato I* comentrio */, um nico comen
trio pode aparecer em duas ou mais linhas. O programa a seguir, comenta2.c, ilustra o uso do formato /*
comentrio /:
/* Programa: COMENTA.C
Escrito por: Kris Jamsa e Lars Klander
Data de criao: 22-12-97

Propsito: Ilustrar o uso de comentrio em um programa C. */

#include <stdio.h>

void main(void)
{
10 P ro g ram a nd o em C/C+ + A B b l ia

printf ("Bblia do Programador C/C++, do Jamsa!"); /* Exibe uma mensagem */


>

Como voc pode ver, o primeiro comentrio do programa contm cinco linhas. Quando voc usa o for
mato I* comentrio */para seus comentrios, certifique-se de que cada smbolo de incio de comentrio (/*) tenha um
smbolo de finalizao correspondente (*/). Se o smbolo de finalizao estiver faltando, o compilador C ignorar a
maior parte do seu programa, o que, eventualmente, resultar em erros de sintaxe que sero difceis de detectar.
A maioria dos compiladores C retornar um erro de sintaxe se voc tentar colocar um comentrio dentro
de outro, como mostrado aqui:
/* Este comentrio tem /* um segundo */ comentrio dentro */

17 MELHORANDO A LEGIBILIDADE DO S E U PROGRAMA


Na Dica 16, voc aprendeu como usar comentrios dentro de seus programas para melhorar sua legibilidade.
Toda vez que criar um programa, assuma que voc ou outro programador ter que modific-lo de alguma forma.
Portanto, essencial que voc escreva seus programas de modo que eles sejam fceis de ler. O programa C a se
guir, dificil.c, exibir uma mensagem na sua tela:
#include <stdio.h>
void main(void) {printf("Bblia do Programador C/C++, do Jamsa!);)
Embora este programa seja compilado com sucesso e exiba a mensagem desejada, ele difcil de ler, para
dizer o mnimo. Um bom programa no somente funciona, mas tambm fcil de ler e de compreender. A cha
ve para criar programas legveis incluir comentrios que explicam o processamento de programa e usar linhas
em branco para melhorar o formato do programa. Em dicas posteriores voc aprender o importante papel que
as endentaes (ou recuos) tm para produzir cdigo legvel de programas.

18 P r e s t a n d o At en o s Men sa g en s de A d v e r t n c ia do

C o m p il a d o r
Quando seu programa contm um ou mais erros de sintaxe, o compilador C exibir mensagens de erro na sua
tela e no criar um programa executvel. medida que voc for criando programas, algumas vezes o compilador
exibir uma ou mais mensagens de advertncia na sua tela, mas ainda criar o arquivo do programa executvel.
Por exemplo, o seguinte programa C, semstdio.c, no inclui o arquivo de cabealho stdio.h:
void main(void)
{
printf("Bblia do Programador C/C++, do Jamsa!");
>

Quando voc compilar este programa, o compilador Turbo C+ + Lite exibir a seguinte mensagem de ad
vertncia:
Warning semstdio.c 3: Function 'printf' should have a prototype in function

Quando o compilador exibir uma mensagem de advertncia, voc dever determinar imediatamente a cau
sa da queixa do compilador e corrigi-la. Embora as advertncias possam nunca causar um erro durante a execu
o do seu programa, algumas advertncias criaro a oportunidade para erros que so muito difceis de depurar
mais tarde. Separando tempo para localizar e corrigir a causa das advertncias do compilador, voc aprender
muito mais sobre o funcionamento interno de C e C++.

19 Co n t r o l a n d o as A d v e r t n c ia s do C o m p il a d o r
Na Dica 18, voc aprendeu que deve prestar ateno s mensagens de advertncia que o compilador exibe na
tela. Para lhe ajudar a fazer melhor uso das advertncias do compilador, muitos compiladores permitem que voc
defina o nvel de mensagem que deseja. Dependendo do seu compilador, voc poder usar uma opo de linha
de comando para controlar o nvel de advertncia ou pode usar pragmas, explicadas na Dica 145. Uma pragma
I ntroduo lin g u a g em C 11

uma diretiva para o compilador. Como voc aprender, diferentes compiladores suportam diferentes pragmas.
Por exemplo, para desabilitar a advertncia Identifier is declared but never used (O identificador declarado mas
nunca usado) dentro do Turbo C++ Lite, seu cdigo incluiria a seguinte pragma:

#pragma warn -use

Se voc no estiver usando o Turbo C++ Lite, consulte a documentao que acompanha seu compilador
para determinar se voc pode desativar mensagens de advertncias especficas.

U s a n d o C o m e n t r io s para Ex c l u ir Co m a n d o s do

P rogram a 20
Na Dica 16, voc aprendeu que deve usar comentrios dentro de seus programas para melhorar a legibilidade.
medida que seus programas se tornarem mais complexos, voc poder usar comentrios para ajudar a depurar
(remover erros) de seus programas. Quando o compilador C encontrar as barras duplas (//), ele ignorar todo
o texto restante at o fim da linha atual. Da mesma forma, quando o compilador encontrar o smbolo de incio
de comentrio (/*), ele ignorar todo o texto que segue, at o smbolo de finalizao de comentrio (*/). Quando
voc testar seus programas, algumas vezes desejar eliminar um ou mais comandos do seu programa. Um modo
de eliminar os comandos do seu programa simplesmente excluir os comandos do seu arquivo-fonte. Um se
gundo modo de eliminar comandos transform-los em comentrios. No programa a seguir, semsaida.c, todos os
comandos p rin tf foram transformados em comentrios:

#include <stdio.h>

void main(void)
{
II printf ("Esta linha no aparece");
/* Isto um comentrio
printf ("Esta linha tambm no aparece");
*/
>

Como ambos os comandos />n/aparecem dentro de comentrios, o compilador ignora os dois. Como re
sultado, nada aparece na tela quando voc executa o programa. medida que seus programas se tornarem mais
complexos, ser muito conveniente poder usar comentrios para desativar certos comandos.
Como voc aprendeu na Dica 16, a maioria dos compiladores C retornar um ou mais erros de sintaxe se
voc tentar colocar um comentrio dentro de outro. Quando voc usar comentrios para desabilitar comandos,
tome cuidado para no colocar inadvertidamente um comentrio dentro de outro.

Co m p r e e n d e n d o a I m p o r t n c ia dos No m e s 21
medida que voc examinar as dicas apresentadas neste livro, encontrar nomes de variveis e de funes cujos
nomes iniciam com um trao de sublinhado, tal como _dos_getdrive ou _chmode. Em geral,voc somente usa
tais variveis e funes dentro do ambiente do DOS. Se voc estiver escrevendo programasque executaro sob
o DOS, Windows, Macintosh, UNIX, ou possivelmente algum outro sistema operacional, dever evitar usar es
sas funes, pois provvel que elas no estejam disponveis nos outros sistemas. Portanto, para migrar seu pro
grama do DOS para outro sistema operacional, voc ter que fazer alguma programao adicional. Algumas
funes podem ter duas implementaes: uma com um trao de sublinhado (_cbmode) e uma sem (chmode).
Como regra, use a funo ou varivel sem o sublinhado, que neste caso chmode.

Co m p r e e n d e n d o o P o n t o -e -V r g u l a 22
Examinando programas C, voc ver que eles utilizam muito o caractere ponto-e-vrgula. O ponto-e-vrgula em
C tem um significado especial. Como voc sabe, um programa uma lista de instrues que voc quer que o
computador execute. Ao especificar essas instrues em C, voc usar o ponto-e-vrgula para separar um coman
12 P rog ram and o em C/C++ A B b l ia

do do outro. medida que seus programas vo se tornando mais complexos, poder acontecer de um comando
no caber em uma nica linha. Quando o compilador C examinar seu programa, ele procurar o ponto-e-vrgula
para distinguir um comando do prximo. A sintaxe da linguagem C define o uso do ponto-e-vrgula. Se voc
omitir o ponto-e-vrgula, ocorrer um erro de sintaxe, e o programa no passar na compilao.

23 Apresen tan d o as V a r i v e is
Para efetuar um trabalho til, os programas precisam armazenar informaes, tais como um documento editado
em mltiplas sees, dentro de um arquivo e tambm internamente. Como voc sabe, toda vez que roda um pro
grama, o sistema operacional carrega as instrues do seu programa na memria do computador. medida que
o programa roda, ele armazena valores em posies de memria. Por exemplo, assuma que voc tenha um pro
grama que imprime um documento. Toda vez que voc roda o programa, ele exibir uma mensagem pergun
tando o nome do arquivo, bem como o nmero de cpias que voc quer imprimir. Digitando essas informaes,
o programa armazena os valores digitados em posies de memria especficas. Para ajudar seu programa a con
trolar as posies de memria onde ele colocou dados, cada posio tem um endereo exclusivo, tal como ende
reo 0, 1, 2, 3 etc. Como podem existir bilhes desses endereos, manter o controle de posies de
armazenamento individuais poder vir a ser muito difcil. Para simplificar a armazenagem de informaes, os
programas definem variveis, que so os nomes que o programa associa com posies especficas na memria.
Como a palavra varivel implica, o valor que o programa armazena nessas posies pode ser modificado durante
a vida do programa.
Cada varivel tem um tipo especfico, que diz ao computador quanta memria requer os dados que a va
rivel armazena, e quais operaes o programa pode realizar com os dados. Dado o exemplo anterior de um pro
grama que imprime um documento, o programa poderia usar uma varivel chamada nomearq (que armazena o
nome do arquivo que voc deseja imprimir) e uma chamada conta (que armazena o nmero de cpias que voc
deseja imprimir). Dentro do seu programa C, voc referencia as variveis pelo nome. Portanto, deve atribuir no
mes representativos a cada varivel. Dentro de seus programas, voc normalmente declara suas variveis imedia
tamente aps main, antes dos comandos do programa, como mostrado aqui:
void main(void)
{
/ / A s variveis ficam aqui

printf("Bblia do Programador C/C++, do Jamsa!);


>

O programa a seguir mostra como voc declararia trs variveis inteiras (variveis que armazenam nmeros
de contagem, tais como 1, 2, 3 etc.)
void main(void)
{
int idade; // A idade do usurio em anos
int peso; // O peso do usurio em Kg
int altura; // A altura em centmetros
/ / O s outros comandos do programa ficariam aqui
}

Cada varivel tem um tipo que define a quantidade de memria que ela requer, bem como as operaes
que o programa pode realizar com ps dados. Para declarar uma varivel inteira, seus programas C usam o tipo
int. Aps voc declarar uma varivel (isto , dizer ao programa o nome e o tipo da varivel), poder ento atribuir
um valor varivel (isto , armazenar informaes).

24 At r ib u in d o um Valo r a uma V a r i v e l
Uma varivel um nome que seu programa associa com uma posio de armazenamento na memria. Aps voc de
clarar uma varivel dentro de seu programa, poder atribuir um valor varivel usando o sinal de igual (chamado ope
rador de atribuio). O programa a seguir declara trs variveis do tipo int e depois atribui um valor a cada varivel:
void main(void)
{
int idade; / / A idade do usurio em anos
I ntroduo lin g u a g em C 13

int peso; 1 / 0 peso do usurio em Kg


int altura; // A altura em centmetros

idade = 41; // Atribui a idade do usurio


peso = 80; // Atribui o peso
altura = 182; // Atribui a altura

II Outros comandos do programa

Co m p r e e n d e n d o os T ip o s de V a r i v e is 25
Quando voc declara variveis dentro de seus programas, precisa dizer ao compilador C o nome e o tipo da va
rivel. O tipo define um conjunto de valores que a varivel pode armazenar, bem como as operaes que o pro
grama pode realizar com os dados. C suporta quatro tipos bsicos, cada um dos quais est listado na Tabela 25.
Tabela 25 Os quatro tipos bsicos suportados por C.
Nom e do Tipo Propsito
char Armazena um nico caractere, tal como uma letra de A at Z.
int Armazena os nmeros de contagem (chamados inteiros), tais como 1, 2, 3, bem como
nmeros negativos.
float Armazena nmeros de ponto flutuante de preciso simples (com um ponto decimal), tais
como 3.14 ou -54.1343.
double Armazena um nmero de ponto flutuante de dupla preciso (que mais exato que um
nmero em ponto flutuante de preciso simples). Voc usar double para nmeros muito
pequenos ou muito grandes.

Muitas das dicas apresentadas neste livro examinam cada um desses tipos detalhadamente. A maioria das
dicas usa uma ou mais variveis dos tipos bsicos.

D e c l a r a n d o M l t ip l a s V a r i v e is do M e s m o T ip o 26
Como voc aprendeu na Dica 24, ao declarar uma varivel dentro de seu programa, preciso dizer ao compi
lador C o nome e o tipo da varivel. Os comandos a seguir declaram trs variveis do tipo int:
int idade;
int peso;
int altura;
Quando voc declarar variveis do mesmo tipo, C lhe permite listar os nomes das variveis em uma ou
mais linhas, separando o nome de cada varivel por vrgulas, como mostrado aqui:
int idade, peso, altura;
float salario, impostos;

Co m e n t a n d o S u a s V a r i v e is na Dec la ra o 27
Os comentrios ajudam qualquer um que analisar o programa a compreend-lo mais facilmente. Quando voc
escolher nomes de variveis, dever selecionar nomes que descrevam claramente o valor que a varivel armaze
nar. Por exemplo, considere a seguinte declarao:
int idade, peso, altura;
int x, y, z;
Ambas as declaraes criam trs variveis do tipo int. No entanto, na primeira declarao, voc tem uma
idia de como usar cada varivel simplesmente examinando os nomes delas. Alm de usar nomes representativos,
voc tambm dever colocar um comentrio ao lado de cada declarao de varivel, o que explicar ainda melhor
a varivel, como mostrado aqui:
14 P r o g ram a nd o em C/C++ A B b l ia

int idade; // A idade do usurio em anos


int peso; // 0 peso do usurio em Kg
int altura; // A altura em centmetros

28 A t r ib u in d o V a l o r e s s V a r i v e is na Dec la ra o
Aps voc declarar uma varivel dentro de seu programa, poder usar o operador de atribuio (o sinal de igual)
para atribuir um valor varivel. C lhe permite atribuir um valor a uma varivel no momento em que ela de
clarada. Os programadores chamam esse processo de atribuir um valor inicial de inicializao da varivel. Os co
mandos a seguir, por exemplo, declaram e inicializam trs variveis do tipo int:
int idade = 41; // A idade do usurio em anos
int peso = 80; // 0 peso do usurio em Kg
int altura = 182; // A altura em centmetros

29 I n ic ia l iz a n d o M l t ip l a s V a r i v e is durante a D e c la r a o
Na Dica 26, voc aprendeu que C lhe permite declarar duas ou mais variveis na mesma linha, como mostrado aqui:
int idade, peso, altura;
Quando voc declara mltiplas variveis na mesma linha, C lhe permite inicializar uma ou mais variveis:
int idade = 44, peso, altura = 182;
Neste exemplo, C inicializar as variveis idade e altura, e deixar a varivel peso no inicializada.

30 U s a n d o No m e s R e p r e s e n t a t iv o s para as V a r i v e is
Quando voc declarar variveis nos seus programas, dever escolher nomes representativos que descrevam o uso
da varivel. Voc poder usar uma combinao de letras maisculas e minsculas nos nomes de suas variveis.
Como discutido na Dica 8, o compilador C faz distino entre letras maisculas e minsculas. Se voc usar letras
maisculas e minsculas nos nomes de suas variveis, sempre precisar especificar as mesmas combinaes de le
tras. Agora que voc est comeando, deve provavelmente adotar apenas letras minsculas, pois fazer isso reduz
a possibilidade de ocorrncia de erros devido mistura dos tipos de letras.
Voc precisar dar um nome nico a cada varivel que declarar dentro de seus programas. Em geral, voc
pode usar um nmero ilimitado de caracteres no nome de uma varivel. Os nomes das suas variveis podem con
ter uma combinao de letras, nmeros e o caractere de sublinhado, no entanto, os nomes devem iniciar com
uma letra ou com o sublinhado. Os comandos a seguir ilustram alguns nomes vlidos de variveis:
int horas_trabalhadas;
float aliquota_imposto;
float _6_mes_gravidez; // vlido iniciar com o _sublinhado
C predefine vrias palavras-chave que tm significado especial para o compilador. Uma palavra-chave
uma palavra que tem significado para o compilador. Por exemplo, float, int e char so todas palavras-chave.
Q uando voc criar nomes de variveis, no poder usar palavras-chave prprias. A Dica 31 lista as palavras-chave
da linguagem C.

31 Co m p r e e n d e n d o as P a l a v r a s -c h a v e de C
A linguagem C define vrias palavras-chave que tm significado especial para o compilador. Quando voc esco
lher nomes de variveis (e criar suas prprias funes), no use essas palavras-chave. A Tabela 31 lista as pala
vras-chaves de C:
I ntroduo lin g u a g em C 15

Tabela 31 Lista de palavras-chave de C.


Palavras-chave de C
auto default flo a t register struct volatile
break do fo r retum switch while
case double goto short typedef
char else if signed union
const enum int sizeof unsigned
continue extern long static void

C o m p r e e n d e n d o a s V a r i v e is d o T ip o in t 32
Uma varivel um nome que o compilador C associa com uma ou mais posies de memria. Quando voc de
clara uma varivel dentro de seu programa, precisa especificar o tipo e o nome da varivel. O tipo da varivel es
pecifica o tipo de valores que a varivel pode armazenar e o conjunto de operaes que o programa pode realizar
com os dados. C usa o tipo int para armazenar valores inteiros (nmeros de contagem positivos e negativos). O
compilador C normalmente aloca dezesseis bits (dois bytes) para armazenar os valores do tipo int. Uma varivel
do tipo int pode armazenar valores no intervalo de -32.768 at 32.767. A Figura 32 mostra como C representa
um valor inteiro:

Figura 32 Como C representa um valor inteiro.

Os valores do tipo int so nmeros inteiros; eles no incluem uma parte fracionria como os nmeros em
ponto flutuante. Se voc atribuir um valor de ponto flutuante a uma varivel do tipo int, a maioria dos compi
ladores C simplesmente truncar a parte fracionria. Se voc atribuir uma varivel do tipo int a um valor fora
do intervalo de -32.768 at 32.767, uma condio de extravasamento ocorrer, e o valor atribudo estar errado.

C o m p r e e n d e n d o a s V a r i v e is d o T ip o c h a r 33
Uma varivel um nome que o compilador C associa com uma ou mais posies de memria. Quando voc de
clara uma varivel dentro de seu programa, precisa especificar o nome e o tipo da varivel. O tipo de uma varivel
especifica o tipo de valores que a varivel pode armazenar e o conjunto de operaes que o programa pode rea
lizar com os dados. C usa o tipo char para armazenar valores de caracteres (bytes). O compilador C normalmente aloca
oito bits (um byte) para armazenar os valores do tipo char. Uma varivel do tipo char pode armazenar valores de n
meros inteiros no intervalo de -128 a 127. A Figura 33 mostra como C representa um valor do tipo char.

Figura 33 C om o C representa um valor do tipo char.

Os programas podem atribuir um valor a uma varivel do tipo char de dois modos. Primeiro, o programa
pode atribuir o valor ASCII de um caractere. Por exemplo, a letra A tem o valor ASCII 65:
char letra = 65; // Atribui o caractere A varivel letra
16 Pro g ra m a n d o em C/C+ + A B b lia

Segundo, seu programa pode usar uma constante de caractere, que aparece dentro de apstrofos, como
mostrado aqui:
char letra = 'A';
As variveis do tipo char somente contm uma letra de cada vez. Para armazenar mltiplos caracteres, voc
precisa declarar uma string de caracteres, o que discutido mais frente na seo Strings.

34 Co m p r e e n d e n d o as V a r i v e is do T ip o flo a t
Uma varivel um nome que o compilador C associa com uma ou mais posies de memria. Quando voc de
clara uma varivel dentro do seu programa, precisa especificar o tipo e o nome da varivel. O tipo de uma varivel
especifica o tipo de valores que a varivel pode armazenar e o conjunto de operaes que o programa pode rea
lizar com os dados. C usa o tipo float para armazenar valores em ponto flutuante (nmeros positivos e negativos
que contm partes fracionrias). O compilador C normalmente aloca 32 bits (4 bytes) para armazenar valores
do tipo float. Uma varivel do tipo float pode armazenar valores com seis a sete dgitos de preciso no intervalo
de 3.4E-38 at 3.4E+38.
C armazena o valor como uma mantissa de 23 bits, que contm o nmero fracionrio; um expoente de 8
bits, que contm a potncia a qual o computador elevar o nmero quando for determinar seu valor; e um bit
de sinal, que determina se o valor positivo ou negativo. Em outras palavras, se uma varivel continha o valor
3.4E+38, o bit de sinal seria 0, o que indica que o nmero positivo; a mantissa de 23 bits incluiria uma re
presentao binria de 3.4, e o expoente de 8 bits incluiria uma representao binria do expoente 1038. A Figura
34 ilustra como C representa um valor do tipo float. A Dica 337 explica as mantissas e os expoentes em detalhes.

Figura 34 C om o C representa u m valor do tipo float.

Nota: Esta dica e outras dicas posteriores representam os nmeros em ponto flutuante em notao cientfica. Basica
mente, a notao cientfica permite-lhe representar qualquer nmero como um dgito simples esquerda do ponto de
cimal, e um nmero ilimitado de dgitos direita do ponto decimal, e um expoente representando 10 elevado ao valor
desse expoente. Para determinar o valor real do nmero, multiplique o nmero (a mantissa) pelo valor 10 * (onde
x representa o expoente). Por exemplo, o nmero 3.1415967E+7 avaliado como 31415967.0 ou 3.1415967 * 10

35 C o m p r e e n d e n d o a s V a r i v e i s d o T ip o d o u b l e
Uma varivel um nome que o compilador C associa com uma ou mais posies de memria. Quando voc de
clara uma varivel dentro de seu programa, precisa especificar o tipo e o nome da varivel. O tipo da varivel es
pecifica o tipo de valores que as variveis podem armazenar e o conjunto de operaes que 0 programa pode
realizar com os dados. C usa o tipo double para armazenar valores em ponto flutuante (nmeros positivos e ne
gativos que contm as partes fracionrias). O compilador C normalmente aloca 64 bits (8 bytes) para armazenar
os valores do tipo double. Uma varivel do tipo double pode armazenar valores com 14 a 15 dgitos de preciso,
no intervalo de -1.7E-308 at 1.7E+308. A Figura 35 ilustra como C representa um valor do tipo double.

Figura 35 Com o C representa um valor do tipo double.


I ntroduo lin g ua g em c 17

A t r ib u in d o V a l o r e s aos Va lo res em P o n to F l u t u a n t e 36
Um valor em ponto flutuante um valor que contm uma parte fracionria, tal como 123.45. Ao trabalhar com
valores em ponto flutuante dentro de seus programas, voc pode referenciar osvalores usando seus formatos de
cimais, tais como 123.45, ou pode usar o formato exponencial do nmero,1.2345E2. Portanto, os seguintes co
mandos atribuem o mesmo valor varivel raio:
raio = 123.45;
raio = 1.2345E2;
De forma similar, os dois comandos a seguir atribuem o mesmo valor fracionrio varivel raio:
raio = 0.12345;
raio = 12.345E-2;

Co m p r e e n d e n d o os M o d if ic a d o r e s de T ip o 37
C oferece quatro tipos bsicos de dados (int, char, float e double). Como voc aprendeu, cada tipo define um con
junto de valores que a varivel pode armazenar e um conjunto de operaes que o programa pode realizar com
os dados. J vimos que as variveis do tipo int podem armazenar valores no intervalo de -32.768 at 32.767. Da
mesma forma, as variveis do tipo char armazenam valores no intervalo de -128 at 127. Para lhe ajudar a mo
dificar o intervalo de valores que as variveis do tipo in te char podem armazenar, C oferece um conjunto de mo
dificadores de tipo unsigned, long, register, signede short. Um modificador de tipo muda (modifica) o intervalo
de valores que uma varivel pode armazenar ou o modo como o compilador armazena uma varivel. Para mo
dificar um tipo, coloque o modificador de tipo diante do nome do tipo na declarao da varivel, como mos
trado aqui:
unsigned int numero_itens;
register int contador;
long int numero muito grande;
Vrias outras dicas posteriores discutiro os quatro modificadores de tipo em detalhes.

Co m p r e e n d e n d o o M o d if ic a d o r de T ip o u n s ig n e d 38
Um modificador de tipo altera (modifica) o intervalo de valores que uma varivel pode armazenar ou o modo
como o compilador armazena uma varivel. Como voc aprendeu, as variveis do tipo int podem armazenar va
lores positivos e negativos no intervalo de -32.768 at 32.767. Dentro da representao de um valor do tipo int,
o bit mais significativo do valor indica o sinal do valor (positivo ou negativo), como vimos na Dica 32. Em al
guns casos, seu programa pode nunca precisar armazenar um valor negativo em uma varivel especfica. O mo
dificador de tipo unsigned diz ao compilador para no usar o bit mais significativo como um bit de sinal, mas,
em vez disso, permitir que o bit represente valores positivos maiores. Uma varivel do tipo unsigned int pode ar
mazenar valores no intervalo de 0 at 65.535. A Figura 38.1 ilustra como o compilador C armazena uma varivel
do tipo unsigned int.

Figura 38.1 Como o compilador C representa os valores do tipo unsigned int.

Como discutido na Dica 33, as variveis do tipo char podem conter valores no intervalo de -128 at 127.
Ao usar o modificador de tipo unsigned com as variveis do tipo char, voc pode criar variveis que podem ar
mazenar valores no intervalo de 0 at 255. A Figura 38.2 ilustra como o compilador C representa uma varivel
unsigned char.
18 P rog ram and o em C/C++ A B b l ia

Figura 38.2 C o m o o com pilador C representa as variveis do tip o unsigned char.

Os comandos a seguir ilustram as declaraes das variveis com tipo unsigned int ou unsigned char:
void main(void)
{
unsigned int segundo_atuais;
unsigned int indicador_status;
unsigned char borda_menu; // Caractere ASCII estendido
}

39 C o m p r e e n d e n d o o M o d if ic a d o r d e T ip o l o n g
Um modificador de tipo altera (modifica) o intervalo de valores que uma varivel pode armazenar ou o modo
como o compilador armazena uma varivel. Variveis do tipo in t podem armazenar valores positivo e negativo
no intervalo -32.768 at 32.767. Como mostrado anteriormente na Dica 32, o compilador C representa os va
lores do tipo int usando 16 bits, com o bit mais significativo indicando o sinal do valor. Em muitos casos, seus
programas podem armazenar valores inteiros que so maiores (maiores que 32.767) ou menores (menores que
-32.768) que o intervalo de valores que uma varivel do tipo in t pode conter. O modificador de tipo long diz
ao compilador para usar 32 bits (4 bytes) para representar os valores inteiros. Uma varivel do tipo long int pode
armazenar valores no intervalo de -2.147.483.648 at 2.147.483.647. A Figura 39 mostra como o compilador
C armazena uma varivel long int.

Figura 39 C om o o com pilador C representa os valores do tipo long int. ,

N o ta : Muitos compiladores C++ tambm suportam o tipo long double, que seus programas podem usar para repre
sentar os nmeros em ponto flutuante com at 80 dgitos de preciso, em vez do padro de 64 dgitos de preciso. Os
valores do tipo long double usam 10 bytes de memria, com uma mantissa de 60 bits e um expoente de 19 bits. O in
tervalo para um valor long double 3 .4E-4932 at 1.1E+4932. Para determinar se seu compilador suporta declara
es long double, verifique a documentao do seu compilador.

40 C o m b i n a n d o o s M o d if ic a d o r e s d e T ip o u n s ig n e d e l o n g
Na Dica 38 voc aprendeu que o modificador de tipo unsigned instrui o compilador C a no interpretar o bit
mais significativo de um valor como um indicador de sinal, mas, em vez disso, instrui a usar esse bit para repre
sentar um valor maior. Da mesma forma, na Dica 39, voc aprendeu que o modificador de tipo long instrui o
compilador a dobrar o nmero de bits que ele usa para representar um valor inteiro. Em alguns casos, seus pro
gramas podem precisar armazenar valores positivos muito grandes. Combinando os modificadores de tipo un
signed e long, voc pode instruir o compilador C a alocar uma varivel de 32 bits capaz de armazenar valores no
intervalo de 0 at 4.292.967.265. A Figura 40 ilustra como o compilador C representaria uma varivel unsigned
long int:
I n tro duo lin g ua g em C 19

Figura 40 C om o o com pilador C representa valores d o tipo unsigned long int.

Os comandos a seguir declaram variveis do tipo unsigned long int.


void main(void)
{
unsigned long int valor_muito_grande;
unsigned long int divida_publica;
}

Tr a b a lh a n d o com o s Va lo r es Gra n d es 41
Como voc aprendeu, as variveis do tipo int podem armazenar valores no intervalo de -32.768 at 32.767. Da
mesma forma, as variveis do tipo long int podem armazenar valores no intervalo de -2.147.483.648 at
2.147.483.647. Quando voc trabalhar com valores grandes em seus programas, no inclua vrgulas. Em vez dis
so, trabalhe com os nmeros grandes como mostrado aqui:
long int numero_grande = 1234567;
long int um_milhao = 1000000;
Se voc incluir vrgulas dentro de seus nmeros, o compilador C gerar um erro de sintaxe.

Co m p r e e n d e n d o o M o d if ic a d o r de T ip o r e g is t e r 42
Uma varivel o nome que seu programa associa com uma posio de memria. Quando voc declara uma va
rivel, o compilador C aloca memria para conter o valor da memria. Quando seu programa precisar acessar
a varivel, ocorre uma pequena sobrecarga na execuo (o computador consome tempo) enquanto o processador
acessa a memria. Dependendo do uso da varivel, algumas vezes voc pode instruir o compilador a armazenar
a varivel em um registrador (que reside dentro da prpria CPU) para aumentar o desempenho do seu programa.
Como o compilador pode acessar o valor muito mais rapidamente quando ele reside em um registrador, a exe
cuo do seu programa acaba sendo mais rpida. O modificador de tipo register instrui o compilador a manter
a varivel em um registrador sempre que for possvel. Como o processador tem um nmero limitado de regis-
tradores, o compilador no pode manter o valor de uma varivel permanentemente em um registrador. Assim,
o compilador tentar manter a varivel em um registrador sempre que for possvel. Os comandos a seguir mos
tram o uso do modificador de tipo register:
void main(void)
{
register int contador;
register unsigned sinaliz_status;
}
Voc dever usar o modificador de tipo register com as variveis que seu programa acessar repetidamente,
tais como variveis controladoras de um lao que o programa acessa a cada iterao.

Co m p r e e n d e n d o o M o d if ic a d o r de T ip o sho rt 43
Como discutido na Dica 32, o compilador C normalmente representa as variveis do tipo int usando 16 bits.
Portanto, as variveis do tipo int podem armazenar valores no intervalo de -32.768 at 32.767. No entanto, se
voc estiver usando um compilador de 32 bits, o compilador pode representar um valor inteiro usando 32 bits,
o que significa que uma varivel do tipo int poderia armazenar valores no intervalo de -2.147.483.648 at
2.147.483.647. Se voc armazenar um valor que esteja fora do intervalo que uma varivel do tipo /w/pode ar-
20 P rog ram and o em C/C++ A B b l ia

mazenar, ocorre uma condio de extravasamento, e o vaior atribudo estar errado. (A Dica 50 explica o extra-
vasamento em detalhes.) Os programadores escrevem alguns programas sabendo que, ao ocorrer um extravasa
mento, o compilador consistentemente atribuir o valor errante (o que significa que o valor errante sempre o
mesmo) ao valor extravasado. Em outras palavras, o programador escreve o programa para usar extravasamento.
Se voc migrar um programa que usa valores do tipo int desse modo (isto , que conta com o extravasamento
do valor) de um ambiente de 16 para 32 bits, o extravasamento no ocorrer mais, pois o inteiro de 32 bits po
der armazenar um valor maior. Se voc escrever um programa que se baseia em extravasamento, o que presume
que o compilador representa as variveis int com 16 bits, voc poder usar o modificador de tipo short para ga
rantir que o compilador represente uma varivel usando 16 bits. Os comandos a seguir ilustram as declaraes
de variveis do tipo short int:
void main(void)
{
short int valor_chave;
short int numero_pequeno;
}

44 O m it in d o in t d a s D e c l a r a e s M o d if ic a d a s
Dentro desta seo, voc aprendeu sobre vrios modificadores de tipo de C, incluindo long, short e unsigned. Os
comandos a seguir ilustram como usar esses trs modificadores:
unsigned int sinaliz_status;
short int valor_pequeno;
long int numero_muito_grande;
Quando voc usar esses trs modificadores de tipo, a maioria dos compiladores permitir que voc omita
o int, como mostrado aqui:
unsigned sinaliz_status;
short valor_pequeno;
long numero_muito_grande;

45 Co m p r e e n d e n d o o M o d if ic a d o r de T ip o s ig n e d
Como voc aprendeu na Dica 33, os compiladores C normalmente representam as variveis do tipo char usando
oito bits, com o bit mais significativo representando o sinal do valor. Portanto, as variveis do tipo char podem
armazenar valores no intervalo de -128 at 127. Na Dica 38, voc aprendeu que pode usar o qualificador un
signed para instruir o compilador C a no interpretar o bit de sinal, mas, em vez disso, a usar o bit para repre
sentar um valor positivo maior. Usando o modificador de tipo unsigned, uma varivel do tipo char pode
armazenar valores no intervalo de 0 at 255. Se voc estiver usando uma varivel do tipo chart atribuir varivel
um valor fora do intervalo de valores vlidos, haver extravasamento e o valor que o computador atribuir va
rivel no ser aquele que voc deseja. No entanto, em alguns casos, voc escrever programas planejando a ocor
rncia de extravasamento. Se voc acha que futuramente esse programa ser compilado sob um compilador
diferente, que talvez represente as variveis do tipo char como unsigned, possvel usar o modificador de tipo
signed para garantir que o segundo compilador represente as variveis do tipo char usando 7 bits para os dados
e 1 bit para o sinal. Os comandos a seguir mostram declaraes do tipo signed char:
void main(void)
{
signed char valor_byte;
signed char escolha_menu;
}

46 M l t ip l a s O p e r a e s de At r ib u i o
Como voc aprendeu, C usa o sinal de igual (=) como um operador de atribuio. Normalmente, seus programas
C atribuiro valores s variveis em linhas distintas, como mostrado aqui:
I ntroduo lin g u a g em C 21

conta = 0;
soma = 0;
valor = 0;
Quando voc quiser atribuir o mesmo valor a mltiplas variveis, C lhe permite efetuar todas as atribuies
de uma s vez, como mostrado aqui:
conta = soma = valor = 0;
Quando C encontra uma operao de atribuio mltipla, atribui os valores da direita para a esquerda.
Como regra, somente use atribuies mltiplas para inicializar variveis. Usar essas operaes para clculos mais
complexos prejudica a legibilidade do seu programa. Por exemplo, o programa a seguir atribuir a duas variveis
o equivalente maisculo do caractere digitado pelo usurio:
salva_letra = letra = toupper(getchar());

A t r ib u in d o o Valo r de um T ip o de V a r i v e l a um T ip o
Dif e r e n t e 47
U m tipo define o conjunto de valores que uma varivel pode armazenar e o conjunto de operaes que seus pro
gramas podem executar com os dados. C oferece quatro tipos bsicos de dados {int, float, chart double). Alguns
casos podem requerer que voc atribua o valor de uma varivel do tipo int a uma varivel do tipo float, e vice-
versa. Como uma regra geral, voc pode atribuir com sucesso um valor do tipo int a uma varivel do tipo float.
No entanto, quando atribuir o valor de uma varivel do tipo float a uma varivel do tipo int, precisa tomar cui
dado. A maioria dos compiladores truncar o valor em ponto flutuante, descartando a parte fracionria. Porm,
outro compilador poderia arredondar o valor em vez de simplesmente trunc-lo (isto , se a parte fracionria for
maior que 0.5, os dois compiladores convertero o valor de forma diferente). Se voc quiser garantir que seu pro
grama efetue a converso de valores em ponto flutuante para inteiro de forma consistente, considere o uso das
funes ceil e floor, apresentadas mais frente na seo Matemtica.

C r ia n d o S e u s P r p r i o s T i p o s 48
Um tipo define o conjunto de valores que uma varivel pode armazenar e o conjunto de operaes que seu pro
grama pode realizar com os dados. C oferece quatro tipos bsicos de dados (int, float, chart double). Como visto,
voc pode combinar os modificadores de tipo para alterar o intervalo de valores que uma varivel pode arma
zenar. medida que o nmero de variveis declaradas aumentar, voc poder achar conveniente criar seu prprio
nome de varivel, o que oferece um nome de atalho para um tipo usado comumente. Por exemplo, considere
as seguintes declaraes do tipo unsigned long int:
unsigned long int segundo s_de sde_j ane iro;
unsigned long int populacao_mundial_em__2 000;
Usando o comando typedeft C, voc pode definir o nome de tipo ULINT, que idntico ao tipo un
signed long int, como mostrado aqui:
typedef unsigned long int ULINT;
Aps criar o nome do tipo, voc poder usar o nome para definir variveis, como mostrado aqui:
ULINT segundos_desde_janeiro;
ULINT populacao_mundial_em_2 000;
A medida que seus programas forem usando declaraes de variveis mais complexas, voc ver que criar
um novo nome de tipo muito conveniente, pois reduz a quantidade de digitao e a possibilidade de erros.
Nota: O cdigo dentro desta dica define U L IN T em maisculas porque mais fcil para outro programador deter
minar os tipos personalizados se voc os representar deforma diferente que os tipos padro. Voc pode usar letras mais
culas, minsculas ou uma combinao das duas nos nomes dos tipos - a escolha sua. No entanto, seja coerente ao
nomear os tipos personalizados em seus programas ou os diversos tipos dentro do mesmo programa.
22 pr o g r a m a n d o em C/C++ a B b l ia

49 ATRIBUINDO UM VALOR HEXADECIMAL OU OCTAL


Dependendo do seu aplicativo, algumas vezes voc precisar trabalhar com valores octais (base 8) ou hexadecimais
(base 16). Nessas ocasies voc dir ao compilador que quer trabalhar com valores que no so decimais. Se voc
preceder um valor numrico com um 0 (zero), tal como 077, o compilador C tratar o valor como octal. Da
mesma forma, se voc preceder um valor com Ox, tal como OxFF, o compilador tratar o valor como hexade
cimal. Os comandos a seguir ilustram como usar uma constante octal e hexadecimal:
int valor_octal = 0227;
int valor_hexa = OxFPO;

50 Co m p r e e n d e n d o o Ex t ra v a sa m en to
Como voc aprendeu, o tipo de uma varivel define o intervalo de valores que uma varivel pode armazenar e
as operaes que um programa pode realizar com a varivel. Por exemplo, as variveis do tipo int podem arma
zenar valores no intervalo de -32.768 at 32.767. Se voc atribuir um valor fora desse intervalo a uma varivel
do tipo int, ocorrer um erro de extravasamento. Como voc j aprendeu, C usa 16 bits para representar as va
riveis do tipo int. O compilador C usa o mais significativo dos 16 bits para determinar o sinal de uma varivel.
Se o bit mais significativo for 0, o valor ser positivo. Se o bit mais significativo for 1, o valor ser negativo. C
depois usa 15 bits para representar o valor da varivel. Para compreender por que ocorre o extravasamento, voc
precisa considerar a implementao bit a bit do valor. Considere os seguintes valores:
0 0000 0000 0000 0000
1 0000 0000 0000 0001
2 0000 0000 0000 0010
3 0000 0000 0000 0011
4 0000 0000 0000 0100

32.765 0111 1111 1111 1101


32.766 0111 1111 1111 1110
32.767 0111 1111 1111 1111
Se voc somasse 1 ao valor seria 32.767, poderia esperar o resultado 32.768. No entanto, para C o valor
seria -32.768, como mostrado aqui:
32.767 0111 1111 1111 1111
+ 1 0000 0000 0000 0001

-32.768 1000 0000 0000 0000


O programa a seguir, extravas.c, ilustra como ocorre o extravasamento:
tinclude <stdio.h>

void main(void)

int positivo = 327 67;


int negativo = -32768;

printf("%d + 1 %d\n", positivo, positivo+1);


printf("%d - 1 %d\n", negativo, negativo-1);
}

Quando voc compilar e executar este programa, sua tela exibir a seguinte sada:
32767 + 1 -32768
-32768 -1 32767
C:\>
Como voc pode ver, somar um valor a 32.767 produz um nmero negativo, enquanto subtrair um valor
de -32.768 produz um nmero positivo. Um problema que dificulta o extravasamento que, dentro de seus pro
I ntroduo lin g u a g em c 23

gramas, voc normalmente no ver o erro porque o compilador C no retorna um erro quando o extravasamen
to ocorre. Em outras palavras, a execuo do programa continua, apesar do extravasamento. Conseqentemente,
quando voc depurar seus programas, poder ter dificuldade em detectar os erros que resultam de um extrava
samento.
Nota: Se voc usar o compilador Turbo C++ Lite, ou a maioria dos compiladores mais novos (tais como o Microsoft
Visual C++, o Borland C++ 5.02&), o compilador o advertir sobre um problema potencial de extravasamento. O
compilador Turbo C++ Lite far advertncias de Constant is long in function main e Conversion may lose signi-
fica n t digits in function main(), mas, mesmo assim, executar o programa (e extravasar as variveis). Como regra
geral, mesmo se uma mensagem de advertncia do compilador no interromper a compilao do programa, voc dever
observar essas mensagens com ateno e agir apropriadamente.

Co m p r e e n d e n d o a P r e c is o 51
Como vimos, os computadores representam os nmeros internamente usando combinaes de ls e Os (dgitos
binrios). Nas dicas anteriores, voc aprendeu que, como um tipo tem um nmero fixo de bits, cada tipo somen
te pode conter um intervalo especfico de valores. Se voc atribuiu um valor fora do intervalo do tipo, ocorrer
um erro de extravasamento. Os nmeros em ponto flutuante podem experimentar extravasamento e ter preciso
insuficiente. A preciso de um valor define seu grau de exatido. Os valores do tipo float, por exemplo, oferecem
de seis a sete dgitos significativos. Por exemplo, assuma que voc atribuiu o valor 1.234567890 a uma varivel
do tipo float. Como o tipo float somente oferece sete dgitos significativos, voc somente pode contar com pre
ciso at 1.23456. Por outro lado, os valores do tipo double, oferecem 14 a 15 dgitos significativos. Como re
sultado, um valor do tipo double poderia armazenar com exatido o valor 1.234567890.
Quando voc trabalhar com nmeros em ponto flutuante, voc precisa saber que o computador representa
os valores usando um nmero fixo de bits. Portanto, impossvel para o computador sempre representar os va
lores com exatido. Por exemplo, o computador pode representar o valor 0.4 como 0.3999999, ou o valor 0.1 como
0.099999, e assim por diante. O programa a seguir, preciso.c, ilustra a diferena entre preciso dupla e simples:
ttinclude <stdio.h>

void main(void)
{
float exato = 0.123456790987654321;
double mais_exato = 0.1234567890987654321;

printf("Valor de float\t %21.19f\n", exato);


printf("Valor de double\t %21.19f\n, mais_exato);
}

Quando voc compilar e executar o programa preciso.c, sua tela exibir o seguinte resultado:
Valor de float: 0.1234567890432815550
Valor de double: 0.1234567890987654380
C:\>

ATRIBUINDO APSTROFOS E OUTROS CARACTERES 52


medida que voc trabalhar com variveis do tipo char, ou com strings de caracteres, algumas vezes precisar
atribuir um caractere de apstrofo ou de aspas a uma varivel. Por exemplo, para escrever Caixa dagua, voc pre
cisa incluir o apstrofo dentro da string. Nesses casos, voc precisa colocar o caractere dentro de apstrofos pre
cedido por uma barra invertida (\), como mostrado aqui:
char apostrofe = '\ ;
char aspas = '\"';
Alm dos caracteres de apstrofo, seus programas podem requerer que voc atribua um dos caracteres es
peciais listados na Tabela 52. Para fazer isso, simplesmente coloque o smbolo do caractere imediatamente aps
o caractere de barra invertida. Em todos os casos, voc precisa usar letras minsculas para representar o caractere
especial.
24 P rogram ando em C/C++ A B b l ia

Tabela 52 Caracteres de escape definidos por C.


Caractere de Escape Significado
Vj Caractere ASCII do aviso sonoro
Caractere de retrocesso
y Caractere de avano do formulrio
V? Caractere de nova linha
V Retomo do carro (sem alimentao de linha)
V Tabulao horizontal
\v Tabulao vertical
w Caractere da barra invertida
V Apstrofo
V Aspas
\? Interrogao
\nnn Valor ASCII em octal
\xnnn Valor ASCII em hexadecimal

53 In t r o d u o a o Co m a n d o p r in t f
Vrias dicas apresentadas neste livro usam a funo p rin tf para exibir mensagens na tela. Quando seu programa
usa prin tf as informaes que voc instrui printf a imprimir so chamadas parmetros ou argumentos de printf. O co
mando a seguir usa printf para exibir a mensagem Bblia do Programador C/C++, do Jamsa! na sua tela:
printf("Bblia do Programador C/C++, do Jamsa!");
Neste caso, a string de caracteres (as letras que aparecem dentro das aspas) o nico parmetro de printf.
Quando seus programas comearem a trabalhar com variveis, voc poder querer usar p rin tf para exibir os va
lores de cada varivel. A funo p rin tfsuporta mais de um parmetro. O primeiro parmetro sempre precisa ser
uma string de caracteres. Voc pode fazer os parmetros que seguem a primeira string de caracteres serem n
meros, variveis, expresses (tais como 3*15), ou at outras strings de caracteres. Quando voc quiser que p rin tf
exiba um valor ou uma varivel, precisa fornecer informaes sobre o tipo da varivel dentro do primeiro par
metro. Alm de especificar caracteres dentro do primeiro parmetro, voc pode incluir especificadores de forma
to, que instruem p rin tfcomo imprimir os outros parmetros. Esses especificadores de formato tm a forma de
um sinal de porcentagem (%) seguido por uma letra. Por exemplo, para exibir um valor inteiro, voc usa o % d
(d para valor decimal). Da mesma forma, para imprimir um valor em ponto flutuante, voc pode usar % f Os
seguintes comandos printfustram como voc pode usar especificadores de formato com printf:
printf("A idade do usurio %d\n", idade);
printf("O imposto %f\n", custo * 0.07);
printf("Idade do usurio: %d peso: % altura: %d\n,"
idade, peso, altura);
Como voc pode ver, dentro do primeiro parmetro de printf, possvel especificar um ou mais especifi
cadores de formato. Observe que o terceiro comando no coube na linha e continuou na linha seguinte. Quando
seus comandos no couberem em uma linha, procure encontrar uma posio para quebrar a linha (tal como ime
diatamente aps uma vrgula) e depois recue (endente) a linha seguinte. O propsito da endentao melhorar
o aspecro visual do seu programa e tornar evidente a qualquer pessoa que for ler seu programa que a linha conti
nuao da anterior. Vrias dicas a seguir discutem em detalhes os diferentes especificadores de formato de printf.

54 Ex i b i n d o V a l o r e s d o T ip o i n t U s a n d o p r in t f
A funo printfsuporta especificadores de formato que oferecem a p rin tf nformaes sobre seus tipos de parmetros
(tais como int, float, char e. assim por diante). Para exibir valores do tipo int com printf, use o especificador de formato
%d O programa a seguir, intsai.c, usa o especificador de formato % d para exibir valores e variveis do tipo int:
#include <stdio.h>

void main(void)
I ntroduo lin g u a g em C 25

{
int idae = 41;
int altura = 182;
int peso = 80;

printf("Idade do usurio: % peso: % altura: %d\n",


idade, peso, altura);
printf("%d mais %d igual a %d\n", 1, 2, 1 + 2 ) ;
}
Quando voce compilar e executar o programa intsai.c, sua tela exibir a seguinte sada:
Idade do usurio: 41 peso 80 altura 182
1 mais 2 igual a 3
C: \>

Nota: Muitos compiladores C tratam o especificador de formato %i como idntico a %d. No entanto, se voc estiver
criando novos programas, use o especificador %d, pois %i um legado do passado, e os compiladores futuros talvez dei
xem de aceit-lo.

I m p r im in d o um V a l o r I n t e ir o O c t a l o u H e x a d e c im a l 55
A funo p rin tf suporta especificadores de formato que oferecem a printf'informaes sobre seus tipos de par
metros (tais como int, float, chart assim por diante). Dependendo do seu programa, algumas vezes voc pode
querer exibir um valor inteiro em seu formato octal (base 8) ou hexadecimal (base 16). O especificador de for
mato %o (letra o, no zero) instrui p rin tf a exibir um valor em octal. De uma forma similar, os especificadores
% xe %A-instruem p r in tf a exibir um valor no formato hexadecimal. A diferena entre %x e % X que o ltimo
exibe valores hexadecimais em maisculas. O programa a seguir, oct_hexa.c, ilustra o uso dos especificadores de
formato %o, %x e %X:
#include <stdio.h>

void main(void)
{
int valor = 255;

printf("O valor decimal% em octal %o\n", valor, valor);


printf("O valor decimal% em hexadecimal %x\n", valor, valor);
printf("O valor decimal%d em hexadecimal %X\n", valor, valor);
}
Quando voc compilar e executar o programa octjoexa.c, sua tela exibir a seguinte sada:
O valor decimal 255 em octal 377
O valor decimal 255 em hexadecimal ff
O valor decimal 255 em hexadecimal PF
C:\>

Ex i b i n d o V a l o r e s d o T i p o u n s i g n e d i n t U s a n d o p r i n t f 56
Como voc aprendeu, a funo printf suporta especificadores de formato que fornecem a p r in tfnformaes so
bre seus tipos de parmetro (tais como int, char etc.). Para exibir valores do tipo unsigned itit com printf, voc
deve usar o especificador de formato %u. Se voc usar %d em lugar de %u, p rin tf tratar o valor especificado
como tipo int, o que provavelmente exibir o resultado incorreto. O programa seguinte u_intsai.c, usa o espe
cificador de formato %u, bem como %d, para exibir o valor 42000. O programa u_intsai.c ilustra o tipo de erro
que pode ocorrer se voc usar o especificador de formato incorreto:
26 P rogram and o em C/C++ A B b l ia

ttinclude <stdio.h>

void main(void)
{
unsigned int valor = 42000;

printf("Exibindo 42000 como unsigned %u\n", valor);


printf("Exibindo 42000 como int %d\n", valor);
}

Quando voc compilar e executar o programa u_intsai.c, sua tela exibir a seguinte sada:
Exibindo 42000 como unsigned 42000
Exibindo 42000 como int -23536
C:\>
Nota: Quando voc compilar este programa sob o Turbo C++ Lite, o'compilador exibir duas mensagens de erro,
pois ele v o valor constante 42.000 que o programa tenta atribuir varivel unsigned in t valor como um nmero
long em vez de um int. Neste caso, como o propsito do programa mostrar os erros que podem surgir a partir das
declaraes unsigned int, voc dever ignorar as advertncias do compilador. Outros compiladores de 16 bits emitiro
advertncias similares.

57 E x i b in d o V a l o r e s do T ip o l o n g in t Usa n d o p r in t f
Como j vimos, a funo p rin tf suporta os especificadores de formato que lhe oferecem informaes sobre os ti
pos de parmetros (tais como int, float, char etc.). Para exibir valores do tipo long int com printf, voc dever usar
o especificador de formato %ld. Se voc usar % d em lugar de %ld, p rin tf tratar o valor especificado como tipo
int, muito provavelmente exibindo o resultado errado. O programa a seguir, longsai.c, usa o especificador de for
mato %ld, bem como %d, para exibir o valor 1000000. O programa longsai.c ilustra o tipo de erro que poder
ocorrer se voc usar o especificador de formato incorreto:
#include <stdio.h>

void main(void)
{
long int um_milhao = 1000000;

printf ("Um milho %ld\n", um_milhao);


printf ("Um milho %d\n", um_milhao);

Quando voc compilar e executar o programa longsai.c, sua tela exibir a seguinte sada:
Um milho 1000000
Um milho 16960
C:\>

58 E x i b in d o V a l o r e s do T ip o flo a t Usa n d o p r in t f
Como voc sabe, a funo printf suporta especificadores de formato que lhe oferecem informaes sobre os tipos
de seus parmetros (tais como int, float, char etc.). Para exibir valores do tipo float com printf, voc dever usar
o especificador de formato %f. O programa a seguir, floatsai.c, usa o especificador de formato % /para exibir va
lores em ponto flutuante:
ttinclude <stdio.h>

void main(void)
{
float preco = 525.75;
float imposto_vendas = 0.06;
I ntroduo lin g u a g em c 27

printf("O custo do item %f\n", preco);


printf("O imposto sobre a venda do item %f\n",
preco * imposto_vendas);
>

Quando voc compilar e executar o programa floatsai.c, sua tela exibir a seguinte sada:
O custo do item 525.750000
O imposto sobre a venda do item 31.544999
C:\>
Como voc pode ver, por padro, o especificador de formato %/fornece pouca formatao na sada. No
entanto, vrias dicas nesta seo apresentam modos de formatar sada usando printf:

E x i b in d o V a l o r e s do T ip o char Usan d o p r in t f 59
Como voc aprendeu, a funo printfsuporta especificadores de formato que fornecem informaes sobre os ti
pos dos parmetros (tais como int, float, char etc.). Para exibir os valores do tipo char com printf, voc dever
usar o especificador de formato %c. O programa a seguir, char_sai.c, usa o especificador de formato %c para exi
bir a letra A na sua tela:
#include <stdio.h>

void main(void)
{
printf("A letra %c\n, 'A');
printf(A letra %c\n", 65);
}

Como voc pode ver, o programa char_sai.c exibir a letra A usando a constante de caractere A , bem como
o valor ASCII 65. Quando voc compilar e executar o programa char_sai.c, sua tela exibir a seguinte sada:
A letra A
A letra A
C:\>

E x ib in d o V a l o r e s de P onto Flu t u a n t e em um Fo r m a t o
E x p o n e n c ia l 60
J vimos que, a funo p rin tfsu p o m os especificadores de formato que fornecem informaes sobre os tipos de
parmetro (tais como int, float, char, etc.). Na Dica 58, voc aprendeu que, usando o especificador de formato
%f, possvel exibir valores em ponto flutuante. Dependendo dos requisitos do seu programa, algumas vezes
voc pode querer exibir os valores usando um formato exponencial. Para exibir um valor em ponto flutuante em
um formato exponencial, use o especificador de formato %e ou %E. A diferena entre %e e %E que este l
timo instrui p rin tfa usar uma letra E maiscula na sada. O programa a seguir, exp_sai.c, usa os especificadores
de formato %e e %E para exibir valores em ponto flutuante em seus formatos exponenciais:
#include <stdio.h>

void main(void)
{
float pi = 3.14159;
float raio = 2.0031;

printf(A rea do crculo %e\n", 2 * pi * raio);


printf("A rea do crculo %E\n", 2 * pi * raio);
}
Quando voc compilar e executar o programa exp_sai.c, sua tela exibir a seguinte sada:
A rea do crculo 1.258584e+01
28 P ro g ram a nd o em C/C++ A B b l ia

A rea do crculo 1.258584E+01


C:\>
Como voc pode ver, os especificadores de formato %e e %E oferecem pouca formatao da sada. No en
tanto, vrias Dicas nesta seo apresentam modos de formatar a sada usando printf.

61 E x i b in d o V a l o r e s em P onto F lu t u a n t e
Na Dica 58 voc aprendeu que, usando o especificador de formato %fi possvel instruir printf a exibir valores
em ponto flutuante usando seus formatos em ponto decimal. Da mesma forma, na Dica 60, vimos que possvel
usar os especificadores de formato %e e %E para instruir p rin tfa exibir um valor em ponto flutuante usando um
formato exponencial. De uma forma similar, p r in tf suporta os especificadores de formato %g e %G. Quando
voc usa esses especificadores de formato, printfdecide se deve usar o formato % fou %e, dependendo da tcnica
que exibir a sada no formato mais significativo para o usurio. O programa a seguir, flt_pt.c, ilustra o uso do
especificador de formato % g:
iinclude <stdio.h>

void main(void)
{
printf("Exibir 0.1234 resulta em%g\n", 0.1234);
printf("Exibir 0.00001234 resulta em %g\n, 0.00001234);
}
Quando voc compilar e executar o programa flt_pt.c, sua tela exibir a seguinte sada:
Exibir 0.1234 resulta em 0.1234
Exibir 0.00001234 resulta em 1.234e-05
C:\>

62 E x i b in d o uma S t r in g de Ca r a c t e r e s U s a n d o p r in t f
Uma string de caracteres uma seqncia de zero ou mais caracteres. (A seo Compreendendo as Strings, mais
frente, discute as strings de caracteres em maiores detalhes.) Uma das operaes mais comuns que seus progra
mas executaro a sada de string de caracteres. Como voc aprendeu, a funo p r in tf suporta os especificadores
de formato que oferecem informaes sobre seus tipos de parmetro (tais como int, float, char etc.). Para exibir
uma string de caracteres usando printf, voc dever usar o especificador de formato %s. O programa a seguir,
str_sai.c, usa o especificador de formato %s para exibir uma string de caracteres:
#include <stdio.h>

void main(void)
{
char titulo[255] = "Bblia do Programador C/C++, do Jamsa!";

printf("O nome deste livro %s\n", titulo);


>
Quando voc compilar e executar o programa str_sai.c, sua tela exibir a seguinte sada:
O nome deste livro Bblia do Programador C/C++, do Jamsa!
C:\>

63 E x i b in d o um E n d ereo de P o n t e ir o U s a n d o p r in t f
Como j foi visto, a funo printf suporta especificadores de formato que informam os tipos dos parmetros (tais
como int, float, char etc.). Vimos tambm que uma varivel um nome que seu programa associa com uma po
sio de memria. medida que a complexidade do seu programa aumentar, mais cedo ou mais tarde voc tra
balhar com os endereos de memria (chamados ponteiros). Quando voc comear a trabalhar com ponteiros,
algumas vezes precisar exibir o endereo de um ponteiro. Para exibir um endereo de ponteiro usando printf,
I ntroduo lin g u a g em C 29

use o especificador de formato %p. O programa a seguir, ptr_sai.c, usa o especificador %p para exibir um en
dereo de memria:
#include <atdio.h>

void main(void)
{
int valor;

printf("O endereo da varivel valor %p\n", &valor);


>
Quando voc compilar e executar o programa ptr_sai.c, sua tela exibir a seguinte sada:
O endereo da varivel valor FFF4
C:\>
Quando voc usar o especificador de formato %p, o valor atual do ponteiro e o formato que p rin tf usa para
exibir o valor diferir de um sistema operacional para outro. A seo Ponteiros, mais frente, discute em detalhes
o uso de ponteiros.

P reced en d o um Valo r com um S in a l de A d i o ou d e

S ubtrao 64
Como voc aprendeu, p rin tfsuporta vrios especificadores de formato que controlam como p rin tf exibe a sada.
Por padro, quando voc usa p rin tf pata exibir um valor negativo, ele preceder o valor com um sinal de sub
trao. Dependendo do seu programa, algumas vezes voc pode querer que p rin tf exiba o sinal para os valores
positivos tambm. Para instruir p rin tf a exibir o sinal de um valor, simplesmente inclua um sinal de adio ime
diatamente aps o % no especificador de formato. O programa a seguir, exibesin.c, ilustra o uso do sinal de adi
o dentro do especificador de formato:
#include <stdio.h>

void main(void)
{
int neg_int = -5;
int pos_JLnt = 5;
float neg_flt = -100.23;
float pos_flt = 100.23;

printf("Os valores inteiros so %+d and %+d\n", neg_int, pos_int);


printf("Os valores em ponto flutuante ao %+f %+f\n", neg_flt, pos_flt);
}
Quando voc compilar e executar o programa exibesin.c, sua tela exibir o seguinte:
Os valores inteiros so -5 e +5
Os valores em ponto flutuante so -100.230003 +100.230003
C:\>

Fo r m a t a n d o um V a l o r I n t e ir o U s a n d o p r in t f 65
Como voc leu na Dica 54, o especificador de formato % d instrui p rin tf a exibir um valor inteiro. medida que
seus programas se tornarem mais complexos, voc querer que p r in tfformate melhor seus dados. Por exemplo,
assuma que voc queira imprimir uma tabela na tela do seu computador que similar seguinte sada:
Vendedor Quantidade
Jonas 332
Silva 1200
Alex 3311
Davi 43
30 Programando em C/C++ A B b l i a

Quando voc usar o especificador de formato %d, poder instruir p rin tf a exibir um nmero mnimo de
caracteres. O programa a seguir, int_fmt.c, ilustra como voc poderia formatar valores inteiros usando %d:
#include <stdio.h>

void main(void)
{
int valor = 5;

printf ("%ld\n, valor);


printf ("%2d\n", valor);
printf ("%3d\n", valor);
printf ("%4d\n", valor);
>
Quando voc compilar e executar o programa int_fmt.c, sua tela exibir o seguinte:
5
5
5
5
C:\>
O dgito que voc coloca aps o % especifica o nmero mnimo de caracteres que p rin tf usar para exibir
um valor inteiro. Por exemplo, caso especifique % 5 d t o valor que voc quer exibir for 10, p rin tf preceder o
valor com trs espaos. Observe que o valor especifica o nmero mnimo de caracteres que a sada consumir,
Se o valor que voc quer exibir requer mais caracteres do que voc especificou, p rin tfusar o nmero de carac
teres que p rin tfrequer para exibir o valor corretamente.

6 6 S a d a d e I n t e i r o s P r e e n c h i d a c o m Z e r o s
Na Dica 65 voc viu como formatar um valor inteiro colocando o nmero desejado de dgitos imediatamente
aps o % no especificador de formato %d. Se o valor inteiro que printfexibir no precisar do nmero de carac
teres que voc especificou, />rc'//preceder o valor com o nmero de espaos necessrios. Dependendo do pro
psito do seu programa, algumas vezes voc pode querer que p rin tf preceda o valor com zeros (chamado zero de
preenchimento), em vez de espaos. Para instruir p rin tf a preencher um valor com zeros, coloque um 0 (zero)
imediatamente aps o % no especificador de formato, antes do nmero desejado de dgitos. O programa a se
guir, enche.c, ilustra o preenchimento com zeros:
#include <stdio.h>

void main(void)
{
int valor = 5 ;
printf ("%01d\n", valor);
printf ("%02d\n", valor);
printf ("%03d\n", valor);
printf ("%04\n", valor);
>
Quando voc compilar e executar o programa enche.c, sua tela exibir o seguinte:
5
05
005
0005
C:\>
I ntroduo lin g u a g em C 31

E x i b in d o um P r e f ix o A n t e s dos V a l o r e s O c t a is ou

H e x a d e c im a is 67
Na Dica 55 voc aprendeu como usar o especificador de formato %o para exibir valores octais, e os especifica
dores de formato %x e % X para exibir valores hexadecimais. Quando seus programas apresentam esses valores,
algumas vezes voc pode querer preceder os valores octais com um zero (por exemplo, 0777), e os hexadecimais
com Ox (por exemplo, OxFF).
Para instruir prin tfz preceder um valor octal ou hexadecimal com o prefixo apropriado, coloque um sinal
de cerquinha (#) imediatamente aps o % no especificador de formato. O programa a seguir, exibe_oh.c, ilustra
o uso do caractere # no especificador de formato de printf:
#inclue <stdio.h>

void main(void)
{
int valor = 255;

printf("O valor decimal %d em octal %#o\n, valor, valor);


printf("O valor decimal %d em hexadecimal %#x\n", valor, valor);
printf("O valor decimal %d em hexadecimal %#X\n", valor, valor);
}
Quando voc compilar e executar o programa exibe_oh.c, sua tela exibir o seguinte:
O valor decimal 255 em octal 0377
O valor decimal 255 em hexadecimal Oxff
O valor decimal 255 em hexadecimal OxFF
C:\>

Form atando um Va l o r em P on to F l u t u a n t e U s a n d o p r in t f 68
Na Dica 65 voc aprendeu a formatar uni valor inteiro colocando o nmero desejado de dgitos imediatamente
aps o % no especificador de formato %d. Usando uma tcnica similar, p rin tf lhe permite formatar a sada em
ponto flutuante. Quando voc formata um valor em ponto flutuante, especifica dois valores. O primeiro valor
diz a p rin tfo nmero mnimo de caracteres que voc quer exibir. O segundo valor diz a p rin tf o nmero de d
gitos que voc quer que sejam exibidos direita do ponto decimal. O programa a seguir, flt_fmt.c, ilustra como
formatar valores em ponto flutuante usando printf.
#include <stdio.h>

void main(void)
{
float valor = 1.23456;

printf ("%8.1f\n", valor);


printf ("%8.3f\n", valor);
printf ("%8.5f\n", valor);
>
Quando voc compilar e executar o programa flt_fmt.c, sua tela exibir o seguinte:
1.2
1.235
1.23456
C:\>

Fo r m a t a n d o a S a d a E x p o n e n c i a l 69
Na Dica 68 foi visto como usar o especificador de formato %/para formatar valores em ponto flutuante. Usando
tcnicas de formatao similares, voc pode instruir printf a exibir sada em ponto flutuante em um formato ex
ponencial. O programa a seguir, exp_fmt.c, ilustra a sada formatada em exponencial.
32 P rogram and o em C/C++ A B b l ia

#include <stdio.h>

void main(void)
{
float valor = 1.23456;

printf ("%12.le\n, valor);


printf ("%12.3e\n", valor);
printf (%12.5e\n", valor);
}
Quando voc compilar e executar o programa exp_fmt.c, sua tela exibir o seguinte:
1 .2e+00
1.235e+00
1.23456e+00
C:\>

70 J u s t if ic a n d o Esq u er d a a S a d a d e p r in t f
Por padro, quando voc exibir o texto usando os caracteres de formatao, p rin tf exibir o texto justificado
direita. Dependendo do seu programa, algumas vezes voc pode querer que printf'justifique o texto esquerda.
Para justificar texto esquerda, coloque um sinal de subtrao (-) imediatamente aps o % no especificador de
formato. O programa a seguir, esquerda.c, ilustra o uso do sinal de subtrao para justificar o texto esquerda:
#include <stdio.h>

void main(void)
{
int int_valor = 5;
float flt_valor = 3.33;

printf("Justificado direita %5d valorNn", int_valor);


printf("Justificado esquerda %-5 valor\n", int_valor);
printf("Justificado direita %7.2f valor\n", flt_valor);
printf("Justificado esquerda %-7.2f valor\n", flt_valor);
>
Quando voc compilar e executar o programa esquerda.c, sua tela exibir o seguinte:
Justificado direita 5 valor
Justificado esquerda 5 valor
Justificado direita 3.33 valor
Justificado esquerda 3.33 valor
C:\>

71 C o m b in a n d o os E s p e c if ic a d o r e s de Fo r m a t o de

p r in t f
Vrias dicas apresentadas nesta seo discutiram vrios especificadores de formato de printf. medida que voc
usar os especificadores de formato de p rin tf algumas vezes voc poder querer aproveitar dois ou mais especi
ficadores de formato. Por exemplo, voc pode querer exibir um valor hexadecimal justificado esquerda, pre
cedido pelos caracteres Ox. Em tais casos, simplesmente coloque cada um dos especificadores aps o %. O
programa a seguir, todo_fmt.c, ilustra o uso de mltiplos especificadores de formato:
#include <stdio.h>

void main(void)
{
int int_valor = 5;
I ntroduo lin g u a g em C 33

printf("Justificado esquerda com sinal %-+3d\n", int_valor);


>
Quando voc compilar e executar o programa todo_fmt.c, sua tela exibir o seguinte:
Justificado esquerda com sinal +5
C:\>

Qu e b r a n d o uma S t r in g de Ca r a c t e r e s em D u a s L in h a s 72
Quando seus programas usam printf, algumas vezes uma string de caracteres no cabe na linha corrente. Nesses
casos, simplesmente coloque uma barra invertida (\) no final da linha, o que far o texto continuar no incio da
prxima linha, como mostrado aqui:
printf("Esta linha muito longa, e, portanto, no cabe na \
mesma linha.");
Nota: Se voc quebrar o texto para a prxima linha, no inclua espaos no incio da prxima linha de texto. Se exis
tirem espaos, o compilador C os incluir dentro da string.

E x i b in d o S t r i n g s do T ip o n ea r e far 73
A seo Memria, mais frente discute os ponteiros near e fa r em detalhes. Resumidamente, os ponteiros near
e fa r representam os endereos de variveis dentro do espao de memria do programa. Os programas que rodam
dentro de sistemas operacionais mais antigos, tal como o MS-DOS, usam ponteiros fa r para aumentar o inter
valo de endereos de memria que o programa pode usar para armazenar informaes. Quando seus programas
trabalham com ponteiros de string algumas vezes voc querer exibir o contedo da string usando printf. No
entanto, como voc aprender posteriormente na seo Funes, o compilador gerar um erro se voc passar um
ponteiro fa r para uma funo que espera um endereo near. Se voc quiser exibir o contedo de uma string far
(cujo incio um ponteiro de sxnngfar indica) usando p r in tf voc precisar dizer a p rin tf que est usando um pon
teiro far. Para fazer isso, coloque um F maisculo (de far) imediatamente aps o % no especificador de formato,
como mostrado aqui:
printf("%Fs\n, alguma_string_far);
Como %Fs diz a p rin tf que voc est usando um ponteiro far, a chamada da funo est correta. De uma
forma similar, voc pode dizer a p rin tf que est passando uma string near colocando um N maisculo no espe
cificador de formato. No entanto, como p rin tf tspera strings near por padro, os especificadores de formato %Ns
e %s tm o mesmo resultado. O seguinte programa C, nearJr.c, ilustra o uso de %Fs e %Ns dentro de printf:
ttinclude <stdio.h>

void main(void)
{
char *titulo_near = "Bblia do Programador C/C++, do Jamsa!";
char far *titulo_far = "Bblia do Programador C/C++, do Jamsa!;

printf("Ttulo do livro: %Ns\n", titulo_near);


printf("Ttulo do livro: %Fs\n", titulo_far);
>
Nota: O Visual C++ no distingue entre os ponteiros near efar. Se voc tentar compilar o programa near_far.c sob
o Visual C++, o compilador retomar um erro. Para atualizar automaticamente seus programas para rodar sob o Vi
sual C++, inclua o arquivo de cabealho wtndef.h dentro de seus programas.

Trabalh an d o com o s Ca r a c t e r e s E s c a p e d e p r in t f 74
Quando voc trabalha com strings de caracteres, algumas vezes querer usar caracteres especiais, tais como tabu
lao, retorno do carro, ou alimentao de linha. C define vrios caracteres de escape (isto , caracteres que voc
34 P rogram and o em C/C+ + A B b l ia

precede com o smbolo de escape de C, a barra invertida) para facilitar para voc a incluso de caracteres especiais
dentro de uma string. Por exemplo, vrios dos programas apresentados neste livro usam o caractere de nova linha
(\n) para avanar a sada para o incio da prxima linha, como mostrado aqui:
printf("Linha l\nLinha2\nLinha 3\n);
A Tabela 74 lista os caracteres de escape que voc pode usar dentro de suas strings de caractere (e, portanto,
a sada de printf).
Tabela 74 Caracteres de escape definidos por C.
Caractere de Escape Significado
\a Caractere ASCII de aviso sonoro
\h Caractere de retrocesso
V Caractere de avano de formulrio
Vi Caractere de nova linha
V Retomo do carro (sem alimentao de linha)
V Tabulao horizontal
\v Tabulao vertical
\\ Caractere de barra invertida
V Apstrofe
V Aspas
\? Interrogao
\nnn Valor ASCII em octal
\xnnn Valor ASCII em hexadecimal

75 D e t e r m in a n d o o N m er o de Ca r a c t e r e s Q u e p r in t f

Ex ib iu
Quando seus programas efetuam formatao sofisticada na tela, algumas vezes voc querer saber o nmero de
caracteres que p r in tf exibiu. Quando voc usar o especificador de formato %n, p r in tf atribuir a uma varivel
(passada por ponteiro) um contador do nmero de caracteres que p rin tf exibiu. Q programa a seguir, prt_cnt.c,
ilustra o uso do especificador de formato %n:
#include <stdio.h>

void main(void)
{
int primeiro_conta;
int segundo_conta;

printf("Bblia%n do Programador C/C++, do Jamsal%n\n", &primeiro_conta,


&segundo_conta);
printf("Primeiro conta %d Segundo conta %d\n", primeiro_conta,
segundo_conta);
>
Quando voc compilar e executar o programa prt_cnt.c, sua tela exibir o seguinte:
Bblia do Programador C/C++, do Jamsa!
Primeiro conta 6 Segundo conta 38
C:\>

76 Usan d o o Valo r de R eto rn o d e p r in t f


Na Dica 75 voc aprendeu como usar o especificador de formato %n de p rin tfpara determinar o nmero de ca
racteres que p rin tf escreveu. Usar o especificador de formato % n um modo de garantir que p rin tfteve sucesso
I ntroduo lin g u a g em C 35

ao exibir sua sada. Alm disso, quando printf termina, ele retorna o nmero total de caracteres que escreveu. Se
p rin tf e.ncontrar um erro, retornar a constante EOF (que, como voc aprender, indica o fim de um arquivo).
O programa a seguir, printfok.c, usa o valor de retorno de p rin tf para garantir que printf'foi bem-sucedido:

#include <stdio.h>

void main(void)
{
int result;

result = printf("Bblia do Programador C/C++, do Jamsa!\n")j


if (result == EOF)
fprintf(stderr, "Erro dentro de printf\n");
>
Se o usurio tiver redirecionado a sada do programa para um arquivo ou um dispositivo (tal como uma
impressora) e a E/S redirecionada experimentar um erro (tal como dispositivo fora de linha ou disco cheio), seus
programas podem detectar o erro testando o valor de retorno de p rin tf

U s a n d o o C o n t r o la d o r de D is p o s itiv o ANSI 77
Vrias dicas apresentadas neste livro utilizam muito as capacidades de formatao de p rin tf Embora printfofe
rea especificadores de formato que voc usa para controlar o nmero de dgitos mostrados, para exibir sada em octal
ou hexadecimal, ou para justificar texto direita ou esquerda, p rin tf no oferece outros especificadores de formato.
printf ho fornece especificadores de formato que lhe permitem posicionar o cursor em uma linha e coluna especficas,
limpar a tela ou exibir sada em cores. No entanto, dependendo do sistema operacional que estiver usando, voc pode
provavelmente efetuar essas operaes usando o controlador de dispositivo ANSI. 0 controlador ANSI suporta
diferentes seqncias de escape que o instruem a usar cores especficas, a posicionar o cursor e at a limpar a tela.
Os programadores chamam esses comandos de formatao de seqncias de escape, pois elas iniciam com o caractere
ASCII Escape (o valor 27). Se voc esdver usando o DOS, instale o controlador de dispositivo colocando uma entrada
tal como a seguinte dentro do seu arquivo config.sys (e depois reinicialize o computador):
DEVICE=C:\DOS\ANSI.SYS
Aps voc instalar o controlador ANSI, seus programas podem escrever seqncias de Escape usando printf.
Nota: Se voc est rodando o Windows 95 na mesma mquina que compila programas, adicionar o controlador
A N S I o seu arquivo config.sys do sistema, no afetar as operaes no Windows 95.

U s a n d o o C o n t r o la d o r ANSI p a r a Lim p ar S u a T e la 78
Uma das operaes mais comuns que cada um dos seus programas executar quando iniciar sua execuo lim
par a teia de vdeo. Infelizmente, a biblioteca de execuo de C no fornece uma funo que limpa a tela. Para
limpar a tela, use o controlador ANSI descrito na Dica 77, e, depois, chame a seguinte seqncia de escape para
limpar sua tela de vdeo:
Esc[2j
Um modo fcil de chamar a seqncia de escape usar a representao octal do caractere escape (\033).
Para imprimir o caractere escape, faa como mostrado aqui:
printf("\033[2J");

U s a n d o o C o n t r o la d o r ANSI p a r a E x ib ir a s C o r e s
da T e la 79
Vrias dicas apresentadas at aqui neste livro utilizam muito a funo printfpzra. exibir sada. Embora printf ofe
rea especificadores de formato poderosos, no oferece um modo para voc exibir texto em cores. No entanto,
36 P rog ram and o em C/C+ + A B b l ia

se estiver usando o controlador ANSI, como discutido na Dica 77, voc pode usar as seqncias de escape lis
tadas na Tabela 79 para exibir a sada em cores.
Tabela 79 Seqncias ANSI que voc pode usar para definir as cores da tela.
Seqncia de Escape Cor
Esc[30m Cor do primeiro plano preta
Esc[31m Cor do primeiro plano vermelha
Esc[32m Cor do primeiro plano verde
Esc[33m Cor do primeiro plano laranja
Esc[34m Cor do primeiro plano azul
Esc[35m Cor do primeiro plano magenta
Esc[36m Cor do primeiro plano ciano
Esc[37m Cor do primeiro plano branca
Esc[40m Cor de fundo preta
Esc[41m Cor de fundo vermelha
Esc [42 m Cor de fundo verde
Esc[ 43m Cor de fundo laranja
Esc[44m Cor de fundo azul
Esc[45m Cor de fundo magenta
Esc[46m Cor de fundo ciano
Esc[47m Cor de fundo branca

O comando p r in tf a seguir seleciona a cor de fundo azul:


printf("\033[44m");
Similarmente, o comando p r in tf a seguir seleciona texto vermelho em um fundo branco:
printf("\033[47m\033[31m");
No exemplo anterior, prinlfescreve duas seqncias de escape. O controlador ANSI lhe permite especificar
as cores da tela, separando-as com ponto-e-vrgula, como mostrado aqui:
printf("\033[47;31m");

80 U s a n d o o C o n tr o la d o r ANSI p a r a P o s ic io n a r o

C u rs o r
Como voc aprendeu, o controlador ANSI suporta as seqncias ANSI que, por sua vez, lhe permitem limpar
a tela e exibir sada em cores. Alm disso, o controlador ANSI oferece seqncias de escape que lhe permitem
posicionar o cursor para especificar as posies de linha e de coluna, que, por sua vez, lhe permitem exibir sua
sada em posies especficas na tela. A Tabela 80 mostra as seqncias de escape para o posicionamento do cursor.
Tabela 80 Seqncias de escape de posicionamento do cursor do controlador ansi que voc pode usar em seus programas.
Seqncia de Escape Funo Exemplo
Esc[x;yH Posiciona o cursor na linha x, coluna y Esc[10;25H
Esc[xA Move o cursor x linhas para cima Esc[ la
Esc[xB Move o cursor x linhas para baixo Esc[2b
Esc[yC Move o cursor y colunas para a direita Esc[ 10c
Esc[yD Move o cursor y colunas para a esquerda Esc[10d
Esc[S Armazena a posio atual do cursor Esc[S
Esc[U Restaura a posio do cursor Esc[U
Esc[2j Limpa a tela, movendo o cursor para o canto superior Esc[2j
esquerdo
Esc[K Limpa at o final da linha atual Esc[K
In tro d u o l in g u a g e m C 37

E x e c u t a n d o O p e r a e s M a t e m t ic a s B s ic a s em C 81
Quase todos os seus programas, exceto os mais simples, efetuaro operaes aritmticas, tais como adio, subtrao,
multiplicao ou diviso. Para efetuar essas operaes matemticas bsicas, use os operadores descritos na Tabela 81.
Tabela 81 Operadores aritmticos bsicos em C.
Operador Propsito
+ Adio
- Subtrao
* Multiplicao
/ Diviso

O programa a seguir, matemat.c, ilustra como usar os operadores aritmticos bsicos de C:


#include <stdio.h>

void main(void)
{
int segundos_na_hora;
float media;

segundos_na_hora = 60 * 60;
media = ( 5 + 1 0 + 1 5 + 2 0 ) / 4;
printf("Nmero de segundos em uma hora %d\n", segundos_na_hora);
printf("A mdia de 5, 10, 15, e 20 %f\n, media);
printf("O nmero de segundos em 48 minutos %d\n",
segundos_na_hora - 12 * 60);
>
Quando voc compilar e executar o programa matemat.c, sua tela exibir o seguinte resultado:
Nmero de segundos em uma hora 3600
A mdia de 5, 10, 15, e 20 12.00000
O nmero de segundos em 48 minutos 2880
C: \>

C o m p r e e n d e n d o a A r it m t ic a d o M d u l o 82
Na Dica 81 vimos que C usa o operador de barra para a frente (/) para a diviso. Dependendo do seu aplicativo,
algumas vezes voc precisar do resto de uma diviso inteira. Nesses casos, use o operador mdulo (resto) de C.
O programa a seguir, modulo.c, ilustra como usar o operador de mdulo de C:
#include <stdio.h>

void main(void)
{
int resto;
int result;

result = 1 0 / 3 ;
resto = 10 % 3;
printf("10 dividido por 3 %d Resto %d\n", result, resto);
}
Quando voc compilar e executar o programa modulo.c, sua tela exibir o seguinte:
10 dividido por 3 3 Resto 1
38 pr o g r a m a n d o em C/C++ A B b l ia

83 Com preendendo a P re c e d n c ia e a A s s o c ia tiv id a d e dos


O p e ra d o re s
Na Dica 81 voc aprendeu que C usa os seguintes operadores: o sinal de adio (+) para adio; o hfen (-) para
subtrao; o asterisco (*) para multiplicao; e a barra (/) para a diviso. Quando seus programas usam esses ope
radores dentro de expresses aritmticas, voc dever compreender a precedncia dos operadores em C, que es
pecifica a ordem em que C efetua as operaes aritmticas. Por exemplo, considere a seguinte expresso:
result = 5 + 2 * 3 ;
Se voc assumir que C efetua as operaes da esquerda para a direita (a adio antes da multiplicao), o
resultado da expresso ser 21:
reBult = 5 + 2 * 3 ;
= 7*3;
= 21;

N o entanto, se C efetuar as operaes primeiro, o resultado ser 11:


result = 5 + 2 * 3 ;
= 5 + 6;
= 11;
Para evitar o problema de resultados indeterminados, C define uma precedncia dos operadores, que deter
mina quais operaes so executadas primeiro. A Tabela 83 ilustra a precedncia dos operadores em C:
Tabela 83 Precedncia dos operadores em C.
Precedncia dos Operadores (do maior para o menor)
[] -
+ - + * & ! ~ (tipo) sizeof
* / %
+

&
A

I
&&
II
?;
= += -= *= /= %= &= A= 1= = =

Quando voc criar uma expresso, C executar as operaes com as precedncias mais altas primeiro. Se
dois operadores tiverem a mesma precedncia, C efetuar as operaes da esquerda para a direita.

84 F o r a n d o a O rdem de A v a lia o d o s O p e r a d o r e s
Como foi visto na Dica 83, C efetua as operaes em uma expresso com base na precedncia de cada operador
dentro da expresso. Em muitos casos, a ordem que C usar para avaliar os operadores no aquela que voc
quer. Por exemplo, considere a seguinte expresso - seu objetivo calcular a mdia de trs valores:
media = 5 + 10 + 1 5 / 3 ;
Matematicamente, a mdia dos trs valores 5, 10 e 15 10. No entanto, ao avaliar a expresso anterior,
C atribuir varivel media o valor 20, como mostrado aqui:
I ntroduo lin g u a g em C 39

media = 5+10+15/3;
= 5 + 10 + 5;
= 15 + 5;
= 20;
Se voc examinar a tabela de precedncia dos operadores(apresentada na Dica 83), ver que ooperador
de diviso (/) tem uma precedncia mais alta queo operador de adio (+). Portanto, voc precisa modificar a
ordem em que C efetua as operaes. Quando avalia uma expresso, C sempre efetua as operaes que aparecem
dentro de parnteses antes de efetuar as outras operaes. Quando voc agrupar os valores que quer somar dentro
de parnteses, C calcular a mdia correta, como mostrado aqui:
media = (5 + 10 + 15) / 3;
= (15 + 15) /3;c
= (30) / 3;
= 10;
C efetua as operaes dentro dos parnteses com base em suas regras de precedncia de operadores. Se uma
expresso contiver mltiplas expresses dentro de mltiplos conjuntos de parnteses, C efetua as operaes den
tro dos parnteses mais internos primeiro, como mostrado aqui:
result= ( ( 5 + 3 ) * 2 ) - 3 ;
= ((8) * 2) - 3;
= (16) - 3;
= 13;

C o m p re e n d e n d o o O p e r a d o r de In c r e m e n to de C 85
Uma opeao muito comum que os programas realizam incrementar o valor atual de uma varivel por 1. Por
exemplo, o comando a seguir incrementa o valor da varivel conta por 1:
conta = conta + 1;
Como as operaes de incremento so to comuns, C oferece uma notao resumida que voc pode usar
para incrementar as variveis dentro de seus programas, chamada operador de incremento. O comando a seguir
usa o operador de incremento para acrescentar 1 ao valor de conta:
conta++;
O programa a seguir, 0_a_100.c, usa o operador de incremento para imprimir os valores de 0 a 100:
#include <stdio.h>

void main(void)
{
int valor = 0;

while (valor <= 100)


(
printf ("SsdNn", valor);
valor++;
>
}
C oferece um operador de incremento de prefixo e de sufixo. Os dois comandos a seguir incrementam a va
rivel conta por 1:
conta++;
++conta;
O primeiro comando usa o operador de incremento de sufixo de C. O segundo comando usa o operador
de incremento de prefixo. Voc deve distinguir entre os dois operadores, pois C trata os operadores de prefixo e
de sufixo de forma diferente. Quando voc usar o operador de incremento de sufixo, C primeiro usar o valor da
40 P rog ram and o em C/C++ A B b l ia

varivel, e, depois, efetuar a operao de incremento. Por outro lado, quando voc usa o operador de incremento
de prefixo, C primeiro incrementa o valor da varivel e depois usa a varivel. Para compreender melhor a dife
rena entre os operadores de incremento de prefixo e de sufixo, considere o seguinte programa, presufic, que usa
ambos os operadores.
#include <stdio.h>

void main(void)
<
int valor = 1;

printf("Usando sufixo %d\n", valor++);


printf("Valor aps o incremento %d\n", valor);
valor = 1;
printf("Usando prefixo %d\n, ++valor);
printf("Valor aps o incremento %d\n", valor);
}
Quando voc compilar e executar o programa presufic, sua tela exibir o seguinte:
Usando sufixo 1
Valor aps o incremento 2
Usando prefixo 2
Valor aps o incremento 2
C:\>
Como voc pode ver, ao usar o operador de sufixo, C primeiro usa o valor da varivel (exibindo o valor
1), e, depois, incrementa a varivel (resultando em 2). Quando voc usa o operador de prefixo, C primeiro in
crementa a varivel (resultando em 2), e, depois, exibe o valor j incrementado.

8 6 Co m p r e e n d e n d o o O p e r a d o r d e d e c r e m e n t o de C
Da mesma forma como muitas vezes voc quer incrementar o valor de uma varivel, muitas vezes voc quer de-
crementar o valor atual 1 de uma varivel, como mostrado aqui:
conta = conta - 1;
Como as operaes de decremento so to comuns, C oferece uma notao abreviada que voc pode usar
para efetuar tais operaes o operador de decremento de C. O comando a seguir usa o operador de decremento
para subtrair 1 do valor de conta:
conta--;
Como foi o caso com o operador de incremento, C fornece um operador de decremento de prefixo e um de
sufixo. Os dois comandos a seguir decrementam a varivel conta por 1:
conta--;
--conta;
O primeiro comando usa o operador de decremento de sufixo de C. O segundo comando usa o operador
de decremento de prefixo. Voc pode compreender a distino entre os dois operadores, pois C trata os operadores
de prefixo e de sufixo de forma diferente. Quando voc usar o operador de sufixo, C primeiro usar o valor da va
rivel, e, depois, efetuar a operao de decremento. Por outro lado, quando voc usa o operador de prefixo, C
primeiro incrementa o valor da varivel e depois usa a varivel. Para compreender melhor a diferena entre os
operadores de decremento de prefixo e de sufixo, considere o seguinte programa, sufpre.c, que usa ambos os ope
radores.
#include <stdio.h>

void main(void)
{
in t v a lo r = 1;
In tro d u o l in g u a g e m C 41

printf("Usando sufixo %d\n, valor--);


printf("Valor aps o decremento %d\n", valor);
valor = 1;
printf("Usando prefixo %d\n, --valor);
printf("Valor aps o decremento %d\n", valor);
>
Quando voc compilar e executar o programa sufpre.c, sua tela exibir o seguinte:
Usando sufixo 1
Valor aps o decremento 0
Usando prefixo 0
Valor aps o decremento 0
C: \>
Como voc v, ao usar o operador de decremento de sufixo, C primeiro usa o valor da varivel (exibindo
o valor 1) e depois decrementa o valor da varivel (produzindo o valor 1). Quando voc usar o operador de de
cremento de prefixo, C primeiro decrementa a varivel (resultando em 0) e depois exibe o valor j decrementado.

C o m p r e e n d e n d o u m a O p e r a o O U B it a B it 87
medida que a complexidade de seus programas for aumentando voc ver que pode aumentar o desempenho
do programa ou reduzir as necessidades de memria de um programa usando as operaes bit a b it As operaes
bit a b it manipulam os valores um ou mais bits ao mesmo tempo. Quando voc precisar manipular um valor um
nico bit, pode utilizar o operador O U bit a bit da linguagem C (I). O operador O U bit a bit examina cada bit
dentro de dois valores e gera um terceiro valor como resultado. Por exemplo, assuma que duas variveis conte
nham os Valores 3 e 4, cujos bits so, respectivamente, 00000011 e 00000100. O operador O U bit a bit retorna
o valor 7, como mostrado aqui:
3 00000011
4 00000100

7- 00000111
No valor 3, os bits 0 e 1 tm um valor 1 e todos os outros bits tm um valor 0. No valor 4, o bit 2 tem
um valor 1, e todos os outros bits tm o valor 0. O resultado de uma operao O U ter um valor 1 dentro de
cada bit correspondente que tenha um valor 1 em um dos valores originais. Neste caso, o resultado tem um valor
1 nos bits 0, 1 e 2. O programa a seguir, oujbit.c, ilustra como voc usa o operador O U bit a bit da. linguagem
C:
ttinclude <stdio.h>

void main(void)
{
printf("0 I0 %d\n", 0 I 0);
printf("0 I1 %d\n", 0 I 1);
printf("1 I1 %d\n'\ 1 I 1);
printf("1 I2 %d\n", 1 | 2);
printf("128 I 127 %d\n", 128 I 127);
}
Quando voc compilar e executar o programa ou_bit.c; sua tela exibir o seguinte:
0 I0 0
0 I1 1
1 I1 1
1 I2 3
128 I 127 255
C:\>
42 P rog ram and o em C/C++ A B b l ia

88 Co m p r e e n d e n d o uma O p e r a o E B it a B it
Como visto na Dica 87, voc pode descobrir que possvel aumentar o desempenho do seu programa ou reduzir
os requisitos de memria dele usando as operaes bit a bit. As operaes bit a bit manipulam valores um ou mais
bits ao mesmo tempo. Quando precisar manipular dados um ou mais bits ao mesmo tempo, voc pode utilizar
0 operador E b it a b it da linguagem C (&). O operador E b it a b it examina cada bit dentro de dois valores e
gera um terceiro valor como resultado. Por exemplo, assuma que duas variveis contenham os valores 5 e 7, cujos
bits so, respectivamente, 00000101 e 0 0 0 0 0 1 1 1 .0 operador E b it a b it retorna o valor 5, como mostrado aqui:
5 00000101
7 00000111'

5 00000101
Se um bit dentro de ambos os termos tiver um valor 1, o operador E b it a b it ligar o bit correspondente
dentro do resultado. Se um bit dentro de um dos dois termos contm um valor 0, o operador E b it a b it deixar
em 0 o bit correspondente dentro do resultado. Neste caso, os bits 0 e 2 contm valores 1 em ambos os termos,
de modo que o resultado tem valores 1 nos bits 0 e 2, e valores 0 nos bits restantes. O programa a seguir, e_bit.c,
ilustra o uso do operador E b it a b it da linguagem C:
#include <stdio.h>

void main(void)
{
printf("0 & 0 %d\n", 0 & 0);
printf ("0 &1 %d\n", 0 & 1);
printf("1 &1 %d\n", 1 & 1);
printf(1 &2 %d\n", 1 & 2);
printf("15 & 127 %d\n", 15 & 127);
>
Quando voc compilar e executar o programa e_bit.c, sua tela exibir o seguinte:
0 & 0 0
0 & 1 0
1 & 1 1
1 & 2 0
15 & 127 15
C:\>

89 C om preend endo uma O p e ra o OU E x c lu s iv o B rr a B it


Como voc j aprendeu, as operaes bit a bit manipulam um ou mais bits ao mesmo tempo. Quando voc es
tiver manipulando os bits de um valor, em algumas situaes precisar utilizar o operador OU exclusivo (A), que
examina os bits em dois valores e liga os bits do resultado com base na tabela verdade mostrada na Tabela 89.
Tabela 89 Resultados de uma operao OU exclusivo bit a bit.
X Y Resultado
0 0 0
0 1 1
] 0 1
1 1 0

Suponha que duas variveis contenham os valores 5 e 7, cujos bits so, respectivamente, 00000101 e
00000111. O operador O U exclusivo bit a bit retorna o valor 2, como mostrado aqui:
5 00000101
7 00000111

2 00000010
I ntroduo lin g u a g em C 43

O programa a seguir, ou_exciu.c, ilustra o uso do operador O U exclusivo bit a bit da linguagem C:
#include <stdio.h>

void main(void)
{
printf("0 A0 %d\n", 0 A 0);
printf(0 A1 %d\n", 0 A 1);
printf("1 A1 %\n", 1 A 1);
printf ( 1 A2 %d\n", 1 A 2);
printf("15 A 127 %d\n'\ 15 A 127);
>
Quando voc compilar e executar o programa ou_exclu.c, sua tela exibir o seguinte:
0 A0 0
0 A1 1
1 A1 0
1 A2 3
15 A 127 112
C:\>

Co m p r e e n d e n d o a O p e r a o I n v e r s o B it a B it 90
Como j vimos, as operaes bit a bit manipulam um ou mais bits ao mesmo tempo. Quando voc precisar ma
nipular bits, talvez seja necessrio utilizar o operador inverso bit a bit da linguagem C (-). O operador inverso bit
a bit examina cada bit dentro de um valor e produz um segundo valor como resultado. A operao inverso bit
a bit torna cada bit que contm 1 no valor original em 0 no valor resultante, e torna cada bit que contm 0 no
original em 1 no valor resultante. Como um exemplo, assuma que uma varivel caractere sem sinal contenha o
valor 15. Portanto, a operao inverso bit a bit retornaria 240, como mostrado aqui:
15 00001111
240 11110000
Como voc pode ver, cada bit que estava ligado no valor original fica desligado no resultado, e cada bit
que estava desligado no original deixado ligado no resultado. O programa a seguir, invjbit.c, ilustra o uso do
operador inverso bit a bit da linguagem C:
#include <stdio.h>

void main(void)
{
int valor = OxFF;

printf(O inverso de %X %X\n", valor, -valor);


}
Quando voc compilar e executar o programa invjbit.c, sua tela exibir o seguinte:
O inverso de FF FF00
C:\>

A p l ic a n d o uma Opera o ao Valo r de uma V a r i v e l 91


medida que voc efetuar operaes aritmticas dentro de seus programas, ver que freqentemente atribui a
uma varivel o resultado de uma expresso que inclui o valor atual da varivel. Por exemplo, considere os seguin-
tes comandos:
total = total + 100;
conta = conta - 5;
metade = metade / 2;
44 PROGRAMANDO EM C/C++ -- A BBLIA

Para os casos em que um operador de atribuio atualiza uma varivel com o resultado de uma operao
com o valor atual da varivel, C fornece uma tcnica de abreviao para expressar a operao. Em resumo, voc
coloca o operador antes do operador de atribuio. Quando voc usa a tcnica de atribuio abreviada, os co
mandos a seguir sero equivalentes aos trs comandos que acabam de ser mostrados:
total += 100;
conta -= 5;
metade /= 2;
Quando voc usar esta tcnica abreviada, os comandos a seguir so equivalentes:
varivel += 10; varivel = varivel + 10;
varivel <<= 2; varivel = varivel 2;
varivel &= OxFF; varivel = varivel & OxFF;
varivel *= 1.05; varivel = varivel * 1.05;

92 C o m p r e e n d e n d o o O p e r a d o r C o n d ic io n a l d e C
Como voc aprender, o comando if-else de C examina uma condio e efetua um conjunto de operaes se a
condio for verdadeira e outro conjunto se a condio for falsa. De um modo similar, C fornece um operador
condicional que examina uma condio, e, com base no resultado, verdadeiro ou falso, retorna um dentre dois
valores. O formato do operador condicional como segue:
(condio) ? resultadoverdadeiro: resultadofalso
Para compreender melhor o operador condicional, considere a seguinte condio, que testa se a nota em
um teste maior ou igual a 60. Se o valor for maior ou igual a 60, o comando atribuir varivel um resultado um
A, de aprovado. Se o valor for menor que 60, o comando atribuir varivel um resultado R, de reprovado:
resultado = (nota >= 60) ? 'A': 'R';
O comando similar ao seguinte comando if-else:
if (nota >= 60)
resultado = 'A';
else
resultado = 'R';
O seguinte comando p rin tfe xibe a string Aprovado ou Reprovado com base no teste da nota:
printf("Nota %d Resultado %s\n, nota, (nota >= 60) ? "Aprovado":
"Reprovado");
Quando voc usar o operador condicional de C para atribuir o resultado de uma condio a uma varivel,
poder reduzir o nmero de comandos if-else que usa dentro de seus programas.

93 C o m p r e e n d e n d o o O p e r a d o r s iz e o f d e C
Quando seus programas declaram uma varivel, o compilador C aloca memria para armazenar o valor da va
rivel. Ao escrever programas que efetuem operaes de entrada/sada ou aloquem memria para as listas din
micas, ver que conveniente saber a quantidade de memria que seu programa alocou para uma varivel
especfica. O operador sizeofde C retorna o nmero de bytes que uma varivel ou tipo requer. O programa a
seguir, sizeofc, ilustra o uso do operador sizeof:
#include <stdio.h>
void main(void)
{
printf("As variveis do tipo int usam %d bytes\n", sizeof(int));
printf("As variveis do tipo float usam %d bytes\n", sizeof(float));
printf("As variveis do tipo double usam %d bytes\n", sizeof(double));
printf("As variveis do tipo unsigned usam %d bytes\n", sizeof(unsigned));
printf("As variveis do tipo long usam %d bytes\n", sizeof(long));
}
In t r o d u o l in g u a g e m C 45

Dependendo do seu computador e do hardware do sistema, a sada produzida pelo programa sizeofpoder
ser diferente. Quando voc usar o Turbo C++ Lite, o programa exibir o seguinte:
As variveis do tipo int usam 2 bytes
As variveis do tipo float usam 4 bytes
As variveis do tipo double usam 8 bytes
As variveis do tipo unsigned usam 2 bytes
As variveis do tipo long usam 4 bytes
C:\>

Ef e t u a n d o um Deslocam ento B it a B it 94
Quando voc trabalhar com valores no nvel de bit, algumas operaes comuns que voc efetuar so deslocamen
tos de bits, ou para a direita (para longe do bit mais significativo) ou para a esquerda (em direo ao bit mais sig
nificativo). Para ajudar seus programas a efetuar os deslocamentos bit a bit, C oferece dois operadores
deslocamentos bit a bit: um operador que desloca os bits para a direita ( ) e um que desloca os bits para a es
querda ( ) . A expresso a seguir usa o operador de deslocamento para a esquerda bit a bit para deslocar os valores
na varivel sinaliz duas posies para a esquerda:
sinaliz = sinaliz 2 ;
Suponha que a varivel sinaliz contenha o valor 2, como mostrado aqui:
0000 0010
Quando voc deslocar o valor duas casas para a esquerda, o resultado ser 8, como mostrado aqui:
0000 1000
Quando voc desloca valores para a esquerda, C preenche com zeros as posies dos bits menos significa
tivos. No entanto, quando voc desloca o valor para a direita, o valor que C coloca na posio do bit mais sig
nificativo depende do tipo da varivel. Se a varivel for sem sinal (isto , voc a declarou no programa como um
tipo unsigned), C preencher com 0 o bit mais significativo durante a operao de deslocamento para a direita.
No entanto, se a varivel de um tipo com sinal (em outras palavras, se voc no declarou a varivel como un
signed), C usar o valor 1 se o valor atualmente negativo, ou 0 se o valor for positivo. O programa a seguir,
aesloca.c, ilustra o uso dos operadores deslocamento para a direita e deslocamento para a esquerda bit a bit.
#include <stdio.h>
void main(void)
{
unsigned u_val = 1;
signed int valor = -1;
printf ("%u (sem sinal) deslocado esquerda 2 vezes %u\n",
u_val,
u_val << 2);
printf ("%u (sem sinal) deslocado direita 2 vezes %u\n",
u_val, u_val
2 );
u_val = 65535;
printf ("%u (sem sinal) deslocado esquerda 2 vezes %u\n",
u_val,
u_val << 2);
printf ("%u (sem sinal) deslocado direita 2 vezes %u\n",
u_val, u_val
2 );
printf ("%d (com sinal) deslocado esquerda 2 vezes %d\n",
valor,
valor 2);
printf ("%d (com sinal) deslocado direita 2 vezes %d\n",
valor, valor
2);
}
46 P rog ram and o em C/C++ A B b l ia

95 E f e t u a n d o uma R o ta o B i t a B i t
N a Dica 94 voc viu como usar os operadores de deslocamento para a esquerda e para a direita de C. Quando
voc realiza um operao de deslocamento para a esquerda, C preenche com zero o bit menos significativo. Por
outro lado, quando voc realiza uma operao de deslocamento para a direita, o valor que C coloca na posio
do bit mais significativo depende do tipo do valor e do valor atual. medida que voc for trabalhando no nvel
de bit, algumas vezes poder querer simplesmente rotacionar os bits,em vez de desloc-los para a direita ou para
a esquerda. Quando voc rotaciona os bits para a esquerda, o bit mais significativo do valor torna-se o menos
significativo, enquanto os outros bits movem-se uma posio para a direita. Quando voc rotaciona os valores
para a direita, o valor do bit menos significativo torna-se o mais significativo. Para ajud-lo a rotacionar os bits,
muitos compiladores C fornecem as funes _rotl e _rotr, que rotacionam os bits que compem um valor sem
sinal para a esquerda ou para a direita, como mostrado aqui:
#include <stdlib.h>

unsigned _rotl(unsigned valor, int conta);


unsigned _rotr(unsigned valor, int conta);
, A varivel conta especifica o nmero de vezes que voc quer rotacionar o valor. O programa a seguir, ro-
tacao.c, ilustra o uso das funes _rotl e _rotr:
finclude <stdio.h>
#include <stdlib.h>

void main(void)
<
unsigned valor = 1;

printf("%u rotacionado direita uma vez %u\n, valor, _rotr(valor, 1));


valor = 5;
printf("%u rotacionado direita duas vezes %u\n", valor, _rotr(valor, 2));
valor = 65534;
printf("%u rotacionado esquerda duas vezes %u\n", valor, _rotl(valor, 2));
>
Q uando voc compilar e executar o programa rotacao.c, sua tela exibir o seguinte:
1 rotacionado direita uma vez 32768
5 rotacionado direita duas vezes 16385
65535 rotacionado esquerda duas vezes 65531
C:\>
Nota: Muitos compiladores C tambm oferecem asfunes _lrotl e _lrotr, que rotacionam valores inteiros unsigned
long para a esquerda ou para a direita.

96 C o m p re e n d e n d o o s O p e r a d o r e s C o n d ic io n a is
Todos os programas mostrados anteriormene neste livro iniciaram sua execuo com a primeira instruo em
main, e executaram cada instruo na ordem seqencial. medida que seus programas se tornarem mais com
plexos, algumas vezes o programa precisar executar um conjunto de instrues se uma condio for verdadeira
e, possivelmente, outras instrues se a condio for falsa. Por exemplo, seu programa poderia ter diferentes ins
trues para cada dia da semana. Quando um programa realiza (ou no realiza)instrues com base em uma
condio especfica, o programa est realizando processamento condicionai Para realizarprocessamento condicio
nal, o programa avaliar uma condio que gera um resultado verdadeiro ou falso. Por exemplo, a condio Hoje
Segunda-Feira verdadeira ou falsa. Para ajudar seus programas a realizar processamento condicional, C fornece
os comandos if, if-else e switch. Vrias dicas a seguir discutem esses comandos em detalhes.
I ntroduo l in g u a g em C 47

C o m p re e n d e n d o o P r o c e s s a m e n t o it e r a t iv o 97
Todos os programas apresentados aqui anteriormente executaram suas instrues somente uma vez. Em alguns
casos, um programa pode ou no ter executado um conjunto de instrues com base no resultado de uma con
dio testada. medida que seus programas se tornarem mais complexos, algumas vezes um programa precisa
repetir o mesmo conjunto de instrues um nmero especfico de vezes ou at que o programa atenda a uma
condio especfica. Por exemplo, se voc estiver escrevendo um programa que calcula as classificaes dos alu
nos, o programa precisa executar os mesmos passos para cada aluno na classe. Similarmente, se um programa exi
bir o contedo de um arquivo, ele ler e exibir cada linha do arquivo at encontrar o marcador de fim de
arquivo. Quando os programas repetem um ou mais comandos at que uma condio seja encontrada, o pro
grama est realizando processamento iterativo. Cada passagem que o programa faz pelos comandos que est repe
tindo uma iterao. Para ajudar seus programas a realizar processamento iterativo, C providencia os comandos for,
while e do while. Vrias dicas apresentadas neste livro discutem os comandos for, while e do while em detalhes.

C o m p re e n d e n d o Como C R e p r e s e n t a v e r d a d e ir o e
F a ls o 98
Vrias dicas apresentadas nesta seo discutiram as construes condicionais e iterativas de C, que executam um
conjunto de instrues se uma condio for verdadeira e, possivelmente, outro conjunto de instrues se a con
dio for falsa. medida que voc trabalhar com as construes condicionais e iterativas, importante compreender
como C representar um valor verdadeiro ou flso. C interpreta qualquer valor que no seja 0 como verdadeiro. Da
mesma forma, o valor 0 representa falso. Portanto, a seguinte condio ser avaliada como verdadeira:

Muitos programadores inexperientes escrevem suas condies como mostrado aqui:


if (expresso 1= 0) // Testa se uma expresso verdadeira
Quando voc quiser testar se uma condio verdadeira, inclua a expresso como mostrado aqui:
if (expresso)
Quando a expresso avaliada para um valor diferente de zero (verdadeira), C executa o comando que se
gue imediatamente a condio. Quando a expresso avaliada para zero (falsa), C no executa o comando que
segue imediatamente a condio. Os operadores que trabalham com verdadeiro e falso so operadores Booleanos.
O resultado de uma expresso Booleana sempre um valor verdadeiro ou falso.

T e s ta n d o um a C o n d i o com i f 99
medida que seus programas tornarem-se mais complexos, eles freqentemente executaro um conjunto de co
mandos quando a condio for verdadeira, e outro conjunto de comandos quando a condio for falsa. Quando
seu programa precisar executar um processamento condicional, voc usar o comando i f da. linguagem C. O for
mato do comando i f como segue:
if (condio)
comando;
A condio que o comando z/avalia, precisa aparecer dentro de parnteses e ser verdadeira ou falsa. Quan
do a condio for verdadeira, C executar o comando que aparece imediatamente aps a condio. Quando a
condio for falsa, seu programa no executar o comando que segue a condio. Como um exemplo, o coman
do i f a seguir testa se a varivel idade maior ou igual a 21. Se a condio for verdadeira, o programa no executar
o comando printfe continuar sua execuo no primeiro comando aps printf (o comando de atribuio da altura):
if (idade >= 21)
printf("A varivel idade igual ou maior a 21\n");
altura = 182;
48 P rogram and o em C/C++ A B b l ia

100 Co m p r e e n d e n d o os Co m a n d o s S i m ples e

Co m p o s t o s
Quando seu programa executar o processamento condicional, algumas vezes ele executar um ou mais comandos
quando uma condio for verdadeira, e, possivelmente, vrios outros comandos se a condio for falsa. Da mes
ma forma, quando seu programa executar processamento iterativo, algumas vezes seu programa repetir um co
mando; enquanto, outras vezes, o programa poder repetir vrios comandos. Quando voc executar
processamento condicional e. iterativo, C classificar os comandos como simples ou compostos. Um comando sim
ples um comando nico, tal como a atribuio de uma varivel ou uma chamada a printf. O comando z/a seguir
chama um comando simples (printf) quando a condio for verdadeira:
if (condio)
printf("A condio verdadeira\n");
Um comando composto, por outro lado, consiste de um ou mais comandos contidos dentro de abre e fecha
chaves. O comando z/a seguir ilustra um comando composto:
if (condio)
{
idade = 21;
altura = 182;
peso = 80;
>
Quando seu programa precisar executar mltiplos comandos com base em uma condio, ou quando precisar
repetir vrios comandos, voc usar um comando composto e colocar os comandos dentro de abre e fecha chaves.

101 Te s t a n d o a Ig u a l d a d e
medida que seus programas se tornarem mais complexos, eles compararo o valor de uma varivel com con
dies conhecidas e determinaro quais comandos executar em seguida. Para tomar tais decises, seus programas
usaro os comandos ifoxx switch. Como voc aprendeu na Dica 99, o formato do comando if como segue:
if (condio)
comando;
A maioria dos comandos i f testar se o valor de uma varivel igual a um valor especfico. Por exemplo,
o comando a seguir testa se a varivel idade contm o valor 21:
if (idade == 21)
comando;
C usa o sinal de igual duplo (==) nos testes de igualdade. Quando voc escrever testes de igualdade, use
o sinal de igual duplo (==) e no o sinal de igual (=) que C usa para uma atribuio. Como veremos na Dica
112, se voc usar o operador de atribuio (=) em vez do sinal de igual duplo, C considerar sua condio como
uma sintaxe correta. Infelizmente, quando o comando for executado, C no testar se a varivel igual ao valor
especificado. Em vez disso, C atribuir o valor especificado varivel.
Nota: Dependendo do nvel de advertncia, seu compilador talvez exiba uma mensagem de aviso sobre a atribuio
dentro da condio esperada.
Assim como algumas vezes seus programas precisam testar se um valor igual a outro, C usa o smbolo
!= para testar a diferena. O comando a seguir testa se a varivel idade no igual a 21:
if (idade != 21)
comando;
O programa a seguir, ig_dif.c, usa os testes de C para igualdade (==) e diferena (!=):
#include <stdio.h>

void main(void)
I ntroduo lin g u a g em C 49

{
int idade = 21;
int altura = 182;
if (idade == 21)
printf("A idade do usurio 21\n");
if (idade != 21)
printf("A idade do usurio no 21\n");
if (altura == 182)
printf("A altura do usurio 182\n");
if (altura != 182)
printf("A altura do usurio no 182\n");
}
Quando voc compilar e executar o programa ig_dif.c, sua tela exibir o seguinte:
A idade do usurio 21
A altura do usurio 182
C:\> f
Para compreender como usar os operadores de igualdade e de diferena, experimente o programa ig_dif.c
alterando os valores das variveis idade e altura.

E f e t u a n d o T e s t e s R e l a c io n a is 102
medida que seus programas ficarem mais complexos, algumas vezes voc precisar testar se um valor maior
que outro, menor que outro, maior ou igual a outro ou menor ou igual a outro valor. Para ajud-lo a realizar
esses testes, C fornece um conjunto de operadores relacionais. A Tabela 102 lista os operadores relacionais de C.
Tabela 12 Operadores relacionais de C.
Operador Funo
> Operador maior que
< Operador menor que
>= Operador maior ou igual
<= Operador menor ou igual

O comando ifa. seguir usa o operador maior ou igual de C (>=) para testar se a varivel inteira idade su
perior a 20:
if (idade >= 21)
printf ("A idade superior a 20);

Ex e c u t a n d o uma O p e r a o L g ic a e para Testa r


D u a s C o n d i e s 103
Na Dica 99 voc aprendeu como usar o comando i f da. linguagem C para testar condies dentro de seu pro
grama. medida que seus programas tornarem-se mais complexos, eles eventualmente testaro mltiplas con
dies. Por exemplo, voc pode querer que um comando i f teste se o usurio tem ou no um cachorro, e, em
caso afirmativo, se esse cachorro um dlmata. Nos casos em que voc quer testar se duas condies so verda
deiras, use o operador lgico E. A linguagem C representa o operador lgico E com dois sinais de ampersand
(&&), como mostrado no seguinte comando if:
if ((usuario_tem_cachorro) &.& (cachorro == dalmata))
{
// Comandos
>
Ao encontrar um comando i f que usa o operador lgico E (&&), C avalia as condies da esquerda para
a direita. Se voc examinar os parnteses, ver que o comando z/anterior tem a seguinte forma:
50 P rogram and o em C/C+ + A B b l ia

if (condio)
No exemplo a seguir, a condio realmente duas condies conectadas pelo operador lgico E:
(usuario_tem_cachorro) && (cachorro == dalmata)
Para a condio resultante ser avaliada como verdadeira quando seus programas usarem o operador lgico
E, ambas as condies precisam ser avaliadas como verdadeiras. Se uma das condies for falsa, a condio re
sultante ser avaliada como falsa.
Muitas dicas apresentadas neste livro usaro o operador lgico E. Em cada caso, para garantir que cada ex
presso seja avaliada com a precedncia de operador correta, os programas colocaro as condies dentro de pa
rnteses.
Nota: No confunda o operador lgico E (&&) com o operador bit a bit (&). O operador lgico E avalia duas
expresses Booleanas (verdadeira ou falsa) e produz um resultado verdadeiro ou falso. O operador E bit a bit, por
outro lado, manipula bits (ls e Os).

104 E x e c u ta n d o uma O p e ra o L g ic a OU p a r a
T e s t a r D u a s C o n d i e s
Na Dica 99 voc viu como usar o comando /"para testar condies dentro de seus programas. medida que
seus programas se tornarem mais complexos, voc precisar testar mltiplas condies. Por exemplo, voc poder
querer que um comando //"teste se um usurio tem um cachorro ou se ele tem um computador. Nos casos em
que voc quer testar se uma das condies verdadeira (ou se ambas so verdadeiras), pode usarr o operador
lgico OU. C representa a lgica O U com duas barras verticais (II), como mostrado aqui:
if (usuario_tem_cachorro) II (usuario_tem_computador))
{
// Comandos
}
Ao encontrar um comando i f que usa o operador lgico O U (II), C avalia as condies da esquerda para
a direita. Se voc examinar os parnteses, ver que o comando i f anterior est no seguinte formato:
if (condio)
Neste exemplo em particular, a condio realmente duas condies conectadas pelo operador lgico OU,
como mostrado aqui:
(usuario_tem_cachorro) || (usuario_tem_computador))
Para a condio resultante ser avaliada como verdadeira quando voc usar o operador lgico OU, somente
uma das duas condies precisar ser avaliada como verdadeira. Se uma das condies (ou ambas) forem verda
deiras, a condio resultante ser avaliada como verdadeira. Se ambas as condies forem avaliadas como falsas,
o resultado ser falso.
Muitas dicas apresentadas neste livro usam o operador lgico O U (II). Em cada caso, para garantir que toda
expresso ser avaliada com a precedncia correta de operador, os programas colocaro as condies dentro de
parnteses.
Nota: No confunda o operador lgico O U (II) da linguagem C com o operador O U bit a bit (\). O operador lgico
O U avalia duas expresses Booleanas e produz um resultado verdadeiro ou falso. O operador O U bit a bit, por outro
lado, manipula bits (ls e Os).

105 E x e c u ta n d o uma O p e ra o L g ic a NO (NOT)


Quando seus programas usam o comando i f para realizar processamento condicional, o comando i f avalia uma
expresso que produz um resultado verdadeiro ou falso. Dependendo do processamento do seu programa, algu
mas vezes voc somente ir querer que o programa execute um conjunto de comandos quando a condicional
for avaliada como falsa. Por exemplo, assuma que voc queira que um programa teste se o usurio tem um ca
chorro. Se o usurio no tem um cachorro, o programa dever exibir uma mensagem dizendo ao usurio para
I ntroduo lin g u a g em C 51

comprar um dlmata. Se o usurio tiver um cachorro, o programa no dever fazer nada. Quando voc quiser
que seu programa execute um ou mais comandos quando uma condio for falsa, dever usar o operador lgico
NO da linguagem C, que representado usando-se o sinal de exclamao (!). Considere o seguinte comando if:
if (! usuario_tem_cachorro)
printf ("Compre um dlmata\n");
As condies que usam o operador lgico N O essencialmente dizem que, quando uma certa condio no for
verdadeira (em outras palavras, quando a condio for avaliada como falsa), voc dever executar o comando if(on
comandos compostos). Vrias dicas apresentadas neste livro usam o operador lgico NAO dentro de condies.

At r ib u in d o o R esu lta d o d e uma C o n d i o 106


Vrias dicas nesta seo apresentaram diferentes condies que so avaliadas como verdadeiras ou falsas dentro
de um if, while, for ou outro comando. Alm de permitir que voc use condies dentro de estruturas de controle
iterativo e condicional, C tambm lhe permite atribuir o resultado de uma condio a uma varivel. Por exem
plo, assuma que seu programa use o resultado da mesma condio mais de uma vez, como mostrado aqui:

if ((strlen(nome) < 100) && (hoje == SEGUNDA))


{
// comandos
>
else if (strlen(nome) < 100) && (hoje == TERCA))
{
II comandos
>
else if (strlen(nome) >= 100)
{
// comandos
}
Como voc pode ver, o programa usa a condio (strlen(nome) < 100) trs vezes. Cada vez que a condio
aparece, o programa chama a funo strlen. Nos comandos anteriores, o programa poderia (dependendo do valor
de hoje), chamar strlen trs vezes. Os comandos a seguir atribuiro o resultado da condio (verdadeiro ou falso)
varivel nome_ok, e, depois, repetidamente usaro a varivel (e no a condio). Usar a varivel em vez da con
dio, como mostrado aqui, melhora o desempenho do programa:
nome_ok = (strlen(nome) < 100);
if (nome_ok && (hoje == SEGUNDA))
{
// comandos
>
else if (nome_ok && (hoje == TERCA))
{
// comandos
}
else if (! nome_ok)
{
// comandos
>

D e c l a r a n d o V a r i v e is D e n t r o de C o m a n d o s Co m p o s t o s 107
Na Dica 100 voc aprendeu sobre a diferena entre comandos simples e compostos. Como visto, um comando
composto um ou mais comandos agrupados dentro de abre e fecha chaves. O lao while a seguir (que l linhas
de um arquivo e exibe as linhas em letras maisculas) ilustra um comando composto:
while (fgets(linha, sizeof(linha), pa))
{
52 P rogram and o em C/C++ A B b l ia

strupr(linha);
fputs(linha, stdout);
)
medida que seus programas vo ficando mais complexos, algumas vezes o processamento que eles exe
cutam dentro de um comando composto requerer o uso de uma ou mais variveis cujos valores voc usa somen
te dentro do lao (como pode ser o caso com as variveis contadoras). Quando voc usa variveis contadoras, por
exemplo, normalmente declara essas variveis contadoras no incio do seu programa, imediatamente aps o co
mando main. No entanto, se voc usar uma varivel dentro de um comando composto, poder declarar a varivel
no incio do comando, como mostrado aqui:
if (condio)
{
int contador;
float total;
// Outros comandos
}
Neste caso, o programa declara duas variveis no incio do comando composto. Dentro do comando com
posto, voc pode usar essas duas variveis exatamente como se as definisse no incio do seu programa. No en
tanto, voc no pode referenciar essas variveis fora do abre e fecha chaves do comando composto. Uma
vantagem de declarar variveis dentro do comando composto que outro programador quando for ler o cdigo
de seu programa compreender melhor como e quando usar uma varivel. Vrias dicas apresentadas posterior
mente neste livro enfocam o escopo de uma varivel, ou as localizaes dentro do seu programa no qual o pro
grama conhece uma varivel. Como regra, voc deve limitar o conhecimento de uma varivel de um programa
a somente aquelas localizaes que usam a varivel em outras palavras, voc deve limitar o escopo da varivel.
Declarar variveis no incio de um comando composto, como descrito nesta dica, limita o escopo da varivel ao
abre e fecha chaves do comando composto.
Nota: Se voc declarar variveis dentro de um comando composto que tem o mesmo nome que as variveis que voc
definiu fora do comando, o compilador C usar as variveis recm-declaradas dentro do comando composto, e as va
riveis originais fora do comando.

108 Usan d o Rec u o s para Melh o ra r a L e g ib il id a d e


medida que voc cria seus programas, um dos melhores modos de melhorar a legibilidade do programa usar
os recuos (ou endentao). Toda vez que seu programa usar uma chave (tal como no incio de um comando
composto), voc dever considerar a endentao do seu cdigo em dois ou mais espaos. Por exemplo, considere
o seguinte programa, recuos, c:
#include <stdio.h>

void main(void)
{
int idade =10;
int usuario_tem_cachorro = 0 ; II 0 falso

if (idade == 10)
{
printf("Os ces so animais importantes\n");
if (! usuario_tem_cachorro)
printf("Compre um dlmata\n");
>
printf("Happy um dlmata\n");
>
Examinando a endentao, voc pode rapidamente entender quais comandos esto relacionados (por
exemplo, os comandos compostos). A endentao no importante para o compilador. Para o compilador, o
programa a seguir, sem_rec.c, idntico ao exemplo anterior:
I ntroduo lin g u a g em C 53

#include <stdio.h>

void main(void)
{
int idade = 10;
int usuario_tem_cachorro = 0 ; // 0 falso
if (idade == 10)
{
printf("Os ces so animais importantes\n");
if (1 usuario_tem_cachorro)
printf("Compre um dlmata\n");
>
printf("Happy um dlmata\n");
}
Como voc pode ver, a endentao torna o primeiro programa muito mais fcil de compreender, para voc
e para os outros programadores.

Usan d o a V e r if ic a o E s t e n d id a de Ct r l + B r e a k 109
Quando voc criar programas que usam o lao for, while e do para iterao e que rodam no ambiente DOS, al
gumas vezes preciso usar a combinao de teclas Ctrl+Break para finalizar um programa que est preso em um
lao infinito. Por padro, o DOS verifica um Ctrl+Break sempre que escreve na tela, no disco ou na impressora,
ou ao ler um caractere do teclado. Se seu programa no efetua essas operaes dentro do lao que voc quer in
terromper, no possvel usar o comando Ctrl+Break para finalizar o processamento do programa. No entanto,
quando usa o comando BREAK do DOS, voc pode aumentar o nmero de operaes que, ao ser completadas,
instruem o DOS a verificar o pressionamento de Ctrl+Break. Os programadores chamam esse teste adicional de
verificao estendida de Ctrl+Break. O comando BREAK a seguir habilita a verificao estendida de Ctrl+Break:
C:\> BREAK ON <Enter>
Se voc quiser que o DOS habilite automaticamente a verificao estendida de Ctrl+Break assim que o sis
tema iniciar, coloque um comando BREAK=ON no seu arquivo config.sys. Como o DOS est efetuando uma
verificao estendida de Ctrl+Break, o desempenho geral do seu sistema cair ligeiramente. No entanto, como
voc est comeando a programar, ver que sua possibilidade de encerrar um programa usando Ctrl+Break
mais importante que uma ligeira perda no desempenho.

Testan d o Va l o r e s de P onto Flu t u a n t e 1 10


Vrias dicas apresentadas nesta seo usam os comandos i f t while para testar o valor de uma varivel. Por exem
plo, os comandos a seguir testam variveis inteiras:
if (idade == 21)
// comandos

if (altura > 182)


// comandos
No entanto, ao trabalhar com valores em ponto flutuante, voc precisa ter cuidado quando testar o valor de uma
varivel. Por exemplo, o comando a seguir testa uma varivel em ponto flutuante chamada imposto_vendas:
if (imposto_vendas == 0.065)
// comandos
Na Dica 51, voc aprendeu sobre a preciso em ponto flutuante e sobre o fato de o computador precisar
representar valores em ponto flutuante usando um nmero fixo de bits. impossvel para o computador repre
sentar todos os valores exatamente. No caso do comando //anterior, por exemplo, o computador pode representar
o valor 0.065 como 0.0649999. Como resultado, o comando //nunca ser avaliado como verdadeiro. Para evitar
tais erros no seu programa, no teste valores em ponto flutuante exatos. Em vez disso, teste um intervalo aceitvel
de valores, como mostrado aqui:
54 pr o g r a m a n d o em C/C++ A B b l ia

if (fabs(imposto_vendas - 0.065) <= 0.0001)


// comandos
N o exemplo anterior, devido diferena entre o valor na varivel imposto_vendas e 0.065 ser menor ou
igual a 0.0001, o programa considerar os valores iguais.

111 L ao de R e p e t i o I n f in it o
J vimos que, os comandos for, while e do while lhe permitem repetir um ou mais comandos at que eles encon
trem uma dada condio. Dependendo do seu programa, algumas vezes voc querer que o programa repita um
ao infinitamente. Por exemplo, um programa que detecta vazamento radioativo em um reator nuclear deve es
tar permanentemente em execuo. Para manter seus programas em execuo infinita, simplesmente coloque
uma fconstante diferente de zero dentro do lao, como mostrado aqui:
while (1)
Como possvel usar um valor diferente de zero para forar seus programas a ficar em execuo perpetua
mente, voc pode querer definir constantes para melhorar a legibilidade do seu programa. Por exemplo, voc po
deria usar a constante SEMPRE\ como mostrado aqui:
#define SEMPRE 1
while (SEMPRE)
Para criar um lao para o exemplo anterior da central nuclear, voc poderia usar o seguinte:
#define DERRETENDO 0
While (I DERRETENDO)

1 12 Test a n d o uma A t r ib u i o
Como voc aprendeu, C usa um sinal de igual como operador de atribuio e o sinal de igual dobrado para testar
a igualdade, como mostrado aqui:
nota = 100;
if (nota == MAX)
{
// comandos
>
No fragmento de cdigo precedente, o primeiro comando atribui o valor 100 para a varivel nota. Em se
guida, o comando i f testa o valor da varivel. Para ajud-lo a reduzir o nmero de comandos no seu programa,
C lhe permite testar o resultado de uma atribuio. Por exemplo, o comando i f a seguir combina a atribuio
e a condio de teste anterior.
if ((nota = 100) == MAX)
{
// comandos
>
Primeiro, C efetuar a expresso que os parnteses contm, atribuindo o valor 100 varivel nota. Em se
guida, C comparar o valor que voc atribuiu varivel nota constante MAX. Se voc remover os parnteses,
como mostrado aqui, C atribuir um valor diferente e efetuar um teste diferente:
if (nota = 100 == MAX)
Sem os parnteses, C testar se o valor 100 igual constante MAX, e, em caso afirmativo, atribuir o valor 1 (ver
dadeiro) varivel nota. Se o valor 100 no for igual a MAX, o comando atribuir o valor 0 (falso) varivel nota.
I ntroduo lin g u a g em C 55

Mais comumente voc usar o teste de atribuio quando quiser testar o valor que uma funo (tal como
fopen ou getchar) retorna, como mostrado aqui:
if ((pa = fopen("CONFIG.SYS", "r")) == NULL)
<
II comandos
>

if ((letra = getcharO) == 'A')


{
// comandos
}

C u id a d o com o s Co m a n d o s i f -i f -e l s e 1 13
Quando voc usa comandos if-else, um erro de lgica pode causar problemas se voc no controlar qual else cor
responde a qual i f Por exemplo, considere o seguinte fragmento de cdigo:
teste_nota = 100;
nivel_atual = 'B';
if (teste_nota >= 90)
if (nivel_atual == 'A')
printf("Outro A para um aluno A\n");
else
printf("Voc deveria ter se esforado mais\n");
O primeiro comando //testa se a nota de um aluno no exame foi maior ou igual a 90. Em caso afirmativo
um segundo comando i f testa se o aluno j tem um nvel A , e, em caso afirmativo, imprime uma mensagem.
Com base na endentao, voc esperaria que o comando else exibisse sua mensagem se a nota de teste fosse menor
que 90. Infelizmente, no assim que o fragmento de cdigo processa as condies. Quando voc coloca um co
mando else dentro de seu programa, C associa o else com o primeiro comando //sem else. Embora a nota do alu
no no exame seja 100, o fragmento de cdigo anterior imprimir a mensagem dizendo que o aluno deveria ter
se esforado mais. Em outras palavras, o fragmento executa os comandos mostrados aqui:
if (teste_nota >= 90)
if (nivel_atual == 'A')
printf ("Outro A para vim aluno A\n");
else
printf("Voc deveria ter se esforado mais\n");
Para evitar que C associe o comando else com o //errado, coloque o comando //dentro de chaves, forman
do um comando composto, como mostrado aqui:
if (teste_nota >= 90)
{
if (nivel_atual == 'A')
printf("Outro A para um aluno A\n");
>
else
printf("Voc deveria ter se esforado mais\n");

Ex ecu tan d o Com andos um nm ero E s p e c fic o de V e z e s 1 1 4


Uma operao que seus programas executaro comumente repetir um conjunto de comandos um nmero es
pecfico de vezes. Por exemplo, voc poderia querer calcular as notas de exame de 30 alunos, determinar as altas
e baixas de 100 aes negociadas na Bolsa de Valores, ou soar trs vezes o alto-falante interno do seu compu
tador. Para ajudar seus programas a repetir um ou mais comandos um nmero especfico de vezes, C fornece o
comando for, basta implementar o comando fo r como mostrado aqui:
56 P rogram and o em C/C++ A B b l ia

for (valor_inicial; condio_final; valor_incremento)


comando;
Quando seu programa repetir comandos um nmero especfico de vezes, voc normalmente usar uma va
rivel, chamada varivel de controle; que contar o nmero de vezes que voc executar os comandos. O comando
for contm quatro sees. A seo valor_inicial atribui varivel de controle o valor inicial da varivel, que , na
maioria das vezes, 0 ou 1. A seo condio_Jinal normalmente testa o valor da varivel de controle para deter
minar se o programa executou os comandos um nmero desejado de vezes. A seo valor_incremento normal
mente adiciona o valor 1 para a varivel de controle toda vez que os comandos so executados. Finalmente, a
quarta seo do comando for o comando ou comandos que voc quer repetir. Como seu programa repetida
mente executa o comando ou comandos que voc especificou (volta para o incio do comando), o comando for
normalmente chamado de lao for. Considere o seguinte comando for, que exibir os nmeros 1 a 10 na sua tela:
for (contador = 1; contador <= 10; contador++)
printf("%d\n", contador);
No exemplo anterior, contador a varivel controladora do lao. Primeiro, o lao for atribui o valor 1 va
rivel. Segundo, o lao for testa imediatamente se o valor de contador menor ou igual a 10 (a condio final do
lao). Se contador for menor ou igual a 10, o lao for imediatamente executar o prximo comando, que, neste
exemplo, p r in tf Aps o programa completar o comando printf, o lao for executa a expresso que voc espe
cificou na seo valor_incremento do lao. Neste caso, o lao for incrementa o valor de contador em 1. Em se
guida, o lao for imediatamente executa o teste valor_finaL Se o valor de contador for menor ou igual a 10, o lao
continuar. Portanto, na primeira vez em que o lao repetido, o comando p r in tf exibir, o valor 1. Na segunda
iterao, o valor de contador 2, depois 3 e assim por diante. Aps p rin tf exibir o valor 10, a seo valor_incre-
mento incrementar o valor de contador, tornando-o 11. Quando o lao for efetua o teste valorJinal, voc ver
que o valor de contador no mais menor ou igual a 10, de modo que o lao terminar e seu programa conti
nuar o processamento imediatamente aps o lao for.
Para compreender melhor o processamento do lao for, considere o seguinte programa, testafor.c.
#include <stdio.h>

void main(void)
{
int contador;

for (contador = 1; contador <= 5; contador++)


printf("%d ", contador);
printf("Nnlniciando o segundo lao\n");
for (contador = 1; contador <= 10; contador++)
printf("%d ", contador);
printf("Nnlniciando o terceiro lao\n");
for (contador = 100; contador <= 5; contador++)
printf("%d ", contador);
>
Quando voc compilar e executar o programa testafor.c, sua tela exibir o seguinte:
1 2 3 4 5
Iniciando o segundo lao
1 2 3 4 5 6 7 8 9 10
Iniciando o terceiro lao
C:\>
Como voc pode ver, o primeiro lao for exibe os nmeros de 1 at 5. O segundo lao for exibe os valores
de 1 at 10. O terceiro lao for no exibe nenhum valor. Se voc examinar com ateno, ver que o programa
inicialmente atribui varivel de controle do lao o valor 100. Quando o comando for testa o valor, o lao for
atende imediatamente condio final, de modo que o lao no executado.
I ntroduo lin g u a g em C 57

Todos os exemplos apresentados nesta dica usaram comandos simples no lao for. Se voc precisar repetir
mais de um comando, coloque os comandos dentro de abre e fecha chaves, formando um comando composto,
como mostrado aqui:
for (i = 1; i <= 10; i++)
{
// comandos
}

Pa r t es do Co m a n d o fo r S o O p c i o n a is 1 15
Na Dica 114 voc aprendeu que o comando for permite que seu programa repita um ou mais comandos um n
mero especfico de vezes. Como foi visto, o lao for usa trs sees dentro do comando for: uma inicializao,
um teste e um incremento (a quarta seo do lao contm os comandos que o lao for repete):
for (Inicializao; teste; incremento)
Dependendo do seu programa, algumas vezes voc pode no querer usar cada uma das sees do comando
for. Por exemplo, se voc j atribuiu o valor 0 varivel conta, pode pular a seo de inicializao do lao. Depois,
para exibir os nmeros de 0 at 999, seu lao conter o seguinte:
for (; conta < 1000; conta++)
printf(" %d", conta);
No entanto, se voc omitir uma das sees do lao for, precisa incluir o ponto-e-vrgula correspondente.
Por exemplo, o lao for a seguir omite as sees de inicializao e de incremento.
for (/ conta < 1000; )
printf( %d", conta++);
Da mesma forma, o comando for a seguir ficar em execuo perpetuamente:
for (;;)
// comando
Embora o comando for fornea estas sees opcionais, seu programa pode tornar-se mais difcil de ler se
voc as omitir. Como regra, caso no precisar usar todas as trs partes do comando for, voc dever usar uma
construo de lao diferente, tal como o comando while.

Dec rem en ta n d o os Va lo res em um Co m a n d o fo r 1 16


Como voc aprendeu, um comando fo r\\\t permite repetir um ou mais comandos um nmero especfico de ve
zes. As Dicas 114 e 115 apresentaram vrios comandos for. Em cada caso, o lao for contou de 1 a 5, de 1 a 10,
e assim por diante. O comando for tambm ihe permite decrementar a varivel de controle. Por exemplo, o se
guinte comando for conta regressivamente os nmeros 10, 9, 8, e assim por diante, at 1:
for (contador = 10; contador >= 1; contador--)
printf("%d ", contador");
Como voc pode ver, o comando for precedente aproximadamente o oposto dos comandos que voc viu
nas dicas anteriores. O lao inicializa a varivel de controle contador com um valor alto, e, depois, decrementa
contador por um cada vez que o lao repetido.
O programa a seguir,for_regr.c, usa o comando for para contar regressivamente, primeiro de 5 a 1, e, de
pois, de 10 a 1:
ttinclude <stdio.h>

void main(void)
{
int contador;
58 P ro gram ando em C/C++ A B b l ia

for (contador = 5; contador >= 1; contador--)


printf("% ", contador);
printf("\nIniciando o segundo lao\n");
for (contador = 10; contador >= 1; contador--)
printf("%d ", contador);
printf("Xnlniciando o terceiro lao\n);
for (contador = 0; contador >= 1; contador--)
printf("%d ", contador);
)

Quando voc compilar e executar o programa for_regr.c, sua tela exibir a seguinte sada:

5 4 3 2 1
Iniciando o segundo lao
10 9 8 7 6 5 4 3 2 1
Iniciando o terceiro lao
C:\>
Como voc pode ver, o terceiro lao no exibe nenhum valor. Neste exemplo, o comando for inicializa con
tador com um valor que menor que o valor final de 1. Portanto, o lao termina imediatamente.

1 17 Co n t r o l a n d o o In c r e m e n t o d o Lao fo r
Como voc aprendeu, o lao for permite que seus programas repitam um ou mais comandos um nmero espe
cfico de vezes. Nas dicas anteriores, cada lao for incrementou ou decrementou a varivel de controle por 1. C,
no entanto, isso lhe permite incrementar a varivel por qualquer valor que voc quiser. Por exemplo, o seguinte
comando for iocrementa a varivel de controle contador por 10 a cada iterao do lao:

for (contador = 0; contador <= 100; contador += 10)


printf ("%d\n", contador);
De um modo similar, os laos for anteriores inicializaram a varivel de controle em 1 ou em 0. Assim como
voc pode definir a quantidade de incremento ou de decremento para qualquer tamanho que voc queira, C, no
vamente, permite-lhe inicializar a varivel para qualquer valor que voc quiser. O programa a seguir, for_difc,
usa diferentes valores de incremento e de decremento:
#include <stdio.h>

void main(void)
{
int contador;

for (contador = -100; contador <= 100; contador += 5)


printf("%d ", contador);
printf("\nIniciando o segundo lao\n");
for (contador = 100; contador >= -100; contador -= 25)
printf("%d ", contador);
}

1 18 U s a n d o La o s f o r c o m V a l o r e s c h a r e f l o a t
Como voc aprendeu, o comando for permite que seus programas repitam um conjunto de comandos um n
mero especfico de vezes. Cada um dos comandos for apresentados nas dicas anteriores usaram somente valores
do tipo int. No entanto, voc pode usar caracteres e valores em ponto flutuante nos seus laos for. Por exemplo,
o seguinte lao for exibe as letras do alfabeto:
I ntroduo lin g u a g em c 59

for (letra = 'A'; letra <= 'Z'; letra++)


printf("%c", letra);
Da mesma forma, o lao a seguir incrementa um valor de ponto flutuante em 0.5:
for (porcent = 0.0; porcent <= 100.0; porcent = 0.5);
printf("%f\n", porcent);

O programa a seguir, for_mais.c, ilustra o uso de letras e valores em ponto flutuante em um lao for:
#include <stdio.h>

void main(void)
{
char letra;
float porcent;
for (letra = 'A'; letra <= 'Z'; letra++)
putchar(letra);
for (letra = 'z'; letra >= 'a'; letra--)
putchar(letra);
putchar('\n');
for (porcent = 0.0; porcent < 1.0; porcent += 0.1)
printf("%3.lf\n", porcent);
}

Co m p r e e n d e n d o um Lao Nu l l 1 19
Voc j sabe que o lao fo r lhe permite repetir um ou mais comandos at que a varivel de controle do lao aten
da a uma certa condio. No passado, quando os programadores queriam que seus programas fizessem uma bre
ve pausa, talvez para exibir alguma mensagem, eles colocavam um lao N U LO ou no faz nada em seus
programas. Por exemplo, o seguinte lao fo r no faz nada 100 vezes:

for (contador = 1; contador <= 100; contador++)


; // No faz nada

Quando voc colocar um lao N U LO em seus programas, C efetuar a inicializao do lao, e, depois, re
petidamente, testar e incrementar a varivel de controle at que a varivel de controle atenda condio final.
O teste repetido do lao consome tempo do processador, o que faz o programa retardar. Se o programa precisar
de um retardo maior, voc poder aumentar a condio final:

for (contador = 1; contador <= 10000; contador++)


; // No faz nada

Usar as tcnicas de retardo, tais como o lao NULO, poder causar problemas. Primeiro, se o programa
estiver rodando em um computador 286, 386 ou 486, a durao do retardo diferir simplesmente devido di
ferena de velocidade entre os diferentes microprocessadores. Segundo, se o programa estiver rodando em um
ambiente de multitarefa, tal como o Windows, OS/2, ou Unix, os laos no fazem nada consomem tempo que
o processador poderia estar gastando fazendo trabalho importante em outro programa. Se seus programas usam
esse retardo, veja as funes descritas na seo Data e Hora, mais frente.

Co m p r e e n d e n d o o L a o I n f in it o 120
Como voc aprendeu, o lao fo r lhe permite repetir um ou mais comandos um nmero especfico de vezes.
Quando o lao fo r atender condio final, seu programa continuar sua execuo no comando que segue ime
diatamente. Quando voc usa laos for, precisa garantir que o lao atender a sua condio final. Caso contrrio,
o lao continuar sua execuo para sempre. Esses laos interminveis so chamados laos infinitos. Na maioria dos
casos, os laos infinitos ocorrem como resultado de erro na programao. Por exemplo, considere o seguinte lao:
60 P ro g ram a nd o em C/C++ A B b l ia

for (i = 0; i < 100; 1++)


{
printf("%d ", i);
resultado = valor * --i; // causa do erro
>
Como voc pode ver, o segundo comando do lao decrementa o valor da varivel de controle i. Especi
ficamente, o lao decrementa o valor para -1, e, depois, incrementa o valor para 0. Como resultado, o valor nun
ca atinge 100, de modo que o lao no termina. Quando seu programa entra em um lao infinito, talvez voc
possa pressionar C t r l + C para finalizar o programa. O programa a seguir, infinito.c, ilustra um lao infinito:
#include <stdio.h>

void main(void)
{
int i;
int result = 0 ;
int valor = 1;

for (i = 0; i < 100; i++)


{
printf("%d , i);
result = valor * --i;
}
printf("Resultado %d\n", result);
}
Quando voc compilar e executar o programa infinito.c, ele repetidamente exibir o valor 0. Para finalizar
o programa, pressione C t r l + C .

121 Usa n d o o Op e r a d o r V r g u l a de C Den t r o de um

L ao fo r
Como voc aprendeu, quando declara variveis, C lhe permite declarar mltiplas variveis do mesmo tipo sepa
rando os nomes das variveis com vrgulas:
int idade, altura, peso;
Alm disso, C lhe permite separar as inicializaes de variveis com vrgulas, como mostrado aqui:
int idade = 25, altura = 182, peso = 80;
De um modo similar, C lhe permite inicializar e incrementar mltiplas variveis em um lao for separando
as operaes com vrgulas. Considere o lao a seguir, que trabalha com as variveis i e j:
for (i = 0, j = 100; i <= 100; i++, j++)
printf(i = %d j = %d\n", i, j);
Muito provavelmente voc trabalhar com mltiplas variveis em um lao for (tambm conhecido como
laos for embutidos) em seus programas que trabalham com matrizes. Voc aprender mais sobre as matrizes na
seo Matrizes e Estruturas, posteriormente. O programa a seguir, for_2var. C, ilustra o uso do operador vrgula
em um lao for:
#include <stdio.h>

void main(void)
{
in t i, j;
I n troduo lin g u a g em c 61

for (i = 0, j = 100 ; i <= 100 ; i++, j++)


printf(i = %d j = %d\n", i, j);
>

E v it e M o d if ic a r o Va lo r de uma V a r i v e l de

Co n t r o l e em um Lao fo r 122
J vimos que o comando forWxc permite repetir um ou mais comandos um nmero especfico de vezes. Para efe
tuar esse processamento, o lao for usa uma varivel de controle, que funciona como um contador. Como regra,
voc no deve alterar o valor de uma varivel de controle no comando do lao for. O nico local em que o valor
da varivel de controle deve ser alterado nas sees de inicializao e de incremento do lao for. Ao alterar o
valor da varivel de controle nos comandos do programa, voc corre o grande risco de criar um lao infinito, tor
nando seus programas mais difceis de ser compreendidos. No entanto, algumas vezes, voc pode querer que o
lao termine ou pule a iterao atual quando a varivel de controle for igual a um certo valor. Em tais casos, use
o comando break ou continue, discutidos em detalhes em outras dicas nesta seo.

R e p e t in d o um ou M a is Co m a n d o s U s a n d o um Lao w h il e 123
Como voc aprendeu, o comando for lhe permite repetir um ou mais comandos um nmero especfico de vezes.
N o entanto, em muitos casos, seus programas precisam repetir um ou mais comandos at que o lao atenda a
uma condio especfica que no envolva necessariamente uma contagem. Por exemplo, se voc escrever um pro
grama que exiba o contedo de um arquivo na tela, ir querer que o programa exiba cada linha do arquivo. Na
maioria dos casos, voc no saber de antemo quantas linhas o arquivo contm. Portanto, no pode usar um
laoyrpara exibir, por exemplo, 100 linhas. O arquivo poderia conter mais ou menos linhas. Em vez disso, voc
querer que o programa leia e exiba linhas at chegar ao final do arquivo. Para fazer isso, seus programas podem
usar o lao while. Voc formatar o lao while como segue:
while (condio)
comando;
Ao encontrar um lao while no seu programa, C testa a condio especificada. Se a condio for verdadeira,
C efetuar os comandos contidos no lao. Se o comando for falso, C continuar a execuo do seu programa ao
primeiro comando que segue. Um lao while pode repetir um nico comando ou um comando composto de
limitado por abre e fecha chaves, como mostrado aqui:
while (condio)
{
// Comandos
>
O programa a seguir, espera, c, usa o lao while para repetir um lao at que voc pressione a tecla S ou N
em resposta a uma pergunta:
#include <stdio.h>
ttinclude <ctype.h>
ttinclude <conio.h>

void main(void)
{
char letra; // Letra digitada pelo usurio

printf("Quer continuar? (S/N); ");

letra = getch(); // L a letra


letra = toupper(letra); // Converte a letra para maiscula

while ((letra 1= 'S') && (letra != 'N'))


{
62 P rogram and o em C/C++ A B b l ia

putch(7); II Soa o alto-falante


letra = getch(); // L a letra
letra = toupper(letra); // Converte a letra para maiscula
>

printf("\nSua resposta foi %c\n", letra);


}
Primeiro, o programa exibir a mensagem que o primeiro comando p rin tf 'contm. Segundo, o programa
usa getch para ler a tecla pressionada. Para simplificar o teste do lao, o programa converte a letra para maiscula,
de modo que o lao somente precisa testar as letras S ou N. Terceiro, o lao while testar a letra que o usurio
digitou. Se a letra for um S ou N, a condio falhar, e os comandos do lao no sero executados. Se a letra
pressionada no for S ou N, a condio do lao ser verdadeira e seus comandos sero executados. No lao, o
comando soar o alto-falante interno do computador para indicar um caractere invlido. Em seguida, o progra
ma ler a nova tecla e converter a letra para maiscula. O lao depois repetir seu teste para determinar se o
usurio digitou um S ou um N. Se no, os comandos do lao sero repetidos. Caso contrrio, a execuo do pro
grama continuar no primeiro comando que segue o lao.

124 C o m p re e n d e n d o a s P a r t e s de um L a o w h ile
Um lao while lhe permite executar um ou mais comandos at que o programa atenda condio do lao. Na
Dica 114, voc aprendeu que um lao for realmente contm quatro sees: uma inicializao, um teste, um co
mando de execuo e um incremento. Por outro lado, um lao while contm somente um teste e os comandos
que voc quer repetir, como mostrado aqui:
while (condio)
comando;
Voc viu na Dica 120 que um lao infinito um lao cuja condio final nunca atendida, e, portanto
o lao continua a execuo para sempre. Ao escrever programas que usam laos while, voc pode reduzir a pos
sibilidade de um lao infinito garantindo que seus laos while efetuem os mesmos passos executados por um lao
for. Para ajud-lo a lembrar os quatro passos, memorize a sigla ITEM, como ilustrado na Tabela 124:
Tabela 124 Os Componentes da Sigla ITEM.
Ao Descrio
Inicializa Inicializa a varivel de controle do lao
Testa Testa a varivel de controle ou a condio do lao
Executa Executa os comandos desejados no lao
Modifica Modifica o valor da varivel de controle ou efetua um operao que afetar a condio que
voc est testando

Ao contrrio do lao for, que lhe permite explicitamente inicializar e incrementar uma varivel de controle,
um lao while requer que voc inclua comandos no programa que efetuem esses passos para voc. O programa
a seguir, item.c, ilustra como seu programa efetua esses quatros passos. Ao contrrio dos programas anteriores que
voc escreveu, item.c, usa um lao while para exibir os nmeros de 1 a 100:
#include <stdio.h>

void main(void)
{
int contador = 1; // Inicializa a varivel de controle

while (contador <= 100) // Testa a varivel de controle


(
printf("%d , contador); // Executa os comandos
contador++; // Modifica a varivel de controle
}
>
I ntroduo lin g u a g em C 63

Se voc escrever um programa que usa o lao while e o programa ficar preso em um lao infinito, uma das
operaes ITEM no seu programa no est correta.

R e p e t in d o um ou M a is C o m a n d o s U s a n d o d o 125
Voc j sabe que o comando while lhe permite repetir um ou mais comandos enquanto uma condio especfica
atendida. Da mesma forma, o comando fo r lhe permite repetir um ou mais comandos um nmero especfico
de vezes. Alm disso, C fornece o comando do, que lhe permite executar um ou mais comandos pelo menos uma
vez, e, depois, se necessrio, repetir comandos. O formato do comando do como segue:
do
comandos ;
while (condio);
O comando do ideal para situaes que requerem que voc execute um ou mais comandos pelo menos
uma vez. Por exemplo, considere o seguinte fragmento de cdigo:
printf("Quer continuar? (S/N): ");

letra = getch(); // Recebe o caractere


letra = toupper(letra); // Converte a letra para maiscula

while ((letra 1= 'S') && (letra 1= 'N'))


{
putch(7); // Emite vim aviso sonoro
letra = getch(); // Recebe o caractere
letra = toupper(letra); // Converte a letra paramaiscula
>
Como voc pode ver, o cdigo pede que o usurio digite uma tecla, l a tecla e converte-a para maisculas.
Dependendo da tecla que o usurio pressionou, o fragmento iniciar um lao while, que efetua os mesmos co
mandos. Observe que voc pode simplificar os comandos usando o comando do, como mostrado no seguinte
fragmento de cdigo:
printf("Quer continuar? (S/N): );
do
{
letra = getch(); // L a letra
letra = toupper(letra); // Converte a letra para maiscula
if ((letra != 'S') && (letra != 'N'))
putch(7); // Soa o alarme - caractere invlido
}
while ((letra != 'S') && (letra != 'N'));
Ao encontrar um comando do no seu programa, C executa os comandos entre as palavras do e while. C
ento testa a condio que while especifica para determinar se os comandos devem ou no ser repetidos. Portan
to, os comandos que um lao do especifica sempre so executados pelo menos uma vez. Os programas normal
mente usam o lao do para exibir e processar opes do menu. O programa a seguir, do_menu.c, usa o comando
para exibir e processar opes de menu at que o usurio selecione a opo Sair:
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>

void main(void)
{
char letra;

do
{
64 P rogram and o em C/C++ A B b l ia

printf("A Exibir a listagem do diretrio\n");


printf("B Modificar a hora do sistema\n);
printf("C Modificar a data do sistema\n");
printf("S Sair\n");
printf("Escolha: ");

letra = getch();
letra = toupper{letra);

if (letra == 'A')
system("DIR");
else if (letra == 'B')
system("TIME");
else if (letra == 'C')
system("DATE");
>
while (letra 1= 'S');
>

126 C o m p re e n d e n d o o C om ando c o n tin u e de C


Como voc aprendeu, os comandos for, while e do permitem que seus programas repitam um ou mais comandos
at que uma condio especfica seja avaliada como verdadeira ou falsa. Dependendo do propsito do seu pro
grama, algumas vezes, com base em uma segunda condio especfica, voc querer que seu programa pule a ite
rao atual. O comando continue de C lhe permite fazer exatamente isso. Se C encontrar um comando continue
em um lao for, C automaticamente executar a poro de incremento do lao, e, depois, efetuar o teste da con
dio final. Se C encontrar um comando continue em um lao while ou do, ento C imediatamente efetuar o
teste da condio final. Para compreender melhor o comando continue, considere o seguinte programa, par_im-
par.c, que usa continue em um lao for e um lao while para exibir os nmeros pares e mpares entre 1 e 100:
tinclude <stdio.h>

void main(void)
{
int contador;

printf("\nValores pares\n");
for (contador = 1 ; contador <= 100; contador*+)
{
if (contador % 2) // mpar
continue;
printf("%d , contador);
>
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador+ + ;
if (1 (contador % 2)) // Par
continue;
printf("%d ", contador);
>
>

O programa usa o operador mdulo (resto) para determinar se um valor par ou mpar. Se voc dividir um valor
por 2 e obtiver um resto de 1, o valor mpar. Da mesma forma, se obtiver um resto de 0, o valor par.
I ntroduo lin g ua g em C 65

importante observar que voc normalmente pode eliminar a necessidade de usar um comando continue
reprojetando o uso dos comandos i f t else em seu programa. Por exemplo, o programa a seguir sem_cont.c, tam
bm exibe valores pares e mpares sem usar continue:
#inclue <stdio.h>

void main(void)
{
int contador;

printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (1(contador % 2 ) ) II Par
printf(%d , contador);
>
printf("\nValores imparesXn");
contador = 0;
while (contador <= 100)
{
contador++;
if (contador % 2) II mpar
printf("%d , contador);
}
>
Antes de usar um comando continue no seu programa, examine seu cdigo atentamente para determinar
se voc pode escrever os mesmos comandos sem usar continue. N a maioria dos casos, voc ver que o cdigo sem
continue mais fcil de compreender.

F in a l iz a n d o um La o U s a n d o o Co m a n d o break de C 127
J vimos que os comandos for, while e do permitem que seus programas repitam um ou mais comandos at que
uma condio especfica seja avaliada como verdadeira ou como falsa. Dependendo do propsito do seu progra
ma, algumas vezes, com base em uma segunda condio especfica, voc querer que o lao termine automati
camente, com seu programa continuando seu processamento no comando que segue o lao. O comando break
lhe permite fazer exatamente isso. Quando C encontra um break em um lao, a execuo do lao terminar de
imediato. O prximo comando que o programa executa o comando que segue imediatamente o lao. No caso
de um comando for, C no efetuar a seo de incremento do lao em vez disso, o lao termina imediata
mente. O programa a seguir, usabreak.c, ilustra o uso do comando break. O programa percorre os nmeros de
I a 100, e, depois, de 100 a I. Toda vez que o iao chega ao valor 50, o comando break termina imediatamente
o lao:

#include <stdio.h>

void main(void)
{
int contador;

for (contador = 1; contador <= 100; contador++)


{
if (contador == 50)
break;
printf(%d ", contador);
>
printf("XnPrximo lao\n");
for (contador = 100; contador >= 1; contador--)
{
66 P rogram and o em C/C++ A B b l ia

if (contador == 50)
break;
printf("%d ", contador);
}
}
Como foi o caso com o comando continue, voc normalmente reescrever as condies do lao e de if-else
para eliminar a necessidade do comando break em laos. Na maioria dos casos, quando voc reescrever os co
mandos do seu programa para eliminar break, seu programa ficar muito mais fcil para o leitor compreender.
Como regra, limite o uso de break dentro do comando switch.

128 D e s v io s com o Co m a n d o goto


Se voc j programou em BASIC, FORTRAN ou em linguagem Assembly, pode estar habituado a implementar
as operaes if-elsee os laos usando o comando GOTO. Como a maioria das linguagens de programao, C for
nece um comando goto, que permite que a execuo do seu programa desvie-se para uma localizao especfica,
chamada rtulo. O formato do comando goto como segue:
goto rotulo;
rotulo:
O programa C a seguir, goto_100.c, usa o comando goto para exibir os nmeros de 1 a 100:
#include <stdio.h>

void main(void)
{
int conta = 1;

rotulo:
printf("%d ", conta++);

if (conta <= 100)


goto rotulo;
}
Quando voc usa o comando goto, o rtulo precisa residir na funo atual. Em outras palavras, voc no
pode usar goto para desviar-se de main para um rtulo que aparece em outra funo, ou vice-versa.
Como no passado os programadores abusaram do comando goto, voc dever restringir o uso de goto sem
pre que for possvel, e, em lugar dele, usar construes tais como i f if-else e while. Na maioria dos casos, voc
poder usar essas trs construes para reescrever um fragmento de cdigo que usa goto, e, desse modo, produzir
um cdigo mais legvel.

129 T e s t a n d o M l t i p l a s C o n d i e s
Como foi visto, os comandos if-else de C lhe permitem testar mltiplas condies. Por exemplo, considere o se
guinte teste da varivel letra:
letra = getchO;
letra = toupper(letra);

if (letra == 'A')
system("DIR");
else if (letra == 'B')
system("TIME");
else if (letra == 'C')
system("DATE");
I ntroduo lin g u a g em C 67

Nos casos em que voc est comparando a mesma varivel com mltiplos valores, C fornece um comando
switch, com o seguinte formato:
switch (expresso) {
case Constante_l: comando;
case Constante_2: comando;
case Constante_3: comando;

>;
Em vez de usar os comandos if-else anterior, voc poderia usar switch como segue:
switch (letra) {
case 'A': system("DIR");
break;
case 'B': system("TIME");
break;
case 'C': system("DATE");
break;
>;
Ao encontrar um comando switch no seu programa, C avalia a expresso que segue para produzir um re
sultado. C ento compara o resultado com cada um dos valores constantes, especificados por voc, que seguem
a palavra-chave case. Se C encontrar uma coincidncia, ele executar os comandos correspondentes. O comando
break separar comandos correspondentes de um case para o outro. Voc normalmente colocar um comando
break aps o ltimo comando que corresponde a uma opo. Na Dica 130, voc aprender os detalhes que go
vernam o uso do comando break em switch. O programa a seguir, swt_menu.c, usa o comando switch para pro
cessar a seleo de menu de um usurio:
#include <stdio.h>
#include <conio.h>
ttinclude <ctype.h>
#include <stdlib.h>

void main(void)
{
char letra;

do {
printf("A Exibir listagem do diretrioSn");
printf("B Alterar a hora do sistema\n");
printf("C Alterar a data do sistema\n");
printf("S Sair\n");
printf("Escolha: );
letra = getch();
letra = toupper(letra);
switch (letra) {
case 'A': system("DIR");
break;
case 'B': system("TIME");
break;
case 'C': system("DATE");
break;
>;
>
while (letra != 'S');
>
68 P rogramando em C/C++ A B b l ia

1 3 0 C o m p r e e n d e n d o b r e a k D e n t r o d e s w it c h
N a Dica 129 voc aprendeu que o comando switch de C lhe permite a execuo de processamento condicional.
Assim, voc especifica um ou mais correspondentes possveis usando o comando switch. Para cada case, voc
especifica os comandos correspondentes. Ao final dos comandos, voc normalmente coloca um comando break
para separar um comando case de outro. Se voc omitir o comando break, C continuar a executar todos os co
mandos seguintes, independente do case ao qual o comando pertence. Por exemplo, considere o seguinte coman
do switch:
switch (letra) {
case 'A': system("DIR);
case 'B': system("TIME");
case 'C': system("DATE");
>;
Se a varivel letra contiver a letra A, C executar o comando DIR. No entanto, como no existe um co
mando break em seguida, o programa tambm executar os comandos TIM E e DATE. Se a varivel letra con
tivesse a letra B, o programa executaria os comandos TIM E e DATE. Para evitar as execuo dos comandos dos
outros cases, use o comando break, como mostrado aqui:
switch (letra) {
case 'A': system("DIR");
break;
case 'B': system("TIME");
break;
case ' C ' i system("DATE");
break;
};
Algumas vezes voc poder querer que seus programas testem em seqncia vrias opes. Por exemplo,
o programa a seguir, vogais, c, usa um comando switch para contar o nmero de vogais no alfabeto:
#include <stdio.h>

void main(void)
{
char letra;
int conta_vogal = 0;

for (letra = 'A'; letra <= 'Z'; letra++)


switch (letra) {
case 'A':
case 'E':
case 'I's
case 'O':
case 'O': conta_vogal++;
>;
printf("O nmero de vogais %d\n", conta_vogal);
}
Neste caso, se a varivel letra contm o A, E, I ou O, a ocorrncia que executa o comando corresponde
letra U, que incrementa a varivel conta_vogaL Como o comando switch no contm nenhum outro case aps
a letra U, o programa no inclui o comando break.

3 1 U s a n d o o Ca s e d e f a u l t d o C o m a n d o s w t c h
Vimos que o comando switch de C lhe permite efetuar um processamento condicional. Ao usar o comando
switch, voc especifica um ou mais cases que deseja que C confira, como mostrado aqui:
Ma c r o s e co nsta ntes 69

switch (letra) {
case 'A': system("DIR");
break;
case 'B': system("TIME");
break;
case 'C ': system("DATE");
break;
};
medida que voc usar o comando switch, possvel ver que algumas vezes voc desejar que C efetue co
mandos especficos quando os outros cases no conferirem. Para fazer isso, inclua um case default com o comando
switch, como mostrado aqui:
switch (expresso)
case constante_l: comando;
case constante_2: comando;
case constante_3: comando;

default: comando;
>;
Se C no executar nenhumas das opes case que precedem o default, C executar os comandos de default.
O programa a seguir, cons_vog.c, usa o case default para controlar o nmero de letras consoantes no alfabeto:
#include <stdio.h>

void main(void)
{
char letra;
int conta_vogal = 0;
int conta_consoante = 0;

for (letra = 'A'; letra <= 'Z'; letra++)


switch (letra) {
case 'A':
case 'E':
case 'I':
case 'O':
case '': conta_vogal++;
break;
default: conta_consoante++;
>;
printf("O nmero de vogais %d\n", conta_vogal);
printf("O nmero de vogais %d\n", conta_consoante);
>

D e fin in d o C o n s ta n te s no Seu P ro g ra m a 132


Como regra, voc pode aumentar a legibilidade e portabilidade do seu programa substituindo as referncias por
nmeros, tal como 512, com um nome de constante mais representativo. Uma constante um nome que o com
pilador C associa com um valor que no muda. Para criar uma constante, voc usa a diretiva tdefine. Por exem
plo, a diretiva a seguir cria uma constante chamada TAM^LINHA, e atribui constante o valor 128:

ttdefine TAM_LINHA 128

Quando o pr-processador C encontra o nome de constante TAM _LIN no seu programa, ele substitui o
nome da constante pelo valor da constante. Por exemplo, considere a seguinte declarao de string de caracteres:
char linha[128];
70 P rogram and o em C/C++ A B b l ia

char texto[128];

char linha_atual[TAM_LINHA];
char entrada_usuario[TAM_LINHA];
As duas primeiras declaraes criam strings de caracteres que contm strings de 128 caracteres. As duas de
claraes a seguir criam strings de caracteres que esto baseadas em uma constante chamada TAM_LINHA.
Quando outros programadores lerem o cdigo do seu programa,uma das primeiras perguntas que eles podero
fazer por que voc usou 128 na declarao da sua string. No entanto, no caso da segunda declarao, o pro
gramador sabe que voc declarou todas as suas strings em termos de um TAM_LINHA predefinido. Dentro do
seu programa, voc poderia incluir laos similares ao seguinte:
for (i=0; i < 128; i++)
// comandos

for (i=0; i < TAM_LINHA; i++)


// comandos
O segundo lao for torna seu programa mais legvel e fcil de alterar. Por exemplo, assuma que seu pro
grama use o valor 128 para referenciar o tamanho da string. Se, mais tarde, voc quiser alterar o tamanho para
256 caracteres, precisar alterar cada ocorrncia do valor 128 no seu programa um processo demorado. Por
outro lado, se voc estiver usando uma constante tal como TAM _LINHA, somente precisar alterar a diretiva
#define um processo de uma nica etapa , como mostrado aqui:
#defIne TAM_LINHA 256

133 Co m p r e e n d e n d o a Ex p a n s o de Ma c r o s e de

Co n s t a n t e s
Na Dica 132, voc aprendeu que seus programas podem usar a diretiva para definir uma constante den
tro de seu programa. O programa a seguir, ex_macro.c, por exemplo, usa trs constantes:
#define LINHA 128
#define TITULO "Bblia do Programador C/C++, do Jamsa!"
#define SECAO "Macros"

ttinclude <stdio.h>
void main(void)
{
char livro[LINHA];
char nome_biblio[LINHA];

printf("O ttulo deste livro %s\n", TITULO);


printf(SECAO);
}
Quando voc compila um programa C, um pr-processador roda primeiro. O propsito do pr-processa-
dor incluir quaisquer arquivos de cabealho especificados e expandir as macros e as constantes. Antes que o
compilador C realmente comece a compilar seu programa, o pr-processador substituir cada nome de constante
pelo valor da constante, como mostrado aqui:
void main(void)

char livro[128];
char nome_biblio[128] ;
printf("0 nome deste livro %s\n", "Bblia do Programador C/C++, do
Jamsa!);
printf("Macros");
}
Ma c r o s e co n sta n tes 71

Como o pr-processador trabalha com #define, #include e outros comandos #, esses comandos so normal
mente conhecidos como diretivas do pr-processador.

N om eando a s C o n s ta n te s e a s M a c r o s 134
Como voc aprendeu, uma constante um nome que o compilador associa com um valor que no muda. Na
Dica 144, voc aprender sobre as macros de C. Ao usar constantes e macros dentro de seus programas, voc de
ver usar nomes representativos que descrevam exatamente o uso delas. Para ajudar os programadores que lerem
seu cdigo a diferenciar entre constantes e variveis, voc normalmente dever usar letras maisculas para os no
mes de constantes e de macros. As seguintes diretivas #define ilustram vrias definies de macros:
#define VERDADEIRO 1
#define FALSO 0
ttdefine PI 3.1415
#define PROGRAMADOR "Kris Jamsa"
Como voc pode ver, as constantes podem conter valores int, float e at caracteres char*

U s a n d o a C o n s ta n te de P r - p r o c e s s a d o r _F IL E _ 135
Quando voc trabalha em um grande projeto, algumas vezes pode querer que o pr-processador saiba o nome
do arquivo-fonte atual. Por exemplo, voc poderia usar o nome de arquivo dentro de uma diretiva de pr-pro
cessador que inclua uma mensagem para o usurio dizendo que o programa ainda est em desenvolvimento,
como mostrado aqui:
O programa Folha.C ainda est em desenvolvimento e teste.
Esta uma verso Beta.
Para ajudar seus programadores a efetuar esse processamento, o pr-processador C define a constante__FILE_
como igual ao nome do arquivo-fonte atual. O programa a seguir, consfile.c, ilustra o uso da constante__FILE__:
#include <stdio.h>

void main(void)
{
printf("O arquivo % b est em teste Beta\n", __FILE__);
>
Quando voc compilar e executar o programa consfile.c, sua tela exibir o seguinte:
O arquivo consfile.c est sob teste Beta
C:\>
Nota: Embora muitas constantes de pr-processador mudem de um compilador para outro, a constante__FILE
consistente dentro do Turbo C++ Lite, do Visual C++, do Borland C++ 5-02 e do Borland C++ Builder.

U s a n d o a C o n s ta n te de P r - p r o c e s s a d o r ___ LINE__ 136


Ao trabalhar em um projeto grande, algumas vezes voc poder querer que o pr-processador saiba, e potencial
mente use, o nmero da linha atual do arquivo-fonte atual. Por exemplo, se estiver depurando um programa,
voc poderia querer que o compilador exibisse mensagens a partir de vrios pontos dentro do programa, como
mostrado aqui:
Cheguei com sucesso linha 10
Cheguei com sucesso linha 301
Cheguei com sucesso linha 213
O programa a seguir, conslin.c, ilustra o uso da constante de pr-processador__ LIN E :
#include <stdio.h>

void main(void)
72 P rog ram and o em C/C++ A b b l ia

{
p r i n t f ( " C h e g u e i com s u c e s s o l i n h a % d \n " , __ LINE__ ) ;

// O u tro s com andos a q u i

p r i n t f ( " C h e g u e i com s u c e s s o l i n h a % d \n " , __ LINE__ ) ;


}
Q uando voc com pilar e executar o programa, sua tela exibir o seguinte:
C h e g u e i com s u c e s s o l i n h a 5
C h e g u e i com s u c e s s o l i n h a 7

Nota: Embora muitas constantes de pr-processador mudem de um compilador para outro, a constante L IN E
consistente com o Turbo C++ Lite, o Visual C++, o Borland C++ 5.02 e o Borland C++ Builder.

137 A lteran d o a Co n t a g e m de U nha do P r -p r o c e s s a d o r


N a Dica 136 voc aprendeu com o usar a c o n sta n te __ LIN E do pr-processador dentro de seus programas.
Q uando voc usar a co n sta n te __ LIN E . algumas vezes poder querer alterar o nm ero da linha atual do pr-
processador. Por exemplo, assuma que voc esteja u s a n d o __ L IN E para ajudar a depurar seus programas,
como discutido na D ica 136. Se voc restringiu o erro a um conjunto especfico de instrues, pode querer que
o pr-processador exiba os nm eros de linha relativos a um a localizao especfica. Para lhe ajudar a executar esse
processamento, o pr-processador C fornece a diretiva Mine que lhe perm ite alterar o nm ero da linha atual. A
diretiva a seguir, por exemplo, instrui o pr-processador a definir seu nm ero de linha para 100:
# lin e 100

Voc tam bm pode usar a diretiva Mine para alterar o nom e do arquivo de cdigo-fonte que a constante
__ FILE __exibir:
# l i n e 1 "NOMEARQ. C "

O program a a seguir, muda_lin.c, ilustra com o usar a diretiva Mine:


# in c lu d e < s td io .h >

v o id m a in (v o id )
{
p rin tf(
" A r q u iv o %8: C h e g u e i com s u c e s s o l i n h a % d \n " , __ FIL E __ , __ LINE__ ) ;

// O u tro s com andos a q u i

tlin e 1 00 "NOMEARQ.C"

p r i n t f ( " A r q u iv o % s: C h e g u e i com s u c e s s o l i n h a % d \n " ,


__ F IL E __ , __ LINE__ ) ;
>
Q uando voc com pilar e executar o programa muda_lin.c, sua tela exibir o seguinte:
A r q u iv o m u d a _ l i n .C : C h e g u e i com s u c e s s o l i n h a 6
A r q u iv o NOMEARQ.C: C h e g u e i com s u c e s s o l i n h a 102
C :\>

138 G eran d o um E r r o I n c o n d ic io n a l do P r -p r o c e s s a d o r
A medida que seus programas vo se tornando mais complexos e passarem a usar um nm ero grande de arquivos
de cabealho, ser possvel que algumas vezes voc no queira que o program a compile com sucesso caso ele no
tenha definido um a ou mais constantes. Da mesma forma, se voc estiver trabalhando com um grupo de pro
gramadores e quiser que eles saibam de um a modificao que voc tenha feito no programa, poder usar a di
Ma c r o s e c o n sta n tes 73

retiva de pr-processador #error para exibir uma mensagem de erro e finalizar a compilao. Por exemplo, a di
retiva a seguir finaliza a compilao, exibindo uma mensagem para o usurio sobre a atualizao:
#error A rotina string_classif agora usa strings far
Antes que outros programadores possam compilar com sucesso o programa, eles precisam remover a di
retiva #error, tornando-se, portanto, cientes da alterao que voc fez.

Ou t r a s Co n s t a n t e s do P r -p r o c e s s a d o r 139
Vrias dicas nesta seo apresentaram constantes do pr-processador que a maioria dos compiladores suporta. Al
guns compiladores definem muitas outras constantes de pr-processador. O compilador Microsoft Visual C++,
por exemplo, usa mais de 15 outras constantes de pr-processador no discutidas neste livro. Consulte a docu
mentao que acompanha seu compilador para determinar se seus programas podero utilizar outras constantes
de pr-processador. Adicionalmente, consulte na documentao on-line o ttulo Predefined Macros.

R e g is t r a n d o a Da t a e a Hora do P r -p r o c e s s a d o r 140
Ao trabalhar em programas grandes, voc poder querer que seu pr-processador trabalhe com a data e a hora
atuais. Por exemplo, voc pode querer que o programa exiba uma mensagem que informa a data e a hora em
que voc compilou pela ltima vez o programa, como mostrado aqui:
Teste Beta: FOLHA.C: ltima compilao em Jul 8 1998 14:45
Para lhe ajudar a realizar esse processamento, o pr-processador C atribui a data e a hora atuais s cons
tantes __D ATE e __ TIM E . O programa a seguir, datahora.c, ilustra como voc poderia usar as constantes
_DATE_ e _TIME_:
iinclude <stdio.h>

void main(void)
{
printf("Teste Beta: ltima compilao em %s %s\n", _DATE_, __TIME_);
>

Test a n d o a Ad eso ao P a d r o ANSI 141


Embora os compiladores C sejam muito similares, cada um deles oferece capacidades exclusivas. Para lhe ajudar
a escrever programas que depois voc possa migrar facilmente de um sistema para outro, o Instituto Nacional
Americano de Normas (American National Standards Institute (ANSI)) define padres para os operadores, cons
trues, comandos e funes que um compilador deve suportar. Os compiladores que aderem a essas normas so
chamados compiladores A N S I C. A medida que voc cria programas, algumas vezes pode querer determinar se
est ou no usando um compilador ANSI. Para lhe ajudar a fazer isso, os compiladores ANSI C definem a cons
tante __STDC__(de STandarD C). Se o compilador estiver configurado para aderir ao padro ANSI C, ele de
finir a constante. Caso contrrio, ele no definir a constante. O programa a seguir, chc_ansi.c, usa a constante
__ST D C _para determinar se o compilador atual compila para os padres ANSI:
#lnclude <stdio.h>

void main(void)
{
#ifdef __STDC__
printf("Adeso ao ANSI C\n");
ielse
printf("No est no modo ANSI C\n");
#endif
}
Nota: A maioria dos compiladores oferece opes de linha de comando ou pragmas in-line para que voc o instrua
a aderir ao padro ANSI. Voc aprender sobre as opes da linha de comando epragmas posteriormente, neste livro.
74 P rogram and o em C/C++ A B b l ia

142 T e s ta n d o C+ + v e r s u s C
Voc pode usar vrias das dicas apresentadas neste livro tanto na programao em C quanto em C++, enquanto
ourras dicas aplicam-se apenas a C++. medida que voc criar seus prprios programas, algumas vezes desejar
que o pr-processador determine se voc est usando C ou C++ e processe seus comandas apropriadamente. Para
lhe ajudar a realizar esses testes, muitos compiladores C++ definem a constante__cplusplus. Se voc usar um
compilador C padro, a constante estar indefinida. O seguinte programa, chc_cpp.c, usa a constante__cplusplus
para determinar o modo correto do compilador:
#include <stdio.h>

void main(void)
<
#ifdef __cplusplus
printf("Usando C++\n);
#else
printf("Usando C\n");
#endif
}
Se voc examinar os arquivos de cabealho que o compilador fornece, encontrar muitos usos da constante
__cplusplus.
Nota: Muitos compiladores C++ permitem o uso de opes de linha de comando para instru-los a compilar usando
C++, em vez de C padro.

143 A n ulan d o a D e f in i o de uma Ma c r o ou Co n s t a n t e


Vrias dicas apresentadas nesta seo discutiram constantes e macros que o pr-processador define ou que o ar
quivo de cabealho contm. Dependendo do seu programa, voc pode querer que o pr-processador remova a
definio de uma ou mais dessas constantes. Por exemplo, a macro a seguir redefine a macro _toupper, que est
definida no arquivo de cabealho ctype.h:
tdefine _toupper(c) ((((c) >= 'a') && ((c) <= 'z')) ? (c) - 'a' + 'K ': c)
Quando voc compilar este programa, muitos pr-processadores exibiro uma mensagem de advertncia
dizendo que voc redefiniu a macro. Para evitar o aparecimento dessa mensagem de advertncia, use a diretiva
#undefpzia remover a definio atual da macro antes de redefini-la, como mostrado aqui:
#undef _toupper
#define _toupper(c) ((((c) >= 'a') && ((c) <= 'z')) ? (c) - 'a' + 'A': c)

144 Co m p a r a n d o Ma c r o s e Fu n es
Os novos programadores normalmente ficam confusos sobre quando devem usar macros ou funes por causa
das similaridades entre elas. Como voc aprendeu, cada vez que o pr-processador encontra uma referncia de
macro dentro de seu programa, ele substitui a referncia pelos comandos da macro. Portanto, se seu programa
usa uma macro 15 vezes, ele ter 15 cpias diferentes da macro colocada em seu cdigo. Conseqentemente, o
tamanho do programa executvel crescer. Por outro lado, quando o programa usa uma funo, ele somente
contm uma cpia do cdigo, o que reduz o tamanho do programa. Quando o programa usa a funo, ele chama
(desvia-se para) o cdigo da funo. A desvantagem de usar funes, no entanto, que cada chamada de funo
incorre em processamento adicional que torna a chamada da funo ligeiramente mais demorada de executar que
uma macro comparvel. Portanto, se voc quiser desempenho mais alto, use uma macro. Porm, se o tamanho
do programa o que lhe preocupa mais, use uma funo.
Ma c r o s e c o n sta n tes 75

Co m p r e e n d e n d o P r a g m a s do C o m p il a d o r 145
Vrias dicas nesta seo apresentaram diferentes diretivas de pr-processador, tais como #define, #include e #un-
def. Dependendo do seu compilador, seu pr-processador pode suportar vrias diretivas de compilador, chama
das pragmas. O formato de uma pragma como segue:
tpragma diretiva_compilador
Por exemplo, o compilador Turbo C++ Lite oferece as pragmas startup t exit, que lhe permitem especificar
as funes que voc quer que seu programa execute automaticamente quando o programa iniciar ou terminar:
#pragma startup carrega_data
ttpragma exit fecha_todos_ar<iuivos
Observe que a funo que voc nomeia dentro da pragma startup na verdade ser executada antes de main,
de modo que voc no dever usar a pragma startup com muita freqncia. Dependendo do seu compilador, as
pragmas disponveis diferiro. Consulte na documentao que acompanha seu compilador uma descrio com
pleta das pragmas disponveis para seu programa usar.
Nota: Quando voc usa as pragmas startup e exit, a funo que voc nomeia dentro de pragma no pode receber pa
rmetros e no pode retornar nenhum valor; em outras palavras, voc precisa escrever a funo da seguinte maneira:
void function(void)

Apren d en d o so bre os Va lo r es e M a c r o s P r e d e f i n id o s 146


Muitas dicas nesta seo discutiram as macros, as constantes e as vrias diretivas de pr-processador. Um dos mo
dos mais eficientes de aprender como usar macros, constantes e outras diretivas de pr-processador examinar
como o compilador C usa essas opes. O compilador C coloca as macros e as constantes dentro de arquivos de
cabealho que residem no subdiretrio include do compilador. Muitos dos arquivos de cabealho apresentam
modos de usar vrias diretivas de pr-processador. Examinando o contedo de vrios arquivos de cabealho, voc
poder aprender muitos modos de melhorar seus programas utilizando as capacidades do pr-processador.

C r ia n d o S e u s P r p r i o s A r q u iv o s de Ca b e a l h o 147
Como voc sabe, o compilador C fornece diferentes arquivos de cabealho que contm macros, constantes e pro
ttipos de funes relacionados. medida que aumentar o nmero de programas que voc criar, ser possvel
descobrir que muitos dos seus programas usam as mesmas constantes e macros. Em vez de digitar repetidamente
essas macros e constantes em seus programas, voc poder considerar criar seu prprio arquivo de cabealho e
colocar no arquivo as macros e constantes correspondentes. Assumindo que voc crie um arquivo de cabealho
chamado min_defi.h, poder incluir o arquivo no incio de seu programa usando a diretiva Mnclude do pr-pro
cessador, como mostrado aqui:
#include "min_defs.h"
Quando voc incluir suas macros e constantes em um arquivo de cabealho desse modo, poder rapida
mente modificar vrios programas editando o arquivo de cabealho, e, depois, recompilando os programas que
incluem o arquivo.

Usan d o # in c l u d e < n o m e a r q .h > ou # in c l u d e

" n o m e a r q .h " 148


Todos os programas apresentados neste livro incluram o arquivo de cabealho stdio.h, como mostrado aqui:
#include <stdio.h>
Na Dica 147 voc aprendeu como criar e incluir seu prprio arquivo de cabealho, min_defi.h. Voc pode
incluir stdio.h e min_defi.h dentro de seus programas com os seguintes comandos:
76 Programando em C/C++ A Bblia

#include <stdio.h>
#include "inin_defs .h"
Observe nos dois comandos include que os sinais de menor e maior ( o ) delimitam o arquivo de cabealho
stdio.h, enquanto min_defs.c aparece delimitado por aspas. Quando voc delimitar o nome do arquivo de cabe
alho com os sinais de menor e maior, o compilador C procurar o arquivo especificado no seu diretrio de ar
quivos de cabealho. Se o arquivo for encontrado, ser usado pelo pr-processador. Se o compilador no localizar o
arquivo, ele o procurar no diretrio atual ou em um diretrio que voc especificar. Por outro lado, quando voc de
limitar o nome de arquivo de cabealho por aspas, o compilador somente procurar o arquivo no diretrio atual.

149 T e s ta n d o S e um S m b o lo E s t D e fin id o
Vrias dicas nesta seo apresentaram smbolos predefinidos do compilador C. Alm disso, algumas dicas discu
tiram como voc pode definir suas prprias constantes e macros. Dependendo do seu programa, possvel que
algumas vezes voc queira que o pr-processador teste se o programa definiu um smbolo anteriormente e, em
caso afirmativo, processe um determinado conjunto de comandos. Para ajudar seu programa a testar se o pro
grama definiu anteriormente um smbolo, o pr-processador C suporta a diretiva #ifdef. O formato de #ifdef
como segue:
#ide smbolo
// comandos
#endif
Quando o pr-processador encontra a diretiva #ifdef, ele testa se o programa definiu anteriormente o sm
bolo especificado. Em caso afirmativo, ele processa os comandos que seguem a diretiva at encontrar o comando
#endif. s vezes voc quer que o programa processe comandos caso o programa no tenha definido um smbolo.
Em tais casos, pode usar a diretiva #ifndef. Os comandos a seguir usam #ifndef para instruir o pr-processador
a definir a macro _toupper se uma macro similar no estiver definida:
ttifndef _toupper
ttdefine _toupper(c) ((((c) >= 'a') && ((c) <= 'z')) ? (c) - 'a' + 'A': c)
#endif

150 E fe tu a n d o o P ro c e s s a m e n to if- e ls e
Na Dica 149 vimos como usar os comandos #ifdefi #ifndef e #endif para especificar um conjunto de comandos
que voc quer que o processador execute se um programa anteriormente tiver definido (#ifdef) ou no definido
(#ifndef) um smbolo. Algumas vezes voc poder querer levar esse processamento um passo adiante e incluir um
conjunto de comandos que deseja que o processador execute quando a condio testada dentro do comando #ifdef
for verdadeira, e um conjunto diferente se a condio for falsa. Para executar esse processamento, voc poder
usar a diretiva #else, mostrada aqui:
#ifdef smbolo
// Comandos
#else
// Outros comandos
#endi
Por exemplo, ambos os compiladores Microsoft Visual C++ e o Borland C++ 5-02 incluem constantes de
pr-processador excusivas que indicam qual compilador e qual verso voc est usando para compilar o progra
ma. Voc pode usar as constantes exclusivas de cada compilador para responder a diferentes compiladores. Por
exemplo, o fragmento de cdigo a seguir imprimir Microsoft se o compilador for o Visual C++ e Borland se o
compilador for o Borland C++ 5.02:
#ifdef MSCJVER
printf ("Microsoft");
tendif
#ifdef _BORLANDC__
Ma c r o s e c o n sta n tes 77

printf ("Borland");
#endif

E fetu a n d o um Te s t e de C o n d i o de P r -p r o c e s s a d o r
Ma is P o d e r o s o 151
Na dica 149 voc aprendeu como usar os comandos #ifdefe. #ifndef para instruir o pr-processador a testar an
teriormente se um programa definiu ou no um smbolo, e, depois, processar os comandos que seguem com base
no resultado do teste. Em muitos casos, voc poder precisar que o processador teste se vrios smbolos esto de
finidos, no definidos, ou alguma combinao de ambas as coisas. As diretivas a seguir testam primeiro se o sm
bolo M INHA_BIBLIO est definido. Se seu programa definiu anteriormente MINHA_BIBLIO, as diretivas do
pr-processador testam se seu programa tambm definiu anteriormente o smbolo MINHAS_FUNC. Se seu pro
grama ainda no definiu M INHAS_FUNC, o cdigo instrui o pr-processador a incluir o arquivo de cabealho
meu_cdg.h:
#ifdef MINHA_BIBLIO
#ifndef MINHAS_ROTINAS
#include "meu_cdg.h"
#endif
#endif
Embora as diretivas efetuem o processamento desejado, as condicionais embutidas uma dentro de outra o
tornam potencialmente difcil para outro programador entender o que voc deseja. Como uma alternativa, seus
programas podem usar a diretiva # i f com o operador defined para testar se o programa definiu anteriormente o
smbolo, como mostrado aqui:
#if defined (smbolo)
// comandos
#endif
Sua vantagem em usar o comando #if que voc pode combinar teste, ao contrrio do que acontece com
as diretivas #ifaefe. Mfndef. A diretiva a seguir executa o mesmo teste do primeiro exemplo nesta dica:
#if defined(MINHA_BIBLIO) && 1defined(MINHAS_ROTINAS)
tinclude "meu_cdg.h"
#endif
Voc poder usar #ifdefined para criar condies que usam operadores lgicos de C (incluindo &&, II, e !).

R e a l iz a n d o P r o c e s s a m e n t o i f -e l s e e e l s e -i f 152
Como visto na dica anterior, fcil usar a diretiva #//do pr-processador para testar se seu programa definiu ou
no um smbolo. Ao usar a diretiva #ifi voc algumas vezes poder querer que o pr-processador processe um
conjunto de comandos, quando um smbolo estiver definido, e outro conjunto caso o smbolo no esteja defi
nido (pr-processamento condicional). Voc poder realizar pr-processamento condicional usando a diretiva #else:
#if defned(smbolo)
// Comandos
#else
// Comandos
ttendif
Levando o exempo de pr-processamento anterior um passo mais longe, algumas vezes voc poder querer
que o pr-processador teste o status de outros smbolos quando uma condio especificada no passar. As dire
tivas a seguir, por exemplo, instruem o pr-processador a processar um conjunto de comandos se o smbolo M I-
NHA_ BIBLIO estiver definido; outro conjunto se M INHA_BIBLIO no estiver definido e caso
M INH AS_RO TINAS esteja definido; e um terceiro conjunto se nenhum dos smbolos estiver definido:
#if defined (MINHA_BIBLIO)
78 P rog ram and o em C/C+ + A BBLIA

// Comandos
#else if defined (MINHAS_ROTINAS)
// Comandos
#else
// Comandos
#endif
Como voc pode ver, ao usar as diretivas # ife #else, seu controle sobre o pr-processador aumenta signi
ficativamente.
Nota: Alguns compiladores, incluindo o Turbo C++ Lite, suportam a diretiva de pr-processador #elif, que efetua
o mesmo processamento que a construo #else if.

153 D e f in i n d o M a c r o s e Co n s t a n t e s Q u e R e q u e r e m
M l t i p l a s L in h a s
Vrias dicas apresentadas nesta seo definiram constantes e macros. medida que suas constantes e macros vo
se tornando mais complexas, algumas vezes uma definio no caber em uma nica linha. Quando voc precisar
quebrar a definio de uma constante ou de uma macro para a prxima linha, coloque um caractere de barra in
vertida no final da linha, como mostrado aqui:
#define string_caracteres_muito_longa "Esta constante \
string extremamente longa requer duas linhas"

#define _toupper(c) (( ((c ) >= 'a') && ((c) <='z')) \


? (c) - 'a' + 'A': c)

154 C r ia n d o S u a s P r p r i a s M a c r o s
Como voc aprendeu, as macros oferecem um modo de definir constantes que o pr-processador substitui em
todo o seu programa antes que a compilao inicie. Alm disso, as macros lhe permitem criar operaes similares
s funes que trabalham como parmetros. Os parmetros so valores que voc passa para a macro. Por exemplo,
a seguinte macro, SOMA, retorna a soma dos dois valores que voc passa para a macro:
#define SOMA(x, y) ((x) + (y))
O programa a seguir, ex_soma.c, usa a macro SOMA para somar vrios valores:
#include <stdio.h>

ttdefine SOMA(x, y) ((x) + (y))

void main(void)
<
printf("Somando 3 + 5 = %d\n", SOMA(3, 5));
printf("Somando 3.4 + 3.1 = %f\n, SOMA(3.4,3.1));
printf("Somando -100 + 1000 = %d\n", SC>MA(-100, 1000));
}
Dentro da definio da macro SOMA, x e y representam os parmetros da macro. Quando voc passa dois
valores para a macro, tal como SOMA(3, 5) o pr-processador substitui os parmetros dentro da macro, como
mostrado na Figura 154.
No programa ex_soma.c, as substituies do pr-processador resultaro no seguinte cdigo:
printf("Somando 3 + 5 =%d\n", ((3) +(5)));
printf("Somando 3.4 + 3.1= %f\n", ((3.4) + (3.1)));
printf("Somando -100 + 1000 = %d\n", ((-100) + (1000)));
Ma c r o s e c o n sta n tes 79

Figura 154 A substituio d e parm etro para SO M A .

No C o l o q u e P o n t o -e -v r g u l a nas De f in i e s de

Ma c r o s 155
Quando voc examinar a definio de macro da seguinte macro SOMA, observe que a macro no inclui um pon
to-e-vrgula:
#define SOMA(x, y) ((x) + (y))
Se voc incluir um ponto-e-vrgula dentro de sua macro, o pr-processador colocar o ponto-e-vrgula em
cada ocorrncia de macro em todo o seu programa. Por exemplo, assuma que voc tenha colocado um ponto-
e-vrgula no final da definio da macro SOMA, como mostrado aqui:
#define SOMA(x, y) ((x) + (y) );
Quando o pr-processador expandir a macro, ele incluir o ponto-e-vrgula, como mostrado aqui:
printf("Somando 3 + 5 =%d\n", ((3) +(5)););
printf("Somando 3.4 + 3.1= %f\n", ((3.4) + (3.1)););
printf("Somando -100 + 1000 = %d\n", ((-100) + (1000)););
Como o ponto-e-vrgula agora ocorre no meio do comando p rin tf(indicando o final do comando), o com
pilador gerar erros.
Nota: A no ser que voc queira que o pr-processador inclua um ponto-e- vrgula na expanso da macro, no inclua
um ponto-e-vrgula na definio da macro.

C r ia n d o M a c r o s M in e Ma x 156
Na Dica 154 voc criou a macro SOMA, que somou dois valores juntos. As macros seguintes, M I N e MAX, re
tornam o mnimo e o mximo de dois valores:
#define MIN(x,y) (((x) < (y)) ? (x):(y))
#define MAX(x,y) (((x) > (y)) ? (x):(y))
O programa a seguir, min_max.c, ilustra como usar as macros M IN e MAX:
#include <stdio.h>

#define MIN(x,y) (((x) < (y)) ? (x) :(y))


#define MAX(x,y) (((x) > (y)) ? (x):(y))

void main(void)
(
printf("O maior entre 10.0 e 25.0 %f\n", MAX(10.0, 25.0));
printf("O menor entre 3.4 e 3.1 %f\n", MIN(3.4, 3.1));
>
80 P rogram ando em C/C++ A B b l ia

Quando voc executar o programa min_max.c, as substituies do pr-processador resultaro no seguinte


cdigo:
printf("O maior entre 10.0 e 25.0 %f\n", (((10.0) < (25.0)) ? (10.0): (25.0)));
printf("0 menor entre 3.4 e 3.1 %f\n", (((3.4) > (3.1)) ? (3.4): (3.1)));

157 C ria n d o M a c r o s QUADRDO e CUBO


Voc viu que, C lhe permite definir e passar valores para as macros. As duas ltimas macros que voc examinar
nesta seo so QUADRADO e CUBO, que retornam, respectivamente, um valor ao quadrado (x * x) e um valor
ao cubo (x * x * x):
#define QUADRADO(x) ((x) * (x))
#define CUBO(x) ((x) * (x ) * (x))
O programa a seguir, quad_cubo.c, ilustra como usar as macros QUADRADO e CUBO:
#inolude <stdio.h>
ttdefine QUADRADO(x ) ((x) * (x))
#define CUBO(x) ((x) * (x) * (x))

void main(void)
{
printf("O quadrado de 2 %d\n", quadrado (2));
printf("O cubo de 100 %f\n", cubo (100.0));
>
No programa quad_cubo.c, as substituies do pr-processador resultam no seguinte cdigo:
printf("O quadrado de 2 %d\n", ((2) * (2)));
printf("O cubo de 100 %f\n",((100.0) * (100.0) * (100.0)));
Nota: Para evitar o extravasamento, o programa q u a d _ c u b o .c usa o valor em ponto flutuante 100.0 dentro da ma
cro CUBO.

158 C u id a d o com o s Espa o s n a s d e f i n i e s d a s Ma c r o s


Vrias dicas anteriores apresentaram macros que recebem parmetros. Quando voc define macros que recebem
parmetros, precisa tomar cuidado com espao em branco na definio de macro. No coloque um espao entre
o nome da macro e seus parmetros. Por exemplo, considere a seguinte definio de macro, QUADRADO:
#define QUADRADO (x) ((x) * (x))
Quando o pr-processador examina seu programa, os espaos em branco entre o nome da macro fazem o
pr-processador assumir que deve substituir cada ocorrncia do nome QUADRADO com (x) ((x) * (x))t em vez
de substituir com ((x) * (x)). Como resultado, a macro no avalie corretamente, e, na maioria dos casos, o com
pilador gerar mensagens de erro de sintaxe ou advertncias por causa da substituio. Para compreender melhor
o processo de substituio da macro do pr-processador, experimente o programa quad_cubo.c (apresentado na
Dica 157), colocando um espao aps cada nome de macro.

159 Co m p r e e n d e n d o Co m o U s a r os Pa r n t es e s
Em muitas dicas anteriores vimos macros s quais seus programas passaro valores (parmetros). Se voc der uma
olhada nas definies de cada macro, ver que os valores esto envolvidos por parnteses:
#define SOMA(x, y) ((x) + (y))
#define QUADRADO(x ) ((x) * (x))
#define CUBO(x) ((x) * (x) * (x))
Ma c r o s e con sta n tes 81

#define MIN(x, y) (((x) < (y)) ? (x): (y))


#define MAX(x, y) (((x) > (y)) ? (x): (y))
As definies de macros colocam os parmetros dentro de parnteses para suportar as expresses. Como
um exemplo, considere o seguinte comando:
result = QUADRADO(3 + 5);
O comando deve atribuir varivel result o valor 64 (8 * 8 ). Por exemplo, assuma que voc venha a definir
a macro QUADRADO, como segue:
#define QUADRADO(x) (x * x)
Quando o pr-processador substitui a expresso 3 + 5 para x, a substituio torna-se a seguinte:
result = ( 3 + 5 * 3 + 5 ) ;
Lembre-se da precedncia de operadores de C e observe que a multiplicao tem precedncia mais alta que
a adio. Portanto, o programa calcularia a expressofcomo segue:
result = ( 3 + 5 * 3 + 5 ) ;
= ( 3 + 15 + 5);
= 23;
No entanto, quando voc coloca cada parmetro dentro de parnteses, garante que o pr-processador ava
liar a expresso corretamente:
result = quadrado (3+5);
= ((3 + 5) * (3 + 5));
' = ((8 ) * (8 ));
= (6 4 );
= 64;
Nota: Como regra, voc sempre dever colocar os parmetros de suas macros dentro de parnteses.

A s M a c r o s N o T m T i p o 16 0
Na seo Funes, mais frente voc aprender como criar funes que efetuam operaes especficas. Voc
aprender que C lhe permite passar parmetros para suas funes, exatamente como voc passou valores para as
macros. Se sua funo executa uma operao e retorna um resultado, voc precisar especificar o tipo do resul
tado (que int, float, e assim por diante). Por exemplo, a seguinte funo, soma_valores, soma dois valores in
teiros e retorna um resultado do tipo int:
int soma_valores(int x, int y)
{
return (x + y);
>
Dentro de seu programa voc pode somente usar a funo soma_valores para somar dois valores do tipo int.
Se voc tentar somar dois valores em ponto flutuante, um erro ocorrer. Como voc viu, as macros lhe permitem
trabalhar com valores de qualquer tipo. Por exemplo, a macro SOMA, que voc criou anteriormente, suportava
valores dos tipos int e float:
printf("Somando 3 + 5 = %d\n", SOMA(3, 5));
printf("Somando 3.4 + 3.1 = %f\n", SOMA(3.4, 3.1));
Quando voc usa macros para operaes aritmticas simples, elimina a necessidade de funes duplicadas
simplesmente porque quer trabalhar com valores de tipos diferentes. No entanto, como voc aprender poste
riormente na seo Funes, existem outras vantagens e desvantagens a considerar ao decidir se voc vai usar ma
cros ou funes.
82 P rogram and o em C/C+ + A b b l ia

161 V is u a l iz a n d o uma S t r in g de C
Seu computador requer um byte de memria para armazenar um nico caractere ASCII. Como voc aprendeu,
uma string uma seqncia de caracteres ASCII. Quando voc declara uma constante de string, C automatica
mente atribui o caractere N U L L Quando seus programas criam suas prprias strings lendo caracteres do teclado,
eles precisam colocar o caractere NULL no final da string para indicar onde ela termina. Portanto, o melhor
modo para voc visualizar uma string como uma coleo de bytes terminados por um caractere NULL, como
mostrado na Figura 161.

Figura 161 C armazena as strings em posies de byte consecutivos na memria.

Quando as funes trabalham com strings, em geral a funo somente recebe a localizao onde a string
inicia. Aps a funo saber a localizao inicial da string, ela pode percorrer posies sucessivas de memria at
que a funo encontre o caractere NULL (que indica o final da string).

162 Co m o o C o m p il a d o r R e p r e s e n t a uma S t r in g de

Ca r a c t e r e s
Vrias dicas apresentadas neste livro usam constantes de string de caracteres delimitadas por aspas, como no
exemplo a seguir:
"Bblia do Programador C/C++, do Jamsa!"
Quando voc usa uma constante de string de caracteres dentro de seu programa, o compilador C automa
ticamente coloca o caractere NULL (\0) no final da string. Dada a constante string anterior, o compilador C ar-
mazenar a constante na memria, como mostrado na Figura 162.

Figura 162 C automaticamente coloca o caractere NULL nas constantes de string.

163 Co m o C A r m a z e n a as S t r in g s de Ca r a c t e r e s
Muitas das dicas que este livro apresenta utilizam strings de caracteres. Por exemplo, alguns programas usam
strings para ler arquivos e entrada do teclado e efetuar outras operaes. Em C, uma string de caracteres uma
matriz de caracteres terminada por zero ou N U L L Para criar uma string de caracteres, voc simplesmente declara
uma matriz de caracteres, como mostrado aqui:
char string[256];
C criar uma string capaz de armazenar 256 caracteres, que C indexa de string[0] at string[255]. Como
a string pode conter menos que 256 caracteres, C usa o caractere NULL (ASCII 0) para representar o ltimo ca
ractere da string. C tipicamente no coloca o caractere NULL aps o ltimo caractere na string. Em vez disso,
Co m p r e e n d e n d o a s s t r in g s 83

funes tais c o m o ^ t o u gets colocam o caractere NULL no final da string. medida que seus programas ma
nipularem strings, sua responsabilidade garantir que o caractere NULL esteja presente. O programa a seguir,
cria_abc.c, define uma string de 256 caracteres, e, depois, atribui as letras maisculas do alfabeto aos primeiros
vinte e seis dgitos da string:
tinclude <stdio.h>

void main(void)
{
char string[256];
int i;

for (i = 0; i < 26; i++)


string[i] = 'A' + i;
string[i] = NULL;
printf ("A string contm %s\n", string);
}
O programa cria_abc.c usa o lao for para atribuir as letras A at Z string. O programa depois coloca o
caractere NULL aps a letra Z para indicar o final da string. A funo p rintf ento exibir cada caractere na string
at o caractere NULL. As funes que trabalham com strings usam o caractere NULL para determinar o final
da string. O programa a seguir, a_ate_z.c, tambm atribui as letras A at Z a uma string de caracteres. No en
tanto, depois, o programa atribui o caractere NULL string[10], que a posio que segue imediatamente a letra
J. Quando p r in tf exibe o contedo da string, ele parar na letra J:
#include <stdio.h>

void main(void)
{
char string[256];
int i;

for (i = 0; i < 26; i++)


string[i] = 'A' + i;
string[10] = NULL;
printf ("A string contm %s\n", string);
>

Nota: Quando voc trabalhar com strings, sempre precisar incluir o caractere N U LL para representar o final da
string.

A p r e n d e n d o C o m o A D i f e r e de A 164
Como voc aprendeu na Dica 161, uma string de caracteres uma seqncia de zero ou mais caracteres ASCII que
C tipicamente finaliza com NULL (o ASCII 0). Quando voc trabalha com caracteres dentro de C, pode usar o valor
ASCII numrico de um caractere ou pode colocar o caractere dentro de apstrofes, tal como A . Por outro lado,
quando voc usa aspas, tal como A, C cria uma string de caracteres que contm a letra especificada (ou letras), e
finaliza a string com o caractere NULL. A Figura 164 ilustra como C armazena as constantes A e A.

Figura 164 C o m o C arm azena as constantes A e A .

Como C as armazena de forma diferente, as constantes de caractere e string no so iguais, e voc precisar
trat-las de forma diferente dentro de seus programas.
84 Programando em C/C++ A B b lia

16 5 Represen ta n d o um A p s t r o f o Den t r o de uma

Co n s t a n t e de S t r in g
Como voc aprendeu, para criar uma constante de string, seu programa precisar colocar os caracteres desejados
dentro de aspas:
"Isto uma constante de string"
Dependendo dos seus programas, algumas vezes uma constante de string conter um caractere aspas. Por
exemplo, assuma que voc queira representar a seguinte string:
"Parei, ele disse.
Como C usa as aspas para definir as constantes de string, voc precisar ter um modo de dizer ao com
pilador que quer incluir aspas dentro da string. Para fazer isso, use a seqncia de escape \, como mostrado aqui:
"\"Pare!\", ele disse."
O programa a seguir, aspas, c, usa a seqncia de escape \ para colocar aspas dentro de uma constante de string:
#include <stdio.h>

void main(void)
{
char string[] = "\"Pare!\", ele disse.";

printf(string);
}

166 D e t e r m in a n d o o Ta m a n h o de uma S t r in g
Na dica 163 voc aprendeu que as funes de C normalmente usam o caractere NULL para representar o final
de uma string. Funes tais como fgets e cgets automaticamente atribuem o caractere NULL para indicar o final de
uma string. O programa a seguir, exib_str.c, usa a funo gets para ler uma string de caracteres do teclado. O pro
grama depois usa um lao for para exibir os caracteres da string um de cada vez at que a condicional string[i]
!= NULL seja avaliada como falsa:
#include <stdio.h>

void main(void)
{
char string[256]; // String digitada pelo usurio
int i; // ndice para a string

printf("Digite uma string de caracteres e pressione Enter:\n");


gets(string);
// Exibe cada string de caracteres at que NULL seja encontrado
for (i = 0; string[i] 1= NULL; i++)
putchar(string[i]);
printf(\nO nmero de caracteres na string %d\n, i);
>

16 7 Usa n d o a Funo strlen


medida que voc trabalha com strings dentro de seus programas, efetuar muitas operaes com base no n
mero de caracteres na string. Para lhe ajudar a determinar o nmero de caracteres em uma string, a maioria dos
compiladores C fornece uma funo strlen, que retorna o nmero de caracteres em uma string. O formato da
funo strlen como segue:
Co m p r e e n d e n d o a s s t r in g s 85

#include <string.h>
size_t strlen(const char string);
O programa a seguir, strlen.c, ilustra como usar a funo strlen:
#include <stdio.h>
#include <string.h>
void main(void)
{
char titulo_livro[] = "Bblia do Programador C/C++, do Jamsa!";
printf("%s contm % caracteres\n", titulo_livro,
strlen(titulo_livro));
>
Quando voc compilar e executar o programa strlen.c, sua tela exibir o seguinte:
Bblia do Programador C/C++, do Jamsa! contm 38 caracteres
C: \>
Para compreender melhor como a funo strlen funciona, considere a seguinte implementao. A funo
simplesmente conta os caracteres em uma string at, mas no incluindo, o caractere NULL:
size_t strlen(const char string)
{
int i = 0;
while (string[i])
i+ + ;
return(i);
>

C o p ia n d o os Ca r a c t e r e s de uma S t r in g em Outra
S t r in g 168
Quando seus programas trabalharem com strings, algumas vezes voc precisar copiar o contedo de uma string
em outra string. Para lhe ajudar a realizar operaes em strings de caracteres, a maioria dos compiladores C oferece
uma funo strcpy, que copia os caracteres em uma string (o parmetro origem) em outra string (o parmetro destino):
#include <string.h>
char *strcpy(char *destino, const char *origem);
A funo strcpy retorna um ponteiro para o incio da string de destino. O programa a seguir, strcpy.c, ilustra
como voc usar a funo strcpy dentro de seus programas.
#include <stdio.h>
tinclude <string.h>
void main(void)
{
char titulo[]="Bblia do Programador C/C++, do Jamsa!";
char livro[128];
strcpy(livro, titulo);
printf("Nome do livro %s\n, livro);
>
Para compreender melhor como a funo strcpy funciona, considere a seguinte implementao:
char *strcpy(char *destino, const char *origem)
{
while (*destino++ = *origem++)
r
86 P rogram ando em C/C++ A b b l ia

return(destino-l);
}
A funo strcpy simplesmente copia letras da string de origem para o destino, at e incluindo o caractere NULL.

16 9 A n exa n d o o Co n t e d o de uma S t r in g em Outra


Quando seus programas trabalharem com strings, algumas vezes voc precisar anexar o contedo de uma string
em outra string. Por exemplo, se uma string contm um nome de subdiretrio e outra contm um nome de ar
quivo, voc poder anexar o nome de arquivo ao subdiretrio para criar um nome de caminho completo. Os
programadores C referenciam o processo de anexar uma string em outra como concatenao de strings. Para lhe
ajudar a anexar uma string em outra, a maioria dos compiladores C fornece uma funo chamada strcat, que con-
catena (anexa) uma string de origem em uma string-alvo, como mostrado aqui:
ttinclude <string.h>
char *strcat (char alvo, const char *origem);
O programa a seguir, strcat. c, ilustra como usar a funo strcat:
#include <stdio.h>
tinclude <string.h>
void main(void)
{
char nome[64] = "Dlmata Macho"; strcat(nome, Happy");
printf("O nome completo do Happy %s\n", nome);
}
Quando voc compilar e executar o programa strcat. c, sua tela exibir o seguinte:
O nome completo do Happy Dlmata Macho Happy
C:\>

Para compreender melhor a funo strcat, considere a seguinte implementao:


char *strcat(const *alvo, const char *origem)
{
char *original = alvo;
while (*alvo)
alvo++; // Encontra o final da string
while (*alvo++ = *origem++)
t
return (original);
>
Como voc pode ver, a funo strcat percorre os caracteres da string de destino at que a funo encontre
o caractere N U L L A funo strcat, ento, anexa cada caractere na string de origem, at e incluindo o caractere
N U L L na string de destino.

170 A n exan d o n Ca r a c t e r e s em uma S t r in g


Na Dica 169 voc aprendeu que a funo strcat lhe permite anexar (concatenar) os caracteres de uma string em
outra. Em alguns casos, voc no vai querer anexar todos os caracteres em uma string, mas, em vez disso, somen
te os dois, trs, ou n primeiros caracteres na string. Para lhe ajudar a anexar n caracteres a uma string, a maioria
dos compiladores C fornece uma funo chamada strncat, que anexa os primeiros n caracteres de uma string de
origem a uma string de destino, como mostrado aqui:
#include <stding.h>
char *strncat(char *destino, const *origem, size_t n);
Se n especificar um nmero de caracteres maior que o nmero de caracteres na string origem, strncat co
piar caracteres at o final da string e no mais. O programa a seguir, strncat.c, ilustra como usar a funo strncat:
Co m p r e e n d e n d o a s s t r in g s 87

#include <stdio.h>
#include <string.h>

void main(void)
<
char nome[64] = "Fernando";
strncat(nome, " e Rute", 8);
printf("Voc votou em %s?\n", nome);
}
Quando voc compilar e executar o programa strncat. c, sua tela exibir o seguinte:
Voc votou em Fernando e Rute?
C:\>
Para lhe ajudar a entender a funo strncat, considere a seguinte implementao:
char *strncat(char destino, const char *origem, int n)
{
char original = destino;
int i = 0;
while (*destino)
destino++;
while ((i++ < n) && (*destino++ = *origem++))

if (i > n)
destino = NULL;
return(original);
. 1

Tra n sfo rm a n d o uma S t r in g em Ou tra 171


Vrias dicas neste livro mostraram como copiar o contedo de uma string em outra. A funo strxfrm copia o
contedo de uma string em outra (at o nmero de caracteres que voc especifica dentro do parmetro n ) e, de
pois, retorna o tamanho da string resultante:
#include <string.h>
size_t strxfrm(char *alvo, char *origem, size_t n);
O parmetro alvo um ponteiro para o qual a funo strxfrm copia a string origem. O parmetro n especifica
o nmero mximo de caracteres a copiar. O programa a seguir, strxfrm. c, ilustra como usar a funo strxfrm:
tinclude <stdio.h>
iinclude <string.h>
void main(void)
{
char buffer[64] = "Bblia do Programador C/C++, do Jamsa!";
char alvo[64];
int tamanho;
tamanho = strxfrm(alvo, buffer, sizeof(buffer));
printf("Tamanho % Alvo % b Buffer %s\n", tamanho,
alvo, buffer);
}

No U lt r a p a s s e o Tam anho de uma S t r i n g 172


Muitas dicas nesta seo apresentaram funes que copiam ou anexam caracteres de uma string em outra. Quan
do voc efetua operaes de strings de caracteres, precisa garantir que no sobrescreve as localizaes de memria
da string. Como um exemplo dos problemas com a sobrescrira dos limites de uma string, considere a seguinte
declarao, que cria uma string de caracteres capaz de armazenar 10 caracteres.
88 P rog ram and o em C/C++ A B b l ia

char stringtlO];
Se voc atribuir mais de 10 caracteres string, seu sistema operacional poder no detectar o erro. Em vez
disso, os caracteres que voc queria atribuir string podem sobrescrever as posies de memria que correspon
dem s outras variveis. Corrigir um erro de sobrescrita muito difcil, e o erro tambm pode fazer seu programa
e o sistema operacional interromper a execuo. Como regra, declare suas strings ligeiramente maiores do que
voc acha que ser necessrio. Fazendo isso, voc reduz a possibilidade de sobrescrever uma string. Se seus pro
gramas experimentarem erros intermitentes, examine o cdigo de seu programa para determinar se seu programa
pode estar sobrescrevendo uma string de caracteres.

173 D e t e r m in a n d o S e D u a s S t r i n g s S o ou no Ig u a is
Quando seus programas trabalham com strings, voc freqentemente comparar duas .strings para determinar se
elas so ou no iguais. Para lhe ajudar a determinar se duas strings contm os mesmos caracteres, voc poder
usar a funo streql, mostrada aqui:
int streql (char *strl, char *str2)
{
while ((*strl == *str2) && (*strl))
{
strl++;
str2++;
>
return((*strl == NULL) && (*str2 == NULL));
}
A funo streql retornar o valor 1 se as duas strings forem iguais, e 0 se as strings no forem iguais. O se
guinte programa C, streql.c, ilustra como usar a funo streql:
#include <stdio.h>
void main(void)
(
printf("Testando Abc e Abc %d\n", streql("Abc", "Abc"));
printf("Testando abc e Abc %d\n", streql("abc", "Abc"));
printf ("Testando abcd e abc %d\n, streql ("abcd11,
"abc"));
>
Quando voc compilar e executar o programa streql.c\ sua tela exibir a seguinte sada:
Testando Abc e Abc 1
Testando abc e Abc 0
Testando abcd e abc 0
C:\>

17 4 Ig n o r a n d o a Ca ix a ao D e t e r m in a r S e as S t r in g s
S o I g u a is
Na Dica 173 voc criou a funo streql, que permite que seus programas determinem rapidamente se duas strings
so iguais. Quando a funo streql compara duas strings, streql considera os caracteres maisculos e minsculos
como diferentes. Algumas vezes voc pode querer comparar duas strings sem considerar a caixa. Para comparar
strings sem considerar a caixa, voc pode criar a funo strieql, como mostrado aqui:
#include <ctype.h>
int strieql(char *strl, char *str2)
{
while ((toupper(*strl) == toupper(*str2)) && (*strl))
{
strl++;
str2++;
}
Co m p r e e n d e n d o a s s t r in g s 89

return((*strl == NULL) && (*str2 == NULL));


>
Como voc pode ver, a funo strieql converte cada caractere em cada string para maiscula antes de com
parar as duas strings. O programa a seguir, strieqic, ilustra como usar strieql:
#include <stdio.h>
#include <ctype.h>
void main(void)
{
printf("Testando Abc e Abc %d\n", strieql("Abc, "Abc"));
printf("Testando abc e Abc %d\n, strieql("abc", "Abc"));
printf("Testando abcd e abc %d\n", strieql("abcd", "abc"));
>
Quando voc compilar e executar o programa strieql.c, sua tela exibir o seguinte:
Testando Abc e Abc 1
Testando abc e Abc 1
Testando abcd e abc 0
C:\>

Co n v e r t e n d o u m a s t r in g de Ca r a c t e r e s para

Ma i s c u l a s ou M in s c u l a s 175
Quando seus programas trabalharem com strings, algumas vezes voc desejar converter a string para maisculas.
Por exemplo, quando um usurio digitar o nome de um arquivo ou de um cliente, voc poder querer que o pro
grama converta a string digitada em maisculas para simplificar as operaes de comparao ou para garantir que
o programa armazene dados em um formato consistente. Para lhe ajudar a efetuar essas converses, a maioria dos
compiladores C fornece as funes strlwr e stmpr, como mostrado aqui:
ttinclude <string.h>
char *strlwr(char *string);
char *strupr(char (string);
O programa a seguir, strcase.c, ilustra como usar as funes strlwr e srtupr:

Para lhe ajudar a compreender melhor essas duas funes, considere a seguinte implementao de strlwr.
#include <ctype.h>
char *strlwr(char *string)
{
char *original = string;
while (*string)
{
string = tolower(*string);
string++;
}
return(original);
>
Como voc pode ver, tanto strlwr quanto strupr percorrem os caracteres em uma string, convertendo cada
caractere para maiscula ou para minscula, dependendo da funo chamada.
90 P rogram ando em C/C++ A B b l ia

17 6 Obt en d o a P r i m e i r a O c o r r n c ia de um Ca r a c t e r e
em uma S t r in g
medida que seus programas trabalham com strings, algumas vezes voc pode querer encontrar a primeira ocor
rncia (a que est mais esquerda) de um caractere especfico dentro de uma string. Por exemplo, se voc estiver
trabalhando com uma string que contm um nome de caminho, voc poder procurar na string o primeiro ca
ractere de barra invertida (\). Para lhe ajudar a procurar a primeira ocorrncia em uma string, a maioria dos com
piladores fornece uma funo chamada strchr, que retorna um ponteiro para a primeira ocorrncia de um
caractere especfico dentro de uma string, como mostrado aqui:
#include <string.h>

char *strchr(const char *string, int caractere);


Se strchr no encontrar o caractere especificado dentro da string, strchr retornar um ponteiro para o ca
ractere NULL que marca o final da string. O programa a seguir, strchr. c, ilustra como usar a funo strchr:
#include <stdio.h>
#include <string.h>

void main(void)
{
char titulo[64] = "Bblia do Programador C/C++, do Jamsa!";
char *ptr;

ptr = strchr(titulo, 'C');


if (*ptr)
printf("A primeira ocorrncia de C est no deslocamento %cl\n", ptr -
titulo);
else
printf("Caractere no encontrado\n");
}
Quando voc compilar e executar o programa strchr.c, sua tela exibir o seguinte:
A primeira ocorrncia de C est no deslocamento 22
C; \>
Voc deve observar que strchr no contm um ndice para a primeira ocorrncia de um caractere; em vez
disso, strchr contm um ponteiro para o caractere. Para lhe ajudar a compreender melhor a funo strchr, con
sidere a seguinte implementao:
char *strchr(const char *string, int letra)
{
while ((*string != letra) && (*string))
string++;
return(string);
>

177 R eto rn a n d o um n d ic e P r i m e i r a O c o r r n c ia de

uma S t r in g
Na Dica 176 voc aprendeu como usar a funo strchr para obter um ponteiro para a primeira ocorrncia de um
caractere dentro de uma string. No entanto, se voc tratar as strings como matrizes, e no como ponteiros, pro
vavelmente ir preferir trabalhar com um ndice para o caractere, em vez de com um ponteiro. Voc pode usar
a funo strchr para obter um ndice para o caractere desejado subtraindo o endereo inicial da string do ponteiro
que strchr retorna, como mostrado aqui:
Co m p r e e n d e n d o as S t r in g s 91

char_ptr = strchr(string, caractere);


indice = char_ptr - string;
Se strchr no encontrar o caractere na string, ento o valor que strchr atribuir ao ndice ser igual ao ta
manho da string. Alm de usar strchr como detalhado nesta dica, voc tambm pode usar a funo str_indice,
como mostrado aqui:
int str_indice(const char *string, int letra)
{
char *original = string;
while ((string 1= letra) && (*string))
string++;
return(string - original);

E ncontrando a l t im a O c o r r n c i a de um Ca r a c t e r e
em uma S t r in g 178
A medida que seus programas forem trabalhando com strings, algumas vezes voc ir querer localizar a ltima
ocorrncia (a mais direita) de um caractere especfico dentro de uma string. Por exemplo, se voc estiver tra
balhando com uma string que contm um nome de caminho, poder pesquisar na string o ltimo caractere barra in
vertida (\) para localizar a posio onde comea o nome do arquivo. Para lhe aiudar a procurar a ltima ocorrncia
de um caractere dentro de uma string, a maioria dos compiladores fornece uma funo chamada strrchr, que retomar
um ponteiro para a ltima ocorrncia de um caractere especfico dentro de uma string, como mostrado aqui:
#include <string.h>
char *strrchr(const char *string, int caractere);
Se strrchr no encontrar o caractere que voc especificar dentro da string, strrchr retornar um ponteiro para o
caractere NULL que marcar o final da string. O programa a seguir, strrchr. c, ilustra como usar a funo strrchr:
#include <stdio.h>
#include <string.h>
void main(void)
{
char titulo[64] = "Bblia do Programador C/C++, do Jamsa!;
char *ptr;
if (ptr = strrchr(titulo, 'C'))
printf(A ocorrncia mais direita de C est no deslocamento %d\n",
ptr - titulo);
else
printf("Caractere no encontrado\n");
}
Observe que strrchr no contm um ndice ltima ocorrncia de um caractere, mas, em vez disso, contm um
ponteiro para o caractere. Para lhe ajudar a compreender melhor a funo strrchr, considere a seguinte implementao:
char *strrchr (const char *string, int letra)
<
char *ptr = NULL;

while (*string)
{
if (*string == letra)
ptr = string;
string++;
>
return(ptr);
>
92 P rog ram and o em C/C++ A B b l ia

17 9 R eto rn a n d o um n d ic e l t im a O c o r r n c ia de uma

S t r in g
Na Dica 178 voc viu como usar a funo strrchr para obter um ponteiro para a ltima ocorrncia de um caractere
dentro de uma string. No entanto, se voc tratar uma string como uma matriz, e no como um ponteiro, poder obter
um ndice para o caractere desejado subtraindo o endereo inicial da string do ponteiro que strrchr retornar:
char_ptr = strrchr(string, caractere);

indice = char_ptr - string;


Se strrchr no encontrar o caractere na string, o valor que strrchr atribuir ao ndice ser igual ao tamanho
da string. Alm de usar strrchr, voc poder usar a funo strr_index, como mostrado aqui:
int strr_index(const char *string, int letra)
{
char *original = string;
char *ptr = NULL;

while (*string)
{
if (*string == letra)
ptr = string;
string++;
}
return((*ptr) ? ptr-original: string-original);
}

180 Tra ba lh a n d o com S t r in g s do T ip o far


Como ser discutido na seo Gerenciamento da Memria no Windows mais frente, os ponteiros fa r permitem
que os programas do DOS acessem dados que residem fora do segmento atual de 64Kb. Quando voc estiver
trabalhando com ponteiros far, precisar tambm usar funes que esperam que seus parmetros sejam ponteiros
far. Infelizmente, nenhuma das rotinas de manipulao de strings que esta seo apresenta prev ponteiros far
para as strings. Passar um ponteiro fa r para uma das funes de manipulao de string que esta seo detalha pro
vocar um erro. No entanto, para suportar os ponteiros far, muitos compiladores fornecem implementaes de
ponteiros fa r dessas funes. Por exemplo, para determinar o tamanho de uma string que um ponteiro fa r re
ferencia, voc poderia usar a funo _fstrlen, como mostrado aqui:
#include <string.h>
size_t _fstrlen(const char *string)
Para determinar quais funes fa r seu compilador suporta, consulte a documentao do compilador.
Nota: Como voc aprendeu anteriormente, o Visual C++ no suporta as declaraesfa r (sejam funes ou ponteiros),
de modo que voc pode usar a funo strlen com os ponteiros char de qualquer tamanho no Visual C++.

181 E s c r e v e n d o F u n e s S t r in g para as S t r in g s far


Na Dica 180 vimos que vrios compiladores fornecem funes que suportam strings que os ponteiros fa r refe
renciam. Se seu compilador no fornece essas funes, voc mesmo pode criar as funes de string fa r modifi
cando as funes nesta seo. Como um exemplo, a seguinte funo, fitreql, ilustra a implementao baseada em
ponteiros fa r de streql (em vez de a implementao padro baseada em ponteiros locais):
int fstreql (char far *strl, char far *str2)
{
while ((*strl == *str2) && (*strl))
{
strl++;
C o m p r e e n d e n d o a s S t r in g s 93

str2 + + ;
}
return((*strl == NULL) && (*str2 == NULL));
}
Nota: Como voc aprendeu anteriormente, o Visual C++ no suporta as declaraes far, de modo que voc poder
usar a funo streql com os ponteiros char de qualquer tamanho no Visual C++.

Co n t a n d o o n m ero de O c o r r n c ia s de um Ca r a c t e r e
EM UMA STRING 18 2
medida que seus programas forem trabalhando com strings, algumas vezes voc poder querer saber o nmero
de vezes que um caractere ocorre dentro de uma string. Para lhe ajudar a contar o nmero de vezes que um ca
ractere ocorre dentro de uma string, seus programas podem usar a funo charcnt, como mostrado aqui:
int charcnt(const char *string, int letra)
{
int conta = 0;
while (*string)
if (*string == letra)
conta++;
return(conta);
>

In v e r t e n d o o C o n te d o de uma S t r i n g 183
medida que seus programas efetuarem diferentes operaes, algumas vezes voc poder precisar inverter a or
dem de caracteres dentro de uma string. Para simplificar tais operaes, a maioria dos compiladores fornece uma
funo strrev, como mostrado aqui:
#include <string.h>

char *strrev(char *string);


Para compreender melhor a funo strrev, considere a seguinte implementao:
char *strrev(char *string)
{
char *original = string;
char *frente = string;
char temp;

while (*string)
string++;
while (frente < string)
{
temp = *(--string);
string = *frente;
*frente++ = temp;
>
return(original);
}

At r ib u in d o um Ca r a c t e r e E s p e c f i c o a uma

S t r i n g In t e ir a 184
medida que seus programas forem trabalhando com strings, possvel que s vezes voc ir querer definir todos
os caracteres em uma string com um caractere especfico. Por exemplo, algumas vezes voc quer sobrescrever o
94 PROGRAMANDO EM C/C++ -- A BBLIA

valor atual de uma string antes de passar a string para uma funo. Para simplificar a sobrescrita de todo caractere
dentro de uma string, a maioria dos compiladores C fornece uma funo strset, que atribui a cada caractere na
string um caractere especificado, como mostrado aqui:
#include <string.h>

char *strset(char *string, int caractere);


A funo strset atribui o caractere especificado para cada posio na string at encontrar o caractere NULL.
Para compreender melhor a funo strset, considere a seguinte implementao:
char *strset(char *string, int letra)
{
char original = string;

while (*string)
*string++ = letra;
return(original);
>
Como voc pode ver, a funo percorre a string atribuindo o caractere especificado at que a funo en
contre o caractere NULL.

185 Co m p a r a n d o D u a s S t r in g s de Ca r a c t e r e s
Na Dica 173 voc criou a funo streql, que permite que seus programas testem se duas strings de caracteres so
iguais. Dependendo do processamento que seu programa precisa executar, haver algumas vezes (tais como
quando seu programa efetuar uma operao de classificao) que voc dever saber se uma string maior que
outra. Para ajudar seus programas a efetuar operaes que determinem o valor de vrias strings, a maioria dos
compiladores C fornece uma funo chamada strcmp, que compara duas strings de caracteres, como mostrado
aqui:
#include cstring.h>

int strcmp(const char *strl, const *char str2);


Se as strings forem iguais, strcmp retornar o valor 0. Se a primeira string for maior que a segunda, strcmp
retornar um valor menor que 0. Da mesma forma, se a segunda string for maior que a primeira, strcmp retornar
um valor maior que 0. O programa a seguir, strcmp.c, ilustra como usar a funo strcmp:
tinclude cstdio.h>
#include <string.h>

void main(void)
{
printf("Comparando Abc com Abc %d\n", strcmp("Abc", "Abc"));
printf("Comparando abc com Abc %d\n", strcmp("abc", "Abc));
printf("Comparando abcd com abc %d\n, strcmp("abcd", "abc"));
printf("Comparando Abc com Abcd %d\n", strcmp("Abc", "Abcd"));

printf("Comparando abcd com abce %d\n", strcmp("abcd", "abce"));


printf("Comparando Abce com Abcd %d\n, strcmp("Abce", "Abcd"));
>
Para compreender melhor a funo strcmp, considere a seguinte implementao:
int strcmp(const char *sl, const char *s2)
{
while ((*sl == *s2) && (*sl))
{
S l ++;
S2++;
Co m p r e e n d e n d o as S t r in g s 95

}
if ((*el *s2) *& (1 *sl)) // Strings iguais
retum(O);
else if ((*sl) && (1 *s2)) // Iguais mas sl maior
return(-1);
else if ((*s2) && (! *sl)) // Iguais mas s2 maior
return(1);
else
return((*sl > *s2) ? -1: 1); // Diferentes
>

Co m p a r a n d o os P r im e ir o s n Ca r a c t e r e s de Du a s
S t r in g s 186
N a D ica 185 voc aprendeu com o usar a funo strcmp para com parar duas strings. D ependendo da funo do
seu programa, algumas vezes voc poder querer som ente com parar os primeiros n caracteres de duas strings.
Para facilitar a comparao som ente de n caracteres de duas strings, a maioria dos compiladores C fornece uma
funo cham ada stmcmp, com o m ostrado aqui:
#include string.h>

int strncmp(const char *sl, const char *s2, size_t n);


C om o strcmp, a funo stmcmp retornar o valor 0 se as strings forem iguais, e um valor m enor ou maior
que 0, dependendo se a prim eira ou a segunda string for maior. O program a a seguir, stmcmp.c, ilustra como
usar a funo stmcmp:
#include <stdio.h>
#include <string.h>
void main(void)
{
printf("Comparando 3 letras Abc com Abc %d\n", strncntp("Abc", "Abc", 3));
printf("Comparando 3 letras abc com Abc %d\n", strncntp("abc", "Abc", 3));
printf("Comparando 3 letras abcd com abc %d\n", strncmp("abcd", "abc", 3));
printf("Comparando 5 letras Abc com Abcd %d\n,strncmp("Abc", "Abcd", 5 ));
printf ("Comparando 4 letras abcd com abce %d\n", stmcinp( "abcd", "abce", 4));
>
Para com preender m elhor a funo stmcmp, considere a seguinte implementao:
int strncmp(const char *sl, const char *s2, int n)
{
int i = 0;
while ((*sl == *s2) &&-(*sl) && i < n)
{
sl ++ ;
s2++;
i++;
>
if (i == 0) // Strings iguais
return(0);
else if ((*sl == *s2) && (! *sl)) // Strings iguais
return(0);
else if ((*sl) && (! *s2)) // Iguais, mas sl maior
return(-l);
else if ((*s2) && (1 *sl)) / / Iguais, mas s2 maior
return(l);
else
retum((*sl > *s2) ? -1: 1);
96 P rogram and o em C/C++ A B b l ia

>

18 7 C o m p a ra n d o S t r i n g s sem C o n s id e r a r a Caixa
Na Dica 185 voc viu como usar a funo strcmp para comparar duas strings. Da mesma forma, na Dica 186
voc .viu como usar a funo stmcmp para comparar os primeiros n caracteres de duas strings. Tanto strcmp e
strncmp consideram as letras maisculas e minsculas como distintas. Dependendo da funo que seu programa
executa, algumas vezes voc pode querer que a comparao de strings ignore a caixa. Para tais operaes, a maio
ria dos compiladores C fornece as funes stricmp e strncmpi, como mostrado aqui:
#include <string.h>

int stricmp(const char sl, const char s2);


int strncmpi(const char *sl, const char *s2, size_t n);
O programa a seguir, cmpcaixa.c, ilustra como usar as funes stricmp e strncmpi:
#include <stdio.h>
#include <string.h>

void main(void)
{
printf("Comparando Abc com Abc %d\n", stricmp("Abc", "Abc"));
printf("Comparando abc com Abc %d\n", stricmp("abc", "Abc"));
printf("Comparando 3 letras abcd com ABC %d\n", strncmpi("abcd", "ABC", 3));
printf("Comparando 5 letras abc com Abcd %d\n, strncmpi("abc", "Abcd", 5));
}
Quando voc compilar e executar o programa cmpcaixa.c, sua tela exibir a seguinte sada:
Comparando ABC com ABC 0
Comparando abc com Abc 0
Comparando 3 letras abcd com ABC 0
Comparando 5 letras abc com Abcd -1
C: \>

188 Co n v e r t e n d o a Represen ta o em S t r in g de

Ca r a c t e r e s de um n m ero
Quando seus programas trabalham com strings, uma das operaes mais comuns que voc precisa executar
converter uma representao ASCII de um valor para um valor numrico. Por exemplo, se voc pedir que o
usurio digite seu salrio, poder precisar converter a entrada em string de caracteres em um valor em ponto flu
tuante. Para lhe ajudar a converter valores ASCII, a maioria dos compiladores C oferece um conjunto de funes
de biblioteca de execuo que efetuam a converso de ASCII para numrico. A Tabela 188 descreve resumida
mente as funes padro de converso ASCII.
Tabela 188 Funes da biblioteca de execuo que seus programas podem usar para converter representaes ASCII
de um valor numrico.
Funo Propsito
a to f Converte a representao em string de caracteres de um valor em ponto flutuante
atai Converte a representao em string de caracteres de um vaJor inteiro
atol Converte a representao em string de caracteres de um valor inteiro longo
strtod Converte a representao em string de caracteres de um valor em preciso dupla
strtol Converte a representao em string de caracteres de um valor longo

O programa a seguir, asciinum.c, ilustra como usar as funes de ASCII para numrico:
#include <stdio.h>
#include <stdlib.h>
Co m p r e e n d e n d o a s s t r in g s 97

void main(void)
{
int int_result;
float float_result;
long long_result;

int_result = atoi("1234");
float_result = atof("12345.678");
long_result = atol("1234567L);
printf("%d %f %ld\n", int_result, float_result, long_result);
}

D u p lic a n d o o C o n te d o de um a S t r in g 1 8 9
Quando seus programas trabalham com strings, algumas vezes voc pode querer duplicar o contedo de uma
string rapidamente. Se s vezes seu programa precisar copiar a string e outras vezes no, voc poder querer que
o programa aloque memria dinamicamente (durante a execuo do programa) para conter a cpia da string conforme
necessrio. Para permitir que seus programas aloquem memria durante a execuo (dinamicamente) para criar uma
cpia da string de caracteres, a maioria dos compiladores C fornece a funo strdup, como mostrado aqui:
ttinclude <string.h>

char *strdup(const char *alguma_string);


Quando voc chama strdup, a funo usa malloc para alocar memria, e, depois, copia o contedo da string
na posio de memria. Quando seu programa terminar de usar a cpia da string, ele poder liberar a memria
usando o .comando Jree. O programa a seguir, strdup. c, ilustra como usar a funo strdup:
#include <stdio.h>
#include <string.h>

void main(void)
{
char *titulo;

if ((titulo = strdup("Bblia do Programador C/C++, do Jamsa!")))


printf("Titulo: %s\n", titulo);
else
printf("Erro ao duplicar a string");
>
Para compreender melhor a funo strdup, considere a seguinte implementao:
#include <string.h>
#include <malloc.h>

char *strdup(const char *sl)


(
char *ptr;

if ((ptr = malloc(strlen(sl)+l))) // Aloca buffer


strcpy(ptr, sl);
return(ptr);
>

E n c o n tr a n d o um C a r a c t e r e da P r im e ir a O c o r r n c ia
de um D e te rm in a d o C o n ju n to 1 9 0
Na Dica 176 voc aprendeu como usar a funo strchr para localizar a primeira ocorrncia de um caractere es
pecfico. Dependendo da funo que seu programa executar, algumas vezes voc ir querer pesquisar em uma
98 PkOGRAMANDO EM C/C+ + A BBLIA

string a primeira ocorrncia de qualquer caractere de um dado conjunto de caracteres. Para lhe ajudar a procurar
em uma string qualquer caractere de um conjunto, a maioria dos compiladores C fornece a funo strspn, como
mostrado aqui:
#include <string.h>

size_t strspn(const char *sl, const char *s2);


Dentro da string sl, a funo retorna o deslocamento do primeiro caractere no contido dentro da string
s2. O programa a seguir, strspn.c, ilustra como usar a funo strspn:
#include <stdio.h>
#include <string.h>

void main(void)
{
printf("Procurando Abc emAbcDef %d\n", strspn("AbcDef", "Abc"));
printf("Procurando cbA emAbcDef %d\n, strspn("AbcDef", "cbA"));
printf("Procurando Def emAbcAbc %d\n, strspn("AbcAbc", "Def"));
>
Quando voc compilar e executar o programa strspn. c, sua tela exibir o seguinte:
Procurando Abc em AbcDef 3
Procurando cbA em AbcDef 3
Procurando Def em AbcAbc 0
C:\>
Para compreender melhor strspn, considere a seguinte implementao:
size_t strspn(const char *sl, const char *s2)
{
int i, j;

for (i = 0; *slj i ++ , sl++)


{
for (j = 0; s2[jj; j+ + )
if (*sl == s2 [j])
break;
if (s2 [j] == NULL)
break;
>
return(i);
}

191 L o c a l iz a n d o uma S u b s t r in g Den t r o de uma S t r in g


medida que seus programas trabalharem com strings, algumas vezes voc precisar procurar uma substring es
pecfica dentro de uma string. Para lhe ajudar a procurar uma substring em uma string, a maioria dos compi
ladores C fornece uma funo chamada strstr, como mostrado aqui:
#include <string.h>

strstr(string, substring);
Se a substring existir dentro da string, strstr retornar um ponteiro para a primeira ocorrncia da string. Se
strstr no encontrar a substring, a funo retornar NULL. O programa a seguir, strstr. c, ilustra como usar strstr:
iinclude <stdio.h>
#include <string.h>

void main(void)
{
Co m p r e e n d e n d o as S t r in g s 99

printf("Procurando Abc em AbcDef %s\n",


(strstr("AbcDef", "Abc")) "Encontrado" : "No encontrado");
printf("Procurando Abc em abcDef %s\n",
(strstr("abcDef", "Abc")) ? "Encontrado": "No encontrado");
printf("Procurando Abc em AbcAbc %s\n",
(strstr("AbcAbc", "Abc")) ? "Encontrado": "No encontrado");
>
Para lhe ajudar a compreender melhor strstr, considere a seguinte implementao:
char *strstr(const char *sl, const char *s2)
{
\int i, j, k;
for (i = 0;sl [i]; i++)
for (j = i, k = 0; sl[j] ==s2[k]; j++, k++)
if (! s2[k+1])
return(sl + i);
return(NOLL);
}

Co n t a n d o o N m er o de Oc o r r n c ia s da S u b s t r in g 192
Na Dica 191 voc viu como usar a funo strstr para localizar uma substring dentro de uma string. Em certas
ocasies, voc poder querer saber o nmero de vezes que uma substring aparece dentro de uma string. A seguinte
funo, strstr_cnt, permite-lhe determinar quantas vezes uma determinada substring ocorre dentro de uma string:
int strstr_cnt(const char *string, const char *substring)
{
int i, j, k, conta = 0;
for (i = 0;stringti]; i++)
for (j = i, k - =0; string[j]==substring[k]; j ++ , k++)
if (! substring[k + 1])
conta++;
return(conta);
>

Obt en d o um n d ic e para um a S u b s t r in g 193


Na Dica 191 voc aprendeu como usar a funo strstr para obter um ponteiro para uma substring dentro de uma
string. Se voc tratar as strings de caracteres como matrizes, em vez de usar ponteiros, algumas vezes ir querer
saber o ndice do caractere onde uma substring inicia dentro da string. Usando o valor que strstr retorna, voc
pode subtrair o endereo da string para produzir um ndice:
indice = strstr(string, substr) - string;
Se strstr no encontrar a substring, o valor do ndice ser igual ao tamanho da string. Alm disso, seus pro
gramas podem usar a funo substring_index para obter um ndice para uma substring, como mostrado aqui:
int substring_index(const char *sl, const char *s2)
{
int i, j, k;
for (i = 0; sl[i]; i++)
for (j = i, k = 0; sl[j] == s2[k]; j++, k++)
if (I s2[k+1])
return(i);
return(i);
}

Obt en d o a O c o r r n c ia M a is D ir e it a de uma S u b s t r in g 194


Na Dica 191 voc usou a funo strstr para determinar a primeira ocorrncia de uma substring dentro de uma
string. Dependendo da funo do seu programa, algumas vezes voc poder querer conhecer a ltima (a mais
100 P rogram and o em C/C++ A B b l ia

direita) ocorrncia de uma substring dentro de uma string. A funo a seguir, r_strstr, retorna um ponteiro para
a ocorrncia mais direita de uma substring dentro de uma string, ou o valor NULL se a substring no existir:
char *r_etrstr(const char *sl, const char *s2)
{
int i, j, k, esquerda = 0;

for (i = 0; sl[i]; i++)


for (j = i, k = 0; sl[j] == s2[k]; j++, k++)
if (! s2[k+1])
esquerda = i;
return((esquerda) ? sl+esquerda: NULL);
}

195 E x i b in d o uma S t r in g sem o E s p e c if ic a d o r de

Fo rm ato % s
Vrias dicas nesta seo usaram o especificador de formato para exibir strings de caracteres. O comando a seguir,
por exemplo, usa p rin tf para exibir o contedo da varivel string de caractere chamada titulo:
printf("%b ", titulo);
O primeiro argumento passado ao comando printf uma string de caracteres, que pode conter um ou mais
especificadores de formato. Quando seus programas usam p rin tf para exibir somente uma string de caracteres,
como mostra o exemplo anterior, voc pode omitir a string de caracteres que contm o especificador de formato
e passar a p rin tfa string de caracteres que voc quer exibir, como mostrado aqui:
printf(titulo);
Como voc pode ver, o primeiro argumento de p rin tfno nada mais que uma string de caracteres que
contm um u mais smbolos especiais.

19 6 REMOVENDO UMA SUBSTRING DE DENTRO DE UMA STRING


Na Dica 191 voc usou a funo strstr para determinar a posio inicial de uma substring dentro de uma string.
Em muitos casos, seu programa precisa remover uma substring de dentro de uma string. Para fazer isso, voc
pode usar a funo strstr_rem, que remove a primeira ocorrncia de uma substring, como mostrado aqui:
char *strstr_rem(char *string, char *substring)
{
int i, j, k, pos = -1;

for (i = 0; string[i] && (pos == -1); i++)


for (j = i; k = 0; str[j] == substring[k]; j++, k++)
if (! substring[k + 1])
pos = i;
if (pos 1= -1) // A substring foi encontrada
{
for (k = 0; substr[k]; k++)
f
for (j = loc, i = loc + k, string[i]; j++ i++)
stringtj] = string[i];
string[i] == NULL;
>
return(string);
>
Co m p r e e n d e n d o as S t r in g s 101

S u b s t it u i n d o uma S u b s t r in g po r Outra 197


Na Dica 196 voc usou a funo strstr_rem para remover uma substring de dentro de uma string. Em muitos
casos, seus programas precisam substituir a primeira ocorrncia de uma substring por outra substring. Voc pode
fazer isso com a seguinte funo, strstr_rep, como mostrado aqui:
#include <string.h>

char *strstr_rep(char origem, char *antigo, char *novo)


{
char original = origem;
char temp[256];
int tam_antigo = strlen(antigo);
int i, j, k, posicao = -1;

for (i = 0; origem[i] && (posicao == -1); ++i)


for (j = i; k = 0; origem[j] == antigo[k]; j++, k++)
if (1 antigo[k+1])
posicao = i;
if (posicao != -1)
{
for (j = 0; j < posicao; j++)
temp[j] = origem[j];
for (i = 0; novo[i]; i++, j++)
temp[j] s novo[i];
for (k = posicao + tam_antigo; origem[k]; k++, j++)
f temp[j] = origem[k];
temp[j] = NULL;
for (i = 0; origem[i] = temp[i]; i++); // Lao NULL
>
return(original);
>

C o n v e r te n d o uma R e p r e s e n t a o N u m ric a ASCII 198


Quando seus programas trabalham com strings de caracteres, freqentemente precisam converter uma represen
tao ASCII de um valor, tal como 1.2345, ao valor int, float, double, long ou unsigned correspondente. Para lhe
ajudar a efetuar essas operaes, C fornece as funes definidas na Tabela 198.
Tabela 198 As funes que voc pode usar para converter representaes em ASCII para numrico.
Funo Propsito
a to f Converte uma representao ASCII de um valor do tipo float
atoi Converte uma representao ASCII de um valor do tipo int
atol Converte uma representao ASCII de um valor do tipo long int

Os formatos das funes detalhadas na Tabela 198 so como segue:


tinclude <stdlib.h>

double atof(char string);


int atoi(char *string);
int atol(char *string);
Se uma funo no puder converter a string de caracteres para um valor numrico, a funo retornar 0.
O programa a seguir, asc_para.c, ilustra como usar as funes ato:
#include <stdio.h>
#include <stdlib.h>

void main (void)


102 P rogram and o em C/C++ A B b l ia

{
int int_valor;
float flt_valor;
long long_valor;

int_valor = atoi("12345");
flt_valor = atof("33.45");
long_valor = atol("12BAD");
printf("int %d float %5.2f long %l\n", int_valor, flt_valor, long_valor);
}
Quando voc compilar e executar o programa asc_para.c, sua tela exibir a seguinte sada:
int 12345 float 33.45 long 12
C:\>
Observe a chamada que o programa faz a atoL Como voc pode ver, quando a funo encontra o valor
no-numrico (a letra B), a funo finaliza a converso, retornando o valor que a funo j converteu at aquele
ponto.

199 D e t e r m in a n d o S e um Ca r a c t e r e A l f a n u m r i c o
Um caractere alfanumrico uma letra ou um dgito. Em outras palavras, um caractere alfanumrico uma letra
maiscula de A at Z, uma letra minscula de a at z, ou um dgito de 0 at 9. Para ajudar seus programas a
determinar se um caractere alfanumrico, o arquivo de cabealho ctype.h contm uma macro chamada isalnum.
A macro examinar uma letra e retornar o valor 0 se o caractere no for alfanumrico, e um valor diferente de
zero para caracteres alfanumricos, como mostrado aqui:
if (isalnum(letra))
Para compreender melhor a macro isalnum, considere a seguinte implementao:
#define isalnum(c) ((toupper((c)) >= 'A' && (toupper((c )) <= 'Z' II ((c)
>= '0' && ((c) <= '9'))

200 D e t e r m in a n d o se um Ca r a c t e r e uma letra


A medida que seus programas trabalharem com caracteres dentro de strings, algumas vezes precisaro testar se
um caractere contm uma letra do alfabeto (maiscula ou minscula). Para ajudar seus programas a determinar
se um caractere uma letra do alfabeto, o arquivo de cabealho ctype.h fornece a macro isalpha. A macro examina
uma letra e retorna o valor 0 se o caractere no contm uma letra maiscula de A at Z ou minscula de a at
z. Se o caractere contm uma letra do alfabeto, ento a macro retorna um valor diferente de zero:
if (isalpha (caractere))
Para compreender melhor a macro isalpha, considere a seguinte implementao:
#define isalpha(c) (toupper((c)) >= 'A' && (toupper((c)) <= 'Z')

201 D e te rm in a n d o S e um C a r a c t e r e Contm um V a l o r
ASCII
Um valor ASCII um valor no intervalo de 0 at 127. Quando seus programas trabalham com os caracteres de
uma string, algumas vezes voc precisa determinar se um caractere contm um valor ASCII. Para ajudar seus pro
gramas a determinar um va/or ASCII, o arquivo de cabealho ctype.h contm a macro isascii, que examina uma
letra e retorna o valor 0 caso o caractere no contenha um ASCII, e um valor diferente de 0 caso o caractere con
tenha um valor ASCII, como mostrado aqui:
if (isascii (caractere))
Co m p r e e n d e n d o as S t r in g s 103

Para compreender melhor a macro isascii, considere a seguinte implementao:


#define isascii (ltr) ((unsigned) (ltr) < 128)
Como voc pode ver, a macro isascii considera um valor no intervalo de 0 at 127 como ASCII.

D e t e r m in a n d o S e um Ca r a c t e r e um Ca r a c t e r e de

Co n t r o l e 202
Um caractere de controle um valor de AA at AZ ou de Aa at Az. Aplicativos diferentes usam os caracteres de
controle de forma diferente. Por exemplo, o DOS usa o caractere Ctrl+Z para representar o fim de um arquivo.
Outros processadores de texto usam caracteres de controle para representar negrito ou itlico. Quando voc tra
balha com caracteres em uma string, algumas vezes precisa determinar se um caractere um caractere de con
trole. Para ajudar seus programas a efetuar esse teste, o arquivo de cabealho ctype.h contm a macro iscntrl, que
retorna um valor diferente de zero para um caractere de controle e 0 se a letra no for um caractere de controle,
como mostrado aqui:
if (iscntrl(caractere))

D e t e r m in a n d o S e um Ca r a c t e r e um D g it o 203
Um dgito um valor ASCII de 0 at 9. Quando voc trabalha com strings, algumas vezes precisa determinar
se um caractere um dgito. Para lhe ajudar a testar se um caractere um dgito, o arquivo de cabealho ctype.h
fornece a macro isdigit. A macro isdigit examina um caractere e retorna o valor 0 se o caractere no for um dgito,
e um valor diferente de 0 para caracteres no intervalo de 0 a 9, como mostrado aqui:
if (idigit (letra))
Para compreender melhor a macro isdigit, considere a seguinte implementao:
#define isdigit(c) ((c) >= '0' && (c) <= '9')

D e t e r m in a n d o S e um Ca r a c t e r e um Ca r a c t e r e
G r f ic o 204
Um caractere grfico um caractere imprimvel (veja isprint,), excluindo o caractere de espao (ASCII 32). Q uan
do seus programas executam operaes de sada de caractere, algumas vezes voc pode querer saber se um carac
tere um caractere grfico. Para ajudar seus programas a efetuar esse teste, o arquivo de cabealho ctype.h fornece
a macro isgraph. A macro isgraph examina um caractere e retorna o valor 0 se o caractere no for um grfico, e
um valor diferente de 0 para caracteres grficos:
if (isgraph (letra))
Para compreender melhor a macro isgraph, considere a seguinte implementao:
#define isgraph (ltr) ((ltr) >= 32) && ((ltr) <= 127)
Como voc pode ver, um caractere grfico qualquer caractere ASCII no intervalo de 33 a 127.

D e t e r m in a n d o S e um Ca r a c t e r e M a i s c u l o ou

M in s c u l o 205
A medida que seus programas forem trabalhando com caracteres dentro de uma string, algumas vezes voc pre
cisar saber se um caractere uma letra maiscula ou minscula. Para ajudar seus programas a testar a caixa das
letras, o arquivo de cabealho ctype.h fornece as macros islowere isupper. Essas macros examinam um caractere
e retornam um valor 0 para caracteres que no so minsculos (islower) ou maisculos (isupper) e um valor di
ferente de 0 em caso contrrio:
104 Pro g ra m a n d o em C/C+ + A B b lia

if (islower (caractere))

if (isupper (caractere))
Para compreender melhor as macros islower e isupper, considere as seguintes implementaes:
#define islower(c) ((c) >= 'a' && (c) <= 'z')
#define isupper(c) ((c) >= 'A' && (c) <= 'Z')

206 D e te rm in a n d o S e um C a r a c t e r e Im p rim v e l
Quando seus programas efetuam sada de caracteres, voc pode querer examinar cada caractere para garantir que
somente caracteres imprimveis sejam exibidos. Um caractere imprimvel qualquer caractere no intervalo de 32
(o espao) at 127 (o caractere Del). Para ajudar seus programas a testar se um caractere imprimvel, o arquivo
de cabealho ctype.h fornece a macro isprint. A macro isprint retorna um valor diferente de 0 para caracteres im
primveis, e um valor 0 para caracteres que no so imprimveis:
if (isprint (caractere))
Para compreender melhor a macro isprint, considere a seguinte implementao:
#define isprint (ltr) ((ltr) >= 32) ((ltr) <= 127)
Como voc pode ver, a macro isprint considera qualquer caractere ASCII no intervalo de 32 at 127 como
um caractere imprimvel.

207 D e te rm in a n d o S e um C a r a c t e r e um S i n a l de
P o n tu a o
Em um texto dentro de um livro, os sinais de pontuao incluem vrgulas, ponto-e-vrgula, ponto, sinais de in
terrogao etc. No entanto, dentro de C, um sinal de pontuao qualquer caractere grfico ASCII que no seja
alfanumrico. medida que seus programas trabalharem com caracteres em uma string, algumas vezes voc pre
cisar testar se um caractere contm um sinal de pontuao. Para ajudar seus programas a testar sinais de pon
tuao, o arquivo de cabealho ctype.h define a macro ispunct Essa macro examina um caractere e retorna um
valor diferente de 0 para um caractere que contm um sinal de pontuao e um valor 0 para um caractere que
no contm um sinal de pontuao:
if (ispunct (caractere))
Para compreender melhor a macro ispunct, considere a seguinte implementao:
#define ispunct(c) (isgraph(c)) && J isalphanum((c)))

208 D e te rm in a n d o S e um C a r a c t e r e C ontm E s p a o
em B r a n c o
O termo caracteres de espao em branco inclui os seguintes caracteres: espao, tabulao, retorno do carro, nova
linha, tabulao vertical e alimentao de formulrio. Quando seus programas efetuam sada de caracteres, algu
mas vezes voc precisa testar se um caractere contm um espao em branco. Para ajudar seus programas a testar
o espao em branco, o arquivo de cabealho ctype.h fornece a macro isspace. Essa macro examina um caractere
e retorna um valor diferente de 0 para caracteres de espao em branco, e um valor 0 para caracteres de no espao
em branco:
if (isspace (caractere))
Para compreender melhor a macro isspace, considere a seguinte implementao:
#define isspace(c) (((c) == 32) II ((c) ==9) II ((c) == 13))
Co m p r e e n d e n d o as S t r in g s 105

D e t e r m in a n d o S e um Ca r a c t e r e E um Va lo r
H e x a d e c im a l 209
Um valor hexadecimal um dgito no intervalo de 0 at 9 ou uma letra da maiscula A at F ou da minscula
a at f. Quando seus programas trabalham com caracteres em uma string, algumas vezes voc precisa determinar
se um caractere contm um dgito hexadecimal. Para ajudar seus programas a testar se um dgito hexadecimal,
o arquivo de cabealho ctype.h define a macro isxdigit Essa macro examina um caractere e retorna um valor di
ferente de 0 se o caractere for um dgito hexadecimal, e um valor 0 se o caractere no for hexadecimal.
if (isxdigit (caractere))
Para compreender melhor a macro ixdigit, considere a seguinte implementao:
#define isxdigit(c) (isnum((c)) il (toupper((c )) >= 'A' && toupper((c)) <=
' F'))

Co n v e r t e n d o um Ca r a c t e r e para Ma i s c u l a 210
medida que voc trabalha com strings de caracteres, uma operao comum que seus programas precisam exe
cutar converter letras minsculas para maisculas. Quando voc quiser converter a caixa das letras, seus pro
gramas tm duas escolhas. Eles podem usar a macro _toupper, que est definida no arquivo de cabealho ctype.h,
ou podem usar a funo da biblioteca de execuo toupper. Os formatos da macro e da funo so como seguem:
#include <ctype.h>

int _tdupper (int caractere);


int toupper (int caractere);
Embora tanto a macro quanto a funo convertam um caractere para maiscula, elas trabalham de forma
diferente. A macro _toupper no testa se o caractere que est convertendo minsculo. Se voc "chamar a macro
com um caractere que no minsculo, ela causar um erro. Por outro lado, a funo toupper somente converte
letras minsculas, e deixa todos os outros caracteres inalterados. Se voc tiver certeza de que o caractere contm
uma letra minscula, use a macro _toupper, essa macro executa mais rapidamente que a funo. No entanto, se
voc no tiver certeza se o caractere minsculo, use a funo toupper. O programa a seguir, toupper. c, ilustra
o uso de _touppere toupper, bem como os erros que podem ocorrer quando voc usa a macro com caracteres que
no so minsculos:
#include <stdio.h>
#include <ctype.h>

void main(void)
{
char string[]= "Bblia do Programador C/C++, do Jamsa!";
int i;

for (i = 0; stringti]; i++)


putchar(toupper(string[i]));
putchar('\n');
for (i = 0; string[i]; i++)
putchar(_toupper(string[i]));
putchar('\n');

Quando voc compilar e executar este programa, sua tela exibir a primeira string (usando toupper) nas
letras maisculas corretas. No entanto, a segunda string conter caracteres no padro (smbolos, grficos etc.),
pois _toupper tenta converter caracteres maisculos como faz com os caracteres minsculos.
106 Programando em C/C++ A Bblia

21 1 Co n v e r t e n d o um Ca r a c t e r e para M in s c u l o
medida que voc trabalha com strings de caracteres, uma operao comum que seus programas precisam exe
cutar converter um caractere de maisculo para minsculo. Quando voc quiser converter a caixa, seus pro
gramas tm duas escolhas. Podem usar a macro _tolower, que est definida no arquivo de cabealho ctype.h, ou
podem usar a funo da biblioteca de execuo tolower. Os formatos da macro e da funo so estes:
#include <ctype.h>

int _tolower (int caractere);


int tolower (int caractere);
Embora tanto a macro quanto a funo convertam um caractere para minsculo, elas trabalham de forma
diferente. A macro _tobwer no testa se o caractere que est convertendo maisculo. Se voc chamar a macro
com um caractere que no maisculo, ela causar um erro. Por outro lado, a funo tolower somente converte
letras maisculas, e deixa todos os outros caracteres inalterados. Se voc tiver certeza de que o caractere contm
uma letra maiscula, use a macro _tolower, essa macro mais rpida que a funo. No entanto, se voc no tiver
certeza se o caractere maisculo, use a funo tolower. O programa a seguir, tolower.c, ilustra o uso de _tolower
e tolower, bem como os erros que podem ocorrer quando voc usa a macro com caracteres que no so mais
culos:
#include <stdio.h>
#include <ctype.h>

void main(void)
{
char. string[] = "Bblia do Programador C/C++, do Jamsa!";
int i;

for (i = 0; string[i]; i++)


putchar(tolower(string[i]));
putchar('\n');
for (i = 0; string[i]; i++)
putchar(_tolower(string[i]));
putchar('\n');
>
Quando voc compilar e executar este programa, sua tela exibir a primeira string (usando tolower) em le
tras minsculas corretas. No entanto, a segunda string conter caracteres no-padro (smbolos, grficos e assim
por diante), pois _toupper tenta converter caracteres maisculos como faz com os caracteres minsculos.

212 T r a b a lh a n d o com C a r a c t e r e s ASCII


Quando voc trabalha com strings de caracteres e diferentes funes de caracteres, algumas vezes precisa garantir
que um caractere seja um caractere ASCII vlido; isto , que o valor est no intervalo de 0 at 127. Para garantir
que um caractere um caractere ASCII vlido, voc pode usar a macro toascii, que est definida no arquivo de
cabealho ctype.h, como mostrado aqui:
#include <ctype.h>

int toascii (int caractere)


Para compreender melhor a macro toascii, considere a seguinte implementao:
#define toascii (caractere) ((caractere) & 0x7F)
Para melhorar o desempenho, a macro toascii efetua uma operao E bit a bit que zera o bit mais signi
ficativo do byte de valor do caractere. A operao E bit a bit ajuda a macro a garantir que o valor est no intervalo
de 0-127.
Co m p r e e n d e n d o as S t r in g s 107

E s c r e v e n d o S a d a F o r m a t a d a em uma V a r i v e l S t r in g 213
Como voc sabe, a funo p r in tf lhe permite escrever sada formatada na tela. Dependendo dos requisitos do seu
programa, algumas vezes voc precisa trabalhar com uma string de caracteres que contm sada formatada. Por
exemplo, digamos que seus funcionrios tenham um nmero funcional de 5 dgitos e um identificador de 3 le
tras para a regio (tal como Rec, para Recife). Assuma o fato de voc armazenar informaes sobre cada funcio
nrio em um arquivo nomeado com uma combinao desses dois valores (tal como REC12345). A funo sprintf
lhe permite escrever sada formatada em uma string de caracteres. O formato da funo sprintf :
#include <stdio.h>

int sprintf (char string, const char *formato [.argumentos...]);


O programa a seguir, sprintf.c, usa a funo sprintf para criar um nome de arquivo de funcionrios de 8
caracteres:
#include <stdio.h>

void main(void)
{
int func_numero = 12345;
char regio[] = "REC";
char nomearq[64];

sprintf(nomearq, "%B%", regio, func_numero);


printf("Nome do arquivo do func: %s\n", nomearq);
>

Len d o a E ntrada de uma S t r in g de Ca r a c t e r e s 214


Como voc aprendeu, a funo scanflhe permite ler a entrada formatada de stdin. Dependendo do processamen
to do seu programa, algumas vezes uma string de caracteres conter campos que voc quer atribuir a variveis
especficas. A funo sscanfpermite que seus programas leiam valores de uma string e atribuam os valores a va
riveis especficas. O formato da funo sscanf como segue:
#include <stdio.h>

int sscanf (const char *string, const char *formato [,argumentos]);


Os argumentos que seu programa passa para a funo sscanfprecisam ser ponteiros para endereos de va
riveis. Se tfvw/atribuir campos com sucesso, ela retornar o nmero de campos que atribuiu. Se sscanfho atri
buir campos, ento retornar 0 ou EO F c a s o tenha encontrado o final da string. O programa a seguir, sscanfc,
ilustra a funo sscanf.
#include <stdio.h>

void main(void)
{
int idade;
float salario;
char string[] = "33 2500.00";

sscanf (string, "%d %f\n", cidade, &salario);


printf("Idade; %d Salrio %f\n", idade, salario);
}
108 P rogram and o em C/C++ A B b l ia

215 "T o k e n iz a n d o " as S t r in g s para P o u par Espa o


Tokenizarstrings o processo de usar um valor nico para representar uma string. Por exemplo, assuma que voc
tenha um programa que trabalhe com um grande nmero de strings de caracteres. Digamos que o programa con
tenha um banco de dados das contas dos seus clientes por cidade e por estado. Dependendo de como o programa
efetua seu processamento, voc poderia terminar com muitos testes diferentes, como ilustra o programa a seguir:
if (streql (cidade, "Recife))
// Comando
else if (streql (cidade, "Salvador"))
// Comando
else if (streql'(cidade, "Rio"))
// Comando
Dentro de cada uma das funes do seu programa que executa teste repetitivo else if, o programa consome
uma considervel quantidade de espao para as constantes strings, bem como uma quantidade considervel de
tempo realizando comparaes de strings. Em vez de usar chamadas de strings repetitivas, voc pode criar uma
funo chamada tokeniza_strin$ que retorna um token (um smbolo) distinto para cada string. Dentro da funo
de exemplo, o teste de seu programa se tornar o seguinte:
int cidade_token;

cidade_token = tokeniza_string(cidade);
if (cidade_token == Recife_token)
// Comando
else if (cidade_token == Salvador_token)
// Comando
else if (cidade_token == Rio_token)
// Comando
Usar tokens desse modo ajuda a eliminar a quantidade de espao de dados que as consoantes da string con
somem. Eliminar as comparaes de string tambm aumenta o desempenho do programa.

21 6 I n ic ia l iz a n d o uma S t r in g
Na seo Matrizes, Ponteiros e Estruturas mais frente, voc aprender como atribuir valores s matrizes quando
seu programa declarar a matriz. C representa as strings de caracteres como uma matriz de bytes. Quando voc
declara uma string, geralmente especifica um valor inicial, como mostrado aqui:
char titulo[] = "Bblia do Programador C/C++, do Jamsa!";
char secao[64] = "Strings";
N a string titulo, o compilador C alocar uma matriz grande o suficiente para conter os caracteres especi
ficados (mais o caractere N U L L ). Como a string Bblia do Programador C/C++, do Jamsa! tem 38 caracteres
de tamanho, a string titulo pode conter 38 caracteres imprimveis mais o caractere NULL. Se voc, mais tarde,
atribuir mais de 39 caracteres string, sobrescrever a memria que armazena o valor de outra varivel. Na string
secao, o compilador alocar uma string que pode armazenar 64 caracteres. O compilador atribuir aos primeiros
sete bytes da string as letras na palavra Strings, e ao oitavo byte o caractere N U L L O compilador normalmente
inicializa os 56 caracteres restantes como NULL.

217 Co m p r e e n d e n d o as Fu n es
A maioria dos programas apresentados at agora neste livro usa somente a funo main. medida que seus pro
gramas vo se tornando maiores e mais complexos, voc pode simplificar seu trabalho e melhorar a clareza do
programa dividindo o programa em partes menores, chamadas funes. Por exemplo, assuma que voc esteja
criando um programa de contabilidade. Voc poderia ter uma funo que efetuasse as operaes normais de um
contador, uma funo diferente para as contas a pagar, uma terceira para as contas a receber e uma quarta para
gerar um balano. Se voc colocasse todos os comandos do programa dentro de main, seu programa ficaria muito
grande, e seria difcil de entender. medida que o tamanho e a complexidade do programa aumentam, aumenta
Fu n e s 109

tambm a possibilidade de erros. Se voc dividir o programa em blocos menores e mais facilmente gerenciveis,
poder evitar os erros. Uma funo uma coleo nomeada de comandos que efetuam uma tarefa especfica. Por
exemplo, a funo a seguir, oi_j)essoal, usa p r in tf para. exibir uma mensagem:
void oi_pessoal (void)
{
printf("Oi pessoal!\n");
}
A palavra-chave void diz a C que a funo no retorna um valor. Em muitos casos, suas funes usaro return
para retornar o resultado de um clculo para a funo chamadora. Se a funo no usa return para retornar um
resultado, voc deve preceder o nome da funo com void O void que aparece nos parnteses diz a C que a fun
o no usa parmetros. Um parmetro a informao que o programa passa para a funo. Por exemplo, quan
do seus programas chamam printf, as informaes que voc especifica dentro dos parnteses so parmetros.
Quando uma funo no usa parmetros, voc deve colocar a palavra void dentro dos parnteses. Para usar uma
funo, voc simplesmente especifica o nome da funo seguido por parnteses, exatamente como usa printf. Os
programadores referenciam o uso de uma funo como uma chamada da funo. O programa a seguir,
usa_func.c, usa a funo oi_pessoal:
#include <stdio.h>

void oi_pessoal(void)
{
printf("Oi pessoal!\n");
>
void main(void)
{
oi_pessoal()j
}
Ao executar esse programa, a funo main executada primeiro. Como voc pode ver, o nico comando
em main a chamada da funo oi_pessoaL Quando C encontra a chamada da funo, imediatamente transfere
a execuo do programa para a funo, iniciando a execuo do programa com o primeiro comando na funo.
Depois que o ltimo comando na funo termina, C transfere a execuo para o comando que segue imediata
mente a chainada da funo. Para compreender melhor esse processo, mude a funo main dentro de usafunc.c
como mostrado aqui:
void main(void)
<
printf("Prestes a chamar a funo\n");
oi_pessoal() ;
printf("Voltei da chamada da funo\n");
>
Quando voc compilar e executar o programa usafunc.c, sua tela exibir o seguinte:
Prestes a chamar a funo
Oi pessoal!
Voltei da chamada da funo
C:\>

Us a n d o V a r i v e is De n t r o das Fu n es 218
medida que voc cria funes teis, ver que muitas funes requerem que as variveis gerem resultados va
liosos. Para usar uma varivel dentro de uma funo, voc precisa primeiro declarar a varivel, exatamente como
faz em main. Por exemplo, o programa a seguir, tres_ois.c, chama a funo tres_olas.c, que usa a varivel contador
em um lao for para exibir uma mensagem trs vezes:
#include <stdio.h>
110 P rog ram and o em C/C++ A B b l ia

void tres_olas(void)
{
int contador; II Varivel

for (contador = 1; contador <= 3; contador++)


printf("Ol pessoal!\n");
>

void main(void)
{
tres_olas();
>
Quando voc declara variveis dentro de uma funo, os nomes usados para essas variveis so exclusivos
para a funo. Portanto, se seu programa usa 10 funes diferentes e cada funo usa uma varivel chamada con
tador, C considera a varivel de cada funo como distinta. Se sua funo requer muitas variveis, voc dever
declarar as variveis no incio da funo, exatamente como faria dentro de main.

219 Co m p r e e n d e n d o m a in Co m o uma Funo



Quando voc cria um programa C, usa o nome da funo main para determinar o primeiro comando que o pro
grama executar. N a verdade, main uma funo, de modo que, caso tenha perguntas sobre os tipos de opera
es que voc pode executar dentro de suas funes, a regra bem simples: Tudo o que voc pode fazer em main,
voc pode fazer em uma funo. Exatamente como voc pode declarar variveis em main, tambm pode declarar
variveis nas suas funes. Tambm possvel usar construes tais como if, while e for em suas funes. Final
mente, uma funo pode chamar (usar) outra. Por exemplo, o programa a seguir, chama_2.c, usa duas funes.
Quando o programa inicia, main chama a funo tres_olas, que, por sua vez, chama a funo oi_pessoal trs vezes
para exibir mensagens na sua tela, como mostrado aqui:
#include <stdio.h>

void ola_pesaoal(void)
{
printf("Ola, pessoalI\n);
>

void tres_olas(void)
{
int contador;

for (contador = 1; contador < = 3; contador++)


ola_pessoal();
>

void main(void)
{
tres_olas();
>

220 In t r o d u o aos Pa r m et r o s
Um parmetro um valor passado a uma funo. A maioria dos programas apresentados neste livro passou pa
rmetros para a funo printf, como mostrado aqui:
printf("O valor %d\n", result);
medida que voc for usando funes regularmente, poder passar parmetros para uma funo para me
lhorar a utilidade da funo. Por exemplo, considere a seguinte construo da funo tres_olas, que chama a fun
o oi_pessoal trs vezes:
void tres_olas(void)
F u n es 1 11

<
int contador;

for (contador 1; contador <= 3; contador++)


oi_pessoal();
>
Uma funo mais til lhe permite especificar, como um parmetro, o nmero de vezes que voc quer que
o programa exiba a mensagem. Para usar um parmetro, sua funo precisa especificar o nome e o tipo do pa
rmetro, como mostrado aqui:
void ola_conta(int msg_conta)
Neste caso, a funo ola_conta suporta um parmetro do tipo int chamado msg_conta. Quando outra fun
o, tal como main, quiser usar ola_conta, a funo precisa especificar o valor que C atribui para o parmetro
msg_conta:
ola_conta(2); // Exibe a mensagem duas vezes
ola_conta(100); // Exibe a mensagem 100 vezes
ola_conta(1); // Exibe a mensagem uma vez
O programa a seguir, usaparam.c, ilustra como voc poderia usar uma funo com um parmetro:
#include <stdio.h>

void oi_pessoal(void)

printf("Ola, pessoalI\n");
> ,
void ola_conta(int msg_conta)
{
int contador;

for (contador = 1; contador <= msg_conta; contador++)


oi_pessoal();
}

void main(void)
{
printf("Exibe a msg duas vezes\n");
ola_conta(2);
printf("Exibe a msg cinco vezes\n);
ola_conta(5);
}
Como voc pode ver, em main, a chamada da funo para ola_conta inclui o valor que C atribuir ao pa
rmetro msg_conta.
Nota: Ao passar um parmetro para uma funo, o tipo de valor que voc passar para o parmetro (tal como int,
float, char etc.) precisa corresponder ao tipo do parmetro. Dependendo do seu compilador, ele poder detectar incom
patibilidades nos tipos. Se seu compilador no detectar as incompatibilidades nos tipos dos parmetros, podero apa
recer erros que sero muito difceis de detectar e de corrigir.

Usan d o Pa r m et r o s m l t ip l o s 221
Como voc aprendeu, um parmetro um valor que voc passa para uma funo. Em geral, voc pode passar
um nmero irrestrito de parmetros para uma funo. No entanto, as pesquisas mostram que, quando o nmero
de parmetros excede de sete, a funo torna-se mais difcil para compreender e usar corretamente, ficando, por
tanto, mais susceptvel a erros. Quando sua funo usa mais de um parmetro, voc precisa especificar o tipo e
o nome de cada parmetro e separar os parmetros por vrgulas, como mostrado aqui:
112 Pro g ra m a n d o em C/C++ A B b lia

void uma_funcao(int idade, float sal, int num_cargo)


{
// Comandos da funo
>
Quando seu programa quiser chamar a funo, voc precisar especificar valores para cada parmetro,
como mostrado aqui:
uma_funcao(33, 40000.00, 534);
C, por sua vez, atribuir os valores para os parmetros, como mostrado na Figura 221:

Figura 221 M apeando os valores dos parm etros.

222 C om preend endo a s d e c la r a e s de P a r m e tro s em


P ro g ra m a s C M a is A n tig o s
Quando voc cria uma funo que usa parmetros, normalmente especifica o tipo e o nome de cada parmetro,
separados por vrgulas, dentro do cabealho da funo, como mostrado aqui:
void uma_funcao(int idade, float sal, int num_cargo)
{
// Comandos da funo
>
Se voc trabalhar com programas C mais antigos, ver que os programadores declaravam os parmetros assim:
void uma_funcao(idade, sal, num_cargo)
int idade;
float sal;
int num_cargo;
{
// Comandos da funo
>
Se voc encontrar essas declaraes de parmetros, dever compreender que, embora o formato da decla
rao seja ligeiramente diferente, o propsito permanece o mesmo especificar o tipo e o nome do parmetro.
Caso voc se sinta tentado a atualizar o formato da funo, certifique-se de que seu compilador aceita totalmente
o novo formato. Alm disso, lembre-se de que, quanto mais modificaes voc fizer no seu programa, maiores
sero suas chances de introduzir um erro. Como regra geral, Se est funcionando, no conserte!"

223 R e to r n a n d o um V a lo r de um a F u n o
A medida que suas funes se tornarem mais complexas, normalmente realizaro um clculo e retornaro um re
sultado. Para fornecer um resultado ao chamador, uma funo precisar usar o comando return, que voc im
plementar como mostrado aqui:
return (resultado);
O tipo de valor que a funo retorna (int, float, char etc.) determina o tipo da funo. Por exemplo, se uma fun
o retorna um valor do tipo int, voc precisa preceder o nome da funo com o nome do tipo, como mostrado aqui:
int uma_funcao(int valor)
Fu n e s 113


// Comandos da funo
}
A funo a seguir, i_cubo, retorna o cubo do valor inteiro que o programa especifica como seu parmetro.
Por exemplo, se o chamador passar o valor 5 para a funo, i_cubo retornar o valor 5 * 5 * 5, ou 125:
int i_cubo (int valor)
{
return (valor *valor* valor);
{
Como voc pode ver, a funo usa o comando retum para retornar o resultado do clculo ao chamador.
O cdigo dentro da funo de chamada pode atribuir o resultado da funo chamada (tambm conhecido como
valor de retorno) a uma varivel, ou o cdigo pode usar o valor de retorno dentro de uma terceira funo, tal
como printf, como mostrado aqui:
result * i_cubo(5);

printf("O cubo de 5 %d\n", i_cubo(5));


O programa a seguir, i_cubo.c, usa a funo i_cubo para determinar vrios valores diferentes ao cubo:
#include <stdio.h>

int i_cubo(int valor)


{
return(valor * valor * valor);
}

void main(void)
{
printf("O cubo de 3 %\n, i_cubo(3));
printf(O cubo de 5 %d\n", i_cubo(5));
printf("O cubo de 7 %d\n", i_cubo(7));
>
Os valores que voc passa para uma funo precisam corresponder aos tipos de parmetros contidos dentro
da declarao dessa funo. Por exemplo, se voc quiser determinar o cubo de um valor em ponto flutuante, crie uma
segunda funo chamada f_cubo, como mostrado aqui (observe que o valor de retorno tambm do tipo float):
float f_cubo(float valor)
{
r e t u m (valor * valor * valor);
}

Co m p r e e n d e n d o o Co m a n d o return 224
Como voc aprendeu, para uma funo fornecer um resultado ao chamador, ela precisar usar o comando retum.
Quando encontra um comando retum em uma funo, C finaliza imediatamente a execuo da funo e retorna
o valor especificado para o chamador. O programa no executa quaisquer outros comandos dentro da funo
aps o comando retum. Em vez disso, ele continua a execuo na funo chamadora.
medida que voc examina outros programas C, pode encontrar funes que contm mltiplos comandos
retum, cada um dos quais retornando um valor para uma condio especfica. Por exemplo, considere a funo
compara_valores, mostrada aqui:
int compara_valores(int primeiro, int segundo)
{
if (primeiro = = segundo)
r e t u m (0);
else if (primeiro > segundo)
return(1);
114 P rogramando em C/C+ + A B b l i a
Fu n e s 115

void main(void)
{
printf("O cubo de 3 %d\n", i_cubo(3));
printf("O cubo de 3.7 %f\n", f_cubo(3.7));
}

int i_cubo(int valor)


{
return(valor * valor * valor);
}

float f_cubo(float valor)


{
return(valor * valor * valor);
}
Se voc examinar os arquivos de cabealho .h, tais como stdio.h, ver que eles contm muitos prottipos
de funes.

C o m p re e n d e n d o a B ib l io t e c a de E x e c u o 226
Ao ir escrevendo suas prprias funes, freqentemente voc ver que uma funo que criou para um programa
atende s necessidades de um segundo programa. A capacidade de reutilizar as funes em mais de um programa
pode poupar um tempo considervel de programao e de teste. N a seo Ferramentas da Programao, mais
frente, voc aprender a colocar suas funes comumente usadas dentro de uma biblioteca para torn-las mais
fceis de usar em mltiplos programas. No entanto, por ora, voc pode precisar recortar e colar os comandos da
funo de um arquivo de cdigo-fonte em outro.
Antes de gastar um tempo enorme desenvolvendo uma ampla variedade de funes de propsito geral, no
deixe de examinar as funes que seu compilador fornece. Muitos compiladores referenciam essas funes inter
nas como biblioteca de execuo. A maioria dos compiladores fornece centenas de funes de biblioteca de exe
cuo com propsitos que vo de abertura e trabalho com arquivos para acessar informaes do disco ou de
diretrio para determinar o tamanho de uma string de caracteres. As duas ou trs horas que voc gastar para
ler a documentao da biblioteca de execuo pouparo muitas horas de programao que, de outra forma, voc
gastaria reinventando a roda.

C o m p re e n d e n d o o s P a r m e t r o s F o rm a is e R e a is 227
A medida que voc for lendo diferentes livros sobre C, poder encontrar os termos parmetros formais e reais.
Em resumo, parmetros formais so os nomes de parmetros que aparecem na definio da funo. Por exemplo,
os nomes idade, salario e num_cargo so os parmetros normais para a funo info_cargo, como mostrado aqui:
void info_cargo(int idade, float salario, int num_cargo)
{
// Comandos da funo
}
Quando uma funo chama outra funo, os valores que a funo chamadora passa so os parmetros reais.
N o caso da chamada da funo a seguir, os valores 30, 4200.00 e 321 so os parmetros reais:
info_cargo(30, 4200.00, 321);
Os parmetros reais que voc passa para uma funo podem ser valores constantes ou variveis. O tipo do
valor ou da varivel precisa corresponder ao do parmetro formal. Por exemplo, o fragmento de cdigo a seguir
ilustra como usar variveis como parmetros reais:
int idade_trab = 30;
float salario_trab = 4200.00;
int num_cargo = 321;

info_cargo(idade_trab, salario_trab, num_cargo);


116 P rogramando em /C++ A B b l ia

Quando voc chama uma funo com variveis como os parmetros reais, os nomes de varivel usados para
os parmetros reais no tm relacionamento com os nomes dos parmetros formais. Em vez disso, C preocupa-se
somente com os valores que as variveis contm.

228 S o lu c io n a n d o o s C o n f lit o s n o s Nom es


Como voc aprendeu, a maioria dos compiladores C fornece uma extensa biblioteca de funes que voc pode
chamar para efetuar tarefas especficas. Por exemplo, para obter o valor absoluto de uma expresso inteira, voc
pode usar a funo abs. Da mesma forma, para copiar o contedo de uma string em outra, voc pode usar a fun
o strcpy. Ao criar suas prprias funes, algumas vezes uma funo que voc define ter o mesmo nome que
uma funo da biblioteca de execuo. Por exemplo o programa a seguir, mistrcpy.c, cria e usa uma funo cha
mada strcpy:

Quando o nome de uma funo que voc declara dentro de seu programa est em conflito com uma fun
o da biblioteca de execuo, C usa a funo do seu programa, no a funo da biblioteca de execuo.

229 F u n e s Q u e No R e to rn a m in t
Muitas funes vistas anteriormente retornaram valores do tipo int. Quando sua funo no retorna um valor
do tipo int (em vez disso, ela pode retornar float, double, char etc.), voc precisa informar ao compilador o tipo
de retorno da funo. O programa a seguir, exib_med.c, usa a funo valor_medio para determinar a mdia de
trs valores do tipo int. A funo retorna a mdia usando um valor do tipo float:
#include <stdio.h>

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


{
return ((a + b + c) / 3.0);
>

void main(void)
{
printf("A mdia de 100, 133 e 155 %f\n", valor_medio(100, 133, 155));
>
Como voc pode ver, o cabealho da funo especifica o tipo de retorno da funo:
float valor_medio(int a, int b, int c)
Nota: Se voc no especificar um tipo de retomo da juno, o compilador C assumir que a juno retoma o tipo int.
Fu n e s 117

COMPREENDENDO AS VARIVEIS LOCAIS 230


C lhe permite declarar variveis dentro de suas funes. Essas variveis so chamadas variveis locais, pois seus
nomes e valores somente tm significado dentro da funo que contm a declarao da varivel. O programa a
seguir, localerr.c, ilustra o conceito de uma varivel local. A funo valores_locais declara trs variveis, a, b e c,
e atribui s variveis os valores 1, 2 e 3, respectivamente. A funo main tenta imprimir o valor de cada varivel.
No entanto, como os nomes dos valores so locais funo valoresjlocais, o compilador gera erros, dizendo que
os smbolos a, b e c esto indefinidos.
tin c lu d e < s td io .h )

v o id v a lo r e s _ lo c a is ( v o id )
{
i n t a = 1, b = 2, c = 3;

p r i n t f ( " a c o n t m %d b c o n t m % c co n t m % d \ n , a , b, c);

v o i d m a in ( v o id )
{
p r i n t f ( " a c o n t m %d b c o n t m %d c c o n t m % d \ n " , a , b , c ) ;
}

Co m o as Fu n es Usam a P il h a 231
A seo Gerenciamento da Memria no Windows, mais frente, descreve a pilha, que os programas usam para
armazenaf informaes temporariamente. O propsito principal da pilha oferecer suporte para as chamadas das
funes. Quando seu programa chama uma funo, C coloca o endereo da instruo que segue a chamada da
funo (chamado endereo de retomo) na pilha. Em seguida, C coloca os parmetros da funo, da direita para
a esquerda, na pilha. Finalmente, se a funo declara variveis locais, C aloca espao na pilha, que a funo pode,
ento, usar para guardar o valor da varivel. A Figura 231 mostra como C usa a pilha para uma nica chamada
de funo.

Figura 231 C usa a pilha para a chamada de uma funo.

Quando a funo termina, C descarta o espao da pilha que continha as variveis locais e os parmetros.
Em seguida, C usa o valor de retorno para determinar a instruo que o programa executa em seguida. C remove
o valor de retorno da pilha e coloca o endereo no registrador IP (ponteiro da instruo).

Co m p r e e n d e n d o a S o brec arg a da Funo 232


Como voc aprendeu na Dica 231, quando seu programa usa uma funo, C armazena o endereo de retorno,
os parmetros e as variveis locais na pilha. Quando a funo termina, C descarta o espao da pilha que continha
as variveis locais e parmetros, e, depois, usa o valor de retorno para retornar a execuo do programa para a
posio correta.
118 Programando em C/C + + A b b l ia

Embora o uso da pilha de C seja poderoso porque permite que o programa chame e passe informaes para
as funes, C tambm consome tempo de processamento. Os programadores chamam a quantidade de tempo
que o computador requer para colocar e retirar informaes da pilha de sobrecarga da funo. Para compreender
melhor o impacto da sobrecarga da funo no desempenho do seu programa, considere o programa a seguir, sobrecar.c.
O programa primeiro usa um lao para somar os valores de 1 a 100.000. Em seguida, o programa repete um
lao novamente, mas usa uma funo para somar os valores, como mostrado aqui:
#include <stdio.h>
tinclude <time.h>

float soma(long int a, float b)


{
float result;

result = a + b;
return(result);
>

void main(void)
{
long int i;
float result = 0;
time_t hora_inicio, hora_parada;

printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result += i;
time(&hora_parada);
printf("Usando lao % segundos\n", hora_parada -hora_inicio);
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result = soma(i, result);
time(&hora_parada);
printf("Usando funo % segundos\n", hora_parada -hora_inicio);
}
N a maioriaMos sistemas, os clculos baseados em funes podem requerer quase o dobro do tempo de pro
cessamento. Portanto, quando voc usar funes dentro de seus programas, precisar considerar os benefcios que
elas oferecem (tais como facilidade de uso, reutilizao de uma funo existente, reduo de teste, facilidade de
compreenso, e assim por diante) versus a sobrecarga no desempenho que introduzem.

233 Co m p r e e n d e n d o O n d e C Co l o c a as V a r i v e is l o c a is
Como foi visto, C lhe permite declarar variveis dentro de suas funes. Essas variveis so locais funo, o que
significa que somente a funo na qual voc declarou as variveis conhece seus valores e existncia. A seguinte
funo, usa_abc, declara trs variveis locais chamadas a, b e c:
void usa_abc(void)
{
int a, b, c;

a = 3;
b = a + 1;
c = a + b;
printf("a contm %d b contm % c contm %d\n", a,b,c);
}
Fu n es 119

Toda vez que seu programa chama a funo, C aloca espao na pilha para armazenar as variveis locais a,
be c. Quando a funo termina, C descarta o espao anteriormente alocado na pilha e os valores que as variveis locais
continham. Mesmo que sua funo declare muitas variveis locais, C armazena o valor de cada varivel na pilha.

D e c la r a n d o V a r i v e is G lo b a is 234
Na Dica 218 voc aprendeu que as variveis locais so variveis definidas dentro de uma funo cujos nomes e
existncia so conhecidos somente funo. Alm das variveis locais, C tambm permite que seus programas
usem variveis globais, cujos nomes, valores e existncia so conhecidos em todo o seu programa. Em outras pa
lavras, todos os programas C podem usar variveis globais. O programa a seguir, global, c, ilustra o uso de trs
variveis globais, a, b e c:
#include <stdio.h>
int a = 1, b = 2, c = 3; II Variveis globais
void valores_globais(void)
{
printf("a contm %d b contm %d c contm %d\n", a, b, c);
>

void main(void)
{
valoreB_globais();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
Quando voc compila e executa este programa, as funes valores_globais e main exibem os valores da va
rivel global. Observe que voc declara as variveis fora de todas as funes. Ao declarar variveis globais deste
modo, todas as funes do seu programa podem usar e alterar os valores da varivel global simplesmente refe
renciando o nome da varivel global. Embora as variveis globais possam parecer convenientes, o uso incorreto
delas pode causar erros que so difceis de depurar, como voc aprender na dica a seguir.

E v it e U s a r V a r i v e is G lo b a is 235
Na dica anterior vimos como declarar variveis globais, que seu programa conhece em todas as suas funes.
primeira vista, usar variveis globais parece simplificar a programao porque elimina a necessidade de parme
tros de funes e, mais importante, a necessidade de compreender a chamada por valor e a chamada por referncia.
No entanto, infelizmente, as variveis globais com freqncia criam mais erros do que corrigem. Como seu c
digo pode mudar o valor de uma varivel global em virtualmente qualquer ponto dentro do seu programa,
muito difcil para outro programador que esteja lendo seu programa encontrar cada local no programa onde a
varivel global alterada. Portanto, outros programadores podem fazer mudanas no seu programa sem com
preender totalmente o efeito que a modificao tem em uma varivel global. Como regra, as funes somente
devem modificar aquelas variveis passadas para as funes como parmetros. Isso permite que os programadores
estudem os prottipos da funo para determinar rapidamente quais variveis uma funo altera.

S o lu c io n a n d o o s C o n f lit o s de N om es de V a r i v e is
L o c a is e G lo b a is 236
Como voc aprendeu, as variveis locais so variveis que voc declara dentro de uma funo cujos nomes so
conhecidos somente para essa funo. Por outro lado, quando voc declara variveis globais fora de todas as fun
es, toda funo em todo o seu programa conhecer os nomes delas. Se seu programa usa variveis globais, al
gumas vezes o nome de uma varivel global o mesmo que aquele de uma varivel local que seu programa
declara dentro de uma funo. Por exemplo, o programa a seguir, conflito, c, usa as variveis globais a, b e c. A
funo conflito_a usa uma varivel local chamada a e as variveis globais b e c:
120 Programando em C/C++ A Bblia

Quando voc compilar e executar o programa conflito, c, sua tela exibir o seguinte:
a contm 100 b contm 2 c contm 3
a contm 1 b contm 2 c contm 3
C:\>
Quando nomes de variveis globais e nomes de variveis locais esto em conflito, C sempre usar a varivel lo
cal. Como voc pode ver, as alteraes que a funo conflito_a fez na varivel a somente aparecem dentro da funo.
Nota: Embora o propsito deste programa seja ilustrar como C soluciona os conflitos de nomes, ele tambm ilustra
a confuso que pode ocorrer quando voc usa variveis globais. Neste caso, um programador que esteja lendo seu cdigo
precisa prestar muita ateno para determinar que a funo no altere a varivel global a, mas, sim, uma varivel lo
cal. Como a funo combina o uso de variveis globais e locais, o cdigo pode tomar-se difcil de entender.

237 D e fin in d o M e lh o r o E s co p o de uma V a r i v e l G lo b a l


Vimos na Dica 234 que uma varivel global uma varivel que todas as funes no seu programa conhecem.
Dependendo de onde voc define uma varivel global, possvel controlar quais funes so na realidade capazes
de referenciar a varivel. Em outras palavras, voc pode controlar o escopo da varivel global. Quando seu pro
grama declara uma varivel global, quaisquer funes que seguem a declarao da varivel podem referenciar essa
varivel, at o final do arquivo-fonte. As funes que tm definies que aparecem antes da definio da varivel
global no podem acessar a varivel global. Como um exemplo, considere o programa a seguir, escopogl.c, que
define a varivel global titulo:
tinclude <stdio.h>

void titulo_desconhecido(void)
{
printf("O ttulo do livro %s\n", titulo);
>

char titulo[]="Bblia do Programador C/C++, do JamBa!";

void main(void)
{
printf("Titulo: %s\n", titulo);
)
Fu n e s 121

Como vocc pode ver, a funo titulo_desconhecido tentar exibir a varivel titulo. No entanto, como a de
clarao da varivel global ocorre aps a definio da funo, a varivel global desconhecida dentro da funo.
Quando voc tentar compilar este programa, seu compilador gerar um erro. Para corrigir o erro, coloque a de
clarao da varivel global antes da funo.

C o m p re e n d e n d o a Cham ada p o r V a l o r 238


J sabemos que seus programas passam informaes para as funes usando parmetros. Quando voc passa um
parmetro para uma funo, C usa uma tcnica conhecida como chamada por valor para fornecer funo uma
cpia dos valores dos parmetros. Usando a chamada por valor, quaisquer modificaes que a funo fizer nos
parmetros existem somente dentro da prpria funo. Quando a funo termina, o valor das variveis que a fun
o chamadora passou para a funo no modificado dentro da funo chamadora. Por exemplo, o programa
a seguir, naomuda.c, passa trs parmetros (as variveis a, b e c) para a funo exibe_e_altera. A funo, por sua
vez, exibir os valores, somar 100 aos valores e depois exibir o resultado. Quando a funo terminar, o pro
grama exibir os valores das variveis. Como C usa chamada por valor, a funo no altera os valores das variveis
dentro do chamador, como mostrado aqui:
#include <stdio.h>

void exibe_e_altera(int primeiro, int segundo, int terceiro)


{
printf("Valores originais da funo %d %d %d\n, primeiro, segundo,
terceiro);
primeiro += 100;
segundo += 100;
terceiro += 100;
printf(Valores finais da funo %d %& %d\n", primeiro, segundo, terceiro);
>
void main(void)
{
int a = l , b = 2 , c = 3;
exibe_e_altera(a, b, c);
printf("Valores finais em main %d %d %d\n", a,b,c);
}

Quando voc compilar e executar o programa naomuda.c, sua tela exibir o seguinte:
Valores originais da funo 1 2 3
Valores finais da funo 101 102 103
Valores finais em main 1 2 3
C:\>
Como voc pode ver, as alteraes que a funo faz nas variveis somente so visveis dentro da prpria
funo. Quando a funo termina, as variveis dentro de main esto inalteradas.
Nota: Quando voc usa chamada por referncia (que ser apresentada em detalhe na Dica 240), a funo pode mo
dificar o valor de um parmetro para que a modificao seja visvel fora da funo.

E v ita n d o a A l t e r a o n o V a l o r do P a r m e t r o com a
C ham ada p o r V a l o r 239
Na Dica 238 voc aprendeu que, por padro, C usa chamada por valor para passar parmetros para as funes.
Conseqentemente, quaisquer alteraes nos valores dos parmetros ocorrem apenas dentro da prpria funo.
Quando a funo termina, os valores das variveis que o programa passou para a funo esto inalterados. Como
detalha a seo Introduo Linguagem C , uma varivel basicamente um nome atribudo a uma posio de
memria. Toda varivel tem dois atributos de interesse seu valor atual e seu endereo de memria. No caso
122 P rogram and o em C/C++ A B b l ia

do programa naomuda.c, apresentado na dica anterior, as variveis a, b e c poderiam usar os endereos de me


mria mostrados na Figura 239.1:

Memria
Figura 239.1 As variveis armazenam um valor e residem em uma posio de memria especfica.

Quando voc passa parmetros para uma funo, C coloca os valores correspondentes na pilha. No caso
das variveis a, b t c, a pilha contm os valores 1, 2 e 3. Quando a funo acessa os valores da varivel, a funo
referencia as posies da pilha, como mostrado na Figura 239.2.

Pilha

algumajuncao (a, b, c);


Figura 239.2 As funes referenciam valores armazenados na pilha.
Quaisquer modificaes que a funo fizer nos valores dos parmetros realmente alteram os valores da pi
lha, como mostrado na Figura 239.3:

Figura 239.3 As modificaes que as funes fzem nos valores dos parmetros afetam apenas os valores que esto na pilha.
Quando a funo termina, C descarta os valores na pilha bem como as alteraes que a funo fez nos con
tedos da pilha. A funo nunca referencia as posies de memria que contm o valor de cada varivel, de modo
que suas funes no podem fazer alteraes que existam aps a funo terminar em qualquer parmetro que a
funo recebe usando a chamada por valor.

240 Co m p r e e n d e n d o a Ch a m a d a po r R e f e r n c ia
Como voc aprendeu, C passa parmetros para as funes usando chamada por valor por padro. Usando a cha
mada por valor, as funes no podem modificar o valor de uma varivel passada para uma funo. No entanto,
na maioria dos programas, suas funes modificaro as variveis de um modo ou de outro. Por exemplo, uma
funo que l informaes de um arquivo precisa colocar as informaes em uma matriz de strings de caracteres.
Da mesma forma, uma funo tal como strupr (apresentada na seo Strings deste livro) precisa converter as le
tras em uma string de caractere para maisculas. Quando suas funes alteram o valor de um parmetro, seus
programas precisam passar o parmetro para a funo usando chamada por referncia. A diferena entre chamada
por valor e chamada por referncia que, usando a chamada por valor, as funes recebem uma cpia do valor
de um parmetro. Por outro lado, com a chamada por referncia, as funes recebem o endereo de memria
da varivel. Portanto, as funes podem alterar o valor armazenado na posio de memria especfica (em outras
palavras, o valor da varivel); alteraes essas que permanecem aps a funo terminar. Para usar a chamada por
referncia, seu programa precisa usar ponteiros. A seo Matrizes, Ponteiros e Estruturas mais frente discute os
ponteiros em detalhes. No entanto, por ora, pense em um ponteiro simplesmente como um endereo de mem
Fu n e s 123
124 P rogram and o em C/C++ A B b l ia

De um modo similar, o comando a seguir atribui varivel b o valor ao qual a varivel i_ponteiro aponta
atualmente:
b * *i_ponteiro;
Quando voc quiser usar o valor apontado por uma varivel ponteiro, use o operador de redireo (*).
Quando quiser atribuir o endereo de uma varivel a uma varivel ponteiro, use o operador de endereo (&).
O programa a seguir, usa_end.c, iiustra o uso de uma varivel ponteiro. O programa atribui varivel ponteiro
i_ponteiroo endereo da varivel a. O programa ento usa a varivel ponteiro para alterar, exibir e atribuir o valor
da varivel:
#include <stdio.h>

void main(void)
{
int a = 1, b = 2;
int *i_ponteiro;

i_ponteiro = &a; // Atribui um endereo


*i_ponteiro = 5 ; // Altera o valor apontado por i_j?onteiro para 5

// Exibe o valor
printf("O valor apontado por i_ponteiro %d a varivel a %d\n",
*i_ponteiro, a);
b = *i_ponteiro; // Atribui o valor
printf("O valor de b %d\n, b);
printf("Valor de i_ponteiro %x\n", i_ponteiro);
}
Lembre-se de que um ponteiro no nada mais que um endereo de memria. Seu programa precisa atri
buir o valor que o ponteiro (o endereo) contm. No programa usa_end.c, o programa atribuiu ao ponteiro o
endereo da varivel a. O programa poderia ter tambm atribudo o endereo da varivel b.
Nota: Quando voc usa ponteiros, precisa ainda ter em mente os tipos de valores, tais como int, flo a t e char. Seus
programas somente devem atribuir o endereo de valores inteiros s variveis ponteiro, e assim por diante.

243 A lteran d o o Va lo r d e um Pa r m et ro
Como voc aprendeu, para alterar o valor de um parmetro dentro de uma funo, seus programas precisam usar
a chamada por referncia, passando o endereo da varivel. Dentro da funo, voc precisa usar ponteiros. O
programa a seguir, altparam.c, usa ponteiros e endereos (chamada por referncia) para exibir e, depois, alterar
os parmetros que o programa passa para a funo exibe_e__altera:
#include <stdio.h>

void exibe_e_altera(int *primeiro, int *segundo,


int *terceiro)
{
printf("Valores originais da funo %d %d %d\n", primeiro, *segundo,
terceiro);
primeiro += 100;
segundo += 100;
terceiro += 100;

printf("Valores finais da funo %d %d %d\n", *primeiro, *segundo,


terceiro);
>

void main(void)
F u n es 125

{
int a = 1, b = 2, c = 3;

exibe_e_altera(&a, &b, &c);


printf("Valores finais em main %d %d %d\n", a, b ,c);
}
J vimos que, quando o programa chama a funo, ele passa como parmetros os endereos das variveis
a, b e c. Dentro de exibe_e_altera, a funo usa variveis ponteiro e o operador de redireo para afterar e exibir
os valores dos parmetros. Quando voc compilar e executar o programa altparam.c, sua tela exibir a seguinte
sada:
Valores originais da funo 1 2 3
Valores finais da funo 101 102 103
Valores finais em main 101 102 103
C:\>

A lt er a n d o S o m e n t e P a r m e t r o s E s p e c f ic o s 244
Como voc aprendeu, suas funes podem modificar o valor de um parmetro usando a chamada por referncia.
Por exemplo, a dica anterior, apresentou a funo exibe_e_altera, que usou chamada por referncia para alterar
o valor de cada um de seus parmetros. No entanto, em muitos casos, suas funes podem alterar o valor de um
parmetro e ao mesmo tempo deixar o valor de um segundo parmetro inalterado. Por exemplo, o programa a
seguir, mudaprim.c, usa a funo muda_primeiro para atribuir ao parmetro primeiro o valor do parmetro segundo:
#include <stdio.h>

void muda_primeiro(int primeiro, int segundo)


{
primeiro = segundo; // Atribui o valor de segundo a primeiro
}

void main(void)
{
int a = 0, b = 5;

muda_primeiro(&a, b);
printf("Valor de a %d valor de b %d\n", a, b);
>
Como voc pode ver, a funo muda_primeiro usa a chamada por referncia para alterar o valor do par
metro primeiro, e chamada por valor para o parmetro segundo. Quando seus programas usam ambas as tcnicas
e eles usaro , voc precisa ter em mente quando usar ponteiros e quando referenciar diretamente a varivel.
Como regra, os parmetros cujos valores voc quer alterar iro requerer chamada por referncia. Para compreen
der melhor o impacto da chamada por referncia versus chamada por valor, modifique a funo muda_primeiro,
como mostrado aqui:
void muda_primeiro(int *primeiro, int segundo)
{
primeiro = segundo; Atribui o valor de segundo a primeiro
segundo = 100;
>
Quando voc compilar e executar este programa, ver que o valor de primeiro foi alterado, mas o valor de
segundo no foi. Como o parmetro segundo fo\ passado usando chamada por valor, a alterao do parmetro no
visvel fora da funo.
126 Programando em C/C++ A B b lia

245 A Ch a m a d a po r R e f e r n c i a A in d a U s a a P il h a
J vimos que, ao passar parmetros para as funes, C coloca os valores dos parmetros na pilha. C usa a pilha
para armazenar os parmetros esteja voc usando chamada por valor ou chamada por referncia. Quando voc
passa um parmetro por valor, C coloca o valor do parmetro na pilha. Ao passar um parmetro por referncia,
C coloca o endereo do parmetro na pilha. A Dica 244 apresentou o programa mudaprim.c, que usou a funo
muda_primeiro para atribuir o valor do parmetro segundo da funo para o parmetro primeiro da funo.
Quando o programa chama a funo, C coloca o endereo da varivel a e o valor da varivel b na pilha, como
mostrado na Figura 245.
F u n es 127

imprimejboletim(l);
imprimejboletim(l);
imprime_boletim(1 );
>
Quando voc compilar e executar o programa estatica.c, sua tela exibir a seguinte sada:
Imprimindo boletim para o aluno 100
Imprimindo boletim para o aluno 101
Imprimindo boletim para o aluno 102
C:\>
Como voc pode ver, a varivel id_aluno retm seu valor de uma chamada para a prxima.
Nota: Quando voc declara variveis estticas, o compilador C no armazena as variveis na pilha. Em vez disso,
ele coloca as variveis dentro do segmento de dados para que seus valores continuem existindo.

C o m p r e e n d e n d o C o m o C I n ic ia l iz a V a r i v e is E s t t ic a s 247
Na dica anterior voc aprendeu que a palavra-chave static instrui o compilador a reter o valor de uma varivel
da chamada de uma funo para a prxima chamada. Quando sua funo declara uma varivel esttica, C per
mite-lhe inicializar a varivel, como mostrado aqui:
void imprime_boletim(int num_impressora)
{
static int id_aluno = 100; // Inicializada uma vez

// Outros comandos
>
Quando voc declara uma varivel como esttica, o compilador inicializar a varivel com o valor que voc
especificar. Quando voc chamar a funo mais tarde, C no efetuar a atribuio de inicializao novamente.
Essa inicializao de varivel na funo diferente do processamento que C normalmente executa dentro de uma
funo. No caso da funo a seguir, C inicializar a varivel conta toda vez que o programa chamar a funo:
void alguma_funcao(int idade, char *nome)
{
int conta = 1 ; // Inicializada em toda chamada

// Outros comandos
>

USANDO A SEQNCIA DE CHAMADA PASCAL 248


medida que voc vai criando programas C, poder descobrir que gostaria de usar uma funo que criou an
teriormente em Pascal. Dependendo do seu compilador, linkeditor e tipo de biblioteca, poder ainda ser possvel
chamar a funo Pascal a partir do seu programa C. Os passos que voc precisar executar para fazer isso, no en
tanto, dependero do seu compilador. Adicionalmente, dentro do cdigo do seu programa, voc precisar incluir
um prottipo de funo no incio do seu programa que inclui a palavra-chave pascal, como mostrado aqui:
int pascal alguma_funcao(int nota, int nivel);
Se voc programar no ambiente Windows, ver que muitas funes da biblioteca de execuo usam a se
qncia de chamada Pascal. As funes que usam a palavra-chave pascal no podem suportar um nmero varivel
de argumentos (ao contrrio de p rin tf scanf).

Co m p r e e n d e n d o o E f e it o da P a l a v r a -Ch a v e P a s c a l 249
A dica anterior mostrou que, quando seus programas chamam uma funo, C passa parmetros para a funo
usando a pilha. C coloca parmetros na pilha da direita para a esquerda. A Figura 249.1 ilustra o contedo da
pilha para uma chamada de funo em C.
128 P ro gram a n d o em C/C++ A B b l i a

Figura 249.1 O contedo da pilha para a chamada de uma funo em C.

Por outro lado, Pascal coloca argumentos na pilha da esquerda para a direita. A Figura 249.2 ilustra o con
tedo da pilha para a chamada de funo Pascal.

Figura 249-2- O contedo da pilha para a chamada de uma funo Pascal.

Se voc estiver usando uma funo Pascal dentro de seu programa C, use a palavra-chave pascal para ins
truir o compilador C a colocar os parmetros na pilha da esquerda para a direita, na ordem em que Pascal espera.

250 E s c re v e n d o um Ex em p lo de Linguagem M is ta
Como voc aprendeu, muitos compiladores C lhe permitem chamar funes que foram escritas em uma lingua
gem de programao diferente. Se voc estiver chamando uma funo Pascal de dentro de seu programa C, por
exemplo, pode preceder o prottipo da funo usando a palavra-chave pascal J falamos que a palavra-chave pas-
vz/instrui o compilador a colocar os parmetros na pilha da esquerda para a direita. Para ilustrar o processamento
que a palavra-chave pascal efetua, crie a seguinte funo, exibe_valores e preceda a funo com a palavra-chave
pascal:
#include <stdio.h>

void pascal exibe_valores(int a, int b, int c)


{
printf("a %d b %d c %d\n", a, b, c);
>
Em seguida, chame a funo usando o seguinte cdigo de programa:
void main(void)
{
exibe_valores(1, 2, 3);
exibe_valores(100, 200, 300);
}

Para experimentar a funo exibe_valores, remova a palavra-chave pascale observe a mudana na ordem dos
valores dos parmetros que C exibe. Se seus programas posteriormente chamarem uma rotina Pascal, voc pre
cisar usar a palavra-chave pascal no prottipo da funo.
F u n es 129

Co m p r e e n d e n d o a P a l a v r a -Ch a v e cd ecl 251


Na Dica 250 voc aprendeu que, se usar funes escritas em Pascal, usar a palavra-chave pascal para instruir o
compilador a colocar os parmetros na pilha na ordem correta. Quando voc usar funes escritas com mltiplas
linguagens de programao, provavelmente ir querer incluir a palavra-chave cdecl dentro dos prottipos de suas
funes para indicar as funes em C e para oferecer clareza ao leitor. Por exemplo, o seguinte prottipo de fun
o informa o compilador de que a funo muda_valores usa a estrutura de chamada de C:
int cdecl muda_valores(int *, int *, int *);
Quando o compilador encontra a palavra-chave cdecl dentro do cabealho de uma funo, ele faz os pa
rmetros passados para a funo serem colocados na pilha da direita para a esquerda. Alm disso, o compilador
garantir que o linkeditor use o formato C para o nome da funo.

COMPREENDENDO A RECURSO 252


Como voc viu, C lhe permite dividir seu programa em panes menores chamadas funes. Usando funes, o
programa torna-se mais fcil de compreender, programar e testar. Alm disso, voc normalmente poder usar as
funes que criar para um programa dentro de outro programa. medida que seus programas so executados,
uma funo pode chamar outra, que chama outra, que pode, por sua vez, chamar vrias outras funes. Dentro
da srie, cada funo executa uma operao especfica. C permite at mesmo que uma funo chame a si mesma!
Uma funo recursiva uma funo que chama a si mesma para executar uma operao especfica. O processo
de uma funo chamar a si mesma conhecido como recurso. medida que a complexidade de seus programas
e funes aumentar, voc descobrir que pode facilmente definir muitas operaes em termos recursivos.
Quando voc usa programas e funes complexas, pode querer criar uma funo recursiva. Por exemplo,
muitos liVros sobre programao usam o problema do fatorial para ilustrar como a recurso funciona. O fatorial
de 1 1. O fatorial de 2 2*1. O fatorial de 3 3*2*1. Da mesma forma, o fatorial de 4 4*3*2* 1. O processo
do fatorial pode prosseguir infinitamente. Se voc examinar o processamento que o fatorial realiza, ver que o
fatorial de 4, por exemplo, na verdade 4 vezes o fatorial de 3 (3*2*1). Da mesma forma, o fatorial de 3 , na
verdade, 3 vezes o fatorial de 2 (2*1). O fatorial de 2 2 vezes o fatorial de 1 (1). A Tabela 252 ilustra o pro
cessamento do fatorial.

O programa a seguir, fator, c, cria a funo recursiva fatorial, e, depois, usa a funo para retornar os valores
de fatorial para os valores de 1 at 5:
#include <stdio.h>

int fatorial(int valor)


{
if (valor == 1)
return(1);
else
return(valor * fatorial(valor-1));
>

void main(void)
{
int i;

for (i i 1; i <= 5; i++)


130 P rogram and o em C/C++ A b b l ia

printf("O fatorial de %d %d\n", i, fatorial(i));


>
Como voc pode ver, a funo fatorial retorna um resultado que est baseado no resultado da prpria fun
o. A dica a seguir examinar a funo fatorial em detalhes.

253 Co m p r e e n d e n d o a F u n o R e c u r s i v a F a t o r ia l
Na Dica 252 voc aprendeu que uma funo recursiva uma funo que chama a si mesma para efetuar uma
tarefa especfica, apresentando a funo fatorial pata ilustrar a recurso. A funo fatorial recebe um valor de pa
rmetro especfico. Quando a funo inicia, ela primeiro verifica se o valor 1, que, pela definio de fatorial,
1. Se o valor for 1, a funo retornar o valor 1. Se o valor no for 1, a funo retornar o resultado do valor
vezes o fatorial do valor menos 1.
Por exemplo, suponha que o programa chame a funo com o valor 3. A funo retornar o resultado de
3 *fatorial(3-l). Quando C encontrar a chamada da funo dentro do comando retum, C chamar a funo
uma segunda vez desta vez com valor de 3-1 ou 2. Novamente, como o valor no 1, a funo retorna o re
sultado de 2 *fatorial(2-l). Na terceira vez em que a funo chamada, o valor 1. Como resultado, a funo
retorna o valor para a funo chamadora, o que, por sua vez, retorna o resultado de 2*1 para a funo chama
dora. A funo chamadora ento retorna o resultado de 3*2*1 para sua funo chamadora. A Figura 253 ilustra
a cadeia de chamadas de funes recursivas e valores de retorno para a chamada da funo fatorial(3).

Figura 253 O encadeamento de chamadas de funo e valores de retorno para a funo recursiva fatorial.

Uma funo recursiva similar a uma construo de repetio, em que voc precisa especificar a condio
de trmino. Se voc no especificar uma condio de trmino, a funo nunca ter fim. No problema do fatorial,
a condio de trmino o fatorial de 1, que , por definio, 1.

254 P r o g r a m a n d o O u t r o E x e m p l o R e c u r s iv o
Na Dica 252 voc aprendeu que uma funo recursiva uma funo que chama a si mesma para efetuar pro
cessamento especfico. A dica anterior, por sua vez, apresentou e explicou a funo recursiva fatorial. Como a re
curso pode ser um conceito difcil, esta dica apresenta mais uma funo recursiva, exibejnven, que exibir as
letras de uma string em ordem invertida. Dadas as letras ABCDE, a funo exibir na tela EDCBA. O programa
a seguir, inverte.c, usa a funo exibe_invert:
#include <stdio.h>

void exibe_invert(char *8tring)


{
if (*string)
{
exibe_invert(string+l);
F u n es 131

E x i b in d o V a l o r e s para Co m p r e e n d e r M e l h o r a

Rec urso
J foi visto que uma funo recursiva uma funo que chama a si mesma para efetuar uma operao especfica.
A Dica 252 apresentou a funo recursiva fatoriai Para lhe ajudar a compreender melhor o processo de recurso,
o programa exibefat.c inclui comandos p rin tf dentro da funo fatorial para ilustrar o processamento recursivo
da funo dentro do programa:
#include <Btdio.h>

int fatorial(int valor)


{
printf("Em fatorial com o valor %d\n", valor);
if (valor == 1)
{
printf("Retornando o valor l\nn);
return(l);
>
else
{
printf("Retornando %d * fatorial(%d)\n", valor, valor-1);
return(valor * fatorial(valor-1));
>
}

void main(void)
<
printf("O fatorial de 4 %d\n", fatorial(4));
)
Quando voc compilar e executar o programa exibefat.c, sua tela exibir a seguinte sada:
Em fatorial com o valor 4
Retornando 4 * fatorial(3)
Em fatorial com o valor 3
Retornando 3 * fatorial(2)
Em fatorial com o valor 2
Retornando 2 * fatorial(1)
Em fatorial com o valor 1
Retornando o valor 1
0 fatorial de 4 24
C;\>
Inserir o comando p rin tftm todas as suas funes recursivas lhe ajudar a compreender o processamento
que as funes executam.

Co m p r e e n d e n d o a R e c u r s o D ir e t a e I n d ir e t a 256
Uma funo recursiva uma funo que chama a si mesma para realizar uma certa operao. Vrias dicas an
teriores nesta seo apresentaram funes recursivas. Quando uma funo chama a si mesma para realizar uma
132 P rogram and o em C/C++ A B b l ia

tarefa, a funo executa uma recurso direta. Aps voc ter examinado algumas funes recursivas, deve poder
compreender a maioria das funes que usa a recurso direta. Uma forma de recurso mais difcil, a recurso in
direta, ocorre quando uma funo (a funo A) chama outra funo (a funo B), que, por sua vez, chama a fun
o original (funo A). Como a recurso indireta pode resultar em cdigo que muito difcil de compreender,
como regra voc dever evitar usar a recurso indireta sempre que possvel.

257 D e c id in d o U s a r ou N o a Rec urso


Uma funo recursiva uma funo que chama a si mesma para realizar uma tarefa especfica. Ao criar funes,
usando recurso, voc pode criar solues elegantes para muitos problemas. No entanto, voc deve evitar a re
curso sempre que possvel por duas razes. Primeiro, as funes recursivas podem ser difceis de compreender
para os programadores novatos. Segundo, como regra, as funes recursivas normalmente so consideravelmente
mais lentas que suas correspondentes no-recursivas. O programa a seguir, sem_rec.c, chama a funo no-recur-
siva, string_tamanho, com a string Bblia do Programador C/C++, do Jamsa! 100.000 vezes, e, depois, exibe
a quantidade de tempo necessria para realizar o processamento:

ttinclude <stdio.h>
#include <time.h>

int string_tamanho(const char *str)


{
int tamanho = 0;

while (*str++)
tamanho++;
return(tamanho);
>

void main(void)
{
long int contador;
time_t tempo_inicio, tempo_fim;
time(&tempo_inicio);
for (contador = 0; contador < 100000L; contador++)
string_tamanho("Bblia do Programador C/C++, do Jamsal");
time(&tempo_fim);
printf("Tempo de processamento %d\n", tempo_fim - tempo_inicio);
}
Em seguida, o programa ok_recur.c, usa uma implementao recursiva da funo stringjamanho para rea
lizar o mesmo processamento:

#include <stdio.h>
ttinclude <time.h>

int string_tamanho(const char *str)


{
if (*str)
retum(l + string_tamanho(str+l));
else
return(0);
}

void main(void)
{
Fu n e s 133

long int contador;

time_t tempo_inicio, tempo_fim;


time(&tempo_inicio);
for (contador = 0; contador < 100000L; contador++)
string_tamanho("Bblia do Programador C/C++, do Jamsal");
time(&tempo_fim);
printf("Tempo de processamento %d\n, tempo_fim - tempo_inicio);
>

Experimente esses programas, por exemplo, alterando o nmero de chamadas da funo para um ou dois
milhes. Como voc descobrir, a funo no-recursiva executada consideravelmente mais depressa que sua
correspondente recursiva. Portanto, quando voc projeta uma funo recursiva, tenha em mente que pode acres
centar sobrecarga significativa ao tempo de execuo do seu programa.

Co m p r e e n d e n d o P o r Q u e as F u n e s R e c u r s iv a s
So L e n ta s 258
Uma funo recursiva uma funo que chama a si mesma para realizar uma tarefa especfica. Como voc apren
deu na Dica 257, uma razo para evitar o uso da recurso que as funes recursivas em geral so considera
velmente mais lentas que suas correspondentes no-recursivas. As funes recursivas so lentas porque a
sobrecarga da chamada ocorre toda vez que a funo chamada. Como j foi detalhado na Dica 231, toda vez
que seu programa chama uma funo, o compilador C coloca na pilha o endereo do comando que segue ime
diatamente a chamada da funo (chamado endereo de retomo). Em seguida, o compilador coloca os valores dos
parmetros na pilha. Quando a funo termina, o sistema operacional do computador retira o endereo de re
torno da pilha no contador de programa da CPU. Embora os computadores possam realizar essas operaes mui
to rapidamente, elas ainda requerem tempo.
Como um exemplo, assuma que voc chame a funo fatorial recursiva com o valor 50. A funo chamar
a si mesma 49 vezes. Se cada funo somar 10 milissegundos ao tempo de execuo do seu programa, a funo
ser meio segundo mais lenta que uma correspondente no-recursiva, que tem a sobrecarga de uma nica cha
mada. Uma sobrecarga de meio segundo pode no parecer muito, porm, assuma que o programa chame a fun
o 10 vezes. O retardo de meio segundo torna-se de cinco segundos. Se o programa usa a funo 100 vezes, o
retardo torna-se de 50 segundos, e assim por diante. Se voc estiver desenvolvendo um programa que requer m
ximo desempenho, dever tentar eliminar as funes recursivas sempre que possvel.

Nota: Com os novos e mais rpidos microprocessadores (tais como os de 200 M Hz), o retardo provocado pelas funes
recursivas no to imprtante como era antigamente. No entanto, o impacto das funes recursivas ainda signifi
cativo e voc deve tentar escrever cdigo eficiente e legvel sem recurso sempre que possvel.

Co m p r e e n d e n d o Co m o R e m o v e r a Rec urso 259


Uma funo recursiva uma funo que chama a si mesma para realizar uma tarefa especfica. Como voc apren
deu, possvel aumentar o desempenho do seu programa usando funes no-recursivas. Como regra, qualquer
funo que voc pode escrever recursivamente, tambm pode escrever em termos de construes de laos de re
petio, tais como um comando for ou while. O programa a seguir, lacofato.c, usa um lao for para implementar
a funo fatorial:

ttinclude <stdio.h>

int fatorial(int valor)


{
int result = 1;
134 P r og ram and o em C/C++ A B b l ia

int contador;

for (contador = 2; contador < = valor; contador++)


result *= contador;
return(result);
>'

void main(void)
{
int i;

for (i = 1; i <= 5; i++)


printf("O fatorial de % %d\n", i, fatorial(i));
)

Sempre que voc eliminar a recurso dentro de seus programas usando uma construo de lao de repe
tio, geralmente aumentar o desempenho do seu programa. No entanto, tenha em mente que os usurios po
dem compreender mais facilmente algumas operaes que seus programas executaro quando voc implementar
as operaes com recurso. Exatamente como algumas vezes voc precisa escolher entre velocidade e consumo
de memria do seu programa, algumas vezes precisa escolher entre legibilidade e desempenho.

260 P a s s a n d o S t r in g s para a s Fun es


Como voc aprendeu, quando passa parmetros para as funes, C, por padro, passa os parmetros por valor.
Portanto, quaisquer mudanas que sua funo fizer nos parmetros no existiro fora da funo. Para alterar o
valor de um parmetro, voc precisar passar o parmetro por referncia. A exceo a essa regra so as strings de
caracteres. Ao chamar uma funo com uma string de caracteres, voc estar simplesmente passando uma matriz
de byte para a funo. Quando C passa uma matriz (qualquer tipo de matriz no apenas uma string), C passa
o endereo inicial da matriz para a funo. Em outras palavras, C sempre usa a chamada por referncia para as ma
trizes, de modo que voc no precisa usar o operador de endereo.

261 Pa s s a n d o E l e m e n t o s Es p e c f ic o s da M a t r iz
Na dica anterior voc viu que C sempre passa as matrizes para as funes usando a chamada por referncia.
medida que voc trabalha com strings de caracteres, algumas vezes pode querer que uma funo trabalhe com
elementos especficos da matriz. Por exemplo, o programa a seguir, meiamaiu.c usa a funo strupr para converter
uma seo de uma string de caracteres para maisculas:

#include <stdio.h>
finclude <string.h>

void main(void)
{
char alfabeto[] = "abcdefghijklmnopqrstuvwxyz";

strupr(&alfabeto[13]);
printf(alfabeto);
}

A funo strupr espera que o endereo inicial de uma string terminada por NULL seja um parmetro. Nes
te caso, o programa passa para strupr o endereo da letra , o qual a chamada da funo ento segue com vrios
caracteres terminados por NULL. Passando o endereo de um elemento de matriz especfico, seus programas po
dem usar funes para manipular elementos especficos da matriz.
Fu n e s 135

Co m p r e e n d e n d o co n st em P a r m e t r o s F o r m a is 262
Se voc examinar os prottipos para as funes de manipulao de string anteriormente apresentados na seo
Compreendendo as Strings, ver que muitas declaraes de parmetros colocam a palavra-chave const antes dos
argumentos de string de caracteres, como mostrado aqui:
char *strcpy(char *destino, const char *origem);
N o exemplo da definio da funo strcpy, a palavra-chave const especifica que o cdigo da funo no deve
mudar a varivel origem dentro da funo. Se o cdigo de sua funo tentar modificar o valor da string, o com
pilador gerar um erro. O programa a seguir, chcconst.c, usa a palavra-chave const paia. o parmetro string:

Como voc pode ver, a funo nao_muda tenta converter as letras da string para maisculas. No entanto,
como o programa usa a palavra-chave const, o compilador exibir uma mensagem de erro, e o cdigo no com
pilar com sucesso. Voc dever usar a palavra-chave const diante de parmetro que uma funo recebe por re
ferncia quando no quiser que o valor do parmetro seja modificado. Como C normalmente passa parmetros
que no so ponteiros por valor, os parmetros por valor no requerem a palavra-chave const.

USAR CONST NO IM PED E A MODIFICAO DO PARMETRO 2 6 3


Vimos na dica anterior que a palavra-chave const informa o compilador de que a funo no deve modificar um
valor de um parmetro especfico. Se uma funo tentar modificar o valor de um desses parmetros, o compi
lador gerar um erro, e o programa no ser compilado. No entanto, voc deve notar que s porque o cabealho
da funo especifica um parmetro como uma constante, isso no significa que a funo no pode modificar o
valor do parmetro. O programa a seguir, mudacons.c, usa um ponteiro para o parmetro constante string para
converter o contedo da string para maisculas:
#include <stdio.h>
iinclude <ctype.h>

void nao_muda(const char *string)


{
char *apelido = string;

while (*apelido)
*apelido++ = toupper(*apelido);
>

void main(void)
{
char titulo[] = "Bblia do Programador C/C++, do Jamsa!;

nao_muda(titulo);
printf(titulo);
>
136 P rog ram and o em C/C++ A B b l ia

Quando voc compilar e executar o programa mudacons.c, a funo nao_muda converter os caracteres da
string para maisculas. Como voc usou o apelido de ponteiros (referenciar as posies de memria de uma va
rivel usando um nome diferente), o compilador no detecta a mudana no valor do parmetro. Dependendo
do tipo do seu compilador, ele poder gerar uma mensagem de advertncia. Se voc estiver criando suas prprias
funes, no use apelidos para alterar o valor de um parmetro (como faz o programa mudacons.c) Se um pa
rmetro verdadeiramente uma constante, seu valor no deve mudar. O programa dentro desta dica deve ensinar
voc que a palavra-chave const no pode na verdade impedir que o valor de um parmetro mude.

264 Co m p r e e n d e n d o as Dec la r a es de S t r i n g s N o -
L im it a d a s
Em C, uma string uma matriz de valores de caracteres. J vimos na seo Compreendendo as Strings que voc
especifica o nmero mximo de caracteres que a string conter para criar uma string, como mostrado aqui:
char nome[64];
char titulo[32];
char buffer[512];
Quando voc passa uma string de caracteres para uma funo, na verdade passa o endereo inicial da
string. Como o caractere N ULL termina a string, as funes de C no se preocupam com quantos caracteres a
string contm. Como resultado, muitas funes declaram parmetros de strings de caractere como matrizes no-
limitadas (matrizes que no especificam um tamanho), como mostrado aqui:
int strlen(char string[])
A declarao char string[] diz ao compilador que a funo receber um ponteiro para uma string terminada
por NULL. A string pode conter 64 caracteres, 1.024 caracteres, ou talvez apenas o caractere NULL. O programa
a seguir, stmatriz.c, usa uma matriz no-limitada para implementar a funo strlen:
#include <stdio.h>

int strlen(char str[])


{
int i = 0;

while (str[i] != NULL)


i++;
return(i);
}

void main(void)
{
printf("O tamanho de ABC %d\n", strlen("ABC"));
printf("O tamanho de Biblia do Programador C/C++ %d\n",
strlen("Bblia do Programador C/C++"));
printf("Tamanho de uma string NULL %d\n", strlen(""));
>
Quando voc compilar e executar o programa stmatriz.c, ver que a funo trabalhar para strings de qual
quer tamanho. No entanto, como a maioria das funes que trabalha com strings, a funo falhar se a string
no for finalizada pelo caractere NULL.

265 U s a n d o P o n t e ir o s versu s d ec la ra es d e S t r in g
A medida que voc examinar diferentes funes que manipulam strings, ver strings de caracteres declaradas
como matrizes no-limitadas ou como ponteiros, como mostrado aqui:
char *strcpy(char destino[], char origem[]);
char *strcpy(char *destino, char *origem);
Fu n es 137

Ambas as declaraes no exemplo anterior informam o compilador de que ele est trabalhando com
strings. Ambos so funcionalmente idnticos e ambos so corretos. Se voc estiver criando suas prprias funes,
o formato escolhido dever depender de como voc referencia o parmetro dentro da funo. Se voc trata o pa
rmetro como um ponteiro, use a declarao no estilo de ponteiro. Se, em vez disso, voc trata o parmetro como
uma matriz, use a matriz. Tratar o parmetro de um modo consistente tornar seus programas mais fceis de
compreender.

Co m o C U s a a P il h a para os P a r a m e t r o s S t r in g 266
Como voc aprendeu, quando seus programas passam um parmetro para as funes, C coloca o valor ou o en
dereo do parmetro na pilha. Quando voc passa uma string de caracteres para uma funo, C coloca o ende
reo inicial da string na pilha. Por exemplo, a Dica 264 apresentou o programa stmatriz.c, que passou vrias
strings para a funo strlen A Figura 266 ilustra o valor do parmetro que C coloca na pilha para a primeira cha
mada da funo.

Memria tamanho = strlen ("ABC');

Figura 266 Como C passa parmetros string para as funes.

Como voc pode ver, C no coloca os caracteres da string na pilha. Em vez disso, C simplesmente coloca
o endereo da string terminada por N U LL na pilha. Como a funo recebe somente um endereo (em vez de
uma matriz de bytes), a funo no se preocupa com quantos caracteres a string contm.

Co m p r e e n d e n d o as V a r i v e is Ex t e r n a s 267
Freqentemente voc pode usar as funes que cria para um programa dentro de outro. Para simplificar a reu
tilizao das funes, os programadores geralmente colocam as funes em bibliotecas de cdigo-objeto. A seo
Ferramentas, mais frente, discute o uso dessas bibliotecas. Em alguns casos, uma biblioteca pode definir uma
varivel global, tais como as variveis _fmode, _psp, ou ermo discutidas neste livro. Quando o cdigo fora do pro
grama atual define uma varivel global e voc quer usar a varivel global dentro do seu programa, preciso de
clarar a varivel usando a palavra-chave extern. A palavra-chave extern diz ao compilador que outro programa
declarou a varivel externamente (fora do arquivo-fonte atual). Por exemplo, se voc examinar o arquivo de ca
bealho dos.h, encontrar vrias declaraes de variveis externas, incluindo as mostradas aqui:
extern int const _Cdecl _8087j
extern int _Cdecl _argc;
extern char **_Cdecl _argv;
extern char **_Cdecl ambiente;
Se voc no usar a palavra-chave extern, o compilador assumir que voc est usando uma varivel com o
nome especificado. Por outro lado, quando voc incluir a palavra-chave extern, o compilador procurar a varivel
global que voc especificou.

Co l o c a n d o extern em Uso 268


A Dica 267 introduziu a palavra-chave extern, que voc usar dentro de seus programas para dizer ao compilador
para usar uma varivel global que outro programa declarou fora do programa atual. Para compreender melhor
como a palavra-chave extern funciona, compile o arquivo externo, c, que contm a declarao da varivel conta_
dica e a funo exibe_titulo:
138 P rog ram and o em C/C+ + A B b l ia

void exibe_titulo(void)
{
printf("Bblia do Programador C/C++, do Jamsa1");
>
Quando voc compilar e executar o programa externo, c, C criar o arquivo-objeto externo, obj. O programa
exibeext.c, mostrado aqui, usa a varivel externa conta_dica dentro do arquivo externo, obj:
#include <stdio.h>

void main(void)
{
extern int conta_dica;

printf("0 nmero de dicas %d\n", conta_dica);


>
Quando voc compilar o programa exibeext.c, efetue os seguintes passos dentro do compilador Turbo C+ +
Lite (se no estiver usando o Turbo C++ Lite, confira a documentao do seu compilador):
J. Selecione a opo Open Project no m enu Project.
2. M ude para o diretrio que contm o programa exibeext.ce informe o nome do projeto como exibeext.
D um clique com seu mouse em O K para criar o projeto.
3. Selecione a opo Add Item no menu Project.
4. Acrescente o arquivo externo.obj ao projeto.
5. Acrescente o arquivo exibeext.c ao projeto.
6. Selecione a opo Build Ali no menu Compile para criar o arquivo.
Neste taso, o programa exibeext. c exibe o valor da varivel externa conta_dica. O programa no usa a fun
o exibe_titulo, embora pudesse usar bastaria chamar exibejtitulo. No entanto, o objetivo do programa foi
ilustrar o uso da palavra-chave extern.
Nota: Para usar extern dentro de outro compilador, consulte a documentao on-line ou a impressa que veio com o
compilador.

269 Co m p r e e n d e n d o a V a r i v e l E s t t ic a E x t e r n a
A Dica 267 ensinou que a palavra-chave extern diz ao compilador C que voc est referenciando uma varivel
global definida em um programa diferente em outro arquivo. Quando o linkeditor ligar os mdulos do seu pro
grama, ele determinar a posio de memria da varivel. N a dica anterior voc usou a varivel global contajdica,
que foi definida no arquivo-objeto externo.obj. Como o programa exibeext.c referenciou a varivel usando a pa
lavra-chave extern, o programa poderia acessar a varivel. Dependendo de seus programas, algumas vezes voc
usar variveis globais em um arquivo-objeto que no quer funes fora do arquivo-objeto para acessar. Em tais
casos, simplesmente preceda o nome da varivel com a palavra-chave static:
static int nome_varivel;
O arquivo a seguir, estatext.c, declara duas variveis, uma chamada dica_conta e a outra titulo:
#include <stdio.h>

int conta_dica * 1500; // Varivel global


static char titulo[] = "Bblia do Programador C/C++, do Jamsa!";

void exibe_titulo(void)
< \
printf(titulo);
}
Compile o arquivo estatex.c para criar o arquivo-objeto estatex.obj. Em seguida, crie o seguinte programa,
sem_esta.c, que tenta usar ambas as variveis contidas dentro do arquivo estatex.obj.
Fu n e s 139

#include <stdio.h>

void main(void)
{
extern int conta_dica;
extern char *titulo;
void exibe_titulo(void);

printf("O nmero de dicas %d\n", conta_dica);


printf("O ttulo do livro %s\n", titulo);
exibe_titulo();
}
Como voc aprendeu na Dica 268, para compilar e vincular o programa usando o Turbo C++ Lite, siga
o seguintes passos:
1. Selecione a opo O pen Project no menu Project.
2. M ude para o diretrio que contm o programa sem_esta.c e informe o nome do projeto como
sem_esta. D um clique com seu mouse em O K para criar o projeto.
3. Selecione a opo Add item no menu Project.
4. Acrescente o arquivo estatex.obj ao projeto.
5. Acrescente o arquivo sem_esta.c ao projeto.
6. Selecione a opo Build Ali no menu Compile para criar o arquivo.
Quando voc compilar e ligar o programa sem_esta.c, o linkeditor dever exibiruma mensagem dizendo
que o compilador no pode resolver a varivel titulo. Como a palavra-chave static precede a declarao da varivel
titulo, a varivel somente conhecida dentro do arquivo-objeto extem2.obj.

Co m p r e e n d e n d o a P a l a v r a -c h a v e v o l a t il e 270
A medida que a complexidade do seu programa aumenta, voc pode eventualmente escrever funes e rotinas
de baixo nvel que acessam as portas de E/S do PC ou que servem os registradores de interrupo do PC (tam
bm referenciadas simplesmente como interrupes). Quando seus programas efetuam essas operaes, usar uma
interrupo ou acessar uma porta pode mudar suas variveis que correspondem a posies de memria especficas
ou endereos de portas. Como seu programa e muitos fatores externos ao seu programa podem mudar muitas
variveis, voc precisa dizer ao compilador de que o valor da varivel pode mudar a qualquer momento. Para in
formar o compilador que as operaes fora do programa podem alterar o valor de uma varivel, use a palavra-
chave volatile, como mostrado aqui:
volatile int alguma_variavel;
Quando o compilador encontrar a palavra-chave volatile, ele saber que no pode fazer suposies sobre o valor
da varivel a qualquer tempo. Por exemplo, o compilador no colocar o valor da varivel em um registrador
para acesso rpido. Fazer isso incorreria no risco de o valor do registrador no ser o mesmo que o contedo da
memria da varivel, que uma interrupo (por exemplo) poderia ter alterado aps o armazenamento da varivel
no registrador, sem o conhecimento do programa. Em vez disso, quando o programa precisar acessar o valor de
uma varivel, ele especificamente referenciar a posio de memria da varivel.
Nota: Voc geralmente deve declarar as variveis volatile como variveis globais. Deste modo, os programas e as ope
raes de fora referenciam posies de memria contidas dentro do segmento de dados do programa, e no as posies
na pilha, que o programa descarta quando a funo correspondente termina.

Co m p r e e n d e n d o a Estrutura de Ch a m a d a e o

P o n t e ir o de Base 271
Voc aprendeu que, quando seu programa chama uma funo, C coloca o endereo de retorno e os parmetros
da funo na pilha. Dentro da pilha, C referencia as informaes salvas da funo chamada como quadro da cha
mada (callframe). Para ajudar suas funes a localizar rapidamente o quadro da chamada, C atribui o registrador
Ponteiro Base (BP) ao endereo do incio do quadro. C tambm coloca as variveis locais da funo na pilha
(dentro do quadro da pilha). A Figura 271 ilustra o contedo de um nico quadro da pilha:

Figura 271 As inform aes que C coloca na pilha para um a cham ada de funo constitui um q uadro da cham ada.

Quando voc escreve funes em linguagem assembly que sero chamadas dentro de seus programas em
C, precisa compreender o uso e a estrutura dos quadros da pilha para que suas funes em Assembly possam
acessar os valores dos parmetros dentro desse quadro da pilha.

272 Cham ando uma Funo em L in g u a g e m A s s e m bly


Na Dica 236 voc viu que seus programas podem chamar funes escritas em outras linguagens de programao,
tais como Pascal. Alm disso, seus programas podem chamar rotinas em linguagem assembly. A rotina em lin
guagem assembly a seguir, troca_valores, permuta os valores de duas variveis passadas para a funo por refern
cia (por endereo):
MODEL small
CODE
PUBLIC _troca_valores

_troca_valores PROC
push bp
mov bp,sp
sub sp,2
push si
push i
mov si,word ptr [bp+4];Argl
mov i,word ptr [bp+6];Arg2

mov ax,word ptr [si]


mov word ptr [bp-2],ax

mov ax,word ptrfdi]


mov word ptr [si],ax

mov ax.word ptr [bp-2]


mov word ptr [di],ax

pop di
pop si
mov sp,bp
pop bp
saida: ret
_troca_valores ENDP
END
O CD-ROM que acompanha este livro contm o arquivo troca.asm. Se voc estiver usando o Borland
C+ +, monte o arquivo para criar o arquivo-objeto troca.obj, como mostrado aqui:
C:\> TASM TROCA.ASM <Enter>
Em seguida, crie o seguinte programa C, usa_troc.c; que usa a funo troca_valores:
Fu n e s 141

#include <stdio.h>

void troca_valores(int *, int *);

void main(void)
{
int a = 1, b = 2;

printf ("Valores* originais a %d b %\n'', a, b);


troca_valores(&a, &b);
printf("Valores perarutados a %d b %d\n", a, b);
}
Neste caso, voc escreveu a funo troca_valores para suportar ponteiros do tipo near. Se voc alterar os
modelos de memria, precisar alterar a rotina em linguagem assembly.

Reto rn a n d o um Valo r a p a r t ir d e u m a Funo em

L in g u a g e m A s s e m bly 273
Na Dica 261 voc aprendeu como chamar uma funo em linguagem assembly a partir de dentro de um pro
grama C. No programa troca.asm, a funo no retornou um resultado. No entanto, a seguinte rotina em lin
guagem assembly, pega_maximo, retorna o maior dentre dois valores inteiros:
.MODEL small
.CODE
PUBLIC _pega_maximo
_pega_maximo PROC
push bp
mov bp,sp

Argl egu [bp+4]


Arg2 equ [bp+6]

mov ax,Argl ;MoveArgl para AX


cmp Arg2,ax ;ComparaArg2 com Argl
jg arg2_maior ;Desvia se Arg2 for maior
jmp terminado

arg2_maior: mov ax,Arg2

terminado: pop bp
ret
_pega._ma.ximo SNDP
END
O CD-ROM que acompanha este livro contm o arquivo pega_max.asm, que contm a rotina pega_maximo.
Como voc pode ver, a rotina em linguagem assembly coloca seu resultado no registrador AX. Dicas posteriores
explicam os diferentes registradores em detalhe; por enquanto, voc pode considerar o registrador AX como si
milar ao registrador BP, que a dica anterior explicou. O seguinte programa C, usa_max.c, chama a funo da lin
guagem assembly para determinar o maior dentre dois valores:
#include <stdio.h>
extern int pega_maximo(int, int);

void main(void)
{
int result;

result = pega_maximo(100, 200);


printf("O maior valor %d\n", result);
>
142 P rog ram and o em /C++ A B b l ia

Q uando o programa chamar a funo, o compilador C atribuir o valor do registrador AX como o resul
tado da funo.

274 I n t r o d u z in d o F u n e s Q u e N o reto rn am Va lo res


medida que o nmero de funes que voc cria for aumentando, eventualmente voc criar uma funo que
no retornar um valor. Como visto, o compilador C, a no ser que instrudo de outra forma, assume que uma
funo retorna o tipo int. Se suas funes no retornam um valor, voc deve declarar a funo como tipo void,
como mostrado aqui:
void minha_fune(int idade, char *nome);
Se o programa mais tarde tentar usar o valor de retorno da funo, como mostrado aqui, o compilador ge
rar um erro:
result * minha_func(32, "Jamsa");

275 Co m p r e e n d e n d o as F u n e s Q u e No U s a m
Pa r m etro s
Aumentando o nmero de programas e funes criado por voc, possvel, eventualmente, criar uma funo que
no usa nenhum parmetro. Ao definir a funo (e o prottipo da funo), voc dever usar a palavra-chave void
para informar o compilador (e outros programadores) de que a funo no usa parmetros:
int minha_fune(void);
t

Se o programa mais tarde chamar a funo com parmetros, o compilador gerar um erro.

276 Co m p r e e n d e n d o a P a l a v r a -c h a v e auto
medida que voc for examinando programas C, encontrar declaraes de variveis que usam a palavra-chave
auto, como mostrado aqui:
auto int contador;
auto int sinaliz;
A palavra-chave auto informa o compilador de que a varivel local na funo, e que o compilador deve
automaticamente criar e destruir a varivel. O compilador cria variveis automticas alocando espao na pilha.
Como as variveis so automticas por padro, a maioria dos compiladores omite a palavra-chave auto. Dentro
de uma funo, as seguintes declaraes de variveis so idnticas:
auto int contador;
int contador;

277 C o m p re e n d e n d o o E s c o p o
Dentro de seu programa, as funes e as variveis tm um escopo que define as reas dentro do programa onde
seus nomes tm significado. Por exemplo, considere o seguinte programa, doiscont.c, que usa duas variveis cha
madas conta:
#include <stdio.h>

void alarme(int conta_bip)


{
int conta;

for (conta = 1; conta <= conta_bip; conta++)


putchar(7);
>
F u n es 143

void main(void)

int conta;
for (conta = 1; conta <= 3; conta++)
{
printf("Prestes a soar % vezes \n", conta);
alarme(conta);
}
>
Como voc pode ver, ambas as funes alarme e main usam variveis chamadas conta. No entanto, para
C, ambas as variveis so distintas cada uma tem um escopo diferente. No caso da funo alarme, C somente
conhece sua varivel conta (isto , conta tem um escopo definido) enquanto a funo estiver em execuo. Da
mesma forma, no caso de main, sua varivel conta somente tem significado enquanto main estiver em execuo.
Como resultado, o lao for que muda a varivel conta na funo alarme no tem efeito na varivel conta dentro
de main.
Quando voc discute o escopo de uma varivel, freqentemente usa os termos variveis locais e globais.
Uma varivel local tem seu escopo restrito a uma funo especfica. Por outro lado, o programa inteiro conhece
uma varivel global. No caso do programa doiscont.c, cada funo define cada ocorrncia da varivel conta como
local.

Co m p r e e n d e n d o as Ca t e g o r i a s de Esco po de C 278
Como voc aprendeu, o escopo de um identificador (geralmente o nome de uma varivel ou funo) a parte do
programa dentro do qual o identificador tem significado (em outras palavras, onde o programa pode usar o iden
tificador). C define quatro categorias de escopo: bloco, funo, prottipo de funo e arquivo. Adicionalmente,
C++ defirte o escopo de classe. O escopo de bloco define a regio delimitada por chaves dentro da qual seu pro
grama definiu uma varivel. Normalmente, o escopo de bloco referencia uma funo. As variveis locais tm es
copo no bloco. N o entanto, como j vimos na seo Introduo Linguagem C , voc pode declarar variveis
aps qualquer abre chaves. O escopo da varivel existe at o fecha chaves o que significa que um parmetro
com o escopo de bloco somente pode ter escopo dentro de um /condicional. Os parmetros formais tm escopo
de bloco, com o escopo limitado funo que define o parmetro. O escopo da funo define a regio entre o
abre e fecha chaves de uma funo. O nico item com escopo de funo um rtulo usado pelo comando goto.
O escopo de prottipo de funo especifica a regio dentro do incio e fim de um prottipo de funo. Os iden
tificadores que aparecem dentro de um prottipo de funo tm significado somente dentro do prottipo da fun
o, como mostrado aqui:
int uma_funcao(int idade, char *nome);
O escopo de arquivo especifica uma regio da declarao do identificador at o final do arquivo-fonte. As
variveis globais tm escopo de arquivo, o que significa que somente funes que seguem fisicamente a declara
o da varivel global dentro do arquivo podem referenciar uma varivel global. Em C++, o escopo de classe define
a coleo nomeada de mtodos e a estrutura de dados que compem a classe.

Co m p r e e n d e n d o o Espao do No m e e os I d e n t if ic a d o r e s 2 7 9
Como voc sabe, o escopo define a regio de um programa dentro do qual um identificador tem significado. Si
milarmente, o espao do nome define uma regio dentro da qual os nomes de identificadores precisam ser ex
clusivos. No sentido mais simples, um identificador um nome. C define quatro classes de identificadores, como
mostrado na lista a seguir:
Nomes de rtulos em goto: os nomes de rtulo usados em um comando goto precisam ser nicos den
tro de uma funo.
Estrutura, unio e tags de enumerao: um tag um nome de uma estrutura, unio ou tipo enume
rado. Os tags precisam ser nicos dentro de um bloco.
144 P rogram and o em C/C+ + A B b l ia

Nomes de membro de estrutura e de unio: os nomes de membro que aparecem dentro de uma es
trutura ou unio precisam ser nicos. Diferentes unies ou estruturas podem ter os mesmos nomes de
membro.
Variveis, identificadores typedef funes e membros enumerados: esses identificadores precisam ser nicos
dentro do escopo (como explicado na Dica 278) no qual o identificador est definido.

280 Co m p r e e n d e n d o a V is ib il id a d e do I d e n t if ic a d o r
Como voc aprendeu, o escopo define a regio do programa dentro da qual um identificador tem significado. De
um modo similar, a visibilidade de um identificador define a regio do cdigo dentro do qual um programa pode
acessar um identificador. Normalmente, o escopo e a visibilidade de um identificador so os mesmos. No en
tanto, quando seu programa declara um identificador com o mesmo nome dentro de um bloco que aparece den
tro do escopo de um identificador existente, o compilador temporariamente esconde o identificador externo (em
outras palavras, o identificador externo perde a visibilidade e o compilador no o reconhece). Considere o se
guinte programa, visivel.c, que usa dois identificadores chamados valor:
#include <stdio.h>

void main(void)
{
int valor = 1500;
if (valor > 1499)
{
int valor = 1;

printf("O valor interno %d\n", valor);


} '
printf(0 valor externo %d\n, valor);
>

Quando voc compilar e executar o programa visivel.c\ sua tela exibir o seguinte:

O valor interno 1
O valor externo 1500
C:\>

Quando o programa declara a varivel valor dentro do comando if, a declarao da varivel instrui o com
pilador a esconder a ocorrncia externa da varivel com o mesmo nome. No entanto, fora do bloco, a varivel
externa torna-se novamente visvel para o compilador.

281 Co m p r e e n d e n d o a Durao
Quando voc discute variveis, durao especifica a quantidade de tempo durante a qual um identificador possui
memria alocada pelo sistema. C suporta trs tipos de durao: local, esttica e dinmica. As variveis estticas
criadas durante a chamada de uma funo ou variveis definidas dentro de um bloco de comandos tm durao
locaL Seus programas sempre precisam inicializar variveis locais. Caso seu programa no inicialize uma varivel
local, ele no pode prever o contedo da varivel. O compilador cria variveis estticas medida que a execuo
do programa inicia. As variveis estticas normalmente correspondem s variveis globais. A maioria dos com
piladores C inicializa as variveis estticas com 0. O compilador aloca variveis dinmicas a partir do heap du
rante a execuo do programa. Na maioria dos casos, os programas precisam inicializar as variveis dinmicas.

Nota: Algumasfunes da biblioteca de execuo inicializaro as posies de memria com 0 (zero), enquanto outras no.
F u n es 145

Fu n es Qu e S u po rta m um N m e r o V a r i v e l de

Parm etro s 282


J foi visto que C mapeia os parmetros reais que passa para uma funo com os parmetros formais definidos
no cabealho da funo. Se a funo espera trs parmetros, a chamada de sua funo deve incluir trs valores
de parmetro. Caso considere funes tais como p r in tf ou scanf no entanto, voc ver que as funes suportam
um nmero varivel de parmetros. Por exemplo, as seguintes chamadas funo p rin tf so todas vlidas:
printf("Bblia do Programador C/C++, do Jamsa!");
printf("%d %d %d %d %", 1, 2, 3, 4, 5);
printf("%f %s %s %d %x", salario, nome, estado, idade, id);
Como voc ver a seguir, na Dica 283, voc pode usar as macros va_arg va_endt va_start (definidas no
arquivo de cabealho stdarg.li) para instruir seus programas a criar suas prprias funes que suportam um n
mero varivel de parmetros. As macros essencialmente retiram parmetros da pilha, um de cada vez, at que o
programa chegue ao ltimo parmetro. Ao usar essas [macros para obter os parmetro, voc precisar conhecer
o tipo de cada parmetro. No caso de printf, a funo usa os especificadores de formato (por exemplo, %d, %s
e % f) para controlar os tipos de parmetros.

S u po rtan d o um N m e r o V a r i v e l de Par m etro s 283


Nesta dica, voc criar uma funo chamada soma_valores, que soma todos os valores inteiros que a funo cha
madora passa para ela. Como mostrado aqui, a funo suporta um nmero varivel de parmetros. O valor 0
dentro da chamada da funo indica o ltimo parmetro (o que no afeta a soma):

O programa a seguir, advalor.c, contm e usa a funo soma_valores:


#include <stdio.h>
#include <stdarg.h>

int soma_valores(int valor, ...)


{
va_list argumento_ptr;
int result = 0 ;

if (valor 1= 0)
{
result += valor;
va_start(argumento_ptr, valor);
while ((valor = va_arg(argumento_ptr, int)) != 0)
result += valor;
va_end(argumento_ptr);
>
return(result);
>

void main(void)
{
printf("A soma de 3 %d\n", soma_valores(3, 0));
printf("A soma de 3 + 5 %d\n", soma_valores(3, 5, 0));
printf(A soma de 3 + 5 + 8 %d\n, soma_valores(3, 5, 8, 0));
printf(A soma de 3 + 5 t 8 + 9 %d\n", soma_valores(3,5, 8, 9, 0));
}
A funo soma_valores usa a macro va_start para atribuir um ponteiro {argumento_ptr) ao primeiro par
metro na pilha. Em seguida, a funo usa a macro va_arg para obter os valores um de cada vez. A macro va__arg
146 P rog ram and o em C/C++ A B b l ia

retorna um valor do tipo especificado, e, depois, incrementa o argumento_ptr para apontar para o prximo ar
gumento. Quando o argumento_ptr encontra o zero finalizador, a funo usa a macro va_end para atribuir um
valor ao argumento_ptr que impede o uso futuro de argumento_ptr (at que va_jtart reinicialize o argumento_ptr).
Quando voc criar funes que suportem um nmero varivel de parmetros, suas funes precisaro ter um
modo de conhecer o nmero de parmetros e o tipo de cada um. No caso de printf, o especificador de formato
define os parmetros e seus tipos. No caso de soma_valores, o finalizador zero marca o ltimo parmetro. Da
mesma forma, todos os argumentos passados para a funo so do mesmo tipo.
Nota: Observe o uso das reticncias (...) dentro do cabealho da funo soma_valores para indicar um nmero va
rivel de parmetros.

284 Co m o va_ st a r t , va_ a r g e va_ en d F u n c io n a m


Na dica anterior voc aprendeu que pode usar as macros va_start, va_argt va_end, definidas dentro do arquivo
de cabealho stdarg.h, para criar funes que suportam um nmero varivel de parmetros. Para compreender
melhor como essas macros funcionam, considere a seguinte chamada funo soma_valores:
soma_valores(10, 20, 30, 0);
Quando o programa fizer a chamada da funo, o compilador colocar os parmetros na pilha da direita
para a esquerda. Dentro da funo, a macro va_startatribui um ponteiro para o primeiro parmetro, como mos
trado na Figura 284.

Pilha
Figura 284 Usando va_start para atribuir um ponteiro ao primeiro parmetro.
A macro va_arg retorna o valor apontado pelo argumento ponteiro. Para determinar o valor, a macro pre
cisa, conhecer o tipo do parmetro. Um parmetro do tipo int, por exemplo, usar 16 bits, enquanto um par
metro do tipo long usar 32 bits. Aps recuperar o valor do parmetro, a macro va_arg incrementar o argumento
ponteiro para que ele aponte para o prximo argumento. Para determinar o nmero de bytes a adicionar ao pon
teiro, va_arguszT novamente o tipo do parmetro. Aps a macro va_argrecuperar o ltimo argumento, a macro
va_end nulificar o valor do argumento ponteiro.

285 C r ia n d o F u n e s Q u e S u p o r t a m M u it o s P a r m e t r o s
e Tip o s
Nas Dicas 282 e 283 voc aprendeu como criar funes que suportam um nmero varivel de parmetros. In
felizmente, a funo soma_valores que voc criou suporta somente parmetros do tipo int. O programa a seguir,
todotipo.c, modifica a funo soma_valores para suportar valores de todos os tipos. A funo retorna um valor do
tipo float. Para ajudar a funo a determinar os tipos dos parmetros, voc passa para a funo um especificador
de formato similar ao usado por printf. Por exemplo, para somar trs valores inteiros, use a seguinte chamada:
result = soma_valores("%d %d %d", 1, 2, 3);
Da mesma forma, para somar trs valores diferentes em ponto flutuante, use a seguinte chamada:
result = soma_valores(%f %f %f", 1.1, 2.2, 3.3);
Finalmente, para somar valores inteiros e pontos-flutuantes, use a seguinte chamada:
result = soma_valores("%f % %f %d", 1.1, 2, 3.3, 4);
Oper a es d e teclad o 147

Usando o especificador de formato, voc elimina a necessidade do zero finalizador. Adicionalmente, o es


pecificador de formato lhe permite determinar quantos bits cada parmetro usa, como mostrado aqui:

#inclue <stdio.h>
#include <stdarg.h>

double soma_valores (char *str, ...)



va_list marcador;
double result = 0.0;

va_start(marcador, str); // marca o primeiro argumento adicional


while (*str) // examina cada caractere na string
{
if (*str == '%') // se no for um especificador de formato pula
{
switch (*(++str))
{
case 'd': result += va_arg(marcador, int);
break;
case 'f': result += va_arg(marcador, double);
break;
>
>
str++;
>
va_end(marcador);
return(result);
>

void main(void)
{
double result;

printf("Result %f\n", soma_valores("%f", 3.3));


printf("Result %f\n", soma_valores("%f %f",1.1,2 .2));
printf("Result %f\n", soma_valores("%f %d %f",l.l, 1, 2.2));
printf("Result %f\n", soma_valores("% %d %f %d", 1.1, 1,2.2, 3));
>

L en d o um Ca r a c t e r e do Tec la d o 286
At mesmo os mais simples programas precisam freqentemente ler caracteres do teclado. O caractere pode cor
responder a uma opo de menu, uma resposta Sim ou No, ou at uma das muitas letras em um nome. Os pro
gramas normalmente efetuam as operaes de entrada de caractere usando a macro getchar. Voc implementar
a macro getchar como mostrado aqui:
#include <stdio.h>

int getchar(void);
Se for bem-sucedida, getchar retorna o valor ASCII para o caractere lido. Se um erro ocorrer ou getchar en
contrar um final de arquivo (normalmente para entrada redirecionada), getchar retorna EOF. O programa a se
guir, getchar.c, usa getchar para ler uma resposta Sim ou No do teclado:
#include <stdio.h>
#include <ctype.h>

void main(void)
{
148 P rogram and o em C/C++ A B b l ia

int letra;

printf("Digite S ou N para continuar e pressione EnterXn");


do
{
letra = toupper(getchar());
}
while {(letra 1= 'S') && (letra != 'N'));
printf("Voc digitou %c\n",((letra == 'S') ? 'S': 'N'));
}
Como voc pode ver, o programa usa um lao do while para repetidamente chamar getchar at que o usu
rio digite S ou N no teclado.
Nota: Para suportar o redirecionamento da E/S, C realmente define a macro getchar em termos de stdin (o que cor
responde ao teclado por padro).

287 E x i b in d o um Ca r a c t e r e de S a d a
Na dica anterior voc aprendeu como usar a macro getchar para ler um caractere do teclado. De um modo si
milar, C fornece a macro putchar, que escreve um caractere na tela (stdout). O formato da macro putchar :
#include <stdio.h>

int putchar (int letra);


Se putchar for bem-sucedida, ela retornar o caractere escrito. Se ocorrer um erro, putchar retorna EOF.
O programa a seguir, putchar.c, usa putchar para exibir as letras do alfabeto:
#include <stdio.h>

void main(void)
{
int letra;

for (letra = 'A'; letra <= 'Z'; letra++)


putchar(letra);
>
Nota: Como C define putchar em termos de stdout, voc pode usar os operadores de redirecionamento do D O S para
redirecionar a sada do programa putchar para um arquivo ou para a impressora.

288 Co m p r e e n d e n d o a E n t r a d a B u f f e r iz a d a
Quando seu programa usa entrada bufferizada, o sistema operacional no passa as letras que o usurio digita para
o programa at que ele pressione Enter. Deste modo, o usurio pode modificar os caracteres medida que di
gitar, usando a tecla Backspace (Retrocesso) para apagar os caracteres conforme necessrio. Quando o usurio
pressiona Enter, todos os caracteres digitados esto disponveis para o programa. A macro getchar usa entrada
bufferizada. Se voc usar getchar para ler uma resposta de um nico caractere, getchar no ir ler um caractere
at que o usurio pressione Enter. Se o usurio digitar mltiplos caracteres, todos os caracteres estaro dispon
veis para getchar dentro do buffer de entrada. O programa a seguir, es_buff.c, ilustra a entrada bufferizada. Exe
cute o programa, e, depois, digite uma linha de texto. Os caracteres que voc digitar no estaro disponveis para
o programa at que voc pressione Enter. No entanto, aps voc pressionar Enter, o programa ir ler e exibir ca
racteres at encontrar o caractere de nova linha (que o sistema operacional cria quando voc pressiona Enter),
como mostrado aqui:
#include <stdio.h>

void main(void)
{
int letra;
Op e r a e s d e t ec la d o 149

do
{
letra = getcharO;
putchar(letra);
{
while (letra 1= '\n');
>
Quando voc executar o programa es_buff.c, experimente com as letras que voc digitar, usando a tecla
Backspace para apagar letras. Como ver, as letras passadas para o programa correspondem ao seu texto final.

At r i b u i n d o E n t r a d a do Tec la d o a uma S t r in g 289


A seo Compreendendo as Strings deste livro discute vrios modos diferentes de manipular strings. Quando
voc efetuar entrada no teclado, uma das operaes mais comuns que seus programas far atribuir os caracteres
que resultam da entrada no teclado a uma string. O programa a seguir, preenche, c, usa a macro getchar para atri
buir letras varivel string. Para atribuir os caracteres, o programa simplesmente fica em um lao, atribuindo ca
racteres aos elementos da string at encontrar o caractere de nova linha. O programa ento atribui o caractere
marcador N U LL (final da string) posio atual da string, como mostrado aqui:
#include <stdio.h>

void main(void)
{
char string[128];
int indice = 0;
int letra;

printf("Digite uma string e pressione Enter \n");


while ((letra = getcharO) 1= '\n')
string[indice++] = letra;
string[indice] = NULL;
printf("A string foi: %s\n", string);
}

C o m b in a n d o g etc h ar e pu tc h a r 290
Como voc aprendeu, getchar lhe permite ler do teclado (stdin), enquanto putchar lhe permite exibir uma letra
na tela (stdout). Dependendo da funo do seu programa, algumas vezes voc poder querer ler e exibir carac
teres. Por exemplo, o lao do while, a seguir, ir ler e exibir caracteres at e incluindo o caractere de nova linha:
do
{
letra = getcharO;
putchar(letra);
>
while (letra != '\n');
Como getchar e putchar trabalham com valores inteiros, voc pode combinar os comandos anteriores,
como mostrado aqui:
do
putchar (letra = getcharO);
while (letra != '\n')
Neste caso, getchar atribuir o caractere digitado varivel letra. macro putchar; por sua vez, exibir o
valor atribudo a letra.
! 50 Program ando em C/C++ A B b l ia

291 Le m b r e -s e , g etc h ar e pu tc h a r So Ma c r o s
medida que voc cria seus programas, lembre-se de que getchar e. putchar so macros, no funes. Portanto, alguns
compiladores no lhe permitem deixar espaos entre os nomes dessas macros e os parnteses, como mostrado aqui:
letra = getcharO
putchar(letra);
Se voc examinar o arquivo de cabealho stdio.h, encontrar as definies de macros para getchar e putchar.
A seo Redirecionando a E/S e Processando Linhas de Comando, mais frente, explica as definies das macros
getchar e putchar em detalhes.

292 L e n d o um C a r a c t e r e U s a n d o E/S D ir e t a
Conforme voc aprendeu na Dica 288, quando seus programas recebem entrada no teclado, eles podem usar a
entrada direta ou bufferizada. Quando seus programas usam as operaes de entrada direta, os caracteres que o
usurio digita no teclado ficam imediatamente disponveis para o programa (em outras palavras, o sistema ope
racional no bufferiza os caracteres). Se o usurio pressionar a tecla Backspace para apagar um caractere anterior,
o prprio programa precisar tratar a operao de edio (apagando o caractere anterior da tela e removendo o
caractere do buffer). A funo getche permite que seus programas leiam um caractere do teclado usando entrada
direta. O formato da funo getche :
ttinclude <conio.h>
int getche(void)
O programa a seguir, getche. c, usa a funo getche para ler uma resposta Sim ou No do teclado:
#include <stdio.h>
#include <ctype.h>
ttinclude <conio.h>
void main(void)
{
int letra;

printf("Quer continuar? (S/N)t ");


do
{
letra = getche();
letra = toupper(letra);
}
while ((letra 1= 'S') && (letra 1= 'N'));
if (letra == 'S')
printf (" \nSua resposta foi SinAn);
else
printf("\nPor gue no?\n");
>
Ao contrrio do programa getchar. c, que requer que o usurio pressione Enter para tornar a resposta dis
ponvel, as teclas que o usurio digitou no programa getche. c ficam imediatamente disponveis para o programa.

293 E n t r a d a D ir e t a no Tec la d o sem a E x ib i o do

Ca r a c t e r e
Vimos na dica anterior como usar a funo getche para ler caracteres do teclado medida que ele digita os ca
racteres (usando a E/S direta). Quando voc usar getche, o programa exibir as letras que o usurio digita na tela
medida que ele as digitar. Dependendo do seu programa, algumas vezes voc poder querer ler caracteres do
teclado sem exibir os caracteres na tela. Por exemplo, se seu programa pedir que o usurio informe uma senha,
as letras que ele digitar no devero aparecer na tela para que os outros vejam. A funo getch permite que seus
programas leiam caracteres do teclado sem exibir (ecoar) os caracteres na tela. O formato da funo getch este:
Op e r a e s d e tec la d o 151

O programa a seguir, getch.c, usa a funo getch para ler caracteres do teclado. medida que o usurio di
gita, o programa usa getch para ler cada caractere, converte cada caractere para maisculo, e, depois, exibe o equi
valente maisculo de cada caractere na tela. O programa a seguir, getch.c, mostra como voc pode rapidamente
implementar esse processamento:
tinclude <stdio.h>
#include <conio.h>
#include <ctype.h>

void main(void)

int letra;

printf("Digite uma string de caracteres e pressione Enter\n");


do
{
letra = getch();
letra = toupper(letra);
putch(letra);
>
while (letra != '\r');
}

S a b e n d o Q u a n d o U s a r \ r e Xn 294
Como voc aprendeu, C usa a seqncia de escape \r para indicar um avano do carro. Da mesma forma, C
usa \n para representar uma nova linha (retorno do carro e alimentao de linha). Quando seus programas exe
cutam entrada bufferizada usando getchar, C converte a tecla Enter para a seqncia de retorno do carro e ali
mentao de linha. Por outro lado, quando voc executa E/S direta usando getch ou getche, ambas as funes
retornam a tecla Enter simplesmente como um retorno do carro (\r). Portanto, voc precisa testar o caractere
correto dentro de seus programas, como mostrado aqui:
do
{
letra = getchar();
putchar(letra);
>
while (letra != '\n')
do
(
letra = getch();
putchar(letra);
>
while (letra != '\r');

E x e c u t a n d o S a d a D ir e t a 295
J vimos que, as funes getch e getche permitem que seus programas leiam caracteres diretamente do teclado, ig
norando os canais de entrada bufferizada de C (baseados no sistema de arquivos). De uma forma similar, seus
programas podem efetuar sada rpida na tela usando a funo putch, como mostrado aqui:
#include <conio.h>

int putch(int letra);

Se bem-sucedida, putch retorna a letra que exibiu. Se um erro ocorrer, putch retorna EOF. Para efetuar sa
da rpida, a funo putch comunica-se com os servios de vdeo da BIOS ou acessa diretamente a memria de
152 P rogram and o em C/C++ A B b l ia

vdeo do PC. Funes tais como putchar, por outro lado, usam o sistema de arquivos, que por sua vez chama
a BIOS. A funo putch no converte um caractere de alimentao de linha em uma seqncia de retorno do car
ro e alimentao de linha. O programa a seguir, putch. c, usa putch e putchar para exibir as letras do alfabeto 1.001
vezes. O programa ento exibe a quantidade de tempo que cada funo requer, como mostrado aqui:

#include <stdio.h>
tinclude <conio.h>
#include <time.h>

void main(void)
{
int letra;
int conta;

time_t hora_inicio, hora_parada;


time(&hora_inicio);
for (conta = 0; conta < 1000; conta++)
for (letra = 'A'; letra <= 'Z'; letra++)
putchar(letra);
time(&hora_parada);
printf("\n\nTempo requerido por putchar %d segundos\n", hora_parada
-hora_inicio);
printf("Pressione qualquer tecla...\n");
getch();
time(&hora_inicio);
for (conta = 0; conta < 1000; conta++)
fr (letra = ' A ' ; letra <= 'Z'; letra++)
putch(letra);
time(&hora_parada);
printf("\n\nTempo requerido por putch %d segundos\n", hora_parada
-hora_inicio);
>

296 Co l a n d o uma T e c l a D ig it a d a de V o lta no B uffer do

Tec la d o
Como voc aprendeu, a funo getch permite que seus programas leiam um caractere do teclado. Dependendo
de como voc escreve seus programas, algumas vezes voc l caracteres at um caractere especfico, e, depois, pro
cessa as teclas digitadas. Quando o processamento termina, voc l os caracteres restantes. Quando voc escrever
esse cdigo, algumas vezes poder querer que seu programa anule a leitura de um caractere. A funo ungetch
permite que seus programas anulem a leitura de um caractere. Para fazer isso, voc implementar a funo un
getch, como mostrado aqui:

#include <conio.h>

int ungetch(int caractere);


Alm disso, algumas vezes voc pode querer colocar um caractere no buffer do teclado para que seu pro
grama possa reler a tecla digitada que acabou de ler. Usando ungetch, seus programas podem fazer exatamente
isso. O programa a seguir, ungetch. c, l letras do teclado at que encontre uma letra no-minscula. O programa
ento exibe as letras, e, depois disso, l e exibe quaisquer caracteres restantes em uma linha diferente:

#include <stdio.h>
#include <ctype.h>
#include <conio.h>
Op e r a e s d e t ec la d o 153

void main(void)
{
int letra;
int feito = 0;
int maiusc_encontrado = 0 ;

do
{
letra = getch();
if (islower(letra))
putchar(letra);
else
{
if (isupper(letra))
{
ungetch(letra);
maiusc__encontrado = 1;
putchar('\n');
>
}
feito = 1;
while (1 feito);

if (maiusc_encontrado)
do
{
letra = getch();
.} putchar(letra);
while (letra !s '\r');
}
Se voc estiver lendo caracteres usando getchar, poder usar funo ungetc para anular a leitura de um ca
ractere, como mostrado aqui:
ungetc(letra, stdin);

S a d a F o r m a t a d a R p id a U s a n d o c p r in t f 297
Como voc sabe, a funo p r in tf permite que seus programas efetuem sada formatada. C na verdade define a
funo p rin tf em termos do indicativo (handle) de arquivo stdout. Como resultado, voc pode redirecionar a sa
da de p rin tf da tela para um arquivo ou dispositivo. Como p rin tf usa stdout para exibir caracteres, p rin tf usa o
sistema de arquivo de C, que, por sua vez, usa as funes do DOS. Cada uma das funes do DOS, por sua vez,
chama a BIOS. Para sada formatada mais rpida, seus programas podem usar a seguinte funo, cprintf, que tra
balha diretamente com a BIOS ou a memria de vdeo do seu computador:
#include <conio.h>

int cprinft(const char *formato[,argumentos...]);


O seguinte programa, cprintfc, escreve a string Programando em C/C++ A Bblia 1.001 vezes na sua
tela usando p rin tfe da cprintf O programa ento exibe um sumrio do tempo requerido para cada funo:
#include <stdio.h>
#include <conio.h>
#include <time.h>

void main(void)
{
int conta;
154 P rog ram and o em C/C++ A B b l ia

time_t hora_inicio, hora_parada;


time(&hora_inicio);
for (conta = 0; conta < 1001; conta++)
printf("Bblia do Programador C/C++\n");
time(&hora_parada);
printf("\n\nTempo requerido por printf %d segundos\n", hora_parada
-hora_inicio);
printf("Pressione qualquer tecla...\n");
getch();
time(&hora_inicio);
for (conta = 0; conta < 1001; conta++)
cprintf("Bblia do Programador c/c++\r\n);
time(&horamparada);
printf("\n\nTempo requerido por cprintf %d segundos\n",
hora_parada-hora_inicio);
>
Nota: A funo cp rintf no converte o caractere de nova linha para uma seqncia de retomo do carro e alimentao
de linha.

298 E n t r a d a R p id a F o r m a t a d a a p a r t ir do Tec la d o
Na dica anterior voc aprendeu que cprintf permite que seus programas ignorem o sistema de arquivos para efe
tuar sada rpida na tela. De um modo similar, a funo avzw/permite que seus programas executem entrada for
matada rpida a partir do teclado, como mostrado aqui:
#include <conio.h>

int cscanf(char *formato[,argumentos]);


O programa a seguir, cscanf.c lhe pede trs valores inteiros. O programa ento l os valores usando cscanfi
#include <conio.h>

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

cprintf("Digite 3 valores inteiros e pressione Enter\r\n");


cscanf("%d % %", &a, &b, &c);
cprintf("Os valores digitados foram %d %d %d\r\n", a, b, c);
>

299 Escreven d o uma S t r in g de Ca r a c t e r e s


Como voc aprendeu, a funo p rin tf permite que seus programas escrevam sada formatada na tela. Usando
printf, seus programas podem escrever strings, inteiros, nmeros em ponto flutuante, ou combinaes de dife
rentes valores na tela. No entanto, quando seus programas somente precisam escrever uma string de caractere,
voc pode estar apto a aumentar o desempenho do seu programa usando a funo puts em vez de printf, como
mostrado aqui:

iinclude <stdio.h>

int puts(const char *string);


A funo puts escreve uma string terminada por N U LL na tela (na verdade, em stdout). Se puts for bem-
sucedida, puts retorna um valor no-negativo. Se um erro ocorrer, puts retorna EOF. A funo puts escreve au
tomaticamente um caractere de nova linha no final da string. O programa a seguir, puts.c, usa p rin tf e puts para
Op e r a e s d e t ec la d o 155

escrever a string Bblia do Programador C/C++! 1.001 vezes. O programa exibe o tempo requerido por cada
funo:
#include <stdio.h>
#include <conio.h>
#include <time.h>

void main(void)
{
int conta;

time_t hora_inicio, hora_parada;


time(&hora_inicio);
for (conta = 0; conta < 1001; conta++)
printf("Bblia do Programador C/C++\n");
time(&horaj>arada);
printf("\n\nTempo requerido por printf %d segundos\n", hora_parada
-hora_inicio);
printf("Pressione qualquer tecla...\n);
getch();
time(&hora_inicio);
for (conta = 0 ; conta < 1001; conta++)
puts("Bblia do Programador C/C++");
time(&hora_parada);
printf("\n\nTempo requerido por puts %d segundos\n", hora_jparada-
hora_inicio);
>
Nota: Como a juno puts acrescenta automaticamente um caractere nova linha, a string de caractere que o pro
grama instrui puts a exibir no inclui o caractere de nova linha.

E s c r i t a M a is R p id a de S t r i n g U s a n d o E/S D ir e t a 300
Na dica anterior foi visto que a funo puts permite que seus programas escrevam rapidamente uma string de ca
racteres. No entanto, como C define a funo puts em termos de stdout (para poder suportar o redirecionamen
to), a funo precisa usar o sistema de arquivos. Para sada mais rpida das strings na tela, seus programas podem
querer usar a funo cputs, como mostrado aqui:

#include <conio.h>

int cputs(const char string);

Como puts, a funo cputs escreve uma string terminada por N U L L No entanto, ao contrrio de puts, cputs
no acrescenta automaticamente um caractere de nova linha. O programa a seguir, cputs. c, usa as funes puts
e cputs para exibir a string Bblia do Programador C/C++ 1.500 vezes. O programa exibe a quantidade de tem
po que cada funo teve de requerer para gerar a sada:

#include <stdio.h>
#include <conio.h>
#include <time.h>

void main(void)
{
int conta;

time_t hora_inicio, hora_parada;


time(&hora_inicio);
for (conta = 0; conta < 1500; conta++)
puts("Bblia do Programador C/C++");
156 Programando em C/C++ A Bblia

time(&hora_parada);
printf("\n\nTempo requerido por puts %d segundos\n", hora_parada
-hora_inicio);
printf("Pressione qualquer tecla...\n");
getch();
time(&hora_inicio);
for (conta = 0; conta < 1500; conta++)
cputs("Bblia do Programador C/C++\r\n");
t ime (&hora__parada);
printf("\n\nTempo requerido por cputs % segundos\n", hora_parada
-hora_inicio);
}

301 Len d o uma S t r in g de Ca r a c t e r e s do Tec la d o


Na Dica 299 voc aprendeu que C fornece a funo puts, que voc pode usar dentro de seus programas para es
crever uma string de caracteres na tela. De um modo similar, seus programas podem usar a funo gets para ler
uma string de caracteres do teclado, como mostrado aqui:

#include <stdio.h>

char *gets(char *string);

Se for bem-sucedida, gets retornar um ponteiro para a string de caracteres. Se um erro ocorrer ou se gets
encontrar o final do marcador de arquivo, gets retornar o valor NULL. A funo gets l caracteres at e incluindo
o caractere de nova linha. No entanto, gets substitui o caractere de nova linha por N U L L O programa a seguir,
gets. c, usa a funo gets para ler uma string de caracteres do teclado:

#include <stdio.h>

void main(void)
{
char string[256];

printf("Digite uma string e pressione Enter\n);


gets(string);
printf("A string foi %s\n, string);
>
Nota: C na verdade define a juno gets em termos de stdin (que, por padro, o teclado), o que permite que a ju n
o suporte o redirecionamento da E/S.

302 Ex e c u t a n d o E n t r a d a de S t r in g M a i s R a p id a pelo

Tec la d o
Na dica anterior voc aprendeu como seus programas podem usar a funo gets para ler uma string de caracteres
do teclado. Como C define gets em termos de stdin, gets precisa usar o sistema de arquivos para efetuar suas ope
raes de entrada. Se voc no precisar suportar redirecionamento da E/S, poder usar a funo cgets para ler
caracteres do teclado, dessa forma aumentando o desempenho do seu programa. Voc implementar cgets como
mostrado aqui:

#include <conio.h>

char *cgets(char *string);


Op e r a e s d e teclad o 157

Se cgets ler caracteres do teclado com sucesso, retornar um ponteiro para a string que inicia em string[2],
Se um erro ocorrer, cgets retornar NULL. A funo cgets se comporta de forma diferente que gets. Antes de cha
mar cgets com uma string de caracteres, voc precisar primeiro atribuir para string[0] o nmero mximo de ca
ractere que cgets ir ler. Quando cgets retornar, string[l] conter um contador de caracteres que cgets leu. A string
de caracteres terminada por NULL na verdade inicia em string[2]. O programa a seguir, cgets. c, ilustra como usar
a funo cgets:
#include <stdio.h>
#include <conio.h>

void main(void)
{
char buffer[256];

buffer[0] = 253; // Nmero de caracteres que podem ser lidos


printf("Digite uma string e pressione EnterXn");
cgets(buffer);
printf("\n\nO nmero de caracteres lidos foi %d\n", buffer[1]);
printf("String lidas %s\n", &buffer[2]);

Para experimentar este programa, reduza o nmero de caracteres que cgets pode ler para 10. Se o usurio
tentar digitar mais do que 10 caracteres, a funo ignorar os caracteres extras.

E x i b in d o S a d a em Co r e s 303
Usando o controlador de dispositivo ansi.sys, seus programas podem exibir sada na tela em cores. Alm disso,
muitos compiladores fornecem funes de sada baseadas em texto que lhe permitem exibir sada em cores. Se
voc estiver usando o Turbo C++ L ite, o Borland C++ ou o Microsoft C++, a funo outtext (chamada _outtext
no Microsoft C++) lhe permitir exibir sada em cores. Se voc estiver usando o Turbo C++ Lite ou o Borland
C++, somente poder usar a funo outtext no modo grfico. A funo _outtext da Microsoft, por outro lado, tra
balha no modo texto e no modo grfico. Se voc precisar escrever sada em cores, consulte a documentao do
seu compilador para conhecer os detalhes especficos sobre essas funes. Como voc ver, os compiladores for
necem funes que definem a posio do texto, as cores e os modos grficos. Como as rotinas de sada ANSI so
dependentes do compilador, este livro no discutir essas rotinas como dicas.

L im p a n d o a Tela do V d e o 304
A maioria dos compiladores C no fornece uma funo que permita limpar a tela. No entanto, caso esteja usando
o Turbo C++ Lite, o Borland C ou o Microsoft C, voc pode usar a funo clrscr para limpar o contedo de uma
janela modo texto, como mostrado aqui:
#include <conio.h>

void clrscr(void);
O programa a seguir, clrscr. c, usa a funo clrscr para limpar a tela de vdeo:
ttinclude <conio.h>
void main(void)
<
clrscr;
y

A pagando at o F in a l da L in h a A t u a l 305
A medida que seus programas forem efetuando E/S na tela, algumas vezes voc poder querer apagar o contedo
de uma linha da posio atual do cursor at o final da linha. Para fazer isso, seus programas podem usar a funo
clreol, como mostrado aqui:
158 P rogram and o em C/C++ A B b l ia

A funo clreol apaga o contedo da linha atual a partir da posio do cursor, sem mover o cursor.

306 Apagando a L in h a A t u a l da Tela


medida que seus programas efetuarem E/S baseada na tela, algumas vezes voc desejar apagar o contedo da
linha atual, movendo toda a sada que segue uma linha para cima. Em tais casos, seus programas podem usar a
funo delline, como mostrado aqui:
#include <conio.h>

void delline(void);
O programa a seguir, delline. c, preenche a tela com 24 linhas de texto. Quando voc pressionar Enter, o
programa usar delline para apagar as linhas 12, 13 e 14, como mostrado aqui:
#include <conio.h>

void main(void)
{
int linha;

clrscr();
for (linha = 1; linha < 25; linha++)
cprintf("Esta a linha %d\r\n", linha);
cprintf("Pressione uma tecla para continuar: ");
getch();
gotoxy(l, 12);
for (linha =12; linha < 15; linha++)
delline();
gotoxy(l, 25);
}

307 P o s ic io n a n d o o Cu r s o r para S a d a na Tela


Como voc sabe, possvel usar o controlador de dispositivo ansi.sys para posicionar o cursor para as operaes
de escrita na tela. Se voc estiver trabalhando no ambiente do DOS, muitos compiladores fornecero a funo gotoxy,
que lhe permitir posicionar o cursor em uma interseo especficia de linha e coluna, como mostrado aqui:
#include <conio.h>

void gotoxy(int coluna, int linha);


O parmetro coluna especifica uma posio de coluna (x) de 1 at 80. O parmetro linha especifica uma
posio de linha (y) de 1 at 25. Se um dos valores for invlido, o compilador ignorar a operao gotoxy. O se
guinte programa, gotoxy. c, usa a funo gotoxy para exibir sada na tela em posies especficas:
#include <conio.h>

void main(void)
{
clrscrO;
gotoxy(1, 5);
cprintf("Sada na linha 5 coluna l\n");
gotoxy(20, 10);
cprintf("Sada na linha 10 coluna 20\n");
}
Op e r a e s d e tec la d o 159

D e t e r m in a n d o a P o s i o de L in h a e de Co l u n a 308
Na Dica 307 voc aprendeu como usar gotoxy para colocar o cursor em uma posio especfica de linha e coluna.
Em muitos casos, seus programas podero querer conhecer a posio atual do cursor antes de executar uma ope
rao de E/S na tela. As funes wherex e wherey retornam a coluna e a linha do cursor, como mostrado aqui:
#include <conio.h>

int wherex(void);
int wherey(void);
O programa a seguir, wherexy.c, limpa a tela, escreve trs linhas de sada, e, depois, usa as funes wherex
e wherey para determinar a posio atual do cursor:
#include <conio.h>

void main(void)
{
int linha, coluna;

clrscr();
cprintf("Esta a linha l\r\n");
cprintf("A linha 2 um pouco mais longa\r\n");
cprintf("Esta a ltima linha");
linha = whereyO;
coluna = wherex();
cprintf("\r\nA posio do cursor era lin %d col %d\n, linha, coluna);
>

In s e r in d o uma L in h a em B ranco na Tela 309


A medida que seus programas efetuarem operaes de E/S baseadas na tela, algumas vezes voc desejar inserir
uma linha em branco na tela para poder inserir texto no meio de texto existente. Para fazer isso, seus programas
podem usar a funo insline, como mostrado aqui:
#include <conio.h>

void insline(void);
Quando voc chama a funo insline, todo o texto abaixo da posio atual do cursor move-se para baixo
da linha. A linha na parte inferior da tela rola para fora da janela. O programa a seguir, insline.c, escreve 25 linhas
de texto na tela. O programa ento usa a funo insline para inserir texto na linha 12, como mostrado aqui:
#include <conio.h>

void main(void)
{
int linha;

clrscr();
for (linha = 1; linha < 25; linha++)
cprintf("Esta a linha %d\r\n", linha);
cprintf("Pressione uma tecla para continuar: ");
getch();
gotoxy(1, 12);
insline();
cprintf("Isto novo texto!!!");
gotoxy(1, 25);
}
160 P rogram and o em C/C++ A B b l ia

310 C o p ia n d o T e x t o da Tela para um Bu ffer


Quando seus programas efetuam muita E/S na tela, algumas vezes o programa precisa copiar o contedo atual
da tela para um buffer. Para copiar texto da tela, seus programas podem usar a funo gettext, como mostrado
aqui:
#include <conio.h>

int gettext(int esg, int topo, int dir, int base, void *buffer);
Os parmetros esq e topo especificam as posies de coluna e linha do canto superior esquerdo da regio
da tela que voc quer copiar. Da mesma forma, os parmetros dir e base especificam o canto inferior direito da
regio. A funo gettext coloca o texto e seus atributos no parmetro buffer. O PC usa um byte de atributo para
toda letra de texto que exibe na sua tela. Por exemplo, se voc quiser bufferizar 10 caracteres, seu buffer precisar
ser grande o suficiente para conter os 10 caracteres ASCII mais os 10 bytes de atributo (20 bytes em compri
mento). O programa a seguir, salvatel.c, salva o contedo da tela em modo texto no arquivo salvatel.dat:
#include <conio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

void main(void)
{
char buffer [8000];
int indicat;

if ('(indicat = creat("SALVATEL.DAT",S_IWRITE))== -1)


cprintf("Erro ao abrir SALVATEL.DAT\r\n");
else
{
gettext(l, 1, 80, 25, buffer);
write(indicat, buffer, sizeof(buffer));
close(indicat);
}
>
Nota: Na maioria dos casos, o atributo do texto atual 7. Se voc tentar exibir o contedo do arquivo salvateLdat
usando o comando TYPE, seu sistema soar o aviso sonoro para cada byte de atributo.

31 1 Escreven d o um Bu ffer de T exto em uma P o s i o


Es p e c f ic a da Tela
Como foi visto, muitos compiladores baseados no DOS fornecem funes que seus programas podem usar para
controlar a sada no vdeo. Na dica anterior voc aprendeu que seus programas podem usar a funo gettext para
copiar um intervalo de caracteres de tela (e seus atributos) para um buffer. Aps voc copiar o buffer de texto,
poder depois copi-lo de volta para a tela usando a funo puttext, como mostrado aqui:
#include <conio.h>

int puttext(int esq, int topo, int dir, int base, void *buffer);
Os parmetros esq, topo, dir e base especificam as posies de rela nas quais voc quer que o contedo do
buffer seja escrito. O parmetro buffer contm os caracteres e atributos que gettext armazenou anteriormente. O
programa a seguir, puttext.c, move p texto Bblia do Programador C/C++ na sua tela at que voc pressione
uma tecla qualquer:
#include <conio.h>
#include <io.h>
Op e r a e s d e t ec la d o 161

#include <fcntl.h>
#include <sys\stat.h>
#include <stdlib.h>
#include <dos.h>

void main(void)

char buffer[128J;
int linha, coluna;

clrscr();
cprintf("Bblia do Programador C/C++\r\n");
gettext(l, 1, 23, 1, buffer);
while (I kbhitO)
{
clrscr();
linha = 1 + random(24);
coluna = 1 + random(58);
puttext(coluna, linha, coluna+22, linha, buffer);
delay(2000);
>

D e t e r m in a n d o a s d e f in i e s do M odo Texto 312


Como voc aprendeu, muitos compiladores oferecem vrias funes baseadas em texto que seus programas po
dem usar para controlar as operaes de escrita na tela. Para determinar as definies atuais da tela, seus progra
mas podem usar a funo gettextinfo, como mostrado aqui:
#include <conio.h>

void gettextinfo(struct text_info *dados);


O parmetro dados um ponteiro para uma estrutura do tipo text_info, como mostrado aqui:
struct text_info
{
unsigned char winleft; // coluna da esquerda
unsigned char wintop; // linha superior
unsigned char winright; // coluna da direita
unsigned char winbottom; II linha inferior
unsigned char attribute; // atributo do texto
unsigned char normattr; // atributo normal
unsigned char currmode; II modo atual do texto
unsigned char screenheight; // altura em linhas
unsigned char screenwidth; // largura em colunas
unsigned char curx; // coluna do cursor
unsigned char cury; // linha do cursor;

O programa a seguir, textinfo.c, usa a funo gettextinfo para exibir a definio de texto atual:
#include <conio.h>

void main(void)
<
struct text_info texto;

gettextinfo(fitexto);
cprintf("Coordenadas da tela %d,%d at %d,%d\r\n",
texto.wintop, texto.winleft, texto.winbottom, texto.winright);
cprintf("Atributos do texto %d Atributo normal %d\r\n", texto.
162 Programando em C/C++ A B b lia

attribute, texto.normattr);
cprintf("Altura da tela %d largura %d\r\n", texto.screenheight,
texto.screenwidth);
cprintf("A posio do cursor era lin % col %d\r\n", texto.cury,
texto.curx);
>

313 Co n t r o l a n d o as Co r e s da Tela
J vimos que seus programas podem usar o controlador de dispositivo ansi.sys para exibir sada colorida na tela.
Alm disso, muitos compiladores baseados no DOS fornecem a funo textattr, que lhe permite selecionar as co
res de frente e de fundo do texto:
#include <conio.h>

void textattr(int atributo)/


O parmetro atributo contm oito bits que especificam as cores que voc deseja. Os quatro bits menos sig
nificativos especificam a cor da frente. Os trs bits seguintes especificam a cor de fundo, e o bit mais significativo
controla a intermitncia. Para selecionar uma cor, voc precisa atribuir o valor da cor desejada para os bits cor
retos. A Tabela 313 especifica os valores das cores.
Tabela 313 Os parmetros de atributos de cores.

O programa a seguir, textattr. c, ilustra as cores de frente disponveis:


#include <conio.h>

void main(void)
{
int cor;

for (cor = 1; cor < 16; cor++)


{
textattr(cor);
cprintf("Esta a cor %d\r\n", cor);
}
textattr(128 + 15);
cprintf("Isto piscante \r\n");
>
Op e r a e s d e tecla d o 163

At r ib u in d o Co r e s de Fundo 314
Como voc aprendeu na Dica 313, a funo textattr permite que seus programas selecionem cores de frente e
de fundo. Para definir a cor de fundo usando textattr, seu programa precisa atribuir o valor da cor que voc deseja
nos bits de 4 a 6 do valor da cor. Para atribuir o valor da cor, seus programas podem usar operaes de deslo
camento bit a bit, ou voc pode declarar uma estrutura com campos de bit, como mostrado aqui:
struct TextColor {
unsigned char foreground:4;
unsigned char background:3;
unsigned char blinking:l;
>;
O programa a seguir, defcores.c, usa a estrutura TextColor para definir as cores atuais da tela:
#include <conio.h>

void main(void)
{
union TextColor
{
struct
{
unsigned char frente:4;
unsigned char fundo:3;
unsigned char piscante:1;
} bits_cores;
unsigned char valor;
>'cores;
cores.bits_cores.frente = BLUE;
cores.bits_cores,fundo = RED;
cores.bits_cores.piscante = 1;
textattr(cores.valor);
clrscr();
cprintf("Esta a nova cor do texto \n);
>

D e f in i n d o a Co r de F r e n t e U s a n d o T e x t Co l o r 315
Como voc aprendeu, muitos compiladores baseados no DOS fornecem a funo textattr, que lhe permite se
lecionar suas cores de frente e de fundo. Para simplificar o processo de atribuir uma cor de frente, voc pode que
rer usar a funo textcolor, como mostrado aqui:
#include <conio.h>

void textcolor(int corfrente);


O parmetro corfrente especificar um dos valores de cores listados na Tabela 315.
Tabela 315 Valores de cores de frente vlidos para textcolor.
Constante de Cor Valor Constante de Cor Valor
BLACK (Preto) o. D ARK G RAY(Cinza escuro) 8
BLUE (Azul) 1 LIGHTBLUE (Azul claro) 9
GREEN (Verde) 2 LIGHTGREEN (Verde claro) 10
CYAN (Ciano) 3 LIG H TC YA N (Ciano claro) 11
RED (Vermelho) 4 LIGHTRED (Vermelho claro) 12
M AG ENTA (Magenta) 5 LIG H TM A GENTA (Magenta claro) 13
B R O W N (Marrom) 6 YELLOW (Amarelo) 14
L IG H T G R A Y (Cinza claro) 7 W H ITE (Branco) 15
B LIN K (Piscante) 128
164 PROGRAMANDO EM C/C + + A BBLIA

O programa a seguir, textcolor. c, ilustra como usar a funo textcolor para definir a cor de frente:
#include <conio.h>

void main(void)
{
int cor;

for (cor = 1; cor < 16; cor++)


{
textcolor(cor);
cprintf("Esta a cor %d\r\n", cor);
>
textcolor(128 + 15);
cprintf("Isto piscante\r\n");
}

316 D e f in i n d o a Co r de Fund o Usa n d o textbackg ro un d


J vimos que muitos compiladores baseados no D O S fornecem a funo textattr,; que lhe permite selecionar as
cores de frente e de fundo que voc quer para a exibio do texto. Para simplificar o processo de atribuir uma
cor de fundo, voc pode usar a funo textbackground, como mostrado aqui:
#include <conio.h>

void textbackground(int corfundo);


O parrhetro backgroundcolor especificar um dos valores de cores listados na Tabela 316:
Tabela 316 Valores vlidos de cores de fundo.
Constante de C or Valor Constante de C or Valor
BLACK (Preto) 0 RED (Vermelho) 4
BLUE (Azul) 1 M AG ENTA (Magenta) 5
GREEN (Verde) 2 B RO W N (Marrom) 6
C YA N (Ciano) 3 LIGHTGRA Y (Cinza claro) 7

O programa a seguir, fundo, c, usa a funo textbackground para exibir as diferentes cores de fundo:
#include <conio.h>

void main(void)

int cor;

for (cor = 0; cor < 8; cor++)


{
textbackground(cor);
cprintf("Esta a cor %d\r\n", cor);
cprintf("Pressione qualquer tecla para continuar\r\n");
getch();
>
}

317 c o n tro la n d o a I n t e n s id a d e do T exto


Como voc aprendeu, muitos compiladores baseados no DOS fornecem funes que lhe permitem controlar a
sada na tela. Ao usar essas funes para escrever texto na tela, voc ir querer controlar a intensidade (brilho)
das informaes que seus programas escrevem na tela. Para controlar a intensidade, voc poder usar uma das
trs funes a seguir para selecionar a intensidade da sada do texto:
Op e r a e s d e t ec la d o 165

#include <conio.h>

void highvideo(void);
void lowvideo(void);
void normvideo(void);
As funes controlam a intensidade com a qual sua tela exibir texto. O programa a seguir, intensid.c, ilus
tra como usar essas trs funes:
iinclude <conio.h>

void main(void)
{
clrscr();
highvideo();
cprintf("Este texto est em alta intensidae\r\n);
lowvideo();
cprintf("Este texto est em baixa intensidade\r\n");
normvideo();
cprintf("Este texto est em video normal\r\n");
>

D e t e r m in a n d o o M od o At u a l do Texto 318
Como voc sabe, muitos compiladores baseados no DOS fornecem funes que seus programas podem usar para
controlar a sada baseada em texto. Quando seus programas efetuam sada na tela, eles precisam conhecer e pos
sivelmente alterar o modo de texto atual do PC. Por exemplo, um programa que espera 80 colunas exibir re
sultados inconsistentes em uma tela que esteja no modo de 40 colunas. Para ajudar seus programas a alterar o
modo de texto atual, seus programas podem usar a funo textmode, como mostrado aqui:
#include <conio.h>

void textmode(int modo_desejado);


O parmetro modo_desejado especifica o modo de texto que voc deseja. A Tabela 318 lista os modos de
textos vlidos.
Tabela 318 Operaes vlidas do modo de texto.
Constante Valor M odo de Texto
LASTM ODE -1 Modo anterior
BW 40 0 Branco e preto em 40 colunas
C40 1 40 colunas em cores
BW 80 2 80 colunas, branco e preto
C80 3 80 colunas, colorido
M ONO 7 80 colunas, monocromtico
C4350 64 EGA de 43 linhas ou VGA de 50 linhas

Por exemplo, o comando a seguir selecionar um modo de 43 linhas em um monitor EGA ou modo de
50 linhas em um monitor VGA:
textmode(C4350) ;
Nota: Se voc usar textmode para alterar o modo atual da tela, a mudana permanecer em efeito aps seu programa
terminar.

M o v en d o Texto da Te l a de um Lo c a l para Ou tro 319


Voc aprendeu que muitos compiladores baseados no DOS oferecem funes que lhe permitem controlar a sada
do texto. Se seu programa realizar muita sada na tela, algumas vezes voc poder querer copiar ou mover o texto
166 P rog ram and o em C/C++ A B b l ia

que aparece em uma seo da sua tela para outra seo. Para copiar texto na tela, seus programas podem usar a
funo movetext, como mostrado aqui:
#include <conio.h>

int movetext(int esq, int topo, int dir, int base,


int destino_esq, int destino_topo);
Os parmetros esq, topo, dir e base descrevem uma caixa que delimita a regio de texto que voc quer mo
ver. Os parmetros destino_esq e destino_topo especificam a localizao desejada do canto superior esquerdo da
caixa. O programa a seguir, movetext.c, escreve cinco linhas de texto na tela, e, depois, pede para voc pressionar
uma tecla. Ao fazer isso, o programa copiar o texto para uma nova posio, como mostrado aqui:
#include <conio.h>

void main(void)
{
int i;

clrscr();
for (i = 1; i <= 5; i++)
cprintf("Esta a linha %d\r\n", i);
cprintf("Pressione qualquer tecla\n\r");
getch();
movetextd, 1, 30, 6, 45, 18);
gotoxy(l, 24);
>
Para moVer o texto para a nova posio, em vez de apenas copiar o texto para a nova posio, voc precisa
excluir o texto original aps o programa completar a operao movetext.

320 D e fin in d o um a J a n e la de T ex to
Sabemos que muitos compiladores com base no DOS fornecem funes que seus programas podem usar para
controlar melhor a sada na tela. Por padro, essas funes escrevem sua sada na tela inteira. Dependendo do
propsito do seu programa, algumas vezes voc desejar restringir a sada do programa para uma regio especfica
na tela. Para fazer isso, seus programas podem usar a funo window, como mostrado aqui:
#include <conio.h>

void window(int esq, int topo, int dir, int base);


Os parmetros esq, topo, d ir t base definem os cantos superior esquerdo e inferior direito de uma regio de
tela dentro da qual voc quer escrever a sada. O programa a seguir, janela.c, restringe a sada do programa ao
quadrante superior esquerdo da tela:
#include <conio.h>

void main(void)
{
int i, j;

window(l, 1, 40, 12);


for (i = 0; i < 15; i++)
{
for (j = 0; j < 50; j++)
cprintf(%d", j);
cprintf("\r\n");
>
}

Quando a sada do programa atinge o canto direito da tela, a sada quebra para a prxima linha. Aps o
programa terminar, as operaes de sada tero acesso tela inteira.
Matemtica i67

Usan d o o Va lo r A bso lu t o de uma E x p r e s s o I n t e ir a 321


O valor absoluto especifica a distncia do valor de 0. Os vaJores absoluros so sempre positivos. Por exemplo, o
valor absoluto de 5 5. Da mesma forma, o valor absoluto de -5 5. Para ajudar seus programas a determinar
um valor absoluto, C fornece a funo abs, que retorna o valor absoluto de uma expresso inteira. Voc cons
truir a funo abs como mostrado aqui:
#include <stdlib.h>

int abs(int expresso);


O programa a seguir, exib_abs.c, ilustra como usar a funo abs:
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
printf("O valor absoluto de %d %d\n", 5, abs(5));
printf("O valor absoluto de %d %d\n, 0, abs(0));
printf("O valor absoluto de %d %d\n", -5, abs(-5));
>
Quando voc compilar e executar o programa exib_abs.c, sua tela exibir o seguinte:
O valor absoluto de5 5
O valor absoluto de0 0
O valor absoluto de -5 5
C:\>
Nota: Muitos compiladores C tambmfornecem a labs, que retoma o valor absoluto para uma expresso do tipo long int.

U s a n d o o A r c o C o -s e n o 322
O arco co-seno a relao entre a hipotenusa de um tringulo retngulo e o cateto adjacente de um determinado
ngulo agudo. Em outras palavras, o arco co-seno o inverso geomtrico do co-seno de um ngulo. Em outras
palavras, se y o co-seno de algum ngulo teta, teta o arco co-seno de y. Para ajudar seus programas a deter
minar o arco co-seno, C fornece a funo acos. A funo acos retorna o arco co-seno de um ngulo (de 0 a pi)
especificado em radianos (como tipo double), como mostrado aqui:
#include <math.h>

double acos(double expresso);


Se a expresso especificada no estiver no intervalo de -1.0 at 1.0, acos definir a varivel global ermo para
E D O M e exibir um erro D O M A1N em stderr. O programa a seguir, exi^acos.c, ilustra como usar a funo acos:
#include <stdio.h>
ttinclude <math.h>

void main(void)
{
double radianos;

for (radianos= -0.5; radianos <= 0.5; radianos + = 0.2)


printf("% %f\n", radianos, acos(radianos));
>
Nota: Muitos compiladores C tambm fornecem a funo acosl, que retorna o valor arco co-seno para uma expresso
long double.
168 P rog ram and o em C/C++ A B b l ia

323 Usa n d o o A rco S en o


O arco seno a relao entre a hipotenusa de um tringulo retngulo e o cateto oposto a um determinado ngulo
agudo. Em outras palavras, o arco seno o inverso geomtrico do seno de um ngulo. Se y o seno de algum
ngulo teta, ento teta o arco seno de y. Para ajudar seus programas a determinar o arco seno, C fornece a fun
o acos. A funo acos retorna o arco seno de um ngulo (-pi/2 at pi/2), especificado em radianos (como tipo
double), como mostrado aqui:
#include <math.h>

double asin(double expresso);


Se expresso no estiver no intervalo de -1.0 at 1.0, ento asin definir a varivel global ermo para NAN,
e exibir um erro D O M A IN em stderr. O programa a seguir, exi_asin.c, ilustra como usar a funo asin:
#include <stdio.h>
#include <math.h>

void main(void)
{
double radianos;

for (radianos = -0.5; radianos < <=0.5; radianos += 0.2)


printf("% %f\n, radianos, asin(radianos));
>
Nota: Muitos compiladores C tambm fornecem a funo asinl, que retoma o valor arco seno para uma expresso
long double.

324 Usan d o o A r c o Ta n g e n t e
O arco tangente a relao entre o cateto adjacente a um dado ngulo agudo e o cateto oposto a esse ngulo
em um tringulo retngulo. Em outras palavras, o arco tangente o inverso geomtrico da tangente de um n
gulo. Se y a tangente de um ngulo teta, teta o arco tangente de y. Para ajudar seus programas a determinar
o arco tangente, C fornece a funo atan. A funo atan retorna o arco tangente de um ngulo (-pi/2 at pi/2),
especificado em radianos (como tipo double), como mostrado aqui:
ttinclude <math.h>

double atan(double expresso);


O programa a seguir, exi_atan.c, ilustra como usar a funo atan:
#include <stdio.h>
#include <math.h>

void main(void)
{
double radianos;

for (radianos = -0.5; radianos< = 0.5; radiemos += 0.2)


printf("%f %f\n, radianos, atan(radianos));
}
Nota: Muitos compiladores C tambm fornecem a funo atanl, que retoma o valor do arco tangente para uma ex
presso long double. Alm disso, C fornece as funes atan2 e atan2l, que retomam o arco tangente de y/x.

325 Obten d o o Va lo r A b so lu t o de um N m e r o Co m p l e x o
Como voc aprendeu, um nmero complexo contm uma parte real e uma parte imaginria. As funes de C repre
sentam os nmeros complexos como uma estrutura com um membro x e um membro y, como mostrado aqui:
Matemtica 169

struct complex
{
double x, y;
>
Quando voc trabalhar com nmeros complexos, algumas vezes precisar calcular o valor absoluto do n
mero (sua distncia positiva do zero). Para permitir que seu programa calcule o valor absoluto de um nmero
complexo, C fornece a funo cabs, como mostrado aqui:
tinclude <math.h>

double cabs(struct complex valor);


A funo cabs similar a tirar a raiz quadrada da soma do quadrado de cada nmero complexo. No exem
plo a seguir, a funo cabs retornar (102 + 52) 1/2. O programa a seguir, exi_cabs.c, ilustra como usar a funo
cabs da linguagem C:
#include <stdio.h>
#include <math.h>

void main(void)
{
struct complex num_complexo;

num_complexo.x = 10;
num_complexo.y = 5;
printf("O valor absoluto de 10,5 %f\n", cabs(num_complexo));
>
Quando voc compilar e executar o programa exi_cabs.c, sua tela exibir a seguinte sada:
O valor absoluto de 10,5 11.180340
C:\>
Nota: Muitos compiladores C tambm fornecem a funo cabls, que retoma um valor absoluto para nmeros com
plexos long double.

Arred o n d an d o para C im a um Va lo r em P onto


Flutuan te 326
Quando voc trabalha com nmeros em ponto flutuante, algumas vezes precisa arredondar o valor de uma va
rivel em ponto flutuante ou de uma expresso para o valor inteiro mais alto. Para esses casos, C fornece a funo
ceil, como mostrado aqui:
#include <math.h>

double ceil(double valor);


Como voc pode ver, ceil recebe um parmetro do tipo double e retorna um valor do tipo double. O pro
grama a seguir, exi-ceil.c, ilustra como usar a funo ceil
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("O valor %f arredondado para %f\n", 1.9, ceil(1.9));
printf("O valor %f arredondado para %f\n", 2.1, ceil(2.1));
>
Quando voc compilar e executar o programa exi_ceil.c, sua tela exibir a seguinte sada:
170 Program ando em C/C++ A Bblia

O valor 1.900000 arredondado para 2.00000


O valor 2.100000 arredondado para 3.00000
C:\>
Nota: Muitos compiladores tambm fornecem a juno ceill, que arredonda para cima um valor do tipo long double.

327 u sa n d o o C o -s e n o d e um n g u lo
Em um tringulo retngulo, o co-seno de um ngulo o quociente do cateto adjacente pela hipotenusa. Para aju
dar seus programas a determinar o co-seno, C fornece a funo cos. A funo cos retorna o co-seno de um ngulo,
especificado em radianos (como tipo doubl), como mostrado aqui:
tinclude <math.h>

double cos(double expresso);


A funo cos retorna um valor no intervalo de -1.0 at 1.0. O programa a seguir, exib_cos.c, ilustra como
usar a funo cos:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("O co-seno de pi/2 %6.4f\n", cos(3.14159/2.0));
printf("O co-seno de pi %6.4f\n,cos(3.14159));
>
Quando voc compilar e executar o programa exib_cos.c, sua tela exibir o seguinte resultado:
O co-seno de pi/2 0.0000
O co-seno de pi -1.0000
C:\>
Nota: Muitos compiladores C tambm fornecem a funo cosi, que retorna o valor do co-seno para uma expresso
long double.

328 Usan d o o C o -s e n o H i p e r b l i c o de um n g u lo
O co-seno hiperblico de um ngulo o co-seno de um ngulo "na forma circular" definido, usando relaes
de radianos hiperblicos. Para ajudar seus programas a determinar o co-seno hiperblico, C fornece a funo
cosh. A funo cosh retorna um'co-seno hiperblico de um ngulo "circular", especificado em radianos (como
tipo doubl), como mostrado aqui:
#include <math.h>

double cosh(double expresso);


Se ocorrer extravasamento, cosh retornar o valor HUGE_VAL (ou _LHUGE_VAL para cosh) e definir a
varivel giobaJ ermo como ERANGE. O programa a seguir, exi_cosh.c, ilustra como usar a fiino cosh:
#include <stdio.h>
#include <math.h>

void main(void)
{
double radianos;

for (radianos = -0 .5 ; radianos< = 0 .5 ; radianos + = 0 .2 )


printf("%f %f\n", radianos, cosh(radianos));
>
Matemtica 171

Nota: Muitos compiladores C tambm fornecem a funo cosbl, que retoma o valor do co-seno hiperblico para uma
expresso long double.

Usan d o o S en o de um n gulo 329


Em um tringulo retngulo, o seno de um ngulo o quociente entre o cateto oposto e a hipotenusa. Para ajudar
seus programas a determinar o seno, C fornece a funo sin. A funo sin retorna o seno de um ngulo, espe
cificado em radianos (como tipo double), como mostrado aqui:
#include <math.h>

double sin(double expresso);


O programa a seguir, exib_sin.c, ilustra como usar a funo sin:
#include <stdio.h>
#include <math.h>

void main(void)
{
double radianos;

for (radianos = 0.0; radianos < 3.1; radianos + = 0.1)


printf("O seno de %f %f\n", radianos, sin(radianos));
>
Nota: Muitos compiladores C tambm fornecem a funo sinl, que retoma o valor do seno para uma expresso long
double. .

U s a n d o o S e n o H ip e r b l ic o de um n gulo 330
O seno hiperblico de um ngulo o seno de um ngulo na forma circular definido, usando relaes de ra
dianos hiperblicos. Para ajudar seus programas a determinar o seno hiperblico, C fornece a funo sinh. A fun
o sinh retorna um seno hiperblico na forma circular, especificado em radianos (como tipo double), como
mostrado aqui:
#include <math.h>

double 8nh(double expresso);


Se ocorrer extravasamento, sinh retornar o valor HUGE_VAL (ou _LHUGE_VAL para sinhl), e definir
a varivel global ermo como ERANGE. O programa a seguir, ex_sinh.c, ilustra como usar a funo sinh:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

void main(void)
{
double radianos;
double result;

for (radianos = 0.0; radianos < 3.1; radianos += 0.1)


if (((result = sinh(radianos)) == HUGE_VAL) && (errno == ERANGE))
printf("Erro de extravasamento\n");
else
printf("O seno de %f %f\n", radianos, result);
>
Nota: Muitos compiladores C tambm fornecem a funo sinhl, que retoma o valor seno hiperblico para uma ex
presso long double.
172 P ro g ra m a n d o em C/C++ A B b lia

331 Usa n d o a Ta n g e n t e de um n g u lo
Em um tringulo, a tangente de um ngulo a relao entre o cateto oposto e o cateto adjacente. Para ajudar
seus programas a determinar a tangente, C fornece a funo tan. A funo retorna a tangente de um ngulo, es
pecificada em radianos (como tipo doubl), como mostrado aqui:
#include <math.h>

double tan(double expresso);


O programa a seguir, exib_tan.c, ilustra como usar a funo tan:
#include <stdio.h>
#lnclude <math.h>

void main (void)


{
double pi = 3,14159265;
printf ("A tangente de pi %f\n", tan (pi));
printf ("A tangente de pi/4 %f\n", tan (pi/4.0));
>
Quando voc compilar e executar o programa exibe_tan.c, sua tela exibir o seguinte resultado:
A tangente de pi - 0.000000
A tangente de pi/4 1.000000
C:\>
Nota: Muitt/s compiladores C tambm fornecem a funo tanl, que retoma o valor tangente para uma expresso long
double.

332 Usa n d o a Ta n g e n t e H i p e r b l i c a de um n g ulo


A tangente hiperblica de um ngulo a tangente de um ngulo "na forma circular" definida, usando relaes
de radianos hiperblicos. Para ajudar seus programas a determinar a tangente hiperblica, C fornece a funo
tanh. A funo tanh retorna a tangente hiperblica de um ngulo, especificada em radianos (como tipo doubl),
como mostrado aqui:
#include <math.h>

double tanh(double expresso);


Nota: Muitos compiladores C tambm fornecem tanhl, que retoma o valor tangente hiperblico para uma expresso
long double.

333 r e a l iz a n d o a D iv is o I n t e ir a
Como voc aprendeu, C fornece operadores de diviso (/) e de mdulo (%) que permitem que seus programas
efetuem uma diviso para determinar o resto de uma operao de diviso. Similarmente, C fornece a funo div,
que divide um valor numerador por um denominador, retornando uma estrutura do tipo div_t que contm o
quociente e o resto, como mostrado aqui:
struct div_t
{
int quot;
int rem;
> div_t;
A funo div trabalha com valores inteiros, como mostrado aqui:
#include <stdlib.h>

div_t div(int numerador, int denominador);


Matemtica 173

O programa a seguir, div_rest.c\ ilustra como usar a funo div:


#include <stdio.h>
#include <stdlib.h>

void main(void)
{
div_t result;

result * div(ll, 3);


printf(ll dividido por 3 %d resto %d\n", result.quot, result.rem);
>
Quando voc compilar e executar o programa div_rest.c, sua tela exibir a seguinte sada:
11 dividido por 3 3 resto 2
C:\>
Nota: Muitos compiladores C tambm fornecem a funo Idiv, que retoma o quociente e o resto para valores long.

Tr a b a l h a n d o com E x p o n e n c ia l 334
Quando seus programas efetuam operaes matemticas complexas, freqentemente precisam calcular o expo
nencial de ex. Nesses casos, seus programas podem usar a funo exp, que retorna um valor do tipo double, como
mostrado aqui:
#include <math.h>
double exp(double x);
O programa a seguir, exib_exp.c, ilustra como usar a funo exp:
#include <stdio.h>
#include <math.h>
void main(void)
{
double valor;
for (valor = 0.0; valor <= 1.0; valor += 0.1)
printf("exp(%f) %f\n", valor, exp(valor));
>
Nota: Muitos compiladores C tambm fornecem a funo expl, que trabalha com valores do tipo long double.

Usan d o o Valo r Abso lu to de uma Ex p r e s s o em

P onto Flu t u a n t e 335


Como voc aprendeu, o valor absoluto especifica a distncia de um valor at o zero. Os valores absolutos so sem
pre positivos. Por exemplo, o valor absoluto de 2.5 2.5. Da mesma forma, o valor absoluto de -2.5 2.5. Quan
do voc trabalhar com valores absolutos, algumas vezes precisar calcular o valor absoluto de uma expresso em
ponto flutuante. Para esses casos, C fornece a funo fabs, que retorna o valor absoluto para um nmero em pon
to flutuante, como mostrado aqui:
#include <math.h>
float fabs(float expresso);
O programa a seguir, exi_fabs.c, ilustra como usar a funo fabs:
#include <stdio.h>
#include <math.h>
void main(void)
174 P rog ram and o em C/C++ A B b l ia

{
float valor;

for (valor = -1.0; valor < 1.0; valor += 0.1)


printf("Valor %f fabs %f\n", valor, fabs(valor));
>

336 Usa n d o o Resto em po n to Flutu a n te


Na Dica 82 voc aprendeu como usar o operador mdulo (%) de C para obter o resto de uma diviso inteira.
Dependendo do seu programa, algumas vezes voc desejar conhecer o resto de uma diviso em ponto flutuante.
Nesses casos, seus programas podem usar a funo fm od de C para dividir dois valores em ponto flutuante. A
funo fm o d retornar o resto como um valor em ponto flutuante, como mostrado aqui:
#include <math.h>

double fmod(double x, double y);


Como um exemplo, se voc chamar fm od com os valores 10.0 e 3.0, fm od retornar o valor 1.0 (10 divi
dido por 3 3 e o resto 1). O programa a seguir, exi_fmod.c ilustra como usar a funo fmod:
#include <stdio.h>
#include <math.h>

void main(void)
{
double numerador = 10.0;
double denominador = 3.0;

printf("fmod(10, 3) %f\n", fmod(numerador, denominador));


>
Quando voc compilar e executar o programa exi_Jmod.c, sua tela exibir a seguinte sada:
fm o d ( 1 0 , 3) 1 .0 0 0 0 0 0
C :\>
Nota: Muitos compiladores C tambm fornecem afuno fmodl, que retoma a partefracionria de um valor long double.

337 Usa n d o a Ma n t is s a e o Ex po en t e de um Va l o r em

P onto F lu t u a n t e
Quando seus programas trabalham com valores em ponto flutuante, o computador armazena os valores usando
uma mantissa (cujo valor est entre 0.5 e 1.0) e um expoente, como mostrado na Figura 337.

4 Bytes

r----------------------- 1---------------------------1

I I I I I I I I IIN IllllllM lllllll.il.


I--------------------------------------1------------------------------
Bit de Sinal Expoente de 8 bits Mantissa de 23 bits
Figura 337 O computador armazena valores em ponto flutuante usando um formato de mantissa e de expoente.

Para determinar o valor armazenado, o computador combina a mantissa e o expoente, como mostrado aqui:
valor = mantissa * (2 * expoente);
Normalmente, voc no precisa saber que o computador est usando a mantissa e o expoente. No entanto,
dependendo do seu programa, algumas vezes voc poder querer conhecer os valores da mantissa e do expoente.
M a t e m t ic a 175

Para esses casos, C fornece a funo frexp, que retorna a mantissa e atribui o expoente varivel expoente, que
a funo chamadora precisa passar para a funo frexp por referncia:
ttinclude <math.h>

double frexp(double valor, int expoente);


O programa a seguir, frexp.c, ilustra como usar a funo frexp:
#include <stdio.h>
#include <math.h>

void main (void)


{
double valor = 1.2345;
double mantissa;
int exponente;

mantissa = frexp(valor, &expoente);


printf("Mantissa % Expoente %d Valor %f\n,
mantissa, expoente, mantissa * pow(2.0, 1.0 * expoente));
>
Quando voc compilar e executar o programa frexp. c, sua tela exibir a seguinte sada:
Mantissa 0.617250 Expoente 1 Valor 1.234500
C:\>
Nota: Muitos compiladores C tambm fornecem a funo frexpl, que retoma o expoente e a mantissa de um valor
long double.

C a lc u la n d o o R e s u lt a d o de x * 2e 338
Na Dica 334 voc aprendeu como usar a funo exp de C para obter o resultado ex. Dependendo de seus pro
gramas, algumas vezes voc precisar calcular x * 2c. Nessas situaes, voc poder usar a funo Idexp, como
mostrado aqui:
#include <math.h>

double ldexp(double valor, int expoente);


O programa a seguir, Idexp.c, ilustra como usar a funo Idexp:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("3 * 2 elevado potncia 4 %f\n", Idexp(3.0, 4));
}
Quando voc compilar e executar o programa Idexp. c, sua tela exibir a seguinte sada:
3*2 elevado potncia 4 48.000000
C:\>
Nota: Muitos compiladores C tambm fornecem a funo Idexpl para suportar valores long double.

Ca l c u l a n d o o L o g a r it m o N a t u r a l 339
O logaritmo natural de um nmero a potncia a qual e precisa ser elevado para ser igual ao nmero dado. Para
ajudar seus programas a determinar o "logaritmo natural", C fornece a funo log, que retorna o logaritmo na
tural de um valor em ponto flutuante:
176 P ro g ra m a n d o em C/C++ A B b lia

ttinclude <math.h>

double log(double valor);


Se o parmetro valor for menor que 0, log definir a varivel global ermo como ERANGE, e retornar o
valor HUGE__VAL (ou _LHUGE_VAL para logl). O programa a seguir, txibjog.c, ilustra o uso da funo log:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("0 logaritmo natural de 256.0 %f\n", log(256.0));
>
Quando voc compilar e executar o programa exib_log.c, sua tela exibir a seguinte sada:
O logaritmo natural de 256.0 5.545177
C:\>
Nota: Muitos compiladores tambm fornecem a funo logl, que retoma o logaritmo natural de uma expresso long
double.

340 Ca l c u l a n d o o Resu lta d o d e l o g IO x


Voc viu na dica anterior como usar a funo log para calcular um logaritmo natural. medida que seus pro
gramas efetuarem operaes matemticas, algumas vezes voc precisar determinar o logaritmo de base 10 de um
valor (comumente escrito como logIOx). Para esses casos, C fornece a funo loglO, como mostrado aqui:
#include <math.h>

double loglO(double valor);


Se o parmetro valor for 0, loglO definir a varivel global ermo com EDOM, e retornar o valor
HUGE_VAL (ou _LHUGE_VAL para logl01). O programa a seguir, log_10.c, ilustra como usar a funo loglO:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("O loglO de 100 %f\n", loglO ( 1 0 0 . 0 ) ) ;
printf("O loglO de 1 0 0 0 0 %f\n", loglO ( 1 0 0 0 0 .0 ) );
>
Quando voc compilar e executar o programa log_10.c, sua tela exibir a seguinte sada:
LoglO de 100 2.000000
LoglO de 10000 4.000000
C: \>
Nota: Muitos compiladores C tambm fornecem a funo loglOl, que suporta valores long double.

341 D e t e r m in a n d o os V a l o r e s M x im o e M n im o
Quando seus programas comparam dois nmeros, algumas vezes voc deseja conhecer o mximo e o mnimo
dentre dois valores. Para esses casos, o arquivo de cabealho stdlib.h fornece as macros min e max. O programa
a seguir, min_max.c, ilustra como usar essas duas macros:
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
Matemtica 177

1. N.R.T.: Se seu com pilador no definir as m acros min e max, voc precisar incluir am bas as declaraes #define no
incio do seu arquivo-fonte.
178 PROGRAMANDO EM C/C + + A BBLIA

#include <stdio.h>
#include <math.h>

void main(void)
{
int potncia;

for (potncia -2; potncia <= 2; potencia++)


printf("10 elevado a %d %f\n", potncia, pow(10.0, potncia));
>
Quando voc compilar c executar o programa exib_pow.c, sua tela exibir a seguinte sada:
10 elevado a -2 0.010000
10 elevado a -1 0.100000
10 elevado a 0 1.000000
10 elevado a 1 10.000000
10 elevado a 2 100.000000
C;\>

Nota: Muitos compiladores C tambm oferecem a funo pou/l, que suporta valores do tipo long double. Da mesma
forma, se voc estiver trabalhando com valores complexos, o arquivo de cabealho complex.h definir um prottipo de
funo para pou> que trabalha com nmeros complexos.

344 Ca l c u l a n d o o R esu lta d o de 10 x


N a dica anterior voc viu como usar a funo pow para determinar o resultado de um valor elevado a uma dada
potncia. Algumas vezes seus programas precisaro calcular o resultado de 10*. Nesses casos, voc poder usar a funo
pow, ou, se seu compilador suportar (como o Turbo C++ Lite), poder usar powlO de C, como mostrado aqui:
#include <math.h>

double pow(int potncia);


O programa a seguir, powlO.c, ilustra como usar a funo powlO:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("10 elevado a -1 %f\n", powlO(-l));
printf("10 elevado a 0 %f\n",powl0(0));
printf("10 elevado a 1 %f\n",powlO(l));
printf("10 elevado a 2 %f\n",.powl0(2));
>
Quando voc compilar e executar o programa powlO.c, sua tela exibir a seguinte sada:
10 elevado a-1 0.100000
10 elevado a 01.000000
10 elevado a1 10.000000
10 elevado a2 100.000000
c: \>
Nota: Muitos compiladores C tambm fornecem a funo pow 1 OU que suporta valores do tipo long double.

345 Geran do um N m e r o A l e a t r io
Dependendo do seu programa, algumas vezes voc precisa gerar um ou mais nmeros aleatrios. Para esses casos,
C oferece duas funes, rand e random, que retornam nmeros inteiros aleatrios, como mostrados aqui:
Matemtica 179

#include <stdlib.h>

int rand(void);
int random(int teto);
A primeira funo, rand, retorna um nmero inteiro aleatrio no intervalo de 0 at RAN D _M AX(definido
em stdlib.h). A segunda funo, random, retorna um nmero aleatrio no intervalo at teto, onde teto o tama
nho do nmero aleatrio mximo, que a funo chamadora passa para a funo random. O programa a seguir,
aleatori.c, ilustra como usar ambos os geradores de nmeros aleatrios:
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
int i;

printf("Valores de rand\n");
for (i = 0; i < 100; i++)
printf("%d ", rand());

printf("Valores de random(100))\n");
for (i = 0; i < 100; i++)
printf("%d ", random(100));

M a p e a n d o V a l o r e s A l e a t r io s para um In t e r v a lo
E s p e c f ic o 346
Na Dica 345, voc aprendeu que as funes rande random retornam nmeros aleatrios. Quando seu programa
gerar nmeros aleatrios, algumas vezes ele precisar mapear os valores para um intervalo especfico. Se voc es
tiver trabalhando com valores inteiros, poder usar a funo random usando um parmetro para especificar o va
lor mais alto no intervalo dos nmeros aleatrios. No entanto, se voc estiver trabalhando com valores em ponto
flutuante, tais como valores no intervalo de 0.0 at 1.0, poder dividir o nmero por uma constante para derivar
um nmero em ponto flutuante. Para mapear uma srie de inteiros aleatrios em uma srie de nmeros de ponto
flutuante, simplesmente divida o nmero aleatrio pelo limite superior do nmero aleatrio, como mostrado
aqui:
random(100)/100;
Esse exemplo gera um valor aleatrio no intervalo de 0.01 at 0.99. Se seu programa precisar de mais d
gitos no nmero aleatrio em ponto flutuante, voc poder gerar um nmero aleatrio at 1000 e dividir por
1000, como mostrado aqui:
random(lOOO)/1000;
O exemplo anterior gera um valor aleatrio no intervalo de 0.001 at 0.999. Se seu programa precisar de
mais preciso nos seus nmeros aleatrios, simplesmente aumente o tamanho no inteiro aleatrio mximo e a
constante pela qual voc divide o resultado de random. O programa a seguir, mapa_ale.c; mapeia os nmeros
aleatrios para o intervalo de 0.0 at 1.0 e valores inteiros para o intervalo de -5 at 5:
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
int i;

printf("Valores de random\n");
for (i = 0; i < 10; i++)
180 P rogram and o em /C++ A B b l ia

printf("%f\n", random(100)/100);
printf("Valores de random(-5) at random(5)\n");
for (i = 0; i < 100; i++)
printf("%d\n", random(10)-5);
>

347 I n ic ia l iz a n d o o G erad o r de N m e r o s A l e a t r io s
A Dica 345 apresentou as funes rande random de C que voc usar dentro de seus programas para gerar n
meros aleatrios. Quando voc trabalhar com nmeros aleatrios, algumas vezes desejar controlar as sries de
nmeros que o gerador de nmero aleatrio cria (para que voc possa testar o processamento do seu programa
com o mesmo conjunto de nmeros). Tambm haver situaes onde voc ir querer que o gerador crie nmeros
reais aleatoriamente. O processo de atribuir o nmero inicial do gerador de nmeros aleatrios chamado de
inicializar o gerador. Para lhe ajudar a inicializar os geradores de nmeros aleatrios, C fornece duas funes, ran-
domize e srand como mostrado aqui:
#include <stdlib.h>

void randomize(void);
void srand(unsigned semente);
A primeira funo, randomize, usa o relgio do PC para produzir uma semente aleatria. Por outro lado,
a segunda funo, srand lhe permite especificar o valor inicial do gerador de nmeros aleatrios. Seus programas
podero usar srand para controlar o intervalo de nmeros que o gerador de nmeros aleatrios criar. O progra
ma a seguir, inicial, c, ilustra como usar as funes srand e. randomize:
ttinclude <stdio.h>
ttinclude <time.h>
ttinclude <stdlib.h>

void main(void)
{
int i;

srand(100);
printf("Valores de rand\n");
for (i = 0; i < 5 ; i++)
printf("%d ", rand());
printf("NnMesmos 5 nmeros\n");
srand(100);
for (i = 0; i < 5; i++)
printf("%d ", rand());
randomize();
printf(\n5 nmeros diferentes\n");
for (i = 0; i < 5; i++)
printf ("%d ", randO);
>

348 Ca l c u l a n d o a R a iz Q u a d r a d a de um Valo r
Quando seus programas calculam expresses matemticas, eles freqentemente precisam executar operaes de
raiz quadrada. Para ajudar seus programas a realizar as operaes de raiz quadrada, C fornece a funo sqrt, como
mostrado aqui:

ttinclude <math.h>

double sqrt(double valor);


A funo sqrt trabalha somente com valores positivos. Se seu programa chamar sqrt com um valor negativo,
sqrt definir a varivel global ermo como EDOM. O programa a seguir, sqrt. c, ilustra como usar a funo sqrt:
Matemtica 181

Nota: Muitos compiladores C tambm oferecem a funo sqrtl, que retoma a raiz quadrada de um valor long double.

C r ia n d o uma R o t in a de Tratam en to de Erro


M a t e m t ic o 349
Vrias funes apresentadas nesta seo detectam erros de intervalo e de extravasamento. Por padro, quando es
ses erros ocorrem, as funes chamam uma funo especial chamada matherr, que efetua processamento adicio
nal, tal como atribuir varivel global ermo um nmero de erro especfico. Se seus programas definirem suas
prprias funes matherr, as rotinas matemticas de C chamaro sua rotina de tratamento personalizada. Quan
do as rotinas matemticas chamarem sua funo matherr, elas passaro para matherr um ponteiro para uma va
rivel do tipo exception, como mostrado aqui:
struct exception
{
int'type;
char *function;
double argl, arg2, retval;
};
O membro type contm uma constante que descreve o tipo do erro. A Tabela 349 descreve os valores dos erros.
Tabela 349 Constantes de C que descrevem os erros matemticos.
Valor do Erro Significado
D O M A IN Um argumento est fora do domnio de valores que a funo suporta
OVERFLOW Um argumento produz um resultado que extravasa o tipo do resultado
SIN G Um argumento produz um resultado em uma singularidade
TLOSS Um argumento produz um resultado no qual todos os dgitos da preciso
so perdidos
UNDERFLOW Um argumento produz um resultado que extravasa o tipo de resultado

O membro function contm o nome da rotina que experimentou o erro. Os membros argl e arg2 contm
os parmetros que a funo que est experimentando o erro passou para matherr; enquanto retval contm um
valor de retorno padro (que voc pode atribuir). Se matherr no puder determinar a causa especfica do erro,
matherr exibir uma mensagem de erro genrica na tela. O programa a seguir, matherr. c, ilustra como usar uma
rotina de tratamento de erro personalizada:
#include <stdio.h>
#include <math.h>

void main(void)
{
printf("A raiz quadrada de -1 %f\n", sqrt(-l.O));
>

int matherr(struct exception *erro)


{
182 P rogram ando em C/C++ A B b u a

switch (erro->type)
{
case DOMAIN: printf("Erro de dominio\n");
break;
case PLOSS: printf("Erro de perda de preciso parcial\n");
break;
case OVERFLOW: printf("Erro de extravasamento \n");
break;
case SING: printf("Erro na singularidade\n");
break;
case TtiOSS: printf ("Erro de perda da preciso total\n");
break;
case UNDERFLOW: printf("Erro de extravasamento\n");
break;
>;
printf("O erro ocorreu em %a valores %f\n", erro->name, erro->argl);
erro->retval = 1;
return(1);
>
Nota: A Juno matherr somente pega erros de domnio e de extravasamento. Para detectar erros de diviso por zero,
use signaL Muitos compiladores C tambm suportam a Juno matherrl, que suportam argumentos do tipo long double.

350 D e t e r m in a n d o a U n id a d e de D is c o A t u a l
Se seus programas trabalham no ambiente do DOS, algumas vezes voc precisa determinar a unidade de disco
atual. Nesses casos, seus programas podem usar a funo getdisk, como mostrado aqui:
#include <dir.h>

int getdisk(void);
A funo retorna um nmero da unidade de disco, onde 1 a unidade A, 2 a unidade B, e assim por
diante. O programa a seguir, LeUnid.c, usa a funo getdisk para exibir a letra da unidade de disco atual:
#include <stdio-h>
#include <dir.h>

void main (void)


{
printf("A unidade atual %c\n", getdiskO + 'A');
)
Nota: O CD-ROM que acompanha este livro inclui o arquivo win_getd.c, que efetua a mesma tarefa que o pro
grama LeUnid.c. mas trabalha somente sob o Windows 95 e sob o Windows N T.

351 S e l e c io n a n d o a U n id a d e A t u a l
N a dica anterior voc aprendeu como usar a funo getdisk para determinar a unidade de disco atual em um am
biente baseado no DOS. Exatamente como algumas vezes seus programas precisam determinar a unidade de
disco atual, outras vezes eles precisam selecionar uma unidade de disco especfica. Em tais casos, seus programas
podem usar a funo setdisk, como mostrado aqui:
#include <dir.h>

int setdisk(int unidade);


O parmetro unidade um valor inteiro que especifica a unidade desejada, onde 0 a unidade A, 1 a
unidade B, e assim por diante. A funo retorna o nmero de unidades de disco presentes no sistema. O pro
grama a seguir, selec_c.c, usa a funo setdisk para selecionar a unidade C como a unidade atual. O programa tam
bm exibe um contador do nmero de unidades disponveis (como definido pela entrada LASTDRJVE no
arquivo config.sys):
A r q u iv o s , d ir e t r io s e d is c o s 183

O parmetro unid um valor inteiro que especifica a unidade desejada, onde 0 a unidade A, 1 a uni
dade B, e assim por diante. A funo retorna o nmero de unidades de disco presentes no sistema. O programa
a seguir, selec_c.c, usa a funo setdisk para selecionar a unidade C como a unidade atuai. O programa tambem
exibe um contador do nmero de unidades disponveis (como definido pela entrada LASTDRIVE no arquivo
config.sys):
# i n c l u d e < s t d i o .h >
t t in c lu d e < d i r . h >

v o i d m a in ( v o id )
{
i n t c o n ta _ u n id ;
c o n ta _ u n id = s e t d i s k ( 3 ) ;
p r i n t f (" 0 nm ero d e u n i d a d e s d i s p o n v e i s % d \n ", c o n t a _ u n i d ) ;
}
Nota: O CD-ROM que acompanha este livro inclui o arquivo win_setd.cpp, que efetua a mesma tarefa que o pro
grama select_c.c, mas trabalha apenas sob o Windows 95 e sob o Windows N T.

D e t e r m in a n d o o E s p a o Dis p o n v e l no D is c o 352
Quando seus programas armazenam quantidades considerveis de informaes em um disco no importando
se esse disco um disquete, um disco rgido, ou outro tipo cada programa deve controlar o espao disponvel
no disco para reduzir a possibilidade de ficar sem espao durante uma operao crtica no disco. Se voc estiver
trabalhando em um sistema baseado no DOS, seus programas podem usar a funo getdfree. A funo getdfree
retorna uma estrutura do tipo dfree, como mostrado aqui:
s tr u c t d fre e
{
u n s ig n e d d f _ a v a i l ; // Agrupamentos disponveis
u n s ig n e d d f _ t o t a l ; // Total de agrupamentos
u n s ig n e d d f _ b s e c ; // Bytes por setor
u n s ig n e d d f _ s c l u s ; // Setores por agrupamento
}t
O formato da funo getdfree como segue:
i i n c l u d e < d o s .h >

v o id g e td f r e e ( u n s ig n e d c h a r u n id , s t r u c t d f r e e * d ta b e la ) ;
O parmetro unid especifica a unidade desejada, onde 1 a unidade A, 2 a unidade B, e assim por diante.
O programa a seguir, discoliv.c, usa a funo getdfire para obter informaes especficas sobre a unidade de disco atual:
# i n c l u d e < s t d i o .h >
f tin c lu d e < d o s .h >

v o i d m a in ( v o id )
{
s t r u c t d fre e in fo _ d is c o ;
lo n g e s p a c o _ d i s c o ;

g e td f r e e ( 3 , & in fo _ d is c o );
e s p a c o _ d i s c o = (lo n g ) i n f o _ d i s c o . d f _ a v a i l *
( lo n g ) i n f o _ d i s c o . d f J b s e c *
(lo n g ) i n f o _ d i s c o . d f _ s c l u s ;

p r i n t f ( "E sp ao d i s p o n v e l no d i s c o % ld \n " , e s p a c o _ d i s c o ) ;
)
184 P rogram and o em C/C++ A B b l ia

Nota: O CD-ROM que acompanha este livro inclui o arquivo win_free.cpp, que efetua a mesma tarefa que o pro
grama diskfree.c, mas trabalha apenas sob o Windows 95 e sob o Windows N T.

353 C u id a d o com o d b l s p a c e
Algumas dicas nesta seo mostram modos de executar operaes de leitura e escrita absoluta no disco que tra
balham com os setores de um disco. Antes que seus programas efetuem operaes de E/S de baixo nvel, certi
fique-se de que o disco que ser lido no um disco compactado com contedo que o dblspace ou outro utilitrio
de terceiros compactou anteriormente. Os discos compactados armazenam informaes em setores seqenciais.
Se voc gravar um setor de um disco compactado, correr um risco considervel de corromper o disco per
dendo as informaes que ele contm. Como regra, a maioria dos programa no precisa executar essas operaes
de leitura e gravao de baixo nvel no disco. Se voc estiver desenvolvendo um programa utilitrio de disco, tal como
o undelete, certifique-se de que voc saber como testar e trabalhar com discos compactados antes de iniciar.

354 Len d o as In f o r m a e s de uma Ta b e l a de A lo c a o


de A r q u iv o s
Se voc estiver trabalhando em um sistema baseado no DOS, a tabela de alocao de arquivos controlar quais partes
do seu disco estaro em uso, quais partes estar danificadas e quais partes estaro disponveis (para armazenamento de
arquivos e do programa). Se seus programas efetuam operaes de baixo nvel no disco, algumas vezes voc precisa
conhecer informaes, tais como o tipo do disco, bytes por setor, nmero de setores por agrupamento e o nmero
de agrupamentos no disco. Em tais casos, seus programas podem usar as funes getfat ou getfatd como mostrado aqui:
#inclue <dos.h>

void getfat(unsigned char unid, struct fatinfo *fat);


void getfatd(struct fatinfo *fat);
A funo getfat lhe permite especificar a unidade desejada, enquanto que getfatd retorna as informaes
para a unidade atual. Para especificar uma letra de unidade de disco para a funo getfat, especifique um valor
onde 1 a unidade A, 2 a unidade B, 3 a unidade C, e assim por diante. As funes getfat e getfatd atribuem
as informaes a uma estrutura do tipo fatinfo, como mostrado aqui:
struct fatinfo
{
char fi_sclus; II Setores por agrupamento (cluster)
char fi_fatid; II Tipo do disco
unsigned fi_nclus; // Agrupamentos por disco
int fi_bysec; // Bytes por setor
>;
O programa a seguir, getfatd.c, usa a funo getfatdipzta exibir informaes sobre a unidade de disco atual:
#include <stdio.h>
#include <dos.h>
void main(void)
{
struct fatinfo fat;
getfatd(fcfat);
printf("Setores por agrupamento %d\n, fat.fi_sclus);
printf("Agrupamentos por disco %u\n", fat.fi_nclus);
printf("Bytes por agrupamento %d\n", fat.fi_bysec);
printf("Tipo do disco %x\n", fat.fi_fatid & OxFP);
}
Nota: Se seu computador est rodando o Windows N T e voc particionou a unidade como uma unidade N T File
System (NTFS), no h uma tabela FA Tpara voc acessar. Para aprender mais sobre NTFS, visite o site do Depar
tamento de Cincia da Computao da Universidade de Yale em http://pclt.cis.yale.edu/pclt/BOOT/IFS.HTM
A r q u iv o s , d ir e t r io s e d is c o s 185

Co m p r e e n d e n d o a I d e n t if ic a o do D is c o 355
Na Dica 354 voc usou as funes getfat e getfatd para obter informaes sobre a unidade de disco atual. Como
viu, essas funes retornam um byte chamado fi_ fa tid que contm uma representao da identificao do disco
do DOS. A Tabela 355 especifica os possveis valores para fi_fatid
Tabela 355 Identificaes dos valores que o DOS retoma.
Valor (Hexa) Tipo do Disco
FOH 1.44Mb ou 2.88Mb de 3,5 polegadas
Disco Zip
F 8H Disco rgdo
Unidade de CD -RO M
F9H 720Kb de 3.5 ou 1.2Mb de 5.25 polegadas
FAH 320Kb de 5.25 polegadas
FCH 180Kb de 5.25 polegadas
FDH 360Kb de 5.25 polegadas
FEH 160Kb de 5.25 polegadas
FFH 320Kb de 5.25 polegadas

Nota: O CD-ROM que acompanha este livro inclui o arquivo u>in_did.cpp, que lista as identificaes de disco sob
o Windows 95 ou o Windows N T e mostra-as na tela.

E fetu an d o uma L e it u r a ou G ravao Abso lu t a


de S eto r 356
Se voc trabalha no ambiente do DOS, o DOS lhe permite efetuar operaes absolutas de leitura e gravao no
nvel do setor. Normalmente, seus programas usam os servios do DOS para efetuar essas operaes. No entanto,
para tornar essas operaes mais fceis de executar, muitos compiladores C oferecem as funes absread e abswrite,
como mostrado aqui:
#include <dos.h>

int absread(int unidade, int num_setores, long setor_inicial, void *buffer);


int abswrite(int unidade, int num_setores, long setor_inicial, void *buffer);
O parmetro unidade especifica a unidade de disco que voc quer ler, onde 0 a unidade A, 1 a unidade
B, e assim por diante. O parmetro num_setores especifica o nmero de setores que voc quer ler ou gravar, ini
ciando no setor que o parmetro setor_inicial especifica. Finalmente, o parmetro buffer um ponteiro para o
buffer no qual as informaes so lidas ou a partir das quais a sada gravada. Se as funes so bem-sucedidas,
elas retornam o valor 0. Se um erro ocorre, as funes retornam o valor - 1 . 0 programa a seguir, chc_disc.c, l
todo setor no disco C. Se o programa encontrar erros ao ler um setor, ele exibir o nmero do setor:
#include <stdio.h>
#include <dos.h>
#include <alloc.h>

void main(void)
{
struct fatinfo fat;
long sector, total_setores;
void *buffer;

getfat(3, &fat);
total_setores = fat.fi_nclus * fat.fi_sclus;
if ((buffer = malloc(fat.fi_bysec)) == NOLL)
printf("Erro ao alocar o buffer do setor\n");
else
186 P rogram and o em C/C++ A B b l ia

for (sector = 0; sector c total_setores; sector+ + )


if (absread(2, 1, sector, buffer) == -1)
{
printf("\n\007Erro no setor %ld pressione Enter\n", sector);
getchar();
>
else
printf("Lendo o setor %ld\r", sector);
>
Nota: Embora vocpossa efetuar leituras e gravaes absolutas de setor no Windows, o modo como o Windows grava
informaes no disco toma as leituras e gravaes absolutas perigosas e inconsistentes. Voc deve evitar as atividades ab
solutas no disco no Windows e processar as leituras e escritas por meio da Interface de Programao de Aplicativos (Ap
plication Programming Interface API) do Windows.

357 E f e t u a n d o E/S no D is c o B a s e a d a no BIO S


Quando seus programas efetuam operaes em arquivo, usam os servios do DOS para manipular os arquivos.
Os servios do DOS, por sua vez, chamam outros servios do DOS para ler e gravar setores lgicos no disco.
Para efetuar as operaes reais de E/S no disco, os servios do DOS ento chamam os servios do disco da BIOS.
Em tais casos, seus programas podem usar a funo biosdisk, como mostrado aqui:
#include <bios.h>

int biosdisk(int operao, int unidade, int cabea, int trilha, int setor,
int conta_setor, void *buffer);
O parmetro unidade cspeci fica o nmero da unidade, onde O a unidade A, 1 a unidade B, e assim por
diante. Para um disco rgido, 0x80 o primeiro disco rgido, 0x81 a segunda unidade, e assim sucessivamente.
Os parmetros cabea, trilha, setor e conta_setor especificam os setores do disco fsico que voc quer ler ou gravar.
O parmetro buffer um ponteiro pafa o buffer no qual biosdisk l os dados ou a partir do qual biosdisk grava
os dados. Finalmente, o parmetro operao especifica a funo desejada. A Tabela 357.1 lista as operaes vlidas.
Tabela 357.1 Operaes vlidas de biosdisk.
Operao Funo
0 Reinicializa o sistema do disco
1 Retorna o status da ltima operao no disco
2 L o nmero especificado de setores
3 Grava o nmero especificado de setores
4 Verifica o nmero especificado de setores
5 Formata a trilha especificada o buffer contm uma tabela de localizaes ruins
6 Formata a trilha especificada, marcando os setores ruins
7 Formata a unidade comeando na trilha especificada
8 Retorna os parmetros da unidade nos primeiros quatro bytes do buffer
9 Inicializa a unidade
10 Efetua uma leitura longa 512 bytes de setor mais 4 extras
11 Efetua uma escrita longa 512 bytes de setor mais 4 extras
12 Efetua um posicionamento (seek) no disco
13 Reinicializao alternativa do disco
14 L buffer de setor
15 Grava buffer de setor
16 Testa unidade pronta
17 Recalibra a unidade
18 Efetua o diagnstico da RAM da controladora
19 Efetua o diagnstico da unidade
20 Executa o diagnstico interno da controladora
A r q u iv o s , d ir e t r io s e d is c o s 187

Se bem-sucedidas, as funes retornam o valor 0. Se ocorrer um erro, o valor de retorno da funo espe
cifica o erro. A Tabela 357.2 lista os valores de erro.
Tabela 357.2 Valores de status de erro retomados por biosdisk.
Valor do Erro Erro
0 Bem-sucedida
1 Comando invlido
2 Marca de endereo no-encontrada
3 Disco protegido contra gravao
4 Setor no-encontrado
5 A reinicializao do disco rgido falhou
6 Troca do disco
7 Falha no parmetro atividade da unidade
8 Erro de DMA
9 DMA fora do limite de 64Kb
10 Setor ruim
11 Trilha ruim
12 Trilha no-suportada
16 Erro de leitura CRC/ECC
17 Dados corrigidos CRC/ECC
32 Falha na controladora
64 Falha na operao de posicionamento (seek)
128 Sem resposta
170 Disco rgido no-preparado
187 Erro no-definido
204 Falha na gravao
224 Erro de status
255 A operao Sense falhou

Nota: Muitos compiladores tambm oferecem uma funo chamada _bios_disk, que efetua processamento idntico
a biosdisk, com a exceo de que seus programas passam para a funo uma estrutura do tipo diskinfo_t, que contm
os valores drive (unidade), head (cabea), track (trilha), sector (setor) e sector_count (conta_setor).
Nota: Embora voc possa usar bios_disk para executar E/S no disco baseada na BIOS, os mtodos que o Windows
usa para gravar informaes no disco tornam a E/S no disco baseada na BIOS perigosa e inconsistente. Evite a E/S no
disco baseada na BIOS no Windows e processe suas leituras e escritas por meio da Interface de Programao de Apli
cativos (API) do Windows.

Te s t a n d o a P r o n t id o de uma U n id a d e de D is q u e t e 358
Na dica anterior voc aprendeu como usar a funo biosdisk para chamar os servios de disco da BIOS. Uma ope
rao til que a funo biosdisk pode executar testar se uma unidade de disquete contm um disco e est pronta
para ser acessada. O programa a seguir, testa_a.c, usa a funo biosdisk para verificar a unidade de disquete:
tinclude <stdio.h>
#include <bios.h>

void main(void)
{
char buffer[8192];

// Tenta ler a cabea 1, trilha 1, setor 1


if (biosdisk(2, 0, 1, 1, 1, 1, buffer))
printf("Erro ao acessar a unidade\n");
else
printf(Unidade pronta\n");
)
188 P rogram ando em C/C++ A B b l ia

Nota: O CD-ROM que acompanha este livro inclui o arquivo win_a.cpp, que efetua a mesma tarefa que o progra
ma testa_a.c, mas trabalha apenas sob o Windows 95 ou sob o Windows N T.

359 A b r in d o um A r q u iv o U s a n d o fo pen
Muitos programas C que voc criar, iro armazenar e ler informaes de um arquivo. Ames que seus programas
possam ler ou gravar informaes em um arquivo, voc precisar abrir o arquivo. A funo fopen permite que
seus programas abram um arquivo. O formato de fopen como segue:
#include <stdio.h>

FILE *fopen(const char *nomearq, const char *modo);


O parmetro nomearq uma string de caracteres que contm o nome do arquivo desejado, tal como
c:\arqdados.dat". O parmetro modo especifica como voc quer usar o arquivo para ler, gravar ou anexar. A
Tabela 359 descreve o valores de modo que fopen suporta.
Tabela 359 Os valores de modo suportados por fopen.
Modo Significado
a Abre um arquivo para operaes de anexao se o arquivo no existir,o sistema
operacional o criar
r Abre um arquivo existente para operaes de leitura
w Abre um novo arquivo para sada se um arquivo com omesmo nome existir, o
sistema operacional ir sobrescrever o arquivo
r+ Abre um arquivo existente para leitura e gravao
w+ , Abre um novo arquivo para leitura e gravao se um arquivo com o mesmo nome
existir, o sistema operacional ir sobrescrever o arquivo
a+ Abre um arquivo para operaes de anexao e leitura se o arquivo no existir, o
sistema operacional criar o arquivo

A funo fopen retorna um ponteiro (chamado ponteiro de arquivo) para uma estrutura do tipo FILE que
o arquivo de cabealho stdio.h define. Seus programas usaro o ponteiro de arquivo para suas operaes de en
trada e sada. Se a funo fopen no puder abrir o arquivo especificado, ela retornar o valor NULL. Seus pro
gramas sempre devem testar o valor de retorno de fopen para garantir que abriu o arquivo com sucesso, como
mostrado aqui:
if((pa = fopen(NOMEARQ.EXT", "r">> != NULL)
{
II Arquivo aberto com sucesso
}
else
{
// Erro ao abrir o arquivo
}
Dentro do seu programa, voc precisa declarar a varivel ponteiro de arquivo como segue:
void main(void)
{
FILE *pa II Ponteiro para uma estrutura do tipo FILE
Muitos programas abrem um arquivo para entrada e outro para sada. Em tais casos, voc poderia declarar
dois ponteiros de arquivo, como mostrado aqui:
FILE *entrada, *saida;
Muitas dicas nesta seo usam fopen para abrir um arquivo para as operaes de Jeirura, gravao ou anexao.
ARQUIVOS, DIRETRIOS E DISCOS 189

COMPREENDENDO A ESTRUTURA FILE 360


Como voc aprendeu, quando seus programas efetuam operaes de entrada e sada, elas normalmente declaram
ponteiros de arquivo usando a estrutura FILE, como mostrado aqui:
FILE *entrada, *saida;
Se voc examinar o arquivo de cabealho stdio.h, encontrar a definio da estrutura FILE. No caso do
Turbo C++ Lite, a estrutura tem a seguinte forma:
typedef struct
<
short levei; // Nvel do buffer cheio/vazio
unsigned flags; // Sinalizadores de status
char fd; // Descritor de arquivo
unsigned char hold; // Caractere ungetc se no existir um buffer
short bsize; // Tamanho do buffer
unsigned char *buffer; // Buffer de transferncia
unsigned char *curp; // Ponteiro ativo atual
unsigned istemp; // Indicador de arquivo temporrio
short token; // Usado para verificao da validade
} FILE; // Esse o objeto FILE
A estrutura FILE contm o descritor de arquivo de baixo nvel que o sistema operacional usa para acessar
o arquivo, o tamanho do buffer do arquivo e a localizao, o buffer de caracteres que unget usa, um sinalizador
que indica se o arquivo um arquivo temporrio, e outras variveis sinalizadoras. Alm disso, a estrutura FILE
armazena o ponteiro de arquivo que controla sua localizao atual dentro do arquivo.
Se voc estiver trabalhando no ambiente do DOS, a maioria dos compiladores definir uma matriz de ta
manho fixo (normalmente 20) dos ponteiros de arquivo que contm as informaes para cada arquivo que seu
programa abrir. Se seu programa precisar abrir mais de 20 arquivos, consulte a documentao do seu compi
lador para conhecer os passos que precisar seguir para modificar o tamanho da matriz de ponteiros de arquivo.

Fec h an d o um A r q u iv o A b e r t o 361
Exatamente como seus programas precisam abrir um arquivo antes de us-lo, tambm devem fechar o arquivo
quando no precisarem mais dele. Fechar um arquivo instrui o sistema operacional a esvaziar todos os buffers
de disco associados com o arquivo e a liberar os recursos do sistema que o arquivo consumiu, tais como os dados
de ponteiro de arquivo. A funo C fclose fecha o arquivo associado com o ponteiro de arquivo especificado,
como mostrado aqui:
#include <stdio.h>

int fclose(FILE *pont_arquivo);


Se fclose for bem-sucedida, retornar o valor 0. Se ocorrer um erro, fclose retornar a constante EOF, como
mostrado aqui:
if (fclose(pa) == EOF)
printf("Erro ao fechar o arquivo de dados\n");
A medida que voc for examinando programas C, ver que a maioria deles no testa o valor de retorno de
fopen, como mostrado aqui:
fclose(pa);
Na maioria dos casos, se uma operao fechar arquivo apresentar erro, o programa poder fazer muito pou
co para corrigir a situao. No entanto, se voc estiver trabalhando com arquivos de dados crticos,dever exibir
uma mensagem de erro para o usurio para que ele possa examinar o contedo do arquivo.
Nota: Se voc no chamar a juno fclose, C fechar os arquivos abertos quando o programa terminar.
190 P r o g ram a nd o em C/C++ A B b l ia

362 Le n d o e G r a v a n d o In f o r m a e s no A r q u iv o um

Ca r a c t e r e de Ca d a V e z
Quando seus programas efetuam operaes de entrada e sada em arquivos, podem ler e gravar dados um carac
tere de cada vez ou uma linha de cada vez. Para as operaes de entrada e sada de caractere, seus programas po
dem usar as funes fgetc e fpute, cujos formatos so mostrados aqui:
#include <stdio.h>

int getc(FILE *pont_entrada);


int fputc(int caractere, FILE *pont_saida);
A funo fgetc l o caractere atual do arquivo de entrada especificado. Se o ponteiro de arquivo tiver che
gado ao final do arquivo, fgetc retornar a constante EOF. A funo fpute gravar um caractere na posio do
ponteiro de arquivo atual dentro do arquivo de sada especificado. Se um erro ocorrer, Jputc retornar a constante
EOF. O programa a seguir, copconf.c, usa fgetc e jputc para copiar o contedo do arquivo do diretrio-raiz con-
fig-sys para um arquivo chamado config.tst:
#include <stdio.h>

void main(void)
<
FILE *entrada, *saida;
int letra;

if ((entrada = fopen("WCONFIG.SYS", "r")) == NULL)


printf("Erro ao abrir WCONFIG. SYS\n);
else if ((saida = fopen(WCONFIG.TST", "w")) == NULL)
printf("Erro ao abrir WCONFIG.TST\n");
else
{
// L e grava cada caractere no arquivo
while ((letra = fgetc(entrada)) != EOF)
fpute(letra, saida);
fclose(entrada); // Fecha o arquivo entrada
fclose(saida); // Fecha o arquivo saida
>

363 Co m p r e e n d e n d o o P o n t e ir o de P o s i o do P o n t e ir o
de A r q u iv o
A Dica 360 apresentou a estrutura FILE. Como voc aprendeu, um dos campos da estrutura armazena um pon
teiro da posio para a localizao atual dentro do arquivo. Quando voc abre um arquivo para operaes de lei
tura ou gravao, o sistema operacional define o ponteiro da posio no incio do arquivo. Toda vez que voc
ler ou gravar um caractere, o ponteiro da posio avanar um caractere. Se voc ler uma linha de texto do ar
quivo, o ponteiro da posio avanar para o incio da prxima linha. Usando o ponteiro da posio, as funes
de entrada e sada de arquivo sempre podem controlar a localizao atual dentro do arquivo. Quando voc abre
um arquivo no modo de anexao, o sistema operacional define o ponteiro da posio no final do arquivo. Em
dicas posteriores voc aprender a alterar o ponteiro da posio para posies especficas no arquivo usando as
funes Jseek e Jsetpos. A Tabela 363 especifica a localizao na qual fopen coloca o ponteiro da posio quando
voc abre o arquivo nos modos de leitura, gravao e anexao.
A r q u iv o s , d ir e t r io s e d is c o s 191

Tabela 363 Posicionamentos do ponteiro de posio no arquivo que resultam de uma chamada a fopen.
M odo de Abertura Posio do Ponteiro do Arquivo
a Imediatamente aps o ltimo caractere no arquivo
r N o incio do arquivo
u) N o final do arquivo

D e t e r m in a n d o a P o s i o A t u a l no A r q u iv o 364
Na dica anterior voc aprendeu como C controla a posio atual em arquivos abertos para as operaes de en
trada e sada. Dependendo do seu programa, algumas vezes voc precisar determinar o valor do ponteiro de po
sio. Em tais casos, seus programas podem usar a funo fiell, como mostrado aqui:
#include <stdio.h>

long int ftell(FILE *pont_arquivo);


A funo fiell retorna um valor inteiro longo que especifica o byte de deslocamento a partir da posio
atual no arquivo especificado. O programa a seguir, exib_pos.c, usa fiell para exibir informaes do ponteiro de
posio. O programa comea abrindo o arquivo do diretrio-raiz config.sys no modo de leitura. O programa en
to usa fiell para exibir a posio atual. Em seguida, o programa l e exibe o contedo do arquivo. Aps encontrar
o final do arquivo, o programa novamente usar fiell para exibir a posio atual, como mostrado aqui:
#include <stdio.h>

void main(void)
{
FILE *entrada;
int letra;

if ((entrada = fopen("\\CONFIG.SYS", "r")) == NULL)


printf("Erro ao abrir WCONFIG.SYS\n");
else
<
printf("A posio atual o byte %d\n\n", ftell(entrada));
// L e grava cada caractere no arquivo
while ((letra = fgetc(entrada)) 1= EOF)
fputc(letra, stdout);
printf C'\nA posio atual o byte %d\n", ftell(entrada));
fclose(entrada); // Fecha o arquivo entrada
>
>

Co m p r e e n d e n d o os Ca n a is de A r q u iv o s 365
Muitos livros e revistas referem-se aos ponteiros de arquivos de C como ponteiros streams (ou de canais) de arqui
vos. Ao contrrio de muitas outras linguagens de programao, C no assume que os arquivos contm informa
es em um formato especfico. Em vez disso, C considera todos os arquivos como nada mais que uma coleo
de bytes. A medida que voc l um arquivo, l um byte aps o outro; em outras palavras, uma seqncia de bytes.
Seus programas e funes, tais como fgets, precisam interpretar os bytes. Por exemplo, fgets considera o caractere
de alimentao de linha como o final de uma linha e o incio de outra. A funo fgets faz essa interpretao de
caracteres sozinha. Isto , C no interpreta os bytes. A medida que voc for escrevendo programas e fiines que
manipulam arquivos, 'pense nos arquivos como nada mais que uma coleo de bytes.

Co m p r e e n d e n d o as Tr a d u e s de A r q u iv o s 366
As funes de manipulao de arquivos de C, tais como fgets e j(puts, podem interpretar arquivos em uma de duas
formas: modo texto e modo binrio. Por padro, as funes fgets e fputs usam o modo texto. No modo texto, fun
es, tais como fputs, que gravam informaes em um arquivo, convertem o caractere de alimentao de linha
para uma combinao retorno do carro e alimentao de linha. Durante uma operao de entrada, funes, tais
192 Programando em C/C++ A Bblia

como fgets, convertem a combinao retorno do carro e alimentao de linha para um nico caractere de alimen
tao de linha. Por outro lado, no modo binrio, as funes no efetuam essas tradues de caractere. Para lhe
ajudar a determinar o modo de traduo atual, muitos compiladores baseados no DOS e no Windows oferecem
a varivel global _fmode, que contm um dos valores listados na Tabela 366.
Tabela 366 Os valores constantes para _fmode.
Constante Descrio
0_TE X T Tradues no modo texto
0_ B IN A R Y Tradues no modo binrio

Por padro, o valor de _fmode, tanto sob o DOS quanto sob o Windows, 0_TEXT. O programa a seguir,
fmode.ci exibe o valor atual da varivel _fmode:
ttinclude <stdio.h>
#include <fcntl.h> //Contm a declarao de _fmode

void main(void)
{
if (_fmode == 0_TEXT)
printf("Tradues do modo texto\n");
else
printf("Tradues do modo binrio\n");
>

367 Co m p r e e n d e n d o a L in h a FILES = v a l o r no C o n f ig .s y s
Se voc estiver trabalhando em um ambiente baseado no DOS, a linha FILES no arquivo config.sys especificar
o nmero de arquivos que o sistema pode abrir ao mesmo tempo (em um ambiente baseado no Windows, o
Windows limita o nmero de arquivos abertos com base na memria disponvel do sistema, espao no disco, uso
de outros recursos etc.). Como discutido rapidamente nesta seo, Arquivos, Diretrios e Discos, o DOS usa os
primeiros cinco indicativos (handles) de arquivos para stdin, stdout, stderr, stdaux e stdpm. Por padro, o DOS
oferece suporte para oito indicativos de arquivo. Como esse nmero pequeno para quase todos os programas,
exceto os mais simples, a maioria dos usurios aumenta o nmero de indicativos de arquivo para 20 ou 30, como
mostrado aqui:
FILES=30
A linha FILES define o nmero de arquivos que o DOS pode abrir no o nmero que cada programa
rodando sob o DOS pode abrir. Por exemplo, se voc estiver rodando programas residentes na memria, eles po
dero abrir arquivos sem que voc saiba. Se voc definir a linha FILES como um nmero grande de indicativos
(o DOS permite at 255), isso no significa que seus programas C podero abrir todos esses arquivos. Existem
dois problemas com a abertura de um grande nmero de arquivos dentro de seus programas C. Primeiro, a maio
ria dos compiladores restringe o tamanho da matriz de ponteiros de arquivos para 20. Antes de poder abrir mais
do que 20 arquivos, voc precisa alterar o tamanho da matriz. Segundo, como voc aprender, o DOS restringe
em 20 o rimero de arquivos que um ponteiro pode abrir. Antes de poder abrir mais de 20 arquivos, voc precisa
usar um servio do DOS que pede que ele suporte mais do que 20 arquivos abertos para o programa atual.
Nota: A Dica 369 explicar os indicativos de arquivo.

368 U s a n d o E/S em A r q u iv o s de B a ix o N v e l e de

A lto n v e l
Quando seus programas C trabalham com arquivos, podem efetuar dois tipos de operaes de entrada e de sada:
baixo nvel e alto nveL Todas as dicas apresentadas at este ponto usaram as capacidades de alto nvel (ou ba
seadas em canais (streams), tais como fopen, fgets e fputs. Quando voc usa as funes de E/S de arquivo de alto
nvel, elas, por sua vez, usam servios do sistema operacional que esto baseados em indicativos de arquivo. A bi
A r q u iv o s , d ir e t r io s e d is c o s 193

blioteca de execuo de C fornece funes de baixo nvel que seus programas podem usar. Em vez de trabalharem
com um ponteiro stream, as funes de baixo nvel usam descritores de arquivo. A Tabela 368 descreve resumi
damente vrias das funes de baixo nvel mais comumente usadas.
Tabela 368 Funes comuns de arquivo de baixo nvel.
Nom e da Funo Propsito
close Fecha o arquivo associado com o indicativo de arquivo especfico esvaziando
os buffers de arquivo
creat Cria um arquivo para as operaes de sada, retornando um indicativo de
arquivo
open Abre um arquivo existente para entrada ou sada, retornando um indicativo
de arquivo
read L um nmero especfico de bytes a partir do arquivo associado com um
determinado indicativo de arquivo
write Grava um nmero especfico de bytes no arquivo associado com um
determinado indicativo

Quando voc escrever seus programas, sua escolha de usar funes de alto nvel ou de baixo nvel depen
der de sua preferncia pessoal. No entanto, tenha em mente que a maioria dos programadores tem uma melhor
compreenso das funes de manipulao de arquivo de alto nvel de C. Como resultado, se voc usar as funes
de alto nvel, tais como fopen e fgets, mais programadores iro prontamente compreender o cdigo do seu programa.
Nota: A seo E/S no Windows, mais frente, discute em detalhes a E/S em arquivo de baixo nvel e de alto nvel
sob o Windows.

Co m p r e e n d e n d o os I n d ic a t iv o s de A r q u iv o s 369
Como voc sabe, a linha FILES no arquivo config.sys lhe permite especificar o nmero de indicativos de arquivo
que o DOS suporta. Basicamente, um indicativo de arquivo um valor inteiro que define de forma inequvoca
um arquivo aberto. Ao usar as funes de E/S em arquivo de baixo nvel, voc declarar os indicativos de arquivo
do seu programa como tipo int, como mostrado aqui:
int indic_entrada, indic_saida;
As funes open e creat retornaro descritores de arquivo ou o valor -1 se a funo no puder abrir o arquivo:
int arq_novo, arq_antigo;
arq_novo = creat("NOMEARQ.NOV", S_IWRITE); // Cria um novo arquivo para saida
arq_antigo = open("NOMEARQ.ANT", 0_RD0NLY); // Abre um arquivo existente
para leitura
O DOS atribui a cada arquivo que voc abrir ou criar um indicativo de arquivo distinto. O valor do in
dicativo na verdade um ndice na tabela de arquivos do processo, dentro da qual o DOS controla os arquivos
abertos do programa.

Co m p r e e n d e n d o a Ta b e l a de A r q u iv o s do P ro c esso 370
Quando voc roda um programa no ambiente do DOS, o DOS controla os arquivos abertos do programa usan
do uma tabela de arquivos do processo. Dentro do prefixo do segmento do programa, o DOS armazena um pon
teiro fa r para uma tabela que descreve os arquivos abertos do programa. N a verdade, a tabela contm entradas
para uma segunda tabela, a tabela de arquivos do sistema, dentro da qual o DOS controla todos os arquivos aber
tos. A Figura 370 ilustra o relacionamento entre o indicativo de arquivo, a tabela de arquivos do processo e a
tabela de arquivos do sistema.
Sob o Windows, o Gerenciador de Tarefas mantm a lista de todos os processos abertos, e o Windows usa
a tabela de arquivos do sistema do DOS para manter a lista de todos os arquivos abertos. O CD-ROM que
acompanha este livro inclui o programa Task_Man.cpp, que lista todos os programas atualmente abertos no sistema.
194 P rog ram and o em C/C++ A B b l ia

Tabela de Arquivos
do Sistema DOS

Figura 370 O relacionamento entre um indicativo de arquivo, a tabea de arquivos do processo e a tabela de arqui
vos do sistema.

371 V is u a l iz a n d o as E ntradas da Ta b e l a de A r q u iv o s
do P ro cesso
Como a Dica 370 descreveu, o DOS controla os arquivos abertos de um programa usando uma tabela de arqui
vos do processo. No deslocamento 18H, dentro do prefixo de segmento do programa, h uma matriz de valores
inteiros. Os valores que compem essa matriz especificam ndices na tabela de arquivos do sistema DOS. Se um
valor no est em uso, o sistema operacional define-o como FFH (decimal 255). O programa a seguir, tabelarq.c,
exibir os valores na tabela de arquivos do processo. Lembre-se, a tabela contm valores inteiros que servem
como ndices na tabela de arquivos do sistema:
#inclue <stdio.h>
ttinclude <dos.h>
#include <stdlib.h>

void main(void)
{
struct fcbs
{
char unidade;
char nomearq[8];
char extenso[3];
int bloco_atual;
int tamanho_registro;
>;
typedef struct fcba fcb;
struct prefixo_segmento_programa
<
char near *int20;
char near *segroento_prox_paragrafo;
char reservado_l;
char dos_dispatcher[5];
char far *vetor_termino;
char far *vetor_ctrlc;
char far *critico_erro_vetor;
char near *psp_pai;
unsigned char tabela_arq[20];
char near *segmento_bloco_ambiente;
char far *armazenagem_pilha;
int indicativos_disponiveis;
char far *endereco_tabela_arq;
char far *campartilha_psp_anterior;
char reservado_2[20];
char dos_int21_retf[3];
char reservado_J3 [9];
fcb fcbl;
A r q u iv o s , d ir e t r io s e d is c o s 195

fcb fcb2;
char reservado_4[4];
char cauda_comando[128];
} far *psp;
int i;

psp = (struct prefixo_segmento_programa far *) ((long) _psp 16);


for (i = 0; i < 20; i++)
printf("Entrada %d contm %x\n, i, psp->tabela_ar<iuivo[i]);
>
Quando voc compilar e executar o programa tabelarq.c, ver que as primeiras cinco entradas na tabela de
arquivos do processo estaro em uso. Essas entradas correspondem a stdin, stdout, stderr, stdaux e stdprn. Edite
este programa e abra um ou mais arquivos antes de exibir as entradas da tabela de arquivos, e voc encontrar
mais entradas dentro da tabela de arquivos do processo.

Co m p r e e n d e n d o a Ta b e l a de A r q u iv o s do S is t e m a 372
Os indicativos de arquivo so valores de ndice na tabela de arquivos do processo, que, por sua vez, apontam para
a tabela de arquivos do sistema. A tabela de arquivos do sistema armazena informaes sobre todo arquivo que
o DOS, um controlador de dispositivo, um programa residente em memria, ou seu programa abriu. A Figura
372 ilustra o contedo da tabela do sistema de arquivos.

Figura 372 Contedo da tabela do sistema de arquivos do DOS.

O DOS, na verdade, divide a tabela do sistema em duas sees. A primeira seo contm cinco entradas.
A segunda seo fornece espao suficiente para o nmero de entradas que a linha FILES especifica no config.sys
(menos 5 as entradas que residem na primeira seo da tabela).

E x i b in d o a Ta b e l a do S is t e m a de A r q u iv o s 373
\
O DOS armazena informaes sobre todo arquivo aberto dentro da tabela de arquivos do sistema. Usando a lista
de listas do DOS, discutida na seo DOS e BIOS, mais frente, o programa a seguir, tabsis.c, exibe as entradas
na tabela do sistema de arquivos:
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>

void main(void)
196 Programando em C/C++ A Bblia

union REGS regs_ent, regs_saida;


struct SREGS segs;
int i, j;
int tam_estrutura;
struct SystemTableEntry
{
struct SystemTableEntry far *proximo; // Prxima entrada SFT
unsigned conta_arq; // Arquivos na tabela
unsigned conta_indic; // Indicativos para este arquivo
unsigned modo_abertura; // Modo de abertura do arquivo
char atributo_arq; II Byte de atributo
unsigned local_remoto; I I o bit 15 ligado indica remoto
unsigned far *DPD; // Bloco de parmetros da unidade
unsigned agrupamento_inicial;
unsigned hora;
unsigned data;
long tam_arquivo;
long desloc_atual;
unsigned agrupamento_relativo;
long num_setor_diretorio;
char desloc_entrada_diretorio;
char nomearq_ext[11]; // Sem o ponto, espao preenchido
// Ignora os campos SHARE, por exemplo
> far *tabela_ptr, far arquivo;
long far *tabela_sistema;

// L a verso do DOS
regs_ent.x.ax = 0x3001;
intdos (&regs_ent, &regs_saida);
if (regs_saida.h.al < 3)
{
printf("Este programa requer o DOS verso 3 ou posterior\n");
exit (1);
>
else if (regs_saida.h.al == 3)
tam_estrutura = 0x35;
else if (regs_saida.h.al >= 4)
tam_estrutura = 0x3B;
// L a lista de ponteiros
regs_ent.h.ah = 0x52;
intdosx (&regs_ent, &regs_saida, &segs);
// O j>onteiro para a tabela de arquivos do sistema est no deslocamento 4
tabela_sistema = MK_FP(segs.es, regs_saida.x.bx + 4);
tabela_ptr = (struct SystemTableEntry far *) *tabela_sistema;
do {
printf("%d entradas na tabela\n", tabela_ptr->conta_arq);
for (i = 0; i < tabela_ptr->conta_arq; i++)
{
arquivo = MK_FP(FP_SEG(tabela_ptr), FP_OFF(tabela_ptr) +
(i * tam_estrutura));
if (arquivo->conta_indic)
{
for (j = 0; j < 8; j++)
if (arquivo->nomearq_ext[j] 1= ' ')
putchar(arquivo->nomearq_ext[j]);
else
break;
if (arquivo->nomearq_ext[8] != ' ')
putchar('.');
for (j = 8; j < 11; j++)
A r q u iv o s , d ir e t r io s e d is c o s 197

if (arquivo->nomearq_ext[j] != ' ')


putchar(arquivo->nomearq_ext[j]);
printf(" %ld bytes %x atributo %d referncias\n",
arquivo->tam_arquivo, arquivo->atributo_arq,
arquivo->conta_indic);
>
>
tabela_ptr = tabela_ptr->proximo;
} while (FP_OFF(tabela_ptr) != OxFFFF);
}
Quando voc rodar o programa tabsis.cz partir do prom pt do DOS, provavalmente a sada dele no ser
muito interessante. No entanto, se voc tiver o Windows, use o cone Prompt do MS-DOS para abrir uma janela
do DOS. Dentro da janela do DOS, rode o programa tabsis. Voc pode querer editar o programa e usar fopen
para abrir um ou mais arquivos antes de exibir o contedo da tabela do sistema de arquivos.

D e r iv a n d o I n d ic a t iv o s de A r q u iv o s a p a r t ir d e

P o n t e ir o s S t r e a m ( d e Ca n a i s ) 374
A Dica 360 apresentou a estrutura FILE definida no arquivo de cabealho stdio.h. Voc aprendeu, ao efetuar
operaes de arquivo de alto nvel usando fopen e fgets, declarar ponteiros stream (de canais) em termos da es
trutura FILE, como mostrado aqui:
FILE *entrada, *saida;
As funes C, mais tarde, convertem os ponteiros stream em indicativos de arquivos para efetuarem as ope
raes reais de E/S. Para compreender melhor o relacionamento entre ponteiros stream e indicativos de arquivos,
considere o programa a seguir, indicat.c, que abre arquivo config.sys do diretrio-raiz e depois exibe o descritor
de arquivo para o arquivo, bem como os indicativos de arquivo predefinidos stdin, stdout, stderr, stdaux e stdpm:
#include <stdio.h>

void main(void)
{
FILE *entrada;

if ((entrada = fopen("WCONFIG.SYS", "r")) == NULL)


printf("Erro ao abrir WCONFIG.SYS\N");
else
{
printf("Indicativo para CONFIG.SYS %d\n", entrada->fd);
printf("Indicativo para stdin %d\n", stdin->fd);
printf("Indicativo para stdout %d\n", stdout->fd);
printf(Indicativo para stderr %d\n", stderr->fd);
printf("Indicativo para stdaux %d\n", stdaux->fd);
printf("Indicativo para s t d p m %d\n", stdprn->fd);
fclose(entrada);
>
>
Quando voc compilar e executar o programa indicat.c, sua tela exibir o valores de indicativo de 0 at 5.

E x e c u t a n d o S a d a F o r m a t a d a em A r q u iv o 375
Vrias dicas nesta seo apresentam modos de seus programas gravarem dados em um arquivo. Em muitos casos,
seus programas precisam efetuar sada formatada em arquivo. Por exemplo, se voc estiver criando um relatrio
de inventrio, poder querer alinhar as colunas, trabalhar com texto e com nmeros e assim por diante. Na seo
Introduo Linguagem C, anteriormente, voc aprendeu como usar a funo p rin tf para executar E/S forma
tada na tela. De um modo similar, C fornece a funo fprintf, que usa especificadores de formato para gravar sa
da formatada em arquivo, como mostrado aqui:
198 Programando em C/C++ A Bblia

#include <stdio.h>

int fprintf(FILE *pont_arquivo, const char *espec_formato, [argumento


[___ ]]);
O programa a seguir,fyrintf.c, usa fprintfpara. gravar sada formatada em um arquivo chamado fprintf.dat:
#include <stdio.h>

void main(void)
{
FILE *pa;

int paginas = 800;


float preco = 49.95;

if (pa = fopen("FPRINTF.DAT", "w"))


{
fprintf(pa, "Ttulo: Bblia do Programador C/C++\n");
fprintf(pa, "Pginas: %d\n", paginas);
fprintf(pa, "Preo: $%5.2f\n", preco);
fclose(pa);
}
else
printf("Erro ao abrir FPRINTF.DAT\n);
>

376 R en o m ea n d o um A r q u iv o
medida que seus programas forem trabalhando com arquivos, algumas vezes voc precisar renomear ou mover
um arquivo. Para esses casos, C oferece a funo rename. O formato da funo rename :
#include <stdio.h>

int rename(const char *nome_antigo, const char *nome_novo);


Se a funo rename for bem-sucedida em renomear ou mover um arquivo, ela retornar o valor 0. Se um
erro ocorrer, rename retornar um valor diferente de 0 e atribuir varivel global errno um dos valores de status
de erro listados na Tabela 376:
Tabela 376 Valores de status de erro para rename.
Valor Significado
EACCES Acesso negado
ENOENT Arquivo no-encontrado
E XD E V No pode mover de um disco para outro

O programa a sguir, meu_ren.c, usa a funo rename para criar um programa que pode renomear ou mo
ver o arquivo especificado na linha de comando:
#include <stdio.h>

void main(int argc, char *argv[])


{
if (argc < 3)
printf("Voc precisa especificar um nome de arquivo de origem e de
destino\n")?
else if (rename(argv[l], argv[2]))
printf("Erro ao renomear o arguivo\n");
>
Nota: A Dica 1472 detalhar como renomear um arquivo usando a AP I do Windows.
.'-i
A r q u iv o s , d ir e t r io s e d is c o s 199

E x c l u in d o um A r q u iv o 377
Quando seus programas trabalham com arquivos, algumas vezes voc precisa excluir um ou mais arquivos. Em
tais casos, seus programas podem usar a funo remove de C, que tem o seguinte formato:
#include <stdio.h>

int remove(const char *nomearq);


Se a funo remover o arquivo com sucesso, ela retornar o valor 0. Se um erro ocorrer, remove retornar
o valor -1, e atribuir varivel global ermo um dos valores listados na Tabela 377.
Tabela 377 Os erros que a funo remove retoma.
Valor Significado
EACES Acesso negado
ENOENT Arquivo no-encontrado

O programa a seguir, meu_del.c, usa a funo remove para apagar todos os arquivos especificados na linha
de comando:
#include <stdio.h>
void main(int argc, char *argv[])
{
while (*++argv)
if (remove(*argv))
printf("Erro ao remover %s\n", *argv);
}
Alm da funo remove, a maioria dos compiladores C suporta a funo unlink, que tambm exclui um arquivo:
#include <io.h>

int unlink(const char *nomearq);


Se unlink excluir com sucesso um arquivo, ela retomar o valor 0. Se ocorrer um erro, unlink retornar o status
de erro -1, atribuindo varivel global ermo as constantes de status de erro j listadas na Tabela 377. O programa a
seguir, unlink.c, usa a funo unlink para excluir os arquivos especificados na linha de comandos do programa:
#include <stdio.h>

void main(int argc, char *argv[])


{
while (*++argv)
if (unlink(*argv))
printf("Erro ao remover %s\n", *argv);
>
Nota: A Dica 1473 detalhar como excluir um arquivo usando a A P I do Windows.

D e t e r m in a n d o C o m o um Pro gram a Pode Ac essa r


um A r q u iv o 378
Quando seu programa trabalha com arquivos, algumas vezes voc precisa determinar se seu programa pode aces
sar um arquivo especfico. A funo C access confere se um arquivo existe como especificado e se voc pode abrir
o arquivo conforme solicitado. O formato da funo access este:
#include <io.h>

int access(const char *nomearq, int modo_acesso);


200 P rog ram and o em C/C++ A B b l ia

O parmetro modo_acesso especifica como seu programa precisa usar o arquivo, como mostrado na Tabela
378.1:
Tabela 378.1 Valores para o parmetro modo_acesso.
Valor Significado
0 Verifica se o arquivo existe
2 Verifica se o arquivo pode ser gravado
4 Verifica se o arquivo pode ser lido
6 Verifica se o programa tem permisso de leitura e gravao no arquivo

Se o programa puder acessar o arquivo conforme especificado, access retornar o valor 0. Se um erro ocor
rer, access retornar o valor -1, e atribuir varivel global ermo um dos valores de erro listados na Tabela 378.2.
Tabela 378.2 Valores de erro para a funo access.
Valor Significado
EACCES Acesso negado
ENOENT Arquivo no-encontrado

O programa a seguir, acesso, c, usa a funo access para determinar como seu programa pode acessar o ar
quivo especificado na linha de comando do programa:

#include <stdio.h>
#include <io.h>

void main(int argc, char *argv[])


{
int modo_acesso;
modo_acesso = access(argv[1], 0);

if (modo_acesso)
printf("O arquivo %s no existe\n");
else
{
modo_acesso = access(argv[l], 2);
if (modo_acesso)
printf("O arquivo no pode ser gravado\n");
else
printf("O arquivo pode ser gravado\n");
modo_acesso = access(argv[1], 4);
if (modo_acesso)
printf("O arquivo no pode ser lido\n);
else
printf("O arquivo pode ser lido\n");
modo_acesso = access(argv[1], 6);
if (modo_acesso)
printf("O arquivo no pode ser lido/gravadoNn");
else
printf("O arquivo pode ser lido/gravado\n");
}
}
Nota: A Dica 1462 detalha como voc usa os atributos de arquivos no Windows para determinar como um programa
pode acessar um arquivo.

379 D e fin in d o o M o d o de A c e s s o de um A r q u iv o
Quando seus programas trabalham com arquivos, algumas vezes voc desejar alterar o acesso de leitura e gra
vao de um programa. Por exemplo, assuma que voc tenha um arquivo de dados importantes. Para proteger
A r q u iv o s , d ir e t r io s e d is c o s 201

o arquivo quando o programa no estiver em uso, voc poderia definir o arquivo para o acesso de leitura somen
te. Desse modo, o usurio no pode excluir o arquivo acidentalmente. Quando o programa inicia, voc pode
modificar o arquivo para acesso de leitura e gravao, conforme for necessrio. Para esses casos, seus programas
podem usar a funo chmod de C, como mostrado aqui:
#include <sys\stat.h>
#include <io.h>

int chmod (const char nomearq, int modo_acesso);


O arquivo de cabealho sys\stat.h define as constantes de modo de acesso listadas na Tabela 379.1.
Tabela 379.1 Constantes de modo de acesso para chmod.
Valor Significado
S_IW RITE A permisso de gravao est autorizada
S_IREAD A permisso de leitura est autorizada

Para fornecer acesso de leitura e gravao, efetue uma operao O U bit a bit com as duas constantes (S_IWRITE
l\ S_IREAD). Se chmod modificar com sucesso os atributos do arquivo, ela retornar o valor 0. Se ocorrer um erro,
chmod retornar o valor -1 e definir a varivel global ermo para um dos valores de status de erro listados na Ta
bela 379.2.
Tabela 379.2 Os valores de erro que chmod retoma.
Valor Significado
ENOENT Arquivo no-encontrado
EACCES Permisso negada

O programa a seguir, soleitur.c, define o arquivo especificado na linha de comando para acesso de leitura
somente:
#include <stdio.h>
#include <sys\stat.h>
#include <io.h>

void main(int argc, char *argv[])


<
if (chmod(argv[1], S_IREAD))
printf("Erro ao definir %s\n", argv[l]);
}
Nota: A Dica 1463 detalhar o uso de atributos de arquivos sob o Windows para mudar a maneira como um pro
grama pode acessar um arquivo.

Ga n h a n d o M e l h o r Co n t r o l e d o s a t r ib u t o s

do A r q u iv o 380
N a dica anterior voc aprendeu como usar a funo chmod de C para definir os atributos de leitura e gravao
de um arquivo. Quando voc usar o sistema operacional DOS, poder trabalhar com os atributos mostrados na
Tabela 380.1:
202 P rog ram and o em C/C++ A B b l ia

Tabela 380.1 Os atributos que voc pode usar com arquivos dentro do sistema operacional DOS.
Valor Significado
FA ARC H Atributo de arquivar
FA DIREC Atributo de diretrio
FA H ID D E N Atributo de oculto
FA LABEL Rtulo de volume do disco
FA RDONLY Atributo de leitura somente
FA SYSTEM Atributo de sistema

Nota; Alguns compiladores nomeiam essas constantes de forma diferente. Examine o arquivo dos.h fornecido com seu
compilador, para conhecer os nomes corretos das constantes.
Para lhe ajudar a trabalhar com esses atributos, alguns compiladores C fornecem a funo _chmod, cujo
formato mostrado aqui (lembre-se, os parmetros mostrados dentro de colchetes so opcionais):
#include <dos.h>
iinclude <io.h>

int _chmod(const char *nomearq, int operacao [,int atributo]);


A operao diz a _chmod se voc vai querer definir ou ler a definio do atributo. Se a funo chamadora
define a operao 1, _chmod define o atributo especificado. Portanto, o abre e fecha colchetes indicam que o pa
rmetro atributos opcional. Se _chmodot bem-sucedida, ela retornar os atributos atuais do arquivo. Se ocorrer
um erro, _chmodretornar o valor -1, e atribui varivel global ermo um dos valores mostrados na Tabela 380.2.
Tabela 380.2 Os erros que _chmod retoma.
Valor Significado
ENOENT Arquivo no-encontrado
EACCES Permisso negada

O programa a seguir, atributo.c, usa _chmod para exibir os atributos atuais do arquivo.
tinclude <stdio.h>
#include <dos.h>
#include <io.h>

void main(int argc, char *argv[])


{
int atributos;

if ((atributos = _chmod(argv[l], 0)) == -1)


printf("Erro ao acessar %s\n", argv[l]);
else
{
if (atributos & FA_ARCH)
printf("Arquivo ");
if (atributos & f a _DIREC)
printf(*Diretrio ");
if (atributos & FA_HIDDEN)
printf("Oculto ');
if (atributos & FA_LABEL)
printf("Rtulo do Volume ");
if (atributos & FA_RDONLY)
printf("Leitura somente ");
if (atributos & FA_SYSTEM)
printf("Sistema ");
>
>
A r q u iv o s , d ir e t r io s e d is c o s 203

Muitos compiladores C tambm fornecem a funo _dos_getfileattr e _dos_setfileattr, que lhe permite ler
ou definir os atributos do DOS, como mostrado aqui:
#include <dos.h>

int _dos_getfileattr(const char *nomearq. unsigned atributos);


int _dos_setfileattr(const char *nomearq. unsigned atributos);
As funes _dos_gctfileattr e _dos_setfileattr usam as constantes de atributos detalhados na Tabela 380.3.
Tabela 380,3 As constantes de atributo que as funes _dos_getfileattr e _dos_setfileattr usam.
Valor Significado
_A_ARCH Atributo Arquivar
_A _H ID D E N Atributo Oculto
_A_NORM AL Atributo Normal
_A _R D O N LY Atributo Leitura somente
_A_SUBDIR Atributo Diretrio
_A_SYSTEM Atributo Sistema
_A _VO LlD Rtulo de Volume do Disco

Se as funes _dos_getfileattr e _dos_setfileattr so bem-sucedidas, elas retornam o valor 0. Se ocorre um erro,


as funes retornam o valor -1, e atribuem varivel global ermo o valor E N O E N T (arquivo no-encontrado).
Como uma regra, seus programas somente devem manipular os atributos Arquivar, Leitura somente e
Oculto, reservando os outros para uso pelo DOS. Se voc somente modificar o atributo Leitura somente, use a
funo chmod, j apresentada na Dica 379, para aumentar a portabilidade do seu programa.
Nota: A Dica 1463 detalhar o uso de atributos de arquivo sob o Windows para modificar como um programa pode
acessar um arquivo.

Te st a n d o o Erro no Ca n a l de um A r q u iv o 381
Quando seus programas efetuam operaes de E/S em arquivos, eles sempre devem testar os valores de retorno
de funes, tais como, fopen, fputs, fgets e assim por diante para verificar se as operaes foram bem-sucedidas.
Para ajudar seus programas a realizar esse teste, C fornece a macro ferror, que examina o canal de E/S para ve
rificar se houve um erro de leitura ou gravao. Se um erro ocorreu, ferror retorna um valor verdadeiro. Se ne
nhum erro ocorreu, ferror retorna falso, como mostrado aqui:

#include <stdio.h>

int ferror(FILE *canal);

Aps ocorrer um erro de E/S em arquivo, a macro permanecer verdadeira at que seus programas chamem
a macro clearerr para o canal dado:

#include <stdio.h>

int clearerr(FILE *canal);

O programa a seguir, ferror.c, e exibe o contedo de um arquivo na teia. Aps cada operao de E/S,
o programa testa se houve um erro. Se ocorrer um erro, o programa terminar, exibindo uma mensagem de erro
em stderr:

#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[])


{
FILE *pa;
204 programando em C/C++ A Bblia

char linha[256];
if (pa = fopen(argv[1], "r"))
{
while (fgets(linha, sizeof(linha), pa))
{
if (ferror(pa))
{
fprintf(stderr, "Erro ao ler de %s\n",argv[1]);
exit(1);
>
else
{
fputs(linha, stdout);
if (ferror(pa))
{
fprintf(stderr,
"Erro ao gravar em stdout\n");
exit(l);
>
>
>
>
else
printf("Erro ao abrir %s\n", argv[l]);
>

382 D e t e r m in a n d o o Ta m a n h o de um A r q u iv o
medida que seus programas realizarem operaes de E/S em arquivo, algumas vezes voc precisar determinar
o tamanho em bytes de um arquivo. Para esses casos, voc poder usar a funo filelength de. C. A funo file
length retorna um valor Long. Voc precisa passar ao programa um indicativo (handle) de arquivo, no um pon
teiro de arquivo, como mostrado aqui:
#include <io.h>

long filelength(int indic_arquivo);


Se filelengtb for bem-sucedida, ela retornar o tamanho do arquivo em bytes. Se ocorrer um erro, filelength
retornar o valor -1, e definir a varivel global errno como EBADF (nmero de arquivo invlido). O programa
a seguir, tamanho, c, exibir o tamanho do arquivo de um determinado arquivo na tela:
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

void main(int argc, char *argv[])


{
int indic_arquivo;
long tamanho_arq;

if ((indic_arquivo = open(argv[l], OJRDONLY)) == -1)


printf("Erro ao abrir o arquivo %d\n", argv[l]);
else
{
tamanho_arq = filelength(indic_arquivo);
printf("O tamanho do arquivo em bytes %ld\n", tamanho_arq);
close(indic_arquivo);
>
>
Nota: A Dica 1463 detalhar como determinar o tamanho de um arquivo usando a A P I do Windows.
A r q u iv o s , d ir e t r io s e d is c o s 205

E s v a z ia n d o um Ca n a l de E/S 383
Para aumentar o desempenho do seu programa, a biblioteca de execuo de C normalmente bufferiza a sada do
seu arquivo at que tenha um setor para gravar no disco, ou at fechar o arquivo. Deste modo, a biblioteca de
execuo reduz o nmero de operaes lentas de E/S no disco. Infelizmente, quando seus programas usam um
buffer assim, deixam a porta aberta para a possibilidade de perder dados. Quando seu programa efetua uma fun
o, tal como fputs, para gravar sada e a funo no retorna um erro, o programa assume que o sistema opera
cional gravou corretamente os dados no disco. No entanto, na realidade, os dados ainda podem residir na
memria do seu computador. Se o usurio desligar o computador, ele perder dados. Se voc tiver um programa para
o qual precisa garantir que todos os dados sejam gravados no disco, poder usar fflush para instruir a biblioteca de exe
cuo a gravar os dados de seu buffer na memria para o disco. O formato da funo fflush como segue:
#include <stdio.h>

int fflush(FILE *canal_arquivo);


Se fflush for bem-sucedida, ela retornar o valor 0. Se ocorrer um erro, fflush retornar a constante EOF.
Os comandos a seguir ilustram como voc pode usar fflush para esvaziar o buffer do arquivo no disco aps cada
operao de sada:
while (fgets(linha, sizeof(linha), arq_entrada))
{
fputs(linha, arq_saida);
fflush(arq_saida);
>
Nota: Quando voc usa a funo fflush, instrui a biblioteca de execuo a chamar um servio do sistema operacional
para gravar os dados no disco. Se o sistema operacional efetuar sua prpria bufferizao (chamada cache do disco), ele
poder colocar seus dados em seu buffer de memria, e no no disco. Dependendo do software de cache no disco, talvez
voc possa chamar outro servio do sistema para descarregar a saida.

F ec h a n d o To d o s os A r q u iv o s A b e r t o s de uma S V e z 384
Como discutido na Dica 361, antes de seus programas terminarem, voc deve usar a funo fclose para fechar
seus arquivos abertos. Assuma que voc tenha uma funo que execute uma operao crtica. Se a funo expe
rimentar um erro, o programa dever terminar de imediato. Infelizmente, a funo pode no saber que existem
arquivos abertos. Nesses casos, seu programa pode usar a funo C fcloseall para fechar todos os arquivos abertos,
como mostrado aqui:
ttinclude <stdio.h>

int fcloseall(void);
Se fcloseall for bem-sucedida, ela retornar o nmero de arquivos que fechou. Se ocorreu um erro, fcloseall
retorna a constante EOF. Os comandos a seguir ilustram como voc poderia usar fcloseall:
if (status_erro == CRITICO)
{
fprintf(stderr, "Erro crtico de dispositivo\n");
fcloseall();
exit(l);
}

Ob t e n d o o I n d ic a t iv o de A r q u iv o de um Ca n a l
de A r q u iv o 385
Como discutido na Dica 360, quando seus programas efetuam operaes de arquivo, eles podem efetuar ope
raes de baixo nvel usando os canais de arquivo (FILE *canal). Voc tambm pode usar os indicativos de ar
206 P rog ram and o em C/C++ A B b l ia

quivo de baixo nvel {int indicativo). Como foi visto, vrias funes da biblioteca de execuo de C requerem in
dicativos de arquivo. Se seu programa usa canais de arquivo, voc pode fechar o arquivo e reabri-o usando um
indicativo de arquivo, ou pode obter um indicativo de arquivo usando a funo fileno de C, como mostrado aqui:
#include <stdio.h>

int fileno(FILE *canal);


O programa a seguir, fileno. c, usa a funo fileno para obter o indicativo de arquivo para um canal de ar
quivo aberto:
#include <stdio.h>
#include <io.h>

void main(int argc, char *argv[])


(
FILE *canal;
int indicativo;
long tamanho_arquivo;

if (canal = fopen(argv[1], "r"))


(
// Alguns comandos
indicativo = fileno(canal);
tamanho_arquivo = filelength(indicativo);
printf("O tamanho do arquivo %ld\n", tamanho_arquivo);
fclose(canal);
>
else
printf("Erro ao abrir %s\n", argvtl]);
>

386 C r ia n d o um No m e de A r q u iv o T e m p o r r io U s a n d o
P _ t m p d ir
medida que seus programas executam operaes de E/S em arquivos, eles precisam abrir um ou mais arquivos
temporrios ou gravar sada em um arquivo no-existente no disco. Nesses casos, a dificuldade ento torna-se de
terminar um nome de arquivo exclusivo para que o programa no sobrescreva um arquivo existente. Para ajudar
seus programas a gerar nomes de arquivos exclusivos, voc pode usar a funo tmpnam, como mostrado aqui:
#include <stdio.h>

char *tmpnam(char *buffer);


Se seu programa passar um buffer para tmpnam, a funo atribuir o nome temporrio ao buffer. Se voc
chamar tmpnam com NULL, tmpnam alocar memria para o nome de arquivo, retornando ao programa um
ponteiro para o incio do nome de arquivo. A funo tmpnam examina a entrada P_tmpdir no arquivo de cabe
alho stdio.h. Se P_tmpdirestiver definido, tmpnam cria o nome de arquivo exclusivo no diretrio corresponden
te. Caso contrrio, tmpnam criar o arquivo no diretrio atual. Observe que tmpnam no cria na verdade o
arquivo, mas em vez disso, retorna um nome de arquivo que seu programa pode usar com fopen ou open. O pro
grama a seguir, tmpnam. c, ilustra o uso da funo tmpname:
ttinclude <stdio.h>

void main(void)
{
char buffer[64];
int contador;

for (contador = 0; contador < 5; contador++)


A r q u iv o s , d ir e t r io s e d is c o s 207

printf("Nome de arquivo temporrio %s\n", tmpnam(buffer));


>
Nota: O CD-ROM que acompanha este livro inclui o programa mak_temp.cpp, que cria um arquivo temporrio
com a A P I do Windows.

C r ia n d o um No m e de A r q u iv o T e m p o r r io U s a n d o
TMP ou TEMP 387
medida que seus programas executam operaes de E/S, eles freqentemente precisam abrir um ou mais ar
quivos temporrios ou gravar sada em um arquivo no-existente no disco. Nesses casos, a dificuldade ento tor
na-se determinar um nome de arquivo exclusivo para que o programa no sobrescreva um arquivo existente. Para
ajudar seus programas a gerar um nome de arquivo exclusivo, voc pode usar a funo tempnam, como mostrado aqui:
#include <stdio.h>

char *tempnam(char *buffer, char *prefixo);


Se seu programa passa um buffer para tempnam, a funo atribui o nome temporrio ao buffer. Se voc
chamar tempnam com NULL, tempnam alocar memria para o nome de arquivo, retornando para o programa
um ponteiro para o incio do nome de arquivo. O parmetro prefixo lhe permite definir um conjunto de carac
teres que voc quer que tempnam coloque no incio de cada nome de arquivo. A funo tempnam examina as en
tradas do ambiente para determinar se uma entrada TM P ou TEMP existe. Se TM P ou TEMP for definido,
tempnam criar o nome de arquivo exclusivo no diretrio correspondente. Caso contrrio, tempnam criar o arquivo
no diretrio atual. Observe que tempnam na verdade no cria o arquivo, mas, em vez disso, retorna um nome de arquivo
que seu programa pode usar com fopen ou open. O programa a seguir, tempnam.c, ilustra o uso da funo tempnam:
tinclude <stdio.h>

void main(void)
{
char buffer[64];
int contador;

printf("Nome de arquivo temporrio %s\n", tempnam(buffer, "Biblia"));


>

C r ia n d o um A r q u iv o V e r d a d e ir a m e n t e T e m p o r r io 388
Nas Dicas 386 e 387 voc aprendeu como usar as funes tmpnam e tempnam para gerar nomes de arquivo tem
porrios. Como foi visto, tempnam e tmpnam na verdade no criam um arquivo, mas, em vez disso, elas simples
mente retornam um nome de arquivo que atualmente no est em uso. Alm disso, C tambm fornece uma
funo chamada tmpfile que determina um nome de arquivo exclusivo, e, depois, abre o arquivo, retornando um
ponteiro de arquivo para o programa. Voc implementar a funo tmpfile como mostrado aqui:
#include <stdio.h>

FILE tmpfile(void);
Se tmpfile for bem-sucedida, ela abrir o arquivo no modo de leitura e gravao, retornando um ponteiro
de arquivo. Se ocorrer um erro, tmpfile retornar NULL. O arquivo que tmpfile retorna um arquivo tempo
rrio. Quando o programa terminar (ou chamar rmtemp), o sistema operacional excluir o arquivo e descartar
seu contedo. O s comandos a seguir ilustram como seu programa poderia usar a funo tmpfile:
FILE *arq_temp;

if (arq_temp = tmpfileO)
{
// Arquivo temporrio aberto com sucesso
208 P r og ram and o em C/C++ A B b l ia

// Comandos que usam o arquivo


>
else
printf("Erro ao abrir o arquivo temporrio\n");

389 R e m o v e n d o A r q u iv o s T e m p o r r i o s
Na dica anterior voc aprendeu que a funo tmpfile permite que seus programas criem um arquivo temporrio
com contedo que existe somente durante a execuo do programa. Dependendo dos seus programas, voc po
der querer descartar os arquivos temporrios antes de o reprogram a terminar. Nesses casos, seu programa po
der usar a funo rmtmp, cujo formato mostrado aqui:
#include <stdio.h>
int rmtmp(void);
Se rmtmp for bem-sucedida, ela retornar o nmero de arquivo que fechou ou excluiu com sucesso.

390 P e s q u is a n d o o C a m in h o de Co m a n d o s pa ra um

A r q u iv o
Quando voc trabalha dentro do ambiente do DOS, o comando PATH define os diretrios que o DOS pesquisa
para os arquivos EXE, CO M e BAT quando voc executa o comando externo. Como os subdiretrios definidos
no PATH em geral contm seus comandos mais comumente usados, algumas vezes voc poder querer que um
programa pesquise as entradas de subdiretrio PATH para um arquivo de dados. Para esses casos, alguns com
piladores fornecem a funo searchpath. Voc chama a funo com o nome de arquivo desejado. Se searchpath
localiza o arquivo com sucesso, ela retornar um nome de caminho completo para o arquivo que seus programas
podem usar dentro de fopen. Se searchpath no encontrar o arquivo, ela retorna NULL, como mostrado aqui:
#include <dir.h>
\
char searchpath(const char nomearq);
O programa a seguir, caminho, c, ilustra o uso da funo searchpath para pesquisar o nome de arquivo es
pecificado:
tinclude <stdio.h>
#include <dir.h>

void main(int argc, char *argv[])


{
char *caminho;

if (caminho = searchpath(argv[1]))
printf("Nome do caminho: %s\n", caminho);
else
printf("Arquivo no-encontrado\n");
>
Nota: A funo searchpath pesquisa o arquivo especificado no diretrio atual antes de pesquisar os subdiretrios in
dicados pelo comando Path.

391 P e s q u is a n d o um A r q u iv o na L is t a de S u b d ir e t r io
DE UM ITEM DO AM BIENTE
Na Dica 390 voc usou a funo searchpath para pesquisar um arquivo especificado nos diretrios no caminho de
comandos. De um modo similar, voc pode querer pesquisar os diretrios especificados em uma entrada de am
biente diferente para um arquivo. Por exemplo, muitos compiladores C definem as entradas LIB e INCLUDE, que es
pecificam a localizao dos arquivos de biblioteca (com a extenso .lib) e arquivos de cabealho (com a extenso .h).
A r q u iv o s , d ir e t r io s e d is c o s 209

Para pesquisar os diretrios que os itens LIB e IN C LU D E especificam, voc pode usar a funo _searchenv, como
mostrado aqui:
#include <dos.h>

char *_searchenv(const char *nomearq, const char *item_ambiente, *nomecaminho);


A funo _searchenv pesquisa o nome de arquivo especificado nos diretrios especificados em item_ambien-
te. Se _searchenv encontrar o nome de arquivo, ela atribuir o nome de caminho do arquivo ao buffer de string
de caracteres do nome de caminho, retornando um ponteiro para o nome de caminho. Se _searchenv no encon
trar o arquivo, ela retornar NULL. O programa a seguir, pesq_amb.c, usa a funo _searcbenv para pesquisar um
arquivo especificado nos subdiretrios especificados no item LIB.
#include <stdio.h>
#include <stdlib.h>

void main(int argc, char *argv[])


( !
char caminho[128];

_searchenv(argv[1], LIB", caminho);


if (caminho[0])
printf("Nome do caminho: %s\n", caminho);
else
printf("Arquivo no-encontrado\n");
>
Nota: A .funo _searchenv pesquisa no diretrio atual o arquivo especificado antes de pesquisar os subdiretrios in
dicados no ambiente.
Nota: Nas Dicas 1474 at 1476 voc aprender como usar a API do Windows para localizar arquivos no seu sistema.

A b r in d o A r q u iv o s no D ir e t r io TEMP 392
Como voc sabe, muitos programas criam seus arquivos temporrios no subdiretrio especificado pelo item
TEM P do arquivo config.sys. Dentro de seus programas, voc pode facilmente criar seus prprios arquivos dentro
do diretrio indicado pela linha TEMP, usando a funo getenv. Os comandos a seguir ilustram como seus pro
gramas podem abrir um arquivo tempdado.dat, dentro do diretrio temporrio:
char nomecaminho[_MAX_CAMINHO];
strcpy(nomecaminho, getenv("TEMP"));

if (nomecaminho[0])
strcat(nomecaminho, "\\TEMPDADO.DAT");
else
strcat(nomecaminho, "TEMPDADO.DAT");
if (pa = fopen(nomecamlnho, "w"))
Neste fragmento de cdigo, se o item TEM P existir, o programa abrir o arquivo no subdiretrio corres
pondente. Se no houver um item TEM P, o programa abrir o arquivo no diretrio atual. Observe que o frag
mento de cdigo assume que a varivel TEM P no contm um valor que termina com uma barra invertida.
Idealmente, seus programas testaro o valor atual de TEM P e atuaro de forma apropriada.

M in im izan d o a s O p e r a e s de E/S em A r q u iv o 393


Comparado com a rpida velocidade eletrnica da CPU e da memria do seu computador, o disco mecnico
muito lento. Como resultado, voc deve tentar minimizar o nmero de operaes de E/S no disco que seus pro
gramas precisam executar. Com relao s operaes de arquivo, o arquivo aberto provavelmente consome a
maior parte do tempo. Portanto, voc sempre deve examinar seus programas para garantir que no abra e feche
um arquivo sem necessidade, ou que, repetidamente, abra um arquivo dentro de um lao. Por exemplo, consi
dere os seguintes comandos:
210 PROGRAMANDO EM C/C + + -- A BBLIA

while (escolha_menu 1= SAIR)



if (pa = fopen("BANCODAD.DAT", "r"))
{
// Pega o nome do cliente
pega_cliente(nome);
// Pesquisa no arquivo as informaes do cliente
pesquisa_info_cliente(nome, pa, i>uffer_dados);
fclose(pa);
}
else
{
erro_abrir_arquivo("Abortando...");
>
escolha_menu = pega_escolha_menu();
>
Os comandos repetem o lao, obtendo informaes do cliente at que o usurio selecione a opo SAIR.
Observe que a chamada da funo fopen ocorre dentro do lao. Portanto, o programa repetidamente executa a
operao lenta de E/S de arquivo. Para aumentar o desempenho do sistema, o programa deve colocar fopen fora
do lao. Se a funo pesquisa_cliente precisar comear no incio do arquivo, o programa poder rebobinar o ar
quivo, como mostrado aqui:
if (pa fopen("BANCODAD.DAT", "r"))
erro_abrir_arquivo("Abortando...");
while (escolha_menu 1= SAIR)
{
/ / .Pega o nome do cliente
pega_cliente(nome);
rewind(pa)/
// Pesquisa no arquivo as informaes do cliente
pesquisa_info_cliente(nome, pa, buffer_dados);
escolha_menu = pega_escolha_menu();
>
fclose (pa)j

394 E s c r e v e n d o C d ig o Q u e U s a B a r r a s I n v e r t id a s nos

No m e s de D ir e t r io
Vrias dicas apresentadas nesta seo trabalham com nomes de diretrio. Por exemplo, a funo chdir permite
que seus programas selecionem um diretrio especfico. Quando seu programa especifica um nome de diretrio
como um valor constante, certifique-se de usar barras invertidas duplas (\\) dentro de nomes de caminho, como
requerido. A seguinte chamada da funo chdir, por exemplo, tenta selecionar o subdiretrio DOS:
status = chdir("\DOS");
Quando voc usa um caractere de barra invertida dentro de uma string, lembre-se de que C trata o carac
tere de barra invertida como um smbolo especial. Quando o compilador C encontra a barra invertida, ele con
fere o caractere que segue para determinar se um smbolo especial, e, em caso afirmativo, substitui o caractere
com os correspondentes ASC II corretos. Se o caractere que aparece aps a barra invertida no for um smbolo
especial, o compilador C ignorar o caractere da barra invertida. Portanto, a funo chdir anterior tentaria sele
cionar o diretrio DOS em vez de WDOS. A chamada correta da funo neste caso seria como segue:
status = chdir (" W D O S " );
A r q u iv o s , d ir et r io s e d is c o s 211

M o d if ic a n d o o D i r e t r io A t u a l 395
medida que seus programas vo sendo executados, algumas vezes eles precisaro mudar do diretrio atual. Para
lhe ajudar a efetuar essa operao, a maioria dos compiladores fornece a funo chdir. A funo chdir muito
similar ao comando C H D IR do DOS: se voc chamar a funo com uma string que no contm uma letra de
unidade de disco, chdir procurar o diretrio na unidade atual. A seguinte chamada de funo, por exemplo, se
leciona o diretrio dados na unidade C:
status = chdir(C:WDADOS"); // Observe o uso de V
De uma forma similar, o comando a seguir seleciona o diretrio tclite na unidade atual:
status = chdir(\\TCLITE");
Se a funo chdir for bem-sucedida, ela retornar o valor 0. Se o diretrio no existir, chdir retornar o va
lor -1, e definir a varivel global ermo com a constante ENOENT. O programa a seguir, meuchdir. c, implementa
o comando C H D IR do DOS.

Nota: Alguns compiladores definem o smbolo _M A X _P A TH no arquivo de incluso direct.h (ou dir.h), em vez de
usar MAXPA TH.
Nota: A Dica 1468 explicar em detalhes a mudana de diretrios sob o Windows.

C r ia n d o um D ir e t r io 396
Durante a execuo, seus programas podem precisar criar um diretrio. Para ajudar seus programas a fazer isso,
a maioria dos compiladores C fornece uma funo mkdir, que muito similar ao comando MKDIR do DOS.
Se voc chamar a funo com uma string que no contm uma letra de unidade de disco, mkdir criar o diretrio
na unidade atual. Por exemplo, a seguinte chamada de funo cria o diretrio DADOS na unidade C:
status = mkdir ("C: W D A D O S ); // Observe o uso de W
De uma forma similar, o comando a seguir cria o diretrio TEM PDADO na unidade atual, no diretrio
atual:
status = mkdir("TEMPDADO");
Se a funo mkdir br