DOMANDA Come dichiarare una variabile valida sia come int,float,double.

Pubblicità

stex99.

Nuovo Utente
Messaggi
6
Reazioni
1
Punteggio
21
Sto creando una libreria in linguaggio C
Dopo aver creato il file con estensione .h ho inserito i prototipi delle mie funzioni.
Poi mi sono domandato:
Voglio creare una funzione che faccia la somma di due numeri inseriti dunque io scrivo come prototipo:
void spinaci (double, double);
dunque mi pare chiaro che se dovessi usarla inserendo però variabili di tipo int potrebbe non funzionare.
viceversa se dovessi dichiarare un prototipo del tipo:

void spinaci (int, int);
e poi usare variabili di tipo double.


Ecco, potrei fare un cambio di tipologia di variabile nei futuri programmi che scriverò (tipo trasformo variabili di tipo double in int...se possibile… o viceversa), oppure creo più funzioni (spinaci1 spinaci2...) ciascuna con una diversa scelta dell'argomento. In entrambi i casi è piuttosto scomodo.
Mi chiedo come posso generalizzare la cosa, ossia definire una tipologia di variabile che vada d'accordo con tutte quelle che uso nei miei corsi universitari (int, double, float).
che faccio?
 
Eheh. In C++ esiste l’overload di una funzione, per non parlare dei conseguenti Template.
In C ti crei manualmente tu le funzioni che ti servono. Certo che un intero è tranquillamente un float e un float è tranquillamente un double perciò puoi usare double per tutti.
 
Eh, stai toccando uno degli aspetti dolenti del C: non ci sono tipi generici.
Ovviamente puoi memorizzare un int in un double, in quanto la parte decimale verrebbe troncata (perdendo quindi l'informazione).

Oltre a duplicare il codice, e duplicare quindi le funzioni come suggerito da _Achille, rendendole però magari accessibili utilizzando lo stesso nome, e quindi decidere durante l'esecuzione quale chiamare, puoi sfruttare il preprocessore e lasciare a lui la scrittura delle diverse tipologie di funzioni...

Ho ipotizzato il calcolo della media di N valori (4 nel mio caso, per semplicità); non effettuo controlli sulla prima posizione dell'array, essendo solo un esempio.

C:
//
// name: templates.h
//

#define CONCAT(x, y) x ## y

#define get_average(T) CONCAT(get_average_, T)

TYPE get_average (TYPE) (TYPE * array, int len)
{
    TYPE sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];
   
    return sum / len;
}

Uso la concatenazione dei token (quel ## sulla prima macro), nota anche come "token pasting". In sostanza concatena due token validi. Quindi l'altra macro, get_average, forma quello che è il nome completo della funzione, ad esempio: get_average_int, get_average_double etc etc.

C:
//
// main.c
//
#include<stdio.h>

#define TYPE int
#include "templates.h"
#undef TYPE

#define TYPE double
#include "templates.h"
#undef TYPE


int main()
{
    int    int_array[]    = {10,20,40,50};
    double double_array[] = {10.5, 20.5, 30.5, 33.5};
   
    int    avg_int    = get_average(int)(int_array, 4);
    double avg_double = get_average(double)(double_array, 4);
   
    printf("Media ints: %d\n", avg_int);
    printf("Media doubles: %f\n", avg_double);

    return 0;
}

Output:
Codice:
Media ints: 32
Media doubles: 26.375000

Dopo svariate correzioni, analizzando il preprocessore, sono riuscito a far funzionare qualcosa. Da notare comunque che nel sorgente è necessario includere l'header più volte impostando un TYPE differente.

Questo è il codice dopo l'espansione (è necessario compilare con gcc -E nome_file.c):
C:
# 5 "templates.h"
int get_average_int (int * array, int len)
{
    int sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];

    return sum / len;
}
# 5 "generic.c" 2



# 1 "templates.h" 1




double get_average_double (double * array, int len)
{
    double sum = array[0];
    for(int i=0; i<len; i++)
        sum += array[i];

    return sum / len;
}
# 9 "generic.c" 2



int main()
{
    int int_array[] = {10,20,40,50};
    double double_array[] = {10.5, 20.5, 30.5, 33.5};

    int avg_int = get_average_int(int_array, 4);
    double avg_double = get_average_double(double_array, 4);

    printf("Media ints: %d\n", avg_int);
    printf("Media doubles: %f\n", avg_double);

    return 0;
}
 
Pubblicità
Pubblicità
Indietro
Top