Você está na página 1de 102

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.

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 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 PDP-11, 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. 1. Linguagens de baixo nvel.

Quando nascemos, medida que crescemos, nossa percepo e o contato com a realidade do mundo, nos anexa s coisas como elas j foram sedimentadas na cultura de um povo. Assim tambm ocorre com o idioma e, de um modo geral, com algumas cincias que assimilamos em sequer darmos conta disso.

Por exemplo, quando uma criana conta para outra que possui trinta ou quarenta figurinhas, no percebe, mas est fazendo uso do sistema numrico decimal (base 10). E o sistema numrico decimal est incrustado em nosso cotidiano. Via de regra, todos os valores que

usamos e todas as contas que fazemos tm esse sistema numrico como base. Por exemplo, quando escrevo 543, voc entende 543 e no tem dvidas, pois sabe o que 543 significa. Raciocinando em sistema numrico decimal, tambm no difcil compreender que:

543 = (5 x 10) + (4 x 10) + (3 x 10) pois 543 = (5 x 100) + (4 x 10) + (3 x 1) pois 543 = 500 + 40 + 3.

Infelizmente, os sistemas computacionais no representam valores usando o sistema numrico decimal. Internamente, os computadores representam valores usando dois nveis de voltagem (normalmente 0v e +5v). Com esses dois nveis de voltagem, ns podemos representar dois valores. Por conveno, adota-se o zero e o um. Ento, para todos os efeitos, os computadores s conhecem uma linguagem que constituda por zeros e uns, ou cdigo de mquina, mais conhecida por linguagem binria. Nesse contexto, se quisermos representar o nmero 543, devemos escrever:

1000011111

Qualquer quantia de dgitos binrios com valor igual a zero pode anteceder um nmero binrio sem alterar-lhe o valor. Por exemplo, podamos representar o nmero 543 assim:

00000000000000000000000000000000001000011111.

Ante o exposto, no fica difcil compreender que a menor unidade de dados num computador um dgito binrio. Um dgito binrio o mesmo que um bit, abreviatura de binary digits.

Complicado? No incio da era dos computadores (aqueles gigantes vlvula), os programas eram escritos basicamente em binrio, mas, felizmente, longe se vo os dias em que se precisava programar diretamente em binrio, embora ainda exista quem trabalhe nesta base.

O sistema numrico binrio tem um modo de funcionamento semelhante ao sistema numrico decimal, porm com duas diferenas bsicas:

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

2. o sistema numrico binrio usa potncias de 2, em vez de potncias de 10.

Embora um bit seja capaz de assumir apenas dois valores (zero e um), o nmero de elementos que se pode representar com um nico bit infinitamente grande. Por exemplo, pode-se representar quaisquer dois valores diferentes com um nico bit: falso ou verdadeiro, maior ou menor, redondo ou quadrado e assim por diante, numa lista incomensurvel. Todavia, esse tipo de construo no usual.

Um srio problema com o sistema binrio o tamanho de suas representaes. Veja bem, enquanto a verso decimal de 543 contm apenas trs dgitos: 5, 4 e 3, a representao binria do mesmo valor contm dez dgitos: 1000011111. Disso decorre que, ao se trabalhar com valores grandes, os nmeros binrios rapidamente se tornam difceis de ser controlados. Embora seja possvel converter binrios

em decimal e vice-versa, tal tarefa no simples nem trivial. Mas essa a linguagem que a mquina entende.

Alternativamente, tentou-se programar em hexadecimal, que pode representar dezesseis valores entre 0 e 15 decimais. Os nmeros hexadecimais possuem duas caractersticas positivas:

1. sua converso para binrio relativamente simples; e

2. so razoavelmente compactos.

O sistema hexadecimal uma base de numerao que comea a ser contado no "0" e termina em "F":

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.

O sistema hexadecimal possui uma relao simples com o sistema binrio, uma vez que para cada grupo de quatro dgitos binrios temos um em hexadecimal.

veja a tabela abaixo: decimal 1 2 3 4 5 binrio 0001 0010 0011 0100 0101 hexadecimal 1 2 3 4 5

6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 0001 0000 0001 0001 0001 0010 0001 0011 0001 0100 0001 0101 0001 0110 0001 0111 0001 1000 0001 1001 0001 1010 0001 1011 0001 1100 0001 1101 0001 1110 0001 1111 0010 0000

6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20

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:

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

Veja agora, a mesma frase em linguagem C:

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

Em Pascal:

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

Visualmente, o que diferencia estas linguagens de programao daquelas ditas de baixo nvel justamente o fato de nestas linguagens podermos encontrar algum sentido naquilo que estamos lendo ou escrevendo. Um simples programa como este que foi apresentado nessas linguagens de alto nvel, seria praticamente ininteligvel para ns, se fosse escrito em binrio.

De uma forma simplista, podemos dizer que nas linguagens de alto nvel, o prprio programa tradutor (compilador ou interpretador) que usamos se encarrega de conversar com a mquina, transformando todos os comandos que inserimos no programa para uma linguagem que a mquina compreenda qual a resposta a ser dada. Ou seja, o tradutor converte o cdigo-fonte em um cdigo executvel pela mquina.

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

1. Deixar o cdigo o mais claro e compreensvel possvel, inserindo comentrios e usando-os adequadamente, bem como tomar bastante cuidado com a grande liberalidade na forma que o formato livre admite.

Documentar o trabalho
Em princpio, comentrios so textos que inserimos no programa para esclarecer qual a tarefa que determinado comando realiza. Comentrios so muito importantes em nossos cdigos C++. A linguagem C++ suporta dois estilos de comentrios:

a) comentrio no estilo C: /* ...*/


/* Neste tipo de comentrio, tudo aquilo que estiver inserido entre a chave de abertura do comentrio (barra e asterisco) e a chave de fechamento do comentrio (asterisco e barra) ser desconsiderado pelo compilador,

independentemente da quantidade de linhas usadas. */

b) comentrio no estilo C++: //


// Neste tipo de comentrio, tudo aquilo que estiver inserido direita // do comentrio (barras duplas), at o final da linha // ser desconsiderado pelo compilador. // Neste estilo, a cada nova linha, // precisamos iniciar um novo comentrio.

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

Uma vez iniciado um comentrio no estilo C, no podemos inserir outro comentrio dentro deste, pois o compilador considerar apenas a primeira chave de fechamento, o qu ocasionar um erro:
/* Abrimos um comentrio no estilo C; /* at a primeira chave de fechamento no h problemas, pois a abertura desse novo comentrio, na verdade no ocorreu, sendo considerada parte integrante do comentrio inicial */ aqui comea a parte ilegal do comentrio, e o compilador deve acusar o erro */

Cuidado com o formato livre

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

Abaixo transcrevemos um mesmo programa escrito de trs formas diferentes:


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

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

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

O resultado apresentado pelo programa acima rigorosamente o mesmo em qualquer das trs hipteses.

Evidentemente, se, quando trabalharmos num projeto, no tivermos cuidado de escrever um bom e legvel cdigo, o resultado poder apresentar-se bagunado, dificultando sua compreenso e, at mesmo, a localizao e conserto de bugs (erros no cdigo que afetam diretamente o resultado) no programa.

Certamente em pouco tempo voc j estar desenvolvendo sua prpria tcnica para escrever bons programas, usando o formato livre a seu favor.

2. Cuidado com o uso de letras maisculas e minsculas

C++ Case Sensitive


C++ Case Sensitive, isto , letras maisculas e minsculas so interpretadas de forma diferente pelo compilador. Dentre outras implicaes, isso significa que se, por acaso, declararmos uma varivel com o nome Temp, os seguintes nomes tero significados diferentes: TemP; TEMP; temp; tEmp; TeMp. Ateno especial devemos ter quando escrevemos os comandos da linguagem nas instrues dos cdigos-fontes, bem como com algumas funes prexistentes. 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 cdigos fontes, bem como exportar os mesmos, j formatados, para o padro .html ou .rtf. Para maiores informaes, consulte http://www.fixedsys.com/context

