C++ primer 第五版 第三章 课后练习

string类的输入字符和getline函数分别是如何处理空白字符的

标准库string的输入运算符自动忽略字符串开头的空白(包括空格符、换行符、制表符等),从第一个真正的字符开始读起,直到遇见下一处空白为止。

getline可保留输入时的空白,直到遇到换行符为止,此时换行符也被读进来,但是并不存储在最后的字符串中。

小贴士:

cin.clear();//更改cin的状态标识符
cin.sync();//清除缓冲区数据流

使用范围for语句将字符串内的所有字符用x代替

#include<iostream>
#include<string>

using namespace std;

int main()
{
    cout << "请输入一段字符串,可以包含空格" << endl;
    string s;
    getline(cin , s);
    for(auto &c : s)//c必须定义成引用类型,否则无法修改字符串的内容
    {
        c = 'X';
    }
    cout << s << endl;
}

读入一个包含标点符号的字符串,输出去除标点符号的剩余部分

#include<iostream>
#include<string>
#include<cctype>

using namespace std;

int main()
{
    string s;
    cout << "请输入一串字符串,最好包含标点符号:" << endl;
    getline(cin , s);
    for(auto c : s)
    {
        if(!ispunct(c))
            cout << c << " " ;
    }
    cout << endl;
    return 0;
}

附录:cctype头文件

定义和初始化vector对象

从cin读入一组词并把它们存入一个vector对象,然后设法把所有词改写为大写形式。输出改变后的结果,每个词占一行。

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

using namespace std;

int main()
{
    vector<string> vString;     //元素类型为string的vector对象
    string s;                   //记录用户的输入值
    char cont = 'y';             //与用户交互,决定是否继续
    cout << "请输入第一个词:" << endl;
    while(cin >> s)
    {
        vString.push_back(s);   //向vector对象中添加元素
        cout << "您要继续吗(y or n)?" << endl;
        cin >> cont;
        if(cont != 'y' && cont != 'Y')
            break;
        cout << "请输入下一个词:" << endl;
    }
    cout << "转换后的结果是:" << endl;
    for(auto &mem : vString)    //使用范围for循环遍历vString中的每个元素
    {
        for(auto &c : mem)      //使用范围for循环遍历mem中的每个字符
            c = toupper(c);     //改写为大写形式
        cout << mem <<endl;
    }
    return 0;
}

读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出。

#include<iostream>
#include<vector>

using namespace std;

int main()
{
    vector<int> vInt;
    int iVal;
    cout << "请输入一组数字:" << endl;
    while(cin >> iVal)							//按ctrl+z结束输入
        vInt.push_back(iVal);
    if(vInt.size() == 0)
    {
        cout << "没有输入数字" << endl;
        return -1;
    }
    cout << "相邻两项的和是:" << endl;
    for(decltype(vInt.size()) i = 0; i < vInt.size()-1; i += 2)
    {
        cout << vInt[i] + vInt[i+1] << " ";     //求相邻两项的和
        if((i + 2) % 10 == 0)					//每行输出5个数字
            cout << endl;
    }
    if(vInt.size() % 2 !=0)						//如果元素数是奇数,单独处理最后一个元素
        cout << vInt[vInt.size() - 1];
    return 0;
}

编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都变成原来的两倍,输出

#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>

using namespace std;

int main()
{
    vector<int> vInt;
    srand((unsigned)time(NULL));    //生成随机数种子
    for(int i = 0; i < 10; i++)     //循环10次
    {
        //每次循环生成一个1000以内的随机数并添加到vInt中
        vInt.push_back(rand() % 1000);
    }
    cout << "随机生成的10个数是:" << endl;
    //利用常量迭代器读取原始数据
    for(auto it = vInt.cbegin(); it != vInt.cend(); it++)
    {
        cout << *it << " ";          //输出当前数字
    }
    cout << endl;
    cout << "翻倍后的10个数字是:" << endl;
    //利用非常亮迭代器修改vInt内容并输出
    for(auto it = vInt.begin(); it != vInt.end(); it++)
    {
        *it *= 2;
        cout << *it << " ";         //输出当前数字
    }
    cout << endl;
    return 0;
}

小贴士:srand和rand()配合使用产生伪随机数序列。
rand函数在产生随机数前,需要系统提供的生成伪随机数序列的种子,rand根据这个种子的值产生一系列随机数。
如果系统提供的种子没有变化,每次调用rand函数生成的伪随机数序列都是一样的。
srand(unsigned seed)通过参数seed改变系统提供的种子值,从而可以使得每次调用rand函数生成的伪随机数序列不同,从而实现真正意义上的“随机”。只有seed变,产生的随机序列才会变。
通常可以利用系统时间来改变系统的种子值,即srand(time(NULL)),可以为rand函数提供不同的种子值,进而产生不同的随机数序列。
小贴士:C++没有定义两个迭代器的加法运算,即直接将两个迭代器相加没有意义,定义了迭代器的减法运算(同一容器),定义了迭代器与整数的加减法运算。指针的算术运算与vector类似,也可以执行递增、递减、比较、与整数相加、两个指针相减等操作。

相比vector,数组的缺点:(1)都能存放类型相同的对象,且对象本身没有名字,需要通过其所在位置访问。(2)数组大小不固定,不能随意向数组中增加额外的元素。(3)数组不能用size,字符数组可以用strlen,其他数组只能用sizeof(array)/sizeof(array[0])的方式计算数组的维度。

比较两个数组是否相等,用vector改写

#include<iostream>
#include<ctime>
#include<cstdlib>

using namespace std;

int main()
{
    const int sz = 5;                 //常量sz作为数组的维度
    int a[sz], b[sz], i;
    srand((unsigned) time(NULL));     //生成随机数种子
    //通过for循环为数组元素赋值
    for(i = 0; i < sz; i++)
        //每次循环产生一个10以内的随机数并添加到a中
        a[i] = rand() % 10;
    cout << "系统数据已经生成,请输入你猜测的5个数字(0~9),可以重复:" << endl;
    int uVal;
    //通过for循环为数组元素赋值
    for(i = 0; i < sz; i++)
        if(cin >> uVal)
            b[i] = uVal;
    cout << "系统生成的数据是:" << endl;
    for(auto val : a)
        cout << val << " ";
    cout << endl;
    cout << "你猜测的数据是:" << endl;
    for(auto val : b)
        cout << val << " ";
    cout << endl;
    int *p = begin(a), *q = begin(b);  //定义 分别令p,q指向a和b的首元素
    //C++ forbids comparison between pointer and integer   while(*p != end(a) && *q != end(b))
    while(p != end(a) && q != end(b))//p,q为指针本身 
    {
        if(*p != *q)
            cout << "抱歉,猜测数据与原数据不等" << endl;
            return -1;
        p++;
        q++;
    }
    cout << "全部猜对" << endl;
    return 0;
}

小贴士:C++不允许使用一个数组初始化另一个数组,也不允许使用vector对象直接初始化数组,允许使用使用数组来初始化vector对象。 vector<int> vInt(begin(a), end(a)); //a为数组

注意练习3.43,3.44,3.45的对比

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值