Você está na página 1de 197

Curso bsico de C++

DicasBCB
http://www.dicasbcb.com.br

Contedo
O b-a-b da programao ............................................................................................................................. 5
Afinal, o qu C++?...................................................................................................................................... 5
Um pouco de histria ..................................................................................................................................... 5
Conceitos........................................................................................................................................................ 6
O bit e o byte................................................................................................................................................ 12
Cuidados gerais ............................................................................................................................................ 12
Documentar o trabalho................................................................................................................................. 13
O programa main()....................................................................................................................................... 15
Primeiro programa ....................................................................................................................................... 15
Imprimindo dados nos componentes ........................................................................................................... 28
Comentrios ................................................................................................................................................. 31
Tipos fundamentais ...................................................................................................................................... 32
O tipo inteiro ................................................................................................................................................ 33
Os tipos ponto flutuante ............................................................................................................................... 36
O tipo caracter.............................................................................................................................................. 36
Modificadores de tipos................................................................................................................................. 38
Variveis ...................................................................................................................................................... 40
Atribuio de valores a variveis ................................................................................................................. 43
Variveis signed e unsigned......................................................................................................................... 45
Excedendo o limite de uma varivel ............................................................................................................ 46
Operaes matemticas com unsigned ........................................................................................................ 47
AnsiString .................................................................................................................................................... 48
Funes que modificam strings ................................................................................................................... 61
Funes que modificam strings ................................................................................................................... 63
AnsiString continuao... (dstring.h) ........................................................................................................... 65
AnsiString continuao... ............................................................................................................................. 66
AnsiString continuao... ............................................................................................................................. 67
A palavra-chave typedef .............................................................................................................................. 67
A diretiva #define ........................................................................................................................................ 68
A palavra-chave const.................................................................................................................................. 69
Operadores matemticos .............................................................................................................................. 73
Expresses.................................................................................................................................................... 75
Entendendo melhor o C++Builder ............................................................................................................... 78
#include <vcl.h> .......................................................................................................................................... 78
#pragma hdrstop........................................................................................................................................... 83
Unit1.h...................................................................................................................................................... 84
#pragma package(smart_init) ................................................................................................................... 85
#pragma resource ......................................................................................................................................... 87
_fastcall, __fastcall ...................................................................................................................................... 88
TComponent ................................................................................................................................................ 88
TComponent::Owner ................................................................................................................................... 89
Operadores de incremento e decremento ..................................................................................................... 90
Operadores relacionais................................................................................................................................. 91
O comando if................................................................................................................................................ 92

Apostila de C++ Builder

Pagina -2-

O comando else............................................................................................................................................ 95
if ...else - Continuao ................................................................................................................................. 95
Comandos aninhados e Indentao .............................................................................................................. 97
Operadores lgicos....................................................................................................................................... 98
O operador condicional ternrio .................................................................................................................. 99
Funes ...................................................................................................................................................... 100
Chamada de Funes ................................................................................................................................. 102
Definio de uma funo ........................................................................................................................... 103
Prottipos de funes ................................................................................................................................. 105
Variveis locais e globais........................................................................................................................... 107
A palavra-chave extern .............................................................................................................................. 109
A palavra-chave static................................................................................................................................ 111
Parmetros das funes.............................................................................................................................. 114
O comando return ...................................................................................................................................... 115
Valores Default .......................................................................................................................................... 117
Funes inline ............................................................................................................................................ 118
O comando goto ......................................................................................................................................... 119
O loop while............................................................................................................................................... 119
break e continue ......................................................................................................................................... 122
O loop while sem fim................................................................................................................................. 122
loop while - continuao ............................................................................................................................ 123
O loop do... while....................................................................................................................................... 124
O loop for................................................................................................................................................... 126
loop for - continuao ................................................................................................................................ 127
Omisso e aninhamento no loop for .......................................................................................................... 128
O comando switch...................................................................................................................................... 130
mtodos Canvas para desenhar objetos grficos........................................................................................ 138
propriedades Canvas .................................................................................................................................. 140
TPen::Width............................................................................................................................................... 143
TPen::Mode................................................................................................................................................ 145
TPenRecall ................................................................................................................................................. 146
Usando brushes .......................................................................................................................................... 146
TBrush::Color ............................................................................................................................................ 148
TBrush::Style ............................................................................................................................................. 148
TBrush::Bitmap.......................................................................................................................................... 150
TBrushRecall ............................................................................................................................................. 151
Ler e inserir pixels ..................................................................................................................................... 151
TCanvas::Pixels ......................................................................................................................................... 152
TBitmap::ScanLine .................................................................................................................................... 153
Propriedades e mtodos comuns de Canvas .............................................................................................. 154
Conhecendo arrays..................................................................................................................................... 165
Excedendo o limite de um array ................................................................................................................ 167
Matrizes multidimensionais ....................................................................................................................... 168
Arrays de caracteres ................................................................................................................................... 172
Estruturas ................................................................................................................................................... 174
Ponteiros .................................................................................................................................................... 176
A reutilizao de um ponteiro.................................................................................................................... 180
Apostila de C++ Builder

Pagina -3-

Ponteiros apontando para outros ponteiros ................................................................................................ 181


Ponteiros apontando para structs ............................................................................................................... 182
O nome do array......................................................................................................................................... 184
Variveis dinmicas ................................................................................................................................... 186
Mais problemas ... ponteiros soltos............................................................................................................ 190
Ponteiros & constantes............................................................................................................................... 193
Referncias................................................................................................................................................. 195
Reatribuio de uma referncia ................................................................................................................. 196

Apostila de C++ Builder

Pagina -4-

O b-a-b da programao
No fique impressionado, se um dia voc descobrir que o aplicativo que voc est usando para ler ou
tratar algum dado em seu computador foi desenvolvido em linguagem de programao C++ (pronuncia-se
"c mais mais"). Mesmo porque, em poucos dias, voc j estar desenvolvendo um processador de texto
que poder, inclusive, ser usado para substituir o bloco de notas do seu Windows.
Na escolha de uma linguagem de programao, deve-se considerar no apenas a facilidade de
aprendizado, mas principalmente aquilo que se quer e que se pode fazer com ela. Uma escolha errada
pode nos trazer prejuzos e frustraes.
Certamente C++ no a linguagem cujos conceitos mais facilmente so assimilados, mas tambm no
uma linguagem difcil. Na verdade, trata-se de uma linguagem de programao poderosa, para qualquer
tipo de desenvolvimento computacional, e quando se comea compreender os seus conceitos fica bastante
interessante e divertido o seu aprendizado. E no h nenhum inconveniente ou dificuldade em se aprender
C++ como primeira linguagem de programao. O que importante que existam a vontade de aprender,
a dedicao e a familiaridade com computadores.

Afinal, o qu C++?
Segundo Bjarne Stroustrup (criador de C++), "C++ uma linguagem de uso geral com uma tendncia
para a programao de sistemas que: uma C melhor; suporta abstrao de dados; suporta
programao orientada a objetos; e suporta programao genrica".
C++ um superset de C. Portanto quaisquer cdigos escritos para a linguagem C devem funcionar
normalmente em C++, porm, no raras vezes, C++ oferece uma maneira melhor, ou mais de uma
maneira, de se obter o mesmo resultado, o qu nos proporciona grande flexibilidade em nosso trabalho.
C++ uma linguagem de programao usada para a criao de uma infinidade de programas como
sistemas operacionais, processadores de texto como o Microsoft Word, planilhas eletrnicas como o
Excel, comunicao, automao industrial, bancos de dados, jogos, games, aplicativos multimdia,
navegadores Web como o Internet Explorer etc; uma linguagem que permite acesso aos recursos do
hardware e vai por a afora, sem deixar de lado os sistema embutidos usados nos automveis, celurares
etc.

Um pouco de histria
Ocorreu em junho de 1983, a primeira utilizao de C++ fora de uma organizao de pesquisa. Podemos
considerar C++ um resultado evolutivo da linguagem de programao BCPL, criada por Martin Richards

Apostila de C++ Builder

Pagina -5-

e que rodava num computador DEC PDP-7, com sistema operacional UNIX. Ken Thompson, em 1970,
efetuou algumas melhorias na linguagem BCPL e a chamou de linguagem "B". Em 1972, Dennis M.
Ritchie, no Centro de Pesquisas da Beel Laboratories, implementou diversas melhorias na linguagem "B"
que, considerada uma sucessora de "B", foi chamada de "C", rodando pela primeira vez num DEC PDP11, em sistema operacional UNIX.
O poder da linguagem "C" logo foi demonstrado, em sua primeira aplicao de peso, quando foi usada
para reescrever o sistema operacional UNIX, at ento escrito em linguagem assembly.
Com o tempo, a linguagem "C" tornou-se bastante popular e importante. Contribuiriam para o sucesso o
fato de essa linguagem possuir tanto caractersticas de baixo nvel quanto de alto nvel; a portabilidade da
linguagem, ou seja, poder ser usada em mquinas de diferentes portes e diferentes sistemas operacionais;
bem como o fato de, em meados de 1970, o sistema operacional UNIX ser liberado para as Universidades,
deixando de ficar restrito aos laboratrios. Por volta de 1980, vrias empresas j ofereciam diversas
verses de compiladores "C", compatveis com outros sistemas operacionais, alm do original UNIX.
Bjarne Stroustrup criou C++. Claramente, como pondera Stroustrup, C++ deve muito a "C" que foi
mantida como um subconjunto. Tambm foi mantida a nfase de "C" em recursos que so suficientemente
de baixo nvel para enfrentar as mais exigentes tarefas de programao de sistemas. Outra fonte de
inspirao para C++ foi Simula67, da qual C++ tomou emprestado o conceito de Classes.
Desde 1980, verses anteriores da linguagem, conhecidas como "C com Classes" tm sido utilizadas. O
nome C++, criado em 1983 por Rick Mascitti, representa as mudanas evolutivas a partir de "C", onde
"++" o operador de incremento em "C".
Bjarne Stroustrup projetou C++ basicamente para poder programar sem ter de usar Assembler, "C" ou
outras linguagens de alto nvel. Seu principal objetivo era tornar a escrita de bons programas mais fcil e
mais agradvel para o programador individual.
Em maro de 1998, o American National Standards Institute (ANSI) aprovou e publicou um padro para
a linguagem C++. A padronizao melhora a portabilidade e a estabilidade dos programas. Usando a
biblioteca Standart de C++, podemos, rapidamente, construir aplicaes confiveis, bem como mant-las
com menos custo e esforo.
Desde seu desenvolvimento por Dr. Bjarne Stroustrup, C++ foi extensamente usado na construo de
grandes e complexas aplicaes como telecomunicaes, finanas, negcios, sistemas embutidos e
computao grfica. A padronizao final da biblioteca de C++ torna mais fcil o seu aprendizado,
facilitando seu uso por uma grande variedade de plataformas, o que, por outro lado, significa garantia de
colocao profissional permanente para os bons programadores da linguagem.

Conceitos
Podemos classificar as linguagens de programao em dois grupos: aquelas consideradas de baixo nvel e
aquelas consideradas de alto nvel.

Apostila de C++ Builder

Pagina -6-

1. Linguagens de baixo nvel.


Quando nascemos, medida que crescemos, nossa percepo e o contato com a realidade do mundo, nos
anexa s coisas como elas j foram sedimentadas na cultura de um povo. Assim tambm ocorre com o
idioma e, de um modo geral, com algumas cincias que assimilamos em sequer darmos conta disso.
Por exemplo, quando uma criana conta para outra que possui trinta ou quarenta figurinhas, no percebe,
mas est fazendo uso do sistema numrico decimal (base 10). E o sistema numrico decimal est
incrustado em nosso cotidiano. Via de regra, todos os valores que usamos e todas as contas que fazemos
tm esse sistema numrico como base. Por exemplo, quando escrevo 543, voc entende 543 e no tem
dvidas, pois sabe o que 543 significa. Raciocinando em sistema numrico decimal, tambm no difcil
compreender que:
543 = (5 x 10) + (4 x 10) + (3 x 10)
pois
543 = (5 x 100) + (4 x 10) + (3 x 1)
pois
543 = 500 + 40 + 3.
Infelizmente, os sistemas computacionais no representam valores usando o sistema numrico decimal.
Internamente, os computadores representam valores usando dois nveis de voltagem (normalmente 0v e
+5v). Com esses dois nveis de voltagem, ns podemos representar dois valores. Por conveno, adota-se
o zero e o um. Ento, para todos os efeitos, os computadores s conhecem uma linguagem que
constituda por zeros e uns, ou cdigo de mquina, mais conhecida por linguagem binria. Nesse contexto,
se quisermos representar o nmero 543, devemos escrever:
1000011111
Qualquer quantia de dgitos binrios com valor igual a zero pode anteceder um nmero binrio sem
alterar-lhe o valor. Por exemplo, podamos representar o nmero 543 assim:
00000000000000000000000000000000001000011111.
Ante o exposto, no fica difcil compreender que a menor unidade de dados num computador um dgito
binrio. Um dgito binrio o mesmo que um bit, abreviatura de binary digits.
Complicado? No incio da era dos computadores (aqueles gigantes vlvula), os programas eram escritos
basicamente em binrio, mas, felizmente, longe se vo os dias em que se precisava programar diretamente
em binrio, embora ainda exista quem trabalhe nesta base.
O sistema numrico binrio tem um modo de funcionamento semelhante ao sistema numrico decimal,
porm com duas diferenas bsicas:

Apostila de C++ Builder

Pagina -7-

1. o sistema numrico binrio contm apenas os dois valores 0 e 1, em vez de 0, 1, 2, 3, 4, 5, 6, 7, 8 e 9; e


2. o sistema numrico binrio usa potncias de 2, em vez de potncias de 10.
Embora um bit seja capaz de assumir apenas dois valores (zero e um), o nmero de elementos que se pode
representar com um nico bit infinitamente grande. Por exemplo, pode-se representar quaisquer dois
valores diferentes com um nico bit: falso ou verdadeiro, maior ou menor, redondo ou quadrado e assim
por diante, numa lista incomensurvel. Todavia, esse tipo de construo no usual.
Um srio problema com o sistema binrio o tamanho de suas representaes. Veja bem, enquanto a
verso decimal de 543 contm apenas trs dgitos: 5, 4 e 3, a representao binria do mesmo valor
contm dez dgitos: 1000011111. Disso decorre que, ao se trabalhar com valores grandes, os nmeros
binrios rapidamente se tornam difceis de ser controlados. Embora seja possvel converter binrios em
decimal e vice-versa, tal tarefa no simples nem trivial. Mas essa a linguagem que a mquina entende.
Alternativamente, tentou-se programar em hexadecimal, que pode representar dezesseis valores entre 0 e
15 decimais. Os nmeros hexadecimais possuem duas caractersticas positivas:
1. sua converso para binrio relativamente simples; e
2. so razoavelmente compactos.
O sistema hexadecimal uma base de numerao que comea a ser contado no "0" e termina em "F":
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.
O sistema hexadecimal possui uma relao simples com o sistema binrio, uma vez que para cada grupo
de quatro dgitos binrios temos um em hexadecimal.

Apostila de C++ Builder

Pagina -8-

veja a tabela abaixo:


decimal

binrio

hexadecimal

0001

0010

0011

0100

0101

0110

0111

1000

1001

10

1010

11

1011

12

1100

13

1101

14

1110

15

1111

16

0001 0000

10

17

0001 0001

11

18

0001 0010

12

19

0001 0011

13

20

0001 0100

14

21

0001 0101

15

22

0001 0110

16

23

0001 0111

17

24

0001 1000

18

25

0001 1001

19

26

0001 1010

1A

27

0001 1011

1B

28

0001 1100

1C

29

0001 1101

1D

30

0001 1110

1E

31

0001 1111

1F

32

0010 0000

20

Apostila de C++ Builder

Pagina -9-

Existem algumas convenes que devem ser adotadas para se diferenciar os sistemas numricos:
1. pode-se colocar um sufixo "d" num valor decimal;
2. a letra "b" deve ser colocada no final de todo e qualquer valor binrio. Exemplo: 1011 0001b
3. a letra "h" deve ser colocada ao final de todo e qualquer valor hexadecimal. Exemplo 4D5Fh;
No h necessidade de enfatizar que a programao em hexadecimal, embora menos complexa que a
binria, continuava sendo demasiadamente complicada e demorada.
Nesse contexto, surge uma nova linguagem de programao: o Assembly, uma linguagem de smbolos
designados mnemnicas, que so instrues Assembly. Cada mnemnica tem a sua correspondncia em
um comando elementar inteligvel pelo computador. Nesse tipo de programao, o programador trabalha
diretamente com registradores da CPU e com a memria, entre outras coisas.
Programar em Assembly significa conversar quase que diretamente com a CPU, tal qual os sistemas
binrio e hexadecimal. Ou seja, nesses tipos de programao, o programa escrito em uma linguagem
muito prxima quela que a mquina entende, e por isso so as linguagens ditas de baixo nvel.
Abaixo, exemplo de instruo em Assembly:
a 100
MOV AX, 20
MOV BX, 30
ADD AX, BX
NOP
Do exemplo, AX e BX so registradores internos da CPU. O comando a 100 determina o endereo
inicial para o programa em 0100h; o programa executa o seguinte: move para o registrador AX o valor 20;
move para o registrador BX o valor 30; soma o contedo do registrador AX com o contedo do
registrador BX e deixa o resultado em AX; e a instruo NOP finaliza o programa.
2. Linguagens de alto nvel
Quando nos referimos s linguagens de alto nvel, estamos falando daquelas que so escritas em um
distanciamento relativo da linguagem mquina. Ou seja, as linguagens de alto nvel so aquelas que se
aproximam da linguagem humana, como a Linguagem Basic, C++, Pascal, Java etc.
Por exemplo, Para fazer uma frase aparecer na tela no DarkBASIC, basta digitar:

Apostila de C++ Builder

Pagina -10-

PRINT " Esta frase que est entre aspas ser exibida na tela! "

Veja agora, a mesma frase em linguagem C:

main()
{
printf (" Esta frase que est entre aspas ser exibida na tela! ");
exit (0);
}

Em Pascal:

program
begin
write (" Esta frase que est entre aspas ser exibida na tela! ");
end

Visualmente, o que diferencia estas linguagens de programao daquelas ditas de baixo nvel justamente
o fato de nestas linguagens podermos encontrar algum sentido naquilo que estamos lendo ou escrevendo.
Um simples programa como este que foi apresentado nessas linguagens de alto nvel, seria praticamente
ininteligvel para ns, se fosse escrito em binrio.
De uma forma simplista, podemos dizer que nas linguagens de alto nvel, o prprio programa tradutor
(compilador ou interpretador) que usamos se encarrega de conversar com a mquina, transformando todos
os comandos que inserimos no programa para uma linguagem que a mquina compreenda qual a resposta
a ser dada. Ou seja, o tradutor converte o cdigo-fonte em um cdigo executvel pela mquina.

Apostila de C++ Builder

Pagina -11-

O bit e o byte
O tipo de dado mais utilizado pelos chips da famlia 80x86 no o bit, e sim o byte. Um byte equivale a
um grupo de oito bits. Para facilitar a leitura e a compreenso, costumam-se adotar algumas convenes:
1. completar com zeros os nmeros binrios para que eles se tornem um mltiplos de quatro ou de oito
bits.
Exemplo: 543 = 001000011111;
2. cada grupo de quatro bits deve ser separado por espao.
Exemplo: 0010 0001 1111.
Um byte pode representar at 256 valores diferentes, pois so oito bits em potncia de dois:
28 = 256.
Geralmente um byte usado para representar valores compreendidos entre 0 e 255 no sinalizados ou
valores entre -127 a 128 sinalizados.
Para os tipos de dados, como os caracteres (letras ou smbolos), que no possuem mais do que 256
elementos, um byte normalmente suficiente.
Embora sejam visualizadas como letras e smbolos, as constantes caracteres so armazenadas
internamente pelo computador como um nmero inteiro entre 0 e 255. O caracter A, por exemplo, tem
valor 65; o B, 66; o C, 67; e assim por diante. Os valores numricos dos caracteres esto padronizados em
uma tabela chamada de American Standard Code for Information Interchange Table ou simplesmente
tabela ASCII.
Um grupo de 16 bits denomina-se word, ou palavra. Com 16 bits podemos representar at 65.536 (216)
valores diferentes: 0 a 65.535 no sinalizados e -32.767 a 32.767 sinalizados. Um dos principais usos para
a palavra so para os valores de inteiros.
Um grupo de 32 bits denomina-se double words. Com 32 bits podemos representar uma infinidade de
tipos de dados, como por exemplo valores ponto flutuante de 32 bits. So 4.294.967.296 (232) valores
diferentes: 0 a 4.294.967.295 no sinalizados e -2.147.483.647 a 2.147.483.647 sinalizados.

Cuidados gerais
Ao escrever um cdigo-fonte em C++, algumas precaues extras devem ser adotadas.

Apostila de C++ Builder

Pagina -12-

1. Deixar o cdigo o mais claro e compreensvel possvel, inserindo comentrios e usando-os


adequadamente, bem como tomar bastante cuidado com a grande liberalidade na forma que o formato
livre admite.

Documentar o trabalho
Em princpio, comentrios so textos que inserimos no programa para esclarecer qual a tarefa que
determinado comando realiza. Comentrios so muito importantes em nossos cdigos C++. A linguagem
C++ suporta dois estilos de comentrios:
a) comentrio no estilo C: /* ...*/
/* Neste tipo de comentrio, tudo aquilo que estiver inserido entre a
chave de abertura do comentrio (barra e asterisco) e a chave de fechamento
do comentrio (asterisco e barra) ser desconsiderado pelo compilador,
independentemente da quantidade de linhas usadas. */

b) comentrio no estilo C++: //


//
//
//
//
//

Neste tipo de comentrio, tudo aquilo que estiver inserido direita


do comentrio (barras duplas), at o final da linha
ser desconsiderado pelo compilador.
Neste estilo, a cada nova linha,
precisamos iniciar um novo comentrio.

Outra aplicao que podemos dar aos comentrios, a de tirar, temporariamente, a validade de uma parte
do programa:
cout << " Esta mensagem aparece na tela! \n";
// cout << " Esta mensagem no aparece na tela! \n";
/* cout << Esta mensagem no aparece na tela! \n"; *

Uma vez iniciado um comentrio no estilo C, no podemos inserir outro comentrio dentro deste, pois o
compilador considerar apenas a primeira chave de fechamento, o qu ocasionar um erro:

/* Abrimos
fechamento
na verdade
comentrio
compilador

um comentrio no estilo C; /* at a primeira chave de


no h problemas, pois a abertura desse novo comentrio,
no ocorreu, sendo considerada parte integrante do
inicial */ aqui comea a parte ilegal do comentrio, e o
deve acusar o erro */

Cuidado com o formato livre


H uma grande liberalidade na forma em que podemos escrever um cdigo C++, o que significa que o
posicionamento de alguns comandos ou caracteres dentro do texto, de regra, no influenciaro no
resultado da compilao. Esclarecendo melhor, espaos, tabulaes, retornos ou comandos escritos em
novas linhas so caracteres desconsiderados pelo compilador.
Abaixo transcrevemos um mesmo programa escrito de trs formas diferentes:

Apostila de C++ Builder

Pagina -13-

void main(void)
{
cout << " C++ possui formato livre!!!\n";
getch();
}

void
main
(
void
)
{
cout
<<
" C++ possui formato livre!!!\n"
;
getch
(
)
;
}

void main(void){cout << " C++ possui formato livre!!!\n";getch();}

O resultado apresentado pelo programa acima rigorosamente o mesmo em qualquer das trs hipteses.
Evidentemente, se, quando trabalharmos num projeto, no tivermos cuidado de escrever um bom e legvel
cdigo, o resultado poder apresentar-se bagunado, dificultando sua compreenso e, at mesmo, a
localizao e conserto de bugs (erros no cdigo que afetam diretamente o resultado) no programa.
Certamente em pouco tempo voc j estar desenvolvendo sua prpria tcnica para escrever bons
programas, usando o formato livre a seu favor.
2. Cuidado com o uso de letras maisculas e minsculas
C++ Case Sensitive
C++ Case Sensitive, isto , letras maisculas e minsculas so interpretadas de forma diferente pelo
compilador. Dentre outras implicaes, isso significa que se, por acaso, declararmos uma varivel com o
nome Temp, os seguintes nomes tero significados diferentes: TemP; TEMP; temp; tEmp; TeMp. Ateno
especial devemos ter quando escrevemos os comandos da linguagem nas instrues dos cdigos-fontes,
Apostila de C++ Builder

Pagina -14-

bem como com algumas funes pr-existentes. Boa parte desses comandos so digitados com letras
minsculas, como por exemplo: cout, cin, if, else, while, do ... while, for, switch ... case, include,
iostream.h, conio.h, open(), getch(), define, undef, \n, \t, \a etc. Mas essa regra, dependendo do
compilador, no absoluta e comporta excees, como algumas funes ou classes internas do C++
Builder, como ShowMessage() ou AnsiString ou quando, por exemplo no IBM-PC, trabalhamos com os
128 caracteres adicionais da tabela ASCII, pois neste tipo de dado, trabalhamos com o cdigo do smbolo
na base hexadecimal.
bastante comum erros de compilao por causa da sensitividade de C++, mas esse no um erro difcil
de se corrigir.

O programa main()
Todo programa C++ deve ter uma funo principal denominada main(), no podendo haver outra funo
com esse mesmo nome, sendo que a execuo do programa sempre ser iniciado em main().
O menor programa possivel em C++ :
main() {}
Ele define a funo main, que no recebe nenhum argumento e no devolve nada. O programa logo
encerra e o mximo que se percebe uma janela piscando rapidamente na tela.
Em se tratando aplicaes tradicionais Windows, necessrio far-se- entendermos a funo WinMain. Em
captulos posteriores, estudaremos essa funo com detalhes

Primeiro programa
Diversos programas-exemplo sero apresentados durante este curso, sendo que os mesmos foram
processados no c++builder 5.02, c++builder 3, c++builder 4 e no c++builder 6, todos da borland. Alguns
desses programas foram escritos com o intuito de ilustrar os tpicos apresentados; outros, para deixar o
curso mais interessante. Sendo assim, procuraremos apresentar tutoriais sobre a confeco de programas,
que iro se completando aos poucos, medida que avanamos no curso. No final, tudo dever fazer
sentido.
O cdigo-fonte de um programa C++ pode ser escrito em qualquer editor de texto simples que possa
salvar seu contedo em formato de texto puro. Podemos, inclusive, usar o Bloco de Notas do Windows.
Porm, no lugar da extenso .txt, devemos salvar os cdigos do programa com extenso .cpp. Contudo, a
forma mais rpida e sensata de se escrever um programa C++ usando o prprio editor de cdigos que
acompanha o ambiente de desenvolvimento C++. Esclarecemos aqui que muitos exemplos deste livro
esto redigidos com fonte formatada (itlica, negrito, colorida etc) apenas para fins didticos e para
facilitar uma eventual localizao no mesmo. Um cdigo-fonte C++ no dever ser escrito com este
formato e sim, conforme j exposto, em formato de texto puro, no formatado. Se voc est procurando
um bom editor de cdigos para seus programas, nos atrevemos a indicar o ConTEXT. Usamos esse editor
grandemente na elaborao destas pginas. Com ele ficou muito fcil padronizar a visualizao dos

Apostila de C++ Builder

Pagina -15-

cdigos fontes, bem como exportar os mesmos, j formatados, para o padro .html ou .rtf. Para maiores
informaes, consulte http://www.fixedsys.com/context
Inicialmente, para compreendermos melhor o conceito dos comandos e das instrues em C++,
trabalharemos um programa definido como aplicao Console Win32, que gera programas parecidos com
o DOS quando esto rodando, mas, na realidade, trata-se de programas de 32 bits executados no ambiente
Windows.
Bem, chega de conversa e vamos por as mos na obra:
1. inicialize o C++Buider;

2. d um clique no menu File;


3. d um clique em New...
4. Na janela que se abrir, selecione a opo Console Wizard e clique em OK;

5. selecione Console em Window Type e clique em finish.


Apostila de C++ Builder

Pagina -16-

O Builder C++, abrir o editor de textos para voc. nesta janela que digitaremos o cdigo-fonte de
nosso programa.

Observe o prprio BuiderC++, por default (padro), j digita parte do cdigo que usaremos. Porm essa
sugesto da Borland, neste tipo de aplicao Console Wizard, em princpio, pode ser ignorada, conforme
demonstramos abaixo. Voc pode optar por qualquer uma das duas formas para desenvolver seus
programas:

Apostila de C++ Builder

Pagina -17-

Na sugesto da Borland:
#pragma hdrstop
#include <condefs.h>
//---------------------------------------------------------------#pragma argsused
int main(int argc, char* argv[])
{
return 0;
}
devemos digitar o cdigo-fonte de nosso programa imbricando-o no cdigo pr-estabelecido acima.
Outra opo que temos deletar todo esse cdigo e simplesmente iniciar nosso programa a partir do
cdigo j visto do menor programa possvel em C++:
main()
{
}
Esse modelo aconselhvel, se voc estiver usando outro tipo de compilador. Caso haja algum conflito
entre o exemplo apresentado e o seu compilador, procure ajuda no manual do mesmo.
Nosso primeiro programa, ao ser compilado, escrever na sada de vdeo uma string (cadeia de caracteres)
com um espao de tabulao na segunda linha da tela, levar o cursor para a terceira linha da tela, emitir
um beep e, por fim, aguardar que uma tecla qualquer seja pressionada para encerrar a aplicao.
Delete toda a sugesto da Borland e, no editor de textos, digite:

#include <iostream>
#include <conio>
main()
{
std::cout << "\n\tEstou fazendo o meu primeiro programa\n\a";
getch();
}

Se preferir manter a sugesto da Borland, o cdigo dever ficar assim:

#pragma hdrstop

Apostila de C++ Builder

Pagina -18-

#include <condefs.h>
#include <iostream>
#include <conio>
//--------------------------------------------------------------------------#pragma argsused
int main(int argc, char* argv[])
{
std::cout << "\n\tEstou fazendo o meu primeiro programa\n\a";
getch();
return 0;
}

Para Salvar, clique o menu File, escolha a opo Save e, na pasta de sua preferncia, salve o programa
com o nome PrimProgram.bpr.
Agora vamos rodar o programa para ver o resultado.
Compilar significa converter o cdigo-fonte em linguagem que o processador (CPU) entenda, ou seja, em
cdigo de mquina, reunindo todos os comandos em um s arquivo. Linkeditar transformar esse cdigo
fonte em um executvel - um .exe (programa pronto).
Para executar o programa, ns podemos pressionar a tecla F9, ou podemos dar um clique em Run no
menu Run, ou podemos clicar a seta verde (Run F9) sob o boto Open Project.

Feito isso, seu primeiro programa produzir um executvel semelhante figura abaixo:

Apostila de C++ Builder

Pagina -19-

Muito bem, salvado o programa, encerre o aplicativo C++Builder. Abra a pasta onde voc salvou o
projeto PrimProgram.bpr e observe que o compilador colocou l cinco arquivos:
PrimProgram.bpr
PrimProgram.cpp
PrimProgram.exe
PrimProgram.obj
PrimProgram.tds
Ora, mas vejam s, ns j temos um arquivo .exe (PrimProgram.exe) em nossa pasta! Inicialize-o e
perceba que o nosso primeiro programa j roda sem auxlio do compilador. Pois bem, pressione uma tecla
qualquer para encerrar o aplicativo e d um (ou dois) clique(s) em PrimProgram.bpr para ver o que
acontece: ... Estamos de volta no ambiente de desenvolvimento do primeiro programa.
A seguir, procuraremos entender como conseguimos criar esse programa. Na explanao, aparecero
nomes como Classes, objetos, macros, funes etc, que talvez lhe paream estranhos e incompreensveis.
No se preocupe, pois, no momento certo, tudo ficar claro.

Apostila de C++ Builder

Pagina -20-

Diretivas de pr-processador
O pr-processador C++ um programa que fornece mecanismos para incluso de arquivos-textos,
cabealhos padro e compilao condicional baseada em macros. Esse programa tambm pode ser usado
para definir e usar macros.
Talvez voc esteja se perguntando: afinal, o qu quer dizer esse monte de coisas?
Por enquanto, apenas para elucidar nosso primeiro programa sem tumultuar nosso entendimento, vamos
nos contentar com uma explicao bem singela:
O pr-processador C++ um programa que roda antes do compilador e, baseando-se em certas instrues
denominadas diretivas de compilao, examina o programa fonte e implementa-lhe algumas
modificaes.
As diretivas de compilao mais comuns so:
#include
#define
#line
#ifdef
#ifndef
#if
#else
#elif
#endif
#undef
#error
#pragma

Apostila de C++ Builder

Pagina -21-

Algumas particularidades:
1. todas as diretivas iniciam com #;
2. devemos respeitar a regra de colocar somente uma diretiva em cada linha. Ou seja, no podemos
colocar outro comando qualquer na linha em que h uma diretiva.
a diretiva #include
Imagine que muitos dos resultados que esperamos obter de nossos programas j esto, de certa forma,
prontos, na biblioteca padro, para ser inseridos em nosso cdigo-fonte. Ou seja, no temos necessidade
de desenvolver determinados arquivos (classes, funes ou gabaritos) porque eles j existem e podem ser
usados em qualquer momento que precisemos deles.
Quando o pr-processador encontra a diretiva #include em nosso cdigo fonte, substitui a mesma pelo
contedo do arquivo indicado (no nosso exemplo, o conio e o iostream). O resultado que o compilador
encontrar e processar o arquivo implementado, e no a diretiva de compilao.
A diretiva #include um mecanismo de tratamento do cdigo-fonte que rene, em um nico arquivo de
compilao, cdigos (arquivos de cabealho ou hearder files, ou arquivos que contenham funes ou
definies de dados) que se encontram dispersos em vrios arquivos.
Para incluir os herder files em nosso cdigo-fonte, devemos usar os smbolos < e > ou " e " para
envolver o arquivo de cabealho:
#include <iostream>
ou
#include "iostream.h"
Se deixarmos espao entre o caracter < e o nome do arquivo de cabealho, ou entre o caracter " e o nome
do arquivo de cabealho, o compilador indicar erro:
< iostream.h> // [C++ Error] Project2.cpp(4): E2209 Unable to open include file ' iostream'.
Convencionou-se usar para os arquivos de cabealho o sufixo .h e para outros tipos de arquivos que
contenham funes ou definies de dados, o sufixo .hpp, .c, ou .cc, .cpp, .cxx, .C, conforme o
compilador. No caso do C++Builder, o arquivo que se encontra associado o .hpp, responsvel pela
interface com a VCL, que foi escrita em Object Pascal.
Historicamente, o sufixo .h era padro para todos os arquivos de cabealho. Entretanto, para evitar
problemas de compatibilidade com cabealhos de verses redefinidas de biblioteca padro, ou com novos
recursos de biblioteca que foram surgindo, resolveu-se suprimir o sufixo .h dos nomes de cabealho
padro (podemos dizer que cabealho padro o arquivo de cabealho definido na biblioteca padro). A

Apostila de C++ Builder

Pagina -22-

partir de ento, nenhum sufixo necessrio para cabealhos da biblioteca padro: <iostream>, <conio>,
<map> etc.
A principal diferena entre a biblioteca padro e a no padro que, enquanto uma biblioteca no padro
tem de ser incorporada manualmente, a padro incorporada automaticamente pelo compilador.
importante saber, ainda, que os recursos da biblioteca padro esto definidos num ambiente de nomes
chamado std e apresentados como uma srie de cabealhos.

O arquivo de cabealho iostream


Para o nosso programa imprimir a string Estou fazendo o meu primeiro programa no vdeo, ns
providenciamos para que a Classe iostream fosse chamada compilao atravs da diretiva #include. A
biblioteca iostream contm as declaraes necessrias ao uso de streams de entrada (teclado) e sada
(vdeo), como, por exemplo, o objeto cout e o operador de insero <<. Obtm-se o operador de insero
<< digitando-se o caracter "menor que" duas vezes.
O objeto cout o responsvel pela sada, no console ou na tela, da string que digitamos: Estou fazendo o
meu primeiro programa.
O operador de insero << (envie para) escreve o argumento da direita (a string) no da esquerda (no
cout).
Alm do cout e do operador de insero << a Classe iostream contm outras definies de impresso e
leitura (I/O), que estudaremos mais adiante.
Voc deve ter notado que demonstramos a incluso dos arquivos de cabealho da Classe iostream de trs
modos diferentes:
#include <iostream> // Cabealho padro sem sufixo .h
#include "iostream.h" // Cabealho de biblioteca no padro
#include <iostream.h> // Cabealho padro com sufixo .h

No h necessidade de inserirmos nenhum sufixo para cabealhos da biblioteca padro, porque os


smbolos < > j denotam o chamamento de cabealhos padro. Contudo, as declaraes dos cabealhos
mais antigos, so colocadas no ambiente de nomes global, carecendo do sufixo .h.
Os cabealhos colocados entre aspas " " determinam que o pr-processador procure o cabealho primeiro
no diretrio atual, e depois na biblioteca padro (Include).
Em nosso programa: #include<iostream> instrui o pr-processador a incluir os recursos de entrada e sada
de iostream padro, e std::cout determina a incluso do cout padro.

Apostila de C++ Builder

Pagina -23-

Se quisermos, podemos tornar todos os nomes std globais, o que nos poupa da tarefa de ter que digitar
constantemente o prefixo std:: antes de cout:
#include <iostream>
using namespace std;
Se algum dos nossos programas no rodar, podemos usar uma verso mais tradicional. Para isso
colocamos o sufixo .h nos cabealhos e removemos o prefixo std::. Exemplo:

#include <iostream.h>
#include <conio.h>
main()
{
cout << "\n\tEstou fazendo o meu primeiro programa\n\a";
getch();
}
Boa parte dos programadores, talvez por praticidade, parece preferir essa segunda verso. Daqui para
frente, escolha sua!

O arquivo de cabealho conio


Nosso programa possui outro cabealho, o arquivo conio. Trata-se de um arquivo de incluso necessrio
utilizao da funo getch(). Quando descrevemos o que o nosso programa faria, afirmamos que, por fim,
ele aguardaria que uma tecla qualquer fosse pressionada para encerrar a aplicao. Essa tarefa foi
desempenhada pela funo getch() que retorna o caracter lido no teclado, sem imprimi-lo no vdeo. Se
quisermos que o caracter lido seja impresso no vdeo, podemos usar a funo getche(), tambm integrante
de a conio.
Lembra-se do menor programa possvel em C++, quando afirmamos que tudo o que veramos seria um
breve piscar da janela na tela e o encerramento do programa? Pois bem, poderamos usar getch() para
segurar a janela na tela at que uma tecla fosse pressionada!

Caracteres especiais
Antes que nossa string fosse imprimida no vdeo, o programa pulou uma linha (caracter de nova linha) e
imprimiu uma caracter de tabulao horizontal. Depois da string, o programa colocou o cursor na linha de
baixo (nova linha) e emitiu um beep (sinal sonoro).
Como fizemos isso?

Apostila de C++ Builder

Pagina -24-

Alguns caracteres no podem ser inseridos diretamente pelo teclado. Por exemplo, se, durante a
elaborao do cdigo-fonte, no meio da string, pressionarmos a tecla Enter pensando que estaremos
inserindo uma nova linha, faremos com que o compilador apresente uma mensagem de erro.
A soluo usarmos algumas combinaes de caracteres que realizam essas tarefas. Essas combinaes,
conhecidas como seqncia de escape, so representadas por uma barra invertida \ e um caracter. Por
exemplo, a combinao \n representa nova linha (Enter), \t representa tabulao horizontal (Tab) e \a
representa o beep. Essas seqncias de escape, ns j conhecemos. Vejamos outras:

Escape

Nome

\a

Bell (alerta)

007

emite um som do computador

\b

Backspace

008

retrocede um caracter

\n

New Line

010

envia o curso para a prxima linha

Carriage

013

move o cursor para o incio da linha

Horizontal

009

pe o cursor para a prxima tabulao

\r

Valor ASCII

Descrio

return
\t
Tab
\xff
\0

representao hexadecimal
Null

000

exibe um caracter nulo

\"

Aspas duplas

034

exibe aspas duplas ()

\'

apstrofe

039

exibe apstrofe (')

\?

Interrogao

063

exibe ponto de interrogao

\\

Barra invertida

092

exibe barra invertida

String(s) de texto
Constante caracter uma letra ou smbolo colocado entre apstrofes: 'a', 'b', '~', 'A', 'B', '\n, '\r', '\xa0',
'\xa2', 'xa3' etc.
Uma importante atividade nos programas em geral a manipulao de textos como palavras, frases,
nomes etc. Na realidade, esses textos so constantes string(s), que se compem de um conjunto de
caracteres colocados entre aspas: "Estou fazendo o meu primeiro programa",
"constante string", "\tOuviram do Ipiranga as margens pl\xa0"
"cidas\n\tde um povo her\xa2ico o brado retumbante\n\te o sol da
liberdade em raios f\xa3lgidos,\n\tbrilhou no c\x82u da P\xa0tria nesse
instante.\n"

Apostila de C++ Builder

Pagina -25-

Funes
Funes so a base de qualquer programa C++. Elas compem, juntamente com as Classes, os blocos
construtivos da linguagem. Dentro das funes, encontramos todos os comandos executveis, sendo que
as mesmas so a maneira tpica de se obter alguma execuo em C++.
Vamos reescrever o primeiro programa. Por enquanto, no queira compreender todos os detalhes da
alterao, uma vez que, por ora, nossa preocupao apenas esclarecer, sem pormenores, quais so os
elementos bsicos de uma funo. Em outra seo deste curso, abordaremos as funes de uma forma
mais abrangente e minuciosa.
Inicialize PrimProgram.bpr, caso no esteja com ele aberto. No compilador, clique em Edit e depois em
Select All; Clique novamente em Edit e depois em Delete. Agora copie o cdigo abaixo no editor de
textos do compilador.

/*Dica: no use o recurso de copiar e colar cdigos-fontes


quando estiver estudando.
Procure digitar todo o cdigo e entender o resultado que cada. instruo
conhecida produzir no programa.*/
#include <iostream>
#include <conio>
using namespace std; // torna todos o nomes std globais
void ModifPrimProg(void); // declara a fino ModifPrimProg
int main() // estamos em main()
{
ModifPrimProg(); // chama a funo ModifPrimProg
return 0;
} // fim de main()
void ModifPrimProg(void) // cabealho da definio da funo
{
cout << "\n\t\tModificando o primeiro programa."
"\n\n\n\t\tDigite dois caracteres mas veja "
"s\xa2 o primeiro: ";
getche(); // retorna e imprime o caracter lido no vdeo
cout << '\a'; // beep - sinal sonoro
getch(); // retorna o caracter sem imprimi-lo no vdeo
} // fim de ModifPrimProg()

Execute o programa e volte aos estudos.


Com essa pequena alterao no cdigo, podemos visualizar melhor alguns detalhes sobre as funes.
Uma funo deve ter a seguinte forma geral:

Apostila de C++ Builder

Pagina -26-

tipo nome(declarao dos parmetros)


{
Primeira_Instruo;
Segunada_Instruo;
Etc_instruo;
}
Nosso programa agora possui quatro funes: main(), ModifPrimProg(), getche() e getch(). O nome
delas : main, ModifPrimProg, getche e getch respectivamente. A funo main(), como sabemos, a
principal, aquela onde a execuo do programa se inicia; ModifPrimProg() uma funo que no
estava em biblioteca alguma, tendo sido criada por ns; getche() e getch() ns tambm j conhecemos do
arquivo de cabealho conio.
Precedendo o nome da funo main() temos o tipo int, que informa ao compilador que main() pode
retornar um tipo int. J a funo ModifPrimProg() do tipo void. O tipo void significa que a funo
no possui valor de retorno. Quando nenhum tipo de retorno for especificado, presume-se o valor de
retorno int para a funo. As funes retornam valores por meio do comando return.
Aps o nome de qualquer funo temos parnteses de abertura "(" e de fechamento ")". Nesses parnteses,
informamos ao compilador a lista de parmetros que a funo pode receber. Logo,
ModifPrimProg(void) no pode receber nenhum parmetro por causa do tipo void.
Entende-se por cabealho da definio da funo o conjunto tipo nome(declarao dos parmetros) que
antecede a chave "{" de abertura do corpo da funo. Entre a chave de abertura "{" e a de fechamento "}"
do corpo da funo, encontramos as tarefas (instrues) que a mesma realiza.
Instrues so as tarefas que determinados comandos realizam. Toda instruo encerrada com um ponto
e vrgula ";":
cout << "uma instruo!";
getch();
return 0;
A falta do ponto e vrgula ensejar mensagem de erro pelo compilador. Porm, no se coloca ponto e
vrgula aps as chaves de abertura e fechamento das funes.

Apostila de C++ Builder

Pagina -27-

No se preocupe em entender, por ora, todos os conceitos apresentados, posto que os abordaremos
novamente no correr do curso. At aqui, tivemos apenas a inteno de coloc-los em contado com o
ambiente de programao C++Builder e com os fundamentos da linguagem C++.

Imprimindo dados nos componentes


Se voc ainda no se sente familiarizado com o C++Builder, ou no se sente seguro para a respeito da
forma correta de se colocar componentes nos formulrios (Forms), antes de prosseguir no curso, d uma
olhada nas seguintes lies:

Introduo ao BCB(http://www.dicasbcb.com.br/Iniciando_o_BCB/Inicia_o_BCB.htm)
Introduo ao BCB - 2 parte(http://www.dicasbcb.com.br/Iniciando_o_BCB2/Inicia_o_BCB2.htm)
Podemos inserir palavras, textos ou frases em diversos componentes atravs cdigos ou de suas
propriedades no Object Inspector. Essas propriedades, uma vez demarcadas, determinam o modo que o
programa iniciar a sua execuo. Podemos, posteriormente, em tempo de execuo, alterar essas
propriedades de diversas formas, conforme o caso.
Exemplos: No Object Inspector, mude o texto da propriedade Caption do Form, de um Label, de um
boto, e assim por diante e visualize, j no projeto, o resultado da alterao.
Outros componentes, derivados de outros ramos, possuem outras formas de ser alterados. Por exemplo,
altere a propriedade Text de um Edit, ou de um MaskEdit; ou a propriedade Items de um ListBox; ou as
propriedades Text e Items de um ComboBox etc.
Vejamos algumas formas de inserir textos em componentes, atravs do cdigo, em tempo de execuo:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y,
"Imprimindo um texto no form com o objeto Canvas" );
Label1 -> Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y,
"Imprimindo um texto no Label com o objeto Canvas" );
Canvas->TextOut( Canvas->PenPos.x = 100, Canvas->PenPos.y = 100,
"Imprimindo um texto nas coordenadas X = 100 e Y = 100 do Form" );
}

Outro exemplo:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)

Apostila de C++ Builder

Pagina -28-

{
/* Este exemplo deve ser testado com dois cliques.
O primeiro chamar a propriedade Caption; o segundo, o objeto Canvas */
Label1 -> Caption = "Testando o Caption";
/* Na linha de cdigo abaixo, precisamos determinar uma coordenada diferente
da default (0, 0), para que esse texto no venha a sobrescrever o Caption de Label */
Label1 -> Canvas->TextOut( Canvas->PenPos.x = 100, Canvas->PenPos.y = 100,
"Imprimindo um texto nas coordenas X = 100 e Y = 100 do Label" );
}

Outro exemplo:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1 -> Caption = "Testando propriedades";
Edit1->Text = "Continuando o teste ...";
ListBox1->Items-> Add(Label1 -> Caption);
ListBox1->Items-> Add("Testando ...");
ComboBox1 -> Text = "Fala, Grande!";
ComboBox1 -> Items -> Add(Label1 -> Caption);
ComboBox1 -> Items -> Add("Fala, Grande...");
ComboBox1 -> Items -> Add(Edit1->Text);
}

Outro exemplo:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
ShowMessage("Al, Thrbio!");
ShowMessage("Al, Thrbio!"
"\nEstou na segunda caixa de mensagem,\n e na terceira linha");
MessageBox(0, "Agora uma caixa de mensagens \nm\n\ta\n\t\ti\n\t\t\ts\neditada!",
"Caixa de Aprendizagem...", 64);
}

Nota introdutria. No avanar deste curso, voc perceber que, propositadamente, usamos alguns nomes,
comandos ou tipos de dados com os quais voc poder no estar habituado a trabalhar. No se assuste e
nem se preocupe em querer entender imediatamente todos os detalhes apresentados, pois tudo dever ficar
bastante claro no tempo certo. Concentre-se, basicamente, em entender a manipulao dos dados
referentes ao tpico apresentado.

Apostila de C++ Builder

Pagina -29-

Conhecendo melhor as propriedades que capturam dados


Nos exemplos anteriores, conhecemos um modo de inserir textos ou strings nos componentes, sem nos
preocuparmos de que modo isso nos pode ser til. Agora aprofundaremos um pouco mais o estudo para
podermos entender que essas propriedades no esto limitadas e pode produzir alguns resultados mais
teis:
void __fastcall TForm1::Button1Click(TObject *Sender)
/* Neste exemplo, iremos corrigir uma falha referente cor do primeiro
exemplo em que usamos o objeto Canvas do Form. Como voc deve ter notado,
as cores da frase sairam com um fundo branco (clWhite), enquento que o form
manteve a cor original clBtnFace, visto que no procedemos a nenhuma alterao
nela. Para visualizar melhor essa situao, d uma olhada na propriedade
Color do Form no Object Inspector. Pois bem, vamos corrigir a cor do fundo
da frase para igual-la ao Form.*/
{
// Ok. A cor do fundo igual cor do Form
Canvas -> Brush -> Color = clBtnFace;
/* A linha de cdigo abaixo nos mostra como podemos usar
propriedades matemticas diretamente no Form*/
Canvas->TextOut( Canvas->PenPos.x = 10,
Canvas->PenPos.y = 100, (5 * 4) + (60 - 50) );
/* Podemos chamar funes que nos mostrem a data e a hora...*/
Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y, Date()/* +Time()*/);
}

Evidentemente, outros componentes tambm so frteis para trabalharmos com dados:


void __fastcall TForm1::Button1Click(TObject *Sender)
{
/*Uma caixa de mensagem que pode nos mostrar a data, a hora ou ambas.*/
ShowMessage( Time() /* + Date()*/ );
}

Por certo, as operaes abaixo j no causam muitas surpresas em voc:

void __fastcall TForm1::Button1Click(TObject *Sender)


{
ShowMessage("Al, Thrbio!\nVoc sabe qual o resultado de "
"286 multiplicado por 132 somado com 412?");

Apostila de C++ Builder

Pagina -30-

ShowMessage((286 * 132) + 412);


Label1 -> Caption = (5 * 4) + 13; // imprime 33 no label
AnsiString a = 2 + 12; // AnsiString pode funcionar como inteiro ou ponto flutuante
/* neste exemplo, o sinal + neste local do cdigo, serve para
concatenar os dados. S ocorre a concatenao porque usamos o
tipo AnsiString. Se tivssemos usado uma varivel inteira ou
ponto flutuante, o resultado seria diferente*/
Label2 -> Caption = "Multiplicao de 14 X 14 = " + a * a;
/* produz o mesmo resultado no Label. O mesmo resultado teramos se
tivssemos usados variveis inteiras ou ponto flutuante*/
Edit1 -> Text = "****Elimina os quatro primeiros caracteres" + 4;
}

Vamos aproveitar para conhecer a base do cdigo que ser usado para construirmos uma calculadora.
Usaremos um Label e um Boto qualquer no Form.
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
/* O cdigo abaixo determina que o programa coloque no Caption de Label1
tudo aquilo que j est nele e mais o nmero 1. */
Label1 -> Caption = Label1 -> Caption + 1;
}

Comentrios
Quando estamos empenhados na tarefa de escrever uma aplicao, fundamental tomarmos algumas
providncias para que no nos percamos nas diversas linhas de cdigo que por ventura utilizaremos. Uma
coisa muito til que podemos, ou melhor, que devemos fazer colocar comentrios que nos esclaream a
utilidade das diversas partes do cdigo. Evidentemente, voc j tem percebido que, junto s linhas de
cdigo, ns colocamos algumas frases esclarecedoras dentro de um par de barras com asterisco /* */, ou
imediatamente aps duas barras //. Essas frases so os comentrios.
C++ aceita esses dois estilos de comentrios:

/* Esse estilo de comentrio derivado da linguagem C. Ele aberto


com uma barra seguida de um asterisco. Tudo aquilo que estiver aps
essa chave de abertura, at encontrar uma chave de fechamento (um
asterisco e uma barra) ser desconsiderado pelo compilador */
//
//
//
//
//

Essas duas barras significam comentrios no estilo C++.


Uma vez aberto, esse comentrio no precisa ser fechado.
Mas ele s vale para a linha em que foi aberto,
a partir do ponto em que foi aberto
e at o final da linha nada mais ser considerado

Apostila de C++ Builder

Pagina -31-

Comentrios tambm podem ser teis para tirar o efeito de determinadas partes de cdigo, quando
estamos fazendo experincias. Voc j viu tal fato, nos exemplos que colocamos o cdigo para apresentar
a data ou a hora. Se voc retirar as chaves de abertura e de fechamento, perceber que o resultado do
programa ser diferente.
Abaixo apresentamos um exemplo de como podemos usar comentrios para retirar efeitos de um cdigo
que j usamos anteriormente. Compile e execute para ver que o resultado do programa ser outro:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Label1 -> Caption = "Testando propriedades";
// Edit1->Text = "Continuando o teste ...";
/* ListBox1->Items-> Add(Label1 -> Caption);
ListBox1->Items-> Add("Testando ..."); */
ComboBox1 -> Text = "Fala, Grande!";
ComboBox1 -> Items -> Add(Label1 -> Caption);
ComboBox1 -> Items -> Add("Fala, Grande...");
ComboBox1 -> Items -> Add(Edit1->Text);
}

Tipos fundamentais
A linguagem C++ possui tipos fundamentais de dados que representam valores como caracteres, inteiros,
pontos flutuantes e booleanos. Os tipos inteiro (int) e pontos flutuantes (float e double) representam os
nmeros de um modo geral. Caracteres (char) representam as letras ou smbolos e o tipo booleano (bool)
oscila entre dois valores, geralmente para representar duas situaes inversas como, por exemplo, falso ou
verdadeiro. Podemos, ainda, considerar um tipo bsico de dados, o tipo enum, ou enumerados, o qual nos
permite definir conjuntos de constantes, normalmente do tipo int, chamados tipos de dados enumerados.
As variveis declaradas deste tipo podero adquirir somente entre os valores definidos.
Coloque um Memo e um Button no Form. No evento OnClick do boto digite:
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
char ValChar = 'a';
int ValInt = 100;
float ValFloat = 100.78; // problemas na preciso
double ValDoub = 9.9876543;
bool ValBool = (2.0000 == (20 - 18)); //Verdade: dois = a vinte menos dezoito
Memo1->Lines->Strings[0] = ValChar; // 1 linha do Memo imprime: a
Memo1->Lines->Strings[1] = ValInt; // 2 linha do Memo imprime: 100
Memo1->Lines->Strings[2] = ValFloat; // 3 linha do Memo imprime: 100.78...
Memo1->Lines->Strings[3] = ValDoub; // 4 linha do Memo imprime: 9.9876543
// Se a afirmao feita na declarao de ValBool verdadeira
if( ValBool == True)
/*5 linha de Memo imprime: Afirmao Verdadeira*/
Memo1->Lines->Strings[4] = "Afirmao Verdadeira";

Apostila de C++ Builder

Pagina -32-

else // seno - ou seja, se a afirmao falsa


/* Quinta linha de Memo imprime: Afirmao Mentirosa */
Memo1->Lines->Strings[4] = "Afirmao Mentirosa";
}

Nota: Se o programa acima no imprimir todas as linhas, pressione a tecla Enter alguma vezes para criar
linhas vazias no Memo. Desta forma, as strings sero colocadas no espao correto. Depois (no tpico
Variveis)
veremos
outra
soluo
mais
adequada
para
o
problema!
A linguagem C++ ainda nos oferece um tipo especial que serve para indicar, justamente a ausncia de
tipo: o void. No exemplo acima percebemos o uso deste tipo junto funo do evento chamado,
indicando que tal funo no devolver nenhum valor. O void tambm ser usado em funes que no
requerem parmetros.

O tipo inteiro
O tipo inteiro um nmero de valor inteiro, ou seja, no fracionrio. De um modo geral, trata-se de
seqncias de dgitos que representam nmeros inteiros, que podem ser escritos na base 8 (octal), na base
10 (decimal) ou na base 16 (hexadecimal).
Um inteiro decimal formado pela seqncia de dgitos decimais: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Exemplos
vlidos para decimais so:
0

12345

- 89

Os nmeros a seguir no so exemplos vlidos para decimais:


00

123.4

1,0

89-8

12 34

045

OBS. Embora alguns compiladores aceitem declaraes do tipo:


int i = 123.4;
todos os nmeros colocados depois do ponto fracionrio (nesse caso, o 4) sero desconsiderados.
Um inteiro hexadecimal formado pela seqncia de dgitos decimais: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
combinados com letras que vo de "A" a "F" (A, B, C, D, E, F ou a, b, c, d, e, f). Como no h regras que
impeam que um hexadecimal possua s valores decimais em sua composio, devemos diferenci-los
dos inteiros decimais inserindo 0x em seus primeiros dgitos. Exemplos vlidos para hexadecimais so:
0x0

0x1234

0x1

0xA

0xaBcD 0x1A9F

Os nmeros a seguir no so vlidos para valores hexadecimais:


00x

Apostila de C++ Builder

0x123.4

0x1,0

0xAGB

Pagina -33-

OxaB cD

FF12

Um inteiro octal formado pela seqncia de dgitos decimais: 0, 1, 2, 3, 4, 5, 6, 7. Devemos diferencilos dos inteiros decimais inserindo 0 em seu primeiro dgito. Exemplos vlidos para octais so:
00

012345

01

- 056

Os nmeros a seguir no so exemplos vlidos para octais:


0

0123.4

01,0

089

012 34 45

Via de regra, os dados inteiros so devolvidos pelo programa no formato decimal. Desta forma, podemos
testar uma aplicao, onde colocaremos valores inteiros em vrios formatos, porm os mesmos sempre
sero exibidos em formato decimal. Voc poder testar valores vlidos e valores no vlidos para cada
base de dados e visualizar os resultados.
Coloque um Label e um Button no Form. No evento OnClick do boto digite:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// declara um valor inteiro decimal cujo nome ser i
int i = 43; // podemos substituir o 43 por hexadecimais,
//octais ou outros valores decimais
Label1 -> Caption = i; // coloca i no Caption de Label1
}

Compile e execute a aplicao. O Label imprimir o nmero 43. Feche a aplicao e substitua o valor 43
(decimal) no Editor de Cdigos por 0x2b (hexadecimal). Rode o programa e d um clique no boto para
ver o resultado. Agora faa a mesma experincia substituindo o 0x2b por 053 (octal). Se voc fez tudo
direitinho, qualquer dos testes que voc executar dever imprimir o nmero 43 no Label do Form. Isso
porque esses valores so equivalentes. Baseando-se nas explicaes introdutrias sobre esses valores
inteiros e na tabela abaixo, faa mais alguns testes para compreender melhor o que ocorre a nvel
equivalncia desses dados.
veja uma tabela inicial:

Apostila de C++ Builder

decimais

octais

hexadecimais

00

0x0

01

0x1

02

0x2

03

0x3

04

0x4

05

0x5

06

0x6

07

0x7

Pagina -34-

010

0x8

011

0x9

10

012

0xA

11

013

0xB

12

014

0xC

13

015

0xD

14

016

0xE

15

017

0xF

16

020

0x10

17

021

0x11

18

022

0x12

19

023

0x13

20

024

0x14

21

025

0x15

22

026

0x16

23

027

0x17

24

030

0x18

25

031

0x19

26

032

0x1A

27

033

0x1B

28

034

0x1C

29

035

0x1D

30

036

0x1E

31

037

0x 1F

32

040

0x20

Tudo pode estar parecendo muito complicado, mas no se preocupe porque o uso de valores octais ou
hexadecimais no comum. Alm do mais, no avanar do curso (ou talvez na seo de tutoriais), ns
aprenderemos a construir uma calculadora que nos apresentar como resultado o valor de converso entre
esses dados. Por enquanto, contentemo-nos com a calculadora do Windows que pode realizar esse tipo de
clculos.

Apostila de C++ Builder

Pagina -35-

Os tipos ponto flutuante


De um modo geral, podemos afirmar que os tipos ponto flutuante so representados pelos nmeros
fracionrios na base decimal. Ou seja, trata-se de nmeros, de regra, constitudos por um ponto fracionrio
que no pode ser substitudo por uma vrgula.
Um nmero de ponto flutuante pode apresentar-se na forma de notao cientfica. Por exemplo: 4.32 vezes
dez elevado a quarta. Neste caso, o vezes dez ( X 10) substitudo por e ou E. Logo o nmero
supramencionado ser representado por 4.32e4, que vale 43200.
OBS. Embora o C++Builder aceite a notao cientfica para inteiros, todos os valores que estiverem
situados aps um eventual ponto fracionrio, no resultado, sero desconsiderados.
Exemplos vlidos para ponto flutuante so:
-1.e4

12.345

.1

1.23e-2

1.23E+2

No podemos colocar vrgulas para representar pontos flutuantes: 12,345 // ilegal.


Os nmeros ponto flutuante se dividem basicamente nos tipos float e double. Posteriormente
entenderemos melhor a que se referem esses nomes.

Eis um cdigo para visualizarmos a matria tratada neste tpico. Para executar esse cdigo, precisaremos
de um Button e dois Label(s) no Form. De quebra, visualizaremos um problema de preciso com o tipo
float.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
float f = 3.65e-2;
double d = 3.65e-2;
Label1 -> Caption = f; // problemas de preciso com o tipo float
Label2 -> Caption = d;
}

O tipo caracter
O tipo caracter uma letra ou um smbolo colocado entre aspas simples. Embora sejam visualizados
como letras ou smbolos, importante ter em mente que, internamente, os computadores armazenam os
caracteres como um nmero inteiro entre 0 e 255. Por exemplo, a letra a associada ao nmero 97, b ao
98, c ao 99, d ao 100 e assim sucessivamente. Os valores numricos dos caracteres esto padronizados em
uma tabela chamada de American Standard Code for Information Interchange Table ou simplesmente
tabela ASCII. Ento conclumos que um char tanto pode ser interpretado como um nmero entre 0 e 255,
Apostila de C++ Builder

Pagina -36-

quanto pode ser interpretado como um elemento de um conjunto de caracteres da tabela ASCII. O tipo
char geralmente tem um byte, o que suficiente para conter os 256 valores mencionados.
Exemplos vlidos para caracteres so:
'a'

'A'

'z'

'5'

''

'%'

''

'*'

Seqncias de escape
Certos caracteres da tabela ASCII devem ser representados pela combinao especial de outros
caracteres. Essas combinaes, conhecidas como seqncia de escape, so representadas por uma barra
invertida ( \ ) e outro caracter. Esse grupo de dois caracteres interpretado como uma seqncia simples.
Por exemplo, ns j usamos em exemplo anterior, o '\n' e o '\t'. Essas combinaes so interpretadas como
nova linha (Enter) e Tab, respectivamente.
Abaixo, representaremos algumas seqncias de escape:

Controle/Caracter

Sequencia de escape

Valor ASCII

nulo (null)

\0

00

campainha (bell)

\a

07

retrocesso (backspace)

\b

08

tabulacao horizontal

\t

09

nova linha (new line)

\n

10

tabulacao vertical

\v

11

alimentacao de folha (form feed)

\f

12

retorno de carro (carriage return)

\r

13

aspas (")

\"

34

apostrofo (')

\'

39

interrogacao (?)

\?

63

barra invertida (\)

\\

92

bom notarmos que, embora alguns desses caracteres possam ser compilados sem a barra invertida ( \ )
em algumas aplicaes pelo C++Builder (", ?), noutras a barra poder fazer falta.

Apostila de C++ Builder

Pagina -37-

Coloque um Label no Form e no evento OnClick do Label digite:


void __fastcall TForm1::Label1Click(TObject *Sender)
{
/*Declara uma varivel int chamada StrInt e atribui a ela o valor que
ser digitado no InputBox pelo usurio*/
int StrInt = StrToInt /*converte AnsiString para int*/
(InputBox("Converte int para char","Digite um valor entre 0 e 255...",""));
Label1 -> Caption = char(StrInt)/*converte int(StrInt) para char*/;
}

Agora rode a aplicao e faa algumas experincias, dando um clique em Label para inserir valores entre
0 e 255 e visualizar a equivalncia de valores entre os nmeros e os elementos da tabela ASCII.

Modificadores de tipos
Podemos alterar o significado de um tipo bsico de dados, adaptando-o a uma necessidade especfica, por
meio de modificadores de tipos precedendo os tipos na declarao:
signed (com sinal);
unsigned (sem sinal);
long (mxima preciso);
short (menor preciso).

Tipo

bytes

possveis valores

char

-128 a 127

unsigned char

0 a 255

signed char

-128 a 127

int

-2147483648 a 2147483647

unsigned int

0 a 4294967295

signed int

-2147483648 a 2147483647

Apostila de C++ Builder

Pagina -38-

Tipo

bytes

possveis valores

short int

-32768 a 32767

unsigned short int

0 a 65535

signed short int

-32768 a 32767

long int

-2147483648 a 2147483647

signed long int

-2147483648 a 2147483647

unsigned long int

0 a 4294967295

float

-(3.4e38) a 3.4e38

double

1.7e308 a -(1.7e308)

long double

10

1.7e308 a -(1.7e308)

O exemplo a seguir usa um Edit, um Memo e um Button no Form. Quando o usurio d um clique no
boto, um loop comea a contar uma seqncia de valores numricos de caracteres para a varivel
unsigned char c e s a encerra quando contar o ltimo caracter, o de nmero 254. No corpo desse loop,
ns declaramos uma varivel do tipo char, que converter os valores numricos da varivel c para os
elementos correspondentes aos nmeros na tabela ASCII, atribuindo esses valores a ch. Feito isso os
valores obtidos sero imprimidos no Edit, exibindo as correspondncias encontradas. Concomitantemente,
quando o dedo do usurio deixa de fazer presso com o mouse sobre o boto, configurando o evento
OnMouseUp, o contedo do Edit (no caso os valores 0 a 254 da tabela ASCII e mais alguns caracteres
para facilitar a visualizao e a leitura) adicionado a Memo1.
void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
/* Declara e inicializa com 0 uma varivel do tipo unsigned char
dentro de um loop for; estabelece o limite de 254 para o loop;
determina o incremento da varivel. */
for(unsigned char c = 0; c < 255; c++)
{
/*Declara uma varivel que converter os
nmeros para o caracter da tabela ASCII*/
char ch = c;
/* Edit1 imprime os nmeros, os caracteres correspondentes da
tabela ASCII e mais alguns caracteres para facilitar a leitura*/
Edit1 -> Text = Edit1 -> Text + c + ' ' + '=' + ' ' + ch + ' ' + ' ';
}
}
//------------------------------------------------------------------

Apostila de C++ Builder

Pagina -39-

void __fastcall TForm1::BitBtn1MouseUp(TObject *Sender,


TMouseButton Button, TShiftState Shift, int X, int Y)
{
// Adiciona o contedo de Edit1 a Memo1
Memo1->Lines->Add(Edit1->Text);
}

O exemplo acima pode ser modificado para exibir somente alguns caracteres ASCII. Por exemplo, aps
rodar a aplicao, o programa apresentar para voc o nmero de cada caracter. Com base nestas
informaes, voc poder, facilmente, montar um programa que imprima somente as letras minsculas do
alfabeto etc.

Variveis
Podemos entender um microcomputador como um sistema de cinco unidades de funcionamento: unidade
de entrada (teclado, mouse, drive de CD-ROM, drive de disquetes etc), unidade de sada (impressora,
monitor etc), unidade de memria (memria RAM -escrita e leitura-, memria ROM - leitura), e as
unidades aritmtica e lgica que se encontram agrupadas na CPU (Unidade Central de Processamento, o
processador).
O chip responsvel pelo controle de todo o computador o processador. Outro circuito de extrema
importncia a memria RAM, que podemos imaginar como um grupo de clulas usadas para
armazenamento temporrio das instrues e dos dados que so acessados e processados pelo
microprocessador em altssima velocidade. Trata de uma memria voltil pois seus dados perdem-se no
momento em que so desligadas, o que no chega a ser um problema, visto que esses dados, de regra, aps
salvos, ficam guardados em algum disco de armazenamento permanente, como os discos rgidos ou os
disquetes, sendo copiados novamente para a memria na ocasio de seu processamento.
A memria RAM constituda por uma imensa seqncia de clulas de armazenamento (localizaes)
com o tamanho de oito bits (um byte) cada, o que permite que cada uma dessas localizaes possa assumir
um entre 256 valores diferentes. Ressalte-se, ainda, que cada clula possui um endereo nico e
inconfundvel, expresso por um valor numrico que define a exata localizao desse byte, bem como que,
apesar do limitado tamanho de cada clula, podemos acessar dois bytes consecutivos (word) ou quatro
bytes consecutivos (doubleword) simultaneamente com um nico endereamento.
Disso decorre que durante a execuo de um programa, as instrues e os dados processados ficam
armazenados na memria do computador. Cada informao representada por certo grupo de bytes (char
- 1 byte, float - 4 bytes, double - 8 bytes etc) e possui um local determinado na memria, um endereo que
pode ser expressado por um valor hexadecimal. No h necessidade de o programador conhecer o
endereo absoluto de cada dado, pois o compilador relaciona o nome de cada varivel com sua posio na
memria, cuidando dessa tarefa da melhor maneira possvel.
Para facilitar o entendimento, podemos imaginar a memria do computador como um enorme armrio de
gavetas. Cada gaveta (clula de armazenamento) numerada seqencialmente e possui o tamanho de 1
byte. Esse nmero seqencial o endereo da gaveta. Conforme o tipo de varivel declarada (char = 1

Apostila de C++ Builder

Pagina -40-

byte; int = 4 bytes; float = 4 bytes; etc), o compilador reservar uma ou mais gavetas seqencialmente
para armazenar o valor correspondente, pois cada tipo de dado possui um tamanho prprio.
Imagine um armrio imenso, com um milhes de gavetas iguais. Seria demasiadamente complicado
localizar determinado objeto numa dessas gavetas se no possussemos uma forma de diferenci-las entre
si. Ento, o nome da varivel funciona como uma inscrio que individualiza a gaveta (endereo na
memria).
Por exemplo, a declarao:
long double LgDbl;

informa ao compilador que ele dever reservar 10 bytes seqenciais (dez gavetas dispostas em seqncia)
para uma varivel do tipo long double cujo nome LgDbl. Observe que as "gavetas" esto reservadas,
porm nenhum "objeto" foi colocado nelas.

Um ponto bastante importante sobre o tamanho das variveis que seu tamanho pode variar de mquina
para mquina, ou sistema operacional para sistema operacional. O tipo int, por exemplo, ocupa 2 bytes no
sistema operacional MS-DOS e 4 bytes no Windows.
Com esses conceitos, j temos informaes suficientes para entender o que vem a ser uma varivel.
Podemos definir uma varivel como um local na memria do computador que a cada momento pode
possuir um valor diferente, porm do mesmo tipo de dados.
Por exemplo, a declarao:
char ch;

faz com que o compilador reserve espao suficiente para um caracter. J a declarao abaixo um pouco
mais completa, pois inicializa a varivel, colocando um caracter A no espao reservado:
char ch = 'A';

O conceito de variveis decorre justamente do fato de que podemos substituir o "contedo" dessas
"gavetas":
ch = 'b'; // ch agora possui outro valor

O exemplo a seguir usa um SpeedButton no Form. Declararemos uma varivel do tipo char num lugar
onde ela ser visvel tanto pelo evento OnMouseDown quanto pelo evento OnMouseUp de
SpeedButton1. Quando o boto do mouse for pressionado sobre o boto, o evento OnMouseDown ser
Apostila de C++ Builder

Pagina -41-

ativado para atribuir o caracter A varivel ch, exibindo esse valor no Caption de SpeedButton1. Quando
o boto do mouse for liberado, o evento OnMouseUp ser ativado para alterar o valor da varivel para b,
exibindo esse valor no Caption de SpeedButton1.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------// declara uma varivel char visvel pelos eventos de SpeedButton1
char ch;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
ch = 'A'; // atribui A para a varivel ch
SpeedButton1 -> Caption = ch;
}
//--------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1MouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
ch = 'b'; // atribui b para a varivel ch
SpeedButton1 -> Caption = ch;
}
//---------------------------------------------------------------------------

O C++Builder implementa a funo sizeof() que nos permite visualizar o tamanho, em bytes, de uma
varivel ou de um tipo de dados:

//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)


{
double Dbl;
Edit1 -> Text = AnsiString(sizeof(Dbl)) + " bytes"; // retorna pelo nome da varivel
/* retorna o valor pelo tipo de dados*/
Edit2 -> Text = AnsiString(sizeof(bool)) + " byte";
RichEdit1 -> Clear(); // apaga o contedo de RichEdit1
for (int linha = 0; linha <= 3; linha ++) // Em breve estudadremos o loop for

Apostila de C++ Builder

Pagina -42-

RichEdit1 -> Lines -> Insert(linha, "");


RichEdit1
RichEdit1
RichEdit1
RichEdit1

->
->
->
->

Lines->
Lines->
Lines->
Lines->

Strings[0]
Strings[1]
Strings[2]
Strings[3]

=
=
=
=

"Tamanho
"Tamanho
"Tamanho
"Tamanho

// prepara RichEdit1 para receber


// as quatro linhas de strings
de
de
de
de

char = " + String(sizeof(char));


int = " + String(sizeof(int));
String = " + String(sizeof(String));
AnsiString = " +
AnsiString(sizeof(AnsiString));

ShowMessage(sizeof(long double));
}
//---------------------------------------------------------------------------

Atribuio de valores a variveis


Conforme voc j deve ter percebido, para criarmos uma varivel, precisamos declarar o seu tipo (char,
int, float, ...), seguido pelo nome da varivel e por um smbolo de ponto e vrgula:
int i;

Com o operador de atribuio = atribumos valores s variveis:


i = 43;

Nada impede que, no momento da declarao, tambm inicializemos a varivel com algum valor:
int i = 43;

Podemos, inclusive, declarar mais de uma varivel na mesma instruo, bem como misturar declaraes
com inicializaes:

// declararamos 5 variveis das quais inicializamos duas (i3 e i4)


int i, i2, i3 = 10, i4 = 15, i5;

O nome de uma varivel deve ser sugestionvel, nos indicando o tipo de dados com o qual ela trabalhar.
Por exemplo, suponhamos um problema onde ser calculada a rea de um retngulo de 10 metros de
comprimento por 7 metros de largura. Poderamos definir as variveis assim:
int compr = 10;
int larg = 7;
int total = compr * larg; // atribui o resultado da multiplicao a total

Apostila de C++ Builder

Pagina -43-

Existem algumas regras que devem ser respeitadas: Os nomes das variveis s podem comear com letras
(a, A, b, B, c, C, d, D, e, E, f, ...) ou por caracter de sublinhar ( _ ); depois de comeado o nome,
podemos colocar letras, nmeros ou caracter de sublinhar no nome:
int i, i1, i_, _i, _2, i_2 ; // Ok. Todas as variveis possuem nomes aceitveis
float 7_i; // nome invlido, pois comea com nmero
char _AF$G; // nome invlido - caracter ilegal $

Coloque um boto BitBtn no Form sem alterar-lhe o tamanho. O exemplo exibir o valor rea do boto
que ser ampliada a cada clique do mouse. Eis o cdigo:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------int altr = 25, larg = 75; // declara e inicializa duas variveis globais
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
/* O cdigo deste bloco ser executado imediatamente
(e somente) quando o aplicativo for inicializado*/
int total = altr * larg; // declara e inicializa uma varivel local
/*Coloca no caption de BitBtn1 o ttulo rea =, mais o valor
da varivel total convertido em AnsiString*/
BitBtn1 -> Caption = "rea = " + AnsiString(total);
}
//--------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
altr = altr + 10; //incrementa a varivel altr com + 10, alterando-lhe o valor
larg = larg + 30; //incrementa a varivel larg com + 30, alterando-lhe o valor
BitBtn1 -> Height = altr; //atribui a BitBtn1 -> Height o novo valor de altr;
BitBtn1 -> Width = larg; //atribui a BitBtn1 -> Width o novo valor de larg;
//atualiza o Caption de BitBtn1
BitBtn1 -> Caption = "rea = " + AnsiString(altr * larg);
}
//---------------------------------------------------------------------------

Nota: No exemplo acima, essa no a melhor forma de se conseguir o resultado, pois o exemplo foi
apenas didtico para ilustrar a declarao, a inicializao e a substituio de valores em variveis. Como
exerccio, procure conseguir o mesmo resultado sem declarar nenhuma varivel, o que poupar memria
durante a execuo do programa. Voc j possui conhecimentos suficientes para tanto!

Apostila de C++ Builder

Pagina -44-

Variveis signed e unsigned

(com e sem sinal)


Quando tratamos dos modificadores de tipos, tivemos oportunidade de observar que em C++ os tipos char
e int possuem as variedades signed (com sinal) e unsigned (sem sinal). Tais modificadores permitem-nos
filtrar alguns valores que podero ser desnecessrios para determinados tipos de aplicao, como por
exemplo os nmeros negativos, ou os valores estendidos da tabela ASCII. Os tipos inteiros (int, short e
long) e os char, de regra, podem armazenar valores positivos ou negativos. Todavia se declarados com o
modificador de tipos unsigned, ficaro restritos a nmeros iguais ou maiores do que zero.
A tabela abaixo exibe os valores possveis para os tipos de dados, com ou sem os modificadores de tipo:

Tipo

bytes

possveis valores

char

-128 a 127

unsigned char

0 a 255

signed char

-128 a 127

int

-2147483648 a 2147483647

unsigned int

0 a 4294967295

signed int

-2147483648 a 2147483647

short int

-32768 a 32767

unsigned short int

0 a 65535

signed short int

-32768 a 32767

long int

-2147483648 a 2147483647

signed long int

-2147483648 a 2147483647

unsigned long int

0 a 4294967295

Observe que o tipo no tem o seu tamanho alterado (nmero de bytes) em virtude da presena dos
modificadores signed ou unsigned. O resultado direto desse fato que, para um mesmo tipo de dados, o
valor mximo que pode ser atribudo a um unsigned o dobro do maior valor positivo que pode ser
atribudo a um signed.

O programa abaixo mostra-nos alguns limites de valores:


Apostila de C++ Builder

Pagina -45-

void __fastcall TForm1::SpeedButton1Click(TObject *Sender)


{
for (char ch = -126; ch > -127; ch++) Memo1->Lines->Add(ch);
Memo1 -> Lines -> Add("");
for (signed char Sch = 1 ;Sch > 0; Sch++) Memo1->Lines->Add(Sch);
Memo1 -> Lines -> Add("");
for (unsigned char Uch = -1000; Uch > 0; Uch++) Memo1->Lines->Add(Uch);
Memo1 -> Lines -> Add("");
for (int i = 2147483600; i > 0; i++) Memo1->Lines->Add(i);
Memo1 -> Lines -> Add("");
for (unsigned int ui = 4294967200; ui > 0; ui++) Memo1->Lines->Add(ui);
Memo1 -> Lines -> Add("");
for (signed short int SSi = 32768; SSi < -32000; SSi++) Memo1->Lines->Add(SSi);
}

Excedendo o limite de uma varivel


Se tentarmos atribuir um valor fora da faixa que a varivel pode conter, ela continuar a partir do zero, se
for unsigned; porm, se for do tipo signed, continuar a armazenar dados a partir do menor valor
negativo.
O Exemplo abaixo leva um SpeedButton e um ComboBox no Form. Quando o usurio clicar o boto, o
programa mostrar o resultado de se tentar atribuir valores no contemplados pela varivel.
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ComboBox1 -> Text = "Excedendo limites de variveis ...";
}
//--------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
ComboBox1 -> Text = "Veja abaixo os novos valores ...";
int i = 2147483647;
ComboBox1 -> Items ->
ComboBox1 -> Items ->
ComboBox1 -> Items ->
ComboBox1 -> Items ->
unsigned int
ComboBox1 ->
ComboBox1 ->
ComboBox1 ->

Add("Limite para int = " + String(i));


Add("Limite + 1 = " + String(i + 1));
Add("Limite + 2 = " + String(i + 2));
Add("");

Ui = 4294967295;
Items -> Add("Limite para unsigned int = " + String(Ui));
Items -> Add("Limite + 1 = " + String(Ui + 1));
Items -> Add("Limite + 2 = " + String(Ui + 2));

Apostila de C++ Builder

Pagina -46-

ComboBox1 -> Items -> Add("");


signed int Si = 2147483647;
ComboBox1 -> Items -> Add("Limite para signed int = " + String(Si));
ComboBox1 -> Items -> Add("Limite + 1 = " + String(Si + 1));
ComboBox1 -> Items -> Add("Limite + 2 = " + String(Si + 2));
ComboBox1 -> Items -> Add("");
char ch =
ComboBox1
ComboBox1
ComboBox1
ComboBox1

127;
-> Items
-> Items
-> Items
-> Items

->
->
->
->

Add("Limite para char = " + String(int(char(ch))));


Add("Limite + 1 = " + String(int(char(ch + 1))));
Add("Limite + 2 = " + String(int(char(ch + 2))));
Add("");

signed char Sch = 127;


ComboBox1 -> Items -> Add("Limite para signed char = " + String (Sch));
ComboBox1 -> Items -> Add("Limite + 1 = " + String(int(char(Sch + 1))));
ComboBox1 -> Items -> Add("Limite + 2 = " + String(int(char(Sch + 2))));
ComboBox1 -> Items -> Add("");
unsigned char Uch = 255;
ComboBox1 -> Items -> Add("Limite para unsigned char = " + String (Uch));
ComboBox1 -> Items -> Add("Limite + 1 = " + String(int(char(Uch + 1))));
ComboBox1 -> Items -> Add("Limite + 2 = " + String(int(char(Uch + 2))));
ComboBox1 -> Items -> Add("");
}
//---------------------------------------------------------------------------

Operaes matemticas com unsigned


J sabemos que uma varivel unsigned no pode ser atribuda com valores negativos. Se, numa operao
matemtica, tivermos um resultado menor do que zero para uma varivel unsigned, no momento em que
o clculo atingir o primeiro valor negativo (-1) a operao remetida para o maior valor do tipo do dado,
de onde o programa dar continuidade aos clculos com os valores restantes.
O exemplo a seguir usa um Label e um Timer no Form. So declaradas duas variveis globais do tipo
unsigned int, sendo que uma funcionar como base do clculo da subtrao e a outra como valor a ser
subtrado. O Label ficar piscando no Form, ou melhor, o Timer far com que o Label fique visvel e
depois de alguns instantes invisvel, e depois visvel, e depois invisvel e assim sucessivamente.
Ajustamos o intervalo de tempo para 500, mas voc pode alterar o valor para mais ou menos, no Code
Editor ou no Object Inspector. Haver um decremento (diminuio do valor em razo de 1) do nmero
apresentado no Label, a cada piscada. Ou seja, o primeiro valor apresentado ser 10; o segundo, 9; o
terceiro, 7; e assim por diante. Observe bem o que acontecer depois que 0 (zero) for apresentado no
Label, onde, equivocadamente, poderamos estar esperando algum valor negativo:

Apostila de C++ Builder

Pagina -47-

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------unsigned int uiBase = 9; /* declara e inicializa a varivel base (observe que
poderia ser uma constante)*/
unsigned int uiAcresce = 1; /* declara e inicializa a varivel que ser
incrementada na subtrao */
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
if (Label1->Visible == true) // se label estiver visivel
{
Label1->Visible=false; // Label1 ficar invisvel
/* e altera-se o Caption de Label1, com o resultado da subtrao,
cada vez que ele ficar invisvel*/
Label1 -> Caption = uiBase - uiAcresce;
/* incrementa a varivel uiAcresce (ela vale 1,
depois 2, depois 3, 4, 5, etc)*/
uiAcresce = uiAcresce + 1;
}
else // ou ento ( se Label1 estiver invisvel)
Label1->Visible=true; // Label1 ficar visvel
}
//---------------------------------------------------------------------------

AnsiString
O C++Builder implementa o tipo AnsiString como uma classe. AnsiString projetado para funcionar
como o tipo long string Delphi. Adequadamente, AnsiString fornece as seguintes caractersticas de
tratamento de strings que so requeridas quando voc chama funes do tipo VCL que usam qualquer
tipo long string Delphi:

reference count
string length

Apostila de C++ Builder

Pagina -48-

data
null string terminator
Se voc no fornecer um valor inicial, as variveis AnsiString so iniciadas com instncia zero.
Podemos conceituar uma string como um caracter, ou uma seqncia de caracteres colocados entre aspas
duplas:
"Al, Thrbio!"
"Guarulhos a terra das Pizzarias..."
"Oba!"
""

A classe AnsiString possui um bom nvel de independncia e flexibilidade nos controles onde usada,
uma vez que no descendente de Tobject, permitindo-nos realizar diversas operaes teis com strings.
A implementao desse arquivo pode ser visualizada no diretrio include/vcl/dstring.h da pasta de
instalao de seu compilador:
#ifndef DSTRING_H
#define DSTRING_H
#pragma delphiheader begin
#include <sysmac.h>
namespace System
{
class
TVarRec;
class RTL_DELPHIRETURN Currency;
class RTL_DELPHIRETURN WideString;
/////////////////////////////////////////////////////////////////////////////
// AnsiString: String class compatible with Delphi's Native 'string' type
/////////////////////////////////////////////////////////////////////////////
class RTL_DELPHIRETURN AnsiString
{
friend AnsiString __fastcall operator +(const char*, const AnsiString& rhs);
public:
// the TStringFloatFormat enum is used by FloatToStrF
enum TStringFloatFormat
{sffGeneral, sffExponent, sffFixed, sffNumber, sffCurrency};
static AnsiString __fastcall StringOfChar(char ch, int count);
static AnsiString __fastcall LoadStr(int ident);
static AnsiString __fastcall LoadStr(HINSTANCE hInstance, int ident);
static AnsiString __fastcall FmtLoadStr(int ident, const TVarRec *args,
int size);
AnsiString& __fastcall
LoadString(HINSTANCE hInstance, int ident);
// Delphi style 'Format'
//
static AnsiString __fastcall Format(const AnsiString& format,
const TVarRec *args, int size);

Apostila de C++ Builder

Pagina -49-

// C++ style 'sprintf' (NOTE: Target buffer is the string)


//
AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this
int __cdecl printf(const char* format, ...); // Returns formatted length

//

static AnsiString __fastcall FormatFloat(const AnsiString& format,


const long double& value);
static AnsiString __fastcall FloatToStrF(long double value,
TStringFloatFormat format, int precision, int digits);
static AnsiString __fastcall IntToHex(int value, int digits);
static AnsiString __fastcall CurrToStr(Currency value);
static AnsiString __fastcall CurrToStrF(Currency value,
TStringFloatFormat format, int digits);
// Constructors
__fastcall AnsiString(): Data(0) {}
__fastcall AnsiString(const char* src);
__fastcall AnsiString(const AnsiString& src);
__fastcall AnsiString(const char* src, unsigned char len);
__fastcall AnsiString(const char* src, unsigned int len);
__fastcall AnsiString(const wchar_t* src);
__fastcall AnsiString(char src);
__fastcall AnsiString(short);
__fastcall AnsiString(unsigned short);
__fastcall AnsiString(int src);
__fastcall AnsiString(unsigned int);
__fastcall AnsiString(long);
__fastcall AnsiString(unsigned long);
__fastcall AnsiString(__int64);
__fastcall AnsiString(unsigned __int64);
__fastcall AnsiString(double src);
__fastcall AnsiString(const WideString &src);
// Destructor
__fastcall ~AnsiString();
// Assignments
AnsiString& __fastcall operator =(const AnsiString& rhs);
AnsiString& __fastcall operator +=(const AnsiString& rhs);
// Comparisons
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
int __fastcall
int __fastcall

operator ==(const AnsiString& rhs) const;


operator !=(const AnsiString& rhs) const;
operator <(const AnsiString& rhs) const;
operator >(const AnsiString& rhs) const;
operator <=(const AnsiString& rhs) const;
operator >=(const AnsiString& rhs) const;
AnsiCompare(const AnsiString& rhs) const;
AnsiCompareIC(const AnsiString& rhs) const; //ignorecase

// Accessing character at specified index


char __fastcall operator [](const int idx) const
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
return Data[idx-1];
}

Apostila de C++ Builder

Pagina -50-

#if defined(ANSISTRING_USE_PROXY_FOR_SUBSCRIPT)
// The use of a proxy class optimizes the case where Unique() must be called
// when accessing the string via the subscript operator. However, the use of
// of the proxy class has some drawbacks. First, it breaks code that apply
// operators to the return value. For example, &MyString[i]. Second, it
// fails in cases where a implicit conversion was relied upon. For example,
//
callFuncThatTakesAnObjectWithACharCtr(MyString[i]);
// In that case, two implicit conversions would be required...
// The first issue can be remedied by enhancing the proxy class to support
// all valid operators. The second issue can be lessened but not completely
// eliminated. Hence, the use of the PROXY class is not the default!
//
private:
class TCharProxy;
friend TCharProxy;
class TCharProxy
{
public:
TCharProxy(AnsiString& strRef, int index) : m_Ref(strRef), m_Index(index) {}
TCharProxy& operator=(char c)
{ m_Ref.Unique(); m_Ref.Data[m_Index-1] = c; return *this; }
operator char() const
{ return m_Ref.Data[m_Index-1]; }
protected:
AnsiString&
int
};

m_Ref;
m_Index;

public:
TCharProxy __fastcall operator [](const int idx)
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
return TCharProxy(*this, idx);
}
#else
char& __fastcall operator [](const int idx)
{
ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
Unique();
// Ensure we're not ref-counted
return Data[idx-1];
}
#endif
// Concatenation
AnsiString __fastcall operator +(const AnsiString& rhs) const;
// C string operator
char* __fastcall c_str() const { return (Data)? Data: "";}
// Query attributes of string
int __fastcall Length() const;
bool __fastcall IsEmpty() const;
// Make string unique (refcnt == 1)

Apostila de C++ Builder

Pagina -51-

AnsiString&

__fastcall Unique();

// Modify string
AnsiString& __fastcall Insert(const AnsiString& str, int index);
AnsiString& __fastcall Delete(int index, int count);
AnsiString& __fastcall SetLength(int newLength);
int __fastcall Pos(const AnsiString& subStr) const;
AnsiString
__fastcall LowerCase() const;
AnsiString
__fastcall UpperCase() const;
AnsiString
__fastcall Trim() const;
AnsiString
__fastcall TrimLeft() const;
AnsiString
__fastcall TrimRight() const;
AnsiString
__fastcall SubString(int index, int count) const;
int
int
double

__fastcall ToInt() const;


__fastcall ToIntDef(int defaultValue) const;
__fastcall ToDouble() const;

// Convert to Unicode
int
__fastcall WideCharBufSize() const;
wchar_t*
__fastcall WideChar(wchar_t* dest, int destSize) const;
// MBCS support
enum TStringMbcsByteType
{mbSingleByte, mbLeadByte, mbTrailByte};
TStringMbcsByteType __fastcall ByteType(int index) const;
bool __fastcall IsLeadByte(int index) const;
bool __fastcall IsTrailByte(int index) const;
bool __fastcall IsDelimiter(const AnsiString& delimiters, int index) const;
bool __fastcall IsPathDelimiter(int index) const;
int
__fastcall LastDelimiter(const AnsiString& delimiters) const;
int
__fastcall AnsiPos(const AnsiString& subStr) const;
char* __fastcall AnsiLastChar() const;
protected:
void ThrowIfOutOfRange(int idx) const;
private:
char *Data;
};
extern AnsiString __fastcall operator +(const char*, const AnsiString& rhs);
#if defined(VCL_IOSTREAM)
ostream& operator << (ostream& os, const AnsiString& arg);
istream& operator >> (istream& is, AnsiString& arg);
#endif
/////////////////////////////////////////////////////////////////////////////
// SmallStringBase
/////////////////////////////////////////////////////////////////////////////
template <unsigned char sz> class SmallStringBase
{
protected:

Apostila de C++ Builder

Pagina -52-

unsigned char Len;


char Data[sz];
};
/////////////////////////////////////////////////////////////////////////////
// SmallString
/////////////////////////////////////////////////////////////////////////////
template <unsigned char sz> class SmallString : SmallStringBase<sz>
{
#if defined(VCL_IOSTREAM)
friend ostream& operator <<(ostream& os, const SmallString& arg)
{
os << AnsiString(arg);
return os;
}
friend istream& operator >>(istream& is, SmallString& arg)
{
AnsiString s;
is >> s;
arg = s;
return is;
}
#endif
public:
__fastcall SmallString() { Len = 0; }
__fastcall SmallString(const SmallString& src);
__fastcall SmallString(const char* src);
__fastcall SmallString(const AnsiString& src)
{
long len = src.Length();
Len = (unsigned char)((len > sz)? sz: len);
strncpy(Data, src.c_str(), Len);
}
char& __fastcall operator [](const unsigned char idx)
{return Data[idx-1];}
SmallString& __fastcall operator =(const SmallString& rhs);
__fastcall operator AnsiString() const;
};
// used when SmallStrings are in unions (can't have a ctor)
// must cast DummySmallString to SmallString to do anything useful
template<unsigned char sz> __fastcall
SmallString<sz>::SmallString(const char* src)
{
long len = strlen(src);
Len = (unsigned char)((len > sz)? sz: len);
strncpy(Data, src, Len);
}

Apostila de C++ Builder

Pagina -53-

template<unsigned char sz> __fastcall


SmallString<sz>::SmallString(const SmallString& src)
{
Len = src.Len;
for (int i = 0; i < Len; i++)
Data[i] = src.Data[i];
}
template<unsigned char sz> SmallString<sz>& __fastcall
SmallString<sz>::operator =(const SmallString& rhs)
{
if (this != &rhs)
{
Len = rhs.Len;
for (int i = 0; i < Len; i++)
Data[i] = rhs.Data[i];
}
return *this;
}
template<unsigned char sz>
inline __fastcall SmallString<sz>::operator AnsiString() const
{
return AnsiString(Data, Len);
}
}
using namespace System;
// The following is provided for backward compatibility.
// Otherwise, the new IntToStr(__int64) causes ambiguity for old code
// that used 'bool', uint and DWORD.
//
namespace Sysutils
{
extern PACKAGE AnsiString __fastcall IntToStr(int Value)/* overload */;
extern PACKAGE AnsiString __fastcall IntToStr(__int64 Value)/* overload */;
}
#pragma option push -w-inl
inline AnsiString __fastcall IntToStr(bool value)
{
return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned int value)
{
return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned long value)
{
return Sysutils::IntToStr(int(value));
}
#pragma option pop
#pragma delphiheader end.

#endif // DSTRING_H
Apostila de C++ Builder

Pagina -54-

Por enquanto no tente entender os fundamentos deste arquivo, pois nele aparecem muitos termos que nos
so novidades ainda. No avanar do curso, muitos desses fundamentos sero abordados, tornando a
compreenso de partes do arquivo mais ou menos intuitiva.
Todavia, vamos verificar alguns tpicos, por dois motivos:
1 - importante que tenhamos conhecimento de determinadas facilidades que AnsiString nos
proporciona;
2 - aprendermos a operar determinadas funes da classe, por intuio.

Nota: Caption o rtulo que pode ser estampado no componente, suportando mudanas em
tempo de execuo. Controles que exibem textos, fazem-no atravs da propriedade Caption
ou da propriedade Text. A propriedade a ser usada depender do tipo do controle. De um
modo geral, Caption usado por textos que aparecem como ttulos de uma janela ou um
rtulo (estampa), enquanto Text usado por textos que aparecem como contedo de um
controle. Via de regra, Text podem ser editados pelo usurio, enquanto Caption uma
propriedade que no recebe o foco da aplicao, tendo como caracterstica a finalidade bsica
de enviar uma informao ao usurio.
Muitos controles usam propriedades da classe AnsiString. Por exemplo, todos os controles que possuem
rtulo (forms, edits, panels, labels) usam AnsiString atravs da propriedade Caption. Outros controles
como o EditBox usam a classe AnsiString como base de seus textos (propriedade Text). Se repararmos
bem, notaremos que ns j temos usado e implementado objetos AnsiString sem qualquer espcie de
declarao. Em outra situao qualquer, a declarao e inicializao de uma string sempre ser necessria
antes do uso respectivo.
A declarao de uma String anloga declarao de um tipo bsico, porm usando a palavra
AnsiString seguida de um nome vlido C++. Eis um exemplo:
AnsiString Pais;

Em dstring.h podemos observar que AnsiString uma classe com seu prprio construtor e destruidor:

//

// Constructors
__fastcall AnsiString(): Data(0) {}
__fastcall AnsiString(const char* src);
__fastcall AnsiString(const AnsiString& src);
__fastcall AnsiString(const char* src, unsigned char len);
__fastcall AnsiString(const char* src, unsigned int len);
__fastcall AnsiString(const wchar_t* src);
__fastcall AnsiString(char src);
__fastcall AnsiString(short);
__fastcall AnsiString(unsigned short);
__fastcall AnsiString(int src);

Apostila de C++ Builder

Pagina -55-

__fastcall
__fastcall
__fastcall
__fastcall
__fastcall
__fastcall
__fastcall

AnsiString(unsigned int);
AnsiString(long);
AnsiString(unsigned long);
AnsiString(__int64);
AnsiString(unsigned __int64);
AnsiString(double src);
AnsiString(const WideString &src);

// Destructor
__fastcall ~AnsiString();

Logo voc tambm pode declarar uma varivel dela com parnteses vazios, determinando a chamada do
construtor da classe. Eis um exemplo:
AnsiString Animal();

H dois modos principais para voc iniciar uma varivel AnsiString. Depois de declar-la, pode-se
determinar o valor desejado para a varivel usando o nome escolhido. Eis um exemplo:
AnsiString Especie;
Especie = "Cachorro";

tambm podemos, tal qual nos tipos bsicos, inicializar a varivel String na sua declarao, fornecendo o
valor desejado para o nome escolhido. Eis um exemplo:
AnsiString Raca("Pastor Alemo");

Uma vez definida, a String poder ser usada, por exemplo, para alterar o Caption de controles:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Meu_Cao;
Meu_Cao = " O Tobby um vira-lata, que s sabe latir, latir e latir...";
Label1->Caption = Meu_Cao;
}
//---------------------------------------------------------------------------

Tambm poder ser usada para preencher um controle Edit:


//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Pre_Hist = "Tiranossauro ou 286???";
Edit1->Text = Pre_Hist;
}
//---------------------------------------------------------------------------

Um texto introduzido num Edit box, por exemplo, , por padro, considerado uma String, visto que o
compilador no pode deduzir que espcie de dado ou valor o usurio deseja manipular. Por essa razo,

Apostila de C++ Builder

Pagina -56-

depois que um valor foi fornecido para um controle que fundamenta-se na classe AnsiString como base
de seu contedo, para executar qualquer operao matemtica com tal String, devemos convert-la para o
tipo de dado desejado. Para essa finalidade podemos, por exemplo, usar a funo StrToInt():
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = "111";
int i = StrToInt(Label1->Caption) - 11;
Edit1->Text = i;
}

Conforme apresentado, a classe AnsiString prov um grande nmero de construtores que nos permitem a
criao de strings de qualquer espcie:
Por exemplo, podemos usar:
um caracter:
AnsiString Simbolo = 'T';

um inteiro
AnsiString Int = 120;

um long int
AnsiString LongoInt = -73495745;

um valor ponto flutuante:


AnsiString PtoFlut = 675.15;

Um double:
AnsiString DplPrec = 2.15e28;

um string
AnsiString AloTher = "Al, Thrbio";

Qualquer dessas variveis pode ser declarada usando os construtores equivalentes:


//--------------------------------------------------------------------------AnsiString Simbolo('T');
AnsiString Int(120);
AnsiString AloTher("Al, Thrbio");
AnsiString PtoFlut(675.15);
AnsiString LongoInt(-73495745);
AnsiString DplPrec(2.15e28);
//---------------------------------------------------------------------------

Baseado na configurao dos construtores AnsiString, podemos converter qualquer valor e torn-lo
disponvel para um controle que use as propriedades AnsiString. Por exemplo, podemos converter e
exibir:

Apostila de C++ Builder

Pagina -57-

um caracter:
char Letra = 't';
Edit1 -> Text = AnsiString(Letra);

um inteiro:
Integer Numero = 256;
Edit1->Text = AnsiString(Numero);

um long integer:
long Valor = 4949431;
Panel1->Caption = AnsiString(Valor);

um valor ponto flutuante:


Single Distancia = 5698.03;
Label1->Caption = AnsiString(Distancia);

um double:
Double Tamanho = 24588;
Edit1->Text = AnsiString(Tamanho);

uma string
AnsiString Servico = "Limpador de Foges";
Button2->Caption = AnsiString(Servico);

Nota: Voc deve ter notado o uso de nomes de tipos diferentes dos apresentados anteriormente.
Por exemplo:
chamamos o tipo int de Integer, o tipo float de Single; o tipo double de Double ...
Por que ser?
No incio do arquivo dstring.h vemos a incluso do arquivo de cabealho sysmac.h:
#include <sysmac.h>

NOTA: Logo abordaremos o uso da palavra typedef para criar outro nome para um tipo de
dados:
Vejamos um trecho do arquivo sysmac.h:
class PACKAGE TVarArray;

Apostila de C++ Builder

Pagina -58-

typedef TVarArray *PVarArray;

typedef bool

Boolean;

//

typedef int

Integer;

// -2147483648..2147484647

typedef char

Char;

// 0..255

typedef wchar_t

WideChar;

// Unicode character

typedef signed char

Shortint;

// -128..127

typedef short

Smallint;

// -32768..32767

typedef unsigned char

Byte;

// 0..255

typedef unsigned short

Word;

// 0..65535

typedef unsigned long

DWord;

// 0..4294967295

typedef void*

Pointer;

//

typedef char

AnsiChar;

//

typedef signed long

Longint;

// -2147483648..2147484647

typedef unsigned int

Cardinal;

// 0..2147484647

typedef long double

Extended;

// 10 byte real

typedef float

Single;

// 4 byte real

typedef double

Double;

// 8 byte real

typedef char* const

Openstring;

typedef void*

file;

//

typedef void*

Text;

//

typedef Text

TextFile;

//

typedef char*

PChar;

//

typedef char*

PAnsiChar;

//

typedef wchar_t*

PWideChar;

//

typedef unsigned char

ByteBool;

//

Apostila de C++ Builder

Pagina -59-

// D16 string/D32 shortstring formalparm

typedef unsigned short

WordBool;

//

typedef Cardinal

LongBool;

//

typedef AnsiString

String;

//

typedef SmallStringBase<255> ShortStringBase;

//

typedef SmallString<255>

ShortString;

//

typedef ShortString*

PShortString;

//

typedef AnsiString*

PAnsiString;

//

typedef PAnsiString

PString;

//

typedef WideString*

PWideString;

//

typedef Extended*

PExtended;

//

typedef Currency*

PCurrency;

//

typedef Variant*

PVariant;

//

typedef __int64

LONG64;

// !! obsolete

typedef GUID

TGUID;

//

typedef TGUID*

PGUID;

//

typedef HRESULT

HResult;

//

typedef Integer __fastcall (*TThreadFunc)(Pointer Parameter);


typedef void (*TModuleUnloadProc)(HINSTANCE hinstance);
typedef bool (*TEnumModuleFunc)(HINSTANCE hinstance, void *data);
typedef struct TVarData *PVarData;

Os nomes direita representam os sinnimos que podem ser usados em substituio aos tipos bsicos. Por
exemplo, Boolean pode ser usado em substituio ao tipo bool.
Nas prximas lies abordaremos vrias implementaes de AnsiString.

Apostila de C++ Builder

Pagina -60-

Nota: voltamos a insistir para que voc no se preocupe quando se deparar com nomes de tipos de dados ainda no estudados
(como classe, por exemplo) visto que no momento apropriado do curso abordaremos tais tpicos com a profundidade
necessria.

Funes que modificam strings


Agora conheceremos algumas implementaes do tipo AnsiString. Embora tenhamos, para facilidade de
compreenso, nos referido s instncias de classes como variveis, tecnicamente isso est incorreto. Na
verdade, a instncia de uma classe (AnsiString, por exemplo) denominada objeto. E os objetos possuem
funes-membro que facilitam sua manipulao. Essas funes-membro podem ser acessadas atravs do
operador ponto ..
Vejamos alguma funes-membro utilizadas para modificar strings.
// Modify string
AnsiString& __fastcall Insert(const AnsiString& str, int index);
AnsiString& __fastcall Delete(int index, int count);
AnsiString& __fastcall SetLength(int newLength);
int __fastcall Pos(const AnsiString& subStr) const;
AnsiString
__fastcall LowerCase() const;
AnsiString
__fastcall UpperCase() const;
AnsiString
__fastcall Trim() const;
AnsiString
__fastcall TrimLeft() const;
AnsiString
__fastcall TrimRight() const;
AnsiString
__fastcall SubString(int index, int count) const;

Insert()
AnsiString& __fastcall Insert(const AnsiString& str, int index);

insere uma string especificada dentro de AnsiString, iniciando a insero na posio determinada pela
varivel index.
O exemplo abaixo leva um Label no Form. Quando o usurio d um clique no Label, o programa
providencia a insero de uma string dentro de outra.
void __fastcall TForm1::Label1Click(TObject *Sender)
{
AnsiString test = "O_ _est_feito";
Label1->Caption = test.Insert("grande_teste", 3);
}

Delete()
AnsiString&

__fastcall Delete(int index, int count);

Apostila de C++ Builder

Pagina -61-

Remove um nmero especificado de caracteres de uma string. Inicia a contagem para a remoo na
varivel especificada por index, encerrando a excluso com a remoo do ltimo caracter contado para
completar count:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
AnsiString test = "O_grande_teste_est_feito";
Label1->Caption = test.Delete(3, 12);
Label1->Caption = test.Insert(" ", 3);
}

SetLength()
AnsiString&

__fastcall SetLength(int newLength);

Determina um novo tamanho para a string, especificado por newLength, desde que esse novo
comprimento seja menor do que o tamanho inicial. SetLength no pode aumentar o tamanho da string:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
AnsiString test = "O_grande_teste_est_feito";
Label1->Caption = test.SetLength(14);
}

Pos()
int __fastcall Pos(const AnsiString& subStr) const;

a posio do primeiro caracter de uma substring especificada na string. Se a substring no for


encontrada na string, Pos() retorna zero.

void __fastcall TForm1::Label1Click(TObject *Sender)


{
AnsiString test = "O_grande_teste_est_feito";

Apostila de C++ Builder

Pagina -62-

Label1->Caption = test.Pos("est");
}

LowerCase() e UpperCase()
AnsiString
AnsiString

__fastcall LowerCase() const;


__fastcall UpperCase() const;

LowerCase() transforma todas as letras da string para letras minsculas e UpperCase() transforma
todas para maisculas:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
AnsiString test = "O_grande_TESTE_est_FEITO";
Label1->Caption = test;
Label2->Caption = test.LowerCase();
Label3->Caption = test.UpperCase();
}

Funes que modificam strings

AnsiString ... continuao


AnsiString
AnsiString
AnsiString
AnsiString

__fastcall
__fastcall
__fastcall
__fastcall

Trim() const;
TrimLeft() const;
TrimRight() const;
SubString(int index, int count) const;

Trim(), TrimLeft()e TrimRight()


AnsiString
AnsiString
AnsiString

__fastcall Trim() const;


__fastcall TrimLeft() const;
__fastcall TrimRight() const;

Podemos usar essas funes-membro para eliminar caracteres em branco no incio (TrimLeft()), no
final (TrimRight()) e no incio e no final da string (Trim()):

Apostila de C++ Builder

Pagina -63-

void __fastcall
{
Label1->Color =
Label2->Color =
Label3->Color =
Label4->Color =
AnsiString test
Label1->Caption
Label2->Caption
Label3->Caption
Label4->Caption

TForm1::Label1Click(TObject *Sender)
clYellow;
clYellow;
clYellow;
clYellow;
= "
= test;
= test.Trim();
= test.TrimLeft();
= test.TrimRight();

O grande teste est feito

";

SubString()
AnsiString

__fastcall SubString(int index, int count) const;

Retorna uma substring especificada de uma string. A substring inicia a contagem dos caracteres em
index e termina de cont-los em count.
O exemplo abaixo possui um Button, um Edit e um Label no Form. Quando o usurio der um clique no
boto, a funo membro SubString() da classe AnsiString ser chamada para acessar uma substring
(parte da frase) contida na varivel Frase:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
// Coloca uma string em Edit1
Edit1 -> Text = "Meu pai se chama Julio Alves";
// Declara e inicializa a varivel Frase com a string contida no texto de em Edit1
AnsiString Frase = Edit1 ->Text;
/* Declara e inicializa a varivel MeuPai com a string que comea no caracter 18
e termina no 28 de Frase*/
AnsiString MeuPai = Frase.SubString(18, 28);
// Concatena string com MeuPai, imprimindo no Label1
Label1 -> Caption = "Papai se chama " + MeuPai;
}
//---------------------------------------------------------------------------

Nota: Como voc deve ter observado, j temos utilizado AnsiString em diversas oportunidades. Tambm
j utilizamos a denominao String que anloga ao uso de AnsiString (Lembre-se da palavra-chave
typedef).
Como sabemos, o C++Builder possui vrias funes para manipulao de strings. Veja abaixo um
exemplo com AnsiPos(), uma funo que retorna a posio de um caracter dentro de uma String:

Apostila de C++ Builder

Pagina -64-

void __fastcall TForm1::Button1Click(TObject *Sender)


{
AnsiString Teste = "abcdefghijlmnopqrstuvxz";
ShowMessage((String)"A posio de 'q' : " + AnsiPos('q', Teste));
}

AnsiString continuao...

(dstring.h)

Agora j conheceremos diversas funes-membro de AnsiString. Como exerccio tente entender a lgica
de alguma funes localizadas no arquivo dstring.h. Evidentemente voc dever consultar o HELP do
C++Builder. Para tanto, voc pode proceder da seguinte maneira. Escolha uma funo-membro. Por
exemplo:
static AnsiString __fastcall IntToHex(int value, int digits);

Copie o nome da funo para o Editor de Cdigos do C++Builder:

IntToHex
D um clique para que o cursor fique situado sobre o nome da funo e tecle F1.
O HELP do BCB dever abrir-se automaticamente mostrando as eventuais opes para essa funo. Eis
uma delas:
AnsiString::IntToHex
AnsiString
Description
Converts a number into a string containing the number's hexadecimal (base 16) representation.
static AnsiString __fastcall IntToHex(int value, int digits);
Value is the number to convert. Digits indicates the minimum number of hexadecimal digits.

Percebemos que a funo em questo trata da converso de valores inteiros para hexadecimais,
devolvendo AnsiString, onde int value o valor a ser convertido e int digits o nmero de
dgitos devolvido pela funo na converso:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
Label1->Caption = IntToHex(100000, 10);
}

Apostila de C++ Builder

Pagina -65-

Percebeu como fcil?!? Sem dvida alguma, a melhor fonte de pesquisas para compreendermos o
funcionamento do C++Builder o seu prprio HELP. Se voc realmente ambiciona aprender programar
C++ usando esse excelente compilador, entendemos que no existe melhor fonte de pesquisas. Grande
problema que parte dos programadores iniciantes encontram diz respeito ao idioma. Nem todos tem
facilidades com ingls. Confesso que eu tambm no possuo grande facilidade. Procuro supri-la com
programas que podem ser baixados na prpria NET. Particularmente, eu prefiro o Babylon (considero as
verses antigas melhores. Alis, tenho o timo hbito de no atualizar aplicativos com os quais eu me
identifico. Vrias vezes me arrependi de atualiz-los, em face de pequenas armadilhas embutidas nas
novas verses do tipo: deixar de ser freeware. Nesses casos, se voc no tomou o cuidado de fazer um
backup do programa de instalao antigo, a dor de cabeas e o arrependimento poder ser considervel).
Um dos trabalhos que estaremos disponibilizando, sempre que possvel, neste site a traduo de partes
que consideramos fundamentais no HELP do BCB.

AnsiString continuao...

(operadores relacionais)
Embora ainda no tenhamos abordado o tema (fato reservado para lies futuras), j tivemos oportunidade
de apreciar exemplos com os comandos if e else. Por enquanto tenhamos em mente que esses comandos
so usados basicamente para efetuar comparaes do tipo:
Se A maior do que B, faa isso;
Seno, faa aquilo.
No caso acima, o termo maior est representando o operador relacional >. Para mais detalhes, d uma
olhadinha no tpico que trata tal assunto.
Ansistring implementa mtodos para tratamento de operadores relacionais:
// Comparisons
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
bool __fastcall
int __fastcall
int __fastcall

operator ==(const AnsiString& rhs) const;


operator !=(const AnsiString& rhs) const;
operator <(const AnsiString& rhs) const;
operator >(const AnsiString& rhs) const;
operator <=(const AnsiString& rhs) const;
operator >=(const AnsiString& rhs) const;
AnsiCompare(const AnsiString& rhs) const;
AnsiCompareIC(const AnsiString& rhs) const; //ignorecase

Vejamos outra implementao de AnsiString:


// Query attributes of string
int __fastcall Length() const;

Apostila de C++ Builder

Pagina -66-

Length() retorna o nmero de caracteres de um AnsiString. Logo podemos escrever um cdigo


mesclando operadores relacionais com essa funo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Str = "Esta a primeira string";
AnsiString Str2 = "Esta a segunda string";
if(Str.Length() > Str2.Length())
ShowMessage((String)"A primeira string maior. Ela possui " +
Str.Length() + " caracteres");
else
ShowMessage((String)"A segunda string maior. Ela possui " +
Str2.Length() + " caracteres");
}

Depois que voc estudar os comandos if e else, e os operadores relacionais, procure fazer alguns
exerccios implementando outros tipos de comparaes suportadas por AnsiString , com outros
operadores relacionais.

AnsiString continuao...

(concatenation)
// Concatenation
AnsiString __fastcall operator +(const AnsiString& rhs) const;

Podemos usar o operador + para concatenar strings (colocar uma aps a outra):
void __fastcall TForm1::Label1Click(TObject *Sender)
{
AnsiString AS1 ("\tTestando");
AnsiString AS2 ("\n\tAnsiString");
String S1 ("\n\nTestando");
String S2 ("\nString");
Label1 -> Caption = AS1 + AS2 + "\n\t\t\tOutro teste" + S1 + S2 + " !!!!";
}

A partir de agora assumimos que voc j conhece razoavelmente a classe AnsiString. Porm ainda h
muito mais a conhecer sobre strings. Dedique algumas horas ao estudo, sempre procurando documentar
os estudos.

A palavra-chave

typedef

Podemos usar a palavra-chave typedef para criar um sinnimo para um tipo de dados existente qualquer.
Isso poder nos auxiliar quando estivermos lidando com nomes de tipos muito longos e, portanto, sujeito a
erros de digitao. Por exemplo, na rea dos cabealhos, digitamos:

Apostila de C++ Builder

Pagina -67-

typedef signed short int ssint;

e, a partir da, todas as vezes que quisermos declarar uma varivel signed short int poderemos faz-lo
atravs da declarao: ssint:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// cria um sinnimo (ssint) para signed short int
typedef signed short int ssint;
// declara e inicializa variveis ssint
ssint Altura = 15, Largura = 20, Comprimento = 26;
ssint Volume;
Volume = Altura * Largura * Comprimento;
// centraliza o caption de Label1
Label1 -> Alignment = taCenter;
// altera o estilo da font de Label1 para negrito, itlico e sublinhado
Label1->Font->Style = Label1->Font->Style<<fsBold<<fsItalic<<fsUnderline;
Label1 -> Caption = "******Clculo do volume de um cubo******\n"
"Altura = " + String(Altura) + "\n"
"Largura = " + String(Largura) + "\n"
"Comprimento = " + String(Comprimento) + "\n"
"Volume = " + String(Volume);
}

A diretiva

#define

Podemos criar um nome para definir valores constantes atravs da diretiva de preprocessador #define.
Esse nome conhecido por constante simblica.

#define Kelvin -273


Embora Kelvin no tenha sido declarado como nenhum tipo em particular (char, float, AnsiString etc), o
compilador saber lidar com os dados da melhor forma possvel em virtude do estilo da declarao. Por
exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
#define Kelvin -273
#define Frase "Ibirarema uma pequena cidade do Estado de So Paulo!"
#define pi 3.141592653589
#define letra 'A'
/* Essas constantes no so to constantes afinal.

Apostila de C++ Builder

Pagina -68-

Se, mantendo a declarao anterior, fizssemos uma


nova declarao para pi:
#define pi 10
o compilador aceitaria esse novo valor desconsiderando o anterior!!!!!*/
Label1 -> Caption = Frase "\n" + AnsiString(Kelvin * pi) + "\n" + letra;
}

Alm da habilidade de definir constantes simblicas, a diretiva #define pode ser usada para definir
macros, desde que se lhe fornea algum argumento:
#define SOMA(X, Y) (X + Y)

Em captulos posteriores, estudaremos essa diretiva com detalhes.

A palavra-chave

const

Outra forma (melhor) que a linguagem C++ nos oferece para definir constantes atravs da palavra-chave
const.
A diferena bsica entre os dois tipos de declarao o fato de que naquela (#define), o tipo de
declarao quem informa ao compilador qual ser o provvel tipo, enquanto nesta (const), o tipo (char,
int etc) declarado:
const int Kelvin = -273;
const double pi = 3.141592653589;
Este mtodo o mais recomendado na maioria dos casos, pois alm de tornar o cdigo mais fcil de ler e
manter, dificulta a introduo de bugs, posto que o compilador pode checar se a constante est sendo
usada de acordo com seu tipo.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
const int km = 170;
const AnsiString Itap = "Em Itapetininga faz muito frio!!!!";
const float mtr = 17;
const char alf = 'm';
// Erro .... Aqui estamos diante de uma verdadeira constante
Itap = "tentando alterar uma constante...";
Label1 -> Caption = Itap + "\n" + AnsiString(km + mtr) + "\n" + alf;
}

Apostila de C++ Builder

Pagina -69-

O tipo enum
O tipo enum cuida tratar de um tipo cuja sintaxe bastante elaborada, para conter um conjunto de valores
definidos pelo usurio chamados dados de tipos enumerados ou enumerao.
Usando a palavra-chave enum, podemos definir um conjunto de constantes agrupadas sob um nome como
um novo tipo de dados, somando-se uma nova maneira s duas formas apresentadas anteriormente para
definio de constantes. A essa coleo de constantes, d-se o nome de constantes enumeradas.
As constantes enumeradas possibilitam-nos a criao de novos tipos de dados, bem como a definio de
variveis desses tipos, sendo que os valores assumidos ficam restritos a determinada coleo de valores.
Podemos, por exemplo, declarar uma enumerao representando os meses do ano:
enum Meses_do_Ano
{
janeiro,
fevereiro,
marco,
abril,
maio,
junho,
julho,
agosto,
setembro,
outubro,
novembro,
dezembro
}; // Fim de enum Meses_do_Ano

Feito isso, podemos definir variveis do tipo Meses_do_Ano, que podem assumir apenas valores inteiros:

enum Meses_do_Ano
{
janeiro = 0,
fevereiro = 1,
marco = 2,
abril = 3,
maio = 20,
junho = 21,
julho = 22,
agosto = 56,
setembro = 57,
outubro = 58,
novembro = 200,
dezembro = 201
}

Apostila de C++ Builder

Pagina -70-

Observe que cada constante enumerada possui um valor inteiro e que podemos atribuir um valor
especfico a determinada constante. Todavia se no especificarmos tal valor, a primeira constante
assumir o valor 0; a segunda, 1; a terceira, 2; a quarta, 3; e assim sucessivamente. Como, em nosso
exemplo optamos por atribuir valores aleatrios s constantes, percebemos que as constantes subseqentes
assumem valores com incremento de 1 a partir das que receberam um valor qualquer (em nosso exemplo,
os meses de maio, agosto e novembro).
Internamente as constantes enumeradas so representadas como sendo do tipo int.
O exemplo a seguir contm um Label no Form. Quando o usurio d um clique no Label, uma caixa de
insero de dados aparece para que seja digitado um valor entre 1 e 12. Dependendo do valor digitado,
teremos a resposta dos ms correspondente no Label:
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
enum Meses_do_Ano
{
janeiro = 1, // especifica o valor 1 para a primeira constante
fevereiro,
// vale 2
marco,
// vale 3 ...
abril,
maio,
junho,
julho,
agosto,
setembro,
outubro,
novembro,
dezembro
}; // Fim de enum Meses_do_Ano
// declara varivel do tipo Meses_do_Ano
Meses_do_Ano Mes;
//declara varivel int
int iMes;
iMes = StrToInt(InputBox ("Caixa para colheita de Valores",
"Digite um nmero entre 1 e 12", ""));
Mes = Meses_do_Ano(iMes);
switch(Mes)
{
case 1:
Label1 -> Color = clGreen; /*escolha uma cor diferente para cada ms*/
Label1 -> Font -> Name = "Arial"; /*e uma font para cada ms*/
Label1 -> Font -> Color = clYellow; /*e uma cor de font para cada ms*/
Label1 -> Caption = AnsiString(iMes) + " equivale a janeiro...";
break;
case 2:
Label1
Label1
Label1
Label1

->
->
->
->

Apostila de C++ Builder

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a fevereiro...";

Pagina -71-

break;
case 3:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a maro...";

case 4:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a abril...";

case 5:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a maio...";

case 6:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a junho...";

case 7:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a julho...";

case 8:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a agosto...";

case 9:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a setembro...";

case 10:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a outubro...";

Apostila de C++ Builder

Pagina -72-

case 11:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a novembro...";

case 12:
Label1
Label1
Label1
Label1
break;

->
->
->
->

Color =
Font ->
Font ->
Caption

clGreen;
Name = "Arial";
Color = clYellow;
= AnsiString(iMes) + " equivale a dezembro...";

default:
ShowMessage(AnsiString(iMes) + " no um valor vlido...");
break;
}
}
//---------------------------------------------------------------------------

Operadores matemticos
A linguagem C++ possui cinco operadores matemticos binrios representados pelos seguintes
operadores:
+ (adio);
- (subtrao);
* (multiplicao);
/ (diviso); e
% (mdulo);
e possui um operador unrio:
- (menos unrio).
Os operadores binrios operam sobre dois operandos e o unrio sobre um.
Os operadores de adio, subtrao, multiplicao e diviso funcionam normalmente como nos clculos
matemticos usuais. J o operador mdulo fornece-nos o resto de uma diviso inteira (sem eventuais
partes fracionrias) como resultado. Por exemplo, quando fazemos a diviso de 9 por 5, o resultado 1 e o
resto 4.
O operador menos unrio serve para trocar o sinal de seu operando (positivo para negativo ou negativo
para positivo):
Apostila de C++ Builder

Pagina -73-

int i = 440;
i = -i;
Label1 -> Caption = i; // Agora o valor de i - 440

O exemplo a seguir (calculadora bsica) possui, no Form, trs componentes Edit e cinco RadioButton(s)
dentro de um RadioGroup. Todas as propriedades do programa sero geradas em tempo de execuo (no
cdigo), e no diretamente no Object Inspector. O usurio dever digitar um valor no Edit1, outro valor
no Edit2 e escolher uma operao matemtica no RadioGroup para visualizar o resultado no Edit3.

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Form1 -> Caption = "Calculadora Bsica";
Form1 -> BorderStyle = bsSizeToolWin; // altera a borda de Form1
Edit1 ->
Edit2 ->
Edit3 ->
Edit3 ->
soltar)

Text = "";
Text = "";
Text = "";
ReadOnly =

// esvazia Edit1
// Esvazia Edit2
// esvazia Edit3
true; // Edit3 no aceita dados via teclado ou mouse (arrastar e

RadioGroup1 -> Caption = "Escolha uma operao";


RadioButton1 -> Caption = "+ (adio)";
RadioButton2 -> Caption = "- (subtrao)";
RadioButton3 -> Caption = "* (multiplicao)";
RadioButton4 -> Caption = "/ (diviso)";
RadioButton5 -> Caption = "% (mdulo)";
}
//--------------------------------------------------------------------------void __fastcall TForm1::RadioButton1Click(TObject *Sender)
{
/*Na operao de adio precisamos declarar variveis e realizar as respectivas
coverses para evitar erros de concatenao de strings em face do operador + */
double primeiro = StrToFloat(Edit1 -> Text);
double segundo = StrToFloat(Edit2 -> Text);
Edit3->Text = primeiro + segundo; //realiza o clculo por via indireta
Edit1->SetFocus(); //chama a funo SetFocus() para colocar o foco em Edit1
}
//--------------------------------------------------------------------------void __fastcall TForm1::RadioButton2Click(TObject *Sender)
{

Apostila de C++ Builder

Pagina -74-

Edit3->Text = double((Edit1->Text) - (Edit2->Text)); //realiza o clculo por via


direta
Edit1->SetFocus(); //chama a funo SetFocus() para colocar o foco em Edit1
}
//--------------------------------------------------------------------------void __fastcall TForm1::RadioButton3Click(TObject *Sender)
{
Edit3->Text = double((Edit1->Text) * (Edit2->Text)); //realiza o clculo por via
direta
Edit1->SetFocus(); //chama a funo SetFocus() para colocar o foco em Edit1
}
//--------------------------------------------------------------------------void __fastcall TForm1::RadioButton4Click(TObject *Sender)
{
Edit3->Text = double((Edit1->Text) / (Edit2->Text)); //realiza o clculo por via
direta
Edit1->SetFocus(); //chama a funo SetFocus() para colocar o foco em Edit1
}
//--------------------------------------------------------------------------void __fastcall TForm1::RadioButton5Click(TObject *Sender)
{
/* Essa parte do cdigo foi corrigido com o comando if ...else pois
apresentava um bug nas operaes em que o divisor era maior que o dividendo*/
//se o valor convertido para ponto flutuante de Edit1 for maior do que o de Edit2
if (StrToFloat(Edit1 -> Text) > StrToFloat(Edit2 -> Text))
// Edit3 apresentar o resto da diviso de Edit1->Text por Edit2->Text
Edit3 -> Text = double((Edit1 -> Text) % (Edit2 -> Text));
// caso contrrio
else
// Edit3 apresentar o valor 0 (zero) em seu texto
Edit3 -> Text = 0;
Edit1 -> SetFocus(); // chama a funo SetFocus() para colocar o foco em Edit1
}//---------------------------------------------------------------------------

Expresses
Todo comando que ao ser efetuado retorna um valor, considerado uma expresso em C++.
So expresses:
-273; // Retorna o valor -273
x = (a + b) - ((c * d) / e);
e assim por diante...
Observe as expresses no exemplo a seguir que leva apenas um Label no Form e ser usado para calcular
o resultado de uma equao de segundo grau:

Apostila de C++ Builder

Pagina -75-

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include <math.h> // Declarar essa biblioteca para funes matemticas
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------AnsiString a, b, c;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Form1->BorderStyle = bsNone; //retira as bordas e barra de ttulos do programa
Label1 -> Caption = "*****CALCULA EQUAO DE SEGUNDO GRAU*****\n"
"D um clique aqui para digitar os valores \"a\", \"b\" e \"c\" ";
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
Form1 -> AutoSize = true; // ajusta o tamanho do form ao label
try
{
retornoA:
a = InputBox("Caixa de Entrada de Valores",
"Digite um valor para 'a'", "");
StrToInt(a);
if (a == 0)
{
MessageBox(0,"Zero no um valor vlido para 'a' !"
"\nDigite outro valor... ",
"Erro no valor escolhido", 16);
goto retornoA;
}
else
Label1 -> Caption = " a = " + a;
Label1 -> Font -> Color = clRed;
Label1 -> Font -> Style = TFontStyles()<< fsBold;
}
catch(...)
{
MessageBox(0, "Erro ... Valor no suportado pelo programa ...",
"Erro de digitao", 16);
}
try
{
b = InputBox("Caixa de Entrada de Valores",
"Digite um Valor para 'b'", "");

Apostila de C++ Builder

Pagina -76-

StrToInt(b);
Label1 -> Caption = Label1 -> Caption + "\n b = " + b;
}
catch(...)
{
MessageBox(0, "Erro ... Valor no suportado pelo programa ...",
" Erro de digitao", 16);
}
try
{
c = InputBox("Caixa de Entrada de Valores",
"Digite um Valor para 'c'", "");
StrToInt(c);
Label1 -> Caption = Label1 -> Caption + "\n c = " + c;
}
catch(...)
{
MessageBox(0, "Erro ... Valor no suportado pelo programa ...",
"Erro de digitao", 16);
}
try
{
Label1 -> Font -> Color = clBlue;
Label1 -> Font -> Style = TFontStyles()<< fsBold;
double x1, x2, delta;
delta = (b*b) - ((a * 4) * c);
if(delta < 0)
MessageBox(0,"delta negativo... no existem razes reais...\n"
"\ntente novamente com outros valores...",
"Erro nos valores", 16);
else
{
Label1 -> Caption =
Label1 -> Caption +

"\n\ndelta = " + FloatToStr(delta);

x1 = ((b * (-1)) + (sqrt (delta))) / (a * 2);


Label1 -> Caption =
Label1 -> Caption + "\nx1 = " + FloatToStr(x1);
x2 = ((b * (-1)) - (sqrt (delta))) / (a * 2);
Label1 -> Caption =
Label1 -> Caption + "\nx2 = " + FloatToStr(x2);
}
}
catch(...)
{
MessageBox(0, "Por favor, digite os valores corretamente",
"Erro de execuo...", 16);
}
}

Apostila de C++ Builder

Pagina -77-

//--------------------------------------------------------------------------void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)


{
if (Key == 13) // se for pressionada a tecla Enter
Close();
// encerra o programa
}
//---------------------------------------------------------------------------

Entendendo melhor o C++Builder


Quando voc inicia o C++Builder, ele escreve automaticamente algumas linhas de cdigo para a sua
aplicao. Tentaremos entender o que significa cada uma dessas linhas:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

Inicialmente, na parte superior da janela, podemos contemplar uma linha de comentrios, constituda
basicamente de vrios hfens seguindo //. Como sabemos, em C++ tudo o que segue a dupla de caracteres
// ser ignorado pelo compilador at o final da linha. O compilador insere essas linhas, basicamente, para
separar sees de cdigos ou funes. Eles esto ali, apenas, para melhorar a visualizao.
Perceba que, existem outras linhas iguais a essa no cdigo e que sempre que codificarmos um um mtodo
de algum evento, atravs da chamada no Object Inspector, essas linhas de comentrio estaro l, criadas
automaticamente para melhorar a visualizao dos cdigos.

#include <vcl.h>
J sabemos que quando o pr-processador encontra a diretiva #include em nosso cdigo fonte, ele
substitui a mesma pelo contedo do arquivo indicado, sendo que o compilador encontrar e processar o
arquivo implementado, e no a diretiva de compilao. Avanado no estudo do cdigo inicial inserido
automaticamente pelo C++Builder, encontramos essa diretiva de determina a incluso do arquivo
chamado vcl.h:

Apostila de C++ Builder

Pagina -78-

#include <vcl.h>
Se voc instalou o C++Builder no diretrio padro, poder abrir e visualizar esse arquivo em
C:\Arquivos de programas\Borland\CBuilder6\Include\Vcl\vcl.h
Vejamos o seu contedo:
/////////////////////////////////////////////////////////////////////////////////
// VCL.H - Borland C++ Builder pre-compiled header file
// $Revision:
1.12.1.0.1.1 $
// Copyright (c) 1997, 2002 Borland Software Corporation
/////////////////////////////////////////////////////////////////////////////////
#ifndef VCL_H
#define VCL_H
#define INC_VCL
#include <basepch0.h>
#endif

// VCL_H

A vcl.h parte da Visual Component Library usada para linkar a definio de componentes como botes,
menus etc. Perceba que no arquivo em questo aparece novamente um include. Vejamos o contedo do
arquivo basepch0.h:
/////////////////////////////////////////////////////////////////////////////////
// BASEPCH0.H - Borland C++ Builder pre-compiled header file
// $Revision:
1.0.1.0.1.0 $
// Copyright (c) 1997, 2002 Borland Software Corporation
//
// BASEPCH0.H is the core header that includes VCL/CLX headers. The headers
// included by BASEPCH0.H are governed by the following macros:
//
// MACRO
DESCRIPTION
DEFAULT
// =======
=============
=======
//
// NO_WIN32_LEAN_AND_MEAN When this macro is defined, BASEPCH.H does
OFF
//
not define WIN32_LEAN_AND_MEAN.
//
// INC_VCL
This macro is defined by VCL.H to
OFF
//
include the base set of VCL headers
//
// VCL_FULL
Same as NO_WIN32_LEAN_AND_MEAN
OFF
//
(NOTE: This macro is for BCB v1.0 backward
//
compatibility)
//
// INC_VCLDB_HEADERS
When this macro is defined, VCL.H includes
//
requires INC_VCL
the core Database headers of VCL.
OFF
//
(Defining this macro is functionally
//
equivalent to including VCLDB.H)
//
// INC_VCLEXT_HEADERS
When this macro is defined, VCL.H includes
//
requires INC_VCL
all VCL headers.
OFF
//
(Defining this macro is functionally

Apostila de C++ Builder

Pagina -79-

//
equivalent to including VCLMAX.H)
//
// INC_CLX
This macro is defined by CLX.H to include
OFF
//
the base set of CLX headers
//
// INC_CLXDB_HEADERS
When this macro is defined, CLX.H includes
//
requires INC_CLX
the core Database headers of CLX.
OFF
//
// INC_CLXEXT_HEADERS
When this macro is defined, CLX.H includes
//
requires INC_CLX
all CLX headers.
OFF
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef __BASEPCH0_H__
#define __BASEPCH0_H__
// v1.0 of BCB checked for VCL_FULL to avoid LEAN_AND_MEAN support
//
#if defined(VCL_FULL)
// BCB v1.0 compatible
#define NO_WIN32_LEAN_AND_MEAN
#endif
#if !defined(_WINDOWS_) // Don't optimize
#if !defined(NO_WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
//
#define _VCL_LEAN_AND_MEAN
//
#endif
//
#endif
//

if WINDOWS.H has already been included

Enable LEAN_AND_MEAN support


BCB v1.0 compatible
NO_WIN32_LEAN_AND_MEAN
_WINDOWS_

#if !defined(COM_NO_WINDOWS_H) //Make sure COM Headers don't include WINDOWS.H/OLE2.H


#define COM_NO_WINDOWS_H
#define UNDEF_COM_NO_WINDOWS_H
#endif
#if !defined(RPC_NO_WINDOWS_H) // Make sure RPC Headers don't include WINDOWS.H
#define RPC_NO_WINDOWS_H
#define UNDEF_RPC_NO_WINDOWS_H
#endif
// Core (minimal) Delphi RTL headers
//
#include <System.hpp>
#include <Types.hpp>
#include <Windows.hpp>
#include <Messages.hpp>
#include <SysUtils.hpp>
#include <Classes.hpp>
// Core (minimal) VCL headers
//
#if defined(INC_VCL)
#include <Controls.hpp>
#include <Graphics.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include <StdCtrls.hpp>
#include <ExtCtrls.hpp>

Apostila de C++ Builder

Pagina -80-

// Full set of VCL headers


//
#if defined(INC_VCLEXT_HEADERS)
#include <Buttons.hpp>
#include <ChartFX.hpp>
#include <ComCtrls.hpp>
#include <DdeMan.hpp>
#include <FileCtrl.hpp>
#include <GraphSvr.hpp>
#include <Grids.hpp>
#include <MPlayer.hpp>
#include <Mask.hpp>
#include <Menus.hpp>
#include <OleCtnrs.hpp>
#include <OleCtrls.hpp>
#include <Outline.hpp>
#include <Tabnotbk.hpp>
#include <Tabs.hpp>
#include <VCFImprs.hpp>
#include <VCFrmla1.hpp>
#include <VCSpell3.hpp>
#endif // INC_VCLEXT_HEADERS
#endif

//

INC_VCL

// Core (minimal) CLX headers


//
#if defined(INC_CLX)
#include <Qt.hpp>
#include <BindHelp.hpp>
#include <QConsts.hpp>
#include <QStdActns.hpp>
#include <QStyle.hpp>
#include <QControls.hpp>
#include <QTypes.hpp>
#include <QGraphics.hpp>
#include <QForms.hpp>
#include <QDialogs.hpp>
#include <QStdCtrls.hpp>
#include <QExtCtrls.hpp>
#include <QMenus.hpp>
#include <QClipbrd.hpp>
#include <QMask.hpp>
#include <QButtons.hpp>
#include <QComCtrls.hpp>
// CLX Database related headers
//
#if defined(INC_CLXDB_HEADERS)
#include <QDBCtrls.hpp>
#include <DB.hpp>
#include <DBTables.hpp>
#endif // INC_CLXDB_HEADERS
// Full set of CLX headers
//

Apostila de C++ Builder

Pagina -81-

#if defined(INC_CLXEXT_HEADERS)
#include <QDBGrids.hpp>
#include <QDBCtrls.hpp>
#include <QDBActns.hpp>
#include <QGrids.hpp>
#include <QImgList.hpp>
#include <QSearch.hpp>
#include <QActnList.hpp>
#include <QCheckLst.hpp>
#include <QPrinters.hpp>
#endif // INC_CLXEXT_HEADERS
#endif

//

INC_CLX

#if defined(INC_OLE_HEADERS)
#include <cguid.h>
#include <dir.h>
#include <malloc.h>
#include <objbase.h>
#include <ole2.h>
#include <shellapi.h>
#include <stddef.h>
#include <tchar.h>
#include <urlmon.h>
#include <AxCtrls.hpp>
#include <OleCtnrs.hpp>
#include <OleCtrls.hpp>
#endif
// Using ATLVCL.H
//
#if defined(INC_ATL_HEADERS)
#include <atl\atlvcl.h>
#endif
#if defined(UNDEF_COM_NO_WINDOWS_H) //Clean up MACRO to prevent inclusion of WINDOWS.H/OLE2.H
#undef COM_NO_WINDOWS_H
#undef UNDEF_COM_NO_WINDOWS_H
#endif
#if defined(UNDEF_RPC_NO_WINDOWS_H) // Clean up MACRO to prevent inclusion of WINDOWS.H
#undef RPC_NO_WINDOWS_H
#undef UNDEF_RPC_NO_WINDOWS_H
#endif
#endif

// __BASEPCH0_H__

Veja quantos include. Por exemplo, #include <Buttons.hpp>, #include <Menus.hpp> etc. Um bom
conhecimento dessas bibliotecas, pode nos facilitar bastante a compreenso. Todavia, por enquanto, no
se preocupe com isso, mesmo porque o compilador cuida muito bem da tarefa, margem de nosso
profundo, ou escasso, conhecimento de suas particularidades. Quanto ao estudo das diretivas, no avanar
do curso procuraremos conhecer pelo menos um pouco de cada uma delas.

Apostila de C++ Builder

Pagina -82-

#pragma hdrstop
A seguir, encontramos a seguinte linha de cdigos:
#pragma hdrstop
Atravs da diretiva #pragma, o C++Builder pode definir diretivas que podem ser passadas ao compilador.
Se o compilador no identificar o nome da diretiva, ele simplesmente ignora #pragma sem emitir qualquer
aviso ou mensagem de ERRO. A sintaxe de pragma #pragma nome_da_diretiva.
O compilador C++Builder suporta as seguintes diretivas #pragma:
#pragma alignment
#pragma anon_struct
#pragma argsused
#pragma checkoption
#pragma codeseg
#pragma comment
#pragma defineonoption
#pragma exit
#pragma hdrfile
#pragma hdrstop
#pragma inline
#pragma intrinsic
#pragma link
#pragma message
#pragma nopushoptwarn
#pragma obsolete
#pragma option

Apostila de C++ Builder

Pagina -83-

#pragma pack
#pragma package
#pragma resource
#pragma startup
#pragma undefineonoption
#pragma warn
Sintaxe: #pragma hdrstop
Descrio: Esta diretiva termina a lista de hearde files escolhidos para pr-compilao. Voc pode us-lo
para reduzir a quantia de espao em disco usados por headers de pr-compilao.
Hearder files pr-compilados podem ser compartilhados entre os arquivos fonte de seu projeto sendo que
somente as diretivas #include antes de #pragma hdrstop so idnticas (comuns a todos os arquivos do
projeto). Ento, voc adquire o melhor desempenho do seu compilador se voc incluir os header files
comuns de seu projeto antes de #pragma hdrstop, e os especficos depois disto. Certifique-se de ter
inserido as diretivas #include antes de #pragma hdrstop de forma indntica em todo o cdigo fonte, ou
que haja apenas pequenas variaes.
O ambiente de desenvolvimento integrado gera o cdigo para aumentar desempenho de header prcompilados. Por exemplo, depois de uma Aplicao Nova, o arquivo fonte " Unit1.cpp" ter a seguinte
aparncia (comentrios adicionados):

#include <vcl.h> // arquivos de header comuns


#pragma hdrstop // fim da lista comum
#include "Unit1.h" // header files especficos
// ....

S se usa essa diretiva pragma em arquivos fonte. Ela no tem nenhum efeito quando usada em um
arquivo header (.h, .hpp etc).

Unit1.h
A seguir, percebemos mais um enunciado include inserido automaticamente pelo BCB:

Apostila de C++ Builder

Pagina -84-

#include Unit1.h
O arquivo de cabealho Unit1.h criado simultaneamente com o arquivo Unit1.cpp que o arquivo
que contm o cdigo principal de um aplicativo (aquele onde temos efetuado a maioria das incluses de
cdigos at agora). J sabemos que os cabealhos colocados entre aspas ... determinam que o prprocessador procure o cabealho primeiro no diretrio atual, e depois na biblioteca padro (Include).
Entende-se por diretrio atual, aquele onde salvamos o projeto, ou seja, onde se encontram os arquivos do
projeto gerados pelo sistema no desenvolvimento do programa. Eventualmente, se o arquivo no se
encontrar em nenhum desses dois diretrios, podemos indicar o seu caminho completo entre as aspas:
C:\\Meu_aplicativo\\Unit1.h
Evidentemente que Unit1.h o nome padro dado pelo C++Builder ao arquivo. Se, num projeto,
salvarmos os arquivos com nomes diferentes, esses nomes sero aqueles que encontraremos
acompanhados do .h e do .cpp. Por exemplo, Edit_Texto.h e Edit_Text.cpp. Outra questo
importante diz respeito ao nmero 1 entre Unit e o .h ou o .cpp. Esse nmero refere-se ao nmero do
componente na aplicao. Se colocarmos um segundo Form no aplicativo, o arquivo principal dele ser
nomeado de Unit2.cpp; um terceiro, de Unit3.cpp , e assim por diante. Evidentemente, conforme exposto,
no precisamos concordar com nomes padro.
Em outra seo, abordaremos tcnicas de como dar nomes a nossas aplicaes e aos componentes nelas
inseridos. Porm, no nosso curso, raramente trocaremos o nome padro fornecido pelo compilador. Por
um motivo muito simples. O nome padro facilita a compreenso para estudantes de lnguas diferentes,
que no compreendem nosso idioma. Quando eu fazia pesquisas na internet, vrias vezes pude aproveitar
cdigos, cujos autores eu nem poderia, de mim mesmo, imaginar a nacionalidade, de to complexa a
forma de escrever (tipo chins, russo, grego etc). Mesmo assim, quando os cdigos eram mantidos no
default fornecido pelo C++Builder, eram-me bastante claros (exceto strings e comentrios,
evidentemente).
Penso que o mnimo que posso fazer, uma vez que a maior parte do que consegui aprender sobre
programao foi atravs da Internet, atravs de uma infinidades de generosos professores annimos.
Porm, quando eu aproveitar exemplos que j fiz anteriormente, alterando os nomes, manterei estes
nomes.

#pragma package(smart_init)
Sintaxe:
#pragma package(smart_init)
#pragma package(smart_init, weak)
Descrio: smart_init argument

Apostila de C++ Builder

Pagina -85-

A diretiva #pragma package(smart_init) utilizada durante a inicializao do aplicativo. Ela assegura


que qualquer unidade de cdigos requisitada pelo programa ser inicializada na segqncia correta, ou
seja, sero inicializadas na ordem determinada por suas dependncias (Includa por default no pacote
arquivo fonte). Tipicamente, voc pode usar o #pragma package para arquivos .CPP que so criados
como packages.
Esta diretiva pragma afeta a ordem de inicializao desta unidade de compilao. Para units, a
inicializao ocorre na seguinte ordem:
1. Pelas suas dependncias de "usos", quer dizer, se unitA depende de unitB, unitB deve ser inicializa
antes de unitA.
2. A ordem de vnculo.
3. Ordem de prioridade dentro da unit.
para arquivos .OBJ regulares (aqueles no construdos como units), a inicializao acontece primeiro de
acordo com a ordem de prioridade e, ento, de acordo com a ordem de vnculo. Mudando a ordem de
vnculo dos arquivos .OBJ muda-se a ordem na qual os objetos construtores globais so chamados.
Os exemplos seguintes mostram como a inicializao difere entre units e arquivos .OBJ regulares.
Tome como um exemplo trs arquivos unit, A, B e C que so inteligentemente inicializados com
#pragma package(smart_init) e possuem valor de prioridade (definidas no parmetro prioridades do
#pragma startup) setados de 10, 20 e 30. As funes so nomeadas de acordo com os seus valores de
prioridades e o parent .OBJ. assim os nomes so a10, a20, a30, b10, e assim por diante.
Desde que todas as trs so units, e se A usa B e C e a ordem de vnculo A, B e ento C, a ordem de
inicializao :

B10 B20 B30 C10 C20 C30 A10 A20 A30


Se, ao invs de units, o arquivo anterior fosse .OBJ a ordem seria:

A10 B10 C10 A20 B20 C20 A30 B30 C30


Os arquivos .CPP que usam #pragma package(smart_init) tambm requerem que algum #pragma link
referencie outro arquivo .OBJ desde um arquivo .CPP que declara #pragma package(smart_init), e deve
estar resolvido na unit. Se #pragma link fizer referncias para arquivos no .OBJ pode ainda ser
resolvido por bibliotecas etc.
Descrio: weak packages
A diretiva #pragma package(smart_init, weak) afeta o modo que um arquivo .OBJ armazenado num
packages .BPI e arquivos .BPL. Se #pragma package(smart_init, weak) aparece em um arquivo de unit,

Apostila de C++ Builder

Pagina -86-

o compilador omite a unit de BPLs quando possvel, e cria uma cpia local non-packaged da unit quando
ela requerida por outra aplicao ou package. Uma unit compilada com esta diretiva dita como sendo
weakly packaged.
#pragma package(smart_init, weak) usado para eliminar conflitos entre packages que possivelmente
dependem da mesma biblioteca externa.
Arquivos Unit contendo a diretiva #pragma package(smart_init, weak) no devem ter variveis globais.
para maiores informaes sobre uso weak packages, veja Weak packaging.

#pragma resource
Sintaxe:
#pragma resource *.dfm
Descrio: Esta diretiva pragma faz o arquivo ser marcado como uma unidade de Form e requer
combinao .dfm. Ou seja, ela determina que o compilador utilize tal arquivo (.dfm) de definio do
Form, requisitado por essa Unit. Tais arquivos so administrados pelo IDE.
Se seu Form requer qualquer varivel, elas devem ser declaradas depois da inscrio do pragma resource.
As declaraes devem ser pertencentes ao Form.

TFormName *Formname;

TForm
TForm representa uma janela padro da aplicao (Form).
Unit: Forms
Descrio:
Quando voc cria formulrios no Form designer em tempo de projeto, eles so implementados como
descendentes de TForm. Forms podem representar a janela principal da aplicao, caixas de dilogo, ou
janelas filhas (MDI children). Um form pode conter outros objetos como TButton, TCheckBox,
TcomboBox etc.
Exemplos de forms incluem objetos TLoginDialog e TPasswordDialog.

Apostila de C++ Builder

Pagina -87-

Nota: Quando trabalhamos com objetos form, no chamamos explicitamente os mtodos Free ou Destroy
para liber-los. Em vez disso, usamos o mtodo liberar (Release method), o qual espera at que todos
event handlers (parte do programa que trata determinadas situaes) tenham terminados sua execuo.

_fastcall, __fastcall
Categoria: modificadores C++Builder, extenso de palavra-chave
Sintaxe:
valor_de_retorno _fastcall nome_da_funo(parm-lista)
valor_de_retorno __fastcall nome_da_funo(parm-lista)
Descrio:
use o modificador __fastcall para declarar funes que aguardam parmetros para serem passados em
registros. os trs primeiros parmetros so passados (da esquerda para a direita) em EAX, EDX, e ECX,
se eles se ajustarem no registro. Os registros no so usados se o parmetro um ponto flutuante ou uma
estrutura (struct type).
Todas as funes-membro da classe Form devem usar a conveno __fastcall.
O compilador trata essa conveno chamada como uma nova language, ao longo das linhas of _cdecl e
_pascal
Funes declaradas usando _cdecl ou _pascal no podem ter os modificadores _fastcall porque eles usam
a pilha para passar os parmetros. Igualmente, o modificador __fastcall no pode ser usado junto com
_export.
O compilador antepe o nome da funo __fastcall com um a-sinal (at-sign) ("@"). Este prefixo aplica-se
a desqualificao de nomes de funo C e para C++.
Para implementao estilo Microsoft VC++ __fastcall, veja __msfastcall e __msreturn.
Nota: o modificador __fastcall est sujeito desqualificao do nome da funo. Veja a descrio do -VC
option.

TComponent
TComponent o ancestral comum de todos os componentes que podem aparecer no form designer.

Apostila de C++ Builder

Pagina -88-

Unit: Classes
Descrio:
Components so objetos persistentes que possuem as seguintes capacidades:
A capacidade de aparecer no Componente palette e ser transferido para o form designer.
A capacidade de administrar-se, a si, e a outros componentes.
Incrementar o fluxo e armazenar capacidades.
A capacidade de ser convertido em um controle ActiveX ou outro objeto COM por wizards na pgina
ActiveX do dilogo New Objects.
1.
2.
3.
4.

No crie instncias de TComponent. Use TComponent como uma classe base quando declarar um
componente no-visual que pode mostrar-se no component palette e ser usado no form designer.
Propriedades e mtodos de TComponent fornecem comportamentos bsicos que classes dependentes
herdam e tambm comportamentos que componentes podem ativar para ajustar seu comportamento.
Para criar componentes os quais so visveis em tempo de execuo para os usurios, use TControl ou
seus descendentes como base. Para criar controles baseados em objetos janelas, use TWinControl ou seus
descendentes como base.

TComponent::Owner
Owner = Proprietrio
Indica o componente que responsvel por carregar e liberar seus componentes.
__property TComponent* Owner = {read=FOwner};
Descrio:
Use Owner para encontrar o proprietrio de um componente. O Owner de um componente responsvel
por duas coisas:
A memria referente ao componente liberada assim que a memria de seu proprietro liberada.
O Owner responsvel por carregar e salvar as propriedades published de seu controle proprietrio.
Por default, um form possui todos os componentes que esto nele. Por sua vez, o form pertencente
aplicao. Assim, quando a aplicao encerrada e a memria correspondente liberada, a memria para
todos os forms (e todos os seus componentes) tambm liberada. Quando um form carregado na
memria, automaticamente so carregados todos os componentes que nele esto instalados.

Apostila de C++ Builder

Pagina -89-

O proprietrio de um componente determinado pelo parmetro passado ao construtor quando o


componente criado. Pelo fato de os componentes serem criados no form designer, o form
automaticamente nomeado como o proprietrio.
Aviso: Se um componente tem um proprietrio diferente de um form ou mdulo de dados, ele no ser
salvo ou carregado com seu proprietrio, a menos que voc o identifique como um subcomponente. Para
identificar um componente como um subcomponente, chame o mtodo SetSubComponent.

Operadores de incremento e decremento


Voc j deve ter percebido que mencionamos expresses do tipo incremento e decremento. Num sentido
mais tcnico, trata-se de dois operadores de extrema utilidade em C++.
O operador de incremento formado por dois sinais de adio ++ e adiciona 1 ao valor da varivel qual
aplicado. Num exemplo anterior (Operaes matemticas com unsigned), a expresso:
uiAcresce = uiAcresce + 1;

produziria o mesmo resultado se fosse substituda por:


uiAcresce++;

J o operador de decremento formado por dois sinais de subrao -- e subtrai 1 do valor da varivel
qual aplicado:
uiDecresce--;

equivalente a:
uiDecresce = uiDecresce - 1;

relevante a posio dos operadores de incremento (++) ou decremento (--) em relao varivel:
++uiAcresce; // operador antecedendo do nome da varivel - prefixo
uiAcresce++; // operador aps o nome da varivel - sufixo
--uiDecresce; // prefixo
uiDecresce--; // sufixo

Apostila de C++ Builder

Pagina -90-

Na posio de prefixo, primeiro o operador aplicado e depois a varivel tem seu valor acessado. Na
posio de sufixo, o valor da varivel acessado antes de o operador ser aplicado.
O exemplo abaixo usa um Button e um Memo no Form. Quando o usurio d cliques no boto, as
variveis so, conforme o caso, incrementadas ou decrementadas, com operadores ps e pr-fixados. A
diferena dos resultados que tais operadores operam nas variveis nessas diversas situaes demonstrada
no Memo:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------int Acresce = 100, ACRESCE = 100,
Decresce = 100, DECRESCE = 100;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Memo1->Lines->Add("incrementa Acresce com sufixo " + String(Acresce++) +
"
" "incrementa ACRESCE com prefixo " + String(++ACRESCE));
Memo1->Lines->Add("decrementa Decresce com sufixo " + String(Decresce--) +
"
" "decrementa DECRESCE com prefixo " + String(--DECRESCE));
}
//---------------------------------------------------------------------------

Operadores relacionais
Existem alguns operadores que fazem comparaes e, por isso, so chamados de relacionais:

Apostila de C++ Builder

>

maior

>=

maior ou igual

<

menor

<=

menor ou igual

==

igual a

Pagina -91-

>

maior

!=

diferente

Os operadores relacionais so bastante usados pelas partes dos programas que trabalham com laos e
comandos de deciso. O exemplo a seguir usa um desses operadores num programa que coloca um efeito
degrad no form:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormPaint(TObject *Sender)
{
/* inicia o loop (lao) for com varivel ponto flutuante. Aqui est
sendo usado um operador relacional menor ou igual */
for ( float fVar = 0; fVar <= 200; fVar = fVar + 0.1)
{
TRect Val; // tipo que define um retngulo
// funo que agrupa as coordenadas do retngulo especificado
SetRect((RECT *)&Val,0,(Height*fVar) / 200, Width,(Height*(fVar+1)) / 200);
//determina a cor para preenchimento do background.
Canvas->Brush->Color=RGB(0,0,255-fVar*1.1);
// preenche o retngulo especificado no canvas usando o Brush atual
Canvas->FillRect(Val);
}
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormResize(TObject *Sender)
{
/* determina a repintura do controle depois de outra importante mensagem Windows ser
tratada*/
Invalidate();
}
//---------------------------------------------------------------------------

O comando if
No incio deste curso informamos que usaramos alguns nomes, comandos ou tipos de dados com os quais
voc poderia no estar habituado a trabalhar. Em algumas ocasies, j tivemos oportunidade de usar o
Apostila de C++ Builder

Pagina -92-

comando if ... else sem, contudo, entrar em detalhes sobre o funcionamento do mesmo, exceto por alguma
rpida explicao, at mesmo em comentrios, que j devem ter lhe dado uma pequena noo acerca do
mesmo. Essa justamente nossa inteno na utilizao antecipada dessas instrues. Voc vai tendo
contato com os comandos e, aos poucos, assimilando sua utilidade e forma de funcionamento. Dessa
forma, o estudo deve ser facilitado no momento que tratamos diretamente do assunto, pois, ainda que no
se lembre das mincias, o comando no ser algo totalmente estranho para voc.
Dentro de cada bloco de cdigos, o fluxo de execuo de um programa faz com que as linhas sejam
executadas na ordem em que aparecem. Por exemplo:
Edit1 -> Text == "";
Edit1 -> SetFocus();

Nestas duas linhas acima, primeiro ser esvaziado o Text de Edit1 que depois receber o foco.
Todavia, bastante comum um programa precisar quebrar esse fluxo na execuo, seguindo por um
caminho diferente, deixando de executar determinadas instrues em resposta a certas condies. O
comando if permite testar uma condio (por exemplo, se o valor de uma varivel booleana verdadeiro true) e seguir para uma ou outra parte do cdigo em virtude do resultado desse teste.
Podemos resumir o uso do if da seguinte forma:
if(expresso)

comando;
mais comum que a expresso avaliada pelo comando if seja do tipo relacional, mas, em princpio, pode
ser de qualquer tipo. Feita a avaliao pelo comando, se o resultado da expresso for zero, ela
considerada falsa, e o comando no ser executado. Se o valor da expresso for diferente de zero, ela
considerada verdadeira, e o comando ser executado.
No exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1 -> Text == "")
Edit1 -> SetFocus();
}

Quando o usurio der um clique no boto, o foco ira para Edit1 somente se Edit1 estiver vazio.
Tambm podemos determinar um bloco de comandos entre chaves { }:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1 -> Text == "")
{
Edit1 -> Text = "Primeiro Comando deste bloco";
Label1 -> Caption = "Segundo Comando deste bloco";

Apostila de C++ Builder

Pagina -93-

Memo1

->

Lines

->

Add("Terceiro

Comando

ltimo

comando

deste

bloco");
}
}

O exemplo a seguir usa um ComboBox, um Label e um Button no Form. Quando o usurio d um clique
no boto, IndexOf() faz uma busca pelo item que contm a string Teste no ComboBox. Se o item
encontrado, o valor numrico do item atribudo varivel que passar a ter um valor igual ou maior do
que zero (zero corresponde ao primeiro item da relao no ComboBox, 1 ao segundo e assim por diante).
Feito isso, o programa chama Delete() para apagar o item correspondente busca. Consecutivamente, o
programa informa o valor da varivel no Label.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
/* Adiciona cabealho (texto) e items no
ComboBox na inicializao do programa*/
ComboBox1 -> Text = "Fatos e Testes";
ComboBox1 -> Items -> Add("Hoje 22 de julho de 2002");
ComboBox1 -> Items -> Add("Teste");
ComboBox1 -> Items -> Add("Est fazendo um pouco de frio");
ComboBox1 -> Items -> Add("A Marta professora");
ComboBox1 -> Items -> Add("Ela est trabalhando no Jd. lamo");
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
/* declara e inicializa varivel iBusc com o nmero devolvido
por IndexOf() para o item que contm Teste*/
int iBusc = ComboBox1->Items->IndexOf("Teste");
// se a a busca tiver xito, a varivel possui valor diferente de -1
if (iBusc > -1)
// chama Delete() para apagar o item buscado
ComboBox1->Items->Delete(iBusc);
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -94-

O comando else
Pode ocorrer de um aplicativo ter de executar uma instruo se determinada condio for verdadeira, e
outra instruo se tal condio for falsa. Um recurso oferecido por C++ para essas situao a
combinao if ... else.
A forma do uso de if ... else pode ser resumido da seguinte forma:
if(expresso)
comando;
else
outro_comando;

O Exemplo a seguir usa um Edit, um Label e um Button no Form. Quando o usurio d um clique no
boto, o programa far uma busca pelo arquivo, cujo caminho estiver especificado no Edit. O resultado da
busca ser informado no Label.
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
/* Declara e inicializa varivel BuscArquiv com o resultado da busca
por um arquivo, cujo caminho completo especificado em Edit1 */
AnsiString BuscArquiv = FileSearch(Edit1->Text, GetCurrentDir());
// Se BuscArquiv estivar vazia (pelo fato de a busca fracassar)
if (BuscArquiv == "")
// O Label informar que no encontrou o arquivo
Label1 -> Caption = "No foi possvel encontrar " + Edit1->Text + ".";
// caso contrrio (Se houver algum dado em BuscArquiv)
else
// Label informar que encontrou o arquivo
Label1 -> Caption = "Encontrado " + BuscArquiv + ".";
}
//---------------------------------------------------------------------------

if ...else - Continuao
O comando if ... else comporta em seu interior quaisquer outros comandos, incluindo combinaes else if,
if ... else:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(StrToInt(Edit1 -> Text) >= StrToInt(Edit2 -> Text))
{
if((StrToInt(Edit1 -> Text) % StrToInt(Edit2 -> Text)) == 0)
{
if(StrToInt(Edit1 -> Text) == StrToInt(Edit2 -> Text))

Apostila de C++ Builder

Pagina -95-

Label1

->

Caption

"O

nmero

de

Edit1

igual

ao

de

Edit2!!!";
else
Label1 -> Caption = "O nmero de Edit1 multiplo do de
Edit2";
}
else
Label1 -> Caption = "O nmero de Edit1 no mltiplo do de Edit2";
}
else
Label1 -> Caption = "O nmero de Edit2 maior que o de Edit1";
}
//---------------------------------------------------------------------------

Nota: O comando else nem sempre estar associado ao comando if mais recente. Um comando if contido
com todas as suas instrues num bloco de chaves {} dever remeter o else (fora desse bloco) para o if
antecedente. Um bloco de cdigo, em virtude de "pequenas" alteraes, poder apresentar resultados
totalmente diferentes. Por exemplo:
//----------------------------------------------------------------------------int x = 45, y = 200, z = 10;
if (x == 1)
{
// incio do bloco
if (y == 200)
z = y - x;
}
//fim do bloco sem else
else // a instruo desse comando ser aplicada se x for diferente de 1
z = y + x;
Label1->Caption = z; /*Resultado: z = 245, pois o comando else, em virtude das chaves {},
est relacionado com o primeiro if, cuja condio falsa, porque x diferente de 1 */

//-----------------------------------------------------------------------------int x = 45, y = 200, z = 10;


if (x == 1); //o ponto e vrgula faz a diferena. No existe instruo para essa condio
if (y == 200)
z = y - x; // Ok. y igual a 200
else
z = y + x; // essa instruo seria aplicada se y fosse diferente de 200
Label1->Caption = z; /*Resultado: z = 155, porque o primeiro if no levado em
considerao em virtude do ponto e vrgula que deixa a instruo deste comando vazia */

//-----------------------------------------------------------------------------int x = 45, y = 200, z = 10;


if (x == 1)
if (y == 200)
z = y - x;
else
z = y + x;
Label1->Caption = z; /*Resultado: z = 10, pois o programa avalia as duas condies e no
encontra uma opo (um segundo else) para o fato de a primeira condio ser falsa */

//------------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -96-

int x = 45, y = 200, z = 10;


if (x == 1)
if (y == 200)
z = y - x;
else
z = y + x;
else
z = 300;
Label1 -> Caption = z; /* Resultado: z = 300, pois esse segundo else vai de encontro
com o fato de a primeira condio ser falsa */

//-----------------------------------------------------------------------------int x = 45, y = 200, z = 10;


if (x == 45)
if (y == 200)
z = y - x;
else
z = y + x;
Label1 -> Caption = z; //
verdadeiras.

Resultado:

155,

porque

as

duas

condies

so

//------------------------------------------------------------------------------

Comandos aninhados e Indentao


J tivemos oportunidade de mostrar a grande importncia do correto uso das chaves {} nos comandos if ...
else. Dito isso, bom realarmos que esses comandos podem ser aninhados tantas vezes quantas forem
necessrias, ou seja, um if ... else pode conter outro if ... else, que pode conter outro if ... else etc, etc, etc.
Esse tipo de codificao pode se tornar difcil de escrever e interpretar, induzindo a erros. Da a
necessidade do adequado uso das chaves {}, bem como de recursos que facilitem a escrita como a
indentao do cdigo.
Promover indentao do cdigo significa indicar os nveis de aninhamento de suas diversas partes,
afastando-se gradualmente (atravs de espaos ou tabulaes) as linhas (ou blocos) de cdigo da margem
da pgina:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1->Text == "Ol")
Label1->Caption = "Ol";
else if(Edit1->Text == "Pessoal")
Label1->Caption = "Pessoal";
else if(Edit1->Text == "da cidade")
Label1->Caption = "da cidade";
else if(Edit1->Text == "de Assis")
Label1->Caption = "de Assis";
else
Label1->Caption = "Ol pessoal de Assis!!!";

Apostila de C++ Builder

Pagina -97-

}
//--------------------------------------------------------------------------Conforme o caso, podemos tornar mais legveis as construes aninhadas if ... else,
sem o recurso da identao:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(Edit1->Text == "Ol")
Label1->Caption = "Ol";
else if(Edit1->Text == "Pessoal")
Label1->Caption = "Pessoal";
else if(Edit1->Text == "da cidade")
Label1->Caption = "da cidade";
else if(Edit1->Text == "de Assis")
Label1->Caption = "de Assis";
else
Label1->Caption = "Ol pessoal de Assis!!!";
}//---------------------------------------------------------------------------

Operadores lgicos
Pode ocorrer de um comando precisar receber mais de uma resposta para tomar uma deciso.
A linguagem C++ oferece trs operadores lgicos que so:

&&

significa: E

||

significa: OU

significa: NO

A sintaxe :
expresso_1 && expresso_2
resulta verdadeiro somente se ambas as expresses forem verdadeiras;
expresso_1 || expresso_2
se pelo menos uma das expresses for verdadeira, o resultado ser verdadeiro;
! expresso
o resultado ser verdadeiro somente se a expresso for falsa.
Como os dois primeiros operadores avaliam duas expresses, so classificados como binrios; j o ltimo,
unrio.
Nota: O tipo TShiftState usado para eventos de teclado e eventos do mouse para determinar o estado das teclas
Alt, Ctrl e Shift, bem como dos botes do mouse, quando ocorrer um evento. Trata-se de um grupo de flags que
indica o seguinte:

Apostila de C++ Builder

Pagina -98-

ssShift

A tecla Shift est segura em baixo.

ssAlt

A tecla Alt est segura em baixo.

ssCtrl

A tecla Ctrl est segura em baixo.

ssLeft

O boto esquerdo do mouse est seguro em baixo.

ssMiddle

O boto do meio do mouse est seguro em baixo..

ssDouble

O mouse recebeu um duplo clique.

O exemplo a seguir leva um label no Form. Conforme o usurio produzir um dos eventos acima, uma
resposta diferente ser dada pelo programa:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
if(Shift.Contains(ssCtrl) && Shift.Contains(ssShift))
Label1->Caption = "Tecla Ctrl \"e\" tecla Shift pressionadas";
if(!Shift.Contains(ssAlt) && !Shift.Contains(ssCtrl) && !Shift.Contains(ssShift))
ShowMessage("A tecla pressionada no a tecla Alt, Shift ou Ctrl.");
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if(Shift.Contains(ssDouble) || Shift.Contains(ssLeft))
Label1->Caption = "Evento do mouse detectado: Duplo Clique \"ou\" boto esquerdo.";
}
//---------------------------------------------------------------------------

O operador condicional ternrio


C++ possui o operador condicional ternrio ? : que nos formece uma maneira concisa de expressar,
simplificadamente, uma instruo if ... else:

Apostila de C++ Builder

Pagina -99-

condio? expresso_1 : expresso_2;


feita uma avaliao da condio. Se ela for verdadeira, o programa retornar a expresso_1; se falsa,
a expresso_2. A nomenclatura ternrio decorre do fato de o operador manipular trs termos. Embora o
operador condicional ternrio seja constitudo de dois caracteres (? :), trata-se de um nico operador.
O exemplo a seguir leva um Edit no Form e usado para permitir a edio de valores numricos inteiros:

//--------------------------------------------------------------------------void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)


{
isdigit(Key)? Key<48 || Key>57 : Key = 0;
}
//---------------------------------------------------------------------------

Funes
Todos os aplicativos escritos em linguagem C ou C++ iniciam a execuo do programa atravs de uma
funo principal. Nas aplicaes tipo Console, essa funo denomina-se main. Aplicaes Win32 GUI
chamam WinMain para iniciar a execuo:
int WINAPI WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpszCmdLine,
int nCmdShow
);

//
//
//
//

manipulador da instancia atual


manipulador da instancia prvia
ponteiro lnha de comando
estado de visualizao da janela

A funo WinMain tem quatro parmetros de entrada:


hInstance

um manipulador para a instncia do programa que estamos executando.


Cada vez que se executa uma aplicao, o Windows cria uma Instncia
para ela, e lhe passa um manipulador de dita instncia para a aplicao

hPrevInstance

um manipulador a instncias prvias da mesma aplicao. Como o


Windows multitarefa, podem existir vrias verses da mesma aplicao
executando-se varias instncias. Em Windows 3.1, este parmetro nos
servia para saber se nossa aplicao j estava sendo executada, e desse
modo podiam compartilhar os dados comuns a todas as instncias. Mas
isso era antes, j que em Win32 usa um segmento distinto para cada
instncia e este parmetro sempre NULL, sendo conservado apenas por
motivo de compatibilidade

lpszCmdLine

ponteiro a uma cadeia (terminada em zero) que especifica os argumentos

Apostila de C++ Builder

Pagina -100-

hInstance

um manipulador para a instncia do programa que estamos executando.


Cada vez que se executa uma aplicao, o Windows cria uma Instncia
para ela, e lhe passa um manipulador de dita instncia para a aplicao
de entrada da linha de comando da aplicao

nCmdShow

este parmetro especifica como se mostrar a janela

No entraremos em detalhes sobre essa funo, visto que tal assunto est reservado para outro curso, sobre
WinAPI, que em breve esperamos estar disponibilizando neste Stio:
Eis um arquivo bsico de um Project.cpp do C++Builder, onde podemos visualizar a funo principal:

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
USERES("Project2.res");
USEFORM("Unit1.cpp", Form1);
//--------------------------------------------------------------------------WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
//---------------------------------------------------------------------------

A funo acima encontra-se num arquivo em separado daqueles que estamos acostumados a trabalhar.
Via de regra, em C++, irrelevante se a funo inicial est colocada no incio ou no fim do arquivo, pois o
programa ignorar o fato, executando do mesmo jeito, tanto numa quanto noutra posio. Evidentemente,
no BCB no devemos alterar, sem prvio conhecimento, o contedo ou disposio da funo WinAPI.
As instrues em C++ aparecem dentro de alguma funo, ou seja, de um grupo de comandos que executa
alguma tarefa, sendo que as funes podem conter instrues que chamam outras funes, bem como
retornar algum valor no seu encerramento para a instruo chamadora.
Criamos a funo AloCy() no exemplo abaixo. Quando o usurio der um clique no boto colocado no
Form, AloCy() ser chamada para imprimir uma mensagem no Label1.

Apostila de C++ Builder

Pagina -101-

//-------------------ilustra o uso de uma funo ---------------------------#include <vcl.h>


#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------void AloCy(); // Prottipo da funo
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AloCy(); // Chama a funo AloCy()
}
//--------------------------------------------------------------------------// Definio da funo AloCy()
void AloCy()
{
Form1 -> Label1 -> Caption = "Al, Cy!!!! \n"
"Como esto todos a em Araatuba???"
"\nEstou com saudades !!!!!";
}

NOTA: Esclarecemos que neste e nos prximos tpicos estaremos trabalhando com funes de uma
maneira que, embora no seja incorreta, no a convencional para o C++Builder. Basicamente
estaremos preocupados em conhecer os fundamentos das funes em C++, sem nos preocupar se essa a
forma ideal de se trabalhar com o BCB.

Chamada de Funes
J tivemos oportunidade de, em tpicos anteriores, verificar que todo programa C++ deve ter uma funo
principal denominada main() ou, conforme o caso, WinMain(), no podendo haver outra funo com
esse mesmo nome, sendo que a execuo do programa sempre ser iniciado por essa funo. As funes
main() e WinMain() so diferentes das outras funes, visto que estas so chamadas aps iniciada e ao
longo da execuo do programa.
Evidente que uma funo, quando chamada, pode tambm chamar a uma outra funo:
//-------------------ilustra chamada de funes----------------------------#include <vcl.h>
#pragma hdrstop

Apostila de C++ Builder

Pagina -102-

#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------void AloCy(); // Prottipo da funo AloCy()
void AloDau(); // Prottipo da funo AloDau()
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AloCy(); // Chama a funo AloCy()
}
//--------------------------------------------------------------------------// Definio da funo AloCy()
void AloCy()
{
Form1 -> Label1 -> Caption = "Al, Cy!!!! \n"
"Como esto todos a em Araatuba???"
"\nEstou com saudades !!!!!";
AloDau(); // Chama AloDau()
return;
}
//-------------------------------------------------------------------------// Definio de AloDau()
void AloDau()
{
// Acrescenta dados no caption de Label1, sem apagar o que j est nele
Form1 -> Label1 -> Caption =
Form1 -> Label1 -> Caption + "\nAlo, Daury!!!!";
return;
}
//-------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
Label1->Caption = ""; // Limpa o caption de Label1
}
//---------------------------------------------------------------------------

Definio de uma funo


A definio de uma funo se d por meio de um cabealho e de um corpo. O cabealho constitudo
pelo tipo retornado, pelo nome da funo, bem como pelos parmetros que a mesma recebe. Os
parmetros so declaraes dos tipos dos valores ou os dados que sero passados para a funo, e sobre
os quais a funo poder operar. Os dados ou valores passados so denominados de argumentos. Por
exemplo, se desejssemos que uma funo efetue uma operao matemtica de diviso de dois nmeros

Apostila de C++ Builder

Pagina -103-

inteiros e nos devolva o resultado que poderia ser valor um ponto flutuante, poderamos ter o cabealho da
definio assim:
float Opera_Divisao( int, int)

J o corpo da funo consiste de uma chave de abertura


{

seguida pelos comandos que executam a tarefa da funo, seguidos pela chave de fechamento
}
Por exemplo:

float Opera_Divisao( int Divsr, int Divdnd)


{
float Result = Divsr / Divdnd;
Return Result;
}

O Exemplo abaixo possui um Button, um Edit e um Label. Preste bastante ateno nos comentrios, pois
eles explicam os cdigos com detalhes:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------/* Prottipo da funo com o tipo retornado,
o nome da funo e o parmetro entre parnteses*/
AnsiString Recb_Pass(AnsiString);
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
/* Cria um texto para Edit1 e um caption para Label1 em tempo de execuo*/
Edit1 -> Text = "Essa string ser passada para"
" a funo Recb_Pass() que a imprimir em Label1";
Label1 -> Caption = "Esta string ser devolvida para Edit1";
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Valor_Devolvido; // declara varivel para receber valor de Recb_Pass()

Apostila de C++ Builder

Pagina -104-

/* recebe valor devolvido pelo comando return de Recb_Pass()*/


Valor_Devolvido =
/*Texto de Edit1 ser passado como parmetro para Recb_Pass()*/
Recb_Pass (Edit1 -> Text);
/*O valor devolvido por Recb_Pass() ser o novo texto de Edit1*/
Edit1 -> Text = Valor_Devolvido;
/*Desabilita Button1 para evitar que valores sejam trocados a cada clique do mouse*/
Button1 -> Enabled = false;
}
//--------------------------------------------------------------------------//Definio de Recb_Pass()
//Recb_Pass() devolver um valor tipo AnsiString
//Recb_Pass() receber AnsiString de Edit1->Text
AnsiString Recb_Pass(AnsiString Valor_Recebido)
{
/*Antes de alterar o caption de Label1, acumula o valor atual na varivel
Valor_a_Devolver para retorn-lo via comando return*/
AnsiString Valor_a_Devolver = Form1 -> Label1 -> Caption;
//Coloca o valor recebido no Caption de Label
Form1 -> Label1 -> Caption = Valor_Recebido;
//Devolve o valor acumulado do caption de Label1
return Valor_a_Devolver;
}

Prottipos de funes
No podemos usar uma funo sem declar-la previamente. Trata-se duma instruo geralmente colocada
no incio do programa ou do arquivo, obrigatoriamente antecedendo a definio e a chamada da funo.
O prottipo informa ao compilador o tipo que a funo retorna, o nome da funo, bem como os
parmetros que ela recebe. Eis um exemplo:
double diametro (int raio);

Esse prottipo est declarando uma funo chamada diametro, que recebe um valor inteiro (a declarao
int dentro dos parnteses: diametro(int raio)) e devolve um valor ponto flutuante (o double que
antecede o nome da funo: double dimetro()). Poderiam ser quaisquer outros tipos.
O prottipo e a definio da funo devem conter o mesmo nome, o mesmo tipo retornado e a mesma lista
de parmetros:
double diametro(int raio); // Prottipo da funo: com ponto e vrgula aps os
parnteses
double diametro(int raio) // Definio da funo: sem ponto e vrgula
{ // chave de abertura do corpa da funo
return raio * 3.14; // nica instruo dessa funo
} // chave de encerramento da funo

Apostila de C++ Builder

Pagina -105-

O nome da varivel passada como parmetro (em nosso exemplo, a inteira raio) facultativo, mas o tipo
obrigatrio. Quanto ao valor de retorno ser um tipo, ou ser void (caso no haja valor de retorno):
void diametro(int raio); // Prottipo da funo

Se nenhum tipo for especificado como valor de retorno, o compilador retornar o tipo int:
O exemplo:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------Experimenta_Tipos(char raio); // Prottipo da funo
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
// o caption de Label1 chama diametro e passa o caracter 'a' como parmetro
/* IMPORTANTE: em qualquer hiptese, na chamada funo no podemos colocar
o tipo de retorno, pois o compilador retornar mensagem de ERRO*/
Label1 -> Caption = /*sem tipo de retorno*/Experimenta_Tipos('a');
}
//--------------------------------------------------------------------------Experimenta_Tipos(char raio) /* Definio da funo sem tipo especificado
para retorno. A funo retornar como sendo int */
{
// 'a' equivale a 97 na tabela ASCII.
return raio * 1000.01;
}

ter como valor de retorno: 97000.


Experimente, nesse mesmo exemplo, colocar como valor de retorno o tipo char. Depois faa o mesmo
como o tipo double. Com essas pequenas pequenas alteraes, voc poder visualizar os diferentes
comportamentos do compilador.
Alm da forma de declarao apresentada (prottipo externo, pois escrito fora e antes das funes),
existe a possibilidade de declararmos o prottipo dentro do corpo de cada funo chamadora (prottipo
interno).

Apostila de C++ Builder

Pagina -106-

Para esses casos, h duas restries:


1. A funo visvel apenas dentro do bloco onde estiver o seu prottipo;
2. devemos declarar o tipo retornado no prottipo (ou void), para que o compilador no interprete o
prottipo como uma chamada funo e, conseqentemente, retorne uma mensagem de erro:

//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)


{
char Experimenta_Tipos(char raio); // Prottipo da funo
Label1 -> Caption = /*sem tipo de retorno*/Experimenta_Tipos('a');
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
char Experimenta_Tipos(char raio); // Prottipo da funo
Label2 -> Caption = /*sem tipo de retorno*/Experimenta_Tipos('a');
}
//---------------------------------------------------------------------------

Variveis locais e globais


J tivemos oportunidade de trabalhar com variveis locais e globais sem, contudo, entrar em detalhes
acerca de suas particularidades.
Comecemos pelas variveis locais. Imaginemos o seguinte bloco de cdigos com as respectivas
mensagens de erro na forma de comentrios:
void __fastcall TForm1::Button1Click(TObject *Sender)
{ // incio do primeiro bloco (bloco externo)
// [C++ Error] Unit1.cpp(20): E2451 Undefined symbol 'a'.
Label1->Caption = a;
{ // incio do segundo bloco (bloco interno)
int a = 10, b = 20;
Label2->Caption = a + b; // Ok. Label2 enxerga as variveis "a" e "b"
// [C++ Error] Unit1.cpp(24): E2451 Undefined symbol 'c'.
Label3->Caption = a + b + c; // Erro. Label3 no enxerga "c"
// [C++ Error] Unit1.cpp(25): E2238 Multiple declaration for 'c'.
int c = 30;
} // fim do bloco interno
//[C++ Error] Unit1.cpp(27): E2451 Undefined symbol 'c'.

Apostila de C++ Builder

Pagina -107-

Label4->Caption = c;
} // fim do bloco externo

Analisemos o cdigo. No exemplo acima visualizamos dois blocos de cdigo: um externo e outro interno.
1 - O componente Label1 no enxerga a varivel porque sua chamada encontra-se antes e fora do bloco da
declarao de a;
2 - no temos qualquer problema com o componente Label2 porque sua chamada se encontra no mesmo
bloco e aps as declaraes das variveis a e b;
3 - Embora a chamada a Label3 se encontre no mesmo bloco, anterior declarao da varivel c.
4 - Label4 no enxerga a varivel c pelo fato de estar fora do bloco onde tal varivel declarada.
Concluso: podemos entender como locais as variveis que se encontram declaradas dentro de
determinado bloco, com a ressalva de que essas variveis so visveis apenas dentro desse bloco e a partir
do local de sua declarao:
J as variveis globais devem ser declaradas antes e fora de qualquer funo, uma vez que elas sero
visveis somente pelas instrues posteriores sua declarao. Logo se voc quiser que uma varivel seja
"vista" por todas as funes de uma determinada Unit, pode declar-la na regio dos include. A seguir
ilustramos um exemplo que demonstra a o relacionamento existente entre as variveis globais e locais:
//--------------------------------------------------------------------------// Unit1.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------int global_1 = 50; // declara e inicializa varivel global
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
/*o cdigo abaixo apresentar um erro, pois
Button1Click no enxerga global_2 */

Apostila de C++ Builder

Pagina -108-

Label1->Caption = global_1 + global_2;


}
//--------------------------------------------------------------------------int global_2; //varivel que ser visvel somente pelas funes abaixo dela
void __fastcall TForm1::Button2Click(TObject *Sender)
{
global_2 = 45; // aqui essa varivel adquire caracterstica de global
int local_de_Button2Click = 12; // varivel local
// no haver erro
Label1->Caption = global_1 + global_2 + local_de_Button2Click;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender)
{
// ERRO: local_de_Button2Click no pode ser visualizada
// pelo evento OnClick de Button3. ELA LOCAL A Button2Click
Label1->Caption = global_1 + global_2 + local_de_Button2Click;
}
//---------------------------------------------------------------------------

Muito importante: as variveis locais so criadas pelo aplicativo cada vez que sua declarao
encontrada pela execuo do programa e so destrudas cada vez que a execuo sai do bloco em que elas
se encontram; j as variveis globais so criadas uma nica vez no incio do programa e destrudas uma
nica vez no encerramento do programa.
O resultado da observao acima que, cada vez que uma varivel local for destruda, se ela for criada
novamente, no ter conservado o valor que possua no momento em que foi destruda. Ser inicializada
novamente com o valor que lhe for atribudo no momento apropriado.
Quanto s variveis globais, seus valores vo sendo alterados durante a execuo do programa, sendo que
cada vez que tal varivel for chamada trar em si o valor resultante da ltima operao em que foi tratada.

A palavra-chave extern
As palavras-chaves extern e static so recursos oferecidos pela linguagem C++ para alterar o
comportamento dos conceitos local e global, abordados no tpico anterior.
A palavra-chave extern pode ser usada para que um arquivo fonte possa usar uma varivel global que se
encontra definida em outro arquivo fonte.

Apostila de C++ Builder

Pagina -109-

O exemplo a seguir trabalha com dois Forms. O primeiro leva um Label e trs Buttons. O segundo leva
um Label e um Button. Declaramos duas variveis inteiras globais no primeiro formulrio (Form1), as
inicializamos e alteramos seus valores conforme o componente que recebe um clique, exibindo o resultado
em Label1. No segundo formulrio (Form2), atravs da palavra-chave extern, manipulamos e exibimos o
resultado, conforme o componente que recebe o clique do mouse:

Unit1.h
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------int a, b;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
a = 1;
b = 2;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)
{
a = 100;
b = 200;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
Label1->Caption = a + b;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender)
{
Form2->ShowModal();
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -110-

Unit2.h
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//--------------------------------------------------------------------------extern int a;
extern int b;
//--------------------------------------------------------------------------__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm2::Label1Click(TObject *Sender)
{
Label1->Caption = a + b;
}
//--------------------------------------------------------------------------void __fastcall TForm2::Button1Click(TObject *Sender)
{
a = 1000;
b = 2000;
}
//---------------------------------------------------------------------------

O recurso extern um modo de trabalhar uma mesma varivel em mais de um arquivo, guardando sempre
o ltimo valor atribudo varivel, no importando em qual arquivo se tenha dado tal atribuio.
Em C++ , extern no mais to necessrio por causa do conceito de namespace, o qual mais facilmente
gerenciado em sistemas grandes. Futuramente abordaremos esse conceito.

A palavra-chave static
As palavra-chave static, usada junto a variveis, possui uma amplitude maior, visto que possui trs
significados distintos. Vejamos cada um deles:
1 - Dentro de um bloco:

Apostila de C++ Builder

Pagina -111-

Como sabemos, as variveis declaradas dentro de um bloco, s existem durante a execuo do bloco.
Quando o bloco acaba, elas so destrudas. Exemplo:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
int numero = 16;
numero+= numero;
Label1->Caption = numero;
}

O exemplo acima sempre exibir o nmero 32 no label. Isto acontece porque cada vez que a funo
chamada, a varivel numero criada com o valor dezesseis, e quando a funo acaba, ela destruda. Se
alterarmos a forma de declarar a varivel, inserindo a palavra-chave static:

void __fastcall TForm1::Label1Click(TObject *Sender)


{
static int numero = 16;
numero+= numero;
Label1->Caption = numero;
}

tudo muda de figura. Declarada deste modo, a varivel numero criada uma nica vez, e no destruda
at o encerramento do programa. Note que ela no poder ser usada fora do bloco onde foi declarada, mas,
exceto por esse fato, essa varivel comporta-se exatamente como uma varivel global. Deste modo, na
primeira vez que chamamos Label1Click(), o label exibe 32; na segunda, 64; na terceira, 128; e assim
por diante... a cada nova chamada, a varivel numero j est l, com o valor deixado na ltima chamada.
2 - Em varivel global.
Em uma varivel global, a palavra static esconde a varivel de acessos atravs de declaraes extern.
Assim se definimos a varivel global numero como:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "Unit2.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------static int numero = 10;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}

Apostila de C++ Builder

Pagina -112-

//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)


{
numero+= numero;
Label1->Caption = numero;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Form2->ShowModal();
}
//---------------------------------------------------------------------------

esta varivel global numero s poder ser usada dentro do fonte em que foi definida.
Uma outra unidade como essa a seguir:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//--------------------------------------------------------------------------extern int numero;
//--------------------------------------------------------------------------__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm2::Label1Click(TObject *Sender)
{
numero+= numero;
Label1->Caption = numero;
}
//---------------------------------------------------------------------------

no apresentar o resultado esperado para extern int numero, provavelmente apresentando alguma
mensagem
de
erro:
[Linker Error] Unresolved external '_numero' referenced from C:\ARQUIVOS DE PROGRAMAS\BORLAND\CBUILDER4\PROJECTS\UNIT2.OBJ.

Esse resultado pode ser desejado para reduzir a interferncias entre equipes de programao.
3) Em uma definio de classe

Apostila de C++ Builder

Pagina -113-

Em uma definio de classe, a palavra static indica que um dado membro compartilhado por todas as
instncias da classe. Esse uso para static em C++ ser abordado no momento oportuno, quando
estivermos estudando as classes.

Parmetros das funes

passando argumentos por valor


Podemos, de modo errado, supor que toda vez que passamos valores na forma de argumentos para outras
funes, estas, ao manipular esses dados, estariam alterando o valor original das mesmas. Observe o
exemplo, onde criamos uma funo para manipular os dados recebidos de ButtonClick():

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------void Impr_Label_1(int a, int b); // Prottipo da funo
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
int a = 10, b = 40; // declara e inicializa duas inteiras
/* imprime os valores de a e b em Label1*/
Label1 -> Caption = "Valor de a = " + String(a) + "\n" +
"Valor de b = " + String(b) + "\n";
Impr_Label_1(a, b); // chama a funo Impr_Label_1 pasando argumentos por valor
/* aps o comando retornar para Button1Click(), imprime novamente o valor local
de a e b no Label, adicionando esta impresso aos valores que j estavem no Label*/
Label1 -> Caption = Label1 -> Caption + "\n" +
"Valor de a aps a chamada a Impr_Label_1() = "
+ String(a) + "\n" +
"Valor de b aps a chamada a Impr_Label_1() = "
+ String(b) + "\n";

Apostila de C++ Builder

Pagina -114-

}
//--------------------------------------------------------------------------void Impr_Label_1(int a, int b)
{
/* A funo Impr_Label_1() recebe dois valores e
cria cpias dessas variveis para operar */
a = 100; // altera o valor da varivel a (cpia) para 100
b = 400; // altera o valor da varivel b (cpia) para 400
/*Imprime o valor das variveis originais e das cpias no label*/
Form1 -> Label1 -> Caption = Form1 -> Label1 -> Caption + "\n" +
"Valor de a em Impr_Label_1() = " + String(a) +
"Valor de b em Impr_Label_1() = " + String(b) +

"\n" +
"\n";

return; // no h valores a retornar


}

Na execuo deste programa. ocorre o seguinte: Quando o usurio d um clique no boto, o valor das
variveis a e b so imprimidos no Label e chamada a funo Impr_Label_1(a, b) que recebe os
valores de a e b como argumentos. Impr_Label_1() cria uma cpia para cada argumento que lhe foi
passado e opera sobre essas cpias, alterando e imprimindo os novos valores no Label. Quando a funo
retorna o controle para a funo chamadora, todas as cpias criadas em Impr_Label_1(a, b) so
destrudas e, ento, ButtonClick() imprime novamente no Label os valores das variveis a e b que, nessa
funo, permanecem inalterados.
Passar argumentos dessa forma, onde a funo cria cpias dos valores transmitidos, d-se o nome de:
passar argumentos por valor.
Podemos, ento, concluir que os valores passados dessa forma a uma funo funcionam como variveis
locais a essa funo.

O comando return
Quando tivermos que retornar um valor de alguma funo, devemos faz-lo atravs do comando return,
seguido do valor a ser retornado:
return altura * largura;

return 412;

Podemos retornar uma expresso, cujo valor deve ser compatvel com o valor retornado por return:
return(ImprLabel_1(int, int));

Apostila de C++ Builder

Pagina -115-

return (i <= 100);

Se no houver valores a retornar, usamos a palavra void indicando a circunstncia:


void Impr_Diam(int raio); // prottipo

O comando return funciona como uma porta de sada da funo. Assim que executado, a expresso que
o segue retornada, sendo desconsideradas todas as instrues posteriores. Contudo, o fato de um
comando return ser encontrado, no significa necessariamente que o mesmo ser executado, pois poder
haver um desvio na linha de execuo do cdigo. Da, podemos ter um ou mais comandos return numa
funo:
if(a > b) return a;
else return b;

Exemplo:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------int Form_Capt(int, int); // prottipo - recebe dois inteiros e devolve um
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
int a = 10, b = 40; //declara e inicializa duas int que sero passadas como
argumentos da funo
Form1->Caption = Form_Capt(a, b); // Chama Form_Capt(), passando a e b como
argumentos
}
//--------------------------------------------------------------------------int Form_Capt(int c, int d)
{
if(c > d)
return c * d;
// retorna c vezes d se c for maior que d
else if(c == d)
return c + d;
// retorna c mais d se c for igual a d
else
return d - c;
// retorna c menos d se c for menor que d
}

Apostila de C++ Builder

Pagina -116-

Valores Default
Conforme vimos, na chamada de uma funo existe a necessidade de fornecermos um argumento que
corresponda a cada parmetro declarado no prottipo e na definio da funo, respeitando-se os tipos que
aparecem no prottipo:
/*double*/ conta (/*int*/ a, /*double*/ b);

Podemos, contudo, estabelecer um valor defaut (padro) para um ou mais parmetros:


/*prottipo*/ double conta ( int raio, double Pi = 3.1416);

Em tais situaes, se na chamada funo no fornecermos um valor, o default ser usado:


conta ( raio); // chamada funo

Se, porm, fornecermos um valor, o default no ser usado:


double Pi = 3.14;
conta (raio, Pi); // chamada funo

No h limites para a quantia de parmetros com valores default. A nica exigncia que os parmetros
com valores default devem ser, sempre, os ltimos na lista de parmetros de uma funo.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------/*prottipo*/ double conta ( int raio, double Pi = 3.1416);
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
double diametro = conta(6);
ShowMessage((String)"O dimetro com o default : " + diametro);
}

Apostila de C++ Builder

Pagina -117-

//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)


{
double diametro = conta(6, 3.14);
ShowMessage((String)"O dimetro sem o default : " + diametro);
}
//--------------------------------------------------------------------------/*definio*/ double conta ( int i, double Pi)
{
return 2*Pi*i;
}

Funes inline
Quando uma funo chamada, a execuo do programa salta para o grupo de instrues constantes dessa
funo na memria. Encerrada a funo, a execuo do programa retorna para a linha de cdigo seguinte
quela que chamou a funo.
Esse trabalho de saltar para o conjunto de instrues onde se encontra definida a funo e depois retornar
para a linha de cdigo seguinte instruo chamadora funo denota um trabalho que ocupa certo
espao em memria, acarretando determinada quantidade de tempo para ser executada.
Para ganhar um pouco de tempo, podemos colocar a palavra-chave inline como primeira palavra do
cabealho da definio de uma funo, para que seja inserida uma cpia da funo em todo lugar onde a
mesma chamada. Contudo esse procedimento s se justifica se a funo chamada for muito pequena
(uma ou duas linhas de instrues), pois nesses casos as instrues necessrias chamada da funo
podem ocupar mais espao na memria do que as instrues do seu prprio cdigo.
Outro cuidado a ser tomado que a definio (e no o prottipo apenas) da funo deve anteceder sua
primeira chamada.
No devemos esquecer que se uma funo inline for chamada muitas vezes, a mesma quantia de vezes
ser realizada uma cpia de seu cdigo no programa, o que poder significar um aumento considervel no
tamanho do executvel.
O exemplo a seguir leva um Label no Form e usado para devolver o valor da rea de um retngulo:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------inline int Area(int a, int b)

Apostila de C++ Builder

Pagina -118-

{
return(a * b);
}
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
int x, y;
x = StrToInt(InputBox("Clculo da rea", "entre com o valor de um lado", ""));
y = StrToInt(InputBox("Clculo da rea", "entre com o valor do outro lado", ""));
Label1->Caption = (String)"rea = " + Area(x, y);
}
//---------------------------------------------------------------------------

O comando goto
A instruo goto formada por duas partes: o comando goto e um rtulo:
goto Erro;

A instruo goto causa um desvio na execuo normal do programa para a instruo seguinte ao rtulo.
Um rtulo um nome (que respeita a conveno para a nomenclatura de variveis) que deve ser colocada
em dois locais: imediatamente aps a instruo goto e, completada por dois pontos, antecedendo a
instruo para a qual o goto desviar a execuo do programa:
Erro:
ShowMessage("Erro... No possvel efetuar diviso por zero...");
// ...
if(Divid / 0)
goto Erro;
// ...

No exemplo, se o usurio tentar efetuar uma diviso por zero, o comando goto remeter a execuo do
programa para " Erro: " que chamar uma caixa de mensagem.
Existem cdigos que possibilitam usar o goto como um lao (loop), mas desaconselhvel, uma vez que
os laos for , while e do... while fazem com muito mais segurana a tarefa.

O loop while
LAOS - Algumas vezes um aplicativo precisa executar operaes repetitivas. A fim de evitar que um
programador tenha de repetir uma diversidade de vezes um mesmo cdigo, criou-se o conceito de loop
(ou lao).

Apostila de C++ Builder

Pagina -119-

Laos so comandos que fazem com que uma ou mais instrues sejam repetidas enquanto determinada
condio no estiver satisfeita.
A linguagem C++ possui trs formas de laos:
for
while
do ... while
Podemos imaginar os laos como uma roda gigante que fica girando at que determinada condio se
verifique. E a cada giro da roda, determinada tarefa realizada. A ocorrncia da ltima tarefa dar-se-ia
com a satisfao da condio.
Quando no possumos prvio conhecimento acerca do nmero de vezes que o corpo de um loop dever
ser executado, o while se mostra como opo mais correta, que, basicamente, far o seguinte: testar uma
condio definida inicialmente; enquanto o comando verificar que a condio continua verdadeira, o
conjunto de instrues contido no corpo do lao continuar sendo executado. No instante em que o
comando verificar um valor de retorno falso para a condio, o processamento ser desviado para fora do
lao.
Voltando ao exemplo da roda gigante, no while no haveria a necessidade de uma catraca contando o
nmero de giros, mas um funcionrio aguardando a ocorrncia de determinado fato para desligar o
aparelho, como, por exemplo, uma pessoa pedir para descer do aparelho.
Se a condio avaliada for falsa logo no incio do loop, o conjunto de instrues ser ignorado e o lao
no ser executado.
Eis a forma do lao while:
while(condio)
corpo_do_loop;

O exemplo a seguir usa um Label no Form. Quando o usurio d um clique no label, inicia-se um loop
onde o comando while ir procurar nove caracteres z, ou Z, em quantas tabelas ASCII forem necessrias,
sendo que essas tabelas sero imprimidas no label. Depois informar o resultado da busca no prprio
label.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"

Apostila de C++ Builder

Pagina -120-

TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Label1->Caption =
"D um clique em mim para iniciar um loop while "
"\nonde sero montadas sucessivas tabelas ASCII "
"\nat encontrar as letras 'z' ou 'Z' nove vezes!";
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
Label1 -> Caption = ""; // Apaga o Caption de Label1
// Declara e inicializa trs variveis para ser incrementadas no loop
int contador = 0;
// varivel que contar o nmero de loops
int paraZ = 0;
// varivel que contar ocorrncias de z e Z
unsigned char caract = 0;
// varivel usada para montar as tabelas ASCII
while( paraZ < 9) // enquanto a varivel paraZ form menor do que 9
{
contador++;
// incrementa contador a cada giro do loop
caract++;
// incrementa caract a cada giro do loop
/* A tabela ASCII vai sendo construda no Caption de Label1 */
Label1->Caption = Label1->Caption + char(caract);
/* Um comando de deciso switch ... case dentro do corpo do loop*/
switch(caract) /* o comando switch ... case avaliar os valores de caract*/
{
/*caso o valor de caract seja 100, 200 ou 256, a tabela ASCII continuar
sendo imprimida na linha de baixo do Label1*/
case 100:
Label1->Caption = Label1->Caption + '\n';
break;
/* o break remete o processamento para fora do comando switch*/
case 200:
Label1->Caption = Label1->Caption + '\n';
break;
case 256:
Label1->Caption = Label1->Caption + '\n';
break;
/*caso o valor de caract seja Z ou z, a varivel paraZ sofre
um incremento e a execuo do programa sai do switch*/
case 'Z':
paraZ++;
break;
case 'z':
paraZ++;
break;
}
// fim do comando switch ... case
}
// fim do loop while
/*o label usar as variveis paraZ e contador para informar os resultados da busca*/
Label1->Caption =
Label1->Caption + "\n\nEncontrei os caracteres "
"\"Z\" e \"z\" " + String(paraZ) + " vezes!";
Label1->Caption =
Label1->Caption + "\n\nPara encontrar esses caracteres, "
"o loop foi executado " + String(contador) + " vezes";
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -121-

O comando goto pode fazer com que a execuo do programa pule para qualquer ponto visvel do cdigo,
e seu uso incorreto ou indiscriminado facilita a introduo de erros. Via de regra, os programadores
evitam usar esse comando, mas existem ocasies em que o mesmo poder ser til.

break e continue
Existem dois comandos que podemos usar no loop while. O comando continue causa uma interrupo na
execuo das instrues, remetendo a execuo para o topo do lao; j o comando break determina a
imediata sada do lao, independentemente de a condio ter sido satisfeita. Ao encontrar a instruo
break, a execuo do programa enviada para primeira instruo aps a chave de fechamento } do corpo
do lao.
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i = 1;
while(i <= 1000)
{
ShowMessage((String)"i igual a " + i++);
if(i <= 5)
continue;
ShowMessage("Agora o corpo todo do lao ser executado, at i ser igual a
10");
if(i == 10)
{
ShowMessage("Agora i igual a 10 e, embora i ainda no seja 1000, "
"vou embora... Adeus...");
break;
}
}
ShowMessage("Se voc est vendo esta mensagem, "
"significa que estamos fora do while");
Close();
}
//---------------------------------------------------------------------------

O loop while sem fim


Podemos inserir uma condio permanentemente verdadeira (igual a 1) para ser testada por um lao
while. Nessas condies, o while ser executado indeterminadamente, num loop sem fim. Essas situaes
carecem de um comando break satisfazendo uma condio de encerramento em algum ponto do lao,
para evitar o travamento da mquina.

Apostila de C++ Builder

Pagina -122-

preciso tomar um cuidado especial sempre que se utilizar laos nos programas, pois qualquer erro de
lgica ou de condio de encerramento poder fazer com que o programa entre em um loop sem fim.
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
int i = 0;
while(1) // tambm poderia ser: while(true)
{
ShowMessage((String)"Mensagem nmero: "+ ++i);
if(i == 10)
break;
}
}
//--------------------------------------------------------------------------

loop while - continuao


A condio avaliada num loop pode ser qualquer expresso vlida em C++, incluindo
expresses construdas com o uso de operadores lgicos &&, ||, ! :
Uma das instrues que compem um bloco de cdigos do corpo de um loop while pode ser
outro lao while. A essa situao denominamos laos while aninhados.
O exemplo a seguir leva um Button e dois Labels no Form. Quando o usurio der um clique no
Button, uma sequncia de loops ser executada, mostrando o resultado final nos Labels:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = "";
Label2->Caption = "";
bool bl = true; // varivel que nos dar uma das formas de encerrar o loop

Apostila de C++ Builder

Pagina -123-

int i = 0; // varivel para avaliao no primeiro loop


int j2 = 0; /* varivel que contar o total de
vezes que o segundo loop executar */
/*enquanto i for menor ou igual a 10 e bl for verdadeira*/
while(i <= 10 && bl == true)
{
i++; // incrementa i (i = i + 1)
/*Label1 exibir o nmero de vezes que o primeiro loop rodar*/
Label1->Caption = Label1-> Caption + " " + i;
int j = 10; // varivel para avaliao no segundo loop
while(j >= 0) /*enquanto j for maior ou igual a zero*/
{
j--; // decrementa j (j = j - 1)
j2++; // incrementa j2
/*Label1 exibir o nmero de vezes que o segundo loop rodar*/
Label2->Caption = Label2->Caption + " " + j2;
}
/*condio para forar o encerramento do loop
antes de a varivel i ser igual a 10*/
if (i >= 4 && j <= 6)
{
bl = false;
}
}
}
//---------------------------------------------------------------------------

O loop do... while


A estrutura do lao do... while muito parecida com a estrutura do lao while. A diferena bsica entre
elas consiste no fato de, enquanto o teste condicional no comando while realizado no incio do loop
(antes das instrues), no lao do... while o teste realizado no fim do loop (aps as instrues).
Dessa forma, o programador garante que pelo menos uma vez as instrues contidas no corpo do lao
sero processadas, mesmo que a condio seja falsa.
eis a sintaxe:
do
{
...
}

Apostila de C++ Builder

Pagina -124-

while(condio)

O exemplo a seguir leva um Button e um Label no Form. Quando o usurio d um clique no Button, uma
mensagem exibida no Label e, aps sete segundos (7000 milisegundos), o programa encerrado.

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
void __fastcall Esperar(int Miliseg);
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = "Aguarde... Aps sete segundos o programa ser fechado";
Esperar(7000); // tempo que o programa aguardar at ser encerrado
Close(); // encerra o programa
}
//--------------------------------------------------------------------------void __fastcall Esperar (int Miliseg)
{
TDateTime Hora; // declara varivel da classe TDateTime
unsigned short Hor, Min, Seg, Miles; // declara vairiveis
int Tempo;
Hora = Time(); // atribui a hora do sistema varivel Hora
/*todas as instrues abaixo sero executadas ao menos uma vez,
(independente de a condio avaliada ser verdadeira) */
do // incio do loop
{
/*DecodeTime() suspende um objeto TdateTime
em horas, minutos, segundos e milisegundos*/
(Time() - Hora).DecodeTime (&Hor, &Min, &Seg, &Miles);
/*incrementa a varivel Tempo*/
Tempo = (Min * 60000) + (Seg * 1000) + Miles;
/*interrompe a execuo da aplicao possibilitando
ao Windows processar determinadas mensagens*/
Application->ProcessMessages();
}
/* o loop ser executado enquanto Tempo for menor que Miliseg */

Apostila de C++ Builder

Pagina -125-

while (Tempo < Miliseg);


}
//---------------------------------------------------------------------------

O loop for
Retornando idia de que poderamos comparar os laos com uma roda-gigante, o lao for funcionaria do
seguinte modo: O aparelho comearia a girar e cada volta seria registrada num contador (ou catraca).
Quando o aparelho atingisse o nmero de voltas determinado no controlador da catraca (na condio), o
aparelho automaticamente se desligaria.
Isso significa que quando possumos prvio conhecimento acerca do nmero de vezes que um loop dever
ser executado (ver while), a melhor opo ser o lao for.
A sintaxe do for um cabealho onde encontramos o valor inicial, a condio e a atualizao separados
por ponto e vrgula dentro de um par de parnteses, antecedendo o corpo do lao que contm os
comandos da instruo:
for( valor inicial; condio; atualizao)
comando;

Geralmente o valor inicial, tambm conhecido como inicializao, uma instruo de atribuio a uma
varivel (geralmente inteira), que ser executado apenas uma vez no incio do loop.
A condio uma instruo que avaliada sempre que o loop inicia ou reinicia. Se o valor retornado pela
condio for verdadeiro (ver while), as instrues do corpo do lao so executadas; caso contrrio, se
falsa, a execuo do programa sai do loop e vai para a instruo seguinte.
A atualizao contm a instruo de acordo com que a varivel ser alterada cada vez que o loop repetir.
Geralmente a varivel ser incrementada. exemplo:
for(int i = 0; i < 100; i++);

O corpo do loop contm as instrues que sero processadas a cada giro do lao.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include <math.h> // biblioteca para floor
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------/*funo para arredondar casas decimais*/
double Arredonda(double valor, int casas_dec);

Apostila de C++ Builder

Pagina -126-

//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)


: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
/*varivel para receber os nmeros inteiros*/
AnsiString a = InputBox("Caixa de Valores", "Digite um Valor", "");
/*varivel para guardar o nmero de casas decimais*/
AnsiString b = InputBox("Caixa de casas decimais", "Digite as casas decimais", "");
/*chama a funo que arredonda casas decimais, atribuindo o valor retornado a b*/
b = Arredonda(StrToFloat(a), StrToInt(b));
/*exibe o valor retornado, j com as casas decimais arredondadas*/
ShowMessage(b);
}
//--------------------------------------------------------------------------double Arredonda(double valor, int casas_dec)
{
int i = 1;
/* j ser incrementada at o nmero de casas decimais*/
for(int j = 1; j <= casas_dec; j++)
i*= 10; // o mesmo que: i = i * 10;
// floor uma funo matemtica usada para arredondar cifras
return floor(valor * i + 0.5) / i;
}
//---------------------------------------------------------------------------

loop for - continuao


O loop for aceita diversas construes como, por exemplo, conter mais de um valor inicial:
for(int i = 0, j = 100; ...

mltiplas condies:
...; i <= j, j >= i; ...

e processar mltiplas instrues de atualizao:


...; i = i + 3, j = j - 7)

Esses mltiplos comandos so separados entre si por vrgulas e das demais instrues por ponto e vrgula.

Apostila de C++ Builder

Pagina -127-

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
Label1->Caption = "";
int i, j, k;
for(i = 0, j
i <=
i++,

// variveis para o lao for


= 50, k = 100; // inicializa as variveis
10, j <= 100, k >= 0; // estabelece os limites
j=j*2, k--) // alteraes para as variveis

/******************************
NOTA: O EXEMPLO NOS DEIXA CLARO QUE O LIMITE A SER OBEDECIDO PELO LOOP
SER O LIMITE MAIOR. OU SEJA, EMBORA A VARIVEL "i" DEVA SER INCREMENTADA
SOMENTE DE "0" AT "10", ELA CONTINUAR SENDO INCREMENTADA AT A VARIVEL "k"
SER SATISFEITA PLENAMENTE O SEU DECREMENTO (DE 100 A 0).
QUANTO VARIVEL "k", NS PROCURAMOS DEMONSTRAR UMA FORMA DE INTERFERIR
EM SUA VARIAO DENTRO DO LAO, ATRAVS DO COMANDO if
******************************/
{
if(j > 900000000) // um novo limite para "j"
j = 53; // "j" agora igual a 53
// as variaes sero demonstradas no Label
Label1-> Caption = (String) Label1->Caption +
" i = " + i + " " + " j = " + j + " " + " k = " + k + '\n';
}
}
//---------------------------------------------------------------------------

Omisso e aninhamento no loop for


Podemos deixar de incluir uma ou mais instrues no cabealho do loop for. Caso isso ocorra, no
podemos nos esquecer de colocar o ponto e vrgula respectivo:
for( ; ; )

Apostila de C++ Builder

Pagina -128-

Dependendo da forma que construmos o lao for, o mesmo poder funcionar como se fosse um loop
while:
//--------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
int i = 1;
for(;i < 10;)
{
ShowMessage((String)"lao for com alguns comandos nulos.
i + "" + " loop");
i++;
}
}

" +

//---------------------------------------------------------------------------

possvel construir um loop for com todos os comandos nulos:


//--------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
int i = 1;
for(;;)
{
if(i<10)
{
ShowMessage((String)"lao for com todos os comandos nulos. " +
i + "" + " loop");
i++;
}
else
break;
}
}
//---------------------------------------------------------------------------

Por incrvel que parea, s vezes podemos colocar instrues que estariam no corpo do loop dentro do
cabealho. Nessas situaes, se o corpo do loop no for usado pelo comando, ser necessrio colocar-se a
instruo de nulo (um ponto e vrgula) no corpo do lao.
//--------------------------------------------------------------------------void __fastcall TForm1::BitBtn1Click(TObject *Sender)
{
for(int i = 1;
i<10;
ShowMessage((String)"lao for com instrues no corpo do lao.
i++ + "" + " loop"));

Apostila de C++ Builder

Pagina -129-

" +

}
//---------------------------------------------------------------------------

loops for aninhados


Os laos for tambm podem ser aninhados (um dentro do outro):
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
StringGrid1->ColCount = 10;
StringGrid1->RowCount = 10;
int coluna, linha, celula;
celula = 0;
for (coluna = 0; coluna < StringGrid1->ColCount; coluna++)
{
for (linha = 0; linha < StringGrid1->RowCount; linha++)
StringGrid1->Cells[coluna][linha] = IntToStr(++celula);
}
}
//---------------------------------------------------------------------------

O comando switch
Existem situaes onde a execuo do programa dever avaliar uma opo entre vrias alternativas. Uma
forma de resolvermos essas situaes, seria atravs de vrias estruturas if ... else; outra forma, atravs
do comando switch() ... case.
Em tais situaes, o uso do comando switch() ... case , de longe, o mais apropriado pois o uso de
vrios if ... else pode tornar o cdigo confuso, sujeito a erros e cansativo de depurar.
O comando switch consiste de um cabealho e de um corpo. O cabealho montado com a palavrachave switch seguida de uma expresso (que pode ser uma constante ou uma varivel) entre parnteses:

Apostila de C++ Builder

Pagina -130-

switch (expresso)

aps o parnteses de fechamento, no h ponto e vrgula, seguindo-se imediatamente a abertura do corpo


do comando com a chave {.
O corpo do comando consiste de vrias opes rotulando a palavra-chave case, bem como os comandos
para os quais ser desviado o controle do programa. Via de regra, essas aes contero o comando break,
remetendo o processamento do programa para fora do switch (primeira linha de cdigo aps o comando).
Sempre que o comando no encontrar uma opo para processar nos case, a opo default, caso exista,
ser processada; se, porm, nesses casos, a opo default no existir, a execuo do programa
atravessar o switch sem executar instruo alguma:

case valor_x:

faz_isso;

break;

case valor_y:

faz_isto;

break;

case valor_z:

faz_aquilo;

break;

default:

faz_outra_coisa;

faz_isso_tambm;

O exemplo a seguir leva um Edit no Form. O cdigo est voltado a impedir a entrada de caracteres no
numricos no Text do Edit.

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------bool virgula = true;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Edit1KeyPress(TObject *Sender, char &Key)
{
if (virgula == false)
DecimalSeparator = '\0';

Apostila de C++ Builder

Pagina -131-

//if(Edit1->Text.Length() != DecimalSeparator)
//virgula = true;
switch(Key)
{
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
case '.':
case ',':
case 13:
case 8:
default:
}

Key
Key
Key
Key
Key
Key
Key
Key
Key
Key
Key
Key
Key
Key
Key

=
=
=
=
=
=
=
=
=
=
=
=
=
=
=

'1';
break;
'2';
break;
'3';
break;
'4';
break;
'5';
break;
'6';
break;
'7';
break;
'8';
break;
'9';
break;
'0';
break;
DecimalSeparator;
DecimalSeparator;
13;
break;
8;
break;
'\0';

virgula = false;
virgula = false;

break;
break;

}
//---------------------------------------------------------------------------

Entendendo o evento OnMouseMove


Um evento OnMouseMove ocorre periodicamente quando o usurio move o mouse. O evento inicia-se
no objeto que est sob o ponteiro do mouse quando o usurio pressiona o boto. Isto permite ao usurio
algumas opes intermedirias enquanto o mouse move. Observe, porm, que podemos chamar esse
evento mesmo sem que qualquer boto esteja pressionado.
Para responder aos movimentos do mouse, defina um evento handler para o evento OnMouseMove.
Num Form vazio, selecione a guia Events do Object Inspector. No setor esquerdo das opes dessa
guia, procure pelo evento OnMouseMove. D um duplo clique no campo situado ao lado direito desse
evento para abrir a janela de edio de cdigos. Imediatamente voc entrar em contato com as seguintes
linhas de cdigo:
//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
}
//---------------------------------------------------------------------------

J temos conhecimento prvio do significado de vrias partes do cdigo acima. Mas h algumas
novidades: TShiftState Shift, int X, int Y)
Apostila de C++ Builder

Pagina -132-

Primeiramente, vamos entender o significado de do tipo TShiftState Shift.


O tipo TShiftState indica o estado das teclas Alt, Ctrl e Shift, bem como dos botes do mouse.
typedef Set<Classes__1, ssShift, ssDouble>

TshiftState;

Descrio: O tipo TShiftState usado para eventos de teclado e eventos do mouse para determinar o
estado das teclas Alt, Ctrl e Shift, bem como dos botes do mouse, quando ocorrer um evento. Trata-se
de um grupo de flags que indica o seguinte:
Valor

Significa

ssShift

A tecla Shift est segura em baixo.

ssAlt

A tecla Alt est segura em baixo.

ssCtrl

A tecla Ctrl est segura em baixo.

ssLeft

O boto esquerdo do mouse est seguro em baixo.

ssRight

O boto direito do mouse est seguro em baixo.

ssMiddle

O boto do meio do mouse est seguro em baixo..

ssDouble

O mouse recebeu um duplo clique.

Podemos entender TShiftState como uma espcie de varivel que, automaticamente, nomeada de
Shift pelo C++Builder no evento estudado.
Quanto s duas variveis inteiras nomeadas respectivamente de X e Y ( int X, int Y ) pelo
C++Builder, nada mais so do que os possveis valores para as coordenadas X e Y do Form.
Ento se, por exemplo, inserirmos as seguintes linhas de cdigo no evento acima:
//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
if(Shift.Contains(ssShift) && X == 0 && Y == 0)
Close();
}
//---------------------------------------------------------------------------

No ficar difcil entender que: se a tecla Shift (Shift.Contains(ssShift)) estiver pressionada


enquanto o mouse mover-se sobre as coordenadas 0 e 0 ( X == 0 && Y == 0 ), ou seja, no extremo
esquerdo do topo de Form1, o programa ser encerrado.

Apostila de C++ Builder

Pagina -133-

TCanvas
A classe TCanvas encapsula um dispositivo de contexto Windows na VCL e um dispositivo de pintura
(Qt painter) em CLX, que lida com todo desenho para forms, containers visuais (como panels) e o objeto
printer, em ambas as formas. Usando o objeto canvas, voc no tem dificuldades para alocar pens,
brushes, palettes, e assim por diante todas as alocaes e desalocaes so tratadas por voc.
TCanvas inclui um grande nmero de grficos primitivos, rotinas para desenhar linhas, shapes (figuras),
polygons (polgonos), fonts (fontes), etc para qualquer controle que contm um canvas.
O exemplo abaixo trata um evento atravs do clique de um boto, determinando o desenho de uma linha
desde as coordenadas X = 100 e Y = 100 at as coordenadas X = 200 e Y = 200, bem como a colocao de
um texto, cujo incio dar-se- nessas ltimas coordenadas:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Canvas->Pen->Color = clBlue;
Canvas->MoveTo( 100, 100 );
Canvas->LineTo( 200, 200 );
Canvas->Brush->Color = clBtnFace;
Canvas->Font->Name = "Arial";
Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y,"Este o fim da linha"
);
}

O objeto TCanvas tambm protege voc contra erros grficos comuns Windows, como por exemplo
restaurar dispositivos contexto, pens, brushes, e assim por diante de acordo com os valores que eles
possuiam antes da operao desenho. TCanvas usado em qualquer lugar no C++Builder onde um
desenho seja requerido ou possvel, e faz grficos facilmente.

TCanvas::CopyMode
Especifica como uma imagem grfica copiada sobre a tela.
__property int CopyMode = {read=FCopyMode, write=FCopyMode, default=13369376};
Descrio:
Use CopyMode para afetar o modo como imagens grficas so desenhadas sobre a tela. CopyMode
usado quando copiamos uma imagem de outra tela usando o mtodo CopyRect. O CopyMode tambm
usado por objetos TBitmap para desenhar sobre a tela.

Apostila de C++ Builder

Pagina -134-

Use CopyMode para executar uma variedade de afeitos quando desenhar uma imagem. Consiga efeitos
especiais como fundir imagens e criar partes de um bitmap transparente combinando imagens mltiplas
com diferentes CopyModes.
A tabela seguinte mostra os possveis valores de CopyMode. (trata-se de constantes definidas em
Windows.hpp.)
cmBlackness

Preenche o retngulo de destino na tela com negro.

cmDstInvert

Inverte a imagem na tela e ignora a fonte.

cmMergeCopy

Combina a imagem na tela e a fonte bitmap usando o operador


booleano AND.

cmMergePaint

Combina a fonte invertida bitmap com a imagem na tela usando o


operador booleano OR.

cmNotSrcCopy

Copia a fonte bitmap invertida para a tela.

cmNotSrcErase

Combina a imagem na tela e a fonte bitmap usando o operador


booleano OR, e inverte o resultado.

cmPatCopy

Copia a fonte moldando na tela.

cmPatInvert

Combina a fonte moldando com a imagem na tela usando o


operador booleano XOR.

cmPatPaint

Combina a fonte invertida bitmap com a fonte moldada usando o


operador booleano OR. Combina o resultado dessa operao com a
imagem na tela usando o operador booleano OR.

cmSrcAnd

Combina a imagem na tela e a fonte bitmap usando o operador


booleano AND.

cmSrcCopy

Copia a fonte bitmap na tela.

cmSrcErase

Inverte a imagem na tela e combina o resultado com a fonte bitmap


usando o operador booleano AND.

cmSrcInvert

Combina a imagem na tela e a fonte bitmap usando o operador


booleano XOR.

cmSrcPaint

Combina a imagem na tela e a fonte bitmap usando o operador


booleano OR.

cmWhiteness

Preenche o retngulo de destino na tela com branco.

Apostila de C++ Builder

Pagina -135-

O seguinte exemplo usa CopyMode para deixar branco fora da imagem quando o usurio escolher
Cortar no menu .
void __fastcall TEdtDsnh::Cortar1Click(TObject *Sender)
{
TRect ARect;
// copia a figura para o Clipboard, atravs do mtodo copiar.
Copiar1Click(Sender);
// preenche a seo cortada com branco. CmBlackness determinaria preto
Image1->Canvas->CopyMode = cmWhiteness;
// dimensiona a seo da tela copiada que ser preenchida com branco
ARect = Rect(0, 0, Image1->Width, Image1->Height);
// complementa as duas linhas acima, retirando a figura (cortando)
Image1->Canvas->CopyRect(ARect, Image1->Canvas, ARect);
// restaura o modo default
Image1->Canvas->CopyMode = cmSrcCopy;
}

TRect, Rect, TextRect, Brush e FrameRect


Rect cria uma estrutura TRect para colocar as coordenadas.
Use Rect para criar uma TRect que representa o retngulo segundo as coordenadas especificadas. Use Rect
para construir parmetros para funes que requerem TRect, especialmente para colocar variveis locais
para cada parmetro.
O exemplo a seguir usa um Button no Form que, ao ser clicado, exibe um texto em um retngulo definido
pelas coordenadas (10 e 10) e (300 e 300). Aps exibir o texto por meio do mtodo TextRect, o
cdigo desenha uma linha definida pelo mtodo FrameRect em volta do retngulo.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
// TRect,

Rect,

TextRect,

Brush

FrameRect

TRect ARect;
// coordenadas do retngulo.
//O mesmo que: ARect = Rect(10,10,300,300);
ARect.Top = 10;
ARect.Left = 10;
ARect.Bottom = 300;
ARect.Right = 300;

Apostila de C++ Builder

Pagina -136-

// TCanvas::TextRect - escreve uma string


// dentro de um recorte retangular
// coordenadas do texto: X = 85 e Y = 100
Canvas->TextRect(ARect, 85, 100, "Texto no recorte retangular");
// clicar uma vez deixar a borda ser vermelha;
// duas vezes, toda a rea dentro do retngulo
Canvas->Brush->Color = clRed;
// A funo FrameRect desenha uma borda em torno do retngulo
// especificado, usando o brush especificado. A largura e altura
// da borda ser sempre uma unidade lgica.
Canvas->FrameRect(ARect);
}

CopyRect
A funo CopyRect copia as coordenadas de um retngulo em outro.
BOOL CopyRect(
LPRECT lprcDst, // aponta para a estrutura do retngulo de destino
CONST RECT *lprcSrc // aponta para a estrutura com o retngulo inicial
);

O parmetro lprcDst aponta para a estrutura RECT que recebe as coordenada lgicas do retngulo inicial
e o parmetro lprcSrc aponta para a estrutura RECT qual pertencem as coordenadas que esto sendo
copiadas.
Se a funo lograr xito, produzir um valor de retorno diferente de zero; se fracassar, o valor de retorno
ser zero. Para obter informaes de erro estendidas, use GetLastError.

TCanvas::CopyRect
Copia partes de uma imagem de um a outro canvas.
void __fastcall CopyRect(const Windows::TRect &Dest, TCanvas* Canvas,
const Windows::TRect &Source);

Use CopyRect para transferir parte da imagem de outro canvas para a imagem do objeto TCanvas. Dest
especifica o retngulo no canvas onde a imagem inicial ser copiada. O parmetro Canvas especifica a
tela com a imagem fonte. Source especifica um retngulo que limita a poro de tela fonte que ser
copiada.
A poro da tela inicial copiada usando o modo especificado por CopyMode.

Apostila de C++ Builder

Pagina -137-

O exemplo a seguir ilustra como usufruir a diferena entre CopyRect e BrushCopy. O bitmap grfico
meu_desenho.bmp carregado dentro de Bitmap e exibido no Canvas de Form1. BrushCopy substitui
a cor negra no grfico com o brush de canvas, enquanto CopyRect mantm a cor intacta.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Form1->WindowState = wsMaximized; // amplia a janela
Graphics::TBitmap *Bitmap; // declara Bitmap
TRect ARect, A2Rect; // declara
ARect = Rect(30, 30, 480, 300); // inicializa ARect determinado as coordenadas
A2Rect = Rect(30, 310, 480, 570); // inicializa o retngulo A2Rect
Bitmap = new Graphics::TBitmap; // alocao dinmica de memria para Bitmap
Bitmap->LoadFromFile("c:\\meu_desenho.bmp"); // carrega o arquivo especificado
// BrushCopy carregar o desenho substituindo as cores negras do mesmo
Form1->Canvas->BrushCopy(ARect, Bitmap, ARect, clBlack);
// CopyRect carregar o arquivo sem alter-lo
Form1->Canvas->CopyRect(A2Rect, Bitmap->Canvas, ARect);
// desaloca a memria dinmica
delete Bitmap;
}

mtodos Canvas para desenhar objetos grficos.


Esta seo mostra a forma de usar alguns mtodos comuns para desenhar objetos grficos. Eles envolvem:
desenhar linhas e mltiplas-linhas;
desenhar figuras;
desenhar retngulos arredondados;
desenhar polgonos.
desenhar linhas e mltiplas-linhas
Canvas pode ser usado para desenhar linhas e mltiplas-linhas. uma linha reta pode ser entendido como
uma linha de pixels conectando dois pontos. Mltiplas-linhas pode ser interpretado como uma srie de
linhas retas, conectando cada ponto inicial com o seu ponto final. O canvas desenha todas as linhas
usando pen (caneta).
desenhar figuras

Apostila de C++ Builder

Pagina -138-

Canvas possui mtodos diferentes para desenhar diferentes espcies de figuras. Voc pode usar pen para
desenhar uma figura e brush (pincel) para preencher o interior da figura. A linha que firma a borda da
figuras controlada pelo corrente objetos Pen.
Esta parte envolve:
desenhar retngulos e elipses;
desenhar retngulos arredondados;
desenhar polgonos.
desenhar retngulos e elipses
Para desenhar retngulo ou elipse na tela, chame o mtodo Rectangle ou o mtodo Ellipse, passando as
coordenadas dos limites do retngulo.
O mtodo Rectangle desenha um retngulo; Ellipse desenha uma elipse que toca todos os lados das
coordenadas de um retngulo que lhe fornece os limites.
O seguinte mtodo desenha um retngulo no canto superior esquerdo do form, colocando, depois, uma
elipse no interior do mesmo:
void __fastcall TForm1::FormPaint(TObject *Sender)
{
// ClientWidth especifica a largura da rea do controle em pixels
Canvas->Rectangle(0, 0, ClientWidth/2, ClientHeight/2);
// ClientHeight especifica a altura da rea do controle em pixels
Canvas->Ellipse(0, 0, ClientWidth/2, ClientHeight/2);
}

desenhando retngulos arredondados


Para desenhar um retngulo arredondado na tela, chame o mtodo RoundRect.
Os quatro primeiros parmetros passados para RoundRect referem-se aos limites do retngulo
(coordenadas), da mesma forma que nos mtodos Rectangle ou Ellipse. RoundRect recebe mais dois
parmetros que indicam como desenhar cantos arredondados.
O seguinte mtodo desenha um retngulo arredondado no quadrante superior esquerdo do form,
arredondando os cantos com sees de um crculo de 30 pixels de dimetro:

Apostila de C++ Builder

Pagina -139-

void __fastcall TForm1::FormPaint(TObject *Sender)


{
Canvas->RoundRect(0, 0, ClientWidth/2, ClientHeight/2, 30, 30);
}

desenhando polgonos
Para desenhar polgonos com qualquer nmero de linhas na tela, use o mtodo Polygon de canvas, que
desenha uma srie de linhas na tela conectando os pontos passados, providenciando, por fim, o
fechamento da figura por unir o ltimo ponto com o primeiro.

Polygon recebe um array de pontos como seu nico parmetro e conecta os pontos com pen, at
conectar o ltimo ponto com o primeiro para fechar o polgono. Depois de estipular os limites, Polygon
usa o brush para preencher a parte interior do polgono.
O exemplo a seguir leva um PaintBox no Form. Quando o programa executado, desenha um polgono
irregular no form, cujas coordenadas so especificadas pelo array. Observe que, uma das maneiras pela
qual voc pode alterar o resultado da execuo, variando as possibilidades de acordo com o exposto nos
comentrios.
void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
TPoint ponto[6];
ponto[0] = Point(0,0);
ponto[1] = Point(30,80);
ponto[2] = Point(280,130);
ponto[3] = Point(280,220);
ponto[4] = Point(340,320);
ponto[5] = Point(440,380);
// ((TPaintBox *)Sender)->Canvas->Brush->Color = clBlue; /*opcional*/
((TPaintBox *)Sender)->Canvas->
Polygon(ponto, 5 /*nmero de lados: ou 4, ou 3, ou 2 ...*/);
}

propriedades Canvas
Com o objeto Canvas, voc pode colocar as propriedades de uma pen para desenhar linhas, um brush
para preencher figuras, uma font para escrever um texto, e um array de pixels para representar a imagem.
As prximas sees descrevem:
Usando pens (canetas);
Usando brushes (pincis);
Lendo e inserindo pixels.
Apostila de C++ Builder

Pagina -140-

Usando pens
A propriedade Pen de um controle canvas o meio de fazer linhas aparecerem, incluindo linhas
trabalhadas como linhas de figuras. Desenhar uma linha linha reta alterar um grupo de pixels que esto
entre dois pontos.
De si mesmo, pen possui quatro propriedades que voc pode alterar: Color, Width, Style, e Mode.

Color muda a cor de pen.


Width muda a largura de pen.
Style muda o estilo de pen.
Mode muda a forma de pen.
O valor dessas propriedades determinam como pen pode alterar os pixels numa linha. Por default, cada
pen inicia com cor negra, com largura (width) de 1 pixel, um estilo slido e um modo chamado copy
que escreve qualquer coisa elaboradamente na tela.
Voc pode usar TPenRecall para rapidamente salvar e restaurar as propriedades de pens.

TPen::Color
Color determina a cor usada para desenhar linhas na tela.
__property TColor Color = {read=GetColor, write=SetColor, default=0};

Voc pode usar Color para mudar a cor usada para desenhar linhas ou figuras. O jeito que Color usado
depende das propriedades Mode e Style.
O exemplo a seguir desenha uma infinidade de elipses de vrios estilos, cores e tamanhos (pen e brush)
no form para preencher inteiramente a tela. Para executar o cdigo, coloque um componente TTimer no
form e use o Object Inspector para criar os eventos handlers OnTimer e OnActivate.

//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -141-

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <stdlib.h> // para random() e randomize(): valores aleatrios
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
int x, y;
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormActivate(TObject *Sender)
{
WindowState = wsMaximized; // janela maximizada
Timer1->Interval = 50; // intervalo de tempo para Timer
randomize();
}
//--------------------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
// inicializa variveis com valores aleatrios
x = random(Screen->Width - 10);
y = random(Screen->Height - 10);
// Cor aleatria para pen
Canvas->Pen->Color = (Graphics::TColor) random(65535);
// comando de deciso
switch (random(5))
{
case 0: Canvas->Pen->Style = psSolid; // estilo da linha
Canvas->Brush->Color = clLime; break; // cor da figura: clLime
case 1: Canvas->Pen->Style = psDash;
Canvas->Brush->Color = random(65535); break; // cor aleatria
case 2: Canvas->Pen->Style = psDot;
Canvas->Brush->Color = random(65535); break;
case 3: Canvas->Pen->Style = psDashDot;
Canvas->Brush->Color = random(65535); break;
case 4: Canvas->Pen->Style = psDashDotDot;
Canvas->Brush->Color = clAqua; break;
}
// desenha elpses com tamanhos diversos escolhidos aleatoriamente
Canvas->Ellipse(x, y, x + random(400), y + random(400));
}

Apostila de C++ Builder

Pagina -142-

//---------------------------------------------------------------------------

TPen::Width
Especifica a largura mxima de um pen em pixels.
__property int Width = {read=GetWidth, write=SetWidth, default=1};

Voc pode usar a propriedade Width para dar linha maior ou menor espessura. Se Width for colocado
para um valor menor do que 1, o valor de pen automaticamente ser remetido para 1.
Nota: O valor de Width influencia os possveis valores vlidos de Style.
O exemplo a seguir desenha muitos grupos, geralmente sobrepostos, de retngulos, retngulos
arredondados e elipses de vrios tamanhos e cores em um form maximizado, preenchendo totalmente o
screen:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <stdlib.h> // para random() e randomize(): valores aleatrios
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
int x, y;
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormActivate(TObject *Sender)
{
WindowState = wsMaximized; // janela maximizada
Timer1->Interval = 600; // intervalo de tempo para Timer
randomize();
}
//--------------------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
x = random(Screen->Width - 10);
y = random(Screen->Height - 10);
Canvas->Pen->Color = (Graphics::TColor) random(65535);
Canvas->Pen->Width = random(50); // Pen ter largura varivel

Apostila de C++ Builder

Pagina -143-

int Dx = random(400); // variveis para os pixels


int Dy = random(400); // do arredondamento do retngulo
Canvas->Brush->Color = random(65535); // cor aleatria p retngulo arredondado
Canvas->RoundRect(x, y, x + Dx, y + Dy, Dx/2, Dy/2);
Canvas->Brush->Color = random(65535); // cor aleatria para o retngulo
Canvas->Ellipse(x, y, x + random(400), y + random(400));
Canvas->Brush->Color = random(65535); // cor aleatria para a elpse
Canvas->Rectangle(x, y, x + random(400), y + random(400));
}
//---------------------------------------------------------------------------

TPen::Style
Determina o estilo que pen desenha linhas.
enum TPenStyle
{psSolid, psDash, psDot, psDashDot, psDashDotDot, psClear, psInsideFrame};
__property TPenStyle Style = {read=GetStyle, write=SetStyle, default=0};

Voc pode usar Style para escolher entre vrias opes de como desenhar linhas, como por exemplo,
desenhar uma linha pontilhada ou tracejada, ou para omitir a linha que aparece como uma moldura em
torno de uma figura. Eis os possveis valores para Style:

psSolid

Uma linha slida.

psDash

Uma linha composta de uma srie de traos.

psDot

Uma linha feita com uma srie de pontos.

psDashDot

Uma linha construda alternando traos e pontos.

psDashDotDot

Uma linha feita com uma srie de combinaes trao-ponto-ponto.

psClear

Linhas no so desenhadas (usado para omitir a linha em volta de figuras


que traa um desenho usando a atual pen).

psInsideFrame

Uma linha slida, mas que pode usar uma cor diferente se Width maior
do que 1.

Nota: S o estilo psInsideFrame produz cor diferente para adaptar propriedade Color que no est na
tabela de cores. Todos os outros escolhem cores na tabela de cores do Windows.
Nota: estilos pontilhados ou tracejados no esto disponveis quando a propriedade Width diferente de
1.

Apostila de C++ Builder

Pagina -144-

Veja o exemplo do tpico Tpen::Color.

TPen::Mode
Determina como pen desenha linhas na tela.
enum TPenMode
{pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot,
pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge, pmNotMerge, pmMask,
pmNotMask, pmXor, pmNotXor};
__property TPenMode Mode = {read=FMode, write=SetMode, default=4};

Use Mode para determinar como a cor de pen atua sobre a cor sobre o canvas. Os efeitos de Mode esto
descritos na seguinte tabela:

Mode

Cores Pixels

pmBlack

Sempre negro.

pmWhite

Sempre branco.

pmNop

Imutvel.

pmNot

Inverso cor de canvas background.

pmCopy

Cor de Pen especificada na propriedade Color.

pmNotCopy

Inverso da cor de pen.

pmMergePenNot

Combinao da cor de pen e o inverso de canvas background.

pmMaskPenNot

Combinao de cores comuns para ambos, pen e inverso de canvas


background.

pmMergeNotPen

Combinao da cor de canvas background e o inverso da cor de pen.

pmMaskNotPen

Combinao de cores comuns para ambos, canvas background e o inverso


de pen.

pmMerge

Combinao da cor de pen e da cor de canvas background.

Apostila de C++ Builder

Pagina -145-

Mode

Cores Pixels

pmNotMerge

Inverso de pmMerge: combinao da cor de pen e cor de canvas


background.

pmMask

Combinao de cores comuns em ambos, pen e canvas background

pmNotMask

Inverso de pmMask: combinao de cores comuns em ambos, pen e


canvas background

pmXor

Combinao de cores em um ou em outro (pen ou canvas background),


mas no em ambos.

pmNotXor

Inverso de pmXor: combinao de cores em um ou outro (pen ou canvas


background), mas no juntos.

TPenRecall
TPenRecall salva e restaura as propriedades de um objeto TPen.
Use TPenRecall para armazenar o estado atual de um objeto TPen. Ento voc estar livre para mudar
esse estado atual armazenado do objeto pen. Para restaurar o objeto pen para o seu estado original
armazenado, basta destruir o objeto TPenRecall o que far com que o objeto pen seja automaticamente
restaurado para as propriedades e valores salvos.
Voc pode atualizar a instncia TPenRecall para refletir as propriedades atuais do objeto TPen chamando
o mtodo Store. Voc pode prevenir a destruio de TPenRecall da atualizao do objeto TPen pela
chamada do mtodo Forget.

Usando brushes
A propriedade Brush de um controle canvas o meio pelo qual podemos preencher o interior de reas,
incluindo figuras. Preencher uma rea com um brush , nada mais, do que um meio de alterarmos um
grande nmero de pixels na rea especificada, ou seja, um pincel.

Brush possui trs propriedades que podemos manipular:


Color Muda a cor de preenchimento.
Style muda o estilo de brush.
Bitmap usa um bitmap como um modelo para brush.
Apostila de C++ Builder

Pagina -146-

O valor dessas propriedades determina o jeito que o canvas preenche figuras ou outras reas. Por default,
qualquer brush inicia branco, com um estilo slido e modelo no bitmap.
Voc pode usar TBrushRecall para rapidamente salvar e restaurar as propriedades de brushes.

Tcanvas::Brush
Determina a cor e o padro de preenchimento para figuras grficas e backgrounds.
__property TBrush* Brush = {read=FBrush, write=SetBrush};

Use a propriedade Brush para especificar a cor e o padro quando desenhar o background ou preencher
em figuras grficas. O valor de Brush est num objeto TBrush. Use as propriedades do objeto TBrush
para especificar a cor e o modelo ou bitmap quando preencher espaos no canvas.
Nota: Fixando a propriedade Brush nomeie o objeto TBrush especificado, no lugar de substituir o objeto
TBrush atual.
O cdigo a seguir carrega um bitmap desde um arquivo, destinando-o ao Brush do Canvas de Form1:
Graphics::TBitmap *BrushBmp = new Graphics::TBitmap;
try
{
BrushBmp->LoadFromFile("C:\meu_desenho.bmp");
Form1->Canvas->Brush->Bitmap = BrushBmp;
Form1->Canvas->FillRect(Rect(0,0,100,100));
}
__finally
{
Form1->Canvas->Brush->Bitmap = NULL;
delete BrushBmp;
}

TCanvas::FillRect
Preenche o retngulo especificado no canvas usando o brush atual.
void __fastcall FillRect(const Windows::TRect &Rect);

Use FillRect para preencher uma regio retangular usando o pincel atual. A regio preenchida inicia-se
com as coordenadas do topo esquerdo do retngulo at as coordenadas da base direita do mesmo.

Apostila de C++ Builder

Pagina -147-

O exemplo a seguir cria um retngulo no form, preenchendo-o de branco (cor default para Brush), ou
vermelho (se voc remover o smbolo: // ).

void __fastcall TForm1::Button1Click(TObject *Sender)


{
TRect NewRect = Rect(20, 30, 350, 290);
//
Canvas->Brush->Color = clRed;
Canvas->FillRect(NewRect);
}

TBrush::Color
Indica a cor do brush.
__property TColor Color = {read=GetColor, write=SetColor, default=16777215};

A propriedade Color determina a cor de brush. Esta cor usada para traar a forma representada pela
propriedade Style, e no a cor background do brush (a menos que Style seja slido).
Nota: Se o valor da propriedade Style for bsClear, a propriedade Color ignorada. Mais ainda,
qualquer valor marcado para a propriedade Color perdido quando Style marcado para bsClear.
O exemplo a seguir leva um Button e um Image no Form. Quando o usurio clicar o boto, uma elipse
desenhada em Image1 (TImage sobre o form), adotando o estilo bsDiagCross para Brush, ou seja,
linhas cruzadas, as quais sero vermelhas:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TCanvas *pCanvas = Image1->Canvas;
pCanvas->Brush->Color = clRed;
pCanvas->Brush->Style = bsDiagCross;
pCanvas->Ellipse(0, 0, Image1->Width, Image1->Height);
}

TBrush::Style
Especifica a forma para brush.
enum TBrushStyle {bsSolid, bsClear, bsHorizontal, bsVertical, bsFDiagonal,

Apostila de C++ Builder

Pagina -148-

bsBDiagonal, bsCross, bsDiagCross


__property TBrushStyle Style = {read=GetStyle, write=SetStyle, default=0};

A propriedade Style determina a forma pintada por brush, a menos que um valor seja determinado por
Bitmap. Os possveis valores de Style so:

bsSolid

bsCross

bsClear

bsDiagCross

bsBDiagonal

bsHorizontal

bsFDiagonal

bsVertical

O exemplo a seguir demonstra o uso dos possveis valores da propriedade Style de Brush, pintando os
exemplos no Form que redimensionado quando o mesmo recebe um clique do mouse:
//--------------------------------------------------------------------------void __fastcall TForm1::FormClick(TObject *Sender)
{
Form1->Height = 430;
Form1->Width = 410;
TCanvas *pCanvas = Form1->Canvas;
pCanvas->Brush->Color = clBlue;

Apostila de C++ Builder

Pagina -149-

pCanvas->Brush->Style = bsDiagCross;
pCanvas->Ellipse(0, 0, 100, 200);
pCanvas->Brush->Color = clRed;
pCanvas->Brush->Style = bsSolid;
pCanvas->Rectangle(101, 0, 200, 200);
pCanvas->Brush->Color = clYellow;
pCanvas->Brush->Style = bsDiagCross;
pCanvas->RoundRect(201, 0, 300, 200, 50, 90);
pCanvas->Brush->Color = clLime;
pCanvas->Brush->Style = bsBDiagonal;
pCanvas->Ellipse(301, 0, 400, 200);
pCanvas->Brush->Color = clFuchsia;
pCanvas->Brush->Style = bsHorizontal;
pCanvas->Rectangle(0, 200, 100, 400);
pCanvas->Brush->Color = clWhite;
pCanvas->Brush->Style = bsFDiagonal;
pCanvas->RoundRect(101, 200, 200, 400, 90, 50);
pCanvas->Brush->Color = clGreen;
pCanvas->Brush->Style = bsVertical;
pCanvas->Ellipse(201, 200, 300, 400);
pCanvas->Brush->Color = clGreen;
pCanvas->Brush->Style = bsClear;
pCanvas->Rectangle(301, 200, 400, 400);
}
//---------------------------------------------------------------------------

Dica: Coloque a propriedade Style para bsClear para eliminar instabilidade na tela (pisca-pisca) quando
o objeto repintado.

TBrush::Bitmap
Especifica uma imagem bitmap externa que define uma composio para brush.
__property TBitmap* Bitmap = {read=GetBitmap, write=SetBitmap};

Bitmap aponta para um objeto TBitmap que guarda uma imagem bitmap. Se Bitmap no estiver vazio, a
imagem bitmap define a composio para brushs. Se a imagem maior do que oito pixels por oito
pixels, somente a regio do topo esquerdo oito-por-oito usado.

Apostila de C++ Builder

Pagina -150-

Mudar a imagem no afeta brush at que TBitmap seja redefinido para a propriedade Bitmap. Deve-se
liberar o TBitmap depois de finalizado com brush, visto que TBrush no pode faz-lo.
O exemplo a seguir leva um Button no Form. Quando o usurio clicar o boto, um bitmap carregado do
disco e destinado para o Brush do Canvas de Form1. O form totalmente preenchido, mesmo que a
figura tenha um dimensionamento menor. Nesse caso as imagens sero colocadas lado a lado.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap *BrushBmp = new Graphics::TBitmap;
try
{
TRect ARect = Rect(0, 0, Width, Height);
BrushBmp->LoadFromFile("C:\\Meu_desenho.bmp");
Canvas->Brush->Bitmap = BrushBmp;
Canvas->FillRect(ARect);
}
__finally
{
Canvas->Brush->Bitmap = NULL;
delete BrushBmp;
}
}

TBrushRecall
TBrushRecall salva e restaura um objeto TBrush.
Use TBrushRecall para guardar o atual estado de um objeto TBrush. Voc ento est livre para mudar o
estado atual do objeto brush. Para restaurar o objeto brush ao seu estado original, basta destruir o objeto
TBrushRecall e o objeto brush automaticamente restaurado para os valores da propriedade salvos.
Voc pode atualizar a instncia TBrushRecall para refletir as propriedades atuais do objeto TBrush pela
chamada do mtodo Store. Voc pode impedir o destruidor de TBrushRecall pela atualizao do objeto
TBrush pela chamada do mtodo Forget.

Ler e inserir pixels


Voc pode reparar que cada tela possui uma propriedade Pixels que representa pontos individuais
coloridos que compem a imagem na tela. Raramente voc precisar acessar Pixels direta ou
individualmente, sendo que eles esto disponveis apenas, por convenincia, para executar pequenas aes
como, por exemplo, buscar ou inserir uma cor.

Apostila de C++ Builder

Pagina -151-

Nota: Manipular pixels individuais muito mais lento do que executar operaes grficas por regies.
No use a propriedade array Pixel para ter acesso a pixels de imagem de um array geral. Para acesso de
alto-desempenho a pixels de imagem, veja a propriedade TBitmap::ScanLine.

TCanvas::Pixels
Especifica as cores dos pixels dentro do atual ClipRect.
__property TColor Pixels[int X][int Y] = {read=GetPixel, write=SetPixel};

Use Pixels para descobrir a cor na superfcie do desenho em uma posio especfica dentro da regio
selecionada. Se a posio estiver fora do retngulo selecionado, a leitura do valor de Pixels retornar -1;
use Pixels para mudar a cor individual de pixels na superfcie do desenho; e use Pixels para detalhar
efeitos em uma imagem. Pixels tambm pode ser usado para determinar a cor que deveria ser usada pelo
mtodo FillRect.
Nem todo contexto de dispositivo suporta a propriedade Pixels. Ler a propriedade Pixels para cada
contexto de dispositivo retorna um valor de -1. Colocar a propriedade Pixels para cada contexto de
dispositivo no realiza ao alguma.
O exemplo a seguir desenha vrias linhas coloridas formando uma moldura, quando o usurio pressiona o
boto.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
for (int i = 10; i <= 300; i++)
{
Canvas->Pixels[i][10] = clRed;
Canvas->Pixels[i][14] = clBlue;
Canvas->Pixels[i][18] = clYellow;
Canvas->Pixels[i][22] = clWhite;
Canvas->Pixels[i][26] = clFuchsia;
Canvas->Pixels[i][30] = clGreen;
Canvas->Pixels[10][i] = clRed;
Canvas->Pixels[14][i] = clBlue;
Canvas->Pixels[18][i] = clYellow;
Canvas->Pixels[22][i] = clWhite;
Canvas->Pixels[26][i] = clFuchsia;
Canvas->Pixels[30][i] = clGreen;
Canvas->Pixels[i][280] = clRed;
Canvas->Pixels[i][284] = clBlue;
Canvas->Pixels[i][288] = clYellow;

Apostila de C++ Builder

Pagina -152-

Canvas->Pixels[i][292] = clWhite;
Canvas->Pixels[i][296] = clFuchsia;
Canvas->Pixels[i][300] = clGreen;
Canvas->Pixels[280][i] = clRed;
Canvas->Pixels[284][i] = clBlue;
Canvas->Pixels[288][i] = clYellow;
Canvas->Pixels[292][i] = clWhite;
Canvas->Pixels[296][i] = clFuchsia;
Canvas->Pixels[300][i] = clGreen;
}
}

Para entender o que cada bloco faz, voc pode tir-lo da execuo, colocando-o entre os smbolos de
comentrio C: /* */

TBitmap::ScanLine
Prov acesso indexado a cada linha de pixels.
__property void * ScanLine[int Row] = {read=GetScanline};

ScanLine usado somente com DIBs (Device Independent Bitmaps) para imagens que so editadas em
ferramentas que fazem trabalhos de pixels de baixo nvel.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
// Este exemplo mostra edio diretamente no Bitmap
Byte *ptr;
try
{
pBitmap->LoadFromFile
("C:\\meu_desenho.bmp");
for (int y = 0; y < pBitmap->Height; y++)
{
ptr = (Byte *)pBitmap->ScanLine[y];
for (int x = 0; x < pBitmap->Width; x++)
ptr[x] = (Byte)y;
}
Canvas->Draw(0,0,pBitmap);
}
catch (...)
{
ShowMessage("No foi possvel carregar ou alterar bitmap");
}

Apostila de C++ Builder

Pagina -153-

delete pBitmap;
}

Propriedades e mtodos comuns de Canvas


A tabela a seguir exibe as propriedades do objeto Canvas geralmente usadas.
Propriedades

descries

Font

Especifica a fonte a ser usada quando escrever textos na imagem. Use as propriedades
do objeto TFont para especificar a aparncia da fonte, como cor, tamanho e estilo da
fonte.

Brush

Determina a cor e a forma que Canvas usa para preencher figuras grficas e
backgrounds. Use as propriedades do objeto TBrush para especificar a cor e a forma
ou bitmap em uso quando preencher espaos no canvas.

Pen

Especifica a espcie de caneta que o canvas usa para desenhar linhas e esboar
figuras. Use as propriedade do objeto TPen para especificar a cor, estilo largura e
modo da caneta.

PenPos

Especifica a posio atual de pen.

Pixels

Especifica a cor de pixels da rea dentro do atual ClipRect.

Estas propriedades so descrevidas em maiores detalhes em Using the properties of the Canvas object.
Abaixo a lista de vrios mtodos que voc pode usar:
Mtodos

Descries

Arc

void __fastcall Arc(int X1, int Y1, int X2, int Y2,
int X3, int Y3, int X4, int Y4);

Desenha um arco na imagem ao longo do permetro da elipse limitada pelo


retngulo especificado.
Use Arc para desenhar uma linha encurvada elipticamente com a Pen (caneta)
atual. O arco atravessa o permetro de uma elipse que limitada pelos pontos
(X1,Y1) e (X2,Y2). O arco desenhado seguindo o permetro da elipse, no sentido
anti-horrio ( esquerda), do ponto de partida para o ponto final. O ponto inicial
definido pela interseco da elipse e uma linha definida pelo centro da elipse e
(X3,Y3). O ponto final definido pela interseco da elipse e uma linha definida
pelo centro da elipse e (X4, Y4). Exemplo:
void __fastcall TForm1::FormPaint(TObject *Sender)
{
TRect R = GetClientRect(); // Coordenadas retangulares
// da janela atual

Apostila de C++ Builder

Pagina -154-

Mtodos

Descries
Canvas->Arc(R.Left, R.Top, R.Right, R.Bottom,
R.Right, R.Top, R.Left, R.Top);
}

Chord

void __fastcall Chord(int X1, int Y1, int X2, int Y2,
int X3, int Y3, int X4, int Y4);

Desenha figura fechada representada pela interseco de uma linha e uma elipse.
Use Chord para criar uma forma que definida por um arco e uma linha que une
os pontos finais do arco. A corda (chord) consiste numa poro da elipse que
limitada pelos pontos (X1,Y1) e (X2,Y2). A elipse dividida por uma linha que liga
os pontos (X3,Y3) e (X4,Y4).
O permetro de chord vai da direita (X3, Y3), para a esquerda, ao longo da elipse
para (X4,Y4), e para trs (X3,Y3). Se (X3,Y3) e (X4,Y4) no estiver na superfcie da
elipse, os cantos correspondentes em chord sero os pontos mais ntimos do
permetro que cruza a linha. O desenho da corda (chord) feito usando valores
tirados de Pen, e a figura preenchida usando valores de Brush.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect R = Rect(20, 5, 350, 350);
Canvas->Chord(20, 5, 350, 350, 10, 10, 200, 200);
}

CopyRect

void __fastcall CopyRect(const Windows::TRect &Dest,


TCanvas* Canvas,const Windows::TRect &Source);

Copia parte de uma imagem de um canvas diferente para dentro do Canvas.


Use CopyRect para transferir parte da imagem de outra tela para a imagem do
objeto TCanvas. Dest especifica o retngulo na tela onde a imagem de fonte ser
copiada. O parmetro de Canvas especifica a tela com a imagem fonte. Source
especifica um retngulo que limita a poro da tela fonte que ser copiada.
A poro da tela fonte copiada usando o modo especificado por CopyMode.
Exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap *Bitmap;
TRect Figura_Copiada;
Figura_Copiada = Rect(0,0,300,300);
Bitmap = new Graphics::TBitmap;
Bitmap->LoadFromFile("c:\\indio2.bmp");
Form1->Canvas->CopyRect(Figura_Copiada,
Bitmap->Canvas,
Figura_Copiada);

Apostila de C++ Builder

Pagina -155-

Mtodos

Descries
delete Bitmap;
}

Draw

void __fastcall Draw(int X, int Y, TGraphic* Graphic);

Desenha o objeto grfico especificado pelo parmetro Graphic na tela na


localizao determinada pelas coordenadas (X, Y).
Chame Draw para colocar um grfico na tela. Draw chama o mtodo Draw da
imagem. A imagem desenhada em um retngulo determinado pelo tamanho de
Graphic, com o canto esquerdo superior nos pontos X e Y.
Grficos podem ser bitmaps, cones, ou metafiles. Se o grfico um objeto
TBitmap, o bitmap desenhado usando o valor de CopyMode. Exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap* figura = new Graphics::TBitmap;
figura->LoadFromFile("c:\\meu_desenho.bmp");
Canvas->Draw(10, 10, figura);
delete figura;
}

Ellipse

void __fastcall Ellipse(int X1, int Y1, int X2, int Y2);

Desenha a elipse definida pelos limites de um retngulo na tela.


Use Ellipse para desenhar um crculo ou elipse na tela. O ponto do topo superior
direito do retngulo o pixel representado pelas coordenadas X1 e Y1 e o ponto
inferior direito pelas coordenadas X2 e Y2. Se os pontos do retngulo formam um
quadrado, um crculo desenhado.
A elipse desenhada usando o valor de Pen, e preenchida usando o valor de Brush.
Exemplo:
TCanvas *pCanvas = Canvas;
pCanvas->Brush->Color = clRed;
pCanvas->Brush->Style = bsSolid;
pCanvas->Ellipse(0, 0, Width*2, Height/2);
pCanvas->Brush->Color = clYellow;
pCanvas->Brush->Style = bsVertical;
pCanvas->Ellipse(0, 0, Width, Height);
pCanvas->Brush->Color = clBlue;
pCanvas->Brush->Style = bsHorizontal;
pCanvas->Ellipse(200, 0, Width*2, Height);

FillRect

void __fastcall FillRect(const Windows::TRect &Rect);

Apostila de C++ Builder

Pagina -156-

Mtodos

Descries
Preenche o retngulo especificado na tela usando o brush (pincel) atual.
Use FillRect para preencher uma regio retangular usando o pincel atual. A regio
preenchida inicia-se com as coordenadas do topo esquerdo do retngulo at as
coordenadas da base direita do mesmo. O exemplo a seguir cria um retngulo no
form, preenchendo-o de azul.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect NewRect = Rect(20, 30, 350, 290);
Canvas->FBrush->Color = ClBlue;
Canvas->FillRect(NewRect);
}

FloodFill

enum TFillStyle {fsSurface, fsBorder};


void __fastcall FloodFill(int X, int Y,
TColor Color, TFillStyle FillStyle);

Preenche a rea da tela usando o brush atual.


Use FloodFill para encher uma regio possivelmente no retangular da imagem
com o valor de Brush. Os limites da regio para ser preenchidos so determinados
pelo passar ao lado externo do ponto (X,Y) quando o limite de cor que envolve o
parmetro Color encontrado.
FillStyle determina qual tipo de mudana de cor define os limites, como indicado
na seguinte tabela.
fsSurface Enche toda a rea que tem a cor indicada pelo parmetro Color. Para
quando outra cor encontrada.
fsBorder Enche toda a rea que no tem a cor indicada pelo parmetro Color. Para
quando Color encontrado.
Use a propriedade Pixels para adquirir o valor exato da cor no ponto (X,Y) quando
usar fsSurface de FillStyle. Semelhantemente, quando FillStyle fsBorder, use
Pixels para adquirir o valor exato da cor limite se um ponto no limite conhecido.
void __fastcall TForm1::FormMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
TCanvas *pCanvas = Canvas;
pCanvas->Ellipse(0, 0, 100, 400);
}
//---------------------------------------------------------------void __fastcall TForm1::FormMouseUp(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)

Apostila de C++ Builder

Pagina -157-

Mtodos

Descries
{
Canvas->FloodFill(ClientWidth/2,
fsBorder);
}

FrameRect

ClientHeight/2,

clBlack,

void __fastcall FrameRect(const Windows::TRect &Rect);

Desenha uma borda de retngulo usando o Brush do canvas.


Use FrameRect para desenhar um 1 pixel de borda ao redor de uma regio
retangular. FrameRect no enche o interior do retngulo com o Brush padro.
Para desenhar um limite usando Pen, use o mtodo Polygon.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect ARect;
Canvas->Brush->Color = clFuchsia;
ARect.Top = 10;
ARect.Left = 10;
ARect.Bottom = 200;
ARect.Right = 200;
Canvas->FrameRect(ARect);
}

LineTo

void __fastcall LineTo(int X, int Y);

Desenha uma linha no canvas desde PenPos para o ponto especificado por X e Y,
colocando a posio atual de Pen para (X, Y).
Use LineTo para desenhar uma linha desde PenPos at o ponto X e Y, mas no
incluindo o mesmo. LineTo altera o valor de PenPos para X e Y. A linha
desenhada usando Pen.
void __fastcall TForm1::FormMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
Canvas->LineTo(X, Y);
}

MoveTo

void __fastcall MoveTo(int X, int Y);

Altera, determinado a posio atual do desenho de acordo com as coordenadas X e


Y.
Muda a posio atual do desenho para o ponto X e Y. Use MoveTo para colocar o
valor de PenPos antes de LineTo. Chamar MoveTo equivalente a setar a
propriedade PenPos.

Apostila de C++ Builder

Pagina -158-

Mtodos

Descries
int p_X, p_Y; // Variveis para trabalhar com o ponto (X,Y)
void __fastcall TForm1::FormMouseMove(TObject *Sender,
TShiftState Shift, int X, int Y)
{
// Canvas->FillRect(ClientRect);
Canvas->MoveTo(p_X, p_Y);
Canvas->LineTo(X, Y);
}
//-------------------------------------------------------------void __fastcall TForm1::FormMouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
p_X = X;
p_Y = Y;
}

Pie

void __fastcall Pie(int X1, int Y1, int X2, int Y2,
int X3, int Y3, int X4, int Y4);

Desenha a figura seccionada em direo da elipse como se dela houvera sido


retirada uma fatia (como num bolo redondo). O seccionamento (ou cunha)
determinado por duas linhas que radiam do centro da elipse pelos pontos (X3, Y3) e
(X4, Y4). A cunha desenhada com Pen, e preenchida com Brush. Exemplo:
Canvas->Pie(50, 50, 300, 200, 50, 30, 100, 50);

Polygon

void __fastcall Polygon(const Windows::TPoint * Points,


const int Points_Size);

Desenha uma srie de linhas na tela, ligando os pontos passados e fechando a


figura ao ligar o ltimo ponto ao primeiro ponto.
Use Polygon para desenhar uma figura com vrios lados fechados na tela, usando o
valor de Pen. Depois de completar o desenho da figura, Polygon preenche a figura
usando o valor de Brush. Para desenhar um polgono na tela, sem preench-lo, use
o mtodo Polyline, especificando o primeiro ponto uma segunda vez no fim (aps
o ltimo ponto).
O exemplo a seguir desenha uma estrela de cinco pontas no Form, preenchendo as
pontas da mesma com amarelo:
void __fastcall TForm1::FormPaint(TObject *Sender)
{
TPoint points[5];
points[0] = Point(40,10);
points[1] = Point(20,60);
points[2] = Point(70,30);
points[3] = Point(10,30);
points[4] = Point(60,60);

Apostila de C++ Builder

Pagina -159-

Mtodos

Descries
Canvas->Brush->Color = 0xffff; // Color = clYellow
Canvas->Polygon(points, 4);
}

PolyLine

void __fastcall Polyline(const Windows::TPoint * Points,


const int Points_Size);

Desenha uma srie de linhas na tela com a atual caneta (pen), conectando cada um
dos pontos passados de acordo com Points. Use Polyline para ligar um grupo de
pontos na tela. Se existem apenas dois pontos, Polyline desenha uma linha linha
simples.
Chamando a funo MoveTo com o valor do primeiro ponto, e ento chame LineTo
repetidamente com todos os pontos subseqentes para desenhar uma imagem na
tela. De qualquer forma, diferente de LineTo, Polyline no altera o valor de
PenPos.
O exemplo a seguir, que procura demonstrar sutis diferenas, desenha duas estrelas
com linhas coloridas. Uma estrela no Form e outra num PaintBox:
void __fastcall TForm1::FormPaint(TObject *Sender)
{
TPoint points[6];
Canvas->Pen->Color = 0xff0000; // clBlue
points[0].x = 40;
points[0].y = 10;
points[1].x = 20;
points[1].y = 60;
points[2].x = 70;
points[2].y = 30;
points[3].x = 10;
points[3].y = 30;
points[4].x = 60;
points[4].y = 60;
points[5].x = 40;
points[5].y = 10;
Canvas->Polyline(points,5);
}
//----------------------------------------------------------void __fastcall TForm1::PaintBox1Paint(TObject *Sender)
{
TPaintBox *pPB = (TPaintBox *)Sender;
TPoint points[6];
pPB->Canvas->Pen->Color = clFuchsia; // Color = 0xff00ff;
points[0].x = 40;
points[0].y = 10;
points[1].x = 20;
points[1].y = 60;
points[2].x = 70;

Apostila de C++ Builder

Pagina -160-

Mtodos

Descries
points[2].y = 30;
points[3].x = 10;
points[3].y = 30;
points[4].x = 60;
points[4].y = 60;
points[5].x = 40;
points[5].y = 10;
((TPaintBox *)Sender)->Canvas->Polyline(points,5);
// A linha acima equivalente a:
// pPB->Canvas->Polyline(points,5);
}

Rectangle

void __fastcall Rectangle(int X1, int Y1, int X2, int Y2);

Desenha um retngulo na tela com o canto superior esquerdo no ponto (X1, Y1) e o
canto inferior direito no ponto (X2, Y2). Use Rectangle para desenhar um retngulo
com Pen e preenchendo-o com Brush. Para preencher a regio retangular externa
desenhando a borda no corrente pen, use FillRect. Para desenhar uma rea
retangular externa adicional, use FrameRect ou Polygon. Para desenhar um
retngulo com cantos arredondados, use RoundRect.
O exemplo a seguir desenha muitos retngulos de vrios tamanhos e cores no form
maximizado preenchendo janela. Para executar o exemplo, inclua o cabealho
stdlib.h, coloque um componente TTimer no Form e use o object inspector para
criar o evento OnTimer.
int x, y;
//--------------------------------------------------------void __fastcall TForm1::FormActivate(TObject *Sender)
{
WindowState = wsMaximized;
Canvas->Pen->Width = 20;
Canvas->Pen->Style = psDot;
Timer1->Interval = 50;
randomize();
}
//---------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
x+= 4;
y+=4;
Canvas->Pen->Color = random(65535);
Canvas->Rectangle(x, y, x + random(400), y + random(400));
if(x > 700)
Timer1->Enabled = false;
}

Apostila de C++ Builder

Pagina -161-

Mtodos

Descries

RoundRect

void __fastcall RoundRect(int X1, int Y1, int X2,


int Y2, int X3, int Y3);

Desenha um retngulo na tela com o canto superior esquerdo no ponto (X1, Y1) e o
canto inferior direito no ponto (X2, Y2). Use Rectangle para desenhar um retngulo
com Pen e preenchendo-o com Brush. Para preencher a regio retangular externa
desenhando a borda no corrente pen, use FillRect. Para desenhar uma rea
retangular externa adicional, use FrameRect ou Polygon. Para desenhar um
retngulo com cantos arredondados, use RoundRect.
Este exemplo desenha retngulos de cantos arredondados de vrios tamanhos e
cores no form maximizado preenchendo a janela. Para executar o exemplo,
coloque um componente TTimer no form e use o object inspector para criar o
evento OnTimer.
int x, y;
void __fastcall TForm1::FormActivate(TObject *Sender)
{
WindowState = wsMaximized;
Canvas->Pen->Width = 20;
Canvas->Pen->Style = psInsideFrame;
Timer1->Interval = 100;
randomize();
}
//---------------------------------------------------------------void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
x+=4;
y+=4;
Canvas->Pen->Color = random(65535);
Canvas->RoundRect(x, y, x + random(400), y + random(400),
40, 40);
if(x == 600)
{
x = 400;
y = 4;
}
}

StretchDraw

void __fastcall StretchDraw(const Windows::TRect &Rect,


TGraphic* Graphic);

Desenha o grfico especificado no parmetro Graphic no retngulo especificado


pelo parmetro Rect. Chame StretchDraw para desenhar um grfico na tela de
forma que a imagem encaixe-se no retngulo especificado. StretchDraw chama o
mtodo Draw do grfico. O objeto grfico determina a forma de preenchimento do

Apostila de C++ Builder

Pagina -162-

Mtodos

Descries
retngulo. Isto talvez envolva mudana de tamanho e/ou relao entre altura e
largura.
Para desenhar o grfico em seu tamanho natural, use o mtodo Draw.
Graphics podem ser bitmaps, cones ou metafiles. se o grfico um objeto
TBitmap, o bitmap desenhado usando o valor de CopyMode.
O cdigo a seguir estica o bitmap para preencher a rea cliente de Form1.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Graphics::TBitmap* figura = new Graphics::TBitmap;
figura->LoadFromFile("c:\\Meu_Desenho.bmp");
// Canvas->Draw(10, 10, figura);
Canvas->StretchDraw(ClientRect, figura);
delete figura;
}

TextHeight, int __fastcall TextHeight(const AnsiString Text);


TextWidth
Retorna a altura (height), em pixels, de uma string desenhada na atual font. Use
TextHeight para determinar o height que uma string ocupa na imagem. Outros
elementos na imagem como linha, boxes, ou linhas adicionais de textos podem ser
posicionadas para acomodar o height do texto. TextHeight retorna o mesmo valor
de TextExtent(Text).cy.
Este exemplo exibe o height de um texto string na atual font do canvas num edit
box no form:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
int x = Canvas->TextHeight(" Curso de C++Builder");
Edit1->Text = String(x) + String(" pixels em height");
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int __fastcall TextWidth(const AnsiString Text);

Retorna a largura (width), em pixels, de uma string desenhada na atual font. Use
TextWidth para determinar o comprimento (length) que uma string ocupa numa

Apostila de C++ Builder

Pagina -163-

Mtodos

Descries
imagem. TextWidth indica se determinada string encaixa-se no espao disponvel.
Outros elementos grficos na imagem como linhas, ou strings adicionais podem ser
posicionadas para acomodar a largura (width) do texto.
TextWidth retorna o mesmo valor que TextExtent(Text).cx.
Esse exemplo determina a largura (width) de uma string especificada, e se a string
demasiadamente grande para ser exibida no Edit, o Edit redimensionado para
acomodar a string. A string exibida no edit box.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
long int t;
String str("Tutorial de C++Builder");
t = Canvas->TextWidth(str);
if(t > Edit1->Width)
Edit1->Width = t + 10;
Edit1->Text = str;
}

TextOut

void __fastcall TextOut(int X, int Y, const AnsiString Text);

Escreve uma string na tela, iniciando nos pontos X e Y, e envia o PenPos para o
fim da string. Use TextOut para escrever uma string na tela. A string pode ser
escrita usando a font atual, ou no. Use o mtodo TextExtent para determinar o
espao ocupado pelo texto na imagem. Para escrever somente o texto que ajusta
dentro do retngulo, use TextRect.
Este exemplo exibe uma string na posio especificada no form quando o usurio
clica o boto no form:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Canvas->Brush->Color = clBtnFace;
Canvas->Font->Name = "Courier New";
Canvas->TextOut(20, 100,
"Este curso C++Builder destina-se a facilitar o aprendizado de
C++ ");
}

TextRect

void __fastcall TextRect(const Windows::TRect &Rect,


int X, int Y, const
Text);

Apostila de C++ Builder

Pagina -164-

AnsiString

Mtodos

Descries

Escreve uma string dentro de um retngulo. Use TextRect para escrever uma string
dentro de uma limitada regio retangular. Qualquer poro da string que ultrapasse
o retngulo passado no parmetro cortado e no aparece. O canto superior
esquerdo do texto colocado no ponto (X, Y).
O cdigo a seguir insere u texto num retngulo definido pelas coordenadas (10, 10)
e (100, 100).
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TRect TheRect;
TheRect.Top = 10;
TheRect.Left = 10;
TheRect.Bottom = 40;
TheRect.Right = 100;
Canvas->TextRect
(TheRect, 20, 20, String("Wilson e Milton... bons amigos!!!"));
}

Conhecendo arrays
As palavras matriz, array ou vetor so sinnimos utilizados para um mesmo tipo de dados utilizado na
linguagem C++ para representar uma coleo de variveis do mesmo tipo, referenciadas por um mesmo
nome e identificadas atravs de um ndice numrico.
Essas variveis ficam alocadas seqencialmente na memria, seguindo o sentido da primeira varivel
(ndice 0 - zero, o endereo mais baixo) para a ltima varivel (ndice n - endereo mais alto).
Para declarar uma matriz, devemos escrever um tipo, seguido do nome da matriz, seguidos pelo ndice,
que nada mais do que um nmero, indicando a quantidade de elementos de array, contido entre
colchetes.
A instruo:
char Abcdario[26];

Apostila de C++ Builder

Pagina -165-

declara uma matriz de vinte e seis ([26]) caracteres (char), cujo nome Abcdario. Quando o compilador
se depara com essa declarao, ele reserva vinte e seis bytes (1 byte para cada char), enfileirados
seqencialmente na memria do computador.
O exemplo a seguir usa matrizes para imprimir o abecedrio num Label:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = "";
char Abcdario[26];
for(int i = 0; i < 26; i++)
{
Abcdario[i] = 97 + i;
Label1 -> Caption = (String)Label1 -> Caption +
"Abcdario[" + i + "] = " + Abcdario[i] + '\n';
}
}
//---------------------------------------------------------------------------

As variveis de uma matriz so numeradas a partir do zero (ndice). No exemplo anterior,


char Abcdario[0]

a primeira varivel;

char Abcdario[1] a segunda varivel;


char Abcdario[2]

a terceira varivel;

...
char Abcdario[25]

a ltima varivel;

Para acessar uma varivel determinada de um array, indicamos o nome do array e o ndice; ou seja, o
nmero que est entre colchetes [ ] e indica a posio da mesma na memria.
No exemplo anterior (Abcdario[]), temos que:
Abcdario[0]

= a (1 posio)

Abcdario[1]

= b (2 posio)

Abcdario[2]

= c (3 posio)

Abcdario[3]

= d (4 posio)

Apostila de C++ Builder

Pagina -166-

Abcdario[4]

= e (5 posio)

...
Abcdario[25]

= z (26 posio)

Vamos reescrever o exemplo para acessar apenas um caracter:

//--------------------------------------------------------------------------// reescrito
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char Abcdario[26];
for(int i = 0; i < 26; i++)
{
Abcdario[i] = 97 + i;
Label1 -> Caption = Abcdario[10];
}
}
//---------------------------------------------------------------------------

Agora o programa acessa apenas a 11 varivel, ou seja, a letra k.

Excedendo o limite de um array


Quando uma matriz declarada, o espao necessrio em memria calculado pelo compilador com base
no tipo da varivel, multiplicado pelo ndice: a declarao float Notas[26] faz que o compilador
reserve 104 bytes seqenciais em memria para armazenar as 26 variveis, visto que cada varivel float
ocupa 4 bytes. Logo, 4 * 26 = 104.
A utilizao de arrays traz uma uma responsabilidade a mais para o programador: a de verificar se o
limite da matriz no foi excedido, uma vez que a linguagem C++ no realiza esse tipo de verificao.
No exemplo anterior, se no cdigo houvesse alguma instruo para que fosse escrito algum dado em
Notas[26], o fato de que no existe espao reservado em memria para essa varivel seria ignorado pelo
compilador que implementaria a instruo (lembre-se de que a primeira varivel de vetores inicia-se com
o ndice zero).
Uma vez que os valores do array esto armazenados seqencialmente na memria, o compilador, sem
fazer qualquer verificao, colocar esse elemento imediatamente aps Notas[25] (endereo mais alto do
exemplo).
Teoricamente, qualquer dado, instruo ou comando poder estar ocupando esse endereo, o que poder
produzir um resultado totalmente desastroso.

Apostila de C++ Builder

Pagina -167-

O exemplo a seguir, que


lgica de programao.

pode causar danos ao sistema, procura demonstrar esse tipo de erro na

//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)


{
Label1->Caption = "";
char Abcdario[26];
for(int i = 0; i <= 26; i++)
{
Abcdario[i] = 97 + i;
Label1 -> Caption = (String)Label1 -> Caption +
"Abcdario[" + i + "] = " + Abcdario[i] + '\n';
}
}
//---------------------------------------------------------------------------

Matrizes multidimensionais
At agora, temos visto vetores unidimensionais (pois apresentam apenas uma dimenso):
char Abcdario[26]; // um par de colchetes

Podemos, tambm, ter matrizes com duas ou mais dimenses:


bidimensionais: unsigned char Bid_Vetor[3][4]; // dois pares de colchetes
tridimensionais: int Trid_Array[2][3][2]; // trs pares de colchetes
e assim por diante, cada par de colchetes representa uma dimenso.
Matrizes com mais de uma dimenso significa: os elementos da matriz so outras matrizes.
Considere uma matriz int bidimensional, cujos ndices so [3] e [4]. Vejamos quais seriam as
coordenadas:
| (0 0), (0 1), (0 2), (0 3) |
| (1 0), (1 1), (1 2), (1 3) |
| (2 0), (2 1), (2 2), (2 3) |

Apostila de C++ Builder

Pagina -168-

As coordenadas das linhas localizam-se no lado esquerdo do interior dos parnteses e as coordenadas das
colunas localizam-se no lado direito do interior dos parnteses. Logo, na primeira linha, a coordena
horizontal so os zeros; na segunda, os um; na terceira, os dois. Na primeira coluna, a coordenada vertical
so os zeros; na segundo, os um; na terceira, os dois; e na quarta, os trs.
Ns podemos inicializar as matrizes na mesma instruo onde a declaramos:
char
{ a,
{ e,
{ i,
};

Bid_Array[3][4] = {
b, c, d }
f, g, h }
j, l, m }

No exemplo acima, o caracter 'g' ocupa as coordenadas (1, 2).


Ento, Bid_Array[1][2] == 'g'.
Nas matrizes de trs dimenses, cada elemento uma matriz de duas dimenses:
char
{
{ //
{ a,
{ e,
} //

Trid_Vetor[3][2][4] =
incio do primeiro elemento[0]
b, c, d }, // primeira linha [0]
f, g, h } // segunda linha [1]
fim do primeiro grupo

{ // incio do segundo grupo [1]


{ i, j, k, l }, // primeira linha [0]
{ m, n, o, p } // segunda linha [1]
} // fim do segundo grupo
{ // incio do terceiro grupo [2]
{ q, r, s, t } // primeira linha [0]
{ u, v, x, z } // segunda linha [1]
} // fim do terceiro grupo
}; // fim da matriz

Na declarao char Trid_Vetor[3][2][4], o ndice [3] declara o nmero de grupos; o ndice [2], o
nmero de linha; e i ndice [4], o nmero de colunas.
Logo,
Trid_Vetor[0][0][0]
Trid_Vetor[0][0][1]
Trid_Vetor[0][0][2]
Trid_Vetor[0][0][3]
Trid_Vetor[0][1][0]
Trid_Vetor[0][1][1]
Trid_Vetor[0][1][2]
Trid_Vetor[0][1][3]

==
==
==
==
==
==
==
==

'a'
'b'
'c'
'd'
'e'
'f'
'g'
'h'

e assim sucessivamente...

Apostila de C++ Builder

Pagina -169-

Outra maneira de dizermos:


'a', 'b', 'c', 'd', 'e', 'f', 'g'

e 'h' esto no primeiro grupo;

'i', 'j', 'k', 'l', 'm', 'n', 'o'

e 'p' esto no segundo grupo; e

'q', 'r', 's', 't', 'u', 'v', 'x'

e 'z' esto no terceiro grupo.

'a', 'b', 'c', 'd', i', 'j', 'k', 'l', 'q', 'r', 's'

e 't' esto na primeira linha; e

e', 'f', 'g', 'h', 'm', 'n', 'o', 'p', 'u', 'v', 'x'

e 'z' esto na segunda linha.

'a', 'e', 'i', 'n', 'q', 'u',

esto na primeira coluna;

'b', 'f', 'j', 'n', 'r', 'v',

esto na segunda coluna;

'c', 'g', 'k', 'o', 's', 'x',

esto na terceira coluna; e

'd', 'h', 'l', 'p', 't', 'z',

esto na quarta e ltima coluna.

Para projetar imagens na tela, o computador trabalha com as coordenas X e Y, dentro de uma matriz
bidimensional denominada Pixels. No Windows 98, se voc der um clique com o boto direito do mouse
sobre a rea de trabalho (Desktop) e escolher a opo Propriedades no menu PopUp que aparecer, poder
acessar a aba Configuraes na caixa que se abrir. No campo rea da tela, encontram-se as opes 640
por 480 pixels, 720 por 480 pixels, 800 por 600 pixels, 1024 por 600 pixels e 1024 por 768 pixels.
Basicamente o computador projeta imagens na tela preenchendo-a com pontos coloridos. Por exemplo, a
opo 800 por 600 pixels significa que sero colocados 800 pontos (pixels) na linha horizontal
(coordenada X) por 600 na vertical (coordenada Y). Logo podemos supor que esses pontos esto
localizados dentro da matriz Pixels de tamanho [800] por [600]: Pixels[800][600];
Atravs do exemplo abaixo podemos conhecer cada coordenada do Form, atravs do evento
OnMouseDown, e, de quebra, conhecer uma forma de mudar a cor do Hint atravs de parmetros
passados para RGB():

//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y)
{
ShowHint = true;
Application->HintColor = RGB(X%255, Y%255, (X+Y)%255);
Hint = (String)"Coordenada X = " + X + '\n' + "Coordenada Y = " + Y
+"\n" + "RGB(" + X%255 + ", " + Y%255 + ", " + (Y+X)%255 + ")";
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -170-

Conforme dissemos, essas coordenadas so preenchidas com pontos coloridos que podem ser visualidas e
acessadas. O exemplo a seguir nos possibilita visualizar a cor do pixels que receber o evento mouse
down:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
Form1->Color = clRed;
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
ShowHint = true;
Hint = ColorToString(Form1->Canvas->Pixels[X][Y]);
}
//---------------------------------------------------------------------------

Agora vamos criar uma matriz bi-dimensional que receber o valor do RGB (cor) do local do form onde
ocorrer o evento mouse down:

//--------------------------------------------------------------------------void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,


TShiftState Shift, int X, int Y)
{
Form1->Color = clPurple;
short Ponto[800][600];
Ponto[X][Y] = ColorToRGB(Canvas->Pixels[X][Y]);
Label1->Caption = Ponto[X][Y];
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -171-

Arrays de caracteres
Podemos declarar e inicializar strings (arrays de caracteres) de mesma forma que fazemos com outros
tipos de matrizes.
Recapitulando um pouco, podemos entender uma constante caracter como sendo uma letra ou smbolo
colocado entre aspas simples: 'A', 'b', 'c', ']'. Tambm j sabemos que tais dados so armazenados
internamente pelo computador como um nmero inteiro entre 0 e 255.
J uma seqncia de caracteres colocados entre aspas duplas constitui uma constante string, ou constante
de caracteres (no plural):
"Assis e Palmital"
"D. Pedro I deu um grito que eca at hoje!"
"A"
"b"

Essa "cadeia" ordenada de caracteres contm um caracter a mais do que parece ter, pois encerrada com
o caracter nulo '\0'. Por exemplo:
char Nome[8] = "Therbio"; // visualmente Therbio possui apenas sete caracteres

Na memria a estrutura de armazenamento que se forma :


Nome

\0

//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)


{
char Nome[ ] = "Therbio"; // no fornecemos um ndice
Label1 -> Caption = sizeof(Nome);
}
//---------------------------------------------------------------------------

diferente a interpretao que o compilador faz quando encontra um caracter entre aspas simples ou entre
aspas duplas:

Apostila de C++ Builder

Pagina -172-

//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)


{
Label1 -> Caption = "Tamanho de \'A\' = " + String(sizeof('A')) + " byte"
"\nTamanho de \"A\" = " + sizeof("A") + " bytes";
}
//---------------------------------------------------------------------------

Certamente voc j percebeu que a diferena se d em virtude do caracter NULL (nulo) colocado a mais
automaticamente pelo compilador.
Existem outras formas de declarar e inicializar constantes de caracteres:
int i[ ] = {0, 1, 2, 3, 4, 5, 6, 7}; // inteiros no precisam do caracter nulo
char ch[ ] = {'T', 'h', 'e', 'r', 'b', 'i', 'o', '\0'}; // essa no a melhor
forma...
char* ch = "Que saudades do Rio Paran!!!!"; // Ponteiros... logo os entenderemos!!!

Nessas declaraes, [ ] significa "array de" e * significa "ponteiro para".


Obs. A expresso
char ch[3] = "Ola";

incorretamente declara uma matriz de ndice trs e a inicializa com os trs caracteres 'O', 'l' e 'a' sem a
terminao usual com o caracter nulo, '\0'. Embora essa notao, algumas vezes, parea funcionar, deve
ser evitada.
Uma forma sempre prefervel a notao:
char ch[ ] = "Ola";

pois inicializa a matriz com a mesma facilidade e implementa, automaticamente, a terminao usual com
o caracter nulo '\0'.
Se na inicializao fornecermos elementos a menos do que o ndice comporta, o valor 0 ser atribudo
inicialmente para os elementos restantes da matriz:
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
/*O exemplo imprime a string referente ao ms de maro e demonstra o
preenchimento de alguns elementos restantes com 0*/
char nome [12] [10] = {"janeiro", "fevereiro", "maro", "abril", "maio",
"junho", "julho", "agosto", "setembro", "outubro",
"novembro", "dezembro"};

Apostila de C++ Builder

Pagina -173-

Label1 -> Caption =

AnsiString(nome[2][0]) +
AnsiString(nome[2][1]) +
AnsiString(nome[2][2]) +
AnsiString(nome[2][3]) +
AnsiString(nome[2][4]) +
// at aqui, imprime maro
int(nome[2][5]) +
// imprime zero
int(nome[2][6] + 'a') + // imprime 97
int(nome[2][6] + 1) + // imprime 1
int(nome[2][7] - 1); // imprime -1

}
//---------------------------------------------------------------------------

Estruturas
Conforme estudamos, uma matriz consiste num agrupamento de elementos do mesmo tipo, enquanto uma
struct (estrutura) consiste num agrupamento de tipos de dados arbitrrios, denominados membros, sob um
nico novo tipo e nome. Por exemplo:
struct dados
{
AnsiString Nome; // conforme a inicializao, aqui haver um ERRO
char* rua;
int Numero;
String Cidade; // e aqui tambm.
char Estado[3]; // ou ento aqui, se a inicializao for de outro tipo
int Cep;
long Idade;
float Peso;
}; // o ponto-e-vrgula necessrio

define um novo tipo de dados agrupados sob o nome dados, onde podemos anotar alguns dados de alguma
pessoa. Observe que existem itens que requerem diferentes tipos de dados. Enquanto alguns armazenaro
strings (sob suas diversas formas, escolhidas aleatoriamente), outros armazenaro nmeros inteiros e, por
fim, o ltimo, valores numricos que poderiam conter uma frao.
Feito isso, podemos declarar variveis do tipo dados como faramos para declarar outra varivel qualquer:

dados DeLima;

Acessamos os membros individuais atravs do operador . (ponto):


DeLima.Nome = "Therbio";
DeLima.Rua = "Rua Central";
DeLima.Numero = 163;

Podemos inicializar estruturas da mesma forma que inicializamos um array:


struct dados // define uma estrutura
{
char *Nome; // sem problemas

Apostila de C++ Builder

Pagina -174-

char rua[12]; // no esquecer de colocar o ndice


int Numero;
char *Cidade;
char Estado[3];
int Cep;
long Idade;
float Peso;
}; // o ponto-e-vrgula necessrio
// inicializa a estrutura igual a uma matriz
dados DeLima =
{
"Therbio", // essa inicializao no trabalha com AnsiString
"Rua Central",
163,
"Ibirarema", // tambm no trabalha com String
"SP",
7073,
40,
91.6
};
// para imprimir num label, precisamos converter os dados em AnsiString ou String
Label1 -> Caption = AnsiString(DeLima.Nome) + '\n' +
String(DeLima.rua) + '\n' +
AnsiString(DeLima.Numero) + '\n' +
String(DeLima.Cidade) + '\n' +
AnsiString(DeLima.Estado) + '\n' +
AnsiString(DeLima.Cep) + '\n' +
AnsiString(DeLima.Idade) + '\n' +
String(DeLima.Peso);

Porm, esse tipo de inicializao acima tem dificuldade para inicializar dados do tipo AnsiString.
Eis outra forma de inicializar os membros individuais atravs do operador . (ponto):
struct dados // define uma estrutura
{
AnsiString Nome;
char *rua; // sem problemas
int Numero;
char *Cidade; // no trabalha com dados do tipo ch[ ] ou ch[i]
String Estado;
int Cep;
long Idade;
float Peso;
}; // o ponto-e-vrgula necessrio
dados DeLima; // declara varivel do tipo dados
// inicializa as variveis que trabalha com AnsiString e String
DeLima.Nome = "Therbio";
DeLima.rua = "Rua Central";
DeLima.Numero = 163;
DeLima.Cidade = "Ibirarema";
DeLima.Estado = "SP";

Apostila de C++ Builder

Pagina -175-

DeLima.Cep = 07073;
DeLima.Idade = 40;
DeLima.Peso = 91.6;
// ok. Nesse exemplo no precisamos converter pra String ou AnsiString
Label1 -> Caption = DeLima.Nome + '\n' +
DeLima.rua + '\n' +
DeLima.Numero + '\n' +
DeLima.Cidade + '\n' +
DeLima.Estado + '\n' +
DeLima.Cep + '\n' +
DeLima.Idade + '\n' +
DeLima.Peso;

Observao:
Ainda que duas struct possuam os mesmos membros:
struct aluno
{
char* Nome;
int Nota;
float media;
};
struct __aluno
{
char* Nome;
int Nota;
float media;
};

elas sempre sero diferentes tipos de dados entre si. Portanto a declarao:
aluno Paulo;
__aluno Paulo_Jose = Paulo;

far com que o compilador acuse um erro, uma vez que se trata de tipos incompatveis entre si:
[C++ Error] Unit 1.cpp(36): E2034 Cannot convert 'aluno' to '__aluno'.

Ponteiros
Podemos entender um microcomputador como um sistema de cinco unidades de funcionamento: unidade
de entrada (teclado, mouse, drive de CD-ROM, drive de disquetes etc), unidade de sada (impressora,
monitor etc), unidade de memria (memria RAM -escrita e leitura-, memria ROM - leitura), e as
unidades aritmtica e lgica que se encontram agrupadas na CPU (Unidade Central de Processamento, o
processador).
O chip responsvel pelo controle de todo o computador o processador. Outro circuito de extrema
importncia a memria RAM, que podemos imaginar como um grupo de clulas usadas para
Apostila de C++ Builder

Pagina -176-

armazenamento temporrio das instrues e dos dados que so acessados e processados pelo
microprocessador em altssima velocidade. Trata de uma memria voltil pois seus dados perdem-se no
momento em que so desligadas, o que no chega a ser um problema, visto que esses dados, de regra, aps
salvos, ficam guardados em algum disco de armazenamento permanente, como os discos rgidos ou os
disquetes, sendo copiados novamente para a memria na ocasio de seu re-processamento.
A memria RAM constituda por uma imensa seqncia de clulas de armazenamento (localizaes)
com o tamanho de oito bits (um byte) cada, o que permite que cada uma dessas localizaes possa assumir
um entre 256 valores diferentes. Ressalte-se, ainda, que cada clula possui um endereo nico e
inconfundvel, expresso por um valor numrico que define a exata localizao desse byte, bem como que,
apesar do limitado tamanho de cada clula, podemos acessar dois bytes consecutivos (word) ou quatro
bytes consecutivos (doubleword) simultaneamente com um nico endereamento.
Conforme exposto, durante a execuo de um programa, as instrues e os dados processados ficam
armazenados na memria do computador. Cada informao representada por certo grupo de bytes (char
- 1 byte, float - 4 bytes, double - 8 bytes etc) e possui um local determinado na memria, um endereo que
pode ser expressado por um valor hexadecimal. No h necessidade de o programador conhecer o
endereo absoluto de cada dado, pois cabe ao compilador relacionar o nome de cada varivel com sua
posio na memria.
Em muitas ocasies prefervel trabalhar com os endereos das variveis a acess-las pela maneira
convencional. A linguagem C++ dispe do operador unrio & que permite que os ponteiros (do ingls
pointer), um tipo especial de varivel, armazenem o endereo de outras variveis.
Considerando-se o poder que os ponteiros representam na linguagem, a compreenso e o uso correto
desses recursos so fundamentais para a criao de muitos programas em C++.
Podemos citar vrios motivos para isso: so a nica forma de implementar determinadas operaes;
produzem cdigo compacto robusto e eficiente; constituem ferramenta bastante poderosa para
manipulao da informao ou de elementos de arrays; constituem um meio para que as funes possam
realmente modificar os argumentos da funo chamadora; so usados na alocao e desalocao da
memria do sistema; so usados para passar strings de uma funo para outra; podem ser usados no lugar
de arrays, o que proporciona aumento de eficincia.
Mas nem tudo simples na utilizao dos ponteiros. Em primeiro lugar, a sintaxe de ponteiros pode ser
nova para muitos programadores de outras linguagens que esto iniciando seus estudos em C++; e, para
complicar, o uso incorreto ou descuidado dos ponteiros pode causar o travamento imediato do programa,
do sistema ou algo pior, como, por exemplo, a formatao do disco rgido.
Conceitualmente, ponteiro uma varivel que contm o endereo de localizao na memria de outro
objeto. Normalmente, esse endereo a localizao de alguma varivel declarada no programa. Ento
dizemos que o ponteiro aponta para determinada varivel. Logo tambm correto cham-lo de
apontador.

Declarao
Apostila de C++ Builder

Pagina -177-

Quando realizamos operaes com ponteiros, basicamente desejamos conhecer o endereo de uma
varivel e manipular o seu contedo. Para tanto, C++ nos fornece dois operadores especiais, o operador
de endereos & (determina o primeiro byte do bloco ocupado pela varivel) e o operador indireto de
contedos * (retorna o contedo, ou seja, o valor do dado armazenado no endereo apontado).
Como qualquer varivel, os apontadores precisam ser declarados. Ao declar-los, tomemos o cuidado de
observar o tipo do bloco que ser apontado. Por exemplo, se queremos um ponteiro apontando para uma
varivel char (bloco de 1 byte), devemos declar-lo como char; se o queremos apontando para uma
varivel int (bloco de 2 (ou 4) bytes, conforme a mquina), tambm devemos declar-lo como int, e assim
por diante.
A declarao de um ponteiro parecida com a declarao de outra varivel qualquer. Eis a sintaxe:
tipo *nome;
onde tipo o grupo a que pertence a varivel e nome o nome que escolhemos para a varivel. Exemplo:
char *ch;
int *pi;
float *flot;
O operador unrio *, mais conhecido como operador indireto, nos permite acessar o contedo do objeto
apontado; permite, tambm, que o compilador saiba que a varivel guardar um endereo, e no outro
dado qualquer.
Quando declaramos um ponteiro, devemos inicializ-lo com algum "valor" que, de regra, ser o
endereo de alguma varivel. Conforme vimos, C++ dispe do operador de endereo & que permite que
um apontador guarde o endereo da varivel a qual se refere:

tipo *nome = &nome1;


onde nome1 o nome da varivel apontada:
char c;
int p;
float flt;

Apostila de C++ Builder

Pagina -178-

char *ch = &c;


int *pi = &p;
float *flot = &flt;
Para compreendermos melhor, vamos supor que a varivel inteira p seja inicializada com o valor 257 (int
p = 257;) e que esteja localizada no endereo 0065FDF8. Ento, aps a atribuio do ponteiro (int *pi
= &p;), pi estar apontado para o endereo de memria 0065FDF8 e *pi ser igual a p, ou seja, seu
valor ser exatamente os mesmos 257.
Veja as instrues:
int *p, p2;
float* flot, *flot2;
A primeira instruo declara um ponteiro p (para int) e uma varivel p2 do tipo int. J a segunda
instruo declara dois ponteiros (flot e flot2) do tipo float. Observe o operador indireto * determinando
os elementos da lista que sero ponteiros. Observe tambm que os trs ponteiros ainda no foram
inicializados, o que significa que eles apontam para um endereo qualquer da memria do micro. Um
ponteiro, nessas circunstncias, pode acarretar srios problemas. Se no existir nenhum "valor" para
inicializar o ponteiro, devemos inicializ-lo com 0 (zero), o que indicar que o ponteiro no se refere a
nenhum objeto:
tipo *nome = 0;
Vamos escrever um simples programa Console Wizard abordando o tema:

#include <iostream>
#include <conio>
using namespace std;
main()
{
int i = 97;
//varivel int
int *Pi = &i;
//ponteiro para int
int *Pi2 = 0;
//Ponteiro apontando para null
cout << "\n\tConteudo via variavel = " << i;
cout << "\n\tEndereco via variavel = " << &i;
cout << "\n\tConteudo via ponteiro = " << *Pi;
cout << "\n\tEndereco via ponteiro = " << Pi;
cout << "\n\n";
int i2 = 98;
//varivel int
Pi2 = & i2;
//inicializa Pi2 com endereo de i2
cout << "\n\tAgora podemos acessar *Pi2 ... "

Apostila de C++ Builder

Pagina -179-

<< *Pi2 << "\n";


getch();

//exibe o contedo de i2 via ponteiro

Veja um exemplo equivalente no ambiente visual do C++Builder:

//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)


{
int i = 97;
//varivel int
int *Pi = &i;
//ponteiro para int
int *Pi2 = 0;
//Ponteiro apontando para null
Label1 -> Caption = "\tContedo via varivel = " + String(i) +
"\n\tEndereo via varivel = " + IntToHex(int(&i), 8) +
"\n\tContedo via ponteiro = " + *Pi +
"\n\tEndereo via ponteiro = " + IntToHex(int(Pi), 8);
int i2 = 98;
//varivel int
Pi2 = & i2;
//inicializa Pi2 com endereo de i2
Label2 -> Caption = "\tAgora podemos acessar *Pi2 ... " +
String(*Pi2);
//exibe o contedo de i2 via ponteiro
}
//---------------------------------------------------------------------------

O cdigo abaixo exibe o endereo da varivel:


//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
double r = 65;
Label1 -> Caption = IntToHex(int(&r), 8);
}
//---------------------------------------------------------------------------

Os exemplos acima ilustram bem o fato de que toda varivel possui um endereo e de que, mesmo sem
saber o endereo especfico da varivel, podemos armazenar esse endereo em um ponteiro.

A reutilizao de um ponteiro
Uma vez declarado e inicializado, podemos redefinir o contedo de um ponteiro indefinidamente. Basta
atribuirmos um novo endereo para o ponteiro, descartando o endereo anterior (que ser perdido pelo
ponteiro). O exemplo a seguir usa um Label no Form. Conforme o evento do mouse, (down, move ou
up), um ponteiro apontar para variveis diferentes, exibindo os valores respectivos no Label:

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -180-

#pragma package(smart_init)
#pragma resource "*.dfm"
int i_1 = 100; // declara e inicializa varivel int global
int *P_i = 0; // declara e inicializa com 0, ponteiro para int
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1MouseDown(TObject *Sender,
TMouseButton Button, TShiftState Shift, int X, int Y)
{
P_i = &i_1; // atribui o endereo0 de i_1 ao ponteiro P_i
Label1 -> Caption = *P_i; // exibe o contedo da varivel (100) via ponteiro
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1MouseUp(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
int i_2 = 200; // declara e inicializa varivel int local
P_i = &i_2; // atribui o endereo da varivel local ao ponteiro
Label1 -> Caption = *P_i; // exibe o contedo da varivel (200) via ponteiro
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1MouseMove(TObject *Sender, TShiftState Shift,
int X, int Y)
{
int i_3 = 300; // declara e inicializa varivel int local
P_i = &i_3; // atribui o endereo da varivel local ao ponteiro
Label1 -> Caption = *P_i; // exibe o contedo da varivel (300)via ponteiro
}
//---------------------------------------------------------------------------

Ponteiros apontando para outros ponteiros


Como sabemos, um ponteiro pode apontar para qualquer tipo de varivel.
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Alvo = "AnsiString uma varivel ou uma classe?";
AnsiString *Aponta_Alvo = &Alvo;
Edit1 -> Text = *Aponta_Alvo;
}

Ele pode, inclusive apontar para outro ponteiro:

Apostila de C++ Builder

Pagina -181-

//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)


{
char Alvo[ ] = "Alvo[ ] uma matriz ou um ponteiro?"; // logo saberemos
char *Aponta_Alvo = &*Alvo; // igual a: char *Aponta_Alvo = &Alvo[0];
Edit1 -> Text = *Aponta_Alvo; // experimente:
Edit1 -> Text = Aponta_Alvo;
}
//---------------------------------------------------------------------------

A notao acima pode parecer estranha. Ocorre que o nome de um array um ponteiro que aponta para o
primeiro elemento da matriz (conforme explicado em outra seo mais adiante). Logo, usamos essa
caracterstica para montar o exemplo acima, onde um ponteiro aponta para outro ponteiro.
veja um exemplo, usando trs ponteiros:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
char *ch = "testando ponteiros";
char **ch_Ptr = &ch;
char ***Ptr_ch_Ptr = &ch_Ptr;
Label1 -> Caption = "*ch = " + String(*ch) + '\n' + "ch = " + ch + '\n' + '\n' +
"**ch_Ptr = " + **ch_Ptr + '\n' + "*ch_Ptr = " + *ch_Ptr + '\n' + '\n' +
"***Ptr_ch_Ptr = " + ***Ptr_ch_Ptr + '\n' +
"**Ptr_ch_Ptr = " + **Ptr_ch_Ptr;
}
//---------------------------------------------------------------------------

Ponteiros apontando para structs


Diferente do que ocorre com matrizes (das quais podemos acessar seus elementos individuais por meio de
ndices), no podemos usar valores numricos para acessar os membros de uma estrutura com base em sua
ordem. Isso ocorre porque, enquanto todos os elementos de uma matriz so constitudos de um mesmo
tipo de dado, os de uma estrutura podem ser constitudos de dados de tipos diferentes.
Uma vez que cada membro da estrutura possui um nome simblico, podemos us-lo no acesso aos dados,
separado do nome do membro atravs do operador . (ponto - que significa "membro de"):
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
struct Endereco
{
AnsiString Nome;
int idade;

Apostila de C++ Builder

Pagina -182-

}Marta; // outra forma de declarar uma varivel struct


TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender)
{
/*inicializa variveis na criao do Form*/
Marta.Nome = "Marta C. Plaa";
Marta.idade = 36;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
(*Label1).Caption = /*Breve voc entender essa notao*/
Marta.Nome + '\n' + Marta.idade;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Label2Click(TObject *Sender)
{
Marta.Nome = "Marta C. Plaa Alves"; // casou!!!
Marta.idade = 432; // se for varivel, aceita estes novos valores
Label1 -> Caption = "Ser que Marta.Nome e Marta.idade so variveis?";
(*Label2).Caption = Marta.Nome + '\n' + Marta.idade + " meses";
}
//---------------------------------------------------------------------------

A notao de ponteiros para estruturas segue um procedimento semelhante, com duas diferenas:
1 - Substituio do nome da estrutura pelo nome do ponteiro;
2 - Substituio do operador . "membro de" pelo operador -> ("aponta para"), que formado por um hfen
- mais o smbolo "maior que > :
No exemplo anterior, altere o evento OnClick, apenas, de Label2:
void __fastcall TForm1::Label2Click(TObject *Sender)
{
Endereco *PtrNome = &Marta, *PtrIdade = &Marta;
(*Label2).Caption =
PtrNome -> Nome + '\n' +
(*PtrIdade).idade; /* Ops!! Parece que j vi essa notao*/
}

Voc j deve ter entendido. Veja:


Label1 -> Caption igual a (*Label1).Caption, assim como, obviamente, PtrNome -> Nome ser igual a
(*PtrNome).Nome, ento essas notaes tm muito em comum!

Apostila de C++ Builder

Pagina -183-

Por a, podemos perceber a grande importncia que os ponteiros representam na linguagem C++,
especialmente no C++Builder. Voc, mesmo sem conscincia, j tem trabalhado com esses conceitos ora
apresentado, desde os nossos primeiros exemplos. Um completo domnio sobre ponteiros, pode fazer a
diferena para qualquer pessoa que se aventure nesse ramo da programao.

O nome do array
Veja o seguinte trecho de cdigo:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
char Abcdario[26];
for(int i = 0; i < 26; i++)
{
Abcdario[i] = 65 + i;
Label1 -> Caption = Abcdario[0];
}
}

Ao ser executado, o programa imprimir o caracter 'A' no label. Como sabemos, os elementos de um vetor
ficam enfileirados seqencialmente na memria do computador. Supondo que Abcdario[0], o primeiro
elemento da matriz, ocupe a posio 651256 na mmria, Abcdario[1] ocuparia a posio 651257;
Abcdario[2], a posio 651258; Abcdario[3], a posio 651259; Abcdario[4], a posio 65125A; e
assim sucessivamente.
Veja agora o prximo exemplo, usando o nome da matriz, que tambm imprime 'A' no Label:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
char Abcdario[26] = {65, 66, 67, 68, 69}; // A, B, C, D, E - na tabela ASCII
Label1 -> Caption = *Abcdario;
}

Pergunta: Se no colocamos o ndice, porque essa aplicao imprime o caracter 'A' no Label? E porque
usamos a notao de ponteiros?
Resposta: Simplesmente porque o nome de um array representa o seu endereo de memria, sendo que tal
endereo o do elemento que ocupa o ndice 0 (zero) da matriz. Ou, de um modo mais objetivo: o nome
de um array um ponteiro que aponta para o primeiro elemento da matriz.
Raciocine. Se
Label1 -> Caption = Abcdario[0]; // imprime 'A'

equivale a

Apostila de C++ Builder

Pagina -184-

Label1 -> Caption = *Abcdario; // imprime 'A'

ento,
Label1 -> Caption = Abcdario[1]; // imprime 'B'

equivale a
Label1 -> Caption = *(Abcdario + 1); // imprime 'B'

e
Label1 -> Caption = Abcdario[2]; // imprime 'C'

equivale a
Label1 -> Caption = *(Abcdario + 2); // imprime 'C'

e assim por diante.


Considere a seguinte declarao:
void __fastcall TForm1::Label1Click(TObject *Sender)
{
int i = 6;
char Abcdario[26] = {65, 66, 67, 68, 69, 70, 71};
Label1 -> Caption = Abcdario[i]; // imprime 'G'
Label2 -> Caption = *(Abcdario + i); // imprime 'G'
}

do exposto temos que a expresso *(Abcdario + i) sempre ter o mesmo valor de Abcdario[i].
Vamos, agora, montar dois exemplos que imprimem os caracteres 'C', 'D', 'E', 'F' e 'G':
int i = 2; /* cada valor de i determina incios de impresso de diferentes*/
{
char Abcdario[26] = {65, 66, 67, 68, 69, 70, 71};
Label1 -> Caption = Abcdario + i; /* se i = 0, Label1 -> Caption = Abcdario;
*/
} // fim do primeiro exemplo
{
char Abcdario[26] = {65, 66, 67, 68, 69, 70, 71};
Label2 -> Caption = &Abcdario[i];
} // fim do segundo exemplo

Agora temos, tambm, que Abcdario + i equivalente a &Abcdario[i].


Vejamos, agora, um exemplo onde um ponteiro declarado e inicializado apontando para um vetor:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1 -> Caption = "";

Apostila de C++ Builder

Pagina -185-

char Ch[] = "O Osmarino um grande amigo de infncia";


char *ApontCh;
ApontCh = &Ch[0];
for(int i = 0; i < 42; i++)
{
Label1 -> Caption = Label1 -> Caption + *ApontCh;
ApontCh++;
}
}

Quando estudamos arrays de caracteres, aprendemos algumas formas de declarar e inicializar constantes
de caracteres, entre elas:
char* ch = "Que saudades do Rio Paran!!!!"; // Ponteiros... logo os entenderemos!!!

Agora j possumos conceitos suficientes para entende o porqu de tal declarao. Veja um exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
char *ch = "Que saudades do Rio Paran!!!!"; // Ponteiros... logo os entenderemos!!!
Label1 -> Caption = *ch; // imprime: Q
Label2 -> Caption = ch; // imprime: Que saudades do Rio Paran!!!!
Label3 -> Caption = *ch + 1; // imprime: 82
Label4 -> Caption = ch + 1; // imprime: ue saudades do Rio Paran!!!!
Label5 -> Caption = *(ch + 1); // imprime: u
}

Concluso: Na linguagem C++, o relacionamento entre arrays e ponteiros muito grande, a ponto de, sob
muitos aspectos, poderem ser tratados juntos.

Variveis dinmicas
Quando um programa executado, o sistema operacional reserva um espao de memria para o cdigo
(ou instrues do programa) e outro espao para as variveis usadas durante a execuo. Grosso modo,
esses espaos ocupam uma mesma regio, que podemos denominar memria local. Tambm existem
outras zonas de memria, como a pilha, usada, entre outras coisas, para realizar o intercmbio de dados
entre as funes. O resto, a memria que no estiver em uso por nenhum programa, o que se conhece
por memria livre (rea de alocao dinmica, heap ou free store). Quando um programa usa a rea de
alocao dinmica, naturalmente estar usando parte desse resto de memria.
O maior poder esperado na utilizao de ponteiros decorre, justamente, de seu uso junto a esse conceito de
alocao de memria no free store.
C++ dispe de dois operadores para acesso memria dinmica: new e delete.

Apostila de C++ Builder

Pagina -186-

Operador new:
O operador new oferece um meio para alocao de espao na memria livre, de uma forma parecida,
porm muito superior quela alocao oferecida pela funo malloc() da livraria padro da linguagem C.
O operador new precisa, necessariamente, ser suprido com o tipo de dados para o qual est alocando
memria, a fim de que o compilador saiba exatamente quanta memria dever reservar para colocar os
dados no heap. Por exemplo:
new double

aloca 8 bytes, suficientes para conter um double.


O operador new retorna um endereo de memria a ser atribudo a um ponteiro:
double *dbl = new double;

Feito isso, o que acontece que dbl passar a apontar para uma varivel double na rea de alocao
dinmica. Logo, podemos inserir algum valor nessa varivel:
*dbl = 563.9082;
Se a reserva de memria no for bem sucedida, o operador new devolver um ponteiro nulo (NULL).
Sintaxe (para tipos pr-definidos baseado no Help do BCB):
<::> new <placement> type-name <(initializer)>
<::> new <placement> (type-name) <(initializer)>

Na sintaxe acima, os smbolos < > significam que os dados inseridos no so obrigatrios. Ex:
placement. Continuemos:
:: new placement tipo ( inicializador) // char *ch = :: new char ('A');
:: new placement (tipo) (inicializador) // char *ch = new (char) (65);

Parnteses envolvendo o tipo opcional. Os argumentos opcionais podem ser os seguintes:


:: , placement e ( inicializador)
O operador ::, relacionado com a sobrecarga de operadores, executa a verso global de new.
O mesmo se aplica a placement, que pode ser usado para fornecer argumentos adicionais para new. Mas
voc poder usar essa sintaxe somente se voc tiver uma verso sobrecarregada de new que seja
compatvel com os argumentos opcionais.

Apostila de C++ Builder

Pagina -187-

O inicializador, se aparece, usada para assinalar valores iniciais para a memria reservada com new,
mas no pode ser usado com arrays.
Um pedido para uma alocao para um dado no-array usa apropriadamente o operador new(). Qualquer
pedido, porm, para alocao array deve chamar o apropriado operador new[]:
:: new tipo[ ]
Alocao de memria para um objeto no-array feito pelo uso de ::new(). Note que essa alocao
sempre usada para tipos pr-definidos. Ela tambm possvel para sobrecarga de operador de funo
global. De qualquer forma, isso geralmente no aconselhvel.
Nota: Classes de arrays requerem um construtor default.
H uma regra de ouro, quando se usa a rea de alocao dinmica:
"toda memria reservada durante a execuo do programa deve ser liberada antes do encerramento do
programa".
A memria liberada atravs do operador delete.
Vejamos um exemplo:
//--------------------------------------------------------------------------void __fastcall TForm1::Label1Click(TObject *Sender)
{
int *a;
char *b = new char;
float *c = new float (123.4);
struct stPunto {
double e,f;
} *d;
a = new int;
d = new stPunto;
*a = 65;
*b = 65;
d->e = 123.456; d->f = 0.5;
Label1 -> Caption = "a = " + String(*a) + '\n' +
"\nb = " + *b + '\n' +
"\nc = " + *c + '\n' +
"\nd = (" + d->e + "
" + (*d).f + ")";
delete a;
delete b;
delete c;
delete d;
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -188-

No seguir a regra de liberar a memria alocada antes do encerramento do programa uma atitude
extremamente irresponsvel, e na maior parte dos casos acarretar conseqncias desastrosas, tais como:

Tenha muito
cuidado: se um ponteiro
perde uma varivel reservada dinamicamente (perda de memria), esta no poder mais ser liberada.
Exemplo:
void __fastcall
{
int *a;
a = new int; //
*a = 10;
a = new int; //
*a = 20;
delete a; // s

TForm1::Button1Click(TObject *Sender)
varivel dinmica
nova varivel dinmica. Perde-se a anterior
possvel liberar a ltima reserva

Neste exemplo vemos como impossvel liberar a alocao de memria feita em primeiro lugar. Se no
necessitamos mais dela, deveramos t-la liberado antes de reserv-la outra vez, e se ainda necessitamos,
devemos guardar sua posio, por exemplo com outro ponteiro.

Operador delete:
Como sabemos, em C++, devemos desalocar a memria usada por qualquer coisa que tenha sido criada
pelo operador new. Existe uma exceo a essa regra que o filho de um form MDI, criado como filho de
um parent MDI, pois esses objetos sero deletados, automaticamente, pelo sistema quando do
encerramento do programa. Logo, os blocos de memria reservados com o operador new sero vlidos at
que sejam liberados com delete ou, em certos casos, at o fim do programa. Mas sempre aconselhvel
liberar-se a memria reservada com new usando delete.
Sintaxe: ::
<::> delete <cast-expression>
<::> delete [ ] <cast-expression>
delete <array-name> [ ];

Acima adotamos a mesma regra usada na sintaxe de new:

Apostila de C++ Builder

Pagina -189-

::delete expresso //expresso normalmente ser um ponteiro.


:: delete [ ] expresso // delete[] expresso usado para arrays dinamicos

como sabemos, em muitos casos, :: opcional.


Quando se usa o operador delete com um ponteiro nulo, nenhuma ao ser realizada. Essa
caracterstica permite usar o operador delete com ponteiros sem a necessidade de se perguntar antes se
o mesmo nulo.

int *i = new (int) ('\0');


delete i;

Nota: Os operadores new e delete so prprios de C++. Em C, usamos as funes malloc e free para
reservar e liberar memria dinmica. Liberar um ponteiro nulo com free pode provocar conseqncias
desastrosas.
Em tpicos mais avanados abordaremos arrays dinmicos (alocados atravs de new e liberados atravs
de delete).

Mais problemas ... ponteiros soltos


Outra forma de se pedir problemas, tentar reutilizar um ponteiro cujo espao apontado na memria foi
liberado pelo operador delete, sem antes atribuir um novo endereo ou uma nova varivel ao ponteiro:
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
int * i = new int (100); // cria varivel dinmica
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender)
{
Label1 -> Caption = *i; // cdigo implementado na criao de Form1
}

Apostila de C++ Builder

Pagina -190-

//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)


{
/*************deleta a varivel dinmica.
**************Se voc clicar Button1 e ENCERRAR O PROGRAMA
**************sem clicar Button2,
**************ou clicar Button2 antes de clicar Button1,
**************no haver bug
*******************************************************/
delete i;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)
{
/********* SE VOC J DEU UM CLIQUE EM Button1********
*********E CLICAR Button2, O BICHO VAI PEGAR**********/
*i = 200;

/* coloca um novo valor no endereo apontado pelo ponteiro...


... s que, se Button1 foi j clicado, no existir uma varivel no
endereo para receber o novo valor... ento!!!!! */
Label1 -> Caption = *i;
}
//---------------------------------------------------------------------------

O melhor resultado produzido nos meus testes pelo exemplo acima foi o seguinte:

Vamos entender o que aconteceu. A instruo:


int * i = new int (100);

de certa forma, combina vrias instrues numa s, pois, na verdade, cria um ponteiro:

Apostila de C++ Builder

Pagina -191-

int * i

uma varivel:
new int

e atribui um valor a essa varivel:


int (100);

S que essa varivel no possui um nome prprio. Observe que o ponteiro no foi criado por new. O
operador new criou apenas a varivel int inominada. Logo o ponteiro no estar sujeito s regras de
criao e destruio new / delete, visto ter sido criado naturalmente pelo programa, como outro ponteiro
qualquer.
Para melhor compreenso, veja a mesma instruo montada de forma diferente:
int * i; // cria naturalmente um ponteiro
i = new int; // cria varivel dinmica e atribui seu endereo ao ponteiro
*i = 100; // inicializa a varivel, via ponteiro

Podemos acessar e modificar essa varivel inominada atravs do ponteiro * i. Quando chamamos o
operador delete ele destri apenas a varivel criada pelo operador new, desalocando a memria
respectiva. A partir desse momento, o sistema fica livre para colocar qualquer tipo de dado nesse
endereo. O ponteiro, que no foi destrudo pelo operador delete, visto que no foi criado por new,
continua existindo e apontando para o mesmo endereo.
Ento, tentar usar esse ponteiro poder ocasionar o imediato travamento do programa, ou a derrubada de
todo o sistema. Ou pior, o programa poder continuar funcionando normalmente, e s travar
posteriormente, o que tornar bastante difcil a soluo do bug.
Vamos refazer o exemplo, retirando o bug atravs da colocao de uma nova varivel no endereo:
Nota: No exemplo abaixo, primeiro d um clique em Button1, e depois em Button2. E depois, para liberar
a memria, clique novamente em Button1 antes de encerrar o programa.
//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
int * i = new int (100);
TForm1 *Form1;
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -192-

__fastcall TForm1::TForm1(TComponent* Owner)


: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender)
{
Label1 -> Caption =
"valor de i =
" + String(*i) +
"\nendereo =
" + IntToHex(int(&*i), 8);
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
delete i;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)
{
i = new int;
*i = 200;
Label1 -> Caption =
"valor de i =
" + String(*i) +
"\nendereo =
" + IntToHex(int(&*i), 8);
// NO ESQUEA DE DESALOCAR A MEMRIA,
// CLICANDO NOVAMENTE (Button1Click)
// ANTES DE ENCERRAR O PROGRAMA
}
//---------------------------------------------------------------------------

Ao rodar o exemplo, voc observar que o ponteiro continuar apontando sempre para o mesmo endereo
de memria. Poderamos, tambm, retirar o bug fazendo com que o ponteiro apontasse para outro
endereo. Para isso alteraramos apenas o cdigo de Button2Click:
//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)
{
int j = 1000; // essa varivel no foi criada por new
i = &j;
Label1 -> Caption = "valor de i =
" + String(*i) +
"\nendereo =
" + IntToHex(int(&*i), 8);
}
//---------------------------------------------------------------------------

Ponteiros & constantes


Veja algumas declaraes usando const com ponteiros, e tente visualizar as possveis diferenas de
resultados, em virtude da posio do prefixo const:
AnsiString * const Const_Str = &Str; // o ponteiro constante
const int* Const_i = &i; // a varivel constante para *Const_i

Apostila de C++ Builder

Pagina -193-

const double
alterados

* const Const_dbl = &dbl; // Nem Const_i, nem *Const_i podem ser

Vejamos agora um exemplo com respectivos comentrios abordando cada situao:

//--------------------------------------------------------------------------#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//--------------------------------------------------------------------------#pragma package(smart_init)
#pragma resource "*.dfm"
//////////////GRUPO DO PONTEIRO CONSTANTE //////////////////
AnsiString Str =
"Testando Ponteiros e Constantes";
AnsiString Str_1 =
"Um novo endereo no pode ser atribudo"
" a um ponteiro const";
AnsiString * const Const_Str = &Str; // ponteiro const para Str
////////////////////////////////////////////////////////////////////////////////
////////////GRUPO DO DADO APONTADO CONSTANTE //////
int i = 100; // obs. i pode ter seu valor alterado, mas no por *Const_i
int i_1 = 200;
const int *Const_i = &i; // o ponteiro (*Const_i) no consegue alterar i
////////////////////////////////////////////////////////////////////////////////
// PONTEIRO E VARIVEL CONSTANTES VIA PONTEIRO
double dbl = 0.123456789; // dbl varivel, mas no via ponteiro *Const_dbl
double dbl_1 = 9.876543210;
const double * const Const_dbl = &dbl; // Const_dbl e *Const_dbl constantes
////////////////////////////////////////////////////////////////////////////////
TForm1 *Form1;
//--------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//--------------------------------------------------------------------------void __fastcall TForm1::FormCreate(TObject *Sender)
{
// eventos na criao de Form1
Label1 -> Caption = *Const_Str;
Label2 -> Caption = *Const_i;
Label3 -> Caption = *Const_dbl;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)

Apostila de C++ Builder

Pagina -194-

{
// altera a varivel via ponteiro. Ok
*Const_Str = "alterando a varivel via ponteiro - operao permitida.";
Label1 -> Caption = *Const_Str;
Const_i = &i_1; // altera endereo apontado via ponteiro. Ok
Label2 -> Caption =
"Alterando endereo via ponteiro. "
"Operao permitida. *Const_i =
"
+ String() + *Const_i;
Const_i = &i; // volta apontar para a varivel inicial
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button2Click(TObject *Sender)
{
// tenta redirecionar ponteiro const para outra varivel... ERRO!!!!
Const_Str = &Str_1; // [C++ Error] Unit1.cpp(57): E2024 Cannot modify a const object.
Label1 -> Caption = *Const_Str;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button3Click(TObject *Sender)
{
// tenta alterar varivel const para ponteiro ... ERRO!!!!
*Const_i = 400; // [C++ Error] Unit1.cpp(63): E2024 Cannot modify a const object.
Label2 -> Caption = *Const_i;
}
//--------------------------------------------------------------------------void __fastcall TForm1::Button4Click(TObject *Sender)
{// tenta alterar varivel / ponteiro const e redirecionar ponteiro const ... ERRO!!!!
*Const_dbl = 5.43; // [C++ Error] Unit1.cpp(69): E2024 Cannot modify a const object.
Const_dbl = &dbl_1; // [C++ Error] Unit1.cpp(70): E2024 Cannot modify a const object.
Label3 -> Caption = *Const_dbl;
}
//---------------------------------------------------------------------------

Referncias
possvel criar um segundo nome para determinado tipo de dados, ou seja, um "apelido". O nome
original e o "apelido" sero, exatamente, o mesmo dado, ocupando, inclusive, o mesmo endereo. Toda
modificao que implementarmos atravs do "apelido" estar afetando, diretamente, o dado original:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString esposa = "Marta"; // declara e inicializa varivel esposa
AnsiString &ref_esposa = esposa; // cria e inicializa uma referncia para esposa
ref_esposa = "Marta minha esposa!"; // altera varivel esposa atravs do "apelido"
Label1 -> Caption = esposa + '\n' + // imprime esposa (modificada por ref_esposa)
// demonstra que se trata do mesmo dado, atravs do endereo
"Endereo de esposa =
" + IntToHex(int(&esposa), 8) + '\n' +
"Endereo de ref_esposa =
" + IntToHex(int(&ref_esposa), 8);
}
//---------------------------------------------------------------------------

Apostila de C++ Builder

Pagina -195-

Analisando o cdigo, percebemos que uma referncia deve ser criada com o mesmo tipo de dados do dado
alvo (AnsiString, no exemplo) e com o operador & antecedendo o "apelido", bem como ser inicializada
com o nome do dado original (esposa, no exemplo). Outra observao importantssima que referncias
devem ser inicializadas na mesma instruo de sua declarao.
Instrues do tipo:
AnsiString &ref_esposa;
ref_esposa = esposa;

Retornaro uma mensagem de erro, avisando que a referncia deve ser inicializada:
[C++ Error] Unit1.cpp(19): E2304 Reference variable 'ref_esposa' must be initialized.

Reatribuio de uma referncia


Desde minha infncia, tenho um grande amigo chamado Wanderley. Desde que o conheo (trinta anos, ou
mais), o Wanderley tem um apelido: "Churrasco". Esse apelido est to difundido na personalidade do
Wanderley, que uma vez ele me falou que eu seria a nica pessoa que o chamava pelo nome verdadeiro.
Todas as outras pessoas tratavam-no por seu apelido. Muitos nem sabem seu verdadeiro nome. Agora
vamos supor uma hiptese meio absurda. Amanh eu chego at o Wanderley para, formalmente,
comunicar-lhe de que, a partir daquele momento, o apelido no ser mais dele. Que o apelido ser meu. E
saio da presena do Wanderley convencido de que, a partir de ento, todos me chamaro de Churrasco,
enquanto trataro o antigo Churrasco por Wanderley. possvel????
NO D PRA TROCAR APELIDO!!!!!
E, POR MAIS QUE SE POSSA QUERER,
NO SE PODE PEGAR O APELIDO DE NINGUM!!!!
Certamente voc j entendeu onde queremos chegar: Uma referncia, uma vez inicializada no momento
de sua criao, apontar sempre para o mesmo dado. No podemos pegar o "apelido" daquele dado e
transferi-lo para outro dado:
//--------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString irma = "Cybele"; // declara e inicializa varivel irma
AnsiString &ref_irma = irma; // cria e inicializa uma referncia para irma
ref_irma = "Cybele minha irm!"; // altera varivel esposa atravs do "apelido"
Label1 -> Caption = irma + '\n' + // imprime irma (modificada por ref_irma)
// demonstra que se trata do mesmo dado, atravs do endereo
"Endereo de irma =
" + IntToHex(int(&irma), 8) + '\n' +
"Endereo de ref_irma =
" + IntToHex(int(&ref_irma), 8);
AnsiString irma_1 = "Daurylene tambm minha irm"; // varivel irma_1

Apostila de C++ Builder

Pagina -196-

irma_1 = ref_irma;

/* parece
varivel.
passa ser
O apelido

que est atribuindo a referncia para a outra


Mas est alterando o contedo de irma_1, que
igual a irma.
continua pertencendo a irma (v. endereos) */

//ref_irma = irma_1; // eis outra possibilidade de verificao no lugar da anterior


Label2 -> Caption =

irma_1 + '\n' + // imprime irma_1, seja qual for o contedo


"Endereo de irma_1 =
" + IntToHex(int(&irma_1), 8) + '\n'

+
// mostra que ref_irma mantm o antigo endereo
"Endereo de ref_irma =
" + IntToHex(int(&ref_irma), 8) +
"\n\n\n" +
irma + '\n' + // mostra que irma foi alterada
// demonstra que se trata do mesmo dado, atravs do endereo
"Endereo de irma =
" + IntToHex(int(&irma), 8) + '\n' +
ref_irma + '\n' +
"Endereo de ref_irma =
" + IntToHex(int(&ref_irma), 8);
}
//---------------------------------------------------------------------------

Pelo exemplo, percebemos que a referncia no pode apontar para outro dado. O que ela faz alterar o
valor dos dados. E pode alterar tanto o valor do alvo, como do outro tipo que estivermos trabalhando,
atribuindo a esse segundo, o valor do alvo, ou vice-versa.

Este curso est disponvel, online, no DicasBCB, o Site dos Programadores C++Builder
http://www.dicasbcb.com.br
nosso frum:
http://www.dicasbcb.com
Autor: Thrbio de Lima Alves (DeLima)
Agradecimentos especiais:
Lucas Santos Sanches ( mais conhecido por scorpio) em nosso Frum.
Lucas, em nome de toda nossa comunidade, muito obrigado por viabilizar esta edio em PDF de nosso
curso, antiga reivindicao de grande parte dos freqentadores de nosso site!

Apostila de C++ Builder

Pagina -197-

Você também pode gostar