Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Programas Associados a Botões: Ordenar e Inverter Sequências, Notas de estudo de Informática

Duas rotinas de programas em c++ para ordenar e inverter sequências de números usando ponteiros. O primeiro programa ordena cinco números armazenados em um vetor e o segundo programa inverte a string lida de um edit. O documento também discute como melhorar o uso de ponteiros no c++.

Tipologia: Notas de estudo

2013

Compartilhado em 11/12/2013

Futebol13
Futebol13 🇧🇷

4.5

(204)

196 documentos

1 / 46

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
Capítulo 4
91
4.5.2. Exercício
Modifique o exemplo 4.5.1, para que a atualização dos EditBox sejam feitos através de um
procedimento.
4.5.3. Exemplo 2
Modifique o exemplo 4.5.1, para usar ponteiros na ordenação da matriz de frutas M.
Resposta
a) Variáveis Globais:
#define comp 8
#define linhas 5
char M[linhas][comp] = {"banana",
"maça",
"abacate",
"pera",
"uva"};
char * pM[linhas];
b) Linhas de programa associadas ao botão "ordena":
{
int nvezes, x;
char *aux;
int fim = 3;
for (x=0; x<5; pM[x] = M[x],x++); // apontar para elementos de M
for (nvezes = 0; nvezes < 4; nvezes++)
{
for (x=0; x<=fim; x++)
{
if (*pM[x] > *pM[x+1]) //[1]
Vetor de ponteiros
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15
pf16
pf17
pf18
pf19
pf1a
pf1b
pf1c
pf1d
pf1e
pf1f
pf20
pf21
pf22
pf23
pf24
pf25
pf26
pf27
pf28
pf29
pf2a
pf2b
pf2c
pf2d
pf2e

Pré-visualização parcial do texto

Baixe Programas Associados a Botões: Ordenar e Inverter Sequências e outras Notas de estudo em PDF para Informática, somente na Docsity!

4.5.2. Exercício

Modifique o exemplo 4.5.1, para que a atualização dos EditBox sejam feitos através de um

procedimento.

4.5.3. Exemplo 2

Modifique o exemplo 4.5.1, para usar ponteiros na ordenação da matriz de frutas M.

Resposta

a) Variáveis Globais:

#define comp 8 #define linhas 5 char M[linhas][comp] = {"banana", "maça", "abacate", "pera", "uva"}; char * pM[linhas];

b) Linhas de programa associadas ao botão "ordena":

int nvezes, x; char aux; int fim = 3; for (x=0; x<5; pM[x] = M[x],x++); // apontar para elementos de M for (nvezes = 0; nvezes < 4; nvezes++) { for (x=0; x<=fim; x++) { if (pM[x] > *pM[x+1]) //[1]

Vetor de ponteiros

aux = pM[x]; pM[x] = pM[x+1]; pM[x+1]= aux; fim--; [2] } } } Edit1->Text = pM[0]; //[3] Edit2->Text = pM[1]; Edit3->Text = pM[2]; Edit4->Text = pM[3]; Edit5->Text = pM[4]; }

Observe que:

  • As linhas de M apresentadas nos Edits, ainda seguem a mesma ordem (pM[0] até pM[4]). é

apresentado;

  • Agora, os ponteiros apontam para as linhas de M. Note que as posições de M não são

alteradas.

4.5.4. Exercícios

1 - O que acontece se a linha [1] for modificada para if (pM[x] > pM[x+1]) ...

2 - Para que serve a linha [2]?

3 - O que acontece se as atribuições aos Edits a partir da linha [3] forem modificadas para

Edit1->Text = *pM[0]; ... Edit1->Text = *pM[4];

4 – Desenvolva o programa de busca binária (aula de vetores), agora usando ponteiros.

5 – Desenvolva uma função para somar o conteúdo de duas matrizes 3x3 usando ponteiros.

a) Dentro do botão "inverte", o trecho do programa que realiza a alocação:

void __fastcall TForm1::InverteClick( **TObject *** Sender) { **char *** s; char aux[2]; char buf[41]=""; int x=0; s = ( char *) malloc(40); if (!s) { Application->MessageBox("mensagem","erro de alocação",MB_OK); exit (1); }

// continua....

Na linha de código s = (char *) malloc(40); do exemplo acima, foi criado um ponteiro "s" do

tipo char. Este ponteiro vai apontar para o endereço inicial, da região de memória alocada por

malloc(). Note que o comando malloc recebe como parâmetro, o valor da quantidade de

memória requerida, neste caso é 40. Mas o que significa este valor "40"? Este tamanho

reserva na memória 40 espaços de tamanho ( char *), ou seja, 40 bytes, que estão reservados

pelo programa e podem, agora, ser acessados através do ponteiro "s".

Após a criação de "s", é necessário (e obrigatório) testar se o ponteiro existe, ou seja, se ele

aponta para algum endereço na memória não nulo. Se por algum motivo, o ponteiro não puder

ser criado, então ele conterá um valor nulo (NULL ou 0). Se isto ocorrer, a execução do

programa deve ser terminada, sob pena de tornar instáveis os outros aplicativos em

execução,ou até travar o sistema operacional. O comando if (!s) testa se o ponteiro existe, ou

seja, se contém um valor diferente de nulo. Se o ponteiro for nulo, é apresentado uma

mensagem de erro e o programa deve ser encerrado. O comando exit(1) encerra o programa

neste ponto.

As outras variáveis locais, definidas no exemplo acima, serão apresentadas a seguir.

// continuação....

strcpy(s,Edit1->Text.c_str()); [1] for (x = strlen(s)-1; x >= 0; x--) [2] { sprintf(aux,"%c",s[x]); [3] strcat(buf,aux); [4] } Edit2->Text = buf; [5] free(s); [6]

Seguindo o exemplo, na linha:

[1] O conteúdo do EditBox é passado para a região de memória apontada por "s".

[2] É executado um loop que varia de x (tamanho de s) até 0, que é a primeira posição da

string s (s[0]).

[3] Converte um caracter em uma string.

[4] A variável local buf concatena cada valor de aux.

[5] Buf é apresentado no formulário;.

Após a utilização da variável alocada dinamicamente, é extremamente importante liberar a

área de memória alocada por malloc, usando o comando free(). A linha

[6] libera a área de memória apontada pelo ponteiro "s".

[5] outra maneira de calcular o tamanho de uma string, usando ponteiros.

[6] "aux" aponta para uma nova região na memória, do tamanho de "s".

[7] testa se o ponteiro existe, ou seja, se "aux" aponta para um endereço diferente de nulo.

[8] encerra o programa se a memória não foi alocada.

[9] inverte o conteúdo da string "s" e armazena em "aux". Incrementa-se índice de y e move o

ponteiro de "s" para o início de "s".

[10] acrescenta finalizador de string.

[11] Edit2 recebe aux; na verdade, o Edit aponta para aux.

[12] libera a área apontada por "aux".

Como pode ser observado, neste exemplo não se fez necessário o uso de bibliotecas de

manipulação de string, ou seja, o programador tem maior controle sobre o que está sendo

executado. Muitas vezes, linguagens de mais alto nível, mascaram efetivamente o que

acontece após o comando ser executado. Da forma apresentada neste exemplo, o programador

consegue entender o que está acontecendo durante a execução do programa, evitando inserir

comandos desnecessários.

5.3. Exercícios

1- O que acontece se for alocado para aux um tamanho de memória diferente do valor de x?

2- Crie um EditBox no formulário para apresentar o conteúdo do ponteiro "aux", após ser

executada a linha [12]. O que será apresentado na tela? Que cuidados deve-se ter ao liberar a

memória apontada pelos ponteiros?

5.4. Portabilidade

O tamanho em bytes, de um dado tipo de variável, pode mudar de máquina para máquina.

Para evitar problemas com diferenças de tamanhos e assegurar a portabilidade de programas,

usa-se o operador sizeof(). sizeof informa ao programa o tamanho cujo tipo de variável ocupa

na memória.

5.4.1. Exemplo do uso de sizeof

int *pont; [1]

pont = ( int *) malloc(sizeof( int )); [2]

if (!pont) [3]

Application->MessageBox("mensagem","erro de alocacao",MB_OK);

exit(1); [4]

do exemplo acima, obsrva-se em:

[1] declaração de um ponteiro para inteiro chamado "pont";

[2] "pont" aponta para o endereço da posição de memória defina pelo comando malloc; note

que o tamanho a ser criado é especificado pelo sizeof(). Porque provavelmente, o inteiro

usado neste exemplo deve reservar 4 bytes por estar operando sobre o Windows; se o mesmo

programa fosse executado no DOS, provavelmente, seria reservado 2 bytes (Ansi C).

[3] realiza o teste de validade do ponteiro.

[4] se o ponteiro não for criado, aborta a execução do programa.

5.5. EXERCÍCIOS

1- Escreva um programa para ler N valores reais fornecidos por um usuário, e que calcule a

média destes valores e apresente o resultado. O programa deve usar ponteiros.

Resposta:

a) Variáveis globais usadas no programa:

