Estruturas em C

Started by Dark_Side, 24 de November , 2006, 12:35:49 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Dark_Side

Hi,

Se você já utilizou sockets na linguagem C, provavelmente, já viu algo parecido com a seguinte declaração:

struct sockaddr_in addr;

E deve ter visto, ainda, algo similar a:

addr.sin_family, addr.sin_port, addr.sin_addr.

O que temos acima é uma variável denominada "addr" que pertence à estrutura "sockaddr_in". Neste caso, "sin_family", "sin_port" e "sin_addr" são membros desta estrutura. 
O que iremos abordar neste artigo, são estruturas em C, desde como criá-las até utilizá-las.

Utilizando estruturas, podemos reunir diversas variáveis em uma outra variável comum.

Geralmente, para se criar um estrutura em C, utilizamos a instrução "struct". A sintaxe seria:

struct NOME_DA_ESTRUTURA{
    variáveis da estrutura;
     }<VARIÁVEIS OPCIONAIS>;

Vejamos um exemplo:

struct st1{
 int x;
 int y;
    }coord;

Acima, nós criamos uma estrutura chamada "st1" que contém os seguintes membros: x e y, respectivamente, ambos do tipo INTEIRO. Na criação da estrutura, já declaramos uma variável que a representa: "coord".

Como podemos acessar os membros desta estrutura? Veja:
coord.x = 10;
coord.y = 20;

Agora, os valores de x e y da estrutura coord são, respectivamente, 10 e 20.
Para acessarmos membros de estruturas, utilizamos "." (ponto) após o nome da variável que possui o tipo da estrutura, e em seguida, o nome do membro.

Vejamos agora um exemplo onde não declaramos nenhuma variável opcional.

struct st1{
 int x;
 int y;
    };

Trata-se da mesma estrutura, porém, não temos a variável "coord" previamente declarada. Como podemos declarar uma nova variável da estrutura "st1" ? Veja:

struct st1 coord;
coord.x = 10;
coord.y = 20;

Desta vez, declaramos a variável "coord" após declarar a estrutura "st1", e em seguida, atribuímos valores aos seus membros. Portanto, para se declarar uma variável pertencente a uma estrutura, fazemos:

struct NOME_DA_ESTRUTURA nome_da_variável;
Vamos ver um exemplo um pouco mais complexo:
#include <stdio.h>

struct valores{
char caractere;
int num_inteiro;
float num_float;
double num_double;
};

int main()
{
struct valores exemplo;

exemplo.caractere = 'A';
exemplo.num_inteiro = 10;
exemplo.num_float = 20.5;
exemplo.num_double = 123.123;

printf("Caractere: %c\nInteiro: %d\nFloat: %f\nDouble:%lf",exemplo.caractere,exemplo.num_inteiro,exemplo.num_float,exemplo.num_double);

return 0;
}


Vamos analisar por partes:

struct valores{
char caractere;
int num_inteiro;
float num_float;
double num_double;
};

Declaramos uma estrutura cujo nome é "valores" e contém os membros: caractere, num_inteiro, num_float e num_double.
Note que não há declaração de variáveis opcionais.

struct valores exemplo;
Declaramos a variável "exemplo" que pertence à estrutura "valores".

exemplo.caractere = 'A';
exemplo.num_inteiro = 10;
exemplo.num_float = 20.5;
exemplo.num_double = 123.123;

Atribuímos a cada membro, um determinado valor.

printf("Caractere: %c\nInteiro: %d\nFloat: %f\nDouble: %lf",exemplo.caractere,exemplo.num_inteiro,exemplo.num_float,exemplo.num_double);

Mostramos os valores atribuídos a cada membro.

Vamos observar atentamente a seguinte estrutura:

struct dados{

char nome[30];
char sobrenome[50];
}eu;


Nota-se que declaramos uma estrutura chamada "dados" e contém dois membros: nome e sobrenome. Associamos a variável "eu" à estrutura já declarada.

Preste atenção quanto ao tipo de dado dos membros - uma string. Como você iria atribuir valores a eles?

eu.nome = "Meu Nome";
eu.sobrenome = "Meu Sobrenome";

Você acha que o método acima está correto? Bem, já adianto que não. Não podemos atribuir valores diretamente a strings em C, exceto em sua inicialização. Como faríamos então? Podemos utilizar funções auxiliares, como a função "strncpy()" por exemplo.

