《C++ Primer》第五版课后习题解答_第六章(3)(16-26)
系统环境: windows 10 1703
编译环境:Visual studio 2017
6.16
s 被定义成常量字符串引用会更好,否则只能和非常量字符串以及非字面量绑定,很有局限性。可以修改为:
bool is_empty(const string& s) { return s.empty(); }
6.17
(1) 判断是否有大写字母
ExamUpper.h
#pragma once #include <iostream> #include <string> using std::string; bool ExamUpper(const string &s);ExamUpper.cpp
#include "ExamUpper.h" bool ExamUpper(const string &s) { for (decltype(s.size()) i = 0; i != s.size(); ++i) { if (isupper(s[i])) { return isupper(s[i]); } else if (i != s.size()) { continue; } } return isupper(s[0]); }ExamMain.cpp
#include "ExamUpper.h" int main() { string s; getline(std::cin, s); int a = ExamUpper(s); std::cout << a << std::endl; return 0; }输入:love leonie 输出:0
输入:Love Leonie 输出:1
(2) 把 string 对象全部改成小写形式
s2lower.h
#pragma once #include <iostream> #include <string> using std::string; string s2lower( string &s);s2lower.cpp
#include "s2lower.h" string s2lower(string &s) { for (auto &a : s) { a = tolower(a); } return s; }s2lowerMain.cpp
#include "s2lower.h" int main() { string s; getline(std::cin, s); s = s2lower(s); std::cout << s << std::endl; return 0; }输入:LOVE LEONIE
输出:love leonie
(3) 在两个函数中我是用的形参类型不同。
检查字符串中是否有大写的函数,形参类型是常量引用。原因有二:1. 避免拷贝大字符串造成的效率降低而是用引用类型;2. 无需在函数中改变原字符串的值,所以使用常量引用类型。
改写字符串为小写形式的函数,形参类型为引用。原因有二:1.避免拷贝大字符串造成的效率降低而是用引用类型;2. 需要在函数中改变原字符串的值,所以使用非常量引用类型。
6.18
(a)
bool compare(matrix &matrix1, matrix &matrix2) { /*...*/ }比较两个矩阵的内容是否相同,并返回一个布尔值。
(b)
vector<int>::iterator change_val(int i, vector<int>::iterator j) { /*...*/ }
6.19
(a) 不合法,形参是有一个,却传入了两个参数;
(b) 合法;
(c) 合法;
(d) 合法(传入的浮点数 3.8 会先被强制转换成 int 类型,再参与函数运算)。
6.20
(1) 当传入的实参为常数,或者传入的实参的值不需要被改变,或者需要传入一个字符串字面值以初始化字符串引用时,需要用常量引用;
(2) 如果形参应该是常量引用,却设为了普通引用,会出现一些出人意料的后果。比如在用字符串字面值初始化引用时,会出现编译错误。或者当其他函数(正确地)将 string 类型的形参定义为常量引用,则错误定义的函数则不能在此类函数中正常使用(见教材 p192)。
6.21
compare.h
#pragma once #include <iostream> using std::cout; using std::cin; using std::endl; int compare(int ival, const int *ip);compare.cpp
#include "compare.h" int compare(int ival, const int *ip) { int ans = (ival >= *ip) ? ival : *ip; return ans; }compareMain.cpp
#include "compare.h" int main() { int i = 0; int j = 0; cout << "Enter two integers: " << endl; cin >> i >> j; int ans = compare(i, &j); cout << "The bigger number is: " << ans << endl; return 0; }因为不需要更改实参的值,指针的类型应为常量整型指针。
6.22
swap.h
#pragma once #include <iostream> using std::cout; using std::cin; using std::endl; void swap(int *&ip1, int *&ip2);swap.cpp
#include "swap.h" void swap(int *&ip1, int *&ip2) { int *temp; temp = ip1; ip1 = ip2; ip2 = temp; }swapMain.cpp
#include "swap.h" int main() { int i = 0; int j = 0; int *ip = &i; int *jp = &j; cout << "Enter two integers: " << endl; cin >> i >> j; swap(ip, jp); cout << "ip " << *ip << " jp " << *jp << endl; return 0; }输入 5 6
输出 ip 6 jp 5
6.23
print.h
#pragma once #include <iostream> using std::cout; using std::endl; using std::begin; using std::end; void print(const int *ip); // 函数 1 void print(const int *beg, const int *end);// 函数 2 void print(const int *ip, size_t size);// 函数 3 void print(int(&ip)[2]);// 函数 4print.cpp
#include "print.h" void print(const int *ip)// 函数 1 { if (ip) { while (*ip) { cout << *ip << endl; ++ip; } } } void print(const int *beg, const int *end)// 函数 2 { while (beg != end) { cout << *beg++ << endl; ++beg; } } void print(const int *ip, size_t size)// 函数 3 { for (size_t i = 0; i != size; ++i) { cout << ip[0] << endl; } } void print(int(&ip)[2])// 函数 4 { for (auto a : ip) { cout << a << endl; } }printMain.cpp
#include "print.h" int main() { int i = 0, j[2] = { 0, 1 }, k[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; print(&i); print(k); // 调用了函数 1,如果在这里选择 print(j),则会报错。 // 因为函数 1,函数 4 同时可被此语句调用。而因为函数 4 规定了大小,所以 print(k) 只能被函数 1 调用 print(begin(j), end(j)); print(begin(k), end(k)); // 调用函数 2 print(j, end(j) - begin(j)); //调用函数 3 //函数 4 不能被调用,因为能满足函数 4 的实参类型,必定能满足函数 1。故尝试使用符合函数 4 要求的实参调用函数,必定会发生重载错误。 return 0; }
6.24
函数想要输出一个长度为 10 的数组。但是,因为数组不能被拷贝,所以传入一个数组时,实际上传入的是指向该数组第一个元素的指针。所以如题所示定义函数,其实定义的形参是一个指针,不包含数组的长度信息,因此会出现错误。
如果要想在传入的实参中包含数组的长度信息,应该采用数组引用形参,如下:
void print(const int (&ia)[10]) { for (size_t i = 0; i != 10; ++i) { cout << ia[i] << endl; } }
6.25
#include <iostream> #include <string> using std::cout; using std::endl; using std::string; int main(int argc, char* argv[]) { string ans; argc = 3; argv[3] = 0; // 保证最后一个指针之后的元素为 0 ans = static_cast<string>(argv[1]) + " " + argv[2]; // 只有参数中存在字符串类型,才能使用加号连接,故用强制类型转换将其中一个参数转换成字符串类型 cout << ans << endl; return 0; }运行可执行文件时键入 Project1.exe Love Leonie
输出 Love Leonie
6.26
#include <iostream> #include <string> using std::cout; using std::endl; using std::string; int main(int argc, char* argv[]) { string ans; argc = 5; argv[5] = 0; // 保证最后一个指针之后的元素为 0 ans = static_cast<string>(argv[1]) + " " + argv[2] + " " + argv[3] + " " + argv[4]; cout << ans << endl; return 0; }运行可执行文件时键入 Project1.exe -d -o ofile data0
输出 -d -o ofile data0