2- Responda as seguintes perguntas:

a) O ponteiro "valores" do exercício acima é um vetor?

b) Para que serve o comando valores++?

c) O que acontece, se não for especificado um valor de N ao executar o programa?

d) A variável char msg[20] pode ser declara como char *msg?

3- Escreva um programa que leia uma matriz fornecida pelo usuário, e apresente na tela a

transposta desta matriz. Use alocação dinâmica para armazenar a matriz. E ponteiros para

acessar seu conteúdo.

int *M; // ponteiro para uma matriz declarado como global

__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { M = (int *)malloc(9 * sizeof(int)); if (!M) { ShowMessage("falta memória"); exit(0); } }

//-------------------------------------------------------------------------

void __fastcall TForm1::ArmazenaClick(TObject *Sender) { *(M+0) = atoi(Edit1->Text.c_str()); *(M+1) = atoi(Edit2->Text.c_str()); *(M+2) = atoi(Edit3->Text.c_str()); *(M+3) = atoi(Edit4->Text.c_str()); *(M+4) = atoi(Edit5->Text.c_str()); *(M+5) = atoi(Edit6->Text.c_str()); *(M+6) = atoi(Edit7->Text.c_str()); *(M+7) = atoi(Edit8->Text.c_str()); *(M+8) = atoi(Edit9->Text.c_str()); }

//------------------------------------------------------------------------- void __fastcall TForm1::TranspostaClick(TObject *Sender) {

// ... inserir o código aqui.

}

//------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action) { free(M); }

//-------------------------------------------------------------------------

4- Modifique o exercício 3, para que o espaço alocado dinamicamente para a matriz M, seja

criado de acordo com a dimensão da matriz, especificada pelo usuário.

5- Modifique o exercício 4.3, criando uma função que aloca espaço dinamicamente, e que

possa ser chamada sempre que for preciso alocar memória.

6. ARQUIVOS EM C

6.1. Ponteiro de arquivo

Arquivos são coleções de dados que recebem um nome único, pelo qual os dados podem ser

acessados e manipulados. Um ponteiro de arquivo é uma variável ponteiro do tipo FILE , que

é uma estrutura declarada em <stdio.h> e contém informações sobre o arquivo. Um

ponteiro para arquivo pode ser obtido da seguinte forma:

FILE *fp;

Para operar com arquivos é necessário realizar as seguintes operações:

6.2. Abrindo arquivos

Antes de qualquer operação com arquivos, é necessário que este arquivo exista. Para isto, é

preciso abrir um arquivo, que em C é dado pelo comando fopen() , da seguinte forma:

FILE * fopen (nomearquivo, modo)

Onde:

nomearquivo é uma string e pode incluir o caminho para o arquivo e a extensão.

modo determina como o arquivo será aberto. O arquivo pode ser do formato texto, ou do

formato binário. Os valores para modo são:

Tipo do ponteiro Nome do ponteiro

Abrir o

arquivo

Operações de

leitura/escrita

Fechar o

arquivo

Modo Descrição

rt abre arquivo texto para leitura

wt abre arquivo texto para escrita

at anexa dados a um arquivo texto

rb abre arquivo binário para leitura

wb abre arquivo binário para escrita

ab anexa elementos a um arquivo binário

r+t abre um arquivo texto para leitura/escrita

w+t cria um arquivo texto para leitura/escrita

a+t anexa dados a um arquivo texto para leitura/escrita

r+b abre um arquivo binário para leitura/escrita

w+b cria um arquivo binário para leitura/escrita

a+b anexa a um arquivo binário para leitura/escrita

6.2.1. Arquivos Tipo Texto

Qualquer arquivo cujo conteúdo está expresso pelos valores de caracteres da tabela ASCII.

Normalmente um arquivo texto não contém nenhum tipo de formatação, e pode ser aberto em

qualquer aplicativo.

Exemplo :

6.3.1. Observações

a) Se o arquivo "teste.txt" não existir, o comando fopen() cria este arquivo em branco. Se a

opção for "w", ele grava as informações neste arquivo recém criado.

b) Se o arquivo "teste.txt" já existir, o comando fopen() abre este arquivo. Se a opção for "w",

ele grava as novas informações sobre o conteúdo antigo. Ou seja, as informações anteriores

são perdidas. Para que isso não aconteça, deve-se usar o modo "a" para anexar dados ao

arquivo existente.

c) O que acontece se um arquivo não puder ser criado, como por exemplo, se não houver mais

espaço em disco, ou se um disquete não estiver inserido no drive especificado? Então, antes

de usar este arquivo, é necessário saber se o arquivo foi criado corretamente, para isso é

obrigatório testar o conteúdo do ponteiro de arquivo. Assim, o comando para abrir um

arquivo, pode ser escrito da seguinte forma:

FILE *fp; [1]

fp = fopen("teste.txt","wt"); [2] if (fp == NULL) [3]

exit(1);

Onde:

[1] é uma variável ponteiro do tipo FILE;

[2] abre o arquivo teste.txt tipo texto no modo de escrita (w);

[3] testa se o ponteiro é diferente ou igual a nulo, se for NULL interrompe a execução do

programa.

6.4. Abrindo um arquivo para leitura

Da mesma forma que é necessário abrir (ou criar) um arquivo para escrever algo, pode-se

abrí-lo apenas para leitura das informações. Desta maneira o conteúdo do arquivo não pode

ser alterado, e sim, apenas consultado. O comando para abrir um arquivo para leitura é dado

como mostra o exemplo abaixo:

FILE *fp; [1]

fp = fopen("teste.txt","rt"); [2]

if (fp == NULL) [3]

exit(1);

Onde:

[1] é uma variável ponteiro do tipo FILE;

[2] abre o arquivo teste.txt tipo texto no modo de leitura (r);

[3] testa se o ponteiro é diferente ou igual a nulo, se for NULL interrompe a execução do

programa.

6.5. Fechando um arquivo

O comando fclose() fecha um arquivo que foi aberto pela chamada de fopen(). Sempre, a

operação com arquivos acontece nesta sequência:

Um arquivo aberto, quando não for sofrer mais nenhum tipo de operação, obrigatoriamente

deve ser fechado. Se não for fechado, o arquivo pode ficar definitivamente inacessível.

Onde:

[1] é uma variável ponteiro do tipo FILE;

[3] abre o arquivo fputc.txt do tipo texto no modo de escrita (w);

[4] testa se o ponteiro é diferente ou igual a nulo, se for NULL interrompe a execução do

programa;

[5] enquanto o conteúdo da string apontada por str for diferente de '\0', cada caracter é

passado para o arquivo apontado por fp, se não ocorrer uma mensagem de final de arquivo,

EOF;

[6] fecha o arquivo apontado por fp.

Exemplo 2: Gravando um arquivo em modo binário.

FILE *fp; [1]

char *str = "texto de exemplo"; [2]

fp = fopen("c:/temp/fputc.txt","wb"); [3]

if (fp == NULL) [4]

exit(1);

while (*str)

if (!ferror(fp)) fputc(*str++,fp); [5]

fclose(fp); [6]

Onde:

[1] é uma variável ponteiro do tipo FILE;

[3] abre o arquivo fputc.txt do tipo binário no modo de escrita (w);

[4] testa se o ponteiro é diferente ou igual a nulo, se for NULL interrompe a execução do

programa;

[5] enquanto o conteúdo da string apontada por str for diferente de '\0', cada caracter é

passado para o arquivo apontado por fp, se não ocorrer uma mensagem de final de

arquivo,EOF. Entretanto, para arquivos abertos para operações binárias, um EOF pode ser um

caracter válido. Então é necessário usar a função ferror para determinar a ocorrência de um

erro;

[6] fecha o arquivo apontado por fp.

6.6.2. fgetc()

Esta função devolve o próximo caracter da stream de entrada na posição atual e incrementa o

indicador de posição do arquivo. Se o final do arquivo for alcançado, a função devolverá

EOF. Para arquivos binários, testar o final de arquivo com o comando feof(). A sintaxe é dada

por:

fgetc( FILE *pont);

Onde, pont é o ponteiro para o arquivo.

Exemplo1: Lendo um arquivo em modo texto.

FILE *fp; [1]

char *ch;

ch = (char *)malloc(20 * sizeof(char)); [2]

if (!ch) exit(1);

fp = fopen("c:/temp/fgetc.txt","rt"); [3]

if (fp == NULL) [4]

exit(1);

while ((*ch++ = fgetc(fp)) != EOF); [5]

fclose(fp); [6]

Onde:

[1] é uma variável ponteiro do tipo FILE;

[2] cria uma área para uma string;

[3] abre o arquivo fgetc.txt do tipo texto no modo de leitura (r);