Você está na página 1de 59

Apostila

de
LINGUAGEM

(Com Exerccios Adicionais)

Prof. Jorge Viana Doria Junior, M.Sc. UFRJ.


Fevereiro 2016.1

SUMRIO

PARTE I A LINGUAGEM C
Introduo Linguagem
C ..............................................................................................
Caractersticas &
histrico .............................................................................................
Caractersticas de um programa
C ................................................................................
Formato de um programa em
C .....................................................................................

04

Identificadores ...............................................................................................................
..

05

Tipos de Dados Para Variveis e


Funes ......................................................................
Standard (j definidos na
linguagem) .........................................................................
Modificadores de
tipo .................................................................................................

05

Declarao de
variveis ....................................................................................................
Variveis
locais ...........................................................................................................
Parmetros
formais ......................................................................................................
Variveis
globais .........................................................................................................
Modificadores de classe de
armazenamento ...............................................................
Variveis automticas auto modificadores de classe de armazenamento ...........
Variveis externas extern modificadores de classe de armazenamento ...............
Variveis estticas statics
........................................................................................
Varivel register
.........................................................................................................

06

Operadores ....................................................................................................................
....
Aritmticos ..............................................................................................................
....
Lgicos ou
Booleanos .................................................................................................
Relacionais ..............................................................................................................
....
Entre
bits .....................................................................................................................
Outros
operadores .......................................................................................................
Precedncia .............................................................................................................
....
Pr-processador e
diretivas .........................................................................................
Diretiva
#define .........................................................................................................

08

1
1.1
1.2
1.3

3.1
3.2

4
4.1
4.2
4.3
4.4
4.4.1
4.4.2
4.4.3
4.4.4

5
5.1
5.2
5.3
5.4
5.5
5.6
5.7
5.8

04
04
04

05
05

06
07
07
07
07
08
08
08

08
09
09
09
09
09
10
10

5.9

Diretiva #include
........................................................................................................

10

5.10

namespace, using namespace, comandos cin e cout do C++


.......................

11

6
6.1

Entrada e sada de dados pela console funes printf e scanf ....................................


printf ......................................................................................................................
.....
scanf .......................................................................................................................
.....

12
12

Instrues de
controle .......................................................................................................
O comando if
...............................................................................................................
O operador ? (substitui o
if) ........................................................................................
O comando switch
.......................................................................................................
Exerccios de
fixao ........................................................................................
O comando for
............................................................................................................
O comando while
........................................................................................................
O comando do { ... } while
..........................................................................................
O comando
continue ...................................................................................................
O comando break
........................................................................................................
O comando goto< label>
.............................................................................................
Exerccios de
fixao .......................................................................................

13

Arrays unidimensionais Vetores


...................................................................................
Exerccios de
fixao ........................................................................................
Arrays unidimensionais de caracteres Strings
................................................................
Funes getchar, putchar, getchar e gets ......................................................
Arrays bidimensionais
Matrizes ...................................................................................
Exerccios de
fixao ........................................................................................

20

10

Funes .........................................................................................................................
.....

27

11

O tipo Pointer
Ponteiro ..................................................................................................
Definio .................................................................................................................
....
Iniciao de ponteiros na
definio .............................................................................

28

6.2

7
7.1
7.2
7.3

7.4
7.5
7.6
7.7
7.8
7.9

8.1

11.1
11.2

12

13
14
14
14
15
15
16
16
17
17
19

21
22
22
24
26

28
29

11.3

Passagem de parmetros por endereo (por


referncia) ..............................................

29

12

A relao entre ponteiros e arrays


...................................................................................

30

13

Ponteiros e arrays
bidimensionais ...................................................................................
Arrays
tridimensionais ................................................................................................
Arrays de ponteiros ragged arrays
..........................................................................

32

Alocao dinmica de
memria ..........................................................................................
A funo
malloc ..........................................................................................................
Vetores gerados
dinamicamente .......................................................................
A funo calloc
...........................................................................................................
A funo realloc
.........................................................................................................
A funo free
...............................................................................................................

36

15

Definio de novos
tipos ...................................................................................................

39

16

Estruturas structs
..........................................................................................................
Iniciao de
estruturas .................................................................................................
Campos de bits
...........................................................................................................
Unies .....................................................................................................................
....
Ponteiros para
estruturas .............................................................................................
Ponteiro para percorrer array de
ponteiros .................................................................

39

17

Ponteiros para
funes .....................................................................................................

45

18

Tipos
enumerados .............................................................................................................

46

19

Arquivos ........................................................................................................................
.....
Funes para Abertura e fechamento de arquivos .................................................
Funo para abertura de
arquivos .....................................................................
Funo para afechamento de
arquivos ..............................................................
Principais funes para leitura e gravao seqenciais .........................................
Principais funes para leitura e gravao direta (tipos texto e binrio) .............

47

13.1
13.2

14

16.1
16.2
16.3
16.4
16.5

19.1
19.1.1
19.1.2
19.2
19.3

34
35

36
37
37
38
38

41
41
41
43
44

47
47
49
49
50

Referncias Bibliogrficas
..............................................................................................
Exerccios Adicionais
........................................................................................................

A Linguagem C
1. Introduo a linguagem C
1.1.

Caractersticas & Histrico

1.2.

Caractersticas de um programa

1.3.

linguagem de mdio nvel;


linguagem estruturada;
verstil (aplicao em vrias reas);
portvel;
cdigo eficiente;
compilao condicional;
compilao separada (funes em vrios arquivos);
linguagem para o programador.
BCPL B C C++
C - 1971 - Kernighan e Ritchie (K & R)
C ANSI (American National Standards Institute) - 1989

Um programa em C composto por pelo menos uma funo, a funo "main";


Todo programa em C comea a sua execuo a partir da funo "main";
Normalmente, um programa em C uma coleo de funes de pequeno tamanho;
Toda funo tem um tipo;
Palavras reservadas e funes da biblioteca do C so sempre escritas com letras minsculas.

Formato de um programa em C

"definies"
funo_1
funo_2
...
funo_n
funco_main / A ordem das funes dentro de um programa pode ser qualquer
Exemplo de um programa
#include <stdio.h>

// Instruo para o pr-processador

void main ( )
{
int i;
i = 10;
printf ("i = %d\n", i);

//
//
//
//
//

Incio da funo main


Incio de bloco
Define i como uma varivel do tipo inteiro
Iinicia i
Chama funo de impresso
6

55
56

// Fim de bloco

//

Toda instruo termina por ; e o prottipo de printf est em stdio.h (standard IO)

2. Identificadores
So usados em nomes de funes e variveis.
A maioria dos compiladores reconhece 31 caracteres tanto para variveis quanto para funes, e:

Devem comear por letra ou '_';


Normalmente se usam letras minsculas;
No podem ser iguais s palavras reservadas;
Minsculas so compredidas como diferentes de maisculas (e.g.: ABC Abc ABc abc).

3.

Tipos de Dados para Variveis e Funes

3.1.

Standard (j definidos na linguagem)

caracter
inteiro
inteiro duplo
real
real duplo
nada

char
int
long int
float
double
void

(1 caractere)
(2 bytes)
(4 bytes)
(4 bytes)
(8 bytes)
(0 bytes)

O tipo inteiro possui o tamanho da palavra da CPU.


Tipo

Tamanho em Bits

Faixa

Char

0 a 255

int

16

-32768 a 32767

long int

32

2,147,483,648 a 2,147,483,647

Float

32

6 dgitos

Double

64

12 dgitos

Void

Sem valor

3.2.

Modificadores de tipo

Alteram o significado do tipo standard.

signed (com sinal)


unsigned (sem sinal)
long (passa inteiro de 2 bytes para 4 bytes)
short (passa inteiro de 4 bytes para 2 bytes)

Se tipo int: long int = long


short int = int

4 bytes
2 bytes
7

Exemplos: signed char


unsigned int

128 a 127
0 a 65535

4. Declarao de Variveis
Variveis devem ser declaradas antes de serem usadas.
Formato: <tipo> <lista de variveis>;
Exemplos: int
a, b, c;
float
soma;
double somatorio, raiz_quadrada;
char
sim, nao;
As variveis podem ser definidas dentro de qualquer bloco:
{
int x, y;
< bloco de comandos >;
}
4.1.

Variveis locais

So as declaradas dentro de blocos e s so reconhecidas dentro do bloco de declarao.


// Exemplo:
#include <stdio.h>
void main ( )
{
int i = 2, j;
j = 2 * i;
printf ("O dobro de %d = %d\n", i, j);
}
/* No exemplo acima, i e j so variveis locais da funo main . */
// Exemplo:
void f1 ( )
{
int x;
x = 5;
...
if (a > 10)
{
int x, y;
x = 20;
y = 40;
...
}
}
// No exemplo, a varivel x tem o valor 5 quando sair do bloco mais interno.

4.2.

Parmetros formais os parmetros das funes.

Quando parmetros so passados por valor a funo s recebe cpia do contedo da varivel.
Exemplo:int soma (int a, int b)
{
return (a + b);
}
No exemplo, a e b so parmetros formais e a funo soma poderia ser chamadadas seguintes formas:
j = soma (2, 3);
ou
x = soma (a, b);
4.3.

Variveis globais

So reconhecidas por todas as funes de um programa ou de um arquivo.


// Exemplo:
#include <stdio.h>
int cont;
void f ( void );
void main ( )
{
cont = 100;
printf("cont em main = %d\n", cont);
cont = cont + 1;
f ( );
}
void f ( )
{
printf("cont em f = %d\n", cont);
}
4.4.

Modificadores de classe de armazenamento

Indicam como as variveis devem ser armazenadas.


Exemplo de mapa da memria de um programa em C em um equipamento genrico:
Stack

Heap
Variveis Estticas e
Globais
rea de Cdigo

4.4.1.

Variveis automticas auto so as variveis definidas normalmente.

Exemplo:int x; <=> auto int x;


9

A palavra auto no necessria.


4.4.2. Variveis externas extern so variveis globais definidas em arquivos diferentes.
// Exemplo: arquivo 1:
void main ( )
{
int x, y;
y = 30;
x = 10;
f ( );
...
}
// arquivo 2:
extern int x, y;
void f ( )
{
...
printf ("%d %d\n", x, y);
...
}
4.4.3. Variveis estticas - static
A varivel no perde o seu valor dentro da funo ou arquivo.
Este tipo de varivel mais empregado para definio de strings.
Quando uma funo definida como static, ela s pode ser ativada por uma funo que esteja no mesmo
arquivo.
4.4.4

Variveis register

A varivel colocada em um dos registradores da CPU e, por isso, dve ser bem escolhida
Ex.: register int i, j;
Este tipo de varivel mais usada em casos nos quais a velocidade importante, como, por exemplo, em
variveis que controlam laos.
5. Operadores
Um operador um caracter ou grupo de caracteres que causar uma manipulao matemtica ou lgica.
Em C, os operadores podem ser aritmticos, relacionais e lgicos e entre bits.
5.1. Aritmticos
+

++

+=
=
*=
/=

adio
subtrao (e menos unrio)
multiplicao
diviso
resto diviso
decremento
incremento

10

5.2.

Lgicos ou boleanos
&& e
| | ou
! no

5.3.

5.4.

Relacionais
>

<

==

!=

>=

<=

maior
menor
igual
diferente
maior ou igual
menor ou igual

Entre bits
&

>>

<<

e
ou
ou exclusivo
complemento (NOT)
deslocamento para direita
deslocamento para esquerda

5.5.

Outros operadores
*

retorna o valor contido em um endereo


&

retorna o endereo de uma varivel


sizeof

retorna o tamanho de uma varivel ou tipo


?

avalia expresso verdadeira


,

equivalente a "faa isto e isto e isto ..."


.

membro de estrutura ou unio

ponteiro para membro de estrutura ou unio


(type)

cast (altera tipo do dado)

5.6.

Precedncia (da maior para a menor)


( )[
!
*
+
<<
<
==
&
^
|
&&
||
?
=
,

]
~
++
/
%

>>
<= >
>=
!=

+=

( type )

* &

sizeof

* =/ =

11

5.7.

Pr-processador e diretivas

O pr-processador um programa que age antes do compilador da linguagem C, aumentando sua capacidade e
auxiliando a portabilidade. Ele comandado por diretivas (que iniciam sempre pelo sinal #). As diretivas s
valem no arquivo onde esto definidas ou arquivos includos abaixo destas diretivas
5.8

# define

Serve para definir uma constante simblica. Por exemplo:


#define TRUE 1
#define FALSE 0
#define MENS_ERRO "Erro. Diviso por zero.\n"
#define MAX_TAM 100
As constantes assim definidas podem ser usadas para atribuir valores a variveis, passadas como parmetros e
para comparaes dentro do programa. Ex.:
int erro;
...
erro = FALSE;
if (a == 0)
flag = TRUE;
if (erro)
printf (MENS_ERRO);
Outra finalidade do #define criar macro funes. Por exemplo:
# define MIN(a, b) ((a) < (b) ? (a) : (b))
ento se: a = MIN(x, 3); a = ((x) < (3) ? (x) : (3));
#define streq (x, y) (strcmp((x), (y)) == 0) /* iguais */
#define strlt (x, y) (strcmp((x), (y)) < 0)
/* x < y */
#define strgt (x, y) (strcmp((x), (y)) > 0)
/* x > y */
Para que se possa reutilizar uma constante devemos torn-la antes indefinida, usando a diretiva #undef a
seguir redefini-la novamente usando outro #define. Por exemplo:
a) # define NOME "teste"
...
# undef NOME
# define NOME "teste"
b) #define TAM 100
#define COMP 100
char array [ TAM ][ COMP ]
#undef COMP
#define COMP 200
char arrayb [TAM][COMP]
5.9

