当前位置:首页 » 编程软件 » c模板编程

c模板编程

发布时间: 2022-10-03 05:29:26

⑴ 在c语言中如何实现函数模板

各种用
C
语言实现的模板可能在使用形式上有所不同。现以一个求和函数
Sum
为例,用
C++
Template
可写如下:
template
R
Sum(const
T
*array,
int
n)
{
R
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
sum
+=
i;
return
sum;
}
如果不是内置类型,该模板隐式地需要
有R
R::operator+=(T)运算符可用。
1.
使用函数指针作为
Functor
替换者
Typedef
struct
tagAddClass
{
Void
(*add)(char*
r1,
const
char*
r2);
Int
elemSize;
Char
sum[MAX_ELEM_SIZE];
}
AddClass;
void
Sum(AddClass*
self,
const
char*
array,
int
n)
{
for
(int
i
=
0
;
i
<
n
;
++i)
self->add(self->sum,
array
+
i*self->elemSize);
}
使用时:
Void
AddInt(char*
r1,
const
char*
r2)
{
*(long*)r1
+=
*(int*)r2;
}
AddClass
addClass
=
{AddInt,
2,
0
};
Int
array[100];
Read(array);
Sum(&addClass,
array,
100);
…..
2.
用宏作为Functor的替换者
#define
GenSumFun(SumFunName,
Add,
RetType,
ElemType)
RetType
SumFunName
(const
ElemType
*array,
int
n)
\
{
RetType
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
Add(sum,
i);
return
sum;
}
使用时:
#define
AddInt(x,
y)
((x)
+=
(y))
GenSumFun(SumInt,
AddInt,
long,
int)
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
…..
3.
所有可替换参数均为宏
至少需要一个额外的文件(实现文件)为
impsum.c
/*
impsum.c
*/
RetType
FunName(const
ElemType
*array,
int
n)
{
RetType
sum
=
0;
for
(int
i
=
0
;
i
<
n
;
++i)
Add(sum,
i);
return
sum;
}
使用时:
#undef
RetType
#undef
FunName
#undef
ElemType
#undef
Add
#define
AddInt(x,
y)
((x)
+=
(y))
#define
RetType
long
#define
FunName
SumInt
#define
ElemType
int
#define
Add
AddInt
#include
impsum.c
…..
Int
array[100];
Read(array);
Long
sum
=
SumInt(array,
100);
4.
总结:
第一种方法,易于跟踪调试,但是效率低下,适用于对可变函数(函数指针)的效率要求不高,但程序出错的可能性较大(复杂),模板函数(Sum)本身很复杂,模板参数也比较复杂(add)的场合。
第二种方法,效率高,但很难跟踪调试,在模板函数和模板参数本身都很复杂的时候更是如此。
第三种方法,是我最近几天才想出的,我认为是最好的,在模板参数(Add)比较复杂时可以用函数(第二种也可以如此),简单时可以用宏,并且,易于调试。在模板函数本身很复杂,而模板参数比较简单时更为优越。但是,可能有点繁琐。

⑵ 用C++语言编写程序实现:设计一个函数模板,实现用冒泡法对10 个某类型数据按升序排序

冒泡排序算法的运作如下:

1、比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2、对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。

3、针对所有的元素重复以上的步骤,除了最后一个。

4、持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

这里只需套用函数模板,将元素的类型设为模板变量即可,代码如下:

template<typenameItem>
voidsort(Item*arr)
{
inti,j;
Itemtemp;

for(j=0;j<9;j++)
for(i=0;i<9-j;i++)
{
if(arr[i]>arr[i+1])
{
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
}
}

⑶ 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++函数模板替代函数编写

一楼的很有意思,你这篇文章其实是很经典的,但与本问题无关...

问题在这一句:

string e = myfunc("aa", "bbb");

编译器已经很明确地告诉你了,不能把2个指针相加,因为在用双引号括起来的字符都是所谓的C风格字符串,即以一个指针来标明其首个字符并以'/0'作为结束信号的字符串,比如:

const char* p = "hello, world!";

如果你将其打出,如:

cout << p;

则指针p便会把其指向的字符逐个打印出来,再遇到'\0'时结束。

在你的问题中,由于"aa"和"bbb"无法被转化为string类,所以编译器不会调用这个函数:

string myfunc(string a, string b)
{
string c = a + b;
return c;
}

而是为它们生成了特定的模版:

char* myfunc(char* a, char* b);

由于两个指针的相加是没有被定义的,所以编译器报错。

由于string e = myfunc("aa", "bbb")中的"aa"和"bbb"被默认作为了C风格的字符串,而编译器没有定义一种隐式的转换方法可以把C风格字符串转化为string类,所以你必须通过显式地把它们转换为string类字符串,可以这样:

string e = myfunc(string("aa"),string("bbb"));

或者用更加一目了然且安全但烦琐而冗长的C++式cast句法:

string e = myfunc(static_cast<string>("aa"), static_cast<string>("bbb"));

另外说下用了模版的话你的这个函数就可以砍掉了:

string myfunc(string a, string b)
{
string c = a + b;
return c;
}

另外如果你不想烦琐地每次调用myfunc来实现2个字符的相加都要通过cast的话也可以把myfunc模板实例化:

#include <iostream>
#include <string>
#include <cmath>
#include <cstring>
using namespace std;

template<class T>
T myfunc(T a,T b){
T c=a+b;
return c;
}
// 模板实例化
template<> const char* myfunc<const char*>(const char* a, const char* b)
{
string temp = string(a) + string(b);
return temp.c_str(); // 结果可能出乎你的预料~
}

// 或者

// 模板实例化
/* template<> const char* myfunc<const char*>(const char* a, const char* b)
{
char* pa = new char[sizeof a + sizeof b];
const char* pc = strcat(strcpy(pa, a), b);
delete [] pa;

return pc; // 同上
}*/

int main(){
int c;
float d;
c=myfunc(3,4);
cout<<c<<endl;
d=myfunc(3.4,4.7);
cout<<d<<endl;
string e=myfunc("aa","bbb");
cout<<e<<endl;
system("pause");
return 0;
}

你运行这个程序得到的e可能是乱码,原因可见一楼的部分提示:

8. 不要再写 char* p = "XXX" 这种语句,要写成 const char* p = "XXX",编译器之所以让前者通过编译是为了兼容以前的大量的旧代码。
BTW:const TYPE* p 和 TYPE const* p 是一样的,风格不同而已。
BTW:C语言中也有const关键字。

详细可见:

http://community.csdn.net/Expert/TopicView3.asp?id=5085350

⑸ 在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语言编程

//计划做的脚本引擎的一部分
//参考的 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;
}

⑺ c++模板概念是什么详细点

有以下这样3个求加法的函数:
int Add(int x,int y)
{
return x+y;
}

double Add(double x,double y)
{
return x+y;
}

long Add(long x,long y)
{
return x+y;
}
它们拥有同一个函数名,相同的函数体,却因为参数类型和返回值类型不一样,所以是3个完全不同的函数。即使它们是二元加法的重载函数,但是不得不为每一函数编写一组函数体完全相同的代码。如果从这些函数中提炼出一个通用函数,而它又适用于多种不同类型的数据,这样会使代码的重用率大大提高。那么 C++的模板就可解决这样的问题。模板可以实现类型的参数化(把类型定义为参数),从而实现了真正的代码可重用性。C++中的模板可分为函数模板和类模板,而把函数模板的具体化称为模板函数,把类模板的具体化成为模板类。

⑻ 如何学习C++编程

大一学习的c++,工作之后也一直用的c++。

1. 涵盖c++入门到精通的图书列表

《The C programming language》必读
《C++ Primer》,号称是一本可以让你从C或java程序员转为一个真正的C++程序员的入门参考书,必读。
《The C++ programming language》,C++之父,人称B教主着作,在看过C++ primer后,应该可以跳章选读。
《Think in c++》,网上说此书的中文版翻译质量奇差,推荐看影印版,选读。
《Effective c++》,类似 Effective java,讲的是最佳实践,程序员必读。


