Skip to content

Commit

Permalink
Add soultions to second half of exercises in chapter 9.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaege committed Jan 21, 2016
1 parent 8e35365 commit 1576acc
Show file tree
Hide file tree
Showing 27 changed files with 602 additions and 5 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,11 @@ This repo is the solutions to exercises in book [_C++ Primer_ (5th Edition)](htt

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
--:|--:|--:|--:|--:|--:|--:|--:|--:|--:
[1](ch9/9.1.cpp)|[2](ch9/9.2.cpp)|[3](ch9/9.3.cpp)|[4](ch9/9.4.cpp)|[5](ch9/9.5.cpp)|[6](ch9/9.6.cpp)|[7](ch9/9.7.cpp)|[8](ch9/9.8.cpp)|[9](ch9/9.9.cpp)|[10](ch9/9.10.cpp)|
[11](ch9/9.11.cpp)|[12](ch9/9.12.cpp)|[13](ch9/9.13.cpp)|[14](ch9/9.14.cpp)|[15](ch9/9.15.cpp)|[16](ch9/9.16.cpp)|[17](ch9/9.17.cpp)|[18](ch9/9.18.cpp)|[19](ch9/9.19.cpp)|[20](ch9/9.20.cpp)|
[21](ch9/9.21.cpp)|[22](ch9/9.22.cpp)|[23](ch9/9.23.cpp)|[24](ch9/9.24.cpp)|[25](ch9/9.25.cpp)|[26](ch9/9.26.cpp)|[27](ch9/9.27.cpp)|[28](ch9/9.28.cpp)|[29](ch9/9.29.cpp)|[30](ch9/9.30.cpp)|
[31](ch9/9.31.cpp)|[32](ch9/9.32.cpp)|[33](ch9/9.33.cpp)|[34](ch9/9.34.cpp)|[35](ch9/9.35.cpp)|[36](ch9/9.36.cpp)|[37](ch9/9.37.cpp)|[38](ch9/9.38.cpp)|[39](ch9/9.39.cpp)|[40](ch9/9.40.cpp)|
[41](ch9/9.41.cpp)|[42](ch9/9.42.cpp)|[43](ch9/9.43.cpp)|[44](ch9/9.44.cpp)|[45](ch9/9.45.cpp)|[46](ch9/9.46.cpp)|[47](ch9/9.47.cpp)|[48](ch9/9.48.cpp)|[49](ch9/9.49.cpp)|[50](ch9/9.50.cpp)|
[1](ch9/9.1.md)|[2](ch9/9.2.cpp)|[3](ch9/9.3.md)|[4](ch9/9.4.cpp)|[5](ch9/9.5.cpp)|[6](ch9/9.6.md)|[7](ch9/9.7.md)|[8](ch9/9.8.md)|[9](ch9/9.9.md)|[10](ch9/9.10.md)|
[11](ch9/9.11.cpp)|[12](ch9/9.12.md)|[13](ch9/9.13.cpp)|[14](ch9/9.14.cpp)|[15](ch9/9.15.cpp)|[16](ch9/9.16.cpp)|[17](ch9/9.17.md)|[18](ch9/9.18.cpp)|[19](ch9/9.19.cpp)|[20](ch9/9.20.cpp)|
[21](ch9/9.21.md)|[22](ch9/9.22.md)|[23](ch9/9.23.md)|[24](ch9/9.24.cpp)|[25](ch9/9.25.md)|[26](ch9/9.26.cpp)|[27](ch9/9.27.cpp)|[28](ch9/9.28.cpp)|[29](ch9/9.29.md)|[30](ch9/9.30.md)|
[31](ch9/9.31.cpp)|[32](ch9/9.32.md)|[33](ch9/9.33.cpp)|[34](ch9/9.34.cpp)|[35](ch9/9.35.md)|[36](ch9/9.36.md)|[37](ch9/9.37.md)|[38](ch9/9.38.cpp)|[39](ch9/9.39.md)|[40](ch9/9.40.md)|
[41](ch9/9.41.cpp)|[42](ch9/9.42.md)|[43](ch9/9.43.cpp)|[44](ch9/9.44.cpp)|[45](ch9/9.45.cpp)|[46](ch9/9.46.cpp)|[47](ch9/9.47.cpp)|[48](ch9/9.48.cpp)|[49](ch9/9.49.cpp)|[50](ch9/9.50.cpp)|
[51](ch9/9.51.cpp)|[52](ch9/9.52.cpp)

<!---
Expand Down
22 changes: 22 additions & 0 deletions ch9/9.27.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <forward_list>
#include <iostream>

int main() {
std::forward_list<int> fli{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto pre = fli.before_begin();
auto cur = fli.begin();
while (cur != fli.end()) {
if (*cur % 2) {
cur = fli.erase_after(pre);
} else {
pre = cur;
++cur;
}
}

for (const auto &i : fli)
std::cout << i << " ";
std::cout << std::endl;

return 0;
}
41 changes: 41 additions & 0 deletions ch9/9.28.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#include <forward_list>
#include <string>
#include <iostream>

void insertAfterStr(std::forward_list<std::string> &fls,
const std::string &s1,
const std::string &s2) {
auto pre = fls.before_begin();
auto cur = fls.begin();
while (cur != fls.end()) {
if (*cur == s1) {
fls.insert_after(cur, s2);
return;
} else {
pre = cur++;
}
}
fls.insert_after(pre, s2);
}

int main() {
std::forward_list<std::string> fls{"s1", "s2", "s3"};

for (const auto &s : fls)
std::cout << s << " ";
std::cout << std::endl;

insertAfterStr(fls, "s2", "s4");

for (const auto &s : fls)
std::cout << s << " ";
std::cout << std::endl;

insertAfterStr(fls, "s5", "s6");

for (const auto &s : fls)
std::cout << s << " ";
std::cout << std::endl;

return 0;
}
3 changes: 3 additions & 0 deletions ch9/9.29.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
`vec.resize(100)` will append 75 value initialized elements at the end of `vec`.

`vec.resize(10)` will remove 90 elements from the end of `vec`.
1 change: 1 addition & 0 deletions ch9/9.30.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
If we use `resize` to expand a container, then the element of the container must have default constructor.
54 changes: 54 additions & 0 deletions ch9/9.31.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include <list>
#include <forward_list>
#include <iostream>

void change(std::list<int> &li) {
for (auto iter = li.begin(); iter != li.end(); )
if (*iter % 2) {
iter = li.insert(iter, *iter);
++iter; ++iter;
//iter += 2; // Error: list doesn't support iterator arithmetic
} else
iter = li.erase(iter);
}

void change(std::forward_list<int> &fli) {
for (auto pre = fli.before_begin(), cur = fli.begin();
cur != fli.end(); ) {
if (*cur % 2) {
pre = fli.insert_after(pre, *cur);
++pre;
++cur;
} else
cur = fli.erase_after(pre);
}
}

int main() {
std::list<int> li{1, 2, 3, 4, 5, 6};
std::forward_list<int> fli{1, 2, 3, 4, 5, 6};

std::cout << "li:\n";
for (const auto & i : li)
std::cout << i << " ";
std::cout << std::endl;

change(li);

for (const auto & i : li)
std::cout << i << " ";
std::cout << std::endl;

std::cout << "fli:\n";
for (const auto & i : fli)
std::cout << i << " ";
std::cout << std::endl;

change(fli);

for (const auto & i : fli)
std::cout << i << " ";
std::cout << std::endl;

return 0;
}
1 change: 1 addition & 0 deletions ch9/9.32.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
It is not legal. The order of evaluation of the arguments in function `insert` is undefined, so that if the second argument is evalated first, then the program logic will be wrong.
19 changes: 19 additions & 0 deletions ch9/9.33.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <vector>
using std::vector;

int main() {
vector<int> v{1, 2, 3, 4, 5};

auto begin = v.begin();
while (begin != v.end()) {
++begin;
begin = v.insert(begin, 42);
//v.insert(begin, 42);
// Iterator `begin` will become invalid after insert, thus if we don't
// update the iterator, any usage of this iterator will have undefined
// behaviours.
++begin;
}

return 0;
}
17 changes: 17 additions & 0 deletions ch9/9.34.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <vector>

int main() {
//std::vector<int> vi{1, 2, 3, 4};
std::vector<int> vi{2, 4};

// If the container contains any odd values, the loop will continue
// infinitely.
auto iter = vi.begin();
while (iter != vi.end()) { // The loop body should be a block.
if (*iter % 2)
iter = vi.insert(iter, *iter);
++iter;
}

return 0;
}
3 changes: 3 additions & 0 deletions ch9/9.35.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The `capacity` of a vector is how many elements the vector **can hold**.

The `size` of a vector is how many elements the vector **already holds**.
1 change: 1 addition & 0 deletions ch9/9.36.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No.
3 changes: 3 additions & 0 deletions ch9/9.37.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
A `list` does not support random access, and element of `list` is stored seperately in memory. There is no need to reallocate its elements, and thus no need to preallocate memory. So the "`capacity`" of a `list` is the same with its `size`.

An `array` has a fixed size, there is also no need to reallocate its elements, and thus no need to preallocate memory. So the "`capacity`" of an `array` is the same with its `size` too.
23 changes: 23 additions & 0 deletions ch9/9.38.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <vector>
#include <iostream>

int main() {
std::vector<int> vi;
std::cout << "Size: " << vi.size()
<< "\tCapacity : " << vi.capacity() << std::endl;

vi.push_back(1);
std::cout << "Size: " << vi.size()
<< "\tCapacity : " << vi.capacity() << std::endl;

for (std::vector<int>::size_type ix = 0; ix != 100; ++ix)
vi.push_back(ix);
std::cout << "Size: " << vi.size()
<< "\tCapacity : " << vi.capacity() << std::endl;

vi.shrink_to_fit();
std::cout << "Size: " << vi.size()
<< "\tCapacity : " << vi.capacity() << std::endl;

return 0;
}
9 changes: 9 additions & 0 deletions ch9/9.39.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
vector<string> svec;
svec.reserve(1024); // Preallocate memory for 1024 `string`s
string word;
while (cin >> word) // Read stirngs into `svec`
svec.push_back(word);
svec.resize(svec.size()+svec.size()/2);
// Reallocate memory, if current capacity is greater then this argument,
// nothing happened, else expand the size to at least the same as the
// argument.
7 changes: 7 additions & 0 deletions ch9/9.40.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If the program reads 256 words, the `capacity` is 1024.

If the program reads 512 words, the `capacity` is 1024.

If the program reads 1000 words, the `capacity` is 1024.

If the program reads 1048 words, the `capacity` is *at least* 1048.
12 changes: 12 additions & 0 deletions ch9/9.41.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#include <vector>
#include <string>
#include <iostream>

int main() {
std::vector<char> vc{'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'};
std::string str(vc.cbegin(), vc.cend());

std::cout << str << std::endl;

return 0;
}
1 change: 1 addition & 0 deletions ch9/9.42.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
We can call `s.reserve(100)` to preallocate the space for the string `s`.
39 changes: 39 additions & 0 deletions ch9/9.43.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <string>
#include <iostream>

void replaceStr(std::string &s,
const std::string &oldVal,
const std::string &newVal) {
// Use `<` operator, because there is possibility that `it` jump over `end()`
for (auto it = s.begin(); it < s.end() - oldVal.size() + 1; ) {
auto it2 = oldVal.cbegin();
for (auto it3 = it; it2 != oldVal.cend(); ++it2, ++it3)
if (*it3 != *it2)
break;
if (it2 == oldVal.cend()) {
std::string::size_type pos = it - s.begin();
s.erase(pos, oldVal.size());
s.insert(pos, newVal);
// Recalculate `it` from `begin()` rather than use `+=` operator, because
// `it` is invalid by `erase()` and `insert()`
it = s.begin() + pos + newVal.size();
} else
++it;
}
}

int main() {
std::string s{"r u ok?\ngo thru\ntho tho altho\nthrough thruu"};

std::cout << "Old:\n" << s << std::endl;
replaceStr(s, "tho", "though");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "thru", "through");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "hl", "hello");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "u", "you");
std::cout << "\nNew:\n" << s << std::endl;

