Vous êtes sur la page 1sur 38

Programao orientada a objetos

com C / C++ em ambiente


multiplataforma
? Parte

1 Fundamentos de C / C++

verso 2.0 de 28 de Fevereiro de 2001


? Por

Sergio Barbosa Villas-Boas

www.del.ufrj.br/~villas
villas@del.ufrj.br

Hello World
// hello.cpp

build

#include <stdio.h>
void main() {
printf("Hello World\n");
}

compilao

ligao
(link)

hello.exe

Legenda:
c:\>hello?
Hello World
c:\>

arquivo texto
arquivo binrio
console

Projetos em C/C++
? Um

projeto a forma de criar um


programa executvel a partir de mais
de um programa fonte *.c (*.cpp).
? Compiladores diferentes tem formas
diferentes de informar quais arquivos
fonte fazem parte de um projeto (ainda
que usem os mesmos arquivos fonte).

Projetos em C/C++ (1)


// f1.c
void f1_1() { /* ... */ }
void f1_2() { /* ... */ }
void f1_3() { /* ... */ }

comp.

f1.obj
f1_1
f1_2
f1_3

// f2.c
void f2_1() { /* ... */ }
void f2_2() { /* ... */ }
void f2_3() { /* ... */ }

comp.

f2.obj
f2_1
f2_2

// fn.c

comp.

f2_3
...
fn.obj
fn_m

biblioteca
padro
Projetos em C/C++)2 (
Projetos em C/C++)2 (
Projetos em C/C++)2 (

f1.obj
f1_1
f1_2
f1_3
f2.obj
f2_1
f2_2
f2_3
...
fn.obj
fn_m

NomeDoProjeto.exe
funes da
biblioteca padro
biblioteca
(standard library)
padro

ligao
(link)

f1_1
f1_2
f1_3
f2_1
f2_2
f2_3
main
other
fn_m

preciso que
haja a funo
main no
executvel
final

Compilao (1)
? Cada

arquivo fonte *.c (*.cpp) compilado


gerando *.obj (ou *.o).
? Cada arquivo fonte *.c (*.cpp) compilado como
se outros arquivos do projeto no existissem.
? No incio da compilao de cada arquivo *.c
(*.cpp), o compilador apenas conhece o
vocabulrio das palavras rerservadas, e a
gramtica da linguagem C/C++.
? O compilador deve conseguir compilar o cdigo
fonte numa nica passagem, ou haver erro de
compilao.

Compilao (2)
? Ao

analisar um trecho de cdigo fonte, o


compilador faz uma das 2 coisas:
Gera cdigo, ou
Aprende o significado de novos identificadores, e
com isso passa a poder compilar com o que
aprendeu.

?O

compilador no pode gerar cdigo a partir


de identificadores que no tenham sido
previamente declarados. A tentativa de fazelo gera erro de compilao.
? Um mesmo arquivo fonte *.c (*.cpp) pode
pertencer a mais de um projeto.

// t1.cpp
#include <stdio.h>
// declara e define
// a funo f1
// (o identificador f1)
void f1() {
// chama a funo printf
printf("Hello");
}
void main() {
f1(); // chama a funo f1
/* a chamada da funo f1
compatvel com a declarao
do identificador f1. */
}

Exemplode compilao
(1)
Exemplode compilao
(1)
Exemplode compilao
(1)

// t2.cpp
#include <stdio.h>
/* Declara a funo f1
(o identificador f1)
prottipo da funo f1.
Essa linha no gera cdigo,
mas faz o compilador aprender
o sifnificado do identificador
f1 */
void f1();
void main() {
f1(); // chama a funo f1
}
/* define a funo f1, sendo
que essa definio compatvel
com o significado do mesmo
identificador previamente
declarado */
void f1() {
// chama a funo printf
printf("Hello");
}

// t1.cpp
#include <stdio.h>
void f1() {
printf("hello\n");
}

biblioteca
padro
(standard
library)

t1.obj
f1

comp.

main

void main() {
f1();
}

link
projeto.exe
printf

c:\>projeto?
hello
c:\>

f1

Construindo executvel
o
Construindo executvel
o
Construindo executvel
o

main

// t2.cpp
#include <stdio.h>
void f1();

biblioteca
padro
(standard
library)

t2.obj
f1

void main() {
f1();
}

comp.

main

void f1() {
printf("hello\n");
}

link
// t2a.cpp
#include <stdio.h>
void main() {
f1(); // No compila.
// O que significa f1 ?
}

projeto.exe
printf
main

Exemplode compilao
(2)
Exemplode compilao
(2)
Exemplode compilao
(2)

void f1() {
printf("hello\n");
}

f1

// t3.cpp
void f1();
void main() {
f1();
}
// t4.cpp
#include <stdio.h>
void f1() {
printf("Hello");
}

t3.obj

comp.

main

biblioteca
padro
(standard
library)

t4.obj

comp.

f1

Exemplode compilao
(3)
Exemplode compilao
(3)
Exemplode compilao
(3)

link
projeto.exe
printf
main
f1

Ligao de blocos (link) (1)


? Num

mesmo projeto, no pode haver entidades


(funes ou objetos) globais com mesmo
identificador.
? No pode haver programa executvel sem a
funo global main. (Em Windows, WinMain)
f1.obj

Erro de Link !

myFun

f2.obj
myFun

ligao
(link)

Tentativa de gerar um
executvel com 2 funes
globais com mesmo
identificador

...

Ligao de blocos (link) (2)


?A

ordem com em que os blocos se


posicionam no executvel final
irrelevante.
printf

printf

f1

f1

main

main

f1

printf

printf

main

main

f1

Equivalentes !

Ligao de blocos (link) (3)


?A

incluso de funes que nunca so


chamadas faz aumentar o cdigo executvel
final, mas no afeta o desempenho do
programa.

// t5.cpp
#include <stdio.h>
void f1() {
printf("Hello");
}
void main() {
f1();
}
void ninguemMeChama() {
printf("Nada");
}

printf

comp.

ligao
(link)

f1
main
ninguemMeChama

Ligao de blocos (link) 4)


