Jump to content
AJBM

Estruturas e apontadores

Recommended Posts

AJBM

Boas!

Eu tenho este codigo.

typedef struct {
int bi;
} Pessoa;
typedef struct {
Pessoa pessoas[10];
int nelementos;
} Pessoas;
int find(Pessoas *pessoas, Pessoa *pessoa) {
int i;
for (i = 0; i < pessoas->nelementos; i++) {
	if (pessoas->pessoas[i].bi == pessoa->bi) {
		return i;
	}
}
return (-1);
}
void removePessoa(Pessoas *pessoas, Pessoa *pessoa) {
int pos = find(&pessoas, &pessoa);

if (pos != (-1)) {

	int i;
	for (i = 0; i < pos; i++) {
		pessoas->pessoas[i] = pessoas->pessoas[i];
	}
	for (i = pos + 1; i < pessoas->nelementos; i++) {
		pessoas->pessoas[i - 1] = pessoas->pessoas[i];
	}
	pessoas->nelementos--;
}
}

int main(int argc, char** argv) {
Pessoas pessoas;
pessoas.nelementos = 0;

Pessoa pessoa;
pessoa.bi = 10;

Pessoa pessoa2;
pessoa2.bi = 20;

Pessoa pessoa3;
pessoa3.bi = 30;

Pessoa pessoa4;
pessoa4.bi = 40;


addPessoa(&pessoas, &pessoa);
addPessoa(&pessoas, &pessoa2);
addPessoa(&pessoas, &pessoa3);
addPessoa(&pessoas, &pessoa4);


listar(&pessoas);

removePessoa(&pessoas, &pessoa3);

printf("\n\n");
listar(&pessoas);
return (EXIT_SUCCESS);
}

A função find por algum motivo não esta a funcionar correctamente e não percebo porque.

Não remove a pessoa que eu passo remove sempre a pessoa2.

Se eu colocar a posição directamente já remove.

Também estou com um problema com o debug eu estou a utilizar o netbeans e quando faço debug aparece um erro GDB has unexpectedly stopped with return -1.073.741.515

Share this post


Link to post
Share on other sites
HappyHippyHippo

vamos lá por pontos :

1 - a tua "interface" das funções não se entram num modelo "interessante".

achas que faz sentido estares a instanciar uma estrutura pessoa para a poderes inserir/procurar/remover da lista ? não

as tuas funções deveriam ter os seguintes protótipos:

#define TAMANHO_NOME 256

typedef struct Pessoa {
 char nome[TAMANHO_NOME];
 int bi;
} Pessoa;

Pessoa * addPessoa(Pessoas * lista, char * nome, int bi);
Pessoa * findPessoa(Pessoas * lista, int bi);
void removePessoa(Pessoas * lista, int bi);

isto facilita a interações com a lista que estás a tentar criar

2 - tirando o problema anterior o problema não se encontra na função find mas na maneira que a estás a chamar:

int find(Pessoas *pessoas,  // tipo de dados do argumento : ponteiro para a lista
        Pessoa *pessoa) {  // tipo de dados do argumento : ponteiro para o elemento com os dados a serem inseridos

 // ...
}

int removePessoa(Pessoas *pessoas,  // tipo de dados do argumento : ponteiro para a lista
                Pessoa *pessoa) {  // tipo de dados do argumento : ponteiro para o elemento com os dados a serem inseridos
 int pos = find(&pessoas,          // que tipo de dados é este ?
                &pessoa);          // que tipo de dados é este ?

3 - o teu código de limpeza da lista não só é desnecessário como tem elementos que não fazem nada:

// isto não faz absolutamente nada
for (i = 0; i < pos; i++) {
 pessoas->pessoas[i] = pessoas->pessoas[i];
}
// isto pode ser simplificado
for (i = pos + 1; i < pessoas->nelementos; i++) {
 pessoas->pessoas[i - 1] = pessoas->pessoas[i];
}

tudo o código apresentado anteriorment pode ser alterado pela linha:

memmove(pessoas->pessoas[pos],                             // destino da cópia
       pessoas->pessoas[pos + 1],                         // elementos a serem movidos
       sizeof(Pessoa) * (pessoas->nelementos - pos - 1)); // quantidade de bytes a serem movidos

4 - nota que nos protótipos que te apresentei não trabalha com o indice, isto porque o ponteiro para o elemento do array já tem em si, a informação necessária sobre o indice do elemento.

olha para o seguinte exemplo:

Pessoas * pessoas;

Pessoa * p = &pessoas->pessoas[0]; // p tem o valor da posição de memória do primeiro elemento do array
        p = &pessoas->pessoas[1]; // p tem o valor da posição de memória do primeiro elemento do array mais o tamanho desse elemento
        p = &pessoas->pessoas[2]; // p tem o valor da posição de memória do primeiro elemento do array mais o tamanho dos dois primeiros elementos



        p = &pessoas->pessoas[0] + sizeof(Pessoa) * 4);  // p aponta para o quinto elemento da lista
