c++ primer 第三章练习题答案

3.1

加入using namespace std、或者使用using std::cin, using std::cout, using std::cerr

3.2

int main()
{
    //getline接受两个参数:输入流和string对象,每次读入一整行
    string s;
    while (getline(cin, s)) 
    {
        cout << s << endl;
    }

    //使用cin读取遇到空格停止
    string s1;
    while (cin >> s1) 
    {
        cout << s1 << endl;
    }
}

3.3

在执行读取操作时string类的输入运算符会自动忽略开头的空白后开始读取,并在遇到下一个空白字符时停止,
getline函数从给定的输入流中读取字符直到遇到换行符\n为止(换行符也读取进来),然后把所读的内容存入到string对象中去(存的过程不包含换行符)。因此,string对象遇到换行符停止,且得到的string对象不包含换行符,在换行符出现前的空白字符均正常读取。

3.4

判断字符串大小:
string s, s1;
cin >> s >> s1;
if (s1 >= s)
    cout << s1;
else
    cout << s;
 
判断字符串等长:
string s, s1;
cin >> s >> s1;
if (s1.size() == s.size())
    cout << "the length of two strings is equal.";
else if (s1.size() >= s.size())
    cout << s1;
else
    cout << s;

3.5

连接成大字符串:
string s, s1;
while (cin >> s) {
    s1 += s;
}
cout << s1;
 
用空格分割:
string s, s1;
while (cin >> s) {
    s1 += s + ' ';
}
cout << s1;

3.6

string s;
while (cin >> s) {
    for (auto &c : s) //传引用!保证可以修改字符串中的值,而不是拷贝出来赋值
        c = 'X';
}
cout << s << endl;

3.7

没有变化,字符串的每一位中存放的为字符(char)类型

3.8

while循环:    
string s;
cin >> s;
int len = s.size();
while (((--len) >= 0)) {
    s[len] = 'X';
}
cout << s << endl;
 
for循环:
string s;
cin >> s;
int len = s.size();
for (int i = 0; i != len; ++i)
    s[i] = 'X';
cout << s << endl;
 
for循环可读性好些

3.9

不合法,s为空字符串,使用下标访问空string会引发不可预知的错误。

3.10

string s, s1;
cin >> s;
for (auto c : s) {
    if (!(ispunct(c)))
        s1 += c;
}
cout << s1 <<endl;

3.11 
合法,c的类型为char,因为auto会忽略顶层const。

3.12
(a) 正确,创建一个vector,该vector的元素是int型的vector对象 
(b) 错误,ivec和svec对象类型不同,svec的元素是string对象,ivec的元素是int型的vector对象 
(c) 正确,创建一个vector,svec的元素是string对象,并对其初始化,svec含有10个元素,每个的值都是"null"

3.13

(a) v1是一个空vector,不含任何元素;
(b) v2是一个含有10个元素的vector,每个元素的值被默认初始化为0
(c) v3是一个含有10个元素的vector,每个元素的值为42
(d) v4是一个含有1个元素的vector,该元素值为10
(e) v5是一个含有2个元素的vector,元素值分别为10,42
(f) v6是一个含有10个元素的vector,v6的元素是string对象,值为null
(g) v7是一个含有10个元素的vector,v6的元素是string对象,每个元素的值为"hi"
 
tips:v7的花括号中提供的元素值不能作为元素的初始值,在确认无法执行列表初始化后,编译器会尝试用默认值初始化vector对象。
(g) vector<string> v7{10,"hi"}; -> 无法列表初始化,等价于 <=> vector<string> v7(10,"hi");

3.14

int n;
vector<int> ivec;
while (cin >> n) {
    ivec.push_back(n);
}

3.15

string s;3.
vector<string> svec;
while (cin >> s) {
    svec.push_back(s);
}

3.16

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 << "v1" << endl;
for (auto c : v1)
    cout << c << endl;
 
