Skip to content

Commit

Permalink
Add solutions to all exercises in chapter 6.
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaege committed Jan 15, 2016
1 parent baf2b49 commit caf2897
Show file tree
Hide file tree
Showing 59 changed files with 771 additions and 10 deletions.
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Solutions to Exercises in **C++ Primer** 5th Edition

This repo is the solutions to exercises in book _C++ Primer_ (5th Edition). All files except explicitly announced are under [Apache License](http://www.apache.org/licenses/LICENSE-2.0).
This repo is the solutions to exercises in book [_C++ Primer_ (5th Edition)](http://www.informit.com/store/c-plus-plus-primer-9780321714114). All files except explicitly announced are under [Apache License](http://www.apache.org/licenses/LICENSE-2.0).

### Contents

Expand Down Expand Up @@ -45,22 +45,22 @@ This repo is the solutions to exercises in book _C++ Primer_ (5th Edition). All

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
--:|--:|--:|--:|--:|--:|--:|--:|--:|--:
[1](ch5/5.1.md))|[2](ch5/5.2.md)|[3](ch5/5.3.cpp)|[4](ch5/5.4.md)|[5](ch5/5.5.cpp)|[6](ch5/5.6.cpp)|[7](ch5/5.7.md)|[8](ch5/5.8.md)|[9](ch5/5.9.cpp)|[10](ch5/5.10.cpp)|
[1](ch5/5.1.md)|[2](ch5/5.2.md)|[3](ch5/5.3.cpp)|[4](ch5/5.4.md)|[5](ch5/5.5.cpp)|[6](ch5/5.6.cpp)|[7](ch5/5.7.md)|[8](ch5/5.8.md)|[9](ch5/5.9.cpp)|[10](ch5/5.10.cpp)|
[11](ch5/5.11.cpp)|[12](ch5/5.12.cpp)|[13](ch5/5.13.md)|[14](ch5/5.14.cpp)|[15](ch5/5.15.md)|[16](ch5/5.16.cpp)|[17](ch5/5.17.cpp)|[18](ch5/5.18.md)|[19](ch5/5.19.cpp)|[20](ch5/5.20.cpp)|
[21](ch5/5.21.cpp)|[22](ch5/5.22.md)|[23](ch5/5.23.cpp)|[24](ch5/5.24.cpp)|[25](ch5/5.25.cpp)

<!---
#### Chapter 6 [](ch6)
#### Chapter 6 [Functions](ch6)

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
--:|--:|--:|--:|--:|--:|--:|--:|--:|--:
[1](ch6/6.1.cpp)|[2](ch6/6.2.cpp)|[3](ch6/6.3.cpp)|[4](ch6/6.4.cpp)|[5](ch6/6.5.cpp)|[6](ch6/6.6.cpp)|[7](ch6/6.7.cpp)|[8](ch6/6.8.cpp)|[9](ch6/6.9.cpp)|[10](ch6/6.10.cpp)|
[11](ch6/6.11.cpp)|[12](ch6/6.12.cpp)|[13](ch6/6.13.cpp)|[14](ch6/6.14.cpp)|[15](ch6/6.15.cpp)|[16](ch6/6.16.cpp)|[17](ch6/6.17.cpp)|[18](ch6/6.18.cpp)|[19](ch6/6.19.cpp)|[20](ch6/6.20.cpp)|
[21](ch6/6.21.cpp)|[22](ch6/6.22.cpp)|[23](ch6/6.23.cpp)|[24](ch6/6.24.cpp)|[25](ch6/6.25.cpp)|[26](ch6/6.26.cpp)|[27](ch6/6.27.cpp)|[28](ch6/6.28.cpp)|[29](ch6/6.29.cpp)|[30](ch6/6.30.cpp)|
[31](ch6/6.31.cpp)|[32](ch6/6.32.cpp)|[33](ch6/6.33.cpp)|[34](ch6/6.34.cpp)|[35](ch6/6.35.cpp)|[36](ch6/6.36.cpp)|[37](ch6/6.37.cpp)|[38](ch6/6.38.cpp)|[39](ch6/6.39.cpp)|[40](ch6/6.40.cpp)|
[41](ch6/6.41.cpp)|[42](ch6/6.42.cpp)|[43](ch6/6.43.cpp)|[44](ch6/6.44.cpp)|[45](ch6/6.45.cpp)|[46](ch6/6.46.cpp)|[47](ch6/6.47.cpp)|[48](ch6/6.48.cpp)|[49](ch6/6.49.cpp)|[50](ch6/6.50.cpp)|
[51](ch6/6.51.cpp)|[52](ch6/6.52.cpp)|[53](ch6/6.53.cpp)|[54](ch6/6.54.cpp)|[55](ch6/6.55.cpp)|[56](ch6/6.56.cpp)
[1](ch6/6.1.md)|[2](ch6/6.2.md)|[3](ch6/6.3.cpp)|[4](ch6/6.4.cpp)|[5](ch6/6.5.cpp)|[6](ch6/6.6.md)|[7](ch6/6.7.cpp)|[8](ch6/6.8/Chapter6.h)|[9](ch6/6.9)|[10](ch6/6.10.cpp)|
[11](ch6/6.11.cpp)|[12](ch6/6.12.cpp)|[13](ch6/6.13.md)|[14](ch6/6.14.md)|[15](ch6/6.15.md)|[16](ch6/6.16.md)|[17](ch6/6.17.cpp)|[18](ch6/6.18.md)|[19](ch6/6.19.md)|[20](ch6/6.20.md)|
[21](ch6/6.21.cpp)|[22](ch6/6.22.cpp)|[23](ch6/6.23.cpp)|[24](ch6/6.24.md)|[25](ch6/6.25.cpp)|[26](ch6/6.26.cpp)|[27](ch6/6.27.cpp)|[28](ch6/6.28.md)|[29](ch6/6.29.md)|[30](ch6/6.30.cpp)|
[31](ch6/6.31.md)|[32](ch6/6.32.cpp)|[33](ch6/6.33.cpp)|[34](ch6/6.34.md)|[35](ch6/6.35.md)|[36](ch6/6.36.cpp)|[37](ch6/6.37.cpp)|[38](ch6/6.38.cpp)|[39](ch6/6.39.md)|[40](ch6/6.40.md)|
[41](ch6/6.41.md)|[42](ch6/6.42.cpp)|[43](ch6/6.43.md)|[44](ch6/6.44.cpp)|[45](ch6/6.45.cpp)|[46](ch6/6.46.md)|[47](ch6/6.47.cpp)|[48](ch6/6.48.md)|[49](ch6/6.49.md)|[50](ch6/6.50.md)|
[51](ch6/6.51.cpp)|[52](ch6/6.52.md)|[53](ch6/6.53.md)|[54](ch6/6.54.cpp)|[55](ch6/6.55.cpp)|[56](ch6/6.56.md)

<!---
#### Chapter 7 [](ch7)
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10
Expand Down
3 changes: 3 additions & 0 deletions ch6/6.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
A **parameter** is the variable in the parentheses after the function name when we defining the function and used inside a function.

An **argument** is the variable in the parentheses after the function name when we calling the function, and it is used to initialize the parameter of the function.
16 changes: 16 additions & 0 deletions ch6/6.10.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <iostream>

void swapInt(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}

int main() {
int a, b;
std::cin >> a >> b;
swapInt(&a, &b);
std::cout << a << " " << b << std::endl;

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

void resetInt(int &i) {
i = 0;
}

int main() {
int a;
std::cin >> a;
std::cout << "before reset: " << a << std::endl;
resetInt(a);
std::cout << "after reset: " << a << std::endl;

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

void swapInt(int &a, int &b) {
int tmp = a;
a = b;
b = tmp;
}

int main() {
int a, b;
std::cin >> a >> b;
swapInt(a, b);
std::cout << a << " " << b << std::endl;

// The reference version looks like easier to use, but the user must know
// from other source that the function will change the value of the argument.

return 0;
}
3 changes: 3 additions & 0 deletions ch6/6.13.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
`void f(T)` will pass the argument by value, which means in the function `f`, a copy of `T` will be made.

`void f(T&)` will pass the argument by reference, which means in the function `f`, the same variable defined in the caller is used.
21 changes: 21 additions & 0 deletions ch6/6.14.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Reference parameters
- Functions must use reference parameters to operate on objects of a type that cannot be copied.
- Functions prefer to use reference parameters to operate on objects of large class types or large containers.
- Functions should use reference parameters to return additional information via the reference parameters.

void printStr(std::ostream &os, const std::string &str, bool &stat) {
if (os << str)
stat = true;
else
stat = false;
}

Nonreference parameters
- Functions should use nonreference parameters when the value of the parameters may changed but should not affect the objects passed to the function.

int sum(int n) {
int sum = 0;
while (n > 0)
sum += n--;
return sum;
}
13 changes: 13 additions & 0 deletions ch6/6.15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
The function prototype is

string::size_type find_char(const string &s,
char c,
string::size_type &occurs)

`s` and `occurs` are both referecnes to avoid copy.

`s` is `const` because it isn't changed inside function and a string literal can be used here. `occurs` is plain reference beacuse it is used to pass information (changed inside function).

`c` is nonreference because copy a `char` is very cheap. It's fine to make it a `const` reference but not plain reference, because we don't want to accidentally change `c` inside function, and we may want to pass a `char` literal to the function.

If `occurs` is made a reference to `const`, then we cannot get how many times the character `c` occurred in string `s`.
1 change: 1 addition & 0 deletions ch6/6.16.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The parameter of the function should be `const string &s`. So that we can pass string literals or const strings to the function.
29 changes: 29 additions & 0 deletions ch6/6.17.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <string>
#include <iostream>

bool hasCapital(const std::string &s) { // Only ASCII
for (auto &c : s) // `c` would be `const char &` since `s` is `const`
if (c >= 'A' && c <= 'Z')
return true;
return false;
}

void toLowerStr(std::string &s) { // Only ASCII
for (auto &c : s)
if (c >= 'A' && c <= 'Z')
c -= 'A' - 'a';
}

// The parameters have different type, because in `hasCapital`, we don't need
// to change the string, but in `toLowerStr`, we need to change the string.

int main() {
std::string str("Hello World!");
std::cout << hasCapital("Abc") << " " << hasCapital("abc") << " "
<< hasCapital(str) << std::endl;
std::cout << str << std::endl;
toLowerStr(str);
std::cout << str << std::endl;

return 0;
}
8 changes: 8 additions & 0 deletions ch6/6.18.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
(a)

bool compare(const matrix &, const matrix &);

(b)

vector<int>::iterator &change_val(int, vector<int>::iterator &);

4 changes: 4 additions & 0 deletions ch6/6.19.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
(a) Illegal. Only one parameter is needed for the function.
(b) Legal.
(c) Legal.
(d) Legal.
25 changes: 25 additions & 0 deletions ch6/6.2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
(a)

//int f() { // Return type doesn't match
string f() {
string s;
// ...
return s;
}

(b)

//f2(int i) { /* ... */ } // Must have a return type
void f2(int i) { /* ... */ }

(c)

//int calc(int v1, int v1) /* ... */ } // Forget begin brace `{`
int calc(int v1, int v1) { /* ... */ }

(d)

//double square(double x) return x * x; // The function body should be a block.
double square(double x) { return x * x; }


7 changes: 7 additions & 0 deletions ch6/6.20.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
If the reference parameters will not be changed inside function, then they should be reference to `const`.

If we make a parameter a plain reference, then we can not pass
- a `const` object,
- or a literal,
- or an object that requires conversion
to a plain reference parameter.
3 changes: 3 additions & 0 deletions ch6/6.21.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
int largerInt(int a, int *pb) {
return a > *pb ? a : *pb;
}
28 changes: 28 additions & 0 deletions ch6/6.22.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include <iostream>

void swapIntPtr(int **pa, int **pb) {
int *tmp = *pa;
*pa = *pb;
*pb = tmp;
}

void swapIntPtr(int *&pa, int *&pb) {
int *tmp = pa;
pa = pb;
pb = tmp;
}

int main() {
int i = 1, j = 2;
int *pi = &i, *pj = &j;
std::cout << "pi = " << pi << " *pi = " << *pi << std::endl;
std::cout << "pj = " << pj << " *pj = " << *pj << std::endl;
swapIntPtr(&pi, &pj);
std::cout << "pi = " << pi << " *pi = " << *pi << std::endl;
std::cout << "pj = " << pj << " *pj = " << *pj << std::endl;
swapIntPtr(pi, pj);
std::cout << "pi = " << pi << " *pi = " << *pi << std::endl;
std::cout << "pj = " << pj << " *pj = " << *pj << std::endl;

return 0;
}
43 changes: 43 additions & 0 deletions ch6/6.23.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <iostream>
#include <iterator>

//void print(const int arr[]) {
// std::cout << "void print(const int arr[])" << std::endl;
// // Cannot get the size of arr, unless by a marker in the array
//}

void print(int i) {
std::cout << "void print(int i)" << std::endl;
std::cout << i << std::endl;
}

void print(const int *bg, const int *ed) {
std::cout << "void print(const int *bg, const int *ed)" << std::endl;
while (bg != ed)
std::cout << *bg++ << std::endl;
}

void print(const int arr[], size_t sz) {
std::cout << "void print(const int arr[], size_t sz)" << std::endl;
for (size_t i = 0; i != sz; ++i)
std::cout << arr[i] << std::endl;
}

void print(const int (&arr)[2]) {
std::cout << "void print(const int (&arr)[2])" << std::endl;
for (auto & e : arr)
std::cout << e << std::endl;
}

int main() {
int i = 0, j[2] = {0, 1};
std::cout << "i:" << std::endl;
print(i);
print(10);
std::cout << "j:" << std::endl;
print(std::begin(j), std::end(j));
print(j, std::end(j) - std::begin(j));
print(j);

return 0;
}
4 changes: 4 additions & 0 deletions ch6/6.24.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The function prototype is the same as `void print(const int *ia)`, which means we can pass any pointer to int to the function, not only an array of ten `int`s. This will lead to an error. We can change the parameter to a reference to array:

void print(const int (&ia)[10]) { /* ... */ }

16 changes: 16 additions & 0 deletions ch6/6.25.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <iostream>
#include <string>

int main(int argc, char *argv[]) {
std::cout << "All " << argc << " argument"
<< (argc > 1 ? "s are:" : " is:") << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << i << "\t" << argv[i] << std::endl;
if (argc < 3) // programname argument1 argument2 0
return -1;
std::string args(argv[1]);
args += argv[2];
std::cout << args << std::endl;

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

int main(int argc, char *argv[]) {
std::cout << "All " << argc << " argument"
<< (argc > 1 ? "s are:" : " is:") << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << i << "\t" << argv[i] << std::endl;

return 0;
}
16 changes: 16 additions & 0 deletions ch6/6.27.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <initializer_list>
#include <iostream>

int sumIntList(std::initializer_list<int> il) {
int sum = 0;
// `il.begin()` or `il.end()` will return `const int *`
for (auto &e : il) // `e` is `const int &`, since element in `il` are `const int`
sum += e;
return sum;
}

int main() {
std::cout << sumIntList({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) << std::endl;

return 0;
}
1 change: 1 addition & 0 deletions ch6/6.28.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The type of `elem` is `const string &`.
1 change: 1 addition & 0 deletions ch6/6.29.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Yes, I would use a reference as the loop control variable. So that we don't need to copy the value from the `initializer_list`.
17 changes: 17 additions & 0 deletions ch6/6.3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#include <iostream>

int fact(int n) { // Ignore overflow
if (n < 1) return n;
int k = n;
while (--n)
k *= n;
return k;
}

int main() {
int n;
std::cin >> n;
std::cout << n << "! = " << fact(n) << std::endl;

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

bool str_subrange(const string &str1, const string &str2) {
if (str1.size() == str2.size())
return str1 == str2;
auto size = (str1.size() < str2.size()) ? str1.size() : str2.size();
for (decltype(size) i = 0; i != size; ++i) {
if (str1[i] != str2[i])
//return; // Error: need a return value
return false;
}
// Error: need a return statement
return true;
}

int main() {
string s1, s2;
std::cin >> s1 >> s2;
std::cout << str_subrange(s1, s2) << std::endl;

return 0;
}
3 changes: 3 additions & 0 deletions ch6/6.31.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
When the object is not a local object, then that's fine to return a reference to it.

When we don't want the reference returned from a function to be an lvalue, we should use a reference to `const` as the return type instead.
Loading

0 comments on commit caf2897

Please sign in to comment.