C++ primer第五版习题 第三章

3.1 使用恰当的using 声明重做 1.4.1节和2.6.2节的练习

1.4.1

#include <iostream>
using std::cout;
using std::endl;
int main(){
    
    int sum = 0;
    for(int val = 50; val <=100; ++val){
        sum += val;
    }
    cout << "sum of 50 to 100 inclusive is "
              << sum << endl;
    
    return 0;
}
#include <iostream>
using std::cout;
using std::endl;
int main(){
    for(int val = 10; val >= 0; --val){
        cout << "val = " << val << endl;
    }
    return 0;
}
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
int main(){
    cout << "Enter two number: " << endl;
    int v = 0, v1 = 0;
    std::cin >> v >> v1;
    
    if(v <= v1){
        for(; v <= v1; ++v){
            cout << v << endl;
        }
    }
    else{
        for(; v1 <= v; ++v1){
            cout << v1 << endl;
        }
    }
}

2.6.2

#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
struct Sale_Data
{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main(){
//    for(Sales_Data sd; cin >> sd; cout << sd << endl);
    Sales_Data book;
    double price;
    cin >> book.bookNo >> book.units_sold >> price >> endl;
    book.revenue = book.units_sold * price;
    cout << book.bookNo << " " << book.units_sold << " " << book.revenue << " " << price << endl;
    
    return 0;
}
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::cerr;
struct Sales_Data{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main(){
    Sales_Data book, book2;
    double price;
    cin >> book.bookNo >> book.units_sold >> price >> endl;
    cin >> book2.bookNo >> book2.units_sold >> price >> endl;
    if(book.bookNo == book2.bookNo){
        cout << book.units_sold + book2.units_sold << endl;
    }else{
        cerr << "输入有误" << endl;
    }
    
    return 0;
}
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::string;
struct Sales_Data{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main(){
    Sales_Data total_book;
    double total_price;
    if(cin >> total_book.bookNo >> total_book.units_sold >> total_price){
//        int cnt = 1;
        total_book.revenue = total_book.units_sold * total_price;
        Sales_Data book;
        double book_price;
        while(cin >> book.bookNo >> book.units_sold >> book_price){
            book.revenue = book.units_sold * book_price;
            if(total_book.bookNo == book.bookNo){
                total_book.units_sold += book.units_sold;
                total_book.revenue += book.revenue;
//                ++cnt;
            }else{
                cout << total_book.bookNo << " " << total_book.units_sold << " " << total_book.revenue << total_price << endl;
//                std::cout << total_book.bookNo << "has " << cnt << "recordings!";
                total_book.bookNo = book.bookNo;
                total_price = book_price;
                total_book.units_sold = book.units_sold;
                total_book.revenue = book.revenue;
            }
            
        }
        cout << total_book.bookNo << " " << total_book.units_sold << " " << total_book.revenue << total_price << endl;
//        std::cout << total_book.bookNo << "has " << cnt << "recordings!";
    }
    else{
        cout << " No Data" << endl;
        return -1;
    }
    return 0;
}
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::string;
struct Sales_Data{
    string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

int main(){
    Sales_Data total_book;
    double total_price;
    if(cin >> total_book.bookNo >> total_book.units_sold >> total_price){
        int cnt = 1;
        total_book.revenue = total_book.units_sold * total_price;
        Sales_Data book;
        double book_price;
        while(cin >> book.bookNo >> book.units_sold >> book_price){
            book.revenue = book.units_sold * book_price;
            if(total_book.bookNo == book.bookNo){
//                total_book.units_sold += book.units_sold;
//                total_book.revenue += book.revenue;
                ++cnt;
            }else{
                cout << total_book.bookNo << "has " << cnt << "recordings!" << endl;
                total_book.bookNo = book.bookNo;
                total_price = book_price;
                total_book.units_sold = book.units_sold;
                total_book.revenue = book.revenue;
            }
           
        }
         cout << total_book.bookNo << "has " << cnt << "recordings!" << endl;
    }
    return 0;
}

3.2 编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词

一次一行

int main(){
    string line;
    cout << "请输入:" << endl;
    while(getline(cin, line)){//以空格为区分
        cout << "a" <<  line << endl;
    }
    return 0;
}

一次一个词

int main(){
    string word;
    cout << "请输入:" << endl;
    while(cin >> word){//以空格为区分
        cout << word << endl;
    }
    return 0;
}

3.3 请说明string类的输入运算符和getline函数分别是如何处理空白字符的。

