Naeio
Naeio

Reputation: 1191

Simulate Polymorphism in C without using pointers

TL;DR :

Is there a type (let's name it convert_type) that allows to do type casting without loosing information, even when dealing with the float type ?

Example of usage :

float f1 = 12.34;
long i1 = 32;

convert_type tmp1 = (convert_type) f;
convert_type tmp2 = (convert_type) i;

float f2 = (float) tmp1; // should be 12.34
long i2 = (long) tmp2; // should be 32

CONTEXT :

I want to create such a function :

convert_type ask(char* question, val_type input_type)

with the type val_typedefined by :

typedef enum {
    INT_T,
    STR_T,
    CHAR_T,
    FLOAT_T
} val_type;

The argument questionhas a string to print in order to ask the input.

The idea of this function is to ask in the stdin an input of type input_type, and ask again until the input is valid.

Example of usage of ask() :

int main(int argc, char const *argv[]) {
    int nb = (int) ask("How many tries to you want ?\n --> ", T_INT);
    char * message = (char*) ask("What is the victory message ?\n --> ", T_STR);
    float prob = (float) ask("What is the probability of winning ?\n --> ", T_FLOAT);
    printf("\n\n");
    printf("Number of tries : %d\n", nb);
    printf("Victory message : %s\n", message);
    printf("Probability : %f\n", prob);
    return 0;
}

I implemented it using the type unsigned long, and I have trouble with float type.

Example of execution :

How many tries to you want ?
 --> many
The input must be a valid integer.
How many tries to you want ?
 --> -2131 
What is the victory message ?
 --> We are the champions !!!
What is the probability of winning ?
 --> 3.4.3
The input must be a valid float value.
What is the probability of winning ?
 --> 2.54


Number of tries : -2131
Victory message : We are the champions !!!
Probability : 2.000000

It is noticeable that unsigned long doesn't work well with float type (the 2.54 became 2.00 because unsigned long contains an integer value I guess).

What type can I use instead ?

Upvotes: 0

Views: 76

Answers (1)

MikeCAT
MikeCAT

Reputation: 75062

If you are careful enough not to cause read/write type mismatch, you can do like this using union:

#include <stdio.h>

typedef union {
    int int_data;
    char* str_data;
    char char_data;
    float float_data;
} convert_type;

typedef enum {
    INT_T,
    STR_T,
    CHAR_T,
    FLOAT_T
} val_type;

convert_type ask(char* question, val_type input_type) {
    static char[] str = "We are the champions !!!";
    convert_type ret;
    fputs(question, stdout);
    /* this is examples of how to set values. reading is omitted. */
    switch (input_type) {
        case INT_T:
            ret.int_data = -2131;
            break;
        case STR_T:
            ret.str_data = str;
            break;
        case CHAR_T:
            ret.char_data = 'a';
            break;
        case FLOAT_T:
            ret.float_data = 2.54;
            break;
    }
    return ret;
}

int main(int argc, char const *argv[]) {
    int nb = ask("How many tries to you want ?\n --> ", INT_T).int_data;
    char * message = ask("What is the victory message ?\n --> ", STR_T).str_data;
    float prob = ask("What is the probability of winning ?\n --> ", FLOAT_T).float_data;
    printf("\n\n");
    printf("Number of tries : %d\n", nb);
    printf("Victory message : %s\n", message);
    printf("Probability : %f\n", prob);
    return 0;
}

Unlike struct, the members of union share one memory space. Therefore, when you write some value to a member of union, the other members of the union become invalid.

Upvotes: 1

Related Questions