? Os

identificadores usados no programa


(nomes das funes, nomes de variveis,
etc) no aparecem em lugar nenhum do
executvel final. O linker os retira. (Desde
que o programa esteja na verso release;
caso esteja na verso debug, os
identificadores precisam existir para serem
utilizados no processo de debug.)

Conceitos Bsicos (1)


? Tipos padro

So os tipos pr-definidos pela linguagem:


bool, char, int, long, float, double , long double
unsigned int, unsigned char, unsigned long
(void)

? Variveis

(locais, globais)

So regies de memria que podem armazenar


dados de um determinado tipo.
? Identificador

nome de funo, varivel ou tipo.

Conceitos Bsicos (2)


Constante literal
serve para carregar variveis.
void main() {
bool b = true;
int a = 4;
float f = 1.1;
double d = 1.1;
long double ld = 1.1;
char c = 'a';
char *szStr = "Nome de algum";
// "..." retorna ponteiro para char
}

Conceitos Bsicos (3)


? Escopo

regio para se acrescentar cdigo. Definido entre


{ e }.
void printAge(int age) {
cout << "Idade = " << age << endl;
}

Uma varivel (objeto) s existe no escopo em que


definida. O objeto construdo no momento
descrito no programa e destrudo automaticamente
quando sai do escopo. Uma varivel global existe
para todas as funes.

Stack Pointer
void f3() {
}

f2

void f2(int k) {
f3();
}

if1

stack pointer

f1

void f1() {
int if1 = 1;
f2(if1);
}
void main() {
f1();
}

Chamadas de funo
main();

f1();

f2();

f1();

f2();

f3();

f3();

10

Funes: parmetros e retorno


Prottipo da Funo (declarao)
<returnType> funName(<par1, par2, etc>);
Descrio da Funo (definio)
<returnType> funName (<par1, par2, etc>)
{
// code
Exemplo de declarao:
}
void printAge(int age);
// no h retorno, portanto o
// retorno cancelado (void)
Exemplo de definio:
void printAge(int age)
{
cout << "Sua idade << age << endl;
}

Outros exemplos de funes (1):


Exemplo: retorna seno ao quadrado
double sin2(double x) {
double ret = sin(x);
ret *= ret; // ret = ret * ret;
return ret;
}
Exemplo de uso:
void main(){
double d = 0.4;
double f = sin2(d);
}

11

Outros exemplos de funes (2):


Exemplo: retorna mdia de 3 nmeros
double mean3(double a, double b, double c) {
double ret = (a+b+c)/3;
return ret;
}
Exemplo de uso:
void main(){
double f = mean3(1.1, 2.2, 3.3);
}

Arquivos de cabealho (header) (1)


? So

arquivos fonte, *.h.


? Ao contrrio dos fontes *.c (*.cpp), no gerase arquivo objeto a partir de arquivo header.
? A sua finalidade ser includo em arquivos
*.c (*.cpp).
? Tipicamente os arquivos header contm
prottipos de funes e outras informaes
que no geram cdigo, mas que so
indispensveis para a compilao.

12

