Você está na página 1de 36

ANSI C para quem tem pressa

Antnio Manuel de Sousa Barros (AMB) amb@isep.ipp.pt 24 de Fevereiro de 2003

Contedo
1 Noes bsicas de sistemas informticos. 1.1 A histria da programao de computadores. . 1.1.1 A linguagem mquina. . . . . . . . . 1.1.2 A linguagem assembly. . . . . . . . . 1.1.3 As linguagens de alto nvel. . . . . . 1.2 Os sistemas operativos. . . . . . . . . . . . . 1.3 Compiladores. . . . . . . . . . . . . . . . . . Estrutura de um programa em C. 2.1 Directivas de pr-compilao. . 2.2 Declarao de variveis globais. 2.3 As funes. . . . . . . . . . . . 2.4 A funo main(). . . . . . . . . 2.5 Exerccios. . . . . . . . . . . . Estruturas de deciso e ciclos. 3.1 Estruturas de deciso. . . . . 3.1.1 if - ... - else - ... . . . 3.1.2 switch... case... . . . 3.2 Ciclos. . . . . . . . . . . . . 3.2.1 Ciclos for(). . . . . . 3.2.2 Ciclos while(). . . . 3.2.3 Ciclos do-...-while(). 3.3 Exerccios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4 4 4 5 5 6 7 8 8 8 9 9 10 11 11 11 12 12 13 13 13 14 15 15 15 15 15 16 16 17 18 18 18 18

Funes. 4.1 As partes de uma funo. . . . . . . . . . . . . 4.1.1 Cabealho ou Prottipo. . . . . . . . . 4.1.2 Corpo de uma funo. . . . . . . . . . 4.2 Funes sem parmetros. . . . . . . . . . . . . 4.3 Funes com parmetros. . . . . . . . . . . . . 4.3.1 Passagem de parmetros por valor. . . . 4.3.2 Passagem de parmetros por referncia.

Vectores. 5.1 Operaes com vectores. . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 Declarar um vector. . . . . . . . . . . . . . . . . . . . . . . . 5.1.2 Aceder aos elementos do vector. . . . . . . . . . . . . . . . .

Apontadores. 6.1 Aceder aos endereos de memria onde se encontram as variveis. . . 6.2 Variveis apontadores. . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Exerccios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Apontadores e memria dinmica. 7.1 A necessidade de memria dinmica. . . . . 7.2 Manuseamento dinmico de memria em C. 7.2.1 Reserva dinmica de memria. . . . 7.2.2 Libertar memria dinmica. . . . . 7.2.3 Ajuste de memria dinmica. . . . 7.3 Exerccios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

20 20 20 22 23 23 23 23 24 24 25 26 26 27 27 27 27 27 28 28 28 28 28 29 29 30 30 30 30 31 31 32 32 32 33 33 33 33 34 34 35

Estruturas de dados. 8.1 Declarao de uma estrutura em C. . . . . . . . . . . . . . . 8.2 Variveis do tipo estrutura. . . . . . . . . . . . . . . . . . . 8.2.1 Declarao de variveis. . . . . . . . . . . . . . . . 8.2.2 Utilizao das variveis. . . . . . . . . . . . . . . . 8.3 Vectores de estruturas. . . . . . . . . . . . . . . . . . . . . 8.3.1 Declarao de vectores. . . . . . . . . . . . . . . . 8.3.2 Operao de vectores. . . . . . . . . . . . . . . . . 8.4 Apontadores para estruturas. . . . . . . . . . . . . . . . . . 8.4.1 Apontadores - declarao e utilizao. . . . . . . . . 8.4.2 Atribuio dinmica de memria para uma estrutura. 8.4.3 Operao dos contedos apontados. . . . . . . . . . 8.5 Denir novos tipos. . . . . . . . . . . . . . . . . . . . . . . 8.6 Exerccios. . . . . . . . . . . . . . . . . . . . . . . . . . .

Ficheiros. 9.1 Ficheiros de texto. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.1.1 Abrir um cheiro de texto. . . . . . . . . . . . . . . . . . . . 9.1.2 Escrever para um cheiro de texto. . . . . . . . . . . . . . . . 9.1.3 Ler de um cheiro de texto. . . . . . . . . . . . . . . . . . . 9.1.4 Fechar um cheiro de texto. . . . . . . . . . . . . . . . . . . 9.2 Ficheiros binrios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.2.1 Abrir um cheiro de binrio. . . . . . . . . . . . . . . . . . . 9.2.2 Escrever para um cheiro binrio. . . . . . . . . . . . . . . . 9.2.3 Ler de um cheiro binrio. . . . . . . . . . . . . . . . . . . . 9.2.4 Fechar um cheiro binrio. . . . . . . . . . . . . . . . . . . . 9.3 Orientao e navegao num cheiro. . . . . . . . . . . . . . . . . . 9.3.1 O cheiro foi aberto correctamente? . . . . . . . . . . . . . . 9.3.2 Como que eu sei que cheguei ao m do cheiro, quando estou a ler? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9.3.3 Estive a consultar o cheiro, mas agora queria realizar uma nova consulta... a partir do incio do cheiro!... . . . . . . . . 9.4 Exerccios. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Este pequeno apontamento serve para apresentar rapidamente as funcionalidades bsicas da linguagem C. No entanto, muito ca por cobrir, devendo o interessado procurar outras fontes para aprender esta linguagem poderosa. O meu livro preferido The C Programming Language de Brian Kernighan e Dennis Ritchie (edio da Prentice Hall). O manual do UNIX (comando man) um companheiro inseparvel durante a escrita de um programa, pelo que outra fonte que vivamente recomendo.

Captulo 1

Noes bsicas de sistemas informticos.


Durante a segunda metade do sculo XX, o papel dos sistemas informticos na sociedade teve um crescimento impressionante. Os computadores tm sido fundamentais no desenvolvimento cientco e tecnolgico (e.g. explorao espacial, projecto do Genoma Humano), mas tem tambm inuenciado a sociedade em geral (e.g. telecomunicaes, operaes bancrias, Internet). Um computador uma mquina electrnica com memria, capaz de realizar vrios clculos aritmticos e lgicos por segundo. Porm, para cada aplicao que se pretenda que o computador realize, necessrio instru-lo sobre as tarefas que dever realizar com os dados. A esta tarefa chama-se Programao. Um programa uma sequncia de instrues que o computador deve realizar de forma a processar os dados e obter os resultados correctamente.

