Ir ao conteúdo
  • Cadastre-se
Francine Guimarães

C Como utilizar printf para printar ponteiros

Posts recomendados

Gente, tô tendo um problema com a função showAll(). Quando vou printar o vetor, aparece só o endereço de memória, não o conteúdo dele em si. Acho que provavelmente tô usando de forma errada os ponteiros, mas não sei como consertar.
Outro problema que encontrei é que, se eu não declarar as variáveis ali no começo(dentro do struct contact) como sendo vetores, da um erro na hr da execução: “Falha de segmentação. Imagem de núcleo gravada”
Código inteiro:

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

int gsize = 1; //Capacidade de armazenamento da agenda.
int gn = 0; //Número de contatos existentes na agenda.

struct contact
{
	char name[100];
	char street[100];
	char ngbhood[100];
	char city[100];
	char state[100];
	int bday[15];
	int cellnumber[20];
	int number[10];
	int CEP[20];
};

void newContact(struct contact *schedule)
{
	
	schedule = (struct contact *)malloc(sizeof(struct contact)*gsize);
	
	if (gn == gsize) //aumenta a capacidade de armazenamento, caso necessário.
	{
		gsize *= 2;
		schedule = realloc(schedule, sizeof(struct contact)*gsize);
	}
	printf("Nome: ");
	scanf("%s", schedule[gn].name);
	printf("Data de nascimento [ddmmaaaa]: ");
	scanf("%d", schedule[gn].bday);
	printf("Telefone: ");
	scanf("%d", schedule[gn].cellnumber);
	printf("Rua: ");
	scanf("%s", schedule[gn].street);
	printf("Nº: ");
	scanf("%d", schedule[gn].number);
	printf("Bairro: ");
	scanf("%s", schedule[gn].ngbhood);
	printf("CEP: ");
	scanf("%d", schedule[gn].CEP);
	printf("Cidade: ");
	scanf("%s", schedule[gn].city);
	printf("Estado: ");
	scanf("%s", schedule[gn].state);
	printf("==================================");
	printf("\nContato adicionado");
	printf("\n==================================");	
	gn++;
}

void showAll(struct contact *schedule)
{
	if (gn == 0)
		printf("\nNão há nada para exibir aqui.");
	else 
	{
		printf("\n-----------------------------------------");
			printf("\n\t\tVisualizando agenda");
			printf("\n-----------------------------------------");
		for (int i = 0; i < gn; i++)
		{
			printf("\nNome: %s\tData de nasciemnto: %d\tTelefone: %d", schedule[i].name, *schedule[i].bday, *schedule[i].cellnumber);
		}
	}
}


void main()
{
	struct contact schedule;
	int op;
	_Bool truth = 1;
	while (truth)
	{
		printf("\n-----------------------------------------");
		printf("\n\t\tAGENDA");
		printf("\n-----------------------------------------");
		printf("\n[1]Cadastrar novo contato");
		printf("\n[2]Ver contatos");
		printf("\n[3]Pesquisar contatos por nome");
		printf("\n\[4]Alterar informações de contato");
		printf("\n[0]Sair");
		printf("\n-----------------------------------------");
		printf("\nSua resposta: _");
		scanf("%d", &op);
		printf("-------------------\n");
		
		switch (op)
		{
			case 1:
				newContact(&schedule);
				break;
			case 2:
				showAll(&schedule);
				break;
			case 0:
				truth = 0;
				break;
			default:
				printf("Opção inválida.");
				break;
		}
	}
	
}

 

  • Amei 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
58 minutos atrás, Francine Guimarães disse:

Gente, tô tendo um problema com a função showAll().

O programa praticamente todo está errado.

1 hora atrás, Francine Guimarães disse:

Quando vou printar o vetor, aparece só o endereço de memória,

Isso que você está vendo e o lixo que tem na memoria.

1 hora atrás, Francine Guimarães disse:

Acho que provavelmente tô usando de forma errada os ponteiros, mas não sei como consertar.

Aqui dois exemplos simples de como usar

Spoiler

Sem uso de funções


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

/* Constantes */
#define MAX_VET 10

/* Dobra o tamanho do vetor */
void DobraTamanho(int **v, int tam);

int main(void)
{
  /* Reserva memoria */
  int d,*vet=malloc(sizeof(int)*MAX_VET);
  if(!vet)      /* ERRO */
    return(-1);
  /* Preenche o vetor com os primeiros 10 numeros */
  for(d=0; d<MAX_VET; d++)
    vet[d]=d;
  /* Muda para uma posição maior da memoria */ 
  vet=realloc(vet,(sizeof(int)*MAX_VET)*2); 
  /* DobraTamanho(&vet,MAX_VET); */
  if(!vet)    /* ERRO */
    return(-1);
  /* Enche o resto da memoria reservada */
  for(d=9; d<MAX_VET*2; d++)
    vet[d]=d;
  /* Mostra todo o vetor */
  for(d=0; d<MAX_VET*2; d++)
    printf("\n%i",vet[d]);
  free(vet);    /* Apaga da memoria */
  return(0);
}

void DobraTamanho(int **v, int tam)
{
  int d;
  (*v)=realloc((*v),(sizeof(int)*tam)*2);
  if(!(*v))
    exit(EXIT_FAILURE);
  /* Limpa a memoria que foi reservada */
  for(d=tam-1; d<tam*2; d++)
    (*v)[d]=0;
}

Com uso de funções


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

/* Constantes */
#define MAX_VET 10

/* Dobra o tamanho do vetor */
void DobraTamanho(int **v, int tam);

int main(void)
{
  /* Reserva memoria */
  int d,*vet=malloc(sizeof(int)*MAX_VET);
  if(!vet)      /* ERRO */
    return(-1);
  /* Preenche o vetor com os primeiros 10 numeros */
  for(d=0; d<MAX_VET; d++)
    vet[d]=d;
  /* Muda para uma posição maior da memoria 
  vet=realloc(vet,(sizeof(int)*MAX_VET)*2);*/
  DobraTamanho(&vet,MAX_VET);
  if(!vet)    /* ERRO */
    return(-1);
  /* Enche o resto da memoria reservada */
  for(d=9; d<MAX_VET*2; d++)
    vet[d]=d;
  /* Mostra todo o vetor */
  for(d=0; d<MAX_VET*2; d++)
    printf("\n%i",vet[d]);
  free(vet);    /* Apaga da memoria */
  return(0);
}

void DobraTamanho(int **v, int tam)
{
  int d;
  (*v)=realloc((*v),(sizeof(int)*tam)*2);
  if(!(*v))
    exit(EXIT_FAILURE);
  /* Limpa a memoria que foi reservada */
  for(d=tam-1; d<tam*2; d++)
    (*v)[d]=0;
}

 

Leia a pagina 141 do C Completo e total para entender melhor o que está acontecendo, também recomendo ler da pagina 113 em diante para entender melhor como ponteiros funcionam.

  • Curtir 3

Compartilhar este post


