C++中怎样写宏定义

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中怎样写宏定义相关的知识,希望对你有一定的参考价值。

求C++中宏的系统的使用方法,包括宏的定义和使用方法,最好能给代码,初次接触宏对他没有概念,希望好心人指点。谢谢

C/C++中宏使用总结
.C/C++中宏总结C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程
序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。

ANSI标准定义的C语言预处理程序包括下列命令:

#define,#error,#i
nclude,#if,#else,#elif,#endif,#ifdef,#ifndef,#undef,#line,#pragma等。非常明显,所有预处理命令均以符号#开头,下面分别加以介绍。

1、#define

命令#define定义了一个标识符及一个串。在源程序中每次遇到该标识符时,均以定义的串代换它。ANSI标准将标识符定义为宏名,将替换过程称为宏
替换。命令的一般形式为:

#define identifier string

注意:

? 该语句没有分号。在标识符和串之间可以有任意个空格,串一旦开始,仅由一新行结束。

? 宏名定义后,即可成为其它宏名定义中的一部分。

? 宏替换仅仅是以文本串代替宏标识符,前提是宏标识符必须独立的识别出来,否则不进行替换。例如: #define XYZ
this is a test,使用宏printf("XYZ");//该段不打印"this is a test"而打印"XYZ"。因为预编译器识
别出的是"XYZ"

? 如果串长于一行,可以在该行末尾用一反斜杠' \'续行。

2、#error

处理器命令#error强迫编译程序停止编译,主要用于程序调试。

3、#i nclude

命令#i nclude使编译程序将另一源文件嵌入带有#i nclude的源文件,被读入的源文件必须用双引号或尖括号括起来。例如:

#i nclude"stdio.h"或者#i nclude

这两行代码均使用C编译程序读入并编译用于处理磁盘文件库的子程序。

将文件嵌入#i nclude命令中的文件内是可行的,这种方式称为嵌套的嵌入文件,嵌套层次依赖于具体实现。

如果显式路径名为文件标识符的一部分,则仅在哪些子目录中搜索被嵌入文件。否则,如果文件名用双引号括起来,则首先检索当前工作目录。如果未发现文件,
则在命令行中说明的所有目录中搜索。如果仍未发现文件,则搜索实现时定义的标准目录。

如果没有显式路径名且文件名被尖括号括起来,则首先在编译命令行中的目录内检索。

如果文件没找到,则检索标准目录,不检索当前工作目录。

4、条件编译命令

有几个命令可对程序源代码的各部分有选择地进行编译,该过程称为条件编译。商业软件公司广泛应用条件编译来提供和维护某一程序的许多顾客版本。

#if、#else,#elif及#endif

#if的一般含义是如果#if后面的常量表达式为true,则编译它与#endif之间的代码,否则跳过这些代码。命令#endif标识一个#if块的
结束。

#if constant-expression

statement sequence

#endif

跟在#if后面的表达式在编译时求值,因此它必须仅含常量及已定义过的标识符,不可使用变量。表达式不许含有操作符sizeof(sizeof也是编译
时求值)。

#else命令的功能有点象C语言中的else;#else建立另一选择(在#if失败的情况下)。

注意,# else属于# if块。

#elif命令意义与ELSE IF 相同,它形成一个if else-if阶梯状语句,可进行多种编译选择。

#elif 后跟一个常量表达式。如果表达式为true,则编译其后的代码块,不对其它#elif表达式进行测试。否则,顺序测试下一块。

#if expression

statement sequence

#elif expression1

statement sequence

#endif

在嵌套的条件编译中#endif、#else或#elif与最近#if或#elif匹配。

# ifdef 和# ifndef

条件编译的另一种方法是用#ifdef与#ifndef命令,它们分别表示"如果有定义"及"如果无定义"。

# ifdef的一般形式是:

# ifdef macroname

statement sequence

#endif

#ifdef与#ifndef可以用于#if、#else,#elif语句中,但必须与一个#endif。

5、#undef

命令#undef 取消其后那个前面已定义过有宏名定义。一般形式为:

#undef macroname

6、#line

命令# line改变__LINE__与__FILE__的内容,它们是在编译程序中预先定义的标识符。命令的基本形式如下:

# line number["filename"]

其中的数字为任何正整数,可选的文件名为任意有效文件标识符。行号为源程序中当前行号,文件名为源文件的名字。命令# line主要用于调试及其它特殊
应用。

注意:在#line后面的数字标识从下一行开始的数字标识。

7、预定义的宏名

ANSI标准说明了C中的五个预定义的宏名。它们是:

__LINE__

__FILE__

__DATE__

__TIME__

__STDC__

如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序也许还提供其它预定义的宏名。

__LINE__及__FILE__宏指令在有关# line的部分中已讨论,这里讨论其余的宏名。

__DATE__宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。

源代码翻译到目标代码的时间作为串包含在__TIME__中。串形式为时:分:秒。

如果实现是标准的,则宏__STDC__含有十进制常量1。如果它含有任何其它数,则实现是非标准的。编译C++程序时,编译器自动定义了一个预处理名
字__cplusplus,而编译标准C时,自动定义名字__STDC__。

注意:宏名的书写由标识符与两边各二条下划线构成。

(部分内容出自:http://www.bc-cn.net/Article/kfyy/cyy/jc/200511/919.html)

8、C、C++宏体中出现的#,#@,##

宏体中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个
双引号。

而##被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定是宏的变
量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那就可以使用:宏参数##
固定部分。当然还可以n个##符号连接 n+1个Token,这个特性也是#符号所不具备的。

#@的功能是将其后面的宏参数进行字符化。

9、C宏中的变参...

...在C宏中称为Variadic Macro,也就是变参宏。比如:

#define myprintf(templt,...) fprintf(stderr,templt,__VA_ARGS__)

或者#define myprintf(templt,args...) fprintf(stderr,templt,args)

第一个宏中由于没有对变参起名,我们用默认的宏__VA_ARGS__来替代它。第二个宏中,我们显式地命名变参为args,那么我们在宏定义中就可以
用args来代指变参了。同C语言的stdcall一样,变参必须作为参数表的最后有一项出现。当上面的宏中我们只能提供第一个参数templt时,C
标准要求我们必须写成: myprintf(templt,);的形式。这时的替换过程为:myprintf("Error!\n",);替换为:
fprintf(stderr,"Error!\n",).

这是一个语法错误,不能正常编译。这个问题一般有两个解决方法。首先,GNU CPP提供的解决方法允许上面的宏调用写成:
myprintf(templt);而它将会被通过替换变成: fprintf(stderr,"Error!\n",);

很明显,这里仍然会产生编译错误(非本例的某些情况下不会产生编译错误)。除了这种方式外,c99和GNU CPP都支持下面的宏定义方式:

#define myprintf(templt, ...) fprintf(stderr,templt, ##__VAR_ARGS__)

这时,##这个连接符号充当的作用就是当__VAR_ARGS__为空的时候,消除前面的那个逗号。那么此时的翻译过程如下:
myprintf(templt);被转化为: fprintf(stderr,templt);

这样如果templt合法,将不会产生编译错误。

10、#pragma的使用【转载】

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对
每个编译器给出了一个方法,在保持与C和C ++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且
对于每个编译器都是不同的。

其格式一般为: #Pragma Para,其中Para 为参数,下面来看一些常用的参数。

(1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常
重要的。其使用方法为:

#Pragma message("消息文本")

当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。

当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。
假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法

#ifdef _X86

#Pragma message("_X86 macro activated!")

#endif

当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示"_

X86 macro activated!"。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。

(2)另一个使用得比较多的pragma参数是code_seg。格式如:

#pragma code_seg( ["section-name"[,"section-class"] ] )

它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。

(3)#pragma once (比较常用)

只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。

(4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文
件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。

有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了
#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。

(5)#pragma resource "*.dfm"表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体、外观的定义。

(6)#pragma warning( disable : 4507 34; once : 4385; error : 164 )

等价于:

#pragma warning(disable:4507 34) // 不显示4507和34号警告信息

#pragma warning(once:4385) // 4385号警告信息仅报告一次

#pragma warning(error:164) // 把164号警告信息作为一个错误。

同时这个pragma warning 也支持如下格式:

#pragma warning( push [ ,n ] )

#pragma warning( pop )

这里n代表一个警告等级(1---4)。

#pragma warning( push )保存所有警告信息的现有的警告状态。

#pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。

#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。例如:

#pragma warning( push )

#pragma warning( disable : 4705 )

#pragma warning( disable : 4706 )

#pragma warning( disable : 4707 )

//.......

#pragma warning( pop )

在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)。
(7)pragma comment(...)

该指令将一个注释记录放入一个对象文件或可执行文件中。

常用的lib关键字,可以帮我们连入一个库文件。

(8)用pragma导出dll中的函数

传统的到出 DLL 函数的方法是使用模块定义文件 (.def),Visual C++ 提供了更简洁方便的方法,那就
是"__declspec()"关键字后面跟"dllexport",告诉连接去要导出这个函数,例如:

__declspec(dllexport) int __stdcall MyExportFunction(int iTest);

把"__declspec(dllexport)"放在函数声明的最前面,连接生成的 DLL 就会导出函
数"_MyExportFunction@4"。

上面的导出函数的名称也许不是我的希望的,我们希望导出的是原版的"MyExportFunction"。还好,VC 提供了一个预处理指示
符"#pragma"来指定连接选项 (不仅仅是这一个功能,还有很多指示功能) ,如下:

#pragma comment(linker,"/EXPORT:MyExportFunction=_MyExportFunction@4")

这下就天如人愿了:)。如果你想指定导出的顺序,或者只将函数导出为序号,没有 Entryname,这个预处理指示符 (确切地说是连接器) 都能够
实现,看看 MSDN 的语法说明:

/EXPORT:entryname[,@ordinal[,NONAME]][,DATA]

@ordinal 指定顺序;NONAME 指定只将函数导出为序号;DATA 关键字指定导出项为数据项。

⑨每个编译程序可以用#pragma指令激活或终止该编译程序支持的一些编译功能。例如,对循环优化功能:

#pragma loop_opt(on) // 激活

#pragma loop_opt(off) // 终止

有时,程序中会有些函数会使编译器发出你熟知而想忽略的警告,如"Parameter xxx is never used in function
xxx",可以这样:

#pragma warn -100 // Turn off the warning message for warning #100

int insert_record(REC *r)

/* function body */

#pragma warn +100 // Turn the warning message for warning #100 back
on

函数会产生一条有唯一特征码100的警告信息,如此可暂时终止该警告。

每个编译器对#pragma的实现不同,在一个编译器中有效在别的编译器中几乎无效。可从编译器的文档中查看。
⑩#pragm pack()的使用

#pragma pack规定的对齐长度,实际使用的规则是:

? 结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和这
个数据成员自身长度中,比较小的那个进行。

? 也就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。

? 而结构整体的对齐,则按照结构体中最大的数据成员 和 #pragma pack指定值之间,较小的那个进行。

注意:文件使用#pragma pack(n) 改变了缺省设置而不恢复,通常可以使用#pragma pack(push, n)和#pragma
pack(pop)进行设置与恢复。

注:关于宏函数的内容在另外的专题。关于宏使用的误区在描述宏的时候已经在文中提到了,最后再给出一个例子,描述的Side Effect是指宏在展开
的时候对其参数可能进行多次Evaluation(也就是取值)对程序造成的错误影响。

假设在一个系统中,有一个32b的寄存器(REG)保存状态,其中高16b表示一种含义,低16b表示另一种含义(这在程序中经常出现)。现在要把高低
16b分开,不考虑实际中的特殊要求,将代码写成:

#define High16bit(REG) (REG>>16)

#define Low16bit(REG) ((REG<<16)>>16)

对于这种写法完成的功能在大多数情况是足够了,这里不讨论。主要谈论这种写法的负面影响,如果在程序中分别在不同的语句中使用High16bit和
Low16bit,那么就可能那就是Side effect,特别寄存器REG是状态寄存器,他的状态可能随时变化,那么引起的问题就是高低16b根本
取的不是同一个时刻状态寄存器。这种错误在程序中找出就比较难了。在这里我把条件弱化了,试想在一个宏体中,如果对参数多次取值也是可能引起问题,那就 更难了。
参考技术A 宏定义,就我的理解就是替换。举个例子
#DEFINE IP 3.1415
编译运行时只把IP 换成3.1415

#define Add(x,y)((x)+(y))
如果我们使用时 4*Add(2,2) 结果翻译成4*(2+2)

改变一下:
#define Add(x,y)(x)+(y) 4*Add(2,2) 结果翻译成4*2+2
总的来说 我们常用的宏都是替换罢了,但是建议少用,因为不会进行类型检查,所以有时候使用不当,会产生运行时错误
以上这些希望对你有帮助
参考技术B http://wenku.baidu.com/view/33759f2ced630b1c59eeb5a5.html
给个网址你去看···

求C++高手!!!

现有多个类定义的头文件,每个文件中必须定义
enum Error_codesuccess,fail,range_error,underflow,overflow,fatal,not_present,duplicate_error,entry_inserted,entry_found,internal_error;
的枚举类型,而每个头文件被主函数调用,怎样防止Error_code的重定义???

使用预编译指令
#ifndef POINT_H_H
#define POINT_H_H 1
enum Error_codesuccess,fail,range_error,underflow,overflow,fatal,not_present,duplicate_error,entry_inserted,entry_found,internal_error;

#endif
参考技术A 用预编译指令
建议看看孙鑫的视频,上面就讲过
参考技术B 学会,多做练习!
1.m个人的成绩存放在score数组中,请编写函数fun,它的功能是:将低于平均分的人数作为函数值返回,将低于平均分的分数放在below所指的数组中。
例如,当score数组中的数据为10、20、30、40、50、60、70、80、90时,函数返回的人数应该是4,below中的数据应为10、20、30、40。
**************************************************
2.请编写函数fun,它的功能是:求出1到1000之内能被7或11整除、但不能同时被7和11整除的所有整数并将它们放在a所指的数组中,通过n返回这些数的个数。

**************************************************
3.请编写函数void fun(int x,int pp[],int *n),它的功能是:求出能整除x且不是偶数的各整数,并按从小到大的顺序放在pp所指的数组中,这些除数的个数通过形参n返回。
例如,若x中的值为30,则有4个数符合要求,它们是1,3,5,15。
**************************************************
4.请编写一个函数void fun(char *tt,int pp[]),统计在tt字符串中“a”到“z”26个字母各自出现的次数,并依次放在pp所指数组中。
例如,当输入字符串abcdefgabcdeabc后,程序的输出结果应该是:3 3 3 2 2 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
**************************************************
5.请编写一个函数void fun(int m,int k,int xx[]),该函数的功能是:将大于整数m且紧靠m的k个素数存入xx所指的数组中。
例如,若输入:17,5,则应输出:19,23,29,31,37。
**************************************************
6.请编写一个函数void fun(char a[],char b[],int n),其功能是:删除一个字符串中指定下标的字符。其中,a指向原字符串,删除后的字符串存放在b所指的数组中,n中存放指定的下标。
例如,输入一个字符串World,然后输入3,则调用该函数后的结果为Word。
**************************************************
7.请编写一个函数int fun(int*s,int t,int *k),用来求出数组的最大元素在数组中的下标并存放在k所指的存储单元中。
例如,输入如下整数:876 675 896 10l 30l 40l 980 43l 451 777 ,则输出结果为:6,980。
**************************************************
8.编写函数fun,函数的功能是:根据以下公式计算s,计算结果作为函数值返回;n通过形参传入。
S=1+1/(1+2)+1/(1+2+3)+……1/(1+2+3+…+n)
例如:若n的值为11时,函数的值为1.833333。
**************************************************
9.编写函数fun,它的功能是:根据以下公式求P的值,结果由函数值带回。m与n为两个正整数且要求m>n。

例如:m=12,n=8时,运行结果为495.000000。
**************************************************
10.编写函数fun,它的功能是:利用以下所示的简单迭代方法求方程COS(X)-X=0的一个实根。
Xn+1=COS(Xn)
迭代步骤如下:
(1)取x1初值为0.0;
(2)x0=x1,把x1的值赋给x0;
(3)x1=COS(x0),求出一个新的x1;
(4)若x0—x1的绝对值小于0.000001,则执行步骤(5),否则执行步骤(2);
(5)所求x1就是方程COS(X)-X=0的一个实根,作为函数值返回。
程序将输出结果Root=0.739085。
**************************************************
11.下列程序定义了NXN的二维数组,并在主函数中自动赋值。请编写函数fun(int a[][N],该函数的功能是:使数组左下半三角元素中的值全部置成0。例如:a数组中的值为:
,则返回主程序后a数组中的值应为:。
**************************************************
12.下列程序定义了NXN的二维数组,并在主函数中赋值。请编写函数fun,函数的功能是:求出数组周边元素的平均值并作为函数值返回给主函数中的s。例如:若a数组中的值为:
,则返回主程序后s的值应为3.375。
**************************************************
13.请编一个函数void fun(int tt[M][N],int pp[N]),tt指向一个M行N列的二维数组,求出二维数组每列中最小元素,并依次放入pp所指一维数组中。二维数组中的数已在主函数中赋予。
**************************************************
14.请编写函数fun,函数的功能是求出二维数组周边元素之和,作为函数值返回。二维数组中的值在主函数中赋予。
例如:若二维数组中的值为:,则函数值为61。
*************************************************
15.请编写一个函数unsigned fun(unsigned w),w是一个大于10的无符号整数,若w是n(n≥2)位的整数,则函数求出w的后n-1位的数作为函数值返回。
例如:w值为5923,则函数返回923;若w值为923,则函数返回23。
**************************************************
16.请编一个函数float fun(double h),函数的功能是对变量h中的值保留2位小数,并对第三位进行四舍五入(规定h中的值为正数)。
例如:若h值为8.32433,则函数返回8.32;若h值为8.32533,则函数返回8.33。
**************************************************
17.请编一个函数fun(char*s),该函数的功能是把字符串中的内容逆置。
例如:字符串中原有的字符串为abcdefg,则调用该函数后,串中的内容为gfedcba。
**************************************************
18.编写程序,实现矩阵(3行3列)的转置(即行列互换)。
例如,若输入下面的矩阵:,则程序输出:
**************************************************
19.编写函数fun,该函数的功能是:从字符串中删除指定的字符。同一字母的大、小写按不同字符处理。
例如:若程序执行时输入字符串为:turbo c and borland c++,从键盘上输入字符n,则输出后变为:turbo c ad borlad c++;如果输入的字符在字符串中不存在,则字符串照原样输出。
**************************************************
20.编写函数int fun(int lim,int aa[MAX]),该函数的功能是求出小于或等于lim的所有素数并放在aa数组中,该函数返回所求出的素数的个数。
**************************************************
21.请编写函数fun,对长度为7个字符的字符串,除首、尾字符外,将其余5个字符按ASCII码降序排列。
例如,若原来的字符串为CEAedca,则排序后输出为CedcEAa。
**************************************************
22.N名学生的成绩已在主函数中放入一个带头节点的链表结构中,h指向链表的头节点。请编写函数fun,它的功能是:找出学生的最高分,由函数值返回。
**************************************************
23.请编写函数fun,该函数的功能是:判断字符串是否为回文?若是则函数返回1,主函数中输出YES,否则返回0,主函数中输出NO。回文是指顺读和倒读都一样的字符串。
例如,字符串LEVEL是回文,而字符串123312就不是回文。
**************************************************
24.请编写一个函数fun,它的功能是:将一个数字字符串转换为一个整数(不得调用C语言提供的将字符串转换为整数的函数)。
例如,若输入字符串“-1234”,则函数把它转换为整数值-1234。
**************************************************
25.请编写一个函数fun,它的功能是:比较两个字符串的长度,(不得调用C语言提供的求字符串长度的函数),函数返回较长的字符串。若两个字符串长度相同,则返回第一个字
符串。
例如,输入:beijing shanghai<CR>(<CR>为回车键),函数将返回shanghai。
*************************************************
26.请编写一个函数fun,它的功能是:根据以下公式求π的值(要求满足精度0.0005,即某项小于0.0005时停止迭代):

程序运行后,如果输入精度0.0005,则程序输出为3.14…。
**************************************************
27.请编写一个函数fun,它的功能是:求出1到m之内(含m)能被7或11整除的所有整数放在数组a中,通过n返回这些数的个数。
例如,若传送给m的值为50,则程序输出:
7 11 14 21 22 28 33 35 42 44 49
**************************************************
28.请编写一个函数fun,它的功能是:找出一维整型数组元素中最大的值和它所在的下标,最大的值和它所在的下标通过形参传回。数组元素中的值已在主函数中赋予。
主函数中x是数组名,n是x中的数据个数,max存放最大值,index存放最大值所在元素的下标。
**************************************************
29.请编写一个函数fun,它的功能是:将ss所指字符串中所有下标为奇数位置上的字母转换为大写(若该位置上不是字母,则不转换)。
例如,若输入abc4EFg,则应输出aBc4EFg。
**************************************************
30.请编写一个函数fun,它的功能是:求出一个2xM整型二维数组中最大元素的值,并将此值返回调用函数。
**************************************************
31.请编写函数fun,其功能是:将s所指字符串中除了下标为偶数、同时ASCII值也为偶数的字符外,其余的全都删除;串中剩余字符所形成的一个新串放在t所指的数组中。
例如,若s所指字符串中的内容为ABCDEFG123456,其中字符A的ASCII码值为奇数,因此应当删除;其中字符B的ASCII码值为偶数,但在数组中的下标为奇数,因此也应当删除;而字符2的ASCII码值为偶数,所在数组中的下标也为偶数,因此不应当删除,其他依此类推。最后t所指的数组中的内容应是246。
**************************************************
32.请编写函数fun,其功能是:将s所指字符串中除了下标为奇数、同时ASCII值也为奇数的字符之外,其余的所有字符都删除,串中剩余字符所形成的一个新串放在t所指的数组中。
例如,若s所指字符串中的内容为ABCDEFGl2345,其中字符A的ASCII码值虽为奇数,但所在元素的下标为偶数,因此必需删除;而字符1的ASCII码值为奇数,所在数组中的下标也为奇数,因此不应当删除,其他依此类推。最后t所指的数组中的内容应是135。
**************************************************
33.假定输入的字符串中只包含字母和*号。请编写函数fun,它的功能是:使字符串中尾部的*号不得多于n个;若多于n个,则删除多余的*号;若少于或等于n个,则什么也不做,字符串中间和前面的*号不删除。
例如,字符串中的内容为****A*BC*DEF*G*******,若n的值为4,删除后,字符串中的内容则应当是****A*BC*DEF*G****;若n的值为7,则字符串中的内容仍为 ****A*BC*DEF*G*******。n的值在主函数中输入。在编写函数时,不得使用C语言提供的字符串函数。
**************************************************
34.学生的记录由学号和成绩组成,N名学生的数据已在主函数中放入结构体数组s中,请编写函数fun,它的功能是:把分数最高的学生数据放在h所指的数组中,注意:分数最高的学生可能不只一个,函数返回分数最高的学生的人数。
**************************************************
35.请编写一个函数,用来删除字符串中的所有空格。
例如,输入asd af aa z67,则输出为asdafaaz67。
**************************************************
36.假定输入的字符串中只包含字母和*号。请编写函数fun,它的功能是:将字符串中的前导*号全部移到字符串的尾部。
例如,字符串中的内容为*******A*BC*DEF*G****,移动后,字符串中的内容应当是A*BC*DEF*G***********。在编写函数时,不得使用C语言提供的字符串函数。
**************************************************
37.某学生的记录由学号、8门课程成绩和平均分组成,学号和8门课程的成绩已在主函数中给出。请编写函数fun,它的功能是:求出该学生的平均分放在记录的ave成员中。请自己定义正确的形参。
例如,若学生的成绩是85.5,76,69.5,85,91,72,64.5,87.5,则他的平均分应当是78.875。
*************************************************
38.请编写函数fun,它的功能是:求出ss所指字符串中指定字符的个数,并返回此值。
例如,若输入字符串123412132,输入字符1,则输出3。
**************************************************
39.请编写函数fun,该函数的功能是:移动一维数组中的内容;若数组中有n个整数,要求把下标从0到p(p小于等于n-1)的数组元素平移到数组的最后。
例如,一维数组中的原始内容为:1,2,3,4,5,6,7,8,9,10;p的值为3。移动后,一维数组中的内容应为:5,6,7,8,9,10,1,2,3,4。
**************************************************
40.请编写函数fun,该函数的功能是:移动字符串中的内容,移动的规则如下:把第1到第m个字符,平移到字符串的最后,把第m+l到最后的字符移到字符串的前部。
例如,字符串中原有的内容为ABCDEFGHIJK,m的值为3,移动后,字符串中的内容应该是DEFGHIJKABC。
**************************************************
41.请编写函数fun,该函数的功能是:将M行N列的二维数组中的字符数据,按列的顺序依次放在一个字符串中。
例如,若二维数组中的数据为:

则字符串中的内容应是WSHWSHWSHWSH。
**************************************************
42.下列程序定义了NxN的二维数组,并在主函数中自动赋值。请编写函数fun(int a[][N],int n),该函数的功能是:使数组右上半三角元素中的值乘以m。例如:若m的值为2,a数组中的值为:,则返回主程序后a数组中的值应为:。
**************************************************
43.编写一个函数,从传入的num个字符串中找出最长的一个字符串,并通过形参指针max传回该串地址(用****作为结束输入的标志)。
************************************************
44.编写一个函数,该函数可以统计一个长度为2的字符串在另一个字符串中出现的次数。例如,假定输入的字符串为:asd asasdfg asd as zx67 asd mklo,子字符串为as,则应输出6。
**************************************************
45.假定输入的字符串中只包含字母和*号。请编写函数fun,它的功能是:只删除字符串前导和尾部的*号,串中字母之间的*号都不删除。形参n给出了字符串的长度,形参h给出了字符串中前导*号的个数,形参e给出了字符串中最后*号的个数。在编写函数时,不得使用C语言提供的字符串函数。
例如,若字符串中的内容为****A*BC*DEF*G*******,删除后,字符串中的内容则应当是A*BC*DEF*G。
**************************************************
46.学生的记录由学号和成绩组成,N名学生的数据已在主函数中放入结构体数组s中,请编写函数fun,它的功能是:按分数的高低排列学生的记录,高分在前。
**************************************************
47.请编写一个函数void fun(char*ss),其功能是:将字符串ss中所有下标为奇数位置上的字母转换为大写(若该位置上不是字母,则不转换)。
例如,若输入abc4EFgh,则应输出aBc4EFgH。
**************************************************
48.请编写函数fun,其功能是:将两个两位数的正整数a、b合并形成一个整数放在c中。合并的方式是:将a数的十位和个位数依次放在c数的千位和十位上,b数的十位和个位数依次放在c数的百位和个位上。
例如,当a=45,b=12,调用该函数后,c=4152。
**************************************************
49.请编写函数fun,其功能是:将s所指字符串中下标为偶数同时ASCII值为奇数的字符删除,s中剩余的字符形成的新串放在t所指的数组中。
例如,若s所指字符串中的内容为ABCDEFGl2345,其中字符C的ASCII码值为奇数,在数组中的下标为偶数,因此必须删除;而字符1的ASCII码值为奇数,在数组中的下标也为奇数,因此不应当删除,其他依此类推。最后t所指的数组中的内容应是BDFl2345。
**************************************************
50.已知学生的记录由学号和学习成绩构成,N名学生的数据已存入a结构体数组中。请编写函数fun,该函数的功能是:找出成绩最高的学生记录,通过形参返回主函数(规定只有一个最高分)。已给出函数的首部,请完成该函数。

以上是关于C++中怎样写宏定义的主要内容,如果未能解决你的问题,请参考以下文章

C++ 宏定义和取消定义

C++ 中define(宏定义) 各种用法(含特殊),小举个例子,谢谢!

[c++] 用宏定义一个函数

C++之预处理命令以及宏定义

高端技巧:怎样使用#define定义变量

如何为 C++ 智能感知引擎定义宏?