1.1
1.1.1

A histria da programao de computadores.


A linguagem mquina.

O primeiro computador electrnico foi o ENIAC. Construdo nos EUA durante a II Guerra Mundial e concludo em 1946, tinha por nalidade calcular rapidamente as tabelas de tiro para peas de artilharia e bombardeamentos. Era uma mquina enorme construda por 18000 vlvulas e 1500 rels, ocupando vrias salas. A sua abilidade era reduzida, dado que as vlvulas fundiam facilmente, devida potncia irradiada por estes componentes. Os programas eram inseridos atravs de um leitor de cartes perfurados (da IBM), sendo escritos directamente em cdigo-mquina (utilizando unicamente os dois nicos smbolos binrios zero e um). Adicionalmente, o ENIAC no era capaz de armazenar os programas em memria, pelo que era necessrio congurar um conjunto de interruptores e ligaes por cabos (trabalho realizado por seis tcnicas) de acordo com o programa a ser executado. No entanto era capaz de calcular uma trajectria de 60 segundos em apenas 30 segundos, em oposio s 20 horas tomadas por um tcnico-matemtico com uma calculadora de secretria. A linguagem mquina, sendo a nica que os computadores entendem, oferece grandes diculdades aos programadores: longo tempo e grandes custos de aprendizagem; 4

mquinas diferentes entendem linguagens-mquina diferentes; muito tempo despendido para escrever um programa; depuramento e correco de programas simplesmente infernal. Desta forma, fcil imaginar que a quantidade de programadores em todo o mundo era extremamente reduzida, o que implicava um reduzido nmero de aplicao de computadores.

1.1.2

A linguagem assembly.

Nos nais da dcada de 1950 e durante a dcada de 1960, ocorreu uma procura macia de poder de clculo devido aos seguinte factores: explorao espacial (fomentado pela Guerra Fria); desenvolvimento de armamento nuclear (tambm fomentado pela Guerra Fria); gesto das grandes corporaes (IBM, General Motors, etc.). A aplicao em mquinas de clculo do recm inventado transstor permitiu a construo de computadores mais veis (devido muito menor irradiao de calor), compactas e rpidas. Porm, o modelo de programao em linguagem-mquina, em que os progamas eram picotados em cartes perfurados no podia dar resposta s crescentes solicitaes do mercado. Os engenheiros pensaram ento numa linguagem de programao rudimentar, em que o nvel de programao estaria muito prximo da linguagem-mquina, mas cuja escrita e leitura por parte de humanos fosse razoavelmente simples. Surgiu ento a linguagem assembly. O programa seria ento escrito pelos programadores em linguagem assembly, sendo por m traduzido para linguagem mquina por um assembler, que recorreria a uma tabela de traduo.

1.1.3

As linguagens de alto nvel.

O assembly permitiu aumentar o nmero de programadores e o desenvolvimento de aplicaes para computadores. No entanto, no conseguia resolver satisfatoriamente todos os problemas de construo de aplicaes: embora facilitado, o depuramento de programas ainda era complicado; era difcil "pegar" num programa escrito por outra pessoa; o programador tinha que ter um bom conhecimento da arquitectura do computador. Em 1957 surgiu a primeira linguagem de alto-nvel: o Fortran. A partir da, surgiram outras linguagens de alto-nvel (e.g. ALGOL, BASIC, COBOL, FORTRAN, C), que ofereciam aos programadores a possibilidade de escreverem programas em linguagens prximas do ingls. Desta forma: a aprendizagem de uma linguagem seria mais rpida; o depuramento de programas era muito mais fcil; 5

o desenvolvimento de aplicaes poderia ser feito em equipas; as aplicaes poderiam ser mais complexas. Dado que o nvel de programao se situa muito acima da linguagem-mquina, a aplicao de simples tradutores como um assembler j no seria possvel. Surgiram ento os compiladores, aplicaes capazes de procurar erros de sintaxe e concepo nos textos dos programas e transformar as instrues em linguagem quase-natural para linguagem mquina. Uma nica instruo como PRINT "Ol, tudo bem?" em BASIC (ordenando o computador para imprimir uma frase no ecr), seria traduzida em algumas dezenas de instrues em cdigo mquina.

1.2

Os sistemas operativos.

Um computador constitudo por um conjunto de dispositivos electrnicos (placa grca, impressora, teclado, disco, etc.). De computador para computador, normal encontrarmos placas grcas diferentes, discos de diferentes capacidades ou fabricantes, pelo que seria muito difcil a um programador construir aplicaes (por exemplo, um processador de texto) para uma mquina especca, e ter que rescrever o programa s para que ele funcionasse num outro computador com uma placa grca diferente. Surgiu ento a necessidade de um sistema operativo, que oferecesse um servio de acesso uniforme aos dispositivos fsicos para as aplicaes. Com a existncia de um sistema operativo, uma aplicao como um editor de texto s precisa de saber ordenar ao sistema operativo que quer que um dado documento seja impresso: caber ao sistema operativo a funo de enviar para a impressora todos os dados necessrios para a impresso (ver gura 1.1).

Figura 1.1: Camadas Aplicao / Sistema Operativo / Hardware. O sistema operativo gere todas as actividades de um computador: fornece o acesso aos dispositivos; realiza o escalonamento das aplicaes; assegura o correcto funcionamento das aplicaes. O sistema operativo depende da arquitectura do computador, existindo para cada arquitectura pelo menos um sistema operativo. Na tabela 1.1 so apresentados alguns sistemas operativos para vrias arquitecturas: 6

Tabela 1.1: Arquitecturas e Sistemas Operativos. Arquitecturas Sistemas operativos Intel x86 Windows UNIX (Linux, Free BSD, Solaris, etc) BeOS PowerPC (Mac) MacOS ver 7, 8, 9 MacOS X (UNIX) HP HP-UX (UNIX) SGI (Silicon Graphics) IRIX (UNIX) SUN Solaris (UNIX)

1.3

Compiladores.

Tal como referido anteriormente, os compiladores transformam os textos dos programas (em linguagem de alto-nvel) em cdigo-mquina. Como o cdigo-mquina produzido para utilizar os recursos oferecidos pelo sistema operativo, facilmente se depreende que para cada sistema operativo dever existir um compilador. Assumindo que se escreveu um programa em linguagem C. Se esse programa for compilado para Windows, o cdigo-mquina gerado no ser inteligvel para o sistema operativo Linux, nem para o MacOS. Para o programa ser executvel em vrios sistemas operativos, pois ento necessrio compil-lo para cada um dos sistemas. Num futuro captulo, ser explicado o processo de compilao de um programa.

