c模板编程pdf
‘壹’ C中实现模板
模版的功能,不能用c语言实现的!
这种功能,需要编译器的支持。
如果你不是想重载的话,倒是可以实现的。
你最好把问题再简化一下,我觉得我还不太理解你的意思。
‘贰’ C中的模板怎样使用 最好给个例子~
看看这个吧
http://www.njcc.e.cn/njhysite/njhygao_js/xuebao/xuebao0402/zhjm.doc
其他的见
C语言中实现模板函数的方法
在C语言中实现模板函数的方法:
各种用C语言实现的模板可能在使用形式上有所不同。
现以一个求和函数Sum为例,用C++Template可写如下:
template<classT,classR> RSum(constT*array,intn)
{
Rsum=0;
for(inti=0;i<n;++i)
sum+=i;
returnsum;
}
如果不是内置类型,该模板隐式地需要有RR::operator+=(T)运算符可用。
1. 使用函数指针作为Functor替换者
TypedefstructtagAddClass
{
Void(*add)(char*r1,constchar*r2);
IntelemSize;
Char sum[MAX_ELEM_SIZE];
}AddClass;
voidSum(AddClass*self,constchar*array,intn)
{
for(inti=0;i<n;++i)
self->add(self->sum,array+i*self->elemSize);
}
使用时:
…..
VoidAddInt(char*r1,constchar*r2)
{
*(long*)r1+=*(int*)r2;
}
AddClassaddClass={AddInt,2,0};
Intarray[100];
Read(array);
Sum(&addClass,array,100);
…..
2. 用宏作为Functor的替换者
#define GenSumFun(SumFunName,Add,RetType,ElemType) \
RetTypeSumFunName(constElemType*array,intn) \
{ \
RetTypesum=0; \
for(inti=0;i<n;++i) \
Add(sum,i); \
returnsum; \
}
使用时:
#defineAddInt(x,y) ((x)+=(y))
GenSumFun(SumInt,AddInt,long,int)
…..
Intarray[100];
Read(array);
Longsum=SumInt(array,100);
…..
3. 所有可替换参数均为宏
至少需要一个额外的文件(实现文件)为impsum.c
/*impsum.c*/
RetTypeFunName(constElemType*array,intn)
{
RetTypesum=0;
for(inti=0;i<n;++i)
Add(sum,i);
returnsum;
}
使用时:
#undef RetType
#undef FunName
#undef ElemType
#undef Add
#defineAddInt(x,y) ((x)+=(y))
#defineRetTypelong
#defineFunNameSumInt
#defineElemTypeint
#defineAdd AddInt
#includeimpsum.c
…..
Intarray[100];
Read(array);
Longsum=SumInt(array,100);
…..
4. 总结:
第一种方法,易于跟踪调试,但是效率低下,适用于对可变函数(函数指针)的效率要求不高,但程序出错的可能性较大(复杂),模板函数(Sum)本身很复杂,模板参数也比较复杂(add)的场合。
第二种方法,效率高,但很难跟踪调试,在模板函数和模板参数本身都很复杂的时候更是如此。
第三种方法,是我最近几天才想出的,我认为是最好的,在模板参数(Add)比较复杂时可以用函数(第二种也可以如此),简单时可以用宏,并且,易于调试。在模板函数本身很复杂,而模板参数比较简单时更为优越。但是,可能有点繁琐。
一般情况下,没有必要做如此劳心的工作,一切交给编译器去做就行了。但是本人在开发一个文件系统时,由于是基于一种少见的平台,没有可用的C++编译器,有几个函数,除了其中的类型不同(uint16和uint32),和几个可参数化的宏不同,其它地方完全相同,而函数本身很复杂(两百多行代码)。Copy出几个完全类似的函数副本,维护起来特别烦人。非常需要如此的编程模式,故此,分享出来,大家共同探讨。
‘叁’ 求一本《c专家编程》pdf非扫描版
链接: https://pan..com/s/1vvTsBaWnbv_dS8AdDoj_LQ
‘肆’ c语言编程在线急(用标签里的代码模板)
#include"stdio.h"
voidoutput(inta[],intn);
main()
{
intn,i,j,x,pos;
intc=0;//c表示有效的数据个数
inta[20];
scanf("%d",&n);
for(i=0;i<n;i++)//插入n个数据
{
scanf("%d",&x);
//查找插入的位置pos,并且向后移动数据
for(pos=c;pos>0;pos--)
if(x<a[pos-1])
a[pos]=a[pos-1];
else
break;
a[pos]=x;//在pos位置插入数据
c++;//个数加1
}
output(a,n);
return0;
}
voidoutput(inta[],intn)
{
inti;
for(i=0;i<n;i++)
printf("%d",a[i]);
printf(" ");
}
‘伍’ 在c语言中如何实现函数模板
如果要写个函数支持多种数据类型,首先想到的就是C++的模板了,但是有时候只能用C语言,比如在linux内核开发中,为了减少代码量,或者是某面试官的要求…
考虑了一阵子后,就想到了qsort上.qsort的函数原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );
快排时,只要自己实现相应数据类型的比较函数cmpare就可以了.如果比较int型时,一个典型的compare函数如下:
那么,就是说可以利用void *. void *意指未指定类型,也可以理解为任意类型。其他类型的指针可以直接赋值给void *变量,但是void *变量需要强制类型转换为其它指针类型。这个相信大家都知道。那么下面以一个简单的题目为例,来探讨如何在C语言中实现模板函数。
方法1: 利用void *.
在看下面的源程序之前,需要了解几点。首先,在32位平台上,任何类型的指针所占的字节都是4个字节,因为32位机器虚拟内存一般为4G,即2的32次方,只要32位即4个字节就可以足够寻址,sizeof(void *)=4; 其次,虽然各种不同类型的指针所占的空间都为4个字节,但是不同类型的指针所指的空间的字节数却不同(这一点尤为重要,下面的程序我在开始没有调通就因为这点意识不强)。所以,如果你将一个指针强制转换为另一个类型的指针,指针本身所占的字节是不变的,但是,如果对这个指针进行运算,比如 *p,p++,p-=1等一般都是不同的。 再次,函数指针应该了解下,这里不多说。 最后,因为Sandy跟我说,C++开始的时候模板的实现其实就是利用宏替换,在编译的时候确定类型。所以,为了方便,类型也用了预编译指令#define。
<span>#include"stdio.h"</span>
<span>#include"stdlib.h"</span>
<span>//typedefintT;//或者下面的也可以.</span>
<span>#defineTint</span>
//这个FindMin是Sandy写的.felix021也写了个,差不多的就不贴出来的.
voidFindMin(constvoid*arr,intarr_size,intarrmembersize,int*index,
int(*cmp)(constvoid*,constvoid*b)){
inti;
*index=0;
char*p=(char*)arr;
char*tmp=p;
for(i=1;i<arr_size;i++){
if(cmp(tmp,p)>0){
tmp=p;
}
p+=arrmembersize;
}
(*index)=((int)(tmp-arr))/arrmembersize;
}
*/</span>
可以把指针看作是char*,如果转换为int*,那下面的位移就不正确了.</span>
index<span>=</span>i<span>;</span>
<span>}</span>
<span>}</span>
<span>return</span>index<span>;</span>
<span>}</span>
<span>int</span>result<span>;</span><span>//result保存的是最小值索引.</span>
result<span>=</span>FindMin<span>(</span>arr,<span>12</span>,
‘陆’ c语言课程设计报告模板
课程设计报告内容
报告应包括以下内容:
摘要(300~400字)
目录
1. 概述
2. 课程设计任务及要求
2.1 设计任务
2.2 设计要求
3. 理论设计
3.1方案论证
3.2 系统设计
3.2.1 结构框图及说明
3.2.2 系统原理图及工作原理
3.3 单元电路设计
3.3.1单元电路工作原理
3.3.2元件参数选择
4. 系统设计
4.1 软件设计
4.2 编程过程
4.2 编程结果
5. 安装调试
5.2 安装调试过程
5.3 故障分析
6. 结论
7. 使用仪器设备清单
8. 收获、体会和建议
9. 参考文献
‘柒’ 求C语言pdf格式的几本书!!!
这几本在网上都可以找到的,C语言我建议你看的就是 K&R C程序设计,另一本要看的ANSI C标准,其它的都是浮云。。unix编程和系统编程 ,这两本太大了。。但是在网上都可以搜索到。。去google unix系统编程 filetype:pdf会搜索到的。。切记C和指针是拉圾 C缺陷和缺陷拉圾 C专家编程拉圾。。 我是过来人。。特别是ANSI C 标准 (在CSDN有下载 包括C++2011的标准) 看标准才是王道。另外就是你要多去悟,不要限于那些无用的技巧呀, 语法呀。。真的。。C语言学好了。。基本说你在编程语言这块没有问题了,剩下的就是主攻算法,啥MFC 啥reactos 都是浮云,看来楼主是喜欢linux,学linux去csdn下一下常规命令的源码,分析一下linux的源码你会大有长进。。
‘捌’ 求《LINUXC编程一站式学习》全文免费下载百度网盘资源,谢谢~
《LINUX C编程一站式学习》网络网盘pdf最新全集下载:
链接:https://pan..com/s/1wIgN0sfCc9gjkgPdARtUng
简介:通俗易懂的原理剖析,有非常适合初学者的code,有形象化的展示。本书分为两部分:第一部分讲解编程语言和程序设计的基本思想方法,让读者从概念上认识C语言。
‘玖’ 吐血整理:C++编程语言资源汇总
关于 C++ 框架、库和资源的一些汇总列表,内容包括:标准库、Web应用框架、人工智能、数据库、图片处理、机器学习、日志、代码分析等。有需要的小伙伴可以收藏一下!
C++标准库,包括了STL容器,算法和函数等。
C++ Standard Library:是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分。
Standard Template Library:标准模板库
C POSIX library : POSIX系统的C标准库规范
ISO C++ Standards Committee :C++标准委员会
C++通用框架和库
Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合
ASL :Adobe源代码库提供了同行的评审和可移植的C++源代码库。
Boost :大量通用C++库的集合。
BDE :来自于彭博资讯实验室的开发环境。
Cinder:提供专业品质创造性编码的开源开发社区。
Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。
Dlib:使用契约式编程和现代C++ 科技 设计的通用的跨平台的C++库。
EASTL :EA-STL公共部分
ffead-cpp :企业应用程序开发框架
Folly:由Facebook开发和使用的开源C++库
JUCE :包罗万象的C++类库,用于开发跨平台软件
libPhenom:用于构建高性能和高度可扩展性系统的事件框架。
LibSourcey :用于实时的视频流和高性能网络应用程序的C++11 evented IO
LibU : C语言写的多平台工具库
Loki :C++库的设计,包括常见的设计模式和习语的实现。
MiLi :只含头文件的小型C++库
openFrameworks :开发C++工具包,用于创意性编码。
Qt :跨平台的应用程序和用户界面框架
Reason :跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。
ROOT :具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。
STLport:是STL具有代表性的版本
STXXL:用于额外的大型数据集的标准模板库。
Ultimate++ :C++跨平台快速应用程序开发框架
Windows Template Library:用于开发Windows应用程序和UI组件的C++库
Yomm11 :C++11的开放multi-methods.
btsk : 游戏 行为树启动器工具
Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。
Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。
Boost.Asio:用于网络和底层I/O编程的跨平台的C++库。
libev :功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。
libevent :事件通知库
libuv :跨平台异步I/O。
音频,声音,音乐,数字化音乐库
FMOD :易于使用的跨平台的音频引擎和音频内容的 游戏 创作工具。
Maximilian :C++音频和音乐数字信号处理库
OpenAL :开源音频库—跨平台的音频API
Opus:一个完全开放的,免版税的,高度通用的音频编解码器
Speex:免费编解码器,为Opus所废弃
Tonic: C++易用和高效的音频合成
Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。
生物信息,基因组学和生物技术
libsequence:用于表示和分析群体遗传学数据的C++库。
SeqAn:专注于生物数据序列分析的算法和数据结构。
Vcflib :用于解析和处理VCF文件的C++库
Wham:直接把联想测试应用到BAM文件的基因结构变异。
压缩和归档库
bzip2:一个完全免费,免费专利和高质量的数据压缩
doboz:能够快速解压缩的压缩库
PhysicsFS:对各种归档提供抽象访问的库,主要用于视频 游戏 ,设计灵感部分来自于Quake3的文件子系统。
KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。
LZ4 :非常快速的压缩算法
LZHAM :无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。
LZMA :7z格式默认和通用的压缩方法。
LZMAT :及其快速的实时无损数据压缩库
miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。
Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。
Snappy :快速压缩和解压缩
ZLib :非常紧凑的数据流压缩库
ZZIPlib:提供ZIP归档的读权限。
并发执行和多线程
Boost.Compute :用于OpenCL的C++GPU计算库
Bolt :针对GPU进行优化的C++模板库
C++React :用于C++11的反应性编程库
Intel TBB :Intel线程构件块
Libclsph:基于OpenCL的GPU加速SPH流体仿真库
OpenCL :并行编程的异构系统的开放标准
OpenMP:OpenMP API
Thrust :类似于C++标准模板库的并行算法库
HPX :用于任何规模的并行和分布式应用程序的通用C++运行时系统
VexCL :用于OpenCL/CUDA 的C++向量表达式模板库。
C++ B-tree :基于B树数据结构,实现命令内存容器的模板库
Hashmaps: C++中开放寻址哈希表算法的实现
Bcrypt :一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。
BeeCrypt:
Botan: C++加密库
Crypto++:一个有关加密方案的免费的C++库
GnuPG: OpenPGP标准的完整实现
GnuTLS :实现了SSL,TLS和DTLS协议的安全通信库
Libgcrypt
libmcrypt
LibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支
LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具
libsodium:基于NaCI的加密库,固执己见,容易使用
Nettle 底层的加密库
OpenSSL : 一个强大的,商用的,功能齐全的,开放源代码的加密库。
Tiny AES128 in C :用C实现的一个小巧,可移植的实现了AES128ESB的加密算法
数据库,SQL服务器,ODBC驱动程序和工具
hiberlite :用于Sqlite3的C++对象关系映射
Hiredis: 用于Redis数据库的很简单的C客户端库
LevelDB: 快速键值存储库
LMDB:符合数据库四大基本元素的嵌入键值存储
MySQL++:封装了MySql的C API的C++ 包装器
RocksDB:来自Facebook的嵌入键值的快速存储
SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。
调试库, 内存和资源泄露检测,单元测试
Boost.Test:Boost测试库
Catch:一个很 时尚 的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。
CppUnit:由JUnit移植过来的C++测试框架
CTest:CMake测试驱动程序
googletest:谷歌C++测试框架
ig-debugheap:用于跟踪内存错误的多平台调试堆
libtap:用C语言编写测试
MemTrack —用于C++跟踪内存分配
microprofile- 跨平台的网络试图分析器
minUnit :使用C写的迷你单元测试框架,只使用了两个宏
Remotery:用于web视图的单一C文件分析器
UnitTest++:轻量级的C++单元测试框架
Cocos2d-x :一个跨平台框架,用于构建2D 游戏 ,互动图书,演示和其他图形应用程序。
Grit :社区项目,用于构建一个免费的 游戏 引擎,实现开放的世界3D 游戏 。
Irrlicht :C++语言编写的开源高性能的实时#D引擎
Polycode:C++实现的用于创建 游戏 的开源框架(与Lua绑定)。
CEGUI : 很灵活的跨平台GUI库
FLTK :快速,轻量级的跨平台的C++GUI工具包。
GTK+: 用于创建图形用户界面的跨平台工具包
gtkmm :用于受欢迎的GUI库GTK+的官方C++接口。
imgui:拥有最小依赖关系的立即模式图形用户界面
libRocket :libRocket 是一个C++ HTML/CSS 游戏 接口中间件
MyGUI :快速,灵活,简单的GUI
Ncurses:终端用户界面
QCustomPlot :没有更多依赖关系的Qt绘图控件
Qwt :用户与技术应用的Qt 控件
QwtPlot3D :功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件
OtterUI :OtterUI 是用于嵌入式系统和互动 娱乐 软件的用户界面开发解决方案
PDCurses 包含源代码和预编译库的公共图形函数库
wxWidgets C++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序
bgfx:跨平台的渲染库
Cairo:支持多种输出设备的2D图形库
Horde3D 一个小型的3D渲染和动画引擎
magnum C++11和OpenGL 2D/3D 图形引擎
Ogre 3D 用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非 游戏 引擎)
OpenSceneGraph 具有高性能的开源3D图形工具包
Panda3D 用于3D渲染和 游戏 开发的框架,用Python和C++编写。
Skia 用于绘制文字,图形和图像的完整的2D图形库
urho3d 跨平台的渲染和 游戏 引擎。
Boost.GIL:通用图像库
CImg :用于图像处理的小型开源C++工具包
CxImage :用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
FreeImage :开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
GDCM:Grassroots DICOM 库
ITK:跨平台的开源图像分析系统
Magick++:ImageMagick程序的C++接口
MagickWnd:ImageMagick程序的C++接口
OpenCV : 开源计算机视觉类库
tesseract-ocr:OCR引擎
VIGRA :用于图像分析通用C++计算机视觉库
VTK :用于3D计算机图形学,图像处理和可视化的开源免费软件系统。
最后, 对于学习编程或者在工作想升职的程序员兄弟,如果你想更好的提升你的编程能力帮助你提升水平! 笔者这里或许可以帮到你~
编程学习书籍分享:
编程学习视频分享:
分享(源码、项目实战视频、项目笔记,基础入门教程)
欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!
‘拾’ c语言编程
//计划做的脚本引擎的一部分
//参考的 C++编程艺术
//总地来说会有一些难度
//我的是C++应该会给你一些启发
//TypeDef.h
#include "windows.h"
#ifndef B_TYPE_DEF_H
#define B_TYPE_DEF_H
const int MAX_T_LEN = 128;//可以分析的最大符号长度(同时决定了一个字符变量的最大长度为128字节)
const int MAX_ID_LEN = 31;//允许的最大的标识长度(一个标识符是指一个变量名或函数名)
const int MAX_BUF_LEN = 1024;//解释缓冲区1024字节
const int NUM_PARAMS = 32;//最大参数数目
const int MAX_DIM_NUM = 65536//数组最大维数
//需要分析的所有东西
enum Token_Item { UNDEF=1, //未定义
E_TEMP,//当模板使用
E_CHAR,//char关键字
E_INT,//int关键字
E_FLOAT,//float关键字
E_SWITCH,//switch关键字
E_CASE,//case关键字
E_IF,//if关键字
E_ELSE,//else关键字
E_FOR,//for关键字
E_DO,//do关键字
E_WHILE,//while关键字
E_BREAK,//break关键字
E_RETURN,//return关键字
E_COUT,//cout关键字
E_CIN,//cin关键字
LBLOCK, //{
RBLOCK,//}
DOU,//,
EOS,//;
MAO,//:
SFEN,//'已舍弃,不含'分析
LT,//<
LE,//<=
GT,//>
GE,//>=
EQ,//==
NE,//!=
FF,//.
LK,//(
NOT,//!
INC,//++
DEC,//--
ADD,//+
SUB,//-
RK,//)
LZK,//[
RZK,//]
LS,//<<
RS,//>>
ASS,//=
AND,//&&
OR,//||
MUL,//*
DIV,///
MOD,//%
POW,//^
NUMBER, //数字
IDENTIFIER,//标识
STRING,//字符串
END//文件结束
};//需要分析的全部符号
enum Token_Type{
UNK,//未知类型
KEY,//关键字
FJF,//分界符
CMP,//比较运算符
OPE,//运算符
NUM,//数字
IDE,//标识符
STR,//字符串
NON,//结束符号
UDF//未定义
};
typedef struct Token_Table{//符号表
char name[MAX_T_LEN];
Token_Item token;
Token_Type type;
} TOKEN_TABLE,*PTOKEN_TABLE;
enum error_msg //错误类型
{ SYNTAX=1000, NO_EXP, NOT_VAR, DUP_VAR, DUP_FUNC,
SEMI_EXPECTED, UNBAL_BRACES, FUNC_UNDEF,
TYPE_EXPECTED, RET_NOCALL, PAREN_EXPECTED,
WHILE_EXPECTED, QUOTE_EXPECTED, DIV_BY_ZERO,
BRACE_EXPECTED, COLON_EXPECTED,FAIL_OPEN,ERROR_SIZE,
NO_MAIN,ERROR_ASSIGN,ERROR_RZK,ERROR_DIM};
class InterpExc { //错误类
error_msg err;
public:
InterpExc(error_msg e) { err = e; }
error_msg get_err() { return err; }
};
enum Vars{类型
V_Int,
V_Float,
V_String,
V_pInt,
V_pFloat,
V_pString,
V_Udef
};
#endif
#ifndef V_NULL
#define V_NULL (-1)
#endif
//Cfenxi.h
#include "TypeDef.h"
#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#include <string>
using namespace std;
//Fenxi类说明
//curr_pt始终指向将要分析的地址
//prev_pt为前一个分析的地址
//可以使用函数GotoPt来改变当前分析地址
//分析结果放在变量stoken,item,type
//在Cfenxi.cpp中定义了一个文件级变量TOKEN_TABLE tokentable[];
//在使用的时候必须声明这个变量
#ifndef B_CFENXI_H
#define B_CFENXI_H
class Fenxi{
public:
char stoken[MAX_T_LEN+1];//分析出来的符号名
char buff[MAX_BUF_LEN+1];//缓冲区
Token_Item item;//分析出来的具体符号
Token_Type type;//符号大类
long curr_pt;//当前分析点
long prev_pt;//前一个分析点
char pFileName[256];//脚本文件名
PTOKEN_TABLE pTokenTable;//符号表
public:
Fenxi(){};
~Fenxi(){};
void Create(char*,PTOKEN_TABLE,int);//创建分析对象
void GetToken();//分析一步
void GotoPt(long);//跳分析点
void PutBack();//回退一个分析点
private:
int nTableItem;//分析表中的分析数目
long iFileLength;//脚本文件长度
int iBlock;//当前所在区块
int iYouBiao;//当前游标
char cbuff;//当前所指向的字符
char cbuff1;//超前搜索的字符
void MoveNext();//向下移动
void MovePrev();//向前移动
void LoadBlock();//装入一个块
long GetPt(int i,int n){return (long)(i*MAX_BUF_LEN+n);};//计算位置
bool KeyLookUp(char*,Token_Item &);//查找是不是关键词
bool isdelim(char);
};
//解释类
class var_value{
public:
char string_value[MAX_T_LEN+1];
int int_value;
float float_value;
Vars v_type;
public:
var_value()
{
int_value=0;
float_value=0;
string_value[0]=0;
v_type=Udef;
}
var_value(const var_value&);
set_type(Vars type){v_type=type;}
~var_value(){}
friend bool operator == (const var_value& _X, const var_value& _Y);
friend bool operator < (const var_value& _X, const var_value& _Y);
};
class temp_var_value{
public:
char string_value[MAX_T_LEN+1];
int int_value;
float float_value;
int p_int;
int p_float;
int p_string;
vector<int> dim;
Vars v_type;
public:
temp_var_value()
{
int_value=0;
float_value=0;
string_value[0]=0;
p_int=p_float=p_string=V_NULL;
v_type=Udef;
};
temp_var_value(const temp_var_value&);
temp_set_type(Vars type){v_type=type;}
~temp_var_value(){}
friend bool operator == (const temp_var_value& _X, const temp_var_value& _Y);
friend bool operator < (const temp_var_value& _X, const temp_var_value& _Y);
};
struct var_type { //变量类型
char var_name[MAX_ID_LEN+1]; // 变量名
Vars v_type;//数据类型
vector<var_value> value; //变量值
vector<int> v_dim;//变量维数
int v_max;//变量的最大数目
};
struct func_type {
char func_name[MAX_ID_LEN+1]; //函数名
Vars ret_type; //返回值类型
long loc; // 函数入口点,函数的入口点是指分析点指向函数括号后第一个字符
};
class Script{
public:
Fenxi theFx;//词法分析对象,负责对脚本文件的操作
char FileName[256];//脚本文件名
var_value ret_value;//返回值
bool breakfound;//中断
public:
Script(){};
~Script(){};
void Create(char*,PTOKEN_TABLE,int);//创建脚本对象
void ExecuteScript();//开始解释脚本
private:
void PreScan();//预扫描
void decl_global();//声明全局变量
long find_func(char*);//返回函数的入口点
void ItemToVar(Token_Item,Vars&);//根据一个项,得到相当的变量类型
void CallFun();//执行一个函数
void get_args();//得到函数的形式参数名
void Interp();//具体解释
private:
void eval_exp (var_value &value);
void eval_exp0(var_value &value);
void eval_exp1(var_value &value);
void eval_exp2(var_value &value);
void eval_exp3(var_value &value);
void eval_exp4(var_value &value);
void eval_exp5(var_value &value);
void eval_exp6(var_value &value);
void eval_exp7(var_value &value);
void eval_exp8(var_value &value);
bool is_var(char *s);
// 变量名,变量的维数,变量的值,变量的类型
void assign_var(char *var_name,int idx, var_value value);
void find_var_value(char *var_name,int idx,var_value& value);
int find_idx(vector<int>,vector<int>);// 计算[][]
void find_vector(vector<int> &);//读取[]
int cal_idx(vector<int>);
Vars is_var_type;//使用is_var的时候如果返回值是真那么这个变量存储了变量类型
public:
//每执行一个函数的时候就把进入前的局部变量数目
//放到函数结点栈,函数执行完的时候就根据栈里的
//数据改变局部函数表里的变量,从而实现变量的灵活使用
//同理块结点栈的原理也一样
//变量表
vector<var_type> global_vars; //全局变量表
vector<var_type> local_var_stack; //局部变量表(函数参数作为局部变量处理)
vector<func_type> func_table; //函数表
stack<int> func_call_stack;//函数结点栈
stack<int> nest_scope_stack;//块结点栈
};
#endif
//Fenxi.cpp
#include "CFenxi.h"
#include <cstring>
#include <cctype>
#include <fstream>
#include <cstdio>
#include <cmath>
using namespace std;
///////////////////////////////////////////////////////////////////////
/////////////////////////词法分析类的函数定义//////////////////////////
///////////////////////////////////////////////////////////////////////
extern TOKEN_TABLE tokentable[]={
"char",E_CHAR,KEY,
"int",E_INT,KEY,
"float",E_FLOAT,KEY,
"switch",E_SWITCH,KEY,
"case",E_CASE,KEY,
"if",E_IF,KEY,
"else",E_ELSE,KEY,
"for",E_FOR,KEY,
"do",E_DO,KEY,
"while",E_WHILE,KEY,
"break",E_BREAK,KEY,
"return",E_RETURN,KEY,
"cout",E_COUT,KEY,
"cin",E_CIN,KEY,
"{",LBLOCK,FJF,
"}",RBLOCK,FJF,
",",DOU,FJF,
";",EOS,FJF,
"<",LT,CMP,
"<=",LE,CMP,
">",GT,CMP,
">=",GE,CMP,
"==",EQ,CMP,
"!=",NE,CMP,
".",FF,OPE,
"(",LK,OPE,
")",RK,OPE,
"[",LZK,OPE,
"]",RZK,OPE,
"++",INC,OPE,
"--",DEC,OPE,
"<<",LS,OPE,
">>",RS,OPE,
"=",ASS,OPE,
"!",NOT,OPE,
"&&",AND,OPE,
"||",OR,OPE,
"+",ADD,OPE,
"-",SUB,OPE,
"*",MUL,OPE,
"/",DIV,OPE,
"%",MOD,OPE,
"^",POW,OPE,
};
var_value::var_value(const var_value& p)
{
int_value=p.int_value;
float_value=p.float_value;
strcpy(string_value,p.string_value);
v_type=p.v_type;
}
bool operator == (const var_value& _X, const var_value& _Y)
{
if (_X.v_type != _Y.v_type)
{
return false;
}
else
{
switch (_X.v_type)
{
case V_Float:
return (abs(_X.float_value - _Y.float_value) < 0.0001);
break;
case V_Int:
return (_X.int_value == _Y.int_value);
break;
case V_Int:
return !(strcmp(_X.string_value, _Y.string_value));
break;
default:
return false;
}
}
}
bool operator < (const var_value& _X, const var_value& _Y)
{
if (_X.v_type != _Y.v_type)
{
return false;
}
else
{
switch (_X.v_type)
{
case V_Float:
return (_X.float_value < _Y.float_value);
break;
case V_Int:
return (_X.int_value < _Y.int_value);
break;
case V_Int:
return !(strcmp(_X.string_value, _Y.string_value));
break;
default:
return false;
}
}
temp_var_value::temp_var_value(const temp_var_value& p)
{
int_value=p.int_value;
float_value=p.float_value;
strcpy(string_value,p.string_value);
p_int=p.p_int;
p_float=p.p_float;
p_string=p.p_string;
v_type=p.v_type;
}
void Fenxi::Create(char* p,PTOKEN_TABLE ptt,int n)
{
strcpy(pFileName,p);
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(0,ios::end);
iFileLength=fin.tellg();
fin.close();
if(iFileLength==0)
throw InterpExc(ERROR_SIZE);
iBlock=0;
LoadBlock();
MoveNext();//指向第一个字符
iYouBiao=0;//置游标于文件头
curr_pt=0;
prev_pt=0;
cbuff=buff[0];//当前应该分析字符
cbuff1=buff[1];//超前搜索字符
pTokenTable=ptt;
nTableItem=n;//分析表设置
}
void Fenxi::MoveNext()
{
if(iYouBiao==MAX_BUF_LEN-1)//如果当前游标在缓冲区尾
{
iBlock++;
LoadBlock();
cbuff=buff[0];
cbuff1=buff[1];//超前搜索
}
else
{
iYouBiao++;
cbuff=buff[iYouBiao];
if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
{
char temp[2];
temp[1]=0;
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*(iBlock+1));
fin.read(temp,1);
int i=fin.gcount();
temp[i]=0;
fin.close();
cbuff1=temp[0];
}
else
cbuff1=buff[iYouBiao+1];
}
curr_pt=GetPt(iBlock,iYouBiao);
}
void Fenxi::MovePrev()
{
if(iYouBiao==0)//如果当前游标在缓冲区头
{
cbuff1=cbuff;//超前搜索
iBlock--;
LoadBlock();
iYouBiao=MAX_BUF_LEN-1;
cbuff=buff[iYouBiao];
}
else
{
cbuff1=cbuff;//超前搜索
iYouBiao--;
cbuff=buff[iYouBiao];
}
curr_pt=GetPt(iBlock,iYouBiao);
}
void Fenxi::PutBack()
{
GotoPt(prev_pt);
}
void Fenxi::LoadBlock()//装入一个块
{
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*iBlock);
fin.read(buff,MAX_BUF_LEN);
int i=fin.gcount();
buff[i]=0;
iYouBiao=0;
fin.close();
}
void Fenxi::GotoPt(long pt)
{
if(pt/MAX_BUF_LEN==curr_pt/MAX_BUF_LEN)//如果是在同一个块内的话
{
curr_pt=pt;
iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
cbuff=buff[iYouBiao];
}
else//否则要重新装入内存
{
curr_pt=pt;
iBlock=curr_pt/MAX_BUF_LEN;
LoadBlock();
iYouBiao=curr_pt-iBlock*MAX_BUF_LEN;
cbuff=buff[iYouBiao];
}
if(iYouBiao==MAX_BUF_LEN-1)//超前搜索
{
char temp[2];
temp[1]=0;
ifstream fin(pFileName,ios::in|ios::binary);
fin.seekg(MAX_BUF_LEN*(iBlock+1));
fin.read(temp,1);
int i=fin.gcount();
temp[i]=0;
fin.close();
cbuff1=temp[0];
}
else
cbuff1=buff[iYouBiao+1];
}
void Fenxi::GetToken()
{
prev_pt=curr_pt;//保存前一个的位置
char *temp; //利用一个指针向字符里写内容
item=UNDEF;type=UDF;
temp = stoken;
*temp = '\0';
// 如果当前字符是空格且未到文件末
while(isspace(cbuff) && cbuff) MoveNext();
// 跳过行
while(cbuff == '\r') {
MoveNext();
MoveNext();
while(isspace(cbuff) && cbuff) MoveNext();
}
// 是否结尾
if(cbuff == '\0') {
*stoken = '\0';
item = END;
type=NON;
return ;
}
// 检查{}标识符
if(strchr("{}", cbuff)) {
stoken[0]=cbuff;
stoken[1]='\0';
type=FJF;
if(cbuff=='{')
item=LBLOCK;
else
item=RBLOCK;
MoveNext();//指向下一个字符
return ;
}
// 检查注释信息
if(cbuff == '/')
if(cbuff1 == '*') { // /*注释符
MoveNext();
MoveNext();
do { // 找到结尾
while(cbuff != '*') MoveNext();
MoveNext();
} while (cbuff != '/');
MoveNext();
GetToken();
return;
} else if(cbuff1 == '/') { // is a // CMPment
MoveNext();
MoveNext();
// Find end of CMPment.
while(cbuff != '\r' && cbuff != '\0') MoveNext();
if(cbuff == '\r') {MoveNext();MoveNext();}
GetToken();
return;
}
// 检查双操作符
if(strchr("!<>=+-&|", cbuff)) {
switch(cbuff) {
case '|':
if(cbuff1 == '|') {
MoveNext();MoveNext();
*temp = '|';
temp++;
*temp = '|';
temp++;
*temp = '\0';
item=OR;
type=OPE;
}
break;
case '&':
if(cbuff1 == '&') {
MoveNext();MoveNext();
*temp = '&';
temp++;
*temp = '&';
temp++;
*temp = '\0';
item=AND;
type=OPE;
}
break;
case '=':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '=';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=EQ;
type=CMP;
}
break;
case '!':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '!';
temp++;
*temp = '=';
temp++;
*temp = '\0';
item=NE;
type=CMP;
}
break;
case '<':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '=';
item=LE;
type=CMP;
}
else if(cbuff1 == '<') {
MoveNext();MoveNext();
*temp = '<';
temp++;
*temp = '<';
item=LS;
type=OPE;
}
else {
MoveNext();
*temp = '<';
item=LT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '>':
if(cbuff1 == '=') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '=';
item=GE;
type=CMP;
} else if(cbuff1 == '>') {
MoveNext();MoveNext();
*temp = '>';
temp++;
*temp = '>';
item=RS;
type=OPE;
}
else {
MoveNext();
*temp = '>';
item=GT;
type=CMP;
}
temp++;
*temp = '\0';
break;
case '+':
if(cbuff1 == '+') {
MoveNext();MoveNext();
*temp = '+';
temp++;
*temp = '+';
temp++;
*temp = '\0';
item=INC;
type=OPE;
}
break;
case '-':
if(cbuff1 == '-') {
MoveNext();MoveNext();
*temp = '-';
temp++;
*temp = '-';
temp++;
*temp = '\0';
item=DEC;
type=OPE;
}
break;
}
if(*stoken) return;
}
// 其它运算符号
if(strchr("+-*^/=().[]|!%", cbuff)) {
type=OPE;
switch(cbuff){
case '+':
item=ADD;break;
case '-':
item=SUB;break;
case '*':
item=MUL;break;
case '/':
item=DIV;break;
case '=':
item=ASS;break;
case '(':
item=LK;break;
case ')':
item=RK;break;
case '[':
item=LZK;break;
case ']':
item=RZK;break;
case '.':
item=FF;break;
case '|':
item=UNDEF;type=UDF;break;
case '!':
item=NOT;break;
case '%':
item=MOD;break;
}
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
return ;
}
// 分界符号
if(strchr(";,#:", cbuff)) {
type=FJF;
switch(cbuff){
case ';':
item=EOS;break;
case ',':
item=DOU;break;
case ':':
item=MAO;break;
}
*temp = cbuff;
MoveNext();
temp++;
*temp = '\0';
return ;
}
// 读取一个字符串
if(cbuff == '"') {
MoveNext();
while(cbuff != '"' && cbuff != '\r' && cbuff) {
// Check for \n escape sequence.
if(cbuff == '\\') {
if(cbuff1 == 'n') {
MoveNext();
*temp++ = '\n';
}
}
else if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
if(cbuff == '\r' || cbuff == 0)
throw InterpExc(SYNTAX);
MoveNext(); *temp = '\0';
item=STRING;
type=STR;
return ;
}
// 读取一个数字
if(isdigit(cbuff)) {
while((cbuff>='0'&&cbuff<='9')||(cbuff=='.')) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
*temp = '\0';
item=NUMBER;
type=NUM;
return ;
}
// Read identifier or keyword.
if(isalpha(cbuff)) {
while(!isdelim(cbuff)) {
if((temp - stoken) < MAX_T_LEN)
*temp++ = cbuff;
MoveNext();
}
item=E_TEMP;
}
*temp = '\0';
// Determine if token is a keyword or identifier.
if(item == E_TEMP) { // convert to internal form
if(KeyLookUp(stoken,item)) type=KEY; // is a keyword
else {type = IDE;item=IDENTIFIER;}
}
if(type==UDF)
throw InterpExc(SYNTAX);
}
bool Fenxi::KeyLookUp(char *s,Token_Item &it){
int i;
// char *p;
// 转为小写字母
// p = s;
// while(*p) { *p = tolower(*p); p++; }
for(i=0; i<nTableItem; i++) {
if((tokentable[i].type==KEY)&&!strcmp(tokentable[i].name, s))
{
it=tokentable[i].token;
return true;
}
}
return false;
}
// 符号检查
bool Fenxi::isdelim(char c)
{
if(strchr(" !:;,+-<>/*^=().|&[]\"%", c) || c == 9 ||
c == '\r' || c == 0) return true;
return false;
}