# include

Permite incluir o contedo de um arquivo no programa.


Exemplos: #include <stdio.h>
// Procura stdio.h no diretrio de arquivos header
#include "stdio.h"
// Procura stdio.h no diretrio corrente
#include "b:auxiliar.h"
// Procura auxiliar.h no drive b
Esta ltima forma deve ser evitada, pois gera dependncia do sistema operacional.

O comando #include <iostream> usada para incluir o acesso a biblioteca padro de entrada e
sada de dados do C++.
12

A <iostream> uma biblioteca usada para entrada e sada de dados. Ela fornece o objeto std::cout,
que serve para enviar uma mensagem para a tela e utiliza o operador <<, que indica: envie estes
caracteres para sada (cout = C out).
A <iostream> fornece tambm o objeto std::cin, que usado para entrada de dados. Observe o uso
do operador >> que indica: armazene a entrada do usurio neste objeto.
5.10 namespace
O que um namespace ? Como o prprio nome diz, signifca espao para nomes.
Quando se monta programas utilizando bibliotecas externas, podem ocorrer duplicaes de nomes,
isto , um objeto defnido em uma bibliotecas tem o mesmo nome de um objeto defnido por voc.
Por exemplo: voc criou as funes min ( ) e max ( ), que retornam o menor e maior valor de um
vetor. Mas a STL biblioteca padro para tratamento de vetores em C++ j tem estas funes e ,
por isso, o compilador no saber que funo min( ) e max ( ) voc quer chamar.
Solucionar o problema da duplicao de nomes pode ser complexo, pois se estes nomes pertencerem
a bibliotecas externas, voc precisaria contatar os desenvolvedores delas para resolver os confitos,
ou renomear seus objetos e funes. O namespace veio para resolver este problema.
Para usar os objetos standart de C++ preciso incluir a palavra std e a seguir o operador de
resoluo de escopo, isto : std::nomeObjeto;
std::cout << Entre com x : ;
std::cin >> x ;

// cout = sada de dados


// cin = entrada de dados

Obs.:os comandos cin e cout devem ser utilizados somente em programao ambientadas em C++
5.11 using namespace std
Mas possvel utilizr os objetos standarts de C++ diretamente, isto , sem o uso de std::. Para tal
basta colocar a declarao using namespace std no incio do programa.
// Exemplo: Declara que vai usar os objetos standart de C++

using namespace std;


int x = 3 ;
cout < < Entre com x : ;
cin> > x ;

6. Entrada e Sada de Dados Pela Console Funes printf e scanf


Ao contrrio de outras linguagens, no C as operaes de leitura e impresso, tanto na tela quanto em arquivos,
totalmente feita por funes. Os prottipos destas funes se encontram no arquivo stdio.h, o qual deve
sempre ser includo quando forem usadas funes de IO (entrada e sada).
6.1.

printf
13

Principal funo de impresso no vdeo e retorna o nmero de caracteres impressos.


Formato: int printf (formato, argumentos);
Obs1.: Em C, o valor de retorno de uma funo pode ser ignorado.
Obs2.: Em C, as funes podem ter um nmero varivel de parmetros.
Ex.: printf (" \n FIM \n" ) ;
Principais formatos de impresso:

%d

inteiro

%c

caracter

%f

float

%ld

long int

%lf

double

%s

string

%e

notao cientfica
// A sada pode ser formatada atravs do tamanho do campo:
%3d

inteiro com 3 dgitos.


%7.2f
float com dois dgitos aps o ponto decimal.
6.2.

scanf

Principal funo de leitura do teclado.


Formato: int scanf (formato, parmetros);
Retorna o nmero de variveis lidas corretamente ou EOF em caso de erro grave.
Principais formatos:
%d inteiro
%c caracter
%f float
%ld long int
%lf double
%s string
Para a funo scanf, o branco considerado delimitador. Por exemplo, scanf ("%d %d", &a, &b);
mostrar 1 3 ou 1 3 (depende dos espaos entre os %d). J scanf ("%d , %d", &a, &b); mostrar 1 , 3
(um, vrgula e trs).
// Ex.: Ler dois nmeros e imprimir a soma.
# include <stdio.h>
void main ( )
{
int a, b, c;
printf("Entre 2 numeros: ");
scanf("%d %d", &a, &b);
c = a + b;
printf("soma = %d\n", c);
/* ou poderia ser printf("soma = %d\n", a + b); */
}
7. Instues de controle
7.1.

if { } ; if { } else { } ; if { } else { if { }} ; etc


14

// Exemplo 1
if ( teste ) < um s comando; >
// Exemplo 2
if ( teste )
{
< bloco de comandos; >
}
else
{
bloco de comandos;
}
// Exemplo 4: ler 2 nmeros e indicar o maior
#include <stdio.h>
void main ( )
{
int a, b;
printf ("Entre 2 numeros: ");
scanf ("%d %d", &a, &b);
if (a == b)
/* todo teste de igualdade utiliza == */
printf ("Sao iguais\n");
else if (a > b)
printf ("O primeiro maior\n");
else
printf ("O segundo maior\n");
}
// Exemplo 5: ler uma srie de nmeros reais e indicar o maior e o menor.
#include <stdio.h>
void main ( )
{
float min, max, x;
printf ("Entre os numeros:\n");
scanf ("%f", &x);
min = max = x;
/* atribuio mltipla */
while (scanf("%f", &x) == 1)
if (min > x) min = x;
else
if (max < x)
max = x;
printf (" \n O maior : %f\n", max);
printf (" \n O menor : %f\n", min);
}
7.2. O operador ? (substitui o if)
uma outra forma de utilizao do comando if (til para pequenos comandos do tipo if).
if (a == 10)
{
b = 20;
}
else
{
b = 30;
}

b = (a == 10)

15

? 20 :

30;

7.3.

O comando switch substitui grandes if's.

switch (exp)
// A expresso exp deve fornecer um resultado inteiro.
{
case cte 1: bloco1;
// cte = constante valor ou caractere (entre aspas simples)
break;
case cte 2: bloco2;
break;
case cte 3: bloco3;
break;
...
...
case cte n: bloco n;
break;
default
: bloco default;
break; /* no necessrio break aqui */
}
Exerccios de Fixao
1)

Implemente um programa que receba 3 (trs) nmeros inteiros, atravs do teclado, e visualize qual o
maior e qual o menor deles.

2)

Implemente um programa que receba 4 (quatro) nmeros inteiros, atravs do teclado, e que, aps, os
visualize em ordem decrescente.

3)

Implemente um programa que receba um nmero inteiro, atravs do teclado, pertencente ao intervalo
[1000,1010.000[, e que, aps, determine e visualize: (i) seus dgitos individualmente; (ii) denomine por
extenso o valor de cada dgito; e (iii) a soma dos dgitos pares do nmero informado.

4)

Implemente um programa que receba 3 (trs) nmeros inteiros, atravs do teclado, e verifique se eles
podem formar um tringulo eqiltero, um tringulo retngulo, ou se no permitem a formao de um
tringulo.
Obs.: Relao Triangular: cada lado de um tringulo tem de ser menor que a soma dos outros dois lados ;

7.4.

for ( . . . ) { . . . }

Formato: for (inicializao; condio; incremento)// Todos os campos do for so opcionais


{
< bloco de comandos; >
}
// Exemplos: Imprimir os nmeros de 1 a 10
#include <stdio.h>
void main ( )
{
int i;
for (i = 1; i <= 10; i++) printf ("%d\n", i);
}
#include <stdio.h>
void main( )
{
int i = 1;
16

for ( ; i <= 10; )

printf("%d\n", i++);

}
7.5.

while

Formato:

while (condio)
{
< bloco de comandos ; >
}
// Executa o bloco enquanto a condio for verdadeira (em C, verdadeiro o que no for zero).
//Exemplo: Seja fazer um programa que imprima a soma dos nmeros de 1 a 5 com um lao while.
// Soluo 1:
#include <stdio.h>
void main( )
{
int i = 1, soma = 0;
while (i <= 5) soma += i++;
printf ("\nSoma = %d\n", soma);
}
// Soluo 2:
#include <stdio.h>
void main ( ){
int i = 1, soma = 0;
while (i <= 5) soma += i++;
printf ("\nSoma = %d\n", soma);
}
Obs.: i ++; ++ i;
se a = 1:
para b = ++ a;

b=2ea=2
para b = a ++;

b=1ea=2
var = var op exp;
x = x + 5;
x = x / (a + b);
7.6.

var op = exp;
x + = 5;
x / = a + b;

do while

Formato: do

{
< bloco de comandos; >:
}
while (condio);

Repete o bloco de comandos enquanto a condio for verdadeira.


// Exemplo: Imprimir os nmeros de 1 a 10
#include <stdio.h>
void main ( )
{
int i = 1;
do
printf ("%d\n", i++ ); while (i <= 10);
}
// Exemplo: Calcular o fatorial de um nmero lido usando for.
// Soluo 1:
#include <stdio.h>
void main ( )
17

{
int n, i, fator = 1;
printf ("Entre o numero: "); scanf ("%d", &n);
for (i = 1; i <= n; i++) fator *= i;
printf (" \n Fatorial de %d = %d \n", n, fator ) ;
}
// Soluo 2:
#include <stdio.h>
void main ( )
{
int n, i, fat;
printf ("Entre o numero: "); scanf ("%d", &n);
i = n;
for (fat = 1; n > 1; n ) fat *= n;
printf( " \n Fatorial de %d = %d \n", i, fat ) ;
}
7.7.

continue

Continua com o prximo incremento no for ignorando as instrues restantes dentro do bloco do for.
...
for (i = 0; i < 10; i++)
{
if (i == 0)
continue;
/* evita diviso por zero */
printf("%f\n", (float) 10 / i);
}

7.8.

break

Interrompe a execuo de um for, while, do ... while ou switch. O fluxo de execuo do programa desviado
para primeira instruo fora do bloco que possui o break.
Ex.: while (1)
/* loop infinito */
{
scanf("%d" , &a);
if (a != 0)processa ( );
else
break;
}
7.9.

goto label

Desvia o fluxo de execuo do programa para um label em outro ponto do programa.


goto Label_1;
processa ( );
Label_1:
...
// Para label sem instrues deve-se usar um ; no final: Erro_Fatal: ;
// Exemplo: Fazer um programa que simule uma calculadora, com as quatro operaes, teste // a diviso
por zero e sinal invlido.
# define FALSE 0 /* definio de constantes */
# define TRUE 1
18

# include <stdio.h>
void main ( )
{
float v1, v2, res;
char op;
int erro = FALSE; /* usa int como varivel lgica */
printf ("Entre sua expresso:\n");
scanf ("%f %c %f", &v1, &op, &v2); /* le a expresso */
switch ( op )
{
case '+' : res = v1 + v2; break;
case '' : res = v1 v2: break;
case '*' : res = v1 * v2; break;
case '/' : if (v2 == 0.0)
{
printf (" \n Erro: Diviso por zero\n");
erro = TRUE;
}
else res = v1 / v2; break;
default: erro = TRUE;
printf (" \n Sinal invlido \n " ) ;
break;
}
if (!erro)
// No precisa fazer erro == TRUE
printf ("\nO resultado : %10.4f\n", res);
}
// Exemplo: Fazer um programa que leia um valor n e leia e imprima o quadrado de n nmeros.
#include <stdio.h>
void main ( )
{
float x;
int n;
printf ("\n Nmero de valores a serem lidos: ");
scanf ("%d", &n);
while (n );
{
printf(" \nValor: ");
scanf (" %f ", &x);
printf (" \n Quadrado de %f = %f\n", x, x * x ) ;
}
}
/*
Obs.: Outras funes de entrada e sada de dados
int getchar ( void ); // Erro = EOF
int putchar ( int );
// Erro = EOF; OK = caractere impresso.
*/

19

Exerccios de Fixao
A seguir so apresentados vrios exerccios. Quando algum deles necessitar utilizar comandos de repetio,
resolva-os: (a) utilizando somente o comando do { ... } while ; (b) utilizando somente o comando while{ . . . };
e (c) utilizando somente o comando for { . . . }.
1)