cout << "v2" << endl;
for (auto c : v2)
    cout << c << endl;
 
cout << "v3" << endl;
for (auto c : v3)
    cout << c << endl;
 
cout << "v4" << endl;
for (auto c : v4)
    cout << c << endl;
 
cout << "v5" << endl;
for (auto c : v5)
    cout << c << endl;
 
cout << "v6" << endl;
for (auto c : v6)
    cout << c << endl;
 
cout << "v7" << endl;
for (auto c : v7)
    cout << c << endl;

3.17

string s;
vector<string> svec;
while (cin >> s) {
    for (auto &c : s) { //注意传引用
        c = toupper(c); //将改为大写的char赋值给原char
    }
    svec.push_back(s);
}
for (int i = 0; i != svec.size(); ++i)
    cout << svec[i] << endl;

3.18

不合法,因为ivec为空vector,vector的下标只能用于访问已存在的元素,且不能使用下标形式添加元素,只能使用push_back添加
 改为:
vector<int> ivec;
ivec.push_back(42);

3.19

vector<int> ivec(10,42);
 
vector<int> ivec{42,42,42,42,42,42,42,42,42,42};
 
vector<int> ivec;
for(int i = 0; i < 10; ++i)
    ivec.push_back(42);
 
使用圆括号形式初始化固定大小且元素值相同的vector最方便。

3.20

//输出相邻整数
int n;
vector<int> ivec;
while (cin >> n) {
    ivec.push_back(n);
}
for (int i = 1; i != ivec.size(); ++i)
    cout << ivec[i - 1] + ivec[i] << " ";
 
//输出首尾元素和
int n;
vector<int> ivec;
while (cin >> n) {
    ivec.push_back(n);
}
int len = ivec.size();
for (int i = 0; i != (len / 2) + 1; ++i)
    cout << ivec[i] + ivec[len - i - 1] << " ";//下标千万不要越界
 

3.21

// 使用!=进行for循环的判断,在标准库提供的所有容器均有效,
// 养成使用迭代器和!=的习惯,就不用太在意用的到底是哪种容器类型
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 << "v1" << endl;
for (auto it = v1.begin(); it != v1.end(); ++it)
    cout << *it << endl;
 
cout << "v2" << endl;
for (auto it = v2.begin(); it != v2.end(); ++it)
    cout << *it << endl;
 
cout << "v3" << endl;
for (auto it = v3.begin(); it != v3.end(); ++it)
    cout << *it << endl;
 
cout << "v4" << endl;
for (auto it = v4.begin(); it != v4.end(); ++it)
    cout << *it << endl;
 
cout << "v5" << endl;
for (auto it = v5.begin(); it != v5.end(); ++it)
    cout << *it << endl;
 
cout << "v6" << endl;
for (auto it = v6.begin(); it != v6.end(); ++it)
    cout << *it << endl;
 
cout << "v7" << endl;
for (auto it = v7.begin(); it != v7.end(); ++it)
    cout << *it << endl;

3.22

vector<string> text;
string str;
while (cin >> str) {
    text.push_back(str);
}
for (auto it = text.begin(); it != text.end() && !it->empty(); ++it)    {
    for (auto &c : *it)
        c = toupper(c);
    cout << *it << endl;
}

3.23

vector<int> ivec;
int n;
int num = 10;
while (cin >> n && num) 
{
    ivec.push_back(n);
    num--;
}

for (auto it = ivec.begin(); it != ivec.end(); ++it) {
    *it *= 2;
    cout << *it << " ";
}

3.24

// 输出相邻整数和
vector<int> ivec;
int n;
while(cin>>n)
    ivec.push_back(n);
for (auto it = ivec.begin() + 1; it != ivec.end(); ++it) {
    cout << *it + *(it-1) << " ";
}
 
// 输出首尾相加和
// 学会尾部迭代器的使用
vector<int> ivec;
int n;
while(cin>>n)
    ivec.push_back(n);
