2013-07-16 4 views
5

Я относительно новичок в языке программирования C, и я пытаюсь понять, как создать функцию, которая может принимать разные типы данных в качестве параметров. Функция должна рассчитывать и возвращать количество элементов в массиве символов или целых чисел. У меня уже есть две отдельные функции, которые будут делать это, но мне бы очень хотелось иметь возможность использовать одну функцию для обеих задач. Есть ли способ сделать это в C?Создайте функцию C, которая принимает параметры разных типов данных

Заранее благодарен!

ответ

5

В C нет стандартных перегрузок функций (и нет шаблонов), но вы могли бы, вероятно, изучить функции «printf-like» (или variadic functions), и, возможно, они могут делать то, что вам нужно. В любом случае они допускают список гибких параметров.

Существует такая here такая функция, которая принимает целочисленный массив с переменным размером.

Возможно, вы могли бы иметь сигнатуру, такую ​​как void iterate(const char* format, ...); использовать в следующих случаях:

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

Или

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

Aniket делает хорошую точку, хотя, как вы считаете элементы в целочисленном массиве? Если вы передадите массив int в качестве аргумента, вам нужно будет также передать размер, который побеждает цель подсчета элементов в массиве (как вы уже знаете, то есть размер).

Я предполагаю, что вы не знаете размер, но у вас есть значение терминатора в массиве (например, -1).

Я взломал что-то быстрое, что любопытное делает то, что вам нужно, с учетом вышеупомянутого предположения.

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

Печатается:

$ ./a.out 
6 
6 
+0

Что такое 'int size'? –

+0

Размер массива? Я проясню это, поскольку кажется, что это не ясно. – Nobilis

+0

Хорошо, если он знает размер массива перед рукой, почему он будет использовать суперфункцию, подобную этой, чтобы автоматически вывести тип и вызвать соответствующую функцию для вычисления длины массива? :-) –

1

Вы должны сделать аргументы своей функции в формате void *. Таким образом, вы можете передавать разные типы данных и вводить их в соответствии с тем, который вы хотите. Однако вам нужно следить, потому что нет гарантированного способа правильно «угадать» тип, на который указывает void*.

2

В любом случае, вам понадобится какой-то системы вывода типов сказать C компилятор, который вызываемая функция. Это означает, что вам нужно будет знать, какой тип массива вы можете отправить в качестве параметра этой «суперфункции» вашего.

В C нет «автоматического ввода-вывода», который позволяет вам отражать тип данных во время выполнения. Еще лучше, вам, возможно, придется написать собственную среду выполнения, чтобы это произошло.

Немного тривиальный хак способ сделать это:

#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 имеет '_Generic'. – jxh

2

Итак, давайте предположим, что ваши две функций называется sizeof_char_array и sizeof_int_array.

В C11, есть новая функция под названием «общий выбор», который позволит вам делать то, что вы хотите с относительно простым макросом:

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

(я даже не имеет реализаций C11, чтобы проверить это против, так что предостережение emptor!)

До C11 это иногда выполнялось с помощью макроса с использованием регулярно названных функций. Вы можете определить макрос, который будет вызывать одну функцию или другой в зависимости от макро аргумента намек:

#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) */ 

Если входной аргумент действительно массив, вы можете использовать макрос, чтобы вычислить его размер напрямую:

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

В случае массива, следующее выражение истинно:

(void *)arr == &arr 

Поскольку адрес массива имеет такое же расположение в памяти как адрес его первого элемента.

Итак, макрос вычисляет: sizeof(arr)/sizeof(arr[0]). Поскольку оператор sizeof сообщает размер в байтах своего аргумента, вычисленное выражение приводит к количеству элементов в массиве. Тем не менее, если вы используете дозорный элемент для вычисления длины, макрос ARRAY_SZ приведет к размеру, по крайней мере, одного размера, чем длина найденного перемещения массива для дозорного.

В случае, если аргумент не является массивом, тогда выражение приводит к исключению с разделителем на 0.

+0

, строго говоря: -P, OP хочет вызывать две разные функции от одной функции в зависимости от типа данных, которые имеет указатель. –

+0

Так что, я думаю, он хочет какую-то систему ввода-вывода. Просто моя мысль об этом. –

+0

@Aniket: Это не имеет большого значения для меня, поскольку вы не можете вывести длину массива после того, как он передан функции. Длина массива должна быть передана функции (если только вывод не сделан через контрольное значение). – jxh

2

Ответ довольно прост. Вам нужна функция для этой задачи. Просто попробуйте этот кусок кода

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

и все.

Смежные вопросы