Implemente um programa que receba, atravs do teclado, um nmero natural, sem o zero, menor que
1001 (mil e um), e que, aps, visualize a soma de todos os nmeros mpares naturais at o nmero
digitado.

2)

Implemente um programa que receba, atravs do teclado, um nmero natural, sem o zero, menor que
501 (quinhentos e um), e que, aps, visualize todos os nmeros pares mltiplos de 3 (trs) entre 1 e o
nmero digitado.

3)

Implemente um programa que receba 3 (trs) nmeros inteiros, atravs do teclado, cujos significados
so, respectivamente: o primeiro termo de uma Progresso Aritmtica P. A. ; a razo desta P.A.; e sua
quantidade de termos. Aps, o programa dever determinar e visualizar a soma dos termos pares da P.A.
supracitada.

4)

Implemente um programa que calcule e visualize a soma dos 15 (quinze) primeiros termos da
Progresso Geomtrica 3, 9, 27, ... .

5)

sabido que a srie de Fibonacci : 1 1 2 3 5 8 13 . . . , que pode ser definida assim:


a 1 = 1 ; a2 = 1 ; e
20

an = (an 1) + (an 2) para n 3


2.1) Implemente um programa que visualize um certo termo da srie de Fibonacci cuja posio na
srie deve ser informada atravs do teclado e deve pertencer ao intervalo [ 0 , 20 ].
2.2) Implemente um programa que visualize a soma dos N primeiros termos da srie de Fibonacci,
sendo N informado atravs do teclado e devendo pertencer ao intervalo [1, 25 ].
2.3) Implemente um programa que exteriorize todos os quadrados perfeitos pertencentes aos 25
primeiros termos da srie de Fibonacci.
6)

Implemente um programa que receba dois nmeros inteiros, atravs do teclado, maiores que 0 (zero) e
menores que 1000 (mil), e visualize todos os cubos perfeitos compreendidos entre eles, inclusive.

7) Implemente um programa que receba, atravs do teclado, um nmero inteiro maior que 1 (menos um) e
menor que 6(seis), e que, aps, visualize seu fatorial.

8. Arryas unidimensionais (vetores) numricos


Definio de vetores unidimensionais:
<tipo> <nome>[<tam>];
Ex.: int vet[5]; define vet como um vetor inteiro de 5 posies
A posio do primeiro elemento vet [ 0 ] e do ltimo vet [ 4 ].
Exemplos de acesso:
int vet [ 5 ];
vet[ 0 ] = 10;
vet[ 1 ] = 20;
vet[ 2 ] = 40;
for (i = 0 ; i < 5; i++ )
vet [ i ] = 0;

// Zera o vetor vet

Iniciao na definio:
Para vetor local:
static int vet[ ] = {1, 3, 5};
static float vet[10];
static int vet[5] = {1, 2, 3};

// assume que o vetor vet possui 3 elementos


// assume vet com 10 elementos, que so iniciados com 0.
// assume vet com 5 elementos; o 4 e o 5 so iniciados com 0.

Para vetor global:


int vet[ ] = {10, 20, 40, 50};// assume vet tem 4 elementos
Quando um vetor extern ou static for iniciado sem dimenso, ela ser igual ao nmero de valores da iniciao.
Caso seja fornecida a dimenso e faltem elementos na iniciao, os elementos no iniciados valem zero.
// Exemplo: Fazer uma funo que retorne o maior nmero de um vetor double.
# include <stdio.h>
double maxval (double [ ], int);
void levet
(double [ ], int);
21

void main ( )
{
double vet [ 100 ];
int i, n;
printf (" Nmero de elementos do vetor: " ) ;
scanf (" %d ", &n);
levet (vet, n);
printf (" \n Maior valor = %lf ", maxval (vet, n) );
}
void levet (double v[ ], int n )
/* double v[ ]; no precisa dar a dimenso */
{
int i;
double aux;
printf("Entre os elementos do vetor:");
for (i = 0; i < n; i++) { scanf (" %lf ", &aux );
v [ i ] = aux;
}
}
double maxval (double v[ ], int n )
{
int i;
double maior ; maior = v[ 0 ];
// maior comea como sendo o primeiro
for (i = 1; i < n; i++)
if (v [ i ] > maior) maior = v [ i ];
return (maior);
}
Exerccios de Fixao
1) Escreva um algoritmo que preencha um vetor, de dimenso 100 (cem), com valores inteiros maiores que 0
(zero) e menores que 101 (cento e um), informados atravs do teclado, e que, aps, visualize somente os
valores mltiplos de 5, sem utilizar o comando que fornea o resto de diviso automaticamente.
2)

Escreva um algoritmo que preencha um vetor com valores inteiros, informados atravs do teclado,
mas de tal modo que nunca sejam armazenados 2 (dois) valores iguais nele. Mais ainda; aps terminar o
preenchimento o algoritmo dever visualizar todo contedo do vetor.

3)

Escreva um algoritmo que preencha 2 (dois) vetores com valores inteiros maiores que 0 (zero) e
menores que 101 (cento e um) , informados atravs do teclado, e que, aps, processe a gerao de um
terceiro vetor que contenha todos os elementos dos dois primeiros vetores, porm sem que ocorra repetio
de valores.

4)

Escreva um algoritmo que preencha um vetor com valores inteiros maiores que 0 (zero) e menores
que 101 (cento e um), informados atravs do teclado, e que, aps, visualize todos os valores presentes no
vetor que faam parte dos primeiros 10 (dez) termos da srie de Fibonacci.

5)

Escreva um algoritmo que preencha um vetor com valores inteiros maiores que 10 (menos dez) e
menores que 10 (dez), informados atravs do teclado, e que, aps, visualize, sem repeties, todos os
valores mpares presentes no vetor que faam parte dos 15 (quinze) primeiros termos da srie de
Fibonacci.

6)

Resolva os exerccios a seguir de 3 modos diferentes, ou seja: utilizando os comandos while { ... }; do
{ . . . }, while { . . .} e for { . . .}. Mais ainda: as visualizaes devero ocorrer: percorrendo o(s) vetor(es)
em ordem crescente e, aps, em uma outra verso do exerccio, percorrendo o(s) vetor(es) ordem
decrescente.
22

a)

Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com
os nomes e as notas (as notas tm de estar contidas no intervalo 0 nota 10) dos alunos,
respectivamente, de uma turma de 100 alunos e, aps, exteriorize somente os nomes dos alunos que
obtiveram notas iguais ou maiores que 5 (cinco).

b) Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com as
idades de 100 pessoas. A primeira estrutura do tipo vetor dever receber somente as idades das pessoas
do sexo masculino, enquanto a segunda dever armazenar as idades das pessoas do sexo feminino.
Aps, o programa dever exteriorizar os nomes, o sexo e as idades das pessoas que possuem idade
compreendida entre 20 (vinte) e 40 (quarenta) anos, inclusive.
7) Escreva um algoritmo que calcule e visualize a soma S conforme a representao abaixo.
S ( a1 an ) 2 ( a2 - an 1 ) 2 ( a3 - an 2 ) 2 ... ( an - a1 ) 2
Os valores de a1 a2 , ... , an devero ser naturais consecutivos e o valor n dever ser informado atravs do
teclado, e estar compreendido no intervalo fechado [ 1 , 100 ] .
8.1.

Arryas unidimensionais (vetores) de caractreres Strings

Consideraes Gerais:
1.
2.
3.
4.

So arrays de caracteres.
Em C, toda string acaba com o caracter '\0'.
Exemplo da definio de um vetor de caracteres: char str [ 7 ];
A considerao 3 define str como vetor de 6 caracteres mais o caractere de final de string.
Exemplo:char str [ 7 ];
str[0] = 'C';
str[1] = 'a';
str[2] = 'r';
str[3] = 'l';
str[4] = 'o';
str[5] = 's';
str[6] = '\0';

Na memria teramos:

C
a
r
l
o
s
\0

0
1
2
3
4
5
6

Podemos iniciar uma string de duas formas:


1) Como um vetor: static char str [ ] = {'C', 'a', 'r', 'l', 'o', 's', '\0'};
2) Deixar que o compilador inicie:
static char str[ ]="Carlos";
Obs.: No possvel a atribuio direta:
char str[ 7 ];
str = "Carlos"; /* Erro: no vale a atribuio */
23

// assume 6 caracteres mais '\0' = 7


// assume 6 caracteres mais '\0' = 7

