• Nenhum resultado encontrado

Register

No documento Apostila3LinguagemCeC++ (páginas 44-54)

6 Comandos para Tomada de Decisão

7.4.5 Register

A classe de armazenamento register indica que a variável associada deve ser guardada fisicamente numa memória de acesso muito mais rápida chamada registrador. Um registrador da máquina é um espaço de memória junto ao microprocessador onde se podem armazenar variáveis do tipo inteiro ou char. Opera como uma variável do tipo auto, mas possui um tempo de acesso muito mais rápido, isto é, o programa torna-se mais rápido usando register. Variáveis que usualmente utilizam este tipo são as variáveis de laços e argumentos de funções, justamente, para que possamos aumentar a velocidade do programa.

Como os computadores possuem um número limitado de registradores (2 para o IBM-PC), o seu programa também só poderá utilizar um número limitado de variáveis register. Mas isto não nos impede de declarar quantas variáveis register quisermos. Se os registradores estiverem ocupados o computador simplesmente ignora a palavra register das nossas declarações.

register int i;

for(i = 0; i< 10; i++)

printf(“Número: %d”, i);

7.5 Exercícios

7.1 Um número primo é qualquer inteiro positivo divisível apenas por si próprio e por 1. Escreva uma função que receba um inteiro positivo e, se este número for primo, retorne 1, caso contrário retorne 0. Faça um programa que imprima na tela os ‘n’ primeiros números primos, onde ‘n’ será fornecido pelo usuário.

7.2 Crie um programa para gerar números aleatórios, utilizando variáveis static para armazenar o valor da semente.

7.3 Crie um programa para calcular o fatorial de um número, para tal implemente uma função recursiva.

Curso de Linguagem Computacional C/C++

7.4 Escreva um programa que solicite ao usuário um ano e imprima o calendário desse ano. Utilize os programas desenvolvidos nos exercícios 4.2 e 4.3. Organize o programa de forma adequada através de funções.

7.5 Escreva uma função recursiva de nome soma() que receba um número inteiro positivo n como argumento e retorne a soma dos n primeiros números inteiros. Por exemplo, se a função recebe n = 5, deve retornar 15, pois:

Curso de Linguagem Computacional C/C++

8 Diretivas do Pré-Processador

O pré-processador C é um programa que examina o código fonte em C e executa certas modificações no código, baseado em instruções chamadas diretivas. O pré-processador faz parte do compilador e pode ser considerado uma linguagem dentro da linguagem C. Ele é executado automaticamente antes da compilação. Diretivas do pré-processador seriam instruções desta linguagem. As instruções desta linguagem são executadas antes do programa ser compilado e têm a tarefa de alterar os códigos-fonte, na sua forma de texto.

Instruções para o pré-processador devem fazer parte do texto que criamos, mas não farão parte do programa que compilamos, pois são retiradas do texto compilador antes da compilação. Diretivas do pré-processador são instruções para o compilador propriamente dito. Mais precisamente, elas operam diretamente no compilador antes do processo de compilação ser iniciado. Linhas normais de programa são instruções para o microprocessador; diretivas do pré-processador são instruções para o compilador.

