《C++ Primer》第14章 14.8节习题答案

《C++ Primer》第14章 操作重载与类型转换

14.8节 函数调用运算符 习题答案

练习14.33:一个重载的函数调用运算符应该接受几个运算对象?

【出题思路】

理解调用运算符。

【解答】

0个或多个。

练习14.34:定义一个函数对象类,令其执行if-then-else的操作:该类的调用运算符接受三个形参,它首先检查第一个形参,如果成功返回第二个形参的值,如果不成功返回第三个形参的值。

【出题思路】

本题练习定义调用运算符。

【解答】

#include <iostream>
#include <string>
#include<sstream>        //istringstream 必须包含这个头文件

using namespace std;

class IfElseThen
{
public:
    IfElseThen() { }
    IfElseThen(int i1, int i2, int i3): iVal1(i1), iVal2(i2), iVal3(i3)
    {

    }

    int operator() (int i1, int i2, int i3)
    {
        return i1 ? i2 : i3;
    }

    void print()
    {
        cout << "iVal1 = " << iVal1 << " iVal2 = " << iVal2 << " iVal3 = " << iVal3 << endl;
    }

private:
    int iVal1, iVal2, iVal3;
};

int main()
{
    IfElseThen ifelse;
    cout << "ifelse==========" << ifelse(5, 6, 2) << endl;
    return 0;
}

运行结果:ifelse==========6

练习14.35:编写一个类似于PrintString的类,令其从istream中读取一行输入,然后返回一个表示我们所读内容的string。如果读取失败,返回空string。

【出题思路】

本题练习定义调用运算符。

【解答】

#include <iostream>
#include <string>

using namespace std;

class ReadString
{
public:
    ReadString(istream &is = cin)
        :is(is)
    {

    }
    string operator()()
    {
        string line;
        if(!getline(is, line))
        {
            line = " ";
        }
        return line;
    }

private:
    istream &is;
};

int main()
{
    ReadString readString;
    cout << "call operator() = " << readString() << endl;
    return 0;
}

运行结果:

 练习14.36:使用前一个练习定义的类读取标准输入,将每一行保存为vector的一个元素。

【出题思路】

本题练习使用调用运算符。

【解答】

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class ReadString
{
public:
    ReadString(istream &is = cin)
        :is(is)
    {

    }
    string operator()()//重载函数对象运行符
    {
        string line;
        if(!getline(is, line))
        {
            line = " ";
        }
        return line;
    }

private:
    istream &is;
};

void testReadString()
{
    ReadString rs;
    vector<string> vec;
    while(true)
    {
        string line = rs(); //调用函数对象
        if(!line.empty())
        {
            vec.push_back(line);
        }
        else
        {
            break;
        }
    }
    cout << "output==============" << endl;
    for(auto iter: vec)
    {
        cout << iter << endl;
    }
}

int main()
{
    testReadString();

    return 0;
}

运行结果:

练习14.37:编写一个类令其检查两个值是否相等。使用该对象及标准库算法编写程序,令其替换某个序列中具有给定值的所有实例。

【出题思路】

本题练习定义和使用调用运算符。

【解答】

#include <iostream>
#include <vector>
#include <sstream>
#include <string>
#include <algorithm>    // std::replace_if

using namespace std;

class IntCompare
{
public:
    IntCompare(int v): val(v)
    {

    }
    bool operator()(int v)
    {
        return val == v;
    }

private:
    int val;
};

int main()
{
    vector<int> vec = {1,2,3,2,1};
    const int oldValue = 2;
    const int newValue = 200;
    IntCompare icmp(oldValue);
    std::replace_if(vec.begin(), vec.end(), icmp, newValue);
    cout << "icmp==================" << icmp.operator()(3) << endl;
    return 0;
}

运行结果:icmp==================0

练习14.38:编写一个类令其检查某个给定的string对象的长度是否与一个阈值相等。使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个、长度为2的单词有多少个、……、长度为10的单词又有多少个。

【出题思路】

本题练习定义和使用调用运算符。

【解答】

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class StrLenIs
{
public:
    StrLenIs(int len):m_len(len)
    {  }
    bool operator()(const string &str)
    {
        return str.length() == m_len;
    }

private:
    int m_len;
};

void readStr(istream &is, vector<string> &vec)
{
    string word;
    while(is >> word)
    {
        vec.push_back(word);
    }
}

int main()
{

    vector<string> vec;
    readStr(cin, vec);
    const int minLen = 1;
    const int maxLen = 10;
    for(int i = minLen; i <= maxLen; i++)
    {
        StrLenIs slenIs(i);
        //相当于每次调用 slenIs(vec.at(i))
        cout << "len:" << i << ",count:" << count_if(vec.begin(), vec.end(), slenIs) << endl;

    }
    return 0;
}

运行结果:

练习14.39:修改上一题的程序令其报告长度在1至9之间的单词有多少个、长度在10以上的单词又有多少个。

【出题思路】

本题练习定义和使用调用运算符。

【解答】

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

class StrLenBetween
{
public:
    StrLenBetween(int minLen, int maxLen):
        minLen(minLen), maxLen(maxLen)
    {    }

    bool operator()(const string &str)
    {
        return str.length() >= minLen && str.length() <= maxLen;
    }

private:
    int minLen;
    int maxLen;
};

class StrNotShorterThan
{
public:
    StrNotShorterThan(int len):m_len(len)
    {  }
    bool operator()(const string &str)
    {
        return str.length() >= m_len;
    }
    //重载函数调用符
    int operator()() { return m_len; }

private:
    int m_len;
};