Captulo 2

Estrutura de um programa em C.
2.1 Directivas de pr-compilao.

Nesta primeira fase, necessrio indicar ao compilador quais as bibliotecas de funes que devem ser includas aquando da compilao, e denir os nomes e valores de constantes que sero utilizadas durante a escrita do programa. Um exemplo possvel para este bloco seria o seguinte: #include <stdio.h> #include <math.h> #define PI 3.14159265 As duas primeiras linhas indicam ao compilador que o programa utiliza funes que se encontram denidas nos cheiros stdio.h (standard input/output) e math.h. Funes tipicamente utilizadas so: stdio.h - printf() e scanf() para sada e entrada de dados; math.h - sin(), sqrt() e outras operaes matemticas. A terceira linha de cdigo atribui ao nome PI o valor 3.14159265. Todas as referncias PI ao longo do texto do programa sero substitudas por 3.14159265 antes da compilao.

2.2

Declarao de variveis globais.

Uma varivel que seja acessvel pelo mesmo nome em qualquer funo do programa chamada global. A declarao de uma varivel global feita a seguir ao bloco de directivas de pr-compilao. Uma varivel declarada indicando o tipo de valores que poder conter seguido do identicador (nome) da varivel. Atendendo ao seguinte exemplo de declarao de variveis:

int contador = 0; float cateto1, cateto2, hipotenusa; A primeira linha declara a varivel contador para conter nmeros inteiros e inicializa-a com o valor 0. Na segunda linha, so declaradas as variveis cateto1, cateto2 e hipotenusa, para conter nmeros com parte fraccionria.

2.3

As funes.

No ltimo bloco escreve-se o cdigo das funes (aquilo que realmente faz mexer o programa). As funes so declaradas atravs do tipo do valor retornado, o identicador da funo e a lista dos argumentos que a funo recebe. No seguinte exemplo, teremos uma funo que calcula o comprimento da hipotenusa de um tringulo rectngulo, recebendo como argumentos os comprimentos dos catetos: float calculahipotenusa (float cat1, float cat2) A funo chamada calculahipotenusa() devolve um resultado do tipo oat ( esquerda do nome da funo), aceitando como argumentos dois valores do tipo oat, que sero identicados dentro da funo pelos nomes cat1 e cat2. A sequncia de instrues que a funo deve realizar encapsulada entre chavetas. Em C, as chavetas so utilizadas para agrupar sequncias de instrues. Dentro do grupo de instrues, existe um primeiro bloco em que so declaradas as variveis locais funo e, nalmente, a sequncia de instrues. Continuando o exemplo, o cdigo da funo poderia ser o seguinte: { float hip; /* Declarao da varivel local hip */ cat1 = cat1 * cat1; /* Eleva os catetos ao quadrado */ cat2 = cat2 * cat2; hip = cat1 + cat2; /* Soma o quadrado dos catetos */ hip = sqtr(hip); /* e determina a raiz quadrada */ return(hip); /* Retorna o valor da variavel hip */ }

2.4

A funo main().

O programa, depois de compilado, comea a executar as instrues contidas numa funo especial: a funo main(). Esta funo deve conter o algoritmo principal, e chamar as funes necessrias execuo do algoritmo. Tendo em conta os exemplos anteriores, poderamos escrever a seguinte funo main(): 9

main() { float c1, c2, hipotn; /* Declara as variveis locais */ /* Escreve no ecr a frase entre aspas */ printf("Clculo de hipotenusa...\n"); /* O utilizador introduz os comprimentos dos catetos */ printf("Introduza o comprimento de um dos catetos: "); scanf("%f", &c1); printf("Introduza o comprimento do outro cateto: "); scanf("%f", &c2); /* A hipotenusa calculada, chamando a */ /* funo calculahipotenusa() */ hipotn = calculahipotenusa(c1, c2); printf("O comprimento da hipotenusa: %f\n", hipotn); }

2.5

Exerccios.

1. Dados os valores de duas resistncias, pretende-se obter os valores das resistncias equivalentes quando associadas em srie e em paralelo. Projecte o algoritmo de um programa capaz de realizar esta tarefa.

10

Captulo 3

Estruturas de deciso e ciclos.


3.1 Estruturas de deciso.

As estruturas de deciso so teis sempre que se tem que optar por um conjunto de operaes, dependendo de uma condio. A execuo do programa segue sempre em frente (no confundir com os ciclos).

3.1.1

if - ... - else - ...

Quantas vezes no somos confrontados com situaes em que temos que tomar uma deciso em funo de um conjunto de condies? Um caso que se aplica todos os dias (excepto quando estamos de cama, doentes) quando temos que atravessar uma estrada. Mentalmente, utilizamos o seguinte algoritmo: SE (no passam carros nos prximos instantes) ENTO Atravesso a rua SENO Sigo at aos semforos. A linguagem C, como foi criada por americanos, tem implementada esta estrutura de deciso, mas em ingls... Para facilitar a vida ao programador, o ENTO omitido (quando se avalia algo, de esperar que alguma aco possa ser despoletada). O SENO e aces subsequentes so opcionais (nem sempre temos que fazer qualquer coisa, caso o resultado da avaliao no nos interesse). O resultado este: if ( condio lgica ) { aces a tomar } else { aces alternativas a tomar } No seguinte exemplo, caso o saldo de um carto de telemvel seja inferior ao valor de uma chamada, dever ser emitida uma mensagem a informar que a chamada no se pode efectuar. Obviamente, se o saldo for maior, nada dever ocorrer.

11

if (saldo < compra) { printf("O saldo insuficiente para realizar a compra.\n"); printf("Por favor, efectue um carregamento do seu carto.\n"); } No seguinte caso, avaliada a relao maior-igual-menor entre dois nmeros: if (a > b) printf("%d maior que %d.\n", a, b); else if (a < b) printf("%d menor que %d.\n", a, b); else printf("So iguais.\n");

3.1.2

switch... case...

