2013-07-16 18 views
5

Sono relativamente nuovo al linguaggio di programmazione C e sto cercando di capire come creare una funzione che può accettare diversi tipi di dati come parametri. La funzione dovrebbe contare e restituire il numero di elementi in un array di caratteri o interi. Ho già due funzioni separate che lo faranno, ma mi piacerebbe davvero poter usare una funzione per entrambe le attività. C'è un modo per farlo in C?Creare una funzione C che accetta parametri di diversi tipi di dati

Grazie in anticipo!

risposta

5

Non esiste un sovraccarico di funzione standard in C (e non ci sono modelli), ma probabilmente si potrebbe esaminare le funzioni "printf-like" (o variadic functions) e forse possono fare ciò che è necessario. Se possibile, consentono una lista di parametri flessibile.

C'è un esempio here di tale funzione che accetta una matrice di numeri interi di dimensioni variabili.

Forse si potrebbe avere una firma funzione come void iterate(const char* format, ...); che usate nei seguenti modi:

iterate("char", some_char_array); // for char arrays/strings 

O

iterate("int", some_int_array); // for integer arrays 

Aniket rende un buon punto anche se, come si fa a contare gli elementi in un array intero? Se si passa un array int come argomento, è necessario passare anche la dimensione che sconfigge lo scopo del conteggio degli elementi nell'array (come già sapete che è la dimensione).

Presumo che non si conosca la dimensione ma si dispone di un valore di terminatore nell'array (ad esempio -1).

Ho hackerato qualcosa di veloce che in qualche modo fa quello che ti serve tenendo presente l'assunto sopra.

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

int iterate(const char* format, ...) 
{ 
    va_list ap; 
    va_start(ap, format); 

    if (strcmp(format, "char") == 0) 
    { 
     char* array = va_arg(ap, char*); 

     return strlen(array); 
    } 
    else if (strcmp(format, "int") == 0) 
    { 
     int j = -1; 
     int* int_array = va_arg(ap, int*); 
     while (int_array[++j] != -1) 
        ;  
     return j; 
    } 
    return 0; 
} 

int main() 
{ 
    printf("%d\n", iterate("char", "abcdef")); 
    int arr[] = {5, 4, 3, 2, 1, 0, -1}; 
    printf("%d\n", iterate("int", arr)); 

    return 0; 
} 

Questo stampa:

$ ./a.out 
6 
6 
+0

cos'è 'int size'? –

+0

Dimensioni dell'array? Lo chiarirò perché sembra non essere chiaro. – Nobilis

+0

beh se conosce la dimensione dell'array in anticipo, perché userà una funzione super come questa per inferire automaticamente il tipo e chiamare la funzione appropriata per calcolare la lunghezza dell'array? :-) –

1

È necessario impostare gli argomenti della funzione in un tipo void *. In questo modo, puoi passare diversi tipi di dati e digitare il cast in quello desiderato. Tuttavia, è necessario fare attenzione perché non esiste un modo garantito per "indovinare" correttamente il tipo a cui punta un void*.

2

In entrambi i casi, sarà necessario un qualche tipo di sistema di tipo-inferenze per dire al compilatore C quale funzione da chiamare. Il che significa che dovrai conoscere, in anticipo, il tipo di array che potresti inviare come parametro a questa "super funzione" della tua.

Non c'è "inferenza di tipo automatico" in C che può far riflettere sul tipo di dati in fase di esecuzione. Ancora meglio, potresti dover scrivere il tuo ambiente runtime per far sì che ciò accada.

Un modo hackish po 'banale per fare questo:

#include <stdio.h> 

size_t GetLengthOfArray(size_t sizeOfOneElementInArray, size_t sizeOfTheArrayInBytes) 
{ 
    return sizeOfTheArrayInBytes/sizeOfOneElementInArray; 
} 
int main(int argc, char *argv[]) 
{ 
    char cArr[10] = {'A','B','C','D','E','F','G','H','I','J'}; 
    int iArr[5] = {10,20,30,40,50}; 
    printf("%d is the length of cArr\n%d is the length of iArr",GetLengthOfArray(sizeof(cArr[0]),sizeof(cArr)), 
                   GetLengthOfArray(sizeof(iArr[0]),sizeof(iArr))); 
    return 0; 
} 
+0

C11 ha '_Generic'. – jxh

2

Quindi, supponiamo che i tuoi due funzioni sono chiamati sizeof_char_array e sizeof_int_array.

In C11, v'è una nuova funzionalità denominata "selezione generico" che vi permetterà di fare quello che vuoi con un relativamente semplice macro:

#define sizeof_array(X) \ 
    _Generic (*(X), \ 
       char: sizeof_char_array, \ 
       default: sizeof_int_array) (X) 

(non hanno nemmeno un'implementazione C11 per testare questo contro, quindi caveat emptor!)

Prima di C11, questo a volte veniva eseguito con una macro che utilizzava regolarmente funzioni con nome. È possibile definire una macro che chiama una funzione o l'altro a seconda di una macro argomento suggerimento:

#define sizeof_array(xtype, x) sizeof_ ## xtype ##_array(x) 

int a[] = { 1, 2, 3, 4, -1 }; 
char b[] = "abc"; 

sizeof_array(int, a); /* macro expands to sizeof_int_array(a) */ 
sizeof_array(char, b); /* macro expands to sizeof_char_array(b) */ 

Se l'argomento d'ingresso è davvero un array, è possibile utilizzare una macro per calcolare direttamente le sue dimensioni:

#define ARRAY_SZ(x) (sizeof(x)/((void *)x == &x ? sizeof(x[0]) : 0)) 

nel caso di una matrice, la seguente espressione è vero:

(void *)arr == &arr 

poiché l'indirizzo di un array ha la stessa posizione nella memoria, come l'indirizzo del suo primo elemento.

Quindi, la macro calcola: sizeof(arr)/sizeof(arr[0]). Poiché l'operatore sizeof riporta la dimensione in byte del suo argomento, l'espressione calcolata determina il numero di elementi nella matrice. Tuttavia, se si sta utilizzando una sentinella per calcolare la lunghezza, la macro ARRAY_SZ risulterà in una dimensione di almeno una più grande della lunghezza trovata che attraversa la matrice per la sentinella.

Nel caso in cui l'argomento non sia un array, l'espressione restituisce un'eccezione 0 per divisione.

+0

in senso stretto :-P, l'OP vuole chiamare due funzioni diverse da una funzione a seconda del tipo di dati contenuti nel puntatore. –

+0

Quindi immagino, lui vuole una sorta di sistema di inferenza di tipo. Solo il mio pensiero su questo. –

+0

@Aniket: Non ha molto senso per me, dal momento che non è possibile dedurre la lunghezza di un array dopo che è passato a una funzione. La lunghezza dell'array deve essere passata alla funzione (a meno che l'inferenza non sia effettuata attraverso un valore sentinella). – jxh

2

La risposta è abbastanza semplice. Hai bisogno di una funzione per questa attività. Basta provare questo pezzo di codice

#define len(array) sizeof(array)/sizeof(array[0]) 

e il gioco è fatto.

Problemi correlati