2017-10-22 2 views
0

Ich habe ein Problem in Rückgabewerte int/double mit void*.Generic Struct in C

Zum Beispiel:

#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); 
    } 
    } 


} 

Aber die Funktion funktioniert nicht mit double Werten, nur mit int.

Ein weiterer neuer Code, jetzt kann der Code doppelt drucken, aber in der Funktion queue_remove_double gibt es ein Problem, sie sollte das erste Element aus einer Warteschlange entfernen und das erste Element drucken. Ich glaube, dass dieses Problem von der generischen Struktur ist, weil die Funktion den ersten entfernt und ihn in einer normalen Struktur druckt.

Input: 
E 1.2 
E 2.1 
D 
X 

Output: 
1.200 

The wrong output: 
2.100 
+2

von 'Prox' meinst du "next"? Und gibst du ein "double *" oder ein "double"? Das wird einen Unterschied machen. Woher weißt du, dass es nicht mit doppelten Werten funktioniert? Gibt der Compiler einen Fehler aus? –

+0

Und woher wissen Sie, wenn der Rückgabewert ein 'int' (oder Zeiger auf' int') vs ein 'double' (oder Zeiger auf' double') ist? Wenn Sie einen einzelnen Wert zurückgeben, warum brauchen Sie den 'next' (' prox'?) Zeiger? Wenn Sie eine Liste mit Werten zurückgeben, sollten Sie es auch sagen, aber vielleicht sollten Sie das auch sagen. Wie ist der Raum, auf den das 'info' Mitglied zeigt, zugewiesen? Wie wird ein Knoten (oder eine ganze Liste von Knoten) freigegeben? –

+0

Es scheint wahrscheinlich, dass hier ein [XY Problem] (http://mywiki.wooledge.org/XyProblem) lauert. Während das, was Sie tun möchten, getan werden kann, ist es nicht klar, dass es so gemacht werden kann, wie Sie es versuchen, und es ist nicht klar, warum Sie es zuerst versuchen. Also, vielleicht müssen Sie ein Beispiel finden, das zeigt, wie/warum dies nützlich wäre. –

Antwort

1

Es funktioniert auf Codeblocks IDE. Geben Sie den Typ von * info an, um zu wissen, wie der Zeiger gewirkt wird.

#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

Verwenden Sie eine Besetzung mit dem Zeiger. Sie müssen den Typ des Zeigers kennen.

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

Können Sie diese neue Funktion sehen, die ich oben in den Code eingegeben habe? Danke für diese zwei Antworten. –

0

Ihr Problem ist Zeiger. Wenn Sie n1 verwenden, enthält void * immer den letzten n1-Wert, da er auf n1 zeigt. Dann, wenn Sie die Liste (queue_remove_double) freizugeben, ist immer der Wert von n1 zeigen (die aktuellste) ...

Einige Lösungen:
(1) Array - unten zeigte - zeitlich begrenzt ist ....
(2) neuer Doppel Wert mit der Kopie von variablen (malloc Doppel) - „unbegrenzter,“ (Grenze des Speichers ...)

im neuen Doppel Fall:

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; 
} 

vergessen Sie nicht, Befreie den Speicher vom neuen Double in der Remove-Funktion!

einige Lösungen:
LÖSUNG 1 - Das Array von Doppel:

#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); 

} 

einige Lösungen:
SOLUTION 2 - Eine neue Doppel mit der Kopie der Wert

#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); 

}