因为百度空间没有了,所及将以前写的一篇关于C语言粘贴符的使用的随笔迁移至此。

最近在百度知道看到有关C语言泛型的问题因为举例比较长,在这里作为回答,并作为C语言知识的记录,如果有不同意见,欢迎大家互相探讨,其实我的模拟泛型的思路就是使用粘贴符##以及宏定义完成。下面举例双向链表的实现,代码如下:

#include "stdafx.h"
#include <string.h> // 这里是对双向链表的定义,相当于泛型模板
#define DECLARE(node_type) struct node_type##_node{struct node_type##_node* priv; struct node_type##_node* next; node_type value;}
// 这里是初始化一个给定节点的宏定义,node是一个结构体,如果是指针,会出现错误。
#define INIT_LINK_NODE(node) do{node.priv=NULL, node.next=NULL;}while(0)
// 这个宏定义初始化一个给定指针的node,node必须是指针,否则会出现错误。
#define INIT_LINK_NODE_P(pnode) do{node->priv=NULL, node->next=NULL;}while(0)
// 这个宏定义用来定义一个value为type类型的变量
#define NEW(type, var_name) struct type##_node var_name
// 这个宏定义用来定义一个value为type类型的node数组
#define ARRAY(type, var_name, len) struct type##_node var_name[len]
// 这个宏用来引用value值类型为type的node类型,例如可用在 sizeof(TYPE(int))
// 这样就计算出了value值类型为int的node节点的字节长度。
#define TYPE(type) struct type##_node typedef struct people_{
char name[50];
long birthday;
char hobby[100];
}people; // 以下是对具体类型链表的声明。
DECLARE(int); // 声明一个value类型是int类型的链表node
DECLARE(double); // 声明一个value类型是double类型的链表node
DECLARE(people); // 声明一个value类型是struct_node类型的node int _tmain(int argc, _TCHAR* argv[])
{
// 接下来就是测试是否能够正常使用链表的时候
NEW(int, int_node);
NEW(double, double_node);
NEW(people, people_node);
ARRAY(int, int_node_array, 10);
ARRAY(double, double_node_array, 10);
ARRAY(people, people_node_array, 10); // 接下来分别测试value值类型分别为int,double, people
// 的node类型。
int_node.next = NULL;
int_node.priv = NULL;
int_node.value = 300;
printf("int_node{priv:%d, next:%d, value:%d}\n",
(int)int_node.priv, (int)int_node.next, int_node.value); double_node.next = NULL;
double_node.priv = NULL;
double_node.value = 3.5268;
printf("double_node{priv:%d, next:%d, value:%f}\n",
(int)double_node.priv, (int)double_node.next, double_node.value); people_node.next = NULL;
people_node.priv = NULL;
strcpy(people_node.value.name, "Tom");
people_node.value.birthday = 19000425;
strcpy(people_node.value.hobby, "basketball");
printf("people_node{priv:%d, next:%d, "
"value{name:%s, birthday: %d, hobby:%s}}\n",
(int)people_node.priv, (int)people_node.next, &people_node.value.name,
people_node.value.birthday, &people_node.value.hobby); //ARRAY(int, int_node_array, 10);
//ARRAY(double, double_node_array, 10);
//ARRAY(people, people_node_array, 10);
// 接下来分别测试数组。
// --------------------------整形数组
int_node_array[0].priv = NULL;
int_node_array[0].next = &(int_node_array[1]);
int_node_array[0].value = 0;
for(int i = 1; i < 9; i++)
{
int_node_array[i].priv = &(int_node_array[i-1]);
int_node_array[i].next = &(int_node_array[i+1]);
int_node_array[i].value = i;
}
int_node_array[9].priv = &(int_node_array[8]);
int_node_array[9].next = NULL;
int_node_array[9].value = 9;
TYPE(int)* p_int_node = &(int_node_array[0]);
while(NULL != p_int_node)
{
printf("int_node{priv:%d, next:%d, value:%d}\n",
(int)p_int_node->priv, (int)p_int_node->next, p_int_node->value);
p_int_node = p_int_node->next;
} // ------------------------------double类型数组
double_node_array[0].priv = NULL;
double_node_array[0].next = &double_node_array[1];
double_node_array[0].value = 5.2;
for(int i = 1; i < 9; i++)
{
double_node_array[i].priv = &double_node_array[i-1];
double_node_array[i].next = &double_node_array[i+1];
double_node_array[i].value = i + 0.56657;
}
double_node_array[9].priv = &double_node_array[8];
double_node_array[9].next = NULL;
double_node_array[9].value = 9.5;
TYPE(double)* p_double_node = &double_node_array[0];
while(NULL != p_double_node)
{
printf("double_node_array{priv:%d, next:%d, value:%f}\n",
(int)p_double_node->priv, (int)p_double_node->next, p_double_node->value);
p_double_node = p_double_node->next;
} // ------------------------------people类型数组
people_node_array[0].next = &people_node_array[1];
people_node_array[0].priv = NULL;
strcpy(people_node_array[0].value.name, "Tom_a");
people_node_array[0].value.birthday = 19000425;
strcpy(people_node_array[0].value.hobby, "basketball_a");
for(int i = 1; i < 9; i++)
{
people_node_array[i].priv = &people_node_array[i-1];
people_node_array[i].next = &people_node_array[i+1];
strcpy(people_node_array[i].value.name, people_node_array[i-1].value.name);
strcpy(people_node_array[i].value.hobby, people_node_array[i-1].value.hobby);
people_node_array[i].value.birthday = people_node_array[i-1].value.birthday+1;
people_node_array[i].value.name[4]++;
people_node_array[i].value.hobby[11]++;
}
people_node_array[9].priv = &people_node_array[8];
people_node_array[9].next = NULL;
strcpy(people_node_array[9].value.name, people_node_array[8].value.name);
strcpy(people_node_array[9].value.hobby, people_node_array[8].value.hobby);
people_node_array[9].value.birthday = people_node_array[8].value.birthday+1;
people_node_array[9].value.name[4]++;
people_node_array[9].value.hobby[11]++;
TYPE(people)* p_people_node = &people_node_array[0];
while(NULL != p_people_node)
{
printf("people_node{priv:%d, next:%d, "
"value{name:%s, birthday: %d, hobby:%s}}\n",
(int)p_people_node->priv, (int)p_people_node->next, p_people_node->value.name,
p_people_node->value.birthday, p_people_node->value.hobby);
p_people_node = p_people_node->next;
} return 0;
}

