Jump to content
hornet900

realloc

Recommended Posts

hornet900

  Boa tarde. Estou a tentar fazer um exercício de programação e tenho aqui uma duvida. Eu pretendo fazer um vetor de estruturas, em que cada vez que o utilizador pretender introduzir mais um elemento, o tamanho deste vetor aumenta uma unidade. Estou a fazer isto com a função "realloc", e aqui começam o problemas. Antes de mais pergunto se é possível usar a função "realloc", sem antes usar a função "malloc" ou "calloc". Depois não estou a conseguir incrementar o valor do tamanho do vetor, porque estou a fazer algo mal. De referir que eu tenho que fazer este incremento numa função. Deixo aqui o código que tenho.

#include <stdio.h>
#include <stdlib.h>
#include <alloc.h>

struct transistor{
   int ano_fabrico, ganho;
   char fabricante[50], referencia[50];
};

void dados_transistor(struct transistor *,int );
void ler_transistor(struct transistor *,int );

int main(){

struct transistor *tr=NULL;
char opcao;

do{
dados_transistor(tr);
printf("Pretende inserir mais transistores?");
fflush(stdin);
scanf("%c",&opcao);
}while(opcao=='s');
ler_transistor(tr,n);
free(tr);

    return 0;
}

void dados_transistor(struct transistor *tr){
   tr=(struct transistor *) realloc (n,sizeof(tr));
   printf("\nInsira o fabricante do transistor %d:",n+1);
   gets((*(tr+n)).fabricante);
   printf("\nInsira a referencia do transistor %d:",n+1);
   gets((*(tr+n)).referencia);
   printf("\nInsira o ano de fabrico do transistor %d:",n+1);
   scanf("%d",&(*(tr+n)).ano_fabrico);
   printf("\nInsira o ganho do transistor %d:",n+1);
   scanf("%d",&(*(tr+n)).ganho);
   fflush(stdin);
}

void ler_transistor(struct transistor *tr, int n){
int i;
printf("\n\nTransistor        Fabricante       Referencia      Ano de fabrico    Ganho");
for(i=0;i<n;i++)
printf("\n\n%d                 %s               %s             %d                %d",i+1,(*(tr+i)).fabricante,(*(tr+i)).referencia,(*(tr+i)).ano_fabrico,(*(tr+i)).ganho);

}

Share this post


Link to post
Share on other sites
KTachyon
In case that ptr is NULL, the function behaves exactly as malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.

Portanto, a resposta é sim, podes utilizar o realloc antes de fazeres malloc (ou derivadas).

tr=(struct transistor *) realloc (n,sizeof(tr));

Em primeiro lugar, estás a alocar sizeof(tr), quando devias estar a alocar memória para um ponteiro para um struct transistor.

Em segundo lugar, só estás a alocar espaço para os ponteiros, ou seja, tens que alocar memória para cada uma das structs apontadas pelos ponteiros.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
pmg

Da funcao main tens que passar o endereco do apontador e nao, como estas a fazer, o seu valor.

