練習9.1
(a)list更合適,因為按照字典序插入到容器中代表需要在容器中間插入元素
(b)deque更合適,因為deque支持雙端插入和刪除
(c)無具體的插入刪除操作,讀取整數數量也是未知,可以選擇vector
練習9.2
int main(int argc, char* argv[]) { std::list<std::deque<int>> lq; }
練習9.3
指向同一個容器的元素,或者尾后迭代器
end不在begin之前
練習9.4
bool find(vector<int>::const_iterator& begin, vector<int>::const_iterator& end, int i) { while (begin != end) { if (*begin == i)return true; } return false; }
練習9.5
vector<int>::const_iterator& find(vector<int>::const_iterator& begin, vector<int>::const_iterator& end, int i) { while (begin != end) { if (*begin == i)return begin; } std::cerr << "don't find the num in the arrange"; return end; }
練習9.6
在C++定義的容器類型中,只有vector和queue容器提供迭代器算數運算和除!=和==之外的關系運算
練習9.7
vector<int>::size_type
練習9.8
讀取
list<string>::iterator||list<string>::const_iterator
寫入
list<string>::iterator
練習9.9
cbegin返回的是const迭代器對象,begin不是
練習9.10
it1:vector<int>::iterator
it2:const vector<int>::iteratorit3:vector<int>::const_iterator
it4:const vector<int>::const_iterator
練習9.11
vector<int> v1;//空 vector<int> v2(v1);//v1的拷貝 vector<int> v3{ 0,1,2,3 };//初始化為初始化列表的拷貝 vector<int> v4(v3.begin(), v3.end());//初始化為迭代器之間元素的拷貝 vector<int> v5(10);//包含10個元素,每一個都被值初始化為0 vector<int> v6(10, 5);//包含10個元素,每個都初始化為5
練習9.12
接受一個容器創建其拷貝的構造函數:要求具有相同的容器類型,保存的是相同的元素類型
接受兩個迭代器創建拷貝的構造函數:只要求迭代器范圍內的元素類型相同
練習9.13
int main(int argc, char* argv[]) { list<int> li{ 0,1,2,3 }; vector<double> vd(li.begin(), li.end()); for (auto i : vd) cout << i << " "; cout << endl; vector<int> vi{ 0,1,2,3 }; vector<double> vd2(vi.begin(), vi.end()); for (auto i : vd2) cout << i << " "; }
練習9.14
int main(int argc, char* argv[]) { list<const char*> lc; vector<string> vs; vs.assign(lc.begin(), lc.end()); }
練習9.15
template<typename T> bool check(const vector<T>& v1, const vector<T>& v2) { return v1 == v2; } int main(int argc, char* argv[]) { vector<string> vs1{ "012" }; vector<string> vs2{ "012","123" }; cout << (check(vs1, vs2) ? "相等" : "不相等"); }
練習9.16
template<typename T> bool check(const list<T>& v1, const vector<T>& v2) { if (v1.size() == v2.size()) { auto j = v2.begin(); for (auto i = v1.begin(); i !=v1.end() ; i++,j++) { if (*i != *j)return false; } return true; } return false; } int main(int argc, char* argv[]) { list<string> vs1{ "012" }; vector<string> vs2{ "012","123" }; cout << (check(vs1, vs2) ? "相等" : "不相等"); }
練習9.17
要求不是無序關聯容器,c1和c2必須是相同類型的容器,且必須保存相同類型的元素
練習9.18
int main(int argc, char* argv[]) { std::deque<string> ds; string s; while (cin >> s) { ds.emplace_back(s); s.clear(); } for (auto it = ds.begin(); it != ds.end(); it++) { cout << *it << endl; } }
練習9.19
int main(int argc, char* argv[]) { list<string> ls; string s; while (cin >> s) { ls.emplace_back(s); s.clear(); } for (auto it = ls.begin(); it != ls.end(); it++) { cout << *it << endl; } }
練習9.20
int main(int argc, char* argv[]) { list<int> li; int i; deque<int> di1, di2; while (cin >> i) { li.emplace_back(i); } for (auto it = li.begin(); it != li.end(); it++) { if ((*it) % 2)di1.emplace_back(*it); else di2.emplace_back(*it); } }
練習9.21
int main(int argc, char* argv[]) { vector<string> vst; string word; auto iter = vst.begin(); while (cin >> word) { iter = vst.insert(iter, word); } }
將iter初始化為vst.begin(),第一次調用insert會將我們剛剛讀入的string插入到iter所指向的元素之前的位置。
練習9.22
int main(int argc, char* argv[]) { vector<int> iv{ 0,1,2,3,4,5 }; vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size() / 2; int some_val = 0; while (iter!=mid) { if (*iter == some_val) iv.insert(iter, 2 * some_val); } }
該程序會在滿足程序的情況下在vector開頭插入元素,導致迭代器失效,應更新循環中的迭代器,並保證迭代器不會陷入無限循環
int main(int argc, char* argv[]) { vector<int> iv{ 0,1,2,3,4,5 }; vector<int>::iterator iter = iv.begin(), mid = iv.begin() + iv.size() / 2; int some_val = 0; while (iter!=mid) { if (*iter == some_val) { iter = iv.insert(iter, 2 * some_val); iter += 2; } else iter++; mid = iv.begin() + iv.size() / 2; } }
練習9.23
val,val2,val3和val4的值都相同
練習9.24
at:有未經處理的異常: Microsoft C++ 異常: std::out_of_range
下標運算符:vector subscript out of range
front:front() called on empty vector
begin:cant't dereference value-initialized vector iterator
練習9.25
elem1與elem2相等不會刪除容器元素,如果elem2時尾后迭代器會刪除所有elem1到elem2的所有元素(不包括elem2),如果elem1和elem2皆為尾后迭代器則不會刪除元素
練習9.26
int main(int argc, char* argv[]) { int ia[] = { 0 ,1,1,2,3,5,8,13,21,55,89 }; vector<int> iv; iv.assign(ia, ia + sizeof(ia) / sizeof(int)); auto it = iv.begin(); while (it!=iv.end()) { if (!(*it % 2)) it = iv.erase(it); else it++; } list<int> il; il.assign(ia, ia + sizeof(ia) / sizeof(int)); auto it2 = il.begin(); while (it2 != il.end()) { if (*it2 % 2) it2 = il.erase(it2); else it2++; } }
練習9.27
int main(int argc, char* argv[]) { forward_list<int> flst = { 0,1,2,3,4,5,6,7,8,9 }; auto prev = flst.before_begin(), curr = flst.begin(); while (curr != flst.end()) { if (*curr % 2) { curr = flst.erase_after(prev); } else { prev = curr; curr++; } } }
練習9.28
void fl_find_insert(forward_list<string>& flst, string& s1, string& s2) { auto prev = flst.before_begin(), curr = flst.begin(); while (curr != flst.end()) { if (*curr == s1) { flst.insert_after(prev, s2); return; } else { prev = curr; ++curr; } } flst.insert_after(prev, s2); }
練習9.29
vec.resize(100):調整vec大小為100,由於vec原來包含25個元素,將75個值為0的元素添加到vec末尾
vec.resize(10):調整vec大小為10,由於vec原來包含25個元素,將vec末尾15個元素刪除
練習9.30
元素必須能進行值初始化,若為類類型元素則必須提供默認值或者默認構造函數
練習9.31
list迭代器沒有遞增遞減的操作,需要修改為advance(iter, 2);
forward_list沒有insert和erase操作需要修改
練習9.32
不合法,++遞增符改變了iter的值,將產生未定義的行為。因為賦值運算符左右兩端的運算對象都用到了iter,並且右側的運算對象還改變了iter的值
練習9.33
迭代器失效
練習9.34
遍歷容器,查找所有為奇數的元素並復制該元素插入到容器中,但因為只遞增了一次導致程序只會卡在第一次找到奇數的時候
練習9.35
容器的size是指它已經保存的元素的數目
容器的capacity是在不分配新的內存空間的前提下他最多能保存多少元素
練習9.36
不可能,因為size必然小於等於capacity
練習9.37
list沒有capacity是因為不要求空間是連續的
array沒有capacity是因為array不允許修改空間大小
練習9.38
int main(int argc, char* argv[]) { vector<int> vec1; int a; while (cin >> a) { vec1.push_back(a); cout << "vector的大小" << vec1.size() << endl;; cout << "vector的容量" << vec1.capacity() << endl; } }
練習9.39
為vector分配1024個string元素的內存,傳入值,然后插入容器一半數量的空string元素
練習9.40
256:1024
512:1024
1000:1536
1024:2304
練習9.41
int main(int argc, char* argv[]) { vector<char>cvec(10, 'c'); char *charray=new char[cvec.size()]; memcpy(charray, &cvec[0], cvec.size() * sizeof(char)); string s(charray); }
練習9.42
int main(int argc, char* argv[]) { string s; s.reserve(100); char c; while (cin >> c) { s.push_back(c); } }
練習9.43
void str_find_replace(string& s, string& oldVal, string& newVal) { auto it1 = s.begin(), it2 = newVal.begin(), it3 = newVal.end(); for (; it1 != s.end() - oldVal.size(); it1++) { if (s.substr(it1 - s.begin(), oldVal.size()) == oldVal) { s.erase(it1 - s.begin(), oldVal.size()); it1 = s.insert(it1, newVal.begin(), newVal.end()); it1 += newVal.size(); } } }
練習9.44
void str_find_replace(string& s, string& oldVal, string& newVal) { auto it1 = s.begin(), it2 = newVal.begin(), it3 = newVal.end(); for (; it1 != s.end() - oldVal.size(); it1++) { if (s.substr(it1 - s.begin(), oldVal.size()) == oldVal) { s.replace(it1, it1 + oldVal.size(), newVal); it1 += newVal.size(); } } }
練習9.45
void str_find_add(string& s, string& prev, string& last) { s.insert(0, prev); s.append(last); }
練習9.46
void str_find_add(string& s, string& prev, string& last) { s.insert(0, prev); s.insert(s.size(), last); }
練習9.47
只用find_first_of的
int main(int argc, char* argv[]) { string s = "ab2c3d7R4E6"; string numbers("0123456789"); auto pos = 0; while ((pos = s.find_first_of(numbers, pos)) != string::npos) { cout << s[pos++]; } auto pos1 = 0, pos2 = 0; while ((pos2 = s.find_first_of(numbers, pos1)) != string::npos) { for (; pos1 != pos2; ++pos1) cout << s[pos1]; ++pos1; } if (pos1 != s.find_last_not_of(numbers))cout << s[pos1]; return 0; }
只用find_first_not_of的
int main(int argc, char* argv[]) { string s = "ab2c3d7R4E6"; string numbers("0123456789"); auto pos1 = 0, pos2 = 0; while ((pos2 = s.find_first_not_of(numbers, pos1)) != string::npos) { for (; pos1 != pos2; ++pos1) cout << s[pos1]; ++pos1; } if (pos1 != s.find_last_not_of(numbers))cout << s[pos1]; auto pos = 0; while ((pos = s.find_first_not_of(numbers, pos)) != string::npos){ cout << s[pos++]; } return 0; }
練習9.48
string::npos
練習9.49
int main(int argc, char* argv[]) { string ascender("bdfhklt"); //上出頭部分單詞 string descender("gjpqy"); //下出頭部分單詞 std::ifstream ifs(argv[1]); string s, maxs; auto max = 0; string::size_type pos; if (ifs) { while (!ifs.eof()) { ifs >> s; if (s.find_first_of(ascender) == string::npos && s.find_first_of(descender) == string::npos&&s.size()>max) { max = s.size(); maxs = s; } s.clear(); } } return 0; }
練習9.50
計算整型值的string之和
int main(int argc, char* argv[]) { vector<string> strvec; long long ll = 0; for (const auto& it : strvec) { ll += stoll(it); } cout << ll << endl; return 0; }
計算浮點值的string之和
int main(int argc, char* argv[]) { vector<string> strvec; long double ld = 0; for (const auto& it : strvec) { ld += stold(it); } cout << ld << endl; return 0; }
練習9.51
#ifndef DATE_H_ #define DATE_H_ #include<string> using std::string; class Date { public: Date(string&); ~Date(); private: unsigned year; unsigned month; unsigned day; void str_to_month(string &str,string::size_type& pos); }; Date::Date(string &s) { string::size_type pos1, pos2; if (pos1 = s.find_first_of(",/") == string::npos) { pos1 = s.find_first_of(" "); pos2 = s.find_last_of(" "); str_to_month(s, pos1); day = stoul(s.substr(pos1 + 1, pos2)); year = stoul(s.substr(pos2 + 1, s.size())); } else if (pos1 = s.find_first_of(",") == string::npos) { pos1 = s.find_first_of("/"); pos2 = s.find_last_of("/"); str_to_month(s, pos1); day = stoul(s.substr(pos1 + 1, pos2)); year = stoul(s.substr(pos2 + 1, s.size())); } else if (pos1 = s.find_first_of("/") == string::npos) { pos1 = s.find_first_of(" "); pos2 = s.find_last_of(","); str_to_month(s, pos1); day = stoul(s.substr(pos1 + 1, pos2)); year = stoul(s.substr(pos2 + 1, s.size())); } } Date::~Date() { } inline void Date::str_to_month(string& s, string::size_type& pos1) { if (s.substr(0, pos1) == "Jan" || s.substr(0, pos1) == "January") { month = 1; } else if (s.substr(0, pos1) == "Feb" || s.substr(0, pos1) == "February") { month = 2; } else if (s.substr(0, pos1) == "Mar" || s.substr(0, pos1) == "March") { month = 3; } else if (s.substr(0, pos1) == "Apr" || s.substr(0, pos1) == "April") { month = 4; } else if (s.substr(0, pos1) == "May" || s.substr(0, pos1) == "May") { month = 5; } else if (s.substr(0, pos1) == "Jun" || s.substr(0, pos1) == "June") { month = 6; } else if (s.substr(0, pos1) == "Jul" || s.substr(0, pos1) == "July") { month = 7; } else if (s.substr(0, pos1) == "Aug" || s.substr(0, pos1) == "August") { month = 8; } else if (s.substr(0, pos1) == "Sept" || s.substr(0, pos1) == "September") { month = 9; } else if (s.substr(0, pos1) == "Oct" || s.substr(0, pos1) == "October") { month = 10; } else if (s.substr(0, pos1) == "Nov" || s.substr(0, pos1) == "November") { month = 11; } else if (s.substr(0, pos1) == "Dec" || s.substr(0, pos1) == "December") { month = 12; } else { month = stoul(s.substr(0, pos1)); } } #endif // !DATE_H_
練習9.52
unsigned get_operator_level(const char& c) { if (c == ')')return 4; else if (c == '*' || c == '/')return 3; else if (c == '+' || c == '-')return 2; else return 1; } int main(int argc, char* argv[]) { string s("(11+21)*13-(62+21)/53"); string ns; stack<char> chars; stack<long> numbers; bool other = true; for (const auto&c:s) { if (isdigit(c)) { ns.insert(ns.end(), c); } else if(chars.empty()||c=='('){ chars.push(c); } else if (c != ')') { while (!chars.empty() && get_operator_level(chars.top()) >= get_operator_level(c)) { ns.insert(ns.end(), chars.top()); chars.pop(); } chars.push(c); ns.insert(ns.end(), ' '); } else { while (chars.top() != '(') { ns.insert(ns.end(), chars.top()); chars.pop(); } chars.pop(); } } while (!chars.empty()) { ns.insert(ns.end(), chars.top()); chars.pop(); } for (const auto& c : ns) { if (isdigit(c) && other) { long num = 0; if (!numbers.empty()) { num = numbers.top(); numbers.pop(); } num = num * 10 + c - '0'; numbers.push(num); } else if (isdigit(c)) { numbers.push(c - '0'); other = true; } else if (isspace(c)) { other = false; } else { long num1, num2; num2 = numbers.top(); numbers.pop(); num1 = numbers.top(); numbers.pop(); if (c == '+')numbers.push(num1 + num2); else if (c == '-')numbers.push(num1 - num2); else if (c == '*')numbers.push(num1 * num2); else if (c == '/')numbers.push(num1 / num2); other = false; } } return 0; }
unsigned get_operator_level(const char& c) { if (c == ')')return 4; else if (c == '*' || c == '/')return 3; else if (c == '+' || c == '-')return 2; else return 1; } int main(int argc, char* argv[]) { string s("(11+21)*13-(62+21)/53"); string ns; stack<char> chars; stack<long> numbers; bool other = true; for (const auto&c:s) { if (isdigit(c)) { ns.insert(ns.end(), c); } else if(chars.empty()||c=='('){ chars.push(c); } else if (c != ')') { while (!chars.empty() && get_operator_level(chars.top()) >= get_operator_level(c)) { ns.insert(ns.end(), chars.top()); chars.pop(); } chars.push(c); ns.insert(ns.end(), ' '); } else { while (chars.top() != '(') { ns.insert(ns.end(), chars.top()); chars.pop(); } chars.pop(); } } while (!chars.empty()) { ns.insert(ns.end(), chars.top()); chars.pop(); } for (const auto& c : ns) { if (isdigit(c) && other) { long num = 0; if (!numbers.empty()) { num = numbers.top(); numbers.pop(); } num = num * 10 + c - '0'; numbers.push(num); } else if (isdigit(c)) { numbers.push(c - '0'); other = true; } else if (isspace(c)) { other = false; } else { long num1, num2; num2 = numbers.top(); numbers.pop(); num1 = numbers.top(); numbers.pop(); if (c == '+')numbers.push(num1 + num2); else if (c == '-')numbers.push(num1 - num2); else if (c == '*')numbers.push(num1 * num2); else if (c == '/')numbers.push(num1 / num2); other = false; } } return 0; }