Inicialmente, para compreendermos melhor o conceito dos comandos e das instrues em C++, trabalharemos um programa definido como aplicao Console Win32, que gera programas parecidos com o DOS quando esto rodando, mas, na realidade, trata-se de programas de 32 bits executados no ambiente Windows.

Bem, chega de conversa e vamos por as mos na obra:

1. inicialize o C++Buider;

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

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

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:

Na sugesto da Borland:

#pragma hdrstop #include <condefs.h> //--------------------------------------------------------------#pragma argsused int main(int argc, char* argv[]) { return 0; }

devemos digitar o cdigo-fonte de nosso programa imbricando-o no cdigo pr-estabelecido acima.

Outra opo que temos deletar todo esse cdigo e simplesmente iniciar nosso programa a partir do cdigo j visto do menor programa possvel em C++:
main() { }

Esse modelo aconselhvel, se voc estiver usando outro tipo de compilador. Caso haja algum conflito entre o exemplo apresentado e o seu compilador, procure ajuda no manual do mesmo.

Nosso primeiro programa, ao ser compilado, escrever na sada de vdeo uma string (cadeia de caracteres) com um espao de tabulao na segunda linha da tela, levar o cursor para a terceira linha da tela, emitir um beep e, por fim, aguardar que uma tecla qualquer seja pressionada para encerrar a aplicao.

Delete toda a sugesto da Borland e, no editor de textos, digite:


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

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


#pragma hdrstop #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:

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.

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

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 partir de ento, nenhum sufixo necessrio para cabealhos da biblioteca padro: <iostream>, <conio>, <map> etc.

A principal diferena entre a biblioteca padro e a no padro que, enquanto uma biblioteca no padro tem de ser incorporada manualmente, a padro incorporada automaticamente pelo compilador. importante saber, ainda, que os recursos da biblioteca padro esto definidos num ambiente de nomes chamado std e apresentados como uma srie de cabealhos.

o arquivo de cabealho iostream


Para o nosso programa imprimir a string Estou fazendo o meu primeiro programa no vdeo, ns providenciamos para que a Classe

iostream fosse chamada compilao atravs da diretiva #include. A biblioteca iostream contm as declaraes necessrias ao uso de streams de entrada (teclado) e sada (vdeo), como, por exemplo, o

objeto cout e o operador de insero <<. Obtm-se o operador de insero << digitando-se o caracter "menor que" duas vezes.

O objeto cout o responsvel pela sada, no console ou na tela, da string que digitamos: Estou fazendo o meu primeiro programa.

O operador de insero << (envie para) escreve o argumento da direita (a string) no da esquerda (no cout).

Alm do cout e do operador de insero << a Classe iostream contm outras definies de impresso e leitura (I/O), que estudaremos mais adiante.

Voc deve ter notado que demonstramos a incluso dos arquivos de cabealho da Classe iostream de trs modos diferentes:
#include <iostream> // Cabealho padro sem sufixo .h #include "iostream.h" // Cabealho de biblioteca no padro #include <iostream.h> // Cabealho padro com sufixo .h

No h necessidade de inserirmos nenhum sufixo para cabealhos da biblioteca padro, porque os smbolos < > j denotam o chamamento de cabealhos padro. Contudo, as declaraes dos cabealhos mais antigos, so colocadas no ambiente de nomes global, carecendo do sufixo .h.

Os cabealhos colocados entre aspas " " determinam que o prprocessador procure o cabealho primeiro no diretrio atual, e depois na biblioteca padro (Include).

Em nosso programa: #include<iostream> instrui o pr-processador a incluir os recursos de entrada e sada de iostream padro, e std::cout determina a incluso do cout padro.

Se quisermos, podemos tornar todos os nomes std globais, o que nos poupa da tarefa de ter que digitar constantemente o prefixo std:: antes de cout:

#include <iostream> using namespace std;

Se algum dos nossos programas no rodar, podemos usar uma verso mais tradicional. Para isso colocamos o sufixo .h nos cabealhos e removemos o prefixo std::. Exemplo:
#include <iostream.h> #include <conio.h> main() { cout << "\n\tEstou fazendo o meu primeiro programa\n\a"; getch(); }

Boa parte dos programadores, talvez por praticidade, parece preferir essa segunda verso. Daqui para frente, escolha sua!

o arquivo de cabealho conio

Nosso programa possui outro cabealho, o arquivo conio. Trata-se de um arquivo de incluso necessrio utilizao da funo getch(). Quando descrevemos o que o nosso programa faria, afirmamos que, por fim, ele aguardaria que uma tecla qualquer fosse pressionada para encerrar a aplicao. Essa tarefa foi desempenhada pela funo getch() que retorna o caracter lido no teclado, sem imprimi-lo no vdeo. Se quisermos que o caracter lido seja impresso no vdeo, podemos usar a funo getche(), tambm integrante de a conio.

Lembra-se do menor programa possvel em C++, quando afirmamos que tudo o que veramos seria um breve piscar da janela na tela e o encerramento do programa? Pois bem, poderamos usar getch() para segurar a janela na tela at que uma tecla fosse pressionada!

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

Como fizemos isso?

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 \a \b \n \r \t Tab \xff \0 \" \' \? \\

Nome Bell (alerta) Backspace New Line Carriage return Horizontal

Valor ASCII 007 008 010 013 009

Descrio emite um som do computador retrocede um caracter envia o curso para a prxima linha move o cursor para o incio da linha pe o cursor para a prxima tabulao representao hexadecimal

Null Aspas duplas apstrofe Interrogao Barra invertida

000 034 039 063 092

