You are on page 1of 85

Universidade Federal De Uberlndia

Faculdade de Engenharia Eltrica e Biomdica


1












Apostila Linguagem C




















Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
2
Sumrio
INTRODUO ........................................................................................................................................ 3
EXPRESSES ........................................................................................................................................... 4
TIPOS BSICOS DE DADOS .............................................................................................................................. 4
NOMES DE IDENTIFICADORES .......................................................................................................................... 5
VARIVEIS ................................................................................................................................................... 5
OPERADORES ............................................................................................................................................... 9
ABREVIAES EM C ..................................................................................................................................... 12
COMANDOS DE CONTROLE .................................................................................................................. 13
COMANDOS DE SELEO .............................................................................................................................. 13
COMANDOS DE ITERAO ............................................................................................................................ 18
COMANDOS DE DESVIOS .............................................................................................................................. 22
MATRIZES E STRINGS ........................................................................................................................... 26
MATRIZES UNIDIMENSIONAIS........................................................................................................................ 26
PASSANDO VETORES PARA FUNES ............................................................................................................... 27
STRINGS .................................................................................................................................................... 28
MATRIZES BIDIMENSIONAIS .......................................................................................................................... 30
MATRIZES DE STRINGS ................................................................................................................................. 31
INICIALIZAO DE MATRIZES ......................................................................................................................... 32
PONTEIROS .......................................................................................................................................... 33
VARIVEIS PONTEIROS ................................................................................................................................. 33
OPERADORES DE PONTEIROS......................................................................................................................... 33
ATRIBUIO DE PONTEIROS .......................................................................................................................... 34
INCREMENTANDO E DECREMENTANDO PONTEIROS ........................................................................................... 35
COMPARAO DE PONTEIROS ....................................................................................................................... 36
PONTEIROS E VETORES ................................................................................................................................ 36
PONTEIROS E STRINGS ................................................................................................................................. 37
ALOCAO DINMICA DE MEMRIA .............................................................................................................. 38
PONTEIROS E MATRIZES ............................................................................................................................... 40
VETORES DE PONTEIROS .............................................................................................................................. 41
PONTEIROS PARA PONTEIROS ........................................................................................................................ 42
FUNES ............................................................................................................................................. 44
FUNES RECURSIVAS ................................................................................................................................. 45
FUNES QUE RETORNAM PONTEIROS ............................................................................................................ 46
ESTRUTURAS ........................................................................................................................................ 47
REFERECIANDO ELEMENTOS DE ESTRUTURAS ................................................................................................... 48
MATRIZES DE ESTRUTURAS ........................................................................................................................... 49
PASSANDO ESTRUTURAS PARA FUNES .......................................................................................................... 49
PONTEIROS PARA ESTRUTURAS ...................................................................................................................... 51
ESTRUTURAS ANINHADAS ............................................................................................................................. 52
ENTRADA/SADA PELO CONSOLE ......................................................................................................... 53
FUNO: PRINTF() ...................................................................................................................................... 54
FUNO: SCANF() ....................................................................................................................................... 56
ENTRADA/SADA COM ARQUIVO ......................................................................................................... 58
STREAMS E ARQUIVOS ................................................................................................................................. 58
SISTEMA DE ARQUIVOS ................................................................................................................................ 59
FUNES PARA ARQUIVOS ........................................................................................................................... 61
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
3

Captulo 1 Introduo

A linguagem C foi inventada na dcada de 70. Ela considerada uma linguagem
de mdio nvel por combinar elementos de linguagens de alto nvel com a simplicidade
e funcionalidade de linguagens de baixo nvel.
Os cdigos feitos pela linguagem C so bastante portveis porque podem se
adaptar a um software escrito de um tipo de computador a outro.
Em geral, o C considerado uma linguagem estruturada, o que permite a
compartimentalizao do cdigo e dos dados. Sua principal componente estrutural a
funo. Funes so blocos de construo em que toda a atividade do programa ocorre,
e elas admitem que voc defina e codifique separadamente as diferentes tarefas de um
programa, permitindo, ento, que seu programa seja modular. Aps uma funo ter sido
criada, voc pode contar com que ela trabalhe adequadamente em vrias situaes, sem
criar efeitos inesperados em outras partes do programa. O fato de voc poder criar
funes isoladas extremamente importante em projetos maiores onde um cdigo de
um programador no deve afetar acidentalmente o de outro.
Outra maneira de estruturar e compartimentalizar o cdigo em C atravs do
uso de blocos de cdigo. Um bloco de cdigo um grupo de comandos de programa
conectado logicamente que tratado como uma unidade. Em C, um bloco de cdigo
criado colocando-se uma seqncia de comandos entre chaves. Nesse exemplo







os dois comandos aps o if e entre chaves so executados se x for igual a 4. Esses dois
comandos, junto com as chaves, representam um bloco de cdigo, o que permite que
muitos algoritmos sejam implementados com clareza, elegncia e eficincia.
Todo compilador C vem com uma biblioteca (que um arquivo contendo as
funes padro que seu programa pode usar) C padro de funes que realizam as
tarefas necessrias mais comuns.
















if (x == 4) {
printf(Parabens, voce acertou, x 4);
_getch();
}

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
4
Captulo 2 - Expresses

Tipos Bsicos de Dados

Todas as linguagens de programao de alto nvel suportam o conceito de tipos
de dados, onde um tipo de dado define um conjunto de valores que uma varivel pode
armazenar e o conjunto de operaes que pode ser executado com essa varivel. No C,
existem 5 tipos bsicos de dados, que so: caractere (char), inteiro (int), ponto flutuante
(float), ponto flutuante de preciso dupla (double) e sem valor (void).

O tipo char utilizado para especificar valores definidos pelo conjunto de
caracteres ASCII, este conjunto contm letras, smbolos e at mesmo algarismos, porm
os algarismos no podero ser manipulados matematicamente.

O tipo int utilizado para especificar algarismos inteiros, sendo que estes sim
podero ser manipulados matematicamente.

Os tipos float e double so utilizados para especificar algarismos contnuos
(fracionrios), sendo que o double aborda uma faixa de nmeros maior do que o float e
com maior preciso. O padro ANSI especifica que a faixa mnima de um valor em
ponto flutuante de 1e-37 a 1e+37.

O tipo void declara explicitamente uma funo que no retorna valor algum ou
cria ponteiros genricos, ou seja, utiliza-se void sempre em que no h necessidade de
retornar algum valor.

Tipo Tamanho Intervalo
unsigned char 8 bits 0 at 255
char 8 bits -128 at 127
short int 16 bits -32,768 at 32,767
unsigned int 32 bits 0 at 4,294,967,295
int 32 bits -2,147,483,648 at 2,147,483,647
unsigned long 32 bits 0 at 4,294,967,295
enum 16 bits -2,147,483,648 at 2,147,483,647
long 32 bits -2,147,483,648 at 2,147,483,647
float 32 bits 3.4 x 10-38 at 3.4 x 10+38
double 64 bits 1.7 x 10-308 at 1.7 x 10+308
long double 80 bits 3.4 x 10-4932 at 1.1 x 10+4932

Obs.: O tipo float possui 6 dgitos de preciso, enquanto que os tipos double e long
double possuem 10 dgitos de preciso.







Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
5
Nomes de Identificadores

So considerados identificadores: os nomes de variveis, funes, rtulos e
vrios outros objetos definidos pelo usurio. Esses identificadores podem variar de um a
diversos caracteres. O primeiro caractere deve ser uma letra ou um sublinhado e os
caracteres subseqentes devem ser letras, nmeros ou sublinhados. Abaixo se
encontram alguns exemplos:

Correto Incorreto
valor 1valor
Teste1 Ola&todos
calculo_fatorial calculo...fatorial

A linguagem C diferencia as letras maisculas e minsculas, portanto: valor,
Valor e VALOR so trs identificadores distintos.
Um identificador no pode ser igual a uma palavra-chave de C e no deve ter o
mesmo nome que as funes que voc escrever ou as que esto na biblioteca C.

Variveis

Uma varivel uma posio de memria com um nome, que usada para
guardar um valor que pode ser modificado pelo programa. Todas as variveis em C
devem ser declaradas antes de serem usadas. A forma geral de uma declarao :

tipo nome_da_varivel;

Onde, tipo deve ser um ser um tipo vlido em C, como aqueles vistos
anteriormente; e nome_da_varivel deve obedecer s regras vistas na seo nome
de identificadores, podendo consistir em um ou mais nomes de identificadores
separados por vrgulas. Abaixo esto alguns exemplos:

int i, j, l;
char letra;
double valor;
float peso, altura;

Todas as variveis so constitudas de dois valores, o primeiro a posio de
memria, este um valor hexadecimal. O segundo o valor contido nele, este pode ser
manipulado. Exemplo:


#include <conio.h>
#include <stdio.h>

