| #include <iostream.h> #include <fstream.h> void main() { char c; ifstream infile("xxx"); ofstream outfile("yyy"); if (outfile && infile) // They will be 0 on err. while (infile >> c) outfile << c; } |
| As variáveis infile e outfile recebem o nome do arquivo na inicialização e são usadas exatamente como cin e cout. O código desse exemplo não funciona como seria de esperar porque brancos, tabs e caracteres \0 ao final de cada linha são ignorados, do mesmo modo que espaço em branco quando se usa <<. Nesse caso, melhor usar a função get, como mostrado a seguir: |
| while (infile.get(c)) outfile << c; |
| ou |
| while (infile.get(c)) outfile.put(c); |
| É ainda possível ler linhas inteiras usando-se a função getline, da mesma maneira que se usa a função get. Para abrir um arquivo para acrescentar dados, use o seguinte: |
| ofstream("xxx", iosapp); |
| Essa linha, bem como a notação da função .get, fará mais
sentido na medida em que você conheça mais sobre o C++. O fato de ofstream algumas
vezes receber um, outras vezes dois parâmetros é uma característica
intrínseca ao C++. Note que não há necessidade de uma função close para os arquivos de entrada ou de saída. O arquivo é fechado automaticamente quando se encera o escopo da variável que denomina o arquivo. Se você precisar fechar explicitamente um arquivo, use |
| outfile.close(); |
| 2.3.3 - I/O em string |
| Entradas podem ser lidas a partir de string na memória, e saídas pode ser enviadas para strings na memória, duplicando-se assim as ações de sscanf e sprintf. Para tanto você deve incluir o arquivo strstream.h e declarar a entrada e a saída em string. Uma saída em string e mostrada a seguir: |
| char s[100]; ostrstream outstring(s,100); outstring << 3.14 << " is pi" << ends; cout << s; |
| O string
s é preenchido com o texto 3.14 is pi. Se o tamanho de s for atingido, outstring vai automaticamente interromper a colocação de valores em s. Se um string s já existe e você deseja ler dados a partir dele, você pode usar um fluxo de entrada string como mostrado a seguir: |
| char *s =
"3.14 12 cat"; istrstream instring(s, strlen(s)); float f; int i; char t[100]; instring >> f >> i >> t; |
| A biblioteca iostream tem muitas e muitas outras capacidades não discutidas aqui. Para maiores informações, veja a documentação fornecida junto com o seu compilador. Ela geralmente contém uma referência completa para a biblioteca de I/O |
| 2.4 - Declarações de variáveis |
| Variáveis são declaradas em C++ assim como o são em C. As variáveis podem ser declaradas em qualquer ponto do código em C++, estabelecendo um nível de flexibilidade quase como o que existe em FORTRAN. A variável torna-se existente quando é declarada, e deixa de existir quando o } do bloco corrente é encontrado. Por exemplo, na seguinte codificação: |
| { int i; ... code ... int j; ... code ... int k=func(i,j); ... code ... } |
| todas as três variáveis passam a existir no ponto em que são declaradas, e desaparecem ao }. |
| 2.5 - Constantes |
| Em C você cria uma constante usando uma macro do pré-processador, como no seguinte exemplo: |
| #define MAX 100 |
| Quando o programa é compilado, o pré-processador
encontra cada ocorrência da palavra MAX e a substitui pelo string 100. Em C++ usa-se a palavra const, que é aplicável normalmente às declarações de variáveis: |
| const int MAX=100; |
| A codificação int MAX=100; é formatada
exatamente da mesma maneira que uma declaração normal. O termo const que
precede a declaração simplesmente define que a variável MAX não pode ser modificada.
O uso de letras maiúsculas para nomes de variáveis constantes é uma tradição em C,
que você pode preservar ou abandonar. O modificador const pode também ser usado em listas de parâmetros para especificar o uso correto do parâmetro. As três funções a seguir exemplificam diferentes usos de const. |
| void func1(const int
i) { i=5; // cannot modify a constant } void func2(char * const s) { s="hello"; // cannot modify the pointer } void func3(const char * s) { s="hello"; // this is OK *s='A'; // cannot modify what is pointed to } |
| A notação mostrada em func2 deve, sempre que possível, ser usada quando um parâmetro char* é passado para a função. |
| 2.6 - Sobrecarregando funções |
| Um dos mais poderosos novos recursos do C++ é denominado sobrecarga de função. Uma função sobrecarregada possui várias e diferentes listas de parâmetros. A linguagem distingue qual das opções de chamada da função deve ser usada, com base no padrão das listas de parâmetros. Aqui está uma demonstração extremamente simples desse processo: |
| #include <iostream.h> void func(int i) { cout << "function 1 called" << endl; cout << "parameter = " << i << endl; } void func(char c) { cout << "function 2 called" << endl; cout << "parameter = " << c << endl; } void func(char *s) { cout << "function 3 called" << endl; cout << "parameter = " << s << endl; } void func(char *s, int i) { cout << "function 4 called" << endl; cout << "parameter = " << s; cout << ", parameter = " << i << endl; } main() { func(10); func('B'); func("hello"); func("string", 4); return 0; } |
| Quando esse código é executado, cada versão da função func é escolhida, e chamada, de acordo com as correspondências entre as listas de parâmetros. Você vai conseguir usar essa capacidade, que é uma grande característica do C++, uma vez que você encare sobrecarga de função como uma solução para muitos dos problemas de programação. Por exemplo, se você cria uma função para inicializar um módulo, você pode ter uma chamada diferente, para a mesma função, dependendo da característica do parâmetro que é passado; um string, um inteiro, um ponto flutuante, e assim por diante. |
| 2.7 - Argumentos default |
| C++ também permite que você determine valores default para os parâmetros. Se o parâmetro não for passado, o valor default é usado. Essa capacidade é demonstrada no seguinte código: |
| #include <iostream.h> void sample(char *s, int i=5) { cout << "parameter 1 = " << s << endl; cout << "parameter 2 = " << i << endl; } main() { sample("test1"); sample("test1",10); return 0; } |
| A primeira chamada da função vai apresentar o valor
default 5 para o parâmetro i, enquanto a segunda chamada vai apresentar o valor 10. Quando criando parâmetros default, você precisa evitar ambigüidade entre as listas de parâmetros default e as demais listas de parâmetros. Examinando a função de nosso último exemplo, não é possível criar uma versão sobrecarregada que aceite um parâmetro char* isolado, porque o compilador não conseguiria escolher que versão chamar no caso de se passar um string. |
| 2.8 - Alocação de memória |
| C++ substitui as funções C de alocação e de
desalocação de memória , malloc e free, pelas novas funções new e delete, respectivamente e
torna esse processo muito mais fácil para o programador. new e delete permitem
que tipos de dados definidos pelo programador sejam alocados e desalocados tão facilmente
quanto os tipos já existentes em C++. O código seguinte exemplifica o modo mais simples de uso de new e delete. Um pointer para um inteiro aponta para um bloco de memória criado por new: |
| int *p; p = new int; *p = 12; cout << *p; delete p; |
| É ainda possível alocar blocos compostos de matrizes de tamanhos variados, usando uma técnica similar. Repare o uso de [] para excluir a matriz: |
| int *p; p = new int[100]; p[10] = 12; cout << p[10]; delete [] p; |
| O valor 100 poderia ser uma variável, se desejável. Quando aplicada a tipos de dados definidos pelo programador, new funciona do mesmo modo. Por exemplo: |
| typedef node { int data; node *next; } node; main() { node *p; p=new node; p->date = 10; delete p; } |
| Conforme veremos mais adiante nessa série de tutoriais, o operador delete é bastante sofisticado quando opera com classes definidas pelo programador. |
| 2.9 - Declarações de referência |
| Em C, pointers são freqüentemente usados para passar parâmetros para funções. Por exemplo, a seguinte função swap inverte dois valores que lhe são passados: |
| void swap(int *i, int
*j) { int t = *i; *i = *j; *j = t; } main() { int a=10, b=5; swap(& a, & b); cout << a << b << endl; } |
| C++ provê um novo operador de referência que simplifica muito essa sintaxe. O seguinte código funciona em C++ |
| void swap(int&
i, int& j) { int t = i; i = j; j = t; } main() { int a=10, b=5; swap(a, b); cout << a << b << endl; } |
| Os parâmetros i e j declarados como tipo int& atuam como referências para os inteiros passados (leia int& como uma referência para um inteiro). Quando uma variável é atribuída à referência de uma outra variável, a referência toma o endereço da variável e opera a atribuição para a localização real para a variável . Por exemplo: |
int a; int & b=a; a=0; b=5; cout << a << endl; |
| O código acima produz 5 como saída porque b referencia a. É o mesmo que usar pointer e operadores de endereços em C, mas a sintaxe aqui é muito mais simples. Note que b deve ser inicializado quando de sua criação, como mostrado no exemplo. |
| © 1998 Interface Technologies, Inc by Marshall Brain Tradução de Dagoberto Haele Arnaut |
| | Home | Bookmarks | Universidades | Para Saber mais | Universidades | WEB Directory | Mapa do site | | |