biblioteca
padro
// mymath.cpp
#include<math.h>
double sin2(double x) {
double ret = sin(x);
ret *= ret;
return ret;
}
// mymath_header.h
double sin2(double x);

// sin2_main.cpp
#include"mymath_header.h"
void main(){
double f = sin2(0.4);
}

ligao
(link)

mymath.obj

comp.

No gera-se
mymath_header.obj
sin2_main.obj

projeto.exe

Arquivosdecabealho(header
() )2
Arquivosdecabealho(header
() )2
Arquivosdecabealho(header
() )2

comp.

Arquivos de cabealho (header) (3)


?O

compilador prov diversos arquivos


header, chamados header padro.
? Esses arquivos contm (entre outras coisas)
os prottipos das funes da biblioteca
padro. Ex: printf.
? Os header padro so includos usando a
diretiva #include com <, >.
Ex: #include <stdio.h>
? Os header do usurio so includos usando a
diretiva #include com ", ".
Ex: #include "mymath_header.h"

13

Arquivos de cabealho (header) (4)


?

Poderia haver um nico header padro. Seria c.h.


Mas nesse caso o arquivo seria muito grande e a
compilao demoraria muito. Por isso, o compilador
possui diversos headers padro.
? Dependendo da funo da biblioteca padro que se
deseja usar, inclui-se um ou outro header padro.
Saber qual header corresponde a qual funo da
biblioteca padro informao que se obtm do help
do sistema (isto , no preciso decorar).
Ex: a funo printf requer o header stdio.h

Bibliotecas (1)
?

Uma biblioteca um conjunto de *.obj (ou *.o), que


so reunidos num nico arquivo para facilitar a sua
manipulao.
? Uma biblioteca no executvel. Ela serve para ser
includa num projeto que gera um executvel (ou
outra biblioteca).
? A nica diferena da biblioteca padro para uma
biblioteca que o usurio faa o fato de que em
qualquer projeto a biblioteca padro
automaticamente includa.
? Em Windows, a extenso usada *.lib. Em unix, a
extenso *.a.

14

// f1.cpp
...

// f2.cpp
...

comp.

comp.

f1.obj
f1_1
f1_2
f1_3

ferramenta de criao
de bibliotecas
Bibliotecas( )2
Bibliotecas( )2
Bibliotecas( )2

mylib.lib
mylib.a

f2.obj
f2_1
f2_2

f1_1
f1_2
f1_3
f2_1
f2_2
f2_3
f3_1
f3_2
f3_3

f2_3

// f3.cpp
...

comp.

f3.obj
f3_1
f3_2
f3_3

// usemylib.cpp
#include "mylib.h"
void main () {
f1_2();
f1_3();
}

Pelo menos uma funo


desse bloco usada no
projeto, portanto o
bloco copiado
no programa final
Nenhuma funo desses
blocos usada nesse
projeto, portanto os
blocos no so copiados
no programa final

usemylib.obj

comp.

main

ligao
(link)

Bibliotecas( )3
Bibliotecas( )3
Bibliotecas( )3

biblioteca
padro
f1_1
f1_2
f1_3
f2_1
f2_2
f2_3
f3_1
f3_2
f3_3

projeto.exe
main

f1_1
f1_2
f1_3

15

Controle de fluxo (while)


? Laos

(loops)

while
do .. while
for

#include<iostream.h>
void main () {
int i=0;
while (i < 5) {
cout << "i=" << i << endl;
i++; // i = i + 1;
}
}

i=0
i=1
i=2
i=3
i=4

Controle de fluxo (do.. while)


? Laos

(loops)

while
do .. while
for

#include<iostream.h>
void main () {
int i=0;
do {
cout << "i=" << i << endl;
i++; // i = i + 1;
} while (i < 5);
}

i=0
i=1
i=2
i=3
i=4

16

Controle de fluxo (for)


? Laos

(loops)

while
do .. while
for

#include<iostream.h>
void main () {
for (int i=0; i<5 ; i++)
cout << "i=" << i << endl;
}
for (<1> ; <2> ; <3>)
<4>;
{

i=0
i=1
i=2
i=3
i=4

<1>;
while (<2>) {
<4>;
<3>;
}
}

Controle de fluxo (switch)


#include <iostream.h>
void main() {
int i;
Entre com i:1?
Caso 1
cout << "Entre com i:";
cin >> i;
c:\>program?
switch(i) {
Entre com i:2?
Caso 2
case 1:
cout << "Caso 1" << endl;
c:\>program?
Entre com i:3?
break;
Caso implcito
case 2:
cout << "Caso 2" << endl;
break;
default:
cout << "Caso implcito" << endl;
break;
}
}