exibe um caracter nulo exibe aspas duplas () exibe apstrofe (') exibe ponto de interrogao exibe barra invertida

string(s) de texto
Constante caracter uma letra ou smbolo colocado entre apstrofes: 'a', 'b', '~', 'A', 'B', '\n, '\r', '\xa0', '\xa2', 'xa3' etc.

Uma importante atividade nos programas em geral a manipulao de textos como palavras, frases, nomes etc. Na realidade, esses textos so constantes string(s), que se compem de um conjunto de caracteres colocados entre aspas: "Estou fazendo o meu
primeiro programa", "constante string", "\tOuviram do Ipiranga as margens pl\xa0" "cidas\n\tde um povo her\xa2ico o brado retumbante\n\te o sol da

liberdade em raios f\xa3lgidos,\n\tbrilhou no c\x82u da P\xa0tria nesse instante.\n"

funes
Funes so a base de qualquer programa C++. Elas compem, juntamente com as Classes, os blocos construtivos da linguagem. Dentro das funes, encontramos todos os comandos executveis, sendo que as mesmas so a maneira tpica de se obter alguma execuo em C++.

Vamos reescrever o primeiro programa. Por enquanto, no queira compreender todos os detalhes da alterao, uma vez que, por ora, nossa preocupao apenas esclarecer, sem pormenores, quais so os elementos bsicos de uma funo. Em outra seo deste curso, abordaremos as funes de uma forma mais abrangente e minuciosa.

Inicialize PrimProgram.bpr, caso no esteja com ele aberto. No compilador, clique em Edit e depois em Select All; Clique novamente em Edit e depois em Delete. Agora copie o cdigo abaixo no editor de textos do compilador.
/*Dica: no use o recurso de copiar e colar cdigos-fontes quando estiver estudando. Procure digitar todo o cdigo e entender o resultado que cada. instruo conhecida produzir no programa.*/ #include <iostream> #include <conio> using namespace std; // torna todos o nomes std globais void ModifPrimProg(void); // declara a fino ModifPrimProg int main() // estamos em main() { ModifPrimProg(); // chama a funo ModifPrimProg return 0; } // fim de main() void ModifPrimProg(void) // cabealho da definio da funo {

cout << "\n\t\tModificando o primeiro programa." "\n\n\n\t\tDigite dois caracteres mas veja " "s\xa2 o primeiro: "; getche(); // retorna e imprime o caracter lido no vdeo cout << '\a'; // beep - sinal sonoro getch(); // retorna o caracter sem imprimi-lo no vdeo } // fim de ModifPrimProg()

Execute o programa e volte aos estudos.

Com essa pequena alterao no cdigo, podemos visualizar melhor alguns detalhes sobre as funes.

Uma funo deve ter a seguinte forma geral:

tipo nome(declarao dos parmetros) { Primeira_Instruo; Segunada_Instruo; Etc_instruo; }

Nosso programa agora possui quatro funes: main(), ModifPrimProg(), getche() e getch(). O nome delas : main, ModifPrimProg, getche e getch respectivamente. A funo main(), como sabemos, a principal, aquela onde a execuo do programa se inicia; ModifPrimProg() uma funo que no estava em biblioteca alguma, tendo sido criada por ns; getche() e getch() ns tambm j conhecemos do arquivo de cabealho conio.

Precedendo o nome da funo main() temos o tipo int, que informa ao compilador que main() pode retornar um tipo int. J a funo ModifPrimProg() do tipo void. O tipo void significa que a funo no possui valor de retorno. Quando nenhum tipo de retorno for especificado, presume-se o valor de retorno int para a funo. As funes retornam valores por meio do comando return.

Aps o nome de qualquer funo temos parnteses de abertura "(" e de fechamento ")". Nesses parnteses, informamos ao compilador a lista de parmetros que a funo pode receber. Logo, ModifPrimProg(void) no pode receber nenhum parmetro por causa do tipo void.

Entende-se por cabealho da definio da funo o conjunto tipo nome(declarao dos parmetros) que antecede a chave "{" de abertura do corpo da funo. Entre a chave de abertura "{" e a de fechamento "}" do corpo da funo, encontramos as tarefas (instrues) que a mesma realiza.

Instrues so as tarefas que determinados comandos realizam. Toda instruo encerrada com um ponto e vrgula ";":
cout << "uma instruo!"; getch(); return 0;

A falta do ponto e vrgula ensejar mensagem de erro pelo compilador. Porm, no se coloca ponto e vrgula aps as chaves de abertura e fechamento das funes.

No se preocupe em entender, por ora, todos os conceitos apresentados, posto que os abordaremos novamente no correr do

curso. At aqui, tivemos apenas a inteno de coloc-los em contado com o ambiente de programao C++Builder e com os fundamentos da linguagem C++.

Imprimindo dados nos componentes

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

Introduo ao BCB

Introduo ao BCB - 2 parte

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) { /* 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.

Conhecendo melhor as propriedades que capturam dados

Nos exemplos anteriores, conhecemos um modo de inserir textos ou strings nos componentes, sem nos preocuparmos de que modo isso

nos pode ser til. Agora aprofundaremos um pouco mais o estudo para podermos entender que essas propriedades no esto limitadas e pode produzir alguns resultados mais teis:

void __fastcall TForm1::Button1Click(TObject *Sender) /* Neste exemplo, iremos corrigir uma falha referente cor do primeiro exemplo em que usamos o objeto Canvas do Form. Como voc deve ter notado, as cores da frase sairam com um fundo branco (clWhite), enquento que o form manteve a cor original clBtnFace, visto que no procedemos a nenhuma alterao nela. Para visualizar melhor essa situao, d uma olhada na propriedade Color do Form no Object Inspector. Pois bem, vamos corrigir a cor do fundo da frase para igual-la ao Form.*/ { // Ok. A cor do fundo igual cor do Form Canvas -> Brush -> Color = clBtnFace; /* A linha de cdigo abaixo nos mostra como podemos usar propriedades matemticas diretamente no Form*/ Canvas->TextOut( Canvas->PenPos.x = 10, Canvas->PenPos.y = 100, (5 * 4) + (60 50) ); /* Podemos chamar funes que nos mostrem a data e a hora...*/ Canvas->TextOut( Canvas->PenPos.x, Canvas->PenPos.y, Date()/* +Time()*/); }

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


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

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


void __fastcall TForm1::Button1Click(TObject *Sender)

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

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

Comentrios

Quando estamos empenhados na tarefa de escrever uma aplicao, fundamental tomarmos algumas providncias para que no nos percamos nas diversas linhas de cdigo que por ventura utilizaremos. Uma coisa muito til que podemos, ou melhor, que devemos fazer colocar comentrios que nos esclaream a utilidade das diversas partes do cdigo. Evidentemente, voc j tem percebido que, junto s linhas de cdigo, ns colocamos algumas frases esclarecedoras

dentro de um par de barras com asterisco /* */, ou imediatamente aps duas barras //. Essas frases so os comentrios.

C++ aceita esses dois estilos de comentrios:


/* Esse estilo de comentrio derivado da linguagem C. Ele aberto com uma barra seguida de um asterisco. Tudo aquilo que estiver aps essa chave de abertura, at encontrar uma chave de fechamento (um asterisco e uma barra) ser desconsiderado pelo compilador */ // // // // // Essas duas barras significam comentrios no estilo C++. Uma vez aberto, esse comentrio no precisa ser fechado. Mas ele s vale para a linha em que foi aberto, a partir do ponto em que foi aberto e at o final da linha nada mais ser considerado

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"; else // seno - ou seja, se a afirmao falsa /* Quinta linha de Memo imprime: Afirmao Mentirosa */ Memo1->Lines->Strings[4] = "Afirmao Mentirosa"; }

Nota: Se o programa acima no imprimir todas as linhas, pressione a tecla Enter alguma vezes para criar linhas vazias no Memo. Desta forma, as strings sero colocadas no espao correto. Depois (no tpico Variveis) veremos outra soluo mais adequada para o problema!

A linguagem C++ ainda nos oferece um tipo especial que serve para indicar, justamente a ausncia de tipo: o void. No exemplo acima percebemos o uso deste tipo junto funo do evento chamado, indicando que tal funo no devolver nenhum valor. O void tambm ser usado em funes que no requerem parmetros.

O tipo inteiro

O tipo inteiro um nmero de valor inteiro, ou seja, no fracionrio. De um modo geral, trata-se de seqncias de dgitos que representam nmeros inteiros, que podem ser escritos na base 8 (octal), na base 10 (decimal) ou na base 16 (hexadecimal).

Um inteiro decimal formado pela seqncia de dgitos decimais: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Exemplos vlidos para decimais so: 0 12345 1 - 89

Os nmeros a seguir no so exemplos vlidos para decimais: 00 123.4 1,0 89-8 12 34 045

OBS. Embora alguns compiladores aceitem declaraes do tipo:

int i = 123.4;

todos os nmeros colocados depois do ponto fracionrio (nesse caso, o 4) sero desconsiderados.

Um inteiro hexadecimal formado pela seqncia de dgitos decimais: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 combinados com letras que vo de "A" a "F" (A, B, C, D, E, F ou a, b, c, d, e, f). Como no h regras que impeam que um hexadecimal possua s valores decimais em sua composio, devemos diferenci-los dos inteiros decimais inserindo 0x em seus primeiros dgitos. Exemplos vlidos para hexadecimais so: 0x0 0x1234 0x1 0xA 0xaBcD 0x1A9F

Os nmeros a seguir no so vlidos para valores hexadecimais: 00x 0x123.4 0x1,0 0xAGB OxaB cD FF12

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

Os nmeros a seguir no so exemplos vlidos para octais: 012 34

0123.4 01,0

089

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 0 1 2 3 octais 00 01 02 03 hexadecimais 0x0 0x1 0x2 0x3

4 5 6

04 05 06 07 010 011 012 013 014 015 016 017 020 021 022 023 024 025 026 027 030 031 032 033 034 035 036 037 040

0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17
0x18

7
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

0x19 0x1A
0x1B 0x1C

0x1D 0x1E 0x 1F 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.

Os tipos ponto flutuante

De um modo geral, podemos afirmar que os tipos ponto flutuante so representados pelos nmeros fracionrios na base decimal. Ou seja, trata-se de nmeros, de regra, constitudos por um ponto fracionrio que no pode ser substitudo por uma vrgula.

Um nmero de ponto flutuante pode apresentar-se na forma de notao cientfica. Por exemplo: 4.32 vezes dez elevado a quarta. Neste caso, o vezes dez ( X 10) substitudo por e ou E. Logo o nmero supramencionado ser representado por 4.32e4, que vale 43200.

OBS. Embora o C++Builder aceite a notao cientfica para inteiros, todos os valores que estiverem situados aps um eventual ponto fracionrio, no resultado, sero desconsiderados.

Exemplos vlidos para ponto flutuante so: 1.23e1.23E+2 2

-1.e4 12.345

.1

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

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

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

O tipo caracter

O tipo caracter uma letra ou um smbolo colocado entre aspas simples. Embora sejam visualizados como letras ou smbolos, importante ter em mente que, internamente, os computadores armazenam os caracteres como um nmero inteiro entre 0 e 255. Por exemplo, a letra a associada ao nmero 97, b ao 98, c ao 99, d ao 100 e assim sucessivamente. Os valores numricos dos caracteres esto padronizados em uma tabela chamada de American Standard Code for Information Interchange Table ou simplesmente tabela ASCII. Ento conclumos que um char tanto pode ser interpretado como um nmero entre 0 e 255, 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 nulo (null) campainha (bell) retrocesso (backspace) tabulacao horizontal nova linha (new line) tabulacao vertical alimentacao de folha (form feed) retorno de carro (carriage return) aspas (") apostrofo (') interrogacao (?) barra invertida (\) Sequencia de escape \0 \a \b \t \n \v \f \r \" \' \? \\ Valor ASCII 00 07 08 09 10 11 12 13 34 39 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. Coloque um Label no Form e no evento OnClick do Label digite:

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

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

Modificadores de tipos
Podemos alterar o significado de um tipo bsico de dados, adaptando-o a uma necessidade especfica, por meio de modificadores de tipos precedendo os tipos na declarao:

signed (com sinal); unsigned (sem sinal); long (mxima preciso); short (menor preciso).

Tipo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int float double long double

bytes 1 1 1 4 4 4 2 2 2 4 4 4 4 8 10

possveis valores -128 a 127 0 a 255 -128 a 127 -2147483648 a 2147483647 0 a 4294967295 -2147483648 a 2147483647 -32768 a 32767 0 a 65535 -32768 a 32767 -2147483648 a 2147483647 -2147483648 a 2147483647 0 a 4294967295 -(3.4e38) a 3.4e38 1.7e308 a -(1.7e308) 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 + ' ' + ' '; } } //----------------------------------------------------------------void __fastcall TForm1::BitBtn1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { // Adiciona o contedo de Edit1 a Memo1 Memo1->Lines->Add(Edit1->Text); }

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

Construo do Editor de Textos


Primeira parte

Vamos dar os primeiros passos na construo de um Editor de Textos. Clique em File e depois em New Application. Pegue um componente RichEdit na palleta Win32 (ou Win95) e a coloque no Form. Altere a propriedade BorderStyle do Form para bsNone (para tirar a barra de ttulos e suas propriedades). Altere a propriedade Align do RichEdit para alCliente (Assim o RichEdit ocupar toda a rea cliente do Form). Na palleta Standart pegue um componente PopudMenu (para criarmos alguns menus pop-up), e coloque no Form. D um clique com o boto direito do mouse sobre o componente PopupMenu e escolha a opo Menu Designer ... Abrir-se- o Menu Designer (Editor de Menus). Na propriedade Caption (no Object Inspector) do Editor digite: Arquivo D um clique na parte selecionada do Menu Designer. Aparecer a palavra Arquivo selecionada no menu flutuante, e abrir-se-, logo abaixo, um novo campo para menu. D um clique nesse novo campo (que ficar selecionado) e, na propriedade Caption, digite: Editar Muito bem, j sabemos criar o Menu Popup. Agora, no Menu Designer, onde tem a palavra Arquivo d um clique para selecionar o menu correspondente. Depois, com o boto direito do mouse, d um clique sobre o menu Arquivo j selecionado. Aparecer um menu Pop-up. Escolha a opo Create Submenu. Na propriedade Caption digite: &Abrir

O Smbolo & cria um atalho (tecla de atalho + a letra sublinhada) para o menu. Abaixo do menu Abrir, Crie o menu Locali&zar; abaixo do menu Localizar crie o menu &Salvar; abaixo do menu Salvar crie o trao separador de menus digitando apenas um trao: - ;abaixo do trao, crie o menu Sai&r.

Nota: quando criamos atalho, tomemos cuidado para no usar as mesmas teclas de atalho para funes diferentes.

Construo do Editor de Textos


Segunda parte
Agora d um duplo clique no menu Sair. Abrir-se- o Editor Properties que o Editor de Cdigos do programa. Digite:
Close();

O Cdigo deve ficar assim:

void __fastcall TForm1::Sair1Click(TObject *Sender) { Close(); }

Para ativar o PopupMenu, no evento OnCreate do Form1 digite:


PopupMenu1->AutoPopup = true; RichEdit1->PopupMenu = PopupMenu1;

O Cdigo deve ficar assim:


void __fastcall TForm1::FormCreate(TObject *Sender) { PopupMenu1 -> AutoPopup = true; RichEdit1 -> PopupMenu = PopupMenu1; }

Rode o Programa (Tecla F9). Voc perceber que criou um Editor de Textos bem estranho. Digite ou delete letras e palavras.

Para fechar o programa, d um clique com o boto direito do mouse sobre o Editor e escolha a opo Sair no menu Arquivo.

Se voc seguiu os passos corretamente, e o programa fechou sem problemas, na propriedade WindowState do Form1 escolha a opo: wsMaximized, e rode novamente o programa. Ele ocupar toda a tela do Windows. Siga o mesmo procedimento para encerrar o programa. Uma outra forma de encerrar o aplicativo pressionando simultaneamente as teclas alt + F4.

Construo do Editor de Textos


Terceira parte
Vamos melhorar nosso Editor. D um duplo clique na propriedade Lines de RichEdit1. No editor que se abrir, delete a palavra RichEdit1 e d um OK, o que far que essa string no aparea mais na execuo do programa. Na palette Dialogs, pegue um componente OpenDialog e coloque no projeto. Na propriedade InitialDir de OpenDialog podemos digitar o caminho do diretrio onde queremos que a Caixa de Dilogo Abrir inicialize (por exemplo: C:\Meus documentos) e, feito isso, podemos completar o caminho e escolher um arquivo inicial na propriedade FileName (por exemplo: C:\Meus documentos\Tutorial.txt). Na propriedade Filter, ns podemos escolher os arquivos que o Editor pode abrir, por meio do Filter Editor. No Filter Editor digite:

Filter Name arquivos richtext *.rtf arquivos de texto *.txt todos os arquivo *.*

Filter *.rtf *.txt *.*

e d um OK. Abra o MenuDesigner e d um duplo clique no submenu Abrir para abrir o Editor Properties. Entre as chaves { e } digite:
if (OpenDialog1 -> Execute()) RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName); else MessageBeep(0);