int indice = (p - &pessoas->pessoas[0]) / sizeof(Pessoa); // indice terá o valor de 5;



// NOTA :
p = (Pessoa *) pessoas; // p tambem aponta para o primeiro elemento da lista, mas isto é por outras razões que tem haver com o "empacotamento" dos dados em meória

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
HappyHippyHippo

&pessoas- é um apontador para Pessoas.

&pessoa-é um apontador a Pessoa.

errado

vê bem o que estás a fazer/escrever e principalmente olha para as mensagens do teu compilador


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
AJBM

O meu compilador não apresenta warmings nem erros.

Mas penso que ja descobri, se eu fizer isto find(pessoas,pessoa) ja funciona.

Eu na função remover já passo o endereço para pessoa, e no find ao fazer isto &pessoa, estava a passar o endereço do apontador e não o endereço do valor que eu quero.

Ou seja isto &pessoa representa o endereço do apontador para pessoa, e não o endereço de pessoa.

Share this post


Link to post
Share on other sites
pikax

Utiliza a flag -Wall no compilador para te dar todos os warnings.


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
pikax

o compilador nao da' warning nesta linha?

int pos = find(&pessoas, &pessoa);


Por muito mais que que estude só aprendo uma coisa, que ainda tenho muita coisa para aprender.

A beleza de um código está em decompor problemas complexos em pequenos blocos simples.

"learn how to do it manually first, then use the wizzy tool to save time."

"Kill the baby, don't be afraid of starting all over again. Fail soon, learn fast."

Share this post


Link to post
Share on other sites
AJBM

o compilador nao da' warning nesta linha?

Agora da eu antes tinha some warning e não dava, mudei para more warnings e já da.

Como tinha corrigido o find antes de mudar o nível de warnings não mostrava nada.

Share this post


Link to post
Share on other sites
AJBM

Fiz umas alterações ao código.

Aparentemente esta tudo a funcionar.

Obrigado pela ajuda! :thumbsup:

Pessoa * addPessoa(Pessoas *pessoas, Pessoa *pessoa) {
pessoas->pessoas[pessoas->nelementos] = *pessoa;
pessoas->nelementos++;
return &(pessoas->pessoas[pessoas->nelementos-1]);
}
Pessoa * find(Pessoas *pessoas, int bi) {
int i;
for (i = 0; i < pessoas->nelementos; i++) {
 if (pessoas->pessoas[i].bi == bi) {
	 return &(pessoas->pessoas[i]);
 }
}
return NULL;
}
/**
*
*
* @param pessoas
* @param pessoa
*/
int removePessoa(Pessoas *pessoas, int bi) {
Pessoa *pos = find(pessoas, bi);
if (pos != NULL) {
 memmove(pos, pos + 1,sizeof(Pessoa)*(&(pessoas->pessoas[pessoas->nelementos-1])-pos));
 pessoas->nelementos--;
 return 1;
}
return 0;
}
void listar(Pessoas *pessoas) {
int i;
for (i = 0; i < pessoas->nelementos; i++)
 printf("Bi: %d\n", pessoas->pessoas[i].bi);

}

Share this post


Link to post
Share on other sites
HappyHippyHippo

já testaste o código ? é que a mim parece que andas ai com acessos inválidos de memória ...

além de continuares com código que te obriga a instânciar uma estrutura Pessoa para inserir na lista


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
AJBM

testei e não deu problemas.

int main(int argc, char** argv) {
Pessoas pessoas;
pessoas.nelementos = 0;

addPessoa(&pessoas, 10);
addPessoa(&pessoas, 20);
addPessoa(&pessoas, 30);
addPessoa(&pessoas, 40);

listar(&pessoas);
removePessoa(&pessoas, 20);
printf("\n\n");
listar(&pessoas);
addPessoa(&pessoas, 50);
removePessoa(&pessoas, 40);
printf("\n\n");
listar(&pessoas);
addPessoa(&pessoas,40);
printf("\n\n");
listar(&pessoas);

return (EXIT_SUCCESS);
}