return 0;
}
31 changes: 31 additions & 0 deletions ch9/9.44.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <string>
#include <iostream>

void replaceStr(std::string &s,
const std::string &oldVal,
const std::string &newVal) {
// Use `<` operator, because it is possible that `pos` jumps over the end
for (std::string::size_type pos = 0; pos < s.size(); ) {
if (s.substr(pos, oldVal.size()) == oldVal) {
s.replace(pos, oldVal.size(), newVal);
pos += newVal.size();
} else
++pos;
}
}

int main() {
std::string s{"r u ok?\ngo thru\ntho tho altho\nthrough thruu"};

std::cout << "Old:\n" << s << std::endl;
replaceStr(s, "tho", "though");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "thru", "through");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "hl", "hello");
std::cout << "\nNew:\n" << s << std::endl;
replaceStr(s, "u", "you");
std::cout << "\nNew:\n" << s << std::endl;

return 0;
}
21 changes: 21 additions & 0 deletions ch9/9.45.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include <string>
#include <iostream>

std::string fixName(const std::string &name,
const std::string &prefix,
const std::string &postfix) {
std::string newName = name;
std::string pref = prefix + " ";
newName.insert(newName.begin(), pref.begin(), pref.end());
return newName.append(" " + postfix);
}

int main() {
std::cout << fixName("James", "Mr.", "Jr.") << std::endl;

std::string name, prefix, postfix;
std::cin >> name >> prefix >> postfix;
std::cout << fixName(name, prefix, postfix) << std::endl;

return 0;
}
24 changes: 24 additions & 0 deletions ch9/9.46.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <string>
#include <iostream>

std::string fixName(const std::string &name,
const std::string &prefix,
const std::string &postfix) {
// An easy way.
//std::string newName = prefix + " " + name + " " + postfix;
//return newName;

std::string newName = name;
newName.insert(0, prefix + " ");
return newName.insert(newName.size(), " " + postfix);
}

int main() {
std::cout << fixName("James", "Mr.", "Jr.") << std::endl;

std::string name, prefix, postfix;
std::cin >> name >> prefix >> postfix;
std::cout << fixName(name, prefix, postfix) << std::endl;

return 0;
}
Loading

0 comments on commit 1576acc

Please sign in to comment.