《More effective c++》,上书的补充。
《The C++ standard library》,会写C,不会用标准库怎么行。这就跟java程序员不会用java.util包一样,必读。
《Effective STL》,STL库的最佳实践。Effective C++作者又一力作,必读。
《The annotated STL source》,STL源码分析,这本书应该算是深入/精通类了,选读。
《Generic programming and STL》,号称C++编程里,就是跟模板,泛型打交道,那么精通泛型是势在必行。

《C++ Template》,C++模板编程,代码复用的经验之道,必读。

《Exceptional C++》,跟Effective C++类似,属于最佳实践和难题解析,书中列出了许多应用场景和实例代码供读者揣摩,选读。

《More Exceptional C++》,上书的补充。

《Exceptional C++ Style》,上上书的补充

《Inside The C++ Object Model》,有了上面这些书做铺垫,那么终于可以读此神书了。它会带你游览C++对象模型的底层实现机制。读完此书,任何C++代码看起来如同行云流水,必读。

2. 优秀的C/C++开源项目(阅读代码)

OS:Linux kernel LVS、Linux应用程序

DB:Mysql、PostgreSQL

Complier:VM、GCC

Framework:OpenSip、SipProxy、

Net:ACE(Java Mina、Netty)、TCP/IP、HTTP协议栈

Cache:Memcached、Redis、

Library:STL(java util package)、Boost、Qt(UI)、

balance:Apache、Nginx

GSL

地址:https://github.com/microsoft/GSL

Boost文档

地址:https://www.boost.org/doc/libs/

wxWidgets官网

地址:http://wxwidgets.org/

gtkmm

地址:https://www.gtkmm.org/en/

CopperSpice

地址:https://www.copperspice.com/

Qt

地址:https://www.qt.io/Eigen

地址:http://eigen.tuxfamily.org/index.php?title=Main_Page#Documentation

Plot utils

地址:https://www.gnu.org/software/plotutils/

Asio

地址:https://think-async.com/Asio/

POCO

地址:https://pocoproject.org/

abseil

地址:https://abseil.io/

C++开源库汇总列表

地址:https://en.cppreference.com/w/cpp/links/libs

除了这些开源项目,也可以找一些免费的公开课,那这里也推荐一个ACM金牌大佬讲授的免费C++课程,可以去体验一下:

学好C++才是入职大厂的敲门砖! 当年要是有这课,我的C++也不至于这样

已失效

