Duvida na criação de uma struct

1. Duvida na criação de uma struct

rubens reino serrone
ruser

(usa Linux Mint)

Enviado em 30/06/2020 - 17:07h

Boa noite à todos. Estou começando a programação ando enfrentando um problema em um programa que estou desenvolvendo para minha IC.

typedef struct
{
double x,y,z;
}vetor;

vetor ***p;


void rede(int nx, int ny, int nz, int c)
{
int i,j,k=0;
double norma=0;

if(c==1)
{
double r=1.0*(1000-rand()%2000)/1000;



for(i=0; i<nx; i++)
{
for(j=0; j<ny; j++)
{
for(k=0; k<nz; k++)
{
p[i][j][k].x=1.0*r;
p[i][j][k].y=1.0*r;
p[i][j][k].z=1.0*r;
norma=sqrt(pow(p[i][j][k].x,2)+pow(p[i][j][k].y,2)+pow(p[i][j][k].z,2));
p[i][j][k].x=p[i][j][k].x/norma;
p[i][j][k].y=p[i][j][k].y/norma;
p[i][j][k].z=p[i][j][k].z/norma;

printf("%d %d %d %lf %lf %lf %lf \n",i,j,k,p[i][j][k].x,p[i][j][k].y,p[i][j][k].z,sqrt(pow(p[i][j][k].x,2)+pow(p[i][j][k].y,2)+pow(p[i][j][k].z,2)));

}
}
}
}
else if(c==0)
{
for(i=0; i<nx; i++)
{
for(j=0; j<ny; j++)
{
for(k=0; k<nz; k++)
{
p[i][j][k].x=1.0*(1000-rand()%2000)/1000;
p[i][j][k].y=1.0*(1000-rand()%2000)/1000;
p[i][j][k].z=1.0*(1000-rand()%2000)/1000;
norma=sqrt(pow(p[i][j][k].x,2)+pow(p[i][j][k].y,2)+pow(p[i][j][k].z,2));
p[i][j][k].x=p[i][j][k].x/norma;
p[i][j][k].y=p[i][j][k].y/norma;
p[i][j][k].z=p[i][j][k].z/norma;
printf("%d %d %d %lf %lf %lf %lf \n",i,j,k,p[i][j][k].x,p[i][j][k].y,p[i][j][k].z,sqrt(pow(p[i][j][k].x,2)+pow(p[i][j][k].y,2)+pow(p[i][j][k].z,2)));



}
}
}
}
else
{
printf("Nenhuma das opcoes \n");
exit(0);
}

int main(int argc, char *argv[])
{
srand(time(NULL));

int c=atof(argv[1]);
int nx=atof(argv[2]);
int ny=nx;
int nz=atof(argv[3]);

//param();
rede(nx,ny,nz,c);

return 0;

}




Eu queria saber manusear os ponteiros corretamente pois meu objetivo é criar uma amostra 3d de moléculas( cada molécula tem a componente x, y e z) no entanto, quando inicializo pelo terminal eu preciso indicar o tamanho da molécula e não consigo fazer dessa forma( utilizando argc argv).
Vocês poderiam me ajudar?


  


2. Re: Duvida na criação de uma struct

Nick Us
Nick-us

(usa Slackware)

Enviado em 02/07/2020 - 00:11h

ruser escreveu:
Eu queria saber manusear os ponteiros corretamente pois meu objetivo é criar uma amostra 3d de moléculas( cada molécula tem a componente x, y e z) no entanto, quando inicializo pelo terminal eu preciso indicar o tamanho da molécula e não consigo fazer dessa forma( utilizando argc argv).
Vocês poderiam me ajudar?

DICA 1: Acho que vc precisa dizer exatamente o que você quer, e o que não sabe! Pq não sei se entendi sua pergunta! E precisa informar se é C ou C++ para evitar confusão! Já que o Fórum é misto!

Se o que vc quer é enviar pelo terminal os parametros para o seu programa, você pode fazer assim:
No Terminal digite seus parametros com espaços qdo for executar o programa:
$ ./Test TamanhoMolecula1 TamanhoMolecula2 TamanhoMolecula3 TamanhoMolecula4 

#include <stdio.h>
int main(int argc, char *argv[]) {
printf("argc = %d\n", argc);

for(int x = 0; x != argc; x++)
printf("argv[%d] = %s\n", x, argv[x]);
}

O Programa acima vai retornar
argc = 5
argv[0] = ./Test
argv[1] = TamanhoMolecula1
argv[2] = TamanhoMolecula2
argv[3] = TamanhoMolecula3
argv[4] = TamanhoMolecula4

COMPILE ASSIM
gcc Test.c -o Test -O3 -Wall -pedantic -pedantic-errors -Werror 

Logo basta modificar da forma como vc deseja capturar! Ou o que vc deseja capturar.

Breve explicação: argc é o Index dos Parâmetros que argv armazena. Vc pode mudar os nomes o tipo de variável para o que vc precisar!



3. Re: Duvida na criação de uma struct

Paulo
paulo1205

(usa Ubuntu)

Enviado em 02/07/2020 - 04:16h

Prezado ruser,

Um problema com seu código é que você declara um objeto do tipo “ponteiro para dados do tipo «ponteiro para dados do tipo ‘ponteiro para dados do tipo vetor’»”, mas em nenhum lugar reservou espaço na memória para que esses ponteiros em múltiplos níveis tenham para onde apontar.

Em algum lugar do seu código você tem de ter algo parecido com o seguinte.
p=malloc(nx*sizeof *p);
for(int x=0; x<nx; ++x){
p[x]=malloc(ny*sizeof *p[x]);
for(int y=0; y<ny; ++y)
p[x][y]=malloc(nz*sizeof p[x][y]);
}


Para liberar essa memória, depois que todo seu uso tiver cessadim você teria de fazer o seguinte.
for(int x=nx; x--;){
for(int y=ny; y--;)
free(p[x][y]);
free(p[x]);
}
free(p);



Se quiser gastar um pouquinho menos de memória, reduzindo também a quantidade total de alocações (de 1+(1+ny)*nx para 1+2*nx), pode fazer do seguinte modo.
// Alocação.
p=malloc(nx*sizeof *p);
for(int x=0; x<nx; ++x){
p[x]=malloc(ny*sizeof *p[x]);
p[x][0]=malloc(ny*nz*sizeof *p[x][0]);
for(int y=1; y<ny; ++y)
p[x][y]=p[x][y-1]+nz;
}

/* ... */

// Desalocação.
for(int x=nx; x--;){
free(p[x][0]);
free(p[x]);
}
free(p);



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


4. Re: Duvida na criação de uma struct

rubens reino serrone
ruser

(usa Linux Mint)

Enviado em 02/07/2020 - 12:58h

paulo1205 escreveu:

Prezado ruser,

Um problema com seu código é que você declara um objeto do tipo “ponteiro para dados do tipo «ponteiro para dados do tipo ‘ponteiro para dados do tipo vetor’»”, mas em nenhum lugar reservou espaço na memória para que esses ponteiros em múltiplos níveis tenham para onde apontar.

Em algum lugar do seu código você tem de ter algo parecido com o seguinte.
p=malloc(nx*sizeof *p);
for(int x=0; x<nx; ++x){
p[x]=malloc(ny*sizeof *p[x]);
for(int y=0; y<ny; ++y)
p[x][y]=malloc(nz*sizeof p[x][y]);
}


Para liberar essa memória, depois que todo seu uso tiver cessadim você teria de fazer o seguinte.
for(int x=nx; x--;){
for(int y=ny; y--;)
free(p[x][y]);
free(p[x]);
}
free(p);



Se quiser gastar um pouquinho menos de memória, reduzindo também a quantidade total de alocações (de 1+(1+ny)*nx para 1+2*nx), pode fazer do seguinte modo.
// Alocação.
p=malloc(nx*sizeof *p);
for(int x=0; x<nx; ++x){
p[x]=malloc(ny*sizeof *p[x]);
p[x][0]=malloc(ny*nz*sizeof *p[x][0]);
for(int y=1; y<ny; ++y)
p[x][y]=p[x][y-1]+nz;
}

/* ... */

// Desalocação.
for(int x=nx; x--;){
free(p[x][0]);
free(p[x]);
}
free(p);



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)






