栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

《C++ Primer》第17章 17.4节习题答案

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

《C++ Primer》第17章 17.4节习题答案

《C++ Primer》第17章 标准库特殊设施

17.4节 随机数 习题答案

练习17.28:编写函数,每次调用生成并返回一个均匀分布的随机unsigned int。

【出题思路】

本题练习生成随机数。

【解答】

在函数中定义随机数引擎e作为随机数源,定义均匀分布u生成指定范围内的均匀分布的随机数。然后调用u(e)即可获得一个随机数。注意,将u和e声明为静态变量以保持状态,使得每次调用函数得到序列中的下一个数。

#include 
#include 

using namespace std;

unsigned int rand_int()
{
    //生成0到9999之间(包含)均匀分存的随机数
    static uniform_int_distribution u(0, 9999);
    static default_random_engine e;//生成无符号随机整数

    return u(e);
}

int main()
{
    for(int i = 0; i < 10; ++i)
        cout << rand_int() << " ";
    cout << endl;
    return 0;
}

运行结果:

练习17.29:修改上一题中编写的函数,允许用户提供一个种子作为可选参数。

【出题思路】

本题练习设置种子。

【解答】

为函数设置一个可选参数,当实参是非负整数时,用seed操作对引擎e重新设置种子。主程序三次生成并打印10个随机数,后两次分别重置种子为0和19743。编译运行程序,观察结果。

#include 
#include 

using namespace std;

unsigned int rand_int(long seed = -1)
{
    //生成0到9999之间(包含)均匀分布的随机数
    static uniform_int_distribution u(0, 9999);
    static default_random_engine e;//生成无符号随机整数
    if(seed >= 0)
        e.seed(seed);
    return u(e);
}

int main()
{
    for(int i = 0; i < 10; i++)
        cout << rand_int() << " ";
    cout << endl;

    cout << rand_int(0) << " ";
    for(int i = 0; i < 9; i++)
        cout << rand_int() << " ";
    cout << endl;

    cout << rand_int(19743) << " ";
    for(int i = 0; i < 9; i++)
        cout << rand_int() << " ";
    cout << endl;
    return 0;
}

运行结果:

练习17.30:再次修改你的程序,此次再增加两个参数,表示函数允许返回的最小值和最大值。【出题思路】

本题练习设置随机数的最大值和最小值。

【解答】

再增加两个参数表示允许的最大值和最小值,当给定参数合法时(缺省参数不合法),构造一个uniform_int_distribution对象,生成的随机数最大最小值符合给定参数要求。编译运行程序,观察后两行输出结果。

#include 
#include 

using namespace std;

unsigned int rand_int(long seed = -1, long min = 1, long max = 0)
{
    //生成0到9999之间(包含)均匀分布的随机数
    static uniform_int_distribution u(0, 9999);
    static default_random_engine e;//生成无符号随机整数
    if(seed >= 0)
        e.seed(seed);
    if(min <= max)
        u = uniform_int_distribution(min, max);

    return u(e);
}

int main()
{
    for(int i = 0; i < 10; i++)
        cout << rand_int() << " ";
    cout << endl;

    cout << rand_int(0) << " ";
    for(int i = 0; i < 9; i++)
        cout << rand_int() << " ";
    cout << endl;

    cout << rand_int(19743) << " ";
    for(int i = 0; i < 9; i++)
        cout << rand_int() << " ";
    cout << endl;

    cout << rand_int(19743, 0, 9) << " ";
    for(int i = 0; i < 9; i++)
        cout << rand_int() << " ";
    cout << endl;
    return 0;
}

运行结果:

 练习17.31:对于本节中的游戏程序,如果我们在do循环内定义b和e,会发生什么?

【出题思路】

理解随机数的生成。

【解答】在循环内定义b和e,每个循环步都会用默认的种子(0)重新初始化随机数引擎e。因此,调用b(e)永远得到的是特定随机数序列的第一个数,游戏的先行者永远是固定的。而在循环外定义,则可保持引擎的状态,每次得到随机数序列中的下一个值,游戏的先行者会改变。