Em relação a instanciar Pessoa, para inserir na lista esta errado?

Pessoa * addPessoa(Pessoa *lista,Pessoa *pessoa)

Pessoa * addPessoa(Pessoa *lista,int bi)

Share this post


Link to post
Share on other sites
HappyHippyHippo

faz as contas

memmove(pos,
       pos + 1,
       sizeof(Pessoa) * (&(pessoas->pessoas[pessoas->nelementos-1]) - pos));

//sizeof(Pessoa)                            = tamanho de cada elemento
//&(pessoas->pessoas[pessoas->nelementos-1] = posição de memória do primeiro byte do último elemento 
//pos                                       = posição de memória do primeiro byte do elemento a ser removido

caso exemplo :

remover o penúltimo elemento

a soma total deverá ser igual ao tamanho de 1 elemento >>

sizeof(Address) * 1 (o último elemento)

o teu código:

sizeof(Pessoa) + <posição último elemento> - <posição elemento removido (penúltimo)> =

sizeof(Pessoa) + &(pessoas->pessoas[pessoas->nelementos-1] - &(pessoas->pessoas[pessoas->nelementos-2] =

sizeof(Pessoa) + sizeof(Pessoa) =

sizeof(Pessoa) * 2

caso exemplo :

remover o ante-ante-penúltimo elemento

a soma total deverá ser igual ao tamanho de 3 elementos >>

sizeof(Address) * 3 (os trés último elementos)

o teu código:

sizeof(Pessoa) + <posição último elemento> - <posição elemento removido (penúltimo)> =

sizeof(Pessoa) + &(pessoas->pessoas[pessoas->nelementos-1] - &(pessoas->pessoas[pessoas->nelementos-4] =

sizeof(Pessoa) + sizeof(Pessoa) * 3 =

sizeof(Pessoa) * 4

... como vês ... está errado

não está errado, mas não faz muito sentido em termos de lógica

criar um elemento para criar um elemento

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
AJBM

int removePessoa(Pessoas *pessoas, int bi) {
Pessoa *pos = find(pessoas, bi);
if (pos != NULL) {
	memmove(pos, pos + 1, sizeof (Pessoa)* (&(pessoas->pessoas[pessoas->nelementos - 1]) - pos));
	printf("%d %d %d", pos, &(pessoas->pessoas[pessoas->nelementos - 1]), sizeof (Pessoa)* (&(pessoas->pessoas[pessoas->nelementos - 1]) - pos));
	pessoas->nelementos--;
	return 1;
}
return 0;
}
int main(int argc, char** argv) {
Pessoas pessoas;
pessoas.nelementos = 0;



addPessoa(&pessoas, 10);
addPessoa(&pessoas, 20);
addPessoa(&pessoas, 30);
addPessoa(&pessoas, 40);


listar(&pessoas);


  // removePessoa(&pessoas, 30);
   //removePessoa(&pessoas, 20);
   removePessoa(&pessoas, 10);
}

Penúltimo caso (30)

Output printf: 2272268 2272272 4- corresponde a uma pessoa

Antepenúltimo caso(20):

Output printf: 2272264 2272272 8-- corresponde a 2 pessoa

Primeiro (10)

Output printf: 2272260 2272272 12-- corresponde a 3 pessoa

Edited by AJBM

Share this post


Link to post
Share on other sites
HappyHippyHippo

epá .. mas tu leste o meu post ???

não percebeste onde está o erro ?

vi agora que o erro estava na minha leitura do teu código. estava a ler um '+' onde tinhas um '*', o que invalida a explicação anterior

Edited by HappyHippyHippo

IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
AJBM

ok.

não está errado, mas não faz muito sentido em termos de lógica

criar um elemento para criar um elemento

Se pessoa tivesse por exemplo 10 atributos.

Não fazia sentido muito sentido passar os 10 atributos numa função.

Share this post


Link to post
Share on other sites
HappyHippyHippo

ok.

Se pessoa tivesse por exemplo 10 atributos.

Não fazia sentido muito sentido passar os 10 atributos numa função.

nunca viste a CreateWindowEx ...


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.