本例在VS2010下运行结果如下:

如果使用visual studio 2015 运行代码,需要将strcpy改成strcpy_s,否则会提示错误。

C语言模拟泛型-粘贴符##的使用 迁移的更多相关文章

  1. JAVA语言中的修饰符

    JAVA语言中的修饰符 -----------------------------------------------01--------------------------------------- ...

  2. 语言模拟ATM自动取款机系统

    C语言实验报告       题目名称:C语言模拟ATM自动取款机系统 C语言模拟实现ATM自动取款机功能:输入密码,余额查询,取款,存款,转账,修改密码,退出功能: 代码实现的功能: 账号及密码输入: ...

  3. Swift3.0语言教程使用占位符格式创建和初始化字符串

    Swift3.0语言教程使用占位符格式创建和初始化字符串 Swift3.0语言教程使用占位符格式创建和初始化字符串在很多的编程语言中都存在占位符,占位符就是为指定的内容占留一个位置.此功能一般在开发者 ...

  4. 关于c语言模拟c++的多态

    关于c++多态,个人认为就是父类调用子类的方法,c++多态的实现主要通过虚函数实现,如果类中含有虚函数,就会出现虚函数表,具体c++多态可以参考<深度探索c++对象模型> c语言模拟多态主 ...

  5. c语言模拟c++的继承和多态

    //C++中的继承与多态 struct A { virtual void fun() //C++中的多态:通过虚函数实现 { cout << "A:fun()" < ...

  6. C语言学习笔记--接续符和转义符

    1.C语言中的接续符 (1)编译器将反斜杠剔除,跟在反斜杠后面的字符自动接续到前一行 (2)在接续单词时,反斜杠之后不能有空格,反斜杠下一行之前也不能有空格 (3)接续符适合在宏定义代码块时使用 #i ...

  7. C#深入学习:泛型修饰符in,out、逆变委托类型和协变委托类型

    在C#中,存在两个泛型修饰符:in和out,他们分别对应逆变委托和协变委托. 我们知道,在C#中要想将一个泛型对象转换为另一个泛型对象时,必须要将一个泛型对象拆箱,对元素进行显式或隐式转换后重新装箱. ...

  8. Java C# C语言中的占位符

    一般拼接一段字符串在编程中是很常见的事,下面简单做个总结: 什么是占位符?占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号. 1.Java中处理方法: package com.amos; ...

  9. C语言::模拟实现strlen函数

    题目要求 编写一个C语言程序模拟实现strlen函数. 算法 strlen函数功能是计算字符串中字符的个数.(除\0外) 而字符串本身就是一个字符数组,只不过末尾以\0结束. 因此,我们只需遍历除\0 ...

  10. C语言宏定义##连接符和#符的使用(MFC就是靠##自动把消息和消息函数对应起来了,借助宏来减少switch case代码的编写量)

    C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...

