Académique Documents
Professionnel Documents
Culture Documents
Curso de Linguagem C
Sumrio
Pgina
01
01
02
02
03
05
05
05
06
06
08
08
08
09
09
10
10
11
11
11
12
12
12
12
13
13
13
14
14
14
15
15
16
17
20
20
21
21
22
23
23
24
25
26
26
27
27
28
29
29
30
31
31
32
33
33
37
37
37
38
38
38
39
39
39
39
40
40
40
41
41
41
42
42
42
42
43
43
43
43
44
45
45
45
45
46
50
50
51
51
52
53
53
54
55
55
56
56
57
58
59
60
61
61
63
64
68
68
68
68
69
69
70
70
71
71
72
72
72
73
73
73
74
74
Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
7.2 Determinando o Endereo de uma Varivel
7.3 Como a Linguagem C trata Matrizes como Ponteiros
7.4 Aplicando o Operador de Endereo (&) a uma Matriz
7.5 Declarando Variveis Ponteiros
7.6 Desreferenciando um Ponteiro
7.7 Usando Valores de Ponteiro
7.8 Ponteiros com Parmetros de Funo
7.9 A Aritmtica de Ponteiros
7.10 Incrementando e Decrementando um Ponteiro
7.11 Percorrendo uma String usando um Ponteiro
7.12 Funes que retornam Ponteiros
7.13 Criando uma Funo que retorna um Ponteiro
7.14 Uma Matriz de Ponteiros
7.15 Percorrendo em um Lao uma Matriz de Strings de Caracteres
7.16 Usando um Ponteiro para um Ponteiro para String de Caracteres
7.17 Declarando uma Constante String usando um Ponteiro
7.18 O Ponteiro do tipo Void
7.19 Ponteiros para as Funes
7.20 Ponteiro para uma Funo
7.21 Usando um Ponteiro para um Ponteiro para um Ponteiro
77
77
77
77
78
78
79
79
79
80
80
81
81
81
82
82
82
83
83
83
84
84
87
8.1 Introduo
8.2 O Ponteiro de Arquivo
8.3 Abrindo um Arquivo Usando FOPEN
8.4 A Estrutura FILE
8.5 Fechando um Arquivo Aberto
8.6 Lendo e Gravando Informaes no Arquivo um Caracter de Cada Vez
8.7 O Ponteiro de Posio do Ponteiro de Arquivo
8.8 Determinando a Posio Atual no Arquivo
8.9 O Significado de Canais de Arquivo
8.10 Lendo Linhas de Textos
8.11 Gravando Linhas de Texto
8.12 Exemplo do Uso das Funes Fgets e Fputs
8.13 As Funes Fread( ) E Fwrite( )
8.14 As Funes Fprintf( ) e Fscanf( )
8.15 Testando o Final do Arquivo
8.16 Posicionamento do Ponteiro de Arquivo com Base em sua Posio
Atual
8.17 Excluindo um Arquivo
87
87
87
89
89
90
90
91
91
92
92
92
93
95
96
97
100
97
100
101
102
102
103
103
104
104
105
105
106
106
109
109
110
110
110
111
112
114
115
116
118
121
Referncias Bibliogrficas
134
121
121
122
123
123
124
124
125
126
Nvel Mdio
VELOCIDADE
Assembler
Macro Assembler
Forth
Nvel Alto
CLAREZA
Fortran
Basic
COBOL
Pascal
Ada
MODULA-2
Assembler
timo
timo
pssimo
timo
BASIC
Pascal
fraco
Bom
Bom
razovel
Clipper
COBOL
pssimo
razovel
timo
pssimo
fraco
fraco
timo
fraco
timo
bom
bom
timo
1.6.1 Comentrios
Os comentrios servem principalmente para documentao do programa e so
ignorados pelo compilador, portanto no iro afetar o programa executvel gerado. Os
comentrio iniciam com o smbolo /* e se estendem at aparecer o smbolo */. Um
comentrio pode aparecer em qualquer lugar no programa onde possa aparecer um espao
em branco e pode se estender por mais de uma linha.
O primeiro caso o mais utilizado. Ele serve para incluir alguns arquivos que
contm declarao das funes da biblioteca padro, entre outras coisas. Estes arquivos,
normalmente, possuem a extenso .h e se encontram em algum diretrio pr-definido pelo
compilador. Sempre que o programa utilizar alguma funo da biblioteca-padro deve ser
includo o arquivo correspondente. A tabela a seguir apresenta alguns dos principais .h da
linguagem C: Descrio
stdio.h - Funes de entrada e sada (I/O)
string.h - Funes de tratamento de strings
double
else
enum
extern
float
for
goto
if
int
long
register
return
short
signed
sizeof
static
struct
switch
typedef
union
unsigned
void
volatile
while
nomes de variveis comeam com uma letra ('A'..'Z', 'a'..'z') ou pelo underscore
Correto
count
test23
high_balance
Incorreto
1count
Ol! Aqui
high..balance
Intervalo
-128 a 127
-32768 a 32767
3,4E-38 a 3,4E+38
1,7E-308 a 1,7E+308
sem valor
Tipo
char
unsigned char
signed char
int
unsigned int
signed int
short int
unsigned short int
signed short int
long int
signed long int
unsigned long int
float
double
long double
Intervalo
-128 a 127
0 a 255
-128 a 127
-32768 a 32767
0 a 65535
-32768 a 32767
-32768 a 32767
0 a 65535
-32768 a 32767
-2147483648 a 2147483647
-2147483648 a 2147483647
0 a 4294967295
3,4E-38 a 3,4E+38
1,7E-308 a 1,7E+308
3,4E-4932 a 1,1E+4932
Exemplos:
Exemplos:
#define PI 3,1415926536
#define SINAL "aberto"
#define MULT A*B
\b
\n
\t
\
\\
\a
\xN
Significado
Retrocesso
Nova linha
Tabulao horizontal
Apstrofo
Barra invertida
Sinal sonoro
Constante hexadecimal
Cdigo
\f
\r
\
\0
\v
\N
Significado
Alimentao de formulrio
Retorno de carro
Aspas
Nulo
Tabulao vertical
Constante octal
2.6 Operadores
A linguagem C muito rica em operadores internos. Um operador um smbolo
que diz ao compilador para realizar manipulaes matemticas e lgicas especficas. A
linguagem C possui trs classes gerais de operadores: aritmticos, relacionais e lgicos e
bit-a-bit.
+
*
Soma
subtrao
multiplicao
Ao
/
%
-
diviso
mdulo da diviso (resto da diviso inteira)
sinal negativo (operador unrio)
Ao
>
>=
<
<=
==
!=
Maior
maior ou igual
Menor
menor ou igual
Igual
no igual (diferente)
Ateno!
No existem os operadores relacionais: =<, => e <>.
No confunda a atribuio (=) com a comparao (==).
Ao
&&
||
!
operao AND
operao OR
operador de negao NOT (operador
unrio)
/*
/*
&
|
^
Ao
bit and
bit or
bit xor - exclusive or
<<
>>
~
Rotao a esquerda
Rotao a direita
bit not (complemento)
var op = expr
->
Ao
+
*
/
%
>>
<<
&
^
|
Soma
Subtrao
Multiplicao
Diviso
mdulo (resto da diviso)
Rotao a direita
Rotao a esquerda
And
xor - exclusive or
Or
Exemplo de aplicao:
i+= 2; /* equivalente a: i = i + 2 */
j-= 3; /* equivalente a: j = j 3 */
k >>= 3; /* equivalente a: k = k >> 3;*/
z &= flag; /* equivalente a: z = z & flag;*/
i = ++i;
i = --i;
z = a++;
z = a--;
z = ++a;
z = --a;
++i;
--i;
&
*
Significado
Exemplos:
int var, *x;
x = &var;
var = *x;
Operador
Funo
menos unrio
mais unrio
negao lgica
bitwise not
endereo de
referncia a ptr
tamanho de var
incremento
decremento
multiplicao
diviso inteira
diviso real
resto da diviso
soma
subtrao
shift right
shift left
maior que
maior ou igual a
menor que
menor ou igual a
igual a
diferente de
bitwise AND
bitwise OR
bitwise XOR
logical AND
logical OR
assinalamento
assinalamento
Exemplo C
a = -b;
a = +b ;
! flag
a = ~b ;
a = &b ;
a = *ptr ;
a = sizeof(b) ;
++a; ou a++;
--a; ou a--;
a = b * c;
a = b / c;
a = b / c;
a = b % c;
a = b + c;
a = b c;
a = b >> n;
a = b << n;
a>b
a >= b
a<b
a <= b
a == b
a != b
a = b & c;
a = b | c;
a = b ^ c;
flag1 && flag2
flag1 || flag2
a = b;
a OP= b;
2.8 Expresses
Operadores, constantes e variveis constituem expresses. Uma expresso em C
qualquer combinao vlida dessas partes. Uma vez que muitas expresses tendem a seguir
as regras gerais da lgebra, estas regras so freqentemente consideradas. Entretanto,
existem alguns aspectos das expresses que esto especificamente relacionadas com a
linguagem C e sero discutidas agora.
O resultado final um double, tendo em vista que, neste caso, os dois operandos so
double.
float.
Mdulo 3 Funes na
Linguagem C
3.1 Funes
A maioria dos programas apresentam a funo main. Quando os programas tornamse maiores e mais complexos, pode-se melhorar a clareza e compreenso do trabalho
dividindo-o em partes menores, chamadas funes. Vamos citar o exemplo de um
determinado programa, suponha um programa de contabilidade. Poderia haver no programa
uma funo que efetuasse as operaes normais de um contador, uma funo diferentes
para contas a pagar, uma terceira para contas a receber e uma quarta para gerar um balano.
Se fossem colocados todos os comandos do programa dentro da funo main, o programa
ficaria muito grande, e seria difcil de compreende-lo. medida que o tamanho e a
complexidade do programa aumentam, aumenta tambm a possibilidade de erros. Se o
programa for dividido em blocos menores e mais facilmente gerenciveis, poder evitar
erros. Uma funo uma coleo nomeada de comandos que efetuam uma tarefa
especfica. Por exemplo, a funo ola_mundo, usa a funo printf para exibir uma
mensagem:
void ola_mundo (void)
{
printf(Ol mundo!\n);
}
Ao executar esse programa, a funo main executada primeiro. Como se pode ver,
o nico comando em main a chamada da funo oi_pessoal. Quando C encontra a
chamada da funo, imediatamente transfere a execuo do programa para a funo,
iniciando a execuo do programa com o primeiro comando da funo. Depois que o
ltimo comando da funo termina, a Linguagem C transfere a execuo para o comando
que segue imediatamente a chamada da funo.
Para compreender melhor esse processo, mude a funo main dentro do programa
anterior como mostrado aqui:
void main(void)
{
printf(Prestes chamar a funo\n);
oi_pessoal();
printf(Voltei da chamada da funo\n);
}
Quando se declara variveis dentro de uma funo, os nomes usados para essas
variveis so exclusivos para a funo.
Portanto, se o programa usa dez funes diferentes e cada funo usa uma varivel
chamada contador, a Linguagem C considera a varivel de cada funo como distinta. Se
uma funo requer muitas variveis, elas devero ser declaradas no incio da funo,
exatamente como se faria dentro de main.
por sua vez, chama a funo oi_pessoal trs vezes para exibir mensagens na tela, como
mostrado aqui:
#include <stdio.h>
void ola_pessoal(void)
{
printf("Ola, pessoal!\n");
}
void tres_olas(void)
{
int contador;
for (contador = 1; contador <= 3; contador++)
ola_pessoal();
}
void main(void)
{
tres_olas();
}
Uma funo mais til permite especificar, como um parmetro, o nmero de vezes
que quer que o programa exiba a mensagem. Para usar um parmetro, a funo precisa
especificar o nome e o tipo do parmetro, como mostrado aqui:
void ola_conta(int msg_conta)
O programa a seguir ilustra como pode usar uma funo com um parmetro:
#include <stdio.h>
void oi_pessoal(void)
{
printf("Ola, pessoal!\n");
}
void ola_conta(int msg_conta)
{
int contador;
for (contador = 1; contador <= msg_conta; contador++)
oi_pessoal();
}
void main(void)
{
printf("Exibe a msg duas vezes\n");
ola_conta(2);
printf("Exibe a msg cinco vezes\n");
ola_conta(5);
}
Quando o programa chamar a funo, ser necessrio especificar valores para cada
parmetro, como mostrado aqui:
uma_funcao(33, 40000.00, 534);
O tipo de valor que a funo retorna (int, float, char, etc.) determina o tipo da
funo. Por exemplo, se uma funo retorna um valor do tipo int, necessrio preceder o
nome da funo com o nome do tipo, como mostrado aqui:
A funo a seguir, retorna o cubo do valor inteiro que o programa especifica como
seu parmetro. Por exemplo, se o chamador passar o valor 5 para a funo, a funo
retornar o valor 5*5*5, ou 125:
int i_cubo(int valor)
{
return (valor *valor *valor);
}
Como visto, a funo usa o comando return para retornar o resultado do clculo ao
chamador. O cdigo dentro da funo de chamada pode atribuir o resultado da funo
chamada (tambm conhecido como valor de retorno) a uma varivel, ou o cdigo pode usar
o valor de retorno dentro de uma terceira funo, tal como printf, como mostrado aqui:
result = i_cubo(5);
printf(O cubo de 5 %d\n, I_cubo(5));
O programa a seguir usa a funo i_cubo para determinar vrios valores diferentes
ao cubo:
#include <stdio.h>
int i_cubo(int valor)
{
return(valor * valor * valor);
}
void main(void)
{
printf("O cubo de 3 %d\n", i_cubo(3));
printf("O cubo de 5 %d\n", i_cubo(5));
printf("O cubo de 7 %d\n", i_cubo(7));
}
Os valores que so passados para uma funo precisam corresponder aos tipos de
parmetros contidos dentro da declarao dessa funo. Por exemplo, se quiser determinar
o cubo de um valor em ponto flutuante, crie uma segunda funo chamada f_cubo, como
mostrado a seguir (observe que o valor de retorno tambm do tipo float):
Significado
Os valores so iguais
O primeiro valor maior que o segundo
O segundo valor maior que o primeiro
Como regra, deve-se tentar limitar as funes a usar somente um comando return.
medida que as funes se tornarem maiores e mais complexas, ter muitos comandos
return normalmente tornar as funes mais difceis de compreender. Na maioria dos
casos, pode-se reescrever a funo para que ela use somente um comando return, como
mostrado aqui:
int compara_valores(int primeiro, int segundo)
{
int result;
if (primeiro == segundo)
return = 0;
else if (primeiro > segundo)
return = 1;
else if (primeiro < segundo)
return = 2;
return(result);
}
Neste caso, como a funo simples, pode-se ter dificuldades em compreender qual
a vantagem de usar um nico comando de return. No entanto, medida que as funes se
tornarem mais complexas, a vantagem ficar mais clara. Pode-se observar que, algumas
vezes, usar mais de um comando return produz um cdigo mais legvel do que a alternativa
de um nico return. Deve-se escrever o cdigo mais legvel e facilmente modificvel
quanto possvel; se usar mltiplos return atingir os objetivos pr-estabelecidos, ento utilize
quantos comandos return forem necessrios.
{
printf("a contm %d b contm %d c contm %d\n", a,b,c);
}
#include <stdio.h>
#include <time.h>
float soma(long int a, float b)
{
float result;
result = a + b;
return(result);
}
void main(void)
{
long int i;
float result = 0;
time_t hora_inicio, hora_parada;
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result += i;
time(&hora_parada);
printf("Usando lao %d segundos\n", hora_parada - hora_inicio);
printf("Trabalhando...\n");
time(&hora_inicio);
for (i = 1; i <= 100000L; i++)
result = soma(i, result);
time(&hora_parada);
printf("Usando funo %d segundos \n", hora_parada hora_inicio);
}
#include <stdio.h>
int a = 1, b = 2, c = 3;
/* Variaveis globais */
void valores_globais(void)
{
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
valores_globais();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
/* Variveis globais */
void conflito_a(void)
{
int a=100;
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
conflito_a();
printf("a contm %d b contm %d c contm %d\n", a, b, c);
}
void main(void)
{
int a = 1, b = 2, c = 3;
exibe_e_altera(a, b, c);
printf("Valores finais em main %d %d %d\n", a,b,c);
}
Como pode ser visto, as alteraes que a funo faz nas variveis somente so
visveis dentro da prpria funo. Quando a funo termina, as variveis dentro de main
esto inalteradas.
Para os programas passarem parmetros para funes cujos valores a funo precisa
alterar, os programas passaro as variveis por referncia (endereo de memria), usando o
operador de endereo, como mostrado a seguir:
alguma_funcao(&a, &b, &c);
Quando quiser usar o valor apontado por uma varivel ponteiro, usa-se o operador
de redireo (*). Quando quiser atribuir o endereo de uma varivel uma varivel
ponteiro, usa-se o operador de endereo (&). O programa a seguir ilustra o uso de uma
varivel ponteiro. Ele atribui varivel ponteiro i_ponteiro o endereo da varivel O
programa ento usa a varivel ponteiro para alterar, exibir e atribuir o valor da varivel:
#include <stdio.h>
void main(void)
{
int a = 1, b = 2;
int *i_ponteiro;
i_ponteiro = &a;
*i_ponteiro = 5;
para 5 */
/* Atribui um endereo*/
/* Altera o valor apontado por i_ponteiro
Como foi visto anteriormente, para alterar o valor de um parmetro dentro de uma
funo, os programas precisam usar a chamada por referncia, passando o endereo da
varivel. Dentro da funo, precisa-se usar ponteiros. O programa a seguir usa ponteiros e
endereos (chamada por referncia) para exibir e, depois, alterar os parmetros que o
programa passa para a funo exibe_e_altera:
#include <stdio.h>
void exibe_e_altera(int *primeiro, int *segundo, int *terceiro)
{
printf("Valores originais da funo %d %d %d\n",*primeiro,
*segundo, *terceiro);
*primeiro += 100;
*segundo += 100;
*terceiro += 100;
printf("Valores finais da funo %d %d %d\n",*primeiro,
*segundo, *terceiro);
}
void main(void)
{
int a=1, b=2, c=3;
exibe_e_altera(&a, &b, &c);
printf("Valores finais em main %d %d %d\n", a, b ,c);
}
Como pode ser visto, a funo muda_primeiro usa a chamada por referncia para
alterar o valor do parmetro primeiro, e chamada por valor para o parmetro segundo.
Quando os programas usam ambas as tcnicas, precisa ter-se em mente quando usar
ponteiros e quando referenciar diretamente a varivel. Como regra, os parmetros cujos
valores sero alterados iro requerer chamada por referncia. Para compreender melhor o
impacto da chamada por referncia versus chamada por valor, modifique a funo
muda_primeiro, como mostrado aqui:
void muda_primeiro(int *primeiro, int segundo)
{
*primeiro = segundo; /*Atribui o valor de segundo a primeiro*/
segundo = 100;
}
Quando este programa for compilado e executado, ver que o valor de primeiro foi
alterado, mas o valor de segundo no foi. Como o parmetro segundo foi passado usando
chamada por valor, a alterao do parmetro visvel fora da funo.
if ((n == 1) || (n == 0))return(1);
resposta = n * fatorial_recursivo(n 1);
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial_recursivo(n);
printf(O fatorial de %d %ld\n, n, f);
}
#include <stdlib.h>
#include <stdio.h>
unsigned long int fatorial (int n){
unsigned long int t, resposta;
resposta = 1;
for (t = 1; t < n; t++) resposta = resposta * t;
return(resposta);
void main()
{
unsigned long f;
int n;
printf(Digite um nmero: );
scanf(%d,&n);
f = fatorial(n);
printf(O fatorial de %d %ld\n, n, f);
}
25 3.2 Variveis dentro das Funes: foi visto que possvel e muito valioso o
uso de variveis dentro das funes. Foi mostrado que as variveis declaradas dentro de
uma funo, so vlidas apenas para aquela funo.
26 3.3 Main como uma Funo: foi visto que quando um programa criado,
usa-se o nome da funo main para determinar o primeiro comando que o programa
executar. A funo main a principal funo em um programa.
27 3.4 Introduo aos Parmetros: foi visto que um parmetro uma valor
passado a uma funo. Com eles a funo se torna mais til ao programa e facilita vria
operaes.
28 3.5 Parmetros Mltiplos: foi mostrado que em geral, pode-se passar um
nmero irrestrito de parmetros para uma funo. Quando a funo usa mais de um
parmetro, precisa especificar o tipo e o nome de cada parmetro e separar os parmetros
por vrgulas.
29 3.6 Retornando um Valor de uma Funo: foi visto que funes usam o
comando return para retornar o resultado do clculo ao chamador. O tipo de valor que a
funo retorna (int, float, char, etc.) determina o tipo da funo. Os valores que so
passados para uma funo precisam corresponder aos tipos de parmetros contidos dentro
da declarao dessa funo.
30 3.7 Comando Return: foi visto que quando a Linguagem C encontra um
comando return em uma funo, ela finaliza imediatamente a execuo da funo e retorna
o valor especificado para o chamador. O programa no executa quaisquer outros comandos
dentro da funo aps o comando return. Em vez disso, ele continua a execuo da funo
chamadora.
31 3.8 Prottipos de Funo: foi explicado que o prottipo de uma funo
especifica os tipos de parmetro e de retorno da funo.
32 3.9 Biblioteca de Execuo: foi explicado que a maioria dos compiladores
fornece centenas de funes de biblioteca de execuo com propsito que vo de abertura e
trabalho com arquivos para acessar informaes do disco ou de diretrio para determinar o
tamanho de uma string de caracteres, poupando horas de trabalho de programao.
33 3.10 Funes que no Retornam Int: foi visto que quando uma determinada
funo no retorna um valor do tipo int (em vez disso ela pode retornar float, double, char,
etc.) precisa-se informar ao compilador o tipo de retorno da funo.
34 3.11 Variveis Locais: foi explicado que variveis so locais, quando seus
nomes e valores somente tm significado dentro da funo que contm a declarao da
varivel.
35 3.12 Sobrecarga da Funo: foi visto que a quantidade de tempo que o
computador requer para colocar e retirar informaes da pilha de sobrecarga da funo.
Este tempo tem um papel fundamental no desempenho dos programas em execuo.
36 3.13 Declarando Variveis Globais: foi visto que variveis globais so
aquelas cujos nomes, valores e existncia so conhecidos em todo o seu programa. Foi visto
tambm como declar-las.
A string de controle contm tanto caracteres para serem impressos na tela como
cdigos de formato que especificam como apresentar o restante dos argumentos. Quando os
programas trabalharem com variveis, ser possvel usar printf() para exibir os valores de
cada varivel. A funo printf() suporta mais de um parmetro. O primeiro parmetro
precisa ser sempre uma string de caracteres. Pode-se fazer os parmetros que seguem a
primeira string de caracteres serem nmeros, expresses, variveis, ou at outras strings de
caracteres. Quando for necessrio que printf() exiba um valor ou uma varivel, preciso
fornecer informaes sobre o tipo da varivel dentro do primeiro parmetro. Alm de
Significado
Exibe um caractere
Exibe um inteiro em formato decimal
Exibe um inteiro
Exibe um nmero em notao cientfica (com e minsculo)
Exibe um nmero em notao cientfica (com E maisculo)
Exibe um ponto flutuante em formato decimal
Usa %e ou %f, o que for menor
O mesmo que %g, s que um E maisculo usado se o formato %e
for escolhido
Exibe um nmero em notao octal
Exibe uma string
Exibe um decimal sem sinal
Exibe um nmero em hexadecimal com letras minsculas
Exibe um nmero em hexadecimal com letras maisculas
Exibe um sinal de %
Exibe um ponteiro
Muitas vezes nos programas preciso exibir um valor inteiro em seu formato octal
(base 8) ou hexadecimal (base 16). O especificador de formato %o (letra "o", no zero)
instrui printf() a exibir uma valor em octal. Da mesma forma, %x e %X instruem printf() a
exibir uma valor em hexadecimal, sendo que no primeiro caso em minsculo e no segundo
imprime os valores em maisculo.
Veja a seguir um exemplo que utiliza estes especificadores de formato:
#include <stdio.h>
void main(void)
{
int valor = 255;
printf("O valor decimal %d em octal %o\n", valor, valor);
printf("O valor decimal %d em hexadecimal %x\n", valor, valor);
printf("O valor decimal %d em hexadecimal %X\n", valor, valor);
}
#include <stdio.h>
void main(void)
{
long int um_milhao = 1000000;
printf ("Um milho %ld\n", um_milhao);
printf ("Um milho %d\n", um_milhao);
}
#include <stdio.h>
void main(void)
{
float preco = 525.75;
float imposto_vendas = 0.06;
printf("O custo do item %f\n", preco);
printf("O imposto sobre a venda do item %f\n", preco *
imposto_vendas);
}
caracteres que printf() requer para exibir o valor corretamente. Veja um exemplo que ilustra
este caso logo a seguir:
#include <stdio.h>
void main(void)
{
int valor = 5;
printf ("%1d\n",
printf ("%2d\n",
printf ("%3d\n",
printf ("%4d\n",
}
valor);
valor);
valor);
valor);
valor);
valor);
valor);
valor);
mnimo de caracteres a serem exibidos. O segundo valor diz a printf() o nmero de dgitos
a serem exibidos direita do ponto decimal. O exemplo abaixo ilustra esta tcnica.
#include <stdio.h>
void main(void)
{
float valor = 1.23456;
printf ("%8.1f\n", valor);
printf ("%8.3f\n", valor);
printf ("%8.5f\n", valor);
}
#include <stdio.h>
void main(void)
{
int int_valor = 5;
printf("Justificado esquerda com sinal %-+3d\n", int_valor);
}
Significado
L um nico caractere
L um decimal inteiro
L um decimal inteiro (no pode ser octal ou hexadecimal)
L um decimal sem sinal
L um nmero em ponto flutuante com sinal opcional
L um nmero em ponto flutuante com ponto opcional
L um nmero em ponto flutuante com expoente opcional (double)
L um nmero em base octal
L uma string
L um nmero em base hexadecimal
L um ponteiro
#include <stdio.h>
void main(void)
{
int a,b;
scanf("%d,%d", &a, &b);
}
Nesse caso, nome j um endereo e no precisa ser precedido pelo operador &.
outro caractere. Por exemplo, com uma entrada de x y; scanf(%c%c%c, &a, &b, &c);
retornar com o caractere x em a, um espao em b e o caractere y em c.
5.1 A Declarao If
A declarao if usada quando necessrio testar em um programa duas ou mais
condies. Isto permite ao programador o desenvolvimento de programas complexos. A
forma geral da declarao if :
if (condio)
{
comandos;
}
else
{
comandos;
}
As expresses condicionais sero avaliadas de cima para baixo. Assim que uma
condio verdadeira encontrada, o bloco associado a ela ser executado, e o resto do
encadeamento ignorado. Se nenhuma das condies for verdadeira, ento o else final ser
executado.
Se o else final no estiver presente e todas as outras condies forem falsas, ento
nenhuma ao ser realizada.
Pode-se usar o encadeamento if-else-if para implementar o programa de converso
de base numrica desenvolvido anteriormente. Na verso original, cada declarao if era
avaliada sucessivamente, mesmo se uma das declaraes anteriores tivesse xito. Ainda que
no haja grande significado neste caso, a avaliao redundante de todos os ifs no muito
eficiente ou elegante. O seguinte programa resolve este problema. Nessa verso de
porque redundante.
if(y).
O else agora est associado ao if(x), j que ele no parte do bloco de cdigo do
printf("%d", conta);
No entanto, se for omitido uma das sees do lao for, precisa-se incluir o ponto-evrgula correspondente. Por exemplo, o lao for a seguir omite as sees de inicializao e
de incremento:
for(; conta < 1000; )
printf("%d", conta++);
Usar as tcnicas de retardo, tais como o lao nulo, poder causar problemas.
Primeiro, se o programa estiver rodando em um computador 286, 386 ou 486, a durao do
retardo diferir simplesmente devido diferena de velocidade entre os diferentes
microprocessadores. Segundo, se o programa estiver rodando em um ambiente multitarefa,
tal como o Windows, OS/2 ou Unix, os laos "no fazem nada" consomem tempo que o
processador poderia estar gastando fazendo trabalho importante em outro programa.
/*causa do erro*/
contagem. Por exemplo, para um programa que exiba o contedo de um arquivo na tela,
ser necessrio que o programa exiba cada linha do arquivo. Na maioria dos casos, no
sabe-se quantas linhas o arquivo contm. Portanto, no se pode usar um lao for para exibir,
por exemplo, 100 linhas. O arquivo poderia conter mais ou menos linhas. Em vez disso,
ser necessrio que o programa leia e exiba linhas at chegar ao final do arquivo. Para fazer
isso, os programas podem usar o lao while, como segue:
while (condio)
comando;
O programa a seguir, usa o lao while para repetir um lao at que seja pressionado
a tecla S ou N em resposta a uma pergunta:
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
void main(void)
{
char letra;
Ao
Inicializa
Testa
Executa
Modifica
Descrio
Inicializa a varivel de controle do lao
Testa a varivel de controle ou a condio do lao
Executa os comando desejados no lao
Modifica o valor da varivel de controle ou efetua uma operao que
afetar a condio que voc est testando
}
}
Ao contrrio dos laos for e while, que testam a condio do lao no incio, o lao
do-while verifica sua condio no final do lao. Isso significa que um lao do-while ser
executado pelo menos uma vez. A forma geral do lao do-while :
do{
comandos;
}while(condio);
Talvez o uso mais comum do lao do-while seja em uma rotina de seleo em
menu. J que sempre ser preciso de uma rotina de seleo em menu para ser executada no
mnimo uma vez, o lao do-while uma opo bvia. O seguinte fragmento mostra como
adicionar um lao do-while no menu do programa de converso numrica.
/* Assegura que o usurio especificou uma opo vlida */
do
{
printf (Converte:\n);
printf ( 1: decimal para hexadecimal\n);
printf ( 2: hexadecimal para decimal\n);
printf (informe sua opo: );
scanf (%d, &opcao);
}while(opcao < 1 || opcao > 2);
Depois que a opo tiver sido apresentada, o programa se repetir at que uma
opo vlida seja selecionada.
continue, considere o seguinte programa, que usa continue em um lao for e um lao while
para exibir os nmeros pares e mpares entre 1 e 100:
#include <stdio.h>
void main(void)
{
int contador;
printf("\nValores pares\n");
for (contador = 1; contador <= 100; contador++)
{
if (contador % 2) /* mpar */
continue;
printf("%d ", contador);
}
printf("\nValores mpares\n");
contador = 0;
while (contador <= 100)
{
contador++;
if (! (contador % 2)) /* Par */
continue;
printf("%d ", contador);
}
}
rotulo:
printf("%d ", conta++);
if (conta <= 100)
goto rotulo;
}
Quando usa-se o comando goto, o rtulo precisa residir na funo atual. Em outras
palavras, no pode-se usar goto para desviar-se de main para um rtulo que aparece em
outra funo e vice - versa.
2) Nunca duas constantes case no mesmo switch podem ter valores iguais.
Obviamente, uma declarao switch dentro de outra declarao switch pode ter as mesmas
constantes case;
3) Uma declarao switch mais eficiente que um encadeamento if-else-if.
possvel especificar comandos no switch que sero executados caso nenhuma
correspondncia seja encontrada. Basta adicionar uma declarao default. A declarao
default uma boa maneira de direcionar qualquer final livre que possa ficar pendente na
declarao switch. Por exemplo, no programa de converso de base numrica, pode-se usar
uma declarao default para informar ao usurio que uma resposta invlida foi dada e para
tentar outra vez.
Usa-se freqentemente o switch para desviar uma seleo de menu para a rotina
apropriada. Seguindo essa linha, pode-se us-la para fazer um melhoramento adicional ao
programa de converso de base numrica. A verso mostrada aqui elimina as sries
anteriores de ifs e substitui-as por uma clara declarao switch.
/* Programa de converso de base numrica switch
decimal ---> hexadecimal
hexadecimal ---> decimal*/
#include <stdio.h>
void main()
{
int opcao;
int valor;
printf (Converter: \n);
printf (1: decimal para hexadecimal\n);
printf (2: hexadecimal para decimal\n);
printf (\nInforme sua opo: );
scanf (%d, &opcao);
switch(opcao)
{
case 1:
printf (\nInforme o valor em decimal: );
scanf (%d, &valor);
printf (%d em hexadecimal e: %x, valor, valor);
break;
case 2:
printf (\nInforme o valor em hexadecimal: );
scanf (%x, &valor);
printf (%x em decimal e: %d, valor, valor);
break;
default:
printf (\nOpo invlida. Tente outra vez.)
}
}
switch(y){
case 0:
printf (erro de diviso por zero);
break;
case 1:
process (x, y);
}
break;
case 2:
.
.
.
case M:
printf (Vendas: R$%d\n, 14000);
}
break;
case O:
printf (Vendedores so: Ronaldo, Lisa e Hilton\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 10000);
break;
case L:
printf (Vendas: R$%d\n, 9500);
break;
case H:
printf (Vendas: R$%d\n, 13000);
}
break;
case N:
printf (Vendedores so: Toms, Joo e Raquel\n);
printf (Informe a primeira letra do vendedor: );
vendedor = toupper(getche());
printf (\n);
switch (vendedor)
{
case R:
printf (Vendas: R$%d\n, 5000);
break;
case J:
printf (Vendas: R$%d\n, 9000);
break;
case T:
printf (Vendas: R$%d\n, 14000);
}
break;
}
}
Para ver como o programa funciona, seleciona-se a regio Oeste, digitando O. Isso
indica que case O selecionado pela declarao switch externa. Para ver o total de vendas
de Hilton, digite H. Isso faz com que o valor 13000 seja apresentado.
Note que a declarao break em um switch aninhado no tem efeito no switch
externo.
51 5.2.1 Partes do Comando For so Opcionais: foi visto que muitas partes
constituintes da declarao for so opcionais.
52 5.2.2 Compreendendo um Lao Null: foi visto que este um recurso para
obter um retardo ou uma breve pausa durante a execuo de um programa.
53 5.2.3 Lao Infinito: foi visto que muitas vezes, devido erros de
programao, alguns laos for nunca atingem sua condio final, sendo executados
infinitamente.
54 5.2.4 Usando o operador vrgula da Linguagem C dentro de um lao for:
foi mostrado que a Linguagem C permite inicializar e incrementar mltiplas variveis em
um lao for separando as operaes com vrgula.
55 5.3 A Declarao While: foi visto que ao encontrar um lao while no
programa, a Linguagem C testa a condio especificada. Se a condio for verdadeira,
efetuar os comandos contidos no lao. Se o comando for falso, continuar a execuo de
seu programa ao primeiro comando que segue.
56 5.3.1 Partes de um Lao While: foi estudado as partes componentes do lao
while, de tal forma a conhece-las evitando laos infinitos e erros de programao.
57 5.4 A Declarao Do-While: neste item foi mostrado que o lao do-while
verifica sua condio no final do lao. Isso significa que um lao do-while ser executado
pelo menos uma vez.
58 5.5 Comando Continue: foi visto neste item que o comando continue em um
programa utilizado quando quer-se pular a iterao atual.
59 5.6 Finalizando um Lao Usando o Comando Break: o comando Break
utilizado para terminar imediatamente a execuo de um lao e a partir da continuar
executando a prxima linha de cdigo aps o lao.
60 5.7 Desvios com o comando goto: o comando goto permite que a execuo
do programa desvie-se para uma localizao especfica, chamada rtulo.
61 5.8 A Declarao Switch: na declarao switch, a varivel sucessivamente
testada contra uma lista de inteiros ou constantes caractere. Quando uma associao
encontrada, o conjunto de comandos associado com a constante executado.
62 5.8.1 As Declaraes Switch Aninhadas: da mesma forma vista para a
declarao for, a declarao switch pode ser posta no cdigo de programao da forma
aninhada.
63 5.9 Laos Aninhados: Quando um lao est dentro de outro, diz-se que o
lao mais interno aninhado. Laos aninhados propiciam o meio de resolver alguns
problemas interessantes de programao.
Mdulo 6 Matrizes
De forma similar, a seguinte declarao cria uma matriz do tipo float, que contm
50 salrios:
float salarios [50];
#include <stdio.h>
void main(void)
{
int notas[100];
float salar[100];
char string[100];
printf("Memoria para conter int notas[100] %d bytes\n",
sizeof(notas));
printf("Memoria para conter float salar[100] %d bytes\n",
sizeof(salar));
printf("Memoria para conter char string[100] %d bytes\n",
sizeof(string));
}
Dependendo do compilador, ele pode atribuir 0 aos elementos aos quais o programa
no atribui valores explcitos. No entanto, como regra, no se deve assumir que o
compilador inicializar os outros elementos. Alm disso, se no for especificado um
tamanho de matriz, o compilador alocar memria suficiente para conter somente os
valores que voc especificar. Por exemplo, a seguinte declarao de matriz cria uma matriz
grande o suficiente para conter trs valores do tipo long:
long planetas[] = {1234567L, 654321L, 1221311L};
O programa a seguir, inicializa a matriz notas e depois usa printf para exibir os valores dos
elementos:
#include <stdio.h>
void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};
printf("Valores da Matriz\n");
printf("notas[0] %d\n", notas[0]);
printf("notas[1] %d\n", notas[1]);
printf("notas[2] %d\n", notas[2]);
printf("notas[3] %d\n", notas[3]);
printf("notas[4] %d\n", notas[4]);
}
notas:
O cdigo a seguir usa a varivel i e um lao for para exibir os elementos da matriz
#include <stdio.h>
void main(void)
{
int notas[5] = {80, 70, 90, 85, 80};
int i;
printf("Valores da Matriz\n");
for (i = 0; i < 5; i++)
printf("notas[%d] %d\n", i, notas[i]);
}
Por exemplo, suponha que seja necessrio alterar o cdigo anterior de tal forma que
ele suporte 10 valores. Precisar alterar no somente a declarao da matriz, mas tambm o
lao for. Quanto mais alteraes forem feitas em um programa, maiores as chances de errar.
O programa a seguir declara uma matriz com base na constante TAM_MATRIZ. Como se
v, o programa no somente usa a constante para declarar a matriz, mas tambm usa a
constante como a condio final para o lao for:
#include <stdio.h>
#define TAM_MATRIZ 5
void main(void)
{
int valores[TAM_MATRIZ] = {80, 70, 90, 85, 80};
int i;
for (i = 0; i < TAM_MATRIZ; i++)
printf("valores[%d] %d\n", i, valores[i]);
}
Se mais tarde for necessrio alterar o tamanho da matriz, poder alterar o valor
atribudo constante TAM_MATRIZ para que o programa automaticamente atualize os
laos que controlam a matriz como o tamanho da matriz.
Quando uma funo recebe uma matriz como parmetro, o programa no precisa
especificar o tamanho da matriz na declarao do parmetro. No caso da funo
exibe_valores, os colchetes aps o nome da varivel valor informam o compilador de que o
parmetro uma matriz. Sabendo que o parmetro uma matriz, o compilador no se
preocupa com o tamanho da matriz que o programa passa para a funo.
No item anterior, foi visto que ao declarar o parmetro formal para uma matriz, no
necessrio declarar o tamanho da matriz. Em vez disso, pode-se especificar somente o
abre e fecha colchetes. O programa a seguir passa trs matrizes diferentes (de diferentes
tamanhos) para a funo exibe_valores:
#include <stdio.h>
void exibe_matriz(int valores[], int num_de_elementos)
{
int i;
printf("Prestes a exibir %d valores\n",num_de_elementos);
for (i = 0; i < num_de_elementos; i++)
printf("%d\n", valores[i]);
}
void main(void)
{
int notas[5] = {70, 80, 90, 100, 90};
int conta[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int pequeno[2] = {-33, -44};
exibe_matriz(notas, 5);
exibe_matriz(conta, 10);
exibe_matriz(pequeno, 2);
}
Como foi visto, na Linguagem C o caracter NULL representa o final de uma string
de caracteres. Portanto, as funes podem procurar o caracter NULL nos elementos da
matriz para determinar onde a matriz termina. No entanto, as matrizes de outros tipos, tais
como int, float ou long, no tem um caracter finalizador equivalente. Portanto, voc
normalmente precisa passar para as funes que trabalham com matrizes o nmero de
elementos que a matriz contm.
atual. Em geral, uma matriz no pode consumir mais do que 64Kb de espao. O programa a
seguir pode no passar na compilao porque as matrizes consomem muita memria:
void main(void)
{
char string[66000L];
int values[33000L];
float numbers[17000];
}
/* 66,000 bytes */
/* 33,000 * 2 = 66,000 bytes */
/* 17,000 * 4 = 68,000 bytes */
6, 7, 8, 9,
6, 7, 8, 9,
15, 16, 17,
6, 7, 8, 9,
15, 16, 17,
25, 26, 27,
10}};
10},
18, 19,20}};
10},
18, 19, 20},
28, 29, 30}};
2, 3, 4, 5,
2, 3, 4, 5,
12, 13, 14,
2, 3, 4, 5,
12, 13, 14,
22, 23, 24,
6, 7, 8, 9,
6, 7, 8, 9,
15, 16, 17,
6, 7, 8, 9,
15, 16, 17,
25, 26, 27,
10};
10},
18, 19,20}};
10},
18, 19, 20},
28, 29,30}};
apresentado seguir, uma sntese do que foi tratado em cada item deste mdulo.
Com esta sntese voc poder relembrar conceitos vistos durante nosso estudo ou mesmo
direcionar seu estudo, caso voc j tenha conhecimentos na Linguagem C.
64 6.1 Compreendendo as Matrizes: dada uma explicao que uma matriz
uma estrutura de dados que pode armazenar mltiplos valores do mesmo tipo.
65 6.2 Declarando uma Matriz: neste item visto como declarar uma matriz,
precisando-se especificar o tipo desejado (tal como int, float ou double), bem como o
tamanho da matriz.
66 6.3 Requisitos de Armazenamento de uma Matriz: foi visto que ao
declarar uma matriz, o compilador aloca memria suficiente para conter o nmero de
valores especificado. A quantidade real de memria que o compilador aloca depende do
tipo da matriz.
67 6.4 Inicializando uma Matriz: neste item explicada de maneira clara
como inicializar diferentes tipos de matrizes.
68 6.5 Acessando Elementos da Matriz: foi visto que para acessar um
elemento da matriz, voc especifica o nome da matriz e o elemento que deseja.
69 6.6 Percorrendo em um Lao Elementos da Matriz: foi mostrado que
quando se referencia muitos elementos de uma matriz, especificar nmeros para cada
elemento da matriz individualmente pode ser demorado e tedioso. Como uma alternativa,
os programas podem usar uma varivel para referenciar os elementos da matriz.
70 6.7 Usando Constantes Para Definir as Matrizes: mostra como os
programas usam constantes para definir matrizes.
71 6.8 Passando uma Matriz a uma Funo: visto que programas passam
para a funo tanto a matriz como o nmero de elementos que a matriz contm.
72 6.9 Revisitando as Matrizes Como Funes: . foi visto um programa que
passa trs matrizes diferentes (de diferentes tamanhos) para a funo exibe_valores.
73 6.10 Como as Matrizes de String Diferem: explica as principais diferenas
das matrizes de string.
74 6.11 Quantos Elementos Uma Matriz Pode Armazenar: foi visto que se o
ambiente de trabalho for o DOS, a quantidade de memria que as matrizes podem consumir
depender do modelo de memria atual. Em geral, uma matriz no pode consumir mais do
que 64Kb de espao.
75 6.12 Matrizes Multidimensionais: foi visto que a Linguagem C permite
matrizes bi, tri e multidimensionais.
76 6.13 Inicializando Elementos em Uma Matriz Bidimensional: foi
mostrado como inicializar uma matriz bidimensional.
77 6.14 Percorrendo em Um Lao Uma Matriz Bidimensional: foi mostrado
um programa que usa as variveis linha e coluna para exibir os valores contidos dentro da
matriz tabela.
Mdulo 7 Ponteiros
7.1 Ponteiros como Endereos
Como j foi visto, uma varivel o nome de uma posio na memria que pode
armazenar um valor de um determinado tipo. Os programas referenciam cada posio na
memria usando um endereo exclusivo. Um ponteiro uma varivel ou um valor que
contem um endereo. A Linguagem C utiliza muito os ponteiros. Quando se passa matrizes
ou string para as funes, o compilador C passa um ponteiro. Da mesma forma, quando
uma funo precisa alterar o valor de um parmetro, o programa deve passar para a funo
um ponteiro para o endereo de memria da varivel.
Como qualquer varivel, precisa-se atribuir um valor a uma varivel ponteiro antes
de poder usar o ponteiro dentro do programa. Quando atribui-se um valor a um ponteiro,
realmente atribui um endereo. Assumindo que anteriormente tenha-se declarado int conta,
o comando a seguir atribui o endereo da varivel conta ao ponteiro iptr:
iptr = &conta;
iptr = &conta;
printf("Valor de iptr %x Valor de conta %d Endereo de conta
%x\n", iptr, conta, &conta);
}
Da mesma forma, o comando a seguir atribui o valor apontado pela varivel iptr
para a varivel conta:
conta = *iptr;
{
int contador = 10;
int *iptr;
iptr = &contador;
/* Atribui o endereo */
printf("Endereo em iptr %x Valor em *iptr %d\n", iptr, *iptr);
*iptr = 25;
resultante ser 1001. Se fosse somado 1 a um ponteiro do tipo int (que requer dois bytes na
memria), o endereo resultante ser 1002. Quando for efetuada a aritmtica de ponteiro
necessrio ter em mente o tipo de ponteiro. Alm de somar valores aos ponteiros, os
programas podero subtrair valores ou somar e subtrair dois ponteiros.
Como pode ser visto, a funo exibe_string declara a varivel string como um
ponteiro. Usando o ponteiro, a funo simplesmente percorre os caracteres da string at
encontrar o caractere NULL. Para exibir o caractere, a funo exibe_string primeiro
desreferencia o endereo do ponteiro (obtendo o caractere). Em seguida, a funo
incrementa o ponteiro para apontar para o prximo caractere na string.
Segunda,
Tera,
Quarta,
Quinta,
Se for examinado o tipo da matriz da direita para a esquerda, ser visto que a matriz
contm sete elementos. O asterisco antes do nome da varivel especifica um ponteiro. Se
combinar o nome do tipo char que precede o nome da varivel, a declarao se tornar
uma matriz de ponteiros para strings de caractere.
O programa a seguir percorre em um lao a matriz dias, que contm ponteiros para
strings que contm os nomes dos dias da semana, como mostrado aqui:
#include <stdio.h>
void main(void)
{
char *dias[7] = {"Domingo", "Segunda", "Tera",
"Quarta", "Quinta", "Sexta", "S bado"};
int i;
for (i = 0; i < 7; i++)
printf("dias[%d] contm %s\n", i, dias[i]);
}
Quando se declara uma matriz com colchetes vazios, o compilador C aloca memria
suficiente para armazenar os caracteres especificados (e o terminador NULL), atribuindo
varivel titulo um ponteiro para o primeiro caractere. Como o compilador C
automaticamente aloca a memria necessria e depois trabalha com um ponteiro para a
memria, os programas podem usar um ponteiro de string de caracteres, em vez de uma
matriz, como mostrado a seguir:
char *titulo = Unesp Ilha Solteira;
Observe o uso dos parnteses entre os nomes das variveis. Se os parnteses fossem
removidos, as declaraes serviriam como prottipos de funo para as funes que
retornam ponteiros para um tipo especfico, como mostrado aqui:
int *min();
int *max();
float *media();
Ao ler uma declarao de varivel, deve-se comear com a declarao mais interna
que aparece dentro dos parnteses, e, depois, trabalha-se da direita para a esquerda:
int (*min)();
84 7.4 Aplicando o Operador de Endereo (&) a uma Matriz: foi visto que se
o operador de endereo for aplicado a uma matriz, a Linguagem C retornar o endereo
inicial da matriz.
85 7.5 Declarando Variveis Ponteiros: foi visto que para declarar um ponteiro,
precisa-se especificar o tipo do valor ao qual o ponteiro aponta (tal como int, float, char,
etc.) e um asterisco (*) antes do nome da varivel.
86 7.6 Desreferenciando um Ponteiro: foi explicado que desreferenciar um
ponteiro o processo de acessar o valor de uma posio de memria especfica. Para
desreferenciar o valor de um ponteiro, usa-se o operador asterisco de indireo (*).
87 7.7 Usando Valores de Ponteiro: foi apresentado o cdigo de um programa
em que o valor de um ponteiro usado para receber o endereo de uma varivel de depois o
ponteiro usado para indicar o valor armazenado na posio de memria que ele indica.
88 7.8 Ponteiros com Parmetros de Funo: foi visto que quando for
necessrio alterar o valor de um parmetro, dever passar para a funo um ponteiro para
um parmetro. Foi apresentado um programa que usa os ponteiros para dois parmetros do
tipo int para permutar os valores das variveis.
89 7.9 A Aritmtica de Ponteiros: foi explicada de manira clara a aritmtica de
ponteiros, que trata os ponteiros como valores que podem ser somados ou subtrados.
90 7.10 Incrementando e Decrementando um Ponteiro: foram vistas as
operaes de incremento e o decremento do valor de um ponteiro, que servem para apontar
para a prxima posio ou para a posio anterior na memria.
91 7.11 Percorrendo uma String usando um Ponteiro: foi visto um programa
que usa uma funo para exibir uma string de caracteres usando um ponteiro.
92 7.12 Funes que retornam Ponteiros: foi explicado que o valor que uma
funo retorna sempre do tipo declarado no prottipo ou cabealho da funo. Alm de
retornar esses tipos bsicos, as funes podem declarar ponteiros para os valores.
93 7.13 Criando uma Funo que retorna um Ponteiro: foi visto um
programa que cria uma funo que converte todos os caracteres de uma string para
maisculas e depois retorna um ponteiro para uma string.
94 7.14 Uma Matriz de Ponteiros: foi explicado que assim como pode-se criar
funes que retornam ponteiros, tambm pode-se criar matrizes de ponteiros. Mais
comumente sero usadas matrizes para conter strings de caracteres.
95 7.15 Percorrendo em um Lao uma Matriz de Strings de Caracteres: foi
visto um programa que percorre em um lao uma matriz , que contm ponteiros para strings
que contm os nomes dos dias da semana.
96 7.16 Usando um Ponteiro para um Ponteiro para String de Caracteres:
foi visto um programa que usa um ponteiro para um ponteiro para string de caracteres para
exibir o contedo de uma matriz.
97 7.17 Declarando uma Constante String usando um Ponteiro: foi visto
como declarar uma constante string usando um ponteiro.
98 7.18 O Ponteiro do tipo Void: foi dada uma explicao geral sobre o
ponteiro do tipo void.
99 7.19 Ponteiros para as Funes: foi visto que a Linguagem C permite que os
1007.20 Ponteiro para uma Funo: foi visto que o uso mais comum de um
ponteiro para uma funo passar essa funo como um parmetro para outra funo.
1017.21 Usando um Ponteiro para um Ponteiro para um Ponteiro: foi visto
que a Linguagem C permite criar variveis que so ponteiros para outros ponteiros. Em
geral, no h limite no nmero de indirees (ponteiros para ponteiros) que os programas
podem usar.
onde fp o nome que escolhemos para a varivel (podia ser qualquer outro).
Significado
"a+t"
Muitos programas abrem um arquivo para entrada e outro para sada. Em tais casos,
voc poderia declarar dois ponteiros de arquivo, como mostrado aqui:
FILE *entrada, *saida;
Se fclose for bem sucedida, retornar o valor 0. Se ocorrer um erro, fclose retornar
a constante EOF, como mostrado aqui:
if (fclose(pa) == EOF)
printf ("Erro ao fechar o arquivo de dados\n");
medida que for examinando programas em Linguagem C, ser visto que a maioria
deles no testa o valor de retorno de fopen, como mostrado aqui:
fclose(pa);
Na maioria das vezes, se uma operao fechar arquivo apresentar erro, o programa
poder fazer muito pouco para corrigir a situao. No entanto, se estiver trabalhando com
arquivos de dados crticos, dever exibir uma mensagem de erro para o usurio para que ele
possa examinar o contedo do arquivo.
Se no chamar a funo fclose, C fechar os arquivos abertos quando o programa
terminar.
seguir, usa fgetc e fputc para copiar o contedo do arquivo do diretrio raiz config.sys para
um arquivo chamado config.tst:
#include <stdio.h>
void main(void)
{
FILE *entrada, *saida;
int letra;
if ((entrada = fopen("\\CONFIG.SYS", "r"))==NULL)
printf("Erro ao abrir \\CONFIG.SYS\n");
else if ((saida = fopen("\\CONFIG.TST", "w"))==NULL)
printf("Erro ao abrir \\CONFIG.TST\n");
else
{
/* L e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, saida);
fclose(entrada);
/* Fecha o arquivo entrada */
fclose(saida);
/* Fecha o arquivo saida */
}
}
a
r
w
A funo ftell retorna um valor inteiro longo que especifica o byte de deslocamento
partir da posio atual no arquivo especificado. O programa a seguir usa ftell para exibir
informaes do ponteiro de posio. O programa comea abrindo o arquivo do diretrio
raiz config.sys no modo de leitura. O programa ento usa ftell para exibir a posio atual.
Em seguida, o programa l e exibe o contedo do arquivo. A ps encontrar o final do
arquivo, o programa novamente usar ftell para exibir a posio atual, como segue:
#include <stdio.h>
void main(void)
{
FILE *entrada;
int letra;
if ((entrada = fopen("\\CONFIG.SYS", "r")) == NULL)
printf("Erro ao abrir \\CONFIG.SYS\n");
else
{
printf("A posio atual o byte %d\n\n",
ftell(entrada));
/* L e grava cada caractere no arquivo*/
while ((letra = fgetc(entrada)) != EOF)
fputc(letra, stdout);
printf("\nA posio atual o byte %d\n",
ftell(entrada));
fclose(entrada);
/* Fecha o arquivo entrada */
}
}
dados. O parmetro limite especifica o nmero de caracteres que o buffer pode conter.
Quando fgets l caracteres do arquivo, fgets ler at limite - 1 (limite menos um) ou at o
primeiro caractere de nova linha (\n), o que vier primeiro. A funo ento colocar um
caractere NULL no buffer para indicar o final da string.
Muitos programas usam a funo sizeof para especificar o tamanho do buffer, tal
como sizeof(string). Finalmente o parmetro canal especifica o arquivo a partir do qual
fgets precisa ler a string. Precisa-se ter aberto previamente o canal usando fopen. Se fgets
ler informaes com sucesso do arquivo, fgets retornar um ponteiro para a string. Se
ocorrer um erro ou se chegar ao final do arquivo, fgets retornar NULL.
#include <stdio.h>
void main(int argc, char **argv)
{
FILE *entrada, *saida;
char string[256];
if ((entrada = fopen(argv[1], "r")) == NULL)
printf("Erro ao abrir %s\n", argv[1]);
else if ((saida=fopen(argv[2], "w")) == NULL)
{
printf("Erro ao abrir %s\n", argv[2]);
fclose(entrada);
}
else
{
while (fgets(string, sizeof(string), entrada))
fputs(string, saida);
fclose(entrada);
fclose(saida);
}
}
No caso da funo fread( ), buffer um ponteiro para uma regio de memria que
receber os dados lidos do arquivo.
No caso de fwrite( ), buffer um ponteiro para uma regio de memria onde se
encontram os dados a serem escritos no arquivo. O buffer usualmente um ponteiro para
uma matriz ou uma estrutura.
O nmero de bytes a ser lido ou escrito especificado por num_bytes.O argumento
count determina quantos itens (cada um tendo num_bytes de tamanho) sero lidos ou
escritos. Finalmente, fp um ponteiro para um arquivo de um fluxo previamente aberto por
fopen( ).
A funo fread( ) retorna o nmero de itens lidos, que pode ser menor que count
caso o final de arquivo seja encontrado ou ocorra um erro.
A funo fwrite( ) retorna o nmero de itens escritos, que ser igual a count a
menos que ocorra um erro.
Quando o arquivo for aberto para dados binrios, fread( ) e fwrite( ) podem ler e
escrever qualquer tipo de informao. O programa a seguir escreve um float em um arquivo
de disco chamado teste.dat.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void main()
{
FILE *fp;
float f = 3.141592654;
if ((fp = fopen(teste.dat, wb)) == NULL)
{
puts (No posso abrir arquivo!);
exit(1);
}
if (fwrite(&f, sizeof(float), 1, fp)!=1)
{
puts(Erro escrevendo no arquivo!);
}
fclose(fp);
}
Uma das aplicaes mais teis de fread( ) e fwrite( ) envolve leitura e escrita em
matrizes e estruturas. Por exemplo, este fragmento de programa escreve o contedo da
matriz em ponto flutuante exemplo no arquivo exemplo.dat usando uma simples
declarao fwrite( ).
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
float exemplo[10][10];
int i, j;
if ((fp = fopen(exemplo.dat, wb)) == NULL)
{
puts(No posso abrir arquivo!);
exit(1);
}
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
exemplo[i][j] = (float) i+j;
}
}
/*O cdigo a seguir grava a matriz inteira num nico passo*/
if (fwrite(exemplo, sizeof(exemplo), 1, fp) != 1)
{
puts(Erro ao escrever arquivo!);
exit(1);
}
fclose(fp);
}
Note como sizeof usado para determinar o tamanho da matriz exemplo. O prximo
exemplo usa a funo fread( ) para ler a informao escrita pelo programa anterior. Ele
exibe os nmeros na tela para verificao.
#include <stdio.h>
#include <stdlib.h>
void main()
{
FILE *fp;
float exemplo[10][10];
int i,j;
if ((fp = fopen(exemplo.dat, rb)) == NULL)
{
puts(No posso abrir arquivo!);
exit(1);
}
/*O cdigo a seguir l a matriz inteira num nico passo*/
if (fread(exemplo, sizeof(exemplo), 1, fp) != 1)
{
puts(Erro ao ler arquivo!);
exit(1);
}
for (i = 0; i < 10; i++)
{
Embora fprintf( ) e fscanf( ) sejam a maneira mais fcil de ler e escrever tipos de
dados nos mais diversos formatos, elas no so as mais eficientes em termos de tamanho de
cdigo resultante e velocidade. Assim, se a velocidade e tamanho so uma preocupao,
deve-se dar preferncia as funes fread( ) e fwrite( ).
Para ilustrar o quo til essas funes podem ser, o seguinte programa mantm uma
lista de telefones em um arquivo em disco. Pode-se inserir nomes e nmeros ou verificar
um nmero dado um nome.
#include
#include
#include
#include
#include
<stdio.h>
<string.h>
<stdlib.h>
<ctype.h>
biblioteca.c /*biblioteca com funes de tela*/
do
{
printf ((A)diciona, (C)onsulta, (T)ermina: );
ch = toupper(getche());
printf(\n);
}while (ch != T && ch != A && ch != C);
return(ch);
}
void add_num(void)
{
FILE *fp;
char nome[80];
int prefixo, num;
if (fp = fopen(fones.db, a)) == NULL)
{
printf (O arquivo da lista no pode ser aberto!\n);
exit(1);
}
printf (Informe o nome e o nmero: );
fscanf (stdin, %s%d%d, nome, &prefixo, &num);
fscanf (stdin, %*c); //remove o CR do buffer do teclado
fprintf (fp, %s %d %d, nome, prefixo, num);
fclose (fp);
}
void consulta(void)
{
FILE *fp;
char nome[80], nome2[80];
int prefixo, num;
if (fp = fopen(fones.db, r)) == NULL)
{
printf (O arquivo da lista no pode ser aberto!\n);
exit(1);
}
printf (Nome? );
gets (nome);
/*consulta um nmero*/
while (!feof(fp))
{
fscanf (fp, %s%d%d, nome2, &prefixo, &num);
if (!strcmp(nome, nome2))
{
printf (%s: %d-%d\n, nome, prefixo, num);
break;
}
}
fclose(fp);
}
do arquivo antes de efetuar uma operao especfica. Nesses casos, os programas podem
chamar a funo feof, como segue:
#include <stdio.h>
int feof(FILE *canal);
Significado
Da posio atual no arquivo
Do incio do arquivo
Do final do arquivo
#include <stdio.h>
int remove (const char *nomearq);
EACES
ENOENT
Significado
Acesso negado
Arquivo no encontrado
Alm da funo remove, a maioria dos compiladores C suporta a funo unlink, que
tambm exclui um arquivo:
#include <stdio.h>
int unlink(const char *nomearq);
No modo grfico, a tela do monitor de vdeo dividida numa fina malha de pontos
individuais, chamados de elementos de imagem, ou pixel. Qualquer pixel pode ser apagado
ou iluminado, o que vem a ser o princpio bsico para a criao de imagens grficas. A
resoluo da tela descrita em termos do nmero de pixeis por linha ou por coluna. Uma
tela VGA (Adaptador Grfico Colorido) tem 640 linhas por 480 colunas, como est
mostrado na Figura (a). importante notar que o sistema de numerao inicia no canto
superior esquerdo da tela no ponto (x,y) = (0,0).
(0,479
)
EIXO X
EIXO Y
(0,0)
(639,0)
(639,479)
(a)
(b)
(0,320)
yc
(479,0)
(0,0)
xc
(0,-319)
9.2
Detectando
o Adaptador Grfico
Provavelmente em seu programa seja necessrio detectar qual o adaptar grfico est
em uso. Para isso usamos a funo detectgraph. Esta funo detecta qual adaptador (CGA,
VGA, EGA, Hercules etc.) est conectado e informa o modo de resoluo mais alto do
driver daquele adaptador. A sintaxe da funo :
detectgraph(&gdriver,&gmode);
3 - EGA
Placa Grfica
CGAC0 CGAC1 CGAC2
CGAC3 CGAHI
MCGAC0 MCGAC1
MCGAC2 MCGAC3
MCGAMED MCGAHI
EGALO EGAHI
01
4 - EGA64
EGA64LO EGA64HI
01
5 - EGA-MONO
6 - IBM8514
EGAMONOHI
IBM8514HI IBM8514LO
3
01
7 - HERCULES
8 - ATT400
HERCMONOHI
ATT400C0 ATT400C1
ATT400C2 ATT400C3
ATT400MED ATT400HI
VGALO VGAMED
VGAHI
PC3270HI
0
012345
2 - MCGA
9 - VGA
10 - PC3270
Gmode
01234
012345
012
0
N LinhasxColunas
320x200 320x200 320x200 320x200
640x200 - 2 color
320x200 320x200 320x200 320x200
640x200 - 2 color 640x480 - 2 color
640x200 - 16 colors 640x350 - 16
colors
640x200 - 16 colors 640x350 - 4
colors
640x350 - 2 colors
640x480 - 256 colors 1024x768 256 colors
720X348 - 2 color
320x200 320x200 320x200 320x200
640x200 - 2 colors 640x400 - 2
colors
640x200 - 16 colors 640x350 - 16
colors 640x480 - 16 colors
720x350 - 2 colors
#include <stdio.h>
#include <graphics.h>
main()
{
int adaptador_grafico,i,j;
int modo_grafico;
clrscr();
detectgraph(&adaptador_grafico,&modo_grafico);
printf("\n O adaptador detectado %d ",adaptador_grafico);
printf("\n O modo de alta resolucao %d",modo_grafico);
getch();
}
ela CGA, VGA, EGA, etc. A seguir, o programa ilustra o uso destas duas funes grficas:
#include <stdio.h>
#include <graphics.h>
main()
{
int adapt, mod, xmax, ymax;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
xmax=getmaxx();
ymax=getmaxy();
outtextxy(100,100,Estamos no modo grfico!
tecla.);
getch();
closegraph();
printf("\n O eixo x da tela vai de 0 a %d", xmax);
printf("\n O eixo y da tela vai de 0 a %d", ymax);
getch();
}
Aperte
uma
Os parmetros entre parnteses indica para o seu programa que ele desenhe uma
linha ligando o ponto xi,yi ao ponto xf,yf.
A seguir, o uso da funo line(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
line(0, 0, getmaxx(), getmaxy());
getch();
closegraph();
}
sintaxe:
rectangle(xsup, ysup, xinf, yinf);
Os parmetros entre parnteses indica para o seu programa que ele desenhe um
retngulo na tela com o canto superior esquerdo no ponto (xsup, ysup) e o canto inferior
direito no ponto (xinf, yinf).
A seguir, ilustramos o uso da funo rectangle(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
rectangle(5, 10, 300, 100);
getch();
closegraph();
}
Os parmetros entre parnteses indicam para o seu programa que ele imprima um
pixel (ponto) no ponto (x, y),usando a cor especificada por cor.
A seguir, ilustramos o uso da funo putpixel(), com um programa exemplo:
#include <graphics.h>
main()
{
int adapt, mod ;
detectgraph(&adapt,&mod);
initgraph(&adapt,&mod,"c:\\tc");
putpixel(50,100,15);
outtextxy(55,110," aqui 1" );
putpixel(300,100,15); outtextxy(303, 102," aqui 2");
getch();
closegraph();
}
Os parmetros entre parnteses indicam para o seu programa que ele desenhe um
crculo partir das coordenadas (xcentro, ycentro),de raio raio.
seguir:
Os valores que se pode atribuir ao parmetro cor para a tela VGA so dados a
COR
PRETO
VERDE
VERMELHO
MARROM
CINZA ESCURO
VERDE CLARO
VERMELHO CLARO
AMARELO
0
2
4
6
8
10
12
14
VALOR
COR
AZUL
CIANO
MAGENTA
CINZA CLARO
AZUL CLARO
CIANO CLARO
MAGENTA CLARO
BRANCO
1
3
5
7
9
11
13
15
VALOR
setfillstyle(padrao,cor);
floodfill(x, y, borda);
A funo floodfill(x, y, borda) preenche uma rea na tela grfica ao redor do ponto
dado por (x, y) com a cor e o padro atuais de preenchimento, setados pela instruo
setfillstyle(), at encontrar a cor especificada por borda.
A funo setfillstyle() ajusta o padro e a cor de preenchimento grfico atuais, sendo
que o parmetro padrao assume um dos valores abaixo:
0
2
4
6
8
10
Nmero
Padro
Cor de fundo
Linhas horizontais
Linhas inclinadas grossas ///
linhas inclinadas grossas \\\
cruzes grossas agrupadas
pontos esparsos
1
3
5
7
9
11
Nmero
Padro
Cor slida
Linhas inclinadas finas ///
Linhas inclinadas finas \\\
cruzes finas agrupadas
linhas intercaladas
pontos densos
10.1 Estruturas
Na Linguagem C, uma estrutura uma coleo de variveis referenciadas sobre um
nome, provendo um meio conveniente de manter informaes relacionadas juntas. Uma
declarao de estrutura forma uma fonte que pode ser usada para criar variveis de
estruturas. As variveis que compreendem a estrutura so chamadas de campos.
Observa-se que a declarao termina com um ponto-e-vrgula. por isso que uma
estrutura uma declarao. Temos ainda que, a etiqueta endereo, identifica essa estrutura
de dados particular e o seu especificador de tipo.
Neste ponto do cdigo, nenhuma varivel foi declarada. Somente a forma dos dados
foi definida. Para declarar uma varivel com essa estrutura, deve-se escrever:
struct endereo info_adr;
Isso passar um ponteiro para caractere para o comeo do campo nome. Se fosse
necessrio acessar os elementos individuais de info_adr.nome, poderia indexar nome. Por
exemplo, pode-se imprimir o contedo da info_adr.nome, um caractere por vez, usando
este cdigo:
int t;
for (t = 0; info_adr.nome[t]; ++t) putchar (info_adr.nome[t]);
Isso cria 100 conjuntos de variveis que so organizados como definido na estrutura
endereo. Para acessar uma estrutura especfica, o nome da estrutura indexado.
Por exemplo, para imprimir o cdigo cep na estrutura 3, deve-se escrever:
printf (%lu, info_adr[2].cep);
Aqui esto exemplos de cada campo sendo passado para uma funo:
func1
func2
func3
func4
func5
caractere em x
inteiro em y
float em x
da string em s
do caractere em s[2]
Note que o operador & precede o nome da varivel estrutura, no o nome do campo
individual. Note tambm que o elemento string s j significa o endereo, assim, o operador
& no requerido.
Passando Estruturas Inteiras para Funes: Quando uma estrutura usada como
argumento para uma funo, a estrutura inteira passada usando-se o mtodo padro de
chamada por valor (passagem de parmetro por cpia). Isso, obviamente, significa que
qualquer mudana feita no contedo de uma estrutura dentro da funo para qual ela
passada no afeta a estrutura usada como argumento.
A considerao mais importante para se ter em mente quando se usa uma estrutura
como parmetro que o tipo do argumento deve corresponder ao tipo do parmetro. Por
exemplo, este programa declara o argumento arg e o parmetro parm para serem do mesmo
tipo de estrutura:
#include <stdio.h>
/*define um tipo de estrutura*/
struct exemplo{
int a, b;
char ch;
};
void fl(struct exemplo parm)
{
printf (%d, parm.a);
}
void main()
{
struct exemplo arg;
arg.a = 1000;
fl(arg);
}
Esse programa, como fcil de se ver, imprimir o nmero 1000 na tela. Como
mostrado, melhor definir um tipo estrutura globalmente e, ento, usar o seu nome para
declarar variveis estrutura e parmetros, quando necessrio. Isso ajuda a assegurar a
correspondncia entre os argumentos e os parmetros. Tambm, mostram para outras
pessoas que estiverem lendo o programa que parm e arg so do mesmo tipo.
Usando Ponteiros para Estruturas: Existem muitos usos para ponteiros para
estruturas. Um deles na obteno de uma chamada por referncia para uma funo. Outro
na criao de estruturas dinmicas (listas, filas, pilhas, rvores, etc.).
Existe uma desvantagem maior em passar tudo, at a mais simples estrutura, para
funes: o esforo necessrio para levar (e trazer) todos os campos da estrutura para a pilha.
Em estruturas simples, com poucos campos, esse esforo no to importante, mas, se
muitos campos so usados e se algum deles matriz, a performance de tempo de execuo
pode se tornar inaceitvel. A soluo para esse problema passar somente um ponteiro para
estrutura.
Quando um ponteiro para estrutura passado para uma funo, somente o endereo
da estrutura empurrado (e puxado) para a pilha. Isso significa que uma chamada de
funo extremamente rpida pode ser executada. Tambm, como estar referenciando a
estrutura em si e no uma cpia, a funo ter condies de modificar o contedo dos
campos da estrutura usada na chamada.
Para encontrar o endereo de uma varivel estrutura, o operador & colocado antes
do nome da varivel estrutura. Por exemplo, este fragmento coloca o endereo de cliente no
ponteiro p.:
struct sal{
float saldo;
char nome[80];
} cliente;
struct sal *p; /* declarao de um ponteiro para estrutura*/
Raramente ser visto referncias feitas a um campo de uma estrutura com uso
explcito do operador *, como mostrado no exemplo anterior. Uma vez que o acesso a um
campo de uma estrutura por meio de um ponteiro para a dada estrutura to comum, um
operador especial definido pela Linguagem C realiza esta tarefa. Ele o ->, chamada de
operador seta. Ele formado utilizando-se o sinal de menos seguido por um sinal de maior
que. A seta usada no lugar do operador ponto, quando se acessa um campo da estrutura
utilizando-se um ponteiro para a varivel estrutura. Por exemplo, a declarao anterior
usualmente escrita assim:
p->saldo
Para ver como um ponteiro para uma estrutura pode ser usado, examine este
programa simples que imprime horas, minutos e segundos na sua tela, usando uma rotina
de espera cronometrada:
#include <stdio.h>
#include <conio.h>
struct estrut_horas{
int horas;
int minutos;
int segundos;
};
void espera()
{
long int t;
for (t = 1; t < 128000; ++t);
}
void atualiza (struct estrut_horas *t)
{
t->segundos++;
if (t->segundos == 60)
{
t->segundos = 0;
t->minutos++;
}
if (t->minutos == 60)
{
t->minutos = 0;
t->horas++;
}
if (t->horas == 24) t->horas = 0;
espera();
}
void exibe(struct estrut_horas *t)
{
printf (%d:, t->horas);
printf (%d:, t->minutos);
Essa linha de cdigo diz ao compilador para pegar o endereo da varivel t (que o
tempo na funo main( )) e atribuir zero ao seu campo chamado horas.
struct x{
int a[10][10]; /*matriz 10x10 de inteiros*/
float b;
} y;
Aqui endereo a estrutura definida anteriormente e emp foi definida como tendo
dois elementos. O primeiro elemento a estrutura do tipo endereo, que conter um
endereo de um empregado. O segundo salrio, que armazena o salrio do empregado. O
seguinte fragmento de cdigo atribui o cep 98765777 para o campo cep do endereo do
funcionrio:
funcionrio.endereo.cep = 98765777;
10.2 Unies
Na Linguagem C, uma union uma localizao de memria usado por muitos tipos
de variveis diferentes. A declarao de uma union similar ao de uma estrutura, como
mostrado neste exemplo:
union u_tipo{
int i;
char ch;
};
Assim como com estruturas, essa declarao no declara qualquer varivel. Pode-se
declarar uma varivel tanto colocando-se o nome dela no fim da declarao como pelo uso
de uma declarao em separado. Para declarar uma varivel union, chamada cnvt, do tipo
u_tipo, usando a declarao dada anteriormente, pode-se escrever:
union u_tipo cnvt;
10.3 Enumeraes
A lista de enumerao uma lista de nomes separados por vrgulas que representam
os valores que uma varivel da enumerao pode ter. Tanto o nome do tipo enumerado
como a lista de variveis so opcionais. Assim como com estruturas, o nome do tipo
enumerado usado para declarar variveis do seu tipo. O fragmento seguintes define uma
enumerao chamada moeda e declara dinheiro para ser desse tipo:
enum moeda {penny, nickel, dime, quarter,
half_dollar, dollar};
enum moeda dinheiro;
Uma suposio comum, mas errnea, feita a respeito das enumeraes que os
smbolos podem ser atribudos e exibidos diretamente. Esse no o caso. Por exemplo, o
seguinte fragmento de cdigo no proceder como desejado:
/*isto no funciona*/
dinheiro = dollar;
printf (%s, dinheiro);
/*este cdigo est incorreto*/
gets(s);
strcpy (dinheiro, s);
Algumas vezes, possvel declarar uma matriz de strings e usar o valor de uma
enumerao como ndice na transformao de uma valor enumerado na sua string
correspondente. Por exemplo, este cdigo tambm produzir a string apropriada:
char nome[][20] = {
penny,
nickel,
dime,
quarter,
half_dollar,
dollar
};
.
.
.
printf (%s, nome[dinheiro]);
Esse cdigo funcionar se nenhuma inicializao de smbolos for usada, uma vez
que a matriz de strings deve ser indexada comeando em zero. Por exemplo, este programa
imprime os nomes das moedas:
#include <stdio.h>
enum moeda {penny, nickel, dime, quarter,
half_dollar, dollar};
char nome[][20] =
{
penny,
nickel,
dime,
quarter,
half_dollar,
dollar
};
void main()
{
enum moeda dinheiro;
for (dinheiro = penny; dinheiro <= dollar; dinheiro++)
{
printf (%s, nome[dinheiro]);
}
}
Nela, temos que tipo qualquer tipo de dado permitido e nome o novo nome para
esse tipo.
O novo nome definido uma adio, no uma substituio, ao nome existente. Por
exemplo, pode-se criar um novo nome para o tipo float usando-se a seguinte declarao:
typedef float flutuante;
Essa declarao diz ao compilador para reconhecer flutuante como um outros nome
para float. A seguir, pode-se criar uma varivel float usando-se flutuante:
flutuante atraso;
typedef. No se cria um novo tipo de dado, mas, ao contrrio, define-se um novo nome para
um tipo existente. Este processo pode auxiliar programas dependentes de mquinas a serem
portveis.
4
IP1
3
IRQ
2
MUX2
1
MUX1
0
MUX0
O resultado final da converso pode ento ser lido nos endereos BASE e
BASE+1 com a seguinte configurao:
Endereo BASE - Leitura
7
6
5
AD9
AD10
AD11
Endereo BASE+1 - Leitura
4
AD12 (LSB)
3
0
2
0
1
0
0
0
7
AD1 (MSB)
6
AD2
5
AD3
4
AD4
3
AD5
2
AD6
1
AD7
0
AD8
Observa-se acima que o LSB lido no endereo (BASE), com apenas 4 bits
menos significativos. No endereo (BASE+1) esto os 8 bits mais significativos. Para
ordenao nos 12 bits, deve, portanto, realizar a leitura nos respectivos endereos,
rotacionar o byte menos significativo 4 casas a direita e somar com o byte superior
rotacionado 4 casas a esquerda.
O seguinte trecho de programa em linguagem C realiza a converso de um valor
analgico em digital, em 12 bits, j provendo a ordenao dos bits.
outportb(BASE+1,0);
/* Partida no conversor A/D, 12 bits */
a=0x80;
while(a==0x80)
a=inportb(BASE+2)&0x80; /*espera por EOC = 0, fim converso */
BS=(inportb(BASE)&0xF0)>>4; /* leitura Byte inferior e correo */
Bi=inportb(BASE+1);
/* leitura byte superior */
vec = 16 * BS + Bi ;
/* rearranjo valor digital em 12 bits */
4
DA4
4
X
3
DA3
3
DA11 (MSb)
2
DA2
2
DA10
1
DA1
0
DA0 (LSb)
1
DA9
0
DA8
i < NP;
NP-1
xmin
xmax
x max x min
NP 1
x min
i*
k x min
i
x max x min
NP 1
[11.1]
x max x min
NP 1
k i * x x min
11.4.2 - Fator de Escala Eixo Y
Nesse caso so envolvidos os valores mximo e mnimo do vetor, devendo ser
desenvolvida uma rotina para tal objetivo.
ymin
vecmax
[11.2]
[11.3]
vec[i]
ymax
vecmin
y max y min
vec min vec max
y y min
vec[i] vecmax *
y y min
vec[i] vec max
y max
vec min
y max y min
vecmin vecmax
y min
vec max
[11.4]
[11.5]
[11.6]
xmax =
ymax =
deltax
deltay
getmaxx();
getmaxy();
= (0.9*xmax-0.1*xmax)/(NP-1));
/* [11.2] */
= ((0.45*ymax-0.05*ymax)/(vec_min-vec_max)); /* [11.5]*/
vec_max = vec[i];
vec_min = vec[i];
<stdio.h>
<graphics.h>
<math.h>
<stdlib.h>
<ctype.h>
<conio.h>
<dos.h>
<stdarg.h>
float vec[NP+1],vec_max,vec_min,xmax,ymax;
float A=1,R=1,K=200,deltax,deltay,ki,kf,yi,yf;
float K2,B;
int BS[NP+1],Bi[NP+1];
int BDAS[NP+1],BDAI[NP+1];
double magr[NP+1], magi[NP+1];
int y1,x1,k,vetor[NP+1];
void main(void)
{
char L;
int graf,gmode;
detectgraph(&graf,&gmode);
initgraph(&graf,&gmode,"c:\\tc");
xmax = getmaxx();
ymax = getmaxy();
L = 'G';
while(L!='S')
{
cleardevice();
switch(L)
{ case 'A': datan(); superior(); fft();
inferior(); break;
case 'G': seno();
superior(); fft();
inferior(); break;
case 'P': convad(); superior(); fft();
inferior(); convda();
break;
}
L=toupper(getch());
}
closegraph();
}
datan()
{
int i;
FILE *infile;
if((infile = fopen("datan.c","rb")) == NULL)
{ perror("Desculpe mas nao encontrei o datan.c");
exit(1);
}
for(i=0;i< NP; i++ )
fscanf(infile,"%f ", &vec[i]);
fclose(infile);
}
superior()
{
int i;
tela();
max_min();
deltax = (0.92*xmax/(NP-1));
deltay = (0.35*ymax/(vec_min-vec_max));
settextstyle(0,0,1); setcolor(YELLOW);
x1=0.008*xmax; y1=0.44*ymax;
gprintf(&x1,&y1,"%3.1f",vec_min);
x1=0.008*xmax; y1=0.1*ymax;
gprintf(&x1,&y1,"%3.1f",vec_max);
setcolor(RED); setlinestyle(1,0,0);
if(vec_min<0)
{
k=(-vec_max)*deltay+0.1*ymax;
line(0.08*xmax,k,xmax,k);
x1=0.03567*xmax;
gprintf(&x1,&k,"0.0");
}
setlinestyle(0,0,0);
setcolor(BLACK);
for (i=1;i<NP ;i++)
{ ki = ((i-1)*deltax)+0.08*xmax ;
yi = ((1.0*(vec[i-1]-vec_max))*deltay)+0.1*ymax;
kf = (i*deltax)+0.08*xmax;
yf = ((1.0*(vec[i]-vec_max))*deltay)+0.1*ymax;
line(ki,yi,kf,yf);
}
}
max_min()
{ int i;
vec_max = vec_min = vec[0];
for ( i = 1; i < NP ; i++ )
{
if( vec[i] > vec_max)
if( vec[i] < vec_min)
}
}
vec_max = vec[i];
vec_min = vec[i];
tela()
{
nome()
{
setcolor(LIGHTRED); settextstyle(0,0,1);
outtextxy(0.05*xmax,0.03*ymax,"DEMO");
outtextxy(0.02*xmax,0.04*ymax,"");
outtextxy(0.84*xmax,0.02*ymax,"MICRO - 2");
outtextxy(0.85*xmax,0.05*ymax,"06/2006");
setcolor(WHITE); rectangle(.2*xmax,0,0.80*xmax,.08*ymax);
setcolor(GREEN); settextstyle(0,0,2);
outtextxy(0.26*xmax,0.03*ymax,"ANALISADOR ESPECTRAL");
setcolor(MAGENTA); settextstyle(5,0,2);
outtextxy(0.47*xmax,0.48*ymax,"Tempo");
outtextxy(0.45*xmax,0.92*ymax,"Frequencia");
setcolor(BLACK);
outtextxy(0.25*xmax,0.97*ymax,"[A]rquivo [G]erador [P]laca [S]air");
setcolor(MAGENTA); settextstyle(0,1,1);
outtextxy(0.025*xmax,0.24*ymax,"Tensao");
outtextxy(0.025*xmax,0.67*ymax,"Tensao");
}
seno()
{
int i;
float xi,yi;
double teta,B,K2;
B=random(50)+1.0;
K2=random(250)+1.0;
A=random(100)+1.0;
for(i=0;i<NP;i++)
{ teta=360.*i*PI/(180.*NP);
vec[i]=A*sin(100.0*teta)+ B*sin(K2*teta)+
10.0*random(100)/101.0;
}
}
inferior()
{
int i;
max_min();
setcolor(YELLOW);
settextstyle(0,0,1);
x1=0.02*xmax;
y1=0.89*ymax;
gprintf(&x1,&y1,"%3.1f",vec_min);
settextstyle(0,0,1);
x1=0.01*xmax;
y1=0.55*ymax;
gprintf(&x1,&y1,"%3.1f",vec_max);
setcolor(BLACK);
deltax = (2*0.92*xmax/(NP-1));
deltay = (0.35*ymax/(vec_min-vec_max));
for (i=1;i<NP/2;i++)
{
ki = (i-1)*deltax+0.08*xmax ;
yi = ((1.0*(vec[i-1]-vec_max))*deltay)+0.55*ymax;
kf = (i)*deltax+0.08*xmax;
yf = ((1.0*(vec[i]-vec_max))*deltay)+0.55*ymax;
line(ki,yi,kf,yf);
}
}
convad()
{ int i,a;
for(i=0;i<NP;i++)
{
outportb(BASE+1,0);
a=0x80;
while(a==0x80)
a=inportb(BASE+2)&0x80;
BS[i]=(inportb(BASE)&0xF0)>>4;
Bi[i]=inportb(BASE+1);
vec[i]=16*BS[i]+Bi[i];
vetor[i]=vec[i];
}
}
convda()
{ int i;
for(i=0;i<=NP;i++)
{
BDAI[i]=vetor[i]&0xFF;
BDAS[i]=(vetor[i]&0xF00)>>8;
}
while(!kbhit())
{ for(i=0;i<=NP;i++)
{ outportb(BASE+8,BDAI[i]);
outportb(BASE+9,BDAS[i]);
}
}
}
/*
fft()
{
int ii,jj,n,mudado,ni,m,l,k;
int N,gm,gd;
double ur,ui,wr,wi,tr,ti,tur;
float ji;
for(ii=0;ii<=NP;ii++) magr[ii]=magi[ii]=0.0;
n = log10(NP)/log10(2);
/ ******** bit reverso *************/
for(jj = 0; jj < NP; jj++)
{
mudado=0;
ni = 1;
for(ii=1;ii<=n; ii++)
{ if((ni&jj)!= 0)
mudado|=(1<<(n+1-ii));
ni<<=1;
}
magr[(mudado>>1)+1]=vec[jj]/NP;
}
for(m=1;m<=n;m++)
{ ur = 1; ui =0;
jj = 1;
k = 1<<(m-1);
wr = cos(PI/k); wi = -sin(PI/k);
for(jj=1;jj<=k;jj++)
{ for(l=jj;l<=NP;l+= (1<<m))
{ tr = magr[l+k]*ur-magi[l+k]*ui;
ti = magr[l+k]*ui+magi[l+k]*ur;
magr[l+k] = magr[l] - tr;
magi[l+k] = magi[l] - ti;
magr[l] = magr[l] + tr;
magi[l] = magi[l] + ti;
}
tur = ur*wr-ui*wi;
ui = ur*wi+ui*wr;
ur = tur;
}
}
for(ii=0;ii<NP;ii++)
{ magr[ii] = magr[ii+1];
magi[ii] = magi[ii+1];
vec[ii]=2*sqrt(pow(magi[ii],2.)+ pow(magr[ii],2.));
}
vec[0]=0;
/* faz o valor medio do vetor igual a zero */
}
int gprintf( int *xloc, int *yloc, char *fmt, ... )
{
va_list argptr;
/* Argument list pointer
*/
char str[140];
/* Buffer to build sting into */
int cnt;
/* Result of SPRINTF for return */
va_start( argptr, format ); /* Initialize va_ functions */
cnt = vsprintf(str,fmt,argptr); /*prints string to buffer*/
outtextxy(*xloc,*yloc,str); /* Send string in graphics mode */
*yloc += textheight("H")+2; /* Advance to next line
*/
va_end( argptr );
/* Close va_ functions
*/
return( cnt );
*/
Figura
Referncias
Bibliogrficas