《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]);// 函数 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

posted @ 2017-09-15 10:52  Adam_fei  阅读(158)  评论(0编辑  收藏  举报