Você está na página 1de 126

Centro Universitrio de Maring - CESUMAR

Cursos de AUTOMAO INDUSTRIAL e ENGENHARIA DE CONTROLE E AUTOMAO

Disciplina de Informtica para Automao Prof. EE. Carlos Henrique Z. Pantaleo 2005

Informtica para Automao Linguagem de Programao

SUMRIO
1 Programao em C...........................................................................................................................5 2 Conceitos Bsicos da Programao C.............................................................................................7 2.1 Histrico de C......................................................................................................................7 2.2 Criando um Programa Executvel.......................................................................................8 2.3 A Estrutura Bsica de um Programa em C..........................................................................9 2.4 Variveis............................................................................................................................11 2.5 Tipos de Dados...................................................................................................................12 2.6 Constantes..........................................................................................................................14 2.7 Ponteiros.............................................................................................................................16 2.8 Exerccios...........................................................................................................................18 3 Entrada/Sada Console...................................................................................................................19 3.1 Printf()........................................................................................................................19 3.2 Cprintf().........................................................................23 3.3 Scanf()....................................................................................................................23 3.4 Getch(), Getche() e Getchar()....................................................................................24 3.5 Putch() ou Putchar()...........................................................................................................25 3.6 Exerccios...........................................................................................................................25 4 Operadores .....................................................................................................................................27 4.1 Operadores Aritmticos.....................................................................................................27 4.2 Operadores Relacionais......................................................................................................28 4.3 Operadores lgicos binrios...............................................................................................29 4.4 Operadores de Ponteiros....................................................................................................30 4.5 Operadores Incrementais e Decrementais..........................................................................31 4.6 Operadores de Atribuio..................................................................................................33 4.7 O Operador Lgico Ternrio..............................................................................................34 4.8 Precedncia........................................................................................................................35 4.9 Exerccios...........................................................................................................................35 5 Laos.................................................................................................................................................37 5.1 O Lao For.........................................................................................................................37 5.2 O Lao While.....................................................................................................................39 5.3 O Lao Do-While...............................................................................................................40 5.4 Break e Continue........................................................................................................41 5.5 Goto....................................................................................................................................42 5.6 Exerccios...........................................................................................................................42
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

6 Comandos para Tomada de Deciso.............................................................................................44 6.1 If.....................................................................................................................44 6.2 If-Else.........................................................................................................................45 6.3 Switch.........................................................................................................................46 6.4 Exerccios...................................................................................................................49 7 Funes ............................................................................................................................................50 7.1 Sintaxe................................................................................................................................50 7.2 Exemplos............................................................................................................................51 7.3 Prototipagem......................................................................................................................54 7.4 Classes de Armazenamento...............................................................................................55 7.4.1 Auto.....................................................................................................55 7.4.2 Extern......................................................................................................55 7.4.3 Static....................................................................................................................56 7.4.4 Variveis Estticas Externas...............................................................................57 7.4.5 Register................................................................................................................58 7.5 Exerccios...........................................................................................................................58 8 Diretivas do Pr-Processador.........................................................................................................60 8.1 Diretiva #define..................................................................................................................60 8.2 Macros................................................................................................................................61 8.3 Diretiva #undef..................................................................................................................63 8.4 Diretiva #include................................................................................................................63 8.5 Compilao Condicional....................................................................................................65 8.6 Operador defined................................................................................................................66 8.7 Diretiva #error....................................................................................................................66 8.8 Diretiva #pragma...............................................................................................................67 8.9 Exerccios...........................................................................................................................67 9 Matrizes...........................................................................................................................................68 9.1 Sintaxe de Matrizes............................................................................................................69 9.2 Inicializando Matrizes........................................................................................................70 9.3 Matrizes como Argumentos de Funes............................................................................73 9.4 Chamada Por Valor e Chamada Por Referncia................................................................75 9.5 Strings .......................................................................................................................78 9.5.1 Strings Constantes...........................................................................................79 9.5.2 String Variveis...................................................................................................79 9.5.3 Funes para Manipulao de Strings.................................................................81 9.6 Exerccios...........................................................................................................................83
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

10 Tipos Especiais de Dados.............................................................................................................84 10.1 Typedef............................................................................................................................84 10.2 Enumerados (Enum)........................................................................................................84 10.3 Estruturas (Struct)............................................................................................................86 10.4 Unies..............................................................................................................................91 10.5 Bitfields............................................................................................................................93 10.6 Exerccios.........................................................................................................................94 11 Ponteiros e a Alocao Dinmica de Memria...........................................................................95 11.1 Declarao de Ponteiros e o Acesso de Dados com Ponteiros.........................................95 11.2 Operaes com Ponteiros.................................................................................................96 11.3 Funes & Ponteiros........................................................................................................99 11.4 Ponteiros & Matrizes.....................................................................................................101 11.5 Ponteiros & Strings........................................................................................................103 11.6 Ponteiros para Ponteiros.................................................................................................105 11.7 Argumentos da Linha de Comando...............................................................................109 11.8 Ponteiros para Estruturas...............................................................................................110 11.9 Alocao Dinmica de Memria....................................................................................112 11.9.1 Malloc()...............................................................................................114 11.9.2 Calloc()................................................................................................115 11.9.3 Free()...............................................................................................................116 11.10 Exerccios.....................................................................................................................116 12 Manipulao de Arquivos em C................................................................................................118 12.1 Tipos de Arquivos..........................................................................................................118 12.2 Declarao, abertura e fechamento................................................................................118 12.3 Leitura e escrita de caracteres........................................................................................120 12.4 Fim de Arquivo (EOF)...................................................................................................120 12.5 Leitura e escrita de strings.............................................................................................121 12.6 Arquivos Padres..........................................................................................................122 12.7 Gravando um Arquivo de Forma Formatada.................................................................123 12.8 Leitura e escrita de valores binrios...............................................................................124 12.9 Exerccios.......................................................................................................................125

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

1 Programao em C
Atualmente, empregam-se cada vez mais sistemas computacionais na automatizao de processos industriais. Os sistemas computacionais empregados variam desde um simples circuito lgico digital, passando por uma circuito composto por um microprocessador ou um CLP, at sistemas complexos envolvendo um ou mais microcomputadores ou at estaes de trabalho. Um engenheiro que atua nesta rea deve conhecer os sistemas computacionais disponveis e ser capaz de selecionar o melhor equipamento para uma dada aplicao. Alm disto, este profissional deve conseguir instalar este sistema, configur-lo e acima de tudo program-lo para que este execute a tarefa de automatizao atendendo os requisitos industrias do sistema, como imunidade a falhas ou comportamento determinstico com restries temporais (sistemas tempo-real). Neste contexto, a programao destes sistemas se faz de suma importncia. Basicamente, a inteligncia dos sistemas automatizados implementada atravs de programas computacionais, comandando os componentes de hardware para executar a tarefa com o comportamento desejado.

Figura 1 - Comparao entre os diversos sistemas computacionais para aplicaes industriais.

Nas ltimas dcadas, o desenvolvimento em hardware permitiu que cada vez mais os processos industrias sejam automatizados e interligados atravs de sistemas computacionais. Entretanto, a evoluo em software no se deu em tamanha velocidade como a de hardware. Desta

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

forma, um dos grandes paradigmas tecnolgicos hoje o desenvolvimento de programas para a realizao de tarefas complexas e que exigem um alto grau de inteligncia. A maneira de se comunicar com um computador chama-se programa e a nica linguagem que o computador entende chama-se linguagem de mquina. Portanto todos os programas que se comunicam com a mquina devem estar em linguagem de mquina. Para permitir uma maior flexibilidade e portabilidade no desenvolvimento de software, foram implementados nos anos 50 os primeiros programas para a traduo de linguagens semelhantes humana (linguagens de "alto nvel") em linguagem de mquina. A forma como os programas so traduzidos para a linguagem de mquina classifica-se em duas categorias: Interpretadores: Um interpretador l a primeira instruo do programa, faz uma consistncia de sua sintaxe e, se no houver erro converte-a para a linguagem de mquina para finalmente execut-la. Segue, ento, para a prxima instruo, repetindo o processo at que a ltima instruo seja executada ou a consistncia aponte algum erro. So muito bons para a funo de depurao ("debugging") de programas, mas so mais lentos. Ex.: BASIC Interpretado, Java. Compiladores: Traduzem o programa inteiro em linguagem de mquina antes de serem executados. Se no houver erros, o compilador gera um programa em disco com o sufixo Este programa no pode ser executado at que sejam .OBJ com as instrues j traduzidas.

agregadas a ele rotinas em linguagem de mquina que lhe permitiro a sua execuo. Este trabalho feito por um programa chamado linkeditor que, alm de juntar as rotinas necessrias ao programa .OBJ, cria um produto final em disco com sufixo .EXE que pode ser executado diretamente do sistema operacional. Compiladores bem otimizados produzem cdigo de mquina quase to eficiente quanto aquele gerado por um programador que trabalhe direto em Assembly. Oferecem em geral menos facilidades de depurao que interpretadores, mas os programas so mais rpidos (na ordem de 100 vezes ou mais). Ex.: BASIC Compilado, FORTRAN, PASCAL, MDULA - 2, C, C++. Alm da velocidade, outras vantagens podem ser mencionadas: desnecessria a presena do interpretador ou do compilador para executar o programa j compilado e linkeditado; programas .EXE no podem ser alterados, o que protege o cdigo-fonte.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

Desta forma, os compiladores requerem o uso adicional de um editor de ligaes ("Linker"), que combina mdulos-objetos ("Traduzidos") separados entre si e converte os mdulos assim "linkados" no formato carregvel pelo sistema operacional (programa .EXE).

2 Conceitos Bsicos da Programao C


2.1 Histrico de C O compilador "C" vem se tornando o mais difundido em ambiente industrial. A linguagem "C" se originou das linguagens BCPL e B desenvolvidas em 1970. A primeira verso de "C" foi implementada para o sistema operacional UNIX pela Bell Laboratories, especificamente por Dennis M. Ritchie e Ken Thompson no incio da dcada de 70, e rodava em um DEC PDP11 (Digital Equipment Corporation). A linguagem C foi utilizada para portar o UNIX para outros computadores. A linguagem "C" possui uma caracterstica dual: considerada linguagem estruturada de alto-nvel; Assembly de alto-nvel, que permite escrever programas muito prximos linguagem de mquina, sendo usada para desenvolver muitas aplicaes como compiladores, interpretadores, processadores de texto e mesmo sistemas operacionais. Ex: UNIX, MSDOS, TPW. A linguagem de programao C tornou-se rapidamente uma das mais importantes e populares, principalmente por ser muito poderosa, porttil, pela padronizao dos compiladores existentes (atravs da norma ANSI C) e flexvel. compactos e de execuo rpida. A linguagem C baseada em um ncleo pequeno de funes e estruturas bsicas, desta forma, todo programa desenvolvido a partir deste ncleo bsico. Isto implica na grande portabilidade de C, haja vista que basta a implementao deste ncleo bsico para um dado processador e automaticamente j estar disponvel um compilador C para este processador. Por esta razo, existem compiladores C para a grande parte dos sistemas computacionais atualmente disponveis. Devido tambm a este pequeno ncleo, um programador C capaz de desenvolver Os programas em C tendem a ser bastante

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

programas to eficientes, pequenos e velozes quanto os programas desenvolvidos em Assembly. Por isso, diz-se que C uma linguagem de alto nvel, porm, prxima da linguagem de mquina.

2.2 Criando um Programa Executvel Primeiro, escreva o seu programa (arquivo em modo ASCII), com o auxlio de um programa denominado de compilador, e grave o programa em disco dando a ele um nome como sufixo .C. O programa gerado chamado de cdigo fonte. Na seqncia, compile o fonte seguindo as instrues do seu compilador, o que criar um programa com o sufixo .OBJ em disco. O programa gerado chamado de objeto. Por fim, basta linkeditar o objeto seguindo as instrues do seu linkeditor o que criar um programa com sufixo .EXE em disco. O programa gerado chamado de executvel. A Figura 2 apresenta o processo de gerao de um programa em C.

Figura 2 - Ilustrao do processo de criao de um programa em C.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

2.3 A Estrutura Bsica de um Programa em C A forma geral de um programa em "C" a seguinte:


<diretivas do pr-processador> <declaraes globais>; main() { <declaraes locais>; <instrues>; } <outras funes> /* comentrios */

Vamos comear por um programa bem simples em C. escrever na tela a frase Bom Dia!!!!.
/* Programa : Bom Dia! */ #include <stdio.h> void main() { printf(Bom Dia!!!!); }

Voc pode escrever este programa O programa serve para

em um arquivo ASCII e salv-lo com um nome terminando em .C.

Na primeira linha, os smbolos /* e */ servem para delimitar um comentrio do programa. muito importante que os programas sejam comentados de forma organizada. Isto permite que outras pessoas possam facilmente entender o cdigo fonte. Os comentrios no so interpretados pelo Depois, compilador, servindo apenas para a documentao e esclarecimento do programador. segue-se com uma diretiva para o pr-processador #include <stdio.h>. Isto advm do fato de C ter um ncleo pequeno de funes bsicas. Ao escrever esta linha de cdigo, o pr-processador ir acrescentar ao programa todas as funcionalidades definidas na

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

10

biblioteca stdio e ir link-la posteriormente ao programa. todos os servios disponveis nesta biblioteca.

Desta forma, voc poder usufruir

Por fim, temos a funo main(). Esta funo indica ao compilador em que instruo deve ser comeada a execuo do programa. Portanto, esta funo deve ser nica, aparecendo somente uma vez em cada programa. O programa termina quando for encerrada a execuo da funo main(). No caso deste programa exemplo, ela no recebe nenhum parmetro e tambm no retorna parmetro nenhum. Isto fica explcito atravs da palavra-chave void escrita na frente do programa. Se em vez de void tivssemos escrito int, isto significaria que a funo main() deveria retornar um valor do tipo inteiro ao final de sua execuo. Como este o valor retornado pela funo main(), este tambm ser o valor retornado pelo programa aps a sua execuo. caractersticas sero apresentadas em detalhes nos prximos captulos. Todo o corpo de uma funo em C inicializado e finalizado atravs das chaves { e }. Estas chaves definem o bloco de instrues a serem executados por esta funo. dada dentro do programa printf (Bom Dia!!!!);. para escrever dados na janela console. A primeira instruo Printf uma funo definida em stdio.h As funes e as suas

Todas as instrues de programa tm que ser declaradas As

dentro de alguma funo (na main() ou outra qualquer). Todas as instrues devem estar dentro das chaves que iniciam e terminam a funo e so executadas na ordem em que as escrevemos. instrues C so sempre encerradas por um ponto-e-vrgula ( ; ). instruo e no um simples separador. O ponto-e-vrgula parte da

Esta instruo uma chamada funo printf(), os

parnteses nos certificam disso e o ponto-e-vrgula indica que esta uma instruo. Nota-se que a funo chamada escrevendo-se o nome desta e colocando-se os parmetros desta dentro dos parnteses. A final de cada instruo, faz-se necessrio o acrscimo de um ponto-vrgula ;. As variveis em C podem estar dentro de uma funo ou no incio do arquivo fonte. Variveis declaradas no incio do arquivo fonte so consideradas globais, isto , so visveis (acessveis) para todas as funes do programa. Variveis declaradas dentro de uma funo so consideradas locais, isto , visveis somente pela funo onde so declaradas. "C" distingue nomes de variveis e funes em maisculas de nomes em minsculas. Voc pode colocar espaos, caracteres de tabulao e pular linhas vontade em seu programa, pois o compilador ignora estes caracteres. Em C no h um estilo obrigatrio. Entretanto, procure manter os programas to organizados quanto for possvel, pois isto melhora muito a legibilidade do programa, facilitando o seu entendimento e manuteno.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

11

2.4 Variveis As variveis so o aspecto fundamental de qualquer linguagem de computador. nome para referenciar o seu contedo. Uma

varivel em C um espao de memria reservado para armazenar um certo tipo de dado e tendo um O espao de memria de uma varivel pode ser Em outras palavras, uma compartilhado por diferentes valores segundo certas circunstncias.

varivel um espao de memria que pode conter, a cada tempo, valores diferentes.
/* Programa : Exemplo de variveis! */ #include <stdio.h> void main() { int num; num = 2; } /* declaracao */ /*atribui um valor*/

printf(Este o nmero dois: %d, num); /*acessa a varivel*/

A primeira instruo (int num) um exemplo de declarao de varivel, isto , apresenta um tipo, int, e um nome, num. A segunda instruo (num = 2) atribui um valor varivel e este valor ser acessado atravs de seu nome. Usamos o operador de atribuio (=) para este fim. A terceira instruo chama a funo printf() mandando o nome da varivel como argumento. Esta l o valor da varivel e substitui na posio indicada por %d, compondo assim a frase apresentada na tela. O emprego da funo printf() ser apresentado em detalhe, posteriormente. Em C todas as variveis devem ser declaradas. Se voc tiver mais de uma varivel do mesmo tipo, poder declar-las de uma nica vez separando seus nomes por vrgulas. Exemplo:
int aviao, foguete, helicoptero;

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

12

2.5 Tipos de Dados O tipo de uma varivel informa a quantidade de memria, em bytes, que esta ir ocupar e a forma como o seu contedo ser armazenado. Em C existem apenas 5 tipos bsicos de variveis, que so:

Com exceo de void, os tipos de dados bsicos podem estar acompanhados por modificadores na declarao de variveis. Os modificadores de tipos oferecidos em C so:

Tipos de Dados Resultantes:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

13

Observao: As declaraes que aparecem na tabela acima entre parnteses (), indicam que estas declaraes so optativas. Por exemplo short unsigned int indica a mesma preciso que unsigned int. O tipo int tem sempre o tamanho da palavra da mquina, isto , em computadores de 16 bits ele ter 16 bits de tamanho. Emprega-se o complemento de dois dos nmeros positivos para o clculo e representao dos nmeros negativos. A escolha de nomes significativos para suas variveis pode ajud-lo a entender o que o programa faz e prevenir erros. Uma varivel no pode ter o mesmo nome de uma palavra-chave de C. Em C, letras minsculas e maisculas so diferentes.

Exemplo de um programa que emprega as variveis apresentadas.


void main() { float y; int i; double x = 3.24; char c = 'a'; i = 100; y = (float) i; } /*varivel Real no inicializada*/ /*varivel Inteira no inicializada*/ /*var. Double inicializada com 3.24 */ /*varivel Char inicializada com a */ /*varivel i recebe o valor 100 */ /*converte tipos */

Preste ateno na operao y= (float) i;. Esta operao muita empregada para converso de tipos de variveis diferentes. Suponha que voc tenha uma varivel x de tipo A e queira

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

14

convert-la para o tipo B e armazen-la em y deste tipo. Voc pode executar esta operao atravs do operador:
y = ((B) x);

Ateno: Cuidado ao converter variveis com preciso grande para variveis com preciso pequena, ou seja, variveis que utilizam um nmero diferente de bits para representar dados. Voc pode perder informaes importantes por causa desta converso. Por exemplo, se voc converter um float num int, voc perder todos os dgitos depois da vrgula (preciso).
void main() { float y = 3.1415; int x = 0; x = (int) y; } /* Equivalente : x = 3 */

2.6 Constantes Um constante tem valor fixo e inaltervel.


printf(Bom Dia!!!!);

No primeiro programa exemplo, mostramos o

uso de uma cadeia de caracteres constante juntamente com a funo printf():

H duas maneiras de declarar constantes em C: a) usando a diretiva #define do pr-processador:


#define < nome da constante > < valor >

Esta diretiva faz com que toda apario do nome da constante no cdigo seja substituda antes da compilao pelo valor atribudo. valor sobre todo o cdigo). Exemplo: No reservado espao de memria no momento da declarao define. A diretiva deve ser colocada no inicio do arquivo e tem valor global (isto , tem

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

15

#define #define #define

size true false

400 1 0 /* no se utiliza ";" nem "=" */

b) utilizando a palavra-chave "const":


const < tipo > < nome > = < valor >;

Esta forma reserva espao de memria para uma varivel do tipo declarado. Uma constante assim declarada s pode aparecer do lado direito de qualquer equao (isto equivale a dizer que no pode ser atribudo um novo valor quela varivel durante a execuo do programa). Exemplo:
const char letra = 'a'; const int size = 400; const double gravidade = 9.81; /* Programa: Exemplo do uso de Constantes */ #define { const char c = c; const int num = 10; int val = Size; } Size 4 void main()