Boa tarde Paulo, primeiramente gostaria de agradecer a todos pela atenção e ajuda, e estou quase resolvendo o meu problema seguindo a sua solução Paulo.
Meu intuito é fazer um struct vetor p[x][y][z] de maneira dinâmica com ponteiro como você mencionou.
No entanto estou enfrentando problemas para alocar a memória visto que sou novo em programação. Devo usar o calloc ou malloc?
Enfrento um erro de segmentação (imagem do núcleo gravada).
Segue o que estou tentando fazer:

void alloc(int lx, int lz)

{ int i,j=0;
int ly=lx;

p=calloc(lx,sizeof(double**));



for(i=0;i<lx;++i)
{

p[i]=calloc(lx,sizeof(double*));

for (j=0;j<lx;++j)
{
p[i][j]=calloc(lx,sizeof(double));



}
}
}


Mas ao colocar valores dentro de uma molécula p[1][1][1] ( esse 1,1,1 é a posição da molécula na rede, e cada molécula vai apresentar as componentes x,y,z) a leitura da coluna em i não está sendo feita. Segue a imagem.
o dado de entrada é : 1 3 3 ( 1 é a opção da rede ser ordenada, 3=lx=ly e 3=lz).

Não sei se fui claro, mas eu queria digitar o tamanho da rede lx lz e criar uma struct p[lx][ly][lz].

