Escolar Documentos
Profissional Documentos
Cultura Documentos
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
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-
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
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.
Pagina -6-
Pagina -7-
Pagina -8-
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
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:
Pagina -10-
PRINT " Esta frase que est entre aspas ser exibida na tela! "
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.
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.
Pagina -12-
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. */
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
Pagina -13-
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
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;
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:
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();
}
#pragma hdrstop
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:
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.
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
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
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.
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!
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?
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
\b
Backspace
008
retrocede um caracter
\n
New Line
010
Carriage
013
Horizontal
009
\r
Valor ASCII
Descrio
return
\t
Tab
\xff
\0
representao hexadecimal
Null
000
\"
Aspas duplas
034
\'
apstrofe
039
\?
Interrogao
063
\\
Barra invertida
092
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"
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.
Pagina -26-
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++.
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)
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.
Pagina -29-
Pagina -30-
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:
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";
Pagina -32-
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
123.4
1,0
89-8
12 34
045
0x1234
0x1
0xA
0xaBcD 0x1A9F
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
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:
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.
Pagina -35-
12.345
.1
1.23e-2
1.23E+2
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
\n
10
tabulacao vertical
\v
11
\f
12
\r
13
aspas (")
\"
34
apostrofo (')
\'
39
interrogacao (?)
\?
63
\\
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.
Pagina -37-
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
Pagina -38-
Tipo
bytes
possveis valores
short int
-32768 a 32767
0 a 65535
-32768 a 32767
long int
-2147483648 a 2147483647
-2147483648 a 2147483647
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 + ' ' + ' ';
}
}
//------------------------------------------------------------------
Pagina -39-
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
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:
Pagina -42-
->
->
->
->
Lines->
Lines->
Lines->
Lines->
Strings[0]
Strings[1]
Strings[2]
Strings[3]
=
=
=
=
"Tamanho
"Tamanho
"Tamanho
"Tamanho
ShowMessage(sizeof(long double));
}
//---------------------------------------------------------------------------
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:
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
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!
Pagina -44-
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
0 a 65535
-32768 a 32767
long int
-2147483648 a 2147483647
-2147483648 a 2147483647
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.
Pagina -45-
Ui = 4294967295;
Items -> Add("Limite para unsigned int = " + String(Ui));
Items -> Add("Limite + 1 = " + String(Ui + 1));
Items -> Add("Limite + 2 = " + String(Ui + 2));
Pagina -46-
127;
-> Items
-> Items
-> Items
-> Items
->
->
->
->
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
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);
Pagina -49-
//
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)
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
// 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:
Pagina -52-
Pagina -53-
#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);
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;
}
//---------------------------------------------------------------------------
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,
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 double:
AnsiString DplPrec = 2.15e28;
um string
AnsiString AloTher = "Al, Thrbio";
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:
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 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;
Pagina -58-
typedef bool
Boolean;
//
typedef int
Integer;
// -2147483648..2147484647
typedef char
Char;
// 0..255
typedef wchar_t
WideChar;
// Unicode character
Shortint;
// -128..127
typedef short
Smallint;
// -32768..32767
Byte;
// 0..255
Word;
// 0..65535
DWord;
// 0..4294967295
typedef void*
Pointer;
//
typedef char
AnsiChar;
//
Longint;
// -2147483648..2147484647
Cardinal;
// 0..2147484647
Extended;
// 10 byte real
typedef float
Single;
// 4 byte real
typedef double
Double;
// 8 byte real
Openstring;
typedef void*
file;
//
typedef void*
Text;
//
typedef Text
TextFile;
//
typedef char*
PChar;
//
typedef char*
PAnsiChar;
//
typedef wchar_t*
PWideChar;
//
ByteBool;
//
Pagina -59-
WordBool;
//
typedef Cardinal
LongBool;
//
typedef AnsiString
String;
//
//
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;
//
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.
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.
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&
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&
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;
Pagina -62-
Label1->Caption = test.Pos("est");
}
LowerCase() e UpperCase()
AnsiString
AnsiString
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();
}
__fastcall
__fastcall
__fastcall
__fastcall
Trim() const;
TrimLeft() const;
TrimRight() const;
SubString(int index, int count) 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()):
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();
";
SubString()
AnsiString
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:
Pagina -64-
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);
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);
}
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
Pagina -66-
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:
Pagina -67-
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.
Pagina -68-
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)
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;
}
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
}
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
->
->
->
->
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...";
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
Pagina -74-
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:
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'", "");
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 +
Pagina -77-
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:
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
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
//
Pagina -80-
//
INC_VCL
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.
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
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):
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:
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
Pagina -85-
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.
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.
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.
Pagina -89-
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
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:
>
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";
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);
}
//---------------------------------------------------------------------------
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))
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 */
//------------------------------------------------------------------------------
Pagina -96-
Resultado:
155,
porque
as
duas
condies
so
//------------------------------------------------------------------------------
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:
Pagina -98-
ssShift
ssAlt
ssCtrl
ssLeft
ssMiddle
ssDouble
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.";
}
//---------------------------------------------------------------------------
Pagina -99-
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
);
//
//
//
//
hPrevInstance
lpszCmdLine
Pagina -100-
hInstance
nCmdShow
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.
Pagina -101-
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
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
}
//---------------------------------------------------------------------------
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)
seguida pelos comandos que executam a tarefa da funo, seguidos pela chave de fechamento
}
Por exemplo:
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()
Pagina -104-
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
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;
}
Pagina -106-
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 */
Pagina -108-
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.
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();
}
//---------------------------------------------------------------------------
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:
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:
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)
{
}
Pagina -112-
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
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.
//--------------------------------------------------------------------------#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";
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";
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));
Pagina -115-
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
}
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);
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);
}
Pagina -117-
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)
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).
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"
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";
}
//---------------------------------------------------------------------------
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();
}
//---------------------------------------------------------------------------
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;
}
}
//--------------------------------------------------------------------------
Pagina -123-
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 */
Pagina -125-
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);
Pagina -126-
mltiplas condies:
...; i <= j, j >= i; ...
Esses mltiplos comandos so separados entre si por vrgulas e das demais instrues por ponto e vrgula.
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++,
/******************************
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';
}
}
//---------------------------------------------------------------------------
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++;
}
}
" +
//---------------------------------------------------------------------------
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"));
Pagina -129-
" +
}
//---------------------------------------------------------------------------
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:
Pagina -130-
switch (expresso)
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';
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;
}
//---------------------------------------------------------------------------
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-
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
ssAlt
ssCtrl
ssLeft
ssRight
ssMiddle
ssDouble
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();
}
//---------------------------------------------------------------------------
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.
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
cmDstInvert
cmMergeCopy
cmMergePaint
cmNotSrcCopy
cmNotSrcErase
cmPatCopy
cmPatInvert
cmPatPaint
cmSrcAnd
cmSrcCopy
cmSrcErase
cmSrcInvert
cmSrcPaint
cmWhiteness
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;
}
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;
Pagina -136-
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.
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;
}
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);
}
Pagina -139-
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.
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.
//---------------------------------------------------------------------------
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));
}
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
Pagina -143-
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
psDash
psDot
psDashDot
psDashDotDot
psClear
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.
Pagina -144-
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
pmCopy
pmNotCopy
pmMergePenNot
pmMaskPenNot
pmMergeNotPen
pmMaskNotPen
pmMerge
Pagina -145-
Mode
Cores Pixels
pmNotMerge
pmMask
pmNotMask
pmXor
pmNotXor
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.
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.
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: // ).
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,
Pagina -148-
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;
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.
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.
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;
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");
}
Pagina -153-
delete pBitmap;
}
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
Pixels
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);
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
Pagina -155-
Mtodos
Descries
delete Bitmap;
}
Draw
Ellipse
void __fastcall Ellipse(int X1, int Y1, int X2, int Y2);
FillRect
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
Pagina -157-
Mtodos
Descries
{
Canvas->FloodFill(ClientWidth/2,
fsBorder);
}
FrameRect
ClientHeight/2,
clBlack,
LineTo
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
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);
Polygon
Pagina -159-
Mtodos
Descries
Canvas->Brush->Color = 0xffff; // Color = clYellow
Canvas->Polygon(points, 4);
}
PolyLine
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;
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;
}
Pagina -161-
Mtodos
Descries
RoundRect
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
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;
}
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
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
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
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];
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';
}
}
//---------------------------------------------------------------------------
a primeira varivel;
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)
Pagina -166-
Abcdario[4]
= e (5 posio)
...
Abcdario[25]
= z (26 posio)
//--------------------------------------------------------------------------// 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];
}
}
//---------------------------------------------------------------------------
Pagina -167-
Matrizes multidimensionais
At agora, temos visto vetores unidimensionais (pois apresentam apenas uma dimenso):
char Abcdario[26]; // um par de colchetes
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 }
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
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...
Pagina -169-
'a', 'b', 'c', 'd', i', 'j', 'k', 'l', 'q', 'r', 's'
e', 'f', 'g', 'h', 'm', 'n', 'o', 'p', 'u', 'v', 'x'
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():
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:
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
\0
diferente a interpretao que o compilador faz quando encontra um caracter entre aspas simples ou entre
aspas duplas:
Pagina -172-
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!!!
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"};
Pagina -173-
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;
Pagina -174-
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";
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:
Pagina -178-
#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 ... "
Pagina -179-
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"
//---------------------------------------------------------------------------
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
}
//---------------------------------------------------------------------------
Pagina -181-
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;
}
//---------------------------------------------------------------------------
Pagina -182-
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*/
}
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
Pagina -184-
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'
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
Pagina -185-
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.
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
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);
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;
}
//---------------------------------------------------------------------------
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> [ ];
Pagina -189-
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).
Pagina -190-
O melhor resultado produzido nos meus testes pelo exemplo acima foi o seguinte:
de certa forma, combina vrias instrues numa s, pois, na verdade, cria um ponteiro:
Pagina -191-
int * i
uma varivel:
new int
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;
//---------------------------------------------------------------------------
Pagina -192-
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);
}
//---------------------------------------------------------------------------
Pagina -193-
const double
alterados
//--------------------------------------------------------------------------#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)
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);
}
//---------------------------------------------------------------------------
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.
Pagina -196-
irma_1 = ref_irma;
/* parece
varivel.
passa ser
O apelido
+
// 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!
Pagina -197-