Em C uma constante caractere escrita entre aspas simples, uma constante cadeia de caracteres entre aspa duplas e constantes numricas com o nmero propriamente dito. Exemplos de constantes: a) caractere: a b) cadeia de caracteres: Bom Dia !!!! c) nmero: -3.141523

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

16

2.7 Ponteiros Uma das mais poderosas caractersticas oferecidas pela linguagem C o uso de ponteiros. Um ponteiro proporciona um modo de acesso a variveis sem referenci-las diretamente. entre a varivel e o programa que a acessa. Basicamente, um ponteiro uma representao simblica de um endereo. Portanto, utilizase o endereo de memria de uma varivel para acess-la. Um ponteiro tem como contedo um endereo de memria. Este endereo a localizao de uma outra varivel de memria. Dizemos que uma varivel aponta para uma outra quando a primeira contm o endereo da segunda. A declarao de ponteiros tem um sentindo diferente da de uma varivel simples. instruo:
int *px;

mecanismo usado para isto o endereo da varivel. De fato, o endereo age como intermedirio

declara que *px um dado do tipo int e que px um ponteiro, isto , px contm o endereo de uma varivel do tipo int. Para cada nome de varivel (neste caso px), a declarao motiva o compilador a reservar dois bytes de memria onde os endereos sero armazenados. Alm disto, o compilador deve estar O endereo de uma ciente do tipo de varivel armazenada naquele endereo; neste caso inteiro.

varivel pode ser passado um ponteiro atravs do operador &, como apresentado abaixo:
void main() { int num, valor; /* declara as variveis como inteiras */ int *ptr; ptr = 0; ptr = &num; num = 10; valor = *ptr; }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

/* declara um ponteiro para um inteiro */ /* inicializa o ponteiro com o endereco 0 */ /* atribui ao ptr o endereo da varivel num*/ /* atribui varivel inteira o valor 10 */ /* acessa o contedo apontado por ptr e */ /* atribui a valor */

Informtica para Automao Linguagem de Programao

17

Neste programa, primeiro declaram-se duas variveis inteiras.

Em seguida, declara-se um

ponteiro para uma varivel do tipo inteira. Este ponteiro tem o seu contedo inicializado com 0. Este um procedimento normal na manipulao de ponteiros, muito empregado para evitar o aparecimento de erros. ser acessado. Na seqncia, emprega-se o operador & para obter o endereo da varivel num e armazenar este endereo em ptr. Logo aps, atribumos a varivel inteira num o valor 10. Como ptr contm o endereo de num, logo ptr poder j acessar o valor 10 armazenado na varivel num. Isto feito na ltima linha, onde o contedo apontado por ptr acessado e copiado para a varivel valor. Outro exemplo da manipulao de ponteiros:
void main() { int i, j, *ptr; i = 1; j = 2; ptr = &i; *ptr = *ptr + j; } /* declara as variveis */ /* i recebe o valor 1 */ /* j recebe o valor 2 */ /* ptr recebe o valor do endereo de i */ /* equivale a: i = i + j */

Pois, enquanto o endereo de um ponteiro for nulo, isto indicar que este

endereo contm um valor invlido e, portanto, o contedo representado por este endereo no deve

Nosso objetivo neste momento no apresentar todas as potencialidades dos ponteiros. Estamos aqui apresentando os ponteiros primeiramente como um tipo de dado especial. O importante aqui entender o contedo de um ponteiro e como este pode ser empregado. Posteriormente, apresentaremos as funcionalidades dos ponteiros medida que formos evoluindo no aprendizado de C.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

18

2.8 Exerccios 2.1 Crie o seu programa Hello, World! ou Ol, Mame!; 2.2 Crie um programa que contenha todos os tipos de variveis possveis e as combinaes dos modificadores possveis. Inicialize estas variveis com valores tpicos. Use o mtodo para a converso de tipos para converter: a) A varivel do tipo char em todos os outros tipos de variveis. b) A varivel do tipo double em todos os outros tipos de variveis. acontece com a preciso das variveis. 2.3 Crie um programa que exemplifique a utilizao de ponteiros. Que contenha pelo menos a declarao de um ponteiro, sua inicializao com zero, a obteno do endereo de uma varivel com o operador & e o acesso ao dado representado pelo ponteiro. 2.4 Utilize as diretivas #define para criar constantes e empregue estas constantes para inicializar as variveis do programa acima. 2.5 Analise o seguinte programa e aponte onde est o erro.
#define Default_Y 2 void main() { const int num = 10; int y = Default_Y; const int *ptr = 0; ptr = &num; *ptr = *ptr + y; }

Discuta o que

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

19

3 Entrada/Sada Console
As rotinas de entrada/sada do console se encontram nas bibliotecas "stdio.h" e "conio.h" e, por isso, estas bibliotecas devem ser includas nos programas aplicativos atravs da diretiva include:
#include <stdio.h> #include <conio.h>

Algumas das funes de entrada e sada para a console mais utilizadas so apresentadas a seguir: 3.1 Printf() A funo printf() uma das funes de E/S (entrada e sada) que podem ser usadas em C. Ela no faz parte da definio de C mas todos os sistemas tm uma verso de printf() implementada. Ela permite a sada formatada na tela. J vimos duas aplicaes diferentes da funo printf():
printf(Bom Dia!!!!); printf(Este o nmero dois: %d, num);

A funo printf() pode ter um ou vrios argumentos. No primeiro exemplo ns colocamos um nico argumento: Bom Dia !!!!. printf():
printf(string-formatao, < lista de parmetros >);

Entretanto, no segundo colocamos dois: Este o nmero

dois: %d que est esquerda e o valor 2 direita da vrgula que separa os argumentos. Sintaxe de

A string de formatao pode conter caracteres que sero exibidos na tela e cdigos de formatao que indicam o formato em que os argumentos devem ser impressos. No nosso segundo exemplo, o cdigo de formatao %d solicita a printf() para imprimir o segundo argumento em formato decimal na posio da string onde aparece o %d. Cada argumento deve ser separado por uma vrgula.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

20

Alm do cdigo de formatao decimal (%d), printf() aceita vrios outros. exemplo mostra o uso do cdigo %s para imprimir uma cadeia de caracteres:
#include <stdio.h> int main(int argc, char* argv[]) {

O prximo

printf(%s esta a %d milhoes de milhas \n do sol., Venus, 67); }

A sada ser: Venus est a 67 milhoes de milhas do sol. Aqui, alm do cdigo de formatao, a expresso de controle de printf() contm um conjunto de caracteres estranho: \n. O \n um cdigo especial que informa a printf() que o restante da A combinao de caracteres \n representa, na impresso deve ser feito em uma nova linha. Enter em um editor de texto). Os caracteres que no podem ser obtidos diretamente do teclado para dentro do programa (como a mudana de linha) so escritos em C, como a combinao do sinal \ (barra invertida) com outros caracteres. Por exemplo, \n representa a mudana de linha. A string de formatao define a forma como os parmetros sero apresentados e tem os seguintes campos: "%[Flags] [largura] [.preciso] [FNlh] < tipo > [\Escape Sequence]" onde:

verdade, um nico caractere em C, chamado de nova-linha (equivalente ao pressionamento da tecla

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

21

largura = nmero mximo de caracteres a mostrar; preciso = nmero de casas aps a vrgula a mostrar F = em ponteiros, apresentar como "Far" => base : offset (xxxx : xxxx) N = em ponteiros, apresentar como "Near" => offset h = apresentar como "short" l = apresentar como "long"

A seguir so mostrados alguns exemplos da formatao apresentada acima:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

22

#include <stdio.h> int main(int argc, char* argv[ ]) { float x; double y = -203.4572345; int a, b; a = b = 12; x = 3.141523; printf("Bom dia"); printf("\n\t Bom dia\n"); /*pula linha aps escrever bom dia*/ printf("O valor de x %7.3f\n", x); printf("Os valores de i, j e y so: %d %d %lf \n", a, b, y); }

Obs: Caso voc queira imprimir na tela os caracteres especiais \ ou %, voc deve escrevlos na funo printf() de forma duplicada, o que indicar ao compilador que este no se trata de um parmetro da funo printf() mas sim que deseja-se imprimir realmente este caractere. O exemplo abaixo apresenta este caso:
#include <stdio.h> void main() { int reajuste = 10; printf(O reajuste foi de %d%%. \n, reajuste); }

a sada ser: O reajuste foi de 10%.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

23

3.2 Cprintf() Basicamente cprintf() igual a printf(), mas usa as coordenadas atuais do cursor e da janela que forem ajustados anteriormente, bem como ajustes de cr de caracteres. Utilize esta funo para escrever na tela em posies pr-definidas. 3.3 Scanf() A funo scanf() outra das funes de E/S implementadas em todos os compiladores C. Ela o complemento de printf() e nos permite ler dados formatados da entrada padro (teclado). A funo scanf() suporta a entrada via teclado. Um espao em branco ou um CR/LF (tecla Enter) definem o fim da leitura. Observe que isto torna inconveniente o uso de scanf() para ler strings compostas de vrias palavras (por exemplo, o nome completo de uma pessoa). Para realizar este tipo de tarefa, veremos outra funo mais adequada na parte referente strings. Sua sintaxe similar de printf(), isto , uma expresso de controle seguida por uma lista de argumentos separados por vrgula. Sintaxe:
scanf(string de definio das variveis, <endereo das variveis>);

A string de definio pode conter cdigos de formatao, precedidos por um sinal % ou ainda o caractere * colocado aps o % que avisa funo que deve ser lido um valor do tipo indicado pela especificao, mas no deve ser atribudo a nenhuma varivel (no deve ter parmetros na lista de argumentos para estas especificaes). A lista de argumentos deve consistir nos endereo das variveis. O endereo das variveis pode ser obtido atravs do operador & apresentado na seco sobre ponteiros. Exemplo:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

24

#include <stdio.h> void main() { float x; printf ("Entre com o valor de x : "); scanf ("%f",&x); } /*l o valor do tipo float e armazena em x*/

Esta funo funciona como o inverso da funo printf(), ou seja, voc define as variveis que deveram ser lidas da mesma forma que definia estas com printf(). Desta forma, os parmetros de scanf() so em geral os mesmos que os parmetros de printf(), no exemplo acima observa-se esta questo. O cdigo de formatao de scanf() igual ao cdigo de formatao de printf(). scanf():
#include <stdio.h> main() { float anos, dias; printf(Digite a sua idade em anos: ); scanf(%f, &anos); dias = anos*365; printf(Sua idade em dias e %.0f.\n, dias); }

Por isso,

veja as tabelas de formatao de printf() para conhecer os parmetros de scanf(). Outro exemplo de

3.4 Getch(), Getche() e Getchar() Em algumas situaes, a funo scanf() no se adapta perfeitamente pois voc precisa pressionar [enter] depois da sua entrada para que scanf() termine a leitura. usar getch(), getche() ou getchar(). Neste caso, melhor A funo getchar() aguarda a digitao de um caractere e

quando o usurio apertar a tecla [enter], esta funo adquire o caractere e retorna com o seu
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

25

resultado.

Getchar() imprime na tela o caractere digitado. A funo getch() l um nico caractere Ambas funes no requerem que o usurio digite [enter]

do teclado sem eco-lo na tela, ou seja, sem imprimir o seu valor na tela. A funo getche() tem a mesma operao bsica, mas com eco. para finalizar a sua execuo. Veja exemplo abaixo, junto funo putch(). 3.5 Putch() ou Putchar() A funo putch() apresenta um nico caractere na tela, recebendo-o como parmetro. funo putchar() executa a mesma operao, com caracteres. Exemplo:
#include <stdio.h> #include <conio.h> void main() { char c1, c2; c1 = getch(); c2 = getche(); putch(c1); putchar(c2); } /* l caractere c1 mas no mostra na tela */ /* l caractere c2, escrevendo-o na tela */ /* escreve valor de c1 na tela */

printf("\nO primeiro valor digitado foi: "); printf("\nO segundo valor digitado foi: ");

3.6 Exerccios 3.1 Escreva um programa que contenha uma nica instruo e imprima na tela:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

26

3.2 Escreva um programa que imprima na tela:

3.3 Escreva um programa que pea os dados da conta bancria de um cliente e, posteriormente, escreva na tela os dados do cliente tambm de forma organizada. 3.4 Escreva um programa que exemplifique todos os tipos de formataes fornecidas para o printf(). 3.5 Escreva um programa que pea ao usurio para entrar com um valor real (float), converta este valor para uma varivel do tipo char e depois imprima o seu valor na tela em formato decimal e em formato caractere. 3.6 Faa um programa que pea ao usurio para entrar com um caractere, converta este nmero para um valor inteiro e apresente na tela o valor deste nmero em formato float e o endereo da varivel que o contm. Utilize ponteiros para armazenar e acessar este valor.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

27

4 Operadores
4.1 Operadores Aritmticos C uma linguagem rica em operadores, em torno de 40. Alguns so mais usados que

outros, como o caso dos operadores aritmticos que executam operaes aritmticas. C oferece 6 operadores aritmticos binrios (operam sobre dois operandos) e um operador aritmtico unrio (opera sobre um operando). So eles: Binrios: = + * / % Unrio: Menos unrio (indica a troca do sinal algbrico do valor) Em C, o sinal de Atribuio Soma Subtrao Multiplicao Diviso Mdulo (devolve o resto da diviso inteira)

O operador = j conhecido dos exemplos apresentados anteriormente. ao nome da varivel esquerda.

igual no tem a interpretao dada em matemtica. Representa a atribuio da expresso direita J os operadores + - / * representam as operaes aritmticas A seguir est um programa que usa vrios bsicas de soma, subtrao, diviso e multiplicao.

operadores aritmticos e converte temperatura Fahrenheit em seus correspondentes graus Celsius.


#include <stdio.h> void main() { int ftemp = 0; int ctemp = 0; printf("Digite temperatura em graus Fahrenheit: "); scanf("%d", &ftemp);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

28

ctemp = (ftemp - 32)*5/9; printf("Temperatura em graus Celsius e %d", ctemp); }

O operador mdulo (%) aceita somente operandos inteiros. inteiro sua esquerda pelo inteiro sua direita. dividimos 17 por 5 teremos resto 2. 4.2 Operadores Relacionais

Resulta o resto da diviso do

Por exemplo, 17%5 tem o valor 2 pois quando

Os operadores relacionais so usados para fazer comparaes. Em C no existe um tipo de varivel chamada booleana, isto , que assuma um valor verdadeiro ou falso. O valor zero (0) considerado falso e qualquer valor diferente de 0 considerado verdadeiro e representado pelo inteiro 1. Os operadores relacionais comparam dois operandos e retornam 0 se o resultado for falso e 1 se o resultado for verdadeiro. Os operadores relacionais disponveis em C so:

O programa a seguir mostra expresses booleanas como argumento da funo printf():


#include <stdio.h> void main() { int verdade, falso; verdade = (15 < 20); falso = (15 == 20);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

29

printf("Verdadeiro= %d, falso= %d\n", verdade, falso); }

Note que o operador relacional igual a representado por dois sinais de iguais. Um erro comum o de usar um nico sinal de igual como operador relacional. O compilador no o avisar que este um erro, por qu? Na verdade, como toda expresso C tem um valor verdadeiro ou falso, este no um erro de programa e sim um erro lgico do programador. 4.3 Operadores lgicos binrios Estes operadores so empregados para comparar os bits contidos em duas variveis, por isso, so denominados operadores lgicos binrios. Ou seja, estes operadores fazem uma comparao lgica entre cada bit dos operandos envolvidos. Os operadores binrios disponveis so:

A seguir temos um exemplo da aplicao destes operadores.


#include <stdio.h> void main() { int i, j, k; i = 1; j = 2; printf("\ti = %x (00000001)\n\tj = %x (00000010)", i, j); k = i & j; /* k = i AND j */ printf("\n\t i & j => %x (00000000)", k);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

30

k = i ^ j; k = i << 2; }

/* k = i XOR j */ /*k = i deslocando 2 bits esquerda (4)*/

printf("\n\t i ^ j => %x (00000011)", k); printf("\n\t i << 2 => %x (00000100)", k);

Primeiro o programa faz uma comparao binria e (&) entre o nmero 1 (0x00000001) e o nmero 2 (0x00000010). Por isso o resultado obtido logicamente 0, ou seja, 0x00000000. Em seguida, o programa faz uma comparao binria ou (^) entre estes dois nmeros, resultando agora, logicamente, 3, ou seja, (0x00000011). Por fim, o programa desloca o nmero 1 em duas casas para a esquerda, representado no programa pelo operador << 2. Assim, o resultado o nmero 4 ou, em binrio, (0x00000100). A partir deste exemplo fica clara a utilizao destes operadores.

4.4 Operadores de Ponteiros Estes operadores j foram apresentados anteriormente na seco sobre ponteiros (ver 2.7). O primeiro operador server para acessar o valor da varivel, cujo endereo est armazenado em um ponteiro. O segundo operador server para obter o endereo de uma varivel.

O programa abaixo apresenta novamente a aplicao destes operadores.


void main() { int i, j, *ptr; ptr = &i; /* atribui a ptr o endereo da varivel i */ /* ptr = valor de i ! */ } j = *ptr; /*atribui a j o contedo do endereo definido por*/

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

31

4.5 Operadores Incrementais e Decrementais Uma das razes para que os programas em C sejam pequenos em geral que C tem vrios operadores que podem comprimir comandos de programas. seguintes operadores: Neste aspecto, destacam-se os

O operador de incremento (++) incrementa de um seu operando. Este operador trabalha de dois modos. O primeiro modo chamado pr-fixado e o operador aparece antes do nome da varivel. O segundo o modo ps-fixado em que o operador aparece seguindo o nome da varivel. Em ambos os casos, a varivel incrementada. Porm quando ++n usado numa instruo, n incrementada antes de seu valor ser usado, e quando n++ estiver numa instruo, n incrementado depois de seu valor ser usado. ressaltando esta questo.
#include <stdio.h> void main() { int n, m, x, y; n = m = 5; x = ++n; y = m++; printf("O valor de n=%d, x=++n=%d, m=%d e y=m++=%d;",n,x,m,y); }

O programa abaixo mostra um exemplo destes operadores,

Vamos analisar duas expresses seguintes.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

32

a) k = 3*n++; Aqui, primeiro n multiplicado por 3, depois o resultado atribudo a k e, finalmente, n incrementado de 1. b) k = 3*++n; Primeiro n incrementado em 1, depois n multiplicado por 3 e, por fim, o resultado atribudo a k. Dica: Para evitar problemas, faa uso de parnteses para guiar a execuo do programa evitando que o compilador no compreenda a ordem correta de executar a operao. Abaixo, temos um outro exemplo dos operadores incrementais apresentado vrias aplicaes destes operadores:
void main() { int i = 10; int *ptr = 0; i = i + 1; i++; i = i - 1; i--; ptr = &i; (*ptr)++; ptr++; /* incrementa i */ /* incrementa i */ /* decrementa i */ /* decrementa i */ /* recebe o endereco de i */ /* incrementa valor de i */ /* incrementa em 2 Bytes (1 inteiro */ /* ocupa 2 Bytes) o valor do endereo */ /* apontado pelo ponteiro ptr */ }

Ateno para a ltima instruo ptr++. Esta instruo ir altera o endereo armazenado em ptr. Se o valor deste ponteiro for acessado, o dado representado por este ponteiro no tem mais Por isso, tome cuidado ao nenhuma relao com a varivel i, podendo conter qualquer dado. seu programa gere erros fatais para o sistema operacional.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

manipular ponteiros para no acessar variveis com uso desconhecido. Isto poder fazer com que o

Informtica para Automao Linguagem de Programao

33

4.6 Operadores de Atribuio O operador bsico de atribuio (=) pode ser combinado com outros operadores para gerar instrues em forma compacta. Cada um destes operadores usado com um nome de varivel sua esquerda e uma expresso sua direita. A operao consiste em atribuir um novo valor varivel que depender do operador e da expresso direita. Se x uma varivel, exp uma expresso e op um operador, ento: x op= exp; equivale a x = (x)op(exp);

Exemplo:
#include <stdio.h> void main() { int total = 0; int cont = 10; printf("Total=%d\n", total); total += 1; printf("Total=%d\n", total);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

34

total ^= 2; printf("Total=%d\n", total); total <<= 2; printf("Total=%d\n", total); total *= cont; printf("Total=%d\n", total); }