OBS: Eu cortei a imagem, logo após da uma falha de segmentação

att

Rubens


5. Re: Duvida na criação de uma struct

rubens reino serrone
ruser

(usa Linux Mint)

Enviado em 02/07/2020 - 17:46h

Já resolvi!
o problema estava no sizeof double em que eu estava colocando calloc, sendo que o p é uma variavel tipo struct então seria assim:


typedef struct
{
double x,y,z;
}vetor;

vetor ***p;

void alloc(int lx, int lz)

{ int i,j=0;
int ly=lx;

p=calloc(lx,sizeof(vetor**));

for(i=0;i<lx;i++)
{

p[i]=calloc(lx,sizeof(vetor*));

for (j=0;j<lx;j++)
{
p[i][j]=calloc(lz,sizeof(vetor));



}
}
}



Obrigado a todos!



6. Re: Duvida na criação de uma struct

Paulo
paulo1205

(usa Ubuntu)

Enviado em 02/07/2020 - 20:10h

Uma chamada a calloc() na forma
p=calloc(n_elementos, tamanho_elementos) 
é funcionalmente equivalente ao seguinte:
p=malloc(n_elementos*tamanho_elementos);
memset(p, 0, n_elementos*tamanho_elementos);

A vantagem disso é que você sabe que todos os elementos terão um valor conhecido (zero), em vez de valores aleatórios (ou remanescentes de uso anterior daquela memória). Por outro lado, se você sabe que vai sobrescrever todos os elementos após a alocação, o tempo gasto com o preenchimento dos zeros, que parece ser o caso do seu programa, pode ser poupado se você usar malloc().

Com relação ao erro que você cometeu, eis uma razão pela qual eu recomendo que não se usem nomes de tipos na hora de chamar funções de alocação, mas que se faça o compilador inferir o tamanho a partir do tipo do próprio ponteiro que vai receber a alocação.

Compare:
// Usando nomes de tipos.
struct teste { /* ... */ };

struct teste ***cubo_teste;