17

rvalue e lvalue
#include <iostream.h>
void main () {
float f = 1.1;
float & lvalue _f = f;
lvalue_f = 2.2;
cout << "f=" << f << endl;
cout << " lvalue_f=" << lvalue _f << endl;
cout << &f << " - " << & lvalue_f << endl;
}

f=2.2
lvalue_f=2.2
0x0012FF7C - 0x0012FF7C

Array
#include <iostream.h>
void main() {
float f[5];
for (int i=0 ; i < 5 ; i++) {
f[i] = 1 + i / 10.0;
cout << f[i] << endl;
}
}
#include <iostream.h>
#define N 5
void main() {
float f[N];
for (int i=0 ; i < N ; i++) {
f[i] = 1 + i / 10.0;
cout << f[i] << endl;
}
}

left
valu
e

a=b;

ue
val
t
h
rig

void main () {
int i;
i = 5; // OK
5 = i; // error:
// '=' : left operand
// must be l-value
}

f
lvalue_f

<float>
<float &>

M programao
2 constantes
relacionadas em
trechos diferentes
do programa.
1
1.1
1.2
1.3
1.4

f <float*>
f[0]
f[1]
f[2]
f[3]
f[4]

<float>
<float>
<float>
<float>
<float>

18

Ponteiros (1)
na
nd
nc

CPU

mem

endereos (address)
dados
controle

outro
perifrico

Em CPU 386 ou mais moderno, na=32


(isto , 4 bytes ou 8 nibbles)

Ponteiros (2)
?O

tamanho de um ponteiro relacionado ao


nmero de fios no barramento de endereos
da CPU. No h relao entre o tamanho do
ponteiro e o tamanho do que ele aponta.
? O ponteiro pode apontar para dados ou para
cdigo.
Apontar para dados apontar para variveis
(objetos).
Um ponteiro pode apontar para uma varivel do
tipo ponteiro. Nesse caso trata-se de ponteiro
para ponteiro. No h limite para o nmero de
vezes que um ponteiro aponta para um ponteiro.
Apontar para cdigo apontar para uma funo.

19

Ponteiros (3)

&f

f
pf

<float>
<float*>

#include<iostream.h>
void main () {
float f = 1.1;
float *pf;
pf = &f;
*pf = 2.2;
cout << "f=" << f << endl;
cout << "pf=" << pf << endl;
}
f=2.2
pf=0x0066FDF4

Ponteiro para ponteiro


#include<iostream.h>
void main () {
float f = 1.1;
float *pf = &f;
float **ppf = &pf;
float ***pppf = &ppf;
*pf = 2.2;
cout << f << endl;
**ppf = 3.3;
cout << f << endl;
***pppf = 4.4;
cout << f << endl;
}

&f
f
&pf
pf
&ppf
ppf
pppf

<float>
<float*>
<float**>
<float***>

2.2
3.3
4.4

20

f <float*>
f[0]
f[1]
f[2]
f[3]
f[4]

Arrays e ponteiros

<float>
<float>
<float>
<float>
<float>

? *(p+i)

equivalente a p[i]
? Na soma de um ponteiro com um inteiro,
automaticamente multiplica-se o inteiro pelo
tamanho do tipo
p+i*sizeof(TYPE)
?O

significado sinttico (nmero de vezes


ponteiro para ponteiro) de * a esquerda o
mesmo de colchete [ ] a direita.

Parmetros por valor e por


referncia (1)
#include <iostream.h>
void f1(float z) {
z = 1.1;
}
void f2(float *x) {
*x = 2.2;
}
void f3(float & v) {
v = 3.3;
}
void main () {
float a = 10.1;
cout << "a=" << a <<
f1(a);
cout << "a=" << a <<
f2(&a);
cout << "a=" << a <<
f3(a);
cout << "a=" << a <<
}

z=a (por valor)


x=&a (pseudo por referncia)
v=a (verdadeiro por referncia)
endl;
endl;
endl;
endl;

a=10.1
a=10.1
a=2.2
a=3.3

21

Parmetros por valor e por


referncia (2)
#include <iostream.h>
void f1(float z) {
z = 1.1;
}
void f2(float * x) {
*x = 2.2;
}
void f3(float & v) {
v = 3.3;
}
void main () {
float a = 10.1;
cout << "a=" << a <<
f1(a);
cout << "a=" << a <<
f2(&a);
cout << "a=" << a <<
f3(a);
cout << "a=" << a <<
}

f1

<float> 1.1

<float> 10.1

f2

&a

<float *> &a

<float> 10.1

endl;

f3

endl;