4.7 O Operador Lgico Ternrio O operador condicional possui uma construo um pouco estranha. o nico operador em C que opera sobre trs expresses. Sua sintaxe geral possui a seguinte construo:
exp1 ? exp2 : exp3

A exp1 avaliada primeiro.

Se seu valor for differente de zero (verdadeira), a exp2 Se exp1 for zero,

avaliada e seu resultado ser o valor da expresso condicional como um todo.

exp3 avaliada e ser o valor da expresso condicional como um todo. Na expresso:


max = (a>b)?a:b

a varivel que contm o maior valor numrico entre a e b ser atribuda a max. Outro exemplo:
abs = (x > 0) ? x : -x;

A expresso
printf( %d uma varivel %s !, x, ((x%2)?Impar:Par);

imprime mpar se x for um nmero mpar, caso contrrio imprimir par.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

35

4.8 Precedncia O operador ! o de maior precedncia, a mesma que a do operador unrio. seguinte mostra as precedncias dos operadores: A tabela

4.9 Exerccios: 4.1 Qual o resultado da seguinte expresso: int a = 1, b = 2, c = 3; int result = ++a/a&&!b&&c||b--||-a+4*c>!!b; 4.2 Escreva uma expresso lgica que resulte 1 se o ano for bissexto e 0 se o ano no for bissexto. Um ano bissexto se for divisvel por 4, mas no por 100. Um ano tambm bissexto se for divisvel por 400. 4.3 Faa um programa que solicite ao usurio o ano e imprima Ano Bissexto ou Ano NoBissexto conforme o valor da expresso do exerccio anterior. Utilize o operador condicional.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

36

4.4 Num cercado, h vrios patos e coelhos. Escreva um programa que solicite ao usurio o total de cabeas e o total de ps e determine quantos patos e quantos coelhos encontram-se nesse cercado. 4.5 Uma firma contrata um encanador a 20.000,00 por dia. Crie um programa que solicite o nmero de dias trabalhados pelo encanador e imprima a quantia lquida que dever ser paga, sabendo-se que so descontados 8% para imposto de renda. 4.6 Faa um programa que solicite um caractere do teclado por meio da funo getch(); se for uma letra minscula imprima-a em maisculo, caso contrrio imprima o prprio caractere. Use uma expresso condicional. 4.7 Faa um programa que solicite ao usurio uma seqncia binria com 16 bits. Transforme esta seqncia de 0 e 1 em um nmero inteiro. Depois manipule este nmero inteiro para verificar se os bits 0, 3, 7, 14 esto habilitados (valor igual a 1). Pea a usurio se ele deseja modificar algum bit especfico da palavra. Se ele quiser, modifique o bit desejado para o valor por ele fornecido.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

37

5 Laos
Em C existem 3 estruturas principais de laos: o lao for, o lao while e o lao do-while. 5.1 O Lao For O lao for engloba 3 expresses numa nica, e til principalmente quando queremos repetir algo um nmero fixo de vezes. Sintaxe:
for(inicializao; teste; incremento) instruo;

Os parnteses, que seguem a palavra chave for, contm trs expresses separadas por pontoe- vrgulas, chamadas respectivamente de : expresso de inicializao, expresso de teste e expresso de incremento. As 3 expresses podem ser compostas por quaisquer instrues vlidas em C. Inicializao: executada uma nica vez na inicializao do lao. Serve para iniciar variveis. Teste: esta a expresso que controla o lao. Esta testada quando o lao inciado ou reiniciado. Sempre que o seu resultado for verdadeiro, a instrues do lao sero executadas. Incremento: Define a maneira como a varivel de controle do lao ser alterada cada vez que o lao repetido (conta++). execuo do corpo do lao. Exemplo:
#include <stdio.h> void main() { int conta; for(conta = 0; conta < 10; conta += 3)

Quando a expresso se tornar falsa, o lao terminado. Esta instruo executada, toda vez, imediatamente aps a

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

38

printf("conta=%d\n", conta); }

Qualquer uma das expresses de um lao for pode conter vrias instrues separadas por vrgulas. A vrgula na verdade um operador C que significa faa isto e isto. Um par de expresses separadas por vrgula avaliado da esquerda para a direita.
#include <stdio.h> void main() { int x, y; for( x=0, y=0; x+y < 100; x = x+1, y++) printf("%d\n", x+y); }

Podemos usar chamadas a funes em qualquer uma das expresses do lao. Qualquer uma das trs partes de um lao for pode ser omitida, embora os pontos-e-vrgulas devam permanecer. Se a expresso de inicializao ou a de incremento forem omitidas, elas sero simplesmente desconsideradas. verdadeira. O corpo do lao pode ser composto por vrias instrues, desde que estas estejam delimitadas por chaves { }. O corpo do lao pode ser vazio, entretanto o ponto-e-vrgula deve permanecer para indicar uma instruo vazia. Quando um lao est dentro de outro lao, dizemos que o lao interior est aninhado. Para mostrar esta estrutura preparamos um programa que imprime tabuada.
#include <stdio.h> void main() { int i,j,k; printf("\n"); for(k=0; k<=1; k++) {
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Se a condio de teste no est presente considerada permanentemente

Informtica para Automao Linguagem de Programao

39

printf("\n"); for(i=1; i<5; i++) printf("Tabuada do %3d ", i+4*k+1); printf("\n"); for(i=1; i<=9; i++) { for(j = 2+4*k; j<=5+4*k; j++) printf("%3d x%3d = %3d ", j, i, j*i); printf("\n"); } } }

5.2 O Lao While O lao while utiliza os mesmos elementos que o lao for, mas eles so distribudos de maneira diferente no programa. Sintaxe:
while(expresso de teste) instruo;

Se a expresso de teste for verdadeira (diferente de zero), o corpo do lao while ser executado uma vez e a expresso de teste avaliada novamente. Este ciclo de teste e execuo repetido at que a expresso de teste se torne falsa (igual a zero), ento o lao termina. Assim como o for, o corpo do lao while pode conter uma instruo terminada por (;), nenhuma instruo desde que possua um (;) e um conjunto de instrues separadas por chaves { }. exemplo, onde um lao while substituiu um antigo lao for.
#include <stdio.h> void main() {
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Abaixo temos um

Informtica para Automao Linguagem de Programao

40

int conta = 0; while(conta < 10) { printf("conta=%d\n", conta); conta++; } }

Quando se conhece a priori o nmero de loops que o lao deve fazer, recomenda-se o uso do lao for. Caso o nmero de iteraes dependa das instrues executadas, ento se recomenda o uso do lao while. Os laos while podem ser aninhados como o lao for. C permite que no interior do corpo de um lao while, voc possa utilizar um outro lao while.

5.3 O Lao Do-While O lao Do-While cria um ciclo repetido at que a expresso de teste seja falsa (zero). Este lao bastante similar ao lao while. vez. Sintaxe:
do { instruo; } while(expresso de teste);

A diferena que no lao do-while o teste de condio

avaliado depois do lao ser executado. Assim, o lao do-while sempre executado pelo menos uma

Embora as chaves no sejam necessrias quando apenas uma instruo est presente no corpo do laop do-while, elas so geralmente usadas para aumentar a legibilidade. laos while e do-while: Exemplo usando os

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

41

#include <stdio.h> #include <conio.h> #include <stdlib.h> void main() { char ch, c; int tentativas; do { ch = rand()%26 + 'a'; tentativas = 1; printf("\nDigite uma letra de 'a' a 'z':\n"); while((c=getch())!= ch) { printf("%c e incorreto. Tente novamente. \n\n",c); tentativas++; } printf("\n%c e correto",c); printf("\nvoce acertou em %d tentativas", tentativas); printf("\nQuer jogar novamente? (s\\n): "); }while(getche()=='s'); } /* requerida para rand() */

5.4 Break e Continue O comando break pode ser usado no corpo de qualquer estrutura do lao C. Causa a sada imediata do lao e o controle passa para o prximo estgio do programa. Se o comando break estiver em estruturas de laos aninhados, afetar somente o lao que o contm e os laos internos a este. J o comando continue fora a prxima interao do lao e pula o cdigo que estiver abaixo. Nos while e do-while um comando continue faz com que o controle do programa v diretamente para o teste condicional e depois continue o processo do lao. No caso do lao for, o computador

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

42

primeiro executa o incremento do lao e, depois, o teste condicional, e finalmente faz com que o lao continue.

5.5 Goto O comando goto faz com que o programa pule para a instruo logo aps o label passado como parmetro. Este comando desnecessrio e desaconselhado. Foi implementado somente para manter a compatibilidade com outros compiladores. A instruo goto tem duas partes: a

palavra goto e um nome. O nome segue as convees de nomes de variveis C. Por exemplo:
goto parte1;

Para que esta instruo opere, deve haver um rtulo (label) em outra parte do programa. Um rtulo um nome seguindo por dois pontos.
parte1: printf(Anlise dos Resultados.\n);

A instruo goto causa o desvio do controle do programa para a instruo seguinte ao rtulo com o nome indicado. Os dois pontos so usados para separar o nome da instruo.

5.6 Exerccios 5.1 Escreva um programa que imprima os caracteres da tabela ASCII de cdigos de 0 a 255. O programa deve imprimir cada caractere, seu cdigo decimal e hexadecimal. usando os parmetros de formatao de printf(). 5.2 Escreva um programa, utilizando um lao while, que leia caracteres do teclado. Enquanto o usurio no pressionar a tecla ESC de cdigo 27, os caracteres lidos no so ecoados no Monte uma tabela

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

43

vdeo.

Se o caractere lido for uma letra minscula, o programa a imprime em maisculo e, se for

qualquer outro caractere, ele mesmo impresso. 5.3 Elabore um programa que solicite um nmero inteiro ao usurio e crie um novo nmero inteiro com os dgitos em ordem inversa. Por exemplo, o nmero 3567 deve ser escrito 7653.

5.4 Escreva um programa que desenhe uma moldura na tela do micro, desenhando um sol com as tuas iniciais no meio da tela e escrevendo Feliz Natal e o seu nome embaixo.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

44

6 Comandos para Tomada de Deciso


Uma das tarefas fundamentais de qualquer programa decidir o que deve ser executado a seguir. Os comandos de deciso permitem determinar qual a ao a ser tomada com base no Isto significa que podemos selecionar entre aes resultado de uma expresso condicional.

alternativas dependendo de critrios desenvolvidos no decorrer da execuo do programa. C oferece 3 principais estruturas de deciso: if, if-else, switch. Estas estruturas so o tema deste captulo.

6.1 If O comando if usado para testar uma condio e caso esta condio seja verdadeira, o programa ir executar uma instruo ou um conjunto delas. Este um dos comandos bsicos para qualquer linguagem de programao. Sintaxe:
if(expresso de teste) instruo;

Como C no possui variveis booleanas, o teste sobre a condio opera como os operadores condicionais, ou seja, se o valor for igual a zero (0) a condio ser falsa e se o valor for diferente de zero, a condio ser verdadeira. deve ser delimitado por chaves { e }. Um comando if pode estar dentro de outro comando if. Dizemos ento que o if interno est aninhado. O programa abaixo mostra exemplos do uso e da sintaxe dos comandos if. O primeiro if mostra a forma aninhada do comando if, o segundo apresenta a sintaxe bsica e o ltimo um exemplo onde o comando if executa um bloco de instrues. Como os laos, o comando if pode ser usado para uma nica instruo ou para um conjunto delas. Caso se utilize para um conjunto de instrues, este conjunto

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

45

#include <stdio.h> #include <conio.h> void main() { char ch; printf("Digite uma letra de 'a' a 'z':"); ch = getche(); if(ch >= 'a') if(ch <= 'z') printf("\n Voce digitou um caractere valido!"); if(ch == 'p') if(ch != 'p') { printf("\nVoce nao digitou a tecla 'p'!); printf(\n Digite um caractere para finalizar."); ch = getche(); } } /* Forma basica de um comando if */ /*if executando um bloco de instrucoes*/ printf("\nVoce pressionou a tecla 'p'!"); /* Dois comandos if aninhados */

6.2 If-Else No exemplo anterior o comando if executar uma nica instruo ou um grupo de instrues, se a expresso de teste for verdadeira. No far nada se a expresso de teste for falsa. O comando else, quando associado ao if, executar uma instruo ou um grupo de instrues entre chaves, se a expresso de teste do comando if for falsa. O if-else tambm permite o aninhamento de outros comandos if, ou if-else dentro do bloco de instrues do aps o else. Sintaxe:
if(expresso de teste) instruo_1; else instruo_2;

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

46

Exemplo:
#include <stdio.h> void main() { int x, y; for(y=1; y<24; y++) { for(x=1; x<24; x++) if(x==y || x==24-y) printf("\xDB"); else printf("\xB0"); printf("\n"); } } /* cor clara */ /* Nova Linha */ /* passo de largura */ /* diagonal? */ /* cor escura */ /* passo de descida */

6.3 Switch O comando switch permite selecionar uma entre vrias aes alternativas. vezes so deselegantes. O comando switch tem um formato limpo e claro. Embora

construes if-else possam executar testes para escolha de uma entre vrias alternativas, muitas A instruo switch consiste na palavra-chave switch seguida do nome de uma varivel ou de um nmero constante entre parnteses. O corpo do comando switch composto de vrios casos rotulados por uma constante e opcionalmente um caso default. A expresso entre parnteses aps a palavra-chave switch determina para qual caso ser desviado o controle do programa. O corpo de cada caso composto por qualquer nmero de instrues. Geralmente, a ltima instruo break. O comando break causa a sada imediata de todo o corpo do switch. Na falta do comando break, todas as instrues aps o caso escolhido sero executadas, mesmo as que pertencem aos casos seguintes. Sintaxe:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

47

switch(varivel ou constante) { case constante1: instruo; instruo; break; case constante2: instruo; instruo; break; case constante3: instruo: instruo: break; default: instruo; instruo; }

Voc no poder usar uma varivel nem uma expresso lgica como rtulo de um caso. Pode haver nenhuma, uma ou mais instrues seguindo cada caso. Estas instrues no necessitam estar entre chaves. O corpo de um switch deve estar entre chaves. Se o rtulo de um caso for igual ao valor da expresso do switch, a execuo comea nele. Se nenhum caso for satisfeito e existir um caso default, a execuo comear nele. Um caso default opcional. No pode haver casos com rtulos iguais. A seguir apresentamos um exemplo que calcula o dia da semana a partir de uma data. O ano deve ser maior ou igual a 1600, pois nesta data houve uma redefinio do calendrio.
#include <stdio.h> #include <conio.h> void main() {

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

48

int D, M, A, i; long int F = 0; do { do { printf("\nDigite uma data na forma dd/mm/aaaa: "); scanf("%d/%d/%d", &D, &M, &A); } while(A<1600 || M<1 || M>12 || D<1 || D>31); F = A + D + 3*(M-1) - 1; if(M<3) { A--; i = 0; } else i = .4*M+2.3; F+= A/4 - i; i = A/100 + 1; i *= .75; F -= i; F %= 7; switch(F) { case 0: printf("\nDomingo"); break; case 1: printf("\nSegunda-Feira"); break; case 2: printf("\nTerca-Feira"); break; case 3: printf("\nQuarta-Feira");
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

49

break; case 4: printf("\nQuinta-Feira"); break; case 5: printf("\nSexta-Feira"); break; case 6: printf("\nSabado"); break; } }while(getche()!=27); } /*Tecla ESC nao for pressionada*/