Todas as diretivas do pré-processador são iniciadas com o símbolo (#). As diretivas podem ser colocadas em qualquer parte do programa, mas é costume serem colocadas no início do programa, antes de main(), ou antes do começo de uma função particular.

8.1 Diretiva #define

A diretiva #define pode ser usada para definir constantes simbólicas com nomes apropriados. Como por exemplo, podemos criar uma constante para conter o valor de pi:

#define PI 3.14159

e depois utilizar o valor desta constante no programa:

area_esfera = (4*raio*raio*PI);

Quando o compilador encontra #define, ele substitui cada ocorrência de PI no programa por 3.14159.

O primeiro termo após a diretiva #define (PI), que será procurada, é chamada “identificador”. O segundo termo (3.14159), que será substituída, é chamada ”texto”. Um ou mais espaços separam o identificador do texto.

Note que só podemos escrever um comando deste por linha. Observe também que não há ponto-e-vírgula após qualquer diretiva do pré-processador.

A diretiva #define pode ser usada não só para definir constantes, como mostra o exemplo seguinte:

#include <stdio.h>

#define ERRO printf("\n Erro.\n")

void main() {

int i;

printf("\nDigite um numero entre 0 a 100: "); scanf("%d", &i);

if(i<0||i>100) ERRO;

Curso de Linguagem Computacional C/C++

8.2 Macros

A diretiva #define tem a habilidade de usar argumentos. Uma diretiva #define com argumentos é chamada de macro e é bastante semelhante a uma função. Eis um exemplo que ilustra como macro é definida e utilizada:

/* Exemplo do uso de Macros*/ #include <stdio.h> #define PRN(n) printf("%.2f\n",n); void main() { float num1 = 27.25; float num2; num2 = 1.0/3.0; PRN(num1); PRN(num2); }

Quando você usar a diretiva #define nunca deve haver espaço em branco no identificador. Por exemplo, a instrução

#define PRN (n) printf(“%.2f\n”,n)

não trabalhará corretamente, porque o espaço entre PR e (n) é interpretado como o fim do identificador.

Para definir um texto ”muito grande” devemos delimitar a linha anterior com uma barra invertida \ e prosseguir com a definição em outra linha.

Toda ocorrência de PRN(n) em seu programa é substituída por

printf(“%.2f\n”,n). O n na definição da macro é substituído pelo nome usado na chamada a macro em seu programa; portanto, PRN(num1)será substituído por

printf(“%.2f\n”,num1). Assim, n age realmente com um argumento.

Macros aumentam a clareza do código, pois permitem a utilização de nomes sugestivos para expressões.

Por segurança, coloque parênteses envolvendo o texto todo de qualquer diretiva #define que use argumentos, bem como envolvendo cada argumento. Por exemplo:

#define SOMA(x,y) x+y ans = 10 * SOMA(3,4);

O complilador substituíra SOMA(3,4) por 3+4, e o computador executará:

ans = 10 * 3+4;

ou seja, um erro. Para evitar isto, você deve definir a macro da seguinte forma:

#define SOMA(x,y) ((x)+(y))

Como macros são simples substituições dentro dos programas, o seu código aparecerá em cada ponto do programa onde forem usadas. Assim, a execução do programa será mais rápida que a chamada a uma função toada vez que se fizer necessário. Em contra partida, o código do programa será aumentado, pois o código da macro será duplicado cada vez que a macro for chamada. Outra vantagem do uso de macros é a não necessidade de especificar o tipo do dado.

8.3 Diretiva #undef

A diretiva #undef remove a mais recente definição criada com #define.

#define GRANDE 3 #define ENORME 8

#define SOMA(x,y) ((x)+(y)) ...

#undef GRANDE /* cancela a definição de GRANDE */ #define ENORME 10 /* redefine ENORME para o valor 10 */ ...

#undef ENORME /* ENORME volta a valer 8 */ ...

#undef ENORME /* cancela a definição de ENORME */ ...

#undef SOMA /* cancela a macro SOMA */

Observe que, para remover uma macro, somente o nome da macro deve constar na diretiva

#undef. Não deve ser incluída a lista de argumento.

8.4 Diretiva #include

A diretiva #include causa a inclusão de um código fonte em outro.

Aqui está o exemplo de sua utilidade: suponha que você escreveu várias fórmulas matemáticas para calcular áreas de diversas figuras.

Os arquivos de inclusão são textos escritos em caracteres ASCII normais, criados geralmente para incorporar definições de constantes, macros, protótipos de funções, definições de tipos de dados complexos e declarações de variáveis externas. Geralmente, os arquivos de inclusão têm nome terminado com o sufixo “.H” (header ou cabeçalho).

Por exemplo, o arquivo conio.h contém o protótipo das funções getch() e getche()

e é por esse motivo incluído nos programas que fazem uso destas funções.

Você pode colocar estas fórmulas em macros em um programa separado. No instante em que você precisar reescrevê-las para a utilização em seu programa use a diretiva #include para inserir este arquivo no seu código fonte. Exemplo:

#define PI 3.14159

#define AREA_CIRCULO(raio) (PI*(raio)*(raio)) #define AREA_RETANG(base,altura) ((base)*(altura)) #define AREA_TRIANG(base,altura) ((base)*(altura)/2)

Grave o programa acima como areas.h. Quando você quiser utilizar estas macros, basta incluir nos seus outros programas uma das diretivas:

#include <areas.h> /* para arquivos localizados na biblioteca do compilador */

#include “areas.h” /* para arquivos locais ou localizados na biblioteca do compilador */ O uso consciente das diretivas #define e #include podem melhorar e muito o desempenho e a organização dos seus projetos de software. Procure explorá-las para conhecer todo os seus potenciais.

Curso de Linguagem Computacional C/C++

8.5 Compilação Condicional

O pré-processador oferece diretivas que permitem a compilação condicional de um programa. Elas facilitam o desenvolvimento do programa e a escrita de códigos com maior portabilidade de uma máquina para outra ou de um ambiente a outro. São elas, as diretivas:

#if, #ifdef, #ifndef, #elif, #else e #endif

Cada diretiva #if deve terminar pela diretiva #endif. Entre #if e #endif pode ser colocado qualquer número de #elif, mas só se permite uma única diretiva #else. A diretiva

#else é opcional e, se estiver presente, deve ser a última anterior a #endif.

Abaixo apresentamos um exemplo onde definimos o valor de uma constante com #define

e depois a utilizamos para fazer uma compilação condicional :

#define DEBUG 1 ... #if DEBUG == 1 printf(“\nERRO = ”, erro1); #elif DEBUG == 2 printf(“\nERRO = ”, erro2); #else

printf(“\nERRO não documentado.”); #endif

Para testar constantes definidas com #define que não tenham valor nenhum, podemos utilizar #ifdef e #ifndef. Por exemplo:

#define VERSAO_DEMO ... #ifdef VERSAO_DEMO #define NUM_REC 20 #include “progdemo.h” else

#define NUM_REC MAXINT #include “program.h”

#endif

O último exemplo mostra como um único programa-fonte pode gerar dois executáveis diferentes: se a diretiva que define VERSAO_DEMO for inserida, o executável poderá manipular somente 20 registros e estará criada a versão demo de seu programa. Caso esta diretiva não esteja presente, o programa poderá manipular o número máximo de registros.

A diretiva #ifndef verifica a não-definição da constante. Por exemplo:

#ifndef WINDOWS

#define VERSAO “\nVersão DOS” #else

#define VERSAO “\nVersão Windows” #endif

8.6 Operador defined

Curso de Linguagem Computacional C/C++

#if defined(UNIX) && !defined(INTEL_486) ...

#endif

8.7 Diretiva #error

A diretiva #error provoca uma mensagem de erro do compilador em tempo de compilação.

#if TAMANHO > TAMANHO1

#error “Tamanho incompatível” #endif

8.8 diretiva #pragma

• #pragma inline - indica ao compilador C a presença de código Assembly no arquivo. • #pragma warn - indica ao compilador C para ignorar "warnings" (avisos)

8.9 Exercícios

8.1 Escreva uma macro que tenha valor 1 se o seu argumento for um número ímpar, e o valor 0 se for par.

8.2 Escreva uma macro que encontre o maior entre seus três argumentos.

8.3 Escreva uma macro que tenha valor 1 se o seu argumento for um caractere entre ‘0’ e ‘9’, e 0 se não for.

8.4 Escreva uma macro que converta um dígito ASCII entre ‘0’ e ‘9’ a um valor numérico entre 0 e 9.

8.5 Escreva um programa que solicite ao usuário uma letra e retorne o número equivalente desta letra na tabela ASCII em decimal e hexadecimal. Utilize a compilação condicional para gerar um programa com interface para diferentes línguas, por exemplo uma para português e outra para inglês. Caso nenhuma das duas for definida, gere um erro de compilação. Dica, coloque o texto de cada língua em um header diferente. Por exemplo, os textos em português ficam definidos em “progport.h” e os textos em inglês em “progingl.h”

8.6 Faça com que o programa do exercício 7.4, escreva o calendário de um ano qualquer dado pelo usuário em três línguas diferentes: alemão, inglês e português. Utilize a mesma idéia que o programa anterior.

Curso de Linguagem Computacional C/C++

9 Matrizes

Uma matriz é um tipo de dado usado para representar uma certa quantidade de variáveis de valores homogêneos.

Imagine que você esteja precisando armazenar e manipular as notas de um ano inteiro de um conjunto de 40 alunos. Você certamente precisará de uma maneira conveniente para referenciar tais coleções de dados similares. Matriz é o tipo de dado oferecido por C para este propósito.

Um matriz é uma série de variáveis do mesmo tipo referenciadas por um único nome, onde cada variável é diferenciada através de um número chamado “subscrito” ou “índice”. Colchetes são usados para conter o subscrito. A declaração:

int notas[5];

aloca memória para armazenar 5 inteiros e anuncia que notas é uma matriz de 5 membros ou “elementos”.

Vamos agora fazer um programa que calcula a média das notas da prova do mês de Junho de 5 alunos.

/* Exemplo de matrizes */ /* media das notas de 5 alunos */

#include <stdio.h>

#define NUM_ALUNOS 5

void main() {

int notas[NUM_ALUNOS]; /* Declaracao de matrizes */ int i, soma;

for(i=0; i<NUM_ALUNOS; i++) {

printf("Digite a nota do aluno %d: ", i);

scanf("%d", &notas[i]); /* atribuindo valores a matriz */ }

soma = 0;

for(i=0; i<NUM_ALUNOS; i++)

soma = soma + notas[i]; /* lendo os dados da matriz */ printf("Media das notas: %d.", soma/NUM_ALUNOS);

}

9.1 Sintaxe de Matrizes

As dimensões são definidas entre colchetes, após a definição convencional do tipo de variável.

<Tipo> <nome> [<dimensão1>] [<dimensão2>] ... ;

Em C, matrizes precisam ser declaradas, como quaisquer outras variáveis, para que o compilador conheça o tipo de matriz e reserve espaço de memória suficiente para armazená-la. Os elementos da matriz são guardados numa seqüência contínua de memória, isto é, um seguido do outro.

O que diferencia a declaração de uma matriz da declaração de qualquer outra variável é a parte que segue o nome, isto é, os pares de colchetes [ e ] que envolvem um número inteiro, que

Curso de Linguagem Computacional C/C++ indica ao compilador o tamanho da matriz. A dimensão da matriz vai depender de quantos pares de colchetes a declaração da matriz tiver. Por exemplo:

int notas[5]; /* declaração de uma matriz unidimensional = vetor */ unsigned float tabela[3][2]; /* matriz bidimensional */

char cubo[3][4][6]; /* matriz tridimensional */

Analisando-se a primeira declaração: a palavra int declara que todo elemento da matriz é do tipo int, notas é o nome dado a matriz e [5] indica que a nossa matriz terá 5 elementos do tipo “int”. Por definição uma matriz é composta por elementos de um único tipo.

O acesso aos elementos da matriz é feito através do número entre colchetes seguindo o nome da matriz. Observe que este número tem um significado diferente quando referencia um elemento da matriz e na declaração da matriz, onde indica o seu tamanho.

Quando referenciamos um elemento da matriz este número especifica a posição do elemento na matriz. Os elementos da matriz são sempre numerados por índices iniciados por 0 (zero). O elemento referenciado pelo número 2

notas[2]

não é o segundo elemento da matriz mas sim o terceiro, pois a numeração começa em 0. Assim o último elemento da matriz possui um índice, uma unidade menor que o tamanho da matriz.

O acesso com notas[i] pode ser tanto usado para ler ou escrever um dado na matriz. Você pode tratar este elemento como um variável simples, no caso de notas[i], como uma variável inteira qualquer.

Como proceder caso você não conheça a quantidade de termos que você precisa para a tua matriz? Aplique a idéia apresentada no programa exemplo acima, com a diretiva:

#define NUM_ALUNOS 5

para alocar um número maior de termos, de forma a possuir espaço suficiente alocado para conter todos os possíveis termos da matriz.

Atenção: A linguagem C não realiza verificação de limites em matrizes; por isto nada

impede que você vá além do fim da matriz. Se você transpuser o fim da matriz durante uma operação de atribuição, então atribuirá valores a outros dados ou até mesmo a uma parte do código do programa. Isto acarretará resultados imprevisíveis e nenhuma mensagem de erro do compilador avisará o que está ocorrendo.

Como programador você tem a responsabilidade de providenciar a verificação dos limites, sempre que necessário. Assim a solução é não permitir que o usuário digite dados, para elementos da matriz, acima do limite.

9.2 Inicializando Matrizes

Em C a inicialização de uma matriz é feita em tempo de compilação. Matrizes das classes

extern e static podem ser inicializadas. Matrizes da classe auto não podem ser inicializadas. Lembre-se de que a inicialização de uma variável é feita na instrução de sua declaração e é uma maneira de especificarmos valores iniciais pré-fixados.

O programa a seguir exemplifica a inicialização de uma matriz:

/* exemplo de inicialização de matrizes */ /* programa que produz troco */

#include <stdio.h> #define LIM 5

Curso de Linguagem Computacional C/C++

{

int d, valor, quant;

static int tab[] = {50, 25, 10, 5, 1}; printf("Digite o valor em centavos: "); scanf("%d", &valor);

for(d=0; d<LIM; d++) {

quant = valor/tab[d];

printf("Moedas de %d centavos = %2d\n", tab[d], quant); valor %= tab[d];

} }

A instrução que inicializa a matriz é:

static int tab[] = {50, 25, 10, 5, 1};

A lista de valores é colocada entre chaves e os valores são separados por vírgulas. Os valores são atribuídos na seqüência, isto é, tab[0] = 50, tab[1] é 25, tab[2] é 10 e assim por diante. Note que não foi necessária a declaração da dimensão da matriz. Caso tivéssemos escrito explicitamente a dimensão da matriz, esta deveria se maior ou igual a dimensão fornecida pelo colchetes. Se há menos inicializadores que a dimensão especificada, os outros serão zero. É um erro ter-se mais inicializadores que o necessário.

Se em seu programa você deseja inicializar uma matriz, você deve criar uma variável que existirá durante toda a execução do programa. As classes de variáveis com esta característica são

extern e static.

A linguagem C permite matrizes de qualquer tipo, incluindo matrizes de matrizes. Por exemplo, uma matriz de duas dimensões é uma matriz em que seus elementos são matrizes de uma dimensão. Na verdade, em C, o termo duas dimensões não faz sentido pois todas as matrizes são de uma dimensão. Usamos o termo mais de uma dimensão para referência a matrizes em que os elementos são matrizes.

As matrizes de duas dimensões são inicializadas da mesma maneira que as de dimensão única, isto é, os elementos (matrizes) são colocados entre as chaves depois do sinal de igual e separados por vírgulas. Cada elemento é composto por chaves e seus elementos internos separados por vírgulas. Como exemplo segue abaixo uma matriz bidimensional:

char tabela[3][5] = { {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {1, 1, 0, 0, 1} };

Cada elemento da matriz tabela na verdade será outra matriz, então por exemplo:

tabela[2] == {1, 1, 0, 0, 1}

Da mesma maneira se aplica para matrizes de três ou mais dimensões:

int tresd[3][2][4] =

{ { {1, 2, 3, 4} , {5, 6, 7, 8} }, { {7, 9, 3, 2} , {4, 6, 8, 3} },

Curso de Linguagem Computacional C/C++ A matriz de fora tem três elementos, cada um destes elementos é uma matriz de duas dimensões de dois elementos onde cada um dos elementos é uma matriz de uma dimensão de quatro números.

Como podemos acessar o único elemento igual a 0 na matriz do exemplo anterior? O primeiro índice é [2], pois é o terceiro grupo de duas dimensões. O segundo índice é [1], pois é o segundo de duas matrizes de uma dimensão. O terceiro índice é [0], pois é o primeiro elemento da matriz de uma dimensão. Então, temo que a primitiva abaixo é verdade:

Tresd[2][1][0] == 0

9.3 Matrizes como Argumentos de Funções

No documento Apostila3LinguagemCeC++ (páginas 44-54)

Documentos relacionados