cubo_teste=malloc(comprimento*sizeof(struct teste **));
for(int x=0; x<comprimento; ++x){
cubo_teste[x]=malloc(largura*sizeof(struct teste *));
for(int y=0; y<largura; ++y)
cubo_teste[x][y]=malloc(altura*sizeof(struct teste));
}

// Fazendo o compilador usar o tipo correto.
struct teste { /* ... */ };

struct teste ***cubo_teste;

cubo_teste=malloc(comprimento*sizeof *cubo_teste);
for(int x=0; x<comprimento; ++x){
cubo_teste[x]=malloc(largura*sizeof *cubo_teste[x]);
for(int y=0; y<largura; ++y)
cubo_teste[x][y]=malloc(altura*sizeof *cubo_teste[x][y]);
}


No primeiro código, eu tive de repetir o nome do tipo em cada operação de alocação. Além disso eu tive de tomar cuidado com a quantidade de asteriscos em cada uma das alocações. Se eu decidir que o cubo não vai mais conter elementos do tipo struct teste, mas sim doubles ou ints ou do tipo struct vetor, eu terei de alterar o nome do tipo na declaração e em cada uma das operações de alocação. Semelhantemente, se eu decidir que cada elemento vai guardar um ponteiro para o dado, em lugar de guardar diretamente os próprios dados, eu terei de ajustar a quantidade de asteriscos na declaração e em cada alocação que aparecer no código. Se eu esquecer de corrigir qualquer uma dessas operações, o programa estará semanticamente errado, mas o compilador não vai avisar do erro porque só consegue analisar a sintaxe.

Fazendo do jeito que eu advogo, acho que a vida fica mais simples: o que aparece do lado esquerdo da atribuição também aparece, precedido de um asterisco, como operando de sizeof na hora de expressar o tamanho de cada elemento. Com isso, eu não preciso meu preocupar com contar asteriscos corretamente, nem com a necessidade de corrigir cada uma das operações de alocação, caso eu decida trocar o tipo dos elementos do cubo.

O exemplo foi com malloc(), mas pode ser usado também com calloc() e realloc().

O único caso em que isso não serve é se o tipo do destino da atribuição for void *, porque não faz sequer sentido tentar obter o conteúdo de um ponteiro para um dado cujo tipo é desconhecido. Nesse caso, pode ser necessário usar o nome de um outro tipo, se tal tipo for fixo e não estiver amarrado a nenhum dado preexistente.

Por outro lado, mesmo quando o ponteiro destino tem o tipo void *, se houver um dado de referência, pode ser conveniente deixar o compilador ter o trabalho de inferir tipo e tamanho a partir dessa referência, pelos mesmos motivos expostos acima. Um exemplo patente é o uso canônico de realocação, mostrado abaixo.
struct teste *p_dados;
size_t n_dados;

/* ... */

size_t novo_tamanho=recalcula_tamanho_necessario(p_dados, n_dados);
if(n_dados!=novo_tamanho){
// Realocação de p_dados usando a forma "canônica":
// - ponteiro intermediário diferente do ponteiro original (para preservar o valor do ponteiro caso não consiga alocar outra região de memória),
// - tipo do ponteiro intermediário "void *" (desacoplado do tipo do ponteiro original, para diminiur esforço de manutenção, caso o tipo do ponteiro original mude),
// - cálculo do novo tamanho usa o tipo do apontado pelo ponteiro original, inferido pelo compilador a partir da declaração do ponteiro, sem precisar repetir explicitamente.
void *novo_p_dados=realloc(p_dados, novo_tamanho*sizeof *p_dados);
if(novo_p_dados){
n_dados=novo_tamanho;
p_dados=novo_p_dados;
}
else{
printf(stderr, "AVISO: Não foi possível alterar nº de elementos (causa do erro: %s).\nProsseguindo com tamanho anterior. Pressione <ENTER> para continuar.\n", strerror(errno));
int n;
while((n=getchar())!=EOF && n!='\n')
;
}
}



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts