C++ Primer课后习题解答(第六章)

Exercises Section 6.1

Ex6.1

1. 参数是用来传递的,变量是通过定义得到的
2. 在调用过程中,有时候需要输入参数,此时参数会有值,可以直接传入;变量只有在赋值后才能使用

Ex6.2

a)
// origin code   返回类型不匹配
int f() { 
	string s;
    // ...
    return s;
}

// correct
string f() {
	string s;
    // ...
    return s;
}

b)
// origin code   函数没有返回类型
f2() (int i) { /* ... */ }

// correct 
int f2() (int i) { /* ... */ }

c)
// origion code   函数参数名字不能一样
int calc(int v1, int v1) { /* ... */ }

// correct 
int calc(int v1, int v2) { /* ... */ }

d)
// origin code  缺少花括号
double square(double x) return x * x;

// correct 
double square(double x) { return x * x; }

Ex6.3 6.4

#include<iostream>

int fact(int val)
{
    int ret = 1;
    while (val > 1)
    {
        ret *= val;
        --val;
    }
    return ret;
}

int main()
{
    int value = 0;
    int result = 0;
    std::cout << "Please enter a value: ";
    std::cin >> value;
    result = fact(value);
    std::cout << "The result is " << result << std::endl;
    system("pause");
    return 0;
}

Ex6.5

unsigned int v_abs(int value)
{
    if (value >= 0)
        return value;
    else 
        return -value;
}

Exercises Section 6.1.1

Ex6.6

parameter: 函数的参数
local variable: 函数内部的局部变量,当函数结束时失效
local static variable: 当程序终止时才会失效

Ex6.7

int times = 0;

int call_times()
{
    return times++;
}

Exercises Section 6.1.2

Ex6.8

// 文件名 Chapter6.h
int fact(int val);
unsigned int v_ans(int value);

Exercises Section 6.1.3

Ex6.9

// 文件名 fact.cc
#include "Chapter6.h"

int fact(int val)
{
    int ret = 1;
    while (val > 1)
    {
        ret *= val;
        --val;
    }
    return ret;
}

// 文件名 factMain.cc
#include<iostream>
#include "Chapter6.h"

int main()
{
    int value = 0;
    int result = 0;
    std::cout << "Please enter a value: ";
    std::cin >> value;
    result = fact(value);
    std::cout << "The result is " << result << std::endl;
    system("pause");
    return 0;
}

Exercises Setion 6.2.1

Ex6.10

#include<iostream>

using namespace std;

void swap_int(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}

int main()
{
    int value1 = 1, value2 = 2;
    int *a = &value1;
    int *b = &value2;
    swap_int(a, b);
    cout << value1 <<" " << value2 << endl;
}

Exercises Section 6.2.2

Ex6.11

void reset(int &i)
{
	i = 0;
}

Ex6.12

#include<iostream>

using namespace std;

void swap_int(int &a, int &b)
{
	int temp = a;
    a = b;
    b = temp;
}

int main()
{
    int value1 = 1, value2 = 2;
    swap_int(value1, value2);
    cout << value1 <<" " << value2 << endl;
}

Ex6.13

void f(T): 函数 f 有一个类型 T 的参数,返回值类型为 void
void f(T&): 函数有一个类型 T& 的参数,返回值类型为 void

Ex6.15

参数s: 字符串s不需要修改值,故而为 const
参数occurs: 需要修改值,故而不为 const
使用引用避免产生副本;由于参数 c 的类型很小,所以不使用引用也可
参数s设置为 plain reference 也可以;occurs 设置为 const 则会发生错误

Exercises Section 6.2.3

Ex6.16

// origion code
bool is_empty(string &s) { return s.empty(); }

// correct
bool is_empty(const string &s) { return s.empty(); }

Ex6.17

// 判断是否有大写字母存在
bool contains_capital_letters(const string &s)
{
    for (char c : s)
    {
        if (isupper(c))
            return true;
    }
    return false;
}

// 将字符串中所有字符改成小写字母
void to_lowercase(string &s)
{
    for (char &c : s)
    {
        c = tolower(c);
    }
}

Ex6.18

a) bool compare(matrix &, maxtrix &);
b) vector<int>::iterator change_val(int, vector<int>::iterator);

Ex6.19

double calc(double);
int count(const string &, char);
int sum(vector<int>::iterator, vector<int>::iterator, int);
vector<int> vec(10);

a) calc(23.4, 55.1);	// 非法,参数数量过多
b) count("abcda", 'a');	// 合法
c) calc(66);	// 合法,会进行隐式转换
d) sum(vec.begin(), vec.end(), 3.8);	// 合法

Ex6.20

当引用参数不需要被修改时可以使用 const;
能编译通过,只不过参数值可能被修改

Exercises Section 6.2.4

Ex6.21

int larger(int v, int *p)
{
	if (v > (*p))
    	return v;
    else 
    	return (*p);
}

Ex6.22

void swap(int *a, int *b)
{
	int temp = *a;
    *a = *b;
    *b = temp;
}

Ex6.23

void print(int value)
{
	cout << value << endl;
}

void print(int (&arr)[])
{
	for (auto elem : arr)
    	cout << elem << endl;
}

Ex6.24

// origin code   输出数组中每个元素的值,数组下标为 int 类型
void print(const int ia[10])
{
	for (size_t i = 0; i != 10; ++i)
    	cout << ia[i] << endl;
}

Exercises Section 6.2.5

Ex6.25

#include<iostream>
#include<string>

using namespace std;

int main(int argc, char *argv[])
{
    string result;
    for (int i = 1; i != argc; ++i)
        result += argv[i];
    cout << result << endl;
    system("pause");
    return 0;
}

Ex6.26

#include<iostream>

using namespace std;

int main(int argc, char *argv[])
{
    for (int i = 1; i != argc; ++i)
        cout << "Argument " << i << " is " << argv[i] << endl;
    system("pause");
    return 0;
}

Exercises Section 6.2.6

Ex6.27

#include<iostream>

using namespace std;

int main()
{
    int sum = 0;
    initializer_list<int> list = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (auto it = list.begin(); it != list.end(); ++it)
    {
        sum += *it;
    }
    cout << sum << endl;
    system("pause");
    return 0;
}

Ex6.28

const string &

Ex6.29

使用引用能够减小开销

Exercises Section 6.3.2

Ex6.31

当返回的不是函数体内创建的引用时,返回引用有效;
当返回的是函数体外或者传入的 const 引用时,返回 const 引用有效

Ex6.32

// origin code  合法;给数组ia中的元素赋值其下标值
int &get(int *arry, int index) { return arry[index]; }
int main() {
	int ia[10];
    for (int i = 0; i != 10; ++i)
    	get(ia, i) = i;
}

Ex6.33

void print_vector(const vector<size_type> &v, unsigned size)
{
    if (size >= v.size())
    {
        cout << endl;
        return;
    }
    cout << v[size] << " ";
    print_vector(v, size + 1);
}

Ex6.34

最终结果为0

Ex6.35

如果使用factorial(val--),那么首先会进行factorial(val),然后再将val减1

Exercises Section 6.3.3

Ex6.36

string(&f(string(&arrStr)[10]))[10];

Ex6.37

// 尾置返回类型
auto f(string(&arrStr)[10])) -> string(&)[10];

// 类型别名
typedef str string[10];
str (&f(str(&arrStr)));

// decltype
decltype(arrStr) &f(string (&arrStr)[10]);

Ex6.38

int odd[] = {1, 3, 5, 7, 9};
int even[] = {2, 4, 6, 8};
decltype(odd) &arrPtr(int i);

Exercises Section 6.4

Ex6.39

a) int calc(int , int);		// 两个int类型参数,返回类型为int
   int calc(const int, const int);	// 两个 const int 类型参数,返回类型为 int

b) int get();	// 无参,返回类型为 int
   double get();	// 非法,无参函数不能同名

c) int *reset(int *);	// 一个int*类型参数,返回类型为 int*
   double *reset(double *);	// 一个double*类型参数,返回类型为 double*

Exercises Section 6.5.1

Ex6.40

a) int ff(int a, int b = 0, int c = 0);	// 合法
b) char *init(int ht = 24, int wd, char bckgrnd);	// 非法;一旦某个形参被赋值,那么它后面的形参都必须赋值

Ex6.41

char *init(int ht, int wd = 80, char bckgrnd = ' ');
a) init();	// 非法;ht没有默认值
b) init(24, 10);	// 合法;等价于init(24, 10, ' ');
c) intit(14, '*');	// 非法;只能够省略尾部参数

Ex6.42

#include <iostream>

using namespace std;

string make_plural(size_t ctr, const string &word, const string &ending="s")
{
    return (ctr > 1) ? word + ending : word; 
}

int main()
{
    cout << "singular:" << make_plural(1,"success","es") << " " << make_plural(1,"failure") << endl;
    cout << "plural:" << make_plural(2,"success","es") << " " << make_plural(2,"failure") << endl;
    return 0;
}

Exercises Section 6.5.2

Ex6.43

a) inline bool eq(const BigInt&, const BigInt&) { ... }	// 头文件;因为被inline修饰的函数在程序中可能出现多次,并且需要精确匹配
b) void putValues(int *arr, in size);	// 可以在源文件也可以在头文件

Ex6.44

inline bool isShorter(const string &s1, const string  &s2)
{
	return s1.size() < s2.size();
}

Ex6.46

// 可以 
constexpr bool isShorter(const string &s1, const string  &s2)
{
	return s1.size() < s2.size();
}

Exercises Section 6.5.3

Ex6.48

string s;
while (cin >> s && s != sought) { }	// empty body
assert(cin);	// 用户只要输入内容,则该语句永远为真

// 修改如下
assert(s == sought);

Exercises Section 6.6

Ex6.49

candidate function: 与被调用的函数同名的函数并且在调用时已经声明
viable function: 与被调用函数不仅同名,而且参数个数要相等,参数类型相等或者能够转换

Ex6.50

void f();
void f(int);
void f(int, int);
void f(double, double = 3.14);

a) f(2.56, 42);		// illegal;the call is ambiguous
b) f(42);		// f(int)
c) f(42, 0);	// f(int, int)
d) f(2.56, 3.15);	// f(double, double)

Exercises Section 6.6.1

Ex6.52

void manip(int, int);
double dobj;

a) manip('a', 'z');	// rank 3
b) manip(55.4, dobj);	// rank 4

Ex6.53

a) // 如果调用函数时,实参有常量引用类型,则调用第二条语句
	int calc(int&, int&);
    int calc(const int&, cosnt int&);
   
b) // 如果调用函数时,实参指针指向的变量为常量,则调用第二条语句
	int calc(char*, char*);
	int calc(const char*, const char*);
   
c) //	指针的顶层const不算重载,重复定义(非法) 
	int calc(char*, char*);
	int clac(char* const, char* const);

Exercises Section 6.7

Ex6.54

int f(int, int);
using pf = decltype(f) *;
vector<pf> v;

Ex6.55

// 加法
int add(int a, int b)
{
	return a + b;
}

// 减法
int subtract(int a, int b)
{
	return a - b;
}


// 乘法
int multiply(int a, int b)
{
	return a * b;
}

// 除法
int divide(int a, int b)
{
	return b != 0 ? a / b : 0;
}

Ex6.56

std::vector<decltype(func) *> vec{add, subtract, multiply, divide};
for(auto f : vec) 
	std::cout << f(2, 2) << std::endl;
posted @   astralcon  阅读(38)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示