Escolar Documentos
Profissional Documentos
Cultura Documentos
DEPARTAMENTO
DE
DO
ALTO
Linguagem de Programao II
C, Pascal e Delphi
2009
5.2.2 Argumentos das funes .............................................................................................. 38 5.2.3 Tipos de funes........................................................................................................... 40 5.3 ARGUMENTOS PASSADOS A PROGRAMAS ........................................................................... 42 5.3.1 Argumentos passados a programas em PASCAL ........................................................ 42 5.3.2 Argumentos passados a programas em C.................................................................... 42 6. 6.1 6.2 6.3 6.4 7. MATRIZES......................................................................................................................... 44 MATRIZES EM PASCAL....................................................................................................... 44 MATRIZES EM C ................................................................................................................ 45 STRINGS ............................................................................................................................ 46 MATRIZES E VETORES COMO PARMETROS DE FUNES ................................................... 47 DELPHI............................................................................................................................... 50
2.1 ELEMENTOS DA LINGUAGEM ............................................................................................... 6 2.1.1 Elementos definidos pela linguagem: ............................................................................ 6 2.1.2 Elementos definidos pelo Usurio ................................................................................. 8 2.2 TIPOS DE DADOS ................................................................................................................. 8 2.2.1 Tipos predefinidos pela linguagem................................................................................ 8 2.2.2 Tipos definidos pelo usurio........................................................................................ 10 2.3 CONVERSES DE TIPOS DE DADOS ..................................................................................... 10 2.4 CONSTANTES E VARIVEIS ................................................................................................ 11 2.4.1 Constantes.................................................................................................................... 11 2.4.2 Variveis ...................................................................................................................... 12 2.4.3 Classes de armazenamento .......................................................................................... 12 2.5 OPERADORES..................................................................................................................... 13 2.5.1 Operadores aritmticos ............................................................................................... 13 2.5.2 Operadores de atribuio ............................................................................................ 13 2.5.3 Operadores relacionais e lgicos ................................................................................ 13 2.5.4 Operadores bit a bit ..................................................................................................... 14 2.5.5 Operadores de incremento e decremento .................................................................... 15 2.5.6 Operador Condicional ................................................................................................. 15 2.5.7 Operador Vrgula......................................................................................................... 16 3. ESTRUTURA DO PROGRAMA...................................................................................... 17 3.1 ESTRUTURA DE UM PROGRAMA EM PASCAL ..................................................................... 17 3.1.1 Identificao do programa .......................................................................................... 17 3.1.2 Bloco de Declaraes .................................................................................................. 17 3.1.3 Bloco de Comandos ..................................................................................................... 18 3.2 ESTRUTURA DE UM PROGRAMA EM C ............................................................................... 18 3.2.1 Bloco de Diretivas de Compilao .............................................................................. 18 3.2.2 Bloco de Declaraes: ................................................................................................. 19 3.2.3 Bloco de Implementao:............................................................................................. 19 4. COMANDOS ...................................................................................................................... 20 4.1 COMANDOS SIMPLES ......................................................................................................... 20 4.1.1 Comandos de Entrada e Sada..................................................................................... 20 4.1.2 Comandos de Desvio Incondicional ............................................................................ 25 4.2 ESTRUTURAS DE CONTROLE .............................................................................................. 26 4.2.1 Seqncia ..................................................................................................................... 26 4.2.2 Comandos condicionais ............................................................................................... 26 4.2.3 Comandos de Repetio............................................................................................... 31 5. FUNES E PROCEDIMENTOS................................................................................... 37 5.1 PROCEDIMENTOS ............................................................................................................... 37 5.1.1 Passagem de parmetros ............................................................................................. 37 5.2 FUNES ........................................................................................................................... 38 5.2.1 Estilos e prottipos das funes................................................................................... 38
7.1 CONCEITOS BSICOS.......................................................................................................... 51 7.1.1 Programao em Windows: Janelas e eventos............................................................ 51 7.2 PROGRAMAO ORIENTADA A OBJETO (POO) ................................................................. 51 7.3 O AMBIENTE DO DELPHI .................................................................................................... 52 7.3.1 Arquivos que Compem um Aplicao ........................................................................ 52 7.3.2 Arquivos Gerados pela Compilao ............................................................................ 53 7.4 CDIGO FONTE DO ARQUIVO PROJECT(.DPR).................................................................... 53 7.5 CDIGO FONTE DO ARQUIVO UNIT (.PAS) ......................................................................... 53 7.5.1 Seo Unit.................................................................................................................... 53 7.5.2 Seo Uses ................................................................................................................... 54 7.5.3 Seo Interface............................................................................................................ 54 7.5.4 Seo Type ................................................................................................................... 54 7.5.5 Seo Var ..................................................................................................................... 54 7.5.6 Seo Implementation .................................................................................................. 54 7.5.7 Seo uses adicional .................................................................................................... 55 7.5.8 Inicialization ................................................................................................................ 55 7.5.9 Exemplo........................................................................................................................ 55 7.6 CODE EDITOR (EDITOR DE CDIGO).................................................................................. 56 7.7 FORM (FORMULRIO)........................................................................................................ 56 7.8 OBJECT INSPECTOR (INSPETOR DE OBJETOS) ..................................................................... 57 7.9 COMPONENT PALETTE( PALHETA DE COMPONENTES) ....................................................... 58 7.10 COMPONENTES .................................................................................................................. 58 7.10.1 Nomenclatura .......................................................................................................... 58 7.10.2 Propriedades ........................................................................................................... 58 7.10.3 Eventos..................................................................................................................... 59 7.10.4 Mtodos ................................................................................................................... 60 7.10.5 Forms (janelas)........................................................................................................ 60 7.10.6 TMainMenu ............................................................................................................. 61 7.10.7 TPopUpMenu........................................................................................................... 62 7.10.8 TLabel...................................................................................................................... 62 7.10.9 TEdit ........................................................................................................................ 62 7.10.10 TMemo ..................................................................................................................... 62 7.10.11 TButton .................................................................................................................... 63 7.10.12 TCheckBox............................................................................................................... 63 7.10.13 TRadioButton........................................................................................................... 63 7.10.14 TListBox................................................................................................................... 63 7.10.15 TComboBox ............................................................................................................. 64
7.10.16 TScrollBox ............................................................................................................... 64 7.10.17 TGroupBox .............................................................................................................. 64 7.10.18 TRadioGroup ........................................................................................................... 64 7.10.19 TPanel...................................................................................................................... 64 7.10.20 TActionList .............................................................................................................. 65 7.10.21 TBitBtn..................................................................................................................... 65 7.10.22 TMaskEdit................................................................................................................ 65 7.10.23 TBevel ...................................................................................................................... 66 7.10.24 TShape ..................................................................................................................... 66 7.10.25 TImage ..................................................................................................................... 66 7.10.26 TPageControl .......................................................................................................... 66 7.10.27 TTabSheet ................................................................................................................ 66 7.10.28 TTimer ..................................................................................................................... 66 7.10.29 TStatusBar ............................................................................................................... 67 7.10.30 TStatusPanels .......................................................................................................... 67 7.10.31 TStatusPanel............................................................................................................ 67 7.10.32 TStringGrid.............................................................................................................. 67 7.11 CAIXAS DE MENSAGEM ..................................................................................................... 68 7.11.1 ShowMessage........................................................................................................... 68 7.11.2 MessageBox ............................................................................................................. 68 7.11.3 InputBox................................................................................................................... 69 7.12 DICAS ................................................................................................................................ 70 7.13 EXEMPLOS DE PROGRAMAS EM DELPHI ............................................................................. 73 8. ESTRUTURAS, UNIES E ITENS DIVERSOS............................................................ 78 8.1 ESTRUTURAS ..................................................................................................................... 78 8.1.1 Passando uma estrutura para uma funo .................................................................. 79 8.1.2 Matriz de Estruturas .................................................................................................... 79 8.1.3 Estruturas dentro de estruturas ................................................................................... 80 8.1.4 Ponteiros para estruturas ............................................................................................ 81 8.1.5 Estruturas em Pascal e Delphi .................................................................................... 82 8.2 UNIES .............................................................................................................................. 84 8.3 ITENS DIVERSOS................................................................................................................. 85 8.3.1 typedef .......................................................................................................................... 85 8.3.2 enum............................................................................................................................. 86 9. ARQUIVOS......................................................................................................................... 87 9.1 ARQUIVO TIPADO EM DELPHI E PASCAL ............................................................................ 87 9.1.1 Declarao de arquivos ............................................................................................... 87 9.1.2 Funes de abertura e fechamento de arquivos .......................................................... 88 9.1.3 Funes de escrita e gravao..................................................................................... 90 9.2 ARQUIVOS TEXTO EM PASCAL E DELPHI ........................................................................... 95 9.2.1 Funes para manipulao de arquivos texto ............................................................. 97 9.3 ARQUIVOS SEM TIPOS EM PASCAL E DELPHI ....................................................... 99 9.3.1 Funes para manipulao de arquivos sem tipos...................................................... 99 9.3.2 Arquivos com diversas estruturas em Pascal e Delphi.............................................. 100 9.4 ARQUIVOS EM C .............................................................................................................. 103 9.4.1 Declarao de arquivos ............................................................................................. 105 9.4.2 Funes de abertura e fechamento de arquivos ........................................................ 105 9.4.3 Funes de escrita e gravao................................................................................... 106
9.4.4 Funes de Escrita e Gravao em Arquivos Texto .................................................. 108 9.4.5 Funes "fseek" , "ftell" e "rewind"........................................................................... 111 9.4.6 Arquivos com diversas estruturas .............................................................................. 112 9.5 RESUMO DO USO DE ARQUIVOS TIPADOS EM PASCAL ..................................................... 114 9.6 MANIPULAO DE ARQUIVOS COM DELPHI..................................................................... 121 10. PONTEIROS..................................................................................................................... 129 10.1 DEFINIO DE PONTEIROS ............................................................................................... 129 10.1.1 Declarao de variveis tipo ponteiro .................................................................. 130 10.1.2 Usando variveis tipo ponteiro ............................................................................. 131 10.1.3 Inicializando variveis do tipo ponteiro................................................................ 132 10.1.4 Limitaes no operador de endereos................................................................... 133 10.1.5 Ponteiros para matrizes......................................................................................... 133 10.1.6 Ponteiros para ponteiros ....................................................................................... 134 10.1.7 Aritmtica com ponteiros....................................................................................... 135 10.2 PONTEIROS PARA FUNES .............................................................................................. 135 10.3 PONTEIROS EM PASCAL ................................................................................................... 137 11. ALOCAO DINMICA DE MEMRIA .................................................................. 140 11.1 11.2 LISTA ENCADEADA COM ALOCAO DINMICA DE MEMRIA:......................................... 143 EXEMPLO DE UTILIZAO DE ALOCAO DINMICA DE MEMRIA COM DELPHI .............. 150
1. INTRODUO
C uma linguagem de programao que foi desenvolvida por Dennis Ritchie durante o comeo dos anos 70 para ser usada na implementao de sistemas operacionais e outras tarefas de programao de baixo nvel. Em 1960 um comit de cientistas europeus definiu a linguagem Algol. Em meados dos anos 60 pesquisadores da Universidade de Cambridge desenvolveram a linguagem BCPL na tentativa de terem um Algol simplificado. Ainda nos anos 60, Dennis Ritchie desenvolveu a linguagem B a partir da BCPL. Em 1971 ritchie e thompson escreveram a primeira verso da linguagem C. O desenvolvimento inicial de C ocorreu entre 1969 e 1973 (de acordo com Ritchie, o perodo mais criativo foi durante 1972). Em 1973 ela tornou-se poderosa o suficiente para reimplementar o kernel do sistema operacional Unix. Em 1978, Brian Kernighan e Dennis Ritchie publicaram o agora bastante conhecido "C Programming Language" (tambm conhecido como "o livro branco", K&R). C tornou-se imensamente popular fora do Bell Labs depois de 1980 e foi por um tempo a linguagem dominante em programao de sistemas e de aplicaes de micro-computadores. Ela se consagrou como a linguagem de programao de sistemas, e a mais importante da comunidade Open Source. Bjarne Stroustrup e outros no Bell Labs trabalharam no final dos anos 80 para adicionar a orientao a objetos ao C, criando uma linguagem chamada C++. C++ agora a linguagem mais comum para aplicaes comerciais nos sistemas Microsoft Windows, embora C permanea mais popular no mundo Unix. Implementaes de C no checam erros tais como buffer overflow ou acesso a memria no alocada em tempo de execuo. Ferramentas tm sido criadas para ajudar programadores a evitar esses erros. Foi chamada "C" porque apresenta muitas caractersticas derivadas de uma linguagem anterior chamada B, em homenagem ao seu parente, BCPL. BCPL, por sua vez, descendeu de uma linguagem derivada do Algol, CPL. A linguagem de programao C foi padronizada na forma de um padro ISO, ISO 9899. A primeira edio do ISO deste documento foi publicado em 1990 (ISO 9899:1990) e foi uma pequena modificao de um padro ANSI um pouco anterior, ANSI X3.159-1989 "Programming Language C". Edies seguintes tm sido feitas, algumas das quais tm sido amplamente ignoradas.
2. DADOS
2.1 Elementos da Linguagem
Normalmente uma linguagem de programao possui dois tipos de elementos: os elementos definidos pela linguagem e os elementos definidos pelo prprio usurio:
2.1.1.4 Palavras Reservadas ou Palavras Chave Palavras Reservadas so smbolos que possuem significado definido na linguagem, no podendo ser redefinidos ou usado como nome de identificador. PASCAL array const downto file goto label not packed record then until with C break const do enum for int return sizeof switch unsigned while
auto char default else float if register signed struct union volatile
case continue double extern goto long short static typedef void
Na linguagem C, o restante dos comandos so todos funes (da biblioteca padro ou no). Todas as palavras reservadas devem ser escritas em minsculo. A linguagem Pascal tem ainda alguns identificadores predefinidos pela linguagem conhecidos como Identificadores Padro. Podem ser constantes, tipos, variveis ou subprogramas (procedimentos ou funes) e podem ser escritos tanto em minsculo como em maisculo: abs eof ln read sin true arqtan eoln maxint readln sqr trunc boolean exp odd real sqrt write char false ord reset str writeln chr input output rewrite succ cos integer pred run text
2.1.1.5 Delimitadores Os elementos da linguagem (identificadores, nmeros e smbolos especiais) devem ser separados por pelo menos um dos seguintes delimitadores: branco, final de linha ou comentrio.
-2.147.483.648 a 2.147.483.647 4 bytes 2.9 x 10 39 a 1.7 x 10 38 6 bytes 1.5 x 10 45 a 3.4 x 10 38 4 bytes 5.0 x 10 324 a 1.7 x 10 308 8 bytes 1.9 x 10 4951 a 1.1 x 10 4932 10 bytes -9.2 x 10 18 a 9.2 x 10 18 8 bytes os caracteres da tabela ASCII 1 byte TRUE ou FALSE 1 byte tipo estruturado composto por um quantidade de caracteres x 1 byte conjunto de elementos tipo char * os tipos assinalados somente podem ser utilizados em mquinas com co-processador matemtico (8087, 80287, 80387, 80487) ou com chip processador 80486 DX ou superior. DELPHI tipo shortint byte smallint word integer ou longint cardinal ou longword int64 real * single double extended comp ** char boolean string intervalo de representao -128 a 127 0 a 255 -32.768 a 32.767 0 a 65535 -2.147.483.648 a 2.147.483.647 0 a 4294967295 tamanho 1 byte 1 byte 2 bytes 2 bytes 4 bytes 4 bytes
tipo long int long double tipo unsigned char unsigned int unsigned long int
Modificadores de Tipo Modificador Long intervalo de representao -2.147.483.647 a 2.147.483.647 4 bytes 1.2 E-4932 a 1.2 E4932 10 bytes Modificador Unsigned intervalo de representao 0 a 255 1 byte 0 a 65.535 2 bytes 0 a 4.294.967.295 4 bytes
tamanho
tamanho
-2 63 a 2 63 8 bytes 2.9 x 10 39 a 1.7 x 10 38 6 bytes 1.5 x 10 45 a 3.4 x 10 38 4 bytes 5.0 x 10 324 a 1.7 x 10 308 8 bytes 1.9 x 10 4932 a 1.1 x 10 4932 10 bytes -2 63 a 2 63 8 bytes os caracteres da tabela ASCII 1 byte TRUE ou FALSE 1 byte tipo estruturado composto por um quantidade de caracteres x 1 byte conjunto de elementos tipo char * Apenas para manter compatibilidade com Pascal. Este tipo no nativo para processadores Intel e as operaes com este tipo so mais lentas que os demais. ** O mesmo que um inteiro de 64 bits (int64) C tipo char int float double void intervalo de representao -128 a 127 -32.768 a -32767 3.4 E-38 a 3.4 E38 1.7 E-308 a 1.7 E308 tamanho 1 byte 2 bytes 4 bytes 8 bytes 9
2.2.2.2 Tipo enumerado contnuo O tipo enumerado contnuo pode ser definido como um intervalo de um tipo enumerado discreto j definido ou de um tipo padro.
TYPE tpdias = (segunda, tera, quarta, quinta, sexta, sbado, domingo); TYPE tpfimsem = sbado..domingo; TYPE tpdiautil = segunda..sexta; VAR fimsem: tpfimsem; fimsem:= sbado; if (fimsem = domingo) then ...
10
Ao contrrio das outras linguagens, C e C++ executam converses automticas de dados para um tipo maior ou trunca o valor para um tipo menor. Devemos ter cuidado quando usamos operaes de modo misto em C ou C++, pois os valores podem ser truncados, enquanto que no Pascal devemos prever exatamente o tipo da varivel que necessitamos, por exemplo: PASCAL:
a, b:integer; c: real; a:=5; b:=3; c:=a/b; c = 1,66666667
2.4.2 Variveis
Uma declarao de varivel consiste do nome do tipo seguido do nome da varivel (em C e C++) ou do nome da varivel seguido do nome do tipo (em Pascal). Todas as variveis devem ser declaradas antes de serem usadas. As variveis devem ser declaradas no incio de cada funo, procedimento ou incio do programa. No podem ocorrer declaraes de variveis aps a primeira sentena executvel de uma rotina. As variveis podem ser globais ou locais. Variveis globais so declaradas fora de qualquer funo, valem em qualquer ponto do cdigo, so inicializadas com zero automaticamente e uma nica vez, so armazenadas na memria. Variveis locais so declaradas dentro das funes, existem apenas enquanto a funo na qual foi declarada est ativa. Dentro de funes variveis locais com mesmo nome de variveis globais tem preferncia, no so inicializadas automaticamente, ou seja, deve-se informar um valor inicial, so alocadas na pilha ("stack"). Os parmetros das funes so tratados como se fossem variveis locais, so inicializados com o valor passado na chamada, so declarados na lista de parmetros, so passados por valor, somente tipos escalares de dados podem ser parmetros.
C:
int a, b; float c; c=a/b; c=1,000000
C:
float a, b; int c; a=5; b=3; c=a/b; c=1
C:
int a; float b,c; a=5; a=5; b=3; b=3; c=a/b; c=1,666667
A linguagem C e C++ permitem a converso temporria dos tipos de variveis atravs do operador de converso. Sempre que voc necessitar a mudar o formato de uma varivel temporariamente, simplesmente preceda o identificador da varivel com o tipo entre parnteses para aquele que quiser converter. Se utilizarmos o primeiro exemplo de C acima podemos obter o resultado esperado usando um operador de converso ou cast:
int a, b; float c; a=5; b=3; c=(float)a/b; c=1,666667
Neste caso a inicializao somente ser feita na primeira evocao da rotina. O valor de "x" sobreviver de uma chamada para outra da rotina (cada vez que for chamada, "x" aumentar de valor).
11
12
Se uma varivel global possui o atributo "static" significa que ela somente poder ser usada no arquivo onde est declarada, sendo invisvel a outros arquivos que componham o sistema. extern: significa que a varivel est declarada em outro arquivo, onde sua rea alocada. utilizada para variveis globais a diferentes arquivos componentes de um mesmo projeto (programa). volatile: informa ao compilador para no otimizar o uso de uma varivel colocando-a em registrador. utilizado quando uma varivel pode ser atualizada concorrentemente por mais de um processo.
maior que menor que maior ou igual menor ou igual igual diferente
maior que menor que maior ou igual menor ou igual igual diferente
Os operadores lgicos so usados para combinar expresses relacionais. Tambm devolvem como resultado valores lgicos verdadeiro ou falso. PASCAL e DELPHI and or not xor e ou no ou exclusivo && || ! ^ C e ou no ou exclusivo
2.5 Operadores
2.5.1 Operadores aritmticos
PASCAL e DELPHI + * / MOD DIV soma subtrao multiplicao diviso resto da diviso inteira inteiro da diviso + * / % C soma subtrao multiplicao diviso resto da diviso inteira
Uma expresso relacional ou lgica em C ou C++, retornar zero para o valor lgico falso e um para o valor lgico verdade. No entanto, qualquer valor diferente de zero ser considerado um valor verdade quando inserido em uma expresso lgica.
OPERAO e ou no ou exclusivo shift para direita (diviso por 2) shift para esquerda (multiplicao por 2)
+=
*=
/=
%=
Pascal
char a, b, c;
a=1; b=3;
a, b, c: byte
a:=1; b:=3
C 13
Linguagem de Programao II - URI Campus de Frederico Westphalen
14
(C) c = a & b
00000001 & 00000011 00000001 (Pascal) c:= a and b (C) c = ~a ~ 00000001 11111110 (Pascal) c:= not a (C) c = b >> 1 00000011 00000001 (Pascal) c:= b shr 1
00000001 ^ 00000011 00000010 (Pascal) c:= a xor b (C) c = b << 1 00000011 00000110 (Pascal) c:= b shl 1
Escrever "m++" ou "++m" quando estes se encontram isolados em uma linha no faz diferena. Quando estiverem sendo usados em conjunto com uma atribuio, entretanto: Ex:
int m, n; m = 5; n = 4; m = n++; Res: m = 4 n = 5 m = ++n; m = 5 n = 5
Obs.: A declarao:
printf("%d %d %d",n,n++,n+1);
est correta, porm o resultado pode variar de acordo com o compilador dependendo da ordem em que os parmetros so retirados da pilha (stack).
15
16
3. ESTRUTURA DO PROGRAMA
3.1 Estrutura de um Programa em Pascal
Normalmente um programa Pascal possui trs partes distintas: Identificao do programa, Bloco de declaraes e Bloco de comandos.
A declarao dos tipos iniciadas pela palavra reservada TYPE, seguida de um ou mais identificadores separados por vrgula, um sinal de igual, um tipo e um ponto e vrgula: TYPE <tipoident1> , ... , <tipoidentn> = <tipo> ; 3.1.2.4 Parte de Declaraes de Variveis: Quando declaramos uma varivel temos que definir, alm do nome, seu tipo. O tipo especifica os valores que podero ser atribudos a esta varivel. O tipo pode ser algum dos tipos predefinidos pela linguagem ou um tipo definido pelo usurio. A declarao das variveis iniciada pela palavra reservada VAR, seguida de um ou mais identificadores, separados por vrgula, um tipo um ponto e vrgula: VAR < ident1> , ... , <identn> : <tipo> ; 3.1.2.5 Parte de Declaraes de Subprogramas: Nesta parte so declarados e implementados os subprogramas (funes e procedimentos) e devem estar declarados e implementados antes da sua chamada em qualquer parte do programa principal ou de subprogramas.
17
18
#include <stdio.h> /* inclui a biblioteca padro de comandos de entrada e sada que se encontra no diretrio padro*/ #include outros.h /*inclui uma outra bliblioteca criada pelo usurio que se encontra no diretrio corrente */ Tambm nesse bloco podemos definir as macros para o nosso programa. Uma macro pode ser simplesmente a substituio de um texto como a implementao de uma pequena funo, por exemplo: #define MAXINT 32767 #define triplo(x) ((x)*3) #define pqt Pressione Qualquer Tecla Para Continuar...
4. COMANDOS
4.1 Comandos Simples
Os comandos simples ou no estruturados, caracterizam-se por no possurem outros comandos relacionados.
19
20
char c; double d;
4.1.1.1.3 Readkey O comando READKEY l um caracter do teclado e associa a uma varivel do tipo char. 4.1.1.2 Comandos de E/S em C A linguagem C no possui nenhum comando de entrada e sada predefinido na linguagem. Todas as operaes de E/S so realizadas por funes que encontram-se nas mais diversas bibliotecas. As principais funes so: 4.1.1.2.1 A funo printf() A funo printf a funo para sada formatada de dados e funciona da seguinte forma: o primeiro argumento uma string entre aspas (chamada de string de controle) que pode conter tanto caracteres normais como cdigos de formato que comeam pelo caracter de porcentagem. Caracteres normais so apresentados na tela na ordem em que so encontrados. Um cdigo de formato informa a funo printf que um item no caracter deve ser mostrado. Os valores correspondentes encontram-se no segundo argumento (lista de argumentos). SINTAXE: printf(<string de controle>,<lista de argumentos>);
printf(%d %f %c %lf,a,b,c,d);
Sintaxe completa de um cdigo de formato: %[flags][largura][.preciso][tamanho]<tipo> <tipo> indica o tipo do valor a ser exibido. Listados acima. [flags]: - + indica alinhamento pela esquerda fora os nmeros a comearem por + ou -
os negativos ficam com o sinal de - e os positivos com um espao em branco no lugar do sinal. [largura]: n indica o nmero mximo de casas a ocupar.
Obs.: Alm de cdigos de formato e caracteres normais a string de controle pode conter ainda caracteres especiais iniciados pelo smbolo \. Exemplos:
printf(O preo R$ %d,00,preco); printf(So %d horas e %d minutos., hora, minuto); printf(O nome %s.,nome); printf(%d dividido por %d igual a %f, n1, n2, (float)n1/n2); printf(O cdigo de %c %d, letra, letra);
0n idntico ao anterior, apenas com a diferena de que as casas no ocupadas sero preenchidas com zeros. [preciso]: n [tamanho]: l long indica o nmero de casas aps a vrgula.
Cdigos de formato: Normalmente os cdigos de formato so utilizados na sua forma mais simples: %c %ld %o %x caracter simples inteiro longo octal hexadecima %d %f %s %lf decimal ponto flutuante cadeia de caracteres double
Caracteres especiais: Alguns caracteres, como o de tabulao, no possuem representao grfica na tela. Por razes de compatibilidade, a linguagem C fornece constantes iniciadas pelo caracter \ para indicar esses caracteres. \n \r \t \b \ \\ \0 \a nova linha retorno do carro tabulao retrocesso (backspace) aspas barra nulo sinal sonoro 22
Obs.: Deve haver uma varivel ou constante para cada cdigo de formato! O tipo das variveis ou constantes tambm deve coincidir com os cdigos de formato.
int a; float b; Linguagem de Programao II - URI Campus de Frederico Westphalen
21
\xn Exemplos:
printf(Ol!\n); printf(Linha1\nLinha2\n); printf(\tPargrafo\nHoje %d/%d/%d\n,dia,mes,ano); printf(Este o \\\\ backslach\n); printf(\xB3\n); printf(Ateno!!!\a\a\a Erro!!!\a\n);
void main() { float anos, dias; printf(Digite sua idade em anos: ); scanf(%f,&anos); dias=anos*365; printf(Voc j viveu %f dias\n,dias); }
4.1.1.2.2 A funo scanf() a funo de entrada formatada de dados pelo teclado. Sua sintaxe similar da funo printf. scanf(<expr. de controle>, <lista de argumentos>); A expresso de controle pode conter tanto cdigos de formatao precedidos pelo sinal %, que indicam o tipo dos dados a serem lidos, como caracteres de espaamento. a) Cdigos de formato: %c %d %e %f %s %u %l %lf Sintaxe: l um caracter l um inteiro decimal l um nmero em notao cientfica l um nmero de ponto flutuante l uma string l um decimal sem sinal l um inteiro longo l um double [largura][cdigo de formato]
Obs.: Por enquanto vamos assumir que todas as variveis da lista de argumentos, com exceo das variveis string, devero ser antecedidas do operador &. Mais adiante vamos entender a razo do operador & e quando o mesmo deve ser utilizado.
c) Search set possvel ainda, no caso de entradas de strings determinar o conjunto de caracteres vlidos (todos os caracteres que no aparecerem nesse conjunto sero considerados separadores). Sintaxe: Exemplos: %[A-Z] %[abc] %[^abc] %[A-Z0-9a-z] todos os caracteres de A at Z apenas os caracteres a, b ou c todos os caracteres menos a, b, c maisculas + minsculas + dgitos %[search set]
4.1.1.2.3 As funes getche() e getch() So funes que lem caracteres do teclado sem esperar a tecla <ENTER>. Ambas no recebem argumentos e devolvem o caracter lido para a funo que os chamou. A diferena entre as duas reside no fato de que getche ecoa o caracter lido no vdeo. Exemplo:
void main() { char ch; printf(Digite algum caracter: ); ch=getch(); printf(\nA tecla digitada foi %c e seu valor na tabela ASCII %d.,ch,ch); }
b) Caracteres de Espaamento: So considerados caracteres de espaamento o espao em branco, o caracter \t e o \n. Sempre que um destes surgir na string de controle de um comando scanf ele indicar que o mesmo deve ser considerado como separador dos valores a serem entrados Esses caracteres sero ento lidos pelo scanf, porm, no armazenados. Normalmente quando o usurio est entrando com valores atendendo a um scanf, quando o mesmo digita um destes caracteres de espaamento, o mesmo lido e no armazenado. A diferena que se o caracter de espaamento aparece na string de controle, ento o scanf n encerrado enquanto o mesmo no for digitado.
23
24
Obs.: Devido maneira diferenciada como tratam o buffer de teclado, o uso das rotinas getch e scanf no mesmo programa pode trazer problemas. Para contorn-los, a funo fflush(stdin) garante que o buffer do teclado (stdin - entrada padro) esteja vazio.
#include <ctype.h> char x; void main() { clrscr(); inicio: printf("R-Repetir, F-finalizar por bem, Outra tecla- Finalizar de qualquer maneira\n"); x=toupper(getch()); if (x=='R') goto inicio; if (x=='F') goto fim_ok; goto fim_qm; fim_ok: printf("Finalizando por bem"); goto fim; fim_qm: printf("Finalizando de qualquer maneira"); fim: getch(); }
Em Pascal: label <rtulo>; begin GOTO <rtulo>; ... <rtulo> : <comandos>; end.
Devemos evitar sempre que possvel o uso de comandos desse tipo. Exemplo em Pascal:
uses crt; label inicio, fim_ok, fim_qm, fim; var x:char; begin clrscr; inicio: writeln('R-Repetir, F-finalizar por bem, Outra tecla- Finalizar de qualquer maneira'); x:=upcase(readkey); if (x='R') then goto inicio; if (x='F') then goto fim_ok; goto fim_qm; fim_ok: writeln('Finalizando por bem'); goto fim; fim_qm: writeln('Finalizando de qualquer maneira'); fim: readkey; end.
Neste caso a ao somente ser executada se a expresso ou o conjunto de expresses lgicas for verdadeira. No caso do comando if-else o programa pode ter duas aes distintas. Se a expresso for verdadeira, ser executado o conjunto de aes do comando1. Se for falsa ser executado o conjunto de aes do comando2. Em Pascal a implementao do comando if : 25
Linguagem de Programao II - URI Campus de Frederico Westphalen
Exemplo em C:
#include <stdio.h> #include <conio.h> Linguagem de Programao II - URI Campus de Frederico Westphalen
26
O comando if no necessita de uma expresso lgica no lugar do teste. Em C, qualquer expresso que resultar ZERO ser considerada como FALSA e qualquer outro valor considerado VERDADEIRO. Em Pascal somente aceito os valores booleanos TRUE ou FALSE. Em C tambm temos o comando if else if - else que freqentemente utilizado para executar mltiplas comparaes sucessiva. Sua forma geral : if (expresso1) ao1; else if (expresso2) ao2; else if (expresso3) ao3;
Exemplos em Pascal
uses crt; var x: integer; begin x:=10; if x>15 then begin writeln(X maior que 15); end; end. uses crt; var x, y: integer; begin x:=10; if (x>15) and (y>15) then begin writeln(X e Y so maiores que 15); end else begin writeln(X e Y no so maiores que 15); end; end.
Logicamente, cada ao poderia ser um bloco composto exigindo seu prprio conjunto de chaves. Este tipo de controle de fluxo lgico avalia a expresso at que encontre uma que VERDADEIRA. Quando isto ocorre, todos os testes condicionais restantes sero desviados. No exemplo anterior, nenhuma ao seria tomada se nenhuma das expresses fosse avaliada como VERDADEIRA. Para executar uma ao padro no caso de no satisfazer nenhuma das expresses declaradas pode-se colocar um else sem expresso de teste para realizar a ao pretendida, por exemplo: if (expresso1) ao1; else if (expresso2) ao2; else if (expresso3) ao3; else ao_padro; Exemplo:
#include <stdio.h> #include <conio.h> int x; void main() { x = 16; if (x == 5) { printf("X vale 5\n"); } else if (x == 10) Linguagem de Programao II - URI Campus de Frederico Westphalen
Obs.: Deve-se tomar cuidado com os comando if-else aninhados. O else sempre est associado ao if mais prximo dentro do mesmo nvel de comandos. Blocos mais internos no so considerados.
Linguagem de Programao II - URI Campus de Frederico Westphalen
27
28
{ printf("X vale 10\n"); } else if (x == 15) { printf("X vale 15\n"); } else { printf("X no vale 5, 10 ou 15\n"); } }
end.
end;
Em C o comando de seleo mltipla o comando SWITCH: Em C devemos tomar um pouco de cuidado, pois o comando switch possui algumas peculiaridades. Sua sintaxe :
switch (expresso) { case <valor1>: <comandos1>;
4.2.2.2 Comando de Seleo mltipla: SWITCH ou CASE Quando se deseja testar uma varivel ou uma expresso em relao a diversos valores usamos o comando de seleo mltipla. O valor da expresso seletora comparado com cada elemento da lista de valores. Se existir um valor igual ser executada somente a seqncia relacionada ao valor. Caso contrrio, ou nenhuma seqncia ser executada, ou a seqncia relacionada clusula padro ser executada se ela existir.
break; case <valor2>: <comandos2>; break; ... case <valor n>: <comandos n>; break; default: <comandos_padro>; }
Em Pascal o comando de seleo mltipla o comando CASE: CASE <seletor> OF <valor1> : <comandos1>; <valor2> : <comandos2>; ... <valorn> : <comandosn>; ELSE : <comandos_padro>; END; Exemplo:
uses crt; var x:integer; begin x := 15; case x of 5: begin writeln('X vale 5'); end; 10: begin writeln('X vale 10'); end; 15: begin writeln('X vale 15'); end; else begin writeln('X nao vale 5, 10 ou 15'); end; Linguagem de Programao II - URI Campus de Frederico Westphalen
Exemplo:
#include <stdio.h> #include <conio.h> int x; void main() { x = 15; switch(x) { case 5: { printf("X vale 5\n"); break; } case 10: { printf("X vale 10\n"); break; } case 15: { printf("X vale 15\n"); break; } default: { printf("X nao vale 5, 10 ou 15\n"); } Linguagem de Programao II - URI Campus de Frederico Westphalen
29
30
} getch(); }
Devemos tomar bastante cuidado com o comando obrigatrio break, que faz a poro restante do comando switch ser pulada. Caso ele seja removido do segmento de cdigo, seriam executados todos os comandos abaixo dele.
Quando o comando de lao for encontrado, a expr_inicializao executada primeiro, no incio do lao, e nunca mais ser executada. Geralmente esse comando fornece a inicializao da varivel de controle do lao. Aps isso testada a expr_teste, que chamada de cndio de trmino do lao. Quando expr_teste avaliada como VERDADEIRA, o comando ou comandos dentro do lao sero executados. Se o lao foi iniciado, expr_incremento executada aps todos os comandos dentro do lao serem executados. Contudo, se exp_teste avaliada como FALSA, os comandos dentro do lao sero ignorados, junto com expr_incremento, e a execuo continua no comando que segue o final do lao. O esquema de endentao para os laos for com diversos comandos a serem repetidos assim:
for (expr_inicializao; expr_teste; expr_incremento) { comando_a; comando_b; comando_c; }
As variveis de controle de um lao de for podem ter seu valor alterado em qualquer ponto do lao. Qualqur uma das expresses de controle do lao de for pode ser omitida desde que sejam mantidos os ;. As variveis utilizadas nas trs expresses de controle no precisam ter relao entre si. Ex.:
void main() { char c; int x,y; for(c=9;c>0;c--) { printf(%d,c); } for(c=9;c>0; ) { printf(%d,c); c--; } for(x=0,y=0; x+y<100; x=x+4, y++) { printf(%d+%d=%d\n,x,y,x+y); } for(;;) { printf(no saio deste lao nunca!!!!\n);
Exemplos:
for i:= 1 to 10 do begin writeln(i, x, 7, =, i*7); end; for i:= 10 downto 1 do begin writeln(i, x, 7, =, i*7); end;
Em C a sintaxe do comando :
for (expr_inicializao; expr_teste; expr_incremento) <comando>;
Exemplos:
for (i=1; i<=10; i++) { printf(%d x 7 = %d \n, i, i*7); } Linguagem de Programao II - URI Campus de Frederico Westphalen
31
32
4.2.3.3 Do While ou Repeat Estes comandos, assim como o comando WHILE, so usados quando no conhecido o nmero de vezes que uma seqncia de comandos dever ser executada. Porm a seqncia ser executada pelo menos uma vez.
4.2.3.2 While Assim como o lao for, while um lao com teste no inco. Isto significa que a expresso teste avaliada antes dos comandos dentro do corpo do lao serem executados. Por causa disto, os laos com teste no incio podem ser executados de zero a mais vezes. Geralmente estas estruturas so usadas quando um nmero indefinido de repeties esperado. Em Pascal a sintaxe :
WHILE <condio> do <comandos>;
Exemplo:
var a:char; Begin repeat clrscr; writeln(1 - Executar); writeln(2 - Sair); a := readkey; if a = 1 then executar; until a =2; end.
Exemplo:
uses crt; var a,b,ano: integer; begin a:=1500; b:=2000; ano:=0; while a < b do begin a := a * 1.05; b := b * 1.02; ano++; end; writeln(ano, anos); end.
Em C a sintaxe do comando :
do <comandos> while(cond_teste);
Em C a sintaxe :
while (expr_teste) <comandos>;
Exemplo.:
void main() { char a; do { clrscr(); printf(1 - Executar\n); printf(2 - Sair\n); a = getche(); if (a == 1) executar(); } while (a != 2); }
Exemplo.:
void main() { int a, b,ano; a=1500; b=2000; ano=0; while(a<b) { a=a*1.05; b=b*1.02; ano++; } printf(%d anos,ano); }
Observe que em Pascal usamos o comando repeat e until fazendo com que o lao repita at que a condio seja satisfeita e em C usamos o comando do e while fazendo com que o lao repita enquanto a condio esteja sendo satisfeita.
33
34
4.2.3.4 Comandos de desvio Nas linguagem C e Pascal temos os comandos de desvio que interrompem a execuo de um lao. 4.2.3.4.1 Comando break O comando break pode ser usado para sair de um lao for, while ou do-while (repeat) mais interno, desde que no mesmo subprograma, passando a seqncia da execuo para a primeira linha aps o lao. Exemplo em Pascal:
uses crt; var x: char; i: integer; begin for i:= 1 to 100 do begin write('Digite um numero entre 0 e 9: '); x:=readkey; if (x < #48) or (x > #57) then break; writeln(x, ' foi digitado!'); end; end.
end.
Exemplo em C:
void main() { int i; for(i=1;i<=10;i++) { if ( i % 2 != 0) continue; printf(O nmero %d par!,i); } }
4.2.3.4.3 Funo Exit A funo exit causa a imediata interrupo do programa e o retorno ao sistema operacional. Em C, o valor do parmetro retornado ao processo que o chamou que geralmente o sistema operacional. O valor 0 ( exit(0);) geralmente indica que o processo terminou sem problemas. Exemplo em Pascal:
uses crt; begin while true do begin write('Xx '); if keypressed then exit; end; end.
Exemplo em C:
void main() { char x, i; for(x=1;x<=100;x++) { printf(Digite um nmero de 0 a 9:); x = getch(); if (y < 48 || y > 57) break; printf(%d foi digitado \n,x); } }
Exemplo em C:
#include <stdio.h> #include <conio.h> #include <stdlib.h> void main() { while(1) { printf("Xx "); if ( kbhit()) exit(0); } }
4.2.3.4.2 Comando continue O comando continue causa o fim de um dos laos de uma repetio e o retorno imediato ao teste. Exemplo em Pascal:
uses crt; var i: integer; begin for i:= 1 to 10 do begin if (i mod 2 <> 0) then continue; writeln(i, ' e par!'); end; Linguagem de Programao II - URI Campus de Frederico Westphalen
4.2.3.4.4 Comando return O comando return causa uma interrupo no fluxo de comandos de uma funo e o retorno a funo chamadora. Pode ser usado com ou sem argumento dependento do tipo de funo em que utilizado, porm no possvel em uma nica funo seu uso com e sem argumentos.
35
36
5.2 Funes
5. FUNES E PROCEDIMENTOS
As funes formam o alicerce da programao em C e C++. Conforme vamos aumentando a prtica em programao, os programas comeam a tomar uma aparncia modular quando programamos com funes. Podemos fazer toda a programao em C e C++ dentro de uma funo. Isto porque todos os programas devem incluir main, que uma funo. As funes so similares aos mdulos de outras linguagens. Pascal utiliza procedimentos e funes. Fortran utiliza somente funes, e a linguagem Assembly utiliza somente procedimentos. O modo como as funes trabalham determina o alto grau de eficincia, legibilidade e portabilidade do cdigo do programa em C.
Em Pascal as funes podem ser vistas como um procedimento que retorna um nico valor. Ex.:
PROGRAM FUNCAO; VAR pr, imp: REAL; FUNCTION calc_imposto(preco: REAL):REAL; BEGIN calc_imposto = preco * 0.17; END; BEGIN READLN(pr); imp = calc_imposto(pr); WRITELN('Preo: ',pr,' Imposto: ',imp); END.
5.1 Procedimentos
Um procedimento um tipo de subprograma utilizado na linguagem Pascal, que se assemelha em muito com um programa em Pascal. Possui um cabealho de identificao com o nome do procedimento, uma lista opcional de parmetros de comunicao, um bloco de declaraes e um bloco de comandos. Em C uma funo void ou que retorna um valor nulo, pode ser comparada com um procedimento utilizado na linguagem Pascal, porm todas os subprogramas em C so funes e devem retornar um valor (ou retornar void, vazio).
38
O comando return permite que uma funo retorne um nico valor. Esse valor obtido na rotina chamadora na medida em que a chamada na funo feita atravs de uma atribuio (Ex. 2). Ex. 1:
... int v; v=30; func1(v,25);
...
void func1(int a, int b) { int x; a = a + 10; b = b - 10; x = a + b; printf("%d\n",x); } Ex. 2: void main() { float pr, imp; scanf("%f",&pr); imp=calc_imposto(pr); printf("Preo: %f, Imposto: %f\n",pr,imp); } float calc_imposto(float preco); { float imposto; imposto=preco * 0.17; return(imposto); }
Observe que o argumento da funo func1 um ponteiro para inteiro. O que se passa na chamada dessa funo, no o valor da varivel a, mas sim seu endereo (at porque nesse momento a nem ao menos foi inicializado). Dentro da funo func1, o valor digitado pelo usurio multiplicado por 2 e armazenado, no na varivel p que contm o endereo de a, mas na prpria varivel a. Desta forma, quando a funo acaba e o controle volta rotina chamadora, o valor correto j est armazenado em a. Note-se, ento, que o uso de um * antes de uma varivel ponteiro em uma expresso significa que no estamos nos referindo ao valor do ponteiro, mas sim ao valor para o qual aponta. Resumindo, podemos dizer que: &a *p o endereo de a o contedo da varivel apontada por p
No exemplo 1 acima, o valor da varivel v e o valor 25 so passados respectivamente para os argumentos a e b da funo func1. Apesar do valor de a e b ser alterado dentro da funo, essa mudana no se refletir no valor da varivel v pois o que passado para a funo apenas uma cpia do valor da varivel. 5.2.2.2 Passagem de parmetros por referncia A passagem de parmetros por referncia faz com que os valores das variveis passadas por referncia sejam alterados dentro da funo. Em C, quando queremos que isto acontea, ao invs de passarmos o valor como parmetro de uma funo, passamos o endereo dessa varivel (que no deixa de ser um valor). O endereo, no caso, faz as vezes de "referncia" para a varivel e nos permite alterar o contedo da mesma dentro da sub-rotina. Ex:
void main() { int a; func1(&a); Linguagem de Programao II - URI Campus de Frederico Westphalen
39
40
Funes do tipo char: As funes so do tipo char quando recebem um caracter como argumento.
Ex.:
#include <stdio.h> #include <conio.h> void impressao(char c); void main() { char meucaracter; printf("Informe um caracter pelo teclado\n"); meucaracter=getch(); impressao(meucaracter); } void impressao(char c) { int i; for(i=0;i<10;i++) printf("O caracter : %c\n",c); }
Funes do tipo double: As funes que aceitam e retornam um tipo double, ou seja um float com muita preciso so do tipo double. Todas as funes que esto definidas em math.h aceitam e retornam tipo double.
Funes do tipo int: As funes so do tipo int quando aceitam e retornam um inteiro como argumentos. Funes do tipo long: As funes so do tipo long quando aceitam e retornam long int como argumentos. Funes do tipo float: As funes so do tipo float quando aceitam e retornam float como argumentos. Ex.:
#include <stdio.h> #include <math.h> void hipotenusa(float x, float y); main() { float cateto_y, cateto_x; printf("Altura do tringulo retngulo: "); scanf("%f",cateto_y); printf("Base do tringulo retngulo: "); scanf("%f",cateto_x); hipotenusa(cateto_y,cateto_x); return(0); } void hipotenusa(float x, float y) { double minhahipo; minhahipo = hipot((double)x,(double)y); printf("A hipotenusa do tringulo : %f\n",minhahipo); } Linguagem de Programao II - URI Campus de Frederico Westphalen
program parametros; uses crt; var I: integer; begin if ParamCount = 0 then begin Writeln('Este programa no tem argumentos!'); exit; end; for I := 1 to ParamCount do Writeln('O ',I,' parmetro : ',ParamStr(I)); end.
41
42
O segundo argumento um ponteiro para as strings argv. Todos os argumentos so strings de caracteres, de modo que so conhecidos no programa como:
argv[1] argv[2] ... primeiro argumento segundo argumento
6. MATRIZES
Matrizes so variveis indexadas que contm diversos itens de dados do mesmo tipo. Cada matriz possui um nome, e seus elementos so acessados com a associao de um ndice ao nome da matriz. Uma matriz possui quatro propriedades bsicas: a) Os itens de dados individuais na matriz so chamados de elementos. b) Todos os elementos devem ser do mesmo tipo de dados. c) Todos os elementos so armazenados contiguamente na memria do computador, e em linguagem C o ndice do primento elemento sempre ser zero. d) O nome da matriz um valor constante que representa o endereo do primeiro elemento na matriz. Como todos os elementos so do mesmo tamanho, no podemos definir matrizes usando uma mistura de tipos de dados, pois a localizao de um elemento feita com base no endereo do primeiro elemento mais o deslocamento proporcional ao ndice. As matrizes podem ser unidimensionais quando o acesso a um de seus elementos feito atravs de um nico ndice, tambm conhecida como vetores em Pascal, ou multidimensionais quando possuem mais que uma dimenso, sendo necessrio mais de um ndice para acessar um de seus elementos.
Ex.:
#include <stdio.h> #include <stdlib.h> void main(int argc, char *argv[]) { int i; if (argc < 2) { printf("Este programa no tem argumentos!"); exit(1); } for (i=1;i < argc; i++) printf("O %d argumento %s\n",i,argv[i]); }
Os argumentos so recebidos da linha de comando e impressos na tela na mesma ordem. Se nmeros forem informados na linha de comando, eles sero interpretados como strings ASCII e impressos como caracteres. Se desejarmos fazer clculos com esses nmeros devemos convertlos de string para nmero com as funes de converso apropriadas (atoi, atol, atof que encontram-se definidas em stdlib.h)
43
44
Notas: Array[1..40,1..3] of integer; Uma matriz pode ser declarada e inicializada declarando-se no bloco de constantes:
const num1: array [1..5] of integer = (2,4,6,8,10); num2: array [1..2,1..5] of integer = ((10,20,30,40,50),(15,25,35,45,55));
Observe qua no se pode usar uma varivel na definio da matriz para dimensionar o seu tamanho, pois o compilador precisa alocar a memria necessria no momento da compilao.
6.3 Strings
Em Pascal temos o tipo de dado string predefinido na linguagem que nada mais que um vetor de caracteres.
6.2 Matrizes em C
Uma matriz em C definida escrevendo-se o tipo da matriz, seguida de um nome, e um par de colchetes contendo uma expresso constante que define o tamanho da matriz. <tipo> <nomematriz> [<tamanho>] Ex: int alunos[40]; Uma matriz multidimensional definida escrevendo-se o tipo da matriz, seguida de um nome, e tantos pares de colchetes quantas forem a dimenses, contendo uma expresso constante que define o tamanho da matriz em cada dimenso. Ex: int Notas[40][3]; Em C o primeiro elemento sempre ser o elemento de ndice 0. Uma matriz pode ser inicializada explicitamente quando declarada: Ex.:
#include <conio.h> #include <stdio.h> int numeros[3] = {2,4,6}; char vogais[5] = {'a','b','c','d','e'}; int num[2][5]={{2,4,6,8,10},{1,3,5,7,9}}; void main() { int i,j; for (i=0;i<2;i++) { printf("\n"); for (j=0;j<5;j++) { printf(" %d",num[i][j]); } } }
A linguagem C no possui este tipo de dado. Toda a vez que queremos uma string em C devemos declar-la como: char <nome> [<tamanho>]; Quando precisamos de um vetor de string, declaramos como uma matriz de caracteres, por exemplo, se queremos uma lista de 250 nomes com 80 letras cada: char nomes[250][80]; Toda a vez que precisamos fazer operaes com strings em C, como comparao, cpia de valores, concatenao, devemos usar as funes predefinidas em string.h:
Funo strcat strchr strcmp
Sintaxe e Funo char *strcat(char *dest, const char *src); Adiciona uma string a outra strcat adiciona uma cdia da string de origem para o final da string de destino. char *strchr(char *s, int c); Procura numa string a primeira ocorrncia de um caracter. Retorna um ponteiro para a primeira ocorrncia do caracter dentro da string. Se o caracter no for encontrado, strchr retorna NULL.. int strcmp(const char *s1, const char *s2); Compara uma string com outra e retorna: < 0 se s1 for menor que s2 = 0 se s1 for igual s2 > 0 se s1 for maior que s2 char *strcpy(char *dest, const char *src); Copia uma string para outra. Copia string src para dest. Retorna um ponteiro para a string dest. size_t strcspn(const char *s1, const char *s2); Procura em s1 at que qualquer um dos caracteres contidos em s2 encontrado. O nmero de caracteres que so lidos em s1 o valor retornado. int stricmp(const char *s1, const char *s2); Compara uma string com outra sem distino entre maiscula e minscula e retorna: < 0 se s1 for menor que s2 = 0 se s1 for igual s2 > 0 se s1 for maior que s2 size_t strlen(const char *s); Calcula e retorna o tamanho de uma string. char *strlwr(char *s); Converte letras maisculas em minsculas numa string. char *strncat(char *dest, const char *src, size_t n); Adiciona uma poro de uma string a outra. strncat copia n caracteres de src para o final de dest e acrescenta um caractere NULL.
45
46
strncmp
strncpy strnicmp
int strncmp(const char *s1, const char *s2, size_t n); Compara uma poro de uma string com uma poro de outra string. strncmp faz a mesma comparao que strcmp, mas analisa no mximo os n primeiros caracteres e retorna: < 0 se s1 for menor que s2 = 0 se s1 for igual s2 > 0 se s1 for maior que s2 char *strncpy(char *dest, const char *src, size_t n); Copia um um determinado nmero de bytes (n) de uma string para outra.. int strnicmp(const char *s1, const char *s2, size_t n); Compara uma poro de uma string com uma poro de outra string sem distino de maisculas com minsculas. strncmp faz a mesma comparao que stricmp, mas analisa no mximo os n primeiros caracteres. Retorna: < 0 se s1 for menor que s2 = 0 se s1 for igual s2 > 0 se s1 for maior que s2 char *strnset(char *s, int ch, size_t n); Altera os n primeiros caracters de uma string para um caractere especfico (ch). char *strrchr(const char *s, int c); Procura numa string pela ltima ocorrncia de um caracter (c). char *strrev(char *s); Reverte uma string. strrev muda todos os caracteres numa string para a ordem reversa, com exeo do caracter nulo de terminao. char *strset(char *s, int ch); Altera todos os caracteres numa string para um determinado caracter (ch). size_t strspn(const char *s1, const char *s2); Procura numa string s1 pelo primeiro segmento que difere de s2, retornando a posio onde inicia a diferena. char *strstr(const char *s1, const char *s2); Procura numa string s1 pela ocorrncia de uma dada substring s2. char *strupr(char *s); Converte letras minsculas numa string para maisculas.
47
48
7. DELPHI
O que o Delphi ? O Delphi nada mais que um simples IDE, IDE um ambiente integrado para desenvolvimento composto por compilador, editor de texto, ferramenta de depurao e alguns recursos a mais. Um IDE nem sempre um ambiente grafico. A diferena entre o IDE DELPHI para os outros IDE's por ai, que o DELPHI um IDE RAD. Sim o DELPHI RAD, isto , a medida em que os componentes vo sendo selecionados, o DELPHI escreve o cdigo fonte para voc. Os componentes em geral, incluem classes e propriedades muito utilizadas e que se relacionam com outros objetos. Tudo que nele existe foi pensando em Velocidade de Desenvolvimento. Um exemplo tpico para o RAD do DELPHI : Ao colocar um Boto num formulrio, veja o que ocorre: na clausula "uses", acrescenta a lib que contm o objeto TButton. Tambem criado um TButton.Create que cria o objeto para ser usado, mas dessa vez fica no arquivo .DFM. Se o object TButton possuir dependencias de outras classes, o DELPHI se encarrega de encontra-las e inclui-las em sua aplicacao.
Exemplo de passagem de passagem de parmetro por referncia de uma matriz. No caso de matrizes, pelo menos uma das dimenses tem que ser conhecida.
#include <stdio.h> #include <conio.h> void imprime(int mat2[][3], int l); void main() { int i, j, mat[3][3]; clrscr(); for (i=0;i<3;i++) { for (j=0;j<3;j++) { scanf("%d",&mat[i][j]); } } imprime(mat,3); } void imprime(int mat2[][3], int linha) { int a, b; for (a=0;a<linha;a++) { printf("\n"); for (b=0;b<3;b++) { printf("%d ",mat2[a][b]); } } }
Mas o DELPHI uma linguagem ou no ? Pois , se algum lhe perguntar em que linguagem voc cria seus sistemas, no diga "DELPHI" to rapidamente. Voc s deve dizer DELPHI, quando estiver em volta de um meio onde as pessoas conheam o DELPHI, tal como, lista de discusso sobre o assunto, forums relacionados, etc... Talvez voc esteja achando que estou sendo purista demais, no ? Veja bem, se voc for a uma lista, diga-mos de Linux, e falar que voce escreve programas em DELPHI, os programadores Linux que normalmente usam C, C++, etc... que no so usurios de DELPHI, mas entendem o que linguagem, vo entender que voc no entende nada sobre programao, pois voc no respondeu adequadamente. Na certa, vo achar que voc um daqueles que fica arrastando botezinhos, labelzinhos e depois vende um aplicativo quase sem nenhuma programao. Concluso : Se algum lhe perguntar que linguagem voc usa, nunca diga "DELPHI", diga : Object Pascal! ObjectPascal, a liguagem Quando voc est usando o DELPHI, a linguagem gerada por ele o ObjectPascal. Tanto isso verdade que possivel compilar o programa e seu codigo fonte sem a presena do DELPHI. Faa o teste :
dbcc32 [nome-do-dpr] lib [nome-das-libs]
49
O ObjectPascal, a linguagem pascal orientado a objetos, com todo o poder do OOP. Se voc for um timo programador ObjectPascal, talvez nem precise do DELPHI para escrever seus programas. O pessoal do FreePascal (outra linguagem compatvel com ObjectPascal) j faz isso h bastante tempo. Mas convenhamos, o DELPHI quebra um galho, com todos aqueles packages e componentes, a linha de comando para se compilar um projeto ObjectPascal na mo (da at Linguagem de Programao II - URI Campus de Frederico Westphalen 50
medo)... certamente no seria das tarefas mais agradveis. Temos de dar os parabens a Borland, escrever um IDE decente para uma linguagem no nada fcil. Outras linguagens, mesmos as mais complexas tornam-se fceis para o iniciante se tivermos um IDE decente, principalmente se for RAD. O pessoal do KDE (Linux) j vem trabalhando h muito tempo no Kdevelopment, um IDE parecido com o DELPHI para a linguagem C++, no entanto, no um IDE RAD, apenas um IDE. O KDevelopment um bom IDE, mas acho que no existe interesse em transforma-lo em RAD.
Exemplo: Se colocarmos um boto no form, a classe deste form ser modificada para incluir este boto. Os eventos e mtodos deste form, tambm esto na classe. Assim, supondo que o form se chame Form1 (nome default), para por exemplo desativar o boto que inclumos (de nome Buttom1) escreveramos:
Form1.Buttom1.Enabled := false;
Note como o Buttom1 faz parte da estrutura que define o form. Mas se quisermos ativar mtodo RePaint (Repintar) do form faramos:
Form1.Repaint;
Veja que Repaint, no uma varivel, tecnicamente uma procedure, mas fazemos referncia a ela como parte da estrutura Form1. Pode parecer confuso no incio, mas facilita muito a programao.
.PAS
.DFM
.CFG
.RES .DSK
Obs.: .~DF, .~PA , .~DP so arquivos de backup. Devido a grande quantidade de arquivos de uma aplicao, cada projeto deve ser montado em um diretrio especfico.
51
52
Obs.: Estes arquivos podem ser apagados para economizar espao em disco.
USES - Clusula que inicia uma lista de outras unidades compiladas (units) em que se basea: SysUtils = utilitrios do sistema (strings, data/hora, gerar arquivos) WinProcs = acesso a GDI, USER e KERNEL do Windows
PROGRAM - Define o Projeto; USES - Clusula que inicia uma lista de outras unidades. Forms = a unidade do Delphi que define a forma e os componentes do aplicativo In = A clausula indica ao compilador onde encontrar o arquivo Unit. Unit1 = A unidade que voc criou {$R *.RES} - Diretiva compiladora que inclui o arquivo de recursos. Abaixo veja como fica o Project quando voc abre um projeto novo:
program Project1; uses Forms, Unit1 in 'UNIT1.PAS' {Form1}; {$R *.RES} begin Application.CreateForm(TForm1, Form1); Application.Run; end.
Wintypes= tipos de dados e valores constantes Messages=constantes com os nmeros das mensagens do Windows e tipos de dados das Mensagens Classes=elementos de baixo nvel do sistema de componentes Graphics=elementos grficos Controls=elementos de nvel mdio do sistema de componentes Forms=componentes de forma e componentes invisveis de aplicativos Dialogs=componentes de dilogo comuns
53
54
Form. As declaraes desta seo so visveis apenas por ela mesma. Esta seo formada pelo seguinte cdigo: {$R*.DFM} - Diretiva compiladora que inclui toda a interface, propriedades da forma e componentes do arquivo *.DFM {$S+} - Diretiva compiladora que ativa verificao de pilha.
7.5.8 Inicialization
Nesta seo, que opcional, pode ser definido um cdigo para proceder as tarefas de inicializao da Unit quando o programa comea. Ela consiste na palavra reservada inicialization seguida por uma ou mais declaraes para serem executadas em ordem.
7.5.9 Exemplo
Abaixo veja como fica a unit quando voc abre um projeto novo:
unit Unit1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} {Uses Adicional} {Initialization} end.
55
56
Coluna de Propriedades
Separador de Colunas Coluna de Valores Propriedades aninhadas ( Duplo clique para visualizar subpropriedades)
7.10 Componentes
Os componentes so os objetos visuais e no visuais que permitem desenvolver uma aplicao com o Delphi. Cada janela, campo de edio, boto ou rtulo um componente.
Pgina de Propriedades
Pgina de Eventos
7.10.1 Nomenclatura
A pgina Properties (Propriedades) permite que voc estabelea parmetros de formulrios e componentes. Estes parmetros especificam os valores iniciais de caractersticas como nome do componente e sua posio no formulrio. A pginas Events (Eventos) permite associar os componentes com aes do usurio. Para ativar o ObectInspector durante a programao deve-se pressionar a tecla F11. Para nomear os componentes podemos usar uma conveno muito usada, onde as primeiras letras, minsculas, identificam o tipo do componente e o restante identifica a funo deste, assim, btnSair, seria o boto de sair. Se a funo do componente for um nome composto esse nome deve ser escrito com os primeiros nomes abreviados e com letras de caso varivel, como em btnRelVendas, que seria o boto do relatrio de vendas ou btnRelVenProduto, que seria o boto do relatrio de vendas por produto.
7.10.2 Propriedades
As propriedades so caractersticas dos componentes, como foi mostrado anteriormente.
57
58
Ctl3D Enabled Font Height HelpContext Hint Left Name PopupMenu ShowHint TabOrder TabStop Tag Top Visible Width
Define a aparncia 3D do componente Define se o componente est ativo, se pode ser usado Fonte utilizada no componente Altura Nmero utilizado para chamar o Help on-line String utilizada em dicas instantneas Posio esquerda Nome do componente Menu de contexto do componente Define se o Hint ser mostrado A ordem de tabulao do componente, usada quando o usurio tecla TAB Indica se o componente ser selecionado quando o usurio teclar TAB Propriedade no utilizada pelo Delphi, que pode ser usada como propriedade personalizada Posio superior Define se o componente est visvel Largura
7.10.4 Mtodos
Os mtodos realizam aes definidas pelo componente, veja os exemplos abaixo e atente para os parmetros passados. Note que podemos chamar os mtodos de evento como qualquer outro mtodo e que os mtodos de evento pertencem ao Form, no aos componentes.
Edit1.Clear; Form2.Show; Close; ScaleBy(110, 100); Button1.ScrollBy(10, 10); Button1.OnClick(Sender); Button1Click(Self); Form2.Button1Click(Sender);
7.10.3 Eventos
Os Eventos acontecem em resposta a uma ao do usurio ou do prprio sistema, ao programar um mtodo de evento, devemos levar em considerao que este s ser executados quando o evento acontecer. Uma das tarefas mais importantes na programao baseada em eventos determinar quais eventos sero usados e qual a ordem desses eventos, por exemplo, quando o usurio clicar em um boto, qual evento acontecer primeiro, OnEnter, OnMouseDown ou OnClick? Os eventos podem ser compartilhados entre componentes, dessa Forma, voc pode ter um boto na barra de ferramentas que faz a mesma coisa que uma opo de menu. Para isso, basta escolher o evento na lista em vez de clicar duas vezes no Object Inspector. Podemos tambm mudar os mtodos de evento em cdigo, pois os eventos tambm so propriedades e podem ser usados como tal. Voc pode atribuir um evento de outro componente ou diretamente o nome do mtodo, como mostrado abaixo.
Button1.OnClick := Edit1.OnExit; Button2.OnClick := Edit2Click;
59
60
OnClose OnActivate OnDeactivate OnResize Mtodo Cascade Tile ArrangeIcons ShowModal Show Close Previous Next
Quando o Form fechado Quando o Form recebe o foco Quando o Form perde o foco Quando o Form muda de tamanho Descrio Organiza as Forms filhos em cascata (MDI) Organiza as Forms filhos lado a lado (MDI) Organiza os cones dos Forms Filhos minimizados (MDI) Ativa o Form modal, que o usurio tem que fechar para poder continuar a usar a aplicao Mostra o Form Fecha o Form Ativa o Form anterior (MDI) Ativa a prximo Form (MDI)
7.10.7 TPopUpMenu
Menu de contexto de um componente. Cada componente tem uma propriedade PopUpMenu, que indica seu menu de contexto.
7.10.8 TLabel
Utilizado para exibir rtulos
Propriedade Alignment AutoSize WordWrap Transparent FocusControl ShowAccelChar Descrio Alinhamento do texto no componente Define se o tamanho do componente ser automaticamente ajustado ao tamanho do Caption Retorno automtico de linha Define se o componente ser transparente Componente que receber o foco quando a tecla de atalho do Caption (&) for pressionada Indica se o caractere & ser usado para definir tecla de atalho
7.10.6 TMainMenu
Menu principal de um Form.
Propriedade Items Descrio Itens de menu, essa propriedade guarda todas as alteraes feitas no Menu Designer
7.10.9 TEdit
Utilizado para entrada de texto em uma nica linha. Este componente permite somente a utilizao de texto (string), portanto qualquer leitura e escrita que envolva nmeros deve ser realizada com a respectiva converso de String para Inteiro (StrToInt ou StrToIntDef), de String para Real (StrToFloat), de Inteiro para String (IntToStr) ou de Real para String (FloatToStr). Exemplo:
Var x: integer; begin Edit1.text := Teste de Sistema; x := StrToInt(Edit2.text) * 2 ; Edit3.text := IntToStr(x); Edit4.clear; Propriedade Text AutoSelect MaxLength CharCase PasswordChar ReadOnly Mtodo Clear ClearSelection Descrio Texto do componente Indica se o texto ser ou no selecionado quando o componente receber o foco Nmero mximo de caracteres permitidos Define se as letras aparecero em maisculo, minsculo ou normal Caractere utilizado para esconder o texto digitado (Senhas) Define se ser permitido alterar o texto Descrio Limpa o contedo do componente Limpa o texto selecionado no componente
Este componente permite a fcil construo de menus. Aps sua colocao no form, basta executar um duplo-click que aparecer o MenuDesigner, colocando na propriedade Caption o contedo do item de menu. Voc pode clicar e arrastar os itens do menu para rearranj-los em seu projeto. No necessrio rodar o projeto para ver os resultados o menu est sempre visvel na janela de formulrio, com a aparncia que ter durante a execuo do programa. Para se criar sub-menus, clique com o boto direito do mouse no item que voc deseja criar o sub-menu, e escolha a opo Create Submenu (Ctrl+Right); o processo de construo igual ao descrito acima. No h limite para os nveis de sub-menu. Pode-se deletar menus selecionan-dos, e pressinando a tecla Del; e inserir menus clicando-se na tecla Insert - estas operaes so igualmente possveis atravs do acionamento de speedmenu do MenuDesigner (acessa-se o speedmenu, clicando-se o boto direito do mouse sob o MenuDesigner). Colocando um & antes de uma letra do menu (capitulao), ela aparece sublinhada. O usurio pode selecionar a opo do menu apenas pressionando a letra quando o menu estiver aberto. Regras para capitulao: 1 primeira letra; 2 se houver duas letras iniciais iguais, pega-se a primeira consoante; se houver a primeira consoante igual; pega-se o Segunda consoante e assim procede-se at esgortar-se as consoantes; 3 caso os passos 1 e 2 se esgotarem, pega-se a primeira vogal e assim sucessivamente; 4 se no for possvel capitular as opes, pode-se diferencia-las com o acrscimo de caracteres extras ou optar-se por no capitul-las
7.10.10 TMemo
Permite entrada de dados texto em mltiplas linhas. Contm propriedades e mtodos do TEdit. Este componente tambm permite somente a utilizao de texto (string), portanto qualquer leitura e escrita que envolva nmeros deve ser realizada com a respectiva converso de String para Inteiro (StrToInt ou StrToIntDef), de String para Real (StrToFloat), de Inteiro para String (IntToStr) ou de Real para String (FloatToStr).
61
62
Exemplo:
Var x: integer; begin memo1.clear; memol.lines.add(Teste de Sistema); x := StrToInt(Edit2.text) * 2 ; memo1.lines.add(IntToStr(x));
Define se a seleo poder ser estendida pelo uso das teclas Shift e Ctrl Define se os itens podero aparecer parcialmente ou somente por completo Lista de strings com os itens da lista ndice do item selecionado, comeando em 0 De acordo com o ndice indica se um item em particular esta selecionado Indica quantos itens esto selecionado Define se os itens aparecero ordenados
7.10.15 TComboBox
Propriedade Lines WantReturns WantTabs ScrollBar Descrio Propriedade do tipo TStrings que armazena as linhas de texto do componente Define se a tecla ENTER ser tratada como quebra de linha Define se a tecla TAB ser tratada como espao de tabulao Define as barras de rolagem
7.10.11 TButton
Componente boto padro do Windows, utilizado para executar aes.
Propriedade Cancel Default ModalResult Mtodo Click Descrio Dispara o evento OnClick do boto quando a tecla ESC pressionada em qualquer controle Dispara o evento OnClick do boto quando a tecla ENTER pressionada em qualquer controle Associa o boto a opo de fechamento de um Form modal Descrio Ativa o evento OnClick do boto
7.10.16 TScrollBox
Container com barras de rolagem automticas.
7.10.17 TGroupBox
Componente container com um ttulo e borda 3D. Utilizado com RadioButtons.
7.10.12 TCheckBox
Utilizado para obter inFormaes de checagem.
Propriedade AllowGrayed Checked State Descrio Determina se o checkbox ter trs possibilidades de estado Determina se o checkbox est marcado Estado atual do checkbox
7.10.18 TRadioGroup
Componente que agrupa e controla RadioButtons automaticamente.
Propriedade Columns Items ItemIndex Descrio Nmero de colunas de RadioButtons Lista de strings com os itens do RadioGroup, cada item da lista representa um RadioButton Item selecionado, iniciando em 0
A principal propriedade deste componente a Checked, que indica se o CheckBox est marcado ou desmarcado. Tipicamente, este controle mostra dois tipos de escolha (True ou False). Mas podemos configurar para que ele mostre trs estados diferentes. Para isto colocamos a propriedade AllowGrayed para True e passamos a ler o estado do componente pela propriedade State, que pode assumir um dos trs valores seguintes: cbUnchecked, cbGrayed, cbChecked.
Para acessar o ndice do componente selecionado utilize: <nome do componente>.ItemIndex Ex.: showmessage (Selecionada a + IntToStr(RadioGroup1.ItemIndex) + Opo.); showmessage (Selecionada a + IntToStr(ComboBox1.ItemIndex) + Opo.); showmessage (Selecionada a + IntToStr(ListBox1.ItemIndex) + Opo.); Para acessar o texto do componente selecionado utilize: <nome do componente>.Items[<nome do componente>.ItemIndex ] showmessage (Opo escolhida: + ListBox1.Items[ListBox1.ItemIndex]); showmessage (Opo escolhida: + RadioGruop1.Items[RadioGroup1.ItemIndex]); showmessage (Opo escolhida: + ComboBox1.Items[ComboBox1.ItemIndex]); showmessage (Opo escolhida: + ComboBox1.Text);
7.10.13 TRadioButton
Usado em grupo, pode ser utilizado para obter inFormaes lgicas mutuamente exclusivas, mas recomendado usar o RadioGroup em vez de RadioButtons.
7.10.14 TListBox
Utilizado para exibir opes em uma lista.
Propriedade Columns MultiSelect Descrio Nmero de colunas de texto da lista Define se ser permitida a seleo de mltiplos itens
7.10.19 TPanel
Componente Container utilizado para agrupar componentes em um painel. 63
Linguagem de Programao II - URI Campus de Frederico Westphalen
64
Descrio Estilo da moldura interna do painel Estilo da moldura externa do painel Largura das molduras Estilo da Borda Largura da borda, distncia entre as molduras interna e externa
7.10.23 TBevel
Moldura ou linha com aparncia 3D.
Propriedade Shape Style Descrio Tipo de moldura a ser desenhada Define alto ou baixo relevo para a linha
7.10.20 TActionList
Usado para criar lista de aes para serem usadas com SpeedButtons e MenuItems.
7.10.24 TShape
Grfico de uma Forma geomtrica.
7.10.21 TBitBtn
Boto especializado, com Bitmap.
Propriedade Glyph LayOut Margin Spacing Kind Descrio Bitmap exibido pelo boto Posio do Bitmap no Boto Indica o espao entre a borda do boto e o Bitmap Indica o espao entre o Bitmap e o texto do boto Seleciona um tipo padro para o boto, mudando vrias propriedades, como Glyph e ModalResult
Descrio Preenchimento da figura, objeto do tipo TBrush Tipo da linha, objeto do tipo TPen Forma geomtrica
7.10.25 TImage
Componente usado para exibir figuras.
Propriedade Center Picture Stretch Descrio Determina de a figura ser centralizada no componente Figura a exibida, pode ser BMP, ICO, WMF ou EMF Define se o tamanho da figura deve ser ajustada ao do componente
7.10.22 TMaskEdit
Permite entrada de dados texto em uma linha, utilizando uma mscara de edio. Possui todas as propriedades do componente TEdit.
Propriedade EditMask Descrio Mscara de edio
7.10.26 TPageControl
Usado para criar controles com mltiplas pginas, que podem ser manipuladas, em tempo de projeto, atravs do menu de contexto. Cada pgina criada um objeto do tipo TTabSheet.
Propriedade ActivePage MultiLine TabHeigth TabWidth Evento OnChange OnChanging Mtodo FindNextPage SelectNextPage Descrio Pgina ativa Define mltiplas linhas de guias de pginas Altura das guias Largura das guias Descrio Aps uma mudana de pgina Permite a validao de uma mudana de pgina Descrio Retorna a prxima pgina Seleciona a prxima pgina
Mscaras Uma mscara composta por trs partes, a primeira parte a mscara propriamente dita, a segunda parte indica se os caracteres literais sero salvos e a terceira parte indica qual o caractere utilizado para representar os espaos a serem digitados no texto. Estes so os caracteres especiais que podem compor a mscara de edio:
Caractere ! > < \ l L a A 9 0 c C # : / Descrio Espaos em branco no sero considerados no texto Todos os caracteres seguintes sero maisculos at que aparea o caractere < Todos os caracteres seguintes sero minsculos at que aparea o caractere > Indica um caractere literal Somente caractere alfabtico Obrigatoriamente um caractere alfabtico Somente caractere alfanumrico Obrigatoriamente caractere alfanumrico Somente caractere numrico Obrigatoriamente caractere numrico Permite um caractere Obrigatoriamente um caractere Permite um caractere numrico ou sinal de mais ou de menos, mas no os requer. Separador de horas, minutos e segundos Separador de dias, meses e anos
7.10.27 TTabSheet
Pgina de um PageControl.
Propriedade PageIndex TabVisible Descrio Ordem da pgina Define se a aba da pgina visvel
7.10.28 TTimer
Permite a execuo de um evento a cada intervalo de tempo. 65
Linguagem de Programao II - URI Campus de Frederico Westphalen
66
Descrio Tempo em milissegundos quando o componente ir disparar o evento OnTimer Descrio Chamado a cada ciclo de tempo determinado em Interval
7.10.29 TStatusBar
Utilizado para criar barras de status para exibir informaes.
Propriedade SimplePanel SimpleText SizeGrip Panels Descrio Indica se haver apenas um panel Texto exibido caso SimplePanel seja True Define se a ala de redimensionamento padro deve ser mostrada Propriedade do tipo TStatusPanels, com os painis do StatusBar. O texto da barra de status definido com a propriedade StatusBarX.panels[X].text
7.11.1 ShowMessage
Esta funo permite colocar uma caixa de dilogo contendo um boto de OK e uma mensagem. No podemos colocar outros botes nem mudar o ttulo, que sempre o nome do programa.
showmessage(Coloque sua mensagem aqui!);
7.10.30 TStatusPanels
Lista de panels de um StatusBar.
Propriedade Count Items Mtodo Add Descrio Nmero de panels Lista de panels, cada panel um objeto do tipo TStatusPanel Descrio Adiciona um novo panel lista
7.11.2 MessageBox
Esta permite que atribuam valores arbitrrios ao ttulo e as mensagens. Existem dois tipos de MessageBox: um da API ( MessageBox ) e um do Delphi ( Application.MessageBox ). Ambos permitem que se atribuam valores tanto ao recheio como para o ttulo; tambm permitem que se acrescentem constantes MB_xxx para mudar o aspecto da caixa de dilogo. MessageBox retorna um valor dependendo do boto pressionado. Sintaxe: MessageBox(<Mensagem da caixa>, <Titulo>, Constantes MB_xxx); <Mensagem da caixa>: string que ser mostrado no interior da caixa. <Titulo>: string que ser mostrado no titulo da caixa. <Constantes MB_xxx>: concatenao de constantes que mudaro o aspecto da caixa. Podem ser:
Valor MB_ABORTRETRYIGNORE MB_APPLMODAL MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 MB_DEFBUTTON4 MB_HELP MB_ICONASTERISK MB_ICONERROR MB_ICONEXCLAMATION MB_ICONHAND MB_ICONINFORMATION MB_ICONQUESTION MB_ICONSTOP MB_ICONWARNING MB_OK Significado A caixa de dilogo conter trs botes: Anular, Repetir e Ignorar A caixa de dilogo ser modal. O primeiro boto da caixa de dilogo fica como default O segundo boto da caixa de dilogo fica como default O terceiro boto da caixa de dilogo fica como default O quarto boto da caixa de dilogo fica como default adicionado um boto de Ajuda na caixa de dilogo, quando for pressionado ou a tecla F1 gerado o evento de Help, vlido somente para Windows 95, Mostra um i azul, minsculo dentro de um balo (MB_ICONINFORMATION) Mostra um X banco, dentro de um circulo vermelho, o mesmo que MB_ICONHAND, somente para windowes 95. Mostra um ponto de exclamao, dentro de um tringulo amarelo O mesmo que MB_ICONSTOP O mesmo que MB_ICONASTERIX Mostra um ponto de interrogao dentro de um balo O mesmo que MB_ICONERROR O mesmo quer MB_ICONEXCLAMATION, vlido somente para windows 95. A caixa de dilogo conter um boto de OK
7.10.31 TStatusPanel
Panel de um StatusBar.
Propriedade Text Width Bevel Alignment Descrio Texto do panel Largura em pixels Moldura do panel Alinhamento do texto de um panel
7.10.32 TStringGrid
Componente para exibio e edio de uma tabela de strings. organizado em linhas e colunas e o elemento bsico a celula.
Propriedade ColCount RowCount DefaultColWidth DefaultRowHeight Cells FixedCols FixedRows Row Col Options LoadFromFile SaveToFile Descrio Quantidade de lolunas Quantidade de linhas Altura padro das colunas Largura padro das linhas Texto das clulas. uma matriz em que deve ser especificado linha e coluna. Exemplo: StringGrid1.cells[2,3] Quantidade de Colunas fixas Quantidade de Linhas fixas Linha Selecionada Coluna selecionada Conjunto de Opes do StringGrid Carrega figura de um arquivo Salva figura para um arquivo
67
68
A caixa de dilogo conter os botes de OK e Cancelar A caixa de dilogo conter botes de Repetir e Cancelar A caixa de dilogo conter botes de Sim e No A caixa de dilogo conter botes de Sim, No e Cancelar
7.12 Dicas
Resumo dos componentes com as principais propriedades e mtodos:
Componente Application
Propriedades
Form Label Caption Enabled Font Name Enabled Font Maxlength Name PasswordChar ReadOnly Text Caption Enabled Font Name Text Caption Checked Enabled Font Name Caption Checked Enabled Font Name State Enabled Font Lines Maxlength Name ReadOnly ScrollBars Enabled Font Items MultiSelect Name Sorted
Edit
Setfocus Clear
Setfocus
RadioButton
Setfocus
CheckBox
Setfocus
7.11.3 InputBox
Permite que o usurio digite uma string na caixa de dilogo. Possui os botes OK e Cancel. Se o usurio clicar em cancel o texto padro retornado. Sintaxe: InputBox(<Ttulo>, <Mensagem da Caixa>, <texto padro>
var Texto: string; begin Texto:= InputBox('Gerenciador de Aplicativo', 'Informe a Senha', 'Ningum'); showmessage(texto); end; Linguagem de Programao II - URI Campus de Frederico Westphalen
Memo
ListBox
69
70
ComboBox
RadioGroup
Enabled Font ItemIndex Items Name Sorted Text Enabled Font ItemIndex Items Name
Para pedir confirmao antes de encerrar o programa, inserir o cdigo abaixo no evento OnCloseQuery do Formulrio:
if application.messagebox('Encerrar o Programa?', 'Confirmao', MB_APPLMODAL+MB_ICONQUESTION+MB_YESNO) = idyes then canclose:= true else canclose:= false;
Converses Todos os componentes de entrada de dados utilizam a propriedade text que string. Para manipulao de nmeros necessrio uma converso do formato.
Funo Date DateToStr DecodeDate DecodeTime Now FloatToStr FormatFloat Descrio retorna a data corrente converte um valor data em string. Separa a data em dia, ms, ano Separa a hora em hora, minutos, segundos, centsimos Retorna a data e hora do sistema converte um nmero float numa string. formata um nmero float e retorna uma string. (#,##.00,10000,2) = 10.000,24 converte um nmero inteiro numa string. converte uma string num nmero inteiro e atribui um valor padro em caso de erro transforma um nmero em string com nmero de casas pr-definido converte uma string em data. converte uma string num nmero float. converte uma string num nmero inteiro converte uma string em hora retorna a hora corrente. converte a hora corrente em string. Transforma uma string num nmero e permite analisar o sucesso desta transformao Exemplo Edit.text := 'Hoje ' + DateToStr(Date); DecodeDate(Date, ano, mes, dia); DecodeTime(Now, Hora, Min, Seg, cent);
Para aceitar somente nmeros em campos Edit e ComboBox, Inserir o cdigo abaixo no evento OnKeyPress do controle de edio:
end;
Para saltar de um campo para outro usando a tecla ENTER, Inserir o cdigo abaixo no evento OnKeyPress do controle de edio de cada componente:
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char); begin if Key=#13 then begin SelectNext(Sender as TWinControl, True, True); key:=#0; end; end;
IntToStr StrToIntDef
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if key=#13 then begin key:=#0; PostMessage( handle, WM_KEYDOWN, VK_TAB, 1); end; end;
Para saltar de um campo para outro usando a tecla ENTER de todos os componentes, Inserir o cdigo abaixo no evento OnKeyPress do Formulrio:
Str(X:0:2, S); CData := StrToDate(Edit1.Text); x:= StrToFloat(edit1.text); i:= x:= StrToInt(edit1.text); ATime := StrToTime(Edit1.Text); Edit1.text := 'A hora ' + TimeToStr(Time)
Atribua true propriedade KeyPreview do Formulrio. Esta rotina no funcionar em formulrios que tenham TMemo ou TDBMemo. Estes componentes precisam da tecla ENTER para gerar novas linhas. Em formulrios assim, a rotina pode ser usada, desde que seja inserido no evento OnEnter do componente Memo o cdigo:
procedure TForm1.Memo1Enter(Sender: TObject); begin Form1.KeyPreview:=false; end; procedure TForm1.Memo1Exit(Sender: TObject); begin Form1.KeyPreview:=true; end;
var I, erro: Integer; begin Val(Edit1.Text, I, erro); if erro <> 0 then begin Showmessage('Erro); end;
71
72
Edit3.clear; Edit1.setFocus; Observe que o cdigo deve ficar dentro do procedimento que implementa o evento, desta forma: procedure TForm1.Button2Click(Sender: TObject); begin Edit1.clear; Edit2.clear; Edit3.clear; Edit1.setFocus; end;
2. Faa um programa em Delphi que leia 2 nmeros e escreva a soma dos mesmos. O programa deve ter: - 2 campos de entrada de valor - 1 campo de escrita - 2 botes de ao: OK e Limpar
Mude o ttulo da janela do Form (propriedade Caption do Form) para Nome Completo; Mude as propriedades do campo que escreve o Nome Completo para que fique somente leitura (ReadOnly = true) e que no aceite a parada na tabulao (TabStop = false); Implemente o mtodo ao clicar no do boto OK, dando 2 cliques sobre o mesmo ou selecionando o boto e dando 2 cliques sobre o evento OnClick do ObjectInspector, colocando o seguinte cdigo
Edit3.text := Edit1.text + ' ' + Edit2.Text;
Observe que o cdigo deve ficar dentro do procedimento que implementa o evento, desta forma:
procedure TForm1.Button1Click(Sender: TObject); begin Edit3.text := Edit1.text + ' ' + Edit2.Text; end;
Mude o ttulo da janela do Form (propriedade Caption do Form) para Soma de 2 Nmeros; Mude as propriedades do campo que escreve a Soma para que fique somente leitura (ReadOnly = true) e que no aceite a parada na tabulao (TabStop = false); Implemente o mtodo ao clicar no do boto OK, dando 2 cliques sobre o mesmo ou selecionando o boto e dando 2 cliques sobre o evento OnClick do ObjectInspector, criando 3 variveis (a, b, soma) e implementando o seguinte cdigo:
Importante: Quando for apagar um cdigo, apague somente o cdigo que voc escreveu. A estrutura que o Delphi criou para implementar os eventos no pode ser apagada por voc. Se quiser remover, deixe-a sem nenhum cdigo implementado, que na prxima Compilao, o Delphi a remover. Implemente o mtodo ao clicar no do boto Limpar, dando 2 cliques sobre o mesmo ou selecionando o boto e dando 2 cliques sobre o evento OnClick do ObjectInspector, colocando o seguinte cdigo
procedure TForm1.Button1Click(Sender: TObject); var a, b, soma: integer; begin a:= StrToInt(Edit1.Text); b:= StrToInt(Edit2.Text); soma := a + b; Edit3.text := IntToStr(soma); end; Linguagem de Programao II - URI Campus de Frederico Westphalen
O Delphi cria esta estrutura para implementar os eventos. O programa deve ser implementado dentro dela
73
74
Implemente o mtodo ao clicar no do boto Limpar, dando 2 cliques sobre o mesmo ou selecionando o boto e dando 2 cliques sobre o evento OnClick do ObjectInspector, colocando o seguinte cdigo:
end;
end;
3. Faa um programa em Delphi que leia um nmero e escreva os seus mltiplos entre 1 e 200. O programa deve ter: 1 campos de entrada de valor 1memo para a apresentao do resultado 3 botes de ao: Executar, limpar, sair
4. Faa um programa em Delphi que leia um valor para a escolha e 3 valores para serem ordenados e escreva: - em ordem crescente, se a escolha for o primeiro boto - em ordem decrescente, se i a escolha for o segundo boto - o maior valor entre os dois, se i a escolha for o terceiro boto O programa deve ter: 1RadioGroup com 3 RadioButtons (Opo 1, 2, 3) 3 campos de entrada de valor 1Memo para a apresentao do resultado 3 botes de ao: ordenar, limpar, sair
Renomeie o boto Calcular para BtCalcular Renomeie o boto Limpar para BtLimpar Renomeie o boto Sair BtSair; Implemente o evento ao Clicar no Boto Calcular:
procedure TForm1.BtCalcularClick(Sender: TObject); var x, i: integer; begin memo1.clear; x:=StrToIntDef(Edit1.Text, 0); if x>0 then begin for i:= 1 to 200 do Linguagem de Programao II - URI Campus de Frederico Westphalen
75
76
procedure TForm1.BtLimparClick(Sender: TObject); begin Edit1.clear; Edit2.clear; Edit3.clear; Memo1.clear; RadioGroup1.ItemIndex:=-1; Edit1.setfocus; end;
procedure TForm1.BtOrdenarClick(Sender: TObject); var a, b, c, aux: integer; begin Memo1.clear; a:=StrToIntDef(Edit1.text, 0); b:=StrToIntDef(Edit2.text, 0); c:=StrToIntDef(Edit3.text, 0); if a>b then begin aux:=a; a:=b; b:=aux; end; if a>c then begin aux:=a; a:=c; c:=aux; end; if b>c then begin aux:=b; b:=c; c:=aux; end; BtLimpar.setfocus; if RadioGroup1.itemindex=0 then begin memo1.lines.add(IntToStr(a)); memo1.lines.add(IntToStr(b)); memo1.lines.add(IntToStr(c)); end else if RadioGroup1.itemindex=1 then begin memo1.lines.add(IntToStr(c)); memo1.lines.add(IntToStr(b)); memo1.lines.add(IntToStr(a)); end else if RadioGroup1.itemindex=2 then begin memo1.lines.add(IntToStr(a)); memo1.lines.add(IntToStr(c)); memo1.lines.add(IntToStr(b)); end else begin showmessage('Voc deve escolher a ordem de classificao!'); RadioGroup1.setfocus; end end;
Por exemplo se queremos criar uma estrutura (tipo definido pelo usurio) cadastro e definirmos uma varivel cliente que do tipo (estrutura) cadastro:
#include <stdio.h> #include <conio.h> struct cadastro { char nome[30]; char endereco[50]; char cidade[20]; } cliente; void main() { printf(Nome: ); gets(cliente.nome); printf(Endereo: ); gets(cliente.endereco); printf(Cidade: ); gets(cliente.cidade); clrscr(); printf(%s mora na rua %s, na cidade de %s, cliente.nome, cliente.endereco,cliente.cidade); }
77
78
printf(Nome: ); gets(cliente[i].nome); printf(Endereo: ); gets(cliente[i].endereco); printf(Cidade: ); gets(cliente[i].cidade); } clrscr(); for(i=0;i<5;i++) { printf(%s mora na rua %s, na cidade de %s \n, cliente[i].nome, cliente[i].endereco, cliente[i].cidade); } }
79
80
void leprod(produto *ptr); void imprimeprod(produto *ptr); void main() { leprod(&p1); leprod(&p2); clrscr(); imprimeprod(&p1); imprimeprod(&p2); getch(); } void leprod(produto *ptr) { int aux; float aux2; fflush(stdin); printf("Codigo: "); scanf("%d",&aux); ptr->codigo = aux; fflush(stdin); printf("Descricao: "); gets(ptr->descr); printf("Preco: "); scanf("%f",&aux2); ptr->preco = aux2; } void imprimeprod(produto *ptr) { printf("%d\n",ptr->codigo); puts(ptr->descr); printf("%0.2f\n",ptr->preco); }
Ento poderemos declarar um ponteiro denominado meu_ponteiro para meus_dados como este:
struct grande_estrutura_dados *meu_ponteiro;
A partir de agora, podemos nos referir aos campos em meus_dados como meus_dados.chave, como:
meu_ponteiro->chave = 5;
Em outras palavras, meu_ponteiro um ponteiro para uma estrutura; para alcanar um campo na estrutura para a qual ele aponta, utilize o operador seta, ->. Essa a razo pela qual o operador -> foi desenvolvido: para permitir escolher campos isolados da estrutura que est sendo apontada. Foram includos os operadores * e & expressamente para aqueles casos em que apontamos para uma estrutura, porque & ou * sozinhos no podem acessar elementos. Ou seja, no existe algo como *meu_ponteiro.chave; temos que utilizar em seu lugar meu_ponteiro>chave. Uma estrutura somente pode ser passada para uma funo por referncia, atravs de um ponteiro para a estrutura. Por exemplo:
#include <stdio.h> #include <conio.h> struct produto { int codigo; char descr[80]; float preco; }p1, p2; Linguagem de Programao II - URI Campus de Frederico Westphalen
81
campos de um arquivo deve ser feita atravs da referncia do nome do registro e o nome do campo unidos por um ponto (.).
Pode-se tambm armazenar os registros em memria, atravs do uso de vetores ou matrizes de estrutras.
Exemplo: Program ExemploRegistroSeletivo; uses crt; type cadastro = record codigo: integer; nome: string[30]; rg: string[15]; end; var cad: Array [1..10] of cadastro; i: integer; begin clrscr; for i:= 1 to 10 do begin write('Codigo: '); readln(cad[i].codigo); write('Nome: '); readln(cad[i].nome); write('RG: '); readln(cad[i].rg); end; clrscr; for i:= 1 to 10 do begin writeln(cad[i].codigo, ' - ', cad[i].nome, ' - ', cad[i].rg); end; readkey;
Exemplos : TYPE registro = RECORD nome : STRING[30]; ende : STRING[25]; fone : STRING[8]; idade : BYTE; END; tela END; = RECORD atributo : BYTE; caracter : CHAR;
end.
BEGIN reg.nome := Roberto; reg.ende := Rua Annima, 0; reg.fone := 999-9999; reg.idade:= 30; writeln(Nome: , reg.nome); writeln(Endereo: , reg.ende); writeln(Fone: , reg.fone); writeln(Idade: , reg.idade); write(Nome: ); readln(reg.nome); write(Endereo: readln(reg.ende); write(Fone: readln(reg.fone); write(Idade: readln(reg.idade); writeln(Nome: , reg.nome); writeln(Endereo: , reg.ende); writeln(Fone: , reg.fone); writeln(Idade: , reg.idade); END.
8.2 Unies
Uma Unio um tipo de dados muito similar uma estrutura, com a diferena de que todos os membros de uma unio compartilham a mesma rea de armazenamento, enquanto cada membro de uma estrutura possui a sua prpria rea. As unies so teis para economizar memria, em situaes nas quais os campos de uma estrutura so mutuamente exclusivos. Ex.:
union algum { int i; char c; } u;
Neste caso, a varivel u somente poder conter o valor do campo i ou do campo c, mas no de ambos. O compilador reservar rea suficiente para o maior tipo contido na unio. Em Pascal e Delphi, podemos ter uma estrutura de registro seletivo :
83
84
uniao = record Nome: string[30]; case campo: Classe of Num: (N: real); Str: (S: string); end; var un: uniao; op: char; begin clrscr; write('Nome: '); readln(un.nome); writeln('O que voce quer armazenar: [N] Numero - [S] - String?'); op:=readkey; if upcase(op)='N' then begin write('Digite um numero: '); readln(un.N); writeln(un.nome); writeln(un.N:0:6); end else begin write('Digite uma string: '); readln(un.S); writeln(un.nome); writeln(un.S); end; readkey; end.
8.3.2 enum
O tipo de dado enum permite que criemos um tipo de dado com uma escolha de itens. enum til quando a informao pode ser melhor representada por uma lista de valores inteiros,
Neste tipo de registro, temos a possibilidade de variar a estrutura. dependendo da condio encontrada no decorrer do programa para um campo-sinal previamente declarado como tipo escalar, esta estrutura de seleo chamada de unio discriminada, cabendo desta forma ao programador manter vlida.
85
86
9. ARQUIVOS
Para comearmos a manipular arquivos, necessitamos lembrar alguns conceitos bsicos a respeito dos mesmos. Quando pensamos em arquivos, a primeira coisa que nos vem memria a idia de um arquivo fsico igual aos arquivos encontrados nos escritrios. De forma geral um arquivo serve para armazenar informaes atravs de fichas. Em informtica, estes conceitos so perfeitamente vlidos, pois para o armazenamento de informaes em um arquivo, temos que dar uma forma ao arquivo e dar forma s informaes que estaro contidas nele.
semelhantes, como por exemplo abrir uma gaveta, retirar ou colocar uma ficha, fechar uma gaveta, identificar o arquivo atravs de uma etiqueta qualquer, organizar as informaes, etc. Veremos ento os comandos para fazermos tais tarefas: O primeiro comando que veremos o que nos permite associar a varivel do tipo arquivo ao nome externo deste arquivo, ou seja, o nome local que este deve estar.
ASSIGN Este procedimento permite que associemos o nome externo de um arquivo a uma varivel do tipo arquivo. O nome externo aquele utilizado pelo sistema operacional, portanto deve ser vlido para o mesmo. So possveis todas as formas de referncia usadas no PATH, e quando a unidade ou subdiretrios forem omitidos, estes assumiro o default. Aps o uso do ASSIGN, este continuar valendo at que seja dado um novo ASSIGN. O tamanho mximo do nome do arquivo de 79 bytes. Este procedimento nunca deve ser usado em um arquivo j aberto, pois caso o nome do arquivo tenha tamanho zero, o arquivo ser associado ao dispositivo padro de saida. Sua sintaxe: ASSIGN(VAR <arq>, <nomearq> : STRING); arq, deve ser uma varivel do tipo arquivo. por exemplo:
Exemplo: PROGRAM teste_assign; VAR arq1, arq2 : FILE OF BYTE; BEGIN ASSIGN(arq2,teste.dat); ASSIGN(arq1,''); {o nome externo do arquivo omitido} END. {determina que o dispositivo de saida } {ser o standart }
FILE Esta declarao define uma varivel como sendo arquivo. Sua sintaxe : identificador : FILE OF tipo; ou identificador : FILE; Vejamos um exemplo de definio de um tipo arquivo:
TYPE registro = RECORD nome : STRING[30]; cep : LONGINT; rg : STRING[8]; cic : STRING[11]; END; VAR arquivo_pessoal : FILE OF registro; arquivo_numerico : FILE OF BYTE; arquivo_sem_tipo : FILE;
RESET Este procedimento permite-nos abrir um arquivo j existente. No caso do uso deste, para a tentativa de abertura de um arquivo no existente, ocorrer um erro de execuo. Para que o
Porm, somente a declarao de uma varivel do tipo arquivo no quer dizer que j podemos manipular o arquivo, assim como no arquivo fsico, aquele de ao, aqui teremos tarefas
Linguagem de Programao II - URI Campus de Frederico Westphalen
87
88
procedimento tenha sucesso necessrio que antes de execut-lo, tenhamos utilizado o procedimento ASSIGN. Sua sintaxe : RESET(VAR <arquivo> [:FILE; <tamanho> : WORD]);
Exemplo: PROGRAM teste_reset; Uses CRT; VAR arquivo : FILE OF BYTE; nomearq : STRING[67]; BEGIN WRITE('Entre com o nome do arquivo que quer abrir ') ; READLN(nomearq); ASSIGN(arquivo,nomearq); RESET(arquivo); END.
Pascal chamada IORESULT. Para no abortar um programa quando ocorre um erro de I/O, usa-se a diretiva {$I}. Para voltar ao padro, usa-se a diretiva {$I+}. Por exemplo:
PROGRAM teste_rewrite_ou_close; Uses Crt; VAR arquivo : FILE OF BYTE; nomearq: STRING[67]; BEGIN WRITE('Entre com o nome do arquivo que quer abrir '); READLN(nomearq); ASSIGN(arquivo,nomearq); {$I-} RESET(arquivo); {$I+} if IORESULT <> 0 then REWRITE(arquivo); END.
Este comando apenas permite-nos abrir um arquivo j existente. para que possamos abrir um arquivo novo, temos um outro comando:
REWRITE Este comando permite criar e abrir um novo arquivo. Caso o arquivo j exista, ter seu contedo eliminado e ser gerado um novo arquivo. Antes de executarmos este procedimento, devemos usar o ASSIGN, e caso a varivel do tipo arquivo no seja tipada, o tamanho de cada registro ser de 128 bytes, isto se no for especificado o tamanho do registro. Sua sintaxe: REWRITE(VAR <arquivo> [: FILE ; <tamanho> : WORD]); Vejamos um exemplo, usando o comando REWRITE :
PROGRAM teste_rewrite; Uses Crt; VAR arquivo : FILE OF BYTE; nomearq: STRING[67]; BEGIN WRITE('Entre com o nome do arquivo que quer abrir '); READLN(nomearq); ASSIGN(arquivo,nomearq); REWRITE(arquivo); END.
A segunda tarefa que devemos nos preocupar o fato do arquivo permanecer aberto, ou abrirmos o mesmo arquivo mais de uma vez. Para termos um uso adequado de um arquivo, devemos abri-lo e depois de utilizado fech-lo.
RESET Este procedimento permite gue se feche um arquivo anteriormente aberto, s sendo permitido o fechamento de um arquivo por vez. Sua sintaxe: CLOSE (VAR <arq>); Exemplo :
PROGRAM teste_close; VAR arquivo : FILE OF BYTE; nomearq: STRING[67]; BEGIN WRITE('Entre com o nome do arquivo que quer abrir'); READLN(nomearq); ASSIGN(arquivo,nomearq); REWRITE(arquivo); CLOSE(arquivo); END.
Em ambos os exemplos anteriores, vemos uma deficincia. Enquanto um comando apenas nos permite a abertura de arquivos j existentes, o outro apenas abre arquivos novos ou destri um possvel contedo anterior. Para resolver esse problema podemos usar as diretivas de compilao para checagem de erros de entrada/sada {$I }. Esta diretiva retorna um cdigo de erro em uma funo do Turbo
89
90
ou ainda, fazer manuteno em informaes j existentes. Vejamos ento, como so os comandos que nos permitem tais tarefas:
PROGRAM teste_read_arq; Uses Crt; CONST nomearq = TESTE.DAT; max = 10; TYPE registro = RECORD nome : STRING[30]; ender : STRING[25]; END; VAR arquivo: FILE OF registro; reg: registro; ind: BYTE; BEGIN ASSIGN(arquivo,nomearq); RESET(arquivo); FOR ind := 1 TO MAX DO BEGIN READ(arquivo,reg); WRITELN ( 'Este o ', ind, '. Nome ', reg.nome) ; WRITELN('Este ' o ',ind,'. Endereco ',reg.ender); END; CLOSE(arquivo); END.
9.1.3.1 WRITE Este procedimento alm de ser usado para exibir mensagens e variveis no dispositivo padro de sada (video), pode ser usado para gravar informaes em outros dispositivos, como um arquivo. Sua sintaxe: WRITE(<arq>, <reg1>[,<reg2>,..., <regn>] ;
Exemplo: PROGRAM teste_write_arq; CONST nomearq = 'TESTE.DAT'; max = 10; TYPE registro = RECORD nome : STRING[30]; ender: STRING[25]; END; VAR arquivo : FILE OF registro; reg : registro; ind : BYTE; BEGIN ASSIGN(arquivo,nomearq); REWRITE(arquivo); FOR ind := 1 TO MAX DO BEGIN WRITE('Digite o ',ind,'o Nome '); READLN(reg.nome); WRITE('Digite o ',ind,'o Endereco '); READLN(reg.ender); WRITE(arquivo,reg); END; CLOSE(arquivo); END.
No exemplo anterior, no temos problema algum ao executar a leitura no arquivo, pois este havia sido gravado anteriormente por ns mesmos e com uma quantidade de registros predefinidos. Porm, na maioria das vezes, no temos idia da quantidade de registros contidos em um arquivo e para esta situao,devemos saber quando chegamos ao final de um arquivo. O Turbo nos fornece tal funo : 9.1.3.3 EOF Esta funo nos retorna o valor TRUE quando for encontrada a marca de fim de arquivo. Sua sintaxe : EOF(VAR <arq>) : BOOLEAN; Utilizando o exemplo anterior, com uma pequena variao :
9.1.3.2 READ Como j vimos anteriormente, este procedimento permite que atribuamos a uma varivel, um valor obtido por um dispositivo associado. Este dispositivo pode ser tambm um arquivo, e se no caso da leitura em arquivo, for detectado o fim do mesmo, ser gerado um erro. Sua sintaxe: READ(<arq>, <reg>); Vejamos um exemplo simples de uma leitura em arquivos:
Linguagem de Programao II - URI Campus de Frederico Westphalen
PROGRAM teste_eof; Uses crt; CONST nomearq = 'TESTE.DAT'; TYPE registro = RECORD nome : STRING[30]; ender: STRING[25]; END; VAR
91
92
arquivo: FILE OF registro; reg: registro; ind: BYTE; BEGIN ASSIGN(arquivo,nomearq); RESET(arquivo); ind := 1; WHILE NOT EOF(arquivo) DO BEGIN READ(arquivo,reg); WRITELN ( 'Este o ,ind,'. Nome ',reg.nome) ; WRITELN('Este o ',ind,'. Endereco ', reg.ender); ind := ind + 1; END; CLOSE(arquivo); END.
FOR ind := 1 TO MAX DO BEGIN WRITE('Digite o ',ind,'o Nome '); READLN(reg.nome); WRITE('Digite o ',ind,'o Endereco '); READLN(reg.ender); WRITE(arquivo,reg); END; SEEK(arquivo,4); READ(arquivo,reg); WRITELN ('Este o 5 Nome ',reg.nome) ; WRITELN ('Este o 5 Endereco ', reg.ender); CLOSE(arquivo); END.
9.1.3.5 FILEPOS Esta funo nos retoma a posio atual do ponteiro do arquivo. Assim que abrimos um arquivo, com RESET ou REWRITE, a posio do ponteiro zero, ou seja, o primeiro registro, no pode ser usado em arquivos do tipo TEXTO. Sua sintaxe : FILEPOS(VAR <arq>) : LONGINT;
O lao repetido at que seja encontrada a marca de fim de arquivo. Porm, para a manuteno de alguns registros de um determinado arquivo, temos que saber qual a posio deste registro no arquivo e tambm qual a posio do ltimo registro. Quando estamos manipulando um arquivo, existe a todo momento um ponteiro que fica deslocando-se de acordo com as leituras e gravaes, ou seja, quando abrimos um arquivo,este ponteiro indica a posio zero, ou que o primeiro registro fisico do arquivo. A cada leitura ou gravao este ponteiro avana uma posio, mas existem algumas funes e procedimentos que permitem a manipulao deste ponteiro. 9.1.3.4 SEEK Este procedimento permite que movamos o ponteiro do arquivo para uma posio preestabelecida, podendo ser usado em arquivos de qualquer tipo exceto os de tipo TEXTO. S pode ser usado em arquivos previamente abertos. Sua sintaxe : SEEK(VAR <arq>; <posicao> : LONGINT);
Exemplo: PROGRAM teste_seek; CONST max = 10; TYPE registro = RECORD nome : STRING[30]; ender: STRING[25]; END; VAR arquivo : FILE OF registro; reg : registro; ind : BYTE; BEGIN ASSIGN(arquivo,TESTE.DAT); REWRITE(arquivo); Linguagem de Programao II - URI Campus de Frederico Westphalen
9.1.3.6 FILESIZE Esta funo retorna o tamanho de um arquivo em nmero de registros. Caso o arquivo esteja vazio, a funo retornar 0. No pode ser usada, em arquivos do tipo TEXTO. Sua sintaxe: FILESIZE(VAR <arq>) : LONGINT;
93
94
identificado pela sequncia CR LF, Carriage Retum, e Line Feed, correspondentes aos caracteres ASCII $0D e $0A. O identificador TEXT define uma varivel como sendo arquivo do tipo texto. 9.1.3.7 WITH Este comando permite que a referncia a uma varivel do tipo registro seja simplificada. Podemos encadear at sete registros em um comando WITH. A referncia aos campos dos registros pode ser efetuada com o uso deste comando sem a utilizao do ponto, ligando o nome do registro ao nome do campo. Sua sintaxe: WITH <registro1>, [<registron>...] DO BLOCO;
Exemplo PROGRAM teste_with; CONST max = 10; TYPE registro = RECORD nome : STRING[30]; ender: STRING[25]; END; VAR arquivo : FILE OF registro; reg : registro; ind : BYTE; BEGIN ASSIGN(arquivo,'TESTE.DAT'); REWRITE(arquivo); WITH reg DO BEGIN FOR ind := 1 TO MAX DO BEGIN WRITE('Digite o ',ind,' Nome '); READLN(nome); WRITE('Digite o ',ind,' Endereco '); READLN(ender); WRITE(arquivo,reg); END; SEEK(arquivo,0); WHILE NOT EOF(arquivo) DO BEGIN READ(arquivo,reg); WRITELN ('Este o ',filepos(arquivo),' Nome ',nome) ; WRITELN ('Este o ',filepos(arquivo),' Endereco ', ender); END; END; CLOSE(arquivo); END.
Exemplo:
PROGRAM teste_text; USES CRT; VAR arq : TEXT; ch : CHAR; BEGIN WRITELN('Escolha onde deseja que seja impressa a frase WRITELN(' Impressora, Disco, ou Video, (I, D,V) ' ) ; REPEAT ch := UPCASE(READKEY); UNTIL ch IN ['I','D','V']; IF ch = 'I' THEN ASSIGN(arq,'PRN') ELSE IF ch = 'D' THEN ASSIGN(arq,'TESTE.DAT') ELSE ASSIGN(arq,'CON'); {$I-} REWRITE(ARQ); {$I+} IF IORESULT <> O THEN WRITELN('Arquivo nao aberto ') ELSE BEGIN WRITELN(arq,'Teste de TEXT '); CLOSE(arq); END; WRITE('Tecle algo para continuar '); READKEY; END.
Este outro exemplo copia o arquivo autoexec.bat para um novo arquivo removendo todas as linhas marcadas com comentrio (rem).
Program ExemploArquivoTexto; Uses CRT, Strings; var arq1, arq2: text; buffer: string; aux: string[3]; i: integer; begin assign(arq1,'c:\autoexec.bat'); assign(arq2,'c:\autoexec.new'); {$I-} reset(arq1); {$I+} if IORESULT <> 0 then begin writeln('Nao foi possivel abrir o arquivo C:\AUTOEXEC,BAT'); Linguagem de Programao II - URI Campus de Frederico Westphalen
95
96
end; rewrite(arq2); while not eof(arq1) do begin readln(arq1,buffer); aux:=copy(buffer,1,3); for i:= 1 to 3 do begin aux[i]:=upcase(aux[i]); end; if aux<>'REM' then begin writeln(arq2,buffer); end; end; writeln(arq2,'rem - Alterado pela exemplo de Arquivos Texto usando Pascal!'); flush(arq2); end.
9.2.1.3 SEEKEOF Esta funo retorna verdadeiro se encontrado status de final de arquivo. bastante parecida com a funo EOF, exceto que esta salta todos os brancos e tabs quando da leitura. Somente para arquivos do tipo texto. Sua sintaxe: SEEKEOF[(VAR <arq>:TEXT)] : BOOLEAN;
9.2.1.4 SEEKEOLN
Esta funo retorna verdadeira se encontrada marca de fim de linha, salta todos os caracteres em branco e tabulaes encontradas durante a leitura. Sua sintaxe: SEEKEOLN[(VAR <arq> : TEXT)] : BOOLEAN; 9.2.1.5 FLUSH Este procedimento permite que seja descarregada a rea de Buffer de um arquivo do tipo Texto. Em sua utilizao, pode ser usada a funo IORESULT, que retornar zero caso a operao for bem sucedida. Sua sintaxe : FLUSH(VAR <arq> : TEXT);
Exemplo: PROGRAM teste_flush; var arq : TEXT; BEGIN ASSIGN(arq,'\autoexec.bat'); APPEND(arq); WRITELN(arq,'ECHO INCLUIDO PELO TURBO'); FLUSH(arq); END.
PROGRAM teste_append; VAR arq : TEXT; {define arq do tipo arquivo texto} BEGIN ASSIGN(arq,'\autoexec.bat'); {associa o nome externo a APPEND(arq); WRITELN(arq,'ECHO INCLUIDO PELO TURBO'); CLOSE(arq); END.
arq}
No exemplo anterior, caso no tivssemos nos utilizando da rotina FLUSH, a gravao no teria sido efetivada, pois a informao estaria apenas bufferizada. 9.2.1.6 SETTEXTBUF Este procedimento permite-nos associar um arquivo com tipo TEXTO a uma rea de buffer na rea de dados do programa. Utilize sempre que possivel mltiplos de 128 para o tamanho do Buffer. Normalmente, esta rea j est disposta pelo sistema operacional e corresponde a 128 Bytes. Este comando deve ser usado antes que o arquivo seja aberto, podendo ser usado tanto para
Linguagem de Programao II - URI Campus de Frederico Westphalen
9.2.1.2 EOF(TEXT) Esta funo retorna verdadeiro se for encontrado o fim de um arquivo do tipo texto. A diferena entre EOF para Texto e EOF para arquivos tipados que na primeira, a referncia ao arquivo opcional. Sua sintaxe:
Linguagem de Programao II - URI Campus de Frederico Westphalen
97
98
leitura como para gravao. Este procedimento acelera os procedimentos de leitura e de gravao. Sua sintaxe : SETTEXTBUF(VAR <arq>:TEXT; VAR <buffer> [;<tamanho> : WORD]);
ASSIGN(arqent,nomeent); RESET(arqent,l); WRITE ('Entre com o nome do arquivo de Destino ') ; READLN(nomesai); ASSIGN(arqsai,nomesai); REWRITE(arqsai,l); WRITELN('Copiando ', FileSize(arqent),' bytes...'); REPEAT BLOCKREAD(arqent,buf,sizeof(buf),lidos); BLOCKWRITE(arqsai,buf,lidos,gravados); UNTIL (lidos = 0) OR (gravados <> lidos); Close(arqent); Close(arqsai); END.
de fundamental importncia, que ao abrir o arquivo coloque-se alm da varivel tipo File, tambm o tamanho 1.
9.3.1.3 TRUNCATE Este procedimento faz com que o arquivo seja truncado em seu tamanho, na posio corrente do ponteiro do arquivo. Sua sintaxe ; TRUNCATE(VAR <arq>);
PROGRAM teste_block; VAR arqent,arqsai nomeent,nomesai lidos, gravados buf : : : : FILE; STRING[79]; WORD; ARRAY[1..4096] OF CHAR;
99
100
nome: array[1..11] of char; tipo: char; reservado1: array[1..4] of char; tamanho: byte; num_dec: byte; reservado2: array[1..14] of char; end;
Os dados so gravados a partir do 1 byte posterior ao tamano do cabealho (cab.tam_cab). No incio de cada registro (conjunto de atributos) gravado um byte para marcar se o registro est deletado (se o caracter for igual a 42 (*)) ou no (se o caracter for igual a 32 (espao em branco)), e so todos gravados em modo texto, sendo que cada registro referente a cada atributo possui o tamanho definido na descrio do atributo (tamanho + num_dec).
Program LeDBF; Uses CRT; TYPE str_dbf = record versao: byte; ano: byte; mes: byte; dia: byte; n_regs: longint; tam_cab: integer; tam_reg: integer; reservado: Array[1..20] of char; end; descr_atr = record nome: array[1..11] of char; tipo: char; reservado1: array[1..4] of char; tamanho: byte; num_dec: byte; reservado2: array[1..14] of char; end; VAR desc: descr_atr; dbf: str_dbf; arq:FILE; quant, i: integer; aux: char; nomeaux: Array[1..256] of string[12]; tipo: Array[1..256] of char; tam, dec: Array[1..256] of byte; buffer: char; nome_arquivo: string; tm, cont, k, qtd, l, tm1, tm2, op, tamanho, zz, byteslidos: integer; BEGIN clrscr; write('Nome do Arquivo: '); Linguagem de Programao II - URI Campus de Frederico Westphalen
readln(nome_arquivo); assign(arq,nome_arquivo); {$I-} reset(arq,1); {$I+} if IORESULT <> 0 then begin writeln('Nome de Arquivo Invalido!'); readkey; exit; end; BLOCKREAD(arq,dbf,32,byteslidos); writeln('versao: ',dbf.versao); writeln('ano: ',dbf.ano); writeln('mes: ',dbf.mes); writeln('dia: ',dbf.dia); writeln('n reg: ',dbf.n_regs); writeln('t_cab: ',dbf.tam_cab); writeln('t_reg: ',dbf.tam_reg); writeln('reserv: ',dbf.reservado); writeln('-------------------------------'); readkey; quant := trunc((dbf.tam_cab-sizeof(str_dbf))/sizeof(descr_atr)); writeln('Blidos: ',byteslidos); writeln('Quant: ',quant); writeln('Tam cab: ',sizeof(str_dbf)); writeln('Tam campos: ',sizeof(descr_atr)); for i:=1 to quant do begin BLOCKREAD(arq,desc,sizeof(descr_atr),byteslidos); tipo[i]:=desc.tipo; tam[i]:=desc.tamanho; nomeaux[i]:=desc.nome; dec[i]:=desc.num_dec; writeln(desc.nome, ' - ',desc.tipo, ' - ',desc.tamanho, ' ',desc.num_dec); end; write('Ler quantos registros - (999 - todos)? '); readln(qtd); seek(arq,dbf.tam_cab); if (qtd=999) then qtd:=dbf.n_regs; cont:=1; while ((cont<=qtd) and (not eof(arq))) do begin writeln(' Registro: ',cont,' -------------------------'); BLOCKREAD(arq,aux,1,byteslidos); if (aux<>' ') then writeln('-> ',aux,' (deletado) '); for k:=1 to quant do begin write(nomeaux[k],': '); for l:= 1 to tam[k] do begin BLOCKREAD(arq,buffer,1,byteslidos); write(buffer); end; writeln; end; readkey; cont:=cont+1; end; writeln(' ************* FIM '); readkey; clrscr; end.
101
102
9.4 Arquivos em C
Um arquivo em C no possui a idia de registro. Podemos gravar dados no formato de caracter (ASCII) ou em binrio (binary file). A seqncia e interpretao dos dados de inteira responsabilidade do programador do sistema. Um arquivo em C uma seqncia contnua de butes gravados em memria secundria. Cada byte do arquivo possui um endereo nico que o deslocamento relativo ao incio do arquivo. Toda a manipulao de arquivos realizada atravs de funes de biblioteca. Existem dois nveis de funes: as rotinas de baixo nvel - mais eficientes, que utilizam diretamente os recursos do sitema operacional - e as de alto nvel - mais fceis de serem utilizadas - construdas sobre as funes de baixo nvel. Para as rotinas de alto-nvel, os arquivos so acessados atravs de ponteiros para estruturas do tipo FILE, definidas em stdio.h. Para as rotinas de baixo nvel os arquivos so identificados por um nmero inteiro que o cdigo identificador do arquivo retornado pelo sistema operacional (file handle). Na estrutura FILE, o nmero identificador do arquivo o campo fd. As rotinas de alto-nvel possuem por sua vez dois conjuntos de rotinas: rotinas para manipulao de arquivos texto e rotinas para manipulao de arquivos binrios. A diferena bsica entre os dois conjuntos que as rotinas de manipulao de arquivos binrios armazenam uma cpia dos bytes da memria principal para a secundria enquanto que as de manipulao de arquivos texto armazenam a representao ASCII dos valores. Principais rotinas de baixo nvel (prototipadas em io.h) access chmod close creat eof getftime lock lseek open read tell unlock write - Verifica se um arquivo existe e se pode ser lido/gravado. - Modifica os atributos de um arquivo. - Fecha um arquivo. - Cria um arquivo. Est em desuso - Verifica se a leitura chegou ao final de um arquivo. - Informa a data de criao/acesso de um arquivo. - Coloca um arquivo em uso exclusivo. utilizada para fazer controle de acesso concorrente em ambiente multi-usurio ou de rede. - Descola o ponteiro de leitura para um byte especfico no arquivo. - Abre/cria um arquivo. - L dados de um arquivo. - Informa em qual byte est o ponteiro do arquivo. - Libera o arquivo do uso exclusivo. - Escreve dados em um arquivo.
fclose feof fflush fgetc fgets fputc fputs fread fscanf fseek ftell fwrite remove rename setvbuf fflushall fprintf
- Fecha um arquivo. - Informa se a leitura chegou ao fim de arquivo. - Esvazia o buffer do arquivo. - L um caracter de um arquivo. - L uma string de um arquivo. - Escreve um caracter em um arquivo. - Escreve uma string em um arquivo. - L dados de um arquivo. - L dados de um arquivo, como scanf - Desloca o ponteiro do arquivo para um determinado byte. - Indica em qual byte se localiza o ponteiro do arquivo. - Escreve em um arquivo. - Remove um arquivo. - Muda o nome de um arquivo. - Modifica o tamanho interno do buffer do arquivo. - Descarrega o buffer de todos os arquivos. - Escreve em um arquivo, no mesmo formato que printf.
Obs: Existem cinco arquivos tipo stream pr-definidos automaticamente abertos quando um programa entra em execuo: stdin stdout stderr stdaux stdprn - Dispositivo padro de entrada (geralmente teclado). - Dispositivo padro de sada (geralmente vdeo). - Dispositivo padro para sada de erros. - Dispositivo auxiliar (porta serial, por exemplo). - Impressora padro do sistema.
que
so
Exemplo:
printf(%d,x);
o mesmo que
fprintf(stdout, %d, x);
103
104
No MS-DOS ainda h como segundo caracter de modo as opes: b t especifica que o arquivo binrio especifica que o arquivo texto
Funo fclose A funo fclose deve ser usada toda a vez que no for mais necessrio trabalhar com um arquivo. Libera os buffers alocados pelo sistema operacional para o gerenciamento do arquivo garantindo que todos os dados so efetivamente descarregados no dispositivo de memria secundria. Libera tambm a estrutura do tipo FILE. Sintaxe: fclose <fstream> onde: * fstream = ponteiro para o arquivo
* modo = string constante composta por dois caracteres que indica o modo de abertura do arquivo: modos: w r a abre/cria para escrita. Se j existe, destrudo. abre somente para leitura. abre o arquivo para escrita a partir do fim do mesmo ou cria se o arquivo no existir.
Exemplo:
fclose(arq1); fclose(arq2);
r+ abre um arquivo j existente tanto para leitura como para gravao. Se este arquivo j existir ele no ser destrudo. w+ abre um arquivo tanto para leitura como para gravao. Se este arquivo j existir ele ser destrudo. a+ abre um arquivo para leitura/gravao ao final do arquivo. Se o arquivo no existe ele criado.
105
106
fwrite(<ptr>, <tamanho>, <nro>, <fstream>); onde: * * * * ptr = ponteiro para o incio dos dados a serem gravados tamanho = tamanho do registro lgico; nro = quantidade de registros lgicos (registro fsico = nro x tamanho); fstream = ponteiro para o arquivo;
fread(&buf,sizeof(int),10,arq1);
Exemplo de um programa que grava e escreve na tela uma estrutura de nome e idade:
#include #include #include #include <conio.h> <stdio.h> <stdlib.h> <io.h>
fwrite retorna o nmero de itens que conseguiu gravar no arquivo. 9.4.3.2 Funo fread A funo fread tem a funo inversa da funo fwrite carregando um conjunto de bytes do dispositivo de memria secundria para a memria principal. Possui os mesmos parmetros que fwrite porm com o sentido inverso. Sintaxe fread(<ptr>, <tamanho>, <nro>, <fstream>); onde: * ptr = ponteiro para o incio da rea onde devem ser armazenados os dados lidos; * * * tamanho = tamanho do registro lgico; nro = quantidade de registros lgicos a serem lidos; fstream = ponteiro para o arquivo;
typedef struct { char nome[30]; int idade; }pessoa; pessoa cliente; FILE *arq1; int i, tamanho; void main() { clrscr(); arq1 = fopen("clientes.dat","ab+"); if (arq1==NULL) exit(1); for(i=0;i<4;i++); { printf("nome: "); fflush(stdin); gets(cliente.nome); fflush(stdin); printf("idade: "); scanf("%d",&cliente.idade); fwrite(&cliente,sizeof(cliente),1,arq1); } clrscr(); rewind(arq1); while(!feof(arq1)) { fread(&cliente,sizeof(pessoa),1,arq1); if(!feof(arq1)) { printf("nome: %s - %d anos\n",cliente.nome, \ cliente.idade); } } getch(); }
fread retorna o nmero de itens que conseguiu ler do arquivo. 9.4.3.3 Funo feof - Teste de Fim de Arquivo: A funo de teste de fim de arquivo feof retorna o valor lgico verdadeiro quando o programa tenta ler o arquivo aps o ltimo byte gravado. Sintaxe: <x> = feof (<fstream>); onde: fstream = ponteiro para o arquivo; x = um inteiro que recebe o valor 1 se foi encontrado o fim de arquivo, seno recebe 0. Ex.: while(!feof(arq1))
Linguagem de Programao II - URI Campus de Frederico Westphalen
107
108
Sintaxe: fputc(<char>,<fstream>); onde: * char = caracter a ser gravado; * fstream = ponteiro para o arquivo; 9.4.4.2 Funo fgetc A funao fgetc permite que se leia um caracter (um byte) de um arquivo texto. Sintaxe: <c> = fgetc(<fstream>); onde: * c = varivel que recebe o caracter lido; * fstream = ponteiro para o arquivo; 9.4.4.3 Funo fputs A funao fputs permite que se grave um string em um arquivo texto. Sintaxe: fputs(<str>,<fstream>); onde: * str = ponteiro para o string a ser gravado (substitui o \0 por um \n no momento da gravao); * fstream = ponteiro para o arquivo; 9.4.4.4 Funo fgets A funao fgets permite que se leia um string inteiro de uma s vez de um arquivo texto. L todos os caracteres at encontrar um \n ou estourar o limite estabelecido nos parmetros. Sintaxe: fgets(<str>,<tammax>,<fstream>); onde:
* str = ponteiro para o string a ser lido (carrega todos os caracteres at encontrar um \n e acrescenta um \0 no fim do string). * tammax = nmero mximo de caracteres que podemser lidos. * fstream = ponteiro para o arquivo; 9.4.4.5 Funo fprintf A funao fprintf permite a gravao formatada de dados em um arquivo texto. Os dados so armazendados no arquivo da mesma maneira que seriam jogados no dispositivo de sada padro. A sintaxe igual a da funo printf diferenciando-se apenas pela indicao do arquivo destino. Sintaxe: fprintf (<fstream>, <string de controle>, <lista de argumentos>); * funciona como o comando printf com a diferena que os caracteres so enviados para o arquivo especificado por fstream. 9.4.4.6 Funo fscanf Possui a mesma filosofia de fprintf s que para a leitura de dados. Possui sintaxe idntica a da funo scanf diferenciando-se apenas pela indicao do arquivo fonte. Sintaxe: fscanf (<fstream>, <string de controle>, <lista de argumentos>); Funciona como o comando scanf com a diferena que os caracteres so lidos do arquivos especficado por fstream O programa abaixo um exemplo de programa que utiliza as funes fgets, fputs, fgetc, fputc, fscanf, fprintf, para manipular um arquivo texto.
#include #include #include #include <stdio.h> <conio.h> <stdlib.h> <string.h>
FILE *arq1; char i, caracter, meu_complemento[20], frase_do_arq[80]; void main() { arq1 = fopen("teste.txt","w+t"); if(arq1==NULL) { printf("Nao foi possivel abrir o arquivo!"); exit(1); } strcpy(meu_complemento,"Maravilhoso!"); fprintf(arq1,"Ola Mundo %s\n",meu_complemento); Linguagem de Programao II - URI Campus de Frederico Westphalen
109
110
fputs("Este e' o alfabeto: ",arq1); for(i=65;i<=90;i++) { fputc(i,arq1); } clrscr(); rewind(arq1); fscanf(arq1,"%s",frase_do_arq); printf("%s",frase_do_arq); fgets(frase_do_arq,80,arq1); printf("%s",frase_do_arq); while(!feof(arq1)) { caracter=fgetc(arq1); putchar(caracter); } getch(); }
varivel_long = ftell (ponteiro_arquivo); A funo rewind simplesmente reinicializa para o incio do arquivo o marcador de posio no arquivo apontado por ponteiro_arquivo. A sintaxe : rewind(ponteiro_arquivo);
A funo ftell retorna a posio atual do marcador de posio no arquivo apontado por ponteiro_arquivo. Esta posio indicada por um deslocamento medido em bytes, a partir do incio do arquivo. A sintaxe :
Os dados so gravados a partir do 1 byte posterior ao tamano do cabealho (cab.tam_cab). No incio de cada registro (conjunto de atributos) gravado um byte para marcar se o registro est deletado (se o caracter for igual a 42 (*)) ou no (se o caracter for igual a 32 (espao em branco)), e so todos gravados em modo texto, sendo que cada registro referente a cada atributo possui o tamanho definido na descrio do atributo (tamanho + num_dec).
Linguagem de Programao II - URI Campus de Frederico Westphalen
111
112
typedef struct { char versao; char ano; char mes; char dia; long int n_regs; int tam_cab; int tam_reg; char reservado[20]; } str_dbf; typedef struct { char nome[11]; char tipo; char reservado1[4]; char tamanho; char num_dec; char reservado2[14]; } descr_atr; descr_atr desc; str_dbf dbf; FILE *arq; int quant, i; char aux; char nomeaux[256][12]; char tipo[256]; char tam[256]; char dec[256]; int tm, j, k, qtd, l, tm1, tm2, op, tamanho, zz; void main(int argc, char *argv[]) { if (argc!=2) { printf("\nA sintaxe e' ledbf arquivo.dbf\n"); exit(1); } clrscr(); arq=fopen(argv[1],"rb"); if (arq==NULL) { printf("Arquivo Inexistente!"); exit(1); } fread(&dbf,sizeof(str_dbf),1,arq); printf("versao: %d\n",dbf.versao); printf("ano: %d\n",dbf.ano); printf("mes: %d\n",dbf.mes); printf("dia: %d\n",dbf.dia); printf("n reg: %ld\n",dbf.n_regs); printf("t_cab: %i\n",dbf.tam_cab); printf("t_reg: %i\n",dbf.tam_reg); printf("reserv: %s\n",dbf.reservado); printf("-------------------------------\n\n"); Linguagem de Programao II - URI Campus de Frederico Westphalen
tamanho=sizeof(str_dbf); getch(); quant=(int)((dbf.tam_cab-sizeof(str_dbf))/sizeof(descr_atr)); for (i=0;i<quant;i++) { fread(&desc,sizeof(descr_atr),1,arq); tipo[i]=desc.tipo; tam[i]=desc.tamanho; strcpy(nomeaux[i],desc.nome); dec[i]=desc.num_dec; printf("\n%11s - %c - %2d - %2d",desc.nome, desc.tipo, desc.tamanho, desc.num_dec); tamanho += sizeof(descr_atr); } printf("\n\nLer quantos registros - (999 - todos)? "); scanf("%d",&qtd); fseek(arq,dbf.tam_cab,0); if (qtd==999) qtd=dbf.n_regs; j=1; while ((j<=qtd) &&(!(feof(arq)))) { printf("\n\n Registro: %d -------------------------",j); fread(&aux,1,1,arq); if (aux!=' ') printf("\n-> %c (deletado) ",aux); for (k=0;k<quant;k++) { printf("\n %12s: ",nomeaux[k]); for (l=1;l<=tam[k];l++) { fread(&aux,1,1,arq); printf("%c",aux); } } getch(); j++; } printf("\n ************* FIM "); getch(); clrscr(); }
113
114
Clientes o conjunto de informaes que contm o cdigo, o nome e a cidade de cada cliente. Depois necessrio definir uma varivel para o tipo criado, pois somente a criao de tipos no define nada, pois eles no tem ligao direta com o programa. Na seo VAR do programa vamos definir as variveis para o tipo criado. Normalmente se usa uma abreviao do tipo para denominar a varivel, mas pode-se utilizar qualquer nome.
VAR cli:clientes; arq: file of clientes;
Se o programa utilizar a gerao automtica de cdigo, no procedimento incluso devemos: 1. Posicionar o ponteiro no incio do registro: SEEK(ARQ,0). 2. Fazer um loop com o comando WHILE para que enquanto no chegue no final do arquivo, leia todos os registros para armazenar o ltimo cdigo. 3. Criar um codigo auxiliar que armazene o ltimo cdigo vlido ( > 0 ). 4. Testar se o ltimo cdigo maior ou menor que 0 e calcular o novo cdigo para o cliente. 5. Estabelecer uma condio de sada do lao da incluso (Nome vazio, no nosso caso ).
Toda a vez que no programa quisermos fazer referncia aos registros de CLIENTES, vamos utilizar a varivel CLI e toda a vez que quisermos fazer referncia ao arquivo vamos utilizar a varivel ARQ. Antes de se utilizar os comandos para criar, abrir ou fechar o arquivo necessrio associlo com um arquivo que vai ser gerado no Winchester ou no disquete com o comando ASSIGN, como por exemplo:
ASSIGN(ARQ,CLIENTES.DAT);
Observe que se no especificarmos a unidade de disco na qual ser gerado o arquivo CLIENTES.DAT ele ser gerado na unidade que est o programa principal, mas pode-se tambm especificar uma unidade especfica, como por exemplo:
ASSIGN(ARQ,B:CLIENTES.DAT);
Para criar arquivos usado o comando REWRITE(variavel do arquivo). No nosso programa seria utilizado REWRITE(ARQ). Para abrir os arquivos utilizado o comando RESET(ARQ) e para fechar o arquivo o comando CLOSE(ARQ). Em aplicativos torna-se interessante abrir o arquivo uma nica vez no incio do programa principal e caso no exista ento cria-se automaticamente e fech-lo no final do programa principal antes do END. evitando o constante abre-e-fecha arquivo. Para isso usa-se uma diretiva de compilao {$I-} que impede que o programa trave em caso de erro ao tentar abrir um arquivo que no existe e devolve o cdigo do erro na varivel IORESULT para ser analisada. Se o arquivo j existe, o cdigo de erro 0 (zero = sem erro) caso contrrio deve-se criar o arquivo. Em seguida voltamos a fazer com que o programa trave em caso de erro com a diretiva de compilao {$I+}.
procedure incluso var cod:integer; begin cod:=0; cli.codigo:=0; seek(arq,0); { posiciona o ponteiro no 1.0 registro } while(not eof(arq)) do { enquanto nao encontra o fim de arquivo } begin read(arq,cli); { le os registros } if cli.codigo>0 then cod:=cli.codigo; end; repeat { Repete o procedimento ... } if cli.codigo < 0 then begin cli.codigo:=cod+1; { incrementa o codigo para os novos registros } end else begin cli.codigo:=cli.codigo+1; end; write('Nome: '); readln(cli.nome); { le o nome do cliente que esta sendo cadastrado } if (cli.nome <> '') and (cli.nome <> ' ') then begin write('Cidade: '); readln(cli.cidade); write(arq,cli); {grava os registros} end; until (cli.nome='') or (cli.nome=' '); {...ate' que o nome esteja vazio} end;
procedure abre_arquivo; begin assign(arq,'clientes.dat'); {$I-} reset(arq); {$I+} if IORESULT <> 0 then rewrite(arq); end; Linguagem de Programao II - URI Campus de Frederico Westphalen
Se o programa no utilizar a gerao automtica de cdigo, no procedimento incluso devemos: 1. Posicionar o ponteiro no final do arquivo: SEEK(ARQ, FILESIZE(ARQ)). 2. Estabelecer uma condio de sada do lao da incluso (Nome vazio, no nosso caso ).
115
116
var cod:integer; begin cod:=0; cli.codigo:=0; seek(arq,FILESIZE(arq)); { posiciona o ponteiro no final do arquivo } repeat { Repete o procedimento ... } write(Cdigo: ); readln(cli.codigo) write('Nome: '); readln(cli.nome); if (cli.nome <> '') and (cli.nome <> ' ') then begin write('Cidade: '); readln(cli.cidade); write(arq,cli); {grava os registros} end; until (cli.nome='') or (cli.nome=' '); end;
posicionar o ponteiro no 1 registro do intervalo (varivel contadora). atravs de um loop com o comando WHILE ler todos os registros enquanto o cdigo for menor que o segundo valor lido. mostrar na tela os registros cujo cdigo no esteja marcado para excluso (cdigo negativo).
Para Listar todos os registro, devemos posicionar o ponteiro no incio do arquivo, fazer um loop com o comando WHILE, para que enquanto no chegue no final do arquivo, leia os registros e mostre na tela os que no forem cdigo -1 (cdigos marcados para excluso).
procedure lista_tudo; begin seek(arq,0); { posiciona no 1.o registro do arquivo } while (not eof(arq)) do { enquanto nao chega no final do arquivo } begin read(arq,cli); if cli.codigo > 0 then {se codigo for maior que 0 escreve os campos} begin writeln('Codigo: ',cli.codigo); writeln('Nome: ',cli.nome); writeln('Cidade: ',cli.cidade); writeln(' pressione qualquer tecla p/continuar . . .'); readkey; end; end; end;
procedure lista_intervalo; var p:char; pos, x, cod1, cod2:integer; begin write('Listar desde o codigo: '); readln(cod1); write(' ate o codigo: '); readln(cod2); seek(arq,0); cli.codigo := 0; while (cli.codigo < cod2) and (not eof(arq)) do { le ate que encontra o (cod2) } begin read(arq,cli); if cli.codigo > cod1 then begin writeln('Codigo: ',cli.codigo); writeln('Nome: ',cli.nome); writeln('Cidade: ',cli.cidade); writeln(' pressione qualquer tecla p/continuar . . .'); readkey; {espera que seja press. uma tecla para listar outro } end; end; end;
Para listar um registro, alterar um registro ou excluir um registro, o mtodo para localiz-lo sempre o mesmo e pode ser definido por uma funo que recebe o cdigo como parmetro e retorna TRUE se encontrou o cdigo ou retorna FALSE se no o encontrou: posiciona-se o ponteiro no incio do arquivo. procurar atravs de um loop com o comando WHILE o registro desejado, armazenando a sua posio. posicionar no prprio registro para que, se for alterado, o ponteiro j esteja na posio correta.
function achoucliente(cod: integer): boolean; begin achoucliente:=FALSE; seek(arq,0); while not eof(arq) do begin read(arq,cli); if(cli.codigo=cod) then begin seek(arq, filepos(arq)-1); achoucliente:=TRUE; break; end; Linguagem de Programao II - URI Campus de Frederico Westphalen
Para Listar um intervalo, no caso de estar utilizando um program com gerao automtica de cdigo, devemos: ler duas variveis que correspondem ao intervalo a ser listado, posicionar o ponteiro no incio do arquivo, zerar a varivel cli.cdigo para que ele entre sempre no lao da varivel contadora. procurar atravs de um loop com o comando WHILE o primeiro registro do intervalo, armazenar a posio do mesmo no arquivo atravs de uma varivel contadora,
Linguagem de Programao II - URI Campus de Frederico Westphalen
117
118
end;
end; else
writeln(' pressione qualquer tecla p/continuar . . .'); readkey; end begin writeln('Codigo nao encontrado'); writeln(' pressione qualquer tecla p/continuar . . .'); readkey; end;
Com essa funo fica simples fazer a alterao ou excluso: l-se o cdigo a alterar chama-se a funo encarregada de encontrar o cdigo l-se os novos dados e grava-se com a funo read. Observando que a funo de localizao se encarrega de deixar o ponteiro posicionado no registro que se quer alterar se for uma excluso, no precisa ler os novos valores e sim atribu-los como nulo e com cdigo negativo
end;
Para fazer a incluso de registros sem gerao automtica de cdigo devemos: l-se o cdigo a incluir chama-se a funo encarregada de localizar o cdigo somente continua a incluso aps certificar-se que a funo no localizou o cdigo no arquivo, garantindo que o cdigo no est includo no arquivo.
procedure alterar; var codaux, x: integer; begin write('Codigo a alterar: '); readln(codaux); if (achoucliente(codigoaux)) then begin write('Novo Nome: '); readln(cli.nome); write('Nova Cidade: '); readln(cli.cidade); write(arq,cli); {grava os registros na posio correta} end else begin writeln('Codigo nao encontrado'); writeln(' pressione qualquer tecla p/continuar . . .'); readkey; end; end;
procedure incluir var cod, codaux:integer; begin repeat write(Codigo a Incluir: ); readln(codaux); until (not achoucliente(codigoaux)); cli.codigo:=codaux; write('Nome: '); readln(cli.nome); write('Cidade: '); readln(cli.cidade); seek(arq,FILESIZE(arq)); { posiciona o ponteiro no final do arquivo } write(arq,cli); {grava o registro} end;
Para listar um nico registro: l-se o cdigo a listar chama-se a funo encarregada de encontrar o cdigo imprime-se os dados, j que a funo se encarregou de deixar na memria os dados do registro escolhido
A compactao do arquivo, que a eliminao fsica dos registros excludos que foram apenas marcados como nulos uma operao demorada e deve ser evitada. Para no continuar com os espaos desperdiados recomendvel sua reutilizao numa nova incluso, alterando o procedimento incluir para gravar no primeiro registro nulo, ao invs de incluir no final do arquivo. Isso obviamente deixa o arquivo desordenado e deve ser usado com cuidado nas rotinas que prevem um arquivo com numerao automtica e ordenado. A rotina de incluso ficaria assim:
procedure incluir var cod, codaux:integer; begin repeat write(Codigo a Incluir: ); readln(codaux); until (not achoucliente(codigoaux)); cli.codigo:=codaux; write('Nome: '); readln(cli.nome); write('Cidade: '); readln(cli.cidade); seek(arq,0); { posiciona no 1.o registro do arquivo } Linguagem de Programao II - URI Campus de Frederico Westphalen
procedure listar; var codaux, x: integer; begin write('Codigo a alterar: '); readln(codaux); if (achoucliente(codigoaux)) then begin writeln(Nome: ,cli.nome); writeln('Cidade: ',cli.cidade); Linguagem de Programao II - URI Campus de Frederico Westphalen
119
120
while (not eof(arq)) do { enquanto nao chega no final do arquivo } begin read(arq,cli); { l o registro } if cli.codigo < 0 then { se codigo for nulo} begin seek(arq, filepos(arq)-1); { volta um registro } break; { e interrompe a busca } end; end; {se no tiver nenhum nulo, vai at o final do arquivo } write(arq,cli); {grava o registro} end;
Clientes: ter o Form que far as operaes de incluso, consulta, alterao e excluso de Clientes num nico Form. 2. Crie uma nova Unit que conter o cdigo de manipulao de arquivos comum a todas operaes: V em File => New... => 3. Salve a Unit com um nome significativo, por exemplo: UnFuncoesArquivo
4. Na seo Interface, defina o tipo do registro do arquivo e crie as variveis cli (registro com os dados do cliente) e arqcli (arquivo onde sero gravados/lidos os registros):
TYPE clientes = record codigo:integer; nome:string[40]; cidade:string[30]; end; VAR cli:clientes; arq: file of clientes;
5. Na seo Implementation, crie as funes que sero usadas em todos as operaes: 6. Inclua o prottipo (primeira linha) das funes e procedimentos na seo Interface. 7. A Unit dever ficar assim:
unit UnFuncoesArquivo;
interface TYPE clientes = record codigo:integer; nome:string[40]; cidade:string[30]; end; VAR cli:clientes; arq: file of clientes; function achoucliente(cod: integer): boolean; procedure abre_arquivo; procedure fecha_arquivo; implementation procedure abre_arquivo; begin assign(arq,'clientes.dat'); {$I-} reset(arq); {$I+}
121
122
if IORESULT <> 0 then rewrite(arq); end; procedure fecha_arquivo; begin close(arq); end; function achoucliente(cod: integer): boolean; begin achoucliente:=FALSE; seek(arq,0); while not eof(arq) do begin read(arq,cli); if(cli.codigo=cod) then begin seek(arq,filepos(arq)-1); {volta um registro para ficar posicionado no prprio registro} achoucliente:=TRUE; break; end; end; end; end.
12. Inclua a unit de Funes de Arquivo neste form. Para isso V em File => Use Unit... e escolha a unit UnFuncoesArquivo. 13. Implemente o evento ao entrar (OnEnter) do Edit1 com o seguinte cdigo, para limpar todos os campos e desabilitar o boto OK, lembrando que s deve ser escrito o cdigo entre o begin e o end, j que a estrutura deve ser gerada pelo Delphi, atravs da caixa do ObjectInspector:
procedure TFrCadIncCliente.Edit1Enter(Sender: TObject); begin Edit1.Clear; Edit2.Clear; Edit3.Clear; button1.enabled:=false; end;
8. Na unit do menu, inclua essa unit criada. Para isso V em File => Use Unit... e escolha a unit UnFuncoesArquivo. 9. No Form do menu, implemente o evento OnCreate, colocando a chamada para o procedimento de abertura do arquivo, para abrir o arquivo ao iniciar o programa:
procedure TFrMenu.FormCreate(Sender: TObject); begin abre_arquivo; end;
10. No Form do menu, implemente o evento OnClose, colocando a chamada para o procedimento de fechamento do arquivo, para fechar o arquivo ao encerrar o programa:
procedure TFrMenu.FormClose(Sender: TObject; var Action: TCloseAction); begin fecha_arquivo; end;
123
124
end;
17. Crie um form semelhante ao anterior, sem o boto OK para a consulta de clientes e implemente os eventos OnEnter do Edit1 e OnClick do boto Cancelar com o mesmo cdigo do form de Incluso, exceto a linha que desabilita o button1 (button1.enabled := false). 18. Implemente o evento ao sair (OnExit) do Edit1 com o seguinte cdigo:
procedure TFrCadConsCliente.Edit1Exit(Sender: TObject); var cod: integer; begin cod:= strtointdef(Edit1.text,0); if cod > 0 then begin if achoucliente(cod) then { se achou o cliente } begin Edit2.text := cli.nome; { mostra no form os dados } Edit3.text := cli.cidade; end else begin showmessage('Cliente no cadastrado'); edit1.setfocus; end; end; end;
22. Crie um form semelhante ao primeiro, para a excluso de dados do clientes e implemente os eventos OnEnter do Edit1 e OnClick do boto Cancelar com o mesmo cdigo do form de Incluso. Ao invs do boto OK coloque o caption Excluir. 23. Implemente o evento ao sair (OnExit) do Edit1 com o seguinte cdigo:
procedure TFrCadExcCliente.Edit1Exit(Sender: TObject); var cod: integer; begin cod:= strtointdef(Edit1.text,0); if cod > 0 then begin if achoucliente(cod) then begin Edit2.text := cli.nome; Edit3.text := cli.cidade; button1.enabled:=true; end else begin showmessage('Cliente no cadastrado'); edit1.setfocus; end; end; end;
19. Crie um form semelhante ao primeiro, para a alterao de dados do clientes e implemente os eventos OnEnter do Edit1 e OnClick do boto Cancelar com o mesmo cdigo do form de Incluso. 20. Implemente o evento ao sair (OnExit) do Edit1 com o seguinte cdigo:
procedure TFrCadAltCliente.Edit1Exit(Sender: TObject); var cod: integer; begin cod:= strtointdef(Edit1.text,0); if cod > 0 then { se um cdigo vlido } begin if achoucliente(cod) then { se o cliente j est cadastrado } begin Edit2.text := cli.nome; { mostra os dados no Form } Edit3.text := cli.cidade; button1.enabled:=true; { habilita o boto OK } end else begin showmessage('Cliente no cadastrado'); edit1.setfocus; end; end; end;
125
126
Edit1.setfocus; end;
25. Crie um form semelhante ao primeiro com os seguintes botes: OK, Excluir, Cancelar. Este form far todas as operaes de dados do clientes. Implemente os eventos OnEnter do Edit1 e OnClick do boto Cancelar com o mesmo cdigo do form de Incluso. 26. Implemente o evento ao sair (OnExit) do Edit1 com o seguinte cdigo:
procedure TFrCadCliente.Edit1Exit(Sender: TObject); var cod: integer; begin cod:= strtointdef(Edit1.text,0); if cod > 0 then begin if achoucliente(cod) then { se o cdigo j est cadastrado } begin Edit2.text := cli.nome; { mostra os dados } Edit3.text := cli.cidade; button1.enabled:=true; { habilita o boto OK } button2.enabled:=true; { habilita o boto Excluir } end else begin button1.enabled:=true; { habilita somente o boto OK } end; end; end;
29. Altere a propriedade ScrollBars do Memo para ssVertical. 30. Implemente o evento OnClick do boto OK para fechar o Form:
procedure TFrListCliente.Button1Click(Sender: TObject); begin close; end;
Implemente os eventos OnClick de cada opo do menu para chamar os forms implementados.
28. Para fazer a listagem dos registros, crie um Form com um Memo e um boto, como o exemplo:
Linguagem de Programao II - URI Campus de Frederico Westphalen
127
128
*endereo_da_casa = 10;
10. PONTEIROS
10.1 Definio de ponteiros
Ponteiro uma varivel que pode manter um endereo de uma varivel. Um modo conveniente e muito eficiente de acessar uma varivel fazer referncia a ela atravs de uma segunda varivel que contm o endereo da varivel a ser acessada (ponteiro). Por exemplo, suponha que voc tenha uma varivel int chamada contedo_da_casa e outra chamada endereo_da_casa que pode conter o endereo de uma varivel do tipo int. Em C, preceder uma varivel com o operador de endereos & retorna o endereo da varivel em lugar do seu contedo. A sintaxe para atribuir o endereo da varivel em lugar do seu contedo. A sintaxe para atribuir o endereo de uma varivel a uma varivel que contm o endereo : endereo_da_casa = &contedo_da_casa Uma varivel que pode manter um endereo, como endereo_da_casa, chamada de varivel ponteiro ou simplesmente um ponteiro. contedo da casa [0318] Esta figura ilustra este relacionamento. A varivel contedo_da_casa foi colocada na memria no endereo 0318. Aps a execuo do comando anterior, o endereo de contedo_da_casa foi atribudo para a varivel ponteiro endereo_da_casa. Pode-se expressar este relacionamento dizendo que endereo_da_casa aponta para contedo_da_casa. Para acessar o contedo da clula cujo endereo est armazenado em endereo_da_casa, somente preceda a varivel ponteiro com um *, como em *endereo_da_casa. Por exemplo, se voc executar os seguintes comandos: endereo_da_casa = &contedo_da_casa; *endereo_da_casa = 10; O valor da clula (varivel) chamada contedo da casa ser 10. Podemos pensar no * como uma instruo para seguir a seta (figura) para encontrar a clula referenciada. Note que, se endereo_da_casa mantiver o endereo de contedo_da_casa, ambos os comandos que seguem tero o mesmo efeito, isto , ambos armazenaro o valor 10 em contedo_da_casa: contedo_da_casa = 10;
Linguagem de Programao II - URI Campus de Frederico Westphalen
int *endereo_para_int;
O tipo de dado endereo_para_char diferente do tipo endereo_para_int. Os erros em tempo de execuo e advertncias durante a compilao podem ocorrer num programa que define um ponteiro para um tipo de dado e ento o utiliza para apontar para algum outro tipo de dado. tambm uma prtica inadequada na programao definir um ponteiro de um modo e depois utiliz-lo de outro:
int *int_ptr; float valor_real = 23.45;
int_ptr = &valor_real; Aqui, a varivel int_ptr foi definida ser do tipo int *, significando que pode conter o endereo de uma clula de memria do tipo int. O terceiro comando tenta atribuir a int_ptr o endereo &valor_real de uma varivel float declarada.
129
130
*int_ptr = valor2; copia o contedo da varivel valor2 na clula apontada pelo endereo armazenado em int_ptr. valor1 20 [1395] valor2 20 [3321] temp 10 [0579] int_ptr 1395 [1925]
valor2 = temp; O ltimo comando do programa simplesmente copia o contedo da varivel inteira temp em outra varivel inteira valor2. valor1 20 [1395] valor2 10 [3321] temp 10 [0579] int_ptr 1395 [1925]
A primeira linha do programa contm as definies e inicializaes padres. O comando aloca trs clulas para manter um nico int, dando a cada clula um nome, e inicializa duas delas. assumido que a clula chamada valor1 est localizada no endereo 1395, que a clula chamada valor2 est localizada no endereo 3321 e que a clula chamada temp est localizada no endereo 0579.
valor1 10 [1395]
valor2 20 [3321]
temp [0579]
int_ptr [1925]
O segundo comando no programa define int_ptr como um ponteiro para um tipo de dado int. O comando aloca a clula e lhe d um nome (colocado no endereo 1925). Lembre-se que, quando o asterisco combinado com o tipo de dado (neste caso int), a varivel contm o endereo de uma clula do mesmo tipo de dado. Como int_ptr no foi inicializada, ela no aponta para nenhuma varivel int em particular. O terceiro comando atribui a int_ptr o endereo de valor1: valor1 10 [1395] valor2 20 [3321] temp [0579] int_ptr 1395 [1925]
O prximo comando no programa: temp = *int_ptr; valor1 10 [1395] valor2 20 [3321] temp 10 [0579] int_ptr 1395 [1925]
Observe que no foi inicializado *int_ptr (que poderia ser um inteiro qualquer), mas foi inicializado int_ptr (que precisa ser um endereo para um int). Esta inicializao na declarao deixa a interpretao do cdigo bastante confusa, pois o exemplo acima poderia ser escrito com mais clareza, apesar de utilizar uma linha a mais assim:
int valor1; int *int_ptr; int_ptr = &valor1;
J que as strings em C so vetores, podemos inicializar strings nos programas associandoas ao endereo do primeiro caracter, como no exemplo abaixo:
#include <stdio.h> #include <conio.h> void main() { char *palindroma = Socorram o Marrocos; int indice; for(indice=0;indice < strlen(palindroma); indice++) printf(%c,palindroma[indice]); printf(\n); for(indice=strlen(palindroma)-1;indice>=0; indice--)
usa a expresso *int_ptr para acessar o contedo da clula qual int_ptr aponta: valor1. Portanto, o valor inteiro 10 armazenado na varivel temp. Se omitssemos o asterisco na frente de int_ptr, o comando de atribuio ilegalmente armazenaria o contedo de int_ptr (o endereo 1395), na clula chamada temp, que somente pode armazenar um inteiro, e no um endereo. O quinto comando no programa:
Linguagem de Programao II - URI Campus de Frederico Westphalen
131
132
b) No pode ser utilizado com expresses envolvendo operadores como + / * -: endereco_variavel = &(valor1 + 10); c) No pode ser utilizado precedendo variveis declaradas como register:
register int reg1;
endereco_variavel = ®1;
o nome da matriz classe uma constante cujo valor o endereo do primeiro elemento da matriz de 10 floats. O comando a seguir atribui o endereo do primeiro elemento da matriz varivel ponteiro float_ptr: float_ptr = classe Um comando equivalente : float_ptr = &classe[0]; Entretanto, como float_ptr contm o endereo de um float, os seguintes comandos so ilegais pois tentam atribuir um valor para a constante classe ou seu equivalente &classe[0]:
Linguagem de Programao II - URI Campus de Frederico Westphalen
133
134
void (*func)(int); func um ponteiro para uma funo void que possui um inteiro como parmetro; float (*ptf)(int,double); ptf um ponteiro para uma funo que retorna float e possui como parmetros um int e um double.
Os ponteiros para funes tm importantes usos. Por exemplo, considere a funo qsort (ordena um vetor), que tem como um de seus parmetros um ponteiro para uma funo. Ns no podemos passar uma funo por valor, isto , passar o prprio cdigo, mas podemos passar um ponteiro para o cdigo, ou seja, um ponteiro para a funo. Exemplos:
Observe apenas que se o valor de ptr_int antes do incremento fosse 2000, aps o incremento esse valor passou para 2002, pois um incremento de int corresponde a 2 bytes, da mesma forma que ptr_float passaria de 3000 para 3004.
#include <stdio.h> int soma(int a, int b); int sob(int a, int b); void main() { int (*pf)(int,int); int i, a, b, r;
for(i=0;i<4;i++) { pf=(i%2==0)?soma:sub; printf(\nDigite um valor: ); scanf(%d,&a); printf(\nDigite outro valor: ); scanf(%d,&b); r=(*pf)(a,b); printf(%d\n, r); } } int soma(int a, int b) { printf(A soma : \n); return(a+b); } int sub(int a, int b); { printf(A subtrao : \n); return(a-b); }
135
136
{ void (*vet[3])(); /* vetor de ponteiros para funes */ int op; vet[0] = zero; vet[1] = um; vet[2] = dois; do { printf(Digite um nmero entre 0 e 2: ); scanf(%d,&op); (*vet[op])(); } while (op<0 || op>2); } void zero() { printf(Zero!\n); } void um() { printf(Um!\n); } void dois() { printf(Dois!\n); }
write('x: '); readln(x); write('y: '); readln(y); px := @x; writeln('Valor apontado por px: ', px^); px := @y; writeln('Valor apontado por px: ', px^); writeln('X: ',x); writeln('Y: ',y); readkey; end.
Para usar um ponteiro para vetor ou para uma matriz necessrio primeiro criar um tipo para o qual o ponteiro possa apontar e declarar uma varivel ponteiro que aponte para o tipo criado. Podemos observar que uma matriz nada mais do que o endereo do primeiro elemento, portanto o tipo criado no precisa ter o tamanho da matriz a que se quer associar ao ponteiro, mas deve ter as mesmas dimenses da matriz:
type y= array[1..1,1..1] of integer; var px : ^y;
O ponteiro pode ento receber o endereo de uma matriz do mesmo tipo para o qual ele aponta
px := @x;
A partir dessa associao, pode-se acessar os elementos da matriz atravs do nome seguido dos ndices ou do ponteiro seguido de ^ e dos ndices
o mesmo que writeln( x[8,5] ); writeln( px^[8,5] );
Exemplo:
px : ^integer; z : ^real; mm : ^char; {ponteiro para um inteiro} {ponteiro para um real} {ponteiro para um char}
Exemplo:
uses crt; type y= array[1..1,1..1] of integer; var x: Array[1..10,1..10] of integer; px: ^y; i, j: integer; begin clrscr; for i:= 1 to 10 do begin for j:= 1 to 10 do begin x[i,j]:=i*10+j; end; end; for i:= 1 to 10 do
Para mostrar o valor apontado pelo ponteiro usa-se o nome do ponteiro seguido de um ^
writeln( px^ );
Exemplo:
uses crt; var x,y: integer; px: ^integer; begin clrscr; Linguagem de Programao II - URI Campus de Frederico Westphalen
137
138
begin for j:= 1 to 10 do begin write(x[i,j] :5); end; writeln; end; writeln( o mesmo que: ); px := @x; for i:= 1 to 10 do begin for j:= 1 to 10 do begin write(px^[i,j] :5); end; writeln; end; readkey; end.
Em Pascal tambm pode-se utilizar aritmtica com ponteiro, de modo que incrementandoos em uma unidade eles so incrementados em tantos bytes quanto o tipo para quem eles apontam. Outra forma de mostrarmos uma matriz usando artimtica com ponteiros :
uses crt; var x: Array[1..10,1..10] of integer; px: ^integer; i, j: integer; begin clrscr; for i:= 1 to 10 do begin for j:= 1 to 10 do begin x[i,j]:=i*10+j; end; end; px := @x[1,1]; for i:= 1 to 10 do begin for j:= 1 to 10 do begin write(px^ :5); px^:=px^+1; end; writeln; end; readkey; end.
A funo malloc obtm armazenagem suficiente para tantas vezes o tamanho de um float quanto for solicitado. Cada bloco de armazenagem requisitado inteiramnte separado e distinto de todos os outros. No podemos fazer suposies sobre onde os blocos sero alocados. Os blocos so tipicamente identificados com algum tipo de informao que permite que o sistema
139
140
operacional gerencie sua localizao e tamanho. Quando o bloco no mais necessrio, podemos retorn-lo para o sistema operacional por meio do seguinte comando: free( < nome_ponteiro > ) Em Pascal as funes so semelhantes no modo de operar mas um pouco diferentes na sintaxe. O procedimento Getmem recebe dois parmetros, sendo o primeiro o nome do ponteiro e o segundo a quantidade de bytes a serem alocados. Uma diferena a ser observada que o procedimento de liberao de memria Freemem precisa tambm da informao da quantidade de bytes a serem liberados. O exemplo abaixo em Pascal semelhante ao anterior escrito em C:
uses crt; type vetor = Array [1..1] of real; var fpt: ^vetor; i, qtd: integer; begin clrscr; write('Quantidade de valores: '); readln (qtd); GetMem(fpt, sizeof(real) * qtd); for i:= 1 to qtd do begin write(i,' valor: '); readln(fpt^[i]); end; for i:= 1 to qtd do begin writeln(i,' valor: ', fpt^[i]:6:2); end; readkey; FreeMem(fpt,sizeof(integer)*qtd); end.
#include <conio.h> #include <alloc.h> int **matriz; int *colunas; unsigned long lin, col, i, j; void main() { clrscr(); printf("Memoria livre: %lu bytes\n", (unsigned long) coreleft()); printf("Linhas: "); scanf("%d",&lin); matriz=(int **) malloc(sizeof(int *) * lin); colunas=(int *) malloc(sizeof(int) * lin); printf("Memoria livre: %lu bytes\n", (unsigned long) coreleft()); if (matriz==NULL) { printf("Nao foi possivel alocar memoria\n"); exit(1); } for(i=0;i<lin;i++) { printf("Colunas na linha %d: ",i); scanf("%d",&col); matriz[i]=(int *) malloc(sizeof(int)*col); if(matriz[i]==NULL) { printf("Nao foi possivel alocar memoria\n"); exit(1); } colunas[i]=col; printf("Memoria livre: %lu bytes\n", (unsigned long) coreleft()); } printf("Memoria livre: %lu bytes\n", (unsigned long) coreleft()); for(i=0;i<lin;i++) { printf("Linha %d:\n",i); for(j=0;j<colunas[i];j++) { printf("%d Valor: ",j); scanf("%d",&matriz[i][j]); } } for(i=0;i<lin;i++) { printf("\n"); for(j=0;j<colunas[i];j++) { printf("%5d",matriz[i][j]); } } for(i=0;i<lin;i++) { free(matriz[i]); } free(matriz); free(colunas); printf("\nMemoria livre: %lu bytes\n", (unsigned long) coreleft()); getch(); }
Quando precisamos de variveis com um tamanho desconhecido na compilao, devemos usar alocao dinamica de memria, no heap. Devemos porm tomar o cuidado de liberar a memria quando no precisamos mais da varivel, pois o compilador s devolve automaticamente a memria ocupada pelas variveis locais. Se no liberarmos a memria corretamente, o programa pode vir a travar. A grande vantagem da utilizao de alocao dinmica que permite-se criar estruturas semelhantes a matrizes com dimenses desconhecidas no momento da compilao. Devido a uma limitao da linguagem Pascal, uma matriz ou vetor no pode ocupar mais do que 64 Kbytes de memria, portanto, quando necessitamos de uma matriz ou vetor com mais de 64 Kbytes devemos usar alocao dinmica de memria. Pode-se inclusive criar matrizes com nmero variado de colunas para cada linha, como por exemplo:
#include <stdio.h> #include <stdlib.h> Linguagem de Programao II - URI Campus de Frederico Westphalen
141
142
printf("Sem memoria"); exit(1); } ledados(aux,cod); if(prim==NULL) { prim=aux; ult=prim; } else { ult->prox=aux; ult=aux; } } imprime(); getch(); liberamem(); } void ledados(produto *p, int c) { float precoaux; clrscr(); p->codigo=c; fflush(stdin); printf("Codigo: %d\n",p->codigo); printf("Descricao: "); gets(p->descr); fflush(stdin); printf("Preco: "); scanf("%f",&precoaux); p->preco=precoaux; p->prox=NULL; } void imprime() { aux=prim; while(aux!=NULL) { printf("%d - %s - %f\n",aux->codigo, aux->descr, aux->preco); aux = aux->prox; } } void liberamem() { aux=prim; while(aux!=NULL) { free(aux); aux = aux->prox; }
Podemos observar no exemplo a seguir, uma lista encadeada com alocao dinmica de memria.
#include <stdio.h> #include <conio.h> #include <stdlib.h> typedef struct produto { int codigo; char descr[40]; float preco; struct produto *prox; }produto; produto *prim, *ult, *aux; int cod; void ledados(produto *p, int c); void imprime(); void liberamem(); void main() { prim=ult=NULL; while(1) { clrscr(); printf("Codigo: "); scanf("%d",&cod); if (cod<0) break; aux=(produto *) malloc(sizeof(produto)); if (aux==NULL) { Linguagem de Programao II - URI Campus de Frederico Westphalen
} O exemplo abaixo a implementao de uma lista encadeada com alocao de memria simples, sem ordenao sendo toda nova informao includa no final da lista:
#include #include #include #include #include <stdio.h> <stdlib.h> <conio.h> <alloc.h> <ctype.h>
143
144
void listar(); void insere(unsigned char infoaux); struct lista { unsigned char info; struct lista *elo; }; struct lista *pri, *aux, *ult, *pen; unsigned char infoaux; void main() { clrscr(); pri=NULL; ult=NULL; do { gotoxy(1,1); printf("Digite uma Letra: "); infoaux=toupper(getch()); if ((infoaux>=65)&&(infoaux<=90)) insere(infoaux); listar(); } while ((infoaux>=65)&&(infoaux<=90)); getch(); liberar(); } void listar() { struct lista *lult; lult=pri; gotoxy(1,10); while(lult!=NULL) { printf("%c ",lult->info); lult=lult->elo; } } void liberar() { struct lista *lult; lult=pri; gotoxy(1,10); while(lult!=NULL) { aux=lult; lult=lult->elo; free(aux); } } void insere(unsigned char infoaux) { aux=(struct lista *) malloc(sizeof(struct lista)); if (aux==NULL) { printf("Nao foi possivel alocar memoria\n"); exit(1); } if (pri==NULL) Linguagem de Programao II - URI Campus de Frederico Westphalen }
else
O exemplo abaixo a implementao de uma lista encadeada com alocao de memria com ordenao das informaes, ou seja, as informaes so inseridas na lista de forma que ela sempre est com os dados em ordem crescente:
#include #include #include #include #include <stdio.h> <stdlib.h> <conio.h> <alloc.h> <ctype.h>
void liberar(); void listar(); void insere(unsigned char infoaux); struct lista { unsigned char info; struct lista *elo; }; struct lista *pri, *aux, *ult, *pen; unsigned char infoaux; void main() { clrscr(); pri=NULL; do { gotoxy(1,1); printf("Digite uma Letra: "); infoaux=toupper(getch()); if ((infoaux>=65)&&(infoaux<=90)) insere(infoaux); listar(); } while ((infoaux>=65)&&(infoaux<=90)); getch(); liberar(); } void listar() { struct lista *lult; lult=pri; gotoxy(1,10); while(lult!=NULL) { printf("%c ",lult->info);
145
146
lult=lult->elo; }
void liberar() { struct lista *lult; lult=pri; gotoxy(1,10); while(lult!=NULL) { aux=lult; lult=lult->elo; free(aux); } } void insere(unsigned char infoaux) { int inseri; aux=(struct lista *) malloc(sizeof(struct lista)); if (aux==NULL) { printf("Nao foi possivel alocar memoria\n"); exit(1); } if (pri==NULL) { aux->info=infoaux; aux->elo=NULL; pri=aux; } else { if(pri->info > infoaux) { aux->info=infoaux; aux->elo=pri; pri=aux; } else { if(pri->elo == NULL) { aux->info=infoaux; aux->elo=NULL; pri->elo=aux; } else { inseri=0; pen=pri; ult=pri; while(inseri == 0 && ult->elo != NULL) { if (ult->elo != NULL) { pen=ult; ult=ult->elo; } if (ult->info > infoaux) { aux->info=infoaux; aux->elo=ult; Linguagem de Programao II - URI Campus de Frederico Westphalen
pen->elo=aux; inseri=1; }
O exemplo a seguir apresenta uma lista encadeada com alocao dinmica de memria em Pascal.
program listadinamicaordenada; uses crt; type lista = record info: string[10]; prox: Pointer; end; var aux, pri, ult, pen: ^lista; infoaux: string[10]; procedure listar; begin aux:=pri; gotoxy(1,10); while aux<> nil do begin writeln(aux^.info); aux:=aux^.prox; end; end; procedure liberar; begin aux:=pri; gotoxy(1,10); while aux<> nil do begin ult:=aux; aux:=aux^.prox; dispose(ult); end; end; procedure insere(infoaux: string); var inseri: boolean; begin new(aux); if aux=nil then begin writeln('Nao foi possivel alocar memoria.'); exit; end; aux^.info:=infoaux; if pri=nil then
147
148
begin aux^.prox:=nil; pri:=aux; end else begin if pri^.info > infoaux then begin aux^.prox:=pri; pri:=aux; end else begin if pri^.prox = nil then begin aux^.prox:=nil; pri^.prox:=aux; end else begin inseri:=false; pen:=pri; ult:=pri; while (inseri = false) and (ult^.prox <> nil) do begin if ult^.prox <> nil then begin pen:=ult; ult:=ult^.prox; end; if ult^.info > infoaux then begin aux^.prox:=ult; pen^.prox:=aux; inseri:=true; end; end; if inseri=false then begin aux^.prox:=nil; ult^.prox:=aux; end; end; end; end; end; begin pri:=nil; repeat clrscr; writeln('Digite um nome: '); readln(infoaux); if length(infoaux)>0 then insere(infoaux); listar; until length(infoaux)=0; readkey; liberar; end.
149
150
Para fazer a listagem em ordem de nome (poderia ser qualquer outro campo) usando uma lista encadeada com alocao dinmica, crie um novo form com a mesma estrutura do Form de Listagem de Clientes e implemente o seguinte cdigo: 1. Na seo Type crie um novo tipo que um registro (record) com as estrutura da lista de clientes:
lista = record codigo:integer; nome:string[40]; cidade:string[30]; prox: Pointer; end;
4. Use a unit UnFuncoesArquivo (File => Use Unit... => UnFuncoesArquivo.pas) 5. Na seo implementation crie um procedimento que far a insero dos dados na lista:
procedure insere(c: clientes); var inseri: boolean; begin new(aux); { aloca um novo nodo } Linguagem de Programao II - URI Campus de Frederico Westphalen
151
152
if aux=nil then begin showMessage('Nao foi possivel alocar memoria.'); exit; end; aux^.nome:=c.nome; { preenche com os dados } aux^.codigo:=c.codigo; aux^.cidade:=c.cidade; { faz a ligao da lista j em ordem } if pri=nil then { se a lista est vazia } begin aux^.prox:=nil; pri:=aux; end else begin if pri^.nome > c.nome then { se o nome menor que o 1.o da lista } begin aux^.prox:=pri; pri:=aux; end else begin if pri^.prox = nil then { se a lista s tem 1 elemento } begin aux^.prox:=nil; pri^.prox:=aux; end else { se a lista j tem vrios elementos } begin inseri:=false; pen:=pri; ult:=pri; while (inseri = false) and (ult^.prox <> nil) do begin if ult^.prox <> nil then begin pen:=ult; ult:=ult^.prox; end; if ult^.nome > c.nome then begin { se o nome da lista maior que o nome atual } pen^.prox:=aux; {o prx do penltimo aponta para o novo } aux^.prox:=ult; {o prx do novo aponta para o ltimo} {assim o novo ficar entre o penltimo e o ltimo lido } inseri:=true; end; end; if inseri=false then { se chegou ao final da lista sem inserir } begin ult^.prox:=aux; { insere no fim da lista } aux^.prox:=nil; { e no aponta para ningum } end; end; end; end; end;
while (not eof(arq)) do { enquanto nao chega no final do arquivo } begin read(arq,cli); if cli.codigo > 0 then {se codigo for maior que 0 insere na lista} begin insere(cli); end; end; memo1.clear; { limpa o memo } memo1.lines.add('Cd - Nome - Cidade '); { escreve o cabealho } aux:=pri; while aux<> nil do { percorre a lista mostrando os dados } begin memo1.lines.add(IntToStr(aux^.codigo) + ' - ' + aux^.nome + ' - ' + aux^.cidade); aux:=aux^.prox; end; aux:=pri; while aux<> nil do { percorre a lista liberando a memria } begin ult:=aux; aux:=aux^.prox; dispose(ult); end; end;
Este tipo de ordenao com todos os campos do arquivo sendo colocados na memria pode ser feita se o arquivo possui poucos campos. Se o mesmo tiver vrios campos deve-se colocar na lista ou no vetor somente o campo que se quer indexar (ordenar) e um registro com a posio do registro no arquivo (guarda um nmero inteiro obtido com a funo FilePos). Desta forma, quando quisermos mostrar os demais dados do arquivo, basta usar o comando seek posicionando no registro correto, fazendo a leitura e mostrando os dados. O programa ficaria assim (em negrito est o que foi alterado em relao ao anterior):
unit UnListClienteNom2; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrListClienteNom2 = class(TForm) Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; lista = record nome:string[40]; posicao:integer; prox: Pointer; end; var FrListClienteNom2: TFrListClienteNom2; aux, pri, ult, pen: ^lista;
153
154
end; implementation uses UnFuncoesArquivo; {$R *.DFM} procedure insere(n: string; p: integer); var inseri: boolean; begin new(aux); { aloca um novo nodo } if aux=nil then begin showMessage('Nao foi possivel alocar memoria.'); exit; end; aux^.nome:=n; { preenche com os dados } aux^.posicao:=p; { faz a ligao da lista j em ordem } if pri=nil then { se a lista est vazia } begin aux^.prox:=nil; pri:=aux; end else begin if pri^.nome > n then { se o nome menor que o 1.o da lista } begin aux^.prox:=pri; pri:=aux; end else begin if pri^.prox = nil then { se a lista s tem 1 elemento } begin aux^.prox:=nil; pri^.prox:=aux; end else { se a lista j tem vrios elementos } begin inseri:=false; pen:=pri; ult:=pri; while (inseri = false) and (ult^.prox <> nil) do begin if ult^.prox <> nil then begin pen:=ult; ult:=ult^.prox; end; if ult^.nome > n then begin { se o nome da lista maior que o nome atual } pen^.prox:=aux; { o prx do penltimo lido aponta para o novo } aux^.prox:=ult; { o prx do novo aponta para o ltimo} { assim o novo ficar entre o penltimo e o ltimo lido } inseri:=true; end; end; if inseri=false then { se chegou ao final da lista sem inserir } begin ult^.prox:=aux; { insere no fim da lista } aux^.prox:=nil; { e no aponta para ningum } end; end; end; end; Linguagem de Programao II - URI Campus de Frederico Westphalen 155 procedure TFrListClienteNom2.FormShow(Sender: TObject); var p: integer; begin pri:=nil; seek(arq,0); { posiciona no 1.o registro do arquivo } while (not eof(arq)) do { enquanto nao chega no final do arquivo } begin p:=filepos(arq); {guarda a posio do registro antes da leitura } read(arq,cli); if cli.codigo > 0 then {se codigo for maior que 0 insere na lista} begin insere(cli.nome, p); end; end; memo1.clear; { limpa o memo } memo1.lines.add('Cd - Nome - Cidade '); { escreve o cabealho } aux:=pri; while aux<> nil do { percorre a lista j em ordem } begin { usando a lista para posicionar a leitura } seek(arq, aux^.posicao); { posiciona a leitura no arquivo } read(arq, cli); { l o registro e mostra os dados do arquivo} memo1.lines.add(IntToStr(cli.codigo)+' - '+ cli.nome+' - '+cli.cidade); aux:=aux^.prox; end; aux:=pri; while aux<> nil do { percorre a lista liberando a memria } begin ult:=aux; aux:=aux^.prox; dispose(ult); end; end; procedure TFrListClienteNom2.Button1Click(Sender: TObject); begin close; end; end.
156
12. EXERCCIOS
1. Altere o exemplo do clculo de mdia para calcular tambm nmeros reais. 2. Sabendo-se que a mdia de quilmetros por litro de um automvel calculado dividindo-se a quantidade de quilmetros pela quantidade de combustvel, faa um programa em Delphi que leia a quantidade de quilmetros percorridos e a quantidade de combustvel e calcule e escreva a mdia de quilmetros por litro.
3. Pela Frmula de Bskara conseguimos encontrar as 2 razes (x1 e x2) de uma equao de 2 Grau:
considerando que o tempo mximo de durao de um jogo de 24 horas e que o jogo pode iniciar em um dia e terminar no dia seguinte. 7. Fazer um programa em Delphi que l 5 valores e conta quantos destes valores so negativos, escrevendo esta informao. 8. Fazer um programa em Delphi que l um nmero no conhecido de valores e conta quantos deles esto em cada um dos intervalos [0, 25], (25, 50], (50, 75], (75, 100].
Observao: Usar um campo Memo para fazer a leitura dos valores. Para acessar cada uma das linhas usar as propriedades: Memo1.Lines.Count para saber a quantidade de linhas. Memo1.Lines[i] para acessar cada uma das linhas do memo. como no exemplo abaixo:
Fazer um programa em Delphi que leia o valor de a, b, c e calcula e escreve as razes da equao, se houver, ou uma mensagem informando que no existem razes 4. Fazer um programa em Delphi que escreve os nmeros mltiplos de 13 entre 0 e 1000, juntamente com a soma e a quantidade dos mesmos. 5. Faa um programa em Delphi com um menu principal com as seguintes opes: - Arquivo Sair - Clculos Mdias Nmeros Primos - Sobre Mdias: Fazer um form que permita a leitura de 3 valores: a, b, c e calcule e escreva a mdia aritmtica e harmnica correspondente. ma = (a + b + c )/3 mh = 3 / (1/a + 1/b +1/c) Obs.:Para o clculo de mdia harmnica, a nota mnima 1. Nmeros Primos: Fazer um form que leia dois valores e escreva os nmeros primos entre esses dois nmeros lidos. Sair: Sair do programa Sobre: Fazer um form com as informaes de quem produziu o programa. O programa deve ter: Um cone personalizado Um nome personalizado na Barra de Ttulo do aplicativo Uma caixa de dilogo confirmando se o usurio realmente deseja sair do aplicativo 6. Fazer um programa em Delphi que l a hora de incio de um jogo e a hora de trmino do jogo, com horas e minutos. Calcular e escrever a durao do jogo, tambm em horas e minutos,
9. Faa um programa em Delphi que l uma matriz M(6,6) e um valor A e multiplica a matriz M pelo valor A e coloca os valores da matriz multiplicados por A em uma nova matriz. 10. Faa um programa em Delphi que leia uma matriz 5 x 5 e escreva a soma de todas as linhas, colunas, diagonal principal e diagonal secundria.
Observao: Usar um componente Para acessar cada uma StringGrid1.Cells[i,j] . StringGrid para das clulas fazer a usar leitura as dos valores. propriedades:
11. Fazer um programa em Pascal que faa o controle de 10 contas-corrente (banco), com as operaes: Abrir conta Depsito Saque Consulta de Saldo Usar vetores para armazenar os seguintes dados: nro. da conta, saldo, nome do titular. 12. Fazer um programa semelhante ao anterior em Delphi, com um menu e um Form para cada Operao. 13. Fazer um programa semelhante ao anterior em Delphi, com um menu e um Form para cada Operao, usando arquivos ao invs de vetores.
157
158
BIBLIOGRAFIA
GUEZZI, Carlo & JAZAYERI, Mehdi. Conceitos de Linguagem de Programao. Rio de Janeiro, Ed. Campus. 1985. KELLY-BOOTLE, Stan. Dominando o Turbo C. Rio de Janeiro, Ed. Cincia Moderna. 1989. KERNIGHAM, Brian W. & RITCHIE, Dennis M. C: A Linguagem de Programao. Rio de Janeiro, Ed. Campus. 1986. LONGO, Maurcio B.; SMITH Jr., Ronaldo & POLISTCHUCK, Daniel. Delphi 3 Total. Rio de Janeiro, Brasport Livros e Multimdia Ltda. 1997. MECLER, Ian & MAIA, Luiz Paulo. Programao e Lgica com Turbo Pascal. Rio de Janeiro, Ed. Campus. 1989. PALMER, Scott D. Guia do Programador - Turbo Pascal for Windows. Rio de Janeiro, Editora Cincia Moderna. 1992. PAPPAS, Chris H. & MURRAY, Wiliam H. Borland C++. So Paulo, Makron Books. 1995. RINALDI, Roberto. Turbo Pascal 7.0: Comandos e Funes. So Paulo, rica. 1993. SCHILDT, Herbert. Linguagem C: Guia Prtico e Interativo. So Paulo, McGraw-Hill. 1989. WIENER, Richard S. Turbo C Passo a Passo. Rio de Janeiro, Ed. Campus. 1991
159