Link para o post
Compartilhar em outros sites
void newContact(struct contact **schedule) //o ponteiro tem que passado por referencia (ponteiro do ponteiro) se quiser alterar seu valor 
{
  //schedule = (struct contact *)malloc(sizeof(struct contact)*gsize); isso nao pode ficar aqui, você chama malloc apenas uma vez

ver a função DobraTamanho do exemplo do posto de @KXSY

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
1 hora atrás, Francine Guimarães disse:

Gente, tô tendo um problema com a função showAll().

 

Olá!

 

Eu diria que seu problema está espalhado pelo programa todo por enquanto.

Esse vetor de itens da agenda estaria declarado onde? Não está. Usar realloc() para ir aumentando o espaço e usar aritmética para acessar os elementos funciona, claro. Mas é chato. Talvez pudesse usar outra estrutura de dados, como uma lista ou uma pilha. Está seguindo um enunciado ou inventou esse problema para aprender?

 

newContact() poderia devolver o endereço de um novo registro e você insere em sua estrutura. Pode simplificar as coisas.

showAll() poderia devolver o total de itens que percorreu no cadastro. É mais comum e dá pra conferir com o total que você tem.

2 horas atrás, Francine Guimarães disse:

Outro problema que encontrei é que, se eu não declarar as variáveis ali no começo(dentro do struct contact) como sendo vetores, da um erro na hora da execução

 

Isso não é um problema: é a realidade de você querer que por exemplo o nome tenha mais de uma letra, char. E assim por diante, com o telefone, endereço e tal. Você precisa alocar espaço para os dados, permanentemente ou declara tudo como char* e vai dar um trabalho danado para alocar um a um e liberar depois.

 

realloc() é um inferno porque nada garante que ao mudar de tamanho os dados vão ficar a partir do mesmo endereço, então pode ser que durante o programa a agenda inteira seja movida na memória algumas vezes sem seu controle. Mas funciona.

 

Em geral o que se faz é usar coisas como uma lista de itens, onde um item aponta para o próximo na agenda, e aí você tem a vantagem de poder inserir já na ordem em que vai pesquisar os dados. Ou usar vetores de ponteiros com um certo número de posições, e ir alocando mais sob demanda. 

 

Claro que isso se seu programa for salvar a agenda em disco e recuperar de novo da próxima vez...

 

De todo modo, apenas usando essa sua ideia e malloc() realloc() faça o seguinte: crie uma pequena estrutura de controle com a capacidade atual da agenda e o endereço de início dela, e passe um ponteiro para esse endereço como argumento de suas rotinas show() update() showAll() newContact() e tal.

 

 

adicionado 51 minutos depois

Eu não entendi mesmo a relação entre o título do tópico e seu programa :(

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tenta desse jeito:

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

#define limparTela system("clear")  // No Windows mude para "cls"

typedef struct Contato {
    char nome[255];
    char nascimento[11];
    char telefone[14];
    char rua[255];
    char numero[10];
    char bairro[255];
    char cidade[255];
    char estado[3];
    char cep[10];

    struct Contato *proximo;
} Contato_t;

/**
 * Pausa o programa até o usuário apertar ENTER.
 */
void apertarEnter() {
    printf("\n[ ENTER ] ");
    if (getchar() == '\n') getchar();
}

/**
 * Adiciona um novo contato na lista.
 *
 * @param primeiro Primeiro elemento da lista.
 */
void adicionar(Contato_t *primeiro) {
    while (primeiro->proximo != NULL) {
        primeiro = primeiro->proximo;
    }

    primeiro->proximo = malloc(sizeof(Contato_t));

    limparTela;
    printf(">> Adicionar \n");

    printf("Nome: ");
    scanf(" %[^\n]s", primeiro->proximo->nome);

    printf("Data de nascimento: ");
    scanf(" %[^\n]s", primeiro->proximo->nascimento);

    printf("Telefone: ");
    scanf(" %[^\n]s", primeiro->proximo->telefone);

    printf("Rua: ");
    scanf(" %[^\n]s", primeiro->proximo->rua);

    printf("Número: ");
    scanf(" %[^\n]s", primeiro->proximo->numero);

    printf("Bairro: ");
    scanf(" %[^\n]s", primeiro->proximo->bairro);

    printf("Cidade: ");
    scanf(" %[^\n]s", primeiro->proximo->cidade);

    printf("Estado: ");
    scanf(" %[^\n]s", primeiro->proximo->estado);

    printf("CEP: ");
    scanf(" %[^\n]s", primeiro->proximo->cep);

    primeiro->proximo->proximo = NULL;

    printf("\n");
    printf("Contato adicionado com sucesso. \n");
    apertarEnter();
}

/**
 * Percorre todos os elementos da lista e imprime cada um deles.

 * @param primeiro Primeiro elemento da lista.
 */
void imprimir(Contato_t *primeiro) {
    /*
     * Como o primeiro elemento da lista não tem nada, esse flag é usado para
     * pular a impressão desse elemento.
     */
    int flag = -1;

    limparTela;
    printf(">> Relatório \n");

    while (primeiro != NULL) {
        if (++flag == 0) {
            primeiro = primeiro->proximo;
            continue;
        }

        printf("------------------------------------------- \n");
        printf("      Nome: %s \n", primeiro->nome);
        printf("Nascimento: %s \n", primeiro->nascimento);
        printf("  Telefone: %s \n", primeiro->telefone);
        printf("       Rua: %s \n", primeiro->rua);
        printf("    Número: %s \n", primeiro->numero);
        printf("    Bairro: %s \n", primeiro->bairro);
        printf("    Cidade: %s \n", primeiro->cidade);
        printf("    Estado: %s \n", primeiro->estado);
        printf("       CEP: %s \n", primeiro->cep);
        printf("------------------------------------------- \n");

        primeiro = primeiro->proximo;
    }

    apertarEnter();
}

int main() {
    char opcao = '0';

    // O primeiro elemento deve ser inicializado
    Contato_t primeiro;
    strcpy(primeiro.nome, "");
    strcpy(primeiro.nascimento, "");
    strcpy(primeiro.telefone, "");
    strcpy(primeiro.rua, "");
    strcpy(primeiro.numero, "");
    strcpy(primeiro.bairro, "");
    strcpy(primeiro.cidade, "");
    strcpy(primeiro.nome, "");
    strcpy(primeiro.estado, "");
    primeiro.proximo = NULL;

    do {
        limparTela;
        printf("[ 1 ] - Adicionar \n");
        printf("[ 2 ] - Imprimir \n");
        printf("[ 0 ] - Sair \n");
        printf("> ");
        scanf(" %c", &opcao);

        switch (opcao) {
            case '1':
                adicionar(&primeiro);
                break;
            case '2':
                imprimir(&primeiro);
                break;
            default:
                break;
        }
    } while (opcao != '0');

    limparTela;
    return 0;
}
  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

@AdrianoSiqueira Eu acho que o seu algorítimo tem alguns erros. erro_memory_edit.thumb.png.f84ac63e00610e5e8f006aa389e861f6.png

Eu acho que você tentou fazer algo assim.

Spoiler

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

/* Constantes */
#define T_NOME 10   /* Tamanho do campo nome */
#define T_SENHA T_NOME    /* Tamnaho do campo senha */

#define N_ARQUIVO "d_usua"    /* Nome padrão do arquivo */

/* Tipos */
typedef struct 
{
  char nome[T_NOME];
  char senha[T_SENHA];
}TUsuario;

typedef struct Lista
{
  TUsuario usuario;
  struct Lista *proximo;
}TLista;

/* Procedimentos */

/* Cria no simples */
void CriaNo(TLista **l,const TUsuario u);
/* Cria no na lista */
void CriaNoLista(TLista **l,const TUsuario u);
/* Apaga toda a lista */
void ApagaLista(TLista *l);
/* Apaga um unico nó na lista */
void ApagaNoLista(TLista **l, TLista *no);
/* Funções */

/* Busca no nome na lista */
TLista *BuscaNoNome(TLista *l,char *n);

int Menu(void);

int main()
{
  /* Variaveis */
  TLista *inicio=NULL,*ponteiro,*fim;   /* Ponteiros para lista encadeada */
  TUsuario usuario;   /* Auxiliar na captura de dados do usuario */
  char tecla;   /* Usado para pegar a tecla digitada */
  /* Verifica se o arquivo existe */
  FILE *arq=fopen(N_ARQUIVO,"rb+");
  if(!arq)
  {
    printf("\nNão há dados cadastrados.\n");
    printf("\nDeseja criar um novo arquivo\nS/N:\t");
    scanf("%c",&tecla);
    getchar();
    if(toupper(tecla)!='S')
    {
      printf("\nO programa sera encerra.\n");
      return(0);
    }
    /* Cria o arquivo */
    arq=fopen(N_ARQUIVO,"wb+");
    if(!arq)
    {
      printf("\nErro.\nNão foi possivel criar o arquivo.\n");
      return(-1);
    }
    /* Cadastra usuarios */
    printf("\nCadastro de novos usuarios no sistema!");
    do
    {
      printf("\nDigite o nome do usuario:\t");
      fgets(usuario.nome,T_NOME,stdin);
      printf("\nDigite a senha do usuario:\t");
      fgets(usuario.senha,T_SENHA,stdin);
      /* Cria lista encadeada */
      if(!inicio)
      {
        CriaNo(&inicio,usuario);
        fim=inicio;
      }
      else
        CriaNoLista(&fim,usuario);
      printf("\nDigite S/para sair do cadastro e C/para continuar:\t");
      scanf("%c",&tecla);
      getchar();
    }while(toupper(tecla)!='S');
    /* Guarda no arquivo a lista. */
    ponteiro=inicio;
    while(ponteiro)
    {
      if(1!=fwrite(&ponteiro->usuario,sizeof(TUsuario),1,arq))
      {
        printf("\nOcorreu um erro ao gravar o arquivo.\n");
        ApagaLista(inicio);
        return(-1);
      }
      ponteiro=ponteiro->proximo;
    }
  }
  else
  {
    /* Le a lista do arquivo */
    size_t quant;
    do
    {
      quant=fread(&usuario,sizeof(TUsuario),1,arq);
      if(quant)
        if(!inicio)
        {
          CriaNo(&inicio,usuario);
          fim=inicio;
        }
        else
          CriaNoLista(&fim,usuario);
    }while(quant);
  }
  /* Menu principal do programa */
  do
  {
    tecla=1;
    switch(Menu())
    {
      case 0:
        tecla=0;
      break;
      case 2:
        do
        {
          printf("\nDigite o usuario para ser removido:\t");
          fgets(usuario.nome,T_NOME,stdin);
          ponteiro=BuscaNoNome(inicio,usuario.nome);
          if(ponteiro)
          {
            ApagaNoLista(&inicio,ponteiro);
            /* Apaga o arquivo antigo */
            fclose(arq);
            remove(N_ARQUIVO);
            /* Cria um novo arquivo */
            arq=fopen(N_ARQUIVO,"wb+");
            if(!arq)
            {
              printf("\nErro.\nNão foi possivel criar o arquivo.\n");
              ApagaLista(inicio);
              return(-1);
            }
            /* Salva a lista novamente */
            ponteiro=inicio;
            while(ponteiro)
            {
              if(1!=fwrite(&ponteiro->usuario,sizeof(TUsuario),1,arq))
              {
                printf("\nNão foi possivel acessar o arquivo.\n");
                ApagaLista(inicio);
                return(-1);
              }
              ponteiro=ponteiro->proximo;
            }
          }
          else
          {
            printf("\nNome de usuario não encontrado.");
            printf("\nDeseja procurar novamente?\nS/N:\t");
            scanf("%c",&tecla);
            getchar();
          }
        }while(toupper(tecla)!='N');
      break;
      case 3:
        printf("\nDigite o nome do usuario:\t");
        fgets(usuario.nome,T_NOME,stdin);
        ponteiro=BuscaNoNome(inicio,usuario.nome);
        if(ponteiro)
        {
          printf("\nUsuario encontrado\n");
          printf("\nNome:\t%sSenha:\t%s",ponteiro->usuario.nome,ponteiro->usuario.senha);
        }
        else
          printf("\nUsuario não encontrado.\n");
        printf("\n\n\nPressione enter para continuar.");
        getchar();
      break;
      case 4:
        printf("\nLista de usuarios\n");
        ponteiro=inicio;
        while(ponteiro)
        {
          printf("\nNome:\t%sSenha:\t%s",ponteiro->usuario.nome,ponteiro->usuario.senha);
          ponteiro=ponteiro->proximo;
        }
        printf("\n\n\nPressione enter para continuar.");
        getchar();
      break;
    }
  }while(tecla);
  /* Finaliza o programa */
  ApagaLista(inicio);
  fclose(arq);
  return(0);
}

void CriaNo(TLista **l,const TUsuario u)
{
  *l=malloc(sizeof(TLista));
  if(!(*l))
    exit(EXIT_FAILURE);
  (*l)->usuario=u;
  (*l)->proximo=NULL;
}

void CriaNoLista(TLista **l,const TUsuario u)
{
  CriaNo(&(*l)->proximo,u);
  (*l)=(*l)->proximo;
}

void ApagaLista(TLista *l)
{
  TLista *temp;
  while(l)
  {
    temp=l->proximo;
    free(l);
    l=temp;
  }
}

void ApagaNoLista(TLista **l, TLista *no)
{
  if((*l)!=no)
  {
    TLista *temp=(*l),*aux;
    while(temp&&temp!=no)
    {
      aux=temp;
      temp=temp->proximo;
    }
    if(temp==no)
    {
      if(temp->proximo)
      {
        aux->proximo=temp->proximo;
        free(temp);
      }
      else
      {
        aux->proximo=NULL;
        free(temp);
      }
    }
  }
  else
  {
    TLista *temp=(*l)->proximo;
    free(*l);
    (*l)=temp;
  }
}

TLista *BuscaNoNome(TLista *l,char *n)
{
  TLista *temp=l;
  while(temp)
  {
    if(!strcmp(temp->usuario.nome,n))
      return(temp);
    temp=temp->proximo;
  }
  return(NULL);
}

int Menu(void)
{
  int n;
  do
  {
    printf("\nMenu do usuario.");
    printf("\n0:sair.");
    printf("\n1:Cadastrar novo usuario.");
    printf("\n2:Remover cadastro.");
    printf("\n3:Buscar cadastro por nome.");
    printf("\n4:Mostrar Cadastros.");
    printf("\n:>");
    scanf("%i",&n);
    getchar();
    if(n<0||n>4)
      printf("\nOpção invalida.\n");
  }while(n<0||n>4);
  return(n);
}

 

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
12 minutos atrás, AdrianoSiqueira disse:

@KXSY Estranho, não tive nenhum erro quando compilei no GCC no Linux.

coloque no final do comando de compilar o comando "-fsanitize=address"

Exemplo:gcc main.c -o main -fsanitize=address

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olá

 

Escrevi uma mínima implementação de sua lógica usando malloc() e realloc() para mostrar o que eu queria dizer com os cuidados para implementar isso.

Procurei mudar um mínimo no que escreveu e recomendo que leia com cuidado. Rode em sua máquina se possível. Como eu disse, recomendo usar uma estrutura de dados diferente, mas usar um vetor tem seu apelo e é muito rápido, apesar dos efeitos colaterais de usar realloc() e dos riscos de perder um ponteiro no caminho

 

Usei uma implementação para a sua agenda como se fosse uma classe em C++ e acho que vai entender porque: para não correr riscos com os ponteiros

 

Nas declarações inicias não há qualquer alocação, apenas declaramos as estruturas e protótipos das funções. Não há variáveis globais

 

O programa sempre começa por main() e por uma boa razão: a execução começa por main(). Recomendo sempre fazer isso em seus programas

 

A estrutura básica

struct contact
{
int   ID;
char  name[100];
};

typedef struct contact Contact;

struct control
{
int                        capacity;
int                        in_use; // quando esgotar aloca uma igual quantia
Contact*                  schedule;
};
typedef struct control                Control;

Veja que a agenda fica dentro dessa struct Control para manter o isolamento. Assim pode até usar qualquer número de agendas no mesmo programa.

 

Não usei os outros campos da agenda porque seria irrelevante, e acrescentei um ID que nunca duplica, para os testes. E usei nomes com "sobrenome" BulkInsertnnnn onde nnnn é o próprio ID do contato, assim se sabe se sumiu alguém só de olhar. Bulk Insert é uma expressão comum para funções que inserem registros "no atacado".

 

Criei novos nomes Control e Contact para as structs pra não ter que ficar repetindo struct toda hora e porque na verdade eu sempre esqueço :( . E usei a primeira letra em maiúscula porque é uma convenção comum em java e C++ para nomes de Classes.

 

A Estrutura de controle

 

Usei as mesmas variáveis que usou: a capacidade e o total em uso até o momento. E o ponteiro para o endereço de início da agenda. Como todas as funções recebem o endereço essa estrutura de controle como parâmetro, estamos seguros que esse ponteiro está preservado, porque ele será o alvo de malloc()/realloc() afinal. E um erro aqui vai certamente cancelar o programa. E temos pressa.

 

As funções

 

Usei um prefixo x_ para as funções, para criar um micro namespace como em C++ para evitar colisão com nomes que você use já

 

Control*                x_inicia(int c);

 recebe um int que é a quantia inicial de registros a alocar e devolve o endereço da estrutura Control gerada.

 

Control*                x_termina(Control* control);

recebe um endereço de uma estrutura Control e apaga tudo. Retorna um endereço de Control que será sempre NULL, e serve para exercitar o saudável hábito de invalidar o ponteiro em seu programa, já que uma referência posterior a ele vai, claro, cancelar seu programa.

 

int                          x_bulkInsert(int t, Control* control);

Insere t registros na agenda em control, usando ID sequenciais e nomes  'name BulkInsertnnnn' onde nnnn é o ID do contato. Assim não precisamos inventar nomes durante os testes e se pode confirmar sequencia e unicidade deles, de graça e por definição.

 

int                           x_newContact(Contact* novo, Control* c);

Insere o contato novo na agenda incluída em c. É diferente do modo como fez: recomendo NUNCA pegar os dados, validar e coisas assim na rotina que insere: chame a rotina que insere com um valor confiável e teste antes. Facilita muito a sua vida quando se tem pressa.

 

Contact*                x_realoca(Control* control);

Realoca a estrutura de contatos, usando sua lógica de dobrar o tamanho a partir do início. Como seu exemplo inicia com 1 vamos ter 1,2,4,8,16 ou seja 2^n. E devolve o novo endereço da estrutura. Claro que o endereço já está dentro de control, mas assim pode acrescentar mais um nível de garantia de que o ponteiro será preservado.

 

 int                          x_showAll(Control* c);

Só imprime o conteúdo da agenda de contatos incluída em c. Só usei o nome e ID porque claro não faz a menor diferença. E temos pressa.

 

Um programa de teste

int main(int argc, char** argv)
{
    Control*        control = x_inicia(1);        // inicia com 1
    x_bulkInsert(21, control);                    // insere 21
    x_showAll(control);                           // mostra todos
    control = x_termina(control);                 // libera os registros
    return 0;                                     // termina
}

Ao inserir 21 vai usar 1/2/4/8/16/32 registros e ao final a capacidade deve estar em 32. Sempre é melhor saber antes o que se espera do teste...

 

O resultado

inicia(): sizeof(Contact) = 104, capacidade = 1, em uso = 0

***** BulkInsert(21) *****
realoca(): capacidade vai ser alterada para 2
realoca(): sizeof(Contact) = 104, capacidade = 2, em uso = 1
realoca(): capacidade vai ser alterada para 4
realoca(): sizeof(Contact) = 104, capacidade = 4, em uso = 2
realoca(): capacidade vai ser alterada para 8
realoca(): sizeof(Contact) = 104, capacidade = 8, em uso = 4
realoca(): capacidade vai ser alterada para 16
realoca(): sizeof(Contact) = 104, capacidade = 16, em uso = 8
realoca(): capacidade vai ser alterada para 32
realoca(): sizeof(Contact) = 104, capacidade = 32, em uso = 16

showAll(): sizeof(Contact) = 104, capacidade = 32, em uso = 21

001, Nome: 'Name BulkInsert0001', ID=1
002, Nome: 'Name BulkInsert0002', ID=2
003, Nome: 'Name BulkInsert0003', ID=3
004, Nome: 'Name BulkInsert0004', ID=4
005, Nome: 'Name BulkInsert0005', ID=5
006, Nome: 'Name BulkInsert0006', ID=6
007, Nome: 'Name BulkInsert0007', ID=7
008, Nome: 'Name BulkInsert0008', ID=8
009, Nome: 'Name BulkInsert0009', ID=9
010, Nome: 'Name BulkInsert0010', ID=10
011, Nome: 'Name BulkInsert0011', ID=11
012, Nome: 'Name BulkInsert0012', ID=12
013, Nome: 'Name BulkInsert0013', ID=13
014, Nome: 'Name BulkInsert0014', ID=14
015, Nome: 'Name BulkInsert0015', ID=15
016, Nome: 'Name BulkInsert0016', ID=16
017, Nome: 'Name BulkInsert0017', ID=17
018, Nome: 'Name BulkInsert0018', ID=18
019, Nome: 'Name BulkInsert0019', ID=19
020, Nome: 'Name BulkInsert0020', ID=20
021, Nome: 'Name BulkInsert0021', ID=21

showAll() ***** end of listing *****

Até aqui OK: não sumiu ninguém, realloc() funcionou e o último é, bem, o último com ID=21

 

Um outro teste com duas agendas e uma maior


int main(int argc, char** argv)
{
	Control*	control = x_inicia(1);	// inicia com 1
	x_bulkInsert(21, control);			// insere 21
	x_showAll(control);					// mostra todos
	control = x_termina(control);		// libera os registros

	printf(
	    "\n\nCriando agenda maior e mostrando os 2 primeiros e os dois ultimos\n");
	Control* bigOne = x_inicia(1);
	x_bulkInsert(2049, bigOne);		// insere 2049 = 2^11 + 1
	/* mostra nome e ID dos ultimos caras */
	printf(
		"\n%03d, Nome: '%s', ID=%d\n\n...\n\n",
		1,
		bigOne->schedule[0].name,
		bigOne->schedule[0].ID
	);
	printf(
		"%03d, Nome: '%s', ID=%d\n",
		2047 + 1,
		bigOne->schedule[2047].name,
		bigOne->schedule[2047].ID
	);
	printf(
		"%03d, Nome: '%s', ID=%d\n",
		2048 + 1,
		bigOne->schedule[2048].name,
		bigOne->schedule[2048].ID
	);
	bigOne = x_termina(bigOne);		

	return 0;							// termina
}

A primeira parte é a mesma, claro. Mas depois uma segunda agenda, bigOne é criada com 2049 registros, apenas para forçar realloc() a alocar 4096. E mostramos apenas o primeiro e os dois últimos nomes, para ver que podemos usar a agenda inteira como um vetor comum, que é o objetivo afinal

 

Resultado (apenas da segunda parte)

Criando agenda maior e mostrando o primeiro e os dois ultimos

inicia(): sizeof(Contact) = 104, capacidade = 1, em uso = 0

***** BulkInsert(2049) *****

realoca(): capacidade vai ser alterada para 2
realoca(): sizeof(Contact) = 104, capacidade = 2, em uso = 1
realoca(): capacidade vai ser alterada para 4
realoca(): sizeof(Contact) = 104, capacidade = 4, em uso = 2
realoca(): capacidade vai ser alterada para 8
realoca(): sizeof(Contact) = 104, capacidade = 8, em uso = 4
realoca(): capacidade vai ser alterada para 16
realoca(): sizeof(Contact) = 104, capacidade = 16, em uso = 8
realoca(): capacidade vai ser alterada para 32
realoca(): sizeof(Contact) = 104, capacidade = 32, em uso = 16
realoca(): capacidade vai ser alterada para 64
realoca(): sizeof(Contact) = 104, capacidade = 64, em uso = 32
realoca(): capacidade vai ser alterada para 128
realoca(): sizeof(Contact) = 104, capacidade = 128, em uso = 64
realoca(): capacidade vai ser alterada para 256
realoca(): sizeof(Contact) = 104, capacidade = 256, em uso = 128
realoca(): capacidade vai ser alterada para 512
realoca(): sizeof(Contact) = 104, capacidade = 512, em uso = 256
realoca(): capacidade vai ser alterada para 1024
realoca(): sizeof(Contact) = 104, capacidade = 1024, em uso = 512
realoca(): capacidade vai ser alterada para 2048
realoca(): sizeof(Contact) = 104, capacidade = 2048, em uso = 1024
realoca(): capacidade vai ser alterada para 4096
realoca(): sizeof(Contact) = 104, capacidade = 4096, em uso = 2048

001, Nome: 'Name BulkInsert0001', ID=22

...

2048, Nome: 'Name BulkInsert2048', ID=2069
2049, Nome: 'Name BulkInsert2049', ID=2070

 

Tudo ok: alocou 2048 a mais e usou um só :) O último é o último e os primeiros 21 estão na outra agenda.

 

Eis o programa todo 

#define            _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


struct contact
{
    int            ID;
    char        name[100];
    //char        street[100];
    //char        ngbhood[100];
    //char        city[100];
    //char        state[100];
    //int        bday[15];
    //int        cellnumber[20];
    //int        number[10];
    //int        CEP[20];
};
typedef struct contact        Contact;

struct control
{
    int         capacity;
    int         in_use;            // quando esgotar aloca uma igual quantia
    Contact*    schedule;
};
typedef struct control        Control;


int             x_bulkInsert(int, Control*); // insere muitos registros
Control*        x_inicia(int);               // inicia estrutura com determinada capacidade 
int             x_newContact(Contact*, Control* c); // cria um
Contact*        x_realoca(Control*);    // duplica o tamanho da agenda
int             x_showAll(Control*);    // lista todos
Control*        x_termina(Control*);    // inicia estrutura com determinada capacidade 


int main(int argc, char** argv)
{
    Control*    control = x_inicia(1);    // inicia com 1
    x_bulkInsert(21, control);            // insere 21
    x_showAll(control);                   // mostra todos
    control = x_termina(control);         // libera os registros

    printf(
        "\n\nCriando agenda maior e mostrando os 2 primeiros e os dois ultimos\n");
    Control* bigOne = x_inicia(1);
    x_bulkInsert(2049, bigOne);        // insere 2049 = 2^11 + 1
    /* mostra nome e ID dos ultimos caras */
    printf(
        "\n%03d, Nome: '%s', ID=%d\n\n...\n\n",
        1,
        bigOne->schedule[0].name,
        bigOne->schedule[0].ID
    );
    printf(
        "%03d, Nome: '%s', ID=%d\n",
        2047 + 1,
        bigOne->schedule[2047].name,
        bigOne->schedule[2047].ID
    );
    printf(
        "%03d, Nome: '%s', ID=%d\n",
        2048 + 1,
        bigOne->schedule[2048].name,
        bigOne->schedule[2048].ID
    );
    bigOne = x_termina(bigOne);        
    qsort
    return 0;                            // termina
}


int                x_bulkInsert(int t, Control* control)
{
    // insere n registros no cadastro, com nome a partir
    // de 'Name BulkInsert0001' em diante 
    // para acelerar os testes. Realoca a agenda quando for preciso
    Contact        contato;
    int            n;
    printf("\n***** BulkInsert(%d) *****\n", t);
    for (int i = 1; i <= t; i += 1)
    {
        sprintf(contato.name, "Name BulkInsert%04d", i);
        n = x_newContact(&contato, control);
        if (n < 0)
        {
            control->schedule = x_realoca(control);
            n = x_newContact(&contato, control);
        }    // end if
    }    // for i
    return 0;
}    // x_bulkInsert()


Control*        x_inicia(int c)
{
    int q;
    Control*        control = (Control*) malloc(sizeof(Control));
    control->capacity = c;
    q = sizeof(Contact) * c;
    control->in_use = 0;
    control->schedule = (Contact*)malloc(sizeof(Contact) * c);
    printf("inicia(): sizeof(Contact) = %d, capacidade = %d, em uso = %d\n",
        sizeof(Contact),
        control->capacity,
        control->in_use
    );
    return control;
};


int                x_newContact(Contact* novo, Control* c)
{
    static int sequence = 0;
    if (c->in_use >= c->capacity) return -1;    // não cabe mais

    Contact* next = c->schedule + c->in_use;
    sequence += 1;
    strcpy(next->name, novo->name);                // usa so o nome
    next->ID = sequence;
    //printf("Criado contato com ID = %d e nome '%s'\n",
    //    next->ID, next->name);
    c->in_use += 1;
    return 1;
}


Contact*        x_realoca(Control* control)
{
    int q = control->capacity +    control->capacity;    // dobra o tamanho da agenda
    printf("realoca(): capacidade vai ser alterada para %d\n", q);
    control->schedule = (Contact*) realloc(control->schedule, sizeof(struct contact) * q);
    control->capacity = q;
    if (control->schedule == NULL)
    {
        printf("realoca(): ERRO ao realocar agenda\n");
        exit(1);
    }
    printf("realoca(): sizeof(Contact) = %d, capacidade = %d, em uso = %d\n",
        sizeof(Contact),
        control->capacity,
        control->in_use
    );
    return control->schedule;
};


int                x_showAll(Control* c)
{
    printf("\nshowAll(): sizeof(Contact) = %d, capacidade = %d, em uso = %d\n\n",
        sizeof(Contact),
        c->capacity,
        c->in_use
    );
    for (int i = 0; i < c->in_use; i += 1)
    {
        printf(
            "%03d, Nome: '%s', ID=%d\n",
            i+1,
            c->schedule[i].name,
            c->schedule[i].ID
        );
    }    // for
    printf("\nshowAll() ***** end of listing *****\n\n");
    return 0;
};    // x_showAll()


Control*        x_termina(Control* control)
{
    // apaga tudo
    free(control->schedule);
    free(control);
    return NULL;
};

// fim do texto

 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Gente, muito obrigada. Já deixei de lado esse código e fiz outro. 

Obrigada pela disposição de vocês!

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
25 minutos atrás, Francine Guimarães disse:

Gente, muito obrigada. Já deixei de lado esse código e fiz outro. 

Obrigada pela disposição de vocês!

 

Bom que conseguiu. De todo modo recomendo comparar o que eu expliquei com o seu primeiro programa e com o definitivo. Talvez possa aproveitar algo no futuro

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...