Você está na página 1de 104

Programao I

Snia Virginia Alves Frana

Volume 3

Recife, 2009

Universidade Federal Rural de Pernambuco Reitor: Prof. Valmar Corra de Andrade Vice-Reitor: Prof. Reginaldo Barros Pr-Reitor de Administrao: Prof. Francisco Fernando Ramos Carvalho Pr-Reitor de Extenso: Prof. Paulo Donizeti Siepierski Pr-Reitor de Pesquisa e Ps-Graduao: Prof. Fernando Jos Freire Pr-Reitor de Planejamento: Prof. Rinaldo Luiz Caraciolo Ferreira Pr-Reitora de Ensino de Graduao: Prof. Maria Jos de Sena Coordenao de Ensino a Distncia: Prof Marizete Silva Santos Produo Grfica e Editorial Capa e Editorao: Allyson Vila Nova, Rafael Lira e Italo Amorim Reviso Ortogrfica: Marcelo Melo Ilustraes: Diego Almeida e Glaydson da Silva Coordenao de Produo: Marizete Silva Santos

Sumrio
Apresentao.........................................................................................5 Conhecendo o Volume 3.......................................................................6 Captulo 1 Armazenamento de Dados em Vetores..........................8 1.1 O que so vetores?.......................................................................8 1.2 Declarao de Vetores..................................................................9 1.3 Referncia a elementos de vetor. ................................................ 11 1.4 Inicializao de vetores...............................................................13 1.5 Leitura de elementos para o vetor...............................................15 1.6 Impresso dos elementos de um vetor. .......................................22 1.7 Tamanho de um vetor e segmentao de memria....................27 1.8 Passando vetores como parmetros de funes........................28 Captulo 2 Armazenamento de Dados em Registros. ....................35 2.1 O que so registros?...................................................................35 2.2 Declarao de um Registro.........................................................36 2.3 Acessando os campos do registro. ..............................................39 2.4 Vetor de registro..........................................................................40 2.5 Acessando os campos do vetor de registro. ................................42 2.6 Usando vetor de registro.............................................................43

Captulo 3 Armazenamento de Dados em Arquivos......................61 3.1 O que so arquivos?. ...................................................................61 3.2 Comandos para manipular arquivos binrios..............................64 3.3 Implementao das operaes bsicas em um arquivo. .............76 Consideraes Finais........................................................................103 Conhecendo a Autora. .......................................................................104

Apresentao
Caro(a) cursista, Seja bem-vindo (a) ao terceiro mdulo da disciplina Programao I. Neste mdulo, vamos dar mais um passo no nosso aprendizado sobre a linguagem de programao C. Nos dois volumes anteriores, aprendemos os comandos bsicos do C, a utilizar as estruturas de controle (seleo e repetio) e a modularizar nossos programas em mdulos ou funes. Com estes assuntos, adquirimos a capacidade de desenvolver programas mais elaborados. Neste livro, ns vamos aprender novas formas de armazenar nossos dados. Com os vetores e registros, poderemos manusear um volume maior de dados, de forma facilitada. Outro assunto muito importante que ser abordado neste volume o armazenamento de dados em arquivos. Atualmente, ao terminar a execuo do programa, todos os dados que foram digitados so perdidos. Com o armazenamento de dados em arquivos, isto no acontece. Assim, iremos desenvolver programas com operaes como: cadastro de elementos, remoo, alterao, consultas, listagens, etc. Continuem resolvendo as questes propostas no final de cada captulo, alm de executar buscas na Internet, visando um maior aprofundamento de cada assunto. Ao final deste mdulo, teremos a capacidade de resolver questes com operaes presentes nos principais sistemas de controle do mercado, como por exemplo: sistema de controle de estoque, sistema de controle de cliente, etc. Vamos comear mais uma nova etapa no conhecimento da linguagem de programao C? Bons estudos! Professora Snia Virginia Alves Frana

Programao I

Conhecendo o Volume 3
Neste terceiro volume, vocs iro encontrar o mdulo 3 da disciplina: Programao I. Este volume est estruturado em trs captulos, que sero estudados ao longo de 15h/aula. Para facilitar seus estudos, veja a organizao deste volume. Captulo 1: Armazenamento de Dados em Vetores Carga Horria do Captulo 1: 5 h/aula Objetivos do Captulo 1: Apresentar o uso de vetores para o armazenamento de dados. Contedo Programtico do Captulo 1 Definio de vetores; Declarao, leitura e escrita de dados em vetores; Passagem de vetores como parmetros de funes; Captulo 2: Armazenamento de Dados em Registros Carga Horria do Captulo 2: 5 h/aula Objetivos do Captulo 2: Apresentar o uso de registros para o armazenamento de dados. Contedo Programtico do Captulo 2 Definio de registros; Declarao, leitura e escrita de dados em registros; Vetor de registro; Captulo 3: Armazenamento de Dados em Arquivos Carga Horria do Captulo 3: 5 h/aula Objetivos do Captulo 3: Apresentar os principais comandos para o armazenamento de dados em arquivos. Com os arquivos, os dados manipulados no programa podem ser armazenados definitivamente. Contedo Programtico do Captulo 3 Definio de arquivos; 6

Programao I

Ponteiros; Comandos para manipulao de dados em arquivos; Ao final de cada captulo vocs encontraro: A seo Atividades e Orientaes de Estudo: que contm exerccios para a fixao do assunto estudado, alm de indicao de fruns de discusso. A seo Conhea Mais: que contm dicas de sites e livros que devem ser lidos para ampliar os seus conhecimentos. A seo Vamos Revisar?: que apresenta um resumo dos principais tpicos abordados no captulo.

Programao I

Captulo 1 Armazenamento de Dados em Vetores


Vamos conversar sobre o assunto? Neste terceiro volume, vamos aprender novas formas de armazenar nossos dados. Comearemos aprendendo como armazenar os dados em vetores. Com os vetores, ns podemos armazenar um grande conjunto de dados, facilitando o acesso e manuseio dos mesmos. Os dados so a alma de um programa. Assim, a manipulao dos dados de forma mais adequada e facilitada trar ganhos para o programa e para o programador. Vamos continuar a nossa caminhada?

1.1 O que so vetores?


Imaginem que um professor nos encomendou um programa, que tenha que armazenar as mdias dos 50 alunos de uma turma. Como faramos para armazenar essas mdias? At o ponto que estudamos a linguagem C, teramos que declarar 50 variveis do tipo float, uma por uma. Que trabalheira, no mesmo? E se o professor tivesse 300 alunos? Passaramos um tempo s declarando variveis e, alm disso, teramos muito trabalho para fazer o controle das mesmas. Mas no se preocupem, com os vetores, o professor pode ter mais de 1000 alunos, que a declarao e manuseio dos dados ser bem fcil.
Saiba Mais
Em ingls, um vetor chamado de array (que significa cadeia). Assim, quando temos um array, temos uma cadeia de inteiros, reais ou caracteres.
1

Os vetores so usados quando precisamos armazenar um conjunto de dados do mesmo tipo. Por exemplo: armazenar as 50 mdias dos alunos de uma turma (todas as mdias so do tipo float). Os vetores so bem convenientes j que iremos colocar todas as informaes dentro de um mesmo conjunto e faremos referncia de cada dado, individualmente, atravs de um ndice1. De maneira mais formal, os vetores so chamados de estruturas de dados homogneas (j que armazenam dados do mesmo tipo). Os vetores so formados por dados de mesmo tipo (homogneo) e possuem nmero fixo de elementos (esttico). Para entendermos melhor os vetores, vamos visualizar a sua representao grfica, na figura 1.1.

Programao I

media

3.0 0

7.5 1

5.8 2

9.5 3

8.2 4

Figura 1.1: Representao grfica de um vetor

Na figura 1.1, temos um vetor chamado media, formado por 5 elementos. Vocs lembram quando tnhamos uma varivel simples? Representvamos com uma nica caixa. Agora, com os vetores, teremos um conjunto de dados, por isso ele formado por vrias caixas. Em cada uma delas poderemos armazenar um valor. Todas as caixas tm um nico nome. Neste exemplo, o vetor se chama media. Notem que, abaixo de cada caixa temos um nmero. Estes nmeros so chamados de ndices. atravs do ndice, que iremos informar qual das caixas do vetor que estamos querendo acessar. J que todas as caixas tm um nico nome (media), a forma de diferenciar uma da outra o ndice. Entenderam? Na linguagem C, o ndice de um vetor, comea a partir de 0. Assim, em um vetor com 5 elementos, os ndices variam de 0 a 4 (como no exemplo da figura 1.1). Por isso, o primeiro elemento do vetor media est na posio de ndice 0. Podemos dizer que a mdia do segundo aluno est na posio de ndice 1 do vetor media, e igual a 7.5. Esta no a nica maneira de estruturar um conjunto de dados. Tambm podemos organizar dados sob forma de tabelas. Neste caso, cada dado referenciado por dois ndices e dizemos que se trata de um conjunto bidimensional (ou matriz). Vamos aprender, nas prximas sees, como manusear os vetores nos nossos programas.

1.2 Declarao de Vetores


Como j foi mencionado, um vetor um conjunto de variveis do mesmo tipo, que possuem um nome identificador e um ndice de referncia. A sintaxe para a declarao de um vetor a seguinte:
Sintaxe

tipo identificador[tamanho];

Programao I

onde: tipo: o tipo de dados que o vetor armazena: int, float, char, etc. identificador: o nome do vetor. As regras para nomear um vetor so as mesmas usadas para nomear variveis, constantes e funes. tamanho: o tamanho do vetor. Isto , o nmero de elementos que o vetor pode armazenar. A seguir, so apresentados exemplos de declaraes de vetores. Os vetores so declarados na seo de declarao de variveis do programa. Se estivermos desenvolvendo um programa modularizado, podemos declarar o vetor como uma varivel local de um mdulo.
Exemplo 1.1: declarao de vetores

1 2 3
Ateno
Ns j havamos utilizado vetor de caracteres, uma vez que trabalhamos com variveis que armazenam uma cadeia de caracteres. No prximo volume, teremos um captulo dedicado a este assunto.
2

int idade[100]; float nota[25]; char nome[80];

No primeiro exemplo, temos a declarao de um vetor chamado idade, que pode armazenar at 100 nmeros inteiros. No segundo exemplo, temos um vetor chamado nota, com capacidade para armazenar at 25 nmeros reais. E, finalmente, no terceiro exemplo, temos um vetor chamado nome, com capacidade de armazenar at 80 caracteres2. Ao declararmos um vetor, j temos que ter uma previso de quantos elementos sero armazenados no mesmo. Com isso, o processador saber quanto de memria precisa ser reservada para armazenar os dados do vetor, ao executar o programa. A quantidade de memria (em bytes) usada para armazenar um vetor pode ser calculada como:
quantidade de memria = tamanho do tipo * tamanho do vetor

O tamanho do tipo indica quantos bytes so necessrios para armazenar um determinado tipo de varivel (vimos este assunto no Volume 1 Captulo 3). Ao compilar o programa, a quantidade de memria necessria para armazenar o vetor alocada. Os vetores tm tamanhos fixos e no podemos armazenar mais elementos do que a quantidade que foi solicitada no momento da declarao do vetor. 10

Programao I

Por isso, so chamados de estticos. A quantidade de elementos no pode aumentar em tempo de execuo do programa. Tambm possvel declarar um vetor com tamanho parametrizado: usando uma constante. Declaramos uma constante com a diretiva #define, no incio do programa, e depois declaramos o vetor com esta constante como tamanho do vetor. Deste modo, podemos alterar o nmero de elementos do vetor antes de qualquer compilao do programa. Esta uma maneira simples de administrar o espao de memria usado pelo programa, e tambm testar os limites de um vetor.
Exemplo 1.2: Declarao de vetor usando uma constante no local do tamanho do vetor.

1 2

#define TAMANHO 30 int valor[TAMANHO];

No exemplo 1.2, o vetor valor ter capacidade de armazenar 30 elementos (este o valor da constante TAMANHO).

1.3 Referncia a elementos de vetor


Agora que j sabemos como criar os vetores, a partir da sua declarao, vamos aprender como acessar um elemento do vetor. Segue abaixo a sintaxe.
Sintaxe

identificador[indice]

onde: identificador: o nome do vetor que queremos acessar. ndice: o ndice do elemento do vetor que queremos acessar. Cada elemento do vetor referenciado pelo nome do vetor e, entre colchetes, tem-se o ndice, que um nmero inteiro. O ndice ir indicar qual elemento do vetor estamos querendo referenciar. A seguir, so apresentadas algumas atribuies a elementos de um vetor chamado valor, que composto por 10 elementos do tipo float.

11

Programao I

Exemplo 1.3: Acessando os elementos de um vetor

1 2 3 4 5 6

float valor[10]; int x; x = 3; valor[1] = 6.6; valor[x] = 9.9 valor[x+2] = 10.0;

//declarao do vetor

Entre os colchetes, que indicam o ndice do vetor que ser acessado, podemos ter: um valor (exemplo da linha 4), uma varivel (exemplo da linha 5) ou uma expresso (exemplo da linha 6). Devemos ter cuidado quando usamos variveis e expresses, pois estas devem ser inteiras e devem ter um valor dentro da capacidade de armazenamento do vetor. Ou seja, se o vetor foi declarado com tamanho 10, no podemos tentar acessar o ndice 18 do vetor. Na linha 4, foi atribudo 6.6 ao elemento de ndice 1 do vetor valor. Na linha 5, como a varivel x tem armazenado 3, ento o valor[3], receber 9.9. Quando temos uma expresso, que o caso da linha 6, a expresso resolvida primeiro. Assim, como x = 3, e entre os colchetes temos x+2, o resultado ser 5. Dessa forma, valor[5] receber 10.0. A seguir, temos a situao final do vetor valor, aps as atribuies dos valores do exemplo.
Valor 0 6.6 1 2 9.9 3 4 10.0 5 6 7 8 9

Figura 1.2: Situao do vetor valor aps atribuies

Viram como fcil trabalhar com vetor? Em uma nica linha, ns criamos um conjunto de variveis, do tamanho da nossa necessidade. Posteriormente, acessamos cada uma destas variveis utilizando o nome do vetor e o ndice da varivel. Na prxima seo, vamos ver como fazemos para inicializar os elementos de um vetor, no momento da declarao.

12

Programao I

1.4 Inicializao de vetores


No momento da declarao de um vetor, tambm podemos inicializar os seus elementos, fazendo a atribuio de valores aos mesmos. A sintaxe para a inicializao dos elementos de um vetor a seguinte:
Sintaxe

tipo identificador[tamanho] = {lista de valores};

Onde: tipo: o tipo dos elementos do vetor: int, float, char, etc. identificador: o nome do vetor. tamanho: o tamanho do vetor. Isto , o nmero de elementos que o vetor pode armazenar. lista de valores: uma lista, separada por vrgulas, dos valores de cada elemento do vetor. A lista de valores colocada entre chaves. Vamos ver a seguir, exemplos de inicializao de vetores.
Exemplo 1.4: Inicializao de vetores

1 2 3 4

int idade[7] = {12, 30, 14, 7, 13, 15, 6}; char vogal[5] = {a, e, i, o, u}; float nota[5] = {8.4, 6.9, 4.5}; float media[5] = {0};

No exemplo da linha 1, temos o vetor chamado idade e para cada posio do vetor, foi atribudo um valor. Aps esta atribuio, o vetor idade ficar assim:
idade 12 0 30 1 14 2 7 3 13 4 15 5 6 6

Figura 1.3: Situao do vetor idade aps inicializao

No segundo exemplo, temos um vetor de caracteres, chamado vogal. Quando inicializamos um vetor deste tipo de varivel, os valores 13

Programao I

devem ser colocados entre apstrofo. Ao final desta atribuio, o vetor vogal ficar como mostra a figura 1.4.
vogal a 0 e 1 i 2 o 3 u 4

Figura 1.4: Situao do vetor idade aps inicializao

Na linha 3, temos a inicializao do vetor nota, que composto por cinco elementos. Notem que, entre as chaves, no temos cinco valores. Temos apenas trs. Quando no quisermos inicializar todo o vetor, podemos colocar apenas os valores dos primeiros elementos, e aos demais, ser atribudo zero (automaticamente). Vejam na figura 1.5 como ficar o vetor nota, aps a sua inicializao.
nota 8.4 0 6.9 1 4.5 2 0.0 3 0.0 4

Figura 1.5: Situao do vetor idade aps inicializao

Seguindo o raciocnio do exemplo anterior, quando precisarmos inicializar todos os elementos do vetor com zero, fazemos como mostra o exemplo da linha 4. Colocamos apenas um zero entre as chaves, o primeiro elemento ser inicializado com zero, e os demais tambm. Neste caso, o vetor media ficar como apresentado na figura 1.6.
media 0.0 0 0.0 1 0.0 2 0.0 3 0.0 4

Figura 1.6: Situao do vetor media aps inicializao

