Académique Documents
Professionnel Documents
Culture Documents
CINCIA DA COMPUTAO
LINGUAGEM DE PROGRAMAO II
PROGRAMAO EM C
Professores:
Mozart Lemos de Siqueira
Tasso Gomes de Faria
SUMRIO
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
5
5
5
5
5
5
7
7
8
8
8
9
11
11
11
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
12
12
12
13
14
14
14
14
15
15
16
17
18
19
19
20
21
21
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
23
23
25
25
26
26
26
27
27
4 MATRIZES . . . . . . . . . . .
4.1
Strings . . . . . . . . . . . . .
4.2
Matrizes Bidimensionais . . .
4.3
Matrizes de Strings . . . . . .
4.4
Matrizes Multidimensionais .
4.5
Inicializao de Matrizes . . .
4.6
Exerccios: . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
29
30
32
33
33
34
34
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
. . . . . . . . . . .
36
36
38
38
40
6 FUNES . . . . . . . . . . . . . . . . .
6.1
Modularidade . . . . . . . . . . . . . . .
6.2
Forma de uma Funo . . . . . . . . . .
6.3
Regras de Escopo . . . . . . . . . . . . .
6.4
Argumentos de Funes . . . . . . . . .
6.5
O Comando return . . . . . . . . . . . .
6.6
Funes do Tipo void . . . . . . . . . . .
6.7
Passagem por Parmetros . . . . . . . .
6.7.1
Chamada por Valor . . . . . . . . . . .
6.7.2
Chamada por Referncia . . . . . . . .
6.7.3
Matrizes como Argumentos de Funes
6.8
Prottipos de Funes . . . . . . . . . .
6.9
Exerccios . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
41
41
41
42
42
43
43
44
44
45
46
46
47
7 APONTADORES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7.1
Apontadores: passagem de parmetros por referncia . . . . . . . . . .
7.2
Alocao Dinmica de ponteiros . . . . . . . . . . . . . . . . . . . . . .
7.3
Exerccios: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
48
50
52
54
8 ARQUIVOS . . . . . . . . . .
8.1
Introduo . . . . . . . . . .
8.2
Arquivos . . . . . . . . . . . .
8.3
Funes . . . . . . . . . . . .
8.3.1
Ponteiro de Arquivo . . . . .
8.3.2
Abrindo um arquivo (fopen) .
55
55
55
55
55
55
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
. . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
8.3.3
Fechando um arquivo (fclose) . . . . . . . . . . . . .
8.3.4
Escrevendo e Lendo um caractere . . . . . . . . . . .
8.3.5
Lidando com Strings (fputs e fgets) . . . . . . . . . .
8.3.6
Lidando com blocos de dados binrios(fread e fwrite)
8.3.7
Realizando Procuras (fseek) . . . . . . . . . . . . . .
8.4
Exerccios . . . . . . . . . . . . . . . . . . . . . . . .
9
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
BIBLIOGRAFIA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
57
57
58
59
60
61
62
Esse captulo apresenta uma breve introduco ao Sistema Operacional Linux, suas caractersticas bsicas e seus principais comandos. O objetivo dar suporte para o aluno
desenvolver seus programas no ambiente Linux, utilizando o compilador gcc. Uma introduo a Linguagem de Programao C tambm apresentada, atravs do histrico da
linguagem e da descrio da estrutura bsica de um programa escrito com ela.
Para desmontar:
Para montar:
Obs.: Para acessar o contedo do disquete, copiar, deletar, mover ou qualquer outra
tarefa relativa aos arquivos, use os comandos do Linux no diretrio /mnt/floppy,
esse diretrio o disquete!
Comando
man <comando>
ls
ls -la
cd <nome-dir>
mkdir <nome-dir>
touch <nome-arquivo>
rmdir <nome-dir>
cp <origem> <destino>
mv <origem><destino>
mv <nome1> <nome2>
rm file
ps
kill -9 nro
pwd
cat f
more f
free
passwd
Funo
Manual de usurio Linux para os comandos
Lista arquivos do diretrio
Lista arquivos no diretrio com detalhes
Muda para o diretrio
Cria o novo diretrio
Cria ou atualiza data, se o arquivo j existe
Deleta diretrio (deve estar vazio)
Copia arquivo
Move dado da origem para o destino
Renomeia diretrio ou arquivo 1 para 2
Remove arquivo (cuidado!)
Imprime o numero dos processos ativos
Mata processo nro
Imprime diretrio corrente
Mostra contedo do arquivo f
Mostra contedo do arquivo f tela a tela
Exibe memria livre
Altera senha do usurio
Diretrio
/
bin
boot
dev
etc
home
lib
mnt
root
sbin
tmp
usr
Contedo
Diretrio raiz do sistema
Arquivos executveis(binrios)
Arquivos estticos de boot de inicializao(boot-loader)
Arquivos de dispositivos de entrada/sada
Configurao do sistema da mquina local
Diretrio local (home) dos usurios
Arquivos das bibliotecas compartilhadas usados freqentemente
Ponto de montagem de partio temporrios (floppy, cdrom, etc)
Diretrio local do superusurio (root)
Arquivos de sistema essenciais
Arquivos temporrios gerados por alguns utilitrios
Todos os arqs dos diversos aplicativos devem estar aqui
Tabela 1.2: Principais diretrios do Linux
onde gcc o comando que dispara o compilador, o argumento, no obrigatrio,
para entrar com o nome do executvel. Caso seja omitido , o compilador retornar
um nome padro para o executvel igual a
. Dvidas sobre o comando podem ser
resolvidas digitando
.
Obs.: Para executar o programa digite antes do nome do executvel. Isso neces
A linguagem C formada por pouco mais de 30 palavras-chave, por isso, normalmente necessria a declarao das bibliotecas que contem funes no nativas na linguagem. Como exemplo podemos citar as funes de entrada e sada de dados presentes
na biblioteca padro.
Em C, maisculas e minsculas so diferentes por isso preste ateno na hora de
digitar o programa fonte. Essa caracterstica chamada de case sensitive. Os smbolos /*
(inicio de comentrio) e */ (final do comentrio) indicam comentrios de cdigo e podem
abranger uma ou mais linhas do programa. Para comentar somente uma linha, pode-se
utilizar //.
Todo programa em C consiste em uma ou mais funes. A nica funo que necessariamente precisa estar presente a denominada main(), que a primeira funo a ser
chamada quando a execuo do programa comea. Embora main() no seja tecnicamente
parte da linguagem C, tratada como se fosse. No pode ser usada como nome de varivel, porque pode confundir o compilador.
1.2.3 Primeiro exemplo
O nico caminho para aprender uma nova linguagem de programao escrever programas nesta linguagem, Normalmente os autores utilizam um exemplo clssico no primeiro programa, o famoso - Oi Mundo!
Esse ser o seu primeiro programa, para cria-lo, utilize algum editor de textos para
digitar os fontes e um compilador para gerar o executvel.
#include<stdio.h>
main()
{
printf(Oi mundo! n");
}
10
Um programa C, independentemente de seu tamanho, consiste de uma ou mais "funes que especificam as operaes computacionais que devem ser feita. Funes C so
similares aos procedimentos em Pascal. No nosso exemplo main() uma funo. Normalmente voc pode escolher o nome que quiser, menos para main.
Um mtodo de comunicao de dados entre funes por argumentos. Os parnteses
seguindo o nome da funo envolvem a lista de argumentos, sendo que nesse exemplo,
main uma funo sem argumentos. As chaves envolvem os comandos que formam
a funo, elas so anlogas ao BEGIN-END do Pascal. Uma funo ativada por seu
nome, seguido de uma lista de argumentos entre parnteses. Os parnteses devem estar
presentes mesmo quando no h argumentos.
A linha:
printf (Oi mundo! n);
uma chamada de funo, que chama a funo printf, com o argumento Oi mundo! n.
printf uma funo de biblioteca que imprime no terminal (a menos que outro destino
seja especificado). Nesse caso ela imprime a cadeia de caracteres que compem seu argumento.
Uma seqncia de qualquer nmero de caracteres entre aspas ... chamada cadeia
de caracteres. A seqncia n na cadeia a notao C para o caractere nova linha, que,
quando impresso provoca o avano do cursor do terminal para o inicio da prxima linha.
Se voc omitir o n, voc encontrar sua sada no terminada por uma alimentao de
linha.
printf nunca fornece uma nova linha automaticamente, de forma que mltiplas ativaes pode ser usadas para construir uma linha de sada passo a passo. Nosso primeiro
programa poderia ter sido escrito como:
#include<stdio.h>
main()
{
printf(Oi");
printf(mundo!");
printf( n");
}
O cdigo acima produziria uma sada idntica ao anterior.
O n, apresentado no cdigo anterior, representa um nico caractere. Uma seqncia
de escape tal como n prov um mecanismo geral e extensvel para a representao de
caracteres difceis de obter ou invisveis. Entre outros que C prove, esto:
n para quebra de linha,
t para tabulao,
b para retrocesso,
" para a aspa,
11
{ /* inicio de bloco */
<Comandos>
} /* fim de bloco */
12
2.1 Identificadores
Os nomes das variveis, funes, rtulos e outros objetos definidos pelo usurio, so
chamados de identificadores. Algumas observaes sobre os identificadores so importantes, como:
O primeiro caractere deve ser uma letra ou um sublinhado. Os caracteres subseqentes devem ser letras, nmeros ou sublinhados. Por exemplo: count, total23 e
peso.
Podem ter qualquer tamanho, mas os seis primeiros caracteres devem ser significativos.
Em C, letras minsculas e maisculas so tratadas diferentemente, portanto "Aula"
diferente de "aula". Case sensitive
Um identificador no pode ser igual a uma palavra chave do C.
2.2 Variveis
Uma varivel uma possio de memria que pode ser identificada atravs de um
nome. Estas podem ter seu contedo alterado por um comando de atribuio e aps a
atribuio mudam de valor.
Toda varivel tem:
um nome (identificador)
um tipo de dado
um valor
13
//...
int a,b,c;
a = 3; // a recebe o valor 3
b = a * 2; // b recebe o dobro do valor de a
c = a + b + 2; // c recebe 11
//...
Tipo
hline char
int
unsigned int
long int
unsigned long int
float
double
long double
faixa mnima
-127 a 127
-32.767 a 32.767
0 a 65.535
-2.147.483.647 a 2.147.483.647
0 a 4.294.967.295
Seis dgitos de preciso
Dez dgitos de preciso
Dez dgitos de preciso
14
func1(void)
{
int x;
x = 10;
}
func2(void)
{
int x;
x = -199;
}
No exemplo, pode-se verificar que existem duas funes (fun1 e func2). Estas possuem variveis locais com o mesmo nome, x. Dentro da func1, o valor acessvel de x
ser 10. Em func2, o valor ser -199. Ou seja, nenhuma funo tem acesso ao valor das
variveis locais de outras funes.
Ressalva-se que todas as variveis devem ser declaradas no incio das funes, e se
forem declaradas no meio do programa/funo, ocorrer um erro no processo de compilao. Outro fator importante que as variveis locais s "existem"ou esto disponveis
quando a funo est sendo executada, aps a finalizao da execuo da funo, esta rea
de memria liberada e o valor se perde.
2.5.2 Variveis Globais
As variveis globais so reconhecidas por todo o programa, e podem ser utilizadas em
qualquer trecho de cdigo. O valor destas permanece disponvel por toda a execuo do
programa.
15
#include<stdio.h>
int total;
void contas()
{
total = total + 3;
}
main()
{
int i;
total = 0;
for(i=0;i<10;i++)
contas();
printf(Total = %d n",total);
}
Pode-se verificar no cdigo exemplo que a varivel total foi declarada no incio do
programa e esta ser acessvel a todo o programa. Tanto que o seu valor inicializado
com zero na funo principal e que seu valor tambm pode ser alterado pela funo contas.
No final o programa imprimir na tela: "Total: 27".
2.6 Constantes
Constantes so valores declarados que no podem ser alterados durante a execuo do
programa. Portanto, em C as constantes referem-se a valores fixos que o programa no
pode alterar. Esta podem aparecer dentro das expresses ou podem ser declaradas, como
por exemplo:
const valor = 10;
const taxa = 1.5;
const letra = S;
Define
A diretiva define atribui a um identifcador uma string que o substituir toda a vez que
for encontrador no arquivo-fonte. Esta associa um identificador a um valor. O padro C
ANSI refere-se ao identificador como um nome de macro e ao processo de substituio
como substituio de macro (geralmente declarado com letra maiscula, sempre aps a
declarao das bibliotecas). O formato utilizado :
#define nome_da_macro valor.
Veja os exemplos:
#define VERDADEIRO 1
#define FALSO 0
#define MSG "Digite S para Sair"
16
Operador Aritmtico
+
*
/
%
-++
Ao
Subtrao
Adio
Multiplicao
Diviso
Mdulo da diviso (resto)
Decremento
Inremento
#include<stdio.h>
main()
{
int x,y;
x = 5;
y = 2;
printf(%d n",x/y);
printf(%d n",x%y);
x ++;
printf(%d n",x);
}
//mostra 2 (truncado)
// mostra 1, o resto da diviso
// x foi incrementado em 1
// mostra 6, pois x foi incrementado
Operador relacional Ao
==
Igual
!=
Diferente
<=
Menor ou igual
>=
Maior ou igual
<
Menor
>
Maior
17
#include<stdio.h>
main()
{
int i,j;
printf( nEntre com 2 nros inteiros:);
scanf(%d %d, &i, &j);
printf( n%d == %d e %d n", i, j, i==j);
printf( n%d != %d e %d n", i, j, i!=j);
printf( n%d <= %d e %d n", i, j, i<=j);
printf( n%d >= %d e %d n", i, j, i>=j);
printf( n%d < %d e %d n", i, j, i < j);
printf( n%d > %d e %d n", i, j, i > j);
}
Para fazer operaes com valores lgicos (verdadeiro e falso) temos os operadores
lgicos:
Operador lgico
&&
|| (pipes)
! (exclamao)
Ao
AND
OR
NOT
#include<stdio.h>
main()
{
int i,j;
printf( nEntre com 2 nros inteiros (0 ou 1):);
scanf(%d %d, &i, &j);
printf( n%d AND %d %d n", i, j, i && j);
printf( n%d OR %d %d n", i, j, i || j);
printf( n NOT %d %d n", i,!i);
}
18
Operador binrio Ao
!(exclamao)
NOT
&
AND
| (pipe)
OR
XOR
Complemento de 1
Desloca p/direita
Valor de x
7
14
112
192
96
24
!
&&
!!
= += -= *= /=
19
Formato
Um caracter (char)
Um nmero inteiro decimal (int)
Nmero em notao cientfica com o "e"minsculo
Nmero em notao cientfica com o "e"maisculo
Ponto flutuante decimal
Escolhe automaticamente o melhor entre %f e %e
Escolhe automaticamente o melhor entre %f e %E
Nmero octal
String
Decimal "unsigned"(sem sinal)
Hexadecimal com letras minsculas
Hexadecimal com letras maisculas
Imprime um %
Ponteiro
Exemplo:
Cdigo
printf ("Um %%%c %s",c,"char");
printf ("%X %f %e",107,49.67,49.67);
printf ("%d %o",10,10);
Imprime
Um %c char
6B 49.67 4.967e1
10 12
20
Imprime
|456.67 |
| 2.67|
|Ola
|
Formato
Um caracter (char)
Um nmero inteiro decimal (int)
Um short it
Um long int
Nmero em notao cientfica
Ponto flutuante decimal
Um double
String
Inteiro curto
Hexadecimal com letras minsculas
Ponteiro
21
#include<stdio.h>
main()
{
int i;
char string1[20];
printf( nEntre com 1 nros inteiros:);
scanf(%d, &i);
sprintf(string1, Valor de i = %d", i);
puts(string1);
}
J no programa abaixo, foi utilizada a funo sscanf para converter a informao armazenada em string1 em seu valor numrico:
#include<stdio.h>
main()
{
int i,j,k;
char string1[]=10 20 30;
sscanf(string1,"%d %d %d", &i, &j, &k);
printf("Valores lidos: %d, %d, %d", i, j, k);
}
2.12 Exerccios
1. Faa um programa que receba dois valores do tipo inteiro e efetue as quatro operaes
bsicas, mostrando o resultado no final das quatro.
2. Faa um programa que receba o nome do usurio, quatro notas e calcule a mdia do
aluno. A frmula da mdia final : (nota1+2*nota2+3*nota3+4*nota4)/10.
3. Faa um programa que solicite o tamanho do lado de um quadrado e calcule a rea do
mesmo, mostrando o resultado.
22
_
23
3.1 if/else
Execuo condicional de comandos. A instruo if causa a execuo de uma ou de
um conjunto de instrues, dependendo do valor resultante de uma expresso avaliada.
Sintaxe:
if (expresso)
comando1;
[else]
[comando2; ]
Se a expresso for verdadeira, executa o comando1, caso contrrio executa o comando2. Se comando1 ou comando2 tiverem mais de uma instruo deve-se criar blocos
usando e .
Exemplo:
if (n != 0)
x = a*b/n;
else {
n = x*x;
x = a*b/n;
}
As instrues de execuo condicional dependem da avaliao de uma expresso condicional. Esta expresso composta por vrias operaes, que so efetuadas atravs dos
operadores lgicos e relacionais (ou mesmo atribuies e operaes matemticas), devolvendo um valor booleano TRUE ou FALSE. O C no possui o tipo boolean e no atribui
conceito abstrato para VERDADEIRO e FALSO. Para o C V ou F representado por um
valor inteiro, com o seguinte significado:
0 - FALSO (FALSE),
No Zero - VERDADEIRO (TRUE).
Ou seja, para o C, o valor 0 considerado FALSO, enquanto que todos os demais valores (-1, 1, 2, 1000, -1000, etc) so considerados VERDADEIROS. Quando o C precisa
CALCULAR uma expresso, atribuindo o conceito de V ou F, ele usar SEMPRE o valor
1 para Verdadeiro e o valor 0 para FALSO. Assim fica fcil entender o que ocorre nestes
exemplos:
24
main()
{
int x, y, r;
x = 20;
y = 10;
r = x > y; /* Sim, o x maior que y. Ento esta sentena
considerada como VERDADEIRA. O C ir avaliar ela como
tendo resultado 1 (VERDADEIRO). r recebe 1, portanto */
if (x)
{ // x vale 20. 20 para o C conceito de VERDADEIRO.
r = 0;
}
r = y + ((x>y) && (y > 0));
/* complicou, no? Temos uma sentena AND que ser
calculada como sendo VERDADEIRA (1) ou FALSA (0).
Como x maior que y (V, 1) e y maior que 0 (V),
a sentena (x>y) && (y > 0) VERDADEIRA,
valendo 1. y + 1 = 11. r receber 11.*/
}
Devido clausula else ser opcional, pode existir uma ambigidade no uso de ifelse
aninhado. O compilador resolve isto associando o else ao ltimo if sem else. Por exemplo:
if (n>0)
if (a>b)
z=a;
else
z=b;
Se a>b, ento z=a, quando n>0. Se a<=b, ento z=b, quando n>0. Se n<=0, o valor de
z no ser alterado nesta poro de cdigo.
Entretanto se tivermos:
if (n>0)
{
if (a>b)
z=a;
}
else
z=b;
Se a>b, ento z=a, quando n>0. Se n<=0, ento z=b. Se n>0 e a<=b, o valor de z no
ser alterado nesta poro de cdigo.
25
3.2 while
Enquanto a condio descrita pela expresso for satisfeita (ou seja, verdadeira), o
comando ser repetido. O comando somente ser executado se a expresso condicional
for verdadeira. A avaliao da expresso realizada da mesma forma que no comando
if. O comando while o nico e o principal comando de repetio realmente necessrio,
sendo que pode substituir qualquer outra construo do tipo: for, repeat/until, do/while,
goto ...).
Sintaxe:
while (expresso)
comando1;
Exemplo: contagem de bits setados na varivel n.
bits = 0;
while (n != 0)
{
if (n & 1)
bits++;
n = 1;
3.3 for
O comando for serve para a execuo de um nmero fixo de vezes (ou no), enquanto
uma varivel percorre uma determinada faixa de valores. Esta varivel chamada de
varivel de ndice.
Sintaxe:
for (inicio; condio; modific)
comando;
Onde temos "incio"como sendo uma expresso que ir gerar o valor inicial da varivel de ndice utilizada pelo comando. A "condio"ir indicar uma condio para o
prosseguimento do lao (enquanto tal condio for verdadeira ir repetir o lao). E finalmente "modific"ser o comando dado a cada execuo do lao, sendo este realizado ao
final de um lao do for, modificando o valor da varivel de ndice, antes de um novo teste
da condio. Cada um destes elementos (incio, condio e comando) pode ainda estar
dividido em sries de comandos, como nas expresses do if.
Exemplo: nmeros mpares de 3 a 21, com for:
for (i = 3; i <= 21; i = i+2)
printf("%d n", i);
26
Para criarmos um lao infinito (sem fim) podemos fazer um comando da seguinte
forma: for(;;) - comando sem expresses de controle. O comando for equivalente a
seguinte estrutura:
while (condio)
{
comando;
modific;
}
3.4 do/while
O comando do/while o inverso do comando while, ou seja, o teste executado ao
final deste ao invs de ser no incio. Este comando tambm equivalente ao comando
repeat/until (Pascal) s que a expresso avaliada em um estaria negada em relao ao
outro.
Sintaxe:
do
comando; } while (expresso);
O comando ser executado e depois ser testada a condio dada pela expresso, e
caso esta seja verdadeira (TRUE) ser novamente executado o comando.
3.6 switch/case
Faz uma associao de valores com comandos a executar. Conforme o valor dado,
executa um certo nmero de instrues. Serve como uma estrutura mais sofisticada que
os ifs encadeados.
Sintaxe:
switch (varivel)
{
case <valor1> : <comando1>;
case <valor2> : <comando2>;
27
<comando3>;
...
[ default : comando4; ]
}
No comando switch no possvel definir intervalos para os quais o comando ser
executado, temos que definir os valores textualmente, um a um. Os valores utilizados no
case devem ser do tipo inteiro ou char.
O uso do comando break muito importante quando associado ao switch, pois caso
este no seja usado a cada case, ser feita a execuo de todos os comandos at encontrar
o fim do switch, sendo executado inclusive o default, se houver. Por isso a estrutura
comumente usada em um comando case :
case A:
x++;
break;
case b:
case B:
y++;
break;
...
3.8 Exerccios:
1. Escrever um programa que solicite dois numeros ao usurio. O programa deve comparar os valores e imprimir na tela os dois nmeros digitados, a soma deles, o maior e
o menor deles.
2. Escrever um programa que recebe trs numeros inteiros (a, b e cod) e imprima na tela:
a+b, se cod >= 0;
a-b, se cod < 0.
3. Fazer uma funo que receba um nmero (do teclado) e retorne o fatorial deste nmero
(exemplo 5!= 5*4*3*2*1;), usando comandos de repetio (Lembre que os fatoriais
de 0 e de 1 so iguais a 1). Deve pedir para o usurio repetir a entrada se o nmero
que ele digitou for negativo. Deve ser capaz de calcular fatoriais maiores que 65535,
limite para um inteiro.
28
4. Faa um programa completo que leia do teclado 10 nmeros inteiros e depois imprima:
a) A soma de todos os elementos
b) O maior e o menor elemento
5. Escrever um trecho de cdigo, usando atribuio condicional, que teste o contedo de
duas variveis e atribua o maior valor a uma terceira varivel.
6. Faa um programa para calcular o valor de , dado por:
8. O valor aproximado de
!
#"$ , implemente um programa que calcule o valor de
Sendo
, baseado
nos n primeiros elementos dessa srie. O n deve ser informado pelo usurio, quanto
maior esse numero, mais preciso ser o valor de .
29
4 MATRIZES
Uma matriz uma coleo de variveis do mesmo tipo, e esta referenciada por um
nome comum. Cada elemento de uma matriz acessado atravs de um ndice. O ndice
0 corresponde ao primeiro elemento de uma matriz, e o ndice mais alto, representa o
ltimo elemento de uma matriz.
Basicamente existem alguns tipos de matrizes:
Matrizes Unidimensionais: So matrizes de apenas uma dimenso, e so geralmente chamadas de vetores ou listas (estticas).
Matrizes Bidimensionais: So matrizes de duas dimenses.
Matrizes Multidimensionais: So matrizes de n dimenses.
A forma geral de se declarar uma matriz unidimensional :
tipo nomevar [tamanho];
Por exemplo, se quisermos declarar um vetor (matriz unidimensional) com o nome
teste que armazena 10 nmero inteiros, teramos que definir o tipo (int) e o tamanho do
vetor (10). Ressalva-se que o primeiro ndice de um vetor em C sempre ser o 0. Ou seja,
os ndices deste vetor iriam de 0 a 9, onde tm-se 10 posies. A declarao do vetor
ficaria assim: int teste[10];
Criando um vetor de 3 posies do tipo double, pode-se analisar como fazer o acesso
a cada ndice. Vejamos:
Exemplo 1:
main()
{
double vetor[3];
vetor[0]=3.9;
vetor[1]=4.9;
vetor[2]=0.7;
printf("O valor do primeiro elemento eh:%lf n",vetor[0]); /*Sera impresso 3.9*/
printf("O valor do ultimo elemento eh:%lf n",vetor[2]); /*Sera impresso 0.7*/
}
Quando o C v uma declarao como esta ele reserva um espao na memria suficientemente grande para armazenar o nmero de clulas especificadas em tamanho. Por
exemplo, se declararmos:
30
4.1 Strings
Strings so vetores de caracteres, chars. As strings so o uso mais comum para os
vetores. As strings tm o seu ltimo elemento como um 0. A declarao geral para
uma string : char nome-da-string [tamanho];
Uma constante string uma lista de caracteres entre aspas. Por exemplo: Oi Mundo.
Neste caso, no necessrio adicionar o nulo no final das constantes strings manualmente
31
Existem diversas funes para trabalharmos com strings, estas necessitam que no cabealho seja declarada a biblioteca <string.h>.
A tabela 4.1 apresenta as principais funes de manipulao e tratamento de strings:
Nome
strcpy(s1,s2)
strcat(s1,s2)
strlen(s1)
strcmp(s1,s2)
strchr(s1,ch)
strstr(s1,s2)
Funo
Copia s2 em s1.
Concatena s2 ao final de s1.
Retorna o tamanho de s1.
Retorna 0 se s1=s2; menor que 0 se s1<s2; maior que 0 se s1>s2.
Retorna um ponteiro para a primeira ocorrncia de ch em s1.
Retorna um ponteiro para a primeira ocorrncia de s2 em s1.
Tabela 4.1: Manipulao de Strings
Abaixo segue um exemplo de utilizao de algumas funes, as quais utilizam a biblioteca string.h. Cabe ressaltar que existem ainda diversas funes j desenvolvidas as
quais fazem parte da biblioteca. No exemplo, o contedo da string s1 lido do usurio,
e o contedo de s2 atribudo atravs da funo strcpy. A funo strlen ir imprimir o
tamanho de cada string, e a funo strcmp ir comparar se os contedos de s1 e s2 esto
iguais.
32
Exemplo 4:
#include<stdio.h>
#include<string.h>
main()
{
char s1[80],s2[80];
printf (" n Digite uma string qualquer: ");
gets(s1);
strcpy(s2,"Programa Exemplo");
printf(s2);
printf(" n Tamanho: %d %d",strlen(s1),strlen(s2));
if (!strcmp(s1,s2))
printf(" n As strings so iguais n");
else printf (" n As strings so diferentes! n");
}
0
0
0
0
0
9
0
0
Abaixo damos um exemplo do uso de uma matriz, onde a matriz mtrx preenchida,
seqencialmente por linhas, com os nmeros de 1 a 200.
33
Exemplo 5:
#include <stdio.h>
main ()
{
int mtrx [20][10];
int i,j,count;
count=1;
for (i=0;i<20;i++)
for (j=0;j<10;j++)
{
mtrx[i][j]=count;
count++;
printf(" n Linha:%d Col:%d INT:%d n",i,j,mtrx[i][j]);
}
}
34
4.6 Exerccios:
1. A avaliao em um colgio feita atravs de 3 notas. Como a turma pequena, existem
apenas 4 alunos inscritos. Faa um programa que receba as notas dos 4 alunos e
indique a mdia de cada um deles, mostrando as suas notas individualmente. Depois
disso, o programa ainda deve indicar a maior mdia.
2. Faa um programa que tenha um vetor de 20 posies de inteiros positivos. Este deve
receber do usurio os valores, valid-los e armazen-los. O programa deve apenas
imprimir na tela os nmeros inseridos em posies de ndices mpares do vetor.
3. Faa um programa que recebe 8 nmeros e o armazene em um vetor (entrada). Aps
a leitura dos nmeros, deve ser armazenado em outro vetor a raiz quadrada de cada
nmero do vetor de entrada. Imprima as raizes na tela.
4. Fazer o programa que leia o nome do usurio e diga quantas letras este nome tem.
5. Fazer um programa que recebe duas palavras e diz se estas strings so iguais.
6. Fazer um programa que recebe quatro nomes e diz quantos deles comeam com a letra
L e quantos com a letra T.
7. Fazer um programa que recebe separadamente o primeiro nome, o segundo nome e o
ltimo nome de uma pessoa. O programa deve concatenar estes nomes e imprimi-lo
no final.
8. Fazer o programa que leia uma matriz 4x4 e imprima a mdia dos elementos.
9. Fazer o programa que leia uma matriz 6x6 e imprima a mdia dos elementos da diagonal principal (linha=coluna) e tambm a mdia dos elementos da diagonal secundria (linha + coluna == nro_de_linha ).
10. Fazer um programa que recebe uma matriz A 2x2 e uma matriz B 2x2, e crie uma
terceira matriz C 2x2, a qual composta pelos elementos multiplicados de AB.
35
11. Fazer uma programa que gere (sem o usurio digit-la) e imprima na tela a seguinte
matriz:
1
1
1
1
1
1
1
2
2
2
2
1
1
2
3
3
2
1
1
2
3
3
2
1
1
2
2
2
2
1
1
1
1
1
1
1
36
5.1 Estruturas
Matrizes so estruturas de dados homogneos, isto , podem conter colees de dados
do mesmo tipo (todos int, todos float, todos char). Na vida real encontramos muitas
situaes onde temos colees de dados que so de tipos diferentes. Como exemplo
temos uma ficha de cadastro de funcionrio, uma cdula de identidade, uma inscrio em
uma concurso, uma cadastro de usurio em um site, etc.
Num cadastro de usurio temos dados como nome, endereo, telefone, e-mail, data
de nascimento, entre outros. Pode-se notar que esses dados so de tipos diferentes. Para
agrupar esses dados no nos serve uma matriz. H necessidade de uma estrutura de dados
heterogneos, definida pelo usurio.
As estruturas (struct) so agrupamentos de dados, que definem um novo tipo de dado
mais complexo, formado por tipos de dados mais simples.
struct nome_do_tipo_da_estrutura {
tipo-var nome-var;
tipo-var nome-var2;
...}variveis_estrutura;
37
_____estrutura de endereo:
struct tipo_endereco {
char rua [50];
int numero;
char bairro [20];
char cidade [30];
char sigla_estado [3];
long int CEP;
};
*Estrutura ficha_pessoal
para adicionar os dados pessoais de algum:*
struct ficha_pessoal {
char nome [50];
long int telefone;
struct tipo_endereco endereco;
};
_____Programa Principal____
void main (void){
struct ficha_pessoal ficha;
strcpy(ficha.nome,"Luiz Osvaldo Silva");
ficha.telefone=33332234;
strcpy(ficha.endereco.rua,"Rua dos Flores");
ficha.endereco.numero=10;
strcpy(ficha.endereco.bairro,"Menino Deus");
strcpy(ficha.endereco.cidade,"Porto Alegre");
strcpy(ficha.endereco.sigla_estado,"RS");
ficha.endereco.CEP=90000000;
}
Esse programa declara uma varivel ficha do tipo ficha_pessoal e preenche os seus dados. O exemplo mostra como podemos acessar um elemento de uma estrutura: basta usar
o ponto (.). Assim, para acessar o campo telefone de ficha, escrevemos: ficha.telefone
= 33332234; Como a struct ficha pessoal possui um campo, endereo, que tambm
uma struct, podemos fazer acesso aos campos desta struct interna da seguinte maneira:
ficha.endereco.numero = 10; ficha.endereco.CEP=90000000; Desta forma, estamos acessando, primeiramente, o campo endereco da struct ficha e, dentro deste campo, estamos
acessando o campo numero e o campo CEP.
Caractersticas das estruturas:
38
5.1.1 Exerccios
a) Faa um programa que define um tipo para alunos com os seguintes campos: nome
(20 caracteres), cdigo (10 caracteres), notas de 3 provas e mdia final. O programa
dever ler da entrada padro os dados de 4 alunos, calcular a mdia individual de
cada aluno e a mdia geral dos alunos.
b) Modifique o exerccio anterior, mas permita que o usurio fornea antes o nmero
total de alunos que deseja digitar.
c) Considere uma bilhete de passagem de nibbus, conforme mostrado na tabela 5.1. Primeiro - Defina uma estrutura de dados de nome Passagem. Segundo - Considerando
uma onibus de 48 lugares, defina um vetor de Passagens.
Nome da Empresa:___________
Destino:___________________
Horrio:____:____
Distncia: ____km
5.2 Unies
Uma declarao union determina uma nica localizao de memria onde podem
estar armazenadas vrias variveis diferentes. A declarao de uma union semelhante
declarao de uma estrutura:
39
union nome_do_tipo_da_union {
tipo_1 nome_1;
tipo_2 nome_2;
...
tipo_n nome_n;
} variaveis_union;
Nela, temos duas variveis (graus e radianos) que, apesar de terem nomes diferentes,
ocupam o MESMO local da memria. Isto quer dizer que s gastamos o espao equivalente a um nico float. Unies podem ser feitas tambm com variveis de diferentes tipos.
Neste caso, a memria alocada corresponde ao tamanho da maior varivel no union. Veja
o exemplo:
#include <stdio.h>
#define GRAUS G
#define RAD R
union angulo {
int graus;
float radianos;
};
main()
{
union angulo ang;
char op;
printf(" n Numeros em graus ou radianos? (G/R):");
scanf("%c",&op);
if (op == GRAUS) {
ang.graus = 180;
printf(" nAngulo: %d n",ang.graus);
}
else if (op == RAD){
ang.radianos = 3.1415;
printf(" nAngulo: %f n",ang.radianos);
}
else printf(" nEntrada invalida!! n");
}
40
5.3 Enumeraes
Numa enumerao podemos dizer ao compilador quais os valores que uma determinada varivel pode assumir. Sua forma geral :
enum nome_do_tipo_da_enumerao
{
lista_de_valores
} lista_de_variveis
Exemplo:
#include <stdio.h>
enum dias_da_semana {
segunda,
terca,
quarta,
quinta,
sexta,
sabado,
domingo};
main()
{
enum dias_da_semana d1,d2;
d1=segunda;
d2=sexta;
if (d1==d2)
printf (O dia o mesmo);
else printf (So dias diferentes);
}
Voc deve estar se perguntando como que a enumerao funciona. Simples, o compilador pega a lista que voc fez de valores e associa, a cada um, um nmero inteiro.
Ento, ao primeiro da lista, associado zero, ao segundo 1 e assim por diante. As variveis declaradas so ento variveis inteiras.
41
6 FUNES
6.1 Modularidade
Modularidade a tcnica de programar, desenvolvendo um programa a partir de pequenas partes ou mdulos. Em C, construir um mdulo significa construir uma funo.
Inicialmente, modularizar um programa parece dificultar a programao. Mas o que
acontece no desenvolver de qualquer programa o contrrio. As vantagens de se modularizar so: economia de tempo de criao do programa, economia de tempo de manuteno
do programa, reutilizao de mdulos, organizao do cdigo e construo de bibliotecas.
42
#include<stdio.h>
#include<math.h>
void raiz(double x)
{
printf("%lf",sqrt(x));
}
main()
{
double nro;
printf("Digite um numero");
scanf("%lf",&nro);
raiz(nro);
}
43
#include<stdio.h>
void diferenca(int x, int y)
{
printf("%d",x-y);
}
main()
{
diferenca(10,0); /*Imprimir 10 na Tela*/
diferenca(0,10); /* Imprimir -10 na Tela*/
}
#include <stdio.h>
int Square (int a)
{
return (a*a);
}
main ()
{
int num;
printf ("Entre com um numero: ");
scanf ("%d",&num);
num=Square(num);
printf ("O seu quadrado vale: %d",num);
}
44
#include <stdio.h>
void Mensagem (void)
{
printf ("Ola! Eu estou vivo.");
}
int main ()
{
Mensagem();
printf ("Diga de novo:");
Mensagem();
return 0;
}
No exemplo acima, chama-se duas vezes a funo Mensagem. Esta declarada para
retornar um tipo void, ou seja, no retornar valor nenhum, apenas imprimir uma mensagem. Alm disso, dentro da lista de parmetros passamos ainda o tipo void, que siginifica
que nenhum valor ser passado por parmetro tambm.
45
parmetro foi feita por valor, o valor de num no ser alterado quando voltar a funo
main. Logo, este parmetro funciona como uma varivel local dentro da funo, pois o
valor num da funo principal foi copiado para a varivel num da funo sqr.
6.7.2 Chamada por Referncia
Neste tipo de chamado os parmetros podem ser alterados dentro da funo, mantendo
este valor para a funo que o chamou. Este nome vem do fato de que, neste tipo de
chamada, no se passa para a funo os valores das variveis, mas sim suas referncias (a
funo usa as referncias para alterar os valores das variveis fora da funo).
O C s faz chamadas por valor. Isto bom quando queremos usar os parmetros formais vontade dentro da funo, sem termos que nos preocupar em estar alterando os
valores dos parmetros que foram passados para a funo. Mas isto tambm pode ser
ruim s vezes, porque podemos querer mudar os valores dos parmetros fora da funo
tambm. O C++ tem um recurso que permite ao programador fazer chamadas por referncia (deve-se utilizar o compilador g++ para isto). H entretanto, no C, um recurso de
programao que podemos usar para simular uma chamada por referncia.
Quando queremos alterar as variveis que so passadas para uma funo, ns podemos declarar seus parmetros formais como sendo ponteiros. Os ponteiros so a "referncia"que precisamos para poder alterar a varivel fora da funo. O nico inconveniente
que, quando usarmos a funo, teremos de lembrar de colocar um & na frente das variveis que estivermos passando para a funo.
O que so ponteiros? "Ponteiro uma varivel que contm um endereo de memria.
Esse endereo normalmente a posio de uma outra varivel na memria. Se uma
varivel contm o endereo de memria da outra, ento a primeira varivel dita apontar
para a segunda. "
Veja um exemplo:
#include <stdio.h>
void Swap (int *a,int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
void main (void)
{
int num1,num2;
num1=100;
num2=200;
Swap (&num1,&num2);
printf ("Eles agora valem %d %d",num1,num2);
}
O que est acontecendo que passamos para a funo Swap o endereo das variveis
num1 e num2. Estes endereos so copiados nos ponteiros a e b. Atravs do operador
* estamos acessando o contedo apontado pelos ponteiros e modificando-o. O contedo
46
nada mais do que os valores armazenados em num1 e num2, que, portanto, esto sendo
modificados!
6.7.3 Matrizes como Argumentos de Funes
Se declaramos uma matriz de 50 posies, existem basicamente trs maneiras de passarmos ela por parmetro para uma funo, so elas:
void func (int matrx[50]);
void func (int matrx[]);
void func (int *matrx);
Nos trs casos, teremos dentro de func() um int* chamado matrx. Ao passarmos um
vetor para uma funo, na realidade estamos passando um ponteiro. Neste ponteiro
armazenado o endereo do primeiro elemento do vetor. Isto significa que no feita
uma cpia, elemento a elemento do vetor. Isto faz com que possamos alterar o valor dos
elementos do vetor dentro da funo.
Para chamarmos a funo func passando a matriz mt2 de 50 posies, podemos seguir
o seguinte exemplo:
func(mt2);
Muito embora o parmetro mt2 seja declarado como uma matriz de inteiros, o compilador C converte-o para um ponteiro de inteiros. Portanto, seu endereo passado para
a funo. Neste caso, o cdigo dentro da funo estar operando com, e potencialmente
alterando, o contedo real da matriz usada para chamar a funo.
47
6.9 Exerccios
1. Desenvolva uma funo, que receba trs notas e devolva a sua mdia.
2. Desenvolva uma funo que receba trs notas (p1, p2 e p3) e devolva a mdia no
argumento p3.
3. Construa uma funo C que recebe, por parmetro, um valor n, inteiro e positivo, e
escreve os seus divisores.
4. Contrua uma funo que recebe um vetor de x elementos preenchidos, e ordene o
vetor.
5. Desenvolva uma funo em C que recebe o gabarito da LOTO e uma aposta (no
mximo 10 dezenas) e devolve o nmero de pontos da aposta.
6. Desenvolver um algoritmo com uma funo que recebe um vetor e sua dimensio
e devolve o percentual de valores do vetor que so menores do que a mdia dos
valores deste vetor.
7. Dado a funo abaixo, responda:
int func(int n)
{
if (n)
return n*func(n-1);
else return 1;
}
48
7 APONTADORES
Valor Nome
209
teste
000
34
cont
e
texto
x
e
m
p
l
o
0
?
?
...
xx
Temos, ento, que um label, ou seja, um nome de varivel que aponta para o incio de
uma rea de memria reservada para si, cujo tamanho depende do tipo. Ou seja, para o
tipo int, so reservados 2 bytes (em algumas arquiteturas so 4 ou mesmo 8 bytes), para
o tipo char apenas um e para a string texto, so reservados tantos bytes quantos forem
49
pt = 12;
50
char car,a[10],*ptr;
ptr = a;
//ptr aponta para o endereo de a[0]
ptr = &(a[0]);
//igual ao exemplo anterior a = &a[0]
car = *(ptr);
//car recebe o contedo de a[0]
int var[5],*pint;
pint = var;
pint = (var+2);
Como j pode ser visto, a indexao dos arrays feita na mesma maneira em que se
trata com ponteiros. Ento, incrementar um ponteiro significa somar ao endereo atual
tantas unidades quanto for o tamanho do tipo de dado apontado, assim como o endereo
de um elemento de um array pode ser obtido apenas somando-se tantas unidades quanto
for o tamanho do elemento do array.
Portanto podemos fazer somas e incrementos com ponteiros operando-os como se
fossem meros endereos. Sendo que no caso de incrementos, o acrscimo ser feito de
acordo com tipo de dado ao qual o ponteiro atua (soma tantos bytes quanto for o tamanho
do tipo).
Como foi visto, apontadores acessam diretamente a memria do micro, por isso constituem uma ferramenta poderosa mas ao mesmo tempo perigosa, pois um descuido qualquer pode causar srios danos. Sempre que formos usar um ponteiro ele j dever ter sido
inicializado, ou seja, j deve ter sido atribudo algum endereo a ele.
Arrays, algumas informaes extras ...
A diferena entre um array e um ponteiro que quando definimos um array, uma
rea de memria reservada para ele e quando definimos um apontador, no h
alocao de memria. Exemplo:
char *string
-> reserva rea somente para o pointer (2/4 bytes)
char string[10] -> reserva rea para 10 caracteres (10 bytes)
Arrays so passados como parmetros para funes como sendo um ponteiro para
o incio do array.
Como conseqncia do modo de alocao de arrays de mais de uma dimenso,
quando for passado como parmetro o array, temos que indicar as outras dimenses,
exceto a principal. Isto se d pelo fato de que passado apenas o endereo inicial
do array, que tratado como um vetor linear. Sem a indicao das outras dimenses
no conseguimos distinguir os elementos de uma ou de outra dimenso. Exemplo:
funo (a)
int a[ ][10];
51
main ()
{
int a=8;
quadrado(&a);
printf("A resposta foi %d n", a);
}
Observe que a passagem continua sendo por valor porque o que foi passado no o
valor inteiro, mas sim o seu endereo, e este endereo no pode ser mudado dentro da
funo. Veja pelo exemplo a seguir:
int x=34;
int quadrado (int a)
{
a=( a) ( a);
a=&x;
printf("A tem o valor %d n", a);
return(1);
}
//varivel global
main ()
{
int a=8;
quadrado(&a);
printf("A resposta foi %d n", a);
}
52
main ()
{
int a=8, b;
b=&a;
quadrado(b);
printf("A resposta foi %d n", a);
printf("A resposta foi %d n", b);
}
No exemplo acima, criou-se uma varivel do tipo apontador para inteiros e fez-se com
que ela recebesse o endereo de a. A varivel b j contem o endereo de uma rea de
memria e portando a passagem de parmetro feita simplesmente pelo seu nome. Por
fim, imprimir o valor de a ou o valor da posio apontada por b resultar no mesmo valor,
pois b aponta para a.
Portanto, sempre que desejar passar algum valor por referncia, deve-se passar o endereo deste valor, se desejar-se passar o prprio endereo por referncia, deve-se passar
o endereo do endereo. Mais adiante sero vistos outras utilidades para ponteiros.
53
#include <stdio.h>
main()
{
int *vet;
int tamanho,i;
printf("Quantos elementos vc vai digitar? n ");
scanf("%d", &tamanho);
vet = (int *)malloc (tamanho * sizeof(int));
if (!vet) { se vetor vazio (not vetor)...
printf("Erro na reserva de memria n");
return(0);
}
/* usa-se vet como vet[0], vet[1], ... vet[tamanho-1] */
}
Vetores estticos e dinmicos, como j dito, so praticamente o mesmo para o C,
e podem ser manipulados de forma semelhante. Vamos analisar por partes o exemplo
acima.
Ao criarmos o apontador vet, ele ter algum endereo de memria e podera-mos uslo. Mas, este espao em memria pode estar sendo usado por outro, pois no o reservamos
para nosso uso exclusivo (que o que fazemos com int vet[20]). Poderia ser desastrosa a
utilizao nestes termos.
Reservar um espao em memria de uso exclusivo nosso o que tenta fazer o comando
malloc. Digo tenta, porque ele pode no conseguir, por exemplo, caso no haja memria
suficiente. O malloc s reserva espao em bytes e retorna um apontador para este endereo
do tipo void. Por isso que para o compilador aceitar, devemos usar um cast no incio para
o tipo que estamos usando (no caso, int). Como a reserva em bytes, devemos reservar a
quantidade de bytes que reflita a nossa necessidade. No exemplo, temos uma necessidade
de tamanho elementos, sendo que cada elemento do tipo int, o espao que precisamos
de tamanho sizeof(int).
O malloc retorna o endereo reservado se conseguiu ou 0, (NULL) se falhou.
extremamente recomendvel testar seu retorno antes de usar.
No correto afirmar que o malloc cria variveis dinmicas, pois ele apenas reserva
espao deixando sobre a inteira responsabilidade do programador o gerenciamento desta
rea Logo, se o programador fizer mal uso, azar o dele!!! Podemos considerar um pssimo
uso o exemplo a seguir:
#include <stdio.h>
main()
{
int *vet;
int tamanho=20,i;
vet = (int *)malloc (tamanho * sizeof(int));
if (!vet) {
printf("Erro na reserva de memria n");
return(0);
}
vet = &i;
}
54
7.3 Exerccios:
1) Implemente a funo my_strcmp(), semelhante a strcmp() mas apenas retornando 0 se
forem iguais e diferente de zero se no.
2) Faa uma funo para somar dois vetores. A funo deve receber 3 vetores (os 2
vetores a serem somados e o vetor que receber a soma) e o tamanho dos vetores e
deve retornar a mdia dos valores somados (int).
3) Faa uma funo que copie X caracteres para uma outra cadeia de caracteres. A funo
dever retornar o nmero de caracteres efetivamente copiados (pode ser <que x que
a string origem terminar antes). Chamada:
char a[50], b[50], tam;
/* atribua um texto qualquer a a */
tam=copia(b,a,10);
/* copia no maximo 10 caracteres de a para b.
Se a string de a tiver s 5, copia apenas os cinco */
4) Faa um programa que crie dois vetores dinmicos de mesmo tamanho. O tamanho
deve ser passado por parmetro na execuo do programa. O usurio, ao executar
o programa, deve digitar todos os elementos de um dos vetores. Depois que todos
os elementos foram digitados, os elementos do segundo vetor deve ser calculado
da seguinte forma vet2[0]=tamanho-vet1[0], vet2[n]=tamanho-vet1[n]. Finalmente
imprima ambos os vetores.
55
8 ARQUIVOS
8.1 Introduo
O padro C ANSI define um conjunto completo de funes de E/S que pode ser utilizado para ler e escrever qualque tipo de dado.
O sistema de arquivos em C projetado para trabalhar com diversos tipos de dispositivos. O sistema de arquivo com buffer transforma-se em um dispositivo lgico chamado
de stream. Existem dois tipos de streams: texto e binria. Uma stream de texto uma
sequncia de caracteres. J uma stream binria uma sequncia de bytes com alguma
correspondncia.
8.2 Arquivos
Deve-se associar uma stream com um arquivo especfico e para isso tambm precisamos realizar uma operao de abertura. Depois do arquivo aberto, troca-se informaes
entre ele e o programa. Cada stream associada a um arquivo tem uma estrutura de controle do tipo FILE (stdio.h). Alm disso, cada vez que o arquivo aberto, tambm
inicializado o indicador de posio no arquivo. Quando um caractere lido ou escrito no
arquivo, o indicador de posio incrementado.
8.3 Funes
O sistema de arquivos C ANSI composto de diversas funes inter-relacionadas. As
mais comuns so mostradas na Tabela 8.1:
8.3.1 Ponteiro de Arquivo
O ponteiro de arquivo um ponteiro para informaes que definem coisas sobre o
arquivo (nome, status e posio atual do arquivo). Este indentifica um arquivo especfico
em disco e usado pela stream associada para direcionar as operaes de E/S. Para obter
uma varivel ponteiro de arquivo, a sintaxe a seguinte:
FILE *fp;
8.3.2 Abrindo um arquivo (fopen)
A funo fopen( ) abre uma stream para uso e associa um arquivo a ela, retornando
um ponteiro associada ao arquivo. A sintaxe da funo :
FILE *fopen(const char* nomearq, const char* modo);
Em modo devemos indicar como o arquivo dever ser aberto. Um arquivo pode ser
56
Nome
fopen( )
fclose( )
putc( )
fputc( )
getc( )
fgetc( )
fseek( )
fprintf( )
fscanf( )
feof( )
ferror( )
rewind( )
remove( )
fflush( )
Funo
Abre um arquivo
Fecha um arquivo
Escrever um caractere em um arquivo
O mesmo que putc( )
L um caractere de um arquivo
O mesmo que getc( )
Posiciona o arquivo em um byte especfico
para um arquivo o que um printf( )
para um arquivo o que o scanf( ) para o console
Devolve verdadeiro se o fim de arquivo for atingido
Devolve verdadeiro se ocorreu um erro
Recoloca o indicador de posio de arquivo no incio do arquivo
Apaga um arquivo
Descarrega um arquivo
Tabela 8.1: Funes para Arquivos
aberto em modo texto ou binrio. A tabela 8.2 mostra os modos os quais podemos abrir
os arquivos.
Modo
r
w
a
rb
wb
ab
r+
w+
a+
r+b
w+b
a+b
Significado
Abre um arquivo-texto para leitura
Cria um arquivo-texto para escrita
Anexa a um arquivo-texto
Abre um arquivo binrio para leitura
Cria um arquivo binrio para escrita
Anexa a um arquivo binrio
Abre um arquivo-texto para leitura/escrita
Cria um arquivo-texto para leitura/escrita
Anexa/cria um arquivo texto para leitura/escrita
Abre um arquivo binrio para leitura/escrita
Cria um arquivo binrio para leitura/escrita
Anexa a um arquivo binrio para leitura/escrita
57
...
FILE *fp;
if((fp=fopen("prog4all","w"))==NULL) {
printf("O arquivo no pode ser criado n");
exit(1);
}
...
A funo fclose( ) fecha uma stream que foi aberta por meio de uma chamada fopen( ).
Portanto, lembre-se sempre que um arquivo for aberto, voc deve fech-lo antes do final
do programa. A sintaxe do fclose ( ) :
O padro C ANSI define duas funes para escrever caracteres: putc( ) e fputc( ). A
funo putc( ) escreve caracteres em um arquivo que foi aberto, tendo o seguinte prottipo:
A funo getc( ) ir retornar EOF quando o final do arquivo for alcanado. Para
entendermos melhor o funcionamento destas funes, vamos analisar o seguinte exemplo:
58
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
FILE *p;
char c, str[30], frase[80] = "Este e um arquivo chamado: ";
int i;
/* Le um nome para o arquivo a ser aberto: */
printf("Entre com um nome para o arquivo: n");
gets(str);
if (!(p = fopen(str,"w"))) /* Caso ocorra algum erro na abertura do arquivo..*/
{
printf("Erro! Impossivel abrir o arquivo! n");
exit(1); /* o programa aborta automaticamente */
}
/* Se nao houve erro, imprime no arquivo e o fecha ...*/
strcat(frase, str);
for (i=0; frase[i]; i++)
putc(frase[i],p);
fclose(p);
/* Abre novamente para leitura */
p = fopen(str,"r");
c = getc(p); /* Le o primeiro caracter */
while (!feof(p)) /* Enquanto no se chegar no final do arquivo */
{
printf("%c n",c); /* Imprime o caracter na tela */
c = getc(p); /* Le um novo caracter no arquivo */
}
fclose(p); /* Fecha o arquivo */
}
No exemplo, primeiro o arquivo aberto para a escrita, e imprime-se algo nele. Em
seguida, o arquivo fechado e novamente aberto para a leitura.
8.3.5 Lidando com Strings (fputs e fgets)
C suporta funes fputs( ) e fgets( ) que efetuam operaes de leitura e gravao de
strings de caracteres para um arquivo em disco. Abaixo esto os prottipos destas funes:
int fputs(const char *str, FILE *fp);
char *fgets(char *str, int length, FILE *fp);
Estas duas funes esto na biblioteca stdio.h. A funo fgets( ) l uma string da
stream especificada at que um caractere de nova linha seja lido ou que lenght-1 caracteres
tenham sido lidos. Pode-se observar um exemplo que ir inserindo strings num arquivo
at a tecla ENTER ser digitada:
59
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *pf;
char string[100];
if((pf = fopen("arquivo.txt","w")) ==NULL)
{
printf("Nao consigo abrir o arquivo ! n");
exit(1);
}
do
{
printf("Digite uma nova string. Para terminar, digite <enter>: n ");
gets(string);
fputs(string, pf);
putc( n, pf);
}while (strlen(string) > 0);
fclose(pf);
}
60
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *pf;
float pi = 3.1415;
float pilido;
if((pf = fopen("arquivo.bin", "wb")) == NULL)
/* Abre arquivo binrio para escrita */
{
printf("Erro na abertura do arquivo n");
exit(1);
}
if(fwrite(&pi, sizeof(float), 1,pf) != 1) /* Escreve a varivel pi */
printf("Erro na escrita do arquivo n");
fclose(pf); /* Fecha o arquivo */
if((pf = fopen("arquivo.bin", "rb")) == NULL)
/* Abre o arquivo novamente para leitura */
{
printf("Erro na abertura do arquivo n");
exit(1);
}
if(fread(&pilido, sizeof(float), 1,pf) != 1)
/* Le em pilido o valor da varivel armazenada anteriormente */
printf("Erro na leitura do arquivo n");
printf("O valor de PI, lido do arquivo e: %f n", pilido);
fclose(pf);
return(0);
}
61
Nome
SEEK_SET
SEEK_CUR
SEEK_END
Valor
0
1
2
Significado
Incio do arquivo
Ponto corrente no arquivo
Fim do arquivo
8.4 Exerccios
1) Fazer um programa que leia do usurio um determinado nmero de caracteres e armazeneos em um arquivo, chamado de "teste.txt". O programa deve parar de ler quando o
usurio digitar a letra A.
2) Fazer um programa que simule uma lista telefnica. O usurio poder incluir novos
registros (nome + telefone) ou apenas consult-los. importante ressaltar que ao
reiniciar o programa, o usurio deve poder visualizar telefones pr-cadastrados.
3) Fazer um programa que solicite ao usurio o nome de um arquivo de entrada. Aps
abrir este arquivo o programa deve criar outro arquivo que uma cpia do arquivo
de origem. O arquivo destino deve ser uma cpia, com algumas alteraes, so elas:
letras a so substitudas por G, letras c so substitudas por H e letras e so
substitudas pela palavra lp.
4) Faa uma rotina que recebe uma matriz A(4,4) de inteiros e retorna um vetor apenas
com os elementos cuja soma dos ndices par. Faa uma rotina que recebe o vetor
gerado na rotina anterior e armazena o vetor em um arquivo binrio. Faa uma
rotina para ler o arquivo binrio gravado e imprima as informaes na tela.
5) Faa um programa que permita inserir e visualizar o cadastro dos alunos de uma academia. As informaes a serem armazenada so: nome, idade e peso. As informaes
devem ser armazenadas em um arquivo binrio.
62
9 BIBLIOGRAFIA