<float &> 3.3

<float> 10.1

endl;
endl;

Ponteiro para funo


#include<iostream.h>
#include<math.h>
double sin2(double x) {
double ret = sin(x);
ret *= ret;
return ret;
}
double cos2(double x) {
double ret = cos(x);
ret *= ret;
return ret;
}
void main () {
// function pointer
double (*fp)(double);
double x = 0.4;
fp = sin2;
cout << "sin2=" << fp(x) << endl;
fp = cos2;
cout << "cos2=" << fp(x) << endl;
}

fp
x

<double (*)(double)>
<double>

sin2=0.151647
cos2=0.848353

22

Array de ponteiro para funo


#include<iostream.h>
#include<math.h>
double sin2(double x) {
double ret = sin(x);
ret *= ret;
return ret;
}
double cos2(double x) {
double ret = cos(x);
ret *= ret;
return ret;
}
void main () {
double (*fp[2])(double);
// array of function pointer
double x = 0.4;
fp[0] = sin2;
fp[1] = cos2;
cout << "sin2=" << fp[0](x) << endl
<< "cos2=" << fp[1](x) << endl;
}

fp[0] <double (*)(double)>


fp[1] <double (*)(double)>
x
<double>

sin2=0.151647
cos2=0.848353

typedef e ponteiro para funo


#include<iostream.h>
#include<math.h>
double sin2(double x) {
double ret = sin(x);
ret *= ret;
return ret;
}
double cos2(double x) {
double ret = cos(x);
ret *= ret;
return ret;
}
typedef double (*fp_type)(double);
void main () {
fp_type fp[2];
// array of function pointer
double x = 0.4;
fp[0] = sin2;
fp[1] = cos2;
cout << "sin2=" << fp[0](x) << endl
<< "cos2=" << fp[1](x) << endl;
}

fp[0] <double (*)(double)>


fp[1] <double (*)(double)>
x
<double>

sin2=0.151647
cos2=0.848353

23

Alocao de memria (para C++)


alocao de 1 objeto
#include<iostream.h>
void main () {
double *pd;
pd = new double;
*pd = 1.1; // pd[0] = 1.1;
delete pd;
}

alocao de um array de objetos


#include<iostream.h>
#define N 10
void main () {
double *pd;
pd = new double [N];
for (int i=0 ; i < N ; i++)
pd[i] = i + 1.1;
delete [] pd;
}

Tratamento para falha na


alocao de memria
#include<iostream.h>
#include<stdlib.h> // exit
void main () {
double *pd;
pd = new double;
if (!pd) {
cout << "Memory Alloc error" << endl;
exit(1);
}
*pd = 1.1; // p[0] = 1.1;
delete pd;
}

24

Vazamento de memria
(memory leak)

1
0

10010

10

1001010011
10010100

Vazamento de memria (2)

#include<iostream.h>
void main () {
double *pd = new double;
// delete pd;
}

new
delete

Gerente
de memria
alocada

25

#include <crtdbg .h> // include necessary


// use this class for Visual C++ 6.0 only !!
class VBMemCheck {
_CrtMemState s1;
public:
VBMemCheck () { // store memory on constructor
// Send all reports to STDOUT
_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
_CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
_CrtMemCheckpoint( &s1 );
};
void check() {
_CrtDumpMemoryLeaks (); };
};

Vazamento de memria (3)

void do_all () {
double *pd = new double;
}

check

void main () {
VBMemCheck a;
do_all();
a.check ();
}

Essa funo aloca


e no libera memria,
portanto vaza
memria

mark

Vazamento de memria (4)


?A

deteco de vazamento de memria


dependente de compilador (no portvel).
? Um fonte que no vaza memria num
compilador tambm no vai vazar em outro
compilador. Portanto, pode-se testar um
componente de memria para verificar se
ocorre vazamento de memria num
compilador e usar o cdigo em outro
ambiente.

26

Array multidimensional (1)


#include <iostream.h>
#define ROW 3
#define COL 3
typedef double myMatrix [ROW][COL];
void main () {
myMatrix m1,m2,m3;
// double m1[ROW][COL], m2[ROW][COL], m3[ROW][COL];
for ( int i=0 ; i < ROW ; i++) {
for ( int j=0 ; j < COL ; j++) {
m1[i][j] = 1 + i*10 + j*100;
cout << m1[i][j] << " ";
}
cout << endl;
}
}

1 101 201
11 111 211
21 121 221

Array multidimensional (2)