3.C++语法讲解

  • 语言基础
    详细介绍变量、表达式、语句、指针、数组、流程控制、函数、文件组织等。

  • 抽象机制 - 面向对象编程
    深入讲解C++的抽象机制,封装(类)、继承、多态;操作符重载、函数对象、异常处理等。

  • 模板 - 泛型编程
    详细介绍C++的模板机制,类模板、函数模板、模板特化等方面的内容。

  • 4.深入c++面向对象

    4.1、从C到C++

  • 引用和指针:为什么引用很重要

  • const关键字:为什么const很重要

  • 名字空间 (namespace)

  • 4.2、深入C++对象

  • 关于C++对象
    内置类型的对象,如int、double对象,自定义类型的对象

  • 对象类型的定义
    关键字class和struct
    类成员:成员函数和数据成员
    静态数据成员
    成员的访问控制
    对象的size
    关于this指针
    onst成员函数、const究竟修饰什么
    mutable数据成员
    4种特殊成员函数:constructor、destructor、 constructor、operator=
    对象的构造、初始化列表
    对象的析构
    对象的复制
    什么情况下有必要显式定义4种特殊函数
    C++对象生命周

  • 4.3、操作符重载

  • 关于C++中操作符重载机制

  • 重要操作符重载
    算术运算:+, -, *, /, %, ++, --, ...
    关系运算:>, <, ==, !=
    下标存取:[ ]
    函数调用:(),函数对象
    类型转换、单参数构造函数与隐式转换、阻止隐式转换 -- explicit关键字

  • 友元与成员

  • 4.4、面向对象基础 -- 继承

  • 基类与派生类

  • 再谈对象的构造与析构

  • 虚函数、纯虚函数

  • 派生类的内存布局、虚函数表

  • 多态、多态类型、如何体现多态

  • 虚析构、为什么虚析构很重要

  • 4.5、关于继承更多的话题

  • 多继承

  • 虚继承与虚基类

  • 对基类的访问、public / protected / private继承

  • Down cast:static_cast<>和dynamic_cast<>

  • 运行期类型识别 (RTTI)

  • 4.6、C++与面向对象设计

  • C++语言机制提供了完整的OOP支持

  • 超越继承

  • OOP若干法则和设计模式

  • 5.C++泛型编程与STL

    5.1、C++ 模板机制

    5.2、STL 概要

    5.3、STL容器
    5.4、STL迭代

    5.5、STL算法

    5.6、预与定义STL数对象

    5.7、STL适配器

    6. C++进阶

  • 《C++ Primer》

  • 最新版本:第三版(第四版国外已上架, 国内一些网上书店也在预订中)

  • 适合有丰富C经验,缺乏C++经验的。不过我个人一直认为此书带着过于强烈的C语言的痕迹,对于C++的学习未必是 好事。

  • 《The C++ Programming Language》/《C++程序设计语言》

  • 最新版本:第三版特别版

  • 简称 TC++PL,有其他语言的丰富经验的。(也有人简称之为“TCPL”,但需与另一本《The C Programmer Language》区分开来)

  • 《Essential C++》

  • 《Accelerated C++》

  • 这两本薄一些,都是不错的选择。《Accelerated C++》本人没有读过,从各方面的评价来看,完全值得推荐。

  • 以上几本书都有相应的中文版,而且翻译的质量都不错。上面的书未必都需要读一遍,但无论如何,TC++PL是应该阅读的。


  • 《Effective C++》

  • 最新版本:第二版(第三版国外已上架,国内一些网上书店也在预订中)

  • 简称EC。C++程序员必读!很多时候,我们说C++圣经不是指TC++PL,而是这一本。《The Pragmatic Programmer》一书中写到:“一旦你发现自己要参与C++项目的开发,赶快跑(不要走)到书店去购买Scott Mayer的《Effective C++》,可能还要《More Effective C++》”。

  • 《C++ Coding Standards: 101 Rules, Guidelines, and Best Practices》/《C++ 编程规范》

  • 个人认为此书应为C++程序员必备的案头书。几乎Effective系列和Exceptional系 列都在这里得到了总结。最新的模版、异常的业界经验都在这里的到了体现。可能的唯一缺陷就是对一个新手而言,关于“为什么这么做”的问题,解释的不够。

  • 我 的看法是:如果你不理解其中的条款,记忆,并且照做;如果你理解其中的条款,我猜你一定会同意书中的观点。我认为这本书中的内容至少在2009年以前都不 会过时,人们将广为传诵它制定的101条戒律。

  • 还不知道他的简称,也许“101”会成为一个候选者?

  • 提到《Effective C++》,那么另外三本书一一浮出水面:

  • 《More Effective C++》

  • 《Exceptional C++》

  • 《More Exceptional C++》。

  • 新书《Exceptional C++ Style》也是值得一看的好书。

  • 上 述几本书,一本也不应该放过。

  • 个人建议上述书籍按顺序阅读。并且,在将来反复阅读这几本书。
  • 《Thinking in C++》/《C++编程思想》
    这本书及其中文版传言好坏都有,没有认真看过,不做评价,如果确有兴趣,不妨尝试 一下该书。

    以下几本书基本上涉及的都是语言本身,大体上可以按照以下的顺序阅读。

    《C++必知必会》
    如果早一年,这本书将是重量级的,然而它被101和《Exceptional C++ Style》盖过一头。

    《C++ Gotchas: Avoiding Common Problems in Coding and Design》/《C++程序设计陷阱》
    这又是一本我未曾读过,而且广受好评的书。

    《STL 源码剖析》
    这本书我刚到手,就被人"借"走,以至于到现在也没有看过。看过这本书的朋友,可以给一个合适的评价。

    7. C++进阶之数据结构基础

    这是所有编程语言中最应该学习的部分,程序组成的基础之一。

    顺序存储、链式存储、循环链表;

    双向链表、栈(顺序和链式)、队列(顺序和链式);

    栈的应用、树基本概念及遍历、二叉树;

    排序算法、并归算法、选择、插入、快速、希尔。

    以上这些内容你知道吗?

    8. C++进阶之UI界面开发

    掌握QT类库构架,图形界面开发模型;

    掌握QT开发技巧,消息机制,图形处理;

    掌握QT网络编程,UDP,TCP使用方式;

    掌握QT文件处理方式,序列化;

    掌握QT在windows,linux,ios,android不同平台下的移植技术。

    9. C++进阶之Unix/Linux网络服务器

    掌握Unix/Linux平台开发方式;

    熟练使用系统调用;

    熟练Unix/Linux内存管理,进程,线程调度;

    熟悉网络服务器开发方式,熟练编写TCP,UCP网络服务程序;

    掌握同步/异步IO模型在网络编程中的使用方式。

    10.C++进阶之数据库开发

    掌握SQL语言的实用技巧。Oracle,MySQL数据库的使用方式。

    如果你能熟练掌握以上列出的技能,具备解决复杂问题和技术难点的能力,而且你能独立开发一些比较复杂的功能模块,那么很荣幸地告诉你,你已经达到中级水平,薪资过万对你来说简直是小菜一碟。

    11.C++标准参考

    C++ reference

    地址:https://en.cppreference.com/w/

    C++ Coding Standard

    地址:http://www.possibility.com/Cpp/CppCodingStandard.html

    Standard C++

    地址:https://isocpp.org/

    State of C++ Evolution

    地址:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2597.html

    The C++ Resources Network

    地址:http://www.cplusplus.com/

    Draft C++ Standard: Contents

    地址:http://eel.is/c++draft/