void readStr(istream &is, vector<string> &vec)
{
    string word;
    while(is >> word)
    {
        vec.push_back(word);
    }
}

int main()
{
    vector<string> vec;
    readStr(cin, vec);
    StrLenBetween slenBetween(1, 9);
    StrNotShorterThan sNotShorterThan(10);

    cout << "len 1~9: " << count_if(vec.begin(), vec.end(), slenBetween) << endl;
    cout << "len >=10: " << count_if(vec.begin(), vec.end(), sNotShorterThan) << endl;
    cout << endl;
    return 0;
}


运行结果:

练习14.40:重新编写10.3.2节(第349页)的biggies函数,使用函数对象类替换其中的lambda表达式。

【出题思路】

本题练习定义和使用调用运算符。

【解答】

#include <iostream>
#include <string>
#include <sstream>        //istringstream 必须包含这个头文件
#include <vector>
#include <algorithm>


using namespace std;

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

class IsShoter
{
public:
    bool operator() (const string &s1, const string &s2) const
    {
        return s1.size() < s2.size();
    }
};

class NotShorterThan
{
public:
    NotShorterThan(int len): miniLen(len)
    {

    }
    bool operator() (const string &str)
    {
        return str.size() >= miniLen;
    }

private:
    int miniLen;
};

class PrintString
{
public:
    //PrintString() = delete;
    PrintString(ostream &o = cout): os(o)
    {

    }

    void operator() (const string &str)
    {
        cout << str << " ";
    }

private:
    ostream &os;

};

void elimDups(vector<string> &words)
{
    sort(words.begin(), words.end());

    for_each(words.begin(), words.end(), PrintString(cerr));
    cerr << endl;
    auto end_unique = unique(words.begin(), words.end());

    words.erase(end_unique, words.end());

    for_each(words.begin(), words.end(), PrintString(cerr));
    cerr << endl;

}

void biggies(vector<string> &words, vector<string>::size_type sz)
{
    elimDups(words);
    IsShoter is;
    stable_sort(words.begin(), words.end(), is);

    NotShorterThan nst(sz);
    auto wc = find_if(words.begin(), words.end(), nst);

    auto count = words.end() - wc;
    cout << count << " " << make_plural(count, "word", "s") << " of length " << sz << " or longer " << endl;

    PrintString ps;
    for_each(wc, words.end(), ps);
    cout << endl;
}

int main()
{
    vector<string> words;

    string next_word;
    while(cin >> next_word)
    {
        words.push_back(next_word);
    }

    biggies(words, 6);

    cout << "Hello World!" << endl;
    return 0;
}

运行结果:

 练习14.41:你认为C++11新标准为什么要增加lambda?对于你自己来说,什么情况下会使用lambda,什么情况下会使用类?

【出题思路】

本题旨在理解lambda。

【解答】

在C++11中,lambda是通过匿名的函数对象来实现的,因此我们可以把lambda看作是对函数对象在使用方式上进行的简化。当代码需要一个简单的函数,并且这个函数并不会在其他地方被使用时,就可以使用lambda来实现,此时它所起的作用类似于匿名函数。但如果这个函数需要多次使用,并且它需要保存某些状态的话,使用函数对象则更合适一些。

练习14.42:使用标准库函数对象及适配器定义一条表达式,令其

(a)统计大于1024的值有多少个。

(b)找到第一个不等于pooh的字符串。

(c)将所有的值乘以2。

【出题思路】

本题练习使用函数对象。

【解答】

(a): count_if(vec.begin(), vec.end(), bind2nd(greater<int>(), 1024));
(b): find_if(vec.begin(), vec.end(), bind2nd(not_equal_to<string>(), "pooh"));
(c): transform(vec.begin(), vec.end(), vec.begin(), bind2nd(multiplies<int>(), 2));

练习14.43:使用标准库函数对象判断一个给定的int值是否能被int容器中的所有元素整除。

【出题思路】

本题练习使用函数对象。

【解答】

#include <iostream>
#include <string>
#include <sstream>        //istringstream 必须包含这个头文件
#include <vector>
#include <algorithm>
#include <functional>


using namespace std;

bool dividedByAll(vector<int> &ivec, int dividend)
{
    int nInt = count_if(ivec.begin(), ivec.end(), bind1st(modulus<int>(), dividend));
    cout << "nInt=====================" << nInt << endl;
    return  nInt == 0;
}

int main()
{
    vector<int> nInt = {12, 36, 58, 96, 78, 62};

    bool bValue = dividedByAll(nInt, 3);
    if(bValue)
        cout << "所有的数都能被3整除======" << endl;
    else
        cout << "有的数不能被3整除======" << endl;

    bool bValue2 = dividedByAll(nInt, 2);
    if(bValue2)
        cout << "所有的数都能被2整除======" << endl;
    else
        cout << "有的数不能被2整除======" << endl;

    cout << "Hello World!" << endl;
    return 0;
}

运行结果:

 练习14.44:编写一个简单的桌面计算器使其能处理二元运算。

【出题思路】

本题练习使用函数对象。

【解答】

#include <iostream>
#include <map>
#include <string>
#include <functional>
#include <vector>
#include <algorithm>

using namespace std;

map<string, function<int (int,int)> > binOps = {
        {"+", plus<int>()},
        {"-", minus<int>()},
        {"*", multiplies<int>()},
        {"/", divides<int>()},
        {"%", modulus<int>()}
};

int main()
{
    int left, right;
    string op;
    cin >> left >> op >> right;
    cout << binOps[op](left, right);
    return 0;
}

运行结果:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值