C++学习之路(六),C++primer plus 第七章 函数--C++的编程模块-复习题

mac2022-06-30  208

继续录入19年大客光缆]

C++学习之路(六),C++primer plus 第七章 函数--C++的编程模块-复习题

1. 使用函数的 3 个步骤是什么?2. 请创建与下面描述匹配的函数原型3. 编写一个接受 3 个参数的函数:int 数组名、数组长度和一个 int 值,并将数组的所有元素都设置为该 int 值。4. 编写一个接受 3 个参数的函数:指向数组区间中第一个元素的地址、指向数组区间最后一个元素后面的指针以及一个 int 值,并将数组中每个元素都设置为该 int 值。5. 编写将 double 数组名和数组长度作为参数,并返回该数组中最大值的函数。该函数不应该修改数组的内容![在这里插入图片描述](https://img-blog.csdnimg.cn/20191002211205498.png)第一步,写个代码找出数组中最大的值:第二步, 用函数调用的方法找出最大值最后一步,利用调用函数并传递数组名和数组长组 6,为什么不对类型为基本类型的函数使用 const 限定符?7,C++ 程序可使用哪 3 种 C-风格字符串格式?8,编写一个函数,其原型如下:第一步,先写段代码找出字符串中想要替换字符所出现的个数:第二步,将字符串里的 e 替换成 E 9,表达式*“pizza”的含义是什么,“taco”[2]呢?10,C++允许按值传递结构,也允许传递结构的址,如果 glitz 是一个结构变量,如何按值传递它?如何传递它的地址?这两种方法有何利弊?11,函数 judge()的返回类型为 int,它将这样一个函数的地址作为参数:将 const char 指针作为参数,并将返回一个 int 值。请编写 judge()函数的原型。12, 假设有如下结构声明:a, 编写一个函数,它将 application 结构作为参数,并显示该结构的内容。b, 编写一个函数,它将 application 结构的地址作为参数,并显示该参数指向的结构的内容。 13,假设函数 f1()和 f2()的原型如下:14,题外语,恶补下 typedef

1. 使用函数的 3 个步骤是什么?

①声明定义函数 ②函数原形 ③函数调用

2. 请创建与下面描述匹配的函数原型

a. igor()没有参数,且没有返回值。 a:void igor();

b. tofu()接受一个 int 参数,并返回一个 float。 b: float tofu(int);

c. mpg()接受两个 double 参数,并返回一个 double。 c:double mpg(double, double);

d. summation()将 long 数组名和数组长度作为参数,并返回一个 long 值。 d: long summation(long arr[ ], int size);

e. doctor()接受一个字符串参数。 e : void doctor(string str);

f. ofcourse()将 boss 结构作为参数,不返回值。 f: void ofcourse(boss);

g. polt()将 map 结构的指针作为参数,并返回一个字符串。 **g: char polt(map );

3. 编写一个接受 3 个参数的函数:int 数组名、数组长度和一个 int 值,并将数组的所有元素都设置为该 int 值。

void MyFun(int arr[], int size, int value) { for(int i = 0; i < size; i ++) arr[ i ] = value; }

4. 编写一个接受 3 个参数的函数:指向数组区间中第一个元素的地址、指向数组区间最后一个元素后面的指针以及一个 int 值,并将数组中每个元素都设置为该 int 值。

```cpp #include <iostream> using namespace std; int ArSize = 10; void MyFun(int * begin, int * end, int value); int main() { int arr[ 10 ]; // 不知为何,这里不可用 ArSize 代替 10 MyFun(arr, arr + 9, 33); for (int i = 0; i < 10; i ++) cout << "arr[ " << i << " ] = " << arr[ i ] << endl; return 0; } void MyFun(int * begin, int * end, int value) { int * pt; for (pt = begin; pt <= end; pt ++) // 这里 <= 不能掉了 等于号 { *pt = value; } }

运行结果如下

5. 编写将 double 数组名和数组长度作为参数,并返回该数组中最大值的函数。该函数不应该修改数组的内容

昨天晚上把第 5 题写上就回去了,回去路上,睡在床上,也想想这个题目,先想想怎么找出一个数组中的最大值,

第一步,写个代码找出数组中最大的值:
#include <iostream> using namespace std; const int ArSize = 8; // 这里定义的数组长度必须要用 const,否则下面声明的数组就不能用变量名 ArSize int main() { double arr[ ArSize ] = {21, 34, 19, 44, -60, 0, 92}; double BigNum = arr[ 0 ]; for (int i = 0; i < ArSize; i ++) { if (BigNum <= arr[ i + 1 ]) BigNum = arr[ i + 1]; } cout << "BigNum = " << BigNum; return 0; }
第二步, 用函数调用的方法找出最大值
#include <iostream> using namespace std; const int ArSize = 8; double arr[ ArSize ] = {21.5, 34.002, 19.62, 44.30, -60.79, 0.09, 92.66}; double FindBigNum(); int main() { double BigNum = FindBigNum(); cout << "BigNum = " << BigNum << endl; return 0; } double FindBigNum() { double BigNum; for (int i = 0; i < ArSize; i ++) { if (BigNum < arr[ i + 1 ]) BigNum = arr[ i + 1]; } return BigNum; }
最后一步,利用调用函数并传递数组名和数组长组
#include <iostream> using namespace std; const int ArSize = 8; double FindBigNum(const double arr[], const int ArSize); int main() { double arr[ ArSize ] = {21.5, 34.002, 19.62, 44.30, -60.79, 0.09, 92.66}; double BigNum = FindBigNum(arr, ArSize); //double BigNum = FindBigNum(const double arr[], const int ArSize); // 这里这样传递参数不对 cout << "BigNum = " << BigNum << endl; return 0; } double FindBigNum(const double arr[], const int ArSize) { double BigNum; for (int i = 0; i < ArSize; i ++) { if (BigNum < arr[ i + 1 ]) BigNum = arr[ i + 1]; } return BigNum; }

6,为什么不对类型为基本类型的函数使用 const 限定符?

因为函数在调用参数时,使用的是一个副本,而不是原来的数,因此不会修改作为实参的基本类型的值。而指针不同,指针为函数参数时,可以通过修改指针来修改指针所指向的值。基本传递的是形参,对数值做不做修改都无所谓,因为原数据不会随之更改。

7,C++ 程序可使用哪 3 种 C-风格字符串格式?

这个留到以后再来看,之前没有学习C

8,编写一个函数,其原型如下:

int replace(char * str, char c1, char c2); 该函数将字符串中所有的 c1 都替换为 c2,并返回替换次数。 一开始没弄懂什么意思,搞得无从下手,于是从网上看了下代码,才明白,就是给出一个字符串,比如 ”Hello World“ 将其中的所有字符 ‘l’ 替换成字符 ’L‘;照旧,一步步来解析;

第一步,先写段代码找出字符串中想要替换字符所出现的个数:
#include <iostream> using namespace std; int main() { char ch[] = "Show Me The Money"; // 打印出上面的字符串; cont << ch << endl; // 定义字符出现的次数 int count; // 用循环找出所要替换字符并打印出次数 for(int i = 0; i < strlen(ch); i ++) { // 判断字符是不是要替换的字符,是,则进入循环,否则,反之 if (ch[ i ] == 'e') //注意这里是 ==, 而不是= count ++; } cout << "替换字符出现的次数: " << count; return 0; }

看下面代码运行结果: 由于把 == 写成 赋值符=,没有打印出次数,当时没有反应过来,于是用F10大法,发现 for 循环里出现的都是字符 e,明白了由于用错了赋值符号 =,将字符串里所有的字符都替换成了 e

下面是改好后的

这第一算是完工了,下面是第二步,将字符串里的 e 替换成 E

第二步,将字符串里的 e 替换成 E

想到了 strcpy()函数,但貌似这个函数只能用了字符串 string,记得之前做过一些类似的题目,将大写改小写,找出字符串中字母,数字,等等,找了半天书上以前的资料,没发现我想要的资料,又在网上搜了下,发现竟然有个直接的函数,replace(),可以直接拿来用,不过暂时我们要手动,时间又到了吃饭时间了,于是回家吃饭,边吃饭边想,如何替换(其实在最开始的时候,已经用了替换了,只是开始想着找出要替换的次数,没有想到),慢慢的突然想到,就是第一张图片就已经用了替换了,就是赋值运算符。下面是替换后的代码结果:

#include <iostream> using namespace std; //int replace(char * str, char c1, char c2); int main() { char ch[ ] = "show me the money"; cout << ch << ": " << strlen(ch) << endl; int count = 0; for (int i = 0; i <= strlen(ch); i ++) { if (ch[ i ] == 'e') { ch[ i ] = 'E'; count ++; } } cout << "e字节出现的次数: " << count << endl; cout << ch << endl; return 0; }

这TMD蛋痛了,没有保存,网而崩了,白写半天,RRR!

9,表达式*“pizza”的含义是什么,“taco”[2]呢?

*“pizza”被 C++ 解释为第一个元素的地址,因此使用 取值运算符将可以得到第一个元素的值,即字符 p。由于 C++ 将 “taco”解释为第一个元素的地址,因此它将“taco”[2]解释为第二个元素的值,即字符 c。换句话来说,字符串常的行数组名相同。

10,C++允许按值传递结构,也允许传递结构的址,如果 glitz 是一个结构变量,如何按值传递它?如何传递它的地址?这两种方法有何利弊?

按值传递只需要用变量名 glitz 传递参数,而要传递它的地址,变量名前面加上取地址符 &glitz;按值传递将自动保护原始数据,但这是以时间和内存为代价。按地址节省时间和内存,但不能保护原始数据,除非对函数参数使用 const 限定符。另外,按值传递意味着可以使用常规的结构成员表示法,但指针则必须使用间接成员运算符。

11,函数 judge()的返回类型为 int,它将这样一个函数的地址作为参数:将 const char 指针作为参数,并将返回一个 int 值。请编写 judge()函数的原型。

int judge(int (*pf)(const char *));

12, 假设有如下结构声明:

struct applicant { char name[ 30 ]; int credit_ratings[ 3 ]; };

a, 编写一个函数,它将 application 结构作为参数,并显示该结构的内容。

刚做的时候不知道如何定义一个 int 类型成员的结构,在网上搜了下,就是用一个大括号包含 两个大括号 { },将两个基本数据类型的数组括起来,中间用逗号连接,再下面是代码

#include <iostream> using namespace std; struct applicant { char name[ 30 ]; int credit_ratings[ 3 ]; }; void Show_Applicant(applicant application); int main() { applicant application = {"show me the money",{30000, 40000, 50000}}; Show_Applicant(applicant application); return 0; } void Show_Applicant(applicant application) { cout << application.name << endl; for (int i = 0; i < 3; i ++) { cout << application.credit_ratings[ i ]; } }

代码运行如下:

b, 编写一个函数,它将 application 结构的地址作为参数,并显示该参数指向的结构的内容。

#include <iostream> using namespace std; struct applicant { char name[ 30 ]; int credit_ratings[ 3 ]; }; void Show_Applicant(applicant * application); int main() { applicant application = {"show me the money", {30000, 40000, 50000}}; Show_Applicant(&application); return 0; } void Show_Applicant(applicant * application) { cout << application -> name << endl; for (int i = 0; i < 3; i ++) cout << application -> credit_ratings[ i ] ", "; cout << endl; }

代码运行如下:

不知道是不是题目的意思,晚上来看看网上写的答案 晚上看了下网上的代码和我这个差不多

13,假设函数 f1()和 f2()的原型如下:

void f1(applicant *a); const char * f2(const applicant * al, const applicant * a2);

请将 p1 和 p2 分别声明为指向 f1 和 f2 的指针;将 ap 声明为一个数组,它包含 5 个类型与 p1 相同的指针;将 pa 声明为一个指针,它指向的数组包含 10 个类型与 p2 相同的指针。使用 typedef 来完成这项工作。

void f1(applicant *a); // 声明函数 f1,即函数 f1 原型 typedef void*p_f1)(applicant *); // 定义指向函数 f1 的指针类型,被指向的函数是返回值为 void 类型,参数为 applicant *的形式 p_f1 p1 = f1; // 再将指针类型 p_f1 定义变量 p1, 指向 函数名为 f1 的指针,说通俗点就是将 p1 定义为 void(*p1)(applicant *a);这样的函数指针,然后将函数 f1 的地址赋给指针 p1 const char * f2(const applicant * al, const applicant * a2);// 函数 f2原型 typedef const char *(*p_f2)(const applocant *, const applicant *); p_f2 p2 = f2; p_f1 ap[ 5 [; p_f2 (*pa)[ 10 ];

14,题外语,恶补下 typedef

原声明:void (b[10]) (void ()());

变量名为b,先替换右边部分括号里的,pFunParam为别名一:

typedef void (*pFunParam)();

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);

原声明的最简化版:

pFunx b[10];

原声明:doube(*)() (*e)[9];

变量名为e,先替换左边部分,pFuny为别名一:

typedef double(*pFuny)();

再替换右边的变量e,pFunParamy为别名二

typedef pFuny (*pFunParamy)[9];

原声明的最简化版:

pFunParamy e;

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号

就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直

到整个声明分析完。举例:

int (*func)(int *p);

首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针

;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明(*func)是一个函数,所以

func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值

类型是int。

int (*func[5])(int *);

func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明

func的元素是指针(注意这里的*不是修饰func,而是修饰func[5]的,原因是[]运算符

优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数

组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。

示例1:

#include <iostream> using namespace std; typedef void(* funcptr)(void); void hello_(void) { cout << "你好!" << endl; } void bye(void) { cout << "再见!" << endl; } int main() { funcptr p1; // 定义了一个该类型的指针 p1 p1 = hello_; // p1 指向函数 hello p1(); // 这里函数指针调用 hello_(); // 这里是直接调用 funcptr p2; p2 = bye; // p2 指向函数 bye p2(); bye(); return 0; }

代码1运行如下: 示例2:

#include <iostream> using namespace std; int add_(int a,int b) { return a+b; } int multiply_(int a ,int b) { return a*b; } int minus_(int a,int b) { return a-b; } int div_(int a ,int b) { return a/b; } typedef int (*pfunc)(int ,int); int main() { int aa =6,bb=3; pfunc p = add_;//用pfunc来定义一个指向函数的指针变量,pfunc就是一种类型而已 cout << p(aa,bb) <<endl; p = multiply_; cout <<p(aa,bb) <<endl; p = minus_; cout <<p(aa,bb) <<endl; p = div_; cout <<p(aa,bb) << endl; return 0; }

代码2运行如下: 总结到这里明白了一点,typedef 类型 类型名称(参数),可以复杂点, typedef 类型 (变量指针)(参数1(可以没有),参数2(可以没有));

再比如有代码:typdef void(*PFUNC)(void); 一层层的剥开代码,先去掉中间的括号,变成 void *PFUNC(void); 这是一个函数,函数名为 PFUNC,此函数不带参数,返回值是一个指向 void 的指针, 接下来,加上括号,变成 void(*PFUNC)(void); 这里(*PFUNC)优先级最高,表示 PFUNC 是一个指针。而且这个指针指向一个函数。指向的是没有参数且返回值是 void 指针的函数。 再接下来,加上 typedef,成 typedef void(*PFUNC)(void); 这里,定义了一种新类型 PFUNC,这种类型的含义如上所述,是一个指向函数的指针,且指向 的函数必须是无参数且返回值是 void指针。 再接下来,就可以使用 PFUNC 类型来定义新的变量了,比如: PFUNC MyFunc;


最新回复(0)