#include <iostream.h>
#define ROW 3
#define COL 3
typedef double myMatrix [ROW][COL];
void main () {
myMatrix m1;
for ( int i=0 ; i < ROW ; i++) {
for ( int j=0 ; j < COL ; j++) {
m1[i][j] = 1 + i*10 + j*100;
cout << m1[i][j] << " ";
}
cout << endl;
}
}

Correto para array


multidimensional
dinmico, mas no
para array
multidimensional
esttico

m1
m1[0]
m1[1]
m1[2]
m1[0][0]
m1[0][1]
m1[0][2]
m1[1][0]
m1[1][1]
m1[1][2]
m1[2][0]
m1[2][1]
m1[2][2]

<double**>
<double*>
<double*>
<double*>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>

27

Array multidimensional esttico


#define ROW 3
#define COL 3
void main () {
double m1[ROM][COL];
}

rea de ponteiros

rea de dados

A rea de ponteiros no existe


em array multidimensional
esttico. Existe apenas a
rea de dados.

m1
m1[0]
m1[1]
m1[2]
m1[0][0]
m1[0][1]
m1[0][2]
m1[1][0]
m1[1][1]
m1[1][2]
m1[2][0]
m1[2][1]
m1[2][2]

<double**>
<double*>
<double*>
<double*>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>

Array multidimensional dinmico


#define TYPE double
#include < iostream.h>
TYPE **allocMatrix(int r, int c) {
TYPE **ret;
ret = new TYPE* [r];
for (int i=0 ; i < r ; i++)
ret[i] = new TYPE [c];
return ret;
}
void fillMatrix (TYPE **p, int r, int c, double d, bool show) {
for (int i=0 ; i < r ; i++) {
for (int j=0 ; j < c ; j++) {
p[i][j] = d;
if (show) cout << p[i][j] << " ; ";
}
if (show) cout < < endl;
}
}
void deleteMatrix (TYPE **p, int r) {
for (int i=0 ; i < r ; i++)
delete [] p[i];
delete [] p;
}
void do_all() {
TYPE **p;
int row = 3 , col = 3 ;
p = allocMatrix (row, col );
fillMatrix(p,row,col ,1.1,true);
deleteMatrix(p,row);
}
void main() {
VBMemCheck a;
do_all();
a.check();
}

m1
m1[0]
m1[1]
m1[2]
m1[0][0]
m1[0][1]
m1[0][2]
m1[1][0]
m1[1][1]
m1[1][2]
m1[2][0]
m1[2][1]
m1[2][2]

<double**>
<double*>
<double*>
<double*>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>
<double>

28

Diretivas de compilao
#define
// diretiva para o pr processador de texto
#include <iostream.h>
#define N 3
#define MY_FUN(x) ((x)*(x))
void main () {
for ( int i=0; i < N ; i++)
cout << "i=" << i << endl;
double d = MY_FUN(3.3+1.1);
cout << "d=" << d << endl;
}

no usar

; (ponto e vrgula)

i=0
i=1
i=2
d=19.36

Diretivas de compilao
# (para string)
#include <iostream.h>
#define PATH(logid,cmd) "/ usr/" # logid "/bin/" #cmd
void main () {
char *mytool = PATH(francisco ,readmail );
// expandido para: char *mytool = "/usr/" "francisco " "/bin /" "readmail ";
// equivalente a: char *mytool = "/usr/francisco /bin/readmail";
cout << mytool << endl;
}

/usr/francisco/bin/readmail

29

Diretivas de compilao ##
concatenao de identificadores
#include <iostream.h>
#define TIPO(a) FUT ## a
#define FUTSAL "futebol de salo"
#define FUTBOL "tradicional futebol de campo"
void main () {
cout << TIPO(SAL) << endl;
cout << TIPO(BOL) << endl;
}

futebol de salo
tradicional futebol de campo

Compilao condicional
#include <iostream.h>
#include <math.h> // sin
#define DEBUG
void show(double z) {
#if 0
/* commented out
double q;
// this function is a test
q = 1.1;
cout << q << endl;
*/
cout << z << endl;
#endif
}

a=0.389418

void main () {
double a,b,c,d;
a = sin(0.4);
#ifdef DEBUG
cout << "a=" << a << endl;
#endif
show(a);
}

30

Argumentos da funo main


#include <iostream.h>
int main(int argc, char **argv) {
for ( int i=0; i < argc ; i++)
cout << "arg ["<< i << "]: " << argv[i] << endl ;
return 0;
}

c:\>program -c filename.dat "my dear sentence"?


arg[0]: c:\USERS\VILLAS\cpp\test\Debug\test.exe
arg[1]: -c
arg[2]: filename.dat
arg[3]: my dear sentence
c:\>

A biblioteca padro C
?

