Prévia do material em texto
E�trutura� de Dado�
Heterogê�ea� e� C
Um guia completo para organização e manipulação eficiente de dados
em C.
Por Bruno Mateus Barbosa Santos | Engenharia de Software 3 Estácio
Age�da
Fu�da�e�to�
Ponteiros e memória, alocação
dinâmica e endereçamento na
linguagem C
E�trutura� de Dado�
Conceitos básicos, tipos homogêneos e
heterogêneos, algoritmos e aplicações
Struct�
Declaração, manipulação, aninhamento
e arrays de structs em C
Preparação do A�bie�te
Requi�ito�
Compilador C (GCC recomendado)
IDE Dev-C++ ou outra de sua preferência
Conhecimentos básicos de programação em C
O Dev-C++ é um ambiente de desenvolvimento integrado
livre que utiliza os compiladores do projeto GNU para
compilar programas para o sistema operacional Microsoft
Windows.
Material de Apoio
Para baixar o código-fonte dos exemplos, clique aqui ou
acesse a seção "Explore +" deste material.
https://stecine.azureedge.net/repositorio/00212ti/00663/docs/codigo_fonte.zip
Objetivo� de Apre�dizage�
1 E�pregar po�teiro� �a li�guage� C
Compreender o conceito de ponteiros e utilizá-los
para manipulação eficiente de memória e dados
2 Defi�ir e�trutura de dado� �eterogê�ea
Entender o conceito e a importância das estruturas
heterogêneas na organização de dados complexos
3 Aplicar �truct� �a li�guage� C
Implementar e manipular estruturas para resolver
problemas práticos de programação
4 E�pregar e�trutura� ava�çada�
Utilizar estruturas aninhadas, vetores de estruturas e
a instrução typedef para criar código organizado e
eficiente
Po�teiro� e Me�ória
Ponteiros são variáveis especiais que armazenam
endereços de memória, permitindo acesso mais eficiente e
flexível aos dados.
A memória do programa em C é organizada em segmentos
específicos:
Text: Código do programa e constantes
Data: Variáveis globais e estáticas
Stack: Pilha de execução (parâmetros, endereços de
retorno e variáveis locais)
Heap: Blocos de memória alocados dinamicamente
A compreensão da organização da memória é fundamental
para o uso eficiente de ponteiros.
Defi�ição de Po�teiro
"Ponteiro é uma variável que contém um endereço de memória."
(Schildt, 1996)
Um ponteiro é um tipo especial de variável capaz de armazenar um
endereço de memória ou o endereço de outra variável.
Me�ória: Co�ceito� Fu�da�e�tai�
A memória é um componente do computador responsável
pelo armazenamento de dados e instruções. Suas
características incluem:
Composição por palavras (unidades de informação)
Cada palavra possui um endereço único
Capacidade de armazenamento determinada em bytes
Endereço Palavras
0 (00) Palavra 0
1 (001) Palavra 1
2 (010) Palavra 2
3 (011) Palavra 3
4 (100) Palavra 4
5 (101) Palavra 5
6 (110) Palavra 6
Representação de bytes e endereços na memória
Seg�e�to� de Me�ória
Text
Contém o código do programa e suas constantes. É
alocado durante a criação do processo e permanece
do mesmo tamanho durante toda a execução.
Data
Memória de trabalho do processo, onde ficam
alocadas as variáveis globais e estáticas. Tem
tamanho fixo ao longo da execução.
Stack
Contém a pilha de execução, onde são armazenados
parâmetros, endereços de retorno e variáveis locais.
Pode variar de tamanho durante a execução.
Heap
Contém blocos de memória alocados dinamicamente
durante a execução. Varia de tamanho durante a
vida do processo.
Alocação de Me�ória
A alocação de memória é um conceito fundamental na
programação em C, permitindo o gerenciamento eficiente
dos recursos do sistema. Existem três formas principais:
Tipo� de Alocação
Estática: Variáveis globais e estáticas (segmento
DATA)
Automática: Variáveis locais e parâmetros (segmento
STACK)
Dinâmica: Memória alocada em tempo de execução
(segmento HEAP)
A escolha correta do tipo de alocação impacta diretamente
o desempenho e a eficiência do programa.
Alocação E�tática
Ocorre com a declaração de variáveis globais (fora de
funções) ou estáticas (dentro de funções), usando o
modificador static.
Características:
O valor alocado à variável se mantém durante toda a
vida do programa
A memória é reservada na compilação
Localizada geralmente no segmento DATA
Valores preservados entre chamadas de função
#include
static int a = 0; // variável global, alocação estática
void incrementa(void) {
int b = 0; // variável local, alocação automática
static int c = 0; // variável local, alocação estática
printf("a: %d, b: %d, c: %d\n", a, b, c);
a++;
b++;
c++;
}
int main(void) {
int i;
for (i = 0; i
void *malloc(size_t size)
free Libera o número de bytes alocados
previamente na memória, apontado
por ptr.
#include
void free(void *ptr)
realloc Redimensiona a área previamente
alocada, apontada por ptr, para o
novo tamanho newsize.
#include
void *realloc(void *ptr, size_t newsize)
calloc Aloca um bloco de memória para um
array com count elementos de
tamanho eltSize cada e inicializa
todos os bytes com zero.
#include
void *calloc(size_t count, size_t
eltSize)
Variávei� do Tipo Po�teiro
Tipo_da_variável *Nome_da_Variável;
// Exemplos:
int *p; // ponteiro para inteiro
float *q; // ponteiro para float
char *r; // ponteiro para caractere
Ponteiros são variáveis especiais que permitem acesso
indireto a outras variáveis através de seus endereços de
memória.
Declaração de Po�teiro�
Operadore� de Po�teiro�
& - Operador de endereço: obtém o endereço de uma
variável
* - Operador de indireção: acessa o conteúdo do
endereço apontado
Exe�plo de U�o de Po�teiro�
int x = 5; // variável inteira
int *pt_x; // ponteiro para inteiro
// Ponteiro pt_x recebe o endereço de x
pt_x = &x;
// Acessando o valor de x através do ponteiro
printf("Valor de x: %d\n", *pt_x);
// Modificando o valor de x através do ponteiro
*pt_x = 50;
printf("Novo valor de x: %d\n", x);
Indireção de ponteiro: o ponteiro pt_x armazena o endereço
da variável x, permitindo acesso indireto ao seu conteúdo.I�direção Múltipla
int x = 10; // variável inteira
int *pt1; // ponteiro para inteiro
int **pt2; // ponteiro para ponteiro de inteiro
pt1 = &x; // pt1 aponta para x
pt2 = &pt1; // pt2 aponta para pt1
*pt1 = 30; // modifica x para 30
**pt2 = 50; // modifica x para 50
Um ponteiro também pode armazenar o endereço de outro
ponteiro, criando níveis de indireção.
O ponteiro pt2 aponta para pt1, que por sua vez aponta
para x. Através de **pt2, podemos acessar e modificar o
valor de x.
Arit�ética de Po�teiro�
Ponteiros permitem operações aritméticas limitadas,
sempre considerando o tamanho do tipo de dado que
apontam:
Adição: move o ponteiro para frente
Subtração: move o ponteiro para trás
Incremento/decremento: avança/retrocede um
elemento
Comparação: verifica relações entre ponteiros
Quando incrementamos um ponteiro p++, ele avança para o
próximo elemento do tipo apontado, não apenas o próximo
byte.
Ao incrementar um ponteiro para inteiro em um sistema
onde int ocupa 4 bytes, o endereço aumenta em 4 bytes,
não apenas 1.
Utilização do� Po�teiro�
1 Alocação di�â�ica de �e�ória
Permite criar e gerenciar estruturas de dados de
tamanho variável durante a execução do programa.
2 Ma�ipulação de array�
Facilita o acesso e percurso de vetores e matrizes de
forma eficiente.
3 Retor�o �últiplo e� fu�çõe�
Permite que uma função modifique e retorne vários
valores através de parâmetros por referência.
4 E�trutura� de dado� co�plexa�
Essencial para implementação de listas ligadas,
árvores, grafos e outras estruturas de dados
avançadas.
Exe�plo Prático de Po�teiro�
#include
#include
int main(void) {
//v_num é a variável que será apontada pelo ponteiro
int v_num = 10;
//declaração de variável ponteiro
int *ptr;
//atribuindo o endereço da variável v_num ao ponteiro
ptr = &v_num;
printf("Utilizando ponteiros\n\n");
printf("Conteúdo da variável v_num: %d\n", v_num);
printf("Endereço da variável v_num: %x \n", &v_num);
printf("Conteúdo da variável ponteiro ptr: %x", ptr);
getch();
return(0);
}
Algorit�o� e E�trutura� de Dado�
Defi�içõe�
Estrutura de dados: modo de organizar e armazenar
dados no computador para uso eficiente.
Algoritmo: conjunto de passos finitos e organizados para
executar uma tarefa específica.
Os algoritmos manipulam os dados organizados em
estruturas, e juntos formam a base dos programas de
computador.
A eficiência de um programa depende tanto da escolha
adequada da estrutura de dados quanto do algoritmo que a
manipula.
Tipo� de E�trutura� de Dado�
Vetore� e Matrize�
Estruturas lineares e estáticas para
armazenar sequências de elementos
do mesmo tipo.
Li�ta�
Sequências de elementos que podem
ocupar posições não contíguas na
memória.
Pil�a�
Estrutura LIFO (Last-In-First-Out)
onde o último elemento inserido é o
primeiro a sair.
Fila�
Estrutura FIFO (First-In-First-Out)
onde o primeiro elemento inserido é o
primeiro a sair.
Árvore�
Estruturas hierárquicas com
elementos organizados em forma de
árvore.
Grafo�
Estruturas que estabelecem
relações entre elementos,
conectados por arestas.
Tipo� Bá�ico� de Dado�
I�teiro
Representa valores numéricos negativos ou positivos
sem casa decimal (int, short, long)
Real
Representa valores numéricos com casa decimal,
também chamados de ponto flutuante (float, double)
Lógico
Representa valores booleanos, assumindo apenas dois
estados: verdadeiro ou falso (0 ou 1)
Texto
Representa sequências de caracteres, podendo ser uma
única letra (char) ou uma string (char[])
E�trutura� Ho�ogê�ea� v�. Heterogê�ea�
E�trutura� Ho�ogê�ea�
Conjunto de dados formados pelo mesmo tipo de dado.
Vetores (arrays unidimensionais)
Matrizes (arrays multidimensionais)
Acesso por índices
Elementos armazenados em posições contíguas de
memória
E�trutura� Heterogê�ea�
Conjunto de dados formados por tipos de dados diferentes.
Registros (structs em C)
Cada campo pode ser de um tipo diferente
Acesso por nome de campo
Armazenamento em bloco contíguo de memória
Regi�tro� (E�trutura� Heterogê�ea�)
Um registro pode ser composto de vários campos de tipos
diferentes, cada um com seu identificador próprio.
Exemplo de estrutura de registro para funcionários:
Campo Tipo
Matrícula Inteiro
Nome Cadeia de Caracteres
Data de Nascimento Data
Cargo Cadeia de Caracteres
Salário Real
var Ficha_Funcionario: registro
inicio
matricula: inteiro
nome: vetor[1..50] de caractere
Dt_Nascimento: vetor[1..9] de caractere
Cargo: vetor[1..30] de caractere
Salario: real
fim
varReg.campo
// Exemplos:
leia(Ficha_Funcionario.matricula)
escreva(Ficha_Funcionario.nome)
Ficha_Funcionario.cargo rua);
Ace��a�do Me�bro�
Dois operadores são usados para acessar membros de
structs:
Operador de ponto (.) - Para acesso direto aos
membros
Operador de seta (->) - Para acesso via ponteiro
// Atribuição
aluno.codigo = 10;
strcpy(aluno.nome, "Manoel");
aluno.nota = 10.0;
// Impressão
printf("\n%d", aluno.codigo);
printf("\n%s", aluno.nome);
printf("\n%.2f", aluno.nota);
Atribuição e I�pre��ão
A manipulação de structs pode ser facilitada através da
criação de funções específicas para cadastro, impressão e
outras operações.
Exe�plo: Struct para Dado� de Alu�o
/* Cria uma estrutura para armazenar dados de um aluno*/
#include
#include
struct aluno {
int v_nmat; //número da matrícula
float v_nota[3]; //notas
float v_media; //media
};
int main() {
struct aluno Felipe; //declara uma variável do tipo struct
Felipe.v_nmat = 120;
Felipe.v_nota[0] = 8.5;
Felipe.v_nota[1] = 7.2;
Felipe.v_nota[2] = 5.4;
Felipe.v_media = (Felipe.v_nota[0] + Felipe.v_nota[1] + Felipe.v_nota[2])/3.0;
printf("Matricula: %d\n", Felipe.v_nmat);
printf("Media: %.2f\n", Felipe.v_media);
system("pause");
return(0);
}
Exe�plo:Fic�a de Alu�o
/* Ficha de Aluno */
#include
#include
int main(void) {
/*Criando a struct */
struct ficha_de_aluno {
char nome[50];
char disciplina[30];
float nota_prova1;
float nota_prova2;
};
/*Criando a variável aluno que será do tipo struct ficha_de_aluno */
struct ficha_de_aluno aluno;
printf("\n---------- Cadastro de aluno -----------\n\n\n");
printf("Nome do aluno ......: ");
fflush(stdin);
fgets(aluno.nome, 40, stdin);
printf("Disciplina ......: ");
fflush(stdin);
fgets(aluno.disciplina, 40, stdin);
printf("Informe a 1a. nota ..: ");
scanf("%f", &aluno.nota_prova1);
printf("Informe a 2a. nota ..: ");
scanf("%f", &aluno.nota_prova2);
printf("\n\n --------- Lendo os dados da struct ---------\n\n");
printf("Nome ...........: %s", aluno.nome);
printf("Disciplina .....: %s", aluno.disciplina);
printf("Nota da Prova 1 ...: %.2f\n", aluno.nota_prova1);
printf("Nota da Prova 2 ...: %.2f\n", aluno.nota_prova2);
getch();
return(0);
}
Struct� A�i��ada�
Uma struct aninhada é uma estrutura dentro de outra,
permitindo a criação de estruturas de dados mais
complexas e hierárquicas.
Defi�ição
O padrão ANSI C especifica que as estruturas podem ser
aninhadas até 15 níveis, embora a maioria dos compiladores
permita mais.
As structs aninhadas facilitam a modelagem de
relacionamentos complexos, como funcionários
pertencentes a departamentos.
For�a� de Declarar Struct� A�i��ada�
struct funcionario {
int cod;
char nome[30];
float salario;
struct departamento {
int cod;
char descricao[30];
} depto;
struct cargo cargo;
};
For�a 1: E�trutura De�tro de Outra
struct departamento {
int cod;
char descricao[30];
};
struct cargo {
int cod;
char descricao[30];
};
struct funcionario {
int cod;
char nome[30];
float salario;
struct departamento depto;
struct cargo cargo;
};
For�a 2: E�trutura� Separada�
U�a�do Typedef co� Struct�
#include
#include
typedef struct departamento {
int cod;
char descricao[30];
} Departamento;
typedef struct cargo {
int cod;
char descricao[30];
} Cargo;
typedef struct funcionario {
int cod;
char nome[30];
float salario;
Departamento depto;
Cargo cargo;
} Funcionario;
int main(void) {
// Código para manipular a estrutura
}
O comando typedef permite criar um nome alternativo para um tipo de dado, simplificando a declaração de variáveis.
Ma�ipula�do Struct� A�i��ada�
#define LEN 50
struct endereco {
char rua[LEN];
char cidade_estado_cep[LEN];
};
struct student {
char id[10];
int idade;
struct endereco casa;
struct endereco escola;
};
struct student pessoa;
// Acessando campos da pessoa
pessoa.id
pessoa.idade
// Acessando campos da estrutura aninhada casa
pessoa.casa.rua
pessoa.casa.cidade_estado_cep
// Acessando campos da estrutura aninhada escola
pessoa.escola.rua
pessoa.escola.cidade_estado_cep
Ace��a�do Ca�po� A�i��ado�
Note o uso repetido do operador ponto (.) para acessar
campos dentro de campos aninhados.
Array de Struct�
typedef struct {
char nome[200];
char disciplina[100];
float nota;
} Aluno;
Aluno aluno_nota[10]; // Array de 10 structs Aluno
Um array de structs é uma estrutura de dados que
armazena uma sequência de objetos do mesmo tipo, onde
cada objeto é uma estrutura.
Defi�ição e Declaração
Arrays de structs são utilizados principalmente para criar
listas de registros, como cadastros de alunos, produtos,
funcionários, etc.
I�icializa�do e Ma�ipula�do Array� de Struct�
// Inicializando com valores padrão
for(i = 0; i
#include
struct Aluno {
char nome[50];
int idade;
int matricula;
char curso[30];
};
int main() {
int i;
struct Aluno alunos[3]; // Array de structs para 3 alunos
// Cadastrando dados de alunos
strcpy(alunos[0].nome, "Sergio Silva");
alunos[0].idade = 16;
alunos[0].matricula = 1001;
strcpy(alunos[0].curso, "Matematica");
strcpy(alunos[1].nome, "Julia Pereira");
alunos[1].idade = 17;
alunos[1].matricula = 1002;
strcpy(alunos[1].curso, "Fisica");
strcpy(alunos[2].nome, "Joao Souza");
alunos[2].idade = 18;
alunos[2].matricula = 1003;
strcpy(alunos[2].curso, "Quimica");
// Exibindo dados dos alunos cadastrados
printf("=== Dados dos Alunos Cadastrados ===\n");
for (i = 0; i
#include
#define NUM_PRODUTOS 5
struct Produto {
char nome[50];
int codigo;
int quantidade;
float preco;
};
int main() {
int i;
struct Produto produtos[NUM_PRODUTOS];
// Preenchendo os dados dos produtos
strcpy(produtos[0].nome, "Camiseta");
produtos[0].codigo = 101;
produtos[0].quantidade = 50;
produtos[0].preco = 29.99;
strcpy(produtos[1].nome, "Calca Jeans");
produtos[1].codigo = 102;
produtos[1].quantidade = 30;
produtos[1].preco = 79.99;
strcpy(produtos[2].nome, "Tenis Esportivo");
produtos[2].codigo = 103;
produtos[2].quantidade = 20;
produtos[2].preco = 199.99;
strcpy(produtos[3].nome, "Bolsa de Couro");
produtos[3].codigo = 104;
produtos[3].quantidade = 15;
produtos[3].preco = 149.99;
strcpy(produtos[4].nome, "Oculos de Sol");
produtos[4].codigo = 105;
produtos[4].quantidade = 10;
produtos[4].preco = 89.99;
// Exibindo os dados dos produtos
printf("=== Estoque de Produtos ===\n");
for (i = 0; i