C 将 void* 数据转换为 typedef 结构

标签 c pointers data-structures

我有一个 BST 库,其中存储了一些结构:

struct bst_node {
    char *key;
    void* data;                // this one i want to get it casted to struct model
    struct bst_node* left;
    struct bst_node* right;
};

这里是搜索函数,它返回驻留在 bst.c 中的 bst_node:

struct bst_node** search(struct bst_node** root,char *key) {
    struct bst_node** node = root;
    while (*node != NULL) {
        int compare_result = compare(key, (*node)->key);
        if (compare_result < 0)
            node = &(*node)->left;
        else if (compare_result > 0)
            node = &(*node)->right;
        else
            break;
    }
    return node;
}

此时,我在 main.c 中拥有这个结构,它包含在 void* 数据中

typedef struct model_t{
    char name[MAX];
    char file_a[MAX];
    char date[MAX];
    int price;
    accesories *acs;
}model;

假设在 main.c 中我搜索一个项目并返回一个包含我感兴趣的 void* 数据的树节点,如何转换该数据并将其分配给model 以便稍后我可以访问 model 的字段(例如修改配件列表)?

以下是我尝试过的方法:

  1. 返回数据

    model *m;
    m  = (model *)searches(root,mod);  // the searches function is similar to the search posted
    if (m != NULL) {                   //before but instead of a node returns &(*node)->data
        printf("\n--------%s\n",(*m).name);
    
  2. 返回一个节点并将其数据分配给模型 *m 指针

    model* m;
    struct bst_node** node  = search(root,mod);  //return the node containing the string
                                                 //in "mod" and assign node->data to m
    if (node != NULL) {  
         m=(*node)->data;
         print_list(m);             //this functions prints the accesories list
    }
    

我确信有一种方法可以解决这个问题,但我就是找不到任何帮助,我们将不胜感激。

------------------------------------------------------------ ------------------------main.c------------------------------------ -

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


#define MAX 50

typedef struct accesori_t{
    char nome[MAX];
    int prezzo;
    struct accesori_t *next;    
}accesori;

typedef struct modello_t{
    char nome[MAX];
    char file_a[MAX];
    char date[MAX];
    int prezzo;
    accesori *acs;
}modello;



void stampa_lista(struct modello_t *m);
void append_node(struct accesori_t *llist,char *nome, int prezzo);
void stampa_modelli(struct bst_node* root);
void salva_lista(struct bst_node* root,char *nf);
void inserisci_modello(struct bst_node** root);
void cancella_modello(struct bst_node** root);
void inserisci_acs(struct bst_node** root);
void cancella_acs(struct bst_node** root);
//struct modello_t *cerca_modello();
void stampa_affinita(struct bst_node* root);

int main(int argc, char *argv[])
{
    int menu=0;

    char nf[MAX];

    char *t;
    char nome[MAX];
    char file_a[MAX];
    char data[MAX];
    int prezzo,gg,mm,a,index=0;


    int prezzo_a;
    char nomea[MAX];
    struct accesori_t *head,*curr;
    struct accesori_t *tmp;


    FILE *fp;
    FILE *fa;
    fp=fopen("cars.txt","r+");

    struct modello_t *m;
    m = (struct modello_t *)malloc(sizeof(struct modello_t));

    struct bst_node* root=NULL;



    while(fscanf(fp,"%s %s %d %s",nome,data,&prezzo,file_a)!=EOF){

            strcpy((*m).nome,nome);
            strcpy((*m).file_a,file_a);
            strcpy((*m).date,data);
            (*m).prezzo=prezzo;
            //printf("%s\n",(*m).nome);                  

            fa=fopen((*m).file_a,"r+");


            m->acs=(struct accesori_t *)malloc(sizeof(struct accesori_t));
            while(fscanf(fa,"%s %d",nomea,&prezzo_a)!=EOF)
            {                   
                append_node(m->acs,nomea ,prezzo_a);       
                while(m->acs->next != NULL)
                    {
                        m->acs = m->acs->next;
                        //printf("\t%s --- %d\n",m->acs->nome,m->acs->prezzo);

                    }
            }

            insert(&root, m->nome, m);   
            close(fa);

    }

    while(1){

        printf("\n\t1.Stampa Lista modelli");  
        printf("\n\t2.Inserisci nuovo modello");
        printf("\n\t3.Cancella un modello");
        printf("\n\t4.Inserisci Accesorio");
        printf("\n\t5.Cancella Accesorio");
        printf("\n\t6.Salva la lista");
        printf("\n\t7.Stampa Affinita'");
        printf("\n\t0.EXIT");
        printf("\n\t"); 
        printf("\nINSERIRE SCELTA : ");
        scanf("%d",&menu);   

        switch(menu)
        {
            case 1:
                stampa_modelli(root);
                break;

            case 2:
                inserisci_modello(&root);
                break;
            case 3:
                cancella_modello(&root);
                break;
            case 4:
                inserisci_acs(&root);
                break;
            case 5:
                cancella_acs(&root);
                break;
            case 6:
                salva_lista(root,nf);
                break;
            case 7:
                stampa_affinita(root);
                break;
            case 0:
                return;

        }

    }  




  delete_tree(root);
  close(fp);
  system("PAUSE");  
  return 0;
}

void append_node(struct accesori_t *llist,char *nome, int prezzo) {
    while(llist->next != NULL)
        llist = llist->next;

    llist->next = (struct accesori_t *)malloc(sizeof(struct accesori_t));
    llist->next->prezzo = prezzo;
    strcpy( llist->next->nome,nome);
    llist->next->next = NULL;
}

void stampa_lista(struct modello_t *m){
    while(m->acs->next != NULL)
    {
        m->acs = m->acs->next;
        printf("\t%s --- %d\n",m->acs->nome,m->acs->prezzo);

    }
}

void stampa_modelli(struct bst_node* root){
        preorder_traverse(root);
}

void inserisci_modello(struct bst_node** root){

    FILE *fa;
    struct modello_t *temp;
    char nomea[MAX];
    int prezzo_a;
    temp = (struct modello_t *)malloc(sizeof(struct modello_t));

    printf("\nInserire il nome : ");
    scanf("%s",temp->nome);

    printf("\nInserire il file degli accesori : ");
    scanf("%s",temp->file_a);

    printf("\nInserire la data di disponibilita' (gg/mm/aaaa) : ");
    scanf("%s",temp->date);

    printf("\nInserire il prezzo : ");
    scanf("%s",&temp->prezzo);


    printf("%s\n",(*temp).nome);                 
    fa=fopen(temp->file_a,"r");


            temp->acs=(struct accesori_t *)malloc(sizeof(struct accesori_t));
            while(fscanf(fa,"%s %d",nomea,&prezzo_a)!=EOF)
            {                   
                append_node(temp->acs,nomea ,prezzo_a);       
                while(temp->acs->next != NULL)
                    {
                        temp->acs = temp->acs->next;                                               
                    }
            } 
            insert(root, temp->nome, temp);   

    free(temp);
    close(fa);   
}

void cancella_modello(struct bst_node** root){

    char mod[MAX];

    printf("\nInserire il nome del modello da cancellare : ");
    scanf("%s",mod);

    struct bst_node** node = search(root,mod);

    if (*node != NULL) {
        delete(node);
    }

    preorder_traverse((*root));    
    free(node);       
}
void inserisci_acs(struct bst_node** root){
    char mod[MAX];
    char acs[MAX];
    int prezzo_a;

    //struct modello_t* m;

    printf("\nInserire il nome del modello: ");
    scanf("%s",mod);

    struct modello_t **r = searches(root,mod);

    struct modello_t *m = *r; 
    if(m != NULL) { 
        printf("\n--------%s\n",m->nome); 
    } 

    //struct modello_t *m;
    //m  = (struct modello_t *)searches(root,mod); //trovare come fare a far ritornare il void *data

    /*if (m != NULL) {
        printf("\n\nQuesto pezzo di programma e' ancora da rivedere in quanto ho dei problemi\n nel convertire void* data in struct modello\n\n" );


        //m=(*node)->data; // parte problematica
        //stampa_lista(m);
        printf("\n--------%s\n",(*m).file_a);
        printf("\nInserire il nome dell'accesorio da aggiungere: ");
        scanf("%s",acs);
        printf("\nInserire il prezzo dell'accesorio da aggiungere: ");
        scanf("%s",prezzo_a);

        while(m->acs->next != NULL)
        {
            m->acs = m->acs->next; 
            if(m->acs->next == NULL)
                append_node(m->acs,acs ,prezzo_a);                                                   
        }

    }*/
    free(m);    

}
void cancella_acs(struct bst_node** root){
    char mod[MAX];
    char acs[MAX];


    //struct modello_t *m;

    printf("\nInserire il nome del modello: ");
    scanf("%s",mod);

    struct bst_node **node  = search(root,mod);

    if(*node == NULL) 
    { 
        puts("Not found"); 
    } else { 
        struct modello_t *m = (*node)->data; 

    if(m == NULL) 
    { 
        puts("Found, but data is NULL"); 
    } else { 
        printf("\n--------%s\n",m->nome); 
    } 
    }

    /*if (node != NULL) {
        printf("\nQuesto pezzo di programma e' ancora da rivedere in quanto\n ho dei problemi nel convertire void* data in struct modello\n" );


    m=(struct modello_t*)((*node)->data); // parte problematica

     printf("\n--------%s\n",m->prezzo);
    //stampa_lista(m);

    printf("\nInserire il nome dell'accesorio da cancellare: ");
    scanf("%s",acs);


         while(m->acs->next != NULL)
        {   
            if(strcmp(m->acs->next->nome, acs)){
                if(m->acs->next->next==NULL)
                   m->acs->next==NULL;        
                m->acs->next=m->acs->next->next;
                break; 
            } 
            m->acs = m->acs->next; 

        }
    }*/
    free(node);   
}

void salva_lista(struct bst_node* root,char *nf){
    FILE *fp;
    FILE *fa;
    fp=fopen(nf,"w+");
    char na[MAX];

    struct modello_t *m;
    //m = (struct modello_t *)malloc(sizeof(struct modello_t));

    /*while(ritorna_nodi(root)) 
    {       m=ritorna_nodi(root)

            fprintf(fp,"%s %s %d %s",(*m).nome,(*m).date,(*m).prezzo,(*m).file_a);                              
            fa=fopen((*m).file_a,"w+"); 

            while(m->acs->next!=NULL)
            {                   
                fprintf(fp,"%s %d ",m->acs->nome,m->acs->prezzo);
                m->acs=m->acs->next;
            }
            close(fa);               
    }*/
    close(fp);  
}
stampa_affinita(struct bst_node* root)
{
      stm_aff(root);   
}

------------------------------------------------------------ ----bst.c-------------------------------------------------------- --

#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "bst.h"
#include "data.h"


struct bst_node* new_node(char *key,void* data) 
{
    struct bst_node* result = malloc(sizeof(struct bst_node));
    assert(result);
    result->data = data;
    result->key=malloc(strlen(key)*(sizeof(char)));
    strcpy(result->key,key);
    result->left = result->right = NULL;
    return result;
}

int compare(void* left,void* right)
{
    if (strcmp(left,right)<0)
    {
        return -1;
    }
    else if (strcmp(left,right)==0)
    {
        return 0;
    }
    else
    {
        return 1;
    }
}



void free_node(struct bst_node* node) 
{
    assert(node);
    free(node);
    node = NULL;
}

struct bst_node** search(struct bst_node** root,char *key) {
    struct bst_node** node = root;
    while (*node != NULL) {
        int compare_result = compare(key, (*node)->key);
        if (compare_result < 0)
            node = &(*node)->left;
        else if (compare_result > 0)
            node = &(*node)->right;
        else
            break;
    }
    return node;
}

void* searches(struct bst_node** root,char *key) {
    struct bst_node** node = root;
    while (*node != NULL) {
        int compare_result = compare(key, (*node)->key);
        if (compare_result < 0)
            node = &(*node)->left;
        else if (compare_result > 0)
            node = &(*node)->right;
        else
            break;
    }
    return (*node)->data;
}

void insert(struct bst_node** root,char *key, void* data) {
    struct bst_node** node = search(root,key);
    if (*node == NULL) {
        *node = new_node(key,data);
    }
}

void delete(struct bst_node** node) {
    struct bst_node* old_node = *node;
    if ((*node)->left == NULL) {
        *node = (*node)->right;
        free_node(old_node);
    } else if ((*node)->right == NULL) {
        *node = (*node)->left;
        free_node(old_node);
    } else {
        struct bst_node** pred = &(*node)->left;
    while ((*pred)->right != NULL) {
        pred = &(*pred)->right;
    }
    /* Swap values */
    void* temp = (*pred)->key;
    void* temp1 = (*pred)->data;

    (*pred)->data = (*node)->data;
    (*pred)->key = (*node)->key;

    (*node)->data = temp;
    (*node)->key = temp1;

    delete(pred);
    }
}

void visit(struct bst_node* node)
{
    printf("%s\n", node->key);
}

void preorder_traverse(struct bst_node* root)
{
    if (!root) return;

    visit(root);
    preorder_traverse(root->left);
    preorder_traverse(root->right);
}

void inorder_traverse(struct bst_node* root)
{
    if (!root) return;

    inorder_traverse(root->left);
    visit(root);
    inorder_traverse(root->right);
}

void postorder_traverse(struct bst_node* root)
{
        if (!root) return;

        postorder_traverse(root->left);
        postorder_traverse(root->right);
        visit(root);
}

void delete_tree(struct bst_node* root)
{
    if (!root) return;

    delete_tree(root->left);
    delete_tree(root->right);

    free_node(root);
}
void*  ritorna_nodi(struct bst_node* root){

    if (!root) return;

    ritorna_nodi(root->left);    
    return root->data;  
    ritorna_nodi(root->right);      
}
void stm_aff(struct bst_node* root) // visita preorder quindi per ogni nodo visitato stampa la sua lista
{
    if (!root) return;

    //stm_vst(root);
    stm_aff(root->left);
    stm_aff(root->right);
}
/*void stm_vst(struct bst_node* root) // dovrebbe ritornare una lista di accesori di quel nodo
{
   return; 
}*/

------------------------------------------------------------ ------------------------bst.h------------------------------------ --

#ifndef _BST_H_

struct bst_node {
    char *key;
    void* data;
    struct bst_node* left;
    struct bst_node* right;
};

struct bst_node* new_node(char *key,void* data);

void free_node(struct bst_node* node);
typedef int my_comparator(void* left, void* right);



struct bst_node** search(struct bst_node** root,char *key);
void insert(struct bst_node** root,char *key, void* data);
void delete(struct bst_node** node);
void preorder_traverse(struct bst_node* root);
void inorder_traverse(struct bst_node* root);
void postorder_traverse(struct bst_node* root);
void delete_tree(struct bst_node* root);

#endif

所以我遇到问题的部分是 main.c 中的注释部分,任何帮助将不胜感激

最佳答案

你会这样做:

struct bst_node **r = search(root,mod);
if(*r == NULL) {

  puts("Not found");

} else {

  model_t *m = (*r)->data;
  if(m == NULL) {
     puts("Found, but data is NULL");
  } else {
     printf("\n--------%s\n",m->name);
  }

}

如果这不起作用(请详细解释为什么“不起作用”),则还有其他问题。

您还可以更改 search() 函数以仅返回 bst_node* ,此处似乎没有必要处理双指针

关于C 将 void* 数据转换为 typedef 结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9464418/

相关文章:

c - 使用 qsort 排序后存储原始索引

c - ARM:如果中断被禁用,是否需要 LDRX/STRX?

c - 如何从 C 中的字符串中获取子字符串?

c - STM32写Flash

c - 在c中传递数组元素指针

c - 如果地址已知,如何通过指针处理地址内容而不触发段错误?

c - 将指针/数组从函数传递给 main()

c - 二叉树的最低公共(public)祖先(不是二叉搜索树)

algorithm - N-ary树 - 它是否对称

database - 实现 laravel 数据库系统以管理帖子读取/共享/编辑权限的最佳方法