Opcionalmente, podemos inicializar os elementos do vetor enumerando-os um a um. No exemplo 1.5, a seguir, observem que estas duas inicializaes so possveis:

14

Programao I

Exemplo 1.5: Inicializao de vetores

1 2 3 4 5 6

int valor[3] = {7,4,20}; ou int valor[3]; valor[0] = 7; valor[1] = 4; valor[2] = 20;

Na prxima seo, vamos aprender a armazenar, em um vetor, valores que so fornecidos via teclado.

1.5 Leitura de elementos para o vetor


Agora suponham que os valores que vo ser armazenados no vetor sejam fornecidos pelo usurio, via teclado. O que devemos fazer? Devemos utilizar uma estrutura de repetio, para controlar o preenchimento dos dados no vetor, um por um. Assim, podem ocorrer duas situaes: Ns sabemos quantos elementos o usurio vai digitar; Ns no sabemos a quantidade de elementos que o usurio vai digitar. Vamos ver como tratar cada uma das situaes? Quando ns sabemos quantos elementos o usurio vai digitar, poderemos usar uma estrutura de repetio como o for, que ir repetir a leitura dos elementos, na quantidade definida. Vamos ver o Programa Completo 1.1 a seguir: o usurio precisa armazenar 5 elementos em um vetor de inteiros, chamado valor.

15

Programao I

Programa Completo 1.1: Ler 5 nmeros inteiros, armazenando-os em um vetor

1 2 3 4 5 6 7 8 9 10 11

main() { int valor[5]; int i; printf(Cadastro dos elementos do vetor Valor \n\n); for (i=0; i<5; i++) { } getche(); } printf(\n\nElemento %d: ,i+1); scanf(%d,&valor[i]);

Comentrios sobre o Programa Completo 1.1: Linha 3: declarao do vetor valor, que tem a capacidade de armazenar 5 nmeros inteiros. Linha 4: declarao da varivel i, que ir controlar o for. Linha 5: printf para que o usurio saiba que ser feito o cadastro dos elementos no vetor. Linha 6: for que ser repetido 5 vezes, fazendo a leitura dos elementos do vetor. Notem que a varivel de controle do for, o i, inicializado com 0. Isso acontece porque o primeiro ndice do vetor 0. Linha 7: Abre chaves que inicia a sequncia de comandos do for (j que teremos mais de um comando). Nesta linha, tambm temos o printf para que o usurio saiba qual elemento do vetor est sendo cadastrado no momento. Vejam que neste printf temos a expresso: i+1. O motivo de colocarmos esta expresso no printf que, como o i comea com zero e vai at 4, no ficaria muito interessante que sasse uma mensagem, na tela, informando que o usurio estaria cadastrando o elemento 0. O correto dizer que ele est cadastrando o elemento 1. Por 16

Programao I

isso, usamos a expresso i+1. Linha 8: scanf que l o valor, armazenando no vetor. Notem que estamos usando a varivel i, no ndice do vetor. Dessa forma, o i vai variando a cada vez que o for repetido, e assim, os elementos so armazenados em ndices diferentes do vetor. Com isso, nenhum elemento ir sobrepor o outro. Linha 9: fecha chaves que indica o final da sequncia de comandos do for. Linha 10: comando getche que faz com que a tela de execuo do programa fique aberta, e assim podemos ver o resultado do programa. Linha 11: fecha chaves, indicando o final do programa principal. A figura 1.7, apresenta a tela de execuo do Programa Completo 1.1.

Figura 1.7: Tela de execuo do Programa Completo 1.1

Para facilitar o entendimento, vamos fazer um acompanhamento dos valores das variveis do Programa Completo 1.1, ao longo da sua execuo. Vamos considerar que o usurio est cadastrando os valores apresentados na figura 1.7. A figura 1.8 mostra os valores das variveis do programa, conforme o programa vai sendo executado.

17

Programao I

i 0

i+1 1 10 0 10 0 1 15 1

valor

10 0 10 0

15 1 15 1

9 2 9 2 3 6 3 4 4

10 0

15 1

9 2

6 3

12 4

Figura 1.8: Acompanhamento das variveis do Programa Completo 1.1

O que fazemos quando no sabemos quantos elementos sero armazenados no vetor? Neste caso, como no sabemos quantas vezes o for deve ser executado, poderemos fazer a leitura dos dados que sero colocados no vetor, usando um do/while, como mostra o Programa Completo 1.2, a seguir. Neste programa, iremos fazer a leitura de uma quantidade indeterminada de nmeros inteiros, armazenando em um vetor.

18

Programao I

Programa Completo 1.2: Ler um conjunto de nmeros inteiros, armazenando-os em um vetor.

1 2 3 4 5 6 7 8 9 10 11 12 13

main() { int valor[5]; int q, continuar; q=0; printf(Cadastro dos elementos do vetor Valor \n\n); do { printf(\n\nElemento %d: ,q+1); scanf(%d,&valor[q]); q++; outro elemento

printf(\n\nCadastrar (1-sim/2-nao)? ); scanf(%d, &continuar);

} while ((continuar==1) && (q<5)); }

Neste caso, a leitura ser finalizada quando o vetor ficar cheio, com cinco elementos, ou quando o usurio decidir que no deseja mais continuar a leitura. Neste ltimo caso, saberemos quantos elementos foram armazenados no vetor atravs da varivel q. esta varivel que indica, tambm, em qual ndice do vetor o elemento deve ser armazenado3. Comentrios sobre o Programa Completo 1.2: Linha 2: declarao do vetor valor, que tem a capacidade de armazenar 5 nmeros inteiros. Linha 3: declarao das variveis q (que controlam a quantidade de elementos que j foram cadastrados no vetor) e continuar (que armazena a resposta do usurio informando se quer cadastrar mais elementos ou no). Linha 4: inicializao da varivel q com 0. Linha 5: printf para que o usurio saiba que ser feito o cadastro 19

Ateno
3 Quando no sabemos quantos elementos sero cadastrados, temos que estipular um valor para a quantidade de elementos que sero armazenados no vetor. Isso se d porque temos que saber o tamanho do vetor no momento da sua declarao.

Programao I

dos elementos no vetor. Linha 6: do indicando o incio da repetio. Linha 7: Abre chaves que inicia a sequncia de comandos do do/while (j que teremos mais de um comando). Nesta linha, tambm temos o printf para que o usurio saiba qual elemento do vetor est sendo cadastrado no momento. Linha 8: scanf que l o valor que ser armazenado no vetor. Notem que estamos usando a varivel q, no ndice do vetor. Linha 9: incremento da varivel q, indicando que mais um elemento foi cadastrado no vetor. Atravs do valor de q, saberemos se o vetor j est cheio ou no. Linha 10: prinft que pergunta ao usurio se deseja cadastrar outro elemento no vetor. O usurio pode parar o cadastro dos elemento do vetor, no momento que ele desejar. Nesse caso, o vetor pode ficar com posies sem valores armazenados. Linha 11: scanf para ler a resposta do usurio. Linha 12: fecha chaves do do/while e while com a condio que faz com que a repetio fique sendo executada. Como a condio formada por duas expresses relacionais, ns colocamos cada expresso relacional entre parnteses e depois colocamos toda a expresso entre parnteses. As expresses esto conectadas pelo operador && (e). Com isso, quando uma das expresses der falso, a repetio para. Vai parar porque o vetor est cheio (q=5) ou porque o usurio desejou parar, respondendo 2 a pergunta se deseja continuar. Linha 13: fecha chaves, indicando o final do programa principal. A figura 1.9, apresenta a tela de execuo do Programa Completo 1.2.

20

Programao I

Figura 1.9: Tela de execuo do Programa Completo 1.2

Vamos acompanhar o valor das variveis do Programa Completo 1.2? A Figura 1.9 mostra o cadastramento de 3 elementos no vetor. O usurio respondeu que no queria mais cadastrar aps dar entrada ao terceiro elemento. A figura 1.10 mostra os valores das variveis do programa, conforme o programa vai sendo executado.
q q+1 12 0 1 2 3 4 valor

12 0

15 1 2 3 4

12 0

15 1

18 2 3 4

Figura 1.10: Acompanhamento das variveis do Programa Completo 1.2

Agora que j sabemos colocar informaes em um vetor via teclado, vamos ver como apresentar, na tela, os valores armazenados em um vetor.

21

Programao I

1.6 Impresso dos elementos de um vetor


Quando desejarmos apresentar os elementos que esto armazenados no vetor, devemos utilizar uma estrutura de repetio, que far com que cada uma das posies do vetor seja visitada e seu contedo apresentado. Vale lembrar que, quando declaramos um vetor, indicamos a sua capacidade de armazenamento. Mas durante a execuo do programa, pode ser que o usurio no armazene dados suficiente para preencher todas as posies do vetor. Assim, quando formos imprimir os dados de um vetor, precisamos saber quantos elementos tm armazenado no momento da impresso. O Programa Completo 1.3, mostra a leitura e a impresso dos dados armazenados em um vetor.
Programa Completo 1.3: Ler e imprimir um conjunto de nmeros inteiros, armazenando-os em um vetor.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

main() { int valor[5]; int q, continuar, i; q=0; printf(Cadastro dos elementos do vetor Valor \n\n); do { printf(\n\nElemento %d: ,q+1); scanf(%d,&valor[q]); q++; outro elemento

printf(\n\nCadastrar (1-sim/2-nao)? ); scanf(%d, &continuar);

} while ((continuar==1) && (q<5)); printf(\n\nElementos do Vetor: ); for (i=0; i<q; i++) printf( %d ,valor[i]);

getche(); }

22

Programao I

At a linha 12, o Programa Completo 1.3 , praticamente, idntico ao Programa Completo 1.2. A nica diferena que temos, na linha 3, a declarao da varivel i, que ser usada no for que imprimir os elementos do vetor. Vamos ver o que est acontecendo nas demais linhas? Linha 13: printf para informar que sero apresentados os elementos do vetor. Notem que o texto entre aspas no termina com \n. Isso se d porque no queremos que o cursor v para a linha seguinte. Linha 14: for que ser utilizado para percorrer o vetor, acessando cada uma das posies do vetor. A varivel que tem a informao de quantos elementos foram armazenados no vetor q. Dessa forma, o i do for vai variar de 0 at q-1. Uma vez que se q for 3, a ltima posio ocupada no vetor 2. Linha 15: printf que apresenta o elemento do vetor, na posio de ndice i. Este printf tambm no tem o \n, porque queremos que os elementos do vetor sejam impressos um ao lado do outro. Este o nico comando do for, por isso no houve a necessidade de delimitar com chaves. Linha 16: getche que evita o fechamento da janela de execuo do programa, e assim poderemos ver os elementos do vetor impresso. Linha 17: fecha chaves, indicando o final do programa principal. A figura 1.11 apresenta a tela de execuo do programa 1.3. Foram cadastrados os mesmos valores do exemplo anterior.

23

Programao I

Figura 1.11: Tela de execuo do Programa Completo 1.3

Neste caso, apesar do vetor ter sido declarado com 5 posies, s foram preenchidas 3 posies. Vejam que, aps o usurio responder que no quer mais cadastrar, os elementos do vetor so apresentados um ao lado do outro. Vamos ver outro Programa Completo? Neste programa, iremos ler as matrculas e notas dos alunos de uma turma e imprimir as matrculas dos alunos de tiveram nota acima da mdia das notas da turma.
Programa Completo 1.4

1 2 3 4 5 6 7 8 9 10

main() { int mat[10]; float nota[10]; int q, i, continuar; float soma, media; soma = 0; q=0; do { system(cls);

printf(Universidade Aberta do Brasil UFRPE\n\n);

24

Programao I

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

q+1); );