O cdigo dever ficar assim:

void __fastcall TForm1::Abrir1Click(TObject *Sender) { if (OpenDialog1 -> Execute()) RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName); else MessageBeep(0); }

Nosso Editor j est em condies de abrir documentos. Rode o programa e abra alguns documentos de texto (*.txt) ou richtext (*.rtf).

Construo do Editor de Textos


Quarta parte

Passemos ao submenu Localizar. Coloque um componente FindDialog no projeto. Em seguida abra o Menu Designer e d um duplo clique em Localizar. No Editor Properties, entre as chaves { e } que se abrirem, digite:

FindDialog1->Execute(); int FoundAt, StartPos, ToEnd; // declara trs variveis int //////////////////////////////////////////////////////////////////////// // INICIA A BUSCA A PARTIR DA SELEO ATUAL // OU DE OUTRA FORMA // INICIA A PARTIR DO INCIO DO TEXTO /*SelLength devolve o nmero de caracteres selecionados*/ if (RichEdit1->SelLength) /* se h caracteres selecionados em RichEdit1*/ /*SelStart devolve a posio do primeiro caracter selecionado no texto*/ /*o cdigo abaixo devolve a posio do ltimo caracter selecionado*/ StartPos = RichEdit1->SelStart + RichEdit1->SelLength; else StartPos = 0; /////////////////////////////////////////////////////////////////////////// /*Length() retorna o nmero de caracteres de AnsiString*/ /*Ou ToEnd ser igual a Text.Lengt() ou igual ao nmero dos caracteres a serem contados aps o ltimo caracter selecionado*/ ToEnd = RichEdit1->Text.Length() - StartPos; /*FindText busca o texto num controle rich edit para a string especificada no parametro SearchStr (no exemplo: FindDialog1->FindText)*/ FoundAt = RichEdit1->FindText(FindDialog1->FindText, StartPos, ToEnd, TSearchTypes()); if (FoundAt != -1) // se a varivel for difetente de -1 RichEdit1->SetFocus(); // coloca o foco em RichEdit1 // coloca o cursor na primeira ocorrncia RichEdit1->SelStart = FoundAt; // seleciona a string procurada no texto do RichEdit1 RichEdit1->SelLength = FindDialog1->FindText.Length();