// Exemplo: Fazer um programa para ler um nome e dar um bom dia para o dono do nome.
// Soluo 1:
#include <stdio.h>
#define TAM 100
void main()
{
char linha [ TAM ];
int c, i;
printf ( " \n Qual o seu nome ? " ) ;
for (i = 0; (c = getchar ( ) ) != '\n'; i++) linha [ i ] = c;
linha [ i ] = '\0';
printf (" \n Tenha um bom dia " ) ;
for (i = 0; linha [ i ] != '\0'; i++) putchar ( linha [ i ] );
putchar('\n');
}
A funo getchar retorna um caractere do teclado e a funo putchar coloca um caractere no vdeo. Estas
funes, bem como as outras de IO podem ser redirecionadas. Em caso de erro, a funo getchar retorna
EOF.
// Soluo 2:
#include <stdio.h>
#define TAM 100
void main()
{
char linha [ TAM ];
printf (" \n Qual o seu nome ? " );
gets ( linha );
printf (" \n Tenha um bom dia !!!" );
puts (linha);
}
A funo gets tem por finalidade ler uma string e a puts imprimir uma string. A funo puts fornece
automaticamente uma mudana de linha aps a impresso.
Formatos:

// Ponteiros sero abordados com detalhes mais adiante)


char *gets ( char *buf );
// Retorna ponteiro para a string lida ou NULL em caso de erro.
int puts ( char *buf );
// Retorna '\n' se imprimiu bem ou EOF em caso de erro.

Para atribuio de strings, usa-se a funo strcpy, que possui o formato:


char *strcpy (char *destino, char *origem);
Exemplo: strcpy (str, "casa");
/* str passa a ter "casa" */
Para se saber o tamanho de uma funo, usa-se a funo strlen, que possui o formato:
int strlen (char *st);
// Exerccio: construir a funo strlen.
// Soluo 1:
int strlen (char cadeia [ ] )
{
int len = 0, I = 0;
while (cadeia [ I ] != '\0')
{ ++len ;

++ i; }
24

return ( len );
}
// Soluo 2:
int strlen ( char cadeia [ ] )
{
int i;
for (i = 0; cadeia [ i ] != '\0'; i++) ;
return ( i );
}

/* bloco nulo */

// Exerccio: Construir uma funo que copia uma string para um vetor de caracteres
// Soluo 1:
void stringcpy (char[ ], char[ ]);
void stringcpy (char s1[ ], char s2[ ])
{
int i;
for (i = 0; s2 [ i ] != '\0'; i++)
s1[ i ] = s2 [ i ];
s1[ i ] = '\0';
}
// Soluo 2:
void stringcpy(char s1[ ], char s2[ ])
{
int i = 0;
while ( ( s1[ i ] = s2 [ i ]) != '\0' )
i++;
}
9. Arrays bidimensionais (matrizes bidimensionais)
Formato: <tipo> <nome> [ <d1>][ <d2> ];
Onde:
d1 nmero de linhas (varia entre 0 e d1 1)
d2 nmero de colunas (varia entre 0 e d2 - 1)
Exemplo:
int b[3][5]; 3 linhas e 5 colunas
Inicializao na declarao:
static int b[ ][ 3 ] =
{
1, 1, 1,
2, 2, 2,
3, 3, 3
};

|
|
|

static int b[ ][3] =


{
{1, 1, 1},
{2, 2, 2},
{3, 3, 3}
};

25

A iniciao tambm pode ser feita de forma esparsa. Por exemplo:


static int b[ 3 ][ 3 ] =
{
{1, 1},
{1}
};
A matriz gerada pela inicializao acima ser:
110
100
000
Obs.: (1) Para este tipo de iniciao necessrio que se fornea o nmero de linhas e de colunas; (2) o
armazenamento em C feito por linhas; e (3) ao se passar uma matriz bidimensional, a nica dimenso fixa
o nmero de colunas (ao contrrio do Fortran que fixa o nmero de linhas).
// Exemplo
void main ( )
{
int mat[ 10 ][ 20 ];
...
f (mat, 10, 20);
}
A funo f ( ) poderia receber a matriz de duas formas:
void f (int mat [10][20], int lin, int col)
void f (int mat [ ][20], int lin, int col)
{
comandos;
}

ou

// Exemplo de como zerar uma matriz:


void zera (float mat[ ][ 20 ], int, int); /* prottipo */
void main ( )
{
float mat [ 10 ][ 20 ];
zera (mat, 10, 20);
}
void zera (float mat[ ][ 20 ], int lin, int col)
{
register int i, j;
for (i = 0; i < lin; i++)
for (j = 0; j < col; j++) mat[ i ][ j ] = 0.0;
}

26

Exerccios de Fixao
1)

Escreva um algoritmo que preencha uma certa matriz quadrada de ordem 4 (quatro) com nmeros
inteiros, informados atravs do teclado, e que, aps:
a)
Visualize todos nmeros pertencentes a Diagonal Principal DP ;
b)
Visualize todos nmeros pertencentes a Diagonal Secundrio DS ;
c)
Visualize todos nmeros que estejam acima da Diagonal Principal ; e
d)
Visualize a soma de todos os nmeros que estejam abaixo da Diagonal Secundria.
2) Escreva um algoritmo que preencha automaticamente uma certa matriz quadrada de ordem 8 (oito)
conforme a representao grfica abaixo:
colunas

linhas

1
2
3
4
5
6
7
8

1 2
A A
A B
A B
A B
A B
A B
A B
A A

3
A
B
C
C
C
C
B
A

4
A
B
C
D
D
C
B
A

A
B
C
D
D
C
B
A

5
A
B
C
C
C
C
B
A

6
A
B
B
B
B
B
B
A

A
A
A
A
A
A
A
A

3) Escreva um algoritmo que preencha duas matrizes quadradas de ordem 3 com valores inteiros maiores
que 0 (zero) e menores que 101 (cento e um), informados atravs do teclado, sem permitir que sejam
armazenados valores repetidos em cada matriz.
Aps, o algoritmo dever visualizar todos os valores mpares e mltiplos de 11 sem, no entanto,
utilizar o comando mod.
Mais: aps, o algoritmo dever executar a gerao automtica de uma terceira matriz que represente
a soma das outras duas matrizes, tambm sem permitir a ocorrncia de repetio de valores.
Quando ocorrer repetio o valor repetido dever ser substitudo por 0 (Zero) na matriz soma.
Finalmente, o algoritmo dever visualizar os valores presentes na terceira matriz matriz soma
que faam parte dos 10 (dez) primeiros termos da srie de Fibonacci.
4) Escreva um algoritmo que preencha duas matrizes de dimenses 5x3 e 3x2, respectivamente, e que,
aps, calcule e visualize a matriz produto delas.

27

10.

Funes

Formato: < tipo > < nome da funo > ( < parmetros > )
{
declarao de variveis locais;
corpo da funo;
}
< tipo > o tipo do valor a ser retornado pela funo;
se uma funo no retorna valor, o seu tipo void;
os parmetros so sempre passados por valor, isto , uma cpia do valor da varivel passado para a

funo;
para arrays (vetores e matrizes) passado como valor o endereo da primeira posio;
deve-se sempre usar o prottipo da funo;
variveis 'char' so transformadas em 'int' e variveis 'float' so transformadas em 'double'.

O formato da funo varia entre o padro K & R e o ANSI. O padro K & R pode ser usado no ANSI.
formato K & R
int soma (a, b)
int a, b;
{
return (a+b);
}

|
|
|
|
|

formato ANSI
int soma (int a, int b)
{
return ( a + b );
}

O valor retornado por uma funo pode ou no ser utilizado (e.g.: a funo printf ( ) ).
Mais: pode-se retornar de qualquer ponto da funo, bastando usar a instruo return ( ).
// Exemplo: Fazer um programa para ler um nmero e imprimir o seu fatorial utilizando uma
//
funo para ler o nmero, uma para clculo do fatorial e uma para mostr-lo.
# include <stdio.h>
long factorial (long);
long leval
(void);
void printfat
(long);
void main ( )
{
long fat, val;
val = leval ( );
fat = factorial (val);
printfat (fat);
}
long leval ( )
{
long x;
printf (" \nEntre o valor a ser calculado: ");
scanf("%ld", &x);
return ( x );
}
void printfat (long y)
{
printf (" \nFatorial = %ld\n", y);
}
long fatorial (long a)
{
long fator = 1;
long i;
28

for (i = 1; i <= a; i++) fator *= i;


return ( fator );
}
11.

O Tipo Pointer (Ponteiro)

11.1. Definio
Um ponteiro uma varivel que contem como valor um endereo.
Para definirmos uma varivel como ponteiro, devemos fornecer o tipo da varivel para qual apontar e um
nome.
Embora os endereos de variveis de um tipo (e.g.: int), sejam semelhantes aos de outros tipos como float,
char ou double, importante no mistur-los. Para a declarao de um ponteiro tem-se que indicar o tipo de
varivel para o qual ele ir apontar, pois ao serem feitas operaes aritmticas com os ponteiros, eles iro
variar em funo de seu tipo.
Principais vantagens do uso:
superar as restries de passagem de argumento, por valor, para funes;
acessar elementos de arrays de modo alternativo ao uso de ndices;
permitir a criar estruturas dinmicas (rvores e listas encadeadas) bem como suas manipulaes.

Forma de definio:
<tipo> *<nome>;
int *p;
float *pf;
int i, *pt;
pt = &i;

Exemplos:

p um ponteiro para inteiro


pf um ponteiro para float
pt um ponteiro para inteiro
pt recebe oendereo de i

pt

1002

1002

2000
5 (contedo do endereo dado por pt)

*pt

void *pvoid; ponteiro para qualquer tipo


Dado: float x, y, *p, *q;
Temos como operaes possveis:
p = &x;

p aponta para x

y = *p;

y recebe o valor que est no endereo dado por p

q = p;

q e p apontam para o mesmo endereo

Erros comuns:
int *p;
*p = 10;

// no apontou para nenhuma varivel


29

float val;
int *p;
p = &val;

// tipos incompatveis

11.2. Iniciao de ponteiros na definio


int i = 7, p = &i;

/* a inicializao de p e no de *p

*/

11.3. Passagem de parmetros por endereo (referncia)


Para que se possa passar uma varivel por referncia, devemos passar um ponteiro para esta varivel ou, em
outras palavras, o seu endereo.
/*
Exemplo: ler dois valores e troc-los de ordem
*/
#include <stdio.h>
void swap

(int *, int *); /* prottipo de swap */

void main( )
{
int a, b;
scanf (" %d %d", &a, &b); /* le os dados */
swap (&a, &b);

/* chama a funo swap */

printf ("%d : %d\n", a, b);

/* imprime resultado */

}
void swap(int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}
// Exemplo: fazer uma funo que tenha o seguinte prottipo:
void soma (int *r, int a, int b);
# include <stdio.h>
void soma( int *r, int a, int b);

// Os nomes dos parmetros esto declarados por opo.

void main ( )
{
int x, y, z;
printf ( " \n Entre dois nmeros: \n");
scanf ("%d %d", &x, &y);
soma (&z, x, y);
printf (" \n A soma : %d\n", z);
30

}
void soma (int *r, int a, int b)
{
*r = a + b;
}
12.

A relao entre ponteiros e Arrays


Um nome de array um endereo ou ponteiro, que fixo.

// Exemplo:
int k, a[100], *p;
p = a;

// p possui o endereo do primeiro elemento de a


// ou
p = &a[ 0 ]; // p possui o endereo do primeiro elemento de a
Para que p aponte para o elemento seguinte, basta incrementar o endereo de 1.
p = a + 1;
p++;
k = *p++;

// p = &a [ 1 ];
// p aponta para o prximo elemento.
// k valor do elemento apontado por p e p aponta para o prximo elemento

// Exemplos para zerar um vetor:


for (i = 0; i < 100; i++)
a[ i ] = 0;
ou
for (i = 0, p = a; i < 100; i++)
*p++ = 0;

// com ndice
// com ponteiro

// Exemplo: Criar uma funo que retorne o tamanho em bytes de uma cadeia de caracteres
// usando ponteiro.
// Soluo 1:
# include <stdio.h>
int strlen (char* str);
void main ( )
{
static char str [ ] = "Esta string tem 30 caracteres.";
printf (" \nTamanho da string: %d caracteres.\n", strlen (str) );
}
int strlen (register char *s)

register int n;
for (n = 0; *s != '\0'; s++) ++n;
return ( n );
}

// Soluo 2:
# include <stdio.h>
int strlen (char *str);
31

void main ( )

static char str[ ] = "Esta string tem 30 caracteres.";


printf ("\nTamanho da string : %d caracteres.\n", strlen (str) );

}
int
{

strlen(register char *s)


register int n=0;
while (*s++) ++n;
return(n);

}
// Soluo 3:
#include <stdio.h>
int strlen (char *str);
void main ( )
{
static char str[ ] = "Esta string tem 30 caracteres.";
printf (" \n Tamanho da string : %d caracteres.\n", strlen (str) );
}
int strlen (register char *s)
{
register char *ps;
ps = s;
while (*ps) ps++;
return(ps - s);
}

// ps aponta para o inicio da string

// Exemplo: Criar a funo strcpy, que copie o contedo de uma string em outra.
# include <stdio.h>
char *strcpy (char *d, char *o);
void main ( )
{
static char orig[ ] = "teste", dest [ 20 ];
strcpy (dest, orig);
printf("origem = %s ; destino = %s\n", dest, orig);
}
char *strcpy (char *dest, char *origem)
{
char *d = dest;
// O while a seguir faz a copia e incrementa os ponteiros de cada string, at aparecer um
//
caractere nulo significando fim de string.
// Alguns compiladores daro um aviso (warning), achando que se deseja fazer um teste ao
// Invs de atribuio com teste, que o que se pretende fazer realmente.
while (*d++ = *origem++); /* sem bloco */
return (dest );
}
// Exemplo: Criar a funo strcmp que tem como finalidade comparar o contedo de uma
// string com o de outra. A funo tem o seguinte formato: int strcmp (char *s, char *t);
// Esta funo retorna: (a) 0 se as strings forem iguais; (b) < 0 se s < t; e (c) > 0 se s > t
# include <stdio.h>
int strcmp (char *s, char *d);
void main ( )
{
char s1 [ 20 ], s2 [ 20 ];
printf (" \nEntre a primeira string: ");
gets ( s1 );
printf (" \nEntre a segunda string: ");
gets ( s2 );
if ( strcmp (s1, s2) )
32

printf (" \n Diferentes.\n");


else
printf (" \n Iguais.\n");

/* <> de zero */

}
int strcmp (char *s1, char *s2)
{
while (*s1 == *s2)
if (*s1++)
s2++;
else
return(0);
return(*s1 - *s2);
}
Para definio e iniciao de strings, tambm possvel o seguinte tipo de instruo:
char *mens = "Diviso por zero";
A definio acima define mens como sendo um ponteiro para a string "Diviso por zero".
13.

Ponteiros e arrays bidimensionais

Como para vetores unidimensionais, o nome de um array um ponteiro fixo. Assim, as seguintes instrues
so equivalentes e geram o mesmo cdigo:
b[ i ][ j ]

*(*(b + i) + j)

*(b + i * ncolun + j)

O esquema abaixo representa o acesso vetores bidimensionais.

b
b[1]
b[i]
b+i
*(b + i)

b[i][j] =
*(*(b + i) + j)

Como para vetores unidimensionais, existem formas de se acessar matrizes de uma forma mais eficiente, como
veremos a seguir.
Definio de ponteiros para matrizes.
int mat[10][20], (*plin)[20];
plin = mat;
Nas instrues acima, definimos plin como sendo um ponteiro para uma linha de um array com 20 colunas
e mandamos que ele aponte para o primeiro elemento.
Forma de armazenamento na memria:

...
20 elementos

...
20 elementos

...
20 elementos
33

Para acessar um elemento da matriz via ponteiro:


(*plin)[j] ou *(*(plin) + j)
Para se passar para a prxima linha:
plin++;
plin

plin + 1

plin + 9

Nota: ( * plim) [ 20 ] define um ponteiro para linha de um vetor com 20 colunas, enquanto que
*plin[20] define um vetor de 20 elementos do tipo ponteiro.
// Exemplo: Calcular a mdia dos elementos de uma coluna de uma matriz de 3 colunas.
// Soluo:
# include <stdio.h>
double test_avg (int [ ][ 3 ], int, int);
void main ( )
{
double res;
static int board [ ][ 3 ] = {

1,
4,
7,
10,

2,
5,
8,
11,

3,
6,
9,
12

};
res = test_avg ( board, 4, 2 );
printf (" %lf\n", res);
}
double
{

test_avg (int tab[ ][3], int maxlin, int col)


long sum = 0;
int i, (*ptr)[3] = tab;
for (i = 0; i < maxlin; i++)
sum += (*ptr++) [col ];
return ( (double) sum / maxlin );

}
// Exemplo: calcular a mdia dos elementos de uma linha de uma matriz de 3 colunas.
// Soluo:
# include <stdio.h>
double test2_avg ( int[ ][ 3 ], int);
void main ( )
{
static int board[ ][3] =
{
1,
2,
3,
4,
5,
6,
7,
8,
9,
10, 11, 12
};
double res;
res = test2_avg (board, 1);
printf (" %lf\n", res);

/* calcular para linha 1. */

}
34

double test2_avg(int tab[][3], int linha)


{
long soma = 0;
int i;
int *p = &tab[linha][0];
for (i = 0; i < 3; i++)
soma += *p++;
return ( (double) soma / 3 );
}
Notas:

&tab[n][0] = endereo do elemento (n, 0) em tab


tab[n]
= linha n de tab

O nome de um array bidimensional quando usado com um nico ndice um ponteiro para o primeiro
elemento de uma determinada linha.
13.1 Arrays tridimensionais:
Seguem as mesmas regras do bidimensional. Exemplo:
int v [ 3 ][ 4 ][ 5 ]
define um array v com dimenses 3 x 4 x 5.
Definio de um vetor 3D em funes:
int vet[ ][ 4 ][ 5 ]

ou int (*vet)[ 4 ][ 5 ]

13.2 Arrays de ponteiros (ragged arrays)


So arrays com linhas de tamanho varivel. Um array deste tipo composto por ponteiros para outras
variveis e o seu uso mais comum para acessar tabelas de strings.
Exemplo: definir um vetor de ponteiros para uma tabela de dias da semana.
static char *dias[ ] =
{
"segunda", "tera", "quarta",
"quinta", "sexta", "sbado", "domingo"
};
Para esta definio, dias um array de 7 ponteiros para caracteres.
O esquema a seguir apresenta a organizao interna da tabela de dias da semana.

35

dias
0

s e g u n d a \0

1
..
.
6

e r

a \0

d o m i

n g o \0

Os elementos de 'dias' podem ser acessados de duas maneira:


1. dias [ i ]
printf ("%s\n", dias[2]);

// ser impresso "quarta"

2. dias [i ][ j ]
printf ("%c\n", dias[ 1 ][ 2 ]);
// ser impresso ' r '
// dias [ 1 ] "tera"
e
dias [ 1 ][ 2 ] r (de "tera")
// Exemplo: Fazer uma funo para imprimir 'dias'.
#i nclude <stdio.h>
void printab (char *[ ], int);
void printab (char *tab[ ], int n)
{
int i;
for (i = 0; i <= n; i++)
printf(" %s\n ",tab [ i ]);
}
Nota: Um elemento em um array de pointers pode ser usado como se ele fosse um pointer para o primeiro
elemento de uma linha de um array bidimensional (tab [ i ]).

14. Alocao Dinmica de Memria


A linguagem C possui uma srie de funes que permitem alocar e liberar reas de memria, fazendo com
que se possa usar a memria gasta por variveis, vetores, matrizes, listas, pilhas, etc. de uma forma mais
eficiente.
Quando necessrio, o usurio pede uma rea e a utiliza e, quando esta rea no for mais necessria, ela
devolvida ao sistema operacional, de forma a poder ser utilizada em outra etapa do programa.
O esquema abaixo apresenta o mapa da memria de um programa em C.
rea de Cdigo
rea de Variveis Estticas
e Globais
Stack
Heap
A rea disponvel para alocao dinmica se encontra na Heap.
As principais funes para manipulao de memria esto definidas no header stdlib.h e so:
36

malloc
calloc
realloc
free

void *malloc(unsigned int);


ptr = malloc(tam);
Aloca uma rea de tam bytes. Se alocou corretamente, retorna um pointer para o primeiro byte da rea
alocada e em caso de erro retorna NULL.
// Exemplo 1:
int *ptr;
...
ptr = malloc(sizeof(int));
if (ptr == NULL)
{

printf(" \nErro de alocao");


exit ( 1 );

}
*ptr = 10;
...
// Exemplo 2:
int *ptr, *ptraux, i;
...
ptr = malloc(sizeof(int) * 100);
if (ptr == NULL)
{
printf("Erro de alocao");
exit(1);
}
ptraux = ptr;
for (i = 0; i < 100; i++) *ptr++ = i;
ptr = ptraux;
...
Vetores gerados dinamicamente
// Obtm rea para um vetor do tipo float. O nmero de elementos pedido pelo programa.
// Aps a obteno da rea necessria so pedidos dados para o seu preenchimento.
# include <stdio.h>
# include <stdlib.h>
void prtvet (float*, int);
void main ( )
{
int num, i;
float *pvet, *pinic;
printf ("\nEntre com nmero de elementos:\n");
scanf ("%d", &num);
pvet = (float*) malloc(num * sizeof(float));
if (!pvet)
{ printf (" \nErro. Falta de memria.\n");
exit ( 1 );
}
pinic = pvet;
for (i = 0; i < num; i++)
{
printf (" \n%d -> ", i + 1);
scanf ("%f", pvet++);
// No funciona no Turbo C
}
37

pvet = pinic;
prtvet(pvet, num);
free(pvet);

// Imprime o vetor

}
void prtvet (float *p, int n)
{
int i;
for (i = 0; i < n; i++)
printf("\n\%d -> %f", i + 1, *pv++);
}
void *calloc (unsigned int, unsigned int);
ptr = calloc(num, size);
Aloca uma rea de 'tam' * 'num' bytes. Se alocou corretamente, retorna um pointer para o primeiro byte da
rea alocada e em caso de erro retorna NULL. A rea alocada automaticamente zerada.
// Exemplo 1:
int *ptr;
...
ptr = calloc(1, sizeof(int));
if (ptr == NULL)
{
printf ("Erro de alocao");
exit (1);
}
*ptr = 10;
...
// Exemplo 2:
int *ptr, *ptraux, i;
...
ptr = calloc(100, sizeof(int));
if (ptr == NULL)
{
printf (" \nErro de alocao");
exit ( 1 );
}
ptraux = ptr;
for (i = 0; i < 100; i++) *ptr++ = i;
ptr = ptraux;
...
void free ( void *);
free (ptr);
void *realloc (void *, unsigned int)
nptr = realloc(old, tam);
A funo realloc altera o tamanho da rea alocada por malloc ou calloc. O novo tamanho pode ser maior ou
menor do que o tamanho original. Quando chamada, retorna um pointer para a nova rea alocada, sendo old
um pointer para a rea antiga e tam' o novo tamanho em bytes. Em caso de erro, a funo retorna NULL e o
programa deve ser interrompido, j que a rea original poder estar comprometida.
Exemplo:
#include <stdio.h>
#include <stdlib.h>
void prtvet(float*, int);
38