void main()
{
int y = 25; /*y assume o valor 25*/

/* imprime o valor da posio de memoria em hexadecimal */
printf("A posicao de memoria (hexadecimal) e: %X", &y);

/* imprime o valor da posio de memoria em decimal */
printf("\n\nA posicao de memoria (decimal) e: %d", &y);

/* imprime o valor de definido pelo programador */
printf("\n\nO valor contido em x e: %d", y);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
6


As variveis sero declaradas em trs lugares bsicos: dentro de funes
(chamadas de variveis locais), na definio de parmetros das funes (chamadas de
parmetros formais) e fora de todas as funes (chamadas de variveis globais).

Variveis locais so aquelas declaradas dentro de um determinado bloco,
portanto elas no so reconhecidas fora de seu prprio bloco de cdigo. Lembrando que
um bloco de cdigo comea com um abre-chave e termina com uma fecha-chave.
Estas variveis existem apenas dentro deste bloco onde foram declaradas,
portanto ela criada na entrada do seu bloco e destruda na sada.

Exemplo:




A varivel x foi declarada duas vezes, uma vez em funcao1( ) e outra em
funcao2( ). O x na primeira funo no tem nenhuma relao com a segunda, isso
ocorre porque ela uma varivel local, e funciona somente dentro do bloco em que foi
declarada. Quando sai da primeira funo esta varivel destruda, acontecendo o
mesmo na sada da segunda.

A maioria dos programadores declara todas as variveis usadas por uma funo
imediatamente aps o abre-chaves da funo e antes de qualquer outro comando.
Porm, as variveis locais podem ser declaradas dentro de qualquer bloco de cdigo.
Exemplo:







void funcao1()
{
int x;
x = 15;
}

void funcao2()
{
int x;
x = -33;
}
void funcao()
{
int x;
scanf(%d, &x);

if( x = = 1) /*no h espao entre os sinais de igual*/
{
int y = 5; /*esta varivel s criada na entrada
deste bloco*/
printf(O resultado : %d, (x+y));
}
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
7
Nesta funo, a varivel y criada na entrada do bloco de cdigo if e destruda
na sada. Alm disso, y reconhecida apenas dentro do bloco if e no pode ser
diferenciada em qualquer outro lugar.

Parmetros formais: Se uma funo usa argumentos, ela deve declarar
variveis que recebero os valores dos argumentos, estas variveis so chamadas de
parmetros formais. Elas se comportam como qualquer outra varivel local dentro da
funo. Exemplo:








Nos prximos captulos ser ensinado como realizar chamada de funes,
passando variveis como parmetros. Neste exemplo, prestemos ateno na funo
soma(), ela tem como parmetros de entrada as variveis a e b (ambos inteiros), estas
variveis funcionam apenas neste bloco, sendo destrudas aps a sada da funo, se
comportando assim como variveis locais.
Importante: Voc deve ter certeza de que os parmetros formais que esto declarados
so do mesmo tipo dos argumentos que voc utiliza para chamar a funo. Se h uma
discordncia de tipos, resultados inesperados podem ocorrer.

Variveis globais so, ao contrrio das variveis locais, reconhecidas pelo
programa inteiro e podem ser usadas por qualquer pedao do cdigo. Elas guardam seus
valores durante toda a execuo do programa. Elas so criadas declarando-as fora de
qualquer funo e podem ser acessadas por qualquer expresso independente de qual
bloco de cdigo contm a expresso.

Vide no programa seguinte, valor foi declarada fora de todas as funes,
portanto uma varivel global. Exemplo:

/* declarao da funo soma, declarando tambm a e b como
parmetros formais da funo*/
int soma(int a, int b)
return (a+b);

void main()
{
int x = 1, y = 5, z;
z = soma(x,y); /* aqui ocorre uma chamada de funo, passando x e
y como argumentos*/
printf(%d, z); /* imprime 6 na tela */
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
8










A imagem abaixo o resultado do programa apresentado acima:



Observe este programa. As funes main( ) e funcao1( ) usaram a varivel
valor mesmo sem t-la declarado. J a funcao2( ) declarou uma varivel local chamada
valor, ou seja, com o mesmo nome com da varivel global. Quando isso acontece, todas
as referncias ao nome da varivel dentro do bloco onde a varivel local foi declarada
dizem respeito somente a ela mesma e no tem qualquer efeito sobre a varivel global.
Notamos isso no programa acima, quando a funcao1( ) faz a chamada da
funcao2( ) valor recebe a atribuio 40, que imprimido na tela, mas como uma
varivel local, essa destruda assim que sai do bloco, voltando assim para a
funcao1( ), bloco onde valor igual a 50.

Variveis globais so teis quando o mesmo dado usado em muitas funes em
seu programa. No entanto, voc deve evitar usar variveis globais desnecessrias. Elas
ocupam memria durante todo o tempo em que seu programa est executando, no
apenas quando so necessrias.





int valor;
void funcao1();
void funcao2();

void main()
{
valor = 100;
printf(%d : na funcao main, valor);
funcao1();
getch();
}

void funcao1()
{
valor = 50;
printf(\n%d : na funcao 1 depois de valor = 50, valor);
funcao2();
printf(\n%d: na funcao 1 depois de ter passado pela funcao
2, valor);
}

void funcao2()
{
int valor;
valor = 40;
printf(\n%d : na funcao 2 depois de declara valor = 40 como
variavel local, valor);
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
9
Operadores

A linguagem C possui quatro classes de operadores: aritmticos, relacionais,
lgicos e bit a bit. Alm de ter alguns operadores especiais para tarefas particulares.

Operador de Atribuio

Voc pode usar o operador de atribuio dentro de qualquer expresso vlida de
C. A forma geral do operador de atribuio :

Nome_da_varivel = expresso;

Onde expresso pode ser uma simples constante ou uma expresso to complexa
quanto voc necessite.
Voc ver dois termos: lvalue e rvalue, onde lvalue se refere ao termo do lado
esquerdo do igual, e rvalue do lado direito. O lvalue o destino da atribuio, ele
sempre deve ser uma varivel ou um ponteiro, enquanto que o rvalue deve ser uma
constante ou funo. Exemplos:

X = 40; // atribuio de uma constante inteira.
Y = 3.1234; // atribuio de uma constante tipo float.
Z = x + 2y; // atribuio de uma funo.


Converso de Tipos em Atribuies

Converso de tipos refere-se situao em que variveis de um tipo so
misturadas com variveis de outro tipo. Em um comando de atribuio, o valor do lado
direito (rvalue) de uma atribuio convertido no tipo do lado esquerdo (lvalue), como
segue no exemplo abaixo:



















#include <conio.h>
#include <stdio.h>

void main()
{
int x = 2;
char ch;
float f = 30.6954;

ch = x; /* linha 1 */
printf("ch = %c", ch);

x = f; /* linha 2 */
printf("\nx = %d", x);

f = ch; /* linha 3 */
printf("\nf = %f", f);

f = x; /* linha 4 */
printf("\nf = %f", f);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
10
Se executarmos o programa, teremos os seguintes resultados:



Na linha 1, x est entre 0 e 156, portando ch e x possuem valores idnticos, que
nesse caso 2. De outra forma, o valor de ch reflete apenas os bits menos significativos
de x. Na linha 2, x recebe a parte inteira de f. Na linha 3, f converte o valor inteiro de 8
bits armazenado em ch no mesmo valor em formato de ponto flutuante. Isso tambm
ocorre na linha 4, exceto por f converter um valor inteiro de 16 bits no formato de ponto
flutuante.

Operadores Aritmticos

A tabela abaixo lista os operadores aritmticos de C, e suas aes.

Operadores Aes
- Subtrao, tambm menos unrio
+ Adio
* Multiplicao
/ Diviso
% Mdulo da diviso (resto)
-- (dois -) Decremento
++ (dois +) Incremento

O menos unrio multiplica seu nico operando por -1. Isto , qualquer nmero
precedido por um sinal de menos troca de sinal.


Incremento e Decremento

C inclui dois operadores teis geralmente no encontrados em outras linguagens.
So os operadores de incremento e decremento, ++ e --. O operador ++ soma 1 ao seu
operando, e -- subtrai 1. Em outras palavras:





Ambos os operadores de incremento e decremento podem ser utilizados como prefixo
ou sufixo do operando.

Prefixo Sufixo
++x; x++;

Expresso o mesmo que Ou ainda
x = x + 1; ++x; x++;
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
11
Porm, h uma diferena quando esses operadores so usados em uma
expresso. Quando um operador de incremento ou decremento precede seu operando, C
executa a operao de incremento ou decremento antes de usar o valor do operando. Se
o operador estiver aps seu operando, C usa o valor do operando antes de increment-lo
ou decrement-lo. Considere o seguinte:

X = 10;
Y = ++x;

Coloca 11 em y. Porm se o cdigo fosse escrito como

X = 10;
Y = x++;

y receberia 10. Em ambos os casos, x recebe 11, a diferena est em quando isso
acontece.

Operadores Relacionais e Lgicos

No termo operador relacional, relacional refere-se s relaes que os valores
podem ter uns com os outros. No termo operador lgico, lgico refere-se s maneiras
que essas relaes podem ser conectadas. Estes freqentemente trabalham juntos.

Operadores Relacionais
Operador Ao
> Maior que
>= Maior ou igual que
< Menor que
<= Menor ou igual que
= = Igual
!= Diferente

Operadores Lgicos
Operador Ao
&& AND
|| OR
! NOT

A idia de verdadeiro e falso est por trs dos conceitos dos operadores lgicos
e relacionais. Em C, falso zero, enquanto que verdadeiro qualquer valor diferente
de zero. Abaixo temos a tabela verdade dos operadores lgicos, usando 1s e 0s.

x y x&&y x||y !x
0 0 0 0 1
0 1 0 1 1
1 0 1 1 0
1 1 0 1 0
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
12
Ambos os operadores so menores em precedncia do que os operadores
aritmticos. Isto , uma expresso como 12 > 1 + 12 avaliada como se fosse escrita
12 > (1 + 12). O resultado , obviamente, falso.
permitido combinar diversas operaes em uma expresso como mostrado
aqui:
10 > 5 && !(10 < 9) || 3 <= 4
Neste caso, o resultado verdadeiro.

Casts

possvel forar uma expresso a ser de um tipo usando uma construo
chamada cast. A forma geral de um cast

(tipo) expresso

onde tipo um tipo de dado padro de C. Por exemplo, para ter certeza de que a
expresso x/2 ser do tipo float, escreva

(float) x / 2;

Exemplo:



Abreviaes em C

C oferece uma abreviao especial que simplifica a codificao de certos tipos
de comandos de atribuio. A forma geral de uma abreviao C

variavel = variavel operador expresso;

o mesmo que

variavel operador = expresso;

Exemplos:

Expresso o mesmo que
x = x + 8; x += 8;
y = y / 6; y /= 6;
z = z * y; z *= y;

#include <conio.h>
#include <stdio.h>

void main()
{
int x = 10;
printf("\nX/3 e igual a: %f", (float) x/3);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
13
Captulo 3 Comandos de Controle

No C existe vrios comando de controle do programa. O padro ANSI divide os
comandos nestes grupos:

Seleo
Iterao
Desvio
Rtulo
Expresso
Bloco

Comandos de Seleo

if ... else

A forma geral da sentena if

if ( expresso) comando;
else comando;

onde comando pode ser um nico comando, um bloco de comandos ou nada. Enquanto
que else opcional, seu uso no obrigatrio.

Se a expresso verdadeira (algo diferente de 0), o comando ou bloco que forma
o corpo do if executado; caso contrrio, o comando ou bloco que o corpo do else (se
existir) executado. Lembre-se de que apenas o cdigo associado ao if ou cdigo
associado ao else ser executado, nunca ambos.
Abaixo vemos o fluxograma correspondente a esta estrutura de deciso.











Condio?
Bloco1 Bloco2
V F
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
14
O comando condicional controlando o if deve produzir um resultado escalar. Um
escalar um inteiro (int), um caractere (char) ou tipo de ponto flutuante (float). No
entanto, raro usar um nmero de ponto flutuante para controlar um comando
condicional, porque isso diminui consideravelmente a velocidade de execuo. (A CPU
executa diversas instrues para efetuar uma operao em ponto flutuante. Ela usa
relativamente poucas instrues para efetuar uma operao com caractere ou inteiro).

Veja um exemplo do uso do if:







ifs Aninhados

Um if aninhado um comando if que o objeto de outro if ou else. ifs
aninhados so muito comuns em programao. Em C, um comando else sempre se
refere ao comando if mais prximo, que est dentro do mesmo bloco do else e no est
associado a outro if. Por exemplo




Como observado, o ltimo else no est associado a if(j) porque no pertence ao
mesmo bloco. Em vez disso, ltimo else est associado ao if(i). O else interno est
associado ao if(k), que o if mais prximo.
O padro ANSI especifica que pelo menos 15 nveis de aninhamento devem ser
suportados. Na prtica, a maioria dos compiladores permite substancialmente mais.




if(i){
if(j) comando 1;
if(k) comando 2; //este if...
else comando 3; //..est associado a este else
}
else comando 4; // associado a if(i)
#include <conio.h>
#include <stdio.h>

void main()
{
int valor;
printf("Entre com um valor inteiro: ");
scanf("%d", &valor);

if(valor > 0)
printf("\nO valor que voce digitou e positivo");
else
printf("\nO valor que voce digitou e negativo");

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
15
if else if

Uma construo comum em programao a forma ifelseif, algumas vezes
chamada de escada if-else-if devido a sua aparncia. A sua forma geral

if (expresso1) comando 1;
else if (expresso2) comando 2;
else if (expresso3) comando 3;
.
.
.
else comando N;

As condies so avaliadas de cima para baixo. Assim que uma condio
verdadeira encontrada, o comando associado a ela executado e o resto da escada
contornado. Se nenhuma das condies for verdadeira, ento o ltimo else executado.
Isto , se todos os outros testes condicionais falham, o ltimo comando else efetuado.
Se o ltimo else no est presente, nenhuma ao ocorre se todas as condies so
falsas.

?

C contm um operador muito poderoso e conveniente que substitui certas
sentenas da forma if-else. O ? um operador ternrio (que requer trs operandos) que
tem a forma geral

Exp1 ? Exp2 : Exp3;

Onde Exp1, Exp2 e Exp3 so expresses. Note o uso e o posicionamento dos
dois pontos.
O operador ? funciona desta forma: Exp1 avaliada. Se ela for verdadeira,
ento Exp2 avaliada e se torna o valor da expresso. Se Exp1 falso, ento Exp3
avaliada e se torna o valor da expresso. Por exemplo,

X = 10;
Y = X > 9 ? 100 : 200;

a Y atribudo um valor 100. Se X fosse menor que 9, Y teria recebido o valor 200. O
mesmo cdigo, usando o comando if-else

X = 10;
if ( X > 9) Y = 100;
else Y = 200;

Exemplo:

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
16







Este programa anlogo ao da seo if-else, incorporando agora os conceitos do
operador ?. Observe os dois e faa as comparaes.

Switch

C tem um comando interno de seleo mltipla, switch, que testa
sucessivamente o valor de uma expresso contra uma lista de constantes inteiras ou de
caractere. Quando o valor coincide, os comandos associados quela constante so
executados. A forma geral do comando switch

switch (expresso) {
case constante1:
comandos
break;
case constante2:
comandos
break;
.
.
.
default:
seqncia de comandos
}

Abaixo vemos o fluxograma correspondente a esta estrutura de deciso.

#include <conio.h>
#include <stdio.h>

void main()
{
int valor;
printf("Entre com um valor inteiro: ");
scanf("%d", &valor);

valor > 0 ?
printf("\nO valor que voce digitou e positivo")
: printf("\nO valor que voce digitou e negativo");

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
17














O valor da expresso testado, na ordem, contra os valores das constantes
especificadas nos comandos case. Quando uma coincidncia for encontrada, a seqncia
de comandos associada quele case ser executada at que o comando break ou o fim
do comando swtich seja alcanado. O comando default executado se nenhuma
coincidncia for detectada. O default opcional e, se no estiver presente, nenhuma
ao ser realizada se todos os testes falharem.

O comando switch freqentemente utilizado na construo de menus, veja o
exemplo abaixo:















Expresso
Conjunto 1
Conjunto 2
...
Conjunto N
Conjunto D
Rtulo 1
Rtulo 2
Rtulo N
Rtulo D
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
18
























Comandos de Iterao

Os comandos de iterao, conhecidos tambm como laos, permitem que
um conjunto de instrues seja executado at que ocorra uma certa condio. Essa
condio pode ser predefinida (como ocorre no lao for) ou com o final em aberto
(como ocorre nos laos while e do-while).

Lao for

O lao for uma estrutura de repetio, chamada de estrutura de repetio com
contador. Ele executa um bloco de instrues em uma quantidade de vezes predefinida.
A forma geral do comando for

for(inicializao; condio; incremento) {
bloco
}

onde inicializao uma expresso de inicializao do contador, geralmente um
comando de atribuio que usado para colocar um valor inicial na varivel de controle
do lao. A condio uma expresso relacional que determina quando o lao termina. O
incremento define como a varivel de controle do lao varia cada vez que o lao
repetido. Estas trs sees devem ser separadas por ponto-e-vrgula (;). O bloco
executado enquanto a condio for verdadeira, ou seja, uma vez que a condio se torne
falsa, o lao encerrado.

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

void funcao1(); // funo para converso de temperatura
void funcao2(); // funo para calculo de fatorial

void main()
{
int opcao;
printf("1: Conversao de Temperatura");
printf("\n2: Calcular Fatorial");
printf("\nEscolha uma opcao e tecle ENTER: ");
scanf("%d",&opcao); // entrada de variavel

switch(opcao) // analisa a opcao do usuario
{
case 1: // caso seja 1...
funcao1(); // ... executa funo 1
break;

case 2: // caso seja 2...
funcao2(); // ... executa funo 2
break;

default: // caso no seja nenhuma...
exit(0); // ...o programa encerrado
break;
}
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
19
Por exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 100:










Podem existir mais de uma expresso de inicializao e de incremento na
estrutura for. Estas expresses devem ser separadas por vrgulas (,). Mas no pode
haver mais de uma expresso de condio. Por exemplo:

for(i = 0, j = 10; i < 10; i++, j--) { ... }

Lao while

Outra estrutura de repetio disponvel no C o lao while. Sua forma geral :

While(condio){
bloco
}

A condio pode ser qualquer expresso. Este lao se repete quando a condio
for verdadeira, ou seja, qualquer valor diferente de zero. Quando a condio for falsa, o
programa pula este lao e o bloco no executado.

O fluxograma desta estrutura mostrado abaixo:








Exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 100:


Condio?
bloco
V
F
#include <conio.h>
#include <stdio.h>

void main()
{
for(int i = 1; i<=100; i++)
printf("%d ",i);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
20











Lao do-while

Ao contrrio dos laos for e while, que testam a condio do lao no comeo, o
lao do-while sempre ser executado ao menos uma vez. Sua forma geral :

do{
bloco
}while(condio);

A condio qualquer expresso relacional e/ou lgica. O bloco ser executado
uma vez, se a condio for falsa, ou seja, igual a zero, o programa encerra o lao.
Porm, se a condio for verdadeira, ou seja, qualquer nmero diferente de zero, o bloco
executado novamente.

O fluxograma desta estrutura mostrado abaixo:















bloco
Condio?
V
F
#include <conio.h>
#include <stdio.h>

void main()
{
int i = 1;
while(i<=100)
{
printf("%d ", i);
i++;
}

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
21
Exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 100:













O comando do-while uma boa escolha na construo de menus, porque sempre
se deseja que as opes do menu execute ao menos uma vez. Depois que as opes
forem mostradas, o programa ser executado at que uma opo vlida seja selecionada.

Abaixo se encontra o exemplo utilizado na seo do switch, agora utilizando os
conceitos de do-while:


















#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

void funcao1(); //funo para converso de temperatura
void funcao2(); //funo para calculo de fatorial

void main()
{
int opcao;
do{

printf("1: Conversao de Temperatura");
printf("\n2: Calcular Fatorial");
printf("\n3: sair");
printf("\nEscolha uma opcao e tecle ENTER: ");
scanf("%d",&opcao); // entrada de variavel

}while(opcao!=1 && opcao!=2);
/*este bloco ser executado sempre que opcao for
diferente de 1 e de 2*/

switch(opcao) // analisa a opcao do usuario
{
case 1: // caso seja 1...
funcao1(); // ... executa funo 1
break;

case 2: // caso seja 2...
funcao2(); // ... executa funo 2
break;

case 3: // caso seja 3...
exit(0); // ...o programa encerrado
break;
}
}

#include <conio.h>
#include <stdio.h>

void main()
{
int i = 1;
do{
printf("%d ", i);
i++;
}while(i<=100);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
22
Comandos de Desvios

A linguagem C possui quatro comandos que realizam um desvio incondicional:
return, goto, break e continue.

Comando return

O comando return utilizado para retornar de uma funo. Ele um comando
de desvio, pois faz com que a execuo retorne ao ponto em que a funo foi chamada.
A sua forma geral

return expresso;

A expresso opcional, se houver alguma expresso contendo algum valor
associado ao return, este retornado da funo para onde ela foi chamada. Se nenhum
valor de retorno for especificado, assume-se que apenas lixo retornado.
Voc pode usar quantos comandos return quiser dentro de uma funo.
Entretanto, a funo deixar de executar to logo ela encontre o primeiro return.
Uma funo do tipo void no pode ter um comando return.


Comando goto

No C, devido ao seu rico conjunto de estruturas de controle, h pouca
necessidade da utilizao do goto. A grande preocupao da maioria dos programadores
sobre o goto sua tendncia de tornar os programas ilegveis, mas se este for utilizado
prudentemente, pode ser uma vantagem em certas situaes na programao.
O comando goto requer um rtulo para sua operao, o qual rtulo um
identificador vlido em C seguido de dois pontos. O rtulo deve estar na mesma funo
do goto que o utiliza, seno voc no poder efetuar o desvio. A forma geral do goto

goto rtulo;
...
rtulo:
...

Por exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 100:





#include <conio.h>
#include <stdio.h>

void main()
{
int i = 1;

repetir: // rtulo
printf("%d ",i);
i++; // incremento
if(i <= 100)
goto repetir; // chamada do rtulo

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
23
Comando break

O comando break pode ser usado de duas formas. Ele pode ser usado em
conjunto com switch...case como visto anteriormente, ou pode tambm ser usado em
conjunto com um lao de repetio (for, do-while, while) que fora a interrupo deste
lao independentemente da condio de controle.

Por exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 10:













Porm, o comando break fora a sada apenas do lao mais interno de onde ele
se encontra. Por exemplo, o programa abaixo imprime, na tela, os nmeros de 1 a 10, 10
vezes.


























#include <conio.h>
#include <stdio.h>

void main()
{
for(int i = 1; i <= 100; i++)
{
printf("%d ",i);
if(i == 10)
break; // sai do lao quando i = 10
}
_getch();
}
#include <conio.h>
#include <stdio.h>

void main()
{
for(int i = 1; i <= 10; i++)
{
for(int j = 1; j <= 100; j++)
{
printf("%d ",j);
if(j == 10)
break; // sai do lao mais interno quando i=10
}
printf("\n");
}
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
24
Funo exit()

A funo exit() provoca uma terminao imediata do programa inteiro, forando
um retorno ao sistema operacional, ela age como se estivesse finalizando o programa. A
forma geral

void exit(int cdigo_de_sada);

O valor cdigo_de_sada um inteiro que ser passado para o Sistema
Operacional. O zero geralmente usado como um cdigo de retorno que indica uma
terminao normal do programa, enquanto que outros argumentos so usados para
indicar algum tipo de erro.

O exemplo abaixo idntico ao utilizado na seo do-while:























#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

void funcao1(); //funo para converso de temperatura
void funcao2(); //funo para calculo de fatorial

void main()
{
int opcao;
do{

printf("1: Conversao de Temperatura");
printf("\n2: Calcular Fatorial");
printf("\n3: sair");
printf("\nEscolha uma opcao e tecle ENTER: ");
scanf("%d",&opcao); // entrada de variavel

}while(opcao!=1 && opcao!=2);
/*este bloco ser executado sempre que opcao for
diferente de 1 e de 2*/

switch(opcao) // analisa a opcao do usuario
{
case 1: // caso seja 1...
funcao1(); // ... executa funo 1
break;

case 2: // caso seja 2...
funcao2(); // ... executa funo 2
break;

case 3: // caso seja 3...
exit(0); // ...o programa encerrado
break;
}
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
25
Neste exemplo, se o usurio escolher sair do programa, caso 3, o comando
exit(0) encerrar o programa. Note que o argumento utilizado o inteiro zero, que
indica sada normal do programa. As funes funcao1() e funcao2() devem ser
definidas pelo programador.

Comando continue

O comando continue funciona de uma forma um tanto quanto similar ao
comando break. S que, ao invs de forar a terminao do lao, continue fora que
ocorra a prxima iterao deste, pulando qualquer cdigo intermedirio. Para o lao for,
este comando faz com que o teste condicional e a poro de incremento do lao sejam
executados. Para os laos while e do-while, o controle de programa passa para o teste
condicional. Veja o exemplo a seguir, o programa imprime, na tela, os nmeros mpares
de 1 a 100:




























#include <conio.h>
#include <stdio.h>

void main()
{
int resultado;
for(int i = 1; i <= 100; i++)
{
resultado = i%2; // resto da diviso i/2
if(resultado == 0) // se o resto for 0
continue; // continue fora a proxima iterao do lao

printf("%d ",i);
}
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
26
Captulo 4 Matrizes e Strings

Uma matriz um conjunto de variveis de um mesmo tipo. Em C, todas as
matrizes consistem em posies contguas na memria. O endereo mais baixo
corresponde ao primeiro elemento e o mais alto, ao ltimo elemento. Matrizes podem
ter de uma a vrias dimenses. A matriz mais comum em C a de string, que
simplesmente uma matriz de caracteres terminada por um nulo.

Matrizes Unidimensionais

A forma geral para se declarar uma matriz unidimensional

tipo nome[tamanho];

onde tamanho deve ser um inteiro que define quantos elementos a matriz ir armazenar
e tipo o tipo de cada elemento da matriz. Matrizes devem ser explicitamente
declaradas, juntamente com seu tamanho, para que o compilador possa alocar espao
para elas na memria. Por exemplo, se voc quiser declarar um vetor (matriz
unidimensional) do tipo float, chamada notas, e com 50 elementos, este vetor deve ser
declarado da seguinte forma:

float notas[50];

Para vetores, cada elemento possui um ndice, sendo que o primeiro elemento
possui ndice zero e o ltimo possui em seu ndice o tamanho do menos um
(tamanho-1). Por exemplo, considere o vetor

int x[10];

aqui voc est declarando um vetor com dez elementos, x[0] at x[9].


No seguinte cdigo, o programa faz o carregamento de um vetor com os
nmeros de 0 a 99:










Para um vetor, o tamanho total em bytes calculado da seguinte forma:

Total em bytes = sizeof(tipo) * tamanho do vetor

#include <conio.h>
#include <stdio.h>

void main()
{
int x[100];
for(int i = 0; i < 100; i++)
x[i] = i; // x[0]=0... x[1]=1... x[2]=2... etc.
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
27
A linguagem C no possui verificao de limites em matrizes. Voc poderia
ultrapassar o fim de uma matriz e escrever nos dados de alguma outra varivel. Como
programador, voc deve prover verificao dos limites onde for necessrio.

A tabela abaixo exemplifica como um vetor apareceria na memria comeando
na posio 100 e fosse declarado na seguinte forma:

double y[7];

Elemento y[0] y[1] y[2] y[3] y[4] y[5] y[6]
Endereo 100 101 102 103 104 105 106


Passando vetores para funes

Considere o seguinte fragmento de programa que passa o endereo de x para
funo():

void main()
{
int x[15];
funcao(x);
.
.
.
}

Se uma funo recebe um vetor, voc pode declarar o parmetro formal em uma
entre trs formas: como um ponteiro, como uma matriz dimensionada ou como uma
matriz adimensional. Exemplos de como funcao pode receber o vetor x:

funcao(int *x) /* ponteiro */
{
.
.
.
}
Ou

funcao(int x[10]) /* matriz dimensionada */
{
.
.
.
}

Ou ainda

funcao(int x[]) /* matriz adimensional */
{
.
.
.
}

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
28
Todos os trs mtodos possuem resultados idnticos, pois cada um diz ao
compilador q um ponteiro inteiro vai ser recebido. A primeira declarao usa, de fato,
um ponteiro. A segunda emprega a declarao de matriz padro. A ltima declarao
simplesmente especifica que uma matriz do tipo int, de algum tamanho, ser recebida.

Strings

Uma string definida como um vetor de caracteres que terminada por um nulo.
Um nulo especificado como \0 e geralmente zero. Por essa razo, voc precisa
declarar matrizes de caracteres como sendo um caractere mais longo que a maior string
que elas devem guardar. Por exemplo, para declarar um vetor string que guarda uma
string de 10 caracteres, deve-se declarar desta forma

char string[11];

Com isso reserva espao para o nulo no final da string.
Embora a linguagem C no tenha o tipo de dado string, ela permite constantes
string. Uma constante string uma lista de caracteres entre aspas. Por exemplo,

ola mundo

Voc no precisa adicionar o nulo no final das constantes string manualmente, o
compilador C faz isso automaticamente.

C apresenta uma gama de funes de manipulao de strings. Abaixo lista as
mais comuns com seus respectivos efeitos, considere s1 e s2 duas strings, e ch um
caractere.

Funo Efeito
strcpy(s1,s2) Copia s2 em s1
strcat(s1,s2) Concatena s2 ao final de s1
strlen(s1,s2) Retorna o tamanho de s1
strcmp(s1,s2) Retorna 0 se s1 e s2 so iguais; menor que 0 se s1 < s2; maior que
0 se s1 > s2
strchr(s1,ch) Retorna um ponteiro para a primeira ocorrncia de ch em s1
strstr(s1,s2) Retorna um ponteiro para a primeira ocorrncia de s2 em s1

Essas funes utilizam o cabealho STRING.H.

O programa a seguir ilustra o uso dessas funes:










Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
29































Deve-se lembrar que strcmp() retorna zero em caso das strings serem iguais, e
zero falso por isso deve-se usar o operador ! para reverter a condio, assim se tornar
verdadeiro e o bloco dentro do if ser executado.
Se executarmos o programa teremos o seguinte resultado:





#include <conio.h>
#include <stdio.h>
#include <string.h>

void main()
{
char string1[80]; // declarao da string1
char string2[80]; // declarao da string2

printf("Entre com a primeira string: ");
gets(string1); // recebe a string1

printf("Entre com a segunda string: ");
gets(string2); // recebe a string2

printf("\nO tamanho da primeira string e: %d", strlen(string1));
// imprime o tamanho da string1

printf("\nO tamanho da segunda string e: %d", strlen(string2));
// imprime o tamanho da string2

if(!strcmp(string1,string2)) // faz a comparao
printf("\nAs strings sao idnticas");
else
printf("\nAs strings sao diferentes");

printf("\n%s",strcat(string1,string2)); // concatenao
printf("\n%s",string1); // imprime a string1 concatenada

strcpy(string1,"teste"); // copia teste para string1
printf("\n%s",string1);

if(strchr(string2,'a')) // procura pela letra a na string2
printf("\nA segunda string contem a letra a");

if(strstr("ola mundo","ola"))
printf("\nA expressao \"ola mundo\" contem a palavra \"ola\"");

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
30
Matrizes Bidimensionais

A declarao de uma matriz bidimensional semelhante ao de unidimensional.
Por exemplo, se voc quiser declarar uma matriz bidimensional chamada x, do tipo
inteiro e de tamanho 5,10, voc escreveria

int x[5][10];

Similarmente, para acessar o elemento 0,1 voc usaria

X[0][1];

O exemplo abaixo carrega uma matriz bidimensional com os nmeros de 1 a 9 e
o imprime em forma matricial:


















Construindo uma tabela dessa matriz com seus valores, temos a seguinte disposio:

Coluna
Linha
0 1 2
0 1 2 3
1 4 5 6
2 7 8 9

Neste exemplo, o elemento matriz[0][0] possui o valor 1, o elemento
matriz[0][1] possui o valor 2, e assim por diante. O valor do ltimo elemento
matriz[2][2] ser 9.



#include <conio.h>
#include <stdio.h>

void main()
{
int matriz[3][3];

for(int i=0; i<3; i++)
for(int j=0; j<3; j++)
matriz[i][j] = i*3+j+1;

for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
printf("%d",matriz[i][j]);
printf("\n");
}
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
31
Matrizes bidimensionais so armazenadas em uma matriz linha-coluna, onde o
primeiro ndice indica a linha e o segundo, a coluna.
No caso da matriz bidimensional, a seguinte frmula fornece o nmero de bytes
de memria necessrios para armazen-la:

Total em bytes = tamanho do 1 ndice * tamanho do 2 ndice * sizeof(tipo)

Portando, a matriz exemplificada acima, que possui as dimenses 3, 3 teria

3 * 3 * 2

ou 18 bytes alocados, j que cada inteiro ocupa 2 bytes.

Quando passamos uma matriz bidimensional passada como um argumento
para uma funo, apenas um ponteiro para o primeiro elemento realmente passado. No
entanto, uma funo que recebe uma matriz bidimensional como um parmetro formal
deve definir ao menos o comprimento da segunda dimenso. Voc pode especificar a
primeira dimenso, se quiser, mas no necessrio.

Por exemplo, uma funo que recebe uma matriz bidimensional de inteiros com
dimenses 10, 10 declarada dessa forma:

funcao(int matriz[][10])
{
.
.
.
}

Matrizes de Strings

muito comum no C a utilizao das matrizes de strings. Para criar uma, use
uma matriz bidimensional de caracteres. O tamanho do ndice esquerdo indica a
quantidade de strings que deseja e o tamanho do ndice do lado direito indica o
comprimento mximo de cada string. Por exemplo, se voc quiser criar uma matriz de
strings com a capacidade para 50 strings, sendo que, cada uma suporte no mximo 80
caracteres, voc escrever

char nome[50][80];

Para acessar uma string individualmente, voc simplesmente especifica apenas o
ndice esquerdo. Por exemplo, se voc possuir uma lista com os nomes de cinqenta
alunos, e quiser imprimir o nome do 4 aluno, voc dever escrever

printf(%s, nome[3]);

Com isso, toda string da 4 linha ser impressa na tela.



Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
32
Inicializao de Matrizes

C permite a inicializao de matrizes no momento da declarao. A forma geral
de uma inicializao de matriz semelhante de outras variveis, como mostrado aqui:

especificador_de_tipo nome_da_matriz[tamanho1 ...[tamanhoN] = {lista_de_valores};

A lista_de_valores uma lista separada por vrgulas de constantes cujo tipo
compatvel com especificador_de_tipo. A primeira constante colocada na primeira
posio da matriz, a segunda, na segunda posio e assim por diante.

No exemplo abaixo uma matriz inteira de dez elementos inicializada com os
nmeros de 1 a 10:

int i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Isso significa que i[0] ter valor 1 e i[9] ter valor 10;

Matrizes de caracteres que contm strings permitem uma inicializao abreviada
que toma a forma:

char nome_da_matriz[tamanho] = string;

No cdigo abaixo, a matriz de string chamada string inicializada com a frase
ola mundo.

char string[] = ola mundo

Note que no foi definido o tamanho da matriz, quando se realiza uma
inicializao de matriz isso pode ser feito, pois o compilador conta os nmeros de
elementos e aloca o espao automaticamente.
Este cdigo o mesmo que

char string[10] = ola mundo

No esquea de contar um espao extra para o nulo (\0).

Inicializao de matrizes multidimensionais equivalente ao de matrizes
unidimensionais. Por exemplo, a matriz abaixo inicializada com os nmeros de 1 a 9:

int i[3][3] = {1,2,3,4,5,6,7,8,9};

Que tambm pode ser escrita desta forma:

int i[][3] = {1,2,3,4,5,6,7,8,9};





Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
33
Captulo 5 Ponteiros

Um ponteiro uma varivel que contm um endereo de memria. Esse
endereo normalmente a posio de outra varivel na memria. Se uma varivel
contm o endereo de outra, ento a primeira varivel dita para apontar para a
segunda.

Variveis Ponteiros

Se uma varivel ir conter um ponteiro, ela deve ser declarada da seguinte
forma:

tipo *nome;

onde tipo qualquer tipo vlido em C e nome o nome da varivel ponteiro.

Operadores de Ponteiros

Existem dois operadores para ponteiros: * e &. O & um operador unrio
(operador unrio aquele quer requer apenas um operando) que devolve o endereo na
memria de seu operando. Por exemplo,

m = &var;

coloca o endereo da memria da varivel var em m, da dizemos que m est apontando
para var. O endereo no tem relao alguma com o valor de var. O operador & pode
ser imaginado como retornando o endereo de. O comando de atribuio anterior
significa m recebe o endereo de var.

O segundo operador de ponteiro, *, o complemento de &. um operador
unrio que devolve o valor da varivel localizada no endereo que o segue. Neste caso,
se m contm o endereo da varivel var,

q = *m;

coloca o valor de var em q.

Vamos supor que var usa o endereo 100 na posio de memria e que esta
varivel tenha o valor 5. Portanto com a primeira atribuio m ter o valor 100, e com a
segunda atribuio q ter o valor 5, porque 5 estava armazenado na posio 100, que o
endereo que estava armazenado em m. O operador * pode ser imaginado como no
endereo. Nesse caso, o comando anterior significa q recebe o valor que est no
endereo m.






Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
34
Atribuio de Ponteiros

Do mesmo modo que uma varivel comum o contedo de um ponteiro
pode ser passado para outro ponteiro do mesmo tipo.
As variveis ponteiro devem sempre apontar para os tipos de dados corretos.
Uma varivel ponteiro declarada como apontador de dados inteiros deve sempre apontar
para dados deste tipo.

Observar que em C possvel atribuir qualquer endereo a uma varivel
ponteiro. Deste modo possvel atribuir o endereo de uma varivel do tipo float a um
ponteiro inteiro. No entanto, o programa no ir funcionar da maneira correta.

Veja o exemplo abaixo, o endereo do terceiro elemento do vetor v carregado
em p1 e o endereo da varivel i carregado em p2. Alm disso, no final o endereo
apontado por p1 carregado em p2. Os comandos printf() imprimem os valores e os
endereos apontados pelos ponteiros respectivos. %p imprime o valor em hexadecimal
assim como usado pelo computador.





















Com a execuo deste programa, temos o seguinte resultado na tela:





#include <conio.h>
#include <stdio.h>

void main(void)

{

int vetor[] = { 10, 20, 30, 40, 50 };
int *p1, *p2;
int i = 100;

p1 = &vetor[2];
printf("Endereco de p1 e %p e seu valor e %d\n", p1, *p1);

p2 = &i;
printf("\nEndereco de p2 e %p e seu valor e %d\n", p2, *p2);

p2 = p1;
printf("\nEndereco de p2 e %p e seu valor e %d\n", p2, *p2);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
35
Incrementando e Decrementando Ponteiros

O exemplo abaixo mostra que operaes de incremento e decremento podem ser
aplicadas em operandos. O primeiro printf imprime 30 o segundo 40 e o terceiro 50.

















Pode parecer estranho que um endereo que aponte para um nmero inteiro que
armazenado em dois bytes seja incrementado por um e passe para apontar para o
prximo nmero inteiro. A resposta para isto que sempre que um ponteiro
incrementado (ou decrementado) ele passa a apontar para a posio do elemento
seguinte (ou anterior). Do mesmo modo somar trs a um ponteiro faz com que ele passe
apontar para o terceiro elemento aps o atual. Portanto, um incremento em um ponteiro
que aponta para um valor que armazenado em n bytes faz que n seja somado ao
endereo.
possvel usar o seguinte comando:

*(p+1)=10;

Este comando armazena o valor 10 na posio de memria seguinte quela
apontada por p. possvel somarem-se e subtrarem-se inteiros de ponteiros. A
operao abaixo faz com que o ponteiro p passe a apontar para o terceiro elemento aps
o atual.

p = p + 3;

A diferena entre ponteiros fornece quantos elementos do tipo do ponteiro
existem entre os dois ponteiros. No exemplo abaixo impresso o valor 3.








#include <conio.h>
#include <stdio.h>

void main(void)
{
int vetor[] = { 10, 20, 30, 40, 50 };
int *p1;

p1 = &vetor[2];
printf("%d\n", *p1);
p1++;
printf("%d\n", *p1);
p1 = p1 + 1;
printf("%d\n", *p1);

_getch();
}
#include <conio.h>
#include <stdio.h>

void main(void){
float vetor[] = { 1.0, 2.0, 3.0, 4.0, 5.0 };
float *p1, *p2;

p1 = &vetor[2];/* endereco do terceiro elemento */
p2 = &vetor[0];/* endereco do primeiro elemento */
printf("Diferenca entre ponteiros %d\n", p1-p2);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
36
No possvel multiplicar ou dividir ponteiros.

Comparao de Ponteiros

possvel comparar ponteiros em uma expresso relacional. S possvel
comparar ponteiros de mesmo tipo. O trecho de programa abaixo ilustra um exemplo
deste tipo de operaes.

if (c == v)
printf("As variveis estao na mesma posicao.\n");
else
printf("As variaveis nao estao na mesma posicao.\n");

Sendo c e v dois ponteiros declarados e inicializados anteriormente.


Ponteiros e Vetores

Ponteiros e Vetores esto fortemente relacionados na linguagem C. O nome de
um vetor um ponteiro que aponta para a primeira posio do vetor e todas as
operaes j mencionadas para ponteiros podem ser executadas com um nome de vetor.
Por exemplo, a declarao

int v[100];

declara um vetor de inteiros de 100 posies, e a partir dela temos que v um ponteiro
equivalente ao da declarao abaixo

int *v;

Por esta razo as seguintes declaraes so idnticas e podem ser intercambiadas
independentemente do modo como v foi declarado:

v[i] = *(v+i);
&v[i] = v+i;

O exemplo ilustrado abaixo mostra as duas notaes sendo usadas para imprimir
o mesmo vetor.










#include <conio.h>
#include <stdio.h>

void main()
{
float v[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0};
int i;

for (i=0; i<9; i++)
printf("%.1f ", v[i]);

printf("\n");
for (i=0; i<9; i++)
printf("%.1f ", *(v+i));

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
37
Existe uma diferena fundamental entre declarar um conjunto de dados como um
vetor ou atravs de um ponteiro. Na declarao de vetor, o compilador automaticamente
reserva um bloco de memria para que o vetor seja armazenado. Quando apenas um
ponteiro declarado, a nica coisa que o compilador faz alocar um ponteiro para
apontar para a memria, sem que espao seja reservado.

O nome de um vetor chamado de ponteiro constante e, portanto, no pode ter o
seu valor alterado. Assim, os comandos abaixo no so vlidos:











Ponteiros e Strings

Na linguagem C, este tipo de inicializao de ponteiro perfeitamente vlido:

char *str = Esta e uma string

Como voc pode observar, o ponteiro str no um vetor. Todo compilador C
cria o que chamada de tabela de string, que usada internamente pelo compilador
para armazenar as constranges strings usadas pelo programa. Assim, o comando de
declarao anterior coloca o endereo de Esta e uma string, armazenado na tabela de
strings no ponteiro str.
Veja o exemplo abaixo, este programa imprime na tela o contedo da string e de
trs para frente:














#include <conio.h>
#include <stdio.h>

void main()
{
int list[5], i;

/* O ponteiro list nao pode ser modificado recebendo o endereco de i */
list = &i

/* O ponteiro list nao pode ser incrementado */
list++;

_getch();
}
#include <conio.h>
#include <stdio.h>
#include <string.h>

void main()
{
char *str = "Esta e uma string";

printf("%s\n\n", str);

for(int i = strlen(str)-1; i>=0; i--)
printf("%c", str[i]);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
38
Alocao Dinmica de Memria

A alocao dinmica o meio pelo qual um programa pode obter memria
enquanto est em execuo. Como voc sabe, as variveis globais e locais devem ser
declaradas de executar um programa, elas no podem ser acrescentadas durante o tempo
de execuo, portanto elas so constantes. Porm, haver momentos em que um
programa precisa usar quantidades de armazenamento variveis, no constantes

As funes bsicas de alocao de memria so malloc(), calloc() e free(). Estas
funes so encontradas na biblioteca stdlib.h.
As funes malloc() e calloc() alocam memria (neste volume utilizaremos
malloc()) e free() libera. Toda vez que voc alocar espao na memria dever liber-la.

A funo malloc() tem o seguinte prottipo:

void *malloc(size_t numero_de_bytes);

Aqui, numero_de_bytes o nmero de bytes de memria que voc quer alocar.
A funo malloc() devolve um ponteiro do tipo void, o que significa que voc pode
atribu-lo a qualquer tipo de ponteiro, utilizando um cast.

O fragmento de cdigo seguinte aloca 1000 bytes na memria:

char *str;
str = (char *) malloc(1000);

Ou ainda:

char *str;
str = (char *) malloc(1000*sizeof(char));

Como cada elemento do tipo char corresponde a 1 byte, ento teremos 1000
bytes alocados. Se quisermos 150 elementos do tipo int:

int *ptr;
ptr = (int *) malloc(150*sizeof(int));

Mas infelizmente a memria disponvel para o desenvolvimento de nosso
software no infinita, portanto sempre que for feita a alocao dinmica de memria
devemos testar o valor devolvido por malloc(). Se houver um erro de alocao ele
devolver zero (0). Exemplo:

int *ptr;
ptr = (int *) malloc(150*sizeof(int));
if(!ptr)
{
printf(Erro! Memoria Insuficiente);
_getch();
exit(1);
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
39
Como j foi dito, a funo free() libera a memria alocada. Ela possui o seguinte
prottipo:

void free(void *p);

muito importante que voc nunca usar free() com um argumento invlido;
isso destruiria a lista de memria livre.

Veja o programa abaixo utilizando os conceitos de alocao dinmica de
memria:

































Note que foi utilizado um do-while para o recebimento da varivel tam, isso
porque esta varivel no pode assumir um valor menor ou igual a zero, j que no se
pode realizar uma alocao de memria negativa ou igual a zero.




#include <conio.h>
#include <stdio.h>
#include <stdlib.h>

void main(void)
{
float *ptr;
int tam;

do{
printf("Entre com a quantidade de elementos que deseja para
seu vetor: ");
scanf("%d", &tam);
}while(tam<=0); /* tam no pode ser menor ou igual a 0 */

ptr = (float *) malloc(tam*sizeof(float)); /* aloca memoria */
if(!ptr) /* verificao de erro na alocao */
{
printf("Erro! Memoria Insuficiente");
_getch();
exit(1);
}

for(int i = 0; i < tam; i++)
{
printf("Entre com o %d elemento: ", i+1);
scanf("%f", ptr+i); /* recebe o elemento do usuario */
}

system("cls");
printf("Seu vetor e: ");
for(int i = 0; i < tam; i++)
printf("%.2f ", *(ptr+i)); /* imprime o elemento */

free(ptr); /* libera memoria */
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
40
Ponteiros e Matrizes

Nesta seo abordaremos a relao entre ponteiros e matrizes bidimensionais, j
que matrizes unidimensionais (vetores) j foram tratadas anteriormente. No h muita
diferena destes, apenas na forma como o ponteiro tratado para acessar um local
especfico da memria.

Sabemos que um ponteiro aponta para uma rea de memria que endereada
de maneira linear. Deste modo, necessrio mapear o endereo de cada elemento na
matriz, que dado por linha coluna, em um endereo linear.

Considere uma matriz chamada matriz de tamanho LIN, COL que poderia ser
declarada e ter um de seus elementos lidos da seguinte maneira:

















Caso o programa utilizasse ponteiros ao invs de notao de matrizes o trecho de
programa ficaria da seguinte maneira, observe que o endereo de cada elemento da
matriz teve de ser calculado explicitamente:

















#include <conio.h>
#include <stdio.h>
#define LIN 3
#define COL 4

void main()
{
int matriz[LIN][COL];

for(i=0; i<LIN; i++)
{
for (j=0; j<COL; j++)
{
printf("Elemento %d %d = ", i, j);
scanf("%d", matriz[i][j]);
}
}
}

#include <conio.h>
#include <stdio.h>
#define LIN 3
#define COL 4

void main(void){
int *matriz;
int i, j;

matriz = (int *) malloc(LIN*COL*sizeof(int));
if (!matriz){
printf("Erro! memoria suficiente.\n");
_getch();
exit(1);
}

for(i=0; i<LIN; i++){
for (j=0; j<COL; j++){
printf("Elemento %d %d = ", i, j);
scanf("%d", matriz+(i*COL+j));
}
}
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
41
Vetores de Ponteiros

Como ponteiros tambm so variveis possvel ento criar vetores de ponteiros
e utiliz-los. O programa abaixo mostra um programa onde utilizado um vetor de
ponteiros para linhas de caracteres.






























Observe esta declarao:

char *linha[LINHAS];

Ela define um vetor, cujos elementos so ponteiros do tipo char que apontam
para posies de memria. At este momento temos apenas posies reservadas para
armazenar os ponteiros. O espao na memria s efetivamente alocado aps a
chamada da funo malloc().
Neste programa fizemos a alocao linha por linha, onde cada linha possui
capacidade para 60 elementos do tipo char, se comportando portando como uma matriz
de strings (visto no captulo 4), s que utilizando o conceito de ponteiros.




#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#define LINHAS 10
#define COLUNAS 60

void main(void)
{
char *linha[LINHAS];

for(int i = 0; i < LINHAS; i++)
{ /* aloca memoria, linha por linha */
if(!(linha[i] = (char *)malloc(COLUNAS*sizeof(int))))
{
printf("Nao consegui alocar o vetor %d.\n", i);
exit(i);
}
}

for(int i = 0; i < LINHAS; i++)
{
printf("Entre com a linha %d.\n", i);
gets(linha[i]); /* recebe as strings */
}

for(int i = 0; i < LINHAS; i++) /* imprime as strings */
printf("Linha %d: %s\n", i, linha[i]);

for(int i = 0; i < LINHAS; i++)
free(linha[i]); /* libera a memoria, linha por linha */

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
42
Ponteiros para Ponteiros

No exemplo da seo anterior, observamos que o nmero de linhas da matriz
fixo, e, portanto, h uma mistura de notao de ponteiros com matrizes. Vamos
considerar um exemplo onde tanto o nmero de linhas como o de colunas
desconhecido. Neste exemplo iremos criar um vetor de ponteiros que ir armazenar o
endereo inicial de cada linha. Portanto, para obter um elemento da matriz primeiro
devemos descobrir onde est a linha no vetor que armazena os endereos das linhas, em
seguida procuramos na linha o elemento.

O programa abaixo pede ao usurio que digite o nmero de linhas e colunas da
matriz. Em seguida ler todos os elementos da matriz e a imprimir na tela. Observe que
agora foi criado um ponteiro para ponteiro chamado de **matriz.

O programa primeiro pergunta o nmero de linhas da matriz para poder alocar
espao para armazenar os ponteiros para cada uma das linhas. Em seguida alocado
espao para armazenar cada uma das linhas.

































Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
43


















































#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

void main ()
{
int **matriz; /* matriz de ponteiros */
int lin, col; /* nmero de linhas e colunas */

do {
printf("Entre com o numero de linhas: ");
scanf("%d", &lin); /* recebe o numero de linhas */
} while (lin<=0);

/* aloca as linhas da matriz */
matriz = (int **) malloc (lin * sizeof(int *));
if (!matriz)
{
printf("Erro! Memoria Insuficiente!");
_getch();
exit(1);
}

do{
printf("Entre com o numero de colunas: ");
scanf("%d", &col); /* recebe o numero de colunas */
}while (col<=0);

for (int i = 0; i < lin; i++)
{ /* aloca as colunas de cada linha da matriz */
*(matriz+i) = (int *) malloc(col * sizeof (int));
if(! *(matriz+i) ){
printf("Erro! Memoria Insuficiente!");
exit(1);
}
}

printf("Entre com os elementos da matriz\n");
for(int i = 0; i < lin; i++)
{
for(int j = 0; j < col; j++)
{
printf("\nElemento %d %d: ", i, j);
scanf("%d", *(matriz +i) +j);
} /* recebe os elementos */
}

system("cls");
printf("Os elementos da sua matriz sao\n\n");

for(int i = 0; i < lin; i++)
{
for(int j = 0; j < col; j++)
printf("%d ", *(*(matriz +i) +j));
printf("\n"); /* imprime os elementos na tela */
}

free(matriz);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
44
Captulo 6 Funes

Funes so os blocos de construo de C, e o local onde toda atividade
ocorre. Elas so umas das caractersticas mais importantes de C.

A forma geral de uma funo

especificador_de_tipo nome_da_funes(lista_de_parmetros)
{
corpo da funo
}

especificador_de_tipo se refere ao tipo de valor que a funo retorna. Este pode
ser qualquer tipo vlido em C.

lista_de_parmetros uma lista de variveis separadas por vrgulas e seus tipos
associados, se caso a sua funo no precisar de parmetros, a lista ser vazia. No
entanto, os parnteses ainda so necessrios. Exemplos:











Tambm pode ocorrer, como j foi discutido no captulo 2, a necessidade da
declarao de variveis internamente, esse tipo de varivel chamada de varivel local,
essas variveis vem a existir na entrada da funo e so destrudas ao sair, ou seja, no
podem ser acessadas aps o fim da funo.

Em geral os argumentos podem ser passados de duas maneiras, chamada por
valor ou chamada por referncia. No primeiro caso, copiado o valor de um argumento
para o parmetro de uma funo, assim alteraes feitas nos parmetros formais no
possuem efeito nas variveis utilizadas. No segundo caso, chamada por referncia,
repassada para a funo o endereo da varivel como argumento, assim as operaes
ocorrem diretamente no argumento, ou varivel global.










void funcao1(char y, int h)
{
bloco
}

float funcao2(float x, double *z)
{
bloco
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
45
Funes Recursivas

Um tipo especial de funo a funo recursiva, ou recurso, que ocorre quando
um comando no corpo da funo a chama. Um exemplo clssico de funo recursiva o
calculo de fatorial. Veja o exemplo abaixo:



























O mesmo exemplo pode ser feito de forma no-recursiva, veja o trecho do programa:

int fatorial(int x)
{
int resultado = 1;

for(int t = 1; t <= x; t++)
resultado = resultado*(t);

return resultado;
}







#include <stdio.h>
#include <conio.h>

int fatorial(int x);

void main ()
{
int num;

do{
printf("Entre com um numero natural para o calculo do
fatorial: ");
scanf("%d", &num);
}while(num < 0);

printf("\n\nO fatorial de %d e %d", num, fatorial(num));
_getch();
}

int fatorial(int x)
{
int resultado;
if(x == 1)
return 1;
else if(x == 0)
return 1;
else
return resultado = x*fatorial(x-1);
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
46
Funes que retornam ponteiros

As funes que devolvem ponteiros so manipuladas da mesma forma, embora
precisem de ateno especial. Ponteiros para variveis no so variveis, eles so o
endereo na memria de um certo tipo de dado. Para se retornar um ponteiro, a funo
deve ter o tipo de retorno igual a um ponteiro. Veja um exemplo de uma funo que
devolve um ponteiro para a primeira ocorrncia do caractere c na string s























Lembrando que quando se incrementa um ponteiro, ele aponta para o prximo
elemento da memria.

















#include <stdio.h>
#include <conio.h>

char *match(char c, char *s);

void main ()
{
char ch, *s = "ola mundo", *string;

printf("Entre com um caractere: ");
scanf("%c", &ch);

string = match(ch, s);
printf(string);

_getch();
}

char *match(char c, char *s)
{
while(c != *s)
s++;
return s;
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
47
Captulo 7 Estruturas

Em C, uma estrutura uma coleo de variveis referenciadas por um nome,
fornecendo uma maneira conveniente de se ter informaes relacionadas agrupadas.
Uma definio de estrutura forma um modelo que pode ser usado para criar variveis de
estruturas. As variveis que compreendem a estrutura so chamadas elementos da
estrutura.

Por exemplo, se quisermos uma estrutura com dados de um aluno, com
informao deste como seu nome, nmero de matrcula, entre outros, devemos usar o
seguinte fragmento de cdigo que mostra como criar um modelo de estrutura. A
palavra-chave struct informa ao compilador que um modelo de estrutura est sendo
definido.

struct alunos
{
char nome[80];
char numero_matricula[15];
int numero_de_faltas;
float notas[4];
};

Note que a definio termina com um ponto-e-vrgula. Isso ocorre porque uma
definio de estrutura um comando. Alm disso, o nome (ou rtulo) da estrutura
alunos identifica essa estrutura de dados em particular e o seu especificador de tipo.

Com este cdigo, nenhuma varivel foi de fato declarada. Foi feito apenas uma
definio do formato da estrutura. Para declarar uma varivel com essa estrutura escreva

struct alunos informacao;

Isso declara uma varivel do tipo estrutura alunos chamada informacao.
O compilador C aloca automaticamente memria suficiente para acomodar todas
as variveis que formam a varivel estrutura. Neste caso, esta estrutura ocupa na
memria o espao de 113 bytes.

Voc tambm pode declarar uma ou mais variveis enquanto a estrutura
definida. Por exemplo,

struct alunos
{
char nome[80];
char numero_matricula[15];
int numero_de_faltas;
float notas[4];
} informacao, dados, variavel;






Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
48
O nome da estrutura pode ser omitido se voc precisar apenas de uma varivel
estrutura. Isso significa que

struct alunos
{
char nome[80];
char numero_matricula[15];
int numero_de_faltas;
float notas[4];
} informacao;

Declara uma varivel chamada informacao como definido pela estrutura que a precede.

Portanto, a forma geral de uma definio de estrutura

struct nome
{
tipo nome_da_varivel1;
tipo nome_da_varivel2;
.
.
.
tipo nome_da_varivelN;
}variveis_estrutura;

Onde nome ou variveis_estrutura podem ser omitidos, mas no ambos.

Refereciando Elementos de Estruturas

Os elementos individuais de estruturas so referenciados atravs do operador
ponto (.). Por exemplo, digamos que voc deseja acessar o nmero de faltas de um
aluno, atribuindo a esse um valor, escreva

informacao.numero_de_faltas = 2;

O nome da varivel estrutura seguido por um ponto e pelo nome do elemento
referencia esse elemento individual da estrutura. A forma geral para acessar um
elemento de estrutura

nome_da_varivel_estrutura.nome_do_elemento

Portanto, para escrever o numero de faltas na tela escreva

printf("%d",infomrmacao.numero_de_faltas);

Analogamente, pode ser usada a funo gets() para receber o nome do aluno

gets(informacao.nome);






Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
49
Matrizes de Estruturas

Para declarar uma matriz de estruturas, voc deve primeiro definir uma estrutura
e, ento, declarar uma varivel matriz desse tipo. Por exemplo, para declarar uma matriz
de estruturas com 50 elementos do tipo alunos, que foi definido anteriormente, deve-se
escrever

struct alunos informacao[50];

Isso cria 50 conjuntos de variveis que esto organizados como definido na
estrutura alunos.
Para acessar uma determinada estrutura, deve-se indexar o nome da estrutura.
Por exemplo, para imprimir o nmero de faltas do aluno 4, escreva

printf(%d , informao[3].numero_de_faltas);

Como todas as outras matrizes, matrizes de estruturas comeam a indexao em
zero.

Passando estruturas para funes

At agora, todas as estruturas e matrizes vistas foram declaradas como globais.
Mostraremos agora como passar estruturas e seus elementos para funes.

Quando voc passa um elemento de uma varivel estrutura para uma funo,
est, de fato, passando o valor desse elemento para a funo. Veja o exemplo a seguir:

struct novo
{
char x;
int y;
float z;
char s[10];
}var;

Abaixo so mostrados exemplos de cada elemento sendo passado para uma
funo:

funcao1(var.x); /*passa o valor do caractere de x*/
funcao1(var.y); /*passa o valor inteiro de y*/
funcao1(var.z); /*passa o valor float de z*/
funcao1(var.s); /*passa o endereo da string s*/
funcao1(var.s[2]); /*passa o valor do caractere de s[2]*/






Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
50
Porm, se voc quiser passar o endereo de um elemento individual da estrutura,
ponha o operador & antes do nome da estrutura. Por exemplo, escreva:

funcao1(&var.x); /*passa o endereo do caractere de x*/
funcao1(&var.y); /*passa o endereo inteiro de y*/
funcao1(&var.z); /*passa o endereo float de z*/
funcao1(var.s); /*passa o endereo da string s*/
funcao1(&var.s[2]);/*passa o endereo do caractere de s[2]*/

Quando uma estrutura usada como um argumento para uma funo, a estrutura
inteira passada usando o mtodo padro chamado por valor.
Quando usar uma estrutura como parmetro, lembre-se de que o tipo de
argumento deve coincidir com o tipo de parmetro. Por exemplo, esse programa
imprime os nmeros 100 e 250, e uma constante string na tela. Definimos uma estrutura
global e, ento usamos seu nome para declarar variveis estruturas e parmetros,
conforme necessrio.


































#include <stdio.h>
#include <conio.h>
void funcao1(struct estrutura param);
void funcao2(struct estrutura param2);

struct estrutura
{
int a, b;
char ch;
};

void main()
{
struct estrutura arg;
arg.a = 100;
arg.b = 250;
arg.ch = "Ola mundo";
funcao1(arg);
funcao2(arg);
}

void funcao1(struct estrutura param1)
{
printf("%d", param1.a);
}

void funcao2(struct estrutura param2)
{
printf("\n%d", param2.a);
printf("\n%s", param2.ch);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
51
Ponteiros para Estruturas

Na linguagem C permitido usar ponteiros para estruturas assim como ponteiros
para outros tipos de variveis.

Com outros ponteiros, voc declara ponteiros para estrutura colocando * na
frente do nome da varivel estrutura. Por exemplo, o cdigo seguinte declara um
ponteiro para dados do tipo struct.

struct alunos *ptr;

Se vrias estruturas so usadas, a performance de seu programa pode ser
reduzida a nveis inaceitveis, a soluo para esse problema passar apenas um ponteiro
para uma funo. E tambm, atualmente a grande gama dos programas utilizando
estruturas no possui tamanho definido, precisando para isso, realizar uma alocao
dinmica de memria.
Para encontrar o endereo da varivel estrutura, deve-se colocar o operador &
antes do nome desta varivel. Por exemplo:

struct alunos
{
char nome[80];
char numero_matricula[15];
int numero_de_faltas;
float notas[4];
} informacao;

struct alunos *ptr;


ento

ptr = &informacao;

este cdigo pe o endereo da estrutura informacao no ponteiro ptr.

Para acessar os elementos de uma estrutura usando um ponteiro para estrutura,
voc deve usar o operador -> (chamado operador seta). Por exemplo, isso referencia o
campo numero_de_faltas:

ptr -> numero_de_faltas;

Este operador seta usado no lugar do operador ponto quando se est acessando
um elemento de estrutura atravs de um ponteiro para a estrutura.
Portanto lembre-se de usar o operador ponto para acessar elementos de
estruturas quando estiver operando atravs da varivel estrutura, e usar o operador seta
quando voc estiver operando atravs de um ponteiro para a estrutura.






Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
52
Estruturas Aninhadas

Quando um elemento de uma estrutura um elemento de outra estrutura,
dizemos que esta uma estrutura aninhada. Considere o exemplo abaixo:


Como podemos perceber, a estrutura aluno possui dois elementos. O primeiro
elemento a estrutura do tipo endereo, que contm outros dois elementos com dados
do aluno relacionado ao seu endereo. O segundo elemento nome, que um vetor do
tipo char.

Para acessar os elementos de uma estrutura, como sabemos, utilizamos uma
varivel estrutura. Neste caso, como h uma estrutura dentro da outra, devemos utilizar
duas variveis estruturas para acessar algum elemento da estrutura mais interna. O
padro ANSI C especifica que as estruturas podem ser aninhadas at 15 nveis.







#include <stdio.h>
#include <conio.h>

struct endereco
{
char rua[80];
int numero_da_casa;
} var;

struct aluno
{
char nome[80];
struct endereco var;
} info;

void main()
{
printf("Nome: ");
gets(info.nome);

printf("Rua: ");
gets(info.var.rua);

printf("Numero da Casa: ");
scanf("%d", &(info.var.numero_da_casa));

printf("\n\nDados:\n");
printf("Nome: %s", info.nome);
printf("\nEndereco: %s %d", info.var.rua,
info.var.numero_da_casa);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
53
Captulo 8 Entrada/Sada pelo Console

Input/Output traduzindo teramos Entrada/Sada, mais conhecido como
simplesmente I/O ou E/S, so funes como o prprio nome j indica, funes de
entrada e sada. O arquivo de cabealho dessas funes STDIO.H, que quer dizer
standard input/output. Podemos ter funes de I/O de diversas formas, como atravs do
console, ou atravs de arquivos. Primeiramente vamos fala de I/O atravs do console.
As funes I/O mais simples so getchar(), que l um caractere do teclado, e putchar()
que escreve um caractere na tela. Ambas retornam EOF se ocorrer algum erro. Vejamos
um exemplo de funo que l caracteres do teclado e inverte a caixa deles, isto ,
escreve maisculas como minsculas ou vice-versa.




















Contudo existem alguns problemas com o getchar(), como a verso de original
de C era compatvel com o UNIX, getchar() armazena em um buffer a entrada at que
seja pressionado ENTER. Assim temos as funes getch() e getche(), que pertencem a
biblioteca CONIO.H, embora elas no sejam definidas pelo padro ANSI, elas so mais
recomendadas. A funo getch() espera at que uma tecla seja pressionada, e retorna
imediatamente, e no mostra o caractere na tela. A getche() igual a getch(), mas a
tecla mostrada.

Para ler e escrever strings temos as funes gets() e puts(), assim como temos as
funes printf() e scanf(). A diferena bsica que uma chamada a gets() ou puts()
requer bem menos tempo que printf() e scanf() porque elas aceitam apenas strings de
caracteres, no se pode escrever nmeros ou fazer converses de formato. Por essa
razo gets() e puts() so mais utilizadas quando o mais importante possuir um cdigo
altamente otimizado. Sendo assim vamos tratar apenas das funes printf() e scanf().





#include <stdio.h>
#include <conio.h>
#include <ctype.h> //necessrio para as funes islower,
//toupper, tolower

void main()
{
char ch;

printf("Digite uma frase (digite ponto para sair). \n");
do
{
ch = getch();
if (islower(ch))
ch = toupper(ch);
else
ch = tolower(ch);
putchar(ch);
}while (ch != '.');
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
54
Funo: printf()

O prottipo para printf()

int printf(char *string_de_controle, lista_de_argumentos);

string_de_controle constituda, basicamente, de dois tipos de itens. O primeiro
tipo formado pelos caracteres que sero impressos na tela. O segundo contm
comandos de formato que definem a maneira como os argumentos subseqentes sero
mostrados, veja exemplo:

printf(Estou %s linguagem %c, aprendendo, C);

Ser impresso na tela: Estou aprendendo linguagem C

Um comando de formato constitudo do smbolo porcentagem (%) seguido
pelo cdigo de formato, exemplos: %c ; %s ; %i (veja tabela abaixo). Deve haver o
mesmo nmero de argumentos e de comandos de formato e estes dois so combinados
na ordem, da esquerda para a direita.

Cdigo Formato
%c Caractere
%d Inteiros decimais com sinal
%i Inteiros decimais com sinal
%e Notao cientfica (e minsculo)
%E Notao cientfica (E maisculo)
%f Ponto flutuante decimal
%g Usa %e ou %f, o que for mais curto
%G Usa %E ou %F, o que for mais curto
%o Octa sem sinal
%s String de caracteres
%u Inteiros decimais sem sinal
%x Hexadecimal sem sinal (letras minsculas)
%X Hexadecimal sem sinal (letras maisculas)
%p Apresenta um ponteiro
%n
Ponteiro utilizado para inteiro no qual o nmero de caracteres escritos
at esse ponto colocado
%% Escreve o smbolo %

Para se escrever caracteres se utiliza %c, %s para strings, %d ou %i para indicar
decimal com sinal, %d e %i so equivalentes, %f representa nmeros em ponto
flutuante, %e ou %E indicam que se deve mostrar um double em notao cientifica, o
%g ou %G faz com que o printf() decida utilizar %f ou %e, assim selecionando o de
sada mais curta.
Exemplo de utilizao de printf() :

char s[20];
gets(s);
printf(Eu gosto de %s ., s);
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
55

Especificadores de largura mnima de campo

O nmero colocado entre o smbolo % e o cdigo do formato age como
especificador de largura mnima de campo. Se a string, ou nmero, for maior do que o
mnimo, este ser escrito por inteiro, caso contrrio ele preenche a sada com espaos.
Ao invs de espaos, se quiser completar com zeros deve se colocar um zero antes do
especificador da largura mnima. Por exemplo %05d preencher um nmero de menos
de cinco dgitos com zeros de forma que seu comprimento total seja 5. Veja o exemplo
abaixo:













Este programa produz o seguinte resultado:




Especificador de preciso

O especificador de preciso segue o especificador de largura mnima de campo
(se houver algum), consistindo em um ponto seguido de um inteiro. O seu significado
exato depende do tipo de dado a que est sendo aplicado.

Especificador de preciso aplicado a um ponto flutuante determina o nmero de
casas decimais a ser mostrado. Por exemplo, %10.4f mostra um nmero com pelo
menos 10 caracteres e 4 casas decimais.

Aplicado a %g ou %G ele determina a quantidade de dgitos significativos a
serem impressos na tela. Aplicado a tipos inteiros (int), o especificador de preciso
adiciona zeros iniciais para completar o nmero solicitado de dgitos.

Aplicados a strings ele determina o comprimento mximo do campo. Por
exemplo, %5.7s ele ir mostrar uma string de no mnimo 5 e no mximo 7 caracteres.
#include <stdio.h>
#include <conio.h>

void main()
{
double item = 23.435479;

printf("%f", item);
printf("\n%03f", item);
printf("\n%012f", item);
printf("\n%12f", item);

_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
56
Funo: scanf()

Muito parecida com printf(), seria como seu inverso, scanf() a rotina de
entrada pelo console de uso geral. Ela pode ler todos os tipos de dados intrnsecos e
converte automaticamente nmeros ao formato interno apropriado. Seu prottipo :

int printf(char *string_de_controle, lista_de_argumentos);

A funo scanf() devolve o nmero de itens de dados que foi atribudo, com
xito, a um valor. Se houver um erro, esta funo devolve EOF. A string_de_controle
determina como os valores so lidos para as variveis apontadas na
lista_de_argumentos.

Veja a tabela de especificadores de formato para scanf().

Cdigo Significado
%c L um nico caractere
%d L inteiro decimal
%i L inteiro decimal
%e L um nmero em ponto flutuante
%f L um nmero em ponto flutuante
%g L um nmero em ponto flutuante
%o L um octal
%s L uma string
%x L um nmero hexadecimal
%p L um ponteiro
%n Recebe um valor igual ao nmero de caracteres lidos at ento
%u L um inteiro sem sinal
% Busca por um conjunto de caracteres

Exemplo de uma utilizao do scanf():

char ch, string[80];
float f;
int i, *ptr;

scanf(%d %d, &i, ptr);
scanf(%f, &f);
scanf(%c %s, &ch, string);

Todas as variveis utilizadas para receber valores atravs de scanf() devem ser
passadas pelos seus endereos. Isso significa que todos os argumentos devem ser
ponteiros para as variveis usadas como argumentos. Essa a maneira de C criar uma
chamada por referncia e que permite a uma funo alterar o contedo de um
argumento.



Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
57
Quando feita a leitura de um nmero, a funo scanf() termina a leitura de um
nmero quando o primeiro caractere no numrico encontrado. J, quando feita a
leitura de strings, esta funo l os caracteres at que seja encontrado um caractere de
espao em branco.

Descartando espaos em branco indesejados

Descartar espaos em brancos, nada mais do que um caractere de espao em
branco na string de controle. Esse espao em branco faz com que o scanf(), salte um ou
mais caracteres, de espao em branco da stream de entrada, at que seja encontrado o
primeiro caractere de espao no-branco. Exemplo:

string de entrada => aulas MTP

char entrada1[15], entrada2[15];
scanf(%s %s, &entrada, &entrada);

Nesse caso a string entrada1 ser aulas e a entrada2 ser MTP.


Descartando caracteres de espao no-branco

Um caractere no-branco na string de controle faz com que scanf() leia e ignore
caracteres iguais na stream de entrada. Se o caractere especificado no for encontrado
scanf() termina. Exemplo:

sting de entrada => 10,30

int x, y;
scanf(%d,%d, &x, &y);

Nesse caso x = 10 e y = 30.


















Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
58
Captulo 9 Entrada/Sada com Arquivo

A linguagem C no contm nenhum comando E/S (entrada e sada). Ao
contrrio, todas as operaes de E/S ocorrem atravs de chamadas de funes da
biblioteca C padro. Essa abordagem faz o sistema de arquivos de C extremamente
poderoso e flexvel.

Streams e Arquivos

O sistema de entrada e sada de C fornece uma interface consistente ao
programador C, independente do dispositivo real que acessado, ou seja, esse sistema
prov um nvel de abstrao entre o programador e o dispositivo utilizado. Esta
abstrao chamada de stream, enquanto que o dispositivo real chamado de arquivo.

Streams

O sistema de arquivos pode trabalhar com uma grande variedade de dispositivos,
acionadores de disco, terminais, entre outros. Embora cada um dos dispositivos seja
bastante diferente entre si, o sistema de arquivo com buffer transforma-os em um
dispositivo lgico chamado de stream, onde todas as stream se comportam de forma
semelhante. Existem dois tipos de streams: texto e binria.

Uma stream de texto uma seqncia de caracteres. O padro ANSI permite
(mas no exige) que uma stream de texto seja organizada em linhas e terminada por um
caractere de nova linha. Porm, o caractere de nova linha. Porm, o caractere de nova
linha opcional na ltima linha e determinado pela implementao.

Uma stream binria uma seqncia de bytes com uma correspondncia de um
para um com aqueles encontrados no dispositivo externo, ou seja, no ocorre nenhuma
traduo de caracteres. Alm disso, o nmero de bytes escritos (ou lidos) o mesmo
que o encontrado no dispositivo externo.

Arquivos

Para linguagem C, arquivo pode ser qualquer coisa, como um terminal, uma
impressora, ou um arquivo salvo no disco rgido. Para associar uma stream a um
arquivo deve-se realizar uma operao de abertura.

Como j foi dito, todas as streams em C so iguais, porm os arquivos possuem
diferenas. Por exemplo, um disco rgido pode suportar acesso aleatrio, enquanto que
um teclado no pode.

Uma vez que, uma stream estiver associada a um arquivo e voc no precisar
mais trocar informaes entre seu programa e o arquivo, voc realizar uma operao de
fechamento. Se um arquivo aberto para sada for fechado, o contedo, se houver algum,
de sua stream associada escrito no dispositivo externo. Esse processo geralmente
referido como descarga (flushing) da stream e garante que nenhuma informao seja
acidentalmente deixada no buffer de disco. Quando o programa termina, normalmente
com o main() retornando ao sistema operacional ou com um exit(), sendo que, os
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
59
arquivos so fechados automaticamente. Sendo que, eles no so fechados quando um
programa quebra (crash).

Uma stream associada a um arquivo tem uma estrutura de controle de arquivo do
tipo FILE. Essa estrutura definida no cabealho STDIO.H.

Sistema de Arquivos

Ponteiro de Arquivo

Um ponteiro de arquivo um ponteiro para informaes que definem coisas
sobre o arquivo, incluindo seu nome, status e a posio atual do arquivo. Um ponteiro
de arquivo uma varivel do tipo FILE. Para ler ou escrever em um arquivo, seu
programa precisa de um ponteiro de arquivo. Para declarar um ponteiro de arquivo, use
o seguinte comando:

FILE *fp;

Abrindo um Arquivo

Para fins prticos, consideraremos sempre o arquivo neste volume como sendo
um arquivo em disco, desconsiderando perifricos, portas externas, entre outros.
Para abrir um arquivo, voc deve utilizar a funo fopen(), que abre uma stream
para uso e associa um arquivo a ela. Para abrir um arquivo utilize a seguinte comando:

FILE *fp;
fp = fopen(nome_do_arquivo, modo);

onde nome_do_arquivo um nome vlido para o arquivo que voc quiser criar. Por
exemplo, se voc quiser cadastrar alunos e salvar em um arquivo um nome vlido
poderia ser Alunos. Ao dar um nome ao arquivo, voc pode incluir uma especificao de
caminho.
E modo determina como o arquivo ser aberto. Veja abaixo os modos mais
utilizados:

Modo r: Este modo abre um arquivo texto para leitura. Se este arquivo no existir ou
no for encontrado, fopen() retorna um erro.

Modo w: Este modo abre um arquivo texto vazio para escrita. Se este arquivo no
existir, ele ser criado, porm se ele existe, este ser destrudo para criao de um
arquivo vazio para escrita, assim seu contedo ser perdido.

Modo a: Este modo abre um arquivo texto para escrita no final deste, ou seja, em
forma de apndice. Explicando melhor, todo arquivo quando criado possui no final dele
um marcador EOF (end of file, ou final de arquivo); se o arquivo no existir ele ser
criado para escrita, porm se ele existir, ao contrrio do modo w seu contedo no
ser destrudo, o marcador EOF ser removido para que continue escrevendo nele.

Modo rb: Anlogo ao modo r, s que ele abre um arquivo binrio para leitura.
Modo wb: Anlogo ao modo w, s que ele abre um arquivo binrio para escrita.
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
60

Modo ab: Anlogo ao modo a, s que ele abre um arquivo binrio para apndice.

Modo r+: Este modo abre um arquivo para leitura e escrita. Este arquivo deve existir,
seno fopen() retorna um erro. Para escrever neste modo, ao contrrio do apndice, o
indicador de posio no se encontra no final do arquivo, e sim no comeo.

Modo w+: Este modo anlogo ao w. Porm ele realiza a leitura e escrita do
arquivo.

Modo a+: Este modo anlogo ao a. Porm ele realiza a leitura e apndice.

Modo rb+: Anlogo ao modo r+, s que ele abre um arquivo binrio para leitura e
escrita.

Modo wb+: Anlogo ao modo w+, s que ele abre um arquivo binrio para leitura
e escrita.

Modo ab+: Anlogo ao modo a+, s que ele abre um arquivo binrio para leitura e
apndice.

A funo fopen() devolve um ponteiro de arquivo. Seu programa nunca deve
alterar o valor deste ponteiro. Se ocorrer um erro quando estiver tentando abrir um
arquivo, fopen() devolve um ponteiro nulo.
Para abrir um arquivo texto chamado teste para escrita, escreva desta forma:









O comando if utilizado faz a verificao de erro da abertura do arquivo.

Fechando um Arquivo

Para fechar uma stream que foi aberta atravs de uma chamada fopen() utilize
a funo fclose(). Ela escreve qualquer dado que ainda permanece no buffer de disco no
arquivo e, ento, fecha normalmente o arquivo em nvel de sistema operacional. Um
fclose() tambm libera o bloco de controle de arquivo associado stream, deixando-o
disponvel para reutilizao. Por exemplo, para fechar um arquivo como o do exemplo
anterior utilize a seguinte notao:

fclose(fp);

onde fp o ponteiro de arquivo devolvido pela chamada fopen().


FILE *fp;
fp = fopen(teste, w);
if(!fp)
{
printf(Erro na abertura de arquivo);
_getch();
exit(1);
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
61
Funes para Arquivos

O sistema de arquivos ANSI contm diversas funes inter-relacionadas. Veja a
tabela abaixo:

Nome Funo
fopen() Abre um arquivo
fclose() Fecha um arquivo
putc() Escreve um caractere em um arquivo
fputc() O mesmo que putc()
getc() L um caractere de um arquivo
fgetc() O mesmo que getc()
fseek() Posiciona o arquivo em um byte especifico
fprintf() para um arquivo o que printf() para o console
fscanf() para um arquivo o que scanf() para o console
feof() Devolve verdadeiro se o fim de arquivo for atingido
ferror() Devolve verdadeiro se houve um erro
rewind() Reposiciona o indicador de posio de arquivo no incio do mesmo
remove() Apaga um arquivo
fflush() Descarrega um arquivo

Funes: putc() e fputc()

Estas duas funes so equivalentes, elas escrevem caracteres no arquivo
previamente aberto para escrita atravs da funo fopen(). Os prottipos para essas
funes so

int putc(int ch, FILE *fp);
int fputc(int ch, FILE *fp);

onde fp um ponteiro de arquivo devolvido por fopen() e ch o caractere a ser escrito.
Por razes histricas ch definido como int, mas ch um caractere, veja o exemplo
abaixo:
















#include <conio.h>
#include <stdio.h>

void main()
{
char ch1 = 'o';
FILE *fp;

fp = fopen("arquivo.txt","w");
if(!fp)
{
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

putc(ch1, fp);
putc('l', fp);
fputc('a', fp);

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
62
Este cdigo cria um arquivo chamado arquivo do tipo texto (extenso .txt) e
escreve nele a palavra ola, caractere por caractere, exemplificando as diversas formas
como pode ser inserido um caractere em um arquivo.

Funes: getc() e fgetc()

Estas duas funes so equivalentes, elas lem caracteres no arquivo
previamente aberto para leitura atravs da funo fopen(). O prottipo para essa funo

int getc(FILE *fp);
int fgetc(FILE *fp);

onde fp um ponteiro de arquivo devolvido por fopen(). Veja o exemplo abaixo, este
programa l o arquivo escrito pelo exemplo anterior e imprime na tela.






















O lao do-while repetido enquanto ch no atingir o final do arquivo.

Funo: feof()

Quando um arquivo aberto para entrada binria, um valor inteiro igual marca
de EOF pode ser lido. Isso poderia fazer com que a rotina de entrada indicasse uma
condio de fim de arquivo apesar do final fsico do arquivo no tiver sido de fato
alcanado. Como soluo deste problema temos a funo feof(), que determina quando
o final de arquivo foi atingido na leitura de dados binrios. Seu prottipo

int feof(FILE *fp);

#include <conio.h>
#include <stdio.h>

void main()
{
char ch;
FILE *fp;

fp = fopen("arquivo.txt","r");
if(!fp)
{
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

do{
ch = getc(fp);
printf("%c", ch);
}while(ch!=EOF);

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
63
Esta funo devolve verdadeiro se o final do arquivo for atingido; caso contrrio,
devolve falso (0). O seguinte cdigo l um arquivo binrio at que o final do arquivo
seja encontrado.

while(!feof(fp))
ch = getc(fp);

Voc pode utilizar esse mtodo tanto para arquivo texto quanto binrios. Veja o
exemplo a seguir, que anlogo ao da seo anterior, porm utilizando o novo conceito
de feof().























Funes: fputs() e fgets()

As funes fputs() e fgets() efetuam, respectivamente, operaes de escrita e
leitura de strings de um arquivo em disco. Elas funcionam de maneira semelhante a
putc() e getc(), mas, ao invs de escrever ou ler um nico caractere, elas operam com
strings. Seus prottipos so:

int fputs(const char *str, FILE *fp);
char *fgets(char *str, int length, FILE *fp);

A funo fgets() l uma string da stream especificada at que um caractere de
nova linha seja lido ou que length-1 caracteres tenham sido lidos.





#include <conio.h>
#include <stdio.h>

void main()
{
char ch;
FILE *fp;

fp = fopen("arquivo.txt","r");
if(!fp)
{
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

while(!feof(fp))
{
ch = getc(fp);
printf("%c", ch);
}

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
64
Funo: rewind()

A funo rewind() reposiciona o indicador de posio de arquivo no incio do
arquivo especificado, ou seja, ela rebobina o arquivo. Seu prottipo

void rewind(FILE *fp);

Veja o exemplo abaixo, voc entra com strings, que gravado no arquivo, para
encerrar basta voc teclar ENTER no momento em que se pede uma string. Logo depois
o arquivo rebobinado, e feito a leitura dele imprimindo as suas strings na tela.








































#include <conio.h>
#include <stdio.h>
#include <string.h>

void main()
{
char str[80];
FILE *fp;

fp = fopen("arquivo.txt","w+");
if(!fp)
{
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

do{
printf("Entre com string (tecle ENTER para sair):\n");
gets(str);
strcat(str, "\n");
fputs(str, fp);
}while(*str!='\n');

rewind(fp);
system("cls");
while(!feof(fp))
{
fgets(str, 79, fp);
printf(str);
}

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
65
Funo: remove()

Para apagar um arquivo basta utilizar o seguinte cdigo:

remove(fp);

Ele devolve zero caso seja bem-sucedido e um valor diferente de zero caso
contrrio.

Funo: fflush()

A funo fflush() utilizada para esvaziar o contedo de uma stream de sada.
Para utilizar esta funo utilize o seguinte cdigo:

fflush(fp);

Essa funo escreve o contedo de qualquer dado existente no buffer arquivo
associado a fp. Se fflush() for chamada com um valor nulo, todos os arquivos abertos
para sada so descarregados. Esta funo devolve 0 para indicar sucesso; caso
contrrio, devolve EOF.

Funes: fread() e fwrite()

O sistema de arquivo ANSI C fornece duas funes para leitura e escrita de
blocos de qualquer tipo de dado, elas so fread() e fwrite(). Seus prottipos so:

size_t fread(void *buffer, size_t num_bytes, size_t count, FILE*fp);
size_t fwrite(const void *buffer, size_t num_bytes, size_t count, FILE *fp);

Para fread(), buffer um ponteiro para uma regio de memria que receber os
dados do arquivo. Para fwrite(), buffer um ponteiro para as informaes que sero
escritas no arquivos. O nmero de bytes a ler ou escrever especificado por num_bytes.
O argumento count determina quantos itens (cada um de comprimento num_byte) sero
lidos ou escritos. Finalmente, fp um ponteiro para uma stream aberta anteriormente.

A funo fread() devolve o nmero de itens lidos. Esse valor pode ser menor
que count se o final do arquivo for atingido, ou ocorrer um erro. A funo fwrite()
devolve o nmero de itens escritos. Esse valor ser igual a count a menos que ocorra um
erro.

Aparentemente, fread() e fwrite() denotam certa complexidade, mas com a
prtica notar suas vantagens e que apenas questo aparncia, sendo elas funes
extremamente importantes e largamente utilizadas j que seu tempo de leitura e escrita
em um arquivo so menores comparados a outras funes.

Veja o exemplo abaixo, o programa grava em um arquivo binrio usando
fwrite() e logo depois o l utilizando fread():



Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
66




























Pegamos uma linha de cdigo para discusso:

fwrite(&i, sizeof(int), 1, fp);

Isso quer dizer que ser gravado uma vez (pois count 1) a informao contida
na varivel i, que possui o tamanho de um arquivo do tipo int, no arquivo fp.
Sabemos que int possui 2 bytes de tamanho, ento o seguinte cdigo seria
perfeitamente aceitvel:

fwrite(&i, 2, 1, fp);

Note tambm que nosso arquivo binrio, portanto ele foi nomeado com a
extenso .bin, assim como texto .txt.

O programa anterior perfeitamente vlido, ele grava cada dado
individualmente, mas a vantagem do fwrite() e fread() se concentra especialmente em
gravar um bloco de dados contendo vrios bytes com apenas uma linha de cdigo. Veja
o exemplo abaixo, onde feito o cadastro de um usurio utilizando uma estrutura,
escrevendo e lendo seus dados a partir de um arquivo:




#include <conio.h>
#include <stdio.h>

void main()
{
int i = 10;
float f = 21.45;
char ch = 'a';
long l = 8089514;
FILE *fp;

fp = fopen("arquivo.bin","wb+");
if(!fp)
{
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

fwrite(&i, sizeof(int), 1, fp);
fwrite(&f, sizeof(float), 1, fp);
fwrite(&ch, sizeof(char), 1, fp);
fwrite(&l, sizeof(long), 1, fp);

rewind(fp);
fread(&i, sizeof(int), 1, fp);
fread(&f, sizeof(float), 1, fp);
fread(&ch, sizeof(char), 1, fp);
fread(&l, sizeof(long), 1, fp);

printf("%d\n %f\n %c\n %d", i, f, ch, l);

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
67


















































#include <conio.h>
#include <stdio.h>

struct usuario{
char nome[80];
int idade;
float peso;
float altura;
char endereco[81];
char telefone[20];
} var;

void main()
{
FILE *fp;

fp = fopen("arquivo.bin","wb+");
if(!fp){
printf("Erro na abertura do arquivo");
_getch();
exit(1);
}

printf("Nome: ");
gets(var.nome);
printf("\nEndereco: ");
gets(var.endereco);
printf("\nTelefone: ");
gets(var.telefone);
printf("\nIdade: ");
scanf("%d", &var.idade);
printf("\nPeso: ");
scanf("%f", &var.peso);
printf("\nAltura: ");
scanf("%f", &var.altura);

if(fwrite(&var, sizeof(struct usuario), 1, fp)!=1){
printf("Erro na gravacao do arquivo");
_getch();
exit(1);
}

rewind(fp);
if(fread(&var, sizeof(struct usuario), 1, fp)!=1){
printf("Erro na leitura do arquivo");
_getch();
exit(1);
}

system("cls");
printf("Informacoes do Usuario");
printf("\n\nNome: ");
printf("%s", var.nome);
printf("\nEndereco: ");
printf("%s", var.endereco);
printf("\nTelefone: ");
printf("%s", var.telefone);
printf("\nIdade: ");
printf("%d", var.idade);
printf("\nPeso: ");
printf("%f", var.peso);
printf("\nAltura: ");
printf("%f", var.altura);

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
68
O cdigo acima um bom exemplo de como o fwrite() e o fread() so
utilizados, com apenas um fwrite() pode-se escrever no arquivo todo um bloco de
dados, que neste caso a estrutura struct usuario. Analgamente, com apenas um
fread() pode-se ler todo um bloco de dados.

importante fazer uma verificao de erro sempre que escrever ou ler um
arquivo, pois deixa seu programa menos suscetvel a bugs, e se houver realmente um
erro, a identificao deste se torna mais fcil. A verificao de erro exemplificada no
cdigo acima, utilizando o seguinte comando:

if(fwrite(&var, sizeof(struct usuario), 1, fp)!=1){ bloco }

Para entender este comando, lembremos que fwrite() retorna a quantidade de
itens escritos, como o count foi definido com 1, fwrite() dever retornar 1 se for bem-
sucedida a escrita no arquivo. Mas se for diferente de 1, o bloco ser executado e o
programa ser encerrado. Esta lgica anloga ao fread().

Funo: fseek()

A funo fseek() move o indicador de posio de arquivo para um local
especfico definido pelo programador. Seu prottipo :

int fseek(FILE *fp, long numbytes, int origin);

Aqui, fp um ponteiro de arquivo devolvido por uma chamada fopen().
numbytes, um inteiro longo, o numero de bytes a partir de origin, que ser tornar a
nova posio corrente.

Origin Nome da Macro
Incio do arquivo SEEK_SET
Posio atual SEEK_CUR
Final do arquivo SEEK_END

Portanto, para se mover numbytes a partir do incio do arquivo, origin deve
SEEK_SET. Para se mover da posio atual, deve-se utilizar SEEK_CUR e para se
mover a partir do final do arquivo, deve-se utilizar SEEK_END. A funo fseek()
devolve 0 quando vem-sucedida e um valor diferente de zero se ocorrer um erro.

Imaginemos o exemplo da seo anterior, onde feito o cadastro de usurios.
Imaginemos que tenhamos um arquivo com 10 usurios cadastrados e queremos ler a
informao do dcimo, portanto podemos o utilizar o seguinte comando para pular os 9
primeiros usurios e colocarmos o indicador de posio corrente onde desejamos:

fseek(fp, 9*sizeof(struct usuario), SEEK_SET);

Com isso podemos perceber que possvel efetuar movimentaes em mltiplos
de qualquer tipo de dado simplesmente multiplicando o tamanho dos dados pelo nmero
do item que deseja ser alcanado.


Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
69
Funes: fprintf() e fscanf()

O sistema E/S em C inclui duas funes para leitura e escrita em arquivos, elas
so fprintf() e fscanf(). Elas se comportam exatamente como printf() e scanf() exceto
por operarem com arquivos. Os seus prottipos so

int fprintf(FILE *fp, const char *control_string,);
int fscanf(FILE *fp, const char *control_string,);

onde fp um ponteiro de arquivo devolvido por uma chamada fopen(). fprintf() e
fscanf() direcionam suas operaes de E/S para o arquivo apontado por fp.

Veja o exemplo abaixo, o programa l uma string do teclado e os escreve no
arquivo, logo em seguida l do arquivo e imprime na tela:


























Embora as funes fprintf() e fscanf() geralmente sejam a maneira mais fcil de
escrever e ler dados diversos em arquivos em disco, elas no so sempre a escolha mais
apropriada. Como os dados so escritos em ASCII e formatados como apareceriam na
tela (e no em binrio), um tempo extra perdido a cada chamada. Assim, se h
preocupao com velocidade ou tamanho do arquivo deve-se utilizar fread() e fwrite().





#include <conio.h>
#include <stdio.h>

void main()
{
char string[80];
FILE *fp;

fp = fopen("arquivo.txt","w+");
if(!fp)
{
printf("Erro na abertura do
arquivo");
_getch();
exit(1);
}

printf("Entre com uma string: ");
fscanf(stdin, "%s", string);
fprintf(fp, "%s", string);

rewind(fp);
fscanf(fp, "%s", string);
fprintf(stdout, "%s", string);

fclose(fp);
_getch();
}
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
70
Captulo 10 Interface Grfica com OpenGL
O objetivo desta aula aprender a utilizar a biblioteca OpenGL. Para isto, sero
utilizadas as bibliotecas OpenGL, GLU e GLUT, de maneira que o programa fique
portvel e possa ser executado tanto no ambiente Windows como no ambiente Linux.
Para implementao de aplicaes OpenGL na linguagem de programao C/C++
necessrio criar um projeto para linkar as bibliotecas.

A maior vantagem na sua utilizao a rapidez. OpenGL no uma linguagem de
programao, uma poderosa e sofisticada API (Application Programming Interface)
para criao de aplicaes grficas 2D e 3D.

A API inclui aproximadamente 250 comandos e funes.
No existe um formato de arquivo OpenGL para modelos ou ambientes virtuais.
OpenGL fornece um pequeno conjunto de primitivas grficas para construo de
modelos, tais como pontos, linhas e polgonos.

Caractersticas Principais
Projetada para aplicaes grficas interativas 2D e 3D
Derivada de GL (Graphics Library SGI)
Permite criar programas interativos que produzem imagens coloridas de
objetos em movimento
Independente do sistema operacional
Aspectos Tcnicos
As primitivas so vrtices e imagens
No gerencia eventos de controle (mouse, exibio, teclado, etc)
Tipos de Dados
Tipo de dado
OpenGL
Representao
interna
Tipo de dado C
equivalente
Sufixo
GLbyte 8-bit integer signed char b
GLshort 16-bit integer short s
GLint, GLsizei 32-bit integer int ou long i
GLfloat, GLclampf 32-bit floating-point float f
GLdouble,
GLclampd
64-bit floating-point double d
GLU (Graphics Utility Library)
Conjunto de rotinas utilizadas freqentemente
Construdas a partir de comandos OpenGL
Rotinas para:
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
71
Manipulao de projees
Desenho de superfcies qudricas
Curvas e superfcies NURBS (representaes geomtricas complexas
Spline)
Manipulao de superfcies poligonais

Convenes para os Nomes das Funes
<PrefixoBiblioteca><ComandoRaiz><ContadorArgumentosOpcional>
<TipoArgumentosOpcional>
Bibliotecas
GL OpenGL: Contm as funes padres do OpenGl, definidas pelo OpenGL
Architeture Review Board.
GLU - OpenGL Utility Library: contm vrias rotinas que utilizam os
comandos OpenGL de baixo nvel para executar tarefas como, por exemplo,
definir as matrizes para projeo e orientao da visualizao, e fazer o
rendering de uma superfcie. Esta biblioteca fornecida como parte de cada
implementao de OpenGL, e suas funes usam o prefixo glu.
GLUT - OpenGL Utility Toolkit: um toolkit independente de plataforma, que
inclui alguns elementos GUI (Graphical User Interface), tais como menus pop-
up e suporte para joystick. Esta biblioteca, escrita por Mark Kilgard, no
domnio pblico, mas free. O seu principal objetivo esconder a complexidade
das APIs dos diferentes sistemas de janelas. O seu principal objetivo esconder
a complexidade das APIs dos diferentes sistemas de janelas. As funes desta
biblioteca usam o prefixo glut. interessante comentar que a GLUT substitiu a
GLAUX, uma biblioteca auxiliar OpenGL que havia sido criada para facilitar o
aprendizado e a elaborao de programas OpenGL independente do ambiente de
programao (Linux, Windows, etc.).
GLAUX OpenGL Auxiliar Contm os comandos da chamada auxiliar.
Permitem desenvolver aplicaes simples, independente de plataforma e
sistema operacional.
GLX - OpenGL Extension to the X Window System: fornecido como um
"anexo" de OpenGL para mquinas que usam o X Window System. Funes
GLX usam o prefixo glX. Para Microsoft Windows 95/98/NT, as funes WGL
fornecem as janelas para a interface OpenGL. Todas as funes WGL usam o
prefixo wgl. Para IBM/OS2, a PGL a Presentation Manager para a interface
OpenGL, e suas funes usam o prefixo pgl. Para Apple, a AGL a interface
para sistemas que suportam OpenGL, e as funes AGL usam o prefixo agl.
FSG - Fahrenheit Scene Graph: um toolkit orientado objetos e baseado em
OpenGL, que fornece objetos e mtodos para a criao de aplicaes grficas
3D interativas. FSG, que foi escrito em C++ e separado de OpenGL, fornece
componentes de alto nvel para criao e edio de cenas 3D, e a habilidade de
trocar dados em outros formatos grficos.

Primeiro Programa
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
72
Estrutura geral de um Programa OpenGL
Podemos imaginar um programa OpenGL como dividido em vrias sees. Cada seo
representada por um conjunto de funes, invocadas ou do programa principal ou de
outra seo.
#include <gl/glut.h>
// Funo callback chamada para fazer o desenho
void Desenha(void)
{
//Limpa a janela de visualizao com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);
//Executa os comandos OpenGL
glFlush();
}

// Inicializa parmetros de rendering
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutCreateWindow("Primeiro Programa");
glutDisplayFunc(Desenha);
Inicializa();
glutMainLoop();
}


O Cdigo acima vai gerar esta janela.

Agora vamos explicar passo a passo cada comando utilizado.

glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
73

Avisa a GLUT que tipo de modo de exibio deve ser usado quando a janela criada.
Neste caso os argumentos indicam a criao de uma janela single-buffered
(GLUT_SINGLE) com o modo de cores RGBA (GLUT_RGB).
O primeiro significa que todos os comandos de desenho so feitos na janela de
exibio.

glutCreateWindow("Primeiro Programa");

o comando da biblioteca GLUT que cria a janela. Neste caso, criada uma janela
com o nome "Primeiro Programa". Este argumento corresponde a legenda para a
barra de ttulo da janela.

glutDisplayFunc(Desenha);

Estabelece a funo "Desenha" previamente definida como a funo callback de
exibio. Isto significa que a GLUT chama a funo sempre que a janela precisar ser
redesenhada. Esta chamada ocorre, por exemplo, quando a janela redimensionada ou
encoberta;

glClearColor(0.0f, 0.0f, 1.0f, 1.0f);

a funo que determina a cor utilizada para limpar a janela. Seu prottipo : void
glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alfa);.
GLclampf definido como um float na maioria das implementaes de OpenGL. O
intervalo para cada componente red, green, blue de 0 a 1. O componente alfa usado
para efeitos especiais, tal como transparncia.

glClear(GL_COLOR_BUFFER_BIT);

"Limpa" um buffer particular ou combinaes de buffers, onde buffer uma rea de
armazenamento para informaes da imagem. Os componentes RGB so geralmente
referenciados como color buffer ou pixel buffer. Existem vrios tipos de buffer, mas por
enquanto s necessrio entender que o color buffer onde a imagem armazenada
internamente e limpar o buffer com glClear remove o desenho da janela.

glFlush();

Faz com que qualquer comando OpenGL no executado seja executado. Neste primeiro
exemplo tem apenas a funo glClear.

Segundo Programa

Antes de entrar no exemplo 2 vamos conhecer mais algumas funes que possibilitaram
o desenho no OpenGL.

Linhas, Pontos e Polgonos

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
74
Com apenas algumas primitivas simples, tais como pontos, linhas e polgonos,
possvel criar estruturas complexas. Em outras palavras, objetos e cenas criadas com
OpenGL consistem em simples primitivas grficas que podem ser combinadas de vrias
maneiras.

Trs Pontos

glBegin(GL_POINTS);
glColor3f(0.0f, 0.0f, 0.0f);
glVertex2i(100, 50);
glVertex2i(100, 130);
glVertex2i(150, 130);
glEnd();


Para desenhar outras primitivas, basta trocar GL_POINTS, que exibe um ponto para
cada chamada ao comando glVertex, por:

GL_LINES: exibe uma linha a cada dois comandos glVertex;
GL_LINE_STRIP: exibe uma seqncia de linhas conectando os pontos
definidos por glVertex;
GL_LINE_LOOP: exibe uma seqncia de linhas conectando os pontos
definidos por glVertex e ao final liga o primeiro como ltimo ponto;
GL_POLYGON: exibe um polgono convexo preenchido, definido por uma
seqncia de chamadas a glVertex;
GL_TRIANGLES: exibe um tringulo preenchido a cada trs pontos definidos
por glVertex;
GL_TRIANGLE_STRIP: exibe uma seqncia de tringulos baseados no trio
de vrtices v0, v1, v2, depois, v2, v1, v3, depois, v2, v3, v4 e assim por diante;
GL_TRIANGLE_FAN: exibe uma seqncia de tringulos conectados
baseados no trio de vrtices v0, v1, v2, depois, v0, v2, v3, depois, v0, v3, v4 e
assim por diante;
GL_QUADS: exibe um quadrado preenchido conectando cada quatro pontos
definidos por glVertex;
GL_QUAD_STRIP: exibe uma seqncia de quadrilteros conectados a cada
quatro vrtices; primeiro v0, v1, v3, v2, depois, v2, v3, v5, v4, depois, v4, v5, v7,
v6, e assim por diante
Funo que desenha um Quadrado



void Desenha(void)
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
75
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0f, 0.0f, 0.0f);
glTranslatef(-100.0f, -30.0f, 0.0f);
glScalef(1.5f, 0.5f, 1.0f);
glBegin(GL_QUADS);
glVertex2i(100,150);
glVertex2i(100,100); // Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(150,100);
glVertex2i(150,150);
glEnd();
glFlush();
}

Agora sim vamos Fazer nosso Segundo Programa

#include <windows.h>
#include "glut/glut.h"

// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualizao com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);

// Especifica que a cor corrente vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(100,150);
glVertex2i(100,100);
// Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(150,100);
glVertex2i(150,150);
glEnd();

// Executa os comandos OpenGL
glFlush();
}

// Inicializa parmetros de rendering
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
76
void Inicializa (void)
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleo (left, right, bottom, top)
if (w <= h)
gluOrtho2D (0.0f, 250.0f, 0.0f, 250.0f*h/w);
else
gluOrtho2D (0.0f, 250.0f*w/h, 0.0f, 250.0f);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Quadrado");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
Inicializa();
glutMainLoop();
}

Novamente vamos explicar os novos comandos que surgiram em nosso Segundo
Exemplo

glutInitWindowSize(400,350);

Especifica o tamanho em pixels da janela GLUT.

glutInitWindowPosition(10,10);
Especifica a localizao inicial da janela GLUT, que neste caso o canto superior
esquerdo da tela do computador.

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
77
glutReshapeFunc(AlteraTamanhoJanela);

Estabelece a funo "AlteraTamanhoJanela" previamente definida como a funo
callback de alterao do tamanho da janela. Isto , sempre que a janela maximizada,
minimizada, etc., a funo "AlteraTamanhoJanela" executada para reinicializar o
sistema de coordenadas.

glColor3f(1.0f, 0.0f, 0.0f);

Determina a cor que ser usada para o desenho (linhas e preenchimento). A seleo da
cor feita da mesma maneira que na funo glClearColor, sendo que no necessrio
especificar o componente alfa, cujo valor default 1.0 (completamente opaco).

glBegin(GL_QUADS); glEnd();

Usada para desenhar um quadrado preenchido a partir dos vrtices especificados entre
glBegin e glEnd. OpenGL mapeia as coordenadas dos vrtices para a posio atual da
janela de visualizao na funo callback AlteraTamanhoJanela.

glViewport(0, 0, w, h);

Recebe como parmetro a nova largura e altura da janela. O prottipo desta funo :
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);. Seus parmetros
especificam o canto inferior esquerdo da viewport (x,y) dentro da janela, e a sua
largura e altura em pixels (width e height). Geralmente x e y so zero, mas possvel
usar a viewport para visualizar mais de uma cena em diferentes reas da janela.

gluOrtho2D (0.0f, 250.0f*w/h, 0.0f, 250.0f);

usada para determinar que a projeo ortogrfica (2D) ser utilizada para exibir na
tela a imagem 2D que est na janela de seleo definida atravs dos parmetros
passados para esta funo. O prottipo desta funo : void gluOrtho2D(GLdouble left,
GLdouble right, GLdouble bottom, GLdouble top);. No sistema de coordenadas
cartesianas, os valores left e right especificam os limites mnimo e mximo no eixo X;
analogamente, bottom e top especificam os limites mnimo e mximo no eixo Y.

glMatrixMode(GL_PROJECTION); e glLoadIdentity();

Servem, respectivamente, para avisar a OpenGL que todas as futuras alteraes, tais
como operaes de escala, rotao e translao, iro afetar a "cmera" (ou
observador), e para inicializar o sistema de coordenadas antes da execuo de
qualquer operao de manipulao de matrizes. Sem este comando, cada chamada
sucessiva de gluOrtho2D poderia resultar em uma corrupo do volume de
visualizao. Em outras palavras, a matriz de projeo onde o volume de
visualizao, que neste caso um plano, definido;



Exerccio construa a casinha mostrada na janela abaixo.

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
78


Agora que j temos uma boa noo sobre desenho hora de aprender a animar.

Animao com OpenGL e GLUT

Um quadrado numa janela com fundo preto. Agora, o quadrado ser movido numa
direo at bater em uma das bordas da janela e ento mudar de direo.
possvel criar um lao que continuamente altera as coordenadas do objeto antes de
chamar a funo "Desenha". Isto daria a impresso de que o quadrado se move na
janela.
O cdigo do Terceiro Programa exibido a seguir:

#include <windows.h>
#include <gl/glut.h>

// Tamanho e posio inicial do quadrado
GLfloat x1 = 100.0f;
GLfloat y1 = 150.0f;
GLsizei rsize = 50;

// Tamanho do incremento nas direes x e y
// (nmero de pixels para se mover a cada
// intervalo de tempo)
GLfloat xstep = 1.0f;
GLfloat ystep = 1.0f;

// Largura e altura da janela
GLfloat windowWidth;
GLfloat windowHeight;


// Funo callback chamada para fazer o desenho
void Desenha(void)
{
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// Limpa a janela de visualizao com a cor de fundo especificada
glClear(GL_COLOR_BUFFER_BIT);
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
79

// Especifica que a cor corrente vermelha
// R G B
glColor3f(1.0f, 0.0f, 0.0f);

// Desenha um quadrado preenchido com a cor corrente
glBegin(GL_QUADS);
glVertex2i(x1,y1+rsize);
glVertex2i(x1,y1);
// Especifica que a cor corrente azul
glColor3f(0.0f, 0.0f, 1.0f);
glVertex2i(x1+rsize,y1);
glVertex2i(x1+rsize,y1+rsize);
glEnd();

// Executa os comandos OpenGL
glutSwapBuffers();
}

// Funo callback chamada pela GLUT a cada intervalo de tempo
// (a window no est sendo redimensionada ou movida)
void Timer(int value)
{
// Muda a direo quando chega na borda esquerda ou direita
if(x1 > windowWidth-rsize || x1 < 0)
xstep = -xstep;

// Muda a direo quando chega na borda superior ou inferior
if(y1 > windowHeight-rsize || y1 < 0)
ystep = -ystep;

// Verifica as bordas. Se a window for menor e o
// quadrado sair do volume de visualizao
if(x1 > windowWidth-rsize)
x1 = windowWidth-rsize-1;

if(y1 > windowHeight-rsize)
y1 = windowHeight-rsize-1;

// Move o quadrado
x1 += xstep;
y1 += ystep;

// Redesenha o quadrado com as novas coordenadas
glutPostRedisplay();
glutTimerFunc(33,Timer, 1);
}

// Inicializa parmetros de rendering
void Inicializa (void)
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
80
{
// Define a cor de fundo da janela de visualizao como preta
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

// Funo callback chamada quando o tamanho da janela alterado
void AlteraTamanhoJanela(GLsizei w, GLsizei h)
{
// Evita a divisao por zero
if(h == 0) h = 1;

// Especifica as dimenses da Viewport
glViewport(0, 0, w, h);

// Inicializa o sistema de coordenadas
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

// Estabelece a janela de seleo (left, right, bottom, top)
if (w <= h) {
windowHeight = 250.0f*h/w;
windowWidth = 250.0f;
}
else {
windowWidth = 250.0f*w/h;
windowHeight = 250.0f;
}

gluOrtho2D(0.0f, windowWidth, 0.0f, windowHeight);
}

// Programa Principal
int main(void)
{
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(400,350);
glutInitWindowPosition(10,10);
glutCreateWindow("Anima");
glutDisplayFunc(Desenha);
glutReshapeFunc(AlteraTamanhoJanela);
glutTimerFunc(33, Timer, 1);
Inicializa();
glutMainLoop();
}

Novamente vamos explicar os novos comandos OpenGL do
exemplo apresentado.
glutTimerFunc(33, Timer, 1);

Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
81
Estabelece a funo Timer previamente definida como a funo callback de animao.
Seu prottipo : void glutTimerFunc(unsigned int msecs, void (*func)(int value), int
value);. Esta funo faz a GLUT esperar msecs milisegundos antes de chamar a funo
func. possvel passar um valor definido pelo usurio no parmetro value. Como esta
funo "disparada" apenas uma vez, para se ter uma animao contnua necessrio
reinicializar o timer novamente na funo Timer.

void Timer(int value )

a funo chamada pela glutTimerFunc. No exemplo, as variveis utilizadas para
determinar a posio do retngulo so atualizadas nesta funo.

glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB),

Foi usada para trocar o modo de exibio de GLUT_SINGLE para GLUT_DOUBLE.
Isto faz com que todo o rendering seja feito em um offscreen buffer.

glutSwapBuffers();

usada no lugar da glFlush porque quando feita a troca (ou swap) de buffers,
realizada implicitamente uma operao de flush. Esta funo continua fazendo o flush
mesmo que o programa esteja sendo executado no modo single-buffer, porm com uma
qualidade bastante inferior.

Gerenciamento de Eventos (teclado e mouse)

A biblioteca GLUT tambm contm funes para gerenciar eventos de entrada de
teclado e mouse.

glutKeyboardFunc();

Estabelece a funo callback que chamada pela GLUT cada vez que uma tecla que
gera cdigo ASCII pressionada (por exemplo: a, b, A, b, 1, 2). Alm do valor ASCII
da tecla, a posio (x,y) do mouse quando a tecla foi pressionada tambm retornada.
Parmetros de entrada da funo callback: (unsigned char key, int x, int y).

glutSpecialFunc();

Estabelece a funo callback que chamada pela GLUT cada vez que uma tecla que
gera cdigo no-ASCII pressionada, tais como Home, End, PgUp, PgDn, F1 e F2.
Alm da constante que identifica a tecla, a posio corrente (x,y) do mouse quando a
tecla foi pressionada tambm retornada. Parmetros de entrada da funo callback:

(unsigned char key, int x, int y)

GLUT_KEY_F1, GLUT_KEY_F2, GLUT_KEY_F3, GLUT_KEY_F4, GLUT_KEY_F5,
GLUT_KEY_F6, GLUT_KEY_F7, GLUT_KEY_F8, GLUT_KEY_F9, GLUT_KEY_F10,
GLUT_KEY_F11, GLUT_KEY_F12, GLUT_KEY_LEFT, GLUT_KEY_UP,
GLUT_KEY_RIGHT, GLUT_KEY_DOWN, GLUT_KEY_PAGE_UP,
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
82
GLUT_KEY_PAGE_DOWN, GLUT_KEY_HOME, GLUT_KEY_END,
GLUT_KEY_INSERT.

glutMouseFunc

Estabelece a funo callback que chamada pela GLUT cada vez que ocorre um
evento de mouse. Parmetros de entrada da funo callback: (int button, int state, int
x, int y). Trs valores so vlidos para o parmetro button: GLUT_LEFT_BUTTON,
GLUT_MIDDLE_BUTTON e GLUT_RIGHT_BUTTON. O parmetro state pode ser
GLUT_UP ou GLUT_DOWN. Os parmetros x e y indicam a localizao do mouse no
momento que o evento ocorreu.

Utilizando Menus e Exibindo Caracteres

A biblioteca GLUT tambm contm funes para gerenciar menus, exibir caracteres e
verificar a posio do mouse na janela em qualquer instante. As funes para realizar
estas tarefas esto descritas a seguir.

glutBitmapCharacter

Uma das fontes suportadas pela GLUT a bitmap, onde cada caracter corresponde a
um bitmap que gerado com a funo glBitmap. A funo glutBitmapCharacter exibe
um caractere deste tipo usando OpenGL. Os parmetros de entrada desta funo so:

(void *font, int character)

O primeiro parmetro identifica a fonte que ser utilizada, e o segundo o caractere. As
fontes disponveis so:

GLUT_BITMAP_8_BY_13,
GLUT_BITMAP_9_BY_15,
GLUT_BITMAP_TIMES_ROMAN_10,
GLUT_BITMAP_TIMES_ROMAN_24,
GLUT_BITMAP_HELVETICA_10,
GLUT_BITMAP_HELVETICA_12,
GLUT_BITMAP_HELVETICA_18

glutMotionFunc

Estabelece a funo callback que chamada pela GLUT cada vez que o mouse
movido sobre a janela corrente enquanto um ou mais de seus botes esto
pressionados. Parmetros de entrada da funo callback: (int x, int y). Os parmetros
x e y indicam a posio do mouse em coordenadas da janela.

glutPassiveMotionFunc

Estabelece a funo callback que chamada pela GLUT cada vez que o mouse
movido sobre a janela corrente enquanto nenhum de seus botes est pressionado.
Parmetros de entrada da funo callback: (int x, int y). Os parmetros x e y indicam a
posio do mouse em coordenadas da janela.
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
83

glutCreateMenu

Cria um novo menu pop-up e estabelece a funo callback que ser chamada pela
GLUT quando uma de suas entradas for selecionada. Parmetros de entrada da funo
callback: (int value), onde value corresponde ao valor que identifica a entrada do
menu que foi selecionada.

glutAddMenuEntry

Adiciona uma entrada no final do menu corrente. Os parmetros de entrada desta
funo so: (char *name, int value), onde name o conjunto de caracteres que ser
exibido como uma entrada do menu, e value o valor que ser passado para a funo
callback caso esta entrada seja selecionada.

glutAddSubMenu

Adiciona um submenu no final do menu corrente. Os parmetros de entrada desta
funo so: (char *name, int menu), onde name o conjunto de caracteres que ser
exibido como uma entrada do menu, a partir da qual ser aberto o submenu, e menu o
identificador do submenu.

glutAttachMenu

Funo que "relaciona" um boto do mouse com o identificador do menu corrente. O
parmetro de entrada desta funo (int button), que corresponde ao identificador do
boto do mouse (GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON ou
GLUT_RIGHT_BUTTON)

Exerccio
Aplique uma transformao geomtrica de translao na casinha para mud-la de lugar
(importante: a translao, bem como as transformaes de escala e rotao, deve ser
aplicada antes que a casinha seja desenhada);

Como fazer para interagir com o programa sem que seja necessrio compilar o cdigo
cada vez que o objeto, por exemplo, trocado de lugar? Neste caso, utiliza-se uma
Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
84
funo callback para gerenciar eventos do teclado e/ou mouse. Assim como j feito
com a callback que gerencia eventos do teclado "padro", vamos registrar uma uno
callback para gerenciar eventos das teclas especiais acrestando a seguinte linha de
cdigo na funo main, antes da chamada para a funo Inicializa():
glutSpecialFunc(TeclasEspeciais);
Em seguida, declare as seguintes variveis globais, logo aps os includes, utilizando um
tipo de dado OpenGL:
GLint tx, ty;
Inicialize estas variveis na funo Inicializa() com os seguintes valores:
tx = 0;
ty = 0;
Agora altere os parmetros passados para a funo glTranslatef que chamada na
funo Desenha, para que sejam passadas estas variveis, da seguinte maneira:
glTranslatef(tx, ty, 0);
Finalmente, para fazer o tratamento dos eventos, inclua e termine de implementar a
funo callback TeclasEspeciais descrita abaixo. Complete cdigo desta funo de
maneira a permitir transladar o objeto para cima, para baixo, para a esquerda e para a
direita sempre que o usurio pressionar cada uma das teclas de setas (incremente e
decremente as variveis tx e ty)
void TeclasEspeciais(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
break;
case GLUT_KEY_DOWN:
break;
case GLUT_KEY_LEFT:
break;
case GLUT_KEY_RIGHT:
break;
}
glutPostRedisplay();
}














Universidade Federal De Uberlndia
Faculdade de Engenharia Eltrica e Biomdica
85

You might also like