随机推荐

  1. Mac Adobe Photoshop 2025 安装与激活保姆级教程

    为什么选择Photoshop? 作为全球顶尖的图像处理软件,Adobe Photoshop凭借其强大的功能和生态兼容性,成为设计师.摄影师.创意工作者的必备工具.本文以最新版Photoshop 202 ...

  2. 写Leetcode 对业务代码是帮助的

    业务中遇到的表结构以及场景如下: id name pid 1 A 0 2 A 1 3 A 2 4 B 0 5 B 4 6 B 5 7 C 0 8 D 7 9 E 8 是一个层级结构,名字可能相同,也可 ...

  3. flink基础之window

    flink会把数据分成不同的窗口,然后进行汇总和统计. flink的窗口分为timeWindow, countWindow, sessionWindow, gapWindow. timeWindow分 ...

  4. 重磅预告 | 开源家族又添新成员!12月16日Molecule在Github、Gitee等你

    ​ 随着全球开源生态的持续性发展,开源项目数量呈现指数级的增长,并逐渐覆盖全栈技术领域.袋鼠云数栈技术开源团队一直秉承着"源于开源 回馈开源"的理念,坚持以技术为核心,开源开放.不 ...

  5. ATM2.0模块版

    ATM项目开发 (1)在主程序文件中创建程序入口 (2)在核心代码文件(视图层)搭建程序框架 (3)进行代码功能分配 - ATM 项目根目录 - README.md 项目说明书 - start.py ...

  6. hbuilderx打包ios应用和上传应用商店最简单方法

    hbuilderx是一个跨平台的开发软件,一般的软件公司,电脑使用的是windows系统. 那么windows有没有办法开发ios应用呢,因为ios的证书和上传,好像都需要mac电脑来完成. 其实,国 ...

  7. C# 中使用线程、Task和 ThreadPool 的并发性

    C# 中的并发性涉及使用线程和任务等功能在程序中同时执行任务.这就像让多个工人同时完成不同的工作.这在现代应用程序中至关重要,因为它使它们更快.响应更迅速.并发性可确保我们的应用程序平稳运行,快速响应 ...

  8. C# 设置dll 别名

    extern alias VideoFFMPEGX64;using VideoFFMPEGX64::Accord.Video.FFMPEG;

  9. MQTT网关连接华为云物联网平台应用

    1.概述 ZLAN5143D是一款专门为工业环境设计的RS485设备数据采集器/物联网网关,兼具串口服务器.Modbus网关.MQTT网关.RS485转JSON等多种功能于一体.如图 1所示,可以连接 ...

  10. sass 定义全局变量

    定义变量文件 随便写一个scss文件,比如在 src/assets/var.scss $my-color: #00b96b; 打包工具配置 不同工具 如webpack.vite有不同的处理方式加载到全 ...