void main ( )
{
int num, i;
char *p;
p = (char*) malloc(23);
strcpy (p, "AQUI TEM 22 CARACTERES");
printf ("\n%s\n", p);
p = realloc (p, 24);
strcat(p, ".");
printf(" \n%s\n", p);
free ( p );
}
Libera a rea alocada por malloc, calloc ou realloc.
// Exemplo:
int *ptr, *ptraux, i;
...
ptr = malloc(sizeof(int) * 100);
if (ptr == NULL)
{
printf (" \nErro de alocao");
exit ( 1 );
}
ptraux = ptr;
for (i = 0; i < 100; i++) *ptr++ = i;
ptr = ptraux;
...
free (ptr);
...
15. Definio de novos tipos
Para definio de novos tipos, utilizada a instruo typedef.
Formato:
typedef <tipo existente> <novo tipo>;
// Exemplos:
// Para se definir o tipo 'contador':
typedef
int contador;
contador
i, j;
// o mesmo que int i, j
Para se definir o tipo string:
typedef char string [ 81 ];
string text;

// o mesmo que char text[81]

Para se definir o tipo 'boolean':


typedef int boolean;
# define FALSE 0
# define TRUE 1
...
boolean ok = TRUE;
if (ok) . . .
Para se definir o tipo ptrchar (pointer para caractere):
typedef char *ptrchar;
ptrchar pchar;
// o mesmo que char *pchar
39

16.

Estruturas struct

Uma etrutura struct usada quando h necessidade de se combinar dados de um mesmo tipo ou de tipos
diferentes em um nico objeto ou registro.
Forma de definio:
struct <nome>
{

<tipo 1> < campo 1 , campo 2 , . . . , campo n>;


<tipo 2> < campo 1 , campo 2 , . . . , campo n>;
:
<tipo N> < campo 1 , campo 2 , . . . , campo n>;

};
Exemplos:
struct s1
{
int a;
char nome [ 81 ];
char ender [ 100 ];
};

// Define estrutura chamada s1 contendo os seguintes campos


//
//
//
//

Define um campo do tipo inteiro denominado a


Define um array de caracteres denominado nome
Define um array de caracteres denominado endereo
Aqui, a struct s1 passa a ser um tipo

// Agora possvel utilizar a struct s1 para definir duas variveis estruturadas: info1 e info2
struct s1 info1, info2;
Uma outra forma de definirmos este tipo de variveis :
struct { int x, y; } v1, v2;
// No exemplo acima, no foi criado um tipo, e sim duas variveis (v1 e v2) do tipo struct
// Tambm possvel o uso do typedef em conjunto com as estruturas:
typedef struct s1 t_s1;
t_s1 info1, info2;

// Foram criadas duas variveis info1 e info2 do tipo struct t_s1

Acesso aos membros de uma estrutura:


<varivel>.<campo>;
Exemplos:
info1.a = 10;
strcpy(info1.nome, "teste");
struct s2
{
int a;
char *nome;
};

/* nome um ponteiro */

struct s2 info3;
info3.a = 10;
info3.nome = "Jos da Silva";

/* nome um ponteiro */

Operaes possveis entre estruturas:


A partir da definio: struct s1 v1, v2; temos:
40

1) atribuio:
v1 = v2;
2) comparao (somente igualdade e desigualdade)
if (v1 == v2)
{
...
}
possvel perguntarmos se duas estruturas so iguais ou diferentes, mas no se uma maior ou menor do que
a outra. No entanto, os campos (membros) de uma estrutura podem ser comparados com os de outra.
Apesar de na verso ANSI podermos passar estruturas por valor para as funes, isto deve ser evitado, j que
torna a chamada da funo mais lenta e aumenta a rea ocupada no stack.
A forma mais indicada para se passar estruturas utilizar pointers, como ser visto mais adiante.

16.1 Iniciao de estruturas


Para alguns compiladores, necessrio que as variveis locais sejam estticas.
struct s_carta
{
int carta;
char naipe;
};
struct s_carta c =
{
12,
'O'
};

/* Ouro, Copas, Paus e Espadas */

/* inicializa como dama de ouros */

16.2 Campos de bits


Os campos de bits ou bitfields tem como principal finalidade a economia de memria, porm em alguns casos
o cdigo gerado para a sua manipulao pode ser grande, gastando mais memria do que economizando.
Forma de definio:
struct <nome>
{
<tipo 1> <nome 1> : <tamanho em bits>;
<tipo 2> <nome2> : <tamnaho em bits>;
...
<tipo N> <nome n> : <tamanho em bits>;
};
// Obs.: <tipo> pode ser: int, unsigned int e signed int.
// Exemplo:
struct baralho
{
unsigned carta : 4;
unsigned nipe : 2;

/* 0 a 15 */
/* 0,
1,
2,
3
*/
/* ouros, copas,espadas, paus */

};
struct baralho x;
41

x.carta = 9;
x.nipe = 2;

/* 9 de espadas */

Ao contrrio de estruturas normais, os bitfields no podem ser usados com pointers.


16.3 Unies
Permitem armazenar em uma mesma regio valores de tipos diferentes.
Forma de definio:
union <nome>
{
<tipo1> <campo1>;
<tipo2> <campo2>;
...
<tipon> <campon>;
};
// Exemplo:
union mixed
{
char c;
float f;
int i;
};
union mixed x;
x.c = 'A';
...
x.f = 10.0;
...
x.i = 1;
A rea reservada para uma varivel deste tipo calculada pelo tamanho do maior campo. No exemplo acima,
a rea reservada teria o tamanho de um float.
Devemos notar que uma varivel deste tipo guarda apenas um valor de cada vez, isto , ao armazenar o dado
de um novo tipo apaga o do tipo anterior.
A seguir apresentado um exemplo no qual se monta em array de estruturas que guarda elementos de "tipos"
diferentes.
/* Exemplo do uso combinado de estrutura e unio:
Cria um array denominado tabela e dimenso TAMANHO.
Cada elemento do array contem uma estrutura que consiste de um ponteiro para caractere (nome), um
inteiro (tipo) e um membro do tipo union chamado "dados".
Cada membro dados do array pode conter int, float ou char.
*/
# include <stdio.h>
# define INTEGER 0
# define FLOATING 1
# define CHAR 2
# define TAMANHO 6
void main ( )
{
Struct S1
{
42

char *nome;
int tipo;
union
{
int i;
float f;
char c;
} dados;
} tabela [TAMANHO]; // Cria uma um vetor de estruturas denominado tabela
int j;
// Inicia os elementos da estrutura
tabela[ 0 ].nome
tabela[ 0 ].tipo
tabela[ 0 ].dados.c
tabela[ 1 ].nome
tabela[ 1 ].tipo
tabela[ 1 ].dados.c

=
=
=
=
=
=

"Cesar";
CHARACTER;
'A';
"do Vale ";
CHARACTER;
'A';

tabela[ 2 ].nome
= "Ferrari ";
tabela[ 2 ].tipo
= CHARACTER;
tabela[ 2 ].dados.c = 'A';
tabela[ 3 ].nome
= "Idade ";
tabela[ 3 ].tipo
= INTEGER;
tabela[ 3 ].dados.i = 42;
tabela[ 4 ].nome
= "Salrio ";
tabela[ 4 ].tipo
= FLOATING;
tabela[ 4 ].dados.f = 7200.56;
tabela[ 5 ].nome
= "Imposto ";
tabela[ 5 ].tipo
= FLOATING;
tabela[ 5 ].dados.f = 2785.89;
for (j = 0; j < TAMANHO; j++)
{
printf (" %s ", tabela[ j ].nome);
switch (tabela[ j ].tipo)
{
case INTEGER:
printf (" %d\n", tabela[ j ].dados.i);
break;
case FLOATING:
printf (" %.2f\n", tabela[ j ].dados.f);
break;
case CHARACTER:
printf ("%c\n", tabela[ j ].dados.c);
break;
default:
printf ("Tipo desconhecido %d - elemento %d.\n", tabela[ j ].tipo, j);
break;
}
}
}
43

16.4 Pointers para Estruturas


Como vimos anteriormente, devemos passar as estruturas atravs de pointers e no por valor. Isto deve ser
feito mesmo que no alteremos nenhum dos campos da estrutura.
/* Exemplo - Pointer para estruturas */
#include <stdio.h>
struct s_data
{
int dia, mes, ano;
};
typedef struct s_data sdata;
void prtdata (sdata *);
void main ( )
{
sdata data;
data.dia
= 15;
data.mes = 3;
data.ano = 1988;
prtdata ( &data);
/* passa o endereo da estrutura data */
}
void prtdata(sdata *data)
{
printf(" %d/% d/ %d \n", (*data).dia, (*data).mes, (*data). ano);
}
Existem duas formas de se acessar os valores de uma estrutura atravs de pointers:
(* < pointer >).< componente > ou < pointer > < componente >;
Exemplo:
sdata data, *pdata;
pdata = &data;
(*pdata).dia = 31;
(*pdata).mes = 12;
(*pdata).ano = 1989;

// ou pdatadia = 31;
// ou pdatames = 12;
// ou pdataano = 1989;

16.5. Ponteiro para percorrer array de ponteiros.


Como para os outros arrays, o nome de um array de ponteiros um ponteiro para o primeiro elemento do
array. Quando se passa um array de ponteiros como parmetro, o que realmente se passa um pointeiro para
o primeiro elemento do array.
// Exemplo: Imprimir tabela 'dias'.
typedef char *CHARPTR;

/* define tipo pointer para char */

void print_tab(CHARPTR *tab_ptr, int n)


{
CHARPTR *end_ptr = tab_ptr + (n - 1);
while (tab_ptr <= end_ptr)
printf (" %s\n", *tab_ptr++);
}
Esquema dos ponteiros:
44

tab_ptr
0

s e g u n d a \0

1
..
.

end_ptr
6
17.

e r

a \0

d o m i

n g o \0

Ponteiros para funes

Permitem passar funes como argumentos.


Forma de definio:
< tipo > (* func_ptr ) ( < tipos dos argumentos > );
Nota: se no forem colocados os parnteses, estar sendo defininda uma funo que retorna um pointer para
<tipo>.
// Exemplo:
int soma (int, int);
void main ( )
{
int (*ptr_soma) (int, int);
ptr_soma = soma;
// pointer para funo soma
x = (*ptr_soma) (3,5);
// x soma (3, 5);
}
// Exemplo: Fazer um programa que leia duas cadeias de caracteres numricos ou alfanumricos e as
compare conforme o seu tipo.
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
int numcmp (char *, char *);
void check (char *, char *, int (*cmp) (char *, char *));
void main ( )
{
char s1[ 80 ], s2[ 80 ];
gets (s1);
// obtm a primeira cadeia
gets (s2);
// obtm a segunda cadeia
// isalpha devolve um valor de zero se no endereo apontado por s1
//
houver um caractere alfabtico ou zero em caso contrrio
check (s1 ,s2, strcmp); // computa como caracteres
check (s1, s2, numcmp);
// comp. como nmeros

if (isalpha (*s1) )
else
}

void check (char *a, char *b, int (*cmp)(char *, char *))
{
if ( ! ( *cmp) (a, b) )
printf(" \n Iguais.\n");
else
printf ("\n Diferentes.\n");
}
45