No Object Inspector, no evento (Events) OnFind de FindDialog1 escolha a opo Localizar1Click. Em Properties, d um duplo clique em Options. Altere de false para true as seguintes opes:

frHideMatchCase frHideWholeWord frHideUpDown

true true true

Agora seu editor j se encontra apto para efetuar algumas buscas de textos ou caracteres.

Construo do Editor de Textos


Quinta parte
Coloque um componente SaveDialog no projeto, abra o Menu Designer e d um duplo clique em Salvar. No Editor Properties, entre as chaves { e } que se abrirem, digite:

if (SaveDialog1 -> Execute()) RichEdit1 -> Lines -> SaveToFile(SaveDialog1 -> FileName); else MessageBeep(0);

Em SaveDialog, temos funcionando de forma semelhante ao funcionamento em OpenDialog, as propriedades InitialDir, FileName e Filter, com a diferena de que, no presente caso, estamos cuidando de salvar arquivos, e no abri-los.

Como experincia, no Filter Editor digite:

Filter Name arquivos richtext *.rtf arquivos de texto *.txt todos os arquivo *.*

Filter *.rtf *.txt *.*

e escolha um diretrio inicial para salvar os arquivos.

Construo do Editor de Textos


Sexta parte
Pois bem, todos os submenus do menu Arquivo j esto funcionando. Agora vamos criar mais alguns menus e submenus. Selecione o menu Editar no Menu Designer e crie os seguintes submenus: Cortar, Copiar, Colar, Deletar e Selecionar Tudo. Vamos aos cdigos:

submenu Cortar:
void __fastcall TForm1::Cortar1Click(TObject *Sender) { TComponent *pComponent = PopupMenu1->PopupComponent; if (pComponent) { if (pComponent->ClassNameIs("TRichEdit")) ((TRichEdit *)pComponent)->CutToClipboard(); else MessageBeep(0); } }

submenu Copiar

void __fastcall TForm1::Copiar1Click(TObject *Sender) { TComponent *pComponent = PopupMenu1->PopupComponent; if (pComponent) { if (pComponent->ClassNameIs("TRichEdit")) ((TRichEdit *)pComponent)->CopyToClipboard(); else MessageBeep(0); } }

submenu Colar
void __fastcall TForm1::Colar1Click(TObject *Sender) { TComponent *pComponent = PopupMenu1->PopupComponent; if (pComponent) { if (pComponent->ClassNameIs("TRichEdit")) ((TRichEdit *)pComponent)->PasteFromClipboard(); else MessageBeep(0); } }

Agora vamos trabalhar com um cdigo mais simples nas funes Deletar e Selecionar Tudo.

submenu Deletar
void __fastcall TForm1::Deletar1Click(TObject *Sender) { RichEdit1 -> ClearSelection(); }

submenu Selecionar Tudo

void __fastcall TForm1::SelecionarTudo1Click(TObject *Sender) { RichEdit1 -> SelectAll(); }

Exerccio: Pesquise TComponent no Help do C++Builder e procure entender seu papel nas funes que usaram-no. Depois insira comentrios documentando detalhadamente os cdigos acima.

Construo do Editor de Textos


Stima parte
Abaixo do menu Editar, crie o menu Formatar com dois submenus: Fontes e Cores. submenu Fontes

Coloque um componente FontDialog no projeto.

Eis o cdigo:

void __fastcall TForm1::Fontes1Click(TObject *Sender) { /*coloca os atributos do texto selecionado no RichEdit1 em FontDialog1*/ FontDialog1->Font->Assign(RichEdit1->SelAttributes); /*Sendo chamada a caixa de dilogo de fontes*/ if(FontDialog1->Execute()) /*as fontes selecionadas de RichEdit1 recebero os atributos da caixa de dilogos de fontes*/ RichEdit1->SelAttributes->Assign(FontDialog1->Font); }

Nota: TtextAttributes::Assign

Coloca as propriedades de um objeto TTextAttributes em conformidade com as propriedades especificadas em outro objeto TTextAttributes ou num objeto TFont.

Use Assign para mudar todos os atributos de texto simultaneamente. Assign pode colocar as caractersticas das fonts selecionadas num texto em conformidade com as caractersticas default da font ou vice-versa. Quando o incio um objeto TTextAttributes, Assign adapta somente Color, Name, Style, e propriedades Pitch. Quando o incio um objeto TFont, Assign tambm adapta o Size.

Nota: Assign somente substitui em tempo de execuo quando incio um objeto TTextAttributes, um objeto TFont, ou um objeto que tenha implementado um mtodo AssignTo que trate o objeto TTextAttributes. Outras origens produzem excees de erro.

Coloque um componente ColorDialog no projeto.

Eis o cdigo:

void __fastcall TForm1::Cores1Click(TObject *Sender) { if (ColorDialog1 -> Execute()) /*a cor de RichEdit1 ser a cor escolhida em ColorDialog1*/ RichEdit1 -> Color = ColorDialog1 -> Color; }

O cdigo de Cores1Click no subsistente. Ou seja, se voc alterar a cor do editor de textos e fechar o aplicativo, na prxima vez que abrir o editor de textos, ele abrir na cor padro, estabelecida inicialmente

no Object Inspector. Futuramente ns veremos um modo de conservar a cor atrvs de arquivos .INI.

Construo do Editor de Textos


Oitava parte
Vamos alterar algumas propriedades: Para colocar uma barra de rolagem vertical, altere a propriedade ScrollBarss de RichEdit1 para ssVertical. Normalmente os componentes Memo e RichEdit tm uma limitao na quantidade de dados que podem receber, que uma quantia padro. Podemos aument-la ou diminui-la bastante. Na verdade, tudo depende da quantidade de dados que trabalharemos. Para alterar essa quantia de dados devemos mudar a propriedade MaxLength (no Object Inspector ou em tempo de execuo). Por exemplo, se colocarmos a propriedade MaxLength para 2147483645 (que um tamanho praticamente incomensurvel) tais componentes podero receber dois bilhes, cento e quarenta e sete milhes, quatrocentos e oitenta e trs mil, seiscentos e quarenta e cinco caracteres. No momento, nosso projeto deve estar com esta aparncia:

