Академический Документы
Профессиональный Документы
Культура Документы
ndice Geral
C foi escolhido pois possua uma proposta de uso genrico, era rpido e tambm portvel para
diversas plataformas. Algumas outras linguagens que tambm serviram de inspirao para o
informtico foram ALGOL 68, Ada, CLU e ML. Novas caractersticas foram adicionadas, como
funes virtuais, sobrecarga de operadores e funes, referncias, constantes, controle de
memria pelo usurio, melhorias na checagem de tipo e estilo de comentrio de uma linha (//).
A primeira verso comercial da linguagem C++ foi lanada em outubro de 1985.
Em proposta geral, C++ deve ser to eficiente e portvel quanto C, sendo desenvolvida
para ser uma linguagem com tipos de dados estticos.
C++ desenvolvido para ser o quanto mais compatvel com C possvel, fornecendo
transies simples para cdigo C.
C++ desenvolvido para suportar mltiplos paradigmas de programao,
principalmente a programao estruturada e a programao orientada a objetos,
possibilitando mltiplas maneiras de resolver um mesmo problema.
C++ desenvolvido para fornecer ao programador mltiplas escolhas, mesmo que seja
possvel ao programador escolher a opo errada.
Grande parte dos programas da Microsoft, incluindo Windows XP, Windows NT,
Windows 9x, Pacote Office, Internet Explorer, Visual Studio e outros.
Sistemas Operacionais como o j citado Windows, Apple OS X, BeOS, Solaris e
Symbian (sistema operacional para celulares).
Bancos de dados como SQL e MySQL.
Aplicaes Web, como a mquina de busca Google e o sistema de comrcio virtual da
Amazon.
Aplicaes grficas como os programas da Adobe (Photoshop, Illustrator), Maya e
AutoCAD.
Jogos em geral, como o Doom III.
A lista enorme e poderia se estender por muitas e muitas pginas. Atualmente C++ ,
juntamente com Java, a linguagem de programao comercial mais difundida no mundo.
memria de maneira direta, sem recorrer a abstraes apresentadas por outras linguagens de
alto nvel.
A filosofia que existe por trs da linguagens C e C++ que o programador sabe realmente o
que est fazendo. Estas linguagens quase nunca colocam-se no caminho do programador,
deixando-o livre para us-la de qualquer forma que queira, mas arcando com as
consequncias de seu mau ou incorreto uso. O motivo para essa liberdade na programao
permitir ao compilador criar cdigos muito rpidos e eficientes, deixando a responsabilidade da
verificao de erros para o programador. O prprio criador de C++, Bjorne Stroustrup afirma
que C faz com que dar um tiro no p seja fcil; C++ torna isso mais difcil, mas quando ns o
fazemos arrebenta com a perna toda. A citao de Stroutrup trata com humor o fato de o C++,
ao possibilitar a programao de alto nvel, ter facilitado a codificao de algoritmos e
organizao de projetos em relao ao C, uma linguagem que requer constante ateno contra
erros lgicos de programao devido sua alta flexibidade. Por outro lado, o C++ possui
nuances da sintaxe e semntica da linguagem muito sutis, difceis de serem identificados, e
que quando no percebidos podem levar a comportamentos indesejados no cdigo.
As principais vantagens e desvantagens do C++ so listadas a seguir:
Vantagens
Desvantagens
Mdulo 2 Compiladores
2.1 O que um Compilador
Toda linguagem de programao possui um tradutor de cdigo. Este tradutor pode ser um
compilador ou um interpretador, dependendo da linguagem. Interpretadores so programas
que lem o cdigo-fonte e executam ele diretamente, sem a criao de um arquivo executvel.
Chamamos de compilador o programa que traduz um arquivo escrito em cdigo de linguagem
de programao (arquivo-fonte) para a linguagem do microprocessador, criando um arquivo
capaz de executar as instrues pedidas (arquivo executvel).
O primeiro passo de um compilador analisar o cdigo presente no arquivo-fonte, verificando
se existem erros de sintaxe. Caso algum erro de sintaxe seja encontrado, a compilao
interrompida para que o programador possa corrijir estes erros. Caso o cdigo no possua
erros o prximo passo do compilador criar um arquivo de cdigo-objeto, que possui as
instrues do programa j traduzidas para a linguagem da mquina e informaes sobre
alocao de memria, smbolos do programa (variveis e funes) e informaes de debug. A
partir deste arquivo de cdigo-objeto, o compilador finalmente cria um arquivo executvel com
o programa compilado, que funciona independente do compilador e realiza as instrues
criadas pelo programador.
2.3 DevC++
O Dev-C++ um compilador freeware das linguagens C, C++ e C#. uma opo muito
interessante, pois de fcil utilizao e aprendizado para usurios novos e possui muitos
recursos avanados para usurios experientes. Alm de, claro, seu download ser gratuito.
2.3.1 - Instalao
A verso mais recente do DevC++ pode ser baixada atravs da pgina
http://www.bloodshed.net/dev/devcpp.html, no link Download. Utilizou-se, na elaborao desta
apostila, a verso do DevC++ beta 9.2, disponvel diretamente atravs do link
http://prdownloads.sourceforge.net/dev-cpp/devcpp-4.9.9.2_setup.exe. O arquivo de instalao
possui aproximadamente 9 megas. Aps o fim do download, preciso clicar duas vezes neste
arquivo para comear a instalao.
A instalao do DevC++ bem simples. Utilizaremos nesta apostila a instalao completa,
escolhendo o item full durante a etapa da instalao mostrada na figura 1.a.
2.3.2 - Interface
Importante: Na primeira vez que iniciamos o Dev-C++, todos os seus menus esto em ingls.
Porm, o programa traduzido para vrias lnguas, inclusive portugus. Para mudar os menus
do programa para a nossa lngua (ou qualquer outra lngua que desejar), basta acessar o menu
Tools -> Enviroment Options. Uma janela se abrir, com vrias opes referentes ao
funcionamento do ambiente de trabalho. Na aba Interface encontra-se a opo Language
com as vrias linguas em que o programa est disponvel. Basta procurar a opo portuguese
(Brazil) e clicar OK, e o programa j estar traduzido para nossa lngua.
A tela principal do programa mostrada na figura abaixo.
Debug: serve para controlar o debug de um programa, que a sua execuo passo-a-passo
para melhor anlise e busca por erros
Ferramentas: refere-se a vrias opes do compilador, do ambiente de trabalho e de edio,
alm de configuraes diversas
CVS: uma funo extra do compilador, e no nos tem serventia
Janela: possui comandos teis para os casos em que temos vrios arquivos ou projetos
abertos ao mesmo tempo e precisamos alternar entre eles.
Ajuda: d acesso ajuda do programa, que possui uma listagem dos principais comandos do
compilador e um breve tutorial da linguagem C.
Logo abaixo dos menus, temos as barras de ferramenta com as principais funes e comandos
do programa representados por cones para acesso rpido. Basta posicionar o mouse sobre
qualquer um dos cones para saber sua funo.
Abaixo das barras de ferramentas, esto as duas principais janelas do programa. A janela da
esquerda chamada de Navegador de Classes e Projetos, e serve para acessar rapidamente
os vrios arquivos de cdigo pertencentes um projeto ou ento acessar rapidamente as
vrias classes existentes em um programa. A janela da direita nossa tela de trabalho, onde
digitamos nossos cdigos. Note que caso exista mais de um arquivo sendo trabalhado ao
mesmo tempo, podemos alternar entre eles atravs das pequenas abas que existem
diretamente acima da tela de trabalho, cada uma identificada pelo nome de seu arquivo.
Finalmente, a janela inferior do programa possui vrias informaes sobre o processo de
compilao e debugagem de um programa. Ela particularmente til para encontrar erros de
compilao, como veremos mais adiante.
2.3.3 - Utilizao
Para iniciarmos um novo arquivo de cdigo, preciso acessar o menu Arquivo -> Novo ->
Arquivo Fonte (como mostra a figura 1.c) ou ento utilizar o atalho CTRL + N. O novo arquivo
ser criado imediatamente e poderemos comear a trabalhar nele.
Figura 2.4 Utilize o comando Arquivo Fonte para criar um novo arquivo em branco.
As funes bsicas do compilador podem ser encontradas no menu Executar, como mostra a
figura 1.d. Os comandos que utilizaremos so: Compilar (atalho: CTRL + F9), Executar ( CTRL
+ F10) e Compilar & Executar ( atalho: F9). Utilizamos o comando Compilar para compilar o
arquivo cdigo do programa em que estamos trabalhando e gerar um arquivo executvel deste
programa. Em seguida, utilizamos o comando Executar para automaticamente executar o
arquivo criado pela compilao. O comando Compilar & Executar a unio dos dois
comandos: compila e executa o programa logo em seguida. Como j indicado antes, estes trs
comandos possuem cones de acesso rpido na barra de ferramentas (veja a figura 1.e).
Figura 2.5 O menu Executar possui todas os comandos necessrios para compilar e executar
os programas que criaremos.
Figura 2.6 Localizao dos comandos bsicos na barra de tarefas. Coloque o mouse sobre
qualquer um dos cones para saber qual sua funo.
2.3.4 - Erros
Quando compilamos um arquivo de cdigo no Dev-C++, a janela indicadora do progresso da
compilao automaticamente aberta. Caso o arquivo de cdigo no contenha nenhum erro, a
compilao terminar e a janela de progresso permanecer aberta para indicar que tudo correu
bem (verifique o quadrado da janela chamado status: ele dever indicar Done aps o fim da
compilao). Desta maneira, aps o fim da compilao basta fechar a janela e executar o
programa executvel que foi gerado.
Figura 2.8 A janela que indica a posio e o tipo de erros encontrados durante a compilao
do programa.
A figura acima mostra que a janela possui trs colunas: linha, unidade e mensagem. A coluna
linha indica a linha de cdigo onde o erro foi encontrado; a coluna unidade indica o arquivo
onde foi encontrado o erro e a coluna mensagem relata o tipo de erro encontrado. Um duplo
clique em qualquer uma das indicaes de erro nesta janela faz com que a linha de cdigo
onde o erro foi encontrado seja sublinhada em vermelho na janela de edio de cdigo.
Geralmente, os erros encontrados so erros de digitao do cdigo. Quando erramos o nome
de uma varivel ou mesmo um comando, o Dev-C++ indica que o nome errado no foi
declarado anteriormente (varivel_x undeclared(first use in this function)), pois ele age como
se este nome desconhecido fosse uma varivel no declaradada e tenta continuar a
compilao.
Outro erro bastante comum a falta de ponto-e-vrgula no fim de uma linha de comando. Neste
caso, a mensagem de erro geralmente ; expected before algum_comando, indicando que o
compilador esperava o ponto-e-vrgula antes do prximo comando ou varivel. A mensagem de
erro indica a prxima linha de cdigo, mas o ponto-e-vrgula ausente est na linha anterior. O
compilador tambm indica quando utiliza-se o ponto-e-vrgula antes da hora, ou seja, quando o
compilador espera por uma expresso ou comando e encontra somente o ponto-e-vrgula. Por
exemplo, uma declarao de varivel sem declarao de valor: varivel = ;. Neste caso, a
mensagem de erro dada pelo programa expected primary-expression before ';' token.
#include
using
namespace
int
{
//comandos
system("PAUSE
return
}
<iostream>
std;
main()
do
programa
>
null");
0;
As duas primeiras linhas so o cabealho do programa. Todo programa deve ter um cabealho
desse tipo para definir quais as bibliotecas ele utilizar. Bibliotecas so arquivos que
normalmente so instalados juntos com o compilador e que possuem os comandos e funes
pertencentes linguagem.
O cabealho #include<> serve para indicar ao compilador todas as bibliotecas que este
programa utilizar. Na maioria dos programas que escreveremos durante esta apostila, s
utilizaremos o #include <iostream>, que serve para incluir a biblioteca iostream em nossos
programas. Esta biblioteca contm as principais funes, comandos e classes de entrada e
sada de C++, necessrias para realizar programas que, por exemplo, recebam dados via
teclado e enviem dados via monitor.
A segundal linha do cabealho, using namespace std; , um aviso ao compilador que
estaremos utilizando os comandos e funes padro de C++. Ele necessrio porque em C++
podemos criar vrias bibliotecas para serem utilizveis em vrios programas. Cada uma dessas
bibliotecas contm comandos, classes e funes prprias, e para evitar confuses e problemas
com os nomes destes comandos, utilizamos o cabealho using namespace ...; para definir
qual o campo de nomes que estamos utilizando. Num programa normal, que no utiliza outras
bibliotecas alm da padro de C++, utilizamos o namespace std como nosso campo de nomes
de comandos e funes. Assim, sempre que utilizamos um comando prprio de C++, o
compilador reconhecer automaticamente este comando como sendo pertencente biblioteca
padro de C++.
Assim como em C, tudo o que acontece durante a execuo do programa est contido dentro
de uma funo principal, chamada main. Declaramos a funo main com:
int main ( )
Todos os comandos executados pelo programa esto contidos entre as chaves { } da funo
main. No mdulo 4 estudaremos as funes fundo e veremos que um programa pode ter
mais de uma funo, mas indispensvel que todos os programas possuam a funo main.
Cada programa ter seus prprios comandos, logicamente. Entretanto, o encerramento de um
programa geralmente feito da mesma maneira para todos eles. As duas ltimas linhas antes
do fecha-chaves so dois comandos normalmente utilizados ao fim de um programa.
A linha system(PAUSE > null) uma chamada de funo prpria de C++. A funo system(
) recebe argumentos como o PAUSE que na verdade so comandos para o sistema
operacional. Neste caso, ela recebe o comando PAUSE > null para pausar a execuo do
programa at que o usurio aperte uma tecla qualquer. Utilizamos este recurso para que a tela
do programa no seja terminada automaticamente pelo sistema, impedindo que vejamos os
resultados do programa.
Finalmente, o comando return 0 a resposta da funo main para o sistema. Quase toda
funo retorna um valor para o sistema ou programa que a chamou, por exemplo, uma funo
pode retornar o resultado de uma operao matemtica executada por ela. No caso da funo
main, ela retorna um valor para o sistema operacional que executou o programa. Esse valor
interpretado pelo sistema como uma mensagem indicando se o programa foi executado
corretamente ou no. Um valor de retorno 0 indica que o programa foi executado sem
problemas; qualquer outro valor de retorno indica problemas. Quando o programa executado
at o fim, ele retorna 0 ao sistema operacional, indicando que ele foi executado e terminado
corretamente. Quando o programa encontra algum erro ou terminado antes da hora, ele
retorna um valor qualquer ao sistema, indicando erro durante a execuo.
auto
bool
break
case
catch
char
class
const
const_cast
Continue
default
delete
do
double
Dynamic_cast
else
enum
explicit
export
extern
false
float
for
friend
goto
if
inline
int
long
mutable
namespace
new
operator
private
protected
public
short
signed
sizeof
static
static_cast
struct
switch
template
this
throw
true
try
typedef
typeid
typename
union
unsigned
using
virtual
void
register reinterpret_cast
return
Volatile
wchar_t
while
importante notar que a linguagem C++ diferencia letras maisculas e minsculas, ou seja,
char uma palavra reservada de C++ mas CHAR ou ChAr no (entretanto, normalmente
desaconselha-se o uso dessa diferenciao por atrapalhar a legibilidade do cdigo).
Reforando o que j foi mencionado, as palavras reservadas s iro executar os comandos
que lhes foram designados.
Tipo
Tamanho (em
bits)
Intervalo
Char
-128 a 127
unsigned char
0 a 255
Int
16
-32768 a 32767
unsigned int
16
0 a 65535
Short
16
-32768 a 32767
unsigned
short
16
0 a 65535
Long
32
-2147483648 a
2147483647
unsigned long
32
0 a 4294967295
Variveis reais servem para armazenar nmeros que possuem partes fracionrias. Existem
duas maneiras de representar nmeros fracionrios em C++. A primeira, a mais simples,
utilizar o ponto para separar as partes inteiras e fracionrias. Por exemplo:
0.00098
1.2145
3.1461
8.0
(Mesmo no caso de um nmero com parte fracionria igual a zero, a utilizao do ponto
assegura que este nmero seja considerado um nmero de ponto flutuante por C++).
A segunda maneira utilizar a notao cientfica E. Por exemplo : 3.45E7 significa 3.45
multiplicado por 10 elevado stima potncia (10.000.000). Essa notao bastante til para
x
x
100.000.000
1000
=
=
252.000.000
-3200
Assim como os inteiros, os nmeros reais em C++ podem ser representados por 3 tipos de
variveis com diferentes intervalos. So elas: float, double e long double. Float o tipo de
varivel real natural, aquela com a qual o sistema trabalha com maior naturalidade. Double e
long double so teis quando queremos trabalhar com intervalos de nmeros reais realmente
grandes. Utilizamos nmeros reais geralmente para expressar preciso atravs do nmero de
casas decimais, ento podemos dizer que uma varivel float menos precisa que uma varivel
double, assim como uma varivel double menos precisa que long double. A tabela abaixo
mostra os tipos de variveis reais, seu tamanho em bits e o intervalo de armazenagem.
Tipo
Intervalo
Float
32
3,4E-38 a 3,4E+38
Double
64
1,7E-308 a 1,7E+308
long double
80
3,4E-4932 a 1,1E+4932
Equivalente
Binrio
Dgito
Hexadecimal
Equivalente
Binrio
0000
1000
0001
1001
0010
1010
0011
1011
0100
1100
0101
1101
0110
1110
0111
1111
Significado
Cdigo
Significado
\b
Retrocesso
\f
Alimentao de
formulrio
\n
Nova linha
\r
Retorno de carro
\t
Tabulao
horizontal
\"
Aspas
\'
Apstrofo
\0
Nulo
\\
Barra invertida
\v
Tabulao vertical
\a
Sinal sonoro
\N
Constante octal
\xN
Constante
hexadecimal
Usa-se um cdigo de barra invertida exatamente da mesma maneira como usa qualquer outro
caractere. Por exemplo:
ch
printf(Este um teste\n);
\t;
Esse fragmento de cdigo primeiro atribui uma tabulao a ch e, ento, imprime este um
teste na tela, seguido de uma nova linha.
3.9 Operadores
Um operador um smbolo que diz ao compilador para realizar manipulaes matemticas e
lgicas especficas. A linguagem C++ possui trs classes gerais de operadores: aritmticos,
relacionais e lgicos e bit-a-bit.
O ltimo exemplo interessante por mostrar que possvel associar vrios operadores de
atribuio em sequncia, fazendo com que todas as variveis envolvidas tenham o mesmo
valor especificado.
Ao
Soma
subtrao
multiplicao
diviso
Ao
>
Maior
>=
maior ou igual
<
Menor
<=
menor ou igual
==
Igual
!=
no igual (diferente)
AND
&&
operao AND
||
operao OR
Ao
&
bit and
bit or
<<
Rotao a esquerda
>>
Rotao a direita
->
var op = expr
Ao
Soma
Subtrao
Multiplicao
Diviso
>>
Rotao a direita
<<
Rotao a esquerda
&
And
xor - exclusive or
Or
Exemplo de aplicao:
i+=
2;
/*
equivalente
a:
j-=
3;
/*
equivalente
a:
k
>>=
3;
/*
equivalente
z &= flag; /* equivalente a: z = z & flag;*/
i
j
a:
=
=
k
i
j
=
2
3
>>
*/
*/
3;*/
i
i
a;
a;
a
z = a;
1;
1;
a
a
+
?
?
?
=
=
a
a
1;
z
z = --a;
=
=
?
?
?
i
+
1;
1;
a;
++i;
--i;
?
?
z
z
z
=
=
=
++i;
--i;
a++;
a--;
++a;
Significado
&
Exemplos:
int
x
var = *x;
var,
=
*x;
&var;
Funo
Exemplo (C++
menos unrio
a = -b;
mais unrio
a = +b ;
negao lgica
! flag
bitwise not
a = ~b ;
&
endereo de
a = &b ;
referncia a ptr
a = *ptr ;
sizeof
tamanho de var
a = sizeof(b) ;
++
incremento
++a; ou a++;
--
decremento
--a; ou a--;
multiplicao
a = b * c;
diviso inteira
a = b / c;
diviso real
a = b / c;
resto da diviso
a = b % c;
soma
a = b + c;
subtrao
a = b v c;
>>
shift right
a = b >> n;
<<
shift left
a = b << n;
>
maior que
a>b
>=
maior ou igual a
a >= b
<
menor que
a<b
<=
menor ou igual a
a <= b
==
igual a
a == b
!=
diferente de
a != b
&
bitwise AND
a = b & c;
bitwise OR
a = b | c;
bitwise XOR
a = b ^ c;
&&
logical AND
||
logical OR
flag1 || flag2
assinalamento
a = b;
OP=
assinalamento
a OP= b;
3.11 Expresses
Operadores, constantes e variveis constituem expresses. Uma expresso em C++
qualquer combinao vlida dessas partes. Uma vez que muitas expresses tendem a seguir
as regras gerais da lgebra, estas regras so freqentemente consideradas. Entretanto,
existem alguns aspectos das expresses que esto especificamente relacionadas com a
linguagem C e sero discutidas agora.
Operador Associatividade
Explicao
(expresso)
()
3 (todos unrios)
4 (todos
binrios)
5 (todos
binrios)
Agrupamento
E-D
++
--
D-E
Negao Bitwise
++
--
&
Endereo
Contedo de endereo
()
sizeof
Tamanho em bytes
new
new []
delete
delete []
E-D
Multiplicao
Diviso
Resto de diviso
E-D
<<
<
Adio
Subtrao
E-D
>>
7
Negao lgica
Chamada de funo
E-D
Menor que
<=
>=
>
Maior que
==
E-D
!=
Igual a
No igual a
9 (binrio)
&
E-D
Bitwise AND
10
E-D
11
E-D
Bitwise OR
12
&&
E-D
AND Lgico
13
||
E-D
OR Lgico
14
D-E
Atribuio simples
*=
Multiplicao e atribuio
/=
Dividir e atribuio
%=
+=
Adio e atribuio
-=
Subtrao e atribuio
&=
^=
|=
Bitwise OR e atribuio
<<=
>>=
15
:?
D-E
Condicional
16
E-D
e
tipo (varivel_ou_expresso); por exemplo: int (modelos); int (19.99);
Ambos os comandos produzem o mesmo resultado: forar o valor presente na varivel (ou
expresso) ser convertido no tipo desejado. Note que o valor da varivel no alterado;
somente feita uma converso momentnea, cujo valor resultante deve ser armazenada em
outra varivel ou trabalhado imediatamente em uma expresso.
A expresso sqrt(6.25) chama a funo sqrt( ). O nmero entre parnteses o valor que
estamos enviando para a funo sqrt( ), e o chamamos de parmetro ou argumento. A funo
calcular a raiz quadrada de 6.25, e enviar o valor calculado para o programa, o chamado
retorno da funo. Nesta linha de comando, especificamos que o retorno da funo, ou seja,
seu resultado, ser armazenado na varivel x. Resumindo, um valor enviado para a funo, e
a funo retorna o valor resultante para o programa. Entretanto, antes de podermos utilizar a
funo sqrt( ) ou qualquer outra funo em um programa preciso declar-la. Veremos isso em
detalhes no prximo item.
O ltimo exemplo mostra que a escolha do nome do parmetro no prottipo opcional: basta
inserir o tipo de parmetros que sero utilizados pela funo e o compilador alocar a memria
necessria para eles. Porm a atribuio de nomes para parmetros aconselhvel, pois
melhora a legibilidade do programa. Quando declaramos e definimos uma funo no incio do
programa, isto , antes da funo main, podemos omitir o prottipo da funo, fazendo
somente a definio da funo como veremos abaixo.
<tipo da
{
comandos
}
funo>
<nome>
<tipo
do
parmetro>
<nome
da
do
parmetro>)
funo;
A primeira linha da definio de uma funo idntica ao prottipo, com a exceo de que
somos obrigados a declarar nomes para as variveis de parmetro e que a linha no termina
em um ponto-e-vrgula, e sim em uma abre-chaves. Dentro das chaves estaro todos os
comandos pertencentes a funo, inclusive declarao de variveis locais, chamadas para
outras funes e chamadas de retorno. Por exemplo:
int
resultado
return
}
cubo
int
valor)
{
valor*valor*valor;
resultado;
A funo acima calcula o cubo de um valor inteiro. Note que podemos declarar variveis dentro
de uma funo; entretanto, estas variveis s podero ser utilizadas dentro desta mesma
funo. O comando return termina a funo e retorna um valor para o programa.
compara_valores(int
primeiro,
(primeiro
int
==
if
(primeiro
>
if
(primeiro
<
segundo)
segundo)
(0);
segundo)
(1);
segundo)
(2);
Como regra, deve-se tentar limitar as funes a usar somente um comando return. medida
que as funes se tornarem maiores e mais complexas, ter muitos comandos return
normalmente tornar as funes mais difceis de compreender. Na maioria dos casos, pode-se
reescrever a funo para que ela use somente um comando return
<iostream>
std;
namespace
valores_locais(void);
valores_locais(void)
a=1,
b=2,
main
c=3;
(void)
{
cout<<A vale
system("PAUSE
return
}
<<
<<.
vale
<<
<<.
vale
<<
>
<<.\n;
null");
0;
O programa abaixo a verso corrigida do programa acima. Veja que a funo main chama a
funo valores_locais, que por sua vez declara as variveis junto com seus valores e as
imprime na tela corretamente.
#include
<iostream>
using
namespace
std;
void
valores_locais(void);
void
{
int
cout<<"A
}
valores_locais(void)
vale
"<<
a=1,
<<".
vale
int
{
valores_locais();
system("PAUSE
return
}
"<<
b=2,
<<". C
vale
"<<
main
c=3;
<<".\n";
(void)
>
null");
0;
<iostream>
std;
namespace
b
<<".
2,
vale
"<<
3;
<<".
//
Variaveis
globais
valores_globais(void)
vale
"<<
<<".\n";
main(void)
<<".
vale
"<<
b
>
<<".
vale
"<<
<<".\n";
null");
0;
programa declara dentro de uma funo. Por isso, preciso estar atento com o uso de
variveis globais e sua nomeao. Quando nomes de variveis globais e locais estiverem em
conflito, a linguagem C++ usar sempre a varivel local.
<iostream>
std;
namespace
void
exibe_e_altera(int
primeiro,
int
segundo,
{
cout<<"Valores originais da funcao: "<<primeiro<<" "<<segundo<<"
primeiro
=
primeiro
segundo
=
segundo
+
terceiro
=
terceiro
+
cout<<"Valores originais da funcao: "<<primeiro<<" "<<segundo<<"
}
int
{
int
a
exibe_e_altera(a,
cout<<"Valores
system("PAUSE
}
int
terceiro)
"<<terceiro<<"\n";
+100;
100;
100;
"<<terceiro<<"\n";
main(void)
=
finais
1,
b
em
main:
>
2,
b,
"<<a<<"
c
"<<b<<"
3;
c);
"<<c<<"\n";
null");
Como pode ser visto, as alteraes que a funo faz nas variveis somente so visveis dentro
da prpria funo. Quando a funo termina, as variveis dentro de main esto inalteradas.
Para usar a chamada por referncia, seu programa precisar usar ponteiros. Por ora tudo o que
precisamos saber que um ponteiro armazena um endereo de memria, assim como uma
varivel armazena um valor. O mdulo 8 dedicado totalmente explicao de ponteiros e
suas aplicaes em C++, incluindo o funcionamento de uma chamada de funo por
referncia.
Uma descrio detalhada das funes presentes na biblioteca padro de C++ no cabe nesta
apostila. Entretanto, muitos livros e websites contm listagens e explicaes das funes
padres. Um bom exemplo o website http://www.cppreference.com/index.html , que contm
uma vasta referncia sobre vrios aspectos da linguagem C++.
No deixe de examinar as funes que seu compilador fornece. Muitos compiladores
referenciam essas funes internas como biblioteca de execuo. A maioria dos compiladores
fornece centenas de funes de biblioteca de execuo com propsito que vo de abertura e
trabalho com arquivos para acessar informaes do disco ou de diretrio para determinar o
tamanho de uma string de caracteres. As duas ou trs horas que sero gastas para ler a
documentao da biblioteca de execuo pouparo muitas horas de programao.
Para uma linguagem ser recursiva, uma funo deve estar apta a chamar a si prpria. O
exemplo clssico de recursividade mostrado na funo fatorial_recursivo(), que calcula o
fatorial de um nmero inteiro. O fatorial de um nmero N o produto de todos os nmeros
inteiros entre 1 e N. Por exemplo, o fatorial de 3 1 x 2 x 3, ou 6.
#include
#include
using
namespace
unsigned
unsigned
if
((n
resposta
=
return(resposta);
}
int
{
unsigned
int
cout<<"Digite
cin
f
cout<<"O
system("PAUSE
return
}
<iostream>
<cstdio>
std;
long
==
1)
n
fatorial_recursivo
(int
long
||
(n
==
*
fatorial_recursivo(n
n){
resposta;
0))return(1);
1);
main()
long
um
nmero:
>>
fatorial
=
de
"<<n<<"
>
f;
n;
\n";
n;
fatorial_recursivo(n);
"<<f<<"
\n";
null");
0;
e retorno da funo. Assim, elimina-se a necessidade do programa pular para outro ponto na
memria do computador, executar a funo e depois retornar ao ponto onde parou.
Criamos funes inline do mesmo jeito que criamos funes normais: declarando seu prottipo
e sua definio, com parmetros e retorno. S preciso adicionar o prefixo inline antes do
prottipo ou da definio da funo, como mostrado na funo abaixo:
inline
{
x
return
}
int
quadrado
(long
x)
x;
x;
No podemos criar funes inline recursivas, pois logicamente uma funo recursiva tem um
tamanho varivel de acordo com seu nmero de iteraes, que muitas vezes muda durante a
execuo do programa.
Ganha-se velocidade com as funes inline, mas perde-se em memria utilizada. Se um
programa chama uma funo inline 10 vezes, criam-se 10 cpias da funo dentro do cdigo,
aumentando seu tamanho durante a compilao. preciso escolher com cuidado quando
utilizar funes normais e funes inline, tendo em mente o compromisso rapidez de execuo
memria utilizada.
namespace
<iostream>
<cstdio>
std;
void
mensagem
(int
x
=
1)
{
if (x != 1) cout<<"Voce enviou um parametro para a funo! O parametro X igual a "<<x<<"\n";
if (x == 1) cout<<"Voce NAO enviou um parametro para funo! O parametro X igual a
"<<x<<"\n";
}
int
main()
{
int
valor;
cout<<"Entre com um valor. Este valor ser repassado para a funo mensagem
automaticamente!\n";
cin>>valor;
mensagem(valor);
cout<<"Agora chamaremos a funo mensagem sem lhe dar um parametro. Veja o que
acontece:
\n";
mensagem();
system("PAUSE
>
null");
return
0;
}
unsigned char
signed char
char
short
unsigned short
int
unsigned int
long
unsigned long
float
double
long double
O operador de insero tambm fornece facilidades para a exibio de strings. Alm dos tipos
bsicos mostrados acima, o operador de insero tambm reconhece os seguintes tipos de
ponteiros:
Ponteiros sero explicados com maior propriedade no mdulo 8, mas precisamos saber que C
e C++ representam strings utilizando ponteiros para o endereo de memria da string. Este
ponteiro pode ser o nome de uma varivel matriz de tipo char, um ponteiro de tipo char ou
ento uma frase entre aspas. O operador de insero reconhece cada um destes casos e exibe
na tela a string de texto. Por exemplo:
char
nome[20]
char
*
nome2
cout
<<
cout
cout << nome2;
=
=
Jose
<<
Jose
Jose
das
das
das
Couves;
Galinhas;
Dores;
nome;
Estas 3 utilizaes de cout exibem as strings de texto na tela. Veremos mais adiante que toda
string possui um caractere de trmino, \0, que indica para o compilador que a string terminou.
Nestes trs casos, o operador de insero orienta-se por este \0 para terminar a exibio das
strings.
importante ressaltar que o operador de insero no reconhece automaticamente matrizes
numricas e no as exibe automaticamente na tela. Para fazer isso, precisaremos utilizar os
mtodos tradicionais envolvendo loops para mostrar cada membro da matriz de uma vez. Este
assunto ser discutido no mdulo 7, dedicado para matrizes.
<<
hex;
oct;
Aps utilizar qualquer um destes comandos, sempre que pedirmos para cout exibir um nmero
inteiro na tela, o comando automaticamente converter o nmero para a base definida
previamente. Por exemplo:
int
cout
cout << numero;
numero
10;
hex;
<<
Dessa forma, cout exibir na tela no o nmero 10 como estamos acostumados, mas a letra a,
que representa 10 na base hexadecimal. Note que podemos utilizar o operador de insero
duas vezes para deixar o cdigo mais compacto e obter o mesmo resultado:
int
cout << hex << numero;
numero
10;
No se esquea de retornar para a base decimal com cout << dec; aps exibir valores na
base hexadecimal ou octal!
variavel
=
(
10;
);
Neste exemplo, foi especificado cout.width (5); e o valor a ser exibido 10. Assim, cout
predecer o valor 10 com trs espaos em branco.
Observe que o valor especifica o nmero mnimo de caracteres que a sada consumir. Se o
valor a ser exibido requer mais caracteres do que o especificado, ser usado o nmero de
caracteres necessrios para exibir o valor corretamente.
importante observar tambm que o mtodo cout.width s vlido para a prxima utilizao
de cout: aps isto, o nmero mnimo de caracteres volta a ser zero.
Podemos tambm determinar o caractere a ser utilizado para preencher os espaos em branco
de um campo de exibio. Isto feito com o seguinte mtodo:
cout.fill ( caractere);
Onde substitumos caractere pelo caractere que ser exibido. necessrio utilizar aspas
entre o caractere, para indicar para o compilador que no se trata de uma varivel.
O exemplo abaixo mostra a utilizao conjunta destes dois mtodos:
int
cout.width
cout.fill(0);
cout << variavel;
variavel
=
(
10;
);
direita:
cout
<<
right
<<
<valor
Alinhamento esquerda: cout << left << <valor a ser exibido>;
ser
exibido>;
Espaos em branco so considerados fim de entrada pelo comando cin; ao invs de descartar
os caracteres que vierem aps o espao em branco, C++ os guarda em um buffer (uma
espcie de reserva ou pilha de dados). Quando cin for chamado novamente, antes de ler a
nova entrada do teclado, o programa primeiro utiliza os dados que esto nesse buffer. Assim,
temos a impresso que a nova entrada de dados foi descartada pelo programa, mas na
verdade ela foi jogada no buffer, esperando uma nova chamada de cin. Para solucionar este
problema, utilizamos o mtdo de cin cin.getline.
matriz,
50
matriz[60];
);
6.2 A declarao if
Utilizamos a declarao if quando desejamos que o programa teste uma ou mais condies e
execute um ou outro comando de acordo com o resultado deste teste. A sintaxe de if a
seguinte:
if
{
comandos;
}
else
{
comandos;
}
(condio)
<iostream>
std;
namespace
int
{
int
cout<<"Digite
cin>>
if
{
cout<<"O
numero
}
else
{
cout<<"O
numero
}
system("PAUSE
return
}
main()
um
teste;
qualquer:\n";
teste;
50)
numero
(teste
>
que
voce
digitou
maior
que
50";
que
voce
digitou
menor
que
50";
>
null");
0;
possvel tambm aninhar ifs, ou seja, fazer uma declarao if dentro de outra declarao if
anterior. Este um mtodo muito til em programao, mas preciso tomar cuidado ao utilizlo para saber qual bloco else pertence qual if. Em C++, o else ligado ao if mais prximo
dentro do mesmo bloco de cdigo que j no tenha uma declarao else associada a ele. Para
se certificar de que estamos aninhando os ifs e elses corretamente, utilizamos chaves para
delimitar os diferentes blocos, como pode ser visto no cdigo abaixo:
if
{
if
{
cout<<
}
else
>
10)
==
17)
maior
que
10
igual
17;
{
cout<<
}
}
else
{
cout
}
<<
maior
que
10
mas
no
menor
do
igual
que
17;
10;
Note que a segunda declarao if est totalmente contida pelas chaves da primeira declarao
if. Utilizou-se chaves em todas os blocos de comando, para melhor separar as condies dos
blocos de comandos. Alm disso, note o uso da tabulao para separar visualmente os
diferentes blocos e declaraes: poderamos escrever todo o cdigo sem usar tabulao,
alinhando todas as linhas esquerda, mas isto dificultaria a identificao das diferentes
declaraes.
(condio)
if
(condio)
if
(condio)
Cada bloco else if dever testar uma condio diferente. O programa testar todas as
condies na sequncia, de cima para baixo, at encontrar uma condio verdadeira. Quando
isto acontece, os comandos pertencentes ao bloco verdadeiro sero executados enquanto
todos os outros blocos do encadeamento so ignorados. Caso nenhuma condio else if seja
verdadeira, executa-se o bloco de comandos pertencente ao else final. Note que o else
opcional: Se o else final no estiver presente e todas as outras condies forem falsas, ento
nenhuma ao ser realizada.
Utilizando este encadeamento, ampliaremos o programa anterior para que ele teste vrias
condies sobre um nmero enviado pelo usurio, at encontrar uma condio verdadeira.
#include
using
int
{
int
cout<<"Digite
cin>>
if
<iostream>
std;
namespace
main()
um
(teste
numero
<=
teste;
qualquer:\n";
teste;
50)
{
cout<<"O
nmero
que
voc
digitou
menor
que
}
else
if
(teste
>
50
&&
teste
<=
{
cout<<"O nmero digitado maior que 50 e menor ou igual a
}
else
if
(teste
>
100
&&
teste
<=
{
cout<<"O nmero digitado maior que 100 e menor ou igual a
}
else
{
cout<<"O
numero
digitado
maior
que
}
system("PAUSE
>
return
}
50\n";
100)
100\n";
200)
200\n";
200\n";
null");
0;
varivel
)
valor1:
case
comandos;
break;
valor2:
...
case
comandos;
break;
valorx;
default:
comandos;
}
A declarao switch testa o valor de uma nica varivel. Note que existem vrios case, cada
um associado a um determinado valor. A declarao comparar o valor da varivel com o valor
de cada um dos case: quando uma associao encontrada, os comandos pertencentes ao
case relacionado so executados. Se nenhuma associao for encontrada, a declarao
switch executar os comandos pertencentes ao bloco default (note que o bloco default
opcional: caso ele no exista, caso nenhuma associao seja encontrada a declarao switch
termina sem que nenhum comando seja executado). O exemplo abaixo demonstra uma
utilizao da declarao switch.
#include
using
int
namespace
<iostream>
std;
main()
{
int
cout<<"Digite
cout<<"1.
cout<<"2.
cout<<"3.
option
cin>>
switch(option)
{
case
cout<<"Voc
break;
case
cout<<"Voc
break;
case
cout<<"Voc
break;
default:
cout<<"Voc
}
system("PAUSE
return
}
option;
desejada:\n";
1\n";
2\n";
3\n";
0;
option;
opo
Opo
Opo
Opo
=
escolheu
primeira
1:
opo\n";
escolheu
segunda
2:
opo\n";
escolheu
terceira
3:
opo\n";
uma
opo
escolheu
>
invlida!\n";
null");
0;
Aps o fim de cada bloco de comandos case, comum utilizar o comando break;. Este
comando interrompe a execuo do lao em que o programa se encontra, fazendo com que o
programa prossiga para o prximo comando imediatamente aps o lao. No caso de switch, o
comando break assegura que a execuo da declarao switch termine, forando o programa
voltar para sua execuo normal. Caso omitssemos os comandos break; no fim de cada
bloco, a declarao switch executaria os comandos presentes no case em que a associao
foi encontrada, e continuaria a executar todos os comandos presentes em todos os case na
sequncia (incluindo o bloco default) at o trmino da declarao switch. Note que este
comportamento pode ser til em alguns programas, como por exemplo uma sequncia de
operaes matemticas onde utilizamos a declarao switch para escolher o ponto de partida
da sequncia.
valor_inicial;
condio_testada;
valor_incremento)
continua seu fluxo normal. Por exemplo, controle < 30; uma expresso vlida, que
testa se a varivel controle menor do que 30.
valor_incremento uma expresso que incrementar a varivel de controle sempre
que a condio testada anteriormente for verdadeira. Por exemplo, controle = controle
+ 1 ou mais simplesmente controle++
Como j dissemos, os comandos entre as chaves sero executados sempre que a
condio testada for verdadeira, e se repetiro at que a condio se torne falsa e o
lao termine.
O exemplo de cdigo abaixo mostra uma declarao de lao for utilizando o exemplo dado
anteriormente:
#include
using
namespace
<iostream>
std;
int
main()
{
int
controle;
for
(
controle
=
0;
controle
<=
30;
controle++)
{
cout << "Esta frase se repetir at que a varivel controle seja maior do que 30\n";
cout<<
"controle
=
"<<controle<<"\n";
}
system("PAUSE
>
null");
return
0;
}
A varivel controle comea com valor 0. O lao for testa o valor da varivel continuamente,
sempre determinando se ele menor do que 30.
Sempre que o valor da varivel for menor que 30 (condio verdadeira), a varivel de controle
incrementada de 1 e os comandos entre as chaves so executados. Quando a varivel
controle for maior do que 30 (condio falsa), o lao termina e o programa volta a ser
executado normalmente.
O comando for extremamente flexvel. Podemos atribuir qualquer valor que quisermos
varivel de controle, e tambm podemos increment-la (ou decrement-la da forma que
desejarmos). No exemplo abaixo, utilizamos o lao for de forma inversa ao exemplo anterior: a
varivel de controle comea em 60 e vai sendo decrementada de 2 a cada repetio.
#include
using
namespace
<iostream>
std;
int
main()
{
int
controle;
for
(
controle
=
60;
controle
>=
0;
controle
=
controle
2)
{
cout << "Esta frase se repetir at que a varivel controle seja igual a 0\n";
cout<<
"controle
=
"<<controle<<"\n";
}
system("PAUSE
>
null");
return
0;
}
Os trs argumentos do lao for so opcionais: podemos omitir qualquer um dos argumentos,
mas precisamos estar atentos s consequncias que isto traz ao programa. Por exemplo, o
cdigo abaixo omite o argumento de incremento da varivel de controle. No entando, fazemos
o incremento da varivel dentro do bloco de comandos do lao for:
for
{
cout<<x;
x++;
}
(x
0;
<=
50;
(x
0;
<=
50;
Laos infinitos geralmente surgem por algum erro de programao. Quando o programa entra
em um lao infinito, pode-se pressionar Ctrl+C no modo MS-DOS para finalizar o programa.
importante saber que mesmo omitindo um argumento, necessrio incluir o ponto-e-vrgula
correspondente. Podemos omitir tambm a inicializao da varivel de controle, caso ela tenha
sido declarada e inicializada anteriormente no programa.
Tambm podemos criar um lao for nulo, sem um bloco de comandos:
for
{
}
(x
0;
==
50;
x++)
Nesse caso, o programa ainda interrompido para a execuo do lao for, e no faz nada
durante este intervalo. Esta tcnica pode ser utilizada para forar uma pausa na execuo de
um programa, porm ela pouco precisa e desperdia recursos do microprocessador.
Finalmente, podemos utilizar vrias variveis de controle para controlar um mesmo lao for.
Para isto, utilizamos vrgulas para separar as expresses relacionadas a cada varivel dentro
de um mesmo argumento. O cdigo abaixo abaixo ilustra como isto feito:
for
{
cout
}
(i=0,
j=100;
<<
<=
i
100;
i++,
<<
j++)
j;
(condio)
<iostream>
std;
namespace
int
main()
{
int
controle
=
0;
while
(controle
<
20)
{
cout<<"A variavel de controle funcionar se esta frase se repetir somente 20 vezes: ";
controle++;
cout<<controle<<"
\n";
}
system("PAUSE
>
null");
return
0;
}
<iostream>
std;
namespace
main()
controle
frase
foi
=
escrita
(controle
"<<controle<<"
<=
>
1;
{
vezes!\n";
20);
null");
return
}
0;
<iostream>
std;
namespace
main()
1;
mult1,
mult1
1;
mult2
do
<=
10;
mult2;
mult1++)
<=
10;
"<<mult1<<":\n";
mult2++)
numero
";
";
>
null");
0;
namespace
<iostream>
std;
main()
{
int
while
{
cout<<"Escolha uma opo entre 1
cin>>opcao;
if
((opcao>
5)
{
continue;
//opo
invalida:
}
switch
{
//incio
case
cout<<"Opo
1
break;
case
cout<<"Opo
2
break;
case
cout<<"Opo
3
break;
case
cout<<"Opo
4
break;
case
cout<<"Voc
saiu
break;
}
//fim
}
//fim
system("PAUSE
}
opcao;
5)
(opcao!=
e
4.
Escolha
||
volta
para
sair
do
programa\n";
(opcao<
ao
inicio
1))
do
loop
foi
(opcao)
switch
1:
escolhida\n";
foi
2:
escolhida\n";
foi
3:
escolhida\n";
foi
4:
escolhida\n";
do
5:
programa\n";
do
do
do
lao
>
switch
while
null");
Em primeiro lugar, o lao while far com que o programa rode repetidamente at que a varivel
opcao, cujo valor atribudo pelo usurio a cada repetio do programa, tenha valor igual a 5.
A declarao if checa se o valor entrado pelo usurio maior que cinco ou menor que 1. Caso
isto seja verdade, o comando continue interrompe a execuo de todos os comandos
seguintes, fazendo o lao while ser repetido mais uma vez. Caso o usurio entre um valor entre
1 e 5, o comando continue no executado e o lao while continua para o prximo bloco de
comandos, no caso, a declarao switch. A declarao switch utilizada para mostrar qual
opo o usurio escolheu e, no caso do usurio ter escolhido o valor 5, indicar que o programa
terminou. Quando o valor 5 escolhido, a condio do lao while torna-se falsa, terminando o
programa.
Mdulo 7 Matrizes
7.1 Matrizes
Matrizes so variveis que contm vrios valores de um mesmo tipo. Por exemplo, podemos
criar a matriz notas para armazenar as notas obtidas por 100 alunos em um exame, ou ento
utilizar uma matriz chamada gastos_mensais para anotar nossos gastos mensais ao longo do
ano. Uma matriz armazena vrios valores de um mesmo tipo: podemos criar matrizes para
armazenar qualquer um dos tipos bsicos de variveis, como int, float e char. Cada valor
armazenado separadamente em um elemento da matriz, e pode ser acessado e modificado a
qualquer momento.
A declarao de uma matriz muito parecida com a declarao de uma varivel, bastando
adicionar o nmero de elementos que desejamos que ela tenha. A sintaxe a seguinte:
<tipo> <nome> [<numero de elementos>];
Por exemplo, caso quisssemos criar uma matriz chamada catlogo para armazenar 156
inteiros, a declarao seria assim:
int catalogo [156];
Podemos utilizar qualquer tipo de variveis j estudadas anteriormente para criar uma matriz,
como float, int, char. Uma vez criada uma matriz de um determinado tipo, ela s pode receber
valores deste tipo. Note que precisamos definir um tipo para uma matriz: no possvel criar
uma matriz genrica que aceite um tipo qualquer, ou vrios tipos. Isso acontece porque ao
declarar uma matriz, o compilador aloca memria suficiente para conter o nmero de valores
especificado de acordo com o tipo da matriz. Por exemplo, uma matriz de 100 elementos do
tipo int normalmente ir requerer 100*2 ou 200 bytes de memria. Por outro lado, uma matriz
de 100 elementos do tipo float ir requerer 100*4 bytes ou 400 bytes.
Assim como uma varivel normal, podemos atribuir valores para uma matriz no momento de
sua declarao. Isto feito utilizando o operador de atribuio = seguido dos valores contidos
entre chaves e separados por vrgulas. Por exemplo, considere a matriz de inteiros teste
abaixo:
int teste[5] = { 1, 2, 3, 4 , 5};
Tambm podemos atribuir apenas parte dos valores de uma matriz, por exemplo, podemos
criar uma matriz que comporte 50 valores do tipo float e atribuir apenas 5 valores ela,
deixando para atribuir o restante dos valores no decorrer do programa.
float notas[50] = { 7.65, 8.48, 4.27, 6.78, 9.10 };
A linguagem C++ faz com que toda matriz parcialmente inicializada tenha seus valores
restantes automaticamente transformados em zero. Assim, caso precisemos de uma matriz que
s contenha zeros, podemos atribuir o primeiro elemento da matriz como zero e deixar que o
compilador transforme os elementos restantes em zero, como vemos abaixo:
int zeros[75] = {0};
namespace
main()
<iostream>
std;
{
int
matriz[5]
=
{1,2,3,4,5};
cout<<"o
primeiro
valor
da
matriz
:
"<<matriz[0]<<endl;
cout<<"o
ltimo
valor
da
matriz
:
"<<matriz[4]<<endl;
cout<<"Somando o segundo e o quarto elementos da matriz temos: "<< matriz[1] +
matriz[3]<<endl;
matriz[2]
=
27;
cout<<"Mudamos o valor do terceiro elemento da matriz para: "<<matriz[2]<<endl;
system(PAUSE
>
null);
return
0;
}
namespace
<iostream>
std;
int
main()
{
int
sequencia[4];
for
(int
i
=
0;
i
<
4;
i++)
{
cout
<<
"Entre
com
o
elemento
numero
"<<(i+1)<<"
da
sequencia:
";
cin
>>
sequencia[i];
cout
<<
endl;
}
cout
<<
"A
sequencia
entrada
pelo
usuario
foi:
";
for
(int
i
=
0;
i
<
4;
i++)
{
cout
<<
sequencia[i]<<"
";
}
system("PAUSE
>
null");
return
0;
}
Importante: como vimos no exemplo anterior, podemos utilizar variveis para acessar os
elementos de uma matriz. Da mesma forma, podemos definir constantes para indicar o nmero
de elementos de uma matriz. Essa tcnica muito til, pois caso precisemos alterar o nmero
de elementos da matriz ao invs de caarmos no cdigo todas as referncias este nmero,
tudo que precisamos fazer alterar o valor da constante. Assim, veja o mesmo programa
anterior reescrito utilizando uma definio de constante.
#include
using
int
{
const
int
for
cout
cin
cout
}
namespace
<iostream>
std;
main()
int
<<
(int
"Entre
i
com
TAMANHO
=
o
0;
elemento
>>
i
numero
<<
=
4;
sequencia[TAMANHO];
<
4;
i++)
{
"<<(i+1)<<"
da
sequencia:
";
sequencia[i];
endl;
cout
<<
for
(int
cout
}
system("PAUSE
return
}
"A
i
sequencia
=
<<
0;
entrada
i
pelo
usuario
<
4;
sequencia[i]<<"
foi:
i++)
>
";
{
";
null");
0;
//matriz
de
trs
bidimensional
dimenses
namespace
<iostream>
std;
main()
[2]
[2]
i
j
k
[2]
=
=
=
<<
=
0;
0;
0;
{{{
9,
i
j
k
8},
{7,6}},{{5,
<
2;
<
2;
<
2;
tritabela[i][j][k]<<"
4},{3,
i++)
j++)
k++)
2}}};
{
{
{
";
}
cout<<endl;
}
system("PAUSE
return
}
>
null");
0;
<iostream>
std;
namespace
int
resultado
=
i
=
matriz[],
int
tamanho)
=
0;
i
resultado
<
tamanho;
+
{
0;
i++){
matriz[i];
resultado;
int
main()
{
const
int
TAMANHO
=
4;
int
sequencia[TAMANHO];
int
result
=
0;
for
(int
i
=
0;
i
<
4;
i++)
{
cout
<<
"Entre
com
o
elemento
numero
"<<(i+1)<<"
da
sequencia:
";
cin
>>
sequencia[i];
cout
<<
endl;
}
result
=
soma(sequencia,
TAMANHO);
cout << "A soma de todos os elementos da matriz e igual a "<<result<<"."<<endl;
system("PAUSE
>
null");
return
0;
}
Tambm podemos utilizar funes que trabalhem com matrizes multidimensionais. Entretanto,
ao criar o parmetro da matriz preciso declarar o tamanho de todas as dimenses da matriz
com exceo da primeira. Por exemplo:
int soma_tabela ( int matriz [ ] [3] [4], int elementos) { comandos; }
A primeira dimenso deixada em branco, para ter seu tamanho definido pelo outro parmetro
elementos. Entretanto, as outras duas dimenses tem seu tamanho definido respectivamente
em 3 e 4. Caso deixssemos estas outras duas dimenses sem um tamanho definido, o
programa no seria compilado.
muito importante notar que, ao trabalhar com matrizes dentro de funes, estamos
trabalhando com a prpria matriz, ou melhor, com o endereo dos dados desta matriz.
Normalmente, quando trabalhamos com variveis dentro de uma funo, estamos trabalhando
com cpias destes valores. Entretanto, isso no verdade para matrizes, por razes que
veremos no mdulo sobre ponteiros. Por enquanto, basta saber que quando trabalhamos com
matrizes dentro de funes, qualquer modificao feita na matriz feita para valer. Se
somarmos mais 10 a todos os valores de uma matriz em uma funo, quando a funo
terminar a matriz estar modificada. Esta caracterstica muito til para contornar o fato que
no podemos utilizar uma matriz como retorno de uma funo: no precisamos que a funo
retorne uma matriz, s precisamos fazer com que a funo altere a matriz. Por exemplo, o
programa abaixo usa uma funo para ordenar os nmeros dentro de uma matriz.
#include
using
int
int
for
for
if
temp
matriz[i]
matriz[j]
}
}
}
}
<iostream>
std;
namespace
ordena(
(int
(int
i
j
(matriz[j]
int
temp
=
=
matriz[],
0;
i;
i
j
<
int
=
<
<
matriz
tamanho)
tamanho;
tamanho;
[i])
=
=
=
int
{
const
int
TAMANHO
=
int
sequencia[TAMANHO]
=
{27,
12,
cout
<<"Sequencia
original:
for
(int
i
=
0;
i
<
4;
cout
<<
sequencia[i]<<"
}
cout<<endl;
ordena(sequencia,
cout
<<"Sequencia
ordenada:
for
(int
i
=
0;
i
<
4;
cout
<<
sequencia[i]<<"
}
cout<<endl;
system("PAUSE
>
return
}
{
0;
i++){
j++){
{
matriz[i];
matriz[j];
temp;
main()
42,
i++)
4;
-8};
";
{
";
TAMANHO);
";
i++)
{
";
null");
0;
Para evitar este problema, a linguagem C++ introduz dois novos operadores de controle de
memria. Em primeiro lugar, temos o operador new, que utilizado para alocar espaos na
memria de computador durante a execuo de um programa. Em segundo lugar, o operador
delete, que libera a memria alocada com o operador new aps sua utilizao. Este tipo de
criao e destruio de variveis chamado de alocao dinmica. Uma matriz criada dessa
forma chamada de matriz dinmica.
A vantagem de se criar matrizes dinmicas que a memria utilizada pela matriz s tirada
do sistema aps a execuo do operador new, e pode ser liberada novamente aps sua
utilizao com o operador delete. Quando criamos uma matriz do jeito normal, a memria
utilizada por ela guardada pelo programa durante toda sua execuo, consumindo recursos
desnecessrios do computador.
A sintaxe para criar-se uma matriz utilizando o operador new a seguinte:
<tipo> * <nome> = new <tipo> [ <numero de elementos> ];
Por exemplo, para criar uma matriz do tipo float com 10 elementos:
float * lista = new float [10];
O acesso aos elementos da nova matriz feito de forma anloga ao de uma matriz criada do
jeito normal: utilizamos o nome da matriz seguido do nmero do elemento acessado. Como j
dito anteriormente, o primeiro elemento de uma matriz sempre o elemento 0.
Note que no podemos inicializar automaticamente os valores de uma matriz criada dessa
forma. Cada elemento da matriz deve ter seu valor atribudo separadamente.
A outra face do operador new o operador delete. S podemos utilizar este operador com
matrizes criadas pelo operador new, ou seja, matrizes criadas por declarao normal no
podem ser apagadas durante a execuo do programa. Para utilizar o operador delete para
apagar uma matriz, a sintaxe a seguinte:
delete <nome>;
O programa abaixo pede ao usurio o nmero de elementos da matriz, cria uma matriz e
depois volta a pedir ao usurio os valores de cada um dos elementos da matriz. No final do
programa, a matriz deletada.
#include
using
int
int
tamanho
cout<<"Entre
com
o
cin>>tamanho;
cout<<endl;
int
*sequencia
for
(int
i
=
0;
cout
<<
"Entre
com
o
cin>>sequencia[i];
cout<<endl;
}
cout<<"A
matriz
for
(int
i
=
0;
cout
<<
}
cout<<endl;
<iostream>
std;
namespace
main()
=
da
tamanho
=
i
elemento
<
new
tamanho;
"<<(i+1)<<"
da
entrada
e:
<
tamanho;
sequencia[i]<<"
matriz:
{
0;
";
int[tamanho];
i++)
{
matriz:
";
i++)
";
{
";
cout<<"Programa encerrado. A matriz criada ser deletada, e a memria ser devolvida para o
processador.";
delete
sequencia;
system("PAUSE
>
null");
return
0;
}
Mdulo 8 Strings
No falamos at agora de matrizes de caracteres, apesar de j utiliz-las vrias vezes. Uma
matriz de caracteres normalmente chamada de string em linguagem de programao. Em
C++, existem duas maneiras de se criar e trabalhar com strings. Um deles o mtodo antigo,
j utilizado pela linguagem C, de se declarar e trabalhar com uma matriz de caracteres do
mesmo modo que trabalhamos com matrizes numricas. O outro mtodo utilizar as
facilidades da biblioteca padro de C++, que define um tipo de varivel especfico para strings,
com vrias operaes e funes prprias. Nesta apostila trabalharemos com as strings do tipo
C++, por serem elas mais simples e ao mesmo tempo apresentarem mais recursos do que as
strings tipo C.
<iostream>
<string>
<nome
da
string>;
nacionalidade;
Uma string declarada desta forma estar vazia at que um valor seja atribudo ela, das
maneiras j estudadas: atravs de uma atribuio, ou de uma entrada de dados do usurio, por
exemplo.
C++ possui uma srie de facilidades para a inicializao de strings. Cada um desses diferentes
mtodos chamado de inicializador de uma string. A tabela abaixo rene os quatro principais
inicializadores de string:
string s1; - Cria uma string vazia, chamada s1. Esta a inicializao default de uma string:
toda
string
criada
dessa
forma
est
vazia.
string s2 (s1); - Cria a string s2 como uma cpia de outra string (nesse caso, s1).
string s2 (Esta uma string literal); - Cria a string s2 como uma cpia da string literal entre
os
parnteses.
string s2 (x, c); - Cria a string s2, que contm x cpias do caractere entre aspas (no caso, c).
namespace
<iostream>
<string>
std;
int
main()
{
string
vazia;
string
ditado("Casa
de
ferreiro,
espeto
de
pau");
string
copia_ditado(ditado);
string
letra_z(
42,
'z');
cout
<<"Mostrando
o
contedo
da
string
'vazia':"<<
endl;
cout
<<
vazia;
cout
<<"Mostrando
o
contedo
da
string
'ditado':"<<
endl;
cout
<<
ditado;
cout
<<"Mostrando
o
contedo
da
string
'copia_ditado':"<<
endl;
cout
<<
copia_ditado;
cout
<<"Mostrando
o
contedo
da
string
'letra_z':"<<
endl;
cout
<<
letra_z;
system("PAUSE
>
null");
return
0;
}
namespace
<iostream>
<string>
std;
int
main()
{
string
nome;
string
sobrenome;
cout<<"Digite
seu
nome:
";
cin
>>
nome;
cout<<"Digite
seu
sobrenome:
";
cin
>>
sobrenome;
cout << "Seu nome "<<nome<<" e seu sobrenome <<sobrenome<<"."<<endl;
system("PAUSE
>
null");
return
0;
}
Esse programa apresenta alguns problemas quando o usurio possui mais de um nome ou
sobrenome. Por exemplo, caso o nome Jos Ricardo seja inserido, a leitura do sobrenome
ser ignorada e o programa exibir Jos como o nome e Ricardo como sobrenome. Da
mesma forma, no caso da entrada de um sobrenome duplo, somente o primeiro sobrenome
guardado na string sobrenome, sendo o segundo ignorado. Isto acontece por causa da
maneira que C++ trata os espaos em branco em uma entrada via teclado.
Espaos em branco so considerados fim de entrada pelo comando cin; ao invs de descartar
os caracteres que vierem aps o espao em branco, C++ os guarda em um buffer (uma
espcie de reserva ou pilha de dados). Quando cin for chamado novamente, antes de ler a
nova entrada do teclado, o programa primeiro utiliza os dados que esto nesse buffer. Assim,
temos a impresso que a nova entrada de dados foi descartada pelo programa, mas na
verdade ela foi jogada no buffer, esperando uma nova chamada de cin.
Dessa forma, cin no o mtodo recomendado para ler frases inteiras, com palavras
separadas por espaos. Para este objetivo, utilizamos o mtodo cin.getline, que j estudamos
no mdulo 5, com algumas alteraes.
O mtodo cin.getline l linhas inteiras de entrada atravs do teclado, sem se importar com os
espaos em branco. Mas a sintaxe do mtodo cin.getline um pouco diferente, quando
trabalhamos com strings:
getline ( cin, <nome da string>);
Assim, este mtodo recebe todos os caracteres (incluindo os espaos em branco) entrados
pelo usurio, at que ele aperte a tecla Enter. O programa abaixo uma verso melhorada do
programa anterior, utilizando o mtodo cin.getline para receber os dados desejados.
#include
#include
using
int
{
string
string
cout<<"Digite
getline(cin,
cout<<"Digite
getline(cin,
cout <<"Seu nome
system("PAUSE
return
}
namespace
<iostream>
<string>
std;
main()
nome;
sobrenome;
seu
nome:
";
nome);
seu
sobrenome:
";
sobrenome);
"<<nome<<" e seu sobrenome "<<sobrenome<<"."<<endl;
>
null");
0;
s.empty( ) - Funo que retorna verdadeiro se a string est vazia, e falso caso
contrrio.
s.size ( ) - Funo que retorna o tamanho em caracteres da string.
s [n] - Acessa um elemento da string. Funciona exatamente com um elemento de uma
matriz.
s1 + s2 - Concatena duas strings.
s1 = s2 - Atribui o contedo de s2 na string s1.
A primeira funo, <string>.empty indica se uma string est vazia ou no. Esta funo retorna
um valor booleano verdadeiro ( true ou 1 ) caso a string esteja vazia, caso contrrio ela retorna
falso (false ou 0).
A funo <string>.size bastante til para trabalhar com strings entradas pelo usurio. Como
no podemos saber exatamente o nmero de caracteres entrados pelo usurio, til ter uma
funo que nos retorne o tamanho de uma string.
Como vemos acima, possvel acessar um elemento individual de uma string do mesmo modo
que fazemos com matrizes. Esse tipo de acesso til quando precisamos manipular os vrios
caracteres de uma string, como por exemplo, identificar as letras maisculas de uma string e
transform-las em minsculas. Para esse tipo de manipulao caractere caractere, contamos
com as diversas funes da biblioteca cctype, que veremos no item 8.5.
A concatenao de strings particularmente til. Quando utilizamos o sinal de soma entre duas
strings, estamos concatenando elas, ou seja, juntando o comeo da segunda matriz com o final
da primeira. Tambm possvel concatenar strings literais ( frases entre aspas) junto com as
variveis string dessa forma. O programa abaixo ilustra a concatenao de strings.
#include
#include
using
namespace
<iostream>
<string>
std;
int
main()
{
string
nome;
string
sobrenome;
cout<<"Digite
seu
nome:
";
getline(cin,
nome);
cout<<"Digite
seu
sobrenome:
";
getline(cin,
sobrenome);
string
concatena;
concatena
=
nome
+
sobrenome;
cout << "O seu nome completo : " + nome + " " + sobrenome << endl;
system("PAUSE
>
null");
return
0;
}
<iostream>
<string>
#include
using namespace std;
<cctype>
A tabela abaixo resume algumas das funes mais teis desta biblioteca (x um elemento de
uma string, por exemplo, sobrenome[4]) :
isalnum (x) - Retorna verdadeiro (1) caso x for uma letra ou um nmero.
isalpha (x) - Retorna verdadeiro (1) caso x for uma letra.
iscntrl (x) - Retorna verdadeiro (1) caso x for um dgito de controle.
isdigit (x) - Retorna verdadeiro (1) caso x for um nmero.
isgraph (x) - Retorna verdadeiro (1) caso x no for um espao.
islower (x) - Retorna verdadeiro (1) caso x for uma letra minscula.
isprint (x) - Retorna verdadeiro (1) caso x for um caractere imprimvel.
ispunct (x) - Retorna verdadeiro (1) caso x for um caractere acentuado.
isspace (x) - Retorna verdadeiro (1) caso x for um esao em branco.
isupper (x) - Retorna verdadeiro (1) caso x for uma letra maiscula
isxdigit (x) - Retorna verdadeiro (1) caso x for um nmero hexadecimal.
tolower (x) - Transforma um caractere maisculo em minsculo.
toupper (x) - Transforma um caractere minsculo em maisculo.
Com exceo das duas ltimas funes que transformam caracteres, todas as outras testam os
caracteres de uma string, retornando valores booleanos ( true ou false, 1 ou 0 ). O programa
abaixo mostra o uso de algumas dessas funes, atravs da leitura de uma string entrada pelo
usurio. Note que tambm feito o uso da funo <string>.size para determinar o tamanho da
string.
#include
<iostream>
#include
<string>
using
namespace
std;
int
main()
{
string
frase;
int
letras
=
0,
maiusculas
=
0,
minusculas
=
0,
numeros
=
0;
cout<<"Entre com uma frase qualquer, composta de letras maiusculas, minusculas e numeros:
"<<
endl;
getline(cin,
frase);
letras
=
frase.size();
cout<<"Sua
frase
tem
"<<
letras<<
"
letras."<<endl;
for
(int
i
=
0;
i
<
letras;
i++)
{
if
(isdigit(frase[i]))
numeros++;
if
(islower(frase[i]))
minusculas++;
if
(isupper(frase[i]))
maiusculas++;
}
cout<<"Sua
frase
tem
"<<
numeros<<
"
numeros."<<endl;
cout<<"Sua
frase
tem
"<<
minusculas<<
"
letras
minusculas."<<endl;
cout<<"Sua
frase
tem
"<<
maiusculas<<
"
letras
maiusculas."<<endl;
system("PAUSE
>
null");
return
0;
}
Mdulo 9 Ponteiros
9.1 - Endereos de Memria
J dissemos vrias vezes que as variveis ficam armazenadas em determinados espaos na
memria do computador. Ao trabalhar com uma varivel, geralmente no precisamos nos
preocupar com o endereo desta varivel, pois o compilador cuida destes detalhes tcnicos.
Entretanto, pode ser bastante til saber o endereo de uma varivel. Em C++, utilizamos o
operador de endereo & para acessar o endereo de uma varivel. Sua sintaxe muito
simples, bastando inserir o operador & na frente do nome de uma varivel:
&<varivel>
O programa abaixo cria uma varivel inteira e utiliza cout para exibir o valor da varivel e
depois seu endereo, utilizando o operador &.
#include
using
<iostream>
std;
namespace
int
{
int
valor
cout
<<
"A
variavel
cout
<<
cout
<<
"A
variavel
esta
cout
<<
system(PAUSE
return
}
main(
=
o
valor
armazenada
no
&valor
>
armazena
seguinte
seguinte
124;
";
<<endl;
endereo:
";
<<endl;
null);
0;
valor:
<iostream>
std;
namespace
main(
=
{
<<
<<
<<
"
"
"
42,
"
"
"
:
:
:
>
<<
<<
<<
37,
matriz[0]
matriz[1]
matriz[2]
28
<<
<<
<<
};
endl;
endl;
endl;
null);
0;
9.2 Ponteiros
Em linguagem de programao, chamamos de ponteiros as variveis especiais que
armazenam endereos de memria. Como j vimos, as variveis possuem trs atributos
bsicos: seu nome, o valor armazenado por ela e o endereo de memria onde ela est
armazenada. Os ponteiros, ao invs de armazenar valores, armazenam endereos de
memria. Ao utilizar um ponteiro, podemos acessar este endereo e manipular o valor que est
armazenado l dentro.
Ponteiros so utilizados constantemente em C++. Por exemplo, quando trabalhamos com
matrizes sem saber estamos trabalhando com ponteiros: a linguagem C++ ( e a linguagem C
tambm) utiliza ponteiros para acessar as diversas posies de uma matriz.
A declarao de ponteiros bem parecido com a declarao de variveis. Assim como uma
varivel comum, ponteiros precisam ter tipos (como int, float, long) para indicar ao compilador
qual o tipo de valor para o qual o ponteiro aponta. Alm disso, utilizamos o asterisco * antes do
nome do ponteiro, para indicar ao compilador que estamos declarando um ponteiro e no uma
varivel simples. A sintaxe da declarao de um ponteiro vista abaixo:
<tipo> * <nome do ponteiro>;
Ponteiros podem ser de qualquer tipo, como int, float, long e at mesmo sem tipo (void). Abaixo
temos alguns exemplos de declarao de ponteiro:
int
float *media;
*referencia;
Aps declarar um ponteiro, importante atribuir o endereo que ser armazenado por ele. Isto
feito utilizando o operador & para obter o endereo de uma varivel. A atribuio feita da
mesma forma que atribuimos valores para uma varivel. Suponha que tenhamos em um
programa qualquer um ponteiro chamado referencia e uma varivel chamada valor. Caso
desejssemos que o ponteiro referencia armazenasse o endereo da varivel valor, faramos a
seguinte atribuio:
referencia = &valor;
O programa abaixo simplesmente o primeiro programa-exemplo deste mdulo, reescrito
utilizando-se um ponteiro para armazenar o endereo da varivel. Note que cout exibe
corretamente o endereo armazenado pelo ponteiro, da mesma maneira que exibiria uma
varivel:
#include
using
int
{
int
valor
int
cout
<<
"A
variavel
cout
<<
cout
<<
"A
variavel
esta
referencia
cout
<<
system(PAUSE
return
}
<iostream>
std;
namespace
main(
)
=
armazena
o
valor
armazenada
no
=
referencia
>
seguinte
seguinte
124;
*referencia;
valor:
";
<<endl;
endereo:
";
&valor;
<<endl;
null);
0;
O programa abaixo bastante parecido com os anteriores, mas utiliza o asterisco de indireo
para obter o valor da posio de memria indicada pelo ponteiro. Alm disso, este valor
modificado utilizando este mesmo operador:
#include
using
<iostream>
std;
namespace
int
{
int
int
ponteiro
cout
<<
cout
cout
<<
cout
cout
*ponteiro
cout
<<
cout
system(PAUSE
return
}
main(
valor
)
=
*
=
"Endereo
apontado
pelo
<<
ponteiro
"Valor
guardado
por
este
<<
*ponteiro
<<
Valor
=
"Novo
valor
guardado
por
este
<<
*ponteiro
>
42;
ponteiro;
&valor;
ponteiro:
";
<<endl;
endereo:
";
<<endl;
atualizado!;
12458;
endereo:
";
<<endl;
null);
0;
Esta operao til para acessar e modificar valores dentro de posies de memria. Um
ponteiro com o asterisco de indireo se comporta como uma varivel comum. Podemos
utiliz-lo em comandos, expresses, atribuies e onde mais for necessrio.
soma
int
parcela1,
da
int
parcela2)
{
funo
}
A declarao de ponteiros como parmetros feita da mesma forma que declararamos
ponteiros em um programa, declarando o tipo e utilizando o asterisco para indicar que se trata
de um ponteiro.
Ao escrever o corpo da funo, tambm preciso ateno. Como estamos trabalhando com
um ponteiro, preciso lembrar que um ponteiro indica um endereo. Quando precisamos do
valor guardado neste endereo, preciso usar o asterisco antes do ponteiro. Assim, qualquer
operao envolvendo o valor indicado pelo ponteiro deve conter o ponteiro acompanhado do
asterisco. Caso utilizemos o prprio ponteiro, no estamos alterando o valor, e sim o endereo.
De forma resumida:
ponteiro
*ponteiro ? valor
endereo
muito importante ter isso em mente ao criar funes que utilizem ponteiros. A confuso entre
o uso de um ponteiro como endereo ou como valor a principal fonte de erros nestas
situaes. O cdigo abaixo o corpo de uma funo que utiliza ponteiros. Note que utilizamos
um ponteiro e uma varivel normal como parmetros. Alm disso, sempre que utilizamos o
valor referenciado pelo ponteiro durante a funo, utilizamos o asterisco de dereferenciao
antes do nome do ponteiro.
void
int
if
*variavel
return;
}
if
potencia(
int
original
*variavel,int
(elevado
==
=
(elevado
for
(int
*variavel
}
elevado)
0)
==
=
{
2;
{
1;
2;
1)
<=
return;
elevado;
i++)
{
*variavel*original;
Quando utilizamos uma funo deste tipo, preciso que o programa passe um ponteiro como
parmetro desta funo. Isto pode ser feito de duas maneiras: indicando um ponteiro que
contenha um endereo, ou indicando simplesmente o endereo de uma varivel. Como j
vimos, utilizamos o operador & antes do nome de uma varivel para obter seu endereo.
Assim, uma funo que utiliza ponteiros aceita em seu parmetro um ponteiro ou o endereo
de uma varivel ( &varivel ).
O programa abaixo mostra a utilizao de uma funo com chamada por referncia, tendo em
mente os cuidados descritos anteriormente.
#include
using
void
int
if
*variavel
return;
}
if
for
(int
*variavel
}
}
<iostream>
std;
namespace
potencia(
int
original
*variavel,int
(elevado
==
=
(elevado
i
=
int
{
int
int
potencia(
cout
<<
"dois
system("PAUSE
elevado)
{
2;
{
1;
==
i
2;
0)
1)
elevado;
<=
return;
i++)
{
*variavel*original;
main()
dois
j
elevado
=
=
a
"<<
&dois,
j
<<"
>
"<<
dois
<<
2;
5;
j);
endl;
null");
return
}
0;
A utilizao da chamada por referncia parece no ter muita utilidade quando trabalhamos com
variveis simples. Porm, este cenrio muda quando trabalhamos com matrizes: a utilizao da
chamada por referncia a melhor forma de se criar funes que trabalham com matrizes.
conhecido. Os dois mtodos so vlidos e tem sua utilidade, mas de modo geral mais
simples e recomendvel utilizar matrizes do modo j estudado.
#include <iostream> using namespace std; int ordenamatriz( int matriz[], int tamanho) { int temp
= 0; for (int i = 0; i < tamanho; i++){ for (int j = i; j < tamanho; j++){ if (matriz[j] < matriz [i]) { temp
= matriz[i]; matriz[i] = matriz[j]; matriz[j] = temp; } } } } int ordenaponteiro (int *matriz, int
tamanho) { int temp = 0; for (int i =0; i < tamanho; i++) { for (int j = i; j < tamanho; j++){ if (
*(matriz + j) < *(matriz + i ) ) { temp = *( matriz + i ); *(matriz + i) = *(matriz + j); *(matriz + j) =
temp; } } } } int main() { const int TAMANHO = 4; int sequencia[TAMANHO] = {27, 12, 42, -8}; int
sequencia2[TAMANHO] = {21, -27, 1024, 42}; cout<<endl; ordenamatriz(sequencia,
TAMANHO); ordenaponteiro(sequencia2, TAMANHO); cout <<"Sequencia ordenada 1: "; for
(int i = 0; i < 4; i++) { cout << sequencia[i]<<" "; } cout<<endl; cout <<"Sequencia ordenada 2: ";
for (int i = 0; i < 4; i++) { cout << sequencia2[i]<<" "; } cout<<endl; system("PAUSE > null");
return 0; }
desreferncia * duas vezes. O programa abaixo mostra trs maneiras diferentes de se acessar
o valor de inteiro: acessando a prpria varivel, utilizando um ponteiro e o operador de
desreferncia, ou utilizando um ponteiro para ponteiro e o operador de desreferncia duas
vezes.
#include <iostream> using namespace std; int main() { int inteiro = 1024; int *pontinteiro =
&inteiro; int **pontponteiro = &pontinteiro; cout << "Acessando o valor da variavel inteiro:
"<<endl; cout << "De forma direta (pela propria variavel): "<< inteiro << endl; cout << "De forma
indireta (pelo ponteiro para variavel pontinteiro): "<< *pontinteiro << endl; cout << "De forma
duplamente indireta (pelo ponteiro para ponteiro pontponteiro): "<< **pontponteiro << endl;
system("PAUSE > null"); return 0; }
Na verdade, C++ nos permites criar infinitas indirees (ponteiros para ponteiros para
ponteiros...e assim por diante). Mas na prtica, a utilizao de ponteiros para ponteiros
geralmente evitada por causar grande confuso e dificultar a compreenso dos programas.
Explicaremos o uso de cada um deles, cada vez nos aprofundando mais no assunto. Por
enquanto, veremos como criar um arquivo e escrever algumas strings nele utilizando um objeto
ofstream.
Para criar um objeto ofstream, declaramos seu nome de maneira parecida com a declarao
de uma varivel:
ofstream <nome do objeto>
Por exemplo:
ofstream escreve;
A linha acima cria o objeto escreve, do tipo ofstream, capaz de escrever em arquivos. O
prxima passo associar este objeto a um arquivo. Para isto, utilizamos a funo open( ), que
abre o arquivo desejado ou cria um arquivo no disco rgido. A sintaxe de open( ) a seguinte:
<objeto>.open(nome do arquivo);
Por exemplo, vamos utilizar o objeto escreve para criar um arquivo chamado strings.txt.
Para fazer isso, utilizamos a funo open da seguinte maneira:
escreve.open(strings.txt);
Dessa forma, estamos associando o objeto escreve ao arquivo strings.txt. Agora podemos
enviar dados atravs do objeto escreve, e estes dados sero escritos no arquivo strings.txt.
Para fazer isso, utilizamos o objeto que criamos da mesma forma que utilizamos o comando
cout. Da mesma forma como escreveramos na tela do computador com o comando cout
utilizando variveis, strings, strings literais, formatao, etc, podemos utilizar estes recursos
todos tambm com os objeto do tipo ofstream, com a diferena que estas informaes sero
gravadas em um arquivo. O exemplo abaixo rene todos os passos anteriores e utiliza o objeto
escreve para escrever diversos dados em um arquivo, para dar uma idia melhor de suas
possibilidades.
#include
#include
#include
using
int
namespace
<iostream>
<fstream>
<string>
std;
main(){
string
frase;
cout<<"Escreva
uma
frase
para
ser
escrita
no
arquivo
string.txt:";
getline(cin,
frase);
cout<<"Obrigado.
Escrevendo
dados
no
arquivo
strings.txt...\n";
ofstream
escreve;
escreve.open("strings.txt");
escreve << "Utilizamos os objetos ofstream para escrever em arquivos\n";
escreve<< "Note que podemos utilizar os caracteres \\n pra quebrar a linha, como fazamos em
cout\n";
int
numero
=
100;
escreve<<"Podemos escrever o valor de variaveis numericas: " <<numero <<"\n";
int
matriz[3]
=
{42,
19,
99};
escreve<<"Podemos
tambm
escrever
matrizes!";
for
(int
i=0;
i
<
3;
i++){
escreve.width(6);
escreve<<matriz[i]<<"
";
}
escreve<<"\n";
escreve<<"Finalmente, podemos receber dados via cin e escrever estes dados no arquivo!\n";
escreve<<"A frase que voc digitou durante a execuo do programa: "<<frase<<"\n";
escreve.close();
cout<<"Dados
system("PAUSE");
return
}
escritos
no
arquivo.
Fim
do
Programa!";
0;
Procure o arquivo strings.txt em seu sistema, e abra ele (ele provavelmente est no mesmo
diretrio onde est o arquivo executvel do programa que compilamos. Por definio, estes
arquivos ficam no diretrio onde est o compilador, a menos que tenhamos configurado o
compilador para salv-los em outro lugar.). Percebeu a semelhana entre a utilizao do objeto
ofstream com o comando cout? Todos os mtodos que vimos com cout para exibir um dado na
tela podem ser utilizado para gravar um dado em um arquivo.
))
abrir
objeto
arquivo!
Programa
leitura, para limpar
ser
memria
terminado!\n;
do sistema
0;
leitura;
Aps criarmos o objeto e conectarmos ele um arquivo, podemos comear a ler atravs deste
arquivo. A leitura de dados de um arquivo parecida com a leitura de dados enviados atravs
do teclado: criamos uma varivel para armazenar os dados recebidos, e utilizamos o objeto
ifstream para ler e enviar os dados do arquivo para o programa (no caso da leitura via teclado,
o objeto cin receberia os dados enviados pelo usurio e os repassaria para o programa).
Assim, podemos utilizar qualquer um dos mtodos de leitura que estudamos para cin, seja para
ler caracteres, palavras ou frases inteiras.
Para lermos somente um caractere de um arquivo, por exemplo, nossa melhor opo utilizar
o mtodo .get, que serve justamente para esta funo. Criamos uma varivel do tipo char para
armazenar este caractere, e utilizamos o objeto ifstream da forma mostrada no exemplo
abaixo:
char
leitura.get( armazena);
armazena;
O exemplo de cdigo acima utiliza o objeto leitura e o mtodo .get para ler um caractere de
um arquivo, e armazena este caractere na varivel armazena. Poderamos criar um lao de
repetio para obter todos os caracteres do arquivo, como vemos no exemplo abaixo. O lao
while continuar a executar o mtodo .get para ler o arquivo, at que seja encontrado o fim do
arquivo. Quando o fim do arquivo encontrado, o comando leitura.get(armazena) retorna
falso para o lao while, terminando a repetio. Lembre-se que o arquivo strings.txt deve
estar no mesmo diretrio onde estamos executando o programa, caso contrrio erros
ocorrero!
#include
#include
#include
using
<iostream>
<fstream>
<string>
std;
namespace
int
main(){
char
ifstream
leitura.open("strings.txt");
letra;
leitura;
if(!leitura.is_open(
{
cout<<"No
foi
possvel
leitura.clear( ); //reseta o
}
))
abrir
objeto
while
(leitura.get(letra))
leitura.close();
system("PAUSE");
return
}
arquivo!
Programa
ser
leitura, para limpar memria
{cout
<<
terminado!\n";
do sistema}
letra;}
0;
Para lermos uma palavra inteira de um arquivo, ao invs de utilizarmos uma simples varivel de
tipo char, utilizamos uma matriz do tipo char. Da mesma maneira que o comando cin, o objeto
ler todos os caracteres em seu caminho, at que a matriz atinja seu tamanho mximo
especificado OU encontre um espao em branco, uma quebra de linha ou o fim do arquivo.
char
leitura >> matriz_chars;
matriz_chars[80];
Finalmente, para lermos uma linha inteira de um arquivo, utilizamos o mtodo .getline, que j
havamos estudado no mdulo 5. O mtodo getline l uma linha inteira de entrada, at que o
tamanho mximo especificado seja atinjido ou at encontrar uma quebra de linha ou o fim de
arquivo. Relembrando sua sintaxe:
<nome do objeto>.getline ( <matriz_destino>, <limite de caracteres>);
Por exemplo:
char
leitura.getline( matriz_chars, 80);
matriz_chars[80];
O comando acima leria todos os caracteres de uma linha, at encontrar a quebra da linha.
Como vimos com o mtodo .get, podemos utilizar um lao de repetio para lermos todas as
linhas de um arquivo utilizando o mtodo getline. No exemplo abaixo, cada repetio uma
linha do arquivo ser escrita na tela.
#include
#include
#include
using
<iostream>
<fstream>
<string>
std;
namespace
int
main(){
char
ifstream
leitura.open("strings.txt");
if(!leitura.is_open(
{
cout<<"No
foi
possvel
leitura.clear( ); //reseta o
}
while
(leitura.getline(depot,
leitura.close();
system("PAUSE");
return
}
depot[300];
leitura;
))
abrir
objeto
arquivo!
Programa
ser
leitura, para limpar memria
300))
{cout
<<
depot
terminado!\n";
do sistema}
<<"\n";}
0;
Uma pequena diferena que vemos entre esses dois mtodos de ler um arquivo inteiro, que o
mtodo .get l todos os caracteres at o fim de arquivo, incluindo quebras de linha. O mtodo
getline utiliza as quebras de linha para determinar o fim de sua leitura, e descarta elas. Assim,
no exemplo logo acima, tivemos que instruir o programa adicionar uma quebra de linha aps
exibir na tela cada uma das linhas lidas. (Entretanto, lembre-se que para arquivos grandes, o
mtodo getline mais eficiente e mais rpido. Tenha em mente que cada acesso de um objeto
fstream um arquivo demanda um certo processamento: em um arquivo grande, se temos
centenas de linhas, ento temos milhares de caracteres, o que significa que o mtodo get
acessar muito mais vezes o mesmo arquivo do que o mtodo getline).
novamente. Os modos de arquivo servem justamente para isto: para definir como deve ser o
comportamento de um arquivo quando acessado pelo programa. Podemos definir que o
arquivo ser utilizado somente para leitura ou somente escrita, se ser utilizado para anexar
dados ou se ser reescrito totalmente. Definimos o modo do arquivo quando abrimos ele com
um objeto, adicionando um parmetro novo ao mtodo open. Veja a sintaxe abaixo:
<objeto ofstream>.open(nome do arquivo, ofstream::<modo de arquivo>);
ou
<objeto ifstream>.open(nome do arquivo, ofstream::<modo de arquivo>);
A tabela abaixo resume os modos de arquivo disponveis em C++.
ios_base::in
Abre
arquivo
para
leitura.
ios_base::out
Abre
arquivo
para
escrita.
ios_base::ate
Procura
o
final
do
arquivo
ao
abrir
ele.
ios_base::app
Anexa
os
dados
serem
escritos
ao
final
do
arquivo.
ios_base::trunc
Trunca
os
dados
existentes
no
arquivo.
ios_base::binary Abre e trabalha com arquivos em modo binrio.
Note que um arquivo aberto por um objeto ofstream no necessita que definamos o modo de
arquivo ofstream::out, pois este modo j definido para este tipo de objeto por definio. O
mesmo ocorre com o modo ifstream::in e os objetos ifstream.
Alm disso, por definio, um arquivo aberto por um objeto ofstream ir truncar os dados j
existentes no arquivo, escrevendo os dados novos por cima dos antigos. Porm, o modo
ofstream::app nos permite anexar dados ao final de um arquivo. O exemplo abaixo utliza o
modo ofstream::app para criar uma espcie de agenda simplificada em um arquivo de texto.
#include
#include
#include
using
int
int
char
cout<<"PROGRAMA
namespace
main(){
mes;
letra[1000];
0.00042\n";
dia,
AGENDA
Verso
ofstream
agenda.open("agenda.txt",
cout<<"Digite
o
compromisso
no
cin.getline(letra,
cout
<<
"Digite
o
cin
>>
cout
<<
"Digite
o
cin
>>
agenda << "Compromisso
agenda
agenda<<"\n";
cout<<"Obrigado!
Sua
agenda.close();
system("PAUSE");
return
}
<iostream>
<fstream>
<string>
std;
marcado
agenda
para
<<
foi
agenda;
ofstream::app);
espao
abaixo
():
\n";
1000);
dia
do
compromisso:\n";
dia;
ms
do
compromisso:\n";
mes;
dia
"<<dia<<"
atualizada
de
com
"<<mes<<": ";
letra;
sucesso!";
0;
Em termos de programao, uma classe uma estrutura que contm variveis e funes com
o objetivo de representar uma idia. Dentro de uma classe, as variveis e funes so
chamadas de membros da classe. Ainda pensando no exemplo do relgio, dentro desta
classe teramos variveis (ou membros) para as horas, minutos, segundos e tambm para
armazenar o horrio do alarme, assim como funes-membro para ver o horrio atual, ajust-lo
ou ajustar o alarme. Porm, o usurio no precisa ter acesso todas estas variveis: eles s
precisa interajir com as caractersticas operacionais do relgio. Assim, criamos funesmembro para fazer esta interao: uma funo para ver as horas, outra para ajustar o horrio e
outra para ajustar o alarme. Dessa forma, simplificamos a utilizao da classe e tambm
evitamos que o usurio acesse e altere dados que possam atrapalhar o funcionamento do
programa.
Dizemos que os membros da classe que o usurio pode acessar so pblicos, enquanto que
os membros internos so privados. Um membro privado no pode ser acessado ou alterado
pelo usurio: no queremos o usurio cutucando as engrenagens do relgio. Os membros
privados so acessados somente pelos membros pblicos, que fazem a interao entre as
engrenagens do programa e o usurio. Assim, mesmo que tenhamos funes como membros
privados, elas s podem ser executadas por outras funes que sejam membros pblicos da
funo. A funo pblica ver horrio de nossa classe Relgio provavelmente precisa acessar
uma funo privada que atualiza o horrio do relgio, assim como a funo ajusta alarme
altera uma varivel privada que contm o horrio do alarme.
Formalizando, um membro pblico, seja ele uma varivel ou uma funo pode ser acessado a
qualquer momento durante a execuo de um programa (lido ou alterado no caso das
variveis, executado no caso das funes). Quando tentamos acessar diretamente um membro
privado, geramos um erro pois seu acesso proibido para o usurio/programador! Assim, a
nica forma de acessar um membro privado atravs dos membros pblicos. Esta separao
entre membros pblicos e privados feita na declarao da classe.
O prximo conceito essencial da programao orientada objetos o prprio objeto. Um
objeto uma instncia especfica de uma classe. Podemos pensar na classe como um tipo de
varivel, enquanto que o objeto a prpria varivel. Em C++, definimos classes para depois
criar objetos que tenham as caractersticas definidas nestas classes. No exemplo acima,
definimos a classe Relgio, e agora podemos criar quantos relgios forem necessrios: cada
relgio ser um objeto diferente, com funcionamento idntico e caractersticas diferentes. Por
exemplo, criamos os objetos relgio de pulso e relgio-cuco. Os dois so relgios, mas
podemos ajust-los em horrios diferentes, com alarmes diferentes. Cada objeto possui todos
os membros pblicos e privados que definimos na declarao da classe. Assim, utilizamos os
membros pblicos para interajir com os objetos, enquanto que os membros privados so as
engrenagens do objeto. Aqui temos um novo nome para os membros pblicos: chamamos
eles de mtodos do objeto. Um mtodo nada mais do que uma funo que interaja com o
objeto, ou seja, so prprios os membros pblicos que definimos na declarao da classe.
Para termos um exemplo mais concreto, podemos pensar em um programa qualquer do
ambiente Windows. Nas ferramentas de programao Windows, temos vrias classes que
representam os vrios itens que vemos na tela: janelas, menus, cursores, cones. Quando um
programador precisa criar uma janela, ele no precisa ter todo o trabalho para programar uma
janela do zero: ele cria um novo objeto da classe Janela, e define suas caractersticas atravs
das funes pblicas (ou mtodos) da classe. Ele no precisa saber como a janela
desenhada na tela: basta saber quais mtodos definem as caractersticas que ele necessita
para que seu objeto funcione da maneira desejada.
Referncias Bibliogrficas
[1] TORRES, Jair Gustavo M. - Curso de Linguagem C - Ilha Solteira : Faculdade de
Engenharia de Ilha Solteira - FEIS - UNESP - Departamento de Engenharia Eltrica , 2006.
[2] PRATA, Stephen - C + + Primer Plus , 4 edio - Nova York: Sams Publishing. 2001.
[3] Stroustrup , Bjarne - O C + + Programming Language , 3 edio - New Jersey: Addison Wesley. 1997.
[4] LIPPMAN, Stanley B.; LAJOIE, Jose Lajoie , MOO , Barbara E. - C + + Primer , 4 edio New Jersey: Addison- Wesley. 2005.
Downloads
Download da Apostila
Clique no link abaixo para abrir ou salvar a apostila completa em formato pdf, pronto para
impresso ou leitura offline:
Exemplos da Apostila
Abaixo podem ser baixados todos os cdigos dos programas exemplos encontrados na
apostila, separados pelos captulos em que so encontrados:
Exemplos do Mdulo 2
Exemplos do Mdulo 4
Exemplos do Mdulo 6
Exemplos do Mdulo 7
Exemplos do Mdulo 8
Exemplos do Mdulo 9
Home
ndice
Mdulo 01
Mdulo 02
Mdulo 03
Mdulo 04
Mdulo 05
Mdulo 06
Mdulo 07
Mdulo 08
Mdulo 09
Mdulo 10
Mdulo 11
Bibliografia
Downloads
Apostila de C++ - Faculdade de Engenharia de Ilha Solteira - Enrique Camargo Trevelin - 2007