int numcmp(char *a, char *b)


{
if (atoi ( a ) == atoi ( b ) )
return ( 0 );
else
return ( 1 );
}
Observaes sobre o exemplo:

a funo strcmp compara strings;

a funo isalpha retorna <> 0 para letra do alfabeto; e

a funo atoi transforma uma string em nmero inteiro

18.

Tipo enumerado

Faz com que uma varivel possa ter somente um valor dentre um conjunto determinado de valores.
Forma de definio:
enum <nome> {<conjunto de valores separados por vrgulas>};
Exemplo:
enum dia
{segunda, tera, quarta, quinta, sexta, sbado, domingo};
0
1
2
3
4
5
6
Este exemplo define o tipo dia. Uma varivel deste tipo somente poder receber um dos valores dados entre
parnteses.
enum dia, dia1, dia2, todos[7]; /* define variveis */
dia1 = segunda;
todos[6] = domingo;
Note que os valores entre parnteses no so strings.
Uma outra forma de definio possvel :
enum {segunda, ..., domingo} dia1, dia2;
Se usarmos as definies acima, a cada valor do tipo enumerado ser associado um valor inteiro, a partir de
zero (0). Entretanto, podemos indicar os valores inteiros que desejamos associar:
enum frutas {laranja = 7, lim,o = 6, jaca = 0};
enum frutas {pera = 2, laranja, abacate, lim,o = 7};
Apesar das definies acima, os valores dos tipos enumerados no so inteiros.
Erros:
dia1 = 1.0;
dia2 = 2;
Para usarmos o valor inteiro associado, devemos usar um "cast" para inteiro:
i = (int) dia1;

46

19.

Arquivos

A linguagem C possui alguns arquivos pr-definidos e que so automaticamente abertos quando um programa
comea a ser executado.
Eles so:
stdin
stdout
stderr
stdprn

standard
standard
standard
standard

input
output
error
printer

(default = teclado)
(default = vdeo)
(default = vdeo)
(somente alguns compiladores)

Os arquivos pr-definidos stdin, stdout e stderr podem ser redirecionados pelo usurio.
O arquivo stdprn dependente do compilador, podendo existir ou no.
Para estes arquivo pr-definidos, a leitura e impresso se passam como se estivssemos utilizando um arquivo
texto (leitura e gravao seqenciais).
O conceito de arquivos em C um pouco diferente do de outras linguagens.
Na maioria das linguagens, o tipo de acesso (direto ou seqencial) est diretamente ligado forma de abertura
do arquivo, o que no acontece em C.
Em C, o acesso a um arquivo pode ser direto ou seqencial, sendo que esta escolha feita conforme as
necessidades do usurio.
O C possui funes que permitem o acesso tanto direto quanto seqencial e permitem um acesso bastante
eficiente arquivos.
Forma de definio:
FILE *fp;
Para que esta definio esteja correta, necessrio que o arquivo stdio.h tenha sido includo.
19.1. Funes para abertura e fechamento de arquivos
19.1.1.

Abertura de arquivos:
FILE *fopen (char *, char *);
fp = fopen (nome, modo);

47

Esta funo abre o arquivo de nome "nome" com o modo "modo"."nome" e "modo" so strings de caracteres.
Os modos de abertura possveis so apresentados na tabela abaixo:
Modo

Tipo

Read

Write

Cria

Append

r+

rb

rb+

w+

wb

wb+

a+

ab

ab+

Onde:
r read
w write
a append
t texto
b binrio
s sim
n no
Em caso de sucesso na abertura, a funo fopen retorna um ponteiro para o arquivo, o qual ser utilizado
como nome lgico do arquivo dentro do programa e, em caso de erro, retorna NULL.
responsabilidade do usurio verificar se o arquivo foi aberto ou no.
Exemplo:
fp = fopen ("teste.dat", "r");
if (fp == NULL)
// ou if (!fp) fp foi declarado antes como FILE *fp
{
printf(" \n Erro: abertura de arquivo para leitura");
exit ( 1 ); /* retorna para o sistema operacional */
}
O nome do arquivo pode indicar um nome simples ou um nome com path (caminho).
Exemplos de nomes:
"teste.dat"
"C:\programas\testes\teste.dat"
A diferena bsica entre os modos texto e binrio reside no fato de que quando os arquivos so abertos no
modo texto para gravao, o caractere NL (New Line) convertido em dois: CR (Carriage Return) e LF
48

(LineFeed) e quando so abertos no modo texto para leitura, ocorre o inverso. Para arquivos abertos no modo
binrio, esta converso no existe, havendo, portanto, uma correspondncia de 1 para 1.
19.1.2.

Fechamento de arquivos:
int fclose(FILE *);
fclose(fp);

Em caso de sucesso a funo fclose ( ) retorna NULL. Em caso de erro um valor diferente de zero.
Exemplo:
if ((fp = fopen ("teste.dat", "r")) == NULL)
{
printf (" \n Erro de abertura para leitura");
exit (1);
}
...
fclose(fp);
19.2. Principais funes para leitura e gravao seqenciais
Leitura:
char *fgets(char *, int, FILE *);
pchar = fgets(buffer, num, fp);
L caracteres do arquivo dado por fp. A leitura termina quando forem lidos num 1 caracteres, ou quando
encontrar o caractere NL (New Line) ou EOF (End Of File).
Os caracteres lidos so colocados em um buffer. Se a leitura foi correta, a funo retorna um pointer para o
buffer e em caso de erro retorna NULL.
O buffer deve ser grande o suficiente para que sejam colocados os caracteres '\0' e NL.
Exemplo:
char *pchar, buffer[ 100 ];
FILE *fp;
...
pchar = fgets(buffer, 98, fp);
...
int fgetc (FILE *);
v_int = fgetc ( fp );
L um caractere do arquivo dado por fp e retorna o seu cdigo ASCII. Se a leitura chegar ao final do arquivo
ou houver erro de leitura, retornado EOF. Entretanto, deve-se usar esta funo com certo cuidado, j que
EOF pode ser um caractere vlido em arquivos abertos no modo binrio.
int fscanf (FILE *, char *, ...);
fscanf(fp, fmt, args);
Funciona de forma semelhante funo scanf. Le as variveis em args com o formato fmt do arquivo dado
por fp. Em caso de sucesso, retorna o nmero de variveis que foram lidas. Caso se chegue ao final do
arquivo, retornado EOF.
Gravao:
49

int fputs (char *, FILE *);


fputs (str, fp);
Grava a string str no arquivo dado por fp. A funo retorna zero (0) se gravou bem e outro valor em caso de
erro.
int fputc (int, FILE *);
fputc (carac, fp);
Grava o caractere que est na varivel carac no arquivo dado por fp. Em caso de erro, retorna EOF, porm se
o arquivo for aberto em modo binrio, EOF poder ser um caractere vlido.
int fprintf (FILE *, char *, . . . );
fprintf (fp, fmt, args);
Funciona de forma semelhante funo printf. Grava as variveis em args com o formato fmt no arquivo
dado por fp. Em caso de sucesso, retorna o nmero de caracteres que foram gravados e em caso de erro,
retorna um nmero negativo.
// Exemplo: fazer um programa que copie um arquivo em disco para outro. Os nomes dos
// arquivos so fornecidos como parmetros na linha de comando, sendo o primeiro o
// nome do arquivo origem e segundo o nome do arquivo destino.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main (int argc, char *argv[])
{
char buffer [ 512 ];
char arqorg [ 150 ], arqdst [ 150 ];
FILE *nome1, *nome2;
if (argc < 3) {

printf(" \n Erro: Nmero de parmetros incorreto");


exit ( 1 );

}
strcpy (arqorg, argv [ 1 ] );
strcpy (arqdst, argv [ 2 ] );
nome1 = fopen ( arqorg, "rb");
nome2 = fopen ( arqdst,"wb");
if (nome1 == NULL | | nome2 == NULL)
{
printf(" \nErro na abertura dos arquivos.\n");
exit ( 1 );
}
while (fgets (buffer, 512, nome1) )
fprintf (nome2, buffer);
fclose (nome1);
fclose(nome2);
}
19.3. Principais funes para leitura e gravao direta (arquivos tipo binrio)
Normalmente, para acesso direto se abre o arquivo como binrio, para que a correspondncia de caracteres
seja de 1 para 1.
Funes para posicionamento:
rewind: coloca o ponteiro interno de IO no incio do arquivo dado por fp.
50

void rewind (FILE *);


rewind ( fp );
fseek move o ponteiro interno de IO do arquivo dado por fp conforme offset e origem. O parmetro
offset indica o nmero de bytes, a partir da origem origem, que o ponteiro deve se deslocar. Os valores
possveis para origem so:
0 ou SEEK_SET incio do arquivo
1 ou SEEK_CUR posio atual do ponteiro
2 ou SEEK_END final do arquivo
int fseek (FILE *, long int, int);
x = fseek (fp, offset, origem);
// Note que a varivel offset do tipo long int.
// Por exemplo, a instruo fseek (fp, 0l, 0) equivalente a rewind (fp).
// A funo fseek retorna zero (0) para sucesso e um valor diferente de zero (0) para erro.
fread : l para buf nblocos de tam bytes do arquivo dado por fp.
int fread (void *, int, int, FILE *);
x = fread (buf, tam, nblocos, fp);
// A funo fread retorna o nmero de blocos lidos.
fwrite: funciona como fread, s que para gravao. A funo retorna o nmero de blocos que foram
gravados.
int fwrite (void *, int, int, FILE *);
x = int fwrite (buf, tam, nblocos, fp);
// Exemplo: gravar e ler a varivel double x de um arquivo.
...
double x;
...
fwrite (&x, sizeof (double), 1, fp);
...
fread (&x, sizeof (double), 1, fp);
ftell: retorna a posio atual (em bytes) do ponteiro do arquivo em relao origem.
long ftell ( FILE *);
y = ftell ( fp );
// Exemplo: Fazer um programa inicie um vetor de 100 elementos com os nmeros de 0 a 99,
// o grave em um arquivo e o leia para outro vetor.
# include <stdio.h>
# include <stdlib.h>
void main ( )
{
FILE *fp;
int i;
float v1[100], v2[100], *pv;
for (pv = v1, i = 0; i < 100; i++)(*pv)++ = (float) i;
if ((fp = fopen("teste.dat", "wb")) == NULL)
51

// inicia o vetor
// abre o arquivo

printf("\nErro de abertura: gravao");


exit ( 1 );

}
fwrite(v1, sizeof(float), 100, fp);
fclose(fp);

// grava vetor
// fecha o arquivo

if ( ( fp = fopen ("teste.dat", "rb")) == NULL)


{
printf(" \n Erro de abertura: leitura");
exit ( 2 );
}
fread ( v2, sizeof (float), 100, fp);
fclose ( fp );
for (pv = v2, i = 0; i < 100; i++)printf (" %.2f\n", (*PV)++);

// reabre o arquivo teste

// l para novo vetor