Exerccios:

1) O submenu Localizar deve ser retirado do menu Arquivo e colocado no menu Editar;

2) Falta uma funo que ative a impressora para imprimir textos. Providencie a colocao do componente e do cdigo correspondente.

3) Coloque atalhos nos menus. Use as propriedades ShortCut correspondentes.

Construo do Editor de Textos


Nona parte

Feito isso, continuemos. Vamos dar ao nosso Editor a possibilidade de alterar seu tamanho. Abra o MenuDesigner e, abaixo do menu Formatar, crie o menu Janela que dever conter os seguintes submenus: Maximizar, Normal, Minimizar. Vamos aos cdigos:
void __fastcall TForm1::Maximizar1Click(TObject *Sender) { BorderStyle = bsNone; WindowState = wsMaximized; }

void __fastcall TForm1::Normal1Click(TObject *Sender) { BorderStyle = bsNone; WindowState = wsNormal; }

void __fastcall TForm1::Minimizar1Click(TObject *Sender) { BorderStyle = bsSizeable; WindowState = wsMinimized; }

Execute o programa e experimente todos os menus. Observe se todos os comandos esto obedecendo perfeitamente. Caso haja algum problema, d uma olhada se no digitou algum cdigo errado.

Agora vamos deix-lo mais parecido com aqueles editores que estamos acostumados a trabalhar. Em primeiro lugar, altere o nome do submenu Salvar para Salvar Como. Feito isso, d um clique com

o boto direito do mouse sobre o submenu Salvar Como e, em seguida, um clique em insert. Abrir-se- um espao para um novo submenu. D-lhe o nome de Salvar e, como exerccio, digite para ele o cdigo que o usurio salva o texto automaticamente sem chamar a caixa de dilogo Salvar Como (caso o arquivo j esteja gravado em disco). Caso voc no consiga, no se preocupe. Em lies futuras estudaremos esse evento.

Construo do Editor de Textos


Dcima parte
Abra novamente o Menu Designer e crie o menu Visualizar, com os seguintes submenus: Barra de ttulos, Barra de Ferramentas e Rgua. Vamos ao primeiro cdigo:

void __fastcall TForm1::BarradeTtulos1Click(TObject *Sender) { if(BorderStyle == bsSizeable) BorderStyle = bsNone; else BorderStyle = bsSizeable; }

Vamos colocar uma Barra de Ferramentas e uma Rgua em nosso Editor. Primeiramente coloque um componente TPanel (Panel), da pgina Standard no Form. Desse componente, no Object Inspector, delete qualquer caracter da propriedade Caption, altere a propriedade Align para alTop e a Propriedade Visible para false. Feito isso, eis o cdigo do menu correspondente:

void __fastcall TForm1::BarradeFerramentas1Click(TObject *Sender) { if(Panel1->Visible == true) Panel1->Visible = false; else Panel1->Visible = true; }

Aps terminar de digitar o cdigo, coloque um segundo TPanel no Form. As Propriedades so rigorosamente as mesmas: Caption = ; Align = alTop e Visible = false. Voc perceber que esse segundo Panel se instalar abaixo do primeiro (de Panel1). Eis o cdigo:
void __fastcall TForm1::Rgua1Click(TObject *Sender) { if(Panel2->Visible == true) Panel2->Visible = false; else Panel2->Visible = true; }

O primeiro Panel ser usado para construrmos a Barra de Ferramentas e o segundo, a rgua. Rode a aplicao e experimente o resultado parcial.

Construo do Editor de Textos


Dcima primeira parte
O C++Builder possui componentes Buttons que podem carregar imagens. Trata-se dos SpeedButtons e BitBtns. Para colocar imagens nesses botes, basta editar sua propriedade Glyph no Object Inspector. As imagens a seguir, tiradas dos prprios exemplos do C++Builder, sendo que algumas delas podem ser editadas para ser carregadas no boto adequado do nosso editor de textos.

Caso voc ainda no tenha providenciado, vamos agora estudar como podemos colocar um boto (ou menu) Salvar em nosso Editor. Antes, porm, certifique-se de ter providenciado a alterao solicitada no final da seo: Construo do Editor de Textos - Nona parte.

Dificuldade: Quando o boto for pressionado (ou o menu respectivo receber o evento correspondente), o programa dever fazer uma verificao para saber se o arquivo j se encontra gravado em disco; em caso afirmativo, dever conhecer o caminho completo para salvar o arquivo; em caso negativo, dever chamar a caixa de dilogos Salvar Como. Comecemos trabalhando com os menus. V para o Editor de Cdigos e lhe d um clique com o boto direito do mouse. No menu pop-up que se abrir, escolha a opo: Open Source/Header File, ou simplesmente pressione as teclas Ctrl + F6 simultaneamente. Abrir-se- o arquivo de cabealho Unit1.h. Na parte de baixo do arquivo, Depois da linha que inicia as declaraes privadas da classe, declare duas AnsiString que serviro para guardar os caminhos dos arquivos que forem abertos ou salvos, respectivamente. Eis as declaraes.
private: // AnsiString AnsiString public: // User declarations Caminho_Abrir; Caminho_Salvar; User declarations

Nota: Futuramente entenderemos melhor a finalidade deste arquivo.

Agora vamos implementar algumas modificaes nos cdigos dos eventos Abrir e Salvar Como do nosso Editor de Textos:
void __fastcall TForm1::Abrir1Click(TObject *Sender) { if (OpenDialog1 -> Execute()) {

RichEdit1 -> Lines -> LoadFromFile(OpenDialog1 -> FileName); //Caminho_Abrir atribuda com caminho do ltimo arquivo aberto Caminho_Abrir = OpenDialog1->FileName; //atribui Caminho_Abrir para Caminho_Salvar (para ficarem iguais) Caminho_Salvar = Caminho_Abrir; } else MessageBeep(0); } //-------------------------------------------------------------------------void __fastcall Tform1::Salvar1Click/*atual Salvar Como*/ (TObject *Sender) { if (SaveDialog1 -> Execute()) { RichEdit1 -> Lines -> SaveToFile(SaveDialog1 -> FileName); // Caminho_Salvar atribuda com caminho do ltimo arquivo salvo Caminho_Salvar = SaveDialog1->FileName; // atribui Caminho_Salvar para Caminho_Abrir (para ficarem iguais) Caminho_Abrir = Caminho_Salvar; } else MessageBeep(0); } //--------------------------------------------------------------------------

Agora basta digitarmos o cdigo para o menu salvar:


void __fastcall TForm1::Salvar2Click/*Salvar*/(TObject *Sender) { // se o arquivo aberto j foi salvo ... if((Caminho_Abrir == Caminho_Salvar) && (Caminho_Salvar ! = "")) // o arquivo ser salvo sem chamar a caixa Salvar Como RichEdit1->Lines->SaveToFile(Caminho_Abrir); else // seno // a caixa de dilogos Salvar Como ser Chamada Salvar1Click(Sender); }

Vamos agora suspender, por algum tempo, a construo do Editor de Textos, a fim de abordarmos alguns pontos muito importantes. Brevemente retornaremos s lies.

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 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 diferencilas 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 ativado para atribuir o caracter A varivel ch, exibindo esse valor no Caption de SpeedButton1. Quando o boto do mouse for liberado, o evento OnMouseUp ser ativado para alterar o valor da varivel para b, exibindo esse valor no Caption de SpeedButton1.

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

#include "Unit1.h" //-------------------------------------------------------------------------#pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //-------------------------------------------------------------------------// declara uma varivel char visvel pelos eventos de SpeedButton1 char ch; //-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //-------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1MouseDown(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { ch = 'A'; // atribui A para a varivel ch SpeedButton1 -> Caption = ch; } //-------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1MouseUp(TObject *Sender, TMouseButton Button, TShiftState Shift, int X, int Y) { ch = 'b'; // atribui b para a varivel ch SpeedButton1 -> Caption = ch; } //--------------------------------------------------------------------------

O C++Builder implementa a funo sizeof() que nos permite visualizar o tamanho, em bytes, de uma varivel ou de um tipo de dados:
//-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { double Dbl; Edit1 -> Text = AnsiString(sizeof(Dbl)) + " bytes"; // retorna pelo nome da varivel /* retorna o valor pelo tipo de dados*/ Edit2 -> Text = AnsiString(sizeof(bool)) + " byte"; RichEdit1 -> Clear(); // apaga o contedo de RichEdit1

for (int linha = 0; linha <= 3; linha ++) // Em breve estudadremos o loop for RichEdit1 -> Lines -> Insert(linha, ""); // prepara RichEdit1 para receber // as quatro linhas de strings RichEdit1 -> Lines-> Strings[0] String(sizeof(char)); RichEdit1 -> Lines-> Strings[1] String(sizeof(int)); RichEdit1 -> Lines-> Strings[2] String(sizeof(String)); RichEdit1 -> Lines-> Strings[3] sizeof(AnsiString)); ShowMessage(sizeof(long double)); } //-------------------------------------------------------------------------= "Tamanho de char = " + = "Tamanho de int = " + = "Tamanho de String = " + = "Tamanho de AnsiString = " + AnsiString(

Atribuio de valores a variveis


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

Com o operador de atribuio = atribumos valores s variveis:


i = 43;

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

Podemos, inclusive, declarar mais de uma varivel na mesma instruo, bem como misturar declaraes com inicializaes:
// declararamos 5 variveis das quais inicializamos duas (i3 e i4) int i, i2, i3 = 10, i4 = 15, i5;

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

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!

Variveis signed e unsigned


(com e sem sinal)

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

A tabela abaixo exibe os valores possveis para os tipos de dados, com ou sem os modificadores de tipo:

Tipo char unsigned char signed char int unsigned int signed int short int unsigned short int signed short int long int signed long int unsigned long int

bytes 1 1 1 4 4 4 2 2 2 4 4 4

possveis valores -128 a 127 0 a 255 -128 a 127 -2147483648 a 2147483647 0 a 4294967295 -2147483648 a 2147483647 -32768 a 32767 0 a 65535 -32768 a 32767 -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.

O programa abaixo mostra-nos alguns limites de valores:

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

Excedendo o limite de uma varivel

Se tentarmos atribuir um valor fora da faixa que a varivel pode conter, ela continuar a partir do zero, se for unsigned; porm, se for

do tipo signed, continuar a armazenar dados a partir do menor valor negativo. O Exemplo abaixo leva um SpeedButton e um ComboBox no Form. Quando o usurio clicar o boto, o programa mostrar o resultado de se tentar atribuir valores no contemplados pela varivel.
//-------------------------------------------------------------------------__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { ComboBox1 -> Text = "Excedendo limites de variveis ..."; } //-------------------------------------------------------------------------void __fastcall TForm1::SpeedButton1Click(TObject *Sender) { ComboBox1 -> Text = "Veja abaixo os novos valores ..."; int i = 2147483647; ComboBox1 -> Items -> ComboBox1 -> Items -> ComboBox1 -> Items -> ComboBox1 -> Items -> unsigned int ComboBox1 -> String(Ui)); ComboBox1 -> ComboBox1 -> ComboBox1 -> Add("Limite para int = " + String(i)); Add("Limite + 1 = " + String(i + 1)); Add("Limite + 2 = " + String(i + 2)); Add("");

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

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

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

Operaes matemticas com unsigned

J sabemos que uma varivel unsigned no pode ser atribuda com valores negativos. Se, numa operao matemtica, tivermos um resultado menor do que zero para uma varivel unsigned, no momento em que o clculo atingir o primeiro valor negativo (-1) a operao remetida para o maior valor do tipo do dado, de onde o programa dar continuidade aos clculos com os valores restantes.

O exemplo a seguir usa um Label e um Timer no Form. So declaradas duas variveis globais do tipo unsigned int, sendo que uma funcionar como base do clculo da subtrao e a outra como valor a ser subtrado. O Label ficar piscando no Form, ou melhor, o Timer far com que o Label fique visvel e depois de alguns instantes invisvel, e depois visvel, e depois invisvel e assim sucessivamente. Ajustamos o intervalo de tempo para 500, mas voc pode alterar o valor para mais ou menos, no Code Editor ou no Object Inspector. Haver um decremento (diminuio do valor em razo de 1) do nmero apresentado no Label, a cada piscada. Ou seja, o primeiro valor apresentado ser 10; o segundo, 9; o terceiro, 7; e assim por diante. Observe bem o que acontecer depois que 0 (zero) for

apresentado no Label, onde, equivocadamente, poderamos estar esperando algum valor negativo:
//-------------------------------------------------------------------------#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 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:

// // // // // //

DSTRING.H - Support for delphi strings in C++ (AnsiString and template<sz> SmallString) $Revision: 1.25.1.6 $ $Date: 13 Jan 1999 16:32:30 $ Copyright (c) 1997, 1998 Borland International

#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); // C++ style 'sprintf' (NOTE: Target buffer is the string) // AnsiString& __cdecl sprintf(const char* format, ...); // Returns *this int __cdecl printf(const char* format, ...); // Returns formatted length static AnsiString __fastcall FormatFloat(const AnsiString& format, const long double& value); static AnsiString __fastcall FloatToStrF(long double value, TStringFloatFormat format, int precision, int digits); static AnsiString __fastcall IntToHex(int value, int digits); static AnsiString __fastcall CurrToStr(Currency value); static AnsiString __fastcall CurrToStrF(Currency value, TStringFloatFormat format, int digits); // Constructors __fastcall AnsiString(): Data(0) {} __fastcall AnsiString(const char* src); __fastcall AnsiString(const AnsiString& src);

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); __fastcall AnsiString(unsigned int); __fastcall AnsiString(long); __fastcall AnsiString(unsigned long); __fastcall AnsiString(__int64); __fastcall AnsiString(unsigned __int64); __fastcall AnsiString(double src); __fastcall AnsiString(const WideString &src); // Destructor __fastcall ~AnsiString();

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

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

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

Uma vez definida, a String poder ser usada, por exemplo, para alterar o Caption de controles:

//-------------------------------------------------------------------------void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiString Meu_Cao; Meu_Cao = " O Tobby um vira-lata, que s sabe latir, latir e latir..."; Label1->Caption = Meu_Cao; } //--------------------------------------------------------------------------

Tambm poder ser usada para preencher um controle Edit:


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

Um texto introduzido num Edit box, por exemplo, , por padro, considerado uma String, visto que o compilador no pode deduzir que espcie de dado ou valor o usurio deseja manipular. Por essa razo, depois que um valor foi fornecido para um controle que fundamenta-se na classe AnsiString como base de seu contedo, para executar qualquer operao matemtica com tal String, devemos convert-la para o tipo de dado desejado. Para essa finalidade podemos, por exemplo, usar a funo StrToInt():
void __fastcall TForm1::Button1Click(TObject *Sender) { Label1->Caption = "111"; int i = StrToInt(Label1->Caption) - 11; Edit1->Text = i; }

Conforme apresentado, a classe AnsiString prov um grande nmero de construtores que nos permitem a criao de strings de qualquer espcie:

Por exemplo, podemos usar:

um caracter:
AnsiString Simbolo = 'T';

um inteiro
AnsiString Int = 120;

um long int
AnsiString LongoInt = -73495745;

um valor ponto flutuante:


AnsiString PtoFlut = 675.15;

Um double:
AnsiString DplPrec = 2.15e28;

um string
AnsiString AloTher = "Al, Thrbio";

Qualquer dessas variveis pode ser declarada usando os construtores equivalentes:


//-------------------------------------------------------------------------AnsiString Simbolo('T'); AnsiString Int(120); AnsiString AloTher("Al, Thrbio");

AnsiString PtoFlut(675.15); AnsiString LongoInt(-73495745); AnsiString DplPrec(2.15e28); //--------------------------------------------------------------------------

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

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

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

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

um valor ponto flutuante:


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

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

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

Nota: Voc deve ter notado o uso de nomes de tipos diferentes dos apresentados anteriormente.

Por exemplo:

chamamos o tipo int de Integer, o tipo float de Single; o tipo double de Double ...

Por que ser?

No incio do arquivo dstring.h vemos a incluso do arquivo de cabealho sysmac.h:

#include <sysmac.h>

NOTA: Logo abordaremos o uso da palavra typedef para criar outro nome para um tipo de dados:

Vejamos um trecho do arquivo sysmac.h:

class PACKAGE TVarArray; typedef TVarArray *PVarArray;

typedef bool typedef int -2147483648..2147484647 typedef char typedef wchar_t character typedef signed char -128..127 typedef short -32768..32767 typedef unsigned char

Boolean; Integer;

// //

Char; WideChar;

// 0..255 // Unicode

Shortint;

//

Smallint;

//

Byte;

// 0..255

typedef unsigned short typedef unsigned long 0..4294967295 typedef void* typedef char typedef signed long -2147483648..2147484647 typedef unsigned int 0..2147484647 typedef long double

Word; DWord;

// 0..65535 //

Pointer; AnsiChar; Longint;

// // //

Cardinal;

//

real

Extended;

// 10 byte

real

typedef float

Single;

// 4 byte

real

typedef double

Double;

// 8 byte

shortstring formalparm

typedef char* const

Openstring; file; Text; TextFile; PChar; PAnsiChar; PWideChar; ByteBool; WordBool; LongBool; String;

// D16 string/D32

typedef void* typedef void* typedef Text typedef char* typedef char* typedef wchar_t* typedef unsigned char typedef unsigned short typedef Cardinal typedef AnsiString

// // // // // // // // // // // // // //

typedef SmallStringBase<255> ShortStringBase; typedef SmallString<255> typedef ShortString* typedef AnsiString* ShortString; PShortString; PAnsiString;

typedef PAnsiString typedef WideString* typedef Extended* typedef Currency* typedef Variant* typedef __int64 obsolete typedef GUID typedef TGUID* typedef HRESULT

PString; PWideString; PExtended; PCurrency; PVariant; LONG64;

// // // // // // !!

TGUID; PGUID; HResult;

// // //

typedef Parameter);

Integer

__fastcall

(*TThreadFunc)(Pointer

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

typedef struct TVarData *PVarData;

Os nomes direita representam os sinnimos que podem ser usados em substituio aos tipos bsicos. Por exemplo, Boolean pode ser usado em substituio ao tipo bool.

Nas prximas lies abordaremos vrias implementaes de AnsiString.

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

Funes que modificam strings


Agora conheceremos algumas implementaes do tipo AnsiString. Embora tenhamos, para facilidade de compreenso, nos referido s instncias de classes como variveis, tecnicamente isso est incorreto. Na verdade, a instncia de uma classe (AnsiString, por exemplo) denominada objeto. E os objetos possuem funesmembro que facilitam sua manipulao. Essas funes-membro podem ser acessadas atravs do operador ponto ..

Vejamos alguma funes-membro utilizadas para modificar strings.

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

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

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

Delete()
AnsiString& __fastcall Delete(int index, int count);

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

SetLength()
AnsiString& __fastcall SetLength(int newLength);

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

Pos()

int __fastcall Pos(const AnsiString& subStr) const;

a posio do primeiro caracter de uma substring especificada na string. Se a substring no for encontrada na string, Pos() retorna zero.
void __fastcall TForm1::Label1Click(TObject *Sender) { AnsiString test = "O_grande_teste_est_feito"; Label1->Caption = test.Pos("est"); }

LowerCase() e UpperCase()
AnsiString AnsiString __fastcall LowerCase() const; __fastcall UpperCase() const;

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

Funes que modificam strings


AnsiString ... continuao

AnsiString AnsiString AnsiString AnsiString

__fastcall __fastcall __fastcall __fastcall

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

Trim(), TrimLeft()e TrimRight()


AnsiString AnsiString AnsiString __fastcall Trim() const; __fastcall TrimLeft() const; __fastcall TrimRight() const;

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

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

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

O grande teste est

SubString()
AnsiString __fastcall SubString(int index, int count) const;

Retorna uma substring especificada de uma string. A substring inicia a contagem dos caracteres em index e termina de cont-los em count.

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

Nota: Como voc deve ter observado, j temos utilizado AnsiString em diversas oportunidades. Tambm j utilizamos a denominao String que anloga ao uso de AnsiString (Lembre-se da palavrachave 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:

void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiString Teste = "abcdefghijlmnopqrstuvxz"; ShowMessage((String)"A posio de 'q' : " + AnsiPos('q', Teste));

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

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

Percebemos que a funo em questo trata da converso de valores inteiros para hexadecimais, devolvendo AnsiString, onde int

value o valor a ser convertido e int digits o nmero de

dgitos devolvido pela funo na converso:

void __fastcall TForm1::Label1Click(TObject *Sender) { Label1->Caption = IntToHex(100000, 10); }

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

AnsiString continuao...
(operadores relacionais)
Embora ainda no tenhamos abordado o tema (fato reservado para lies futuras), j tivemos oportunidade de apreciar exemplos com os comandos if e else. Por enquanto tenhamos em mente que esses comandos so usados basicamente para efetuar comparaes do tipo: Se A maior do que B, faa isso;

Seno, faa aquilo. No caso acima, o termo maior est representando o operador relacional >. Para mais detalhes, d uma olhadinha no tpico que trata tal assunto. Ansistring implementa mtodos para tratamento de operadores relacionais:
// Comparisons bool __fastcall bool __fastcall bool __fastcall bool __fastcall bool __fastcall bool __fastcall int __fastcall int __fastcall operator ==(const AnsiString& rhs) const; operator !=(const AnsiString& rhs) const; operator <(const AnsiString& rhs) const; operator >(const AnsiString& rhs) const; operator <=(const AnsiString& rhs) const; operator >=(const AnsiString& rhs) const; AnsiCompare(const AnsiString& rhs) const; AnsiCompareIC(const AnsiString& rhs) const; //ignorecase

Vejamos outra implementao de AnsiString:


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

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

podemos escrever um cdigo mesclando operadores relacionais com essa funo:


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

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

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

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

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

A palavra-chave typedef

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

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

A diretiva #define

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

#define Kelvin -273

Embora Kelvin no tenha sido declarado como nenhum tipo em particular (char, float, AnsiString etc), o compilador saber lidar

com os dados da melhor forma possvel em virtude do estilo da declarao. Por exemplo:
void __fastcall TForm1::Button1Click(TObject *Sender) { #define Kelvin -273 #define Frase "Ibirarema uma pequena cidade do Estado de So Paulo!" #define pi 3.141592653589 #define letra 'A' /* Essas constantes no so to constantes afinal. Se, mantendo a declarao anterior, fizssemos uma nova declarao para pi: #define pi 10 o compilador aceitaria esse novo valor desconsiderando o anterior!!!!!*/ Label1 -> Caption = Frase "\n" + AnsiString(Kelvin * pi) + "\n" + letra; }

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

Em captulos posteriores, estudaremos essa diretiva com detalhes.

Você também pode gostar