  • 输入运算符不会读入开头的空白,从第一个字符开始,知道遇到下一个空白为止。在这里插入图片描述
  • getline() 是遇见换行符停止。开头的空白符算的。
    在这里插入图片描述

3.4 编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出比较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。

#include <iostream>
using namespace std;

int main(){
    string s1, s2;
    cin >> s1 >> s2;
    if(s1 == s2){
        cout << "Equal string!" << endl;
    }else{
        string s = s1 > s2 ? s1 : s2;
        cout << s << endl;
    }
}
#include <iostream>
using namespace std;

int main(){
    string s1, s2;
    cin >> s1 >> s2;
    if(s1.size() == s2.size()){
        cout << "same length!" << endl;
    }else{
        string s = s1.size() > s2.size() ? s1 : s2;
        cout << s << endl;
    }
}

3.5 编写一段程序从标准输入中读入多个字符串并将他们连接起来,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分割开来。

#include <iostream>
using namespace std;

int main(){
    string s, curr_s;
    cout << "请输入: " << endl;
    while(cin >> curr_s){
        //s += ' ';
        s += curr_s;
    }
    cout << s << endl;
}

空格分割

#include <iostream>
using namespace std;

int main(){
    string s, curr_s;
    cout << "请输入: " << endl;
    while(cin >> curr_s){
        s += ' ';
        s += curr_s;
    }
    cout << s << endl;
}

3.6 编写一段程序,使用范围for语句将字符串内所有字符用X代替。

#include <iostream>
#include <string>
using namespace std;

int main(){
    string s("Hello World");
    for(auto &c : s){
        c = 'X';
    }
    cout << " " << s << endl;
    return 0;
}

3.7 就上一题完成的程序而言,如果将循环控制的变量设置为char将发生什么?先估计一下结果,然后实际编程进行验证。

不用引用最后的字符串还是原样输出。

3.8 分别用while循环和传统for循环重写第一题的程序,你觉得哪种形式更好呢?为什么?

while 循环

int main(){
    string s = "hello world";
    decltype(s.size()) index = 0;
    while(index <= s.size()){
        s[index] = 'X';
        index++;
    }
    cout << s << endl;
    return 0;
}

for 循环

int main(){
    string s = "hello world";
    for(decltype(s.size()) index = 0; index <= s.size(); ++index)
        s[index] = 'X';
    cout << s << endl;
    return 0;
}

for循环,方便

3.9 下面的程序有何作用?它合法吗?如果不合法?为什么?

string s;
cout << s[0] << endl;

不合法,因为不能用下标访问空字符串

3.10 编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。

int main(){
    string s = "hello !!! world", new_S;
    for(decltype(s.size()) index = 0; index <= s.size(); ++index){
        if(!ispunct(s[index])){
            new_S += s[index];
        }
    }
    cout << new_S << endl;
    return 0;
}

3.11 下面的范围for语句合法吗?如果合法,c的类型是什么?

const string s = "Keep out!";
for(auto &c : s){ /* ... */ }

是否合法要看for语句中的内容,c的类型是string对象中字符的引用,
如果for语句中给她赋值就非法,如果不赋值合法

3.12 下列vector对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。

vector<vector<int>> ivec;         // 老版不正确在C++11当中合法
vector<string> svec = ivec;       // 不正确,类型不一样
vector<string> svec(10, "null");  // 正确

3.13 下列的vector对象各包含多少个元素?这些元素的值分别是多少?

vector<int> v1;         // 空vector,v1执行默认初始化
vector<int> v2(10);     // 10个值为0的元素
vector<int> v3(10, 42); // 10个值为42的元素
vector<int> v4{ 10 };     // 一个值为10的元素
vector<int> v5{ 10, 42 }; // 2个元素,一个值为10,另一个为42
vector<string> v6{ 10 };  // 10个元素,默认是空字符串
vector<string> v7{ 10, "hi" };  // 10个值为“hi”的字符串

3.14 编写一段程序,用cin读入一组整数并把它们存入一个vector对象

int main(){
    int i;
    vector<int> v;
    while(cin >> i){
        v.push_back(i);
    }
}

3.15 改写上题程序,不过这次读入的是字符串。

int main(){
    string i;
    vector<string> v;
    while(cin >> i){
        v.push_back(i);
    }
}

3.16 编写一段程序,把练习3.13中vector对象的容量和具体内容输出出来

int main(){
//    vector<int> v1;
//    vector<int> v2(10);
//    vector<int> v3(10, 42);
//    vector<int> v4{ 10 };
//    vector<int> v5{ 10, 42 };
//    vector<string> v6{ 10 };
    vector<string> v7{ 10, "hi" };
    cout << "size: " << v7.size() << endl;
//    cout << v2.size() << endl;
    cout << "value: ";
//    for(decltype(v7.size()) idx = 0; idx != v7.size(); ++idx){
//        cout << v7[idx] << " ";
//    }
    for(auto i : v7){
        cout << i << " ";
    }
    cout << endl;
}

结果:
v1
v2
v3
v4
v5
v6
v7

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

int main(){
    string word;
    vector<string> text;
    while(cin >> word){
        text.push_back(word);
    }
    for(auto &c : text){
        for(auto &i : c){
            i = toupper(i);
        }
    }
//    for(decltype(text.size()) idx = 0; idx != text.size(); ++idx){
//        text[idx] = toupper(text[idx]);
//    }
    for(auto c : text){
        cout << c << endl;
    }
}

3.18 下面的程序合法吗?如果不合法,你准备如何修改?

vector<int> ivec;
ivec[0] = 42;

3.19 如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?

vector<int> v1(10, 42);
vector<int> v2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
vector<int> v3;
for (int i = 0; i < 10; ++i)
	v3.push_back(42);

显然,第一种好

3.20 读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输入第二个和倒数第二个元素的和,以此类推。

int main()
{
    int i;
    vector<int> i_vec;
    while (cin >> i)
    {
        i_vec.push_back(i);
    }
    
    for (int i = 0; i < i_vec.size() - 1; ++i)
    {
        cout << i_vec[i] << " + " << i_vec[i + 1] << i_vec[i]+i_vec[i + 1] << endl;
    }
    
    //---------------------------------
    cout << "---------------------------------" << endl;
    
    int m = 0;
    auto n = i_vec.size() - 1;
    while (m < n)
    {
        cout << i_vec[m] + i_vec[n] << endl;
        ++m;
        --n;
    }
    return 0;
}

自己也写了,但是这个答案是参照的,对于第二问,我总是忘记可以设置两个类似于指针作用的变量,要记住!!!

3.21 请使用迭代器重做3.3.3节的第一个练习。

int main(){
//    vector<int> v1;
//    vector<int> v2(10);
//    vector<int> v3(10, 42);
//    vector<int> v4{ 10 };
//    vector<int> v5{ 10, 42 };
//    vector<string> v6{ 10 };
    vector<string> v7{ 10, "hi" };
//    int
    for(auto it = v7.cbegin(); it != v7.cend(); ++it){
        cout << *it << " ";
    }
    //string
    for(auto it = v7.cbegin(); it != v7.cend() && !it->empty(); ++it){
        cout << *it << " ";
    }
    return 0;
}

3.22 修改之前那个输出text第一段的程序,首先把text的第一段全部改成大写形式,然后输出它。

int main(){
    vector<string> text = {10, "hi"};
    auto it1 = text.cbegin();
    cout << typeid(it1).name() << endl;
    cout << typeid(*it1).name();
    for(auto it = text.begin(); it != text.end() && !it->empty(); ++it){
        for(auto &c : *it){
            if(isalpha(c))c = toupper(c);
        }
    }
    for(auto it = text.begin(); it != text.end() && !it->empty(); ++it){
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

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

int main(){
    vector<int> v1(10, 2);
    
    for(auto it = v1.begin(); it != v1.end(); ++it){
        *it = *it * 2;
    }
    for(auto it = v1.begin(); it != v1.end(); ++it){
        cout << *it << " ";
    }
    cout << endl;
    
    for(auto &c : v1){
        c = c * 2;
        cout << c << " ";
    }
    cout << endl;
    
    return 0;
}

3.24 请使用迭代器重做3.3.3节的最后一个练习。

int main(){
    int i = 0;
    vector<int> i_vec;
    cout << "请输入:" << endl;
    while(cin >> i){
        i_vec.push_back(i);
    }
    auto beg = i_vec.begin(), end = i_vec.end()-1;//end指的是尾端的下一个元素
//    while(beg != end){
//        cout << *beg + *(beg+1) << " ";
//        ++beg;
//    }
//    cout << endl;
    while(beg < end){
        cout << *beg + *end << " ";
        ++beg;
        --end;
    }
    
    return 0;
}

3.25 3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。

int main(){
    vector<unsigned> scores(11,0);
    unsigned grade;
    auto beg = scores.begin();
    while(cin >> grade){
        if(grade <= 100){
            ++(*(beg+grade/10));
        }
    }
}

3.26 在100页的二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?

因为vector可能存很多东西,beg + end可能超过了边界,会报错。

3.27 假设txt_size 是一个无参函数,它的返回值是int。请回答下列哪个定义是非法的,为什么?

unsigned buf_size = 1024;
(a) int ia[buf_size];
(b) int ia[4 * 7 - 14];
(c) int ia[txt_size()];
(d) char st[11] = "fundamental";
  • (a) 非法。维度必须是一个常量表达式。
  • (b) 合法。
  • © 非法。txt_size() 的返回值必须要到运行时才能得到。
  • (d) 非法。数组的大小应该是12。

3.28 下列数组中元素的值是什么?

string sa[10];//空字符串
int ia[10];//0
int main() {
	string sa2[10];//空字符串
	int ia2[10];//未定义
}

3.29 相比于vector 来说,数组有哪些缺点,请例举一些。

定长,增加元素不灵活,不能够拷贝和赋值。

3.30 指出下面代码中的索引错误。

constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
	ia[ix] = ix;

3.31 编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。

int main()
{
	int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

	return 0;
}

3.32 将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序,实现类似的功能。

int main(){
    int arr[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    int arr2[10];
    
    for(size_t idx=0; idx != 10; ++idx){
        arr2[idx] = arr[idx];
    }
    
    for(auto idx : arr2){
        cout << idx << " ";
    }
    cout << endl; 
    vector<int> v1(10, 2);
    vector<int> v2;
    
    v2 = v1;
    for(auto c : v2){
        cout << c << " ";
    }
    cout << endl;
    
    return 0;
}

3.33 对于104页的程序来说,如果不初始化scores将会发生什么?

数组的值将会显示未定义。

3.34 假定p1 和 p2 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?

p1 += p2 - p1; 

将p1指针移动到p2的位置,任何时候都合法

3.35 编写一段程序,利用指针将数组中的元素置为0。

int main(){
    
    int a[5] = {1,2,3,4,5};
    
    for(int * p = a; p != end(a); ++p){
        *p = 0;
    }
    for(int i = 0; i < 5; ++i){
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

3.36 编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。

待更新

3.37 下面的程序是何含义,程序的输出结果是什么?

const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp) {
    cout << *cp << endl;
    ++cp;
}

打印字符数组ca中的元素,但是因为该数组没有放置空字符串,循环要遇到空字符串才停。

3.38 在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义?

指针存储的是对象的地址,两个指针相减可以表示距离(同一数组中),指针加上整数表示向前或者向后移动整数个位置,相加,如果是两个无关地址,地址相加???没有逻辑上的意义。

3.39 编写一段程序,比较两个string对象。再编写一段程序,比较两个C风格字符串的内容。

int main(){
    string s1 = "Hello!";
    string s2 = "hello!";
    
    if(s1 == s2){
        cout << "The two strings are equal" << endl;
    }else if(s1 > s2){
        cout << "s1" << endl;
    }else{
        cout << "s2" << endl;
    }
    
    const char ca[] = {"Hello"};
    const char ca1[] = {"hello"};
    
    if(strcmp(ca, ca1) == 0){
        cout << "The two strings are equal" << endl;
    }else if(strcmp(ca, ca1) > 0){
        cout << "ca" << endl;
    }else{
        cout << "ca1" << endl;
    }
    
}

3.40 编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用strcpy和strcat把前两个数组的内容拷贝到第三个数组当中。

const char ca[] = {"Hello"};
const char ca1[] = {"hello"};
int main(){
    char total_ca[12]={};
    strcpy(total_ca, ca);//不能写成total_ca = strcpy(total_ca, ca);因为数组名是一个不能被更改的对象。
    strcat(total_ca, " ");
    strcat(total_ca, ca1);
    cout << total_ca << endl;

	return 0;
}

3.41 编写一段程序,用整型数组初始化一个vector对象。

int main(){
    int arr[5] = {1,2,3,4,5};
    vector<int> i_vec(begin(arr), end(arr));
    
    for(auto c : i_vec){
        cout << c << " ";
    }
    
    return 0;
}

3.42 编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组.

int main(){
    vector<int> i_vec;
    for(int i = 0; i < 5; ++i){
//        i_vec[i]  = i; 错误写法
        i_vec.push_back(i);
    }
    for(auto c : i_vec){
        cout << c << " ";
    }
    cout << endl;
    cout << "==========" << endl;
    int arr[5];
    for(int i = 0; i != i_vec.size(); ++i){
        arr[i] = i_vec[i];
    }
    for(auto c : arr){
        cout << c << " ";
    }
    return 0;
}

3.43 编写3个不同版本的程序,令其均能输出ia的元素。版本1使用范围for语句管理迭代过程;版本2和版本3都使用普通for语句,其中版本2要求使用下标运算符,版本3要求使用指针。此外,在所有3个版本的程序中都要直接写出数据类型,而不能使用类型别名、auto关键字和decltype关键字。

int main(){
    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
    //版本1
    cout << "版本1" << endl;
//    for(int *i : ia){
//        cout << typeid( i).name() << endl;
//        for(int *j : begin(*i)){
//            cout << *j << " ";
//        }
//        cout << endl;
//    }
    for(const int (&i)[4] : ia){
        for(int j : i){
            cout << j << " ";
        }
        cout << endl;
    }
    cout << "版本2" << endl;
//    版本2
    for(size_t i = 0; i != 3; ++i){
        for(size_t j = 0; j != 4; ++j){
            cout << ia[i][j] << " ";
        }
        cout << endl;
    }
    cout << "版本3" << endl;
//    版本3
    for(int (*p)[4] = begin(ia); p != end(ia); ++p){
        for(int *q = begin(*p); q != end(*p); ++q){
            cout << *q <<" ";
        }
        cout << endl;
    }
    
    return 0;
}

3.44 改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。

//使用类型别名
int main(){
    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
    //版本1
    cout << "版本1" << endl;
    //    for(int *i : ia){
    //        cout << typeid( i).name() << endl;
    //        for(int *j : begin(*i)){
    //            cout << *j << " ";
    //        }
    //        cout << endl;
    //    }
    using int_array = int [4];
    for(const int_array &i : ia){
        for(int j : i){
            cout << j << " ";
        }
        cout << endl;
    }
    cout << "版本2" << endl;
    //    版本2
    for(size_t i = 0; i != 3; ++i){
        for(size_t j = 0; j != 4; ++j){
            cout << ia[i][j] << " ";
        }
        cout << endl;
    }
    cout << "版本3" << endl;
    //    版本3
    for(int_array *p = begin(ia); p != end(ia); ++p){
        for(int *q = begin(*p); q != end(*p); ++q){
            cout << *q <<" ";
        }
        cout << endl;
    }
    
    return 0;
}

3.45 用auto关键字

//3.45 用auto关键字
int main(){
    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
    //版本1
    cout << "版本1" << endl;
    //    for(int *i : ia){
    //        cout << typeid( i).name() << endl;
    //        for(int *j : begin(*i)){
    //            cout << *j << " ";
    //        }
    //        cout << endl;
    //    }
//    using int_array = int [4];
    for(auto & i : ia){
        for(auto j : i){
            cout << j << " ";
        }
        cout << endl;
    }
    cout << "版本2" << endl;
    //    版本2
    for(auto i = 0; i != 3; ++i){
        for(auto j = 0; j != 4; ++j){
            cout << ia[i][j] << " ";
        }
        cout << endl;
    }
    cout << "版本3" << endl;
    //    版本3
    for(auto p = begin(ia); p != end(ia); ++p){
        for(auto q = begin(*p); q != end(*p); ++q){
            cout << *q <<" ";
        }
        cout << endl;
    }
    
    return 0;
}
发布了8 篇原创文章 · 获赞 1 · 访问量 458

猜你喜欢

转载自blog.csdn.net/Echo_Hsu/article/details/105322142