Quando o leque de aces a realizar depende do valor de uma varivel, podemos utilizar a instruo switch(). Atendendo ao seguinte exemplo: printf("Qual a operao que pretende efectuar? "); operador = getch(); switch (operador) { case +: resultado = a + b; break; case -: resultado = a - b; break; case *: resultado = a * b; break; case /: resultado = a / b; break; default: printf("Operao no permitida!\n"); break; } Mediante o carcter teclado pelo utilizador, o programa ir realizar a operao pretendida. Para cada caso previsto, indicada a sequncia de instrues a realizar. A palavra break termina a sequncia de instrues para cada opo. A opo default realizada sempre que nenhuma das condies anteriores no tenha sido satisfeita.

3.2

Ciclos.

As ciclos decorrem da necessidade de repetir a mesma sequncia de aces at que determinada condio seja alcanada. 12

3.2.1

Ciclos for().

Os ciclos for() so utilizados quando as operaes de inicializao e incremento so simples, normalmente utilizando uma varivel como contador do ciclo. O mtodo de declarao de um ciclo for() o seguinte: for(inicializao; condio; operao no fim de cada ciclo) A inicializao uma operao realizada antes de se iniciar a actividade do ciclo. O ciclo s executado enquanto o valor da condio for verdade. No nal de cada ciclo, executada a instruo que se encontra no terceiro argumento. O seguinte exemplo: soma = 0; for(contador = 1; contador < 5; contador++) { printf("Contador: %d\n", contador); soma += contador; } printf("Somatrio: %d\n", soma); produziria a sada: Contador: 1 Contador: 2 Contador: 3 Contador: 4 Somatrio: 10

3.2.2

Ciclos while().

Os ciclos while() so realizados enquanto uma determinada condio vlida. Se a condio partida for invlida, o ciclo no chega sequer a ser executado (o nmero mnimo de execues do ciclo ZERO). total = 0; while(total < 50000) { scanf("%d", &custo); total += custo; } O exemplo acima, permite introduzir custos enquanto o total de custos menor do que 50000. Note que este exemplo seria mais difcil de implementar com um ciclo for(), j que a condio de incremento no to simples!

3.2.3

Ciclos do-...-while().

Os ciclos do ... while() asseguram que o conjunto de instrues dentro do ciclo executado pelo menos UMA vez, isto porque a condio de execuo do ciclo avaliada apenas no m.

13

do { printf("Insira um nmero entre 0 e 20: "); scanf("%d", &numero); } while ( (numero < 0) && (numero > 20) );

3.3

Exerccios.

1. Dados dois valores, pretende-se saber se o primeiro maior, igual ou menor do que o segundo. Construa uma hiptese possvel de resoluo deste problema. 2. Escreva um algoritmo que permita calcular o factorial de um nmero inteiro (n!). Tenha em ateno de que no existem factoriais de nmeros negativos! Por denio, 0! igual a 1 (um). 3. Num jogo, introduzido um nmero inteiro que dever ser adivinhado pelo jogador, atravs de palpites. Para cada palpite, dever ser indicado ao jogador se o nmero a adivinhar maior ou menor do que o palpite. Quando o jogador nalmente adivinha o valor, dever ser indicado o nmero de palpites realizados.

14

Captulo 4

Funes.
Uma funo um conjunto de instrues, capaz de realizar uma determinada tarefa. A grande vantagem de escrever funes num programa em C, podermos escrever uma nica vez o conjunto de instrues (funo), e cham-la vrias vezes durante a execuo do programa. As funes podem receber valores e realizar processamento sobre esses valores, retornando o resultado desse processamento.

4.1
4.1.1

As partes de uma funo.


Cabealho ou Prottipo.

Uma funo declarada no seu cabealho. O cabealho de uma funo contm os seguintes elementos: o tipo de valor que ser retornado pela funo (tipo do resultado); o nome da funo; uma lista de parmetros entre parntesis, que so recebidos pela funo.

4.1.2

Corpo de uma funo.

Aps o cabealho da funo, dever vir o corpo da funo. O corpo de uma funo o conjunto de instrues que a funo dever realizar, delimitado por chavetas.

4.2

Funes sem parmetros.

As funes sem parmetros tm por funo realizar uma tarefa, independentemente de quaisquer dados. A seguinte funo escreve um menu de seleco no ecr. Imprimir estas quatro linhas de texto no requer a recepo de quaisquer valores. void mensagem () { printf("\n\nEscolha a opo:\n");

15

printf("1 - Inserir\n"); printf("2 - Remover\n"); printf("3 - Sair\n\n"); }

4.3

Funes com parmetros.

Grande parte das funes processam dados que lhes so passados como parmetros. Uma funo que calcule o comprimento de uma hipotenusa, ter que necessariamente receber os valores dos comprimentos dos catetos. H duas formas de passar parmetros: por valor; por referncia.

4.3.1

Passagem de parmetros por valor.

Neste caso, a funo recebe cpias dos valores que foram fornecidos aquando da chamada da funo. Quaisquer alteraes dos valores das cpias no afectaro os valores originais. Suponha o seguinte exemplo: #include <math.h> (...) float hipotenusa (float cateto1, float cateto2) { float hipotenusa; cateto1 = cateto1 * cateto1; cateto2 = cateto2 * cateto2; hipotenusa = cateto1 + cateto2; hipotenusa = sqrt(hipotenusa); return (hipotenusa); } (...) main () { float cat1 = 3.00; float cat2 = 4.00; float hip; hip = hipotenusa(cat1, cat2); (...) } Neste exemplo, as variaveis cateto1 e cateto2 da funo hipotenusa() recebem cpias dos valores das variveis cat1 e cat2 e da funo main(). As operaes realizadas nas

16

variaveis cateto1 e cateto2 (dentro da funo hipotenusa) no afectam os valores das variveis cat1 e cat2.

4.3.2

Passagem de parmetros por referncia.

Neste caso, a funo recebe a localizao em memria das variveis na chamada. Conhecendo a localizao das variveis possvel altera os seus valores. Suponha o seguinte exemplo: float troca (float *variavel1, float *variavel2) { float auxiliar; auxiliar = *variavel1; *variavel1 = *variavel2; *variavel2 = auxiliar; } (...) main () { float a = 3.00; float b = 4.00; troca(&a, &b); (...) } Repare que na chamada da funo troca() na funo main(), so passados os endereos das variveis a e b, na forma &a e &b. No cabealho da funo troca(), as variaveis variavel1 e variavel2 so apontadores (identicados pelo asterisco que os prexa na declarao) para valores do tipo oat. Um apontador uma varivel que guarda um endereo de memria. Nas linhas de instruo, o asterisco (*) indica que queremos aceder ao contedo do endereo apontado: variavel1 indica o endereo; variavel1 indica o contedo no endereo. Desta forma, a funo troca() realiza as seguintes aces: 1. a varivel auxiliar recebe o contedo do endereo apontado pela variavel1; 2. o contedo do endereo apontado pela variavel2 copiado para o contedo do endereo apontado pela variavel1; 3. o valor da varivel auxiliar copiado para o contedo do endereo apontado pela variavel2.