do{
dados_transistor(&tr);

E claro que isto obriga a mudares a funcao dados_transistor(), mas e uma mudanca facil.

-------------------------

Ve la se consegues deixar de usar o fflush(stdin) (1) e o gets() (2).

(1) porque nao esta definido pelo Standard o que acontece quando se faz "flush" a um stream de input (ou a um stream de input/output onde a ultima operacao tenha sido de input). As bibliotecas do Windows definem o que acontece, mas se alguma vez quiseres compilar o teu codigo noutro Sistema Operativo, introduziste um erro que era facil de evitar a nascenca.

(2) gets e impossivel de usar com seguranca. Prefere fgets() e, se necessario, remove o ENTER final.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
hornet900

  Já tentei de varias maneiras e não consegui. Acho que o melhor é parar um pouco com isto e recomeçar mais tarde, estou a ficar vidrado. Obrigado pela ajuda de ambos.

Bem hajam

Share this post


Link to post
Share on other sites
KTachyon

O realloc leva dois argumentos:

1. o ponteiro para a memória que queres realocar

2. o espaço total da memória que queres que passe a ocupar

No teu código tens:

tr=(struct transistor *) realloc (n,sizeof(tr));

O 'n' não parece existir em lado nenhum, e o que deves querer lá colocar é mesmo o tr:

tr = (struct transistor *) realloc (tr, sizeof(struct transistor));

O teu 'n', quando o tiveres, será calculado em conjunto com o sizeof:

tr = (struct transistor *) realloc (tr, n*sizeof(struct transistor));

E, depois, relativamente ao que o pmg disse, se enviares simplesmente o ponteiro, o valor deste só vai ser alterado no scope da função. Para que consigas trabalhar com o ponteiro, uma das soluções é:

void dados_transistor(struct transistor **tr){
   *tr = (struct transistor *) realloc(*tr, sizeof(struct transistor));
    // etc...

Chamando a função como o pmg indicou.

A outra solução é retornares o ponteiro no final da função:

struct transistor* dados_transistor(struct transistor *tr){
   tr = (struct transistor *) realloc(tr, sizeof(struct transistor));
   // etc...
   return tr;
}


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
hornet900

  Consegui fazer o código sem dar erros de compilação, mas quando o executo vai abaixo. Eu penso que é por não estar a aceder bem aos campos da estrutura. Aqui vai:

#include <stdio.h>
#include <stdlib.h>

struct transistor{
   int ano_fabrico, ganho;
   char fabricante[50], referencia[50];
};

void dados_transistor(struct transistor **, int);
void ler_transistor(struct transistor *, int );

int main(){

struct transistor *tr;
char opcao;
int n=1;

do{
dados_transistor(&tr, n);
n++;
printf("Pretende inserir mais transistores?");
fflush(stdin);
scanf("%c",&opcao);
}while(opcao=='s');
ler_transistor(tr,n);
free(tr);
    return 0;
}

void dados_transistor(struct transistor **tr, int n){
   *tr=(struct transistor *) realloc (*tr,n*sizeof(struct transistor));
   printf("\nInsira o fabricante do transistor %d:",n);
   gets((*tr[n]).fabricante);
   printf("\nInsira a referencia do transistor %d:",n);
   gets((*tr[n]).referencia);
   printf("\nInsira o ano de fabrico do transistor %d:",n);
   scanf("%d",&(*tr[n]).ano_fabrico);
   printf("\nInsira o ganho do transistor %d:",n);
   scanf("%d",&(*tr[n]).ganho);
   fflush(stdin);

}

void ler_transistor(struct transistor *tr, int n){
int i;
printf("\n\nTransistor        Fabricante       Referencia      Ano de fabrico    Ganho");
for(i=0;i<n;i++)
printf("\n\n%d                 %s               %s             %d                %d",i+1,(*(tr+i)).fabricante,(*(tr+i)).referencia,(*(tr+i)).ano_fabrico,(*(tr+i)).ganho);

}

Share this post


Link to post
Share on other sites
KTachyon

Estás a aceder mal ao ponteiro. Não te esqueças que dentro da função estás a aceder a um ponteiro para um ponteiro.

(*tr)[n]

Se queres facilitar a leitura/percepção do código, deves ir pela segunda abordagem que indiquei, que implica apenas a utilização de um ponteiro simples e que o retorna no final da função. Se reparares, é assim que funções como o realloc() fazem :)


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
hornet900

Ok, mas assim não consigo incrementar o tamanho do vetor.

Como é que incremento o 'n'?

Share this post


Link to post
Share on other sites
KTachyon

Bem... o 'n' estás a incrementar no do while. Uma das coisas que te falta é começares a partir do índice zero (porque estás a começar a partir do índice 1):

void dados_transistor(struct transistor **tr, int n){
   *tr=(struct transistor *) realloc (*tr,(n+1)*sizeof(struct transistor));  // n inicializado a zero no main

Para evitares o lixo no scanf(), coloca um espaço antes do %c:

scanf(" %c",&opcao);

E usa o scanf() em vez dos gets():

scanf(" %s", (*tr)[n].fabricante);
scanf(" %s", (*tr)[n].referencia);


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
hornet900

  Já funciona  :cheesygrin:.

Mas usei a opção de ponteiro para ponteiro, amanhã vou tentar fazer da outra maneira.

Obrigadão. Se te vir por ai pago-te um copo.

:);):P

Share this post


Link to post
Share on other sites
Anusko

Tal como diz o KTachyon, usa fgets. Para simplificares o código e escusares de andar a usar ponteiros duplos, tal como já te disseram mete a função dados_transistor a retornar um ponteiro.

#include<stdlib.h>
#include<stdio.h>

struct transistor{
  int ano_fabrico, ganho;
  char fabricante[50], referencia[50];
};

struct transistor* dados_transistor(struct transistor *, int);
void ler_transistor(struct transistor *, int );

int main(){
  
  struct transistor *tr = NULL;
  char opcao;
  int n=0;
  
  do{
    tr=dados_transistor(tr, n);
    n++;
    printf("Pretende inserir mais transistores?");
    fflush(stdin);
    scanf("%c",&opcao);
  }while(opcao=='s');
  ler_transistor(tr,n);
  free(tr);
  return 0;
}

struct transistor* dados_transistor(struct transistor *tr, int n){
  tr=(struct transistor *) realloc (tr,(n+1)*sizeof(struct transistor));
  printf("\nInsira o fabricante do transistor %d:",n);
  gets(tr[n].fabricante);
  printf("\nInsira a referencia do transistor %d:",n);
  gets(tr[n].referencia);
  printf("\nInsira o ano de fabrico do transistor %d:",n);
  scanf("%d",&(tr[n].ano_fabrico));
  printf("\nInsira o ganho do transistor %d:",n);
  scanf("%d",&(tr[n].ganho));
  fflush(stdin);

  return tr;
}

void ler_transistor(struct transistor *tr, int n){
  int i;
  printf("\n\nTransistor        Fabricante       Referencia      Ano de fabrico    Ganho");
  for(i=0;i<n;i++)
    printf("\n\n%d                 %s               %s             %d                %d",i+1,(*(tr+i)).fabricante,(*(tr+i)).referencia,(*(tr+i)).ano_fabrico,(*(tr+i)).ganho);
  
}

Share this post


Link to post
Share on other sites
hornet900

  Eu compreendo, pela vossas dicas, que algum do código que uso não é o mais correto, mas foi assim que me ensinaram e é assim que tenho que fazer perante o meu prof. Um dia, quando eu precisar de fazer programas para efeitos de trabalho, vou-me preocupar mais em usar o mais correto, mas agora tenho que fazer como me ensinaram. De qualquer maneira obrigado por se esforçarem para que faça as coisas bem.

Abraço

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.