2017-10-22 294 views
0

我使用void*返回值int/double中存在問題。C中的泛型結構

例如:

#include "stdio.h" 
#include "stdlib.h" 

typedef struct list { 

    void *info; 
    struct list *prox; 

} List; 

typedef struct queue { 

    List* begin; 
    List* end; 

} Queue; 


Queue* create_queue (void) { 

Queue* f = (Queue*) malloc(sizeof(Queue)); 
f->begin = f->end = NULL; 
return f; 

} 


Queue* insert_queue_end (List* end, void* v) { 

List* p = (List*) malloc(sizeof(List)); 
    p->info=v; 
    p->prox=NULL; 
    if(end!=NULL) { 
    end->prox=p; 
    } 
    return p; 
} 

double queue_empty_double(Queue* f) { 
    return (f->begin==NULL); 
} 


double queue_remove_double(Queue* f) { 

    List* t; 
    double v; 


    if(queue_empty_double(f)) { 
    exit(1); 
    } 

    t=f->begin; 
    v=*((double*)(t->info)); 
    f->begin=t->prox; 
    if (f->begin==NULL) { 
    f->end = NULL; 
    } 
    free(t); 
    printf("%.3lf\n",v); 


    } 


    void insert_queue(Queue* f, void* v) { 

    f->end = insert_queue_end(f->end,v); 
    if(f->begin==NULL) { 
    f->begin=f->end; 
    } 

} 

void print_queue_double(Queue* f) { 

    List* i; 
    for(i=f->begin;i!=NULL;i=i->prox) 
    printf("%.3lf\n",*((double*)i->info)); 

    } 



int main() { 
    Queue* f; 
    f = create_queue(); 
    char ent1[100]; 
    double n1; 
    scanf("%s",ent1); 
    while(ent1[0]!='X') 
    { 
    if(ent1[0]=='E') { 
     scanf("%lf",&n1); 
     insert_queue(f,&n1); 
     scanf("%s",ent1); 
    } 
    else if (ent1[0]=='D') { 
     queue_remove_double(f); 
     scanf("%s",ent1); 
    } 
    } 


} 

但功能不double值工作,只是int

另一個新代碼,現在代碼可以打印double,但是在函數queue_remove_double中存在問題,她應該從隊列中移除第一個元素並打印第一個元素。我相信這個問題是來自泛型結構,因爲該函數刪除第一個並在正常結構中打印他。

Input: 
E 1.2 
E 2.1 
D 
X 

Output: 
1.200 

The wrong output: 
2.100 
+2

副本通過'prox'你的意思是「下一個」?你是在傳遞一個double *還是'double'?這會有所作爲。你怎麼知道它不適用於雙值?編譯器是否會引發錯誤? –

+0

你怎麼知道什麼時候返回值是一個'int'(或指向'int')與一個'double'(或指向'double')?如果你要返回一個值,爲什麼你需要'next'('prox'?)指針?如果你要返回一個值列表,就這樣吧,但也許你應該這樣說。 「info」成員指向的空間分配情況如何?一個節點(或整個節點列表)如何被釋放? –

+0