printf(\n\nDados

do

Alunos

%d\n\n,

printf(\nMatricula: ); scanf(%d,&mat[q]); printf(\nNota: ); scanf(%f,&nota[q]); soma = soma + nota[q]; q++; printf(\n\nCadastrar outro(1-sim/2-nao)? scanf(%d, &continuar);

} while ((continuar==1) && (q<10)); media = soma/q; system(cls); printf(Universidade Aberta do Brasil - UFRPE \n\n); printf(Media da turma: %.2f\n\n\n,media); printf(Alunos turma\n\n); com nota acima da media da

for (i=0; i<q; i++) { if (nota[i]>media) printf(%d \n,mat[i]);

printf(\n\nDigite ); getche(); }

qualquer

tecla

para

sair

Comentrios sobre o Programa Completo 1.4: Linhas 2 a 5: declarao das variveis do programa. Vejam que precisamos de um vetor para armazenar as matrculas e um outro para armazenar as notas. 25

Programao I

Linhas 6 e 7: inicializao das variveis soma (que acumula as notas de todos os alunos) e q (que conta quantos elementos foram cadastrados no vetor). Linhas 8 a 20: do/while que faz a leitura das matrculas e das notas de cada aluno, armazenando nos respectivos vetores. Neste do/while, o usurio pode parar o cadastro no momento que ele desejar. Para calcularmos a mdia da turma, temos que somar as notas de todos os alunos e dividir pela quantidade de alunos. Assim, enquanto estivermos no do/while, estamos acumulando as notas de todos os alunos na varivel soma. Linha 21: ao sair do do/while, a mdia da turma pode ser calculada. Linha 22: usa o system(cls) para limpar a tela e dar incio tela que ir apresentar os resultados. Linha 24: printf para apresentar a mdia da turma. Linhas 26 a 29: for para visitar cada posio do vetor que armazena as notas dos alunos. Quando verifica que a nota do aluno maior que a mdia da turma (armazenada na varivel media), a matrcula do aluno apresentada. A figura 1.12 apresenta a tela de execuo do Programa Completo 1.4, na fase do cadastramento dos dados dos alunos (matrcula e nota).

Figura 1.12: Tela de Execuo do Programa Completo 1.4 Cadastro de Alunos

A figura 1.13 apresenta a tela de execuo do programa completo 1.4, na fase do apresentao dos resultados.

26

Programao I

Figura 1.13: Tela de Execuo do Programa Completo 1.4 Apresentao dos Resultados

1.7 Tamanho de um vetor e segmentao de memria


Na linguagem C, devemos ter cuidado com os limites de um vetor. Embora na declarao tenhamos que definir o tamanho de um vetor, o compilador C no faz nenhum teste de verificao de acesso a um elemento dentro do vetor ou no. Por exemplo, se declaramos um vetor como int valor[5], teoricamente, s tem sentido usarmos os elementos valor[0], valor[1], valor[2] , valor[3] e valor[4]. Porm, o compilador C no acusa erro se usarmos valor[12] em algum lugar do programa. Estes testes de limite devem ser feitos dentro do programa, pelo programador. Este fato se deve maneira como o C trata os vetores. A memria do computador um espao (fsico) particionado em pores de 1 byte. Se declararmos um vetor como int valor[3], estamos reservando 12 bytes (3 segmentos de 4 bytes lembrando que cada int ocupa 4 bytes) de memria para armazenar os seus elementos. O primeiro segmento ser reservado para valor[0], o segundo segmento para valor[1] e o terceiro segmento para valor[2]. O segmento inicial chamado de segmento base, de modo que valor[0] ser localizado no segmento base. Quando acessamos o elemento valor[i], o processador acessa o segmento localizado em base+i. Se i for igual a 2, estamos acessando o segmento base+2 ou valor[2] (o ltimo segmento reservado para o vetor). Porm, se i for igual a 7, estamos acessando o segmento base+7 que no foi reservado para os elementos do vetor e que provavelmente est sendo usado por uma outra varivel ou contm uma informao inesperada (lixo). 27

Programao I

Observem que o acesso a um segmento fora do espao destinado a um vetor pode destruir informaes reservadas de outras variveis. Estes erros so difceis de detectar, pois o compilador no gera nenhuma mensagem de erro. Por isso, a soluo mais adequada sempre avaliar os limites de um vetor antes de manipul-lo. Como feito no Programa Completo 1.2 que vai cadastrando os elementos no vetor e para quando o vetor completa a sua capacidade. A princpio, este fato poderia parecer um defeito da linguagem, mas na verdade trata-se de um recurso muito poderoso do C. Poder manipular, sem restries, todos os segmentos de memria uma flexibilidade apreciada por programadores mais experientes.

1.8 Passando vetores como parmetros de funes


Os vetores, assim como as variveis simples, podem ser usados como argumentos de funes. Veremos como se declara uma funo que recebe um vetor como parmetro e como se chama uma funo passando um vetor como parmetro. A sintaxe de uma funo que recebe um vetor como parmetro a seguinte:
Sintaxe

tipo_retorno nome_funo(tipo_vetor nome_vetor[]) { //corpo da funo }

Onde: tipo_retorno: o tipo de retorno da funo. nome_funo: o nome da funo. tipo_vetor: o tipo de dados dos elementos do vetor. nome_vetor: o nome do vetor. Observe que depois do nome do vetor temos o [ e o ], mas no colocamos nada entre eles. Neste caso, no necessrio informar o tamanho do vetor. Quando formos chamar uma funo que recebe um vetor como 28

Programao I

parmetro, usamos a seguinte sintaxe:


Sintaxe

nome_da_funo(nome_do_vetor);

Onde: nome_da_funo: o nome da funo que ser chamada. nome_do_vetor: o nome do vetor que queremos passar como parmetro. Neste caso, indicamos apenas o nome do vetor, sem os colchetes. O exemplo 1.6, a seguir, apresenta a declarao de uma funo que tem um vetor como parmetro e a chamada da funo.
Exemplo 1.6: declarao e chamada de uma funo que tem um vetor como parmetro

1 2 3 4 5 6 7 8 9 10 11 12

float media(float vetor[],float N) { //corpo da funo }

main() { float valor[30]; // declarao do vetor float n; ... med = media(valor, n); // passagem do vetor para a funo ... }

Ateno: Ao contrrio das variveis comuns, o contedo de um vetor pode ser modificado pela funo chamada. Isto significa que podemos passar um vetor para uma funo e alterar os valores de seus elementos. Isto ocorre porque a passagem de vetores para funes feita de modo especial dito passagem por endereo. Portanto, devemos ter cuidado ao manipular os elementos de um 29

Programao I

vetor dentro de uma funo para no modific-los por descuido.

Atividades e Orientaes de Estudos Vamos fazer um conjunto de exerccios, usando o assunto que acabamos de aprender? Segue abaixo uma lista de exerccios em que os dados sero armazenados em vetores. Vamos comear? 1. Ler um conjunto de nmeros e imprimi-los na ordem inversa da leitura. A quantidade de nmeros tambm ser lida e ser no mximo 10. 2. Ler o tamanho e os elementos de dois vetores e, em seguida, caso os vetores tenham o mesmo tamanho, gere e imprima o vetor SOMA, onde seus elementos sero formados pela soma dos elementos de mesmos ndices dos dois vetores lidos. Exemplo:
A 1 0 4 1 7 2 2 3 9 4

3 0

5 1

11 2

4 3

8 4

Soma

4 0

9 1

18 2

6 3

17 4

3. Ler um vetor de nmeros e imprimir os valores armazenados nas posies PARES e, em seguida, os valores armazenados nas posies MPARES. Exemplo:
V 1 0 4 1 7 2 2 3 9 4

Valores nas posies pares: 1 7 9 30

Programao I

Valores nas posies impares: 4 2 4. Ler dois vetores e caso tenham tamanhos iguais, armazene seus elementos alternadamente em um terceiro vetor. Exemplo:
A 1 0 4 1 7 2 2 3 12 4

3 0

5 1

11 2

4 3

15 4

Resultante

1 0

3 1

4 2

5 3

7 4

11 5

2 6

4 7

12 8

15 9

5. Ler um vetor de nmeros inteiros e imprimir as posies do maior e do menor elemento do vetor. Assuma que no existem elementos repetidos no vetor. Exemplo:
V 14 0 13 1 7 2 22 3 9 4

O menor elemento se encontra na posio 2 O maior elemento se encontra na posio 3 6. Ler um vetor de nmeros e inverter a ordem dos elementos desse vetor no prprio vetor. Exemplo: Vetor antes de ser invertido:
V 14 0 13 1 7 2 22 3 9 4

Vetor depois de ser invertido:

31

Programao I

9 0

22 1

7 2

13 3

14 4

7. Ler dois vetores de nmeros e gerar um terceiro vetor formado pela INTERSECO dos dois vetores lidos. O resultado da interseo de dois conjuntos : os elementos que fazem parte dos dois conjuntos. Exemplo:
A 1 0 4 1 7 2 2 3 12 4

3 0

4 1

2 2

14 3

25 4

interseccao

4 0

2 1 2 3 4

8. Ler dois vetores de nmeros e gerar um terceiro vetor formado pela DIFERENA dos dois vetores lidos. O resultado da diferena de dois conjuntos : os elementos do conjunto A que no fazem parte do conjunto B. Exemplo:
A 1 0 4 1 7 2 2 3 12 4

3 0

4 1

2 2

14 3

25 4

Diferenca

1 0

7 1

12 2 3 4

32

Programao I

9. Ler dois vetores de nmeros e gerar um terceiro vetor formado pela UNIO dos dois vetores lidos. O resultado da unio de dois conjuntos : todos os elementos que fazem parte dos conjuntos A e B. Exemplo:
A 1 0 4 1 7 2 2 3 12 4

3 0

4 1

2 2

14 3

25 4

Unio

1 0

4 1

7 2

2 3

12 4

3 5

14 6

25 7 8 9

10. Ler um vetor de nmeros e imprimir os nmeros que se repetem nesse vetor. Exemplo:
V 1 0 4 1 7 2 1 3 2 4 1 5 4 6 25 7 3 8 7 9

Os nmeros que se repetem no vetor so: 1 4 7

Conhea Mais Para ampliar nossos conhecimentos sobre os assuntos tratados neste captulo, leiam o captulo que aborda armazenamento em vetores, do livro: SCHILDT, Herbert. C Completo e Total. So Paulo: Makron, 1996.

33

Programao I

Vamos Revisar? Vamos lembrar rapidinho o que foi visto neste captulo? Leia o resumo a seguir, composto com os principais conceitos apresentados. Vetores: conhecidos como estruturas de dados homogneas, os vetores so um conjunto de variveis que armazenam elementos do mesmo tipo. ndices: para acessar um elemento do vetor, precisamos indicar em que posio do vetor est o elemento. No momento da declarao dos vetores, precisamos indicar quantos elementos sero armazenados no mesmo. de responsabilidade do programador o acesso aos elementos do vetor. Se o programa tentar acessar uma posio que no existe no vetor, o compilador no indicar o erro. Quando passamos um vetor como parmetro de uma funo, seus valores podem ser alterados

34

Programao I

Captulo 2 Armazenamento de Dados em Registros


Vamos conversar sobre o assunto? Neste captulo, vamos aprender mais uma forma de armazenamento de dados, que so os registros. Nos registros podemos agrupar dados de tipos diferentes. Por conta disto, os registros so chamados de estruturas de dados heterogneas. Assim como os vetores, os registros vo facilitar o gerenciamento dos dados dos nossos programas, que esto cada vez maiores. Veremos, tambm, como unir os conceitos de vetores e registros, trabalhando com vetor de registro. Leiam este captulo com calma e ateno, uma vez que iremos utilizar registros em muitas situaes nos nossos programas, certo?

2.1 O que so registros?


Ns j sabemos que um conjunto homogneo de dados composto por variveis do mesmo tipo (vetores). Mas, e se tivermos um conjunto em que os elementos no so do mesmo tipo? Teremos, ento, um conjunto heterogneo de dados, que so chamados de registros. O registro uma das principais formas de estruturar os dados no programa. O conceito de registro visa facilitar o agrupamento de variveis de tipos diferentes, mas que possuem uma relao lgica. Um registro um conjunto de uma ou mais variveis, que podem ser de tipos diferentes, agrupadas sobre um nico nome. O fato de variveis agrupadas em um registro poderem ser referenciadas por um nico nome, facilita a manipulao dos dados armazenados nestas estruturas. Como exemplo de um registro, imaginem uma estrutura que armazene as diversas informaes do boletim de um aluno. O boletim formado por um conjunto de informaes logicamente relacionadas, porm de tipos diferentes, tais como: nmero de matrcula (inteiro), nome do aluno (caractere), nome da disciplina (caractere), mdia (real) e situao (caractere), que so subdivises do registro (elementos de conjunto), tambm chamadas de campos. Logo, um registro composto por campos que so partes que especificam cada uma das informaes. A figura 2.1 apresenta o boletim de notas de um aluno.

35

Programao I

Boletim de Notas Matricula...: 12345 Nome........: Michel Disciplina..: Matemtica Mdia........: 10.0 Situao....: Aprovado

Figura 2.1 Boletim de Notas

Notem que o boletim composto por informaes de diferentes tipos. No entanto, todas as informaes do boletim esto relacionadas ao mesmo aluno. O agrupamento de informaes de tipos diferentes, que tem uma relao lgica, facilitar a manipulao de dados. Nas prximas sees, vamos aprender a declarar e manipular registros.

2.2 Declarao de um Registro


Para declarar uma varivel, precisamos informar o seu tipo e dar um nome mesma. Mas um registro formado por vrias variveis de tipos diferentes. Como iremos declarar um registro? Para declarar um registro, necessrio informar quais variveis, e seus respectivos tipos, fazem parte do registro. Dessa forma, precisamos declarar cada campo do registro, agrupando-os em um novo tipo de dado. A declarao de um registro passa por duas fases: definio de um novo tipo de dado e declarao do registro propriamente dito. Vamos entender melhor isso tudo? Primeiramente, precisamos definir quais campos fazem parte do registro e criar um novo tipo de dado para o nosso programa. Precisamos criar um novo tipo de dado porque no conseguiramos representar o tipo de informao que o registro armazena, utilizando os tipos primitivos disponveis na linguagem: int, float, char, etc. Uma vez que o registro agrupa variveis de tipos de dados diferentes. Para criar um novo tipo de dado, utilizamos a seguinte sintaxe:

36

Programao I

Sintaxe

typedef struct { declarao das variveis; } nome_do_tipo;

Onde: typedef: indica que um novo tipo de dado ser definido. struct: indica que o tipo de dado que ser definido um registro, ou seja, um agrupamento de variveis de tipos de dados diferentes. declarao das variveis: so as variveis que fazem parte do registro. Neste local, precisamos especificar quais as variveis iro compor o registro, alm do tipo das mesmas. As variveis so colocadas entre chaves. nome_do_tipo: dado um nome ao novo tipo de dado que est sendo criado. S depois que o novo tipo de dado criado, que o registro poder ser declarado. Na sequncia, vamos ver a declarao de um registro. Assim como toda varivel, ao declarar uma varivel que um registro, precisamos dizer que tipo de dado o registro armazena. Neste caso, iremos dizer que o registro do tipo de dado que acabamos de definir no typedef. A sintaxe a seguinte:
Sintaxe

nome_do_tipo

nome_do_registro;

Onde: nome_do_tipo: o nome do tipo de dado que definimos no nosso programa, formado pelo agrupamento de vrias variveis. nome_do_registro: o nome da varivel registro que est sendo declarada. O nome de um registro segue as regras dos identificadores. O exemplo 2.1 apresenta a declarao do registro do boletim do aluno:

37

Programao I

Exemplo 2.1: Definio de tipo e declarao de registro

1 2 3 4 5

typedef struct { int matricula; situao[10]; char nome[20], disciplina[20], float media; } Tipo_Aluno;

Tipo_Aluno aluno;

Primeiramente, entre as linhas 1 e 4, foi definido o conjunto de variveis que fazem parte do registro. nesta parte que est sendo definido um novo tipo de dado. Linha 1: com o typedef estamos informando que ser definido um novo tipo de dado. O struct indica que este tipo um agrupamento de variveis de tipos diferentes, ou seja, um registro. Colocamos o abre chaves e comeamos a declarar as variveis que iro compor o registro. Comeamos com a declarao da varivel inteira matricula. Se houvesse mais variveis do tipo int, poderiam ser declaradas nesta mesma linha. Linha 2: declarao das variveis do tipo char: nome, disciplina e situacao. Linha 3: declarao da varivel media que do tipo float. Linha 4: Aps a declarao de todas as variveis que compe o registro, podemos fechar a chaves e, em seguida, dar um nome a esse tipo de agrupamento, que acabamos de definir. Neste caso, o tipo foi chamado de Tipo_Aluno. Ao definirmos um tipo de dado no nosso programa, significa que: podemos declarar variveis dos tipos de dados primitivos (int, float, char, etc), alm de variveis do tipo de dado que ns definimos, neste caso, Tipo_Aluno. Linha 5: declarao de uma varivel chamada aluno, e o tipo de dado que ela armazena Tipo_Aluno, ou seja, armazena: matricula, nome, disciplina, situacao e media. A figura 2.2 mostra a representao grfica da varivel aluno, que do tipo Tipo_Aluno.

38

Programao I

matricula nome disciplina situacao media

aluno
Figura 2.2: Representao grfica do registro aluno

Notem que, a varivel aluno (que um registro) formada pelos campos definidos no Tipo_Aluno. Como uma varivel registro formada por vrios campos, precisamos utilizar uma forma diferenciada para informar qual campo do registro ns estamos querendo acessar. Lembram dos vetores que precisvamos dizer qual elemento do vetor seria acessado? Com os registros vai acontecer algo parecido. Mas isto, ns vamos aprender na prxima seo.

2.3 Acessando os campos do registro


De acordo com a figura 2.2, a varivel aluno um registro formado por vrios campos. Para acessar um campo de um registro, devemos usar a seguinte sintaxe:
Sintaxe

nome_do_registro.campo

Onde: nome_do_registro: o nome da varivel registro que queremos acessar. Aps o nome_do_registro devemos colocar um ponto, que ir separar o nome do registro, do campo que vem logo em seguida.

campo: o campo do registro que ser acessado. 39

Programao I

Pensem da seguinte forma: suponham que queremos acessar o registro aluno, do exemplo 2.1. Ao acessarmos esta varivel, ela possui vrios campos. Precisamos dizer qual deles ser acessado no momento. A seguir, so apresentados exemplos de acesso aos campos do registro aluno. Ao acessar um campo do registro, podemos atribuir valores, como mostra o exemplo 2.2.
Exemplo 2.2: Acesso aos campos de um registro

1 2 3 4

aluno.matricula = 12345; scanf(%f, &aluno.media); gets(aluno.nome); printf(Situacao do aluno: %s, aluno.situacao);

Saiba Mais
O ponto que aparece neste comando, deve ser lido como campo. Assim, a leitura do comando da linha 1 seria: aluno no campo matricula recebe 12345.
4

Na linha 1, estamos acessando o campo matricula do registro aluno. Assim, colocamos o nome do registro, o ponto e o campo que queremos acessar. Com acesso ao campo, fizemos uma atribuio4. Na linha 2, estamos acessando o campo media do registro aluno. Neste caso, ao invs de atribuir um valor ao campo de registro, estamos fazendo uma leitura via teclado e armazenando o valor digitado no campo media. Como o campo media do tipo float, colocamos o %f no scanf, indicando que ser lido um nmero real. Na linha 3, temos o comando de leitura gets, responsvel por ler variveis do tipo char. Neste gets, estamos fazendo uma leitura via teclado e armazenando o valor digitado no campo nome do registro aluno. Na linha 4, temos um printf que apresenta a situao do aluno. Para isso, acessamos o campo situacao do registro aluno. Notem que, se tivermos vrios alunos em uma turma, precisaremos de vrias variveis registro do tipo Tipo_Aluno, uma para cada aluno. Para fazer isso de forma mais simplificada, devemos juntar os conceitos de vetores e registros e criar um vetor de registro. Vamos aprender como faz isto?

2.4 Vetor de registro


Os vetores so formados por um conjunto de dados do mesmo tipo. No captulo anterior, utilizamos vetores que armazenavam dados 40

Programao I

de tipos primitivos, ou seja, tipos disponveis na linguagem int, float, char, etc. Veremos que podemos utilizar como elemento do vetor no apenas um tipo primitivo, mas tambm os tipos construdos (tipos definido pelo programador), neste caso, os registros. Imaginem que queremos armazenar os boletins dos 50 alunos de uma turma. Para isso, ser necessrio um registro diferente para cada aluno. Para agrupar todos estes registros, iremos definir um vetor de registro. Como possumos 50 alunos, podemos criar um vetor no qual cada posio armazena um Tipo_Aluno. Para declarar um vetor de registro, precisamos antes definir os elementos do registro, utilizando o typedef struct, e assim, definir um novo tipo de dado que ser utilizado no programa. Aps definirmos o novo tipo de dado, o vetor poder ser declarado. Para declararmos um vetor, precisamos informar o tipo de dado que o vetor armazena, damos um nome ao vetor e informamos, entre colchetes, o tamanho do vetor. O exemplo 2.3 apresenta a declarao do vetor de registro alunos:
Exemplo 2.3: definio do registro e declarao do vetor de registro

1 2 3 4 5

typedef struct { int matricula; situao[10]; char nome[20], disciplina[20], float media; }Tipo_Aluno;

Tipo_Aluno alunos[50];

Neste exemplo, cada uma das 50 posies do vetor alunos ir armazenar todos os dados que compe o Tipo_Aluno, ou seja: matricula, nome, disciplina, situacao e media. A figura 2.3, a seguir, representa o vetor de registro declarado no exemplo.
matricula nome disciplina media situacao 0 matricula nome disciplina media situacao 1 ... matricula nome disciplina media situacao 48 matricula nome disciplina media situacao 49

alunos

Figura 2.3: Representao grfica do vetor de registro aluno

41

Programao I

Se apenas com os vetores, j havamos adquirido uma facilidade na declarao e manipulao de um grande conjunto de variveis, com os vetores de registros, esta facilidade ser aumentada. Vamos aprender, na prxima seo, como acessamos um campo de um vetor de registro.

2.5 Acessando os campos do vetor de registro


Quando precisamos acessar um elemento do vetor, informamos, entre colchetes, o ndice do elemento do vetor que ser acessado. Quando queremos acessar um campo do registro, informamos o nome da varivel registro, colocamos um ponto e o nome do campo que queremos acessar. J no caso de um vetor de registro, temos que usar a seguinte sintaxe:
Sintaxe

nome_do_vetor[indice].campo

Onde: nome_do_vetor: nome do vetor que queremos acessar. [ndice]: ndice do vetor que ser acessado. .campo: campo do registro que ser acessado. O exemplo 2.4 apresenta acessos a campos do vetor de registro alunos.
Exemplo 2.4: Acesso aos elementos de um vetor de registro

1 2 3 4

alunos[2].media = 7.5; alunos[3].matricula = 12345; gets(alunos[0].nome); scanf(%d,&alunos[2].matricula);

Na linha 1, acessamos o elemento de ndice 2 do vetor alunos e atribumos 7.5 ao campo media. Na linha 2, acessamos o elemento de ndice 3 do vetor alunos e atribumos 12345 ao campo matricula. Nas linhas 3 e 4, temos acessos atravs de comandos de entrada 42

Programao I

de dados. Na linha 3, temos um gets, que obtm o nome do aluno, via teclado, e armazena no ndice 0 do vetor alunos, no campo nome. Na linha 4, temos o scanf que l a matrcula do aluno, armazenando no ndice 2 do vetor alunos, no campo matricula.

2.6 Usando vetor de registro


Vamos fazer um programa completo usando vetor de registro? Este programa ser um pouco maior do que os outros programas que j fizemos, e apresentar uma gama de coisas novas. Alm do uso de vetor de registro, aprenderemos a mostrar os dados do vetor de registro em forma de tabela. Vamos comear? Primeiramente, vamos ler e entender o enunciado do Programa Completo 2.1: faa um programa que cadastre e apresente os dados dos alunos de uma escola. Os dados dos alunos devem ser armazenados em um vetor de registro, com a capacidade de armazenar at 20 alunos. A quantidade de alunos que ser cadastrada desconhecida. No momento do cadastro sero informados os seguintes dados para cada aluno: matrcula, nome, srie(1-4) e se tem irmo na escola (1-sim/0-nao). O programa ir calcular o valor da mensalidade do aluno, que depende da srie do aluno e se o mesmo tem irmo na escola. Valor da Mensalidade: 1 Serie: R$110, 2 Serie: R$130, 3 Serie: R$160, 4 Serie: R$170. O aluno que tiver irmo na escola, receber 20% de desconto no valor da mensalidade. Quando o usurio decidir que no deseja mais cadastrar, o programa apresentar os dados de todos os alunos, em forma de tabela. Para facilitar o entendimento deste enunciado, vejam os exemplos das telas que so apresentadas durante a execuo do programa:
Colgio Legal Cadastro de Aluno Matricula..: Nome.......: Serie(1-4): Irmao na escola (1-sim/0-nao): Cadastrar outro aluno (1-sim/0-nao)?

43

Programao I

Colgio Legal Relatrio Geral Matricula xx xx xx xx xx Nome xxxxx xxxxx xxxxx xxxxx xxxxx Serie x x x x x Irmao x x x x x Mensalidade xx.xx xx.xx xx.xx xx.xx xx.xx

Tecle enter para sair...


Figura 2.4:Exemplos de telas do programa completo 2.1

A primeira tela representa a operao de cadastramento dos dados dos alunos. Nesta tela, que sero fornecidos os dados para o cadastramento dos alunos. Como a mensalidade um dado calculado pelo programa, o usurio no fornecer este dado no momento do cadastro. A segunda tela representa a apresentao dos dados de todos os alunos, em forma de tabela (listagem ou relatrio). Cada linha da tabela apresentar os dados de um aluno. Como precisamos armazenar os vrios dados de cada um dos alunos da escola, se faz necessrio o uso de um vetor de registro. Segue o cdigo do programa completo 2.1, que ser comentado posteriormente.

44

Programao I

Programa Completo 2.1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28

#include <stdio.h> main() { typedef struct{ int mat, serie, irmao; } char nome[20]; float mens; Tipo_Aluno;

Tipo_Aluno alunos[20]; int qa, i, resp; qa =0; do { ); system(cls); printf(Colegio Legal\n); printf(\n\nCadastro de Alunos\n\n); printf(\nMatricula.: ); scanf(%d,&alunos[qa].mat); printf(\nNome......: ); fflush(stdin); gets(alunos[qa].nome); printf(\nSerie(1-4): ); scanf(%d,&alunos[qa].serie); printf(\nIrmao na escola(1-sim/0-nao):

scanf(%d,&alunos[qa].irmao); switch(alunos[qa].serie)

{ case 1: alunos[qa].mens = 110; break; } case 2: alunos[qa].mens = 130; break; case 3: alunos[qa].mens = 160; break; case 4: alunos[qa].mens = 170; break;

45

Programao I

29 30 31 32 33 34 35 36 37 38 39 40 41 42

if (alunos[qa].irmao == 1) alunos[qa].mens = alunos[qa].mens*0.8; qa++; cadastrar outro aluno(1-

printf(\n\nDeseja sim/0-nao)? );

scanf(%d,&resp);

}while ((resp == 1) && (qa <20)); system(cls); printf(Colegio Legal\n); printf(\n\nRelatorio Geral\n); printf(\n________________________________); printf(\nMatricula Mensalidade); Nome Serie Irmao

printf(\n________________________________); for(i = 0; i < qa; i++) printf(\n%9d %-20s %5d %5d %11.2f,

alunos[i].mat, alunos[i].nome, alunos[i].serie, alunos[i].irmao, alunos[i].mens); printf(\n_______________________________); printf(\nTecle enter para sair...); getche(); }

43 44 45 46

Comentrios sobre o Programa Completo 2.1 Linha 1: incluso da biblioteca stdio.h devido o uso do comando fflush. Linha 2: incio do programa principal. Linhas 3 a 6: definio de um novo tipo de dado, que ser chamado de Tipo_Aluno. O Tipo_Aluno formado pelos dados dos alunos: mat (matrcula), nome, serie, irmao (indica se tem irmo na escola) e mens (mensalidade). Linha 7: declarao do vetor de registro alunos, com capacidade de armazenar 20 elementos do Tipo_Aluno. 46

Programao I

Linha 8: declarao das variveis qa (que ir controlar a quantidade de alunos cadastrados no vetor), i (utilizada como varivel de controle do for) e resp (utilizada para saber se o usurio deseja continuar cadastrando novos alunos). Linha 9: inicializao da varivel qa com 0; Linhas 10 a 34: repetio do tipo do/while que ir controlar o cadastro dos dados dos alunos no vetor de registro. Este do/while ir parar a sua execuo se o vetor ficar cheio (20 elementos) ou se o usurio no quiser mais cadastrar. Linha 11: Cada vez que o do/while executado, queremos que a tela seja limpa. Para isso, usamos o system(cls). Esta linha tem, tambm, o abre chaves que indica o incio da sequncia de comandos do do/while. Linhas 12 e 13: printf para indicar o nome do colgio (Colgio Legal) e para indicar o que est sendo feito nesta tela (Cadastro de Alunos). Linhas 14 e 15: printf informando que o usurio deve digitar a matrcula do aluno e scanf que obtm a matrcula do aluno, armazenado-a no vetor de registro alunos, na posio qa e no campo mat. Notem que a varivel qa iniciou com 0. Na primeira vez que o do/while for executado, os dados dos alunos sero armazenados na posio 0 do vetor. A cada vez que a repetio executada, a varivel qa incrementada de uma unidade. Assim, os dados de cada aluno sero armazenados em uma posio, diferente, no vetor de registro. Linhas 16 a 18: printf informando que o usurio deve digitar o nome do aluno. fflush para limpar o buffer e, em seguida, o gets responsvel por ler o nome do aluno, armazenando no vetor de registro alunos, na posio qa e no campo nome. Linhas 19 e 20: printf informando que o usurio deve digitar a srie do aluno (que pode ser de 1 a 4). scanf responsvel por ler a srie do aluno, armazenando no vetor de registro alunos, na posio qa e no campo serie. Linhas 21 e 22: printf informando que o usurio deve digitar se o aluno tem irmo na escola (digitar 1 se tiver irmo e 0 se no tiver irmo na escola). scanf responsvel por ler se o aluno tem irmo na escola, armazenando no vetor de registro alunos, na 47

Programao I

posio qa e no campo irmao. Linhas 23 a 28: depois de obter todos os dados de um aluno, o programa vai calcular o valor da mensalidade do aluno, verificando a srie e se tem irmo na escola. Como cada uma das sries da escola tem um valor diferente de mensalidade, este switch serve para verificar em que srie o aluno est matriculado, para atribuir ao campo mens do registro do aluno, o valor da mensalidade correspondente a sua srie. Linhas 29 e 30: if para verificar se o aluno tem irmo na escola. De acordo com o enunciado, os alunos que tem irmo na escola, recebem uma desconto de 20% na sua mensalidade. Como o if s tem um comando, no foi necessrio o uso de chaves. Linha 31: neste momento, todo o registro do aluno j foi preenchido. Com isso, fazemos o incremento da varivel qa, informando que mais um aluno acabou de ser cadastrado. Linhas 32 e 33: printf que pergunta se o usurio deseja continuar cadastrando novos alunos. scanf para ler a resposta do usurio (1 se ele deseja continuar cadastrando e 0 se deseja parar). Linha 34: fechamento do do/while com a condio que faz a repetio parar. Como mencionado anteriormente, este do/ while fica em execuo enquanto tem posies disponveis no vetor ou enquanto o usurio desejar. Nesta linha, termina a fase de cadastramento dos dados dos alunos no vetor de registro. Linhas 35 a 47: Esta sequncia de comando serve para apresentar os dados dos alunos que foram armazenados no vetor de registro. Por uma questo de organizao, estes dados sero apresentados na forma de tabela. Assim, cada linha da tabela corresponder aos dados de um aluno, ou seja, uma posio do vetor de registro. Para que a tabela fique alinhada, precisamos saber que: a tela tem 80 colunas por 25 linhas. Dessa forma, temos que distribuir as informaes de um jeito que no extrapole as 80 colunas da tela. Para entender melhor esta parte do programa, acompanhem os comandos, observando a figura 2.9 (tela de execuo do programa). Linha 35: limpa a tela para darmos incio apresentao dos dados de todos os alunos. 48

Programao I

Linhas 36 e 37: printf para informar o nome do colgio e para informar o que esta tela faz (Relatrio Geral). Linha 38: printf para passar uma linha na tela. Esta linha vai delimitar o cabealho da tabela. Linha 39: printf que imprime os ttulos de cada coluna da tabela. A tabela ser composta pelas seguintes colunas: Matricula, Nome, Serie, Irmao e Mensalidade. Os ttulos que devemos dar as colunas da tabela so sempre indicados nos enunciados das questes, certo? Sigam esta dica, porque vocs esto comeando a aprender a fazer tabelas agora. Este printf cheio de detalhes, mas vamos ver isso agora, observando a figura 2.5. O resultado deste printf a linha que est indicada com a seta horizontal.

Figura 2.5: Apresentao dos dados em forma de tabela

Vamos ver quais so os passos para montar o printf da linha 39 (cabealhos/ttulos das colunas da tabela). Para cada coluna da tabela, verifiquem quantas letras tem no seu cabealho. Por exemplo, a palavra matrcula tem 9 letras. Vejam que, na figura 2.5, tem a indicao de quantas letras tem em cada um dos cabealhos. A quantidade de letras que tiver o cabealho ser a largura da coluna. Agora, precisamos verificar se os dados dos alunos vo extrapolar a largura de cada uma das colunas da tabela. Vamos ver uma por uma: Matricula: a coluna que ser utilizada para apresentar a matrcula tem uma largura de 9 espaos (quantidade de letras da palavra matrcula). Vamos considerar que nossas matrculas tem sempre menos que 9 dgitos. 49

Programao I

Assim, a largura de 9 espaos para esta coluna suficiente. Nome: a palavra nome s tem 4 letras. Vejam que o nome do aluno foi declarado com 20 letras. Assim, se deixarmos a coluna Nome, com largura 4, no ser suficiente para apresentar os nomes dos alunos. Quando a quantidade de letras do cabealho menor que o contedo que vem na coluna da tabela, devemos completar a coluna com espaos em branco at fazer com que a coluna tenha a largura que precisamos. Srie: tem 5 letras. A srie do aluno varia entre 1 e 4, dessa forma, a largura da coluna Serie (5 espaos) ser suficiente para apresentar o dado. Irmo: tambm tem 5 letras. A varivel que armazena se o aluno tem ou no irmo na escola varia entre 0 e 1, dessa forma, a largura da coluna Irmao (5 espaos), ser suficiente para apresentar o dado. Mensalidade: tem 11 letras. Esta largura suficiente para apresentar o valor da mensalidade do aluno. Agora que j sabemos que apenas a coluna Nome no tem largura suficiente para apresentar os nomes dos alunos, vamos ver quantos espaos em branco ns temos que colocar depois da palavra Nome, para que esta coluna tenha a largura que precisamos. Se o nome do aluno tem at 20 letras e a palavra Nome tem apenas 4 letras, faremos a seguinte conta: 20 4 = 16. Assim, depois da palavra Nome, temos que colocar 16 espaos em branco, para que a nossa coluna passe a ter a largura que precisamos (20). Por fim, temos que definir um espaamento para separar uma coluna da outra. Nos nossos exemplos, vamos usar sempre trs espaos separando uma coluna da outra. A padronizao do espaamento entre as colunas visa facilitar a programao, j que estamos vendo este assunto agora e o mesmo cheio de detalhes. Agora vamos montar o printf, vejam a figura 2.6. Ns vamos colocando os ttulos das colunas da tabela, e entre cada palavra, vamos colocando trs espaos em branco, 50

Programao I

que foi o espaamento definido para separar as colunas. S no caso da coluna nome, que depois que colocamos Nome, devemos dar os 16 espaos em branco para que ela passe a ser uma coluna de largura 20. Mas ainda teramos que dar mais 3 espaos em branco, que para separar a coluna nome, da coluna serie.

Figura 2.6: Detalhamento do printf da linha 39

O printf est pronto! A primeira vista, parece complicado, mas depois vocs estaro fazendo a tabela bem rpido. Linha 40: printf para passar uma linha na tela. Esta linha vai delimitar o cabealho da tabela. Linha 41: for para visitar cada uma das posies do vetor e apresentar os dados dos alunos. A varivel de controle do for, o i, vai variar de 0 at a ultima posio ocupada do vetor. A varivel que tem esta informao o qa. Linha 42: este printf que vai fazer a montagem das linhas da tabela, apresentado os dados dos alunos que esto armazenados no vetor de registro. Este printf tambm tem macetes, pois est relacionado com o printf da linha 39. Vamos l! Lembram que fizemos a contagem para saber a largura de cada coluna da tabela? Vamos precisar desta informao agora. Na primeira parte do printf, temos a string de controle (a figura 2.7 faz o detalhamento dessa parte do printf). Sabemos que as colunas da tabela so: matricula( nmero inteiro e esta coluna deve ter largura 9), nome (vetor de caracteres com at 20 letras), serie (nmero inteiro e esta coluna tem largura 5), irmo (nmero inteiro e esta coluna tem largura 5) e mensalidade (nmero real e esta coluna tem largura 11). Alm disso, sabemos que entre cada coluna, ns colocamos trs espaos em branco. Com estas informaes, vamos montar a string de controle do printf da 51

Programao I

linha 42.

Figura 2.7: Detalhamento do printf da linha 42

Entre o % e a letra que indica o que vai ser impresso (%d, %s ou %f), devemos colocar a largura da coluna. A primeira coluna da tabela a da matricula, que um nmero inteiro e que tem largura 9. Por isso, temos o %9d. Aps cada uma das formataes, colocamos trs espaos em branco, j que foi o espaamento definido entre as colunas da tabela. No caso da varivel caractere nome do aluno (que a segunda coluna da tabela) colocamos %-20s (o para que o nome do aluno seja alinhado pela esquerda). Nas demais formataes no precisamos colocar o -, s utilizamos em campos caractere. Aps a string de controle, colocamos as variveis que sero apresentadas na tela, na ordem em que as colunas foram definidas. Linha 43: printf para passar uma linha na tela. Esta linha vai fechar a tabela. Linha 44: printf que informa que o usurio deve teclar enter para sair. Linha 45: getche() que evita que a tela de execuo feche antes de vermos os resultados. Linha 46: fecha chaves do programa principal. A figura 2.8 apresenta a tela de execuo do programa 2.1, na fase do cadastramento dos alunos.

52

Programao I

Figura 2.8: Tela de execuo do programa completo 2.1 - Cadastro

A figura 2.9 apresenta a tela de execuo do programa 2.1, na fase do apresentao dos dados de todos os alunos cadastrados, em forma de tabela.

Figura 2.9: Tela de execuo do programa completo 2.1 Relatrio Geral

Viram como esta questo cheia de detalhes? Mas no se assustem, a explicao precisava ser minuciosa, para que cada linha do programa fosse entendida. Agora precisamos treinar esse tipo de questo. No percam tempo!

Atividades e Orientaes de Estudos Vamos resolver mais uma lista de exerccios? Esta lista composta por questes em que se faz necessrio o uso de vetor de registro. DICA: sempre coloque as tabelas com os mesmos cabealhos propostos nos enunciados (exemplos de telas). Mos a obra! 1. Uma empresa de turismo deseja um programa que calcule o valor das viagens dos clientes. Sero informados os seguintes 53

Programao I

dados: cdigo do cliente, nome, roteiro desejado(1-Brasil, 2-EUA, 3-frica), tipo de quarto (1-Standard, 2-Luxo), Se deseja alugar carro(1-sim/0-nao) e a quantidade de dias. A quantidade de clientes desconhecida. O programa ir calcular o total da viagem usando os valores da tabela abaixo, que variam de acordo com o roteiro escolhido. A diria do quarto de luxo R$30 mais cara que o valor da diria em um quarto standard. Exemplo: Se a pessoa escolher roteiro 2, em quarto de luxo, a diria ir custar: 320 + 30 = R$ 350.
Roteiro 1 2 3 Diria Hotel Quarto Standard R$ 170 R$ 350 R$ 370 Diria - Aluguel de carro R$ 50 R$ 60 R$ 75

Total da Viagem: dias*diriahotel + dias*diariacarro(se o cliente for alugar carro) Armazenar os dados em um vetor de registro. Imprimir os dados em forma de tabela. Exemplo das telas:
Viagem Legal Turismo Cadastro de Cliente Codigo: Nome: Roteiro (1-Brasil, 2-EUA, 3-frica): Tipo de Quarto (1- Standard, 2-Luxo): Alugar Carro (1-sim/0-nao)? Quantidade de Dias: Inserir outro (1-sim,0-nao)? Viagem Legal Turismo Relatrio Geral Cdigo xx xx xx Nome xxxxx xxxxx xxxxx Roteiro x x x Quarto x x x Carro x x x Dias xx xx xx Total xx.xx xx.xx xx.xx

Tecle enter para sair...

54

Programao I

2. Faa um programa para montar a folha de pagamento dos empregados de uma empresa. Para cada empregado sero lidos os seguintes dados: matricula, nome, cargo(1-Analista de Sistemas/2- programador), sexo(1-mas/2-fem), anos de experincia e quantidade de filhos. O programa ir calcular para cada empregado o seu salrio. Sabe-se que:
Cargo 1 2 Salrio Base R$ 2500 R$ 1700

O salrio ser calculado da seguinte forma: cada cargo tem o salrio base. Alm do salrio base, o empregado recebe os seguintes adicionais: R$ 50, para cada ano de experincia e R$ 40 por cada filho. Portanto, um analista de sistemas com trs anos de experincia e dois filhos ter o salrio = 2500 + 50*3 + 40*2 = R$ 2730. Armazenar as informaes em um vetor de registros. Imprimir o relatrio geral em forma de tabela contendo os dados de cada empregado. A quantidade de empregados da empresa desconhecida (declarar o vetor com capacidade de armazenar 20 funcionrios). Exemplos das telas:
Empresa Legal

Cadastro de Funcionario Matricula: Nome: Cargo(1-Analista de Sistemas, 2- programador): Sexo(1-mas/2-fem): Anos de experincia: Quantidade de filhos: Cadastrar outro (1-sim/2-nao)?

55

Programao I

Empresa Legal Listagem Geral Matricula xx xx xx xx Nome xxxxx xxxxx xxxxx xxxxx Cargo x x x x Sexo x x x x Anos xx xx xx xx Q. Filho x x x x Salrio xxx.xx xxx.xx xxx.xx xxx.xx

Tecle enter para sair...

3. Faa um programa para uma empresa de celular contendo as seguintes operaes: cadastro de clientes e listagem geral. Para cada cliente devemos armazenar: cdigo, nome, sexo (1-feminimo/2-masculino), quantidade de ligaes, plano que o cliente est associado (1-Dia/2-Noite/3-Fixo/4-Empresarial) e Valor da conta. O programa ir calcular o valor da conta de cada cliente. Sabe-se que, cada plano tem uma tarifa diferenciada, segundo a tabela abaixo:
Plano Dia Noite Fixo Empresarial Valor de 1 ligao 1.30 1.60 1.25 1.10

Armazenar os dados em um vetor de registro. Aps o cadastro dos clientes, apresentar a listagem com os dados de todos os clientes, em forma de tabela. A quantidade de clientes desconhecida. Declare o vetor com capacidade de receber at 50 clientes. Exemplos das telas:

56

Programao I

Ligue Mais Cadastro de Cliente Cdigo: Nome: Sexo(1-fem/2-mas): Quantidade de Ligaes: Plano(1-Dia/2-Noite/3-Fixo/4-Empresarial): Cadastrar outro (1-sim/0-nao)? Ligue Mais Listagem Geral Codigo xx xx xx xx Nome xxxxx xxxxx xxxxx xxxxx Sexo x x x x Quant. Lig. xx xx xx xx Plano x x x x Total xxx.xx xxx.xx xxx.xx xxx.xx

Tecle enter para sair...

4. Um professor quer um programa para o clculo da mdia dos alunos de uma turma. Sero informadas a matrcula, nome (20 caracteres), e as trs notas dos alunos. O professor descarta a menor nota do aluno e a media calculada com as duas maiores notas. Calcular a mdia e apresentar os resultados em forma de tabela, aps o cadastramento. Armazenar os dados em um vetor de registro. A quantidade de alunos desconhecida, declare o vetor com capacidade de receber at 20 alunos. Exemplos das Telas:
Universidade Legal Cadastro de aluno Matricula: Nome: Nota 1: Nota 2: Nota 3: Cadastraroutro (1-sim/0-nao)?

57

Programao I

Universidade Legal Relatrio Geral Matricula x x x x xxxxxxxxx xxxxxxxxx xxxxxxxxx xxxxxxxxx Nota1 x.x x.x x.x x.x Nota2 x.x x.x x.x x.x Nota3 x.x x.x x.x x.x Media x.x x.x x.x x.x

Tecle enter para sair...

5. O MEC quer um programa para fazer um relatrio sobre os polos de educao a distncia da UFRPE. Para cada polo so informados os seguintes dados: cdigo do polo, cidade, total de alunos, total de tutores, se possui laboratrio de informtica (1-sim/0-no) e se possui laboratrio de cincias (1-sim/0-no). O MEC quer saber quanto deve ser liberado de verba para cada polo. O calculo ser feito da seguinte forma: Por cada aluno so liberados: R$ 100 Por cada tutor so liberados: R$ 500 Se o polo tem no tem laboratrio de informtica so liberados: R$ 20.000 Se o polo no tem laboratrio de cincias so liberados: R$ 17.000 Ex: um polo com 150 alunos, com 15 tutores, que tem laboratrio de informtica, mas no tem laboratrio de cincias: Verba = 100 x 150 + 500 x 15 + 17000 = 15000 + 7500 + 17000 = 39500. Armazenar os dados dos polos em um vetor de registro. A quantidade de polos desconhecida. Declarar o vetor com a capacidade de armazenar at 20 polos. Aps o cadastros dos polos, apresentar todos os dados dos polos em forma de tabela. Exemplos das telas:

58

Programao I

Ministrio da Educao Cadastro de Polo Codigo: Cidade: Quantidade de alunos: Quantidade de tutores: Tem lab. de informatica (1-sim/0-nao)? Tem lab. de ciencias (1-sim/0-nao)? Cadastrar outro polo (1-sim,0-nao)? Ministrio da Educao Listagem Geral Codigo xx xx xx xx Cidade xxxxx xxxxx xxxxx xxxxx Alunos xxx xxx xxx xxx Tutores xxx xxx xxx xxx LI x x x x LC x x x x Verba Liberada xxxxx.xx xxxxx.xx xxxxx.xx xxxxx.xx

Tecle enter para sair...

Conhea Mais Vocs podero aprender mais sobre registros e vetores de registros lendo os livros: MONTGOMERY, Eduard. Programando em C: Simples e Prtico. So Paulo: Alta Books, 2006. SCHILDT, Herbert. C Completo e Total. So Paulo: Makron, 1996.

Vamos Revisar? Nesta seo iremos revisar os principais tpicos vistos neste 59

Programao I

captulo. Vale a pena dar uma lida para verificar como est o nosso aprendizado. Observem o resumo a seguir: Os registros so um agrupamento de variveis de tipos diferentes, mas que tem uma relao lgica. Por ser formado por elementos de diferentes tipos, os registros so chamados de estruturas de dados heterogneas. Para declarar uma varivel registro, precisamos definir um novo tipo de dado para o programa, utilizando o typedef. Cada elemento do registro chamado de campo. Unindo os conceitos de vetores e de registros, temos os vetores de registro que facilitam a declarao e o manuseio de grandes volumes de dados.

60

Programao I

Captulo 3 Armazenamento de Dados em Arquivos


Vamos conversar sobre o assunto? Neste captulo, vamos aprender a armazenar nossos dados de forma definitiva. At ento, ao terminar a execuo de um programa, todos os dados que foram armazenados nas variveis eram perdidos. Em muitas aplicaes isto no pode acontecer. Por exemplo, um professor precisa ter certeza de que todo o trabalho para digitar as notas dos alunos da turma no ser perdido quando ele fechar o programa. Com os arquivos, poderemos armazenar os dados e recuper-los quando necessrio. Este captulo abordar os comandos que nos possibilitaro manipular dados armazenados em um arquivo. Vamos comear?

3.1 O que so arquivos?


Os arquivos so estruturas de dados manipuladas fora do ambiente do programa. Considera-se como ambiente do programa a memria principal, onde nem sempre conveniente manter certas estruturas de dados. De modo geral, os arquivos so armazenados na memria secundria, como, por exemplo: disco rgido (HD - hard disk), CD e pendrive. 3.1.1. Como os arquivos so organizados? A linguagem C utiliza o conceito de fluxo de dados (stream) para manipular os vrios tipos de dispositivos de armazenamento e seus diferentes formatos. Os dados podem ser manipulados em dois diferentes tipos de fluxos: fluxos de texto e fluxos binrios. Um fluxo de texto (text stream) composto por uma sequncia de caracteres, que pode ou no ser dividida em linhas, terminadas por um caractere de final de linha. Um fluxo binrio (binary stream) composto por uma sequncia de bytes, que so lidos, sem traduo, diretamente do dispositivo externo. A Figura 3.1 ilustra estes dois tipos de fluxos.

61

Programao I

Figura 3.1: Fluxo de dados

No fluxo de texto, os dados so armazenados como caracteres sem converso para a representao binria. Cada um dos caracteres ocupa um byte. O nmero 12 ocupa dois bytes e o nmero 113 ocupa 3 bytes. Um caractere em branco foi inserido entre cada um dos nmeros para separ-los, de modo que a funo de entrada e sada possa descobrir que so dois nmeros inteiros (12 e 113) e no o nmero 12113. No fluxo binrio, cada nmero inteiro ocupa 32 bits (4 bytes) e armazenado na forma binria. Observem que, em arquivos binrios, no h necessidade de separar os nmeros j que eles sempre ocupam 32 bits. Os arquivos binrios so utilizados quando queremos armazenar registros completos. Com estes arquivos, poderemos acessar qualquer registro de forma mais rpida. No caso dos arquivos texto, quando queremos encontrar alguma informao, temos que fazer uma varredura sequencial no arquivo, tornando a busca pouco eficiente. Neste captulo, ser dada nfase ao armazenamento de dados em arquivos binrios. Nas prximas sees, iremos conhecer os comandos para manipular este tipo de arquivo. 3.1.2 Ponteiros Antes de comearmos a conhecer os comandos de manipulao de arquivos binrios, vamos ver um conceito que ser utilizado neste captulo, que : ponteiro. Um ponteiro um tipo de varivel que armazena um endereo de memria. Ns j vimos variveis que armazenam nmeros inteiros, nmeros reais e caracteres. Ao trabalhar com arquivos, precisamos saber em qual endereo de memria o arquivo est armazenado. O endereo de memria onde o arquivo 62

Programao I

est armazenado ser colocado em uma varivel que armazena endereo de memria (ponteiro). Para declarar uma varivel que capaz de armazenar um endereo de memria, usamos a seguinte sintaxe:
Sintaxe

tipo

*nome_do_ponteiro;

Onde: tipo: tipo de varivel que o ponteiro armazena endereo. Podemos dizer que nosso ponteiro armazena o endereo de uma varivel inteira, real, caractere, etc. Para este captulo, estaremos utilizando um ponteiro que vai armazenar o endereo de um arquivo. *: o asterisco na frente do nome de uma varivel simboliza que a varivel que est sendo declarada um ponteiro. nome_do_ponteiro: daremos um nome nossa varivel que armazena endereos. O exemplo 3.1 apresenta exemplos de declaraes de ponteiros que armazenam endereos de memria de arquivos.
Exemplo 3.1: Declarao de ponteiros para arquivos

1 2

FILE *p aluno; FILE *p produto;

Na linha 1, temos a declarao do ponteiro paluno, que ir armazenar o endereo de um arquivo (FILE). Devemos colocar o FILE em maisculo. Na linha 2, temos a declarao de outro ponteiro, pproduto, que armazena o endereo de um FILE. Quando queremos inicializar uma varivel real ou inteira, atribumos zero s mesmas. Quando precisarmos inicializar um ponteiro, devemos atribuir: NULL. Quando um ponteiro armazena NULL, quer dizer que ele no est armazenando um endereo no momento. Tenham calma, daqui a pouco o conceito de ponteiros ficar mais claro. Vamos comear a conhecer os comandos de manipulao de arquivos binrios e entenderemos melhor onde o conceito de ponteiro ser aplicado. 63

Programao I

3.2 Comandos para manipular arquivos binrios


Como j mencionado, os arquivos binrios so utilizados quando queremos armazenar registros. como se tivssemos um vetor de registro, s que os dados no so perdidos ao terminar a execuo do programa. A figura 3.2 mostra a representao grfica de um arquivo binrio.

Figura 3.2: Representao grfica de um arquivo binrio

O arquivo binrio formado por um conjunto de registros, armazenados um aps o outro. As operaes realizadas em um arquivo binrio dependero do local onde se encontrar o leitor. Pense no leitor como se fosse a agulha de uma vitrola (Figura 3.3). Para tocar uma msica, a agulha passa sobre o disco, fazendo a leitura da msica. Dependendo de onde a agulha seja posicionada, tocada uma msica do disco.

Figura 3.3: Vitrola com agulha tocando uma msica

O leitor do arquivo passar sobre os registros, fazendo a leitura dos mesmos. Ns podemos colocar o leitor sobre qualquer registro e executar uma operao sobre o mesmo (leitura e/ou gravao). O arquivo tem uma marcao indicando onde ele termina (end of file). Nas prximas sees, iremos detalhar os comandos para manipular arquivos binrios. As operaes para a manipulao de arquivo esto na biblioteca stdio.h. Com isso, ao trabalhar com arquivos, devemos 64

Programao I

incluir esta biblioteca nos nossos programas. 3.2.1 Declarao de um ponteiro para arquivo Na linguagem C, as funes que manipulam arquivos trabalham com o conceito de ponteiros para arquivo. Com isso, teremos uma varivel que armazenar o endereo de memria onde est armazenado nosso arquivo. Ns vimos na seo 3.2.1 (exemplo 3.1), como fazemos para declarar um ponteiro para um arquivo. Devemos declarar um ponteiro para cada arquivo que formos manipular no nosso programa. 3.2.2 Comando para abrir um arquivo A maior parte das operaes sobre um arquivo (leitura, gravao, etc) s pode ser executada com o arquivo aberto. O comando de abertura do arquivo (fopen) apresenta a seguinte sintaxe:
Sintaxe

ponteiro_arquivo = fopen(nome_do_arquivo, modo_de_abertura);

Onde: ponteiro_arquivo: ao abrir um arquivo, a funo fopen retorna o endereo de memria do arquivo. Por conta disso, devemos atribuir o endereo de memria do arquivo, para um ponteiro. Aps o arquivo ser aberto, usaremos este endereo de memria para acess-lo. nome_do_arquivo: determina qual arquivo dever ser aberto. Neste espao colocado o nome do arquivo, da forma que foi salvo no diretrio. O comando fopen procura o arquivo que desejamos abrir, no mesmo diretrio onde est armazenado o programa executvel. modo_de_abertura: informa que tipo de uso voc vai fazer do arquivo. O modo de abertura indica o que faremos no arquivo: leitura, gravaes e alteraes. Alm disso, o modo de abertura tambm vai indicar se queremos que um novo arquivo seja criado. A tabela abaixo apresenta os principais modos de abertura.

65

Programao I

Modo r+b

Significado Abre um arquivo binrio para leitura e escrita. O arquivo deve existir antes de ser aberto.Dessa forma, este modo de abertura s pode ser usado se o arquivo que estamos querendo abrir j existe no nosso computador. Cria um arquivo binrio para leitura e escrita. Se o arquivo no existir, ele ser criado. Se j existir, o contedo anterior ser destrudo. Este modo de abertura tem a capacidade de criar novos arquivos. Mas, se solicitarmos que seja aberto um arquivo que j existe, o contedo do arquivo ser apagado. Acrescenta dados ou cria um arquivo binrio para leitura e escrita. Caso o arquivo j exista, novos dados podem ser adicionados, apenas, no final do arquivo. Se o arquivo no existir, um novo arquivo ser criado.

w+b

a+b

O exemplo 3.2, apresenta o uso do fopen.


Exemplo 3.2: Abertura de arquivo

1 2 3 4 5

FILE *paluno, *pprofessor; paluno = fopen(alunos.bin, w+b); pprofessor = fopen(professores.bin, r+b); if (pprofessor == NULL) printf(Arquivo de professores no existe);

Na linha 1, temos a declarao de dois ponteiros para armazenar os endereos dos arquivos que iremos abrir logo em seguida. Na linha 2, temos um fopen que ir abrir o arquivo alunos.bin, utilizando o modo de abertura w+b. Caso o arquivo alunos.bin no exista, ele ser criado (com o nome que passamos como parmetro). Normalmente, usamos o modo de abertura w+b quando executamos o nosso programa pela primeira vez. Neste momento, o arquivo ainda no existe. Dessa forma, desejamos que o mesmo seja criado. Mas, se o arquivo alunos.bin j existir, todo o seu contedo ser apagado. E, como resultado, teremos o arquivo aberto, mas sem nenhum registro armazenado. Ao abrir o arquivo, o endereo de memria do arquivo ser armazenado no ponteiro paluno. Na linha 3, temos um fopen que abrir o arquivo professores. bin, utilizando o modo de abertura r+b. Este modo de abertura s utilizado para arquivos que j existem, pois, diferente do modo de abertura w+b, ele no tem a capacidade de criar um arquivo novo. Se tentarmos abrir um arquivo que no existe, o fopen retornar NULL. 66

Programao I

Para saber se um arquivo foi aberto corretamente, podemos fazer um teste como mostra as linhas 4 e 5. Aps executar um fopen, verificamos se o ponteiro est com NULL. Caso afirmativo, porque a abertura no foi executada corretamente. Uma vez aberto, o arquivo fica disponvel para leituras e gravaes atravs da utilizao de funes adequadas. 3.2.3 Comando para fechar um arquivo Aps terminar de usar um arquivo, devemos fech-lo. Para isso, usamos a funo fclose, que tem a seguinte sintaxe.
Sintaxe

fclose(ponteiro_arquivo);

Onde: ponteiro_arquivo: o ponteiro que tem armazenado o endereo de memria do arquivo que queremos fechar. S podemos fechar arquivos que esto abertos. O exemplo 3.3, apresenta o uso do comando fclose. Vamos utilizar os ponteiros declarados no exemplo anterior.
Exemplo 3.3: Fechamento de arquivo

1 2

fclose(palunos); fclose(pprofessores);

Na linha 1, fechamos o arquivo que est armazenado no endereo de memria palunos (que o ponteiro que armazena o endereo do arquivo). Ns s utilizamos o nome do arquivo (o nome que est salvo no diretrio), no momento da abertura. Depois de aberto, s utilizamos seu endereo de memria, certo? 3.2.4 Comando para ler um registro armazenado no arquivo Vamos aprender a ler os dados de um registro armazenado no arquivo? Neste comando, teremos vrios detalhes e devemos ter em mente o seguinte: A leitura feita a partir do ponto onde o leitor se encontra. Ao abrir o arquivo, o leitor posicionado no incio do primeiro 67

Programao I

registro, como mostra a figura 3.2. medida que vamos executando leituras, o leitor vai se deslocando. Dessa forma, precisamos ter noo da posio onde o leitor se encontra. Nos arquivos binrios, SEMPRE fazemos a leitura de um registro completo, independente de quantos campos ele tenha. Um arquivo deve armazenar registro do mesmo tipo. Se os registros so do mesmo tipo, cada um deles ocupar o mesmo espao de memria. Dessa forma, o leitor sempre se deslocar em intervalos regulares. Vamos entender isto melhor, daqui a pouco. Vamos, primeiro, ver a sintaxe do comando de leitura:
Sintaxe

fread (&registro, numero_de_bytes, quantidade, ponteiro_arquivo);

Onde: &registro: o registro que armazenar os dados do registro lido do arquivo. assim, ns pegamos um registro que est no arquivo, e armazenamos no registro passado como parmetro. numero_de_bytes: na verdade, o que o comando de leitura faz informar que o leitor precisa se deslocar, fazendo a leitura de uma certa quantidade de bytes. A quantidade de bytes que o leitor deve se deslocar exatamente quantos bytes de memria o registro ocupa. Por exemplo: se o nosso arquivo armazena registros de alunos, composto pelos campos: matricula (int), nota1 (float), nota2 (float) e media (float). Sabe-se que um int ocupa 4 bytes e um float, tambm, ocupa 4 bytes. Dessa forma, teremos: 4 bytes para a matricula + 4 bytes para a nota1 + 4 bytes para a nota2 + 4 bytes para a media = 16 bytes. Assim, esse registro ocupa 16 bytes (Figura 3.4). esse o nmero de bytes que o leitor dever ler, para recuperar o registro de um aluno, armazenado no arquivo. Existe uma funo chamada sizeof que informa quantos bytes ocupa um tipo de dado. Assim, no precisamos estar lembrados de quantos bytes um int ocupa. Alm disso, no precisamos fazer as contas para saber quantos bytes o nosso registro ocupa. Para utilizar a funo sizeof, precisamos apenas, passar como parmetro 68

Programao I

para a funo, que tipo de dado queremos saber quantos bytes ele ocupa. Por exemplo: sizeof(int) ou sizeof(TAluno). No caso de um registro, a funo vai fazer as contas de quantos bytes cada um dos campos do registro ocupa, e retorna a soma.
4 bytes 4 bytes 4 bytes 4 bytes

matricula

nota1

nota2

media

Figura 3.4: Campos do registro aluno

quantidade: neste terceiro parmetro, usaremos SEMPRE 1. Este parmetro significa quantas vezes a leitura ser executada. Ns sempre queremos que seja feita a leitura de um registro por vez. Por isso, sempre utilizaremos 1. ponteiro_arquivo: precisamos informar em qual arquivo a leitura ser feita. Com isso, passamos o endereo de memria onde o arquivo que ser lido est armazenado. Assim, utilizamos o ponteiro que tem o endereo do arquivo. Agora vamos ver o exemplo 3.4, que apresenta a leitura de um registro do arquivo. Para um melhor entendimento, foram feitas as declaraes das variveis que sero usadas no fread.
Exemplo 3.4: Leitura de um registro do arquivo

1 2 3 4 5 6 7 8

typedef { int matricula; float nota1, nota2, media; } TAluno

TAluno aluno; FILE *paluno;

fread(&aluno, sizeof(TAluno), 1, paluno);

Nas linhas 1 a 3, temos a declarao de um novo tipo de dado, que o agrupamento dos dados do aluno. Este tipo foi chamado de TAluno. Na linha 5, temos a declarao da varivel aluno, que um 69

Programao I

registro do tipo TAluno. Na linha 6, declaramos um ponteiro chamado paluno, que armazena endereo de memria de arquivo.
Ateno
No esquecer de colocar o & na frente da varivel.
5

Na linha 8 que temos o comando de leitura. Vamos interpretar cada parte do comando. No primeiro parmetro, temos a varivel registro que vai armazenar as informaes lidas do arquivo5. Assim, o registro que for lido do arquivo, ser armazenado no registro aluno. No segundo parmetro, precisamos dizer quantos bytes sero lidos. Se iremos ler os dados do registro do aluno, precisamos saber quantos bytes ele ocupa. Para isso, foi usada a funo sizeof. Como parmetro do sizeof foi colocado TAluno, que um tipo criado no programa e que queremos saber quantos bytes esse tipo de dado ocupa. No terceiro parmetro, ns sempre usaremos 1. Finalmente, no quarto parmetro informamos o endereo do arquivo em que ser feita a leitura. Neste caso, o endereo do arquivo est armazenado no ponteiro paluno. Aps a leitura de um registro do arquivo, o leitor estar posicionado no incio do prximo registro. A Figura 3.5 apresenta a posio do leitor antes e depois da execuo do fread.

Figura 3.5: Posio do leitor antes e aps a execuo de um fread

Agora que j sabemos como fazer para ler um registro que est armazenado no arquivo, vamos aprender a gravar um registro no arquivo.

70

Programao I

3.2.5 Comando para gravar um registro no arquivo Para gravar um registro em um arquivo binrio, ns utilizamos o comando fwrite. Este comando muito parecido com o fread. A diferena que o fread l uma sequncia de bytes no arquivo, e armazena em um registro (primeiro parmetro do fread). E o fwrite, pega um registro, e armazena suas informaes no arquivo. Vamos ver a sintaxe do fwrite:
Sintaxe

fwrite(&registro, numero_de_bytes, quantidade, ponteiro_arquivo);

Onde: &registro: o registro que ser armazenado no arquivo. numero_de_bytes: a quantidade de bytes que sero gravadas no arquivo. Neste parmetro, tambm usaremos o sizeof. quantidade: neste terceiro parmetro, tambm, usaremos SEMPRE 1. Este parmetro significa quantas vezes a gravao ser executada. Ns sempre queremos que seja feita a gravao de um registro por vez. Por isso, sempre utilizaremos 1. ponteiro_arquivo: precisamos informar em qual arquivo a gravao ser feita. Assim, utilizamos o ponteiro que tem o endereo do arquivo. Agora vamos ver o exemplo 3.5, que apresenta a gravao de um registro no arquivo. Para um melhor entendimento, foram feitas as declaraes das variveis que sero usadas no fwrite.

71

Programao I

Exemplo 3.5: Leitura de um registro do arquivo

1 2 3 4 5 6 7 8

typedef { int matricula; float nota1, nota2, media;

} TAluno

TAluno aluno; FILE *paluno;

fwrite(&aluno, sizeof(TAluno), 1, paluno);

Na linha 8 que temos o comando de gravao. Vamos interpretar cada parte do comando. No primeiro parmetro, temos a varivel registro que ser gravada no arquivo. No segundo parmetro, precisamos dizer quantos bytes sero gravados. Para isso, foi usada a funo sizeof. No terceiro parmetro, ns sempre usaremos 1. Finalmente, no quarto parmetro informamos o endereo do arquivo em que ser feita a gravao. Neste caso, o endereo do arquivo est armazenado no ponteiro paluno. Devemos lembrar que o comando de gravao no arquivo (fwrite) executado na posio onde o leitor se encontra no momento. Se o leitor estiver posicionado no incio de um registro e executarmos um fwrite, o registro ser gravado sobre o outro. Dessa forma, quando vamos inserir um novo registro no arquivo, devemos posicionar o leitor num ponto do arquivo que no tenha nenhum registro armazenado, ou seja, no final do arquivo. Vamos ver como faz isso? 3.2.6 Comando para posicionar o leitor em um ponto do arquivo As operaes de leitura e gravao so feitas na posio onde o leitor se encontra no momento. Podemos mudar a posio do leitor, colocando-o em um ponto especfico do arquivo. Este comando o fseek. A sintaxe do fseek a seguinte:
Sintaxe

fseek(ponteiro_arquivo,numero_de_bytes, origem);

72

Programao I

Onde: ponteiro_arquivo: precisamos informar em qual arquivo o leitor est sendo posicionado. numero_de_bytes: a quantidade de bytes que o leitor ir se deslocar pelo arquivo, at chegar no local desejado. origem: determina a partir de onde os nmero_de_bytes de deslocamento do leitor sero contados. Os possveis valores so:
Origem SEEK_SET SEEK_CUR SEEK_END Significado O deslocamento do leitor ser contado a partir do incio do arquivo. O deslocamento do leitor ser contado a partir da sua posio corrente. O deslocamento do leitor ser contado a partir do final do arquivo.

O exemplo 3.6 apresenta o uso do comando fseek.


Exemplo 3.6: Comando fseek

1 2

fseek(paluno, 0,SEEK_END); fseek(paluno, 2*sizeof(paluno), SEEK_SET);

No exemplo da linha 1, temos um fseek que ser muito utilizado em nossos programas. Neste fseek solicitado que seja feito o posicionamento do leitor do arquivo de endereo paluno. O deslocamento do leitor ser feito iniciando a contagem a partir do fim do arquivo (SEEK_END)6. O nmero de bytes que o leitor ir se deslocar 0. Este tipo de fseek usado quando queremos gravar um novo registro do nosso arquivo. Jogamos o leitor para o fim do arquivo e no deslocamos nenhum byte. Com isso, temos a garantia que o leitor no est sobre nenhum registro. Dessa forma, podemos gravar um novo registro, sem perder registros que j haviam sido gravados no nosso arquivo. No fseek da linha 2, foi solicitado que o leitor seja posicionado no incio do arquivo (SEEK_SET), antes do deslocamento ser efetivado. Notem que, no segundo parmetro, foi passada uma expresso 2 * o tamanho de um registro. Neste caso, significa que o leitor ir deslocar a quantidade de bytes ocupadas por 2 registros, com isso, ir se posicionar no incio do terceiro registro. 73

Ateno
6 O parmetro origem deve ser colocado todo em letra maiscula.

Programao I

A figura 3.6 apresenta a posio do leitor aps a execuo dos fseek do exemplo.

Figura 3.6: Posio do leitor aps a execuo dos fseek do exemplo 3.6

3.2.7 Comando para posicionar o leitor no incio do arquivo Ns podemos posicionar o leitor no incio do arquivo, utilizando o comando rewind. A sua sintaxe a seguinte:
Sintaxe

rewind(ponteiro_arquivo);

Onde: ponteiro_arquivo: o ponteiro que tem o endereo do arquivo que queremos posicionar o leitor. O exemplo 3.7 apresenta o uso do comando rewind.
Exemplo 3.7: Uso do comando rewind

rewind(paluno);

O comando rewind utilizado quando precisamos fazer uma varredura por todos os registros do arquivo. A varredura iniciada colocando o leitor no incio do arquivo. 74

Programao I

3.2.8 Comando para verificar se chegou ao final do arquivo Quando fazemos uma varredura no arquivo, no sabemos quantos registros tem armazenados no mesmo. No entanto, precisamos saber o momento de parar de executar a leitura dos registros. O comando feof (end of file) informa se o leitor chegou ao final do arquivo ou no. A sintaxe do feof a seguinte:
Sintaxe

int feof(ponteiro_arquivo);

Onde: int: o retorno da funo. A funo feof retorna um nmero inteiro, que indica se o arquivo terminou ou no. Quando a funo retorna zero, significa que ainda no chegou no final do arquivo. Qualquer valor diferente de zero, indica que chegou ao final do arquivo. ponteiro_arquivo: o ponteiro que tem o endereo do arquivo que queremos verificar se chegou ao fim. O exemplo 3.8 apresenta o uso do comando feof.
Exemplo 3.8: uso do comando feof

while (feof(paluno)==0)

Normalmente, o feof usando como condio de um while, como mostra o exemplo 3.8. Este while ser executado enquanto no chegar no final do arquivo. 3.2.9 Comando para remover um arquivo Quando desejamos apagar um arquivo do diretrio, podemos utilizar o comando remove. Este comando s pode ser utilizado em arquivos fechados. A sua sintaxe a seguinte:
Sintaxe

remove(nome_do_arquivo);

Onde: nome_do_arquivo: o nome do arquivo que queremos apagar. 75

Programao I

Neste caso, utilizado o nome do arquivo salvo no diretrio do nosso computador. O exemplo 3.9 apresenta o uso do comando remove.
Exemplo 3.9: uso do comando remove

remove(alunos.bin);

Neste exemplo, computador.

arquivo

alunos.bin

ser

removido

do

3.2.10 Comando para renomear um arquivo Ns podemos renomear um arquivo no diretrio do nosso computador. Para isso, utilizamos o comando rename. Este comando, tambm, s pode ser utilizado em arquivos fechados. A sua sintaxe a seguinte:
Sintaxe

rename(nome_do_arquivo, novo_nome_do_arquivo);

Onde: nome_do_arquivo: o nome do arquivo que queremos renomear. Neste caso; utilizado o nome do arquivo salvo no diretrio do nosso computador. novo_nome_do_arquivo: o novo nome para o nosso arquivo. O exemplo 3.10 apresenta o uso do comando rename.
Exemplo 3.10: uso do comando rename

rename(alunos.bin, alunos_temp.bin);

Neste exemplo, o arquivo alunos.bin, ser renomeado para alunos_temp.bin.

3.3 Implementao das operaes bsicas em um arquivo


Agora a hora de fazermos o nosso programa completo, que 76

Programao I

ir aplicar os comandos de manipulao de arquivo, descritos na seo 3.2. Este programa ir gerenciar os dados dos alunos de uma turma, que sero armazenados em um arquivo. O registro do aluno composto pela matrcula, nome e mdia do aluno. O programa implementar as seguintes operaes: cadastrar aluno, remover aluno, consultar aluno por matrcula, alterar mdia do aluno e listagem de todos os alunos. Mais uma vez, teremos um programa cheio de detalhes, bem maior do que os que fizemos at ento. Por isso, o programa completo 3.1 foi desenvolvido de forma modularizada. Para facilitar o entendimento deste programa, que tem quase 200 linhas, o mesmo foi dividido em 8 partes. Vamos comear? Na primeira parte do programa completo 3.1, teremos as declaraes das variveis globais do programa. Alm de mdulos auxiliares, que sero utilizados ao longo do programa, por outros mdulos.
Programa Completo 3.1 - Parte 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void linha() { int i; for (i=1; i<=80; i++) } printf(_); FILE *paluno; TAluno aluno_aux, aluno_nulo; typedef struct{ int mat; char nome[20]; float med; } TAluno; #include <stdio.h>

77

Programao I

17 18 19 20 21 22 23 24 25 26 27

void cabec() { system(cls); printf(Universidade Pernambuco\n); linha(); } Federal Rural de

void abre_arquivo() { paluno = fopen(aluno.dat, r+b); if (paluno == NULL) } paluno = fopen(aluno.dat, w+b);

Comentrios sobre o Programa Completo 3.1, Parte 1: Linha 1: incluso da biblioteca stdio.h devido o uso do comando fflush e comandos de manipulao de arquivo. Linhas 3 a 6: definio de um novo tipo de dados TAluno, que agrupa os dados de um aluno. O tipo TAluno composto pela matrcula, nome e mdia do aluno. Linha 8: declarao do ponteiro paluno, que armazenar o endereo do arquivo com os registros dos alunos. Linha 9: declarao de dois registros: aluno_aux e aluno_nulo. O registro aluno_aux ser utilizado quando precisamos ler ou gravar um registro no arquivo. O registro aluno_nulo ser utilizado no momento da remoo de um aluno do arquivo. As variveis declaradas nas linhas 8 e 9 so globais, por isso, podem ser acessadas por todos os mdulos do programa. Linhas 11 a 15: temos o primeiro mdulo do nosso programa. O mdulo linha tem como objetivo passar uma linha na tela. Este mdulo ser chamado pelos demais mdulos do programa. Linhas 17 a 21: temos a sequncia de comandos do mdulo cabec. O mdulo cabec faz o cabealho das tela. Ao iniciar uma operao do programa (cadastro, remoo, etc), a tela deve ser limpa e precisamos colocar o nome da universidade no topo 78

Programao I

da tela. O mdulo cabec vai: limpar a tela, colocar o nome da instituio e passar uma linha (fazendo uso do mdulo linha). Linhas 23 a 27: temos a sequncia de comandos do mdulo que responsvel por abrir o arquivo dos alunos, e deix-lo disponvel para uso. Vamos entender a lgica deste mdulo? Primeiramente, feita uma tentativa de abrir o arquivo dos alunos alunos.dat com o modo de abertura r+b, no comando fopen. Lembrem que o modo de abertura r+b s pode ser utilizado quando o arquivo j existe. O processador vai procurar o arquivo alunos.dat no diretrio. Se o arquivo no for encontrado, o ponteiro paluno, ficar com NULL. Mas, se for encontrado, o endereo de memria do arquivo ser armazenado no ponteiro paluno. Na sequncia (linha 25), temos um if que testa o valor do ponteiro paluno. Se o ponteiro paluno estiver com NULL, significa que o arquivo alunos.dat no existe ainda e precisa ser criado. Se isso acontecer, o comando vinculado ao if executado. Este comando um fopen, s que agora utiliza o modo de abertura w+b, que deve ser utilizado para arquivos que no existe. Mas por que no abrimos o arquivo usando logo o w+b? Vocs devem estar lembrados que o modo de abertura w+b apaga todos os registros de um arquivo quando ele j existe. Assim, tentamos primeiro abrir o arquivo com r+b (utilizado para arquivos que j existem e abre o arquivo sem apagar os registros). Se der erro, porque o arquivo no existe. Com isso, tentamos abrir com o modo de abertura w+b. Vamos agora para a parte 2 do programa completo 3.1. Nesta parte temos o mdulo inserir, que responsvel pelo cadastro dos registros dos alunos no arquivo. Para fazer o cadastro de um registro no arquivo binrio, devemos obter os dados do aluno, montando o registro que iremos gravar no arquivo. Quando o registro estiver com todas as informaes do aluno (mat, nome e media), o mesmo poder ser gravado no final do arquivo.

Ateno
7 O nome do arquivo que ns passarmos como parmetro no fopen ser utilizado para salvar nosso arquivo no diretrio. Por exemplo, aps a execuo do mdulo abre_ arquivo, teremos um arquivo chamado alunos. dat no diretrio onde est salvo o programa executvel. Por conveno, coloque os arquivos de dados sempre com a extenso dat ou bin.

79

Programao I

Programa Completo 3.1 - Parte 2 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 void inserir() { int resp; do { cabec(); printf(\n\nCadastrar novo aluno\n\n); printf(\nMatricula: ); scanf(%d, &aluno_aux.mat); printf(\nNome.....: ); fflush(stdin); gets(aluno_aux.nome); printf(\nMedia....: ); scanf(%f, &aluno_aux.med); fseek(paluno, 0, SEEK_END); sizeof(TAluno), 1,

fwrite(&aluno_aux, paluno);

printf(\n\nAluno cadastrado com sucesso! \n\n); printf(\nDeseja (1-sim/0-nao)? ); scanf(%d, &resp); cadastrar outro

} while (resp ==1); }

Comentrios sobre o Programa Completo 3.1, Parte 2 Linha 28: incio do mdulo inserir. Linha 29: declarao da varivel resp. Esta varivel ir armazenar a resposta do usurio, quando for perguntado se ele deseja cadastrar mais alunos. Linha 30: incio de um do/while. O mdulo inserir ficar executando enquanto o usurio desejar cadastrar novos alunos. Nesta linha, tambm temos a chamada do mdulo cabec. Cada vez que um cadastro feito, a tela vai ser limpa, para iniciar um 80

Programao I

novo cadastro. Linha 31: printf que informa o que esta tela faz cadastro de alunos. Linhas 32 e 33: printf solicitando que seja digitada a matrcula do aluno e scanf que l esta informao. Os dados do aluno vo sendo colocados no registro aluno_aux. Linhas 34 a 36: printf solicitando que seja digitado o nome do aluno, fflush para limpar o buffer de entrada (j que teremos a leitura de uma sequncia de caractere) e o gets que l o nome do aluno e armazena no registro aluno_aux. Linhas 37 e 38: printf solicitando que seja digitada a mdia do aluno e scanf que l esta informao. Neste momento, o registro aluno_aux acabou de ser todo preenchido com os dados do aluno e j pode ser gravado no arquivo. Linha 39: para gravar o registro no arquivo, devemos posicionar o leitor no final do arquivo para no correr o risco de fazer a gravao sobre algum outro registro. Para isso, executado o fseek. Linha 40: com o leitor posicionado no final do arquivo, podemos executar o fwrite, que vai gravar o contedo do registro aluno_ aux, no nosso arquivo. Linha 41: printf para informar que o aluno foi cadastrado com sucesso. Linhas 42 e 43: printf para pergunta se o usurio deseja cadastrar outro aluno e scanf que l a resposta para esta pergunta. Linha 44: final do do/while, com a condio de parada. O do/ while executado enquanto o usurio estiver respondendo que quer cadastrar mais alunos. Notem que no precisamos nos preocupar com a capacidade do arquivo. Vamos armazenando quantos registros desejarmos. Linha 45: fecha chaves que indica o final do mdulo inserir. A figura 3.7 apresenta a tela de execuo do programa 3.1, na tela de cadastro de novo aluno.

81

Programao I

Figura 3.7: Tela de cadastro de aluno

Vamos ver agora o cdigo de dois mdulos que sero utilizados pelos mdulos: consultar aluno por matrcula, remover aluno e alterar mdia do aluno. Quando fazemos uma consulta, alterao ou remoo, precisamos localizar o registro do aluno no arquivo e apresentar o registro para o usurio. Por isso, foi criado um mdulo responsvel para procurar um registro no arquivo e, outro mdulo, responsvel por apresentar os dados do registro de um aluno. Vamos l, entender a parte 3 do nosso programa completo 3.1!
Programa Completo 3.1 - Parte 3 46 47 48 49 50 51 52 53 54 55 56 int procura(int matp) { int p; p = 0; rewind(paluno); fread(&aluno_aux, sizeof(TAluno), 1, paluno); while (feof(paluno)==0) { if (aluno_aux.mat == matp) return p;

else

{ paluno);

fread(&aluno_aux,

sizeof(TAluno),

1,

p++;

82

Programao I

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72

return -1; }

void mostre(int pos) { fseek(paluno, pos*sizeof(TAluno), SEEK_SET); fread(&aluno_aux, sizeof(TAluno), 1, paluno); printf(\n\n); linha(); printf(Matricula linha(); printf(%9d linha(); } %-20s %5.1f\n, aluno_aux.mat, Nome Media\n);

aluno_aux.nome, aluno_aux.med);

Comentrios sobre o Programa Completo 3.1, Parte 3: Linhas 46 a 60: temos a sequncia de comandos do mdulo procura. O mdulo recebe um parmetro, que a matrcula do aluno que est sendo procurado. Ao finalizar a sua execuo, esse mdulo retorna um int que pode ser: -1 (significa que procurou o registro do aluno no arquivo e no achou) ou um nmero positivo (que significa em qual posio do arquivo o registro foi encontrado). Este mdulo possui uma varivel local p, que incrementada cada vez que feita a leitura de um registro no arquivo. o valor desta varivel que indica em que posio do arquivo o registro foi encontrado. Para localizar o registro de um aluno, com uma dada matrcula, precisamos percorrer todo o arquivo, at encontrar o registro ou at o arquivo chegar ao fim. Para percorrer o arquivo, colocamos o leitor no incio do mesmo (usando o rewind linha 49) e efetuamos vrios fread, at que chegue no final do arquivo (while da linha 51). Logo aps posicionar o leitor no incio do 83

Programao I

arquivo, fazemos a leitura do primeiro registro do arquivo, para verificar se no o final de arquivo (end of file). Lembrem que, assim que um fread executado, o leitor j fica posicionado no incio do prximo registro, pronto para um novo fread. Quando um registro do arquivo tem a mesma matrcula que est sendo procurada, significa que encontramos o aluno. Com isso, j pode ser dado o retorno, indicando a posio onde o registro foi encontrado (linha 52 e 53). Se fizermos a leitura de todos os registros do arquivo e no encontrar nenhum aluno com a matrcula procurada, o mdulo retornar -1 (linha 59). Linhas 62 a 72: temos a sequncia do mdulo mostre. Este mdulo recebe como parmetro a posio do registro que deve ser apresentado, recupera o registro no arquivo e apresenta os dados do registro em forma de tabela. O mdulo comea com o posicionamento do leitor no incio do registro que deve ser mostrado (linha 63). Notem que, no fseek, no campo que indica o tamanho do deslocamento que o leitor vai dar, feita a conta: pos*sizeof(TAluno). Vamos entender o porqu desta conta. A varivel pos indica em que posio o registro est armazenado no arquivo (se ele o primeiro, segundo, etc.). Consequentemente, saberemos quantos registros tem armazenados antes do registro que queremos mostrar. E assim, saberemos sobre quantos registros o leitor deve se deslocar, at ser posicionado no incio do registro desejado. Com o leitor no ponto certo, podemos fazer a leitura do registro do aluno, armazenando seus dados no registro aluno_aux (linha 64). Aps isto, precisamos apenas apresentar os dados do aluno (linhas 65 a 71). Vamos agora entender o mdulo responsvel por consultar um aluno atravs do seu nmero de matricula. O mdulo consultar vai solicitar que o usurio informe a matrcula do aluno que deseja consultar. Atravs do uso do mdulo procura descoberta em que posio o registro do aluno se encontra armazenado no arquivo. Se o aluno estiver armazenado no arquivo, seus dados so apresentados, atravs do uso do mdulo mostre. Se o aluno no for encontrado, apresentada uma mensagem de erro.

84

Programao I

Programa Completo 3.1 - Parte 4 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 void consultar() { int resp, matcon, posicao; do{ cabec(); printf(\n\nConsultar Aluno\n\n\n); printf(Matricula do aluno: ); scanf(%d, &matcon); posicao = procura(matcon); if (posicao == -1) printf(\n\nMatricula nao encontrada!

\n\n); else

mostre(posicao); consultar outro

printf(\n\nDeseja (1-sim/0-nao)? ); scanf(%d, &resp);

} while (resp == 1); }

Comentrios sobre o Programa Completo 3.1, Parte 4 Linha 73: incio do mdulo consultar. Linha 74: declarao das variveis locais: resp, matcon (matricula que ser consultada) e posicao (armazena em que posio o registro foi localizado). Linha 75: incio de um do/while. O mdulo consultar ficar executando enquanto o usurio desejar consultar alunos. Nesta linha, tambm temos a chamada do mdulo cabec. Cada vez que uma consulta feita, a tela vai ser limpa, para iniciar uma nova consulta. Linha 76: printf que informa o que esta tela faz consultar aluno. Linhas 77 e 78: printf solicitando que seja digitada a matrcula 85

Programao I

do aluno que deseja consultar e scanf que l esta informao. Linha 79: chamada do mdulo procura, passando a matrcula que desejamos consultar como parmetro. O retorno do mdulo procura armazenado na varivel posicao. Linhas 80 a 83: if que verifica se a varivel posicao tem armazenado -1. Se sim, porque o aluno no foi encontrado. Com isso, escrita uma mensagem de erro. Caso posicao no esteja com -1, porque o aluno foi encontrado e seus dados devem ser apresentados. Para apresentar os dados do aluno, fazemos uma chamada ao mdulo mostre, passando a posio onde o aluno foi encontrado como parmetro. Linhas 84 e 85: printf para pergunta se o usurio deseja consultar outro aluno e scanf que l a resposta para esta pergunta. Linha 86: final do do/while, com a condio de parada. O do/ while executado enquanto o usurio estiver respondendo que quer consultar mais alunos. Linha 87: fecha chaves que indica o final do mdulo consultar. A figura 3.8 apresenta a tela de execuo do programa 3.1, na tela de consulta aluno por matrcula.

Figura 3.8: Tela de consulta aluno por matrcula

Vamos agora entender o mdulo responsvel por remover um aluno do arquivo. O mdulo da remoo inicia de forma muito similar ao da consulta. Primeiro, solicitado o nmero da matrcula do aluno 86

Programao I

que ser removido, seu registro localizado e apresentado para que o usurio possa ter certeza que vai remover o registro certo. Na verdade, um registro no removido do arquivo, o que fazemos gravar sobre o registro do aluno que queremos remover, um registro com os dados zerados (aluno_nulo). Assim, toda vez que temos um registro com a matrcula igual a zero no arquivo, significa que ele um registro que foi removido. Se o aluno no for encontrado, apresentada uma mensagem de erro.
Programa Completo 3.1 - Parte 5 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 void remover() { int matrem, conf, resp, posicao; aluno_nulo.mat = 0; aluno_nulo.med = 0; do{ cabec(); printf(\n\nRemover aluno\n\n\n); printf(Matricula: ); scanf(%d, &matrem); posicao = procura(matrem); if (posicao == -1) printf(\nAluno nao encontrado!!\a);

else {

mostre(posicao); printf(\n\nDeseja scanf(%d, &conf); if (conf == 1) remover o aluno

(1-sim/0-nao)? );

{ f s e e k ( p a l u n o , p o s i c a o * s i z e o f (TAluno),SEEK_SET); f w r i t e ( & a l u n o _ n u l o , sizeof(TAluno), 1, paluno); sucesso!); } printf(\n\nAluno removido com

87

Programao I

108 109 110 111 112 113 114

else printf(\nRemocao cancelada!);

printf(\n\n\nDeseja (1-sim/0-nao)? ); scanf(%d, &resp);

remover

outro

} while (resp ==1); }

Comentrios sobre o Programa Completo 3.1, Parte 5: Linha 88: incio do mdulo remover. Linha 89: declarao das variveis locais: resp, matrem (matricula que ser removida), conf (confirmao se deseja remover realmente) e posicao (armazena em que posio o registro foi localizado). Linhas 90 e 91: inicializao dos campos do registro aluno_ nulo. Linha 92: incio de um do/while. O mdulo remover ficar executando enquanto o usurio desejar remover alunos. Nesta linha, tambm temos a chamada do mdulo cabec. Cada vez que uma remoo feita, a tela vai ser limpa, para iniciar uma nova remoo. Linha 93: printf que informa o que esta tela faz remover aluno. Linhas 94 e 95: printf solicitando que seja digitada a matrcula do aluno que deseja remover e scanf que l esta informao. Linha 96: chamada do mdulo procura, passando a matrcula que desejamos remover como parmetro. O retorno do mdulo procura armazenado na varivel posicao. Linhas 97 a 110: if que verifica se a varivel posicao tem armazenado -1. Se sim, porque o aluno no foi encontrado. Com isso, escrita uma mensagem de erro. Caso posicao no esteja com -1, porque o aluno foi encontrado e seus dados devem ser apresentados. Para apresentar os dados do aluno, 88

Programao I

fazemos uma chamada ao mdulo mostre, passando a posio onde o aluno foi encontrado como parmetro. Aps ver os dados do aluno, o usurio pode desistir de remov-lo. Na linha 102, temos o scanf que l se o usurio confirma ou no a remoo. A remoo, propriamente dita, executada nas linhas 104 e 105. Na linha 104, temos o posicionamento do leitor sobre o registro que queremos remover. E, na linha 105, temos a gravao do registro aluno_nulo sobre o registro antigo. Linhas 111 e 112: printf para pergunta se o usurio deseja remover outro aluno e scanf que l a resposta para esta pergunta. Linha 113: final do do/while, com a condio de parada. O do/ while executado enquanto o usurio estiver respondendo que quer remover mais alunos. Linha 114: fecha chaves que indica o final do mdulo remover. A figura 3.9 apresenta a tela de execuo do programa 3.1, na tela de remoo de aluno.

Figura 3.9: Tela de remoo do registro do aluno

Agora vamos entender o mdulo responsvel pela alterao da mdia do aluno. Este mdulo parecido com a remoo. Primeiro, solicitado o nmero da matrcula do aluno que ser alterado, seu registro localizado e apresentado para que o usurio possa ter certeza que vai alterar o registro certo. Na alterao, gravamos um registro com a mdia alterada, sobre o antigo registro do aluno. 89

Programao I

Programa Completo 3.1 - Parte 6 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 void alterar() { int matalt, conf, resp, posicao; do { cabec(); n\n); printf(\n\nAlterar media do aluno\n\

printf(Matricula: ); scanf(%d, &matalt); posicao = procura(matalt); if (posicao == -1) printf(\nAluno,nao encontrado!!\a);

else {

mostre(posicao); a media do

printf(\n\nAlterar aluno(1-sim/0-nao)? ); scanf(%d, &conf); if (conf == 1) {

printf(\nNova media: ); scanf(%f, &aluno_aux.med);

\n\n); SEEK_SET); paluno);

printf(\nMedia alterada com sucesso! fseek(paluno,posicao*sizeof(TAluno), fwrite(&aluno_aux,sizeof(TAluno), mostre(posicao); 1,

printf(\nMedia do aluno alterada com sucesso!\n); } else

90

Programao I

138 139 140 141 142 143

\n\n);

printf(\n\nAlteracao

cancelada!

} alterar outro

printf(\n\nDeseja (1-sim/0-nao)? ); scanf(%d, &resp);

}while (resp ==1); }

Comentrios sobre o Programa Completo 3.1, Parte 6: Linha 115: incio do mdulo alterar. Linha 116: declarao das variveis locais: resp, matalt (matricula que ser alterada), conf (confirmao se deseja alterar a mdia do aluno) e posicao (armazena em que posio o registro foi localizado). Linha 117: incio de um do/while. O mdulo alterar ficar executando enquanto o usurio desejar alterar alunos. Nesta linha, tambm temos a chamada do mdulo cabec. Cada vez que uma alterao feita, a tela vai ser limpa, para iniciar uma nova alterao. Linha 118: printf que informa o que esta tela faz alterar mdia do aluno. Linhas 119 e 120: printf solicitando que seja digitada a matrcula do aluno que deseja alterar e scanf que l esta informao. Linha 121: chamada do mdulo procura, passando a matrcula que desejamos alterar como parmetro. O retorno do mdulo procura armazenado na varivel posicao. Linhas 122 a 139: if que verifica se a varivel posicao tem armazenado -1. Se sim, porque o aluno no foi encontrado. Com isso, escrita uma mensagem de erro. Caso posicao no esteja com -1, porque o aluno foi encontrado e seus dados devem ser apresentados. Para apresentar os dados do aluno, fazemos uma chamada ao mdulo mostre, passando a posio onde o aluno foi encontrado como parmetro. Aps ver os dados do aluno, o usurio pode desistir de alterar a sua mdia. Na 91

Programao I

linha 127, temos o scanf que l se o usurio confirma ou no a alterao. Se o usurio confirma que quer alterar, solicitada a nova mdia do aluno (linha 130). A alterao, propriamente dita, executada nas linhas 132 e 133. Na linha 132, temos o posicionamento do leitor sobre o registro que queremos alterar. E, na linha 133, temos a gravao do registro alterado sobre o registro antigo. Aps os dados serem alterados, o registro do aluno reapresentado atravs de uma chamada ao mdulo mostre (linha 134). Linhas 140 e 141: printf para pergunta se o usurio deseja alterar outro aluno e scanf que l a resposta para esta pergunta. Linha 142: final do do/while, com a condio de parada. O do/ while executado enquanto o usurio estiver respondendo que quer alterar mais alunos. Linha 143: fecha chaves que indica o final do mdulo alterar. A figura 3.10 apresenta a tela de execuo do programa 3.1, na tela de alterao de mdia do aluno.

Figura 3.10: Tela de alterao de mdia do aluno

Veremos, agora, o ltimo mdulo do programa, que a listagem. Este mdulo responsvel por apresentar todos dados dos alunos que esto armazenados no arquivo. Os dados sero apresentados em forma de tabela. Devemos lembrar que s iremos apresentar os 92

Programao I

registros vlidos do arquivo, ou seja, registros com matrcula zerada no devem ser apresentados.
Programa Completo 3.1 - Parte 7 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 void listagem() { cabec(); printf(\n\nListagem Geral\n\n\n); linha(); printf(Matricula linha(); rewind(paluno); fread(&aluno_aux, sizeof(TAluno), 1, paluno); while (feof(paluno)==0) { mat, if (aluno_aux.mat != 0) printf(%9d %-20s %5.1f\n, aluno_aux. Nome Media\n);

aluno_aux.nome, aluno_aux.med);


1,

fread(&aluno_aux, paluno); } linha();

sizeof(TAluno),

printf(tecle enter para voltar ao menu...); getche(); }

Comentrios sobre o Programa Completo 3.1, Parte 7 Linha 144: incio do mdulo listagem. Linha 145: chamada ao mdulo cabec, responsvel por limpar a tela e escrever o nome da instituio. Linha 146: printf que informa o que esta tela faz listagem geral. Linha 147: chamada do mdulo linha, para iniciar o desenho da tabela. 93

Programao I

Linha 148: printf que escreve os cabealhos das colunas da tabela. Linha 149: mais uma chamada ao mdulo linha. Linha 150: posiciona o leitor no incio do arquivo, para que possamos varrer o arquivo, visitando todos os registros do arquivo. Linha 151: Leitura do primeiro registro do arquivo, para verificar se no o final do arquivo. Linhas 152 a 157: while que executado enquanto no chegar no final do arquivo. Para cada registro lido, verificado se o mesmo tem a matrcula igual a zero. Se sim, o registro no apresentado na listagem. Linha 158: chamada do mdulo linha, para fechar a tabela. Linha 159: printf informando que o usurio deve teclar enter para sair da listagem. Linha 160: getche para que possamos ver a listagem. Linha 161: fecha chaves que indica o final do mdulo listagem. A figura 3.11 apresenta a tela de execuo do programa 3.1, na tela de listagem dos dados de todos os alunos.

Figura 3.11: Tela de listagem de dados de todos os alunos

O programa principal do Programa completo 3.1 apresentado a seguir. no programa principal que sero feitas as chamadas aos mdulos que o usurio deseja executar no momento. 94

Programao I

Programa Completo 3.1 - Parte 8 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 main() { int op; abre_arquivo(); do{ cabec(); printf(\n\nOpcoes: \n\n\n); printf( printf( 1- Cadastrar novo aluno\n\n); 2- Remover aluno\n\n); 34Consultar media aluno do por aluno

printf( matricula\n\n);

\n\n);

printf( printf( printf( linha();

Alterar

5- Listagem geral\n\n); 0- Sair\n\n);

printf(Informe a opcao desejada: ); scanf(%d, &op); switch(op) { case 1: inserir(); break; case 2: remover(); break; case 3: consultar(); break; case 4: alterar(); break; case 5: listagem(); break; case 6: limpar(); break; case 0: fclose(paluno); break; default: break; printf(\n\n\aOpcao

invalida!);

95

Programao I

186 187 188

} while (op != 0); }

Comentrios sobre o Programa Completo 3.1, Parte 8: Linha 162: incio do programa principal. Linha 163: declarao da varivel local op, que vai armazenar a operao que o usurio deseja executar. Linha 164: chamada do mdulo abre_arquivo, disponibilizando o mesmo para uso. Linhas 165 a 187: do/while responsvel por ler a operao que o usurio quer executar e fazer a chamada do mdulo que implementa a operao. Linha 188: fecha chaves do programa principal. A figura 3.12 apresenta a tela de execuo do programa 3.1, na tela do menu principal, onde informada a operao que desejamos executar.

Figura 3.12: Tela do menu principal

E assim, terminamos mais um programa completo. Agora, colocar a mo no teclado e comear a programar, armazenando dados em arquivos. 96

Programao I

Atividades e Orientaes de Estudos Temos agora mais uma lista de exerccios para consolidar o nosso entendimento do assunto visto neste captulo. Preparem-se, pois as questes esto maiores. Mas isso bom porque vemos que estamos fazendo programas interessantes, no mesmo? 1. Faa um programa para um shopping contendo as seguintes telas:
Tela de Menu Shopping Center Opes: 1 .Cadastrar loja 2. Consultar loja 3. Listagem de todas as lojas 0. Sair Entre com a opo: Cadastro Shopping Center Cadastro de Loja Cdigo: Nome: rea: Tipo(1-Confeces, 2-Alimentao, 3-Livros, 4- Servios): Cadastrar outra (1-Sim/0-Nao)?

Consulta Shopping Center Consultar Loja Cdigo da loja que deseja consultar: Cdigo xxx Nome xxxxxxx rea xx Tipo xx Condomnio xxxx

Consultar outra (1-Sim/0-Nao)?

97

Programao I

Relatrio Geral Shopping Center Listagem Geral Codigo xxx xxx xxx Nome xxxxxxx xxxxxxx xxxxxxx rea xx xx xx Tipo xx xx xx Condomnio xxxxx xxxxx xxxxx

Tecle enter para voltar ao menu...

O programa ir armazenar os dados das lojas em um arquivo. O programa ir calcular o valor do condomnio de cada loja. O valor do condomnio depende da rea e do tipo da loja. Veja tabela abaixo:
Tipo da loja 1 2 3 4 Valor do m R$ 50 R$ 65 R$ 80 R$ 95

2. Faa um programa para uma Agncia de Turismo armazenando os dados em um arquivo. O programa dever ter as seguintes funes: Cadastrar roteiro, Consultar roteiro, Listagem de todos os roteiros e Simular valor de viagem. A seguir, sugestes de telas.
Tela Principal Vida Boa Turismo Opes: 1- Cadastrar roteiro 2- Consultar roteiro 3- Listagem de todos os roteiros 4- Simular viagem 0- Sair Entre com a opo:

98

Programao I

Tela de Cadastro Vida Boa Turismo Cadastrar Roteiro Cdigo: Pas(1-Brasil, 2-Espanha, -3-Italia): Cidade: Diria de Hotel: R$ Diria Aluguel de Carro: R$ Inserir outro(1-sim,2-no)?

Tela de Remoo de Roteiro Vida Boa Turismo Consultar Roteiro Cdigo do roteiro a ser consultado: Cdigo xxx Pas x Cidade xxxxxxxx Diria Hotel xxx Carro xxxx

Consultar outro (1-Sim/0-Nao)? Tela de Listagem de todos os roteiros Vida Boa Turismo Listagem de todos os roteiros Cdigo xxx xxx xxx Pas x x x Cidade xxxxxxxx xxxxxxxx xxxxxxxx Diria Hotel xxx xxx xxx Carro xxxx xxxx xxxx

Pgina x de x... Tecle enter Tecle enter para voltar ao menu...

99

Programao I

Tela para simular valor de viagem Vida Boa Turismo Simular Viagem Cdigo do roteiro: Cdigo xxx Pas x Cidade xxxxxxxx Diria Hotel xxx Carro xxxx

Quantidade de dias: Alugar carro(1-sim, 2-no)? Valor total da viagem = R$ xxxxx Simular outro roteiro(1-sim, 2-no)?

Observaes: Os dados do roteiro devem ser armazenados em um arquivo. No pode cadastrar roteiros com cdigos repetidos. O valor da viagem deve ser calculado com base nos valores do roteiro escolhido; viagem = quantos dias * valor diria hotel + quantos dias * valor diria carro (caso alugue carro). Na consulta deve passar o cdigo do roteiro e apresentar os dados do roteiro. Na listagem, apresentar os dados de todos os roteiros em forma de tabela.

Conhea Mais Para melhorar o nosso conhecimento sobre manipulao de arquivos binrios, vejam este assunto nos livros: LAUREANO, Marcos. Programando em C Para Linux, Unix e Windows. Rio de Janeiro: Brasport, 2005. MIZRAHI, Victorine Viviane. Treinamento em Linguagem C Curso Completo. So Paulo: Makron, 1999. 100

Programao I

Vamos revisar? Vamos fazer uma reviso do assunto que foi visto neste captulo, lendo o resumo a seguir: Os arquivos servem para armazenar nossos dados de forma definitiva. Os arquivos binrios so adequados para o armazenamento de registros. Cada registro que armazenado no arquivo ocupa a mesma quantidade de memria. Um ponto importante sobre arquivos que toda operao sobre um arquivo ser executada no ponto onde o leitor se encontra. Com o comando fseek, podemos colocar o leitor sobre o registro que desejamos ler ou gravar. S podemos manipular um arquivo que esteja aberto. Aps o uso do arquivo, devemos fech-lo. O arquivo criado pelo programa salvo no mesmo diretrio em que est armazenado o nosso programa executvel.

101

Programao I

Referncias

ARAJO, Jairo. Dominando a Linguagem C. So Paulo: Cincia Moderna, 2004. ASCENIO, Ana Fernanda Gomes e CAMPOS, Edilene Aparecida Veneruchi. Fundamentos de Programao de Computadores. So Paulo: Prentice Hall, 2002. DEITEL, H, M e DEITEL, P. J. Como Programar em C. Rio de Janeiro: LTC, 1999. LAUREANO, Marcos. Programando em C Para Linux, Unix e Windows. Rio de Janeiro: Brasport, 2005. MIZRAHI, Victorine Viviane. Treinamento em Linguagem C Curso Completo. So Paulo: Makron, 1999. MONTGOMERY, Eduard. Programando em C: Simples e Prtico. So Paulo: Alta Books, 2006. OLIVEIRA, Ulisses. Programando em C Volume I Fundamentos. So Paulo: Cincia Moderna, 2004. SCHILDT, Herbert. C Completo e Total. So Paulo: Makron, 1996.

102

Programao I

Consideraes Finais
Neste volume, tivemos a oportunidade de aprender como armazenar dados em vetores, registros e arquivos. O armazenamento adequado dos dados possibilitou o desenvolvimento de programas com operaes mais elaboradas como: cadastro de elementos, remoo, alterao, consultas e listagens. Perceberam o quanto nossos programas evoluram desde o nosso primeiro programa completo, at hoje? Vejam que todos os conceitos que aprendemos esto sempre em uso nos nossos programas. Isto bom porque nos acostumamos com a sintaxe dos comandos. Agora, temos apenas mais um mdulo para finalizar a nossa caminhada, em busca do aprendizado da linguagem de programao C. Continuem firmes nos estudos! Estamos quase no final! At o prximo mdulo.

103

Programao I

Conhecendo a Autora
Sou graduada em Cincia da computao pela Universidade Federal de Sergipe. Fiz mestrado e doutorado na Universidade Federal de Pernambuco, desenvolvendo pesquisas nas reas de Sistemas Distribudos e Geoprocessamento. Comeei a ensinar em 2000, nos cursos de Cincia da Computao e Sistemas de Informao. Desde o incio da minha carreira como professora, ministro disciplinas de Programao e tenho uma paixo pela linguagem C. Atualmente, encontrei uma nova paixo: Educao a Distncia.

104

Você também pode gostar