练习17.32:如果我们在循环内定义resp,会发生什么?

【出题思路】

理解变量生命周期。

【解答】

如果在循环内定义resp,则其生命周期仅在循环体内,而while循环条件判定不属于循环体。因此,在进行循环条件判定时,resp已经被销毁,程序会产生编译错误。

练习17.33:修改11.3.6节(第392页)中的单词转换程序,允许对一个给定单词有多种转换方式,每次随机选择一种进行实际转换。

【出题思路】

本题练习随机数的实际使用。

【解答】

首先,将trans_map的类型(包括buildMap的返回类型)改为map>,以便保存一个单词的多种转换方式。然后,在函数transform中声明随机数引擎e为静态局部变量,以便保存状态,每次得到随机数序列中的下一个数。在检查到存在转换规则后,声明一个均匀分布u,其最小值为0,最大值为转换方法数目减1,因此得到的随机数对应转换方式的下标。最后调用u(e)获得随机数,作为下标获取转换的目标字符串。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

map> buildMap(ifstream &map_file)
{
    //允许多种转换方法
    map> trans_map;//保存转换映射表
    string key;//要转换的单词
    string value;//替换的内容
    //读取第一个单词存入key,一行中剩余内存存入value
    while(map_file >> key && getline(map_file, value))
    {
        if(value.size() > 1)//检查是否有转换规则
            trans_map[key].push_back(value.substr(1));//跳过前导空格
        else
            throw runtime_error("no rule for " + key);
    }

    return trans_map;
}

const string &transform(const string &s, const map> &m)
{
    static default_random_engine e(time(0));//随机数引擎,静态变量保持状态
    //完成真正的转换,此程序的核心代码
    auto map_it = m.find(s);
    //单词在转换映射表中
    if(map_it != m.cend()){
        //随机数分布
        uniform_int_distribution u(0, map_it->second.size() - 1);
        return map_it->second[u(e)];//随机选择一种转换方式
    }
    else {
        return s;//否则返回原词
    }
}

//第一个参数是转换规则文件,第二个也是要转换的文件
void word_transform(ifstream &map_file, ifstream &input)
{
    auto trans_map = buildMap(map_file);//保存转换规则
    //调试用:创建转换规则映射表后打印它
    cout << "Here is our transformation map: nn";
    for(auto entry: trans_map)
    {
        cout << "key: " << entry.first << "tvalue:";
        for(auto s: entry.second)
            cout << s << ", ";
        cout << endl;
    }
    cout << endl << endl;
    //对给定文本进行转换
    string text;//保存输入的每一行
    while(getline(input, text))//读取输入一行
    {
        istringstream stream(text);//读取每个单词
        string word;
        bool firstword = true;//控制是否打印空格
        while(stream >> word){
            if(firstword)
                firstword = false;
            else
                cout << " ";//在单词间格打印空格
            //transform返回第一个参数或转换结果
            cout << transform(word, trans_map);//打印输出
        }
        cout << endl;//此行处理完毕
    }
}

int main(int argc, char **argv)
{
    cout << "argc=========" << argc << endl;
    //打开并检查两个文件
    if(argc != 3)
        throw runtime_error("wrong number of arguments");

    ifstream map_file(argv[1]);//打开转换规则文件
    if(!map_file)//检查是否打开成功
        throw runtime_error("no transformation file");
    ifstream input(argv[2]);//打开要转换的文件
    if(!input)//检查是否打开成功
        throw runtime_error("no input file");

    word_transform(map_file, input);

    return 0;
}

data17_33_input.txt文件内容:

where r u
y don’t u send me a pic
k the l8r

data17_33_map.txt文件内容:

brb be right back
k okay?
y why
r are
u you
pic picture
the thanks!
l8r later

设置命令行参数:

 运行结果:

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/433351.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号