17

Captulo 5

Vectores.
5.1 Operaes com vectores.

Muitas vezes temos necessidade de operar com vrios elementos que representam a mesma grandeza, e que se encontram relacionados: a posio de uma partcula ao longo do tempo, os valores de resistncias elctricas num circuito... Tomemos por um circuito elctrico que contm 10 resistncias. necessrio escrever um programa que efectue uma srie de clculos utilizando os valores das resistncias. Os valores das resistncias devero ser inseridos pelo utilizador. Logo partida, confrontamo-nos com a necessidade de declarar 10 variveis, uma para cada resistncia. A tarefa ainda se complica mais quando tivermos que repetir 10 vezes as instrues de insero dos valores das resistncias. A utilizao de vectores permite facilitar (e bastante) a escrita de programas que utilizem grandes quantidades de dados do mesmo tipo.

5.1.1

Declarar um vector.

A declarao de um vector semelhante de uma varivel. No entanto, teremos que indicar (entre parntesis rectos) a dimenso do vector. Entenda-se por dimenso do vector, o nmero de valores que o vector suporta. main() { float resistencias[10]; (...) } No exemplo anterior, denido um vector chamado resistencia, com capacidade para dez valores do tipo oat.

5.1.2

Aceder aos elementos do vector.

A forma de aceder aos elementos de um vector semelhante forma de aceder ao contedo de uma varivel. No entanto, ser necessrio indicar qual o ndice do elemento ao qual se pretende aceder. Considere um vector como uma rua, e o ndice como o nmero de uma casa nessa rua. 18

O primeiro elemento do vector encontra-se no ndice zero. Desta forma, o ltimo elemento encontra-se no ndice dimenso-1, em que dimenso dimenso do vector. O seguinte exemplo demonstra alguns exemplos de utilizao dos vectores. main() { float resist[10]; /* Insere 6 valores de resistncias para as */ /* posies de 0 a 5. */ for(i=0; i<6; i++) { printf("Insira o valor da resistncia R%d: ", i); scanf("%f", &resist[i]); } resist[7] = (resist[0] + resist[1]) * 0.63; (...) }

19

Captulo 6

Apontadores.
6.1 Aceder aos endereos de memria onde se encontram as variveis.

Em C, possvel determinar o endereo de memria em que uma varivel armazena os seus valores, atravs dos apontadores. Consideremos, por exemplo, a seguinte denio de uma vriavel: int contador = 4; O identicador da varivel - a palavra contador - aponta implicitamente para uma posio em memria, onde se encontra armazenado o valor 4. Endereo na memria 0x1F22E Contedo 4 Identicao da varivel contador

Quando utilizamos o identicador da varivel, acedemos ao seu contedo. Utilizando a seguinte expresso, printf("O valor da variavel :%d.\n", contador); obteramos o resultado O valor da variavel : 4. Caso seja necessrio aceder ao endereo de memria onde se guarda o valor da varivel, utiliza-se o operador &: printf("O endereo da variavel : %p.\n", &contador); que resultaria na seguinte sada: O endereo da variavel : 1F22E.

6.2

Variveis apontadores.

Por vezes, necessrio manipular directamente os endereos de memria.Uma varivel pode ser denida para conter endereos de memria da seguinte forma: 20

int *apontador; O operador * indica que a variavel apontador um apontador para uma posio de memria onde se pretende armazenar - neste caso - um valor inteiro. Supondo o seguinte excerto de cdigo-fonte: int valor = 7; int *apontador; /* A variavel apontador passa a apontar para /* a posio de memria da varivel valor */ apontador = &valor; printf("Endereo de valor: %p,\n", apontador); printf("e actualmente contm o inteiro %d.\n", *apontador); uma possvel sada seria a seguinte: Endereo de valor: 10FF2, e actualmente contm o inteiro 7. Note que a prpria varivel apontador encontra-se num dado endereo de memria. A tabela 6.1 resume os operadores de acesso a posies de memria: Tabela 6.1: Signicados na notao de apontadores. Signicado Indica o endereo onde o contedo da varivel apontador se encontra armazenado em memria. Indica um determinado endereo em memria onde supostamente existe algum valor. Indica o valor existente na posio de memria apontada pela variavel apontador.

Expresso &apontador apontador *apontador

No seguinte caso, pretende-se que uma funo altere / actualize os valores das variveis que so passadas como argumentos. Suponha que num programa se pretende trocar os valores de duas variveis, chamando a funo troca. troca(variavel1, variavel2); Esta chamada da funo forneceria apenas os valores das variveis, sendo impossvel funo actualizar os contedos das variaveis, dado que a funo desconhece os endereos onde os valores se encontram. A funo tem que conhecer os endereos onde as variveis armazenam os seus valores. Isso conseguido utilizando a seguinte chamada: troca(&variavel1, &variavel2); Desta forma, a funo recebe no os valores das variveis, mas sim os seus endereos. O cdigo-fonte da funo poderia ser o seguinte: troca(int *v1, int *v2) { int aux; 21

/* aux passa a ter o valor apontado por v1 */ aux = *v1; /* aux passa a ter o valor apontado por v1 */ *v1 = *v2; /* aux passa a ter o valor apontado por v1 */ *v2 = aux; }

6.3

Exerccios.

1. Escreva um programa que dena uma varivel para conter valores inteiros, e um apontador para inteiros. Ao apontador dever ser atribudo o endereo da varivel. Para a varivel imprima as sua posio em memria e o seu valor. Para o apontador, imprima a sua posio em memria, o seu valor e o valor na posio de memria apontada. 2. Escreva uma funo que retorne um apontador para a 1a ocorrncia de um carcter numa string ou o valor zero se o carcter no existir na string. A funo deve ter como argumentos a string e o carcter a procurar.

22

Captulo 7

Apontadores e memria dinmica.


7.1 A necessidade de memria dinmica.

