C++学习之路(七),C++primer plus 第八章 函数探幽 - 编程练习

8.8 编程练习
1. 编写通常接受一个参数(字符串的地址),并打印该字符串的函数。然而,如果提供了第二个参数(int类型),且该参数不为 0,则该函数打印字符串的次数将为该函数被调用的次数(注意,字符串的打印次数不等于第二个参数的值,而等于函数被调用的次数)。是的,这是一个非常可笑的函数,但它让你能够使用本章的一些技术。在一个简单的程序中使用该函数,以演示该函数是如何工作的。
#include <iostream> using namespace std; char ch[ 20 ] = "oH~mY gOd!"; void display(char * ch, int n = 0); int main() { display(ch); display(ch, 5); display(ch); display(ch, 9); display(ch, 14); return 0; } void display(char * ch, int n) { static int times =0; times ++; cout << times << endl; if (n == 0) cout << ch << endl; esle { for (int i = 0; i < times; i ++) cout << ch << end; } cout << endl; }
程序运行如下:
,基本上完成了题目要求,但是
这句话还是没有好好的理解清楚
2. CandyBar 结构包含 3 个成员。第一个成员存储 candy bar 的品牌名称;第二个成员存储 candy bar 的重量(可能有小数);第三个成员存储(candy bar的热量(整数)。请编写一个程序,它使用一个这样的函数,即将 CandyBar 的引用、char指针、double 和 int 作为参数,并用最后 3 个值设置相应的成员。最后 3 个参数的默认值分别为“Millennium Munch”、2.85 和 350。另外,该程序还包含一个以 CandyBar 的引用参数,并显示结构内容的函数。请尽可能使用 const。
#include <iostream> using namespace std; struct CandyBar { char name[ 20 ]; double height; int cal; }; void set_candybar(CandyBar & cb, char * name = "Millennium Munch", double h = 2.85, int c = 350); void show_candybar(const CandyBar & cb); // 这里和对应的下面加不加 const 运行结果是一样的,不知道区别在哪里 int main() { CandyBar cb; set_candybar(cb); show_candybar(cb); return 0; } void set_candybar(CandyBar & cb, char * name, double h, int c) { for (int i = 0; i < 20; i ++) { cb.name[ i ] = name[ i ]; } cb.height = h; cb.cal = c; } void show_candybar(const CandyBar & cb) { cout << "Name: " << cb.name << endl; cout << "Height: " << cb.height << endl; cout << "Calorie: " << cb.cal << endl; }
代码运行结果:
3. 编写一个函数,它接受一个指向 String 对象的引用作为参数,并将该 string 对象的内容转换为大写,此可使用表 6.4 描述的函数 toupper()。然后编写一个程序,它通过使用一个循环让你能够用不同的输入来测试这个函数,该程序运行情况如下:
Enter a string (q to quit): go away GO AWAY Next string (q to quit): good grief! GOOD GRIEF! Next string (q to quit): q Bye.
先编写一个内联函数来实际此功能:
#include <iostream>
#include <string>
using namespace std;
string name;
int main()
{
cout << "Enter a string (q to quit): ";
getline(cin, name);
while(name != "q" && name != "Q")
{
for(int i = 0; i < name.size(); i ++)
name[ i ] = toupper(name[ i ]);
cout << name << endl;
cout << "Next string (q to quit)" ;
getline(cin, name);
}
cout << "Bye. " << endl;
return 0;
}
上述代码运行为:
另一个版本:
#include <iostream> #include <cstring> #include <string> using namespace std; char name[ 20 ]; int main() { cout << "Enter a string (q to quit): "; cin >> name; while(strcmp(name, "q") && strcmp(name, "Q")) { for (int i = 0; i < 20; i ++) name[ i ] = toupper(name[ i ]); cout << name << endl; cout << "Next string (q to quit): "; cin >> name; } cout << "Bye. " << endl; return 0; }
代码运行情况:
现在来开始实现题目的要求,string 版本:
#include <iostream> #include <string> using namespace std; string name; void toup(string & str); int main() { cout << "Enter a string (q to quit): ";
getline(cin, name);
while(str != "q" && str != "Q")
{
toup(name);
cout << "Next string (q to quit): ";
getline(cin, str);
}
cout << "Bye." << endl;
return 0; } void toup(string & str) { for (int i = 0; str[ i ]; i ++)
str[ i ] = toupper(str[ i ])
}
上述代码运行如下:
char 版本:
#include <iostream> using namespace std; char name[ 20 ]; void toup(char * name); int main() { cout << "Enter a string (q to quit);
cin.getline(name, 20); // cin >> name; 这里用这个不能读取一整行
while(strcmp(name, "q") && strcmp(name, "Q"))
{
toup(name);
cout << "Next string (q to quit): ";
cin.getline(name, 20); // 这里还行加一句
cin >> name;
}
cout << "Bye. " << endl;
return 0; } void toup(char *name) { for (int i = 0; name[ i ]; i ++)
name[ i ] = toupper(name[ i ];
cout << name;
}
代码运行如下:
4. 下面是一个程序框架:
#include <iostream> #include <cstring> // for strlen(), strcpy() using namespace std; struct stringy { char * str; // points to a string int ct; // length of string (not counting '\0') }; // prototypes for set(), show(), and show() go here int main() { stringy beany: char testing[ ] = "Reality isn't what it used to be."; set(beany, testing); // first argument is a reference, // allocates space to hole copy of testing, // new block, copies testing to new block, // and sets ct member of beany show(beany); // prints member string once show(beany, 2); // prints member string twice testing[ 0 ] = 'D'; testing[ 1 ] = 'u'; show(testing); // prints testing string once show(testing, 3); // prints testing string thrice show("Done!"); return 0; }
请提供其中描述的函数和原型,从而完成该程序。注意,应有两个 show()函数,每个都使用默认参数。请尽可能使用 const 参数。set()使用 new 分配足够的空间来存储指定的字符串,这里使用的技术与设计和实现类时使用的相似。(可能还必须修改头文件的名称,删除 using 编译指令,这取决于所用的编译器。)
#include <iostream> #include <cstring> // for strlen(), strcpy() using namespace std; struct stringy { char * str; // points to string char ct; // length of string (not counting '\0') }; // prototypes for set(), show(), and show() go here void set(stringy &, char *); void show(stringy &, int c = 1); void show(char *, int c = 1); int main() { stringy beany; char testing[ ] = "Reality isn't what it used to be."; set(beany, testing); // first argument is a reference, // allocates space to hole copy of testing, // sets str member of beany to point to thd // new block, copies testing to new block, // and sets ct member of beany show(beany); // prints member string once show(beany, 2); // prints member string twice testing[ 0 ] = 'D'; testing[ 1 ] = 'u'; show(testing); // prints testing string once show(testing, 3); // prints testing string thrice show("Done!"); return 0; }
void set(stringy & s, char * ch)
{
s.ct = strlen(ch) + 1;
s.str = new char[s.ct + 1];
strcpy(s.str, ch);
}
void show(stringy & s, int c = 1)
{
for (int i = 0; i < c; i ++)
cout << "str = " << s.str << " ct = " << s.ct << endl;
}
void show(char * s, int c)
{
fot int i = 0; i < c; i ++)
cout << "str = " << s.str << endl;
}
5. 编写模板函数 max5(),它将一个包含 5 个 T 类型元素的数组作为参数,并返回数组中最大的元素(由于长度固定,因此可以循环中使用硬编码,而不必通过参数来传递)。在一个程序中使用该函数,将 T 替换为一个包含 5 个 int 值的数组和一个包含 5 个 double 值的数组,以测试该函数。
// 1.先编写一个返回最大值的代码:
#include <iostream>
#include <time.h>
#include <stdlib.h> // 有的编译器需要加这个
using namespace std;
int main()
{
int s[ 5 ], temp;
srand(time(0));
// cout << "Enter five number: ";
for (int i = 0; i < 5; i ++)
{
// cin >> s[ i ];
s[ i ] = rand() % 100; // 随机1 - 99 数
cout << s[ i ] << " ";
}
cout << endl;
temp = s[ 0 ];
for (int j = 1; j < 5; j ++)
{
if (temp > s[ j ])
continue;
else
temp = s[ j ];
}
cout << "其中最大的数为: " << temp << endl;
return 0;
}
上述是使用随机数中找出最大值的代码,运行结果
// 2.再使用函数模板返回 5 个数中最大值 #include <iostream> #include <time.h> #include <stdlib.h> // 有的编译器需要加这个 using namespace std; template <typename T> void max5(T * s); int main() { int ari[ 5 ]; double ard[ 5 ]; cout << "输入5个整数: "; for (int i = 0; i < 5; i ++) { cin >> ari[ i ]; cout << ari[ i ] << "\t" ; } cout << endl; max5(ari); cout << "输入5个小数: "; for (int j = 0; j < 5; j ++) { cin >> ard[ j ]; cout << ard[ j ] << "\t" ; } cout << endl; max5(ard); return 0; } template <typename T> void max5(T s[]) { T temp; temp = s[ 0 ]; for (int j = 1; j < 5; j ++) { if (temp > s[ j ]) continue; else temp = s[ j ]; } cout << "其中最大的数为: " << temp << endl; }
这是使用模板来找出最大值,代码运行如下
6.编写模板函数 maxn(),它将由一个 T 类型元素组成的数组和一个表示数组元素数目的整数作为参数,并返回数组中最大的元素。在程序对它进行测试,该程序使用一个包含 6 个 int 元素的数组和一个包含 4 个 doulbe 元素的数组来调用该函数。程序还包含一个具体化,它将 char 指针数组和数组中的指针数量作为参数,并返回最长的字符串的地址。如果有多个这样的字符串,则返回其中第一个字符串的地址。使用由 5 个字符串指针组成的数组来测试该具体化。
先编写一段代码,手动输入元素数目和元素数,然后输出最大值,不过印象中,数组的元素数目必须是一个常量来着,普通的输入一个元素数目应该不能编译,不管了,先试下:
#include <iostream> using namespace std; void maxn(int *s, int); int main() { int n; cout << "输入数组元素数目: "; cin >> n; int ari[ n ]; // 错误提示:expected constant expression(应为常量表达式) cout << "输入 " << n << "数组元素数: "; for (int i = 0; i < n; i ++) cout << ari[ i ] << "\t"; // ① 这里缺了 cin >> ari[ i ]; return 0; } void maxn(int * s, int n) { int tmp = ari[ 0 ]; // ② 这里不能用 ari 这个数组名,这个数组名只存在于上面 main 函数中,而这里只能用参数名 s, for (int i = 1; i < n; i ++) { if tmp > ari[ i ]; // ③ 这里是个灰常低级的错误 continue; else tmp = ari[ i ]; } cout << "最大的数是: " << tmp; }
果不基然;以上代码不能编译成功,这里 int ari[ n ]; 提示expected constant expression(应为常量表达式),后来在 网上查了下,一定要有和int * ari = new int[ n ];来代码前面那段代码;另外,上述代码还犯了几处错误:
① 这里缺了 cin >> ari[ i ];
② 这里不能用 ari 这个数组名,这个数组名只存在于上面 main 函数中,而这里只能用参数名 s,
③ 这里是个灰常低级的错误,
全部错误改正后代码运行结果如下:
在网上看到输入5个数中最大的代码有一段是这样的
for (int i = 1; i < 5 ;i ++) if (a[ i ] > temp)temp = a[ i ]; return temp;
我就纳闷了, (a[ i ] > temp)temp = a[ i ]; 这句话是个会什么操作?数学中有这样操作(2 + 3) X 5, 可以把中间的乘号去掉,简写成(2 + 3)5,我还想往上面的, (a[ i ] > temp)temp = a[ i ] 按数学上写法,a[ i ] * temp > temp * temp = a[ i ]; 这是几个意思,这么一写就更不懂了,于是在网上查 (a[ i ] > temp)temp 是什么意思,查不出来......,就在我想来想去不知道什么意思的时候,我在百度查 “5个数中最大值 C++”,的时候看到一段代码是这样写的,
for(int i=0;i<5;i++){ int temp; if(max<a[i]) max=a[i]; if(min>a[i]) min=a[i]; }
看到这里我终于明白了,网上多次写到 if (a[ i ] > temp)temp = a[ i ]; 的代码完全是有误导的嫌疑,不知道是输写习惯还是格式问题,好几个代码都好像是抄一个人写的,不说这个了。
最基本的第一步是完成了,然后是完成第二步题目要求的
#include<iostream> #include<cstring> using namespace std; template<typename T> T maxn(T ar[], int n); template<> const char * maxn(const char * ar[], int n); int main() { int ari[ 6 ] = {1, 2, 6, 9, 8, 3}; double ard[ 5 ] = {1.1, 2.2, 6.6, 9.9, 8.8}; const char * arr[ 4 ] = {"a Aa aAa", "BBBBBbb bBBbbbb bbbbbbbb.", "Ccccc cCc ccccc..", "dd...DD"}; cout << "The max integer of array is:" << maxn(ari, 6) <<endl; cout << "The max double of array is:" << maxn(ard, 5) <<endl; cout << "The max string of array is:" << maxn(arr, 4) <<endl; return 0; } template<typename T> T maxn(T ar[], int n) { T max = ar[ 0 ]; for (int i = 0; i < n; i ++) if (max < ar[ i ]) max = ar[ i ]; return max; } template<> const char * maxn(const char * ar[], int n) { const char * max = ar[ 0 ]; for (int i = 0; i < n; i ++) if (strlen(max) < strlen(ar[ i ])) max = ar[ i ]; return max; }
代码运行情况如下
7. 修改程序清单 8.14,使其使用两个名为 SumArray() 的模板函数来返回数组元素的总和,而不是显示数组的内容。程序应显示 thing 的总和以及所有 debt 的总和。
程序清单 8.14 有两个用来显示数组内容的模板定义。第一个定义(模板A)假设作为参数传递的数组中包含了要显示的数据;第二个定义(模板B)假设数组元素为指针,指向要显示的数据。
程序清单 8.14 temptempover.cpp
//tempover.cpp -- template overloading #include <iostream> using namespace std; template <typename T> // template A void SHowArray(T arr[], int n); template<typename T> // template B void ShowArray(T * arr[], int n); struct debts { char name[ 50 ]; double amount; }; int main() { int things[ 6 ] = {13, 31, 103, 301, 310, 130}; struct debts mr_E[ 3 ] = { {"Ima Wolfe", 2400.0}, {"Ura Foxe", 1300.0}, {"Iby Stout", 1800.0} }; double * pd[ 3 ]; // set pointers to the amount members of the structures in mr_E for (int i = 0; i < 3; i ++) pd[ i ] = &mr_E[ i ].amount; cout << "Listing Mr. E's counts of things: \n"; // things is an array of int ShowArray(things, 6); // usestemplate A cout << "Listing Mr. E's debts: \n"; // pd is an array of pointers to double ShowArray(pd, 3); // uses templalte B(more specialized) return 0; } template<typename T> void ShowArray(T arr[], int n) { cout << "template A\n"; for (int i = 0; i < n; i ++) cout << arr[ i ] << ' '; cout << endl; } template <typename T> void ShowArray(T *arr[], int n) { cout << "template B\n" for (int i = 0; i < n; i ++) cout << *arr[ i ] << ' '; cout << endl; }
修改为显示数组元素的和的代码:
#include <iostream> using namespace std; template <typename T> // template A void SumArray(T arr[], int n); template<typename T> // template B void SumArray(T * arr[], int n); struct debts { char name[ 50 ]; double amount; }; int main() { int things[ 6 ] = {13, 31, 103, 301, 310, 130}; struct debts mr_E[ 3 ] = { {"Ima Wolfe", 2400.0}, {"Ura Foxe", 1300.0}, {"Iby Stout", 1800.0} }; double * pd[ 3 ]; // set pointers to the amount members of the structures in mr_E for (int i = 0; i < 3; i ++) pd[ i ] = &mr_E[ i ].amount; cout << "Listing Mr. E's counts of things: \n"; // things is an array of int SumArray(things, 6); // uses template A cout << "Listing Mr. E's debts:\n"; // pd is an array of pointers to double SumArray<double>(pd, 3); // uses templalte B(more specialized) return 0; } template<typename T> void SumArray(T arr[], int n) { int sumt = 0; cout << "template A\n"; for (int i = 0; i < n; i ++) sumt += arr[ i ]; cout << sumt << ' '; cout << endl; } template <typename T> void SumArray(T *arr[], int n) { double sumd = 0.0; cout << "template B\n"; for (int i = 0; i < n; i ++) sumd += * arr[ i ]; cout << sumd << ' '; cout << endl; }
代码运行如下:
我还在想应该不会这么简单吧,网上去查下,一查还真是这样,唯一的一个难点应该是 sumd += * arr[ i ]; 这个代码中,当我首次用 sumd += arr[ i ],错误提示为
第一次将定义 double sumd = 0 ;改为 double * sum = 0;错误更多,于是就改了 sumd += * arr[ i ]; 这个了;

好了,反观这一章,从19年到10月份,正文到复习到练习,跨越一年,之间经历了历史上一次重大的世界新冠病毒,虽然到目前为止还没有攻克,但这一章经历的时间太长了,主要原因还是在于自身,自制能力差,有点不愿意动脑子,不过还好,也算是勉勉强强的学习完了这一章,好多的东西也不大懂,希望自己能够坚持学习这一本书,看看900+页,看了300+而,1/3了,真是有些不简单,坚持坚持再坚持,准备下一章……
浙公网安备 33010602011771号