這裏似乎有一個[XY問題](http://mywiki.wooledge.org/XyProblem)潛伏在這裏。雖然你想要做的事情可以完成,但目前還不清楚它是否可以在你嘗試完成時完成,而不清楚你爲什麼試圖做到這一點。所以,也許你需要拿出一個例子來說明如何/爲什麼這會有好處。 –

回答

1

它適用於代碼塊ide。指定* info的類型以瞭解如何投射指針。

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

typedef enum DataTypes { 
    INTEGER, 
    FLOAT, 
    DOUBLE, 
    CHAR 
} DataType; 

typedef struct list { 
    void *info; 
    struct list *next; 
    DataType type; 
} List; 


List* create_list(void *firstInfo, DataType firstType) 
{ 
    List *f=(List*)malloc(sizeof(List)); 
    f->info=firstInfo; 
    f->type=firstType; 
    f->next=NULL; 
    return f; 
} 

List* insertion(List *end, void *data, DataType type) 
{ 
    List *p=(List*)malloc(sizeof(List)); 
    p->info=data; 
    p->next=NULL; 
    p->type=type; 
    if(end != NULL) 
    { 
     end->next=p; 
    } 
    return p; 
} 

void showTheList(List **theBase) 
{ 
    List *run=*theBase; 

    while(run != NULL) 
    { 
     switch(run->type) 
     { 
      case INTEGER: 
       printf("Showing the value: %d \n",*((int*)run->info)); 
       break; 
      case FLOAT: 
       printf("Showing the value: %f \n",*((float*)run->info)); 
       break; 
      case DOUBLE: 
       printf("Showing the value: %lf \n",*((double*)run->info)); 
       break; 
      default: 
       printf("Showing the value: %c \n",*((char*)run->info)); 
     } 
     run=run->next; 
    } 
} 

List* getEnd(List **theBase) 
{ 
    List *run=*theBase; 
    while(run->next != NULL) 
     run=run->next; 
    return run; 
} 

void clearList(List **theBase) 
{ 
    List *run=(*theBase)->next; 
    free(*theBase); 
    while(run != NULL) 
    { 
     *theBase=run; 
     run=run->next; 
     free(*theBase); 
    } 
    *theBase=NULL; 
} 

int main(void) 
{ 
    List *theList=NULL; 
    int valA=10; 
    float valB=1.25; 
    double valC=23.45; 
    char valD='C'; 

    theList=create_list(&valA,INTEGER); 

    insertion(getEnd(&theList),&valB,FLOAT); 
    insertion(getEnd(&theList),&valC,DOUBLE); 
    insertion(getEnd(&theList),&valD,CHAR); 

    showTheList(&theList); 

    clearList(&theList); 
    if(theList == NULL) 
    printf("Ok, all operations realized !"); 

    return 0; 
} 
0

嘗試使用帶指針的強制轉換。你需要知道指針的類型。

void print_queue_double(Queue* f) 
{ 
    List* i; 
    for(i=f->begin;i!=NULL;i=i->prox) 
    printf("%.3lf\n",*((double*)i->info)); 
} 
+0

你可以看到我在上面的代碼中放入了這個新函數嗎?謝謝你的這兩個答案。 –

0

你的問題是指針。如果你使用n1,那麼void *總是包含最後的n1值,因爲指向n1。然後,當你釋放列表(queue_remove_double),總是顯示N1(最近)的值...

一些解決方案:
(1)陣列 - 下面顯示 - 僅限....
(2)用的變量(malloc的兩倍)的副本新雙重價值 - 「ilimited」(你的內存的限制...)

在新的雙重情況:

List* insert_queue_end (List* end, void* v) { 

    List* p = (List*) malloc(sizeof(List)); 
    double *data=(double*)malloc(sizeof(double)); /*New double new address*/ 

    *data=*((double*)v); /*Copy the VALUE and not the address to new double in new and fixed address*/ 
    /*void* points to a new double with a new address in memory */ 
    p->info=data; 

    p->prox=NULL; 
    if(end!=NULL) { 
    end->prox=p; 
    } 
    return p; 
} 

不要忘了從刪除功能中的新雙內存中釋放內存!

一些解決方案:
SOLUTION 1 - 雙打的陣列:

#include "stdio.h" 
#include "stdlib.h" 

typedef struct list { 

    void *info; 
    struct list *prox; 

} List; 

typedef struct queue { 

    List* begin; 
    List* end; 

} Queue; 


Queue* create_queue (void) { 

Queue* f = (Queue*) malloc(sizeof(Queue)); 
f->begin = f->end = NULL; 
return f; 

} 

/*Yes the type of return is List* and not Queue* - check your code */  
List* insert_queue_end (List* end, void* v) { 

    List* p = (List*) malloc(sizeof(List)); 

    ///If you want create a new double this is the local - don't use the same address in v ! 
    p->info=v; 

    p->prox=NULL; 
    if(end!=NULL) { 
    end->prox=p; 
    } 
    return p; 
} 

double queue_empty_double(Queue* f) { 
    return (f->begin==NULL); 
} 


double queue_remove_double(Queue* f) { 

    List* t; 
    double v; 
    double isRemoved=0; 

    if(queue_empty_double(f)) { 
    exit(1); 
    } 

    t=f->begin; 
    v=*((double*)(t->info)); 
    f->begin=t->prox; 
    if (f->begin==NULL) { 
    f->end = NULL; 
    } 
    free(t); 
    printf("%.3lf\n",v); 

} 


    void insert_queue(Queue* f, void* v) { 

    f->end = insert_queue_end(f->end,v); 
    if(f->begin==NULL) { 
    f->begin=f->end; 
    } 

} 

void print_queue_double(Queue* f) { 

    List* i; 
    for(i=f->begin;i!=NULL;i=i->prox) 
    printf("%.3lf\n",*((double*)i->info)); 

    } 


int main() { 
    Queue* f; 
    f = create_queue(); 
    char ent1[100]; 
    ///One Double Allocated - only one address in memory !!! 
    ///double n1; 

    double listOfDoubles[20]; ///All doubles allocated and one per one have a address in memory !!! 
    int countDoubles=0; 


    scanf("%s",ent1); 
    while(ent1[0]!='X' && countDoubles < 20) 
    { 
    if(ent1[0]=='E') { 

     ///IN YOUR CODE: 
     ///Fill the same one double... 
     ///scanf("%lf",&n1); 

     ///Testing new code 
     scanf("%lf",&listOfDoubles[countDoubles]); ///a new double with your address 

     ///IN YOUR CODE: 
     ///The same address of one variable. The same result. 
     ///Remember void * is a pointer and use the address of n1, and then, print the most recent &n1 content... 
     ///insert_queue(f,&n1); 

     ///A new double in a new address, the content is not equal 
     insert_queue(f,&listOfDoubles[countDoubles]); 

     countDoubles++; 
    } 
    else if (ent1[0]=='D') { 
     ///free the address and decrement the index of array to reuse a double 
     queue_remove_double(f); 
     countDoubles--; 
    } 
    else 
    { 
     ///Print the list - and see the result "debug" 
     print_queue_double(f); 
    } 
    scanf("%s",ent1); 

    } 
    free(f); 

} 

一些解決方案:
SOLUTION 2 - 一種新的雙用的值

#include "stdio.h" 
#include "stdlib.h" 

typedef struct list { 

    void *info; 
    struct list *prox; 

} List; 

typedef struct queue { 

    List* begin; 
    List* end; 

} Queue; 


Queue* create_queue (void) { 

Queue* f = (Queue*) malloc(sizeof(Queue)); 
f->begin = f->end = NULL; 
return f; 

} 

/*Yes the type of return is List* and not Queue* check your code */  
List* insert_queue_end (List* end, void* v) { 

    List* p = (List*) malloc(sizeof(List)); 
    double *data=(double*)malloc(sizeof(double)); /*New double new address*/ 

    *data=*((double*)v); /*Copy the VALUE and not the address to new double in new and fixed address*/ 
    /*void* points to a new double with a new address in memory */ 
    p->info=data; 

    p->prox=NULL; 
    if(end!=NULL) { 
    end->prox=p; 
    } 
    return p; 
} 

double queue_empty_double(Queue* f) { 
    return (f->begin==NULL); 
} 


double queue_remove_double(Queue* f) { 

    List* t; 
    double v; 
    double isRemoved=0; 

    if(queue_empty_double(f)) { 
    exit(1); 
    } 

    t=f->begin; 
    v=*((double*)(t->info)); 
    f->begin=t->prox; 
    if (f->begin==NULL) { 
    f->end = NULL; 
    } 
    free(t->info); ///free the double 
    free(t); 
    printf("%.3lf\n",v); 

} 


    void insert_queue(Queue* f, void* v) { 

    f->end = insert_queue_end(f->end,v); 
    if(f->begin==NULL) { 
    f->begin=f->end; 
    } 

} 

void print_queue_double(Queue* f) { 

    List* i; 
    for(i=f->begin;i!=NULL;i=i->prox) 
    printf("%.3lf\n",*((double*)i->info)); 

    } 


int main() { 
    Queue* f; 
    f = create_queue(); 
    char ent1[100]; 

    double n1; 


    int countDoubles=0; 


    scanf("%s",ent1); 
    while(ent1[0]!='X' && countDoubles < 20) 
    { 
    if(ent1[0]=='E') { 

     scanf("%lf",&n1); 
     insert_queue(f,&n1); 
    } 
    else if (ent1[0]=='D') { 
     queue_remove_double(f); 
    } 
    else 
    { 
     ///Print the list - and see the result "debug" 
     print_queue_double(f); 
    } 
    scanf("%s",ent1); 

    } 
    free(f); 

}