6.4 Exerccios 6.1 Crie um programa que desenhe na tela um tabuleiro de xadrez. 6.2 Crie um programa que desenhe na tela o seu quadro de horrios deste semestre. 6.3 Escreva um programa que solicite ao usurio trs nmeros inteiros a, b, e c onda a maior que 1. Seu programa deve somar todos os inteiros entre b e c que sejam divisveis por a. 6.4 A sequncia de Fiboncci a seguinte: 1, 1, 2, 3, 5, 8, 13, 21,... Os dois primeiros termos so iguais a 1. Cada termo seguinte igual `a soma dos dois anteriores. Escreva um programa que solicite ao usurio o nmero do termo e calcule o valor do termo. fornecido pelo usurio for igual a 7, o programa dever imprimir 13. 6.5 Implemente um jogo da velha, onde o programa desenha na tela um tabuleiro e voc pede a dois usurios (A e B) na respectiva ordem, que jogada eles querem realizar e depois atualiza o desenho. O programa deve perceber quando o jogo acabou e anunciar o vencedor.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Por exemplo: se o nmero

Informtica para Automao Linguagem de Programao

50

7 Funes
As funes servem para agrupar um conjunto de instrues de acordo com a tarefa que elas desempenham. Uma vez implementada corretamente esta tarefa, voc no precisa mais se Por exemplo, quando usamos preocupar em implementar esta tarefa, basta usar a sua funo. tarefa, pois a funo j fornecia este servio de forma adequada. As funes quando bem empregadas, facilitam bastante a organizao modular do programa, permitem a reutilizao de partes do programa e facilitam a sua manuteno. Uma funo uma unidade de cdigo de programa autnoma desenhada para cumprir uma tarefa particular. Provavelmente a principal razo da existncia de funes impedir que o programador tenha que escrever o mesmo cdigo repetidas vezes.

printf() para imprimir informaes na tela, no nos preocupamos como o programa realiza esta

7.1 Sintaxe A estrutura de uma funo C bastante semelhante da funo main(). A nica diferena que main() possui um nome especial pois a funo main() a primeira a ser chamada quando o programa executado. Sintaxe:
<tipo retorno> <nome>(<tipo parmetro> <nome parmetro>, <..> <..>) { <declaraes locais>; <comandos>; return <expresso ou valor compatvel com o tipo de retorno>; }

O tipo de retorno define o tipo de dado o qual a funo retornar com o resultado de sua execuo. Nome indica qual o nome da funo. Em seguida temos a lista de argumentos da Os funo inseridos entre os parnteses aps o nome da funo e separados por vrgulas.

argumentos so declarados no cabealho da funo com o tipo parmetro e em seguida o nome do


Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

51

parmetro. Uma funo pode ter tantos argumentos quanto voc queira definir.

Quando uma

funo no necessita de parmetros, o nome desta deve ser seguido por parnteses ( ) sem nenhum parmetro no seu interior. A lista de instrues a serem executadas pela funo vem aps a lista de parmetros e deve ser delimitada por chaves { e }. executarem a tarefa. Dentro do bloco de instrues da funo, primeiramente declara-se e inicializa-se as variveis locais e posteriormente temos os comandos da funo (instrues). O comando return encerra a funo e retorna ao ponto do programa onde esta foi chamada. No entanto, return no precisa ser o ltimo comando da funo. Infelizmente, uma funo em C s pode retornar um resultado e este repassado atravs de return. Algumas linguagens como Matlab permitem que uma funo retorne mais do que uma nica varivel contendo o resultado. Funes com tipo de retorno void, no utilizam o comando return pois estas no retornam nenhum tipo de dado. O comando return utilizado quando queremos finalizar esta funo antes Neste caso, ele aparece sem nenhum parmetro a sua direita, de executar todas as instrues. As instrues utilizam os parmetros para

somente o ponto-e-vrgula. Quando uma funo no tem um tipo de retorno definido, o compilador C considera que o tipo de retorno adotado void. Do mesmo modo que chamamos uma funo de biblioteca C (printf(), getche(), ...) chamamos nossas prprias funes. Os parnteses que seguem o nome so necessrios para que o compilador possa diferenciar a chamada a uma funo de uma varivel que voc esqueceu de declarar. ser usado. Visto que a chamada de uma funo constitui uma instruo de programa, deve ser encerrada por ponto-e-vrgula. Entretanto, na definio de uma funo, o ponto-e-vrgula no pode

7.2 Exemplos Abaixo apresentamos um exemplo do emprego das funes:


#include <stdio.h> doisbeep() { int k;
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

52

printf("\x7"); for(k=1; k<10000; k++) ;

/* Beep 1 */ /* Gera um pequeno delay */

printf("\x7"); /* Beep 2 */ } /* funao principal */ void main() { doisbeep(); printf("Digite um caractere: "); getche(); doisbeep(); }

A declarao da funo doisbeep() equivalente a seguinte declarao: void doisbeep(void). Isto acontece pois quando o tipo retornado ou o parmetro for void (representando que nenhum dado ser passado), estes podem ser omitidos j que C considera este tipo como default. Em C, todos os argumentos de funes so passados por valor. Isto significa que funo chamada dada uma cpia dos valores dos argumentos, e ela cria outras variveis temporrias para armazenar estes valores. A diferena principal que, em C, uma funo chamada no pode alterar o valor de uma varivel da funo que chama; ela s pode alterar sua cpia temporria. C permite a criao de funes recursivas, isto , uma funo que dentro do seu corpo de instrues {} existe uma chamada de funo a si prpria. Este caso funciona como uma chamada para uma outra funo qualquer. Basta que na definio da funo voc faa uma chamada prpria funo e voc j ter implementado uma funo recursiva. Entretanto, tenha cuidado com funes recursivas para no fazer com que o programa entre em loops infinitos. Exemplo:
long int Fatorial(long int i) { if(i > 1) return i*Fatorial(i-1);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

53

else return 1; }

Cada chamada recursiva da funo fatorial coloca mais uma varivel i do tipo long int na pilha (stack). , portanto, necessrio ter cuidado com funes recursivas, pois estas podem causar um estouro da pilha. Exemplo de funo para calcular a rea da esfera:
#include <stdio.h> float area(float r); void main() { float raio = 0; printf("Digite o raio da esfera: "); scanf("%f", &raio); printf("A area da esfera e' %.2f", area(raio)); } /* funo area () - retorna a area da funcao */ float area(float r) { return (4*3.14159*potencia(r,2)); } /* funcao que eleva a uma potencia positiva um parametro dado */ float potencia(float num, int pot) { float result = 0; int i = 0; if(pot < 0) return 0; if(pot == 0) return 1; result = num;
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

/* declaracao do prototipo da funcao */

float potencia(float num, int pot);

/* definicao da funcao */ /* retorna float */

/* declaracao de var. local */

/* Indica que houve erro */

Informtica para Automao Linguagem de Programao

54

for(i = 1; i < pot; i++) result *= num; return result; }

7.3 Prototipagem Toda funo que for utilizada em main() e que for declarada aps main(), tem que ser prototipada. O prottipo consiste de uma verso simplificada do cabealho da funo, na forma:
<tipo retorno> <nome da funo> (<tipo dos parmetros>);

Se main() for declarado por ltimo, nenhuma prototipagem necessria.

Prottipos so

tambm utilizados para escrever programas compostos de vrios mdulos, como veremos mais frente. Feita a declarao do prottipo da funo, esta poder ser chamada ou definida em qualquer parte do seu programa, por isso que o prottipo de uma funo tem um papel importante para a organizao e flexibilidade do seu cdigo fonte. O programa anterior e o exemplo abaixo apresentam a forma de se criar o prottipo de uma funo.
double Raiz(double); main() { double x,y; x = 4.0; y = Raiz(x); } double Raiz(double valor) { /* <calculo da raiz do valor>; */ return valor; }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

/* prottipo */

Informtica para Automao Linguagem de Programao

55

7.4 Classes de Armazenamento Todas as variveis e funes em C tm dois atributos: um tipo e uma classe de armazenamento. seguir: auto, extern, static e register. 7.4.1 Auto As variveis que temos visto em todos os nossos exemplos esto confinadas nas funes que as usam; isto , so visveis ou acessveis somente s funes onde esto declaradas. Tais variveis so chamadas locais ou automticas, pois so criadas quando a funo chamada e destruda quando a funo termina a sua execuo. As variveis declaradas dentro de uma funo so automticas por default. automticas so as mais comuns dentre as 4 classes. explicitada usando-se a palavra auto. As duas declaraes abaixo so equivalentes:
auto int n; int n;

Os tipos ns j conhecemos.

As 4 classes de armazenamento sero vistas a

Variveis

A classe de variveis automticas pode ser

7.4.2 Extern Todas as funes C e todas as variveis declaradas fora de qualquer funo tm a classe de armazenamento extern. declaradas depois dela. Variveis com este atributo sero conhecidas por todas as funes A declarao de variveis externas feita da mesma maneira como

declaramos variveis dentro do bloco de uma funo. Uma varivel definida fora de qualquer funo dita extern. A palavra extern indica que a funo usar mais uma varivel externa. Este tipo de declarao, entretanto, no obrigatrio se a definio original ocorre no mesmo arquivo fonte. A seguir temos um exemplo:

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

56

#include <stdio.h> int teclanum; void main() { extern teclanum; printf("Digite teclanum: "); scanf("%d", &teclanum); parimpar(); } /* parimpar() - checa se teclanum e' par ou impar */ void parimpar(void) { extern teclanum; if(teclanum % 2) printf("teclanum e' impar. \n"); else printf("teclanum e' par. \n"); } /* Declaracao de variaveis extern */ void parimpar(void); /* Declaracao de funcoes */

7.4.3 Static Variveis static de um lado se assemelham s automticas, pois so conhecidas somente as funes que as declaram e de outro lado se assemelham s externas pois mantm seus valores mesmo quando a funo termina. Declaraes static tm dois usos importantes e distintos. O mais elementar permitir a variveis locais reterem seus valores mesmo aps o trmino da execuo do bloco onde esto declaradas. Exemplo:
#include <stdio.h> void soma(); void main() {

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

57

soma(); soma(); soma(); } /* soma() - usa variavel static */ void soma() { static int i = 0; i++; printf("i = %d\n", i); }

Observe que i no inicializada a cada chamada de soma(). Portanto, a sada ser:


i = 0 i = 1 i = 2

7.4.4 Variveis Estticas Externas O segundo e mais poderoso uso de static associado a declaraes externas. modular. A diferena entre variveis externas e externas estticas que variveis externas podem ser usadas por qualquer funo abaixo de (a partir das) suas declaraes, enquanto que variveis externas estticas somente podem ser usadas pelas funes de mesmo arquivo-fonte e abaixo de suas declaraes. Isto , voc pode definir uma varivel static em um arquivo fonte onde esto todas as funes que necessitam acesso a esta varivel. Os demais arquivos fontes no tero acesso a ela. Junto a

construes externas, permite um mecanismo de privacidade muito importante programao

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

58

7.4.5 Register A classe de armazenamento register indica que a varivel associada deve ser guardada fisicamente numa memria de acesso muito mais rpida chamada registrador. Um registrador da mquina um espao de memria junto ao microprocessador onde se podem armazenar variveis do tipo inteiro ou char. Opera como uma varivel do tipo auto, mas possui um tempo de acesso muito mais rpido, isto , o programa torna-se mais rpido usando register. aumentar a velocidade do programa. Como os computadores possuem um nmero limitado de registradores (2 para o IBM-PC), o seu programa tambm s poder utilizar um nmero limitado de variveis register. nos impede de declarar quantas variveis register quisermos. ocupados o computador simplesmente ignora a palavra register das nossas declaraes.
register int i; for(i = 0; i< 10; i++) printf(Nmero: %d, i);

Variveis que usualmente

utilizam este tipo so as variveis de laos e argumentos de funes, justamente, para que possamos

Mas isto no

Se os registradores estiverem

7.5 Exerccios 7.1 Um nmero primo qualquer inteiro positivo divisvel apenas por si prprio e por 1. Escreva uma funo que receba um inteiro positivo e, se este nmero for primo, retorne 1, caso contrrio retorne 0. Faa um programa que imprima na tela os n primeiros nmeros primos, onde n ser fornecido pelo usurio. 7.2 Crie um programa para gerar nmeros aleatrios, utilizando variveis static para armazenar o valor da semente.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

59

7.3 Crie um programa para calcular o fatorial de um nmero, para tal implemente uma funo recursiva. 7.4 Escreva um programa que solicite ao usurio um ano e imprima o calendrio desse ano. Utilize os programas desenvolvidos nos exerccios 4.2 e 4.3. adequada atravs de funes. 7.5 Escreva uma funo recursiva de nome soma() que receba um nmero inteiro positivo n como argumento e retorne a soma dos n primeiros nmeros inteiros. recebe n = 5, deve retornar 15, pois: 15 = 1 + 2 + 3 + 4 + 5 Por exemplo, se a funo Organize o programa de forma

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

60

8 Diretivas do Pr-Processador
O pr-processador C um programa que examina o cdigo fonte em C e executa certas modificaes no cdigo, baseado em instrues chamadas diretivas. O pr-processador faz parte do compilador e pode ser considerado uma linguagem dentro da linguagem C. automaticamente antes da compilao. Ele executado Diretivas do pr-processador seriam instrues desta

linguagem. As instrues desta linguagem so executadas antes do programa ser compilado e tm a tarefa de alterar os cdigos-fonte, na sua forma de texto. Instrues para o pr-processador devem fazer parte do texto que criamos, mas no faro parte do programa que compilamos, pois so retiradas do texto compilador antes da compilao. Diretivas do pr-processador so instrues para o compilador propriamente dito. Mais precisamente, elas operam diretamente no compilador antes do processo de compilao ser iniciado. Linhas normais de programa so instrues para o microprocessador; diretivas do pr-processador so instrues para o compilador. Todas as diretivas do pr-processador so iniciadas com o smbolo (#). As diretivas podem ser colocadas em qualquer parte do programa, mas costume serem colocadas no incio do programa, antes de main(), ou antes do comeo de uma funo particular.

8.1 Diretiva #define A diretiva #define pode ser usada para definir constantes simblicas com nomes apropriados. Como por exemplo, podemos criar uma constante para conter o valor de pi:
#define PI 3.14159

e depois utilizar o valor desta constante no programa:


area_esfera = (4*raio*raio*PI);

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

61

Quando o compilador encontra #define, ele substitui cada ocorrncia de PI no programa por 3.14159. O primeiro termo aps a diretiva #define (PI), que ser procurada, chamada identificador. O segundo termo (3.14159), que ser substituda, chamada texto. Um ou mais espaos separam o identificador do texto. Note que s podemos escrever um comando deste por linha. para definir constantes, como mostra o exemplo seguinte:
#include <stdio.h> #define { int i; printf("\nDigite um numero entre 0 a 100: "); scanf("%d", &i); if(i<0||i>100) ERRO; } ERRO printf("\n Erro.\n") void main()

Observe tambm que no h

ponto-e-vrgula aps qualquer diretiva do pr-processador. A diretiva #define pode ser usada no s

8.2 Macros A diretiva #define tem a habilidade de usar argumentos. como macro definida e utilizada:
#include <stdio.h> #define { float num1 = 27.25; float num2;
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Uma diretiva #define com

argumentos chamada de macro e bastante semelhante a uma funo. Eis um exemplo que ilustra

PRN(n)

printf("%.2f\n",n);

void main()

Informtica para Automao Linguagem de Programao

62

num2 = 1.0/3.0; PRN(num1); PRN(num2); }

Quando voc usar a diretiva #define nunca deve haver espao em branco no identificador. Por exemplo, a instruo:
#define PRN (n) printf(%.2f\n,n)

no trabalhar corretamente, porque o espao entre PR e (n) interpretado como o fim do identificador. Para definir um texto muito grande devemos delimitar a linha anterior com uma O n na barra invertida \ e prosseguir com a definio em outra linha. Toda ocorrncia de PRN(n) em seu programa substituda por printf(%.2f\n,n). PRN(num1)ser substitudo por printf(%.2f\n,num1). para expresses. definio da macro substitudo pelo nome usado na chamada a macro em seu programa; portanto, Assim, n age realmente com um argumento. Macros aumentam a clareza do cdigo, pois permitem a utilizao de nomes sugestivos Por segurana, coloque parnteses envolvendo o texto todo de qualquer diretiva #define que use argumentos, bem como envolvendo cada argumento. Por exemplo:
#define SOMA(x,y) x+y

ans = 10 * SOMA(3,4);

O complilador substitura SOMA(3,4) por 3+4, e o computador executar:


ans = 10 * 3+4;

ou seja, um erro. Para evitar isto, voc deve definir a macro da seguinte forma:
#define SOMA(x,y) ((x)+(y))

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

63

Como macros so simples substituies dentro dos programas, o seu cdigo aparecer em cada ponto do programa onde forem usadas. Assim, a execuo do programa ser mais rpida que a chamada a uma funo toada vez que se fizer necessrio. Em contra partida, o cdigo do programa ser aumentado, pois o cdigo da macro ser duplicado cada vez que a macro for chamada. Outra vantagem do uso de macros a no necessidade de especificar o tipo do dado.

8.3 Diretiva #undef A diretiva #undef remove a mais recente definio criada com #define.
#define #define #define ... #undef #define ... #undef #undef #undef ENORME ENORME SOMA /* ENORME volta a valer 8 */ /* cancela a definio de ENORME */ /* cancela a macro SOMA */ GRANDE ENORME 10 /* cancela a definio de GRANDE */ /* redefine ENORME para o valor 10 */ GRANDE ENORME 3 8 ((x)+(y))

SOMA(x,y)

Observe que, para remover uma macro, somente o nome da macro deve constar na diretiva #undef. No deve ser includa a lista de argumento.

8.4 Diretiva #include A diretiva #include causa a incluso de um cdigo fonte em outro. Aqui est o exemplo de sua utilidade: suponha que voc escreveu vrias frmulas matemticas para calcular reas de diversas figuras.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

64

Os arquivos de incluso so textos escritos em caracteres ASCII normais, criados geralmente para incorporar definies de constantes, macros, prottipos de funes, definies de tipos de dados complexos e declaraes de variveis externas. Geralmente, os arquivos de incluso tm nome Por exemplo, o arquivo conio.h contm o terminado com o sufixo .H (header ou cabealho). destas funes. Voc pode colocar estas frmulas em macros em um programa separado. este arquivo no seu cdigo fonte. Exemplo:
#define PI 3.14159 #define AREA_CIRCULO(raio) (PI*(raio)*(raio)) #define AREA_RETANG(base,altura) ((base)*(altura)) #define AREA_TRIANG(base,altura) ((base)*(altura)/2)

prottipo das funes getch() e getche() e por esse motivo includo nos programas que fazem uso No instante em

que voc precisar reescrev-las para a utilizao em seu programa use a diretiva #include para inserir

Grave o programa acima como areas.h.

Quando voc quiser utilizar estas macros, basta

incluir nos seus outros programas uma das diretivas:


#include <areas.h> /* para arquivos localizados na biblioteca */ /* do compilador */ #include areas.h /* para arquivos locais ou localizados */ /* na biblioteca do compilador */

O uso consciente das diretivas #define e #include podem melhorar e muito o desempenho e a organizao dos seus projetos de software. potenciais. Procure explor-las para conhecer todo os seus

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

65

8.5 Compilao Condicional O pr-processador oferece diretivas que permitem a compilao condicional de um programa. Elas facilitam o desenvolvimento do programa e a escrita de cdigos com maior portabilidade de uma mquina para outra ou de um ambiente a outro. So elas, as diretivas: #if, #ifdef, #ifndef, #elif, #else e #endif Cada diretiva #if deve terminar pela diretiva #endif. se estiver presente, deve ser a ltima anterior a #endif. condicional:
#define DEBUG 1 ... #if DEBUG == 1 printf(\nERRO = , erro1); #elif DEBUG == 2 printf(\nERRO = , erro2); #else printf(\nERRO no documentado.); #endif

Entre #if e #endif pode ser colocado

qualquer nmero de #elif, mas s se permite uma nica diretiva #else. A diretiva #else opcional e, Abaixo apresentamos um exemplo onde definimos o valor de uma constante com #define e depois a utilizamos para fazer uma compilao

Para testar constantes definidas com #define que no tenham valor nenhum, podemos utilizar #ifdef e #ifndef. Por exemplo:
#define VERSAO_DEMO ... #ifdef VERSAO_DEMO #define NUM_REC 20 #include progdemo.h
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

66

else #define NUM_REC MAXINT #include program.h #endif

O ltimo exemplo mostra como um nico programa-fonte pode gerar dois executveis diferentes: se a diretiva que define VERSAO_DEMO for inserida, o executvel poder manipular somente 20 registros e estar criada a verso demo de seu programa. Caso esta diretiva no esteja presente, o programa poder manipular o nmero mximo de registros. A diretiva #ifndef verifica a no-definio da constante. Por exemplo:
#ifndef WINDOWS #define VERSAO \nVerso DOS #else #define VERSAO \nVerso Windows #endif

8.6 Operador defined Uma alternativa ao uso de #ifdef e #ifndef o operador defined.
#if defined(UNIX) && !defined(INTEL_486) ... #endif

8.7 Diretiva #error A diretiva #error provoca uma mensagem de erro do compilador em tempo de compilao.
#if TAMANHO > TAMANHO1
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

67

#error Tamanho incompatvel #endif

8.8 diretiva #pragma


#pragma inline - indica ao compilador C a presena de cdigo Assembly no arquivo. #pragma warn - indica ao compilador C para ignorar "warnings" (avisos)

8.9 Exerccios 8.1 Escreva uma macro que tenha valor 1 se o seu argumento for um nmero mpar, e o valor 0 se for par. 8.2 Escreva uma macro que encontre o maior entre seus trs argumentos. 8.3 Escreva uma macro que tenha valor 1 se o seu argumento for um caractere entre 0 e 9, e 0 se no for. 8.4 Escreva uma macro que converta um dgito ASCII entre 0 e 9 a um valor numrico entre 0 e 9. 8.5 Escreva um programa que solicite ao usurio uma letra e retorne o nmero equivalente desta letra na tabela ASCII em decimal e hexadecimal. Utilize a compilao condicional para gerar um programa com interface para diferentes lnguas, por exemplo, uma para portugus e outra para ingls. Caso nenhuma das duas for definida, gere um erro de compilao. Dica, coloque o texto de cada lngua em um header diferente. Por exemplo, os textos em portugus ficam definidos em progport.h e os textos em ingls em progingl.h. 8.6 Faa com que o programa do exerccio 7.4, escreva o calendrio de um ano qualquer dado pelo usurio em trs lnguas diferentes: alemo, ingls e portugus. Utilize a mesma idia que o programa anterior.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

68

9 Matrizes
Uma matriz um tipo de dado usado para representar uma certa quantidade de variveis de valores homogneos. Imagine que voc esteja precisando armazenar e manipular as notas de um ano inteiro de um conjunto de 40 alunos. Voc certamente precisar de uma maneira conveniente para referenciar tais colees de dados similares. Matriz o tipo de dado oferecido por C para este propsito. Um matriz uma srie de variveis do mesmo tipo referenciadas por um nico nome, onde cada varivel diferenciada atravs de um nmero chamado subscrito ou ndice. Colchetes so usados para conter o subscrito. A declarao:
int notas[5];

aloca memria para armazenar 5 inteiros e anuncia que notas uma matriz de 5 membros ou elementos. Vamos agora fazer um programa que calcula a mdia das notas da prova do ms de Junho de 5 alunos.
#include <stdio.h> #define { int notas[NUM_ALUNOS]; int i, soma; for(i=0; i<NUM_ALUNOS; i++) { printf("Digite a nota do aluno %d: ", i); scanf("%d", &notas[i]); /* atribuindo valores a matriz */ } soma = 0; for(i=0; i<NUM_ALUNOS; i++) soma = soma + notas[i]; /* lendo os dados da matriz */ printf("Media das notas: %d.", soma/NUM_ALUNOS); }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

NUM_ALUNOS

void main() /* Declaracao de matrizes */

Informtica para Automao Linguagem de Programao

69

9.1 Sintaxe de Matrizes As dimenses so definidas entre colchetes, aps a definio convencional do tipo de varivel.
<Tipo> <nome> [<dimenso1>] [<dimenso2>] ... ;

Em C, matrizes precisam ser declaradas, como quaisquer outras variveis, para que o compilador conhea o tipo de matriz e reserve espao de memria suficiente para armazen-la. Os elementos da matriz so guardados numa seqncia contnua de memria, isto , um seguido do outro. O que diferencia a declarao de uma matriz da declarao de qualquer outra varivel a parte que segue o nome, isto , os pares de colchetes [ e ] que envolvem um nmero inteiro, que indica ao compilador o tamanho da matriz. A dimenso da matriz vai depender de quantos pares de colchetes a declarao da matriz tiver. Por exemplo:
int notas[5]; /* declarao de uma matriz unidimensional = vetor */ unsigned float tabela[3][2]; /* matriz bidimensional */ char cubo[3][4][6]; /* matriz tridimensional */

Analisando-se a primeira declarao: a palavra int declara que todo elemento da matriz do tipo int, notas o nome dado a matriz e [5] indica que a nossa matriz ter 5 elementos do tipo int. Por definio uma matriz composta por elementos de um nico tipo. O acesso aos elementos da matriz feito atravs do nmero entre colchetes seguindo o nome da matriz. Observe que este nmero tem um significado diferente quando referencia um elemento da matriz e na declarao da matriz, onde indica o seu tamanho. matriz so sempre numerados por ndices iniciados por 0 (zero). nmero 2:
notas[2]

Quando referenciamos um Os elementos da O elemento referenciado pelo

elemento da matriz este nmero especifica a posio do elemento na matriz.

no o segundo elemento da matriz mas sim o terceiro, pois a numerao comea em 0. Assim o ltimo elemento da matriz possui um ndice, uma unidade menor que o tamanho da matriz.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

70

O acesso com notas[i] pode ser tanto usado para ler ou escrever um dado na matriz. Voc pode tratar este elemento como um varivel simples, no caso de notas[i], como uma varivel inteira qualquer. Como proceder caso voc no conhea a quantidade de termos que voc precisa para a tua matriz? Aplique a idia apresentada no programa exemplo acima, com a diretiva:
#define NUM_ALUNOS 5

para alocar um nmero maior de termos, de forma a possuir espao suficiente alocado para conter todos os possveis termos da matriz. Ateno: A linguagem C no realiza verificao de limites em matrizes; por isto nada impede que voc v alm do fim da matriz. Se voc transpuser o fim da matriz durante uma operao de atribuio, ento atribuir valores a outros dados ou at mesmo a uma parte do cdigo do programa. Isto acarretar resultados imprevisveis e nenhuma mensagem de erro do compilador avisar o que est ocorrendo. Como programador voc tem a responsabilidade de providenciar a verificao dos limites, sempre que necessrio. Assim a soluo no permitir que o usurio digite dados, para elementos da matriz, acima do limite.

9.2 Inicializando Matrizes Em C a inicializao de uma matriz feita em tempo de compilao. Matrizes das classes extern e static podem ser inicializadas. Matrizes da classe auto no podem ser inicializadas. O programa a seguir exemplifica a Lembre-se de que a inicializao de uma varivel feita na instruo de sua declarao e uma maneira de especificarmos valores iniciais pr-fixados. inicializao de uma matriz:
#include <stdio.h> #define {
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

LIM

void main()

Informtica para Automao Linguagem de Programao

71

int d, valor, quant; static int tab[] = {50, 25, 10, 5, 1}; printf("Digite o valor em centavos: "); scanf("%d", &valor); for(d=0; d<LIM; d++) { quant = valor/tab[d]; printf("Moedas de %d centavos = %2d\n", tab[d], quant); valor %= tab[d]; } }

A instruo que inicializa a matriz :


static int tab[] = {50, 25, 10, 5, 1};

A lista de valores colocada entre chaves e os valores so separados por vrgulas. Note que no foi necessria a declarao da dimenso da matriz.

Os

valores so atribudos na seqncia, isto , tab[0] = 50, tab[1] 25, tab[2] 10 e assim por diante. Caso tivssemos escrito explicitamente a dimenso da matriz, esta deveria se maior ou igual a dimenso fornecida pelo colchetes. Se h menos inicializadores que a dimenso especificada, os outros sero zero. um erro ter-se mais inicializadores que o necessrio. Se em seu programa voc deseja inicializar uma matriz, voc deve criar uma varivel que existir durante toda a execuo do programa. As classes de variveis com esta caracterstica so extern e static. A linguagem C permite matrizes de qualquer tipo, incluindo matrizes de matrizes. Por exemplo, uma matriz de duas dimenses uma matriz em que seus elementos so matrizes de uma dimenso. Na verdade, em C, o termo duas dimenses no faz sentido pois todas as matrizes so de uma dimenso. Usamos o termo mais de uma dimenso para referncia a matrizes em que os elementos so matrizes.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

72

As matrizes de duas dimenses so inicializadas da mesma maneira que as de dimenso nica, isto , os elementos (matrizes) so colocados entre as chaves depois do sinal de igual e separados por vrgulas. Cada elemento composto por chaves e seus elementos internos separados por vrgulas. Como exemplo segue abaixo uma matriz bidimensional:
char tabela[3][5] = { {0, 0, 0, 0, 0}, {0, 1, 1, 1, 0}, {1, 1, 0, 0, 1} };

Cada elemento da matriz tabela na verdade ser outra matriz, ento, por exemplo:
tabela[2] == {1, 1, 0, 0, 1}

Da mesma maneira se aplica para matrizes de trs ou mais dimenses:


int tresd[3][2][4] = { { {1, 2, 3, 4} , {5, 6, 7, 8} }, { {7, 9, 3, 2} , {4, 6, 8, 3} }, { {7, 2, 6, 3} , {0, 1, 9, 4} } };

A matriz de fora tem trs elementos, cada um destes elementos uma matriz de duas dimenses de dois elementos onde cada um dos elementos uma matriz de uma dimenso de quatro nmeros. Como podemos acessar o nico elemento igual a 0 na matriz do exemplo anterior? O primeiro ndice [2], pois o terceiro grupo de duas dimenses. O segundo ndice [1], pois o segundo de duas matrizes de uma dimenso. O terceiro ndice [0], pois o primeiro elemento da matriz de uma dimenso. Ento, temo que a primitiva abaixo verdade:
tresd[2][1][0] == 0

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

73

9.3 Matrizes como Argumentos de Funes C permite passar um matriz como parmetro para uma funo. A seguir apresentamos como exemplo o mtodo de Ordenao Bolha como exemplo de passagem de matrizes como argumentos. Este um mtodo famoso de ordenao de elementos em uma matriz devido a sua simplicidade e eficincia. A funo comea considerando a primeira varivel da matriz, list[0]. O objetivo colocar o menor item da lista nesta varivel. Assim, a funo percorre todos os itens restantes da lista, de list[1] a list[tam-1], comparando cada um com o primeiro item. Sempre que encontrarmos um item menor, eles so trocados. Terminada esta operao, tomado o prximo item, list[1]. Este item dever conter o prximo menor item. E novamente so feitas as comparaes e trocas. O processo continua at que a lista toda seja ordenada.
#include <stdio.h> #define TAMAX 30 void ordena(int list[], int tam); void main() { int list[TAMAX], tam=0, d; do { printf("Digite numero: "); scanf("%d", &list[tam]); } while(list[tam++] != 0); ordena(list, --tam); for(d=0; d<tam; d++) printf("%d\n", list[d]); } /* ordena() - ordena matriz de inteiros */ void ordena(int list[], int tam) { int register j, i; int temp;
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

74

for(j = 0; j < tam-1; j++) for(i = j + 1; i < tam; i++) if(list[j] > list[i]) { temp = list[i]; list[i] = list[j]; list[j] = temp; } }

O nico elemento novo no programa acima a instruo:


ordena(list, --tam);

ela uma chamada funo ordena() que ordena os elementos de uma matriz segundo o mtodo bolha. Esta funo tem dois argumentos: o primeiro a matriz list e o segundo a varivel que A matriz foi passada como argumento da funo quando escrevemos somente o seu nome como parmetro da funo. Quando desejamos referenciar um elemento da matriz devemos acesslo atravs do nome da matriz seguida de colchetes, onde o ndice do elemento escrito entre os colchetes. Entretanto, se desejamos referenciar a matriz inteira, basta escrever o nome desta, sem colchetes. O nome de uma matriz desacompanhada de colchetes representa o endereo de memria onde a matriz foi armazenada. O operador & no pode ser aplicado a matriz para se obter o endereo desta, pois, a endereo da matriz j est referenciado no seu nome. Portanto, a instruo abaixo seria invlida:
&list;

contm o tamanho da matriz.

O operador & somente pode ser aplicado a um elemento da matriz. Portanto, a instruo:
int * ptr = &list[0];

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

75

ser vlido e ir retornar o endereo da primeira varivel da matriz. da matriz e do primeiro elemento sero equivalentes:
list == &list[0];

Como a rea de memria

ocupada por uma matriz comea atravs do primeiro termo armazenado nesta, portanto, os endereos

Assim, a funo ordena() recebe um endereo de uma varivel int e no um valor inteiro e deve declar-lo de acordo. O tipo :
int []

indica um endereo de uma varivel int.

9.4 Chamada Por Valor e Chamada Por Referncia Quando um nome de uma simples varivel usado como argumento na chamada a uma funo, a funo toma o valor contido nesta varivel e o instala em uma nova varivel e em nova posio de memria criada pela funo. Portanto as alteraes que forem feitas nos parmetros da funo no tero nenhum efeito nas variaes usadas na chamada. Este mtodo conhecido como chamada por valor. Entretanto, as matrizes so consideradas um tipo de dado bastante grande, pois so formadas por diversas variveis. Por causa disto, a linguagem C++ determina ser mais eficiente existir uma nica cpia da matriz na memria, sendo, portanto, irrelevante o nmero de funes que a acessem. Assim, no so passados os valores contidos na matriz, somente o seu endereo de memria. Desta forma, a funo usa o endereo da matriz para acessar diretamente os elementos da prpria matriz da funo que chama. Isto significa que as alteraes que forem feitas na matriz pela funo afetaro diretamente a matriz original.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

76

Quando se passa o nome de uma matriz para uma funo, no se cria uma cpia dos dados desta mas sim, utiliza-se diretamente os dados da matriz original atravs do endereo passado. Esta tipo de passagem de parmetros denominado passagem de parmetros por referncia. A seguir apresentamos um exemplo de passagem de uma matriz bidimensional como parmetro de uma funo. O programa exemplo avalia a eficincia de funcionrios de uma loja, quanto ao nmero de peas vendidas por cada um. O primeiro ndice da matriz indica o nmero de funcionrios da loja e o segundo ndice, o nmero de meses a serem avaliados.
#include <stdio.h> #define FUNC 4 #define MES 3 #define MAXBARRA 50 /* numero de funcionarios */ /* numero de meses */ /* tamanho maximo da barra */

void grafico(int p[][MES], int nfunc); /* declaracao da funcao */ void main() { int pecas[FUNC][MES]; /* declaracao de matriz bidimensional*/ int i, j; for(i=0; i<FUNC; i++) for(j=0; j<MES; j++) { printf("Numero de pecas vendidas pelo funcionario"); printf("%d no mes %d: ", i+1, j+1); scanf("%d", &pecas[i][j]); } grafico(pecas, FUNC); } /* grafico() - desenha um histograma */ void grafico(int p[][MES], int nfunc) { int register i, j; int max, tam = 0, media[FUNC];

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

77

for(i=0; i<nfunc; i++) { media[i] = 0; for(j=0; j<MES; j++) media[i] += p[i][j]; media[i] /= MES; } max = 0; for(i = 0; i< nfunc; i++) if(media[i]>max) max = media[i]; printf("\n\n\n\n FUNC - MEDIA\n--------------\n"); for(i=0;i<FUNC; i++) { printf("%5d - %5d : ", i+1, media[i]); if(media[i]>0) { if((tam=(int)(((float)media[i])*MAXBARRA/max)) <= 0) tam = 1; } else tam = 0; for(; tam>0; --tam) printf("%c", '>'); printf("\n"); } }

O mtodo de passagem do endereo da matriz para a funo idntico ao da passagem de uma matriz de uma dimenso, no importando quantas dimenses tem a matriz, visto que sempre passamos o seu endereo.
grafico(pecas, FUNC);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

78

Como no h verificao de limites, uma matriz com a primeira dimenso de qualquer valor pode ser passada para a funo chamada. Mas uma funo que recebe uma matriz bidimensional dever ser informada do comprimento da segunda dimenso para saber como esta matriz est organizada na memria e assim poder operar com declaraes do tipo:
pecas[2][1]

pois, para encontrar a posio na memria onde pecas[2][1] est guardada, a funo multiplica o primeiro ndice (2) pelo nmero de elementos da segunda dimenso (MES) e adiciona o segundo ndice (1), para finalmente somar ao endereo da matriz (pecas). Caso o comprimento da segunda matriz no seja conhecido, ser impossvel saber onde esto os valores. 9.5 Strings C no possui um tipo de dado especial para tratar strings. Desta forma, uma das aplicaes mais importante de matrizes em C justamente a criao do tipo string, caracterizado por uma sequncia de caracteres armazenados terminados por \0 (que possui o valor 0 na tablea ASCII) em uma matriz. Por esta razo que C no fornece uma estrutura amigvel para a manipulao de Somente com o advento da string comparada com outras linguagens como Pascal, por exemplo.

orientao a objetos (C++) que C veio a fornecer uma estrutura amigvel e flexvel para tratar strings. Esta estrutura ser vista somente nos captulos posteriores. Aqui, apresentaremos string na sua forma bsica em C. String uma matriz tipo de char que armazena um texto formado de caracteres e sempre terminado pelo caractere zero (\0). Em outras palavras, string uma srie de caracteres, onde cada um ocupa um byte de memria, armazenados em seqncia e terminados por um byte de valor zero (\0). Cada caractere um elemento independente da matriz e pode ser acessado por meio de um ndice.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

79

9.5.1 Strings Constantes Qualquer seqncia de caracteres delimitadas por aspas duplas considerada pelo compilador como uma string constante. O compilador aloca uma matriz com tamanho uma (1) unidade maior que o nmero de caracteres inseridos na string constante, armazenando estes caracteres nesta matriz e adicionando automaticamente o caractere delimitador de strings \0 no final da matriz. Vrios exemplos de strings constantes esto presentes ao longo de texto, exemplos como :
printf(Bom Dia!!!!);

O importante lembrar que o compilador sempre adiciona o caractere \0 a strings constantes antes de armazen-las na forma de matriz para poder marcar o final da matriz. Observe que o caractere \0, tambm chamado de NULL, tem o valor zero decimal (tabela ASCII), e no se trata do caractere 0, que tem valor 48 decimal (tabela ASCII). A terminao \0 importante, pois a nica maneira que as funes possuem para poder reconhecer onde o fim da string. 9.5.2 String Variveis Um das maneiras de receber uma string do teclado atravs da funo scanf() pelo formato %s. A funo scanf() l uma string at voc apertar a tecla [enter], adiciona o caractere \0 e armazena em uma matriz de caracteres. Perceba que o endereo da matriz e passado escrevendo-se somente o nome da matriz. Abaixo apresentamos um exemplo, nele fica claro que se voc digitar uma frase com um nmero maior de caracteres do que a matriz alocada, (char[15]) um erro de memria ir ocorrer. Isto se deve ao fato de scanf() no testar a dimenso de matriz e simplesmente adquirir uma seqncia de caracteres at encontrar um caractere do [enter], espao simples ou tabulao. Depois ela armazena a string na matriz fornecida, sem testa a dimenso da matriz. A definio de uma string segue o mesmo formato da definio de matrizes, entretanto o tipo empregado o tipo char.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

80

#include <stdio.h> void main() { char nome[15]; /* declara uma string com 15 caracteres */ printf("Digite seu nome: "); scanf("%s", nome); printf("Saudacoes, %s.", nome); }

Se voc escrever Pedro Silva no programa acima, a funo scanf() ir eliminar o segundo nome. Isto se deve por que scanf() utiliza qualquer espao, quebra de linha ou tabulao para Neste caso, a funo gets() se aplica de forma mais eficiente para a aquisio de strings. A funo gets() adquire uma string at se pressionada a tecla [enter], adicionando o caractere \0 para especificar o fim da string e armazen-la em uma matriz. Desta forma podemos utilizar gets() para ler strings com espaos e tabulaes. Para imprimir strings utilizamos as duas funes principais printf() e puts(). O formato de impresso de strings com prinf() ns j conhecemos, basta escrever o parmetro %s no meio da string de formatao de printf() e posteriormente passar o nome da matriz de caracteres, terminada com \0, como parmetro. Puts() tem uma sintaxe bem simples tambm. Chamando a funo puts() e passando-se o nome da matriz de caracteres terminada por \0 como parmetro, teremos a string impressa na tela (sada padro) at encontrar o caractere \0. Aps a impresso, puts() executa uma quebra de linha automaticamente [enter], o que impossibilita a sua aplicao para escrever duas strings na mesma linha. Abaixo, temos um exemplo:
char nome[] = Carlos Henrique; puts(nome);

determinar o fim da leitura de uma string.

Em C, a forma formal da inicializao de strings ocorre da mesma maneira que uma matriz, ou seja, inicializamos termo por termo como a seguir:
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

81

char text[] = {B, o, m, , d, i, a, !, \0};

C fornece ainda uma maneira bem simples, que foi apresentada no outro exemplo acima. Note que na forma formal de inicializao temos que adicionar explicitamente o caractere \0 para determinar o fim da matriz. J na forma simples, o compilador faz isto automaticamente para voc. 9.5.3 Funes para Manipulao de Strings Em C existem vrias funes para manipular matrizes e tentar tornar a vida do programador um pouco mais fcil. Veremos aqui as 4 funes principais: strlen(), strcat(), strcmp() e strcpy(). Note que estas funes exigem que o caractere \0 esteja delimitando o final da string. A funo strlen() aceita um endereo de string como argumento e retorna o tamanho da string armazenada a partir deste endereo at um caractere antes de 0, ou seja, ela retorna o tamanho da matriz que armazena a string menos um, descontando assim o caractere de final da string \0. Sintaxe:
strlen(string);

A funo strcat() concatena duas strings, isto , junta uma string ao final de outra. Ela toma dois endereos de strings como argumento e copia a segunda string no final da primeira e esta combinao gera uma nova primeira string. A segunda string no alterada. Entretanto, a matriz da primeira string deve conter caracteres livres (ou seja, caracteres alocados localizados aps o delimitador de final de string \0) suficientes para armazenar a segunda string. A funo strcat() no verifica se a segunda string cabe no espao livre da primeira. Sintaxe de strcat():
strcat(string1, string2);

A funo strcmp() compara duas strings e retorna: <0 0 >0 : : : no caso da string 1 < que a string 2 no caso da string 1 = a string 2 no caso da string 1 > que a string2

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

82

Neste contexto, menor que (<) ou maior que (>) indica que, se voc colocar string1 e string2 em ordem alfabtica, o que aparecer primeiro ser menor que o outro. Sintaxe:
strcmp(string1, string2);

A funo strcpy() simplesmente copia uma string para outra. Note, que a string1 deve conter espao suficiente para armazenar os dados da string2. Sintaxe:
strcpy(string1, string2);

Abaixo vamos mostrar um exemplo que apagar um caractere do interior de uma string. Neste exemplo vamos implementar a funo strdel() que move, um espao esquerda, todos os caracteres que esto a direita do caractere sendo apagado.
#include <stdio.h> void strdel(char str[], int n); void main() { char string[81]; int posicao; printf("Digite string, [enter], posicao\n"); gets(string); scanf("%d", &posicao); strdel(string, posicao); puts(string); } /* strdel() - apaga um caractere de uma string */ void strdel(char str[], int n) { strcpy(&str[n], &str[n+1]); }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

83

9.6 Exerccios 9.1 Crie um programa para calcular a matriz transposta de uma dada matriz. inicializar a matriz com zero. Aloque uma

memria para uma matriz bidimensional com dimenso mxima de 10x10. Crie uma funo para Depois questione o usurio para sob a dimenso da matriz que ele Depois, adquira os deseja calcular a transposta, considerando a dimenso mxima permitida. calcule a transporta da matriz e escreva na tela o resultado final da matriz. 9.2 Continue o programa anterior e agora calcule o tamanho de memria alocada para a matriz e que no est sendo utilizada. Ou seja, considerando o tipo de dado da matriz, que a matriz inicial tem tamanho 10x10 e o tamanho utilizado pelo usurio, quantos bytes de memria o computador alocou para a matriz e quantos bytes de memria o usurio realmente utilizou. este problema. 9.3 A decomposio LDU uma decomposio famosa de matrizes aplicada para calcular inversas de matrizes e resolver problemas de equaes lineares. Utilize o programa 9.1 e crie um programa que calcule a decomposio LDU de uma matriz, preferencialmente, com pivotamento. 9.4 Escreva uma funo que indique quantas vezes aparece um determinado caractere em uma dada string. 9.5 Escreva uma funo que localize um caractere em uma string, substituindo-a por outro. 9.6 Escreva uma funo que insira um determinado caractere em uma determinada posio de uma string. 9.7 Escreva uma funo que retire todos os caracteres brancos, tabulaes ou nova linha [enter] de uma dada string. 9.8 Escreva um programa que converta todas os caracteres minsculos de uma string para o correspondente caractere maisculo. 9.9 Refaa o seu exerccio 6.2 para criar uma tabela com os seus horrios ocupados e compromissos na semana. strings. Armazene o valor de cada compromisso atravs de uma tabela de Inicialize a tabela com valor 0, e solicite ao usurio que fornea o seu horrio. Por fim, Crie uma funo que calcule este dado comparando duas matrizes de dimenses quaisquer. Reflita sobre

valores dos termos que compem a matriz, solicitando ao usurio que fornea estes dados. Por fim,

apresente na tela o resultado obtido.


Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

84

10 Tipos Especiais de Dados


Em C podemos definir novos tipos de dados, adicionando complexidade aos tipos de dados j existentes. Com a finalidade de tornar a vida do programador mais fcil e permitir que este crie novos tipos de dados, compostos pelos tipos de dados j pr-existentes (char, int, float, double e matrizes destes tipos). 10.1 Typedef Typedef nos apresenta a primeira forma de criar um novo tipo de dado. Typedef permite a definio de novos tipos de variveis. Os novos tipos so sempre compostos de uma ou mais variveis bsicas agrupadas de alguma maneira especial. Sintaxe:
typedef <tipo> <definio>;

Exemplo da definio de um novo tipo de dado:


typedef double real_array [10]; real_array x, y; /* novo tipo */

/* declara variveis tipo real_array */

No exemplo acima, ambas x e y foram declaradas como sendo do tipo real-array e, por isso, representam um vetor de valores reais (double) com capacidade para armazenar 10 dados deste tipo. 10.2 Enumerados (Enum) Permitem atribuir valores inteiros seqenciais constantes. Tipos enumerados so usados

quando conhecemos o conjunto de valores que uma varivel pode assumir. A varivel deste tipo sempre int e, para cada um dos valores do conjunto, atribumos um nome significativo para represent-lo. A palavra enum enumera a lista de nomes automaticamente, dando-lhes nmeros em
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

85

seqncia (0, 1, 2, etc.). A vantagem que usamos estes nomes no lugar de nmeros, o que torna o programa mais claro. Abaixo so apresentados exemplos da aplicao de tipos enumerados e suas definies:
enum dias { segunda, terca, quarta, quinta, sexta, sabado, domingo }; enum cores { verde = 1, azul = 2, preto, /*no foi dado valor, recebe valor anterior + 1 = 3*/ branco = 7 }; enum boolean { false, true }; void main() { enum dias dia1, dia2; /*declara varivel "dias" do tipo enum*/ enum boolean b1; dia1 = terca; dia2 = terca + 3; if (dia2 == sabado) b1 = true; }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

/* atribui: segunda = 0; */ /* atribui: terca = 1; */ /* atribui: quarta = 2; */ /* atribui: quinta = 3; */ /* atribui: sexta = 4; */ /* atribui: sabado = 5; */ /* atribui: domingo = 6; */

/* false = 0 */ /* true = 1 */

/*declara varivel do tipo enum boolean*/ /* dia2 = sexta */

Informtica para Automao Linguagem de Programao

86

A palavra enum define um conjunto de nomes com valores permitidos para esse tipo e enumera esses nomes a partir de zero (default) ou, como em nosso programa, a partir do primeiro valor fornecido. Se fornecermos um valor a alguns nomes e no a outros, o compilador atribuir o prximo valor inteiro aos que no tiverem valor. A sintaxe fica clara no exemplo acima. Um varivel de tipo enumerado pode assumir qualquer valor listado em sua definio. Valores no listados na sua definio no podem ser assumidos por esta varivel. permitida com eles. 10.3 Estruturas (Struct) Estruturas permitem definir estruturas complexas de dados, com campos de tipos diferentes. Observe que nas matrizes (arrays), todos os campos so do mesmo tipo. dados. Por meio da palavra-chave struct definimos um novo tipo de dado. Definir um tipo de dado significa informar ao compilador o seu nome, o seu tamanho em bytes e o formato em que ele deve ser armazenado e recuperado na memria. Aps ter sido definido, o novo tipo existe e pode ser Abaixo apresentamos as utilizado para criar variveis de modo similar a qualquer tipo simples. variveis deste tipo: As structs permitem, entretanto, criar elementos semelhantes a arrays, mas composta de elementos com tipos diferentes de Tipos enumerados so tratados internamente como inteiros, portanto qualquer operao vlida com inteiros

duas sintaxes que podem ser empregadas para a definio de estruturas e para a declarao de

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

87

Definir uma estrutura no cria nenhuma varivel, somente informa ao compilador as caractersticas de um novo tipo de dado. No h nenhuma reserva de memria. A palavra struct indica que um novo tipo de dado est sendo definido e a palavra seguinte ser o seu nome. Desta forma, faz-se necessrio a declarao de variveis deste tipo. Na primeira sintaxe, mostramos no exemplo como podemos declarar um varivel do tipo da estrutura Dados_Pessoais j na definio da estrutura (P1) e como podemos criar outras variveis deste tipo ao longo do programa (P2 e P3). J na segunda sintaxe, a forma da declarao de variveis deve ser sempre explcita, como mostrado no exemplo. Uma vez criada a varivel estrutura, seus membros podem ser acessados por meio do operador ponto. O operador ponto conecta o nome de uma varivel estrutura a um membro desta. Abaixo, fornecemos exemplos de acesso as variveis definidas por meio de estruturas:
gets(P1.Nome); P1.Idade = 41; P3.Peso = 75.6;

A linguagem C trata os membros de uma estrutura como quaisquer outras variveis simples. Por exemplo, P1.Idade o nome de uma varivel do tipo int e pode ser utilizada em todo lugar onde

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

88

possamos utilizar uma varivel int. uma matriz. Veja um exemplo:


struct data { int dia; char mes[10]; int ano; };

A inicializao de estruturas semelhante inicializao de

data natal = { 25, Dezembro, 1994}; data aniversario = { 30, Julho, 1998};

Uma varivel estrutura pode ser atribuda atravs do operador igual (=) a outra varivel do mesmo tipo:
aniversario = natal;

Certamente constatamos que esta uma estupenda capacidade quando pensamos a respeito: todos os valores dos membros da estrutura esto realmente sendo atribudos de uma nica vez aos correspondentes membros da outra estrutura. Isto j no possvel, por exemplo, com matrizes. Estruturas no permitem operaes entre elas, somente entre os seus membros. Aps definirmos um tipo de dado atravs de uma estrutura, podemos incluir este tipo de dado como membro de uma outra estrutura. Isto cria o que chamamos tipos aninhados de estruturas, onde uma estrutura contm no seu interior como membro outra estrutura. Esta operao funciona assim como uma matriz bidimensional na verdade uma matriz de matrizes unidimensionais. Estruturas podem ser passadas para funes assim como qualquer outra varivel, sendo declarada e utilizada da mesma forma. resultado do seu processamento. mais de um parmetro. Podemos criar uma matriz para estruturas assim como criamos uma matriz de um tipo qualquer, basta declarar o tipo da matriz como o tipo definido pela estrutura. A seguir apresentamos
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Funes podem tambm retornar uma estrutura como o

Para tal, basta declarar o tipo de retorno de uma funo como

sendo um tipo declarado por uma struct. Esta uma forma de fazer com que uma funo retorne

Informtica para Automao Linguagem de Programao

89

um exemplo envolvendo matrizes de estruturas, onde trataremos de uma matriz de estruturas que contm os dados necessrios para representar um livro. A forma de acesso aos membros da estrutura, armazenadas na matriz fica clara no exemplo. As funes atoi() e atof() apresentadas no exemplo abaixo servem para converter strings para um tipo inteiro ou float, respectivamente, e esto definidas em stdlib.
#include <stdio.h> #include <stdlib.h> /* definioes de tipo */ struct list { char titulo[30]; char autor[30]; int regnum; double preco; }; /* declaracao de variaveis e funcoes*/ struct list livro[50]; int n = 0; void novonome(); void listatotal(); void main() { char ch; while(1) { printf("\nDigite 'e' para adicionar um livro"); printf("\n'l' para listar todos os livros: "); ch = getche(); switch(ch) { case 'e' : novonome();
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

/* para atof() e atoi() */

Informtica para Automao Linguagem de Programao

90

break; case 'l': listatotal(); break; default: puts("\nDigite somente opcoes validas!!!!"); } } } /* novonome() - adiciona um livro ao arquivo */ void novonome() { char numstr[81]; printf("\nRegistro %d. \nDigite titulo: ", n+1); gets(livro[n].titulo); printf("\nDigite autor: "); gets(livro[n].autor); printf("\nDigite o numero do livro (3 digitos): "); gets(numstr); livro[n].regnum = atoi(numstr); /* converte string p/ int */ printf("\nDigite preco: "); gets(numstr); livro[n].preco = atof(numstr); n++; } /* listatotal() - lista os dados de todos os livros */ void listatotal() { int i; if(!n) printf("\nLista vazia.\n"); else for(i=0; i<n; i++) { printf("\nRegistro: %d.\n", i+1);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

91

printf("\nTitulo: %s.\n", livro[i].titulo); printf("\nAutor: %s.\n", livro[i].autor); printf("\nNr do registro: %3d.\n", livro[i].regnum); printf("\nPreco: %4.3f. \n", livro[i].preco); } }

10.4 Unies A palavra union usada, de forma semelhante a struct, para agrupar um nmero de diferentes variveis sob um nico nome. Entretanto, uma union utiliza um mesmo espao de memria a ser compartilhado com um nmero de diferentes membros, enquanto uma struct aloca um espao diferente de memria para cada membro. Em outras palavras, uma union o meio pelo qual um pedao de memria ora tratado como uma varivel de um certo tipo, ora como outra varivel de outro tipo. Por isso, unies so usadas para poupar memria e o seu uso no recomendado a no ser em casos extremamente necessrios, pois a utilizao irresponsvel das unies podem causar a perda de dados importantes do programa. Quando voc declara uma varivel do tipo union, automaticamente alocado espao de memria suficiente para conter o seu maior membro. Sintaxe:
union <nome> { <tipo> <campo1>; : <tipo n> <campo n>; };

Exemplo do emprego das unies:


typedef unsigned char byte; union Oito_bytes { double x; /*um double de 8 bytes */
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

92

int i[4]; /* um array com 4 inteiros = 8 bytes */ byte j[8]; /* um array de 8 bytes */ } unionvar; void main() { unionvar.x = 2.7; unionvar.i[1] = 3; /* sobreescreve valor anterior ! */ }

Para verificar que o tamanho de uma varivel union igual ao tamanho do maior membro, vamos utilizar a funo sizeof(). A funo sizeof() resulta o tamanho em bytes ocupado por uma Podemos verificar tambm que dada varivel. Veja o teste realizado abaixo, onde apresentamos o valor em bytes ocupado por cada membro da unio e o valor em bytes ocupado pela unio inteira. obter a posio da memria onde esto armazenados os dados.
#include <stdio.h> union num { char str[20]; int i; float f; } x; void main() { printf("Sizeof(str[20])=%d bytes, mem:%p.\n",sizeof(x.str),x.str); printf("Sizeof(i) = %d bytes, \tmem: %p.\n", sizeof(x.i), &(x.i)); printf("Sizeof(f) = %d bytes, \tmem: %p.\n", sizeof(x.f), &(x.f)); printf("Sizeof(x) = %d bytes, \tmem: %p.\n", sizeof(x), &(x)); } // Cria a variavel do tipo union num.

todos os membros da unio ocupam a mesma posio da memria utilizando o operador & para

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

93

A sada do programa ser como esperado:


Sizeof(str[20]) = 20 bytes, mem: 50EF:0D66. Sizeof(i) = 2 bytes, mem: 50EF:0D66. Sizeof(f) = 4 bytes, mem: 50EF:0D66. Sizeof(x) = 20 bytes, mem: 50EF:0D66.

10.5 Bitfields Bitfields so um tipo especial de estrutura cujos campos tem comprimento especificado em bits. Estas so teis quando desejamos representar dados que ocupam somente um bit. Sintaxe:
struct <nome> { <tipo> <campo> : <comprimento em bits>; };

Exemplo aplicando bitfields:


#define ON 1 #define OFF 0 struct Registro_Flags /* declara bitfield */ { unsigend int Bit_1 : 1; unsigend int Bit_2 : 1; unsigend int Bit_3 : 1; unsigend int Bit_4 : 1; unsigend int Bit_5 : 1; unsigend int Bit_6 : 1; unsigend int Bit_7 : 1; unsigend int Bit_8 : 1; };

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

94

main( ) { struct Registro_Flags Flags; Flags.Bit_1 = ON; Flags.Bit_2 = OFF; } /*declara varivel Flags*/

10.6 Exerccios 10.1 Escreva uma estrutura para descrever um ms do ano. A estrutura deve ser capaz de

armazenar o nome do ms, a abreviao em letras, o nmero de dias e o nmero do ms. Escreva tambm um tipo enumerado para associar um nome ou uma abreviao ao nmero do ms. 10.2 Declare uma matriz de 12 estruturas descritas na questo anterior e inicialize-a com os dados de um ano no-bissexto. 10.3 Escreva uma funo que recebe o nmero do ms como argumento e retorna o total de dias do ano at aquele ms. Escreva um programa que solicite ao usurio o dia, o ms e o ano. Imprima o total de dias do ano at o dia digitado. 10.4 Escreva um programa para cadastrar livros em uma biblioteca e fazer consultas a estes. 10.5 Refaa o programa do exerccio 8.6 utilizando as estruturas aqui desenvolvidas. 10.6 Crie uma estrutura para descrever restaurantes. Os membros devem armazenar o nome, o endereo, o preo mdio e o tipo de comida. todos os dados. 10.7 Crie um programa que faa o controle de cadastro de usurios e controle de alocao para uma locadora de fitas de vdeo. Utilize uma estrutura para os clientes e outra para as fitas.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Crie uma matriz de estruturas e escreva um

programa que utilize uma funo para solicitar os dados de um elemento da matriz e outra para listar

Informtica para Automao Linguagem de Programao

95

11 Ponteiros e a Alocao Dinmica de Memria


No captulo sobre tipos de dados, definimos o que era ponteiro. Ponteiros so tipos especiais de dados que armazenam o endereo de memria onde uma varivel normal armazena seus dados. Desta forma, empregamos o endereo dos ponteiros como uma forma indireta de acessar e manipular o dado de uma varivel. Agora apresentaremos diversas aplicaes de ponteiros, justificaremos por que este so intensivamente empregados na programao C e apresentaremos algumas de suas aplicaes tpicas. 11.1 Declarao de Ponteiros e o Acesso de Dados com Ponteiros C permite o uso de ponteiros para qualquer tipo de dado, sendo este um dado tpico de C (int, float, double, char) ou definido pelo programador (estruturas, unies). anteriormente (2.7), os ponteiros so declarados da seguinte forma:
<tipo> * <nome da varivel> = <valor inicial>; float *p, float *r = 0;

Como havamos visto

A sintaxe basicamente a mesma que a declarao de variveis, mas o operador * indica que esta varivel de um ponteiro, por isso *p e *r so do tipo float e que p e r so ponteiros para variveis float. Lembrando,
*p = 10;

faz com que a varivel endereada por p tenha o seu valor alterado para 10, ou seja, * um operador que faz o acesso a varivel apontada por um ponteiro. O operador & aplicado a uma varivel normal retorna o valor do seu endereo, podemos dizer ento:
int num = 15; p = &num; /* p recebe o endereo de num */

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

96

11.2 Operaes com Ponteiros A linguagem C oferece 5 operaes bsicas que podem ser executadas em ponteiros. prximo programa mostras estas possibilidades. O

Para mostrar o resultado de cada operao, o

programa imprimir o valor do ponteiro (que um endereo), o valor armazenado na varivel apontada e o endereo da varivel que armazena o prprio ponteiro.
#include <stdio.h> void main() { int x = 5, y = 6; int *px; int *py = 0; /* ponteiro inicializado com 0 */ printf("Endereco contigo incialmente em :\n"); printf("\tpx = %p \n\tpy = %p.\n", px, py); printf("Cuidado - ponteiros nao incializados como px!!!\n\n"); px = &x; py = &y; if(px<py) printf("py - px = %u\n", py-px); else printf("px - py = %u\n", px-py); printf("px = %p, \t*px = %d, \t&px = %p\n", px, *px, &px); printf("py = %p, \t*py = %d, \t&py = %p\n\n", py, *py, &py); px++; printf("px = %p, \t*px = %d, \t&px = %p\n\n", px, *px, &px); py = px + 3; printf("py = %p, \t*py = %d, \t&py = %p\n", py, *py, &py); printf("py - px = %u\n", py-px); }

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

97

Resultado do programa:
Endereo contido inicialmente em: px = 21CD:FFFF py = 0000:0000 Cuidado - ponteiros no inicializados como px!!!! px py = 1 px = 4F97:2126, *px = 5, &px = 4F97:2120 py = 4F97:2124, *py = 6, &py = 4F97:211C px = 4F97:2128, *px = 20375, &px = 4F97:2120 py = 4F97:212E, *py = 20351, &py = 4F97:211C py px = 3

Primeiramente, o programa exemplo acima declara as variveis inteiras x e y, declarando dois ponteiros para inteiros tambm. Note que um ponteiro foi inicializado com 0 e o outro no. Para mostrar a importncia da inicializao de ponteiros, resolvemos mostrar na tela o valor inicial destes. Caso, tentssemos acessar o valor da varivel apontada pelo ponteiro py, o programa no executaria esta operao pelo fato do ponteiro conter um endereo invlido 0. Entretanto, se tentarmos acessar o valor da varivel apontada por px, o computador executar esta operao sem problema, pois o endereo est vlido, e assim poderemos cometer um erro gravssimo acessando reas de memrias inadequadas ou proibidas. Inicialize sempre os seus ponteiros com o valor zero ou NULL. Em seguida, atribumos um valor vlido aos ponteiros utilizando o operador (&) para obter o endereo das variveis x e y. O operador (*) aplicado na frente do nome do ponteiro, retornar o valor da varivel apontada por este ponteiro. Como todas as variveis, os ponteiros variveis tm um endereo e um valor. (&) retorna a posio de memria onde o ponteiro est localizado. Em resumo: O nome do ponteiro retorna o endereo para o qual ele aponta. O operador & junto ao nome do ponteiro retorna o endereo onde o ponteiro est armazenado. O operador * junto ao nome do ponteiro retorna o contedo da varivel apontada.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

O operador

Informtica para Automao Linguagem de Programao

98

No programa acima, apresentamos esta idia de forma clara, mostrando na tela estes valores para os dois respectivos ponteiros. Podemos incrementar um ponteiro atravs de adio regular ou pelo operador de incremento. Incrementar um ponteiro acarreta a movimentao do mesmo para o prximo tipo apontado. Por exemplo, se px um ponteiro para um inteiro e px contm o endereo 0x3006. Aps a execuo da instruo:
px++;

o ponteiro px conter o valor 0x3008 e no 0x3007, pois a varivel inteira ocupa 2 bytes. Cada vez que incrementamos px ele apontar para o prximo tipo apontado, ou seja, o prximo inteiro. mesmo verdadeiro para decremento. Se px tem valor 0x3006 depois da instruo:
px--;

ele ter valor 0x3004. Voc pode adicionar ou subtrair de e para ponteiros. A instruo:
py = px + 3;

far com que py aponte para o terceiro elemento do tipo apontado aps px. Se px tem valor 0x3000, depois de executada a instruo acima, py ter o valor 0x3006. programas. Voc pode encontrar a diferena entre dois ponteiros. valor 1 quando px e py so ponteiros para int. Esta diferena ser expressa na unidade tipo apontado, ento, se py tem valor 0x4008 e px o valor 0x4006, a expresso py px ter Testes relacionais com >=, <=, > e < so aceitos entre ponteiros somente quando os dois operandos so ponteiros. Outro cuidado a se tomar quanto ao tipo apontado pelo operandos. Se voc comparar ponteiros que apontam para variveis de tipo diferentes, voc obter resultados sem sentido. Variveis ponteiros podem ser testadas quanto igualdade (==) ou desigualdade (!=) onde os dois operandos so ponteiros (px == py) ou um dos operandos NULL (px != NULL ou px != 0). Novamente, tenha cuidado na manipulao de ponteiros para no acessar regies invlidas de memria ou ocupadas por outros

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

99

11.3 Funes & Ponteiros Um das maneiras mais importantes para passar argumentos para uma funo ou para que a funo retorne um resultado atravs de ponteiros. Ponteiros so empregados em funes principalmente quando necessitamos de umas das seguintes caractersticas: ponteiros permitem que uma funo tenha acesso direto as variveis da funo chamadora, podendo efetuar modificaes nestas variveis; para tipos de dados complexos ou de grande dimenso (estruturas, matrizes, ...) mais fcil e mais rpido acessar estes dados indiretamente atravs de um ponteiro do que realizar uma cpia destes para que a funo possa utilizar o valor copiado. Podemos utilizar ponteiros de estruturas complexas ou matrizes como forma de fazer com que funes retornem mais de um valor como resultado; A passagem de parmetro com ponteiros geralmente mais rpida e eficiente do que com o prprio dado, haja visto que o compilador no faz uma cpia deste dado e um ponteiro necessita somente de 4 bytes para armazenar o seu valor. Para tal, basta que em vez da funo chamadora passar valores para a funo chamada, esta passe endereos usando operadores de endereos (&). Estes endereos so de variveis da funo chamadora onde queremos que a funo coloque os novos valores. acesso. funo.
#include <stdio.h> void altera(int *, int *); void main() { int x = 0, y = 0; altera(&x, &y); printf("O primeiro e %d, o segundo e %d.", x, y); }

Estes endereos devem ser

armazenados em variveis temporrias da funo chamada para permitir posteriormente o seu No exemplo a seguir mostramos como ponteiros podem ser usados como parmetros da

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

100

/* altera(), altera dois numeros da funcao que chama*/ void altera(int *px, int *py) { if(px != 0) *px = 3; if(py != 0) *py = 5; }

Note, que o objetivo da funo prover modificaes nas duas variveis x e y. Numa forma simples, s poderamos efetuar esta operao utilizando-se uma estrutura para conter x e y, ou criando uma funo para alterar cada parmetro. Entretanto, passando-se o endereo das variveis x e y permitimos a funo chamada que altera-se diretamente os seus valores. O valor do endereo das variveis foi obtido com o operador &. A funo necessitou apenas da declarao de um tipo ponteiro em seu cabealho para estar apta a receber endereos de variveis como um de seus parmetros. Uma vez conhecidos os endereos e os tipos das variveis do programa chamador, a funo pode no somente colocar valores nestas variveis como tambm tomar o valor j armazenado nelas. Ponteiros podem ser usados no somente para que a funo passe valores para o programa chamador, mas tambm para que o programa chamador passe valores para a funo. Outro aspecto importante o teste efetuado antes de utilizar a o ponteiro recebido como parmetro:
if(px != 0) *px = 3;

Isto serve para que a funo verifique se o valor de endereo recebido vlido. Tome muito cuidado com a manipulao de ponteiros, um erro no programa ou em uma funo do sistema operacional, pode gerar um ponteiro invlido e o acesso a rea de memria representada por este ponteiro pode causar um erro fatal no seu programa. Este um dos mtodos para prever erros com ponteiros.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

101

11.4 Ponteiros & Matrizes Voc no percebe, mas C trata matrizes como se fossem ponteiros. O tipo matriz na

verdade uma forma mais amigvel que C fornece para tratar um ponteiro que aponta para uma lista de variveis do mesmo tipo. O compilador transforma matrizes em ponteiros quando compila, pois a arquitetura do microcomputador entende ponteiros e no matrizes. Qualquer operao que possa ser feita com ndices de uma matriz pode ser feita com ponteiros. O nome de uma matriz um endereo, ou seja, um ponteiro. Ponteiros e matrizes so idnticos na maneira de acessar a memria. Na verdade, o nome de uma matriz um ponteiro constante. Um ponteiro varivel um endereo onde armazenado um outro endereo. Suponha que declaramos uma matriz qualquer:
int table = {10, 1, 8, 5, 6}

e queremos acessar o terceiro elemento da matriz. Na forma convencional por matriz, fazemos isto atravs da instruo:
table[2]

mas a mesma instruo pode ser feita com ponteiros, considerando que o nome do vetor na verdade um ponteiro para o primeiro elemento do vetor:
*(table+2)

A expresso (table+2) resulta no endereo do elemento de ndice 2 da matriz.

Se cada

elemento da matriz um inteiro (2 bytes), ento vo ser pulados 4 bytes do incio do endereo da matriz para atingir o elemento de ndice 2. Em outras palavras, a expresso (table+2) no significa avanar 2 bytes alm de table e sim 2 elementos da matriz: 2 inteiros se a matriz for inteira, 2 floats se a matriz for float e assim por diante. Ou seja,
*(matriz + indice) == matriz[indice]
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

102

Existem duas maneiras de referenciar o endereo de um elemento da matriz: em notao de ponteiros, matriz+indice, ou em notao de matriz, &matriz[indice]. para esclarecer estes conceitos:
#include <stdio.h> #define LIM 40 void main() { float notas[LIM], soma = 0.0; int register i = 0; do { printf("Digite a nota do aluno %d: ", i); scanf("%f", notas+i); if(*(notas+i) > 0) soma += *(notas+i); }while(*(notas+i++) > 0); printf("Media das notas: %.2f", soma/(i-1)); }

Vamos mostrar um exemplo

O operador de incremento ou decremento no pode ser aplicado a ponteiros constantes. Por exemplo, no podemos substituir o comando (notas + i++) por (notas++), haja visto que notas um ponteiro constante. Para fazer isto, precisamos criar um ponteiro varivel qualquer, atribuir a ele o endereo da matriz e depois incrementar o valor deste ponteiro:
float * ptr = 0; ptr = notas; (notas + i++) == (ptr++) /* so equivalentes */

Como, ptr aponta para uma matriz do tipo float, o operador (++) incrementa em 4 bytes a cada operao. Podemos passar matrizes como parmetros para funes, passando-se como parmetro um ponteiro para o primeiro elemento da matriz e depois utilizando este ponteiro para
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

103

acessar todos os elementos da matriz. Esta sintaxe funciona exatamente igual como se estivssemos passando um ponteiro de uma varivel normal como parmetro. verificar esta sintaxe. 11.5 Ponteiros & Strings Como strings so na verdade tratadas em C como matrizes simples de caracteres finalinazadas por 0 (caractere \0), podemos utilizar as facilidades fornecidas pelos ponteiros para manipular strings tambm. Abaixo mostramos um exemplo que ilustra este caso:
#include <stdio.h> #include <conio.h> char * procstr(char *, char); void main() { char *ptr; char ch, lin[81]; puts("Digite uma sentenca: "); gets(lin); printf("Digite o caractere a ser procurado: "); ch=getche(); ptr = procstr(lin, ch); printf("\nA string comeca no endereco %p.\n", lin); if(ptr) /* if(ptr != 0) */ { printf("Primeira ocorrencia do caractere: %p.\n", ptr); printf("E a posicao: %d", ptr-lin); } else printf("\nCaractere nao existe.\n"); }

Veja a seco anterior para

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

104

char * procstr(char * l, char c) { if(l == 0) return 0; while((*l != c)&&(*l != '\0')) l++; if(*l != '\0') return l; return 0; }

Primeiramente, fornecemos aqui um exemplo de funo que retorna como resultado um ponteiro. Note que, antes de acessarmos o valor deste ponteiro, testamos se este um ponteiro vlido para no cometer nenhum erro acessando uma rea imprpria da memria. O programa utilizou a manipulao de ponteiros para localizar a posio de um caractere em uma string e fornecer a sua posio ao usurio. A maioria das funes em C manipulam strings Em vez de declararmos uma como ponteiros e, por isso, so extremamente rpidas e otimizadas.

string como uma tabela, podemos faze-lo diretamente como sendo um ponteiro. O tipo (char *) reconhecido em C como sendo um tipo string, ou seja, um ponteiro para uma seqncia de caracteres. Por isso, as inicializaes abaixo so equivalentes:
char * salute = Saudacoes; char salute[] = Saudacoes;

Entretanto, esta inicializao alocar memria somente para o correspondente nmero de caracteres da string passada mais um caractere \0 para delimitar a string. Nenhum espao a mais de memria ser alocado neste caso. As duas formas provocam o mesmo efeito, mas so diferentes: a primeira declara salute como um ponteiro varivel e a segunda como um ponteiro constante. O valor de um ponteiro constante no pode ser modificado, j um ponteiro varivel pode ter seu valor modificado, por um incremento (++), por exemplo: Podemos criar em C matrizes de ponteiros

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

105

para strings.

Esta uma das maneiras mais econmicas para alocar memria para uma

matriz de strings sem desperdiar memria. Por exemplo, a inicializao:


static char * list[5] = { Katarina, Nigel, Gustavo, Francisco, Airton };

Vai alocar uma matriz com 5 elementos, onde cada elemento conter o valor de um ponteiro para uma lista de caracteres (string). Desta forma, o espao de memria necessrio para alocar ser somente o tamanho estritamente necessrio. Como a string de ponteiros, basta alocar espao para cada elemento de 2 bytes, enquanto que a seqncia de caracteres apontado por este ponteiro pode estar em qualquer posio de memria. Se quisssemos fazer a mesma inicializao utilizando uma matriz de vetores de caracteres, isto implicaria que teramos que alocar uma tabela MxN para conter todos os caracteres e isto nos levaria a desperdiar algumas posies da memria que no chegaram nunca a conter algum caractere, j que as strings se caracterizam por conter um comprimento diferentes de caracteres. Por isto, uma das razes para se inicializar strings com ponteiros a alocao mais eficiente de memria. Uma outra razo a de obter maior flexibilidade para manipular matrizes de strings. Por exemplo, suponha que desejssemos reordenar as strings da matriz acima. Para fazer isto, no precisamos remover as strings de sua posio e escrev-las em outra matriz na ordem correta, basta trocar de posio os ponteiros que apontam para as strings. em outra posio de memria. 11.6 Ponteiros para Ponteiros A habilidade da linguagem C de tratar partes de matrizes como matrizes cria um novo tpico de C, ponteiros que apontam para ponteiros. Esta habilidade d a C uma grande flexibilidade na Reordenando os ponteiros, obteremos a ordem desejada das strings sem ter que se preocupar em reescrever as strings

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

106

criao e ordenao de dados complexos.

Vamos analisar um exemplo de acesso duplamente

indireto de dados derivados de uma matriz de duas dimenses:


#include <stdio.h> #define LIN 4 #define COL 5 void main() { static int tabela[LIN][COL] = { {13, 15, 17, 19, 21}, {20, 22, 24, 26, 28}, {31, 33, 35, 37, 39}, {40, 42, 44, 46, 48} int c = 10; int j, k; int * ptr = ( int *) tabela; for(j=0; j<LIN; j++) for(k=0; k<COL; k++) *(ptr + j*COL + k) += c; for(j=0; j<LIN; j++) { for(k=0; k<COL; k++) printf("%d ", *(*(tabela+j)+k)); printf("\n"); } } };

Neste exemplo, estamos utilizando o ponteiro tabela para acessar os termos da matriz bidimensional. Mas como fazer para acessar um termo posicionado em tabela[i][j]? Como tabela uma matriz para inteiros, cada elemento ocupar dois bytes e cada coluna com 5 elementos ocupar 10 bytes. Abaixo, mostramos o armazenamento desta tabela na memria (os endereos esto em nmeros decimais para facilitar o entendimento).

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

107

Vamos tentar agora acessar o elemento tabela[2][4], onde a tabela tem dimenso 4x5. a) *(tabela + 2*5 + 4) Note que, podemos tratar uma matriz mxn como sendo um vetor simples de inteiros, pois as linhas so posicionadas na memria uma aps a outra. Ento, se calcularmos a posio de memria ocupada por tabela[2][4], poderemos acessar o seu valor atravs de um ponteiro: int * ptr = tabela : contm o endereo inicial da matriz, no caso 1000. (ptr + 2*5) == (ptr + 10) : contm a posio incial da terceira linha da tabela (tabela[2]), no caso 1020 pois cada elemento ocupa 2 bytes (int). Isto fica claro na matriz acima. Sabendo-se que a terceira linha comea aps 2 linhas com 5 elementos, basta adicionar o nmero de termos contidos nestas linhas ao ponteiro da matriz e obtemos um ponteiro para o incio da linha 2. ((ptr + 2*5) + 4) == (ptr + 14) : contm a posio de memria onde est o termo tabela[2][4], no caso 1028. Com o ponteiro da linha, queremos agora acessar o termo 4 desta linha. Ento, basta adicionar 4 ao ponteiro da linha, que obtemos um ponteiro para o referido termo. *(ptr + 2*5 + 4) == *(ptr + 14) : calculada a posio de memria onde est o referido termo, basta utilizar o operador (*) para acess-lo. b) *( *(tabela + 2) + 4) Considere a declarao da seguinte tabela 4x5:
int tabela[4][5];

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

108

Queremos agora criar um vetor que contenha a terceira linha desta tabela. isto, usando uma das duas declaraes equivalentes:
int linha[5] = tabela[2]; int linha[5] = *(tabela + 2); /* eq. 1 */

Podemos fazer

Note que, uma matriz na verdade um vetor contendo outras matrizes de ordem menor. Na declarao acima, fazemos a atribuio de um elemento da matriz tabela, isto , um vetor com 5 inteiros, para uma matriz que contm 5 inteiros. A diferena das notaes que a segunda utiliza a manipulao de ponteiros na sua declarao. Agora, vamos acessar o quinto termo de linha, isto , linha[4]. Podemos fazer isto pelo mtodo convencional de matrizes ou por ponteiros. Os dois mtodos abaixo so equivalentes:
int num = linha[4]; int num = *(linha + 4);

Desta forma, conseguimos acessar indiretamente o termo tabela[2][4]. Primeiro atribumos a terceira linha da tabela a um vetor simples e depois acessamos o quinto elemento deste vetor. Entretanto, C nos permite realizar o mesmo mtodo de acesso, sem criar este passo intermedirio, basta fazer:
int tabela[4][5]; int num = *(*(tabela + 2) + 4); /* tabela[2][4]; */

Assim, *(tabela+2) retorna o endereo da terceira linha da matriz tabela, equivalente a escrevermos &tabela[2][0]. Ao adicionarmos 4 a este endereo, calculamos o endereo do quinto elemento nesta linha. Portanto, o endereo do quinto elemento (*(tabela+2)+4) e o contedo deste endereo *(*(tabela+2)+4), que 39. Esta expresso m ponteiro para ponteiro. Este princpio aplicado para matrizes de qualquer dimenso, em outras palavras:
tabela[j][k] = *(*(tabela + j) + k); cubo[i][j][k] = *(*(*(cubo + i) + j) + k);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

109

Desta maneira, C nos permite criar ponteiros para ponteiros e fazer estruturas to complexas e flexveis quanto desejarmos. O operador *(ptr) pode ento ser aninhado para obter o valor final apontado pela seqncia de ponteiros. Esta tcnica pode fornecer grande velocidade de execuo e economia de memria, mas tenha cuidado para construir um cdigo claro de forma a evitar problemas devido a um gerenciamento ruim destes ponteiros. 11.7 Argumentos da Linha de Comando C permite que um programa receba uma lista de parmetros atravs da funo main(). forma geral da funo main dada por:
int main(int argc, char* argv[]);

onde argc o nmero de argumentos passados para a funo, e argv uma matriz de string que contm todos os argumentos passados. A funo main() nesta forma geral necessita retornar um No caso, o retorno do valor 0 valor indicando o resultado do programa ao sistema operacional. indicar que o programa foi executado adequadamente. Suponha que voc tenha criado um programa chamado jogo e tenha executado ele no sistema operacional com a linha de comando:
C:> jogo xadrex.txt 2 3.14159

Ao executar o programa passo-a-passo, verificaremos que argc ser igual a 4, indicando que o usurio forneceu 4 parmetros ao programa. Sendo que os parmetros esto armazenados em argv na forma de string e contero os seguintes valores:
argv[0] == jogo; argv[1] == xadrex.txt; argv[2] == 2; argv[3] == 3.14159;

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

110

Conhecendo como funciona os parmetros da funo main(), voc j pode utilizar a atribuio abaixo para obter os valores fornecidos, bastando converter o parmetro do formato ASCII para o tipo de dado requerido :
char * param = argv[3];

11.8 Ponteiros para Estruturas Como j mostramos ponteiros so mais fceis de manipular que matrizes em diversas situaes, assim ponteiros para estruturas so mais fceis de manipular que matrizes de estruturas. Vrias representaes de dados que parecem fantsticas so constitudas de estruturas contendo ponteiros para outras estruturas. O nosso prximo exemplo mostra como definir um ponteiro para estrutura e us-lo para acessar os membros da estrutura.
#include <stdio.h> struct lista /* declara estrutura */ { char titulo[30]; char autor[30]; int regnum; double preco; }; int main(int argc, char * argv[]) { static struct lista livro[2] = { { "Helena", "Machado de Assis", 102, 70.50 }, { "Iracema", "Jose de Alencar", 321, 63.25 } struct lista *ptrl = 0; /* ponteiro para estrutura */ printf("Endereco #1: %p #2: %p\n", &livro[0], &livro[1]); ptrl = &livro[0]; printf("Ponteiro #1: %p #2: %p\n", ptrl, ptrl + 1);
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

};

Informtica para Automao Linguagem de Programao

111

printf("ptrl->preco: R$%.2f \t (*ptrl).preco: R$%.2f\n", ptrl->preco, (*ptrl).preco); ptrl++; /* Aponta para a proxima estrutura */ printf("ptrl->titulo: %s \tptrl->autor: %s\n", ptrl->titulo, ptrl->autor); return 0; }

A declarao feita como se estivssemos declarando uma varivel de qualquer tipo, adicionando-se o operador (*) na frente do nome da varivel. Por isso, a declarao de um ponteiro para uma estrutura feito na forma:
struct lista *ptrl;

O ponteiro ptrl pode ento apontar para qualquer estrutura do tipo lista. A atribuio de um endereo a um ponteiro de estrutura funciona da mesma forma como uma varivel qualquer, empregando-se o operador (&):
ptrl = &(livro[0]);

Vimos no captulo sobre estruturas como fazer o acesso a um elemento de uma estrutura atravs do operador (.). Por exemplo, se quisermos ler o valor do preo da primeira estrutura da matriz livro, procederamos da forma: livro[0].preco = 89.95; Mas como proceder com ponteiros? Podemos faz-lo de duas formas. Primeiro, podemos utilizar o operador (*) para obter a estrutura apontada por um ponteiro e depois empregar o operador normal (.) para acessar um elemento desta estrutura. Aplicando no exemplo acima, teremos:
(*ptrl).preco = 89.95;

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

112

O segundo mtodo utiliza o operador (->) que nos permite acessar um elemento de uma estrutura apontada por um dado ponteiro. Aplicando-se este operador no problema acima, temos:
ptrl->preco = 89.95;

Em outras palavras, um ponteiro para estrutura seguido pelo operador (->) trabalha da mesma maneira que o nome de uma estrutura seguido pelo operador (.). importante notar que ptrl um ponteiro, mas ptrl->preco um membro da estrutura apontada. Neste caso, ptrl->preco uma varivel double. O operador (.) conecta a estrutura a um membro dela; o operador (->) conecta um ponteiro a um membro da estrutura. 11.9 Alocao Dinmica de Memria A linguagem C oferece um conjunto de funes que permitem a alocao ou liberao dinmica de memria. Desta forma, podemos alocar memria para um programa de acordo com a sua necessidade instantnea de memria. so: segmento de dados, onde so alocadas as variveis globais (extern), definidas em preruntime; o segmento de cdigo, onde esto as instrues de mquina do programa em si; o segmento de pilha (stack), onde as funes alocam provisoriamente suas variveis locais (auto). Este segmento tambm usado para passagem de parmetros; o segmento extra, que pode conter mais variveis globais; Toda a rea de memria restante entre o fim do programa e o fim da RAM livre chamada de heap. O heap usado para a criao de variveis dinmicas, que so criadas em run-time (isto , durante a execuo do programa). Este tipo de varivel til quando no se sabe de antemo quantas variveis de um determinado tipo sero necessrias para a aplicao em questo. Quando escrevemos um programa utilizando o mtodo de declarao de variveis visto anteriormente (alocao esttica de memria), o programa ao ser executado alocar somente um
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

A memria de trabalho do computador (RAM) Estes segmentos

usualmente subdividida em vrios segmentos lgicos dentro de um programa.

Informtica para Automao Linguagem de Programao

113

bloco fixo de memria para armazenar todos os seus dados. Isto resolve o problema de termos um espao de memria alocado para podermos armazenar os dados do programa. Entretanto, como visto no captulo de matrizes, este mtodo no otimiza a utilizao do espao de memria alocado. Por exemplo, imagine que voc precise de uma matriz temporria para armazenar alguns dados temporrios durante a execuo de uma dada funo de manipulao de matrizes. Para tal, voc dever declarar esta matriz na funo, o que implicar que o computador ir alocar um bloco de memria para esta matriz. Este espao de memria ficar alocado ao seu programa durante toda a execuo deste, apesar do programa s utilizar uma vez esta matriz e, posteriormente, no precisar mais desta matriz e nem do espao de memria alocado a esta. Com a alocao dinmica de memria, podemos, em tempo de execuo, fazer com que um programa aloque um determinado espao de memria, utilize este espao por um determinado tempo e depois o libere, para que outros programas possam vir a utiliz-lo. No caso do nosso exemplo, podemos fazer com que sempre que a funo for chamada, ela alocar um espao de memria para armazenar a referida matriz e aps o seu uso, o programa liberar este bloco de memria para que outro programa o utilize. Desta forma, se executarmos esta funo apenas uma vez, o programa ir liberar esta memria posteriormente, permitindo assim que outros programas faam um uso mais adequado desta. Desta forma, a alocao dinmica de memria utilizada em programas para alocar e liberar blocos temporrios de memrias durante a execuo de um programa (por isso chamado alocao dinmica). Este bloco de memria solicitado ao sistema operacional que procura um espao livre de memria para o programa. Se o sistema operacional achar um bloco de memria livre do tamanho do bloco solicitado, este passa o bloco de memria para o controle do programa e no ir permitir que nenhum outro programa utilize esta memria enquanto ela estiver alocada. No final do seu uso, o programa libera novamente esta memria ao sistema operacional. Outro exemplo de aplicao da alocao dinmica de memria na utilizao de matrizes quando no sabemos de antemo quantos elementos sero necessrios. Desta forma, podemos utilizar a alocao dinmica de memria para somente alocar a quantidade necessria de memria e no momento em que esta memria for requerida.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

114

11.9.1 Malloc() A funo malloc() utilizada para fazer a alocao dinmica de um bloco de memria a um dado programa. A funo malloc() toma um inteiro sem sinal como argumento. Este nmero representa a quantidade em bytes de memria requerida. A funo retorna um ponteiro para o importante verificar que o

primeiro byte do novo bloco de memria que foi alocado.

ponteiro retornado por malloc() para um tipo void. O conceito de ponteiro para void deve ser introduzido para tratar com situaes em que seja necessrio que uma funo retorne um ponteiro genrico, i.e., que possa ser convertido em um ponteiro para qualquer outro tipo de dado. Este ponteiro void pode ser convertido para um ponteiro do tipo de dado desejado (int, float, struct, ...) empregando-se o mtodo de converso de tipos apresentado na seco sobre tipos de dados (ver 2.5). No prximo exemplo, mostraremos seu emprego novamente. Quando a funo malloc() no encontrar espao suficiente de memria para ser alocado, esta retornar um ponteiro NULL, i.e., um ponteiro invlido. O exemplo abaixo mostra como a funo malloc() opera. nova estrutura.
#include <stdio.h> struct xx { int numl; char chl; }; void main() { struct xx *ptr = 0; int j; printf("sizeof(struct xx) = %d\n", sizeof(struct xx)); for(j=0; j<4; j++){ ptr = (struct xx *) malloc(sizeof(struct xx)); printf("ptr = %x\n", ptr); } }
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Este programa declara uma estrutura chamada xx e chama malloc() 4 vezes.

cada chamada, malloc() retorna um ponteiro para uma rea de memria suficiente para guardar um

Informtica para Automao Linguagem de Programao

115

Note que em nenhuma parte do programa declaramos qualquer varivel estrutura. De fato, a varivel estrutura criada pela funo malloc(); o programa no conhece o nome desta varivel; mas sabe onde ela est na memria, pois malloc() retorna um ponteiro para ela. programa. A cada chamada de malloc() devemos inform-la do tamanho da estrutura que queremos guardar. Ns podemos conhecer este tamanho adicionando os bytes usados por cada membro da Este operador estrutura, ou atravs do uso de um novo operador em C unrio chamado sizeof(). operando. Por exemplo, a expresso:
sizeof(float)

As variveis criadas

podem ser acessadas usando ponteiros, exatamente como se tivessem sido declaradas no incio do

produz um inteiro igual ao tamanho, em bytes, da varivel ou do tipo de dado que est em seu

retornar o valor 4, haja vista que um float ocupa 4 bytes. No programa exemplo, usamos sizeof() em printf() e ele retorna 3, pois a estrutura xx consiste em um caractere e um inteiro. Ento, sizeof() forneceu o tamanho em bytes da estrutura para que malloc() pudesse alocar o espao de memria requerido. Feito isto, malloc() retornou um ponteiro do tipo void, que foi convertido para o tipo struct xx atravs da expresso:
(struct xx *)

11.9.2 Calloc() Uma outra opo para a alocao de memria o uso da funo calloc(). primeiro byte do bloco solicitado. A nova funo aceita dois argumentos do tipo unsigned int. abaixo:
long * memnova; memnova = (long *) calloc(100, sizeof(long));

H uma grande

semelhana entre calloc() e malloc() que tambm retorna um ponteiro para void apontando para o Um uso tpico mostrado

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

116

O primeiro argumento o nmero de clulas de memrias desejadas e o segundo argumento o tamanho de cada clula em bytes. No exemplo acima, long usa quatro bytes, ento esta instruo alocar espao para 100 unidades de quatro bytes, ou seja, 400 bytes. A funo calloc() tem mais uma caracterstica: ela inicializa todo o contedo do bloco com zero. 11.9.3 Free() A funo free()libera a memria alocada por malloc() e calloc(). Aceita, como argumento, um ponteiro para uma rea de memria previamente alocada e ento libera esta rea para uma possvel utilizao futura. Sempre que um espao de memria for alocado, este deve ser necessariamente liberado aps o seu uso. Se no for liberada, esta memria ficar indisponvel para o uso pelo sistema operacional para outros aplicativos. A utilizao consciente da alocao e liberao dinmica de memria A vantagem desta permite um uso otimizado da memria disponvel no computador. A funo free()declara o seu argumento como um ponteiro para void. qualquer tipo de dado.
long * memnova; memnova = (long *)calloc(100, sizeof(long)); /* usa memnova */ free(memnova); /* libera a memria alocada */

declarao que ela permite que a chamada funo seja feita com um argumento ponteiro para

11.10 Exerccios 11.1 Escreva um programa que receba duas strigns como argumentos e troque o contedo de string1 como string2. 11.2 Escreva um programa que inverta a ordem dos caracteres de uma string. Por exemplo, se a string recebida Saudacoes deve ser modificada para seocaduaS.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

117

11.3 Reescreva o programa do exerccio 9.1 utilizando alocao dinmica de memria. 11.4 Reescreva o programa do exerccio 9.3 utilizando alocao dinmica de memria. 11.5 A lista encadeada se assemelha a uma corrente em que as estruturas esto penduradas seqencialmente. Isto , a corrente acessada atravs de um ponteiro para a primeira estrutura, chamada cabea, e cada estrutura contm um ponteiro para a sua sucessora, e o ponteiro da ltima estrutura tem valor NULL (0) indicando o fim da lista. Normalmente uma lista encadeada criada dinamicamente na memria. Crie um programa com uma lista encadeada para armazenar dados de livros em uma biblioteca. 11.6 Crie um programa com lista encadeada para catalogar clientes e fitas em uma vdeo locadora. 11.7 Crie uma estrutura para descrever restaurantes. Os membros devem armazenar o nome, o endereo, o preo mdio e o tipo de comida. Crie uma lista ligada que apresente os restaurantes de um certo tipo de comida indexados pelo preo. comida. 11.8 Escreva um programa para montar uma matriz de estruturas para armazenar as notas de 40 alunos. A primeira coluna da matriz deve conter o nome do aluno, a segunda o telefone, a A professora deve ser capaz de inserir e retirar alunos, e poder terceira a data de nascimento, depois seguem as notas em lista e na ltima coluna deve ser calculada a mdia at o presente momento. editar os dados dos alunos. A professora deve poder tambm listar os dados de todos alunos na O menor preo deve ser o primeiro da lista. Escreva um programa que pea o tipo de comida e imprima os restaurantes que oferecem este tipo de

forma de uma tabela na tela do computador. A lista de alunos deve ser indexada pelo nome destes. Utilize a idia da lista ligada e da alocao dinmica de memria.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

118

12 Manipulao de Arquivos em C
Neste captulo, veremos brevemente a manipulao de arquivos em C. Em um captulo

posterior, ser apresentada novamente a manipulao de arquivos agora utilizando C++. 12.1 Tipos de Arquivos Uma maneira de classificar operaes de acesso a arquivos conforme a forma como eles so abertos: em modo texto ou em modo binrio. so escritos nos arquivos. localizar possveis erros. Arquivos em modo binrio operam em dados binrios, ou seja, os dados escritos neste formato so escritos na forma binria, no necessitando de nenhuma converso do tipo do dado utilizado para ASCII e ocupando bem menos memria de disco (arquivos menores). Uma outra diferena entre o modo texto e o modo binrio a forma usada para guardar nmeros no disco. Na forma de texto, os nmeros so guardados como cadeias de caracteres, enquanto que na forma binria so guardados como esto na memria, dois bytes para um inteiro, quatro bytes para float e assim por diante. 12.2 Declarao, abertura e fechamento C declara um tipo especial de estrutura, chamada FILE, para operar com arquivos. Este tipo definido na biblioteca stdio.h, que deve ser includa na compilao com a diretiva #include para permitir operaes sobre arquivos. Os membros da estrutura FILE contm informaes sobre o Toda operao realizada sobre um arquivo (abertura, arquivo a ser usado, tais como: seu atual tamanho, a localizao de seus buffers de dados, se o arquivo est sendo lido ou gravado, etc. fechamento, leitura, escrita) requer um apontador para uma estrutura do tipo FILE:
FILE *File_ptr;
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Arquivos em modo texto operam em dados

armazenados em formato texto, ou seja, os dados so traduzidos para caracteres e estes caracteres Por esta razo, fica mais fcil de compreender os seus formatos e

Informtica para Automao Linguagem de Programao

119

A abertura de um arquivo feita com a funo fopen():


File_ptr = fopen(Nome do Arquivo,<I/O mode>);

onde as opes para a abertura do arquivo esto listadas abaixo:

A funo fopen() executa duas tarefas. comunicar.

Primeiro, ela preenche a estrutura FILE com as

informaes necessrias para o programa e para o sistema operacional, assim eles podem se Segundo, fopen() retorna um ponteiro do tipo FILE que aponta para a localizao na memria da estrutura FILE. A funo fopen() pode no conseguir abrir um arquivo por algum motivo (falta de espao em disco, arquivo inexistente, etc.) e por isso esta retornar um ponteiro invlido, isto , contendo o valor NULL (0). Por isso, teste sempre se o ponteiro fornecido por fopen() vlido antes de O fechamento de um utilizado, caso contrrio o seu programa pode vir a ter uma falha sria. Quando terminamos a gravao do arquivo, precisamos fech-lo. arquivo feito com a funo fclose():
fclose(File_ptr);

Quando fechamos um arquivo que o sistema operacional ir salvar as suas modificaes ou at mesmo criar o arquivo, no caso de ser um arquivo novo. At ento, o sistema operacional estava

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

120

salvando as alteraes em um buffer antes de escrever estes dados no arquivo. Este procedimento executado para otimizar o tempo de acesso ao disco empregado pelo sistema operacional. Por isso, no esquea de fechar um arquivo, seno os seus dados podem ser perdidos e o arquivo no seja criado adequadamente. Uma outra razo para fechar o arquivo a deliberar as reas de comunicao usadas, para que estejam disponveis a outros arquivos. Estas reas incluem a estrutura FILE e o buffer. Uma outra funo que fecha arquivos a funo exit(). A funo exit() difere da funo fclose() em vrios pontos. Primeiro, exit() fecha todos os arquivos abertos. Segundo, a funo exit() tambm termina o programa e devolve o controle ao sistema operacional. A funo fclose() simplesmente fecha o arquivo associado ao ponteiro FILE usado como argumento. 12.3 Leitura e escrita de caracteres A funo usada para ler um nico caractere de um arquivo getc() enquanto que a funo putc() escreve um caractere em um arquivo. Abaixo, apresentamos exemplos destas funes:

12.4 Fim de Arquivo (EOF) EOF um sinal enviado pelo sistema operacional para indicar o fim de um arquivo. O sinal EOF (Fim de Arquivo) enviado pelo sistema operacional para o programa C no um caractere, e sim um inteiro de valor 1 e est definido em stdio.h.
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

121

Perceba que no exemplo anterior de leitura de caracteres, ns usamos uma varivel inteira para guardar os caracteres lidos para que possamos interpretar o sinal de EOF. Se usarmos uma varivel do tipo char, o caractere de cdigo ASCII 255 decimal (0xFF em Hexa) ser interpretado como EOF. Queremos usar todos os caracteres de 0 a 255 em nosso arquivo e uma varivel inteira nos assegura isto. Neste exemplo, EOF usado para ler todos os caracteres de um dado arquivo, quando no conhecemos de antemo a quantidade de caracteres deste arquivo. A marca de fim de arquivo pode ser diferente para diferentes sistemas operacionais. Assim, o valor de EOF pode ser qualquer. O seu arquivo stdio.h define EOF com o valor correto para o seu sistema operacional; assim, em seus programas, use EOF para testar fim de arquivo. O fim de um arquivo pode tambm ser determinado utilizando-se a funo feof(), que recebe como parmetro um ponteiro vlido para a estrutura FILE. 12.5 Leitura e escrita de strings A funo fputs() escreve uma string em um arquivo e, por isso, toma dois argumentos, sendo o primeiro a matriz de caracteres que ser gravada e o segundo o ponteiro para a estrutura FILE do arquivo a ser gravado. caractere \n. A funo gets() l uma linha por vez de um arquivo texto. A funo gets() toma 3 Na verdade, este argumentos. O primeiro um ponteiro para o buffer onde ser colocada a linha lida. O segundo um nmero inteiro que indica o limite mximo de caracteres a serem lidos. caractere NULL (\0) na prxima posio livre. (\n) ou um caractere de fim de arquivo (EOF). nmero deve ser pelo menos um maior que o nmero de caracteres lidos, pois gets() acrescenta o O terceiro argumento um ponteiro para a estrutura FILE do arquivo a ser lido. A funo termina a leitura aps ler um caractere de nova linha Observe que a funo fputs() no coloca automaticamente o caractere de nova-linha no fim de cada linha. No programa exemplo a seguir, fazemos isto explicitamente com o

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

122

12.6 Arquivos Padres C define um conjunto de arquivos padres utilizados para acessar alguns perifricos do computador (como a impressora) ou para ler da entrada padro (normalmente o teclado) ou escrever para a sada padro (normalmente a tela). Desta forma, _streams[] foi criada como uma matriz de estruturas FILE. Se voc perder um tempo e analisar o seu arquivo stdio.h, encontrar vrias constantes simblicas definidas como:
#define stdin (&_streams[0]) #define stdout (&_streams[1]) #define stderr (&_streams[2]) #define stdaux (&_streams[3]) #define stdprn (&_streams[4])

Estas constantes podem ser usadas para acessar qualquer um dos 5 arquivos padro que so predefinidos pelo MS-DOS e abertos automaticamente quando o seu programa inicia a sua execuo e fechados ao seu fim.

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

123

Cada uma destas constantes pode ser tratada como um ponteiro para uma estrutura FILE dos arquivos in, out, err, aux e prn respectivamente. Voc pode usar os ponteiros FILE definidos em stdio.h para acessar os perifricos predefinidos pelo MS-DOS ou usar seus nomes e definir os ponteiros necessrios. Como exemplo, a instruo:
fgets(string, 80, stdin);

l uma string do teclado. A instruo:


fputs(string, stdprn);

imprimir uma string na impressora.

12.7 Gravando um Arquivo de Forma Formatada Nos captulos iniciais apresentamos a funo printf() para imprimir na tela dados de forma formatada. Para realizar a mesma tarefa, entretanto no para escrever na tela, mas sim para um Esta funo similar a printf() exceto que o ponteiro para arquivo, foi criada a funo fprintf().

FILE tomado como primeiro argumento. Como em printf(), podemos formatar os dados de vrias maneiras; todas as possibilidades de formato de printf() operam com fprintf(). Da mesma forma foi criada a funo fscanf(), que como scanf(), l um dado formatado. A diferena consiste que fscanf() l um dado de um arquivo e recebe um ponteiro para FILE como primeiro argumento. Exemplo:
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

124

#include <stdio.h> FILE *fptr; int size = 0; fptr = fopen(dados.txt, rw); fscanf(fptr, %d, &size); fprintf(fptr, %s %d %f, Casa Nova, 12, 13.45); fclose(fptr);

12.8 Leitura e escrita de valores binrios Quando desejamos operar com arquivos no modo binrio, basta adicionar o caractere b no I/O Mode da funo open(), como apresentado anteriormente. duas novas funes que facilitam este processo: fwrite() e fread(). As funes apresentadas Estas funes so empregadas anteriormente podem ser usadas para ler e escrever no modo binrio, entretanto apresentaremos aqui para escrever/ler os dados armazenados em um bloco de memria (um buffer de memria) em um arquivo. Aplicaes tpicas e na escrita/leitura de dados complexos como matrizes e estruturas. A funo fwrite() toma 4 argumentos. O primeiro um ponteiro do tipo void que aponta Normalmente, pode-se utilizar o operador para a localizao na memria do dado a ser gravado. O segundo argumento um nmero inteiro que indica o tamanho do tipo de dado a ser gravado. quantos itens do mesmo tipo sero gravados. FILE do arquivo onde queremos gravar. A funo fread() toma tambm 4 argumentos. O primeiro um ponteiro void para a O segundo indica tambm a localizao da memria onde sero armazenados os dados lidos. sizeof() para se obter este valor. O terceiro argumento um nmero inteiro que informa a fwrite() O quarto argumento um ponteiro para a estrutura

quantidade de bytes do tipo de dado a ser lido. O terceiro argumento informa a quantidade de itens a serem lidos a cada chamada, e o quarto argumento um ponteiro para a estrutura FILE do arquivo a ser lido. A funo fread() retorna o nmero de itens lidos. Normalmente este nmero deve ser igual ao terceiro argumento. Se for encontrado o fim do arquivo, o nmero ser menor que o valor do As funes fread()e
Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

terceiro argumento, podendo ser zero caso nenhum dado tenha sido lido.

Informtica para Automao Linguagem de Programao

125

fwrite() trabalham com qualquer tipo de dado, incluindo matrizes e estruturas, e armazenam nmeros em formato binrio.

Se "filename" for inicializado com prn, os dados so enviados a impressora. Exemplo:


fileptr=fopen(filename,rb); while(!feof(fileptr)) { fread(&dados, sizeof(dados),1,fileptr); } fclose(fileptr);

12.9 Exerccios 12.1 Escreva um programa que imprima um arquivo na tela de 20 em 20 linhas. O arquivo de entrada deve ser fornecido na linha de comando. aguarda o pressionamento de uma tecla. 12.2 Escreva um programa que imprima o tamanho de um arquivo em bytes. arquivo deve ser fornecido na linha de comando. 12.3 Escreva um programa que criptografa um arquivo usando o operador de complemento de bit-a-bit (~). Quando o programa executado para um arquivo j criptografado, o arquivo recomposto e volta ao original. O nome do A cada impresso de 20 linhas, o programa

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Informtica para Automao Linguagem de Programao

126

12.4 Refaa o problema 11.5, agora salvando a lista de livros em um arquivo. Permita que o usurio possa retirar um livro desta lista, apagando-o do arquivo, ou adicionar um livro em uma posio determinada na lista, reescrevendo a lista no arquivo. manipulao de arquivos. 12.5 Como o exemplo anterior, refaa o problema 11.6 mas agora utilizando o modo binrio. Utilize o modo texto para a

Prof. Carlos Pantaleo Curso de Tecnologia de Automao Industrial e Engenharia de Controle e Automao

Você também pode gostar