Em vrias aplicaes, existe a necessidade de manipular estruturas de dados cuja dimenso no inicialmente conhecida. Suponha o caso em que se pretende conceber um programa que execute vrias estatsticas sobre as idades dos alunos de uma turma. O nmero de alunos de uma turma altamente varivel, o que levanta diculdades utilizao de vectores. Como se deveria dimensionar o vector? Uma dimenso razovel poderia ser insuciente para certas turmas. Um vector muito grande estaria a desperdiar memria. Este factor crtico em aplicaes que operam grandes quantidades de dados relativamente s capacidades da mquina. A utilizao dinmica de memria permite adaptar as necessidades de memria ao problema concreto.

7.2

Manuseamento dinmico de memria em C.

O C no oferece de raz o suporte para operaes de memria dinmica, sendo necessrio incluir a biblioteca standard do C: stdlib.h. Nesta biblioteca, existem duas funes que oferecem as funcionalidades bsicas para utilizao dinmica de memria: malloc() e free().

7.2.1

Reserva dinmica de memria.

A funo malloc() (memory allocation - trad. afectao de memria) reserva uma poro de memria, retornando um apontador genrico (tipo void *) para o inicio da poro reservada, ou o valor NULL no caso da reserva ser impossvel. A sua utilizao representada no exemplo seguinte:

23

float *v; int n; printf("Quantos valores? "); scanf("%d", n); v = (float *) malloc(n * sizeof(float) ); Neste exemplo, reservada uma poro de memria capaz de guardar n nmeros reais (oat), cando o apontador v a apontar para o endereo inicial dessa poro de memria. O cast da funo malloc() - (oat *) - assegura que o apontador retornado para o tipo especicado na declarao do apontador. Certos compiladores requerem obrigatoriamente o cast. Conselho: no altere o valor do apontador que recebeu o retorno da funo malloc(). Desta forma poder sempre saber onde comea o bloco de memria dinmica reservado. Utilize apontadores auxiliares para realizar operaes (leitura, escrita) dentro do bloco de memria.

7.2.2

Libertar memria dinmica.

Outra das vantagens da utilizao dinmica de memria a possibilidade de libertar memria medida que deixa de ser precisa. A memria libertada utilizando a funo free(). Supondo o exemplo da seco anterior, a poro de memria atribuda seria libertada da seguinte forma: free(v);

7.2.3

Ajuste de memria dinmica.

possvel alterar o tamanho do bloco de memria reservado, utilizando a funo realloc(). Esta funo salvaguarda os valores anteriormente em memria, at ao limite do novo tamanho (especialmente importante quando se reduz o tamanho do bloco de memria). O seguinte exemplo ilustra a forma de utilizao desta funo. int *a; a = (int *) malloc( 10 * sizeof(int) ); (...) a = (int *) realloc( a, 23 * sizeof(int) ); (...) free(a); A chamada da funo realloc() recebe como argumentos um apontador para o bloco de memria previamente reservado com uma funo malloc() de forma a saber qual a poro de memria a ser redimensionada, e o novo tamanho absoluto para o bloco de memria.

24

7.3

Exerccios.

1. Leia uma sequncia de 10 nmeros do teclado usando apontadores em lugar de ndices. Usando a mesma tcnica (apontadores) determine o maior e o menor valor. Reserve memria dinmica em vez de declarar o vector de uma forma esttica. 2. Ler uma sequncia de nmeros do teclado (sequncia terminada em zero).Escreva no ecr os nmeros que esto acima da mdia. Utilize um vector dinmico para armazenar os nmeros.

25

Captulo 8

Estruturas de dados.
Uma estrutura uma coleco de uma ou mais variveis, possivelmente de diferentes tipos, agrupadas sob um nico nome para facilitar o seu manuseamento. As estruturas permitem organizar dados complicados, porque permitem tratar um grupo de variveis relacionadas como uma unidade, em vez de entidades separadas. Como exemplos de estruturas teremos: um aluno identicado pelo seu nmero e nome; um ponto identicado pelas suas coordenadas cartesianas (x, y, z)... Os componentes de uma estrutura (nmero e nome no caso do aluno) so chamados campos.

8.1

Declarao de uma estrutura em C.

A declarao de uma estrutura em C iniciada pela palavra struct, seguida por uma lista de declaraes entre chavetas. Uma possvel declarao de uma estrutura para suportar informao relativa a um ponto seria: struct ponto { float x; float y; }; As estruturas declaradas podem ser utilizadas como tipos de campos de outras estruturas. Se pretendermos criar uma estrutura que dena um rectngulo a partir de dois vrtices opostos, poderemos escrever: struct rectangulo { struct ponto p1; struct ponto p2; };

26

8.2
8.2.1

Variveis do tipo estrutura.


Declarao de variveis.

Aps a denio da estrutura, esta pode ser utilizada para declarar vriaveis. A declarao das variveis no muito diferente do usual. Supondo que queremos declarar variveis - r1 e r2 - para conter as posies de duas partculas, podemos escrever o seguinte: struct ponto r1, r2 = {1.5, 3.6}; As variveis so declaradas, sendo r2 inicializada com os valores: x = 1.5; y = 3.6;

8.2.2

Utilizao das variveis.

O campo de uma determinada estrutura pode ser acedido utilizando o operador . (ponto). /* Atribui o valor 2.3 ao campo x da varivel r1. */ r1.x = 2.3; /* Atribui o valor guardado no campo y de r2 no campo y de r1. */ r1.y = r2.y; Para alm da atribuio individual a cada um dos campos, ainda possvel igualar dois registos rapidamente: r1 = r2; A expresso acima atribui a todos os campos de r1 os valores de todos os campos de r2, criando uma cpia efectiva de r2 em r1.

8.3

Vectores de estruturas.

O C permite a declarao de vectores de estruturas. A sua declarao e utilizao praticamente idntica aos vectores de tipo "simples".

8.3.1

Declarao de vectores.

A declarao de um vector para 10 elementos da estrutura ponto denida acima, teria a seguinte forma: struct ponto vp[10];

27

8.3.2

Operao de vectores.

Os campos dos diversos elementos de um vector so acedidos utilizando o operador . (ponto). vp[0].x = 2.3; vp[0].y = 5.2; vp[1].x = vp[0].x * 4; vp[2] = vp[0];

8.4

Apontadores para estruturas.

As estruturas, como agrupamento de variveis que so, utilizam pores de memria que podem ser apontadas pelos apontadores. Vectores de estruturas em memria dinmica podem igualmente ser criados, e operados com apontadores.

8.4.1

Apontadores - declarao e utilizao.

Um apontador para uma estrutura declarado da seguinte forma: struct ponto *ap;

