Ir ao conteúdo
  • Cadastre-se

C Impressão de variáveis em struct não ocorre como esperado


Oceans of mind

Posts recomendados

Eu estou tentando fazer um programa que lê e imprime variáveis de uma struct, a leitura ocorre normal, mas imprime uns dados nada a ver com o que eu inseri 😕 não sei exatamente o que estou fazendo errado.

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

typedef struct{
    long int idPacote;
    char nomePacote[50];
}Pacote;

void cadastrarPacote(Pacote *vec_pacote, int *n);
void imprimirPacote(Pacote *vec_pacote, int *n);

int main(){

    int op, a;
    Pacote *vec_pacote = (Pacote*) malloc (sizeof(Pacote));

    do{

        printf("Insira a opcao: ");
        scanf("%d", &op);

        switch(op){
            case 1:
                cadastrarPacote(vec_pacote, &a);
                break;
            case 2:
                imprimirPacote(vec_pacote, &a);
                break;
            case 3:
                printf("Encerrando o programa...");

                break;
            default:
                printf("tenta outra coisa amadah ");
        }

    }while(op != 3);

    free(vec_pacote);
    return(0);

}

void cadastrarPacote(Pacote *vec_pacote, int *n){

    int op, i=1;

    do{
        printf("ID do pacote: ");
        scanf("%ld", &(vec_pacote+i)->idPacote);

        printf("Nome do pacote: ");
        scanf(" %[^\n]", (vec_pacote+i)->nomePacote);

        printf("Deseja continuar? 1-s 0-n\n");
        scanf("%d", &op);

        if(op == 1){
            i = i + 1;
            vec_pacote = (Pacote*) realloc (vec_pacote, (i+1) * (sizeof(Pacote)));
        }

    }while(op == 1);
    
    *n = i;

}

void imprimirPacote(Pacote *vec_pacote, int *n){

    for(int i=1; i<=*n; i++){
        printf("\nID do pacote: %d\n", (vec_pacote+i)->idPacote);
        printf("Nome do pacote: %s\n", (vec_pacote+i)->nomePacote);

    }

}

 

Link para o comentário
Compartilhar em outros sites

Exclamacao.png.78aa600c6b3a434a3882f612e8d0d279.pngBoa Tarde @Oceans of mind , então meu caro colega de código;  notei que funções com ações semelhantes à 'cadastrarPacote'  seguem a seguinte regra:

 

Ilustração

tipo *lista=  NULL;
tamanho quantidade= 0;

pegar_lista (&lista, &quantidade);

 

[*] lista é um ponteiro de um tipo de dados, então o valor dessa variável é o endereço para variável do seu tipo. Um exemplo desse algoritmo é a função getline em stdio.h

 

C'11

char *string_nome= NULL;
size_t tamanho_nome= 0;

(void) getline (&string_nome, &tamanho_nome, stdin);

 

A função aloca e realoca memória. Sempre alocando de 128 em 128 'pacotes', mesmo se na linha tem 1 'pacote'. Quando 128 é insuficiente, caso tenha +127 e -256 caracteres, a função aloca 256, etc.

"

 

Voltando a sua função e qual um dos seus erros?

Então, erra no primeiro argumento que não se pode alterar o valor na origem em caso de realocarem os dados.

"

 

Link para o comentário
Compartilhar em outros sites

image.png.bcdc60f4769867a31b31ebbee8d3025c.png

 

Não funciona deste modo

 

Esse ponteiro vec_pacote é o único que existe em main(). Quando passa esse ponteiro para cadastrarPacote() ele vai mas não volta. Só que lá você usa realloc() para alocar mais Pacote. E isso pode e muitas vezes vai mudar o endereço dele. Como você não retorna o valor ele se perde lá dentro, bem como toda a memória que você alocou...

 

Citação

Em geral retornar void é um desperdício e muitas vezes um erro. Aqui .e um erro. Evite ao máximo esse tipo de construção.

 

Nesse caso aqui declare 
 

    Pacote* cadastrarPacote(Pacote*, int* n)


E escreva
 

    vec_pacote = cadastrarPacote(vec_pacote, &a);
Citação

 

Esse int* na linha de argumentos mostra um outro erro comum. Não confunda o item com o container do item. Sempre dá problema. Uma lista não é o nó. Uma árvore não é a folha. Um cadastro de pacotes não é um pacote.

 

 

Você queria escrever algo assim:

 


typedef struct
{
    int     idPacote;
    char    nomePacote[50];

}   Pacote;

typedef struct
{
    int      idCadastro;
    int      quantos;
    int      maximo;
    Pacote** pac;

}   Cadastro;

int     _cadastrarPacote(Pacote* pacote, Cadastro* sacola) { return 0; };
int     _imprimirCadastro(Cadastro* sacola) { return 0; };
int     _imprimirPacote(Pacote* pacote) { return 0; };

 

Compare:

 

Um Cadastro é um conjunto de Pacote. Tem um total atual, uma capacidade e um vetor de ponteiros para pacote. Não por acaso main() é declarada
 

    int main( int argc, char**argv);

 

é muito mais prático assim. Um vetor de strings que são os argumentos.

 

Você pode escrever
 

    Cadastro Sacola[12];
    Sacola[1].maximo = 100;
    Sacola[1].quantos = 0;
    Sacola[1].pac = NULL;

 

E veja como é mais expressivo: Tem uma dúzia de sacolas. A segunda delas, já que a primeira é Sacola[0], pode ter um máximo de 100 Pacote. No momento está vazia. O vetor pac vai dar acesso aos pacotes, mas está vazio já que não tem nenhum. E nem começou o programa.

Se você escreve em torno dos dados trabalha menos.


Outro problema


Nunca escreva isso
 

    vec_pacote = (Pacote*)realloc(vec_pacote, (i + 1) * (sizeof(Pacote)));


Escreva assim
 

            //vec_pacote = (Pacote*)realloc(vec_pacote, (i + 1) * (sizeof(Pacote)));
            Pacote* novo = (Pacote*) realloc( vec_pacote,  (i + 1)*(sizeof(Pacote)) );
            if (novo != NULL)
                vec_pacote = novo;
            else
            { // algo errado
            }

Se der erro em realloc() o que vai acontecer? Você vai perder tudo. Não tem outra cópia do ponteiro e não há garantia de que ele não tenha se perdido.

E não use realloc() item a item. É terrivelmente ineficiente. Aloque um bloco razoável de Pacote e ao final libere o que não usar.

 

Mais um palpite:

 

Nunca use um menu em um programa que não está pronto. Só perde seu tempo. Testar isso é o máximo em monotonia e perda de tempo. Use constantes. Use arquivos de texto com os dados. Esses que você edita no próprio IDE. Sim, IDE é masculino. Assim pode testar com os mesmos dados várias vezes em minutos. Ou com vários dados em minutos...

Acha que isso abaixo funciona?
 


    Pacote p1 = { 12, "teste" };
    Pacote p2 = {
        .nomePacote = "Outro pacote",
        .idPacote = 8
    };

    Pacote sacolinha[3] = {
        { 1, "produto 1" },
        { 2, "produto 2" },
        { 3, "produto 3" }
    };

    printf("%d, %s\n", p1.idPacote, p1.nomePacote);
    printf("%d, %s\n", sacolinha[2].idPacote, sacolinha[2].nomePacote);

 

E cria dois pacotes e um vetor sacolinha com 3 pacotes para testar o programa? 

 

Sim, funciona. Veja o p1 e o terceiro produto em sacolinha
 

image.png.abda11879f08bd63c8e608bdcd62084b.png

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário 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 comunidades 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...