⑼ c语言编程时的模板里面{跟//是什么意思

{和}是匹配的
表示一个单独的
程序段

当if
while
for等
这类
控制语句
,要包含多余一句的语句时
需要用{}括起来。
//表示注释

//之后到行末
只给编写程序的人看,
编译器
不会处理。

⑽ 求大神解释一下:在c++编程中,一个函数模板可以应用在多个函数中吗 例如:template<ty

如果你使用模板函数的话,就只能每个函数一个模板参数,例如;
template<typename T> void a(T t){...}

template<typename T> void b(T t){...}

template<typename T> void c(T t){...}

a,b,c三个函数的模板参数T互不相关,如果你想几个函数使用共同的模板参数的话,你应当使用模板类,例如:
template<typename T> class MyClass
{
void a(T t){...}

void b(T t){...}
void c(T t){...}
};
这样a,b,c三个函数的参数类型T就是统一类型了。在这里T对应a,b,c三个函数来说仅仅是参数类型,而不是模板参数了。

热点内容
内置存储卡可以拆吗 发布:2025-05-18 04:16:35 浏览:336
编译原理课时设置 发布:2025-05-18 04:13:28 浏览:378
linux中进入ip地址服务器 发布:2025-05-18 04:11:21 浏览:612
java用什么软件写 发布:2025-05-18 03:56:19 浏览:32
linux配置vim编译c 发布:2025-05-18 03:55:07 浏览:107
砸百鬼脚本 发布:2025-05-18 03:53:34 浏览:944
安卓手机如何拍视频和苹果一样 发布:2025-05-18 03:40:47 浏览:742
为什么安卓手机连不上苹果7热点 发布:2025-05-18 03:40:13 浏览:803
网卡访问 发布:2025-05-18 03:35:04 浏览:511
接收和发送服务器地址 发布:2025-05-18 03:33:48 浏览:372