8.4.2

Atribuio dinmica de memria para uma estrutura.

Utilizando o apontador denido acima, podemos reservar memria para 5 pontos escrevendo a seguinte instruo: ap = (struct ponto *) malloc( 5 * sizeof(struct ponto) ); O apontador ap ca a apontar para o incio de um bloco de memria suciente para armazenar 5 elementos com a estrutura ponto. A funo realloc() funciona de forma semelhante. A funo free() trivial.

8.4.3

Operao dos contedos apontados.

Os contedos apontados so acedidos utilizando o operador -> (hfen + maior que): /* Atribui o valor 2.3 ao campo x no registo apontado por ap */ ap->x = 2.3; /* Atribui o valor do campo y no registo apontado por ap *( /* ao campo y do registo seguinte */ (ap+1)->y = ap->y; Uma outra forma de aceder aos contedos apontados da seguinte forma: /* Equivalente a ap->x = 2.3; */ *ap.x = 2.3; /* Equivalente a (ap+1)->y = 4.33; */ *(ap+1).y = 4.33; 28

8.5

Denir novos tipos.

Em C, possvel denir novos nomes de tipos, utilizando o typedef. typedef struct ponto pontocart; (...) pontocart p1, p2; Aps a introduo typedef, o tipo struct ponto pode ser identicado simplesmente por pontocart.

8.6

Exerccios.

1. Um projctil pode ser caracterizado pela sua posio e velocidade. Estas duas grandezas so vectoriais, sendo compostas pelas componentes x e y. A partir da sua posio inicial r0 = (r0x, r0y) e da sua velocidade inicial v0 = (v0x, v0y) possvel determinar a sua posio-velocidade para qualquer instante a partir das seguintes equaes: x = x0 + v0x * t; y = y0 + v0y * t - 5 * t^2 vx = v0x; vy = v0y - 10 * t; Pretende-se desenvolver um programa que a partir das condies iniciais de lanamento de um projctil se determine a posio e velocidade para qualquer instante (o instante inserido pelo utilizador). Na fase nal de desenvolvimento, o programa dever aceitar a velocidade de lanamento na forma de mdulo e inclinao em relao horizontal. Sugesto: crie uma estrutura para conter a informao de um vector (cartesiano). Crie depois uma outra estrutura onde os dados do projctil (vectores posio e velocidade) recorram anterior estrutura. 2. Declare uma estrutura capaz de armazenar o nome, o nmero, o ano de entrada, o curso e quantidade de cadeiras feitas. Dena um vector de 100 estruturas. (a) Escreva uma funo para ler os valores para uma determinada estrutura do vector. (b) Para um determinado curso (a perguntar ao utilizador), o programa deve responder quantos alunos zeram 10 ou menos cadeiras em mais de cinco anos. (c) Visualize no monitor todos os cursos inseridos sem repeties. (d) O programa deve dizer qual o curso com melhor aproveitamento (curso com maior mdia de cadeiras feitas por aluno).

29

Captulo 9

Ficheiros.
At ao momento, temos trabalhado apenas com memria. Infelizmente, sempre que um programa terminado, os dados em memria so perdidos. Uma forma de eliminar este inconveniente, consiste em guardar os dados em memria secundria (disco). Os dados em disco so armazenados em cheiros, unidades lgicas que agrupam dados relacionados entre si.

9.1

Ficheiros de texto.

Tal como o nome indica, os cheiros de texto permitem armazenar informao na forma de texto.

9.1.1

Abrir um cheiro de texto.

Antes de se realizar qualquer operao de leitura/escrita num cheiro, necessrio abri-lo. Esta operao realizada utilizando a funo fopen(). FILE *fh; /* declarado um apontador para ficheiro. */ (...) /* aberto o ficheiro agenda.txt para leitura. */ fh = fopen("agenda.txt", "r"); O primeiro parmetro da funo fopen() uma string, contendo o nome de um cheiro. O segundo parmetro da funo fopen() uma string, que especica a forma como se pretende aceder ao cheiro, conforme a tabela 9.1.

9.1.2

Escrever para um cheiro de texto.

As funes de escrita para um cheiro de texto so bastante semelhantes s funes de escrita para o monitor. As diferenas situam-se nos nomes das funes (prexadas com a letra f) e a indicao do apontador para o cheiro para o qual se pretende escrever.

30

Modo de acesso Leitura Escrita

Escrita

Leitura / Escrita Leitura / Escrita Leitura / Escrita

Tabela 9.1: Modos de acesso a cheiros String Comentrio "r" A leitura pode ser em qualquer ponto do cheiro. A abertura do cheiro falha se o cheiro no existir. "w" A escrita pode ser em qualquer ponto do cheiro. Durante a abertura, se o cheiro j existir, apagado para criar um novo. "a" A escrita apenas pode ser no nal do cheiro. Durante a abertura, caso o cheiro no exista, criado um novo. "r+" A leitura pode ser em qualquer ponto do cheiro. A escrita pode ser em qualquer ponto do cheiro. "w+" A leitura pode ser em qualquer ponto do cheiro. A escrita pode ser em qualquer ponto do cheiro. "a+" A leitura pode ser em qualquer ponto do cheiro. A escrita apenas pode ser no nal do cheiro.

fputs("Esta frase vai aparecer no ficheiro!\n", fh); numero = 2; fprintf(fh, "Linha %d\n", numero);

9.1.3

Ler de um cheiro de texto.

Tal como nas funes de escrita, as funes de leitura so semelhantes s funes de entrada (geralmente do teclado). O prexo f caracterstico nestas funes, sendo necessrio identicar o cheiro de onde se pretende ler, identicado pelo apontador de cheiro. char string[50]; int a, b; (...) /* L dois inteiro de uma linha de texto do ficheiro. */ fscanf(fh, "%d %d", &a, &b); /* L para a variavel string 50 caracteres, no mximo. */ fgets(string, sizeof(string), fh);

9.1.4

Fechar um cheiro de texto.

Aps todas as operaes de leitura / escrita terem sido realizadas, dever-se- fechar o cheiro, com a funo fclose(). Esta operao assegura que todos os dados cam correctamente armazenados no cheiro. fclose(fh);

31

9.2

Ficheiros binrios.

Os cheiros binrios armazenam os dados tal e qual como eles se encontram na memria. Um int representado num cheiro binrio tal como guardado na memria (em formato mquina). Desta forma, espreitar para um cheiro binrio pode dar resultados ininteligveis para ns, humanos.

