Write a program to read the standard input a line at a time.
Modify your program to read a word at a time.
#include#include using namespace std; int main(void) { string str_in; while(getline(cin,str_in)) cout << str_in << endl; return 0; }
Modified version:
#include3.3#include using namespace std; int main(void) { string str_in; while(cin >> str_in) cout << str_in << endl; return 0; }
Explain how whitespace characters are handled in the string input operator and in the getline function.
对于string的输入运算符(>>)
忽略开头的空白,从第一个非空白字符开始读起,直到遇到下一处空白为止。
对于getline()
读取字符(包括除换行符之外的空白)直到遇到第一个换行符,对于换行符,只读不取。
3.4Write a program to read two strings and report whether the strings are equal. If not, report which of the two is larger.
Now, change the program to report whether the strings have the same length, and if not, report which is longer.
#include#include using namespace std; int main(void) { string str1,str2; cin >> str1 >> str2; if(str1 == str2) cout << "两个字符串相等。"; else { cout << "两个字符串不相等," << "且较大的字符串是:n"; if(str1 > str2) cout << str1; else cout << str2; } cout << endl; return 0; }
changed version:
#include3.5#include using namespace std; int main(void) { string str1,str2; cin >> str1 >> str2; auto size1 = str1.size(), size2 = str2.size(); if(size2 == size1) cout << "两个字符串的长度相等。"; else { cout << "两个字符串的长度不相等," << "且较长的字符串是:n"; if(size1 > size2) cout << str1; else cout << str2; } cout << endl; return 0; }
Write a program to read strings from the standard input, concatenating what is read into one large string. Print the concatenated string.
Next, change the program to separate adjacent input strings by a space.
#include#include using namespace std; int main(void) { string str_in, str; while(cin >> str_in) str = str + str_in; cout << endl << str << endl; return 0; }
Changed version:
#include3.6#include using namespace std; int main(void) { string str_in, str; while(cin >> str_in) str = str + str_in + ' '; cout << endl << str << endl; return 0; }
Use a range for to change all the characters in a string to X.
#include3.7#include using namespace std; int main(void) { string str; cin >> str; for(auto &ch:str) ch = 'A'; cout << str << endl; return 0; }
What would happen if you define the loop control variable in the previous exercise as type char? Predict the results and then change your program to use a char to see if you were right.
str中的字符不会被转换为X。
因为若要通过范围for改变string中字符的值,须把循环变量定义为引用类型。
若非定义为引用类型,而是定义为char, 则循环变量只是依次被初始化为string中的各个字符,改变循环变量对原始string无影响。
3.8Rewrite the program in the first exercise, first using a while and again using a traditional for loop. Which of the three approaches do you prefer and why?
while loop:
#include#include using namespace std; int main(void) { string s; cin >> s; decltype(s.size()) i = 0; while(!s.empty() && i traditional for loop:
#include#include using namespace std; int main(void) { string s; cin >> s; for(decltype(s.size()) i = 0; !s.empty() && i 更喜欢用范围for. 因为可以避免操作索引。
3.9What does the following program do? Is it valid? If not, why not?
string s; cout << s[0] << endl;不合法,因为s为空,因此对s[0]的访问结果未定义。
3.10Write a program that reads a string of characters including punctuation and writes what was read but with the punctuation removed.
#include3.11#include #include using namespace std; int main(void) { string s; cin >> s; for(auto ch:s) if(!ispunct(ch)) cout << ch; cout << endl; return 0; } Is the following range for legal? If so, what is the type of c?
const string s = "Keep out!"; for (auto &c : s) { }
如果for循环体中不改变c的值则合法;否则不合法。
c的类型为const char &.
3.12Which, if any, of the following vector definitions are in error? For those that are legal, explain what the definition does. For those that are not legal, explain why they are illegal.
(a) vector> ivec; (b) vector svec = ivec; (c) vector svec(10, "null");
(a) 合法。声明了一个元素为vector
的vector, 且该vector被默认初始化为空。 (b)不合法。ivec的元素是vector
, 与svec不同,因此无法拷贝给svec. ©合法。声明了svec, 并初始化为含10个string元素且每个元素都为"null".
3.13How many elements are there in each of the following vectors? What are the values of the elements?
(a) vectorv1; (b) vector v2(10); (c) vector v3(10, 42); (d) vector v4{10}; (e) vector v5{10, 42}; (f) vector v6{10}; (g) vector v7{10, "hi"}; (a) 0
(b) 10; 都为0.
© 10; 都为42;
(d) 1; 10.
(e) 2; 10、42.
(f) 10; 都为空串。
(g) 10; 都为"hi".
3.14Write a program to read a sequence of ints from cin and store those values in a vector.
#include3.15#include using namespace std; int main(void) { int i; vector v; while(cin >> i) v.push_back(i); for(auto j:v) cout << j << ' '; cout << endl; return 0; } Repeat the previous program but read strings this time.
#include3.16#include using namespace std; int main(void) { string s; vector v; while(cin >> s) v.push_back(s); cout << endl; for(auto j:v) cout << j << ' '; cout << endl; return 0; } Write a program to print the size and contents of the vectors from exercise 3.13. Check whether your answers to that exercisewere correct. If not, restudy § 3.3.1 (p. 97) until you understand why you were wrong.
#include3.17#include #define PRINT_VN(vn) { cout << #vn << "nsize: " << vn.size() << "ncontents: "; for(auto j:vn) cout << j << " "; cout << endl; } using namespace std; int main(void) { vector v1; vector v2(10); vector v3(10, 42); vector v4{10}; vector v5{10, 42}; vector v6{10}; vector v7{10, "hi"}; PRINT_VN(v1) PRINT_VN(v2) PRINT_VN(v3) PRINT_VN(v4) PRINT_VN(v5) PRINT_VN(v6) PRINT_VN(v7) return 0; } Read a sequence of words from cin and store the values a vector.
After you’ve read all the words, process the vector and change each word to uppercase.
Print the transformed elements, eight words to a line.
#include3.18#include #include using namespace std; int main(void) { vector v; string s; while(cin >> s) v.push_back(s); cout << endl; for(auto i:v) cout << i << endl; return 0; } Is the following program legal? If not, how might you fix it?
vectorivec; ivec[0] = 42; 不合法。应该修改为:
vector3.19ivec; ivec.push_back(42); List three ways to define a vector and give it ten elements, each with the value 42.
Indicate whether there is a preferred way to do so and why.
//方法1: vectorivec1 = {42,42,42,42,42,42,42,42,42,42}; //方法2: vector ivec2(10,42); //方法3: vector ivec3; for(auto i=0;i<10;i++) ivec3.push_back(42); 更喜欢方法2,因为更简单,可读性更好。
3.20Read a set of integers into a vector. Print the sum of each pair of adjacent elements.
Change your program so that it prints the sum of the first and last elements, followed by the sum of the second and second-to-last, and so on.
#include#include using namespace std; int main(void) { vector v; int i; while(cin >> i) v.push_back(i); cout << endl; for(decltype(v.size()) j = 0; j Changed version:
#include#include using namespace std; int main(void) { vector v; int i; while(cin >> i) v.push_back(i); cout << endl; auto v_size = v.size(); for(decltype(v.size()) j = 0; j 3.21 Redo the first exercise from § 3.3.3 (p. 105) using iterators.
#include3.22#include #define PRINT_VN(vn) { cout << #vn << "nsize: " << vn.size() << "ncontents: "; for(auto i=vn.cbegin();i!=vn.cend();i++) cout << *i << " "; cout << endl; } using namespace std; int main(void) { vector v1; vector v2(10); vector v3(10, 42); vector v4{10}; vector v5{10, 42}; vector v6{10}; vector v7{10, "hi"}; PRINT_VN(v1) PRINT_VN(v2) PRINT_VN(v3) PRINT_VN(v4) PRINT_VN(v5) PRINT_VN(v6) PRINT_VN(v7) return 0; } Revise the loop that printed the first paragraph in text to instead change the elements in text that correspond to the first paragraph to all uppercase.
After you’ve updated text, print its contents.#include3.23#include #include using namespace std; int main(void) { vector v; string s; while(getline(cin,s)) v.push_back(s); for(auto i=v.begin(); !i->empty() && i!=v.end(); i++) { for(auto j=i->begin(); j!=i->end(); j++) if(isalpha(*j)) *j = toupper(*j); cout << *i; } cout << endl; return 0; } Write a program to create a vector with ten int elements. Using an iterator, assign each element a value that is twice its current value. Test your program by printing the vector.
#include3.24#include using namespace std; int main(void) { vector v = {2,0,2,2,0,4,2,7,1,8}; for(auto i=v.begin(); i!=v.end(); i++) *i *= 2; for(auto j=v.begin(); j!=v.end(); j++) cout << *j << ' '; cout << endl; return 0; } Redo the last exercise from § 3.3.3 (p. 105) using iterators.
#include#include using namespace std; int main(void) { vector v; int i; while(cin >> i) v.push_back(i); cout << endl; for(auto i=v.cbegin(); i!=v.cend()-1; i++) cout << *i + *(i+1) << ' '; cout << endl; return 0; } changed version:
#include3.25#include using namespace std; int main(void) { vector v; int i; while(cin >> i) v.push_back(i); cout << endl; for(auto i=v.cbegin(),j=v.cend()-1; i <= j; i++,j--) cout << *i + *j << ' '; cout << endl; return 0; } Rewrite the grade clustering program from § 3.3.3 (p. 104) using iterators instead of subscripts.
#include3.26#include using namespace std; int main(void) { vector v(11,0); unsigned u; auto i = v.begin(); while(cin >> u) ++*(i+u/10); cout << endl; for(auto j=v.cbegin(); j!=v.cend(); j++) cout << *j << ' '; cout << endl; return 0; } In the binary search program on page 112, why did we write mid = beg + (end - beg) / 2;
instead of mid = (beg + end) /2; ?
迭代器无法直接相加;但迭代器相减可以得到一个整数,表示两迭代器的距离。
因此mid = (beg + end) /2是错误的用法。
而mid = beg + (end - beg) / 2通过将beg加上首尾距离的一半,得到中间元素的迭代器。
3.27Assuming txt_size is a function that takes no arguments and returns an int value, which of the following definitions are illegal? Explain why.
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";(b)合法
(a)、©、(d)不合法。(a)、©的维度不是常量表达式;(d)数组维度过小,无法容纳字符串字面值结尾的’ ’;
3.28What are the values in the following arrays?
string sa[10]; int ia[10]; int main() { string sa2[10]; int ia2[10]; }数组sa、sa2内的值都为10个空串。
数组ia内的值为10个0;数组ia2内的值未定义。
3.29List some of the drawbacks of using an array instead of a vector.
array须在声明时确定维度,且维度必须为常量表达式。因此无法向数组添加元素。
3.30Identify the indexing errors in the following code:
constexpr size_t array_size = 10; int ia[array_size]; for (size_t ix = 1; ix <= array_size; ++ix) ia[ix] = ix;索引越界了。array_size不是合法索引。for循环括号内应改为:
size_t ix = 0; ix 3.31
Write a program to define an array of ten ints. Give each element the same value as its position in the array.
#include3.32using namespace std; int main(void) { constexpr size_t a_size = 10; int a[a_size]; for(size_t i=0; i Copy the array you defined in the previous exercise into another array.
Rewrite your program to use vectors.#includeusing namespace std; int main(void) { constexpr size_t a_size = 10; int a[a_size]; for(size_t i=0; i using vectors:
#include3.33#include using namespace std; int main(void) { vector v; for(int i=0; i<10; ++i) v.push_back(i); vector v1 = v; for(auto i=v1.cbegin(); i!=v1.cend(); ++i) cout << *i; cout << endl; return 0; } What would happen if we did not initialize the scores array in the program on page 116?
若不初始化,则数组内的值都是未定义的。因此无法正确计算出各个分数段的分数个数。
3.34Given that p1 and p2 point to elements in the same array, what does the following code do? Are there values of p1 or p2 that make this code illegal?
p1 += p2 - p1;相当于p1 = p2;
若p1和p2合法,则该表达式合法。
3.35Using pointers, write a program to set the elements in an array to zero.
#include3.36using namespace std; int main(void) { int ar[10]; int *pbeg = begin(ar), *pend = end(ar); while(pbeg != pend) { *pbeg = 0; ++pbeg; } for(pbeg=begin(ar); pbeg!=pend; ++pbeg) cout << *pbeg; cout << endl; return 0; } Write a program to compare two arrays for equality. Write a similar program to compare two vectors.
Compare two arrays:
#include#define NOT_EQUAL { cout << "The two arrays are not equal.n"; return 0;} using namespace std; int main(void) { int ar1[] = {1,2,3,4}; int ar2[] = {1,2,3}; int *pbeg1 = begin(ar1), *pend1 = end(ar1), *pbeg2 = begin(ar2), *pend2 = end(ar2); if(pend1-pbeg1 == pend2-pbeg2) { while(pbeg1!=pend1) { if(*pbeg1 == *pbeg2) { ++pbeg1; ++pbeg2; } else NOT_EQUAL } } else NOT_EQUAL cout << "The two arrays are equal.n"; return 0; } Compare two vectors:
#include3.37#include #define NOT_EQUAL { cout << "The two vectors are not equal.n"; return 0;} using namespace std; int main(void) { vector v1 = {1,2,3,4}; vector v2 = {1,2,3}; if(v1.size() == v2.size()) { auto i1 = v1.begin(), i2 = v2.begin(); while(i1 != v1.end()) { if(*i1 == *i2) { ++i1; ++i2; } else NOT_EQUAL } } else NOT_EQUAL cout << "The two vectors are equal.n"; return 0; } What does the following program do?
const char ca[] = {’h’, ’e’, ’l’, ’l’, ’o’}; const char *cp = ca; while (*cp) { cout << *cp << endl; ++cp; }该程序段打印数组ca中的所有字符,并继续将数组后的内存区域上的值翻译成字符打印出来,直到遇到’ ’.
3.38In this section, we noted that it was not only illegal but meaningless to try to add two pointers. Why would adding two pointers be meaningless?
因为指针的值是一个内存地址;指针与指针相加相当于将两个地址的数值相加,并不能得到另一个有意义的地址。因此指针相加是无意义的。
3.39Write a program to compare two strings. Now write a program to compare the values of two C-style character strings.
Strings:
#include#include using namespace std; int main(void) { string s1 = "hello"; string s2 = "hello"; if(s1 == s2) cout << "The two strings are equal.n"; else cout << "The two strings are not equal.n"; return 0; } C-style strings:
#include3.40#include using namespace std; int main(void) { char s1[] = "hello"; char s2[] = "hello"; if(strcmp(s1,s2)) cout << "The two strings are not equal.n"; else cout << "The two strings are equal.n"; return 0; } Write a program to define two character arrays initialized from string literals. Now define a third character array to hold the concatenation of the two arrays.
Use strcpy and strcat to copy the two arrays into the third.#include3.41#include using namespace std; int main(void) { constexpr size_t a_size = 1024; char s1[a_size] = "hello,"; char s2[] = "world"; char s3[a_size]; strcat(s1,s2); strcpy(s3,s1); cout << s3 << endl; return 0; } Write a program to initialize a vector from an array of ints.
#include3.42#include using namespace std; int main(void) { int ar[] = {1,2,3,4,5}; vector v(begin(ar),end(ar)); for(auto i=v.begin();i!=v.end();++i) cout << *i; cout << endl; return 0; } Write a program to copy a vector of ints into an array of ints.
#include3.43#include using namespace std; int main(void) { vector v = {1,2,3,4,5}; int ar[5]; int *i=begin(ar); auto j=v.begin(); while(i!=end(ar)) { *i = *j; ++i; ++j; } for(auto i=begin(ar);i!=end(ar);++i) cout << *i; cout << endl; return 0; } Write three different versions of a program to print the elements of ia.
One version should use a range for to manage the iteration, the other two should use an ordinary for loop in one case using subscripts and in the other using pointers. In all three programs write all the types directly. That is, do not use a type alias, auto, or decltype to simplify the code.Use a range for:
#includeusing namespace std; int main(void) { int ia[3][4] = { {0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11} }; //using a range for. for(int (&i)[4]:ia) for(int j:i) cout << j << ' '; cout << endl; return 0; } Use an ordinary for loop(using subscripts):
//using subscripts for(int i=0;i<3;i++) for(int j=0;j<4;j++) cout << ia[i][j] << ' ';Use an ordinary for loop(using pointers):
//using pointers for(int i=0;i<3;i++) for(int j=0;j<4;j++) cout << *(*(ia+i)+j) << ' ';3.44Rewrite the programs from the previous exercises using a type alias for the type of the loop control variables.
//using a range for. //using a type alias using int_arr = int[4]; for(int_arr &i:ia) for(int j:i) cout << j << ' ';3.45Rewrite the programs again, this time using auto.
//using a range for. //using auto for(auto &i:ia) for(int j:i) cout << j << ' ';



