《C++ Primer》第五版习题个人答案
练习3.1
使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。
1.4.1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> using std::cin; using std::cout; using std::endl; int main () { int a=0 ,b=0 ; cout<<"please input two numbers:" <<endl; cin>>a>>b; int min = std::min (a,b); int max = std::max (a,b); while (max>=min) { cout<<max<<endl; max--; } return 0 ; }
2.6.2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> #include <string> using std::cin;using std::cout;using std::cerr;using std::endl;struct Sales_data { std::string bookNo; unsigned units_sold = 0 ; double revenue = 0.0 ; double price = 0.0 ; }; int main () { Sales_data data1,data2; double price=0 ; cin>>data1.bookNo>>data1.units_sold>>price; data1.revenue=data1.units_sold*price; cin>>data2.bookNo>>data2.units_sold>>price; data2.revenue=data2.units_sold*price; if (data1.bookNo==data2.bookNo) { unsigned totalCnt=data1.units_sold+data2.units_sold; double totalRevenue=data1.revenue+data2.revenue; cout<<data1.bookNo<<" " <<totalCnt<<" " <<totalRevenue<<" " ; return 0 ; } else { cerr<<"Data must refer to the same ISBN" <<endl; return -1 ; } return 0 ; }
练习3.2
编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词。
一次读入一行 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> #include <string> using std::cout;using std::cin;using std::endl;using std::string;int main () { string line; while (getline (cin,line)) { cout<<line<<endl; } return 0 ; }
一次读入一个词 1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> #include <string> using std::cout;using std::cin;using std::endl;using std::string;int main () { string line; while (cin>>line) { cout<<line<<endl; } return 0 ; }
练习3.3
请说明string类的输入运算符和getline函数分别是如何处理空白字符的。
>>
运算符在读取std::string
时会跳过前导空白字符,并在遇到下一个空白字符时停止读取。std::getline
函数会读取整行数据,包括空格,直到遇到换行符为止。
练习3.4
编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出比较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。
输出比较大的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;int main () { string str1,str2; while (cin>>str1>>str2) { if (str1 == str2) { cout<< "两字符串相等" <<endl; } if (str1 > str2) { cout<<str1<<endl; } if (str2 > str1) { cout<<str2<<endl; } } return 0 ; }
输出长度大的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;int main () { string str1,str2; while (cin>>str1>>str2) { if (str1.size () == str2.size ()) { cout<< "两字符串等长" <<endl; } if (str1.size () > str2.size ()) { cout<<str1<<endl; } if (str2.size () > str1.size ()) { cout<<str2<<endl; } } return 0 ; }
练习3.5
编写一段程序从标准输入中读入多个字符串并将他们连接起来,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分割开来。
未隔开的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using std::cout;using std::cin;using std::endl;using std::string;int main () { string input,result; while (cin>>input) { result+=input; } cout<<result<<endl; return 0 ; }
隔开的 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using std::cout;using std::cin;using std::endl;using std::string;int main () { string input,result; while (cin>>input) { result += input +" " ; } cout<<result<<endl; return 0 ; }
练习3.6
编写一段程序,使用范围for语句将字符串内所有字符用X代替。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;main (){ string s ("EastWinters" ) ; for (auto &c : s) { c = 'X' ; } cout<<s<<endl; return 0 ; }
练习3.7
就上一题完成的程序而言,如果将循环控制的变量设置为char将发生什么?先估计一下结果,然后实际编程进行验证。
在使用 char
的情况下,循环变量 c
被显式声明为 char
类型,因此在循环体内可以直接修改字符的值。修改为char
不会对程序有影响。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;main (){ string s ("EastWinters" ) ; for (char &c : s) { c = 'X' ; } cout<<s<<endl; return 0 ; }
练习3.8
分别用while循环和传统for循环重写第一题的程序,你觉得哪种形式更好呢?为什么?
3.8.1(使用下标执行迭代) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;main (){ string s ("EastWinters" ) ; decltype (s.size ()) index = 0 ; while (index != s.size () && !isspace (s[index])) { s[index] = 'X' ; ++index; } cout<<s<<endl; return 0 ; }
3.8.2(使用下标执行迭代) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <string> using std::cin;using std::cout;using std::endl;using std::string;main (){ string s ("EastWinters" ) ; for (decltype (s.size ()) index = 0 ;index != s.size () && !isspace (s[index]); ++index) { s[index] = 'X' ; } cout<<s<<endl; return 0 ; }
for
循环相较于while循环
更为简洁。
练习3.9
下面的程序有何作用?它合法吗?如果不合法?为什么?
1 2 string s; cout << s[0 ] << endl;
不合法。如果string s
是一个空字符串且没有进行初始化,那么访问s[0]
将会导致未定义行为。因为在这种情况下,字符串s
是空的,没有任何字符可供访问,所以访问s[0]
将超出字符串的有效索引范围。
练习3.10
编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string> #include <cctype> using std::cin;using std::cout;using std::endl;using std::string;int main () { string s ("East,Winters!" ) ; string str; for (auto a:s ) { if (!ispunct (a)) { str += a; } } cout<<str<<endl; return 0 ; }
练习3.11
下面的范围for语句合法吗?如果合法,c的类型是什么?
1 2 const string s = "Keep out!" ;for (auto &c : s){ }
要根据for循环中的代码来看是否合法,c是string 对象中字符的引用,s是常量。因此如果for循环中的代码重新给c赋值就会非法,如果不改变c的值,那么合法。
练习3.12
下列vector对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。
1 2 3 vector<vector<int >> ivec; vector<string> svec = ivec; vector<string> svec (10 , "null" ) ;
练习3.13
下列的vector对象各包含多少个元素?这些元素的值分别是多少?
1 2 3 4 5 6 7 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" };
练习3.14
编写一段程序,用cin读入一组整数并把它们存入一个vector对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #include <iostream> #include <vector> using std::cin;using std::vector;int main () { vector<int > numbers; int num; while (cin >> num) { numbers.push_back (num); } return 0 ; }
练习3.15
改写上题程序,不过这次读入的是字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <string> #include <vector> using std::cin;using std::string;using std::vector;int main () { string word; vector<string> text; while (cin>>word) { text.push_back (word); } return 0 ; }
练习3.16
编写一段程序,把练习3.13中vector对象的容量和具体内容输出出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string; 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<<"v1容量为:" <<v1.size ()<<endl; cout<<"v2容量为:" <<v2.size ()<<endl; cout<<"v3容量为:" <<v3.size ()<<endl; cout<<"v4容量为:" <<v4.size ()<<endl; cout<<"v5容量为:" <<v5.size ()<<endl; cout<<"v6容量为:" <<v6.size ()<<endl; cout<<"v7容量为:" <<v7.size ()<<endl; cout<<"v1的内容为:" ; for (auto a : v1) { cout << a << " " ; } cout<<endl; cout<<"v2的内容为:" ; for (auto a : v2) { cout << a << " " ; } cout<<endl; cout<<"v3的内容为:" ; for (auto a : v3) { cout << a << " " ; } cout<<endl; cout<<"v4的内容为:" ; for (auto a : v4) { cout << a << " " ; } cout<<endl; cout<<"v5的内容为:" ; for (auto a : v5) { cout << a << " " ; } cout<<endl; cout<<"v6的内容为:" ; for (auto a : v6) { cout << a << " " ; } cout<<endl; cout<<"v7的内容为:" ; for (auto a : v7) { cout << a << " " ; } cout<<endl; return 0 ; }
练习3.17
从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改为大写形式。输出改变后的结果,每个词占一行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string; int main () { string word; vector<string> words; while (cin>>word) { words.push_back (word); } for (auto & w1 : words) { for (auto & w2 : w1) { w2=toupper (w2); } } for (const auto w:words) { cout<<w<<endl; } return 0 ; }
练习3.18
下面的程序合法吗?如果不合法,你准备如何修改?
1 2 vector<int > ivec; ivec[0 ] = 42 ;
不合法。应改为:
ivec
还是一个空的vector
,没有任何元素。使用下标访问时,必须确保该位置已经存在元素,否则会导致未定义行为。 在使用下标访问 vector
的元素之前,必须确保 vector
中已经包含足够的元素。可以通过 resize
或 push_back
方法来添加元素。这样可以避免未定义行为,并确保程序的合法性和正确性。
练习3.19
如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?
如下三种:
1 2 3 4 5 std::vector<int > ivec (10 , 42 ) ; ivec.assign (10 , 42 ); vector<int > ivec3; for (int i = 0 ; i < 10 ; ++i) ivec3.push_back (42 );
第一种方式最好,代码简洁明了,而且执行效率高,因为它一次性分配所需的内存,并且不需要额外的操作。
练习3.20
读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输入第二个和倒数第二个元素的和,以此类推。
输出相邻整数的和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string;int main () { vector<int > numbers; int num; cout<<"请输入一组整数:" <<endl; while (cin>>num) { numbers.push_back (num); } cout<<"相邻整数的和分别为:" <<endl; for (size_t i = 0 ; i < numbers.size ()-1 ; ++i) { cout<<numbers[i]+numbers[i+1 ]<<endl; } return 0 ; }
输出首尾整数相加的和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string;int main () { vector<int > numbers; int num; cout<<"请输入一组整数:" <<endl; while (cin>>num) { numbers.push_back (num); } cout<<"首尾对应元素的和分别为:" <<endl; for (size_t i = 0 ; i < numbers.size ()/2 ; ++i) { cout<<numbers[i]+numbers[numbers.size ()-1 -i]<<endl; } if (numbers.size ()%2 !=0 ) { cout<<numbers[numbers.size ()/2 ]<<endl; } return 0 ; }
练习3.21
请使用迭代器重做3.3.3节的第一个练习。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string; 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<<"v1容量为:" <<v1.size ()<<endl; cout<<"v2容量为:" <<v2.size ()<<endl; cout<<"v3容量为:" <<v3.size ()<<endl; cout<<"v4容量为:" <<v4.size ()<<endl; cout<<"v5容量为:" <<v5.size ()<<endl; cout<<"v6容量为:" <<v6.size ()<<endl; cout<<"v7容量为:" <<v7.size ()<<endl; cout<<"v1的内容为:" ; for (auto it = v1.begin ();it != v1.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v2的内容为:" ; for (auto it = v2.begin ();it != v2.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v3的内容为:" ; for (auto it = v3.begin ();it != v3.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v4的内容为:" ; for (auto it = v4.begin ();it != v4.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v5的内容为:" ; for (auto it = v5.begin ();it != v5.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v6的内容为:" ; for (auto it = v6.begin ();it != v6.end ();++it) { cout << *it << " " ; } cout<<endl; cout<<"v7的内容为:" ; for (auto it = v7.begin ();it != v7.end ();++it) { cout << *it << " " ; } cout<<endl; return 0 ; }
练习3.22
修改之前那个输出text第一段的程序,首先把text的第一段全部改成大写形式,然后输出它。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <iostream> #include <string> #include <cctype> #include <vector> using std::cout;using std::endl;using std::cin;using std::vector;using std::string; int main () { string word; vector<string> words; while (cin>>word) { words.push_back (word); } for (auto it = words.begin ();it != words.end ();++it) { if (!it->empty ()) { for (auto char_it = it->begin (); char_it != it-> end ();++char_it) { *char_it = toupper (*char_it); } } } for (auto it = words.begin ();it != words.end ();++it) { cout<<*it<<endl; } return 0 ; }
练习3.23
编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都变成原来的两倍。输出vector对象的内容,检验程序是否正确。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <vector> using std::cout;using std::endl;using std::vector;int main () { vector<int > numbers = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; for (auto num = numbers.begin ();num !=numbers.end ();++num) { *num *=2 ; } for (auto num = numbers.begin ();num !=numbers.end ();++num) { cout<<*num<<" " ; } cout<<endl; return 0 ; }
练习3.24
请使用迭代器重做3.3.3节的最后一个练习。
输出相邻整数的和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include <iostream> #include <string> #include <vector> using std::cout;using std::endl;using std::cin;using std::string;using std::vector;int main () { vector<int > numbers; int num; while (cin >> num) { numbers.push_back (num); } for (auto it = numbers.begin ();it !=numbers.end ()-1 ;++it) { cout<<(*it+*(it+1 ))<<" " ; } return 0 ; }
输出首尾整数相加的和 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <string> #include <vector> using std::cout;using std::endl;using std::cin;using std::string;using std::vector;int main () { vector<int > numbers; int num; while (cin >> num) { numbers.push_back (num); } auto front_it = numbers.begin (); auto back_it = numbers.end ()-1 ; while (front_it <= back_it) { cout<<(*front_it+*back_it)<<" " ; ++front_it; --back_it; } return 0 ; }
练习3.25
3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <iostream> #include <vector> using std::vector;using std::cin;using std::cout;using std::endl;int main () { vector<unsigned >scores (11 ,0 ); unsigned grade; while (cin >> grade) { if (grade <= 100 ) { ++*(scores.begin ()+grade/10 ); } } for (auto a : scores) { cout << a <<" " ; } cout << endl; return 0 ; }
练习3.26
在100页的二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ? 迭代器是一种抽象的指针,用于遍历容器中的元素。即使对于随机访问迭代器,begin
和end
是迭代器对象,而非数值类型,不能直接相加。begin + end
这种操作在语法和语义上都不成立。
练习3.27
假设txt_size 是一个无参函数,它的返回值是int。请回答下列哪个定义是非法的,为什么?
1 2 3 4 5 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) 不合法,因为buf_size
不是常量表达式。
(b) 合法,4 * 7 - 14
计算结果是14
,这是一个常量表达式。
(c) 不合法,因为txt_size()
返回的值在编译时未知,不是常量表达式。
(d) 非法。数组的大小应该是12。
练习3.28
下列数组中元素的值是什么?
1 2 3 4 5 6 string sa[10 ]; int ia[10 ];int main () { string sa2[10 ]; int ia2[10 ]; }
1 2 3 4 5 6 string sa[10 ]; int ia[10 ]; int main () { string sa2[10 ]; int ia2[10 ]; }
练习3.29
相比于vector 来说,数组有哪些缺点,请例举一些。
大小在定义时必须确定且不可改变。数组的大小一旦声明,就不能动态调整。这会导致内存浪费或空间不足的问题。
没有内置的边界检查,访问数组时越界会导致未定义行为,可能引发严重的错误和安全漏洞。
需要手动管理内存,使用动态数组时必须显式地分配和释放内存,这容易引起内存泄漏和其他管理问题。
无法直接获取数组的大小,必须通过其他变量记录或者显式计算。
不保证自动初始化,未初始化的数组元素会包含未定义的值。
练习3.30
指出下面代码中的索引错误。
1 2 3 4 constexpr size_t array_size = 10 ;int ia[array_size];for (size_t ix = 1 ; ix <= array_size; ++ix) ia[ix] = ix;
错误出现在 for
循环的条件部分 ix <= array_size
。C++ 数组的索引是从 0
开始的,因此有效的索引范围是 0
到 array_size - 1
。但是,当前循环条件会导致索引 ix
从 1
到 array_size
,即 1
到 10
。当 ix
等于 array_size
(即 10
) 时,ia[ix]
会超出数组的范围(ia[10]
),导致越界访问。
练习3.31
编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> int main () { int ia[]={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; for (size_t i = 0 ; i < 10 ; i++) { ia[i] = i ; } for (size_t i = 0 ; i < 10 ; i++) { std::cout << ia[i] << " " ; } return 0 ; }
练习3.32
将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序,实现类似的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> #include <vector> using std::vector;using std::cout;int main () { int ia[]={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; vector<int > vector1 (10 ) ; for (int i = 0 ; i < 10 ; i++) { vector1[i] = i ; } vector<int > vector2 = vector1; for (int i = 0 ; i < 10 ; i++) { cout << vector2[i] << " " ; } return 0 ; }
练习3.33
对于104页的程序来说,如果不初始化scores将会发生什么? 未初始化的 unsigned
变量在 C++ 中会包含一个未定义的值(未定义行为)。这意味着该变量的内容是不可预测的,并且在不同的运行环境或不同的编译器设置下可能会有不同的结果。
练习3.34
假定p1 和 p2 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?
这段代码的功能是“将 p1
移动 p2 - p1
个位置”,也就是将 p1
移动到 p2
所指向的位置。 非法情况 : 1.未定义行为:如果 p1
和 p2
不指向同一个数组中的元素,或者计算 p2 - p1
导致 p1
指向数组范围之外的位置。 2.跨越数组边界:如果 p1
和 p2
的操作结果超出了数组的边界,程序也会出现未定义行为。
练习3.35
编写一段程序,利用指针将数组中的元素置为0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #include <iostream> using std::cout;using std::endl;int main () { int arr[10 ] = {0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; int *p = arr; for ( int i = 0 ; i < 10 ; ++i) { cout<< arr[i] <<" " ; } cout << endl; for (int i = 0 ; i < 10 ; ++i) { *(p+i) = 0 ; cout<< arr[i] <<" " ; } cout << endl; return 0 ; }
练习3.36
编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。
比较两个数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> using std::cout;using std::endl;bool compareArrays (const int * arr1,const int * arr2,size_t size) { for (size_t i = 0 ; i < size; ++i) { if (arr1[i] != arr2[i]) { return false ; } } return true ; } int main () { constexpr size_t arraySize = 5 ; int arr1[arraySize] = {1 ,2 ,3 ,4 ,5 }; int arr2[arraySize] = {1 ,2 ,3 ,4 ,5 }; if (compareArrays (arr1,arr2,arraySize)) { std::cout << "arr1 and arr2 are equal." << std::endl; } else { std::cout << "arr1 and arr2 are not equal." << std::endl; } return 0 ; }
比较两个vector 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <vector> using std::vector;using std::cout;using std::endl;int main () { vector<int > vec1 = {1 ,2 ,3 ,4 ,5 }; vector<int > vec2 = {1 ,2 ,3 ,4 ,5 }; if (vec1 ==vec2) { std::cout << "vec1 and vec2 are equal." << std::endl; } else { std::cout << "vec1 and vec2 are equal." << std::endl; } return 0 ; }
练习3.37
下面的程序是何含义,程序的输出结果是什么?
1 2 3 4 5 6 const char ca[] = { 'h' , 'e' , 'l' , 'l' , 'o' };const char *cp = ca;while (*cp) { cout << *cp << endl; ++cp; }
这个程序的含义是遍历一个字符数组并输出其中的每个字符。 由于数组 ca
没有以空字符 \0
结束,while (*cp)
条件不会在 o
之后立即终止,程序可能会继续读取并输出数组之后的内存内容,导致未定义行为。这种情况下,程序的行为可能是不确定的,可能会输出垃圾字符或导致程序崩溃。
练习3.38
在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义? 两个指针相加没有意义且是非法的,因为指针本质上是内存地址的表示,加法操作在这个上下文中没有定义明确的结果和用途。这种操作既没有逻辑基础,也不符合编程语言的规范和约束。
练习3.39
编写一段程序,比较两个string对象。再编写一段程序,比较两个C风格字符串的内容。
比较两个string 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <string> using std::string;using std::cout;using std::endl;int main () { string s1 = "aaaaa" ; string s2 = "bbbbb" ; if (s1 == s2) { cout<<"equal" <<endl; } else { cout<<"not equal" <<endl; } return 0 ; }
比较两个C风格字符串 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <cstring> using std::cout;using std::endl;int main () { char * str1 = "aaaaa" ; char * str2 = "bbbbb" ; int result = strcmp (str1,str2); if (result == 0 ) { cout<<"equal" <<endl; } else { cout<<"not equal" <<endl; } return 0 ; }
练习3.40
编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用strcpy和strcat把前两个数组的内容拷贝到第三个数组当中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <cstring> using std::cout;using std::endl;const char ca1[] = "aaa" ;const char ca2[] = "bbb" ;char ca3[10 ];int main () { strcpy (ca3,ca1); strcat (ca3," " ); strcat (ca3,ca2); cout << ca3 << endl; return 0 ; }
练习3.41
编写一段程序,用整型数组初始化一个vector对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <vector> #include <iterator> using std::cout;using std::endl;using std::vector;using std::begin;using std::end;int main () { int int_arr[] = {0 ,1 ,2 ,3 ,4 ,5 }; vector<int > ivec (begin(int_arr), end(int_arr)) ; for ( auto i : ivec ) { cout << i << " " ; } return 0 ; }
练习3.42
编写一段程序,将含有整数元素的vector对象拷贝给一个整型数组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <iostream> #include <vector> #include <algorithm> using std::cout;using std::endl;using std::vector;int main () { vector<int > ivec = {0 ,1 ,2 ,3 ,4 ,5 }; int arr[ivec.size ()]; std::copy (ivec.begin (), ivec.end (), arr); for (size_t i = 0 ; i < ivec.size (); ++i) { cout << arr[i] << " " ; } cout << endl; return 0 ; }
练习3.43
编写3个不同版本的程序,令其均能输出ia的元素。版本1使用范围for语句管理迭代过程;版本2和版本3都使用普通for语句,其中版本2要求使用下标运算符,版本3要求使用指针。此外,在所有3个版本的程序中都要直接写出数据类型,而不能使用类型别名、auto关键字和decltype关键字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 #include <iostream> using std::cout;using std::endl;int main () { int ia[3 ][4 ] = { {0 ,1 ,2 ,3 }, {4 ,5 ,6 ,7 }, {8 ,9 ,10 ,11 } }; for (int (&row)[4 ] : ia) { for (int & elem : row) { cout << elem << " " ; } } cout << endl; for (int i = 0 ; i < 3 ; ++i) { for (int j = 0 ; j < 4 ; ++j) { cout << ia[i][j] << " " ; } } cout << endl; int (*p)[4 ] = ia; for (int i = 0 ; i < 3 ; ++i) { for (int j = 0 ; j < 4 ; ++j) { cout << *(*(p + i) +j) << " " ; } } cout << endl; return 0 ; }
练习3.44
改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream> using std::cout;using std::endl;int main () { int ia[3 ][4 ] = { {0 ,1 ,2 ,3 }, {4 ,5 ,6 ,7 }, {8 ,9 ,10 ,11 } }; using int_array = int [4 ]; for (int_array&row : ia) { for (int & elem : row) { cout << elem << " " ; } } cout << endl; for (int i = 0 ; i < 3 ; ++i) { for (int j = 0 ; j < 4 ; ++j) { cout << ia[i][j] << " " ; } } cout << endl; int_array *p = ia; for (int i = 0 ; i < 3 ; ++i) { for (int j = 0 ; j < 4 ; ++j) { cout << *(*(p + i) +j) << " " ; } } cout << endl; return 0 ; }
练习3.45
再一次改写程序,这次使用auto关键字。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 #include <iostream> using std::cout;using std::endl;int main () { int ia[3 ][4 ] = { {0 ,1 ,2 ,3 }, {4 ,5 ,6 ,7 }, {8 ,9 ,10 ,11 } }; using int_array = int [4 ]; for (auto &row : ia) { for (auto & elem : row) { cout << elem << " " ; } } cout << endl; for (auto i = 0 ; i < 3 ; ++i) { for (auto j = 0 ; j < 4 ; ++j) { cout << ia[i][j] << " " ; } } cout << endl; int_array *p = ia; for (auto i = 0 ; i < 3 ; ++i) { for (auto j = 0 ; j < 4 ; ++j) { cout << *(*(p + i) +j) << " " ; } } cout << endl; return 0 ; }