Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
模拟C语言中的模板(针对队列数据类型)_C_Templates - Fatal编程技术网

模拟C语言中的模板(针对队列数据类型)

模拟C语言中的模板(针对队列数据类型),c,templates,C,Templates,我试图用C实现一个队列结构;队列只能容纳ints,不能容纳其他内容。我想知道我是否可以在C中模拟C++模板(可能通过使用预处理器#define),这样我的队列可以容纳任何数据类型 注意:我不想使用void*。我认为这有点冒险,很容易导致奇怪的运行时错误。实现一个包含void*数据的队列,并将此void*解释为指向任何类型,甚至是int之类的基本类型的指针 使用#define是可能的,但是考虑一下调试,如果出现问题…如果您真的想这样做,可以通过简单的typedef来解决: typedef int

我试图用C实现一个
队列
结构;队列只能容纳
int
s,不能容纳其他内容。我想知道我是否可以在
C
中模拟
C++
模板(可能通过使用预处理器
#define
),这样我的
队列可以容纳任何数据类型


注意:我不想使用
void*
。我认为这有点冒险,很容易导致奇怪的运行时错误。

实现一个包含void*数据的队列,并将此void*解释为指向任何类型,甚至是int之类的基本类型的指针

使用#define是可能的,但是考虑一下调试,如果出现问题…

如果您真的想这样做,可以通过简单的
typedef
来解决:

typedef int data_t;

struct queue
{
  data_t* data;
}

您现在可以在所有位置使用
data\u t
,而不是普通的
int
s。但是,请注意,你不能同时使用多个类型(至少,我不知道C++ C++模板的特定行为如何在普通C中模拟)。因为,这些宏只会扩展一次,所以您最多只能得到一个可以重新键入的数据结构,但一旦处理,整个程序的数据结构就是这种类型


这意味着您需要考虑<代码>空白> /COD>类型解决方案,这削弱了C的类型检查。若要尝试修复弱化类型检查,请考虑在结构中嵌入“类型”字段,该字段是“在结构中赋值一次”字符串,表示非空洞*类型。然后,您可以改进与维护结构相关的函数中缺少类型检查的情况。也就是说,如果这样的事情对你来说甚至很重要的话。

那么,我脑海中唯一想到的可能就是宏(
#define
s)。可能是这样的:

队列.h:

#define TYPE int
#define TYPED_NAME(x) int_##x
#include "queue_impl.h"
#undef TYPE
#undef TYPED_NAME

#define TYPE float
#define TYPED_NAME(x) float_##x
#include "queue_impl.h"
#undef TYPE
#undef TYPED_NAME
...
队列\u impl.h:

//no include guard, of course
typedef struct
{
    TYPE *data;
    ...
} TYPED_NAME(queue);

void TYPED_NAME(queue_insert) (TYPED_NAME(queue) *queue, TYPE data)
{
    ...
}
如果它能工作(我不是100%确定,因为我不是这样的预处理器专家),它应该给你结构
int\u queue
float\u queue
,以及函数

void int_queue_insert(int_queue *queue, int data);
void float_queue_insert(float_queue *queue, float data);
当然,对于所有需要的类型,您必须自己实例化“模板”,但这相当于重复
queue.h
中的5行块。实际实现只需编写一次。当然,您可以进一步完善这一点,但基本思想应该是明确的

这将至少为您提供完全类型安全的队列模板,尽管缺乏完全匹配接口的便利性(函数必须带有类型名,因为C不支持重载函数)


但我不确定这是您想要的…

这里有一个版本,可以让您实例化(通过预处理器)并在同一个C文件中使用多种类型(小心,它使用):


您可以使用微妙和丑陋的技巧来创建此类模板。下面是我要做的:

创建模板化列表 宏来定义列表 我首先创建一个宏,我们称之为
define\u list(type)
,它将为给定类型的列表创建所有函数。然后,我将创建一个全局结构,其中包含指向所有列表函数的函数指针,然后在列表的每个实例中都有一个指向该全局结构的指针(请注意,它与。这种事情,

#定义列表(类型)\
\
结构列表类型\
\
类型定义结构\
{ \
int(*为空)(常量结构列表类型*)\
大小(*大小)(常量结构列表类型*)\
常量类型(*前面)(常量结构列表类型*)\
void(*推前)(结构列表类型*,类型)\
}_列表u函数35;#类型\
\
类型定义结构列表元素类型\
{ \
类型数据\
结构列表元素类型*下一步\
}列表元素类型\
\
typedef结构u列表35;#类型\
{ \
大小(t)大小;\
首先列出元素类型*\
列表元素类型*\u最后\
_列出u函数35;#类型*_函数\
}列表类型\
\
列表类型*新列表类型()\
bool list_为空35;##类型(const list_35;##类型*列表)\
大小列表大小类型(常数列表类型*列表)\
常数类型列表u前35;#类型(常数列表##类型*列表)\
无效列表u push 35; front 35;#type(列表###type*list,type elem)\
\
布尔列表为空类型(常量列表类型*列表)\
{ \
返回列表->\u size==0\
} \
\
大小列表大小类型(常数列表类型*列表)\
{ \
返回列表->\u大小\
} \
\
常数类型列表u前35;#类型(常数列表##类型*列表)\
{ \
返回列表->\u第一->\u数据\
} \
\
无效列表u推35;前35;##类型(列表###类型*列表,类型elem)\
{ \
... \
} \
\
_列表函数类型列表函数类型={\
&列表为空类型\
&列表大小类型\
&列表前面的类型\
&列表(推)前(推###类型)\
}; \
\
列表类型*新列表类型()\
{ \
List##type*res=(List##type*)malloc(sizeof(List#type))\
res->_size=0\
res->_first=NULL\
res->_functions=&_list_funcs_35;#type\
返回res\
}
#定义列表(类型)\
列表类型
#定义新列表(类型)\
新的列表类型()
通用接口 以下是一些宏,它们通过存储的函数指针简单地调用列表的函数:

#定义为空(集合)\
集合->函数->为空(集合)
#定义大小(集合)\
集合->函数->大小(集合)
#定义前端(集合)\
收集->功能->前部(收集)
#定义推送前端(集合、元素)\
收集->功能->向前推送(收集,元素)
请注意,如果使用相同的结构来设计列表以外的其他集合,则可以使用la
#define q(t)                                    \
  typedef struct _q_##t {t v; struct q_##t *next} q_##t;

q(char);
q(int);

int              main(void)
{
  q_char         qc;
  q_int          qi;

  qc.v = 'c';
  qc.next = (void *) 0;

  qi.v = 42;
  qi.next = (void *) 0;

  return 0;
}
#include <stdio.h>

#define DEFINE_LL_NODE(CONCRETE_TYPE) \
  struct node_of_ ## CONCRETE_TYPE \
    { \
      CONCRETE_TYPE data; \
      struct node_of_ ## CONCRETE_TYPE *next; \
    };

#define DECLARE_LL_NODE(CONCRETE_TYPE,VARIABLE_NAME) \
  struct node_of_ ## CONCRETE_TYPE VARIABLE_NAME;

/* Declarations for each type.  */
DEFINE_LL_NODE(int)
DEFINE_LL_NODE(char)

int main (void)
{
  /* Declaration of instances of each type.  */
  DECLARE_LL_NODE (int, foo)
  DECLARE_LL_NODE (char, bar)

  /* And you can then use these instances.  */
  foo.data = 1;
  foo.next = NULL;

  bar.data = 'c';
  bar.next = NULL;
}
struct node_of_int { int data; struct node_of_int *next; };

struct node_of_char { char data; struct node_of_char *next; };

int main (void)
{
  struct node_of_int foo;
  struct node_of_char bar;

  foo.data = 1;
  foo.next = ((void *)0);

  bar.data = 'c';
  bar.next = ((void *)0);
}
#include <stdio.h>

#define MaxIndex 100

int Find(int A[])
{
    int j;

    for (j = 0; j < MaxIndex; ++j) {
        if (A[j] < 0) {
            return j;
        }
    }

    return -1;
}

int main(void)
{
    // reminder: MaxIndex is 100.
    int A[MaxIndex];

    /**
     * anonymous scope #1
     *     initialize our array to [0..99],
     *     then set 18th element to its negative value(-18)
     *     to make the search more interesting.
     */
    {
        // loop index, nothing interesting here.
        int i;

        // initialize our array to [0..99].
        for (i = 0; i < MaxIndex; ++i) {
            A[i] = i * i;
        }

        A[17]= -A[17];
    }

    /**
     * anonymous scope #2
     *     find the index of the smallest number and print it.
     */
    {
        int result = Find(A);

        printf(
            "First negative integer in A found at index = %d.\n",
            result
        );
    }

    // wait for user input before closing.
    getchar();

    return 0;
}
/**
 * Make sure that all the options needed are given in order to create our array.
 */
#ifdef OPTION_UNINSTALL
    #undef OPTION_ARRAY_TYPE
    #undef OPTION_ARRAY_LENGTH
    #undef OPTION_ARRAY_NAME    
#else 
    #if (!defined OPTION_ARRAY_TYPE) || !defined OPTION_ARRAY_LENGTH || (!defined OPTION_ARRAY_NAME)
        #error "type, length, and name must be known to create an Array."
    #endif

    /** 
     * Use the options to create a structure preserving structure for our array.
     *    that is, in contrast to pointers, raw arrays.
     */
    struct {
        OPTION_ARRAY_TYPE data[OPTION_ARRAY_LENGTH];
    } OPTION_ARRAY_NAME;

    /**
     * if we are asked to also zero out the memory, we do it.
     * if we are not granted access to string.h, brute force it.
     */
    #ifdef OPTION_ZERO_MEMORY
        #ifdef OPTION_GRANT_STRING
            memset(&OPTION_ARRAY_NAME, 0, OPTION_ARRAY_LENGTH * sizeof(OPTION_ARRAY_TYPE));
        #else
            /* anonymous scope */
            {
                int i;
                for (i = 0; i < OPTION_ARRAY_LENGTH; ++i) {
                    OPTION_ARRAY_NAME.data[i] = 0;
                }
            }
        #endif
        #undef OPTION_ZERO_MEMORY
    #endif
#endif
#include <stdio.h>

int Find(int A[], int A_length)
{
    int j;

    for (j = 0; j < A_length; ++j) {
        if (A[j] < 0) {
            return j;
        }
    }

    return -1;
}

int main(void)
{
    // std::array<int, 100> A;
    #define OPTION_ARRAY_TYPE int
    #define OPTION_ARRAY_LENGTH 100
    #define OPTION_ARRAY_NAME A
    #include "SimpleArray.h"    

    /**
     * anonymous scope #1
     *     initialize our array to [0..99],
     *     then set 18th element to its negative value(-18)
     *     to make the search more interesting.
     */
    {
        // loop index, nothing interesting here.
        int i;

        // initialize our array to [0..99].
        for (i = 0; i < (sizeof(A.data) / sizeof(A.data[0])); ++i) {
            A.data[i] = i * i;
        }

        A.data[17]= -A.data[17];
    }

    /**
     * anonymous scope #2
     *     find the index of the smallest number and print it.
     */
    {
        int result = Find(A.data, (sizeof(A.data) / sizeof(A.data[0])));

        printf(
            "First negative integer in A found at index = %d.\n",
            result
        );
    }

    // wait for user input before closing.
    getchar();

    // making sure all macros of SimpleArray do not affect any code
    // after this function; macros are file-wide, so we want to be 
    // respectful to our other functions.
    #define OPTION_UNINSTALL
    #include "SimpleArray.h"

    return 0;
}
/**
 * this is a smart collection that is created using options and is 
 *      removed from scope when included with uninstall option.
 *
 * there are no guards because this header is meant to be strategically
 *     installed and uninstalled, rather than kept at all times.
 */
#ifdef OPTION_UNINSTALL
    /* clean up */
    #undef ARRAY_FOREACH_BEGIN
    #undef ARRAY_FOREACH_END
    #undef ARRAY_LENGTH
#else
    /** 
     * array elements vary in number of bytes, encapsulate common use case 
     */
    #define ARRAY_LENGTH(A) \
        ((sizeof A.data) / (sizeof A.data[0]))

    /**
     * first half of a foreach loop, create an anonymous scope,
     * declare an iterator, and start accessing the items. 
     */
    #if defined OPTION_ARRAY_TYPE
        #define ARRAY_FOREACH_BEGIN(name, iter, arr)\
            {\
                unsigned int iter;\
                for (iter = 0; iter < ARRAY_LENGTH(arr); ++iter) {\
                    OPTION_ARRAY_TYPE name = arr.data[iter];
    #endif

    /** 
     * second half of a foreach loop, close the loop and the anonymous scope 
     */
    #define ARRAY_FOREACH_END \
            }\
        }
#endif
/**
 * Make sure that all the options needed are given in order to create our array.
 */
#ifdef OPTION_UNINSTALL
    #ifndef OPTION_ARRAY_TYPE
        #undef OPTION_ARRAY_TYPE
    #endif

    #ifndef OPTION_ARRAY_TYPE    
        #undef OPTION_ARRAY_LENGTH
    #endif

    #ifndef OPTION_ARRAY_NAME    
        #undef OPTION_ARRAY_NAME    
    #endif

    #ifndef OPTION_UNINSTALL
        #undef OPTION_UNINSTALL
    #endif
#else 
    #if (!defined OPTION_ARRAY_TYPE) || !defined OPTION_ARRAY_LENGTH || (!defined OPTION_ARRAY_NAME)
        #error "type, length, and name must be known to create an Array."
    #endif

    /** 
     * Use the options to create a structure preserving structure for our array.
     *    that is, in contrast to pointers, raw arrays.
     */
    struct {
        OPTION_ARRAY_TYPE data[OPTION_ARRAY_LENGTH];
    } OPTION_ARRAY_NAME;

    /**
     * if we are asked to also zero out the memory, we do it.
     * if we are not granted access to string.h, brute force it.
     */
    #ifdef OPTION_ZERO_MEMORY
        #ifdef OPTION_GRANT_STRING
            memset(&OPTION_ARRAY_NAME, 0, OPTION_ARRAY_LENGTH * sizeof(OPTION_ARRAY_TYPE));
        #else
            /* anonymous scope */
            {
                int i;
                for (i = 0; i < OPTION_ARRAY_LENGTH; ++i) {
                    OPTION_ARRAY_NAME.data[i] = 0;
                }
            }
        #endif
        #undef OPTION_ZERO_MEMORY
    #endif
#endif
/**
 * this is a smart collection that is created using options and is 
 *      removed from scope when included with uninstall option.
 *
 * there are no guards because this header is meant to be strategically
 *     installed and uninstalled, rather than kept at all times.
 */
#ifdef OPTION_UNINSTALL
    /* clean up, be mindful of undef warnings if the macro is not defined. */
    #ifdef ARRAY_FOREACH_BEGIN
        #undef ARRAY_FOREACH_BEGIN
    #endif

    #ifdef ARRAY_FOREACH_END
        #undef ARRAY_FOREACH_END
    #endif

    #ifdef ARRAY_LENGTH
        #undef ARRAY_LENGTH
    #endif
#else
    /** 
     * array elements vary in number of bytes, encapsulate common use case 
     */
    #define ARRAY_LENGTH(A) \
        ((sizeof A.data) / (sizeof A.data[0]))

    /**
     * first half of a foreach loop, create an anonymous scope,
     * declare an iterator, and start accessing the items. 
     */
    #if defined OPTION_ARRAY_TYPE
        #define ARRAY_FOREACH_BEGIN(name, iter, arr)\
            {\
                unsigned int iter;\
                for (iter = 0; iter < ARRAY_LENGTH(arr); ++iter) {\
                    OPTION_ARRAY_TYPE name = arr.data[iter];
    #endif

    /** 
     * second half of a foreach loop, close the loop and the anonymous scope 
     */
    #define ARRAY_FOREACH_END \
            }\
        }
#endif
#include <stdio.h>

// std::array<int, 100> A;
#define OPTION_ARRAY_TYPE int
#define OPTION_ARRAY_LENGTH 100
#define OPTION_ARRAY_NAME A
#include "SimpleArray.h"  
#define OPTION_UNINSTALL
#include "SimpleArray.h"  

int Find(int A[], int A_length)
{
    int j;

    for (j = 0; j < A_length; ++j) {
        if (A[j] < 0) {
            return j;
        }
    }

    return -1;
}

int main(void)
{
    #define OPTION_ARRAY_NAME A
    #define OPTION_ARRAY_LENGTH (sizeof(A.data) / sizeof(A.data[0]))
    #define OPTION_ARRAY_TYPE int

    #include "SimpleArray.h"

    /**
     * anonymous scope #1
     *     initialize our array to [0..99],
     *     then set 18th element to its negative value(-18)
     *     to make the search more interesting.
     */
    {
        #include "SimpleArrayUtils.h"

        printf("size: %d.\n", ARRAY_LENGTH(A));

        ARRAY_FOREACH_BEGIN(item, i, A)
            A.data[i] = i * i;
        ARRAY_FOREACH_END

        A.data[17] = -A.data[17];


        // uninstall all macros.
        #define OPTION_UNINSTALL
        #include "SimpleArrayUtils.h"
    }

    /**
     * anonymous scope #2
     *     find the index of the smallest number and print it.
     */
    {
        #include "SimpleArrayUtils.h"        
        int result = Find(A.data, (sizeof(A.data) / sizeof(A.data[0])));

        printf(
            "First negative integer in A found at index = %d.\n",
            result
        );

        // uninstall all macros.
        #define OPTION_UNINSTALL
        #include "SimpleArrayUtils.h"
    }

    // wait for user input before closing.
    getchar();

    // making sure all macros of SimpleArray do not affect any code
    // after this function; macros are file-wide, so we want to be 
    // respectful to our other functions.
    #define OPTION_UNINSTALL
    #include "SimpleArray.h"

    return 0;
}
<?php
    class SimpleArray {
        public $length;
        public $name;
        public $type;

        function __construct($options) {
            $this->length = $options['length'];
            $this->name = $options['name'];
            $this->type = $options['type'];
        }

        function getArray() {
            echo ($this->name . '.data');
        }

        function __toString() {            
            return sprintf (
                "struct {\n" .
                "    %s data[%d];\n" .
                "} %s;\n"
                ,
                $this->type,
                $this->length,
                $this->name
            );          
        }
    };
?>
#include <stdio.h>
<?php include('SimpleArray.php'); ?>

int Find(int *A, int A_length)
{
    int i;

    for (i = 0; i < A_length; ++i) 
    {
        if (A[i] < 0) {
            return i;
        }
    }

    return -1;
}

int main(int argc, char **argv)
{
    <?php 
        $arr = new SimpleArray(array(
            'name' => 'A',
            'length' => 100,
            'type' => 'int'
        ));
        echo $arr;
    ?>

    printf("size of A: %d.\n", <?php echo($arr->length); ?>);

    /* anonymous scope */
    {
        int i;

        for (i = 0; i < <?php echo($arr->length)?>; ++i) {
            <?php $arr->getArray(); ?>[i] = i * i;
        }   
        <?php $arr->getArray(); ?>[17] = -<?php $arr->getArray()?>[17];
    }

    int result = Find(<?php $arr->getArray();?>, <?php echo $arr->length; ?>);
    printf(
        "First negative integer in A found at index = %d.\n",
        result
    );

    getchar();       

    return 0;
}
gcc main.c -o main
./main