系统环境: 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]);// 函数 4
print.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