// fecha o arquivo/
// imprime vetor lido

}
/* Exemplo: Fazer um programa que grave em um arquivo trs vetores de 100 elementos
cada, sendo o primeiro formado pelos nmeros de 0 a 99, o segundo os 100 primeiros
nmeros pares e o terceiro os 100 primeiros mltiplos de 3. A seguir fechar o arquivo e
reabri-lo lendo e imprimindo cada um dos vetores.
*/
# include <stdio.h>
#i nclude <stdlib.h>
# define TAM 100
void main ( )
{
FILE *fp;
int i;
float v1[TAM], *pv;
if ((fp = fopen ("teste.vet", "wb")) == NULL)
// Abre arquivo testando se houve erro.
{
printf(" \n Erro ao abrir arquivo inicial.\n");
exit(1);
}
for (pv = v1, i = 0; i < TAM; i++)
*pv++ = (float)i;
// Gera nmeros de 0 a 99
// Grava apenas um bloco de tamanho v1, o que equivale a gravar sizeof (float) x TAM
// Testa se gravou tudo.
if (fwrite(v1, sizeof(v1), 1, fp) != 1)
{
printf (" \n Erro ao gravar vetor 1.\n");
exit ( 2 );
}
for (pv = v1, i = 0; i < TAM; i++)
(*pv)++ = (float) i * 2;
// vet = 0,2,4,...,198
// Grava TAM blocos com dimenso float, o que equivale a gravar sizeof (float) x TAM
// Testa se gravou tudo.
if (fwrite(v1, sizeof(float), TAM, fp) != TAM)
{
printf (" \n Erro ao gravar vetor 2.\n");
exit ( 3 );
}
for (pv = v1, i = 0; i < TAM; i++)
*pv++ = (float) i * 3; /* vet: 0,3,6,...,297 */
// Grava TAM blocos com dimenso float, o que equivale a gravar sizeof (float) x TAM
// E testa se gravou tudo.
if (fwrite(v1, sizeof(float), TAM, fp) != TAM )
{
printf ("\nErro ao gravar vetor 3.\n");
52

exit ( 4 );
};
fclose ( fp );

// Fecha o arquivo/

// Reabre arquivo testando se houve erro.


if ((fp = fopen("teste.vet", "rb")) == NULL)
{
printf(" \n Erro ao reabrir o arquivo.\n");
exit ( 5 );
}
fread(v1, sizeof(v1), 1, fp);
for (pv = v1, i = 0; i < TAM; i++)
printf("%f ", *pv++);
printf ("\n\n");
rewind (fp);

// L o primeiro vetor
// Imprime primeiro vetor
// Pula 2 linhas
// Volta ao incio arquivo

// A partir do inicio e com deslocamento v1, aponta para o segundo vetor.


fseek (fp, (long) sizeof (v1), 0);
fread (v1, sizeof (float), TAM, fp);
for (pv = v1, i = 0; i < TAM; i++)
printf("%f ", *pv++);
printf ("\n\n");
rewind (fp);

// L o segundo vetor
// Imprime segundo vetor
// Pula 2 linhas
// Volta ao incio arquivo

// A partir do incio e com deslocamento de 2 x v1, aponta para o terceiro vetor.


fseek (fp, (long) sizeof (v1) * 2,0);
fread (v1, sizeof (v1), 1, fp);
// L o terceiro vetor
for (pv=v1, i=0; i<TAM; i++)
printf("%f ", *pv++);
// Imprime o terceiro vetor
printf ("\n\n");
// Pula duas linhas
fclose (fp);
// Fecha arquivo
}

Exemplo do uso de estruturas em arquivos:


struct s_prop
{
char nome[20];
double mod;
double coef;
};
typedef struct s_prop sprop;
sprop prop;
sprop variasprops[100];
...
// Grava uma propriedade
fwrite (&prop, sizeof(sprop), 1, fp);

// Grava um elemento da estrutura

// Grava vetor com vrias propriedades


fwrite(variasprops, sizeof(sprop), 100, fp);

53

REFERNCIAIS BIBLIOGRFICAS

1. ZWARCFITER, J.M. & MARKENZON, L.. Estruturas de Dados e Seus Algoritmos. Ed. LTC Rio de
Janeiro, 1994.
2. TENENBAUM, A.et alk. Estruturas de Dados Usando C. Ed. Makron Books, S~saao Paulo, 2001.
3. Furtado, A. et al Estruturas de Dados. Ed. Campus. Rio de Janeiro, 1985.
4. AZEREDO, P.A. Mtodos de Classificao de Dados. Ed. Campus. Rio de Janeiro, 1996.
4. O'BRIEN, S. C Completo e Total. Makron Books do Brasil, So Paulo 1992.

54

5.

ASCENCIO, A. Estruturas de Dados em DELPHI. Ed. Pearson / Prentice Hall, So Paulo,


2005.

6.

PUGA, S. & RISSETTI, G. Lgica de Programao e Estruturas de Dados. Ed. Pearson /


Prentice Hall, So Paulo, 2005.

7.

PUGA, S. & RISSETTI, G. Lgica de Programao e Estruturas de Dados Com


Aplicaes em Java. Ed. Pearson / Prentice Hall, So Paulo, 2005.

55

EXERCCIOS

AD I C I O N AI S

Cadeias de Caracteres - Strings


1)

Escreva um programa que receba, atravs do teclado, 5 (cinco) cadeias de at 20 caracteres e as


armazene em um array unidimensional vetor de dimenso 5 (cinco). Aps o programa dever pesquisar
os caracteres de cada elemento do vetor e, onde encontrar uma consoante b substitu-la pelo caracter 0
(zero), e onde encontrar um caractere consoante diferente de b substitu-la pelo caractere 1 (um).
As substituies devem ocorrer na prpria cadeia, na posio original onde as respectivas consoantes
porventura forem encontradas. Neste estgio do algoritmo as vogais no devem ser manipuladas.
Aps, o programa dever pesquisar novamente o vetor e, para cada elemento do vetor:
a) Visualizar a quantidade de vogais a , e , i , o e u que forem encontradas ;
b) Visualizar a quantidade de conjunto de vogais ae , ai, ao e au que forem encontradas ;
c) Apagar todas as ocorrncias consecutivas da cadeia ua ;
d) Substituir todas ocorrncias de duas vogais consecutivas pela cadeia xx ;
e) Indicar todas as posies relativas das possveis ocorrncias da cadeia ea ; e
f) Inserir seu nome, em formato minsculo, a partir da quarta posio de cada cadeia ;
g) Visualizar, em formato maisculo, todas as vogais presentes nas cadeias do vetor ;
56

h) Sempre que possvel, concatenar seu primeiro sobrenome em cada cadeia do vetor ; e
i ) Visualizar a quantidade de caracter em cada cadeia do vetor.
2) Escreva um programa que receba 1 (um) valor inteiro, 1 (um) caracter alfabtico forosamente em
formato minsculo e 3 (trs) cadeias de 10 (dez) caracteres tambm forosamente em formato
minsculo atravs do teclado e, aps:
a) Transforme o valor inteiro digitado em uma cadeia e o visualize ;
b) Visualize o caracter alfabtico em sua forma maiscula ;
c) Concatene as 2 primeiras cadeias em uma nica cadeia de 20 caracteres, e a visualize ;
d) Visualize a cadeia resultante do processado no item 3 (trs) em formato maisculo ;
e) Execute a gerao de uma 4 a cadeia que deve ser resultante da extrao de 5 caracteres da cadeia
gerada no item 4, a partir de seu 12o (dcimo segundo) caracter ;
f) Extraia 4 (quatro) caracteres da cadeia gerada no item 5 (cinco), a partir de seu 8 o (oitavo), e a
visualize aps a extrao ;
g) Execute a insero da 3a (terceira) cadeia digitada, na 2a (segunda) cadeia digitada, a partir de seu 5 o
(quinto) caracter;
h) Visualize a quantidade atual de caracteres das cadeias geradas at o momento ; e
i)

Informe, se for o caso, a posio do primeiro caracter da subcadeia aba na cadeia 1.

Registros - Structures
3)

Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com os
nomes e as notas (as notas tm de estar contidas no intervalo 0 nota 10) dos alunos, respectivamente,
de uma turma de 100 alunos.
Aps, exteriorize somente os nomes dos alunos que obtiveram notas iguais ou maiores que 5 (cinco).

4) Escreva um programa que preencha, a partir do teclado, duas estruturas distintas do tipo vetor com as
idades de 100 pessoas.
A primeira estrutura do tipo vetor dever receber somente as idades das pessoas do sexo masculino,
enquanto a segunda dever armazenar as idades das pessoas do sexo feminino.
Aps, o programa dever exteriorizar os nomes, o sexo e as idades das pessoas que possuem idade
compreendida entre 20 (vinte) e 40 (quarenta) anos, inclusive.
5)

Escreva um algoritmo que preencha 3 (trs) estruturas do tipo registro com os nomes e as idades de 3
(trs) pessoas cada conjunto de informaes sobre uma pessoa dever ser contedo de um registro e,
aps, visualize o nome da(s) pessoa(s) de mais idade.

4)

Escreva um algoritmo que preencha uma estrutura do tipo vetor de registros, de dimenso igual a 100
(cem), onde cada registro deve conter o nome e a idade de uma pessoa, informados atravs do teclado e
que, aps, visualize o nome da pessoa de menor idade e o nome da pessoa de mais idade.

57

5)

Escreva um algoritmo que preencha uma estrutura do tipo vetor de registros, onde cada elemento
dever armazenar o nome, a idade e os 5 graus (notas) obtidos em 5 (cinco) verificaes de aprendizagem,
de uma turma de 90 (noventa) alunos.
Aps o programa dever visualizar os nomes de todos os alunos da turma acompanhados de sua situao
acadmica aprovado ou reprovado.
A situao de aprovado somente pode ser computada se o aluno obtiver todos os seus graus maiores ou
iguais a 5 (cinco). Caso contrrio, ele dever ser assinalado como reprovado.

6)

Escreva um algoritmo que preencha uma estrutura do tipo vetor de registros, de dimenso100 (cem),
onde cada registro deve armazenar o nome e a idade de uma pessoa e que, aps, os nomes dos alunos de
menor e maior idades, respectivamente.

7)

Escreva um algoritmo que preencha duas estruturas homogneas de dados, a saber:


a)

Um vetor de registros, onde cada elemento deve armazenar cdigo e nome de uma disciplina ; e

b)

Uma certa matriz de registros, onde cada linha representa uma disciplina, dentre aquelas
explicitadas no vetor, e onde devero ser armazenadas (em cada elemento da linha) a matrcula, o nome
e os 3 (trs) graus (notas) obtidos em suas verificaes de aprendizagem.

A turma possui 10 (dez) alunos que cursam, cada um, obrigatoriamente, 5 (cinco) disciplinas.
Aps, o algoritmo dever visualizar os nomes de todos os alunos da turma, acompanhados de sua situao
acadmica aprovado ou reprovado e, se o aluno estiver reprovado, qual(is) a(s) disciplina(s) que o
colocaram em tal situao.
A situao de aprovado somente pode ser computada se o aluno obtiver todos os seus graus maiores ou
iguais a 5 (cinco). Caso contrrio, ele dever ser assinalado como reprovado.
10) Escreva um programa que preencha, com dados fornecidos atravs do teclado:
a)

Dois vetores de dimenso 50 com valores inteiros na faixa de 1 a 50, que serviro como ndices para
as linhas e colunas, respectivamente, de uma certa matriz; e

b)

Uma matriz quadrada supramencionada, de ordem 50, com valores reais maiores que Zero;

No entanto, o programa s dever preencher as posies da matriz (linha x coluna) que tiverem como
ndices os contedos do 1o vetor (ndices para as linhas) e do 2 o vetor (ndices para as colunas). Todas as
outras posies da matriz devero estar preenchidas com Zeros
Abaixo apresentada uma representao grfica do quanto solicitado:

vet_col 1

2
1

vet_lin
1

37

45

50

1
2
3
4
5

3
3

4
4

5
22

6
40

7
46

49
0

50
0

22

40

46

50

58

37

48

45

49

50

50

59