9.2.1

Abrir um cheiro de binrio.

A abertura de um cheiro binrio realizada recorrendo igualmente funo fopen(). No entanto, no modo de utilizao do cheiro dever ser adicionada a letra b para indicar que o cheiro binrio (nem todos os compiladores necessitam da incluso da letra b). FILE *fh; /* declarado um apontador para ficheiro. */ (...) /* aberto o ficheiro binrio temperaturas.dat para leitura. */ fh = fopen("temperaturas.dat", "rb");

9.2.2

Escrever para um cheiro binrio.

As operaes de escrita para um cheiro de binrio devero ser realizadas com a funo fwrite(). A funo fwrite() toma como argumentos: o endereo do incio do bloco de memria a copiar para o cheiro; o tamanho de cada elemento (registo / cha); o nmero de elementos (registos / chas) a escrever; o apontador para o cheiro para onde os dados devero ser escritos. typedef struct { char cidade[50]; short temperatura; } registo; (...) registo ficha; FILE *fh; fh = fopen("temperaturas.dat", "ab"); printf("Insira o nome da cidade: "); gets(ficha.cidade); printf("Insira a temperatura da cidade: "); scanf("%hd", &ficha.temperatura); fwrite(&ficha, sizeof(registo), 1, fh); 32

(...) A linha de cdigo que contm a funo fwrite() copia para o cheiro a poro de memria identicada pela varivel cha.

9.2.3

Ler de um cheiro binrio.

A leitura de um cheiro binrio realizada utilizando a funo fread(). A funo fread() toma como argumentos: o endereo do incio do bloco de memria para onde se deve copiar os contedos do cheiro; o tamanho de cada elemento (registo / cha); o nmero de elementos (registos / chas) a ler; o apontador para o cheiro de onde os dados devero ser lidos. typedef struct { char cidade[50]; short temp; } registo; (...) registo ficha; FILE *fh; fh = fopen("temperaturas.dat", "rb"); fread(&ficha, sizeof(registo), 1, fh); printf("Cidade %s - Temp: %hd o C.\n", ficha.cidade, ficha.temp); (...) A linha de cdigo que contm a funo fread() copia do cheiro para a varivel cha um registo composto por um nome de cidade e respectiva temperatura.

9.2.4

Fechar um cheiro binrio.

Aps todas as operaes de leitura / escrita terem sido realizadas, dever-se- fechar o cheiro, com a funo fclose(). Esta operao assegura que todos os dados cam correctamente armazenados no cheiro. fclose(fh);

9.3
9.3.1

Orientao e navegao num cheiro.


O cheiro foi aberto correctamente?

A operao de abertura de um cheiro pode falhar por vrias razes, tais como: 33

tentar abrir para leitura um cheiro inexistente; criar um cheiro num disco sem espao disponvel ou sem permisses de escrita (e.g. CD-ROM)... Desta forma, convm certicar de que no houve quaisquer problemas antes de se proceder a qualquer leitura ou escrita no cheiro. A funo fopen() retorna um apontador nulo - NULL - quando falha. A seguinte rotina testa a abertura do cheiro, e no caso de falha, aborta a execuo do programa. if ( fh = fopen("ficheiro", "w+") == NULL) { perror("fopen"); exit(0); } (...)

9.3.2

Como que eu sei que cheguei ao m do cheiro, quando estou a ler?

A funo fread() retorna o nmero de elementos efectivamente lidos do cheiro. Quando se chega ao m do cheiro, a funo fread() no consegue ler mais elementos. A seguinte rotina detecta o m do cheiro. if ( fh = fopen("ficheiro", "r") == NULL) { printf("ERRO: No foi possvel abrir o ficheiro!\n"); exit(0); } while( fread(&ficha, sizeof(registo), 1, fh) != 0 ) printf("Cidade %s - Temp %hd o C.\n", ficha.cidade, ficha.temp); O ciclo while() realizado enquanto o nmero de elementos lidos for diferente de zero.

9.3.3

Estive a consultar o cheiro, mas agora queria realizar uma nova consulta... a partir do incio do cheiro!...

Existe um cursor que aponta para o local no cheiro onde se dever realizar a prxima escrita / leitura. Quando se abre o cheiro nos modos "r" e w, este cursor aponta para o incio do cheiro; quando o cheiro aberto em modo a, o cursor colocado no nal do cheiro. Aps uma operao de leitura ou escrita, este cursor avana. Quando se realizam leituras posteriores, so lidos os elementos seguintes. Esta funcionalidade facilita a leitura sequencial de vrios elementos, mas no permite voltar atrs para ler elementos anteriores. Existe a funo rewind() que simplesmente coloca o cursor a apontar para o incio do cheiro. Aceita como nico argumento o apontador para o cheiro que se pretende "rebobinar". rewind(fh);

34

Uma funo mais verstil a fseek() que capaz de colocar o cursor em qualquer ponto do cheiro. A funo fseek() aceita como parmetros: o apontador para o cheiro; o "salto" (em nmero de bytes) a dar no cheiro, podendo ser um nmero o positivo (salto para a frente); o negativo (salto para trs); a posio a partir da qual se pretende dar o "salto" o SEEK_SET se for a partir do incio do cheiro; o SEEK_CUR se for a partir da posio actual do cursor; o SEEK_END se for a partir do nal do cheiro. /* Tem o mesmo efeito de rewind(fh); */ fseek(fh, 0, SEEK_SET); (...) /* Coloca o cursor no final do ficheiro. */ fseek(fh, 0, SEEK_END);

9.4

Exerccios.
Deve escrever trs frases (inseridas pelo utilizador) num cheiro de texto. Dever ler as frases escritas no cheiro referido na alnea anterior, e apresentlas no ecr.

1. Escreva um programa que realize as seguintes operaes:

2. Pretende-se armazenar as temperaturas de vrias cidades de um determinado dia num cheiro binrio. O nome do cheiro dever seguir o seguinte formato DDMMAAAA.dat, em que: DD o dia; MM o ms; AAAA o ano. 2. Cada registo dever conter o nome da cidade e a respectiva temperatura medida. (a) Escreva um programa que dever guardar os registos das temperaturas relativas a uma data inserida pelo utilizador, num cheiro binrio. (b) Escreva um segundo programa que dever apresentar as temperaturas medidas num determinado dia, e calcular a mdia das temperaturas.

35

Você também pode gostar