auto  beg = ivec.begin();
auto  end = ivec.end() - 1;
for (; beg <= end; ++beg, --end) {
    cout << *beg + *end << " ";
}

3.25

vector<int> ivec(11);
int n;
while (cin >> n) {
    n /= 10;
    ++ivec[n];
}
for (auto it = ivec.begin(); it != ivec.end(); ++it ) 
    cout << *it << " ";

3.26

迭代器不支持两个迭代器相加的运算,但支持迭代器加上一个整数的运算
(end - beg) / 2 两个迭代器相减返回difference_type,是带符号整型数,可以与迭代器相加。

3.27
(a) 非法,buf_size为非常量表达式
(b) 合法
(c) 若text_size()为常量表达式(constexpr)时,在编译时确定具体指并替换,则正确;否则错误
(d) 非法,溢出,字符数组利用字符串字面值进行初始化时'\0'会包含

3.28
sa和ia位于定义于任何函数体之外,sa为空字符串;ia数组内每个值均初始化为0。
sa2和ia2在函数体内部,srting类规定没有指定初值则声称一个空串;ia2不被初始化,其中的值未定义。
 
综上,sa和sa2初始化为空串;ia数组内每个值均为0,ia2中值未定义。

3.29

数组没有vector灵活,数组的大小确定不变,不能随意向数组内增加元素。

3.30
int ia[10]中存放ia[0]~ia[9]的值,for循环中访问了ia[10],导致下标越界。

3.31

int a[10];
for(int i = 0; i < 10; ++i)
    a[i] = i;

3.32

//数组不允许直接拷贝
int b[10];
for(int i = 0; i < 10; ++i)
    b[i] = a[i];
 
vector<int> vi;
for (int i = 0; i < 10; ++i)
    vi.push_back(a[i])

3.33

不初始化scores的话,其内部的值是未定义的,无法实现利用下标统计人数段的功能。

3.34

两个指针相减的结果是它们之间的距离,p2 - p1为类型为ptrdiff_t,值为0的数。p1加上这个数指针不变。
上面程序的功能是p1经过运算后指向p2所指向的元素

3.35

int a[10];
for (int i = 0; i < 10; ++i)
    a[i] = i;
int *beg = &a[0];
int *end = &a[10];
for (auto it = beg; it != end; ++it) {
    *it = 0;
    cout << *it << " ";
}

3.36

//判断数组是否相等
int arr1[]{ 0,1,2,3,4 };
int arr2[]{ 0,1,2,3,6 };
auto *beg1 = begin(arr1);
auto *last1 = end(arr1);
auto *beg2 = begin(arr2);
auto *last2 = end(arr2);
auto n1 = *last1 - *beg1;
auto n2 = *last2 - *beg2;
decltype(n1) acount = 0;
if (n1 == n2) {
    for (; beg1 != last1, beg2 != last2; ++beg1, ++beg2); {
        if (beg1 != beg2) {
            cout << "The two array have same size, but they are not equal." << endl;
        }
        if (beg1 == beg2) {
            ++acount;
        }
    }
    if (acount == n1)
        cout << "The two array are equal." << endl;
}
else
    cout << "The two array are not equal." << endl;
 
//判断vector是否相等
vector<int> v1{ 0,1,2,3,4 };
vector<int> v2{ 0,1,2,4,3 };
int vcount = 0;
if (v1.size() == v2.size()) {
    for (auto i = 0; i != v1.size(); ++i) {
        if (v1[i] != v2[i]) {
            cout << "The two vector have same size, but they are not equal." << endl; break;
        }
        else
            ++vcount;
    }
    if (vcount == v1.size())
        cout << "The two vector are equal." << endl;
}
else
    cout << "The two vector are not equal." << endl;

3.37

const char ca[] = {'h', 'e', 'l', 'l', 'o'};
const char *cp = ca;
while(*cp){
    cout << *cp <<endl;
    ++cp;
}
 