Veja:

strncpy(eu.nome,"Meu Nome",30);
strncpy(eu.sobrenome,"Meu Sobrenome",50);

Acima temos o método correto.

Pode-se ainda, declarar estruturas dentro de outras. Veja o exemplo:

struct st1{
int par,impar;
};

struct st2{
char letra1,letra2,letra3;
};

struct valores{
struct st1 numeros;
struct st2 letras;
};

Um pouco confuso não? Vamos simplificar:

struct st1{
int par,impar;
};

Declaramos uma estrutura chamada "st1" com dois membros do tipo inteiro: par e impar.

struct st2{
char letra1,letra2,letra3;
};

Declaramos uma estrutura chamada "st2" com três membros do tipo char: letra1, letra2 e letra3.

struct valores{
struct st1 numeros;
struct st2 letras;
};

Declaramos uma estrutura chamada "valores" com dois membros que também são estruturas: "numeros" que pertence à estrutura "st1" e "letras" que pertence à estrutura "st2".


Para acessarmos os membros da estrutura "valores", faríamos:

valores.numeros
valores.letras

Nota-se, no entanto, que "numeros" e "letras" também são estruturas. Então, para acessar os membros de cada uma delas, fazemos:

valores.numeros.par = 2;
valores.numeros.impar = 3;
valores.letras.letra1 = 'A';
valores.letras.letra2 = 'B';
valores.letras.letra3 = 'C';

Vejamos um caso especial:

struct numeros{
int a,b,c,d;
};

struct numeros num1,num2;

No caso acima, a estrutura "numeros" possui 4 membros do tipo inteiro. Declaramos duas variáveis pertencentes a ela: "num1" e "num2".

Vamos supor que fizemos a seguinte atribuição:

num1.a = 10;
num1.b = 20;
num1.c = 30;
num1.d = 40;

Agora imaginemos uma situação em que os valores dos membros de "num2" devem ser os mesmos de "num1", ou seja, os valores dos membros de cada estrutura devem ser iguais. Uma maneira seria:

num2.a = num1.a;
num2.b = num1.b;
num2.c = num1.c;
num2.d = num1.d;

Existe, porém, uma maneira mais fácil de fazê-lo, veja:

num2 = num1;
Lolz, só isso? Exatamente. Quando temos duas variáveis que representam a mesma estrutura, para tornar seus valores (dos membros) iguais, basta igualar uma variável a outra. Ao fazer esta operação, os valores de cada membro são copiados para os membros da outra estrutura. Após este processo, as estruturas continuam independentes, isto é, se você alterar o valor de um membro em uma estrutura, este mesmo membro, em outra estrutura, continua com o valor inalterado. Veja:

num1.a = 10;
num1.b = 20;
num1.c = 30;
num1.d = 40;

num2 = num1; // num2.a = 10, num2.b = 20, num2.c = 30 e num2.d = 40;

num1.a = 100; // Apenas o valor de "a" na estrutura "num1" será alterado; em "num2", o membro "a" continua valendo 10.

Pode parecer um pouco óbvia a explicação acima, mas existe a possibilidade de que se você alterar o valor de um membro em uma estrutura, o valor deste mesmo membro, em outra estrutura, será alterado também - quando este tal membro for um ponteiro.

Vamos ver um exemplo:

int num = 10;

struct st1{

 int * p;
};


struct st1 ex1,ex2;

ex1.p = #

ex2 = ex1;

Neste exemplo, o membro da estrutura "st1" é um ponteiro para inteiro.

Quando temos:

ex1.p = #
Estamos fazendo com que o membro "p" dentro da estrutura "ex1" aponte para a variável "num" declarada anteriormente.

Agora, veja:

ex2 = ex1;
Nesta situação, copiamos o valor do membro "p" dentro de "ex1" para o membro "p" de "ex2". Mas qual é o valor de "p"? O endereço da variável "num", ou seja, os membros irão apontar para o mesmo endereço de memória. Isso significa que, se fizermos:

num = 200;
Teremos modificações em ambos membros: "ex1.p" e "ex2.p".

Para comprovar, veja:

#include <stdio.h>

int num = 10;

struct st1{

 int * p;
};