A biblioteca padro de C, que escrita na prpria


linguagem C, contm diversas funes de interesse geral
para programas. Funes para colocar mensagens no
console, para manipular arquivos em disco, etc.
Embora tudo que se faz com C permanea vlido em
C++, no vale a pena aprender a usar a biblioteca padro
C. O prprio Stroupstrup (um dos gurus de C/C++)
recomenda assim. Isso porque com os conceitos de
orientao a objeto, foi feita uma nova biblioteca padro
para C++ com funcionalidade equivalente e ampliada da
biblioteca de C. A biblioteca de C++ mais poderosa e
mais fcil de aprender que a de C.

31

Strings em C/C++(1)
? Em

C/C++, qualquer seqncia dentro


de aspas retorna um ponteiro para char.
A seqncia propriamente dita situa-se
em algum lugar na memria apontado
por esse ponteiro.
? Toda seqncia terminada pelo char
zero.

strcpy(p,szMyStr); // BUG
// para onde est copiando ?
}

&buffer[0]
= buffer

'a'
'b'
'c'
zero
buffer[0]
buffer[1]

buffer[9]

strcat

#include <iostream.h>
#include <string.h>
int main() {
char *szMyStr = "abc";
char *p;
char buffer[10];
strcpy(buffer,szMyStr); // OK
strcat(buffer,"def"); // OK
cout << buffer << endl;

"abc"

strcpy

Strings em C/C++ (2)


strcpy, strcat

'a'
'b'
'c'
zero 'd'
'e'
'f'
zero

!
abcdef

32

Strings em C/C++ (3)


strcpy, strcat
/home/usr/fred/public_html
#include <iostream.h>
#include <string.h>
char *htmlPath(char *userName) {
char *path = "/home/usr";
char *html = "/public_html";
static char buffer[300];
strcpy(buffer,path);
strcat(buffer,userName);
strcat(buffer,html);
return buffer; // BUG
// returning reference to local variable
}

buffer[0]
buffer[1]

buffer[299]

void main() {
char *completePath = htmlPath("fred");
cout << completePath << endl;
}

Constantes de buffer e bug (1)


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

c:\>program?
<algum tipo de erro>
c:\>

char *htmlPath(char *userName) {


char *path = "/home/usr";
char *html = "/public_html";
static char buffer[13]; // buffer pequeno
strcpy(buffer,path);
strcat(buffer,userName);
strcat(buffer,html);
return buffer; // BUG
// returning reference to local variable
}
void main() {
char *completePath = htmlPath("fred");
cout << completePath << endl;
}

33

Constantes de buffer e bug (2)


?

O programa somente no tem bug caso a constante do


buffer seja sempre maior que a maior string que seja
processada.
A experincia mostra que bastante provvel que um
componente de software desenvolvido assim acabe
sendo usado numa situao em que a constante
excedida, e portanto ocorre bug.
Caso haja bug, o comportamento do programa
aleatrio. Isso pior que travar a mquina (pois nesse
caso a identificao do bug seria imediata).
Caso o programador coloque sempre dimenses enormes
para os buffers, estar diminuindo a probabilidade de bug.
Mas estar gastando memria desnecessariamente.

Soluo recommendada para strings (1)


?

Use sempre uma classe de string para


processamento de strings.
? H vrias classes para escolher:
CString
vantagem: perfeita para quem programa para Windows
com VisualC e MFC; desvantagem: no funciona em unix.
string
vantagem: padro; desvantagem: requer verses bastante
modernas do compilador, pois usa namespace.
VBString
vantagem: funciona igual em windows e unix, no usa
namespace, contm mtodos adicionais;
desvantagem: no padro.
(Use a VBString baixando a VBLib de
http://www.del.ufrj.br/~villas/cpplibs/ vblib/)

34

#include <iostream.h>
#include "vblib.h"

Soluo recommendada
para strings (2)

void main() {
VBString a;
a = "12345 ";
VBString b("OI");
VBString c(b);
VBString d = a + b;
cout << "VBLib version: " << VBLIB_VERSION << endl;
cout << "d=" << d << endl;

if (c == b) cout << "c equal to b" << endl;


if (c >= b) cout << "c greater or equal to b" << endl;
if (c < b) cout << "c less than to b" << endl;
if (c <= b) cout << "c less than or equal to b" << endl;
if (a != b) cout << "a not equal b" << endl;
if (a == VBString("12345 ")) // don't use: (a == "12345 ")
cout << "VBString equal to constant" << endl;
a = a + a;
cout << "a=" << a << endl;
// common error:
// a = "abc" + "def"; // can not add 2 pointers directly
// use instead
a = "abc";
VBLib version: February 28th, 2001 - Version 2.0
d=12345 OI
a += "def";
}

c
c
c
a

equal to b
greater or equal to b
less than or equal to b
not equal b

VBString equal to constant


a=12345 12345

Strings em C/C++
Retorno de string com VBString
#include <iostream.h>
#include "vblib.h"

/home/usr/fred/public_html

VBString htmlPath(VBString userName) {


char *path = "/home/usr";
char *html = "/public_html";
VBString buffer;
buffer = path;
buffer += userName;
buffer += html;
return buffer;
}
void main() {
VBString completePath = htmlPath("fred");
cout << completePath << endl;
}

buffer[0]
buffer[1]

buffer[299]

35

VBString (1)

a=123
a=123123
a=123123456
a=1231234567.89
a=abc12
a=abc12.12
a=abc12
a=abc12
entre com algo :abc
a=abc

#include <iostream.h>
#include "vblib.h"
void main() {
VBString a;
a = "123";
cout << "a=" << a << endl;
a = "123" + a;
cout << "a=" << a << endl;
a = a + 456; // int
cout << "a=" << a << endl;
a = a + 7.89111; // double
cout << "a=" << a << endl;
a = "abc";
a += 12;
cout << "a=" << a << endl;
a = "abc";
a += 12.12;
cout << "a=" << a << endl;
a = "abc";
a += "12";
cout << "a=" << a << endl;
a = "abc";
a += VBString("12");
cout << "a=" << a << endl;
cout << "entre com algo:";
cin >> a;
cout << "a=" << a << endl;
}

#include <iostream.h>
#include "vblib.h"

VBString (2)

void main() {
VBString a,b;
a = "123456789";
cout << a << endl;
b = a.beforeFind("56"); // b = "1234";
cout << b << endl;
b = a.afterFind("xx"); // b = ""; // string not found
cout << b << endl;
char *find = "67";
char *replace = "def"; // "12345def89"

a.strchg (find,replace); // (changes a)


// find and replace first occurrence of "find" string
cout << a << endl;
a = "123456789123456789123456789123456789";
find = "34";
replace = "abc"; // "12abc5678912abc5678912abc5678912abc56789"
a.strschg(find,replace); // (changes a)
// find and replace all occurrences of "find" string
cout << a << endl;
a = "abc,def,ghi,123,456,7890,yyy";
char tok = ',';
int n=0;
123456789
b = a.strtok(tok,n);
1234
cout << b << endl;
bool found;
b = a.strtok(tok,n,found);
12345def89
if (!found)
12abc5678912abc5678912abc5678912abc56789
cout << "String not found" << endl;
abc
else
abc
cout << b << endl;
}

36

Converso automtica de
VBString para char*
#include <iostream.h>
#include <string.h>
#include "vblib.h"
void myFun(const char *str) {
cout << "Str:" << str << endl;
}
void myFun2(char *str) {
cout << "Str2:" << str << endl;
}

Str:abc
Str2:abc
Str2:abc
abc

void main() {
VBString a = "abc";
char *p = a.getStr(); // get the char* inside VBString
myFun(a); // automatic conversion of VBString
// myFun2(a); // error. Can't convert
myFun2(p);
myFun2(a.getStr());
char buffer[300];
strcpy(buffer,a); // automatic conversion of VBString
cout << buffer << endl;
}

Refazendo a funo htmlpath


#include <iostream.h>
#include <string.h>
VBString htmlPath(const char *userName) {
VBString ret;
char *path = "/home/usr";
char *html = "/public_html";
ret = path;
ret += userName;
ret += html;
/home/usr/fred/public_html
return ret;
}
void main() {
char *completePath = htmlPath("fred");
cout << completePath << endl;
}

37

Maquiagem de tipos (type cast)


#include <iostream.h>
void main () {
float f;
f = 2/5; // diviso de
cout << "f = " << f <<
f = (float)2/(float)5;
cout << "f = " << f <<
}

ints
endl; // resultado errado
// type cast garante diviso de floats
endl; // resultado certo

f = 0
f = 0.4

Maquiagem de tipos (type cast) (2)


?

H tipos que no se pode maquiar para outros. Ex:


float no pode ser maquiando para float*.
? Um ponteiro para qualquer coisa maquivel para
ponteiro para qualquer outra coisa.
? int maquivel para ponteiro e vice-versa.
void main () {
int i, *pi;
i = 3;
pi = (int*)i; // OK
i = (int)pi; // OK
float f, *pf;
f = 3.3;
pf = (float*)f; // error
}

38

Vous aimerez peut-être aussi