程序输出会打印一些非法字符,ca为一个c风格的字符串,必须以'\0'结束,
正确写法为const char ca[] = {'h', 'e', 'l', 'l', 'o', '\0'};
这样会依次输出字符串每一位(除\0结束符),即输出 h e l l o

3.38

指针表示地址值,两个地址相加没有实际意义

3.39

//比较两个string对象
string s1 = "abcde";
string s2 = "abded";
if (s1 > s2)
    cout << "s1 is bigger than s2." << endl;
else if (s1 < s2)
    cout << "s1 is smaller than s2." << endl;
else
    cout << "s1 and s2 are equal." << endl;
 
//比较两个C风格字符串
const char ca1[] = "abcde";
const char ca2[] = "abced";
if (strcmp(ca1, ca2) > 0)
    cout << "ca1 is bigger than ca2." << endl;
else if (strcmp(ca1, ca2) < 0)
    cout << "ca1 is smaller than ca2." << endl;
else
    cout << "ca1 and ca2 are equal." << endl;

3.40

//注意要给出被操作数组的具体大小
char ca1[100] = "abcde";
const char ca2[] = "feagr";
char ca3[100] = "";
strcat_s(ca1, ca2);
strcpy_s(ca3, ca1);
cout << ca3 << endl;

3.41

int arr[]{1, 2, 3, 4, 5};
vector<int> vi(begin(arr), end(arr));

3.42

//使用begin和end函数得到数组首指针和尾后指针
vector<int> vi{ 1,2,3,4,5 };
int arr[5];
int *beg = begin(arr);
int *last = end(arr);
for (auto i : vi) {
    *beg = i;
    ++beg;
}

3.43

int ia[3][4]{ {0,1,2,3},
          {4,5,6,7},
          {8,9,10,11} };
//version 1
for (int (&row)[4] : ia) {
    for (int col : row) {
        cout << col << " ";
    }
    cout << endl;
}
 
//version 2
for (int i = 0; i != 3; ++i) {
    for (int j = 0; j != 4; ++j) {
        cout << ia[i][j] << " ";
    }
    cout << endl;
}
    
//version 3
for (int (*p)[4] = ia; p != ia + 3; ++p) {
    for (int *q = *p; q != *p + 4; ++q) {
        cout << *q << " ";
    }
    cout << endl;
}

3.44

int ia[3][4]{ {0,1,2,3},
          {4,5,6,7},
          {8,9,10,11} };
//version 1
using elem1_1 = int[4];
using elem1_2 = int;
for (elem1_1 &row : ia) {
    for (elem1_2 col : row) {
        cout << col << " ";
    }
    cout << endl;
}
 
//version 2
using elem2 = int;
for (elem2 i = 0; i != 3; ++i) {
    for (elem2 j = 0; j != 4; ++j) {
        cout << ia[i][j] << " ";
    }
    cout << endl;
}
    
//version 3
using elem3_1 = int(*)[4];
using elem3_2 = int*;
for (elem3_1 p = ia; p != ia + 3; ++p) {
    for (elem3_2 q = *p; q != *p + 4; ++q) {
        cout << *q << " ";
    }
    cout << endl;
}

3.45

int ia[3][4]{ {0,1,2,3},
          {4,5,6,7},
          {8,9,10,11} };
//version 1  最外层循环必须是引用,因为不加引用 auto会推断成int*指针


for (auto &row : ia) {
    for (auto col : row) {
        cout << col << " ";
    }
    cout << endl;
}
 
//version 2
for (auto i = 0; i != 3; ++i) {
    for (auto j = 0; j != 4; ++j) {
        cout << ia[i][j] << " ";
    }
    cout << endl;
}
    
//version 3
for (auto p = ia; p != ia + 3; ++p) {
    for (auto q = *p; q != *p + 4; ++q) {
        cout << *q << " ";
    }
    cout << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值