int main()
{
struct st1 ex1,ex2;
ex1.p = #
ex2 = ex1;

printf("ex1.p = %d\nex2.p = %d\n",*ex1.p,*ex2.p); // Note que mostramos o valor da variável apontada e não o endereço de memória para onde o ponteiro aponta.

num = 200; // Mudando o valor da variável apontada pelos ponteiros

printf("\nex1.p = %d\nex2.p = %d\n",*ex1.p,*ex2.p); // Mostramos novamente os valores

return 0;
}

Assim como qualquer outro tipo de variável, podemos ter um array de estruturas. Exemplo:

struct st1
{
int x,y;
};

struct st1 valores[3];

Acima, declaramos um array contendo 3 elementos do tipo "st1" (estrutura). Como o primeiro elemento do array é identificado por ZERO, teremos os seguintes índices: 0, 1 e 2. Vejamos:

valores[0].x = 10;
valores[0].y = 15;

valores[1].x = 60;
valores[1].y = 90;

valores[2].x = 160;
valores[2].y = 170;

Bem simples não ;) ?


É possível utilizar estruturas como argumentos em funções, veja:

#include <stdio.h>

struct st1
{
int x,y;
};

void funcao(struct st1 valores) // A função recebe uma variável pertencente à estrutura "st1" como argumento
{
// Mostramos os valores de cada membro
printf("x = %d\n",valores.x);
printf("y = %d",valores.y);
}

int main()
{
struct st1 var; // Declaramos uma estrutura

// Atribuímos valores ao membros
var.x = 10;
var.y = 20;
funcao(var); // Passamos a estrutura como argumento
return 0;
}

É importante notar que, os valores "x" e "y" da estrutura declarada em "var", serão copiados para a estrutura local "valores" dentro da função.


Para finalizar, veremos como utilizar ponteiros para estruturas.

Exemplo 1:

struct st1
{
int x,y;
};


struct st1 valores;
struct st1 * p = &valores;


No trecho acima, declaramos duas variáveis da estrutra "st1". A última, é um ponteiro para a estrutura. Quando temos:

struct st1 * p = &valores;
Estamos fazendo com que o ponteiro "p" aponte para a estrutura declarada em "valores". A partir daí, para acessarmos os membros de "valores", podemos optar por duas maneiras:

Primeiro método:

(*p).x = 10;
(*p).y = 20;

Neste método, fazemos:

(*NOME_DO_PONTEIRO).membro;


O segundo método é o mais utilizado. É feito utilizando o operador seta "->". Veja:

p->y = 10;
p->x = 20;

No método acima, fazemos:

NOME_PONTEIRO->membro;

Quando se tem (*p).x = 10 ou p->x = 10, estamos fazendo com que o membro "x" da estrutura apontada por "p" tenha o valor igual a 10. O mesmo ocorre com o membro "y" que terá o seu valor igual a 20.

Para verificarmos, veja o exemplo:

#include <stdio.h>

struct st1
{
int x,y;
};

int main()
{
struct st1 valores;
struct st1 * p = &valores;

// Modificamos os valores dos membros "x" e "y" dentro da estrutura "valores" através dos ponteiros
(*p).x = 10;
(*p).y = 20;

printf("valores.x = %d\nvalores.y = %d\n\n",valores.x,valores.y); // Mostramos os valores

// Modificamos novamente os valores dos membros
p->x = 100;
p->y = 200;

printf("valores.x = %d\nvalores.y = %d",valores.x,valores.y); // Exibimos o resultado


return 0;
}


Lolz, é isso.
Bye.

l u b c k e

Parabéns,

Conseguistes explicar muto bem estruturas, vale diser que elas são muito utilizadas. Existem aplicações específicas que a melhor forma de resolver é através de estruturas.


Até mais...

Contato]

TGA

TGA

Parabéns cara, ótima explicação, seus tutos são muito bons.. vlw. abraços..
"A IMAGINAÇÃO É MAIS IMPORTANTE QUE O CONHECIMENTO"
__________________________________________________________

Ðark$pawn

Very Good... Ponto Positivo!!! ;)

branco

se eu parar de estudar daqui uns anos se ja me pega =] aeheahaeh zuando, valew ae pelo tuto deve ta otimo :P pena que nao e de vb xd

=*

até mais
Olha o trem... Quem vai ficar, quem vai partir? Quem vai chorar, quem vai sorrir?

insanity

Ao contrario de você eu agradaço de ser em C ... lol

Realmente os tutoriais do Dark_Side é melhor que de muitos livros ;)

É isso aí continue assim ;)