├── .gitignore ├── Chapter 00 ├── README.md ├── q00.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q06.cpp ├── q08.cpp ├── q09.cpp └── q10.cpp ├── Chapter 01 ├── README.md └── q05.cpp ├── Chapter 02 ├── README.md ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q07.cpp ├── q08.cpp └── q09.cpp ├── Chapter 03 ├── README.md ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp └── q06.cpp ├── Chapter 04 ├── README.md ├── Student_info.cpp ├── Student_info.h ├── grade.cpp ├── grade.h ├── median.cpp ├── median.h ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05-1.cpp ├── q05-2.cpp ├── q06.cpp ├── q07.cpp ├── read_words.cpp └── read_words.h ├── Chapter 05 ├── 10.txt ├── 1000.txt ├── 10000.txt ├── README.md ├── Rotation.cpp ├── Rotation.h ├── frame.cpp ├── frame.h ├── q01.cpp ├── q02-1.cpp ├── q02-2.cpp ├── q03.cpp ├── q05.cpp ├── q06.cpp ├── q07.cpp ├── q08.cpp ├── q09.cpp ├── q10.cpp ├── q11.cpp ├── split.cpp └── split.h ├── Chapter 06 ├── README.md ├── Student_info.cpp ├── Student_info.h ├── analysis.cpp ├── analysis.h ├── find_urls.cpp ├── find_urls.h ├── grade.cpp ├── grade.h ├── median.cpp ├── median.h ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q06.cpp ├── q07.cpp ├── q08.cpp └── q09.cpp ├── Chapter 07 ├── README.md ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q06.cpp ├── q07.cpp ├── q08.cpp └── q09.cpp ├── Chapter 08 ├── README.md ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05-1.cpp └── q05-2.cpp ├── Chapter 09 ├── README.md ├── Student_info.cpp ├── Student_info.h ├── Student_info_ex.cpp ├── Student_info_ex.h ├── Student_info_pf.cpp ├── Student_info_pf.h ├── q01.cpp ├── q03-1.cpp ├── q03-2.cpp ├── q04.cpp ├── q05.cpp └── q06.cpp ├── Chapter 10 ├── README.md ├── String_list.cpp ├── String_list.h ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q06.cpp ├── split.cpp └── split.h ├── Chapter 11 ├── Lis.h ├── README.md ├── Student_info.cpp ├── Student_info.h ├── Student_info_ex_vec.cpp ├── Student_info_ex_vec.h ├── Student_info_pf_vec.cpp ├── Student_info_pf_vec.h ├── Student_info_vec.cpp ├── Student_info_vec.h ├── Vec.h ├── grade.cpp ├── grade.h ├── median.cpp ├── median.h ├── q05-1.cpp ├── q05-2.cpp ├── q05-3.cpp ├── q05-4.cpp ├── q07-1.cpp ├── q07-2.cpp ├── q07-3.cpp ├── q07-4.cpp ├── q07-5.cpp ├── q07-6.cpp ├── q07-7.cpp ├── q08.cpp └── q09.cpp ├── Chapter 12 ├── README.md ├── Str.cpp ├── Str.h ├── Str_Vec.cpp ├── Str_Vec.h ├── Vec.h ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q06.cpp ├── q07.cpp ├── q08.cpp ├── q09.cpp ├── q10.cpp ├── q11.cpp ├── q12.cpp ├── q13.cpp ├── q14.cpp └── q15.cpp ├── Chapter 13 ├── README.md ├── Student_info.cpp ├── Student_info.h ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp ├── q08.cpp └── student_list.txt ├── Chapter 14 ├── Ptr.h ├── Ptr_Ctr.h ├── README.md ├── Str.cpp ├── Str.h ├── Str_Ctr.cpp ├── Str_Ctr.h ├── Student_info.cpp ├── Student_info.h ├── compare_Core_ptrs.cpp ├── compare_Core_ptrs.h ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q05.cpp └── q06.cpp ├── Chapter 15 ├── Pic.cpp ├── Pic.h ├── Pic_Re.cpp ├── Pic_Re.h ├── README.md ├── q01.cpp ├── q02.cpp ├── q03.cpp ├── q04.cpp ├── q05.cpp └── q06.cpp ├── Chapter 16 ├── README.md └── q01.cpp ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # VSCode 35 | .vscode/* 36 | .vscode/settings.json 37 | .vscode/tasks.json 38 | .vscode/launch.json 39 | .vscode/extensions.json 40 | *.code-workspace 41 | 42 | # Local History for Visual Studio Code 43 | .history/ 44 | .vscode/tasks.json 45 | .vscode/launch.json -------------------------------------------------------------------------------- /Chapter 00/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile and run the `Hello, world!` program. 4 | 5 | The code can be found on [q00.cpp](./q00.cpp). You have to build it using a compiler you are using (for example g++). After you have built the program, run the output file (Double click the .exe file if you are using Windows). 6 | 7 | ### Q1: What does the following statement do? 8 | ``` 9 | 3 + 4; 10 | ``` 11 | This statement yields an int with a value of 7. Note that this value is not saved anywhere. 12 | 13 | ### Q2: Write a program that, when run, writes 14 | ``` 15 | This (") is a quote, and this (\) is a backslash. 16 | ``` 17 | The solution can be found in [q02.cpp](./q02.cpp). The trick here is using escape characters such as **\\"** and **\\\\** to print characters that might otherwise break the string. 18 | 19 | ### Q3: The string literal "`\t`" represents a tab character; different C++ implementations display tabs in different ways. Experiment with your implementation to learn how it treats tabs. 20 | A sample program for this question can be found in [q03.cpp](./q03.cpp). It seems g++ uses 8 spaces for a tab. You will see that the output has 7 spaces between the parentheses, as the closing parenthesis is put on the 8th space. 21 | 22 | ### Q4: Write a program that, when run, writes the `Hello, world!` program as its output. 23 | The solution can be found in [q04.cpp](./q04.cpp). Four spaces are used instead of tabs to make the output similar to the original code written in VSCode. 24 | 25 | ### Q5: Is this a valid program? Why or why not? 26 | ``` 27 | #include 28 | int main() std::cout << "Hello, world!" << std::endl; 29 | ``` 30 | This is not a valid program as the curly braces which should be present after the main function are missing. We get a compile-time error regarding this issue. 31 | 32 | ### Q6: Is this a valid program? Why or why not? 33 | ``` 34 | #include 35 | 36 | int main() {{{{{{ std::cout << "Hello, world!" << std::endl; }}}}}} 37 | ``` 38 | This is a valid program, as the curly brackets can be stacked indefinitely. One pair of curly brackets was enough but more can be used for other matters such as limiting the scope of a variable. The unnecessary brackets were probably ignored by the compiler. The code is present in [q06.cpp](./q06.cpp) to experiment. 39 | 40 | ### Q7: What about this one? 41 | ``` 42 | #include 43 | 44 | int main() 45 | { 46 | /* This is a comment that extends over several lines 47 | because it use /* and */ as its starting and ending delimiters */ 48 | std::cout << "Does this work?" << std::endl; 49 | return 0; 50 | } 51 | ``` 52 | This is not a valid program, as the first ***/** in the comment closes the multi-line comment. The words after that remain outside the comment block, causing errors. 53 | 54 | ### Q8: ...and this one? 55 | ``` 56 | #include 57 | 58 | int main() 59 | { 60 | // This is a comment that extends over several lines 61 | // by using // at the beginning of each line instead of using /* 62 | // or */ to delimit comments. 63 | std::cout << "Does this work?" << std::endl; 64 | return 0; 65 | } 66 | ``` 67 | This is a valid program. The code can be found in [q08.cpp](./q08.cpp) to experiment. 68 | 69 | ### Q9: What is the shortest valid program? 70 | The shortest valid program is `main(){}`. The code is in [q09.cpp](./q09.cpp) to experiment. 71 | 72 | ### Q10: Rewrite the `Hello, world!` program so that a newline occurs everywhere that whitespace is allowed in the program. 73 | The program can be found in [q10.cpp](./q10.cpp). -------------------------------------------------------------------------------- /Chapter 00/q00.cpp: -------------------------------------------------------------------------------- 1 | // code is taken from §0/1 2 | 3 | // a small C++ program 4 | #include 5 | 6 | int main() 7 | { 8 | std::cout << "Hello, world!" << std::endl; 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Chapter 00/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "This (\") is a quote, and this (\\) is a backslash." << std::endl; 6 | return 0; 7 | } -------------------------------------------------------------------------------- /Chapter 00/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "A single tab is (\t)." << std::endl; 6 | return 0; 7 | } -------------------------------------------------------------------------------- /Chapter 00/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "// a small C++ program" << std::endl 6 | << "#include " << std::endl << std::endl 7 | << "int main()" << std::endl << "{" << std::endl 8 | << " std::cout << \"Hello, world!\" << std::endl;" 9 | << std::endl << " return 0;" << std::endl << "}"; 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter 00/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main() {{{{{{ std::cout << "Hello, world!" << std::endl; }}}}}} -------------------------------------------------------------------------------- /Chapter 00/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main() 3 | { 4 | // This is a comment that extends over several lines 5 | // by using // at the beginning of each line instead of using /* 6 | // or */ to delimit comments. 7 | std::cout << "Does this work?" << std::endl; 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Chapter 00/q09.cpp: -------------------------------------------------------------------------------- 1 | main(){} -------------------------------------------------------------------------------- /Chapter 00/q10.cpp: -------------------------------------------------------------------------------- 1 | // a small C++ program 2 | #include 3 | int 4 | main 5 | ( 6 | ) 7 | { 8 | std 9 | :: 10 | cout 11 | << 12 | "Hello, world!" 13 | << 14 | std 15 | :: 16 | endl 17 | ; 18 | return 19 | 0 20 | ; 21 | } -------------------------------------------------------------------------------- /Chapter 01/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | { std::string s = "a string"; 7 | std::string x = s + ", really"; 8 | std::cout << s << std::endl; 9 | std::cout << x << std::endl; } 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter 02/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // say what standard-library names we use 5 | using std::cin; using std::endl; 6 | using std::cout; using std::string; 7 | 8 | int main() 9 | { 10 | // ask for the person's name 11 | cout << "Please enter your first name: "; 12 | 13 | // read the name 14 | string name; 15 | cin >> name; 16 | 17 | // build the message that we intend to write 18 | const string greeting = "Hello, " + name + "!"; 19 | 20 | // the number of blanks surrounding the greeting 21 | const int pad = 0; 22 | 23 | // the number of rows and columns to write 24 | const int rows = pad * 2 + 3; 25 | const string::size_type cols = greeting.size() + pad * 2 + 2; 26 | 27 | // write a blank line to separate the output from the input 28 | cout << endl; 29 | 30 | // write rows rows of output 31 | // invariant: we have written r rows so far 32 | for (int r = 0; r != rows; ++r) { 33 | 34 | string::size_type c = 0; 35 | 36 | // invariant: we have written c characters so far in the current row 37 | while (c != cols) { 38 | 39 | // is it time to write the greeting? 40 | if (r == pad + 1 && c == pad + 1) { 41 | cout << greeting; 42 | c += greeting.size(); 43 | } else { 44 | 45 | // are we on the border? 46 | if (r == 0 || r == rows - 1 || 47 | c == 0 || c == cols - 1) 48 | cout << "*"; 49 | else 50 | cout << " "; 51 | ++c; 52 | } 53 | } 54 | cout << endl; 55 | } 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Chapter 02/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // say what standard-library names we use 5 | using std::cin; using std::endl; 6 | using std::cout; using std::string; 7 | 8 | int main() 9 | { 10 | // ask for the person's name 11 | cout << "Please enter your first name: "; 12 | 13 | // read the name 14 | string name; 15 | cin >> name; 16 | 17 | // build the message that we intend to write 18 | const string greeting = "Hello, " + name + "!"; 19 | 20 | // the number of blanks surrounding the greeting 21 | const int pad_vertical = 1; 22 | const int pad_horizontal = 2; 23 | 24 | // the number of rows and columns to write 25 | const int rows = pad_vertical * 2 + 3; 26 | const string::size_type cols = greeting.size() + pad_horizontal * 2 + 2; 27 | 28 | // write a blank line to separate the output from the input 29 | cout << endl; 30 | 31 | // write rows rows of output 32 | // invariant: we have written r rows so far 33 | for (int r = 0; r != rows; ++r) { 34 | 35 | string::size_type c = 0; 36 | 37 | // invariant: we have written c characters so far in the current row 38 | while (c != cols) { 39 | 40 | // is it time to write the greeting? 41 | if (r == pad_vertical + 1 && c == pad_horizontal + 1) { 42 | cout << greeting; 43 | c += greeting.size(); 44 | } else { 45 | 46 | // are we on the border? 47 | if (r == 0 || r == rows - 1 || 48 | c == 0 || c == cols - 1) 49 | cout << "*"; 50 | else 51 | cout << " "; 52 | ++c; 53 | } 54 | } 55 | cout << endl; 56 | } 57 | return 0; 58 | } -------------------------------------------------------------------------------- /Chapter 02/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // say what standard-library names we use 5 | using std::cin; using std::endl; 6 | using std::cout; using std::string; 7 | 8 | int main() 9 | { 10 | // ask for the person's name 11 | cout << "Please enter your first name: "; 12 | 13 | // read the name 14 | string name; 15 | cin >> name; 16 | 17 | // build the message that we intend to write 18 | const string greeting = "Hello, " + name + "!"; 19 | 20 | // the number of blanks surrounding the greeting 21 | int pad; 22 | cout << endl << "Please enter the amount of spacing between the frame and the greeting: "; 23 | cin >> pad; 24 | 25 | // the number of rows and columns to write 26 | const int rows = pad * 2 + 3; 27 | const string::size_type cols = greeting.size() + pad * 2 + 2; 28 | 29 | // write a blank line to separate the output from the input 30 | cout << endl; 31 | 32 | // write rows rows of output 33 | // invariant: we have written r rows so far 34 | for (int r = 0; r != rows; ++r) { 35 | 36 | string::size_type c = 0; 37 | 38 | // invariant: we have written c characters so far in the current row 39 | while (c != cols) { 40 | 41 | // is it time to write the greeting? 42 | if (r == pad + 1 && c == pad + 1) { 43 | cout << greeting; 44 | c += greeting.size(); 45 | } else { 46 | 47 | // are we on the border? 48 | if (r == 0 || r == rows - 1 || 49 | c == 0 || c == cols - 1) 50 | cout << "*"; 51 | else 52 | cout << " "; 53 | ++c; 54 | } 55 | } 56 | cout << endl; 57 | } 58 | return 0; 59 | } -------------------------------------------------------------------------------- /Chapter 02/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // say what standard-library names we use 5 | using std::cin; using std::endl; 6 | using std::cout; using std::string; 7 | 8 | int main() 9 | { 10 | // ask for the person's name 11 | cout << "Please enter your first name: "; 12 | 13 | // read the name 14 | string name; 15 | cin >> name; 16 | 17 | // build the message that we intend to write 18 | const string greeting = "Hello, " + name + "!"; 19 | 20 | // the number of blanks surrounding the greeting 21 | const int pad = 1; 22 | 23 | // the number of rows and columns to write 24 | const int rows = pad * 2 + 3; 25 | const string::size_type cols = greeting.size() + pad * 2 + 2; 26 | 27 | // write a blank line to separate the output from the input 28 | cout << endl; 29 | 30 | // write rows rows of output 31 | // invariant: we have written r rows so far 32 | for (int r = 0; r != rows; ++r) { 33 | 34 | string::size_type c = 0; 35 | 36 | // invariant: we have written c characters so far in the current row 37 | while (c != cols) { 38 | 39 | // is it time to write the greeting? 40 | if (r == pad + 1 && c == pad + 1) { 41 | cout << greeting; 42 | c += greeting.size(); 43 | } else { 44 | 45 | // are we on the border? 46 | if (r == 0 || r == rows - 1 || 47 | c == 0 || c == cols - 1) { 48 | cout << "*"; 49 | ++c; 50 | } else if (r == pad + 1) { 51 | cout << string(pad, ' '); 52 | c += pad; 53 | } 54 | else { 55 | cout << string(cols - 2, ' '); 56 | c += cols - 2; 57 | } 58 | } 59 | } 60 | cout << endl; 61 | } 62 | return 0; 63 | } -------------------------------------------------------------------------------- /Chapter 02/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::cin; 6 | using std::endl; 7 | using std::string; 8 | 9 | int main() 10 | { 11 | int square_length = 3; 12 | // invariant: we have written r rows so far 13 | for (int r = 0; r < square_length; r++) 14 | cout << string(square_length, '*') << endl; 15 | 16 | cout << endl; 17 | 18 | int rectangle_width = 4; 19 | int rectangle_height = 3; 20 | // invariant: we have written r rows so far 21 | for (int r = 0; r < rectangle_height; r++) 22 | cout << string(rectangle_width, '*') << endl; 23 | 24 | cout << endl; 25 | 26 | int triangle_height = 3; 27 | // invariant: we have written r rows so far 28 | for (int r = 0; r < triangle_height; r++) { 29 | int length = r * 2 + 1; 30 | int spaces = (triangle_height * 2 - 1 - length) / 2; 31 | cout << string(spaces, ' '); 32 | cout << string(length, '*'); 33 | cout << string(spaces, ' ') << endl; 34 | } 35 | 36 | return 0; 37 | } -------------------------------------------------------------------------------- /Chapter 02/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | // count down from 10 to -5. 6 | for (int i = 10; i > -6; --i) 7 | std::cout << i << std::endl; 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /Chapter 02/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int product = 1; 6 | // get the product of the numbers in the range [1, 10). 7 | for (int i = 1; i < 10; i++) 8 | product *= i; 9 | 10 | std::cout << product << std::endl; 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /Chapter 02/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | // program that asks the user to enter two numbers and 6 | // tells the user which number is larger than the other. 7 | int num1, num2; 8 | 9 | std::cout << "Enter number 1: "; 10 | std::cin >> num1; 11 | std::cout << "Enter number 2: "; 12 | std::cin >> num2; 13 | std::cout << "The larger number is: "; 14 | 15 | if (num1 > num2) 16 | std::cout << num1; 17 | else 18 | std::cout << num2; 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 03/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Suppose we wish to find the median of a collection of values. Assume that we have read some of the values so far, and that we have no idea how many values remain to be read. Prove that we cannot afford to discard any of the values that we have read. *Hint:* One proof strategy is to assume that we can discard a value, and then find values for the unread—and therefore unknown—part of our collection that would cause the median to be the value that we discarded. 7 | Let's say we have read the values 3, 4, and 7. It seems probable that we can discard the smallest or the largest value. Let's discard them. Now we have 4. Now, let's say we now read 1 and 2. Now we have 1, 2, and 4. It seems that the median should be 2, however, if we have not discarded any values, we would have 1, 2, 3, 4, and 7. The median would be 3, which we have discarded. That proves that we cannot afford to discard any value we have already read. 8 | 9 | ### Q2: Write a program to compute and print the quartiles (that is, the quarter of the numbers with the largest values, the next highest quarter, and so on) of a set of integers. 10 | The program can be found in [q02.cpp](./q02.cpp). It sorts the input numbers and prints each quartile. Note that if the number is not divisible by 4, the remainders are shared within the quartiles. 11 | 12 | ### Q3: Write a program to count how many times each distinct word appears in its input. 13 | The program can be found in [q03.cpp](./q03.cpp). It stores the input words and the number of appearances in separate `vector`s with the same indices for word and its respective count. 14 | 15 | ### Q4: Write a program to report the length of the longest and the shortest `string` in its input. 16 | The program can be found in [q04.cpp](./q04.cpp). It stores the lengths of the `string`s from the input into a `vector`, then sorts the `vector` to find the shortest and longest lengths. The shortest length is the first element, and the longest length is the last element of the vector. 17 | 18 | ### Q5: Write a program that will keep track of grades for several students at once. The program could keep two `vector`s in sync: The first should hold the students' names, and the second the final grades that can be computed as input is read. For now, you should assume a fixed number of homework grades. We'll see in §4.1.3/56 how to handle a variable number of grades intermixed with student names. 19 | The solution can be found in [q05.cpp](./q05.cpp). The program first reads the student's name, followed by final grade, midterm grade, and homework grades. It stores the student's name in a `vector`. Then, it calculates the student's final grade and stores it in another vector, with the same index as the student name `vector`. 20 | 21 | ### Q6: The average-grade computation in §3.1/36 might divide by zero if the student didn't enter any grades. Division by zero is undefined in C++, which means the implementation is permitted to do anything it likes. What does your C++ implementation do in this case? Rewrite the program so that its behavior does not depend on how the implementation treats division by zero. 22 | My implementation, g++, outputs nan when no homework grades are entered. In [q06.cpp](./q06.cpp), the program is rewritten so that it sets the homework grade as zero if no grade is entered. -------------------------------------------------------------------------------- /Chapter 03/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cout; 6 | using std::cin; 7 | using std::endl; 8 | using std::vector; 9 | using std::sort; 10 | 11 | int main() 12 | { 13 | vector numbers; 14 | int n; 15 | 16 | // ask for number input 17 | cout << "Please enter the numbers, followed by end-of-file." << endl; 18 | 19 | // invariant: numbers contains numbers read so far 20 | while (cin >> n) 21 | numbers.push_back(n); 22 | 23 | // sort the numbers 24 | sort(numbers.begin(), numbers.end()); 25 | 26 | // get the properties of the vector 27 | typedef vector::size_type vec_sz; 28 | vec_sz count = numbers.size(); 29 | int quartile_size = count / 4; 30 | int quartile_remainder = count % 4; 31 | 32 | // handle not enough numbers condition 33 | if (count < 4) { 34 | cout << "You must enter at least 4 numbers." << endl; 35 | return(1); 36 | } 37 | 38 | // print the quartiles 39 | for (vec_sz i = count; i-- > 0; ) { 40 | if (i == count - 1) 41 | cout << "First quartile: "; 42 | else if (i == 3 * quartile_size - 1 + quartile_remainder) 43 | cout << endl << "Second quartile: "; 44 | else if (i == 2 * quartile_size - 1 + (quartile_remainder > 1 ? 45 | quartile_remainder - 1 : 0)) 46 | cout << endl << "Third quartile: "; 47 | else if (i == quartile_size - 1 + (quartile_remainder == 3 ? 1 : 0)) 48 | cout << endl << "Fourth quartile: "; 49 | 50 | cout << numbers[i] << " "; 51 | } 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /Chapter 03/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::cin; 8 | using std::string; 9 | using std::vector; 10 | 11 | int main() 12 | { 13 | // ask for string input 14 | cout << "Enter a sentence, followed by end-of-file: " << endl; 15 | 16 | vector words; 17 | vector counts; 18 | typedef vector::size_type vec_sz; 19 | string word; 20 | vec_sz size; 21 | 22 | // read the sentence 23 | // invariant: words contains the words read so far 24 | while (cin >> word) { 25 | int found_index = -1; 26 | size = words.size(); 27 | // search the vector for word 28 | for (vec_sz i = 0; i < size; i++) 29 | if (words[i] == word) 30 | found_index = i; 31 | 32 | // if word exists, increment its count 33 | if (found_index > 0) 34 | ++counts[found_index]; 35 | else { 36 | words.push_back(word); 37 | counts.push_back(1); 38 | } 39 | } 40 | 41 | // write the results 42 | size = words.size(); 43 | for (vec_sz i = 0; i < size; ++i) 44 | cout << "Word: " << words[i] << ", Count: " << counts[i] << endl; 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /Chapter 03/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::cin; 9 | using std::string; 10 | using std::vector; 11 | using std::sort; 12 | 13 | int main() 14 | { 15 | // ask for string input 16 | cout << "Enter a sentence, followed by end-of-file: " << endl; 17 | 18 | typedef vector::size_type vec_sz; 19 | vector sizes; 20 | string word; 21 | 22 | // invariant: sizes contains the length of the words read so far 23 | while (cin >> word) 24 | sizes.push_back(word.size()); 25 | 26 | // sort the sizes vector 27 | sort(sizes.begin(), sizes.end()); 28 | 29 | // write the results 30 | cout << "Shortest length: " << sizes[0] << endl; 31 | cout << "Longest length: " << sizes[sizes.size() - 1] << endl; 32 | } -------------------------------------------------------------------------------- /Chapter 03/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::cin; 8 | using std::string; 9 | using std::vector; 10 | 11 | int main() 12 | { 13 | vector students; 14 | vector grades; 15 | string student; 16 | 17 | typedef vector::size_type vec_sz; 18 | 19 | // set homework amount 20 | const int hw_count = 3; 21 | 22 | // ask for user input 23 | cout << "Please enter student name, followed by midterm grade, " 24 | "final grade, and " << hw_count << " homework grades." 25 | " Send end-of-file to finish submitting." << endl; 26 | 27 | // invariant: 28 | // students contains student names read so far, and 29 | // grades contains the final grades of the students 30 | while (cin >> student) { 31 | students.push_back(student); 32 | double midterm, final; 33 | double hw_sum = 0.0; 34 | 35 | cin >> midterm >> final; 36 | 37 | for (int i = 0; i < hw_count; ++i) { 38 | double grade; 39 | cin >> grade; 40 | hw_sum += grade; 41 | }; 42 | 43 | grades.push_back(0.2 * midterm + 0.4 * final + 0.4 * hw_sum / hw_count); 44 | } 45 | 46 | // write the results 47 | for (vec_sz i = 0; i < students.size(); ++i) 48 | cout << "Student " << students[i] << "'s Final Grade: " << 49 | grades[i] << "." << endl; 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 03/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cin; using std::setprecision; 7 | using std::cout; using std::string; 8 | using std::endl; using std::streamsize; 9 | 10 | int main() 11 | { 12 | // ask for and read the student's name 13 | cout << "Please enter your first name: "; 14 | string name; 15 | cin >> name; 16 | cout << "Hello, " << name << "!" << endl; 17 | 18 | // ask for and read the midterm and final grades 19 | cout << "Please enter your midterm and final exam grades: "; 20 | double midterm, final; 21 | cin >> midterm >> final; 22 | 23 | // ask for the homework grades 24 | cout << "Enter all your homework grades, " 25 | "followed by end-of-file: "; 26 | 27 | // the number and sum of grades read so far 28 | int count = 0; 29 | double sum = 0; 30 | 31 | // a variable into which to read 32 | double x; 33 | 34 | // invariant: 35 | // we have read count grades so far, and 36 | // sum is the sum of the first count grades 37 | while (cin >> x) { 38 | ++count; 39 | sum += x; 40 | } 41 | 42 | // set homework variable, handling the division by zero condition 43 | double homework = count == 0 ? 0 : sum / count; 44 | 45 | // write the result 46 | streamsize prec = cout.precision(); 47 | cout << "Your final grade is " << setprecision(3) 48 | << 0.2 * midterm + 0.4 * final + 0.4 * homework 49 | << setprecision(prec) << endl; 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 04/Student_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "grade.h" 6 | #include "Student_info.h" 7 | 8 | using std::cout; 9 | using std::vector; 10 | using std::istream; 11 | using std::domain_error; 12 | using std::sort; 13 | 14 | // code is taken from §4.4/69 15 | bool compare(const Student_info& x, const Student_info& y) 16 | { 17 | return x.name < y.name; 18 | } 19 | 20 | istream& read(istream& is, Student_info& s) 21 | { 22 | double midterm, final; 23 | vector homework; 24 | // read and store the student's name and final grade 25 | is >> s.name >> midterm >> final; 26 | 27 | // handle end-of-file 28 | if (is) { 29 | read_hw(is, homework); 30 | // save only the final grade 31 | s.final_grade = grade(midterm, final, homework); 32 | } 33 | 34 | return is; 35 | } 36 | 37 | // code is taken from §4.1.3/57 38 | istream& read_hw(istream& in, vector& hw) 39 | { 40 | if (in) { 41 | // get rid of previous contetns 42 | hw.clear(); 43 | 44 | // read homework grades 45 | double x; 46 | while (in >> x) 47 | hw.push_back(x); 48 | 49 | // clear the stream so that input will work for the next student 50 | in.clear(); 51 | } 52 | return in; 53 | } -------------------------------------------------------------------------------- /Chapter 04/Student_info.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define Guard_Student_info 3 | 4 | #include 5 | #include 6 | 7 | struct Student_info { 8 | std::string name; 9 | double final_grade; 10 | }; 11 | 12 | bool compare(const Student_info&, const Student_info&); 13 | std::istream& read(std::istream&, Student_info&); 14 | std::istream& read_hw(std::istream&, std::vector&); 15 | #endif -------------------------------------------------------------------------------- /Chapter 04/grade.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "grade.h" 4 | #include "median.h" 5 | 6 | using std::domain_error; using std::vector; 7 | 8 | // code taken from §4.1/52 9 | // compute a student's overall grade from midterm and final exam grades and homework grade 10 | double grade(double midterm, double final, double homework) 11 | { 12 | return 0.2 * midterm + 0.4 * final + 0.4 * homework; 13 | } 14 | 15 | // code taken from §4.1.2/54 16 | // compute a student's overall grade from midterm and final exam grades 17 | // and vector of homework grades. 18 | // this function does not copy its argument, because median does so for us. 19 | double grade(double midterm, double final, const vector& hw) 20 | { 21 | if (hw.size() == 0) 22 | throw domain_error("student has done no homework"); 23 | return grade(midterm, final, median(hw)); 24 | } -------------------------------------------------------------------------------- /Chapter 04/grade.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_grade_h 2 | #define GUARD_grade_h 3 | 4 | #include 5 | 6 | double grade(double, double, double); 7 | double grade(double, double, const std::vector&); 8 | #endif -------------------------------------------------------------------------------- /Chapter 04/median.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "median.h" 5 | 6 | using std::domain_error; 7 | using std::vector; 8 | using std::sort; 9 | 10 | // code is taken from §4.1.1/53 11 | // compute the median of a vector 12 | // note that calling this function copies the entire argument vector 13 | double median(vector vec) 14 | { 15 | typedef vector::size_type vec_sz; 16 | 17 | vec_sz size = vec.size(); 18 | if (size == 0) 19 | throw domain_error("median of an empty vector"); 20 | 21 | sort(vec.begin(), vec.end()); 22 | 23 | vec_sz mid = size/2; 24 | 25 | return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid]; 26 | } 27 | -------------------------------------------------------------------------------- /Chapter 04/median.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_median_h 2 | #define GUARD_median_h 3 | 4 | #include 5 | 6 | double median(std::vector); 7 | #endif -------------------------------------------------------------------------------- /Chapter 04/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::setw; 7 | 8 | int main() 9 | { 10 | for (int i = 1; i <= 100; i++) 11 | cout << setw(3) << i << setw(6) << i * i << endl; 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter 04/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::setw; 7 | 8 | // function that returns the length of a number 9 | // when converted to a string 10 | int get_length(int number) 11 | { 12 | int length = 1; 13 | while (number / 10 > 0) { 14 | number /= 10; 15 | ++length; 16 | } 17 | 18 | return length; 19 | } 20 | 21 | int main() 22 | { 23 | const int max_number = 999; 24 | 25 | int max_len = get_length(max_number); 26 | int max_sq = get_length(max_number * max_number); 27 | 28 | for (int i = 1; i <= max_number; ++i) 29 | cout << setw(max_len) << i << setw(max_sq + 1) << i * i << endl; 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Chapter 04/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::setw; 7 | using std::streamsize; 8 | using std::setprecision; 9 | using std::fixed; 10 | 11 | // function that returns the length of a number 12 | // when converted to a string 13 | int get_length(double number, const streamsize& decimal_points) 14 | { 15 | int length = 1; 16 | while (number / 10 > 1.0) { 17 | number /= 10; 18 | ++length; 19 | } 20 | 21 | return length + decimal_points + 1; 22 | } 23 | 24 | int main() 25 | { 26 | const double max_number = 1000.0; 27 | const streamsize decimal_points = 2; 28 | 29 | int max_len = get_length(max_number, decimal_points); 30 | int max_sq = get_length(max_number * max_number, decimal_points); 31 | 32 | for (double i = 1.0; i < max_number; ++i) { 33 | streamsize prec = cout.precision(); 34 | cout << fixed << setprecision(decimal_points) << setw(max_len) << i 35 | << setw(max_sq + 1) << i * i << setprecision(prec) << endl; 36 | } 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /Chapter 04/q05-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "read_words.h" 5 | 6 | // program that counts the number of words in the input 7 | 8 | using std::cin; 9 | using std::cout; 10 | using std::endl; 11 | using std::vector; 12 | using std::string; 13 | 14 | int main() 15 | { 16 | vector words; 17 | vector::size_type count = 0; 18 | 19 | // ask for string input 20 | cout << "Enter a sentence, followed by end-of-file: " << endl; 21 | 22 | // using the created function 23 | read_words(cin, words); 24 | 25 | // write the result 26 | cout << "There are " << words.size() << " words in the input." << endl; 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter 04/q05-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "read_words.h" 6 | 7 | // program that counts how many times each word occured 8 | 9 | using std::cin; 10 | using std::cout; 11 | using std::endl; 12 | using std::vector; 13 | using std::string; 14 | using std::sort; 15 | 16 | typedef vector::size_type vec_sz; 17 | 18 | int main() 19 | { 20 | vector words; 21 | 22 | // ask for string input 23 | cout << "Enter a sentence, followed by end-of-file: " << endl; 24 | 25 | // using the created function 26 | read_words(cin, words); 27 | 28 | // sort the vector to group same words 29 | sort(words.begin(), words.end()); 30 | 31 | // write the results 32 | string word = words[0]; 33 | vec_sz count = 0; 34 | for (vec_sz i = 0; i < words.size(); ++i) 35 | if (word != words[i]) { 36 | cout << "Word " << word << " appeared " 37 | << ++count << " time" << (count > 1 ? "s." : ".") << endl; 38 | word = words[i]; 39 | count = 0; 40 | } else 41 | ++count; 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter 04/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "Student_info.h" 9 | 10 | using std::cin; using std::setprecision; 11 | using std::cout; using std::sort; 12 | using std::domain_error; using std::streamsize; 13 | using std::endl; using std::string; 14 | using std::max; using std::vector; 15 | 16 | int main() 17 | { 18 | vector students; 19 | Student_info record; 20 | string::size_type maxlen=0; // the length of the longest name 21 | 22 | // read and store all the students' data 23 | // invariant: students contains all the student records read so far 24 | // maxlen contains the length of the longest name in students 25 | while (read(cin, record)) { 26 | // find the length of longest name 27 | maxlen = max(maxlen, record.name.size()); 28 | students.push_back(record); 29 | } 30 | 31 | // alphabetize the student records 32 | sort(students.begin(), students.end(), compare); 33 | 34 | // write the names and grades 35 | for (vector::size_type i = 0; 36 | i != students.size(); ++i) { 37 | 38 | // write the name, padded on the right to maxlen + 1 characters 39 | cout << students[i].name 40 | << string(maxlen + 1 - students[i].name.size(), ' '); 41 | 42 | // write the grades 43 | try { 44 | streamsize prec = cout.precision(); 45 | cout << setprecision(3) << students[i].final_grade 46 | << setprecision(prec) << endl; 47 | } catch (domain_error e) { 48 | cout << e.what(); 49 | } 50 | cout << endl; 51 | } 52 | return 0; 53 | } -------------------------------------------------------------------------------- /Chapter 04/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::cin; 8 | using std::string; 9 | using std::vector; 10 | 11 | int main() 12 | { 13 | vector doubles; 14 | 15 | // ask the for double input 16 | cout << "Enter doubles, followed by end-of-file: " << endl; 17 | 18 | double d; 19 | while (cin >> d) 20 | doubles.push_back(d); 21 | 22 | // find the average of the numbers stored in the vector 23 | double total = 0; 24 | double count = doubles.size(); 25 | for (vector::size_type i = 0; i < count; ++i) 26 | total += doubles[i]; 27 | 28 | cout << "The average is: " << total / count << endl; 29 | } -------------------------------------------------------------------------------- /Chapter 04/read_words.cpp: -------------------------------------------------------------------------------- 1 | #include "read_words.h" 2 | 3 | using std::istream; 4 | using std::vector; 5 | using std::string; 6 | 7 | istream& read_words(istream& is, vector& words) 8 | { 9 | if (is) { 10 | string word; 11 | 12 | // clear the vector 13 | words.clear(); 14 | 15 | // read and store the words 16 | while (is >> word) 17 | words.push_back(word); 18 | 19 | // reset the error state 20 | is.clear(); 21 | } 22 | 23 | return is; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Chapter 04/read_words.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_read_words_h 2 | #define GUARD_read_words_h 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | std::istream& read_words(std::istream& is, std::vector& vec); 9 | #endif -------------------------------------------------------------------------------- /Chapter 05/10.txt: -------------------------------------------------------------------------------- 1 | YNEFQ 29 32 33 64 30 2 | SHZ 71 64 64 23 87 3 | JSU 20 86 50 38 62 4 | PLLVK 65 92 26 65 64 5 | XZC 24 92 40 59 33 6 | MMYDPWW 47 63 28 72 48 7 | YTBJWXM 54 58 24 22 38 8 | RTDKZL 97 45 61 60 28 9 | WAU 35 71 47 70 73 10 | QOPX 76 98 37 50 98 -------------------------------------------------------------------------------- /Chapter 05/Rotation.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Rotation 2 | #define GUARD_Rotation 3 | 4 | #include 5 | #include 6 | 7 | struct Rotation { 8 | std::vector words; 9 | std::vector::size_type start; 10 | }; 11 | 12 | std::vector get_rotations(const std::string&); 13 | std::vector sort_rotations(std::vector&); 14 | std::string format_rotation(Rotation&, std::string::size_type); 15 | std::string::size_type first_width(const Rotation&); 16 | std::string::size_type first_width(const std::vector&); 17 | bool compare(const Rotation&, const Rotation&); 18 | #endif -------------------------------------------------------------------------------- /Chapter 05/frame.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "frame.h" 4 | 5 | using std::vector; 6 | using std::string; 7 | using std::max; 8 | 9 | // code is taken from §5.8.1/92 10 | string::size_type width(const vector& v) 11 | { 12 | string::size_type maxlen = 0; 13 | for (vector::size_type i = 0; i != v.size(); ++i) 14 | maxlen = max(maxlen, v[i].size()); 15 | return maxlen; 16 | } 17 | 18 | // code is taken from §5.8.1/93 19 | vector frame(const vector& v) 20 | { 21 | vector ret; 22 | string::size_type maxlen = width(v); 23 | string border(maxlen + 4, '*'); 24 | 25 | // write the top border 26 | ret.push_back(border); 27 | 28 | // write each interior row, bordered by an asterisk and a space 29 | for (vector::size_type i = 0; i != v.size(); ++i) { 30 | ret.push_back("* " + v[i] + 31 | string(maxlen - v[i].size(), ' ') + " *"); 32 | } 33 | 34 | // write the bottom border 35 | ret.push_back(border); 36 | return ret; 37 | } -------------------------------------------------------------------------------- /Chapter 05/frame.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_frame_h 2 | #define GUARD_frame_h 3 | 4 | #include 5 | #include 6 | 7 | std::string::size_type width(const std::vector& v); 8 | std::vector frame(const std::vector& v); 9 | #endif -------------------------------------------------------------------------------- /Chapter 05/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "Rotation.h" 7 | 8 | using std::string; 9 | using std::cout; 10 | using std::cin; 11 | using std::endl; 12 | using std::vector; 13 | using std::list; 14 | using std::istream; 15 | using std::sort; 16 | 17 | // read every line in an input stream until end-of-file 18 | list read_each_line(istream& in) 19 | { 20 | list lines; 21 | string s; 22 | // read each line and add them to a vector 23 | while (getline(in, s)) 24 | lines.push_back(s); 25 | 26 | return lines; 27 | } 28 | 29 | int main() 30 | { 31 | // using list for optimization, as we will only 32 | // iterate over read lines 33 | list lines = read_each_line(cin); 34 | 35 | // Save the rotations for each vector 36 | vector rotations; 37 | 38 | // loop for each line 39 | for (list::const_iterator it = lines.begin(); 40 | it != lines.end(); ++it) { 41 | // save each line's rotations and concatenate them 42 | // to the rotations vector 43 | vector lr = get_rotations(*it); 44 | rotations.insert(rotations.end(), lr.begin(), lr.end()); 45 | } 46 | 47 | // sort and format the permutations 48 | sort(rotations.begin(), rotations.end(), compare); 49 | 50 | // write the results 51 | string::size_type max_width = first_width(rotations); 52 | for (vector::iterator it = rotations.begin(); 53 | it != rotations.end(); ++it) 54 | cout << format_rotation(*it, max_width) << endl; 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Chapter 05/q02-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // ctime is used for code runtime estimation 4 | #include 5 | // include the simplified version of Student_info 6 | #include "../Chapter 04/Student_info.h" 7 | 8 | using std::cin; 9 | using std::cout; 10 | using std::endl; 11 | using std::vector; 12 | 13 | vector extract_fails(vector& students) 14 | { 15 | vector fails; 16 | vector::iterator it = students.begin(); 17 | while (it != students.end()) { 18 | // we can access only the final grade from simplified version 19 | if (it->final_grade < 60) { 20 | fails.push_back(*it); 21 | it = students.erase(it); 22 | } else 23 | ++it; 24 | } 25 | 26 | return fails; 27 | } 28 | 29 | int main() 30 | { 31 | vector students; 32 | Student_info student; 33 | 34 | // read all student data 35 | while (read(cin, student)) 36 | students.push_back(student); 37 | 38 | // save the original size 39 | vector::size_type count = students.size(); 40 | 41 | double begin = clock(); 42 | vector fails = extract_fails(students); 43 | double end = clock(); 44 | 45 | cout << "Extracting fails for " << count << " students took " 46 | << (end - begin) / CLOCKS_PER_SEC << " seconds." << endl; 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Chapter 05/q02-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // ctime is used for code runtime estimation 4 | #include 5 | // include the simplified version of Student_info 6 | #include "../Chapter 04/Student_info.h" 7 | 8 | using std::cin; 9 | using std::cout; 10 | using std::endl; 11 | using std::list; 12 | 13 | list extract_fails(list& students) 14 | { 15 | list fails; 16 | list::iterator it = students.begin(); 17 | while (it != students.end()) { 18 | // we can access only the final grade from simplified version 19 | if (it->final_grade < 60) { 20 | fails.push_back(*it); 21 | it = students.erase(it); 22 | } else 23 | ++it; 24 | } 25 | 26 | return fails; 27 | } 28 | 29 | int main() 30 | { 31 | list students; 32 | Student_info student; 33 | 34 | // read all student data 35 | while (read(cin, student)) 36 | students.push_back(student); 37 | 38 | // save the original size 39 | list::size_type count = students.size(); 40 | 41 | double begin = clock(); 42 | list fails = extract_fails(students); 43 | double end = clock(); 44 | 45 | cout << "Extracting fails for " << count << " students took " 46 | << (end - begin) / CLOCKS_PER_SEC << " seconds." << endl; 47 | 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Chapter 05/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | // #include 4 | // ctime is used for code runtime estimation 5 | #include 6 | // include the simplified version of Student_info 7 | #include "../Chapter 04/Student_info.h" 8 | 9 | using std::cin; 10 | using std::cout; 11 | using std::endl; 12 | using std::clock_t; 13 | 14 | typedef std::vector student_container; 15 | // typedef std::list student_container; 16 | 17 | student_container extract_fails(student_container& students) 18 | { 19 | student_container fails; 20 | student_container::iterator it = students.begin(); 21 | while (it != students.end()) { 22 | // we can access only the final grade from simplified version 23 | if (it->final_grade < 60) { 24 | fails.push_back(*it); 25 | it = students.erase(it); 26 | } else 27 | ++it; 28 | } 29 | 30 | return fails; 31 | } 32 | 33 | int main() 34 | { 35 | student_container students; 36 | Student_info student; 37 | 38 | // read all student data 39 | while (read(cin, student)) 40 | students.push_back(student); 41 | 42 | // save the original size 43 | student_container::size_type count = students.size(); 44 | 45 | double begin = clock(); 46 | student_container fails = extract_fails(students); 47 | double end = clock(); 48 | 49 | cout << "Extracting fails for " << count << " students took " 50 | << (end - begin) / CLOCKS_PER_SEC << " seconds." << endl; 51 | 52 | return 0; 53 | } -------------------------------------------------------------------------------- /Chapter 05/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "split.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::string; 9 | using std::vector; 10 | 11 | typedef string::size_type str_sz; 12 | typedef vector::size_type vec_sz; 13 | 14 | vector center(const vector& picture) 15 | { 16 | vector centered_picture = picture; 17 | // the picture is assumed to be rectangular 18 | str_sz width = centered_picture[0].size() - 2; 19 | // iterate over the picture 20 | for (vector::iterator it = centered_picture.begin(); 21 | it != centered_picture.end(); ++it) 22 | // skip first and last lines 23 | if (it != centered_picture.begin() && it != centered_picture.end() - 1) { 24 | // remove * characters 25 | (*it)[0] = ' '; 26 | (*it)[width + 1] = ' '; 27 | vector words = split(*it); 28 | string unpadded_line = ""; 29 | // get each word to find the unpadded line 30 | for (vector::const_iterator jt = words.begin(); 31 | jt != words.end(); ++jt) { 32 | // add the word to unpadded line 33 | unpadded_line += *jt; 34 | // add one space if word is not the last one 35 | if (jt + 1 != words.end()) 36 | unpadded_line += " "; 37 | } 38 | // get the unpadded line width 39 | str_sz unpadded_line_width = unpadded_line.size(); 40 | // get the size of the paddings 41 | str_sz left_padding = (width - unpadded_line_width) / 2; 42 | str_sz right_padding = width - unpadded_line_width - left_padding; 43 | // set centered line 44 | *it = "*" + string(left_padding, ' ') + 45 | unpadded_line + string(right_padding, ' ') + "*"; 46 | } 47 | 48 | return centered_picture; 49 | } 50 | 51 | int main() 52 | { 53 | vector picture; 54 | // create a picture 55 | picture.push_back("*************"); 56 | picture.push_back("* hello *"); 57 | picture.push_back("* my name *"); 58 | picture.push_back("* is Altug! *"); 59 | picture.push_back("*************"); 60 | 61 | vector centered_picture = center(picture); 62 | 63 | // picture and centered_picture have the same size 64 | vec_sz size = picture.size(); 65 | for (vec_sz i = 0; i < size; ++i) { 66 | cout << picture[i] << " "; 67 | if (i == size / 2) 68 | cout << "=>"; 69 | else 70 | cout << " "; 71 | cout << " " << centered_picture[i] << endl; 72 | } 73 | 74 | return 0; 75 | } -------------------------------------------------------------------------------- /Chapter 05/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../Chapter 04/Student_info.h" 4 | // ctime is used for code runtime estimation 5 | #include 6 | 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | using std::vector; 11 | 12 | typedef vector::size_type vec_std_sz; 13 | 14 | // code is taken from §5.1.1/77, modified to fit the simplified 15 | // Student_info structure. 16 | vector extract_fails(vector& students) 17 | { 18 | vector fail; 19 | vec_std_sz i = 0; 20 | 21 | // invariant: elements [0, i) of students represent passing grades 22 | while (i != students.size()) { 23 | if (students[i].final_grade < 60) { 24 | fail.push_back(students[i]); 25 | students.erase(students.begin() + i); 26 | } else 27 | ++i; 28 | } 29 | return fail; 30 | } 31 | 32 | vector resizing_extract_fails(vector& students) 33 | { 34 | vector fail; 35 | vec_std_sz original_size = students.size(); 36 | 37 | for (vec_std_sz i = 0; i != students.size(); ++i) 38 | if (students[i].final_grade < 60) 39 | fail.push_back(students[i]); 40 | else 41 | students.insert(students.begin(), students[i++]); 42 | 43 | students.resize(original_size - fail.size()); 44 | return fail; 45 | } 46 | 47 | int main() 48 | { 49 | vector students; 50 | Student_info student; 51 | // read all student data 52 | while (read(cin, student)) 53 | students.push_back(student); 54 | 55 | // save the original size 56 | vec_std_sz count = students.size(); 57 | 58 | // create a copy to measure both functions 59 | vector students_copy(students); 60 | 61 | // measure time for the original function 62 | double begin = clock(); 63 | extract_fails(students); 64 | double time_original = clock() - begin; 65 | 66 | // measure time for the modified function 67 | begin = clock(); 68 | resizing_extract_fails(students_copy); 69 | double time_modified = clock() - begin; 70 | 71 | // write the results 72 | cout << "Original function took " << time_original / CLOCKS_PER_SEC 73 | << " seconds and the modified function took " << time_modified / 74 | CLOCKS_PER_SEC << " seconds for " << count << " students." << endl; 75 | 76 | return 0; 77 | } -------------------------------------------------------------------------------- /Chapter 05/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "frame.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | vector v; 14 | frame(v); 15 | 16 | // write the frame 17 | for (vector::const_iterator it = v.begin(); 18 | it != v.end(); ++it) 19 | cout << *it << endl; 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter 05/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::string; 7 | using std::max; 8 | using std::cout; 9 | using std::endl; 10 | 11 | // code taken from §5.8.1/92 12 | string::size_type width(const vector& v) 13 | { 14 | string::size_type maxlen = 0; 15 | for (vector::size_type i = 0; i != v.size(); ++i) 16 | maxlen = max(maxlen, v[i].size()); 17 | return maxlen; 18 | } 19 | 20 | // code taken from §5.8.3/95, modified to define s 21 | // outside the scope of the while 22 | vector hcat(const vector& left, const vector& right) 23 | { 24 | vector ret; 25 | 26 | // add 1 to leave a space between pictures 27 | string::size_type width1 = width(left) + 1; 28 | 29 | // indices to look at elements from left and right respectively 30 | vector::size_type i = 0, j = 0; 31 | 32 | // define s here 33 | string s; 34 | 35 | while (i != left.size() || j != right.size()) { 36 | // copy a row from the left-hand side, if there is one 37 | if (i != left.size()) 38 | s = left[i++]; 39 | 40 | // pad to full width 41 | s += string(width1 - s.size(), ' '); 42 | 43 | // copy a row from the right-hand side, if there is one 44 | if (j != right.size()) 45 | s += right[j++]; 46 | 47 | // add s to the picture we're creating 48 | ret.push_back(s); 49 | } 50 | return ret; 51 | } 52 | 53 | int main() 54 | { 55 | vector picture; 56 | // create a picture 57 | picture.push_back("*************"); 58 | picture.push_back("* hello *"); 59 | picture.push_back("* my name *"); 60 | picture.push_back("* is Altug! *"); 61 | picture.push_back("*************"); 62 | 63 | vector another_picture; 64 | // create another picture to horizontally concatenate 65 | picture.push_back("***************"); 66 | picture.push_back("* I am *"); 67 | picture.push_back("* programming *"); 68 | picture.push_back("* in C++! *"); 69 | picture.push_back("***************"); 70 | 71 | // concatenate 72 | vector result = hcat(picture, another_picture); 73 | // the code throws an exception if we switch the parameters 74 | // vector result = hcat(picture, another_picture); 75 | 76 | for (vector::const_iterator line = result.begin(); 77 | line != result.end(); ++line) 78 | cout << *line << endl; 79 | 80 | return 0; 81 | } -------------------------------------------------------------------------------- /Chapter 05/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::cin; 8 | using std::endl; 9 | using std::list; 10 | using std::string; 11 | using std::isupper; 12 | 13 | bool is_all_lower(string word) 14 | { 15 | for (string::const_iterator it = word.begin(); 16 | it != word.end(); ++it) 17 | if (isupper(*it)) 18 | return false; 19 | return true; 20 | } 21 | 22 | int main() 23 | { 24 | list upper; 25 | list lower; 26 | string word; 27 | // read all input 28 | while (cin >> word) 29 | if (is_all_lower(word)) 30 | lower.push_back(word); 31 | else 32 | upper.push_back(word); 33 | 34 | // write all lowercase words 35 | for (list::const_iterator it = lower.begin(); 36 | it != lower.end(); ++it) 37 | cout << *it << " "; 38 | 39 | // write words that contain uppercase 40 | for (list::const_iterator it = upper.begin(); 41 | it != upper.end(); ++it) 42 | cout << *it << " "; 43 | } -------------------------------------------------------------------------------- /Chapter 05/q10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | using std::string; 8 | using std::cout; 9 | using std::cin; 10 | using std::endl; 11 | using std::domain_error; 12 | 13 | bool is_palindrome(string s) 14 | { 15 | string::size_type length = s.size(); 16 | // create a string with the same size as s 17 | string ret = s; 18 | for (string::size_type i = 0; i < length; ++i) 19 | ret[i] = s[length - i - 1]; 20 | 21 | return s == ret; 22 | } 23 | 24 | int main() 25 | { 26 | vector palindromes; 27 | string word; 28 | string longest_word; 29 | string::size_type max_length = 0; 30 | // read all input 31 | while (cin >> word) 32 | if (is_palindrome(word)) { 33 | palindromes.push_back(word); 34 | string::size_type size = word.size(); 35 | // update the longest word 36 | if (size > max_length) { 37 | longest_word = word; 38 | max_length = size; 39 | } 40 | } 41 | 42 | // check if there are any palindromes 43 | if (palindromes.size() == 0) { 44 | throw domain_error("no palindromes found"); 45 | } 46 | 47 | // write the first palindrome 48 | vector::const_iterator it = palindromes.begin(); 49 | cout << "The palindrome(s) are: " << *it; 50 | 51 | ++it; 52 | // write the rest of the palindromes, if any 53 | while (it != palindromes.end()) { 54 | cout << ", " << *it; 55 | ++it; 56 | } 57 | // write the result 58 | cout << endl << endl << "The longest palindrome is \"" << longest_word 59 | << "\" with " << max_length << " letters." << endl; 60 | 61 | return 0; 62 | } -------------------------------------------------------------------------------- /Chapter 05/q11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::string; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | bool is_ascender_or_descender(char c) 12 | { 13 | return c == 'b' || c == 'd' || c == 'f' || c == 'h' || 14 | c == 'k' || c == 'l' || c == 'g' || c == 'j' || 15 | c == 'p' || c == 'q' || c == 'y'; 16 | } 17 | 18 | bool has_ascender_or_descender(string s) 19 | { 20 | // search all characters 21 | for (string::const_iterator it = s.begin(); 22 | it != s.end(); ++it) 23 | if (is_ascender_or_descender(*it)) 24 | return true; 25 | 26 | return false; 27 | } 28 | 29 | int main() 30 | { 31 | vector words; 32 | string word; 33 | string longest_word; 34 | string::size_type max_length = 0; 35 | // read all input 36 | while (cin >> word) 37 | if (has_ascender_or_descender(word)) 38 | words.push_back(word); 39 | else { 40 | string::size_type size = word.size(); 41 | // update the longest word 42 | if (size > max_length) { 43 | longest_word = word; 44 | max_length = size; 45 | } 46 | } 47 | 48 | // write the first word 49 | vector::const_iterator it = words.begin(); 50 | cout << "The word(s) that have ascenders or descenders are: " 51 | << *it; 52 | 53 | ++it; 54 | // write the rest of the words, if any 55 | while (it != words.end()) { 56 | cout << ", " << *it; 57 | ++it; 58 | } 59 | 60 | // write the result 61 | cout << endl << "The longest word that does not have ascenders or " 62 | "descenders is \"" << longest_word << "\" with " << max_length 63 | << " letters." << endl; 64 | 65 | return 0; 66 | } -------------------------------------------------------------------------------- /Chapter 05/split.cpp: -------------------------------------------------------------------------------- 1 | // code is taken from §5.6/88 2 | #include 3 | #include 4 | #include "split.h" 5 | 6 | using std::vector; 7 | using std::string; 8 | 9 | vector split(const string& s) 10 | { 11 | vector ret; 12 | typedef string::size_type string_size; 13 | string_size i = 0; 14 | 15 | // invariant: we have processed characters [original value of i, i) 16 | while (i != s.size()) { 17 | // ignore leading blanks 18 | // invariant: characters in range [original i, current i) are all spaces 19 | while (i != s.size() && isspace(s[i])) 20 | ++i; 21 | 22 | // find end of next word 23 | string_size j = i; 24 | // invariant: none of the characters in range [original j, current j) is a space 25 | while (j != s.size() && !isspace(s[j])) 26 | ++j; 27 | 28 | // if we found some nonwhitespace characters 29 | if (i != j) { 30 | // copy from s starting at i and taking j - i chars 31 | ret.push_back(s.substr(i, j - i)); 32 | i = j; 33 | } 34 | } 35 | return ret; 36 | } -------------------------------------------------------------------------------- /Chapter 05/split.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_split_h 2 | #define GUARD_split_h 3 | 4 | #include 5 | #include 6 | 7 | std::vector split(const std::string&); 8 | #endif -------------------------------------------------------------------------------- /Chapter 06/Student_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "grade.h" 6 | #include "median.h" 7 | #include "Student_info.h" 8 | 9 | using std::cout; 10 | using std::vector; 11 | using std::istream; 12 | using std::domain_error; 13 | using std::sort; 14 | 15 | // code is taken from §4.4/69 16 | bool compare(const Student_info& x, const Student_info& y) 17 | { 18 | return x.name < y.name; 19 | } 20 | 21 | // code is taken from §4.2.2/62 22 | istream& read(istream& is, Student_info& s) 23 | { 24 | // read and store the student's name and final grade 25 | is >> s.name >> s.midterm >> s.final; 26 | 27 | read_hw(is, s.homework); // read and store all the student's homework grades 28 | return is; 29 | } 30 | 31 | // code is taken from §4.1.3/57 32 | istream& read_hw(istream& in, vector& hw) 33 | { 34 | if (in) { 35 | // get rid of previous contetns 36 | hw.clear(); 37 | 38 | // read homework grades 39 | double x; 40 | while (in >> x) 41 | hw.push_back(x); 42 | 43 | // clear the stream so that input will work for the next student 44 | in.clear(); 45 | } 46 | return in; 47 | } -------------------------------------------------------------------------------- /Chapter 06/Student_info.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | struct Student_info { 9 | std::string name; 10 | double midterm, final; 11 | std::vector homework; 12 | }; 13 | 14 | bool compare(const Student_info&, const Student_info&); 15 | std::istream& read(std::istream&, Student_info&); 16 | std::istream& read_hw(std::istream&, std::vector&); 17 | #endif -------------------------------------------------------------------------------- /Chapter 06/analysis.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_analysis_h 2 | #define GUARD_analysis_h 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Student_info.h" 8 | 9 | double analysis(const std::vector&, 10 | double (const Student_info&)); 11 | double optimistic_median(const Student_info&); 12 | double optimistic_median_analysis(const std::vector&); 13 | double grade_aux(const Student_info&); 14 | double median_analysis(const std::vector&); 15 | double average_grade(const Student_info&); 16 | double average_analysis(const std::vector&); 17 | void write_analysis(std::ostream&, const std::string&, 18 | double analysis(const std::vector&), 19 | const std::vector&, 20 | const std::vector&); 21 | void write_analysis(std::ostream&, const std::string&, 22 | double (const Student_info&), 23 | const std::vector&, 24 | const std::vector&); 25 | bool did_all_hw(const Student_info&); 26 | #endif -------------------------------------------------------------------------------- /Chapter 06/find_urls.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "find_urls.h" 6 | 7 | using std::vector; 8 | using std::string; 9 | using std::find_if; 10 | using std::search; 11 | 12 | // code is taken from §6.1.3/106 13 | vector find_urls(const string& s) 14 | { 15 | vector ret; 16 | typedef string::const_iterator iter; 17 | iter b = s.begin(), e = s.end(); 18 | 19 | // look through the entire input 20 | while (b != e) { 21 | 22 | // look for one or more letters followed by :// 23 | b = url_beg(b, e); 24 | 25 | // if we found it 26 | if (b != e) { 27 | // get the rest of the URL 28 | iter after = url_end(b, e); 29 | 30 | // remember the URL 31 | ret.push_back(string(b, after)); 32 | 33 | // advance b and check for more URLs on this line 34 | b = after; 35 | } 36 | } 37 | return ret; 38 | } 39 | 40 | // code is taken from §6.1.3/107 41 | bool not_url_char(char c) 42 | { 43 | // characters, in addition to alphanumerics, that can appear in a URL 44 | static const string url_ch = "~;/?:@=&$-_.+!*'(),"; 45 | 46 | // see whether c can appear in a URL and return the negative 47 | return !(isalnum(c) || 48 | find(url_ch.begin(), url_ch.end(), c) != url_ch.end()); 49 | } 50 | 51 | // code is taken from §6.1.3/107 52 | string::const_iterator 53 | url_end(string::const_iterator b, string::const_iterator e) 54 | { 55 | return find_if(b, e, not_url_char); 56 | } 57 | 58 | // code is taken from §6.1.3/108 59 | string::const_iterator 60 | url_beg(string::const_iterator b, string::const_iterator e) 61 | { 62 | static const string sep = "://"; 63 | 64 | typedef string::const_iterator iter; 65 | 66 | // i marks where the separator was found 67 | iter i = b; 68 | 69 | while ((i = search(i, e, sep.begin(), sep.end())) != e) { 70 | 71 | // make sure the separator isn't at the beginning or end of the line 72 | if (i != b && i + sep.size() != e) { 73 | 74 | // beg marks the beginning of protocol-name 75 | iter beg = i; 76 | while (beg != b && isalpha(beg[-1])) 77 | --beg; 78 | 79 | // is there at least one appropriate character before and after the separator? 80 | if (beg != i && !not_url_char(i[sep.size()])) 81 | return beg; 82 | } 83 | 84 | // the separator we found wasn't part of a URL; advance i past this separator 85 | i += sep.size(); 86 | } 87 | return e; 88 | } 89 | -------------------------------------------------------------------------------- /Chapter 06/find_urls.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_find_urls_h 2 | #define GUARD_find_urls_h 3 | 4 | #include 5 | #include 6 | 7 | std::string::const_iterator 8 | url_end(std::string::const_iterator, std::string::const_iterator); 9 | std::string::const_iterator 10 | url_beg(std::string::const_iterator, std::string::const_iterator); 11 | std::vector find_urls(const std::string&); 12 | #endif -------------------------------------------------------------------------------- /Chapter 06/grade.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "grade.h" 4 | #include "../Chapter 04/median.h" 5 | 6 | using std::domain_error; using std::vector; 7 | 8 | // code taken from §4.1/52 9 | // compute a student's overall grade from midterm and final exam grades and homework grade 10 | double grade(double midterm, double final, double homework) 11 | { 12 | return 0.2 * midterm + 0.4 * final + 0.4 * homework; 13 | } 14 | 15 | // code taken from §4.1.2/54 16 | // compute a student's overall grade from midterm and final exam grades 17 | // and vector of homework grades. 18 | // this function does not copy its argument, because median does so for us. 19 | double grade(double midterm, double final, const vector& hw) 20 | { 21 | if (hw.size() == 0) 22 | throw domain_error("student has done no homework"); 23 | return grade(midterm, final, median(hw)); 24 | } 25 | 26 | // code taken from §4.2.2/63 27 | double grade(const Student_info& s) 28 | { 29 | return grade(s.midterm, s.final, s.homework); 30 | } -------------------------------------------------------------------------------- /Chapter 06/grade.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_grade_h 2 | #define GUARD_grade_h 3 | 4 | #include 5 | #include "Student_info.h" 6 | 7 | double grade(double, double, double); 8 | double grade(double, double, const std::vector&); 9 | double grade(const Student_info&); 10 | #endif -------------------------------------------------------------------------------- /Chapter 06/median.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "median.h" 4 | 5 | using std::vector; 6 | using std::domain_error; 7 | 8 | // code is taken from §4.1.1/53 9 | // compute the median of a vector 10 | // note that calling this function copies the entire argument vector 11 | double median(vector vec) 12 | { 13 | typedef vector::size_type vec_sz; 14 | 15 | vec_sz size = vec.size(); 16 | if (size == 0) 17 | throw domain_error("median of an empty vector"); 18 | 19 | sort(vec.begin(), vec.end()); 20 | 21 | vec_sz mid = size/2; 22 | 23 | return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid]; 24 | } 25 | -------------------------------------------------------------------------------- /Chapter 06/median.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_median_h 2 | #define GUARD_median_h 3 | 4 | #include 5 | 6 | double median(std::vector); 7 | #endif -------------------------------------------------------------------------------- /Chapter 06/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::string; 7 | using std::max; 8 | using std::cout; 9 | using std::endl; 10 | 11 | string::size_type width(const vector& v) 12 | { 13 | string::size_type maxlen = 0; 14 | for (vector::const_iterator it = v.begin(); 15 | it != v.end(); ++it) 16 | maxlen = max(maxlen, it->size()); 17 | return maxlen; 18 | } 19 | 20 | vector frame(const vector& v) 21 | { 22 | vector ret; 23 | string::size_type maxlen = width(v); 24 | string border(maxlen + 4, '*'); 25 | 26 | // write the top border 27 | ret.push_back(border); 28 | 29 | // write each interior row, bordered by an asterisk and a space 30 | for (vector::const_iterator it = v.begin(); 31 | it != v.end(); ++it) 32 | ret.push_back("* " + *it + string(maxlen - it->size(), ' ') + " *"); 33 | 34 | // write the bottom border 35 | ret.push_back(border); 36 | return ret; 37 | } 38 | 39 | vector hcat(const vector& left, const vector& right) 40 | { 41 | vector ret; 42 | 43 | // add 1 to leave a space between pictures 44 | string::size_type width1 = width(left) + 1; 45 | 46 | // iterators to look at elements from left and right respectively 47 | vector::const_iterator it = left.begin(), jt = right.begin(); 48 | 49 | // continue until we've seen all rows from both pictures 50 | while (it != left.end() || jt != right.end()) { 51 | // construct new string to hold characters from both pictures 52 | string s; 53 | 54 | // copy a row from the left-hand side, if there is one 55 | if (it != left.end()) 56 | s = *it++; 57 | 58 | // pad to full width 59 | s += string(width1 - s.size(), ' '); 60 | 61 | // copy a row from the right-hand side, if there is one 62 | if (jt != right.end()) 63 | s += *jt++; 64 | 65 | // add s to the picture we're creating 66 | ret.push_back(s); 67 | } 68 | return ret; 69 | } 70 | 71 | // test reimplemented functions 72 | int main() 73 | { 74 | // create two vectors 75 | vector left; 76 | left.push_back("hello"); 77 | left.push_back("my name"); 78 | left.push_back("is Altug"); 79 | 80 | vector right; 81 | right.push_back("I am"); 82 | right.push_back("programming"); 83 | right.push_back("in C++!"); 84 | 85 | // frame the vectors 86 | vector framed_left = frame(left); 87 | vector framed_right = frame(right); 88 | 89 | // horizontally concatenate 90 | vector concatenated = hcat(framed_left, framed_right); 91 | 92 | // write the results 93 | for (vector::const_iterator it = concatenated.begin(); 94 | it != concatenated.end(); ++it) 95 | cout << *it << endl; 96 | 97 | return 0; 98 | } -------------------------------------------------------------------------------- /Chapter 06/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "find_urls.h" 3 | 4 | using std::vector; 5 | using std::string; 6 | using std::cout; 7 | using std::endl; 8 | 9 | int main() 10 | { 11 | // create an example text 12 | const string test = "Hello, welcome to my GitHub! The link to my" 13 | "repository is https://github.com/altugbakan/accelerated-cpp-solutions" 14 | " and the link to the book's website is http://www.acceleratedcpp.com/"; 15 | 16 | // find the urls 17 | vector urls = find_urls(test); 18 | 19 | // write the results 20 | cout << "Found URLs are: " << endl; 21 | for (vector::const_iterator it = urls.begin(); 22 | it != urls.end(); ++it) 23 | cout << *it << endl; 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Chapter 06/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::vector; 5 | using std::cout; 6 | using std::endl; 7 | 8 | int main() 9 | { 10 | vector u(10, 100); 11 | vector v; 12 | // the code throws an error if we use v.begin() 13 | // copy(u.begin(), u.end(), v.begin()); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /Chapter 06/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::vector; 6 | using std::cout; 7 | using std::endl; 8 | 9 | int main() 10 | { 11 | vector u(1000000, 100); 12 | 13 | // calculate the time for copying 14 | double begin_copy = clock(); 15 | vector v(u); 16 | double end_copy = clock(); 17 | 18 | // clear vector for the next test 19 | v.clear(); 20 | 21 | // calculate the time for back inserter 22 | double begin_back = clock(); 23 | copy(u.begin(), u.end(), back_inserter(v)); 24 | double end_back = clock(); 25 | 26 | // write the results 27 | cout << "copying took " << (end_copy - begin_copy) / 28 | CLOCKS_PER_SEC << " seconds for " << u.size() << " items."; 29 | 30 | cout << "back_inserter took " << (end_back - begin_back) / 31 | CLOCKS_PER_SEC << " seconds for " << u.size() << " items." << endl; 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /Chapter 06/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | // code is taken from §6.2.2/114 12 | int main() 13 | { 14 | // students who did and didn't do all their homework 15 | vector did, didnt; 16 | 17 | // read the student records and partition them 18 | Student_info student; 19 | // read all student data 20 | while (read(cin, student)) { 21 | if (did_all_hw(student)) 22 | did.push_back(student); 23 | else 24 | didnt.push_back(student); 25 | } 26 | 27 | // verify that the analyses will show us something 28 | if (did.empty()) { 29 | cout << "No student did all the homework!" << endl; 30 | return 1; 31 | } 32 | if (didnt.empty()) { 33 | cout << "Every student did all the homework!" << endl; 34 | return 1; 35 | } 36 | 37 | // do the analyses 38 | write_analysis(cout, "median", median_analysis, did, didnt); 39 | write_analysis(cout, "average", average_analysis, did, didnt); 40 | write_analysis(cout, "median of homework turned in", 41 | optimistic_median_analysis, did, didnt); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter 06/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | // code is taken from §6.2.2/114 12 | int main() 13 | { 14 | // students who did and didn't do all their homework 15 | vector did, didnt; 16 | 17 | // read the student records and partition them 18 | Student_info student; 19 | // read all student data 20 | while (read(cin, student)) { 21 | if (did_all_hw(student)) 22 | did.push_back(student); 23 | else 24 | didnt.push_back(student); 25 | } 26 | 27 | // verify that the analyses will show us something 28 | if (did.empty()) { 29 | cout << "No student did all the homework!" << endl; 30 | return 1; 31 | } 32 | if (didnt.empty()) { 33 | cout << "Every student did all the homework!" << endl; 34 | return 1; 35 | } 36 | 37 | // do the analyses 38 | write_analysis(cout, "median", grade_aux, did, didnt); 39 | write_analysis(cout, "average", average_grade, did, didnt); 40 | write_analysis(cout, "median of homework turned in", 41 | optimistic_median, did, didnt); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter 06/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | vector extract_didnt(vector& students) 12 | { 13 | vector didnt; 14 | vector::iterator it = students.begin(); 15 | 16 | while (it != students.end()) { 17 | if (!did_all_hw(*it)) { 18 | didnt.push_back(*it); 19 | it = students.erase(it); 20 | } else 21 | ++it; 22 | } 23 | return didnt; 24 | } 25 | 26 | int main() 27 | { 28 | vector students; 29 | Student_info student; 30 | 31 | // read all student data 32 | while (read(cin, student)) 33 | students.push_back(student); 34 | 35 | // extract students who did not do their homework 36 | vector didnt = extract_didnt(students); 37 | 38 | // write the results 39 | cout << "Students who did all their homework are: "; 40 | for (vector::const_iterator it = students.begin(); 41 | it != students.end(); ++it) 42 | cout << it->name << (it + 1 == students.end() ? "." : ", "); 43 | cout << endl; 44 | 45 | cout << "Students who did not do all their homework are: "; 46 | for (vector::const_iterator it = didnt.begin(); 47 | it != didnt.end(); ++it) 48 | cout << it->name << (it + 1 == didnt.end() ? "." : ", "); 49 | cout << endl; 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 06/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | bool fgrade(const Student_info& s) 12 | { 13 | return optimistic_median(s) < 60; 14 | } 15 | 16 | // code is taken from §5.3/62 17 | vector extract_fails(vector& students) 18 | { 19 | vector fail; 20 | vector::iterator iter = students.begin(); 21 | 22 | while (iter != students.end()) { 23 | if (fgrade(*iter)) { 24 | fail.push_back(*iter); 25 | iter = students.erase(iter); 26 | } else 27 | ++iter; 28 | } 29 | return fail; 30 | } 31 | 32 | int main() 33 | { 34 | vector students; 35 | Student_info student; 36 | 37 | // read all student data 38 | while (read(cin, student)) 39 | students.push_back(student); 40 | 41 | vector fails = extract_fails(students); 42 | 43 | // write the results 44 | cout << "Students who passed the class are: "; 45 | for (vector::const_iterator it = students.begin(); 46 | it != students.end(); ++it) 47 | cout << it->name << (it + 1 == students.end() ? "." : ", "); 48 | cout << endl; 49 | 50 | cout << "Students who failed the class are: "; 51 | for (vector::const_iterator it = fails.begin(); 52 | it != fails.end(); ++it) 53 | cout << it->name << (it + 1 == fails.end() ? "." : ", "); 54 | cout << endl; 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Chapter 06/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | using std::string; 8 | using std::cout; 9 | using std::endl; 10 | 11 | int main() 12 | { 13 | // create the vector 14 | vector words; 15 | words.push_back("hello "); 16 | words.push_back("my "); 17 | words.push_back("name "); 18 | words.push_back("is "); 19 | words.push_back("Altug"); 20 | 21 | // concatenate all elements 22 | string concatenated_words = accumulate(words.begin(), words.end(), string()); 23 | 24 | // write the result 25 | cout << "The result of concatenation is: " << concatenated_words << endl; 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /Chapter 07/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::cin; 8 | using std::endl; 9 | using std::map; 10 | using std::vector; 11 | using std::string; 12 | 13 | int main() 14 | { 15 | string s; 16 | map counters; // store each word and an associated counter 17 | 18 | // read the input, keeping track of each word and how often we see it 19 | while (cin >> s) 20 | ++counters[s]; 21 | 22 | map > occurences; // group counts of the occurences 23 | 24 | // fill the occurences 25 | for (map::const_iterator it = counters.begin(); 26 | it != counters.end(); ++it) { 27 | occurences[it->second].push_back(it->first); 28 | } 29 | 30 | // write the words and associated counts 31 | for (map >::const_iterator it = occurences.begin(); 32 | it != occurences.end(); ++it) { 33 | // write the count 34 | cout << "words that occur " << it->first << " time(s): "; 35 | 36 | // followed by one or more words 37 | vector::const_iterator word_it = it->second.begin(); 38 | cout << *word_it; // write the first word number 39 | 40 | ++word_it; 41 | // write the rest of the words, if any 42 | while (word_it != it->second.end()) { 43 | cout << ", " << *word_it; 44 | ++word_it; 45 | } 46 | // write a new line to separate each count from the next 47 | cout << endl; 48 | } 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /Chapter 07/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "../Chapter 04/Student_info.h" // using the simplifed version 10 | 11 | using std::cin; using std::setprecision; 12 | using std::cout; using std::sort; 13 | using std::domain_error; using std::streamsize; 14 | using std::endl; using std::string; 15 | using std::max; using std::vector; 16 | using std::map; 17 | 18 | int main() 19 | { 20 | vector students; 21 | Student_info record; 22 | string::size_type maxlen = 0; 23 | 24 | // read and store all the records, and find the length of the longest name 25 | while (read(cin, record)) { 26 | maxlen = max(maxlen, record.name.size()); 27 | students.push_back(record); 28 | } 29 | 30 | // alphabetize the records 31 | sort(students.begin(), students.end(), compare); 32 | 33 | // assign letter grades 34 | map > grades; 35 | for (vector::const_iterator it = students.begin(); 36 | it != students.end(); ++it) { 37 | if (it->final_grade > 90) 38 | grades["A"].push_back(*it); 39 | else if (it->final_grade > 80) 40 | grades["B"].push_back(*it); 41 | else if (it->final_grade > 70) 42 | grades["C"].push_back(*it); 43 | else if (it->final_grade > 60) 44 | grades["D"].push_back(*it); 45 | else 46 | grades["F"].push_back(*it); 47 | } 48 | 49 | for (map >::const_iterator it = grades.begin(); 50 | it != grades.end(); ++it) { 51 | // write the grade 52 | cout << "The student(s) who got " << (it->first == "A" || it->first == "F" 53 | ? "an " : "a ") << it->first << " are: "; 54 | 55 | // followed by one or more student names 56 | vector::const_iterator student_it = it->second.begin(); 57 | cout << student_it->name; // write the first student name 58 | 59 | ++student_it; 60 | // write the rest of the student names, if any 61 | while (student_it != it->second.end()) { 62 | cout << ", " << student_it->name; 63 | ++student_it; 64 | } 65 | // write a new line to separate each student name from the next 66 | cout << endl; 67 | } 68 | 69 | return 0; 70 | } -------------------------------------------------------------------------------- /Chapter 07/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | 8 | using std::map; 9 | using std::vector; 10 | using std::string; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::istream; 15 | using std::find; 16 | 17 | // find all the lines that refer to each word in the input 18 | map > 19 | xref(istream& in, 20 | vector find_words(const string&) = split) 21 | { 22 | string line; 23 | int line_number = 0; 24 | map > ret; 25 | 26 | // read the next line 27 | while (getline(in, line)) { 28 | ++line_number; 29 | 30 | // break the input line into words 31 | vector words = find_words(line); 32 | 33 | // remember that each word occurs on the current line 34 | for (vector::const_iterator it = words.begin(); 35 | it != words.end(); ++it) 36 | // push if it does not exist already 37 | if (find(ret[*it].begin(), ret[*it].end(), line_number) 38 | == ret[*it].end()) 39 | ret[*it].push_back(line_number); 40 | } 41 | return ret; 42 | } 43 | 44 | // code is taken from §7.3/128 45 | int main() 46 | { 47 | // call xref using split by default 48 | map > ret = xref(cin); 49 | 50 | // write the results 51 | for (map >::const_iterator it = ret.begin(); 52 | it != ret.end(); ++it) { 53 | // write the word 54 | cout << it->first << " occurs on line(s): "; 55 | 56 | // followed by one or more line numbers 57 | vector::const_iterator line_it = it->second.begin(); 58 | cout << *line_it; // write the first line number 59 | 60 | ++line_it; 61 | // write the rest of the line numbers, if any 62 | while (line_it != it->second.end()) { 63 | cout << ", " << *line_it; 64 | ++line_it; 65 | } 66 | // write a new line to separate each word from the next 67 | cout << endl; 68 | } 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /Chapter 07/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | 8 | using std::map; 9 | using std::vector; 10 | using std::string; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::istream; 15 | using std::find; 16 | 17 | // find all the lines that refer to each word in the input 18 | map > 19 | xref(istream& in, 20 | vector find_words(const string&) = split) 21 | { 22 | string line; 23 | int line_number = 0; 24 | map > ret; 25 | 26 | // read the next line 27 | while (getline(in, line)) { 28 | ++line_number; 29 | 30 | // break the input line into words 31 | vector words = find_words(line); 32 | 33 | // remember that each word occurs on the current line 34 | for (vector::const_iterator it = words.begin(); 35 | it != words.end(); ++it) 36 | // push if it does not exist already 37 | if (find(ret[*it].begin(), ret[*it].end(), line_number) 38 | == ret[*it].end()) 39 | ret[*it].push_back(line_number); 40 | } 41 | return ret; 42 | } 43 | 44 | int main() 45 | { 46 | // call xref using split by default 47 | map > ret = xref(cin); 48 | 49 | // write the results 50 | for (map >::const_iterator it = ret.begin(); 51 | it != ret.end(); ++it) { 52 | 53 | // write the word 54 | cout << it->first << " occurs on line(s): "; 55 | 56 | // followed by one or more line numbers 57 | vector::const_iterator line_it = it->second.begin(); 58 | cout << *line_it; // write the first line number 59 | 60 | ++line_it; 61 | // write the rest of the line numbers, if any 62 | while (line_it != it->second.end()) { 63 | cout << ", "; 64 | 65 | // break up the output line after 15 lines 66 | if ((line_it - it->second.begin()) % 15 == 0) { 67 | cout << endl; 68 | } 69 | cout << *line_it; 70 | ++line_it; 71 | } 72 | // write a new line to separate each word from the next 73 | cout << endl; 74 | } 75 | 76 | return 0; 77 | } -------------------------------------------------------------------------------- /Chapter 07/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | 8 | using std::istream; 9 | using std::cout; 10 | using std::cin; 11 | using std::endl; 12 | using std::logic_error; 13 | using std::domain_error; 14 | using std::map; 15 | using std::vector; 16 | using std::string; 17 | 18 | typedef vector Rule; 19 | typedef vector Rule_collection; 20 | typedef map Grammar; 21 | 22 | // code is taken from §7.4.2/131 23 | // read a grammar from a given input stream 24 | Grammar read_grammar(istream& in) 25 | { 26 | Grammar ret; 27 | string line; 28 | 29 | // read the input 30 | while (getline(in, line)) { 31 | 32 | // split the input into words 33 | vector entry = split(line); 34 | 35 | if (!entry.empty()) 36 | // use the category to store the associated rule 37 | ret[entry[0]].push_back( 38 | Rule(entry.begin() + 1, entry.end())); 39 | } 40 | return ret; 41 | } 42 | 43 | // code is taken from §7.4.3/132 44 | bool bracketed(const string& s) 45 | { 46 | return s.size() > 1 && s[0] == '<' && s[s.size() - 1] == '>'; 47 | } 48 | 49 | // code is taken from §7.4.4/135 50 | // return a random integer in the range [0, n) 51 | int nrand(int n) 52 | { 53 | if (n <= 0 || n > RAND_MAX) 54 | throw domain_error("Argument to nrand is out of range"); 55 | 56 | const int bucket_size = RAND_MAX / n; 57 | int r; 58 | 59 | do r = rand() / bucket_size; 60 | while (r >= n); 61 | 62 | return r; 63 | } 64 | 65 | // code is taken from §7.4.3/132 66 | vector gen_sentence(const Grammar& g) 67 | { 68 | vector rules; // holds the rules 69 | vector sentence; // holds the generated sentence 70 | 71 | rules.push_back(""); 72 | while (!rules.empty()) { 73 | // locate the rule that corresponds to word 74 | Grammar::const_iterator it = g.find(rules[0]); 75 | if (it == g.end()) 76 | throw logic_error("empty rule"); 77 | 78 | // fetch the set of possible rules 79 | const Rule_collection& c = it->second; 80 | 81 | // from which we select one at random 82 | const Rule& r = c[nrand(c.size())]; 83 | 84 | // remove the used rule 85 | rules.erase(rules.begin()); 86 | 87 | // add results to their vectors 88 | Rule::iterator rule_it = rules.begin(); 89 | for (Rule::const_iterator i = r.begin(); i != r.end(); ++i) { 90 | if (bracketed(*i)) { 91 | rule_it = rules.insert(rule_it, *i); 92 | ++rule_it; 93 | } 94 | else 95 | sentence.push_back(*i); 96 | } 97 | } 98 | 99 | return sentence; 100 | } 101 | 102 | // code is taken from §7.4.3/134 103 | int main() 104 | { 105 | // generate the sentence 106 | vector sentence = gen_sentence(read_grammar(cin)); 107 | 108 | // write the first word, if any 109 | vector::const_iterator it = sentence.begin(); 110 | if (!sentence.empty()) { 111 | cout << *it; 112 | ++it; 113 | } 114 | 115 | // write the rest of the words, each preceded by a space 116 | while (it != sentence.end()) { 117 | cout << " " << *it; 118 | ++it; 119 | } 120 | 121 | cout << endl; 122 | return 0; 123 | } -------------------------------------------------------------------------------- /Chapter 07/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | 8 | using std::map; 9 | using std::vector; 10 | using std::string; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::istream; 15 | using std::find; 16 | 17 | // find all the lines that refer to each word in the input 18 | map > 19 | xref(istream& in, 20 | vector find_words(const string&) = split) 21 | { 22 | string line; 23 | int line_number = 0; 24 | map > ret; 25 | 26 | // read the next line 27 | while (getline(in, line)) { 28 | ++line_number; 29 | 30 | // break the input line into words 31 | vector words = find_words(line); 32 | 33 | // remember that each word occurs on the current line 34 | for (vector::const_iterator it = words.begin(); 35 | it != words.end(); ++it) 36 | // push if it does not exist already 37 | if (find(ret[*it].begin(), ret[*it].end(), line_number) 38 | == ret[*it].end()) 39 | ret[*it].push_back(line_number); 40 | } 41 | return ret; 42 | } 43 | 44 | int main() 45 | { 46 | // call xref using split by default 47 | map > ret = xref(cin); 48 | 49 | // write the results 50 | for (map >::const_iterator it = ret.begin(); 51 | it != ret.end(); ++it) { 52 | 53 | // write the word 54 | cout << it->first << " occurs on line" 55 | << (it->second.size() > 1 ? "s: " : ": "); 56 | 57 | // followed by one or more line numbers 58 | vector::const_iterator line_it = it->second.begin(); 59 | cout << *line_it; // write the first line number 60 | 61 | ++line_it; 62 | // write the rest of the line numbers, if any 63 | while (line_it != it->second.end()) { 64 | cout << ", "; 65 | 66 | // break up the output line after 15 lines 67 | if ((line_it - it->second.begin()) % 15 == 0) { 68 | cout << endl; 69 | } 70 | cout << *line_it; 71 | ++line_it; 72 | } 73 | // write a new line to separate each word from the next 74 | cout << endl; 75 | } 76 | 77 | return 0; 78 | } -------------------------------------------------------------------------------- /Chapter 07/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | #include "../Chapter 06/find_urls.h" 8 | 9 | using std::map; 10 | using std::vector; 11 | using std::string; 12 | using std::cout; 13 | using std::cin; 14 | using std::endl; 15 | using std::istream; 16 | using std::find; 17 | 18 | // find all the lines that refer to each word in the input 19 | map > 20 | xref(istream& in, 21 | vector find_words(const string&) = split) 22 | { 23 | string line; 24 | int line_number = 0; 25 | map > ret; 26 | 27 | // read the next line 28 | while (getline(in, line)) { 29 | ++line_number; 30 | 31 | // break the input line into words 32 | vector words = find_words(line); 33 | 34 | // remember that each word occurs on the current line 35 | for (vector::const_iterator it = words.begin(); 36 | it != words.end(); ++it) 37 | // push if it does not exist already 38 | if (find(ret[*it].begin(), ret[*it].end(), line_number) 39 | == ret[*it].end()) 40 | ret[*it].push_back(line_number); 41 | } 42 | return ret; 43 | } 44 | 45 | int main() 46 | { 47 | // call xref using find_urls 48 | map > ret = xref(cin, find_urls); 49 | 50 | // write the results 51 | for (map >::const_iterator it = ret.begin(); 52 | it != ret.end(); ++it) { 53 | 54 | // write the word 55 | cout << it->first << " occurs on line" 56 | << (it->second.size() > 1 ? "s: " : ": "); 57 | 58 | // followed by one or more line numbers 59 | vector::const_iterator line_it = it->second.begin(); 60 | cout << *line_it; // write the first line number 61 | 62 | ++line_it; 63 | // write the rest of the line numbers, if any 64 | while (line_it != it->second.end()) { 65 | cout << ", "; 66 | 67 | // break up the output line after 15 lines 68 | if ((line_it - it->second.begin()) % 15 == 0) { 69 | cout << endl; 70 | } 71 | cout << *line_it; 72 | ++line_it; 73 | } 74 | // write a new line to separate each word from the next 75 | cout << endl; 76 | } 77 | 78 | return 0; 79 | } -------------------------------------------------------------------------------- /Chapter 07/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::domain_error; 7 | 8 | // return a random integer in the range [0, n) 9 | int nrand(int n) 10 | { 11 | if (n <= 0) 12 | throw domain_error("Argument to nrand is out of range"); 13 | 14 | const int buckets = n / RAND_MAX; 15 | 16 | const int last_bucket = RAND_MAX / (n % RAND_MAX); 17 | int r; 18 | 19 | do r = rand() / last_bucket; 20 | while (r >= n); 21 | 22 | // add the remaining buckets for numbers larger than RAND_MAX 23 | for (int i = 0; i < buckets; ++i) { 24 | r += rand(); 25 | } 26 | 27 | return r; 28 | } 29 | 30 | int main() 31 | { 32 | cout << "RAND_MAX is " << RAND_MAX << endl; 33 | 34 | cout << "The results for n = 100000 are: "; 35 | // get 5 samples 36 | for (int i = 0; i < 5; ++i) { 37 | cout << nrand(100000) << " "; 38 | } 39 | 40 | cout << endl << "The results for n = 100 are: "; 41 | // get 5 samples 42 | for (int i = 0; i < 5; ++i) { 43 | cout << nrand(100) << " "; 44 | } 45 | 46 | cout << endl; 47 | return 0; 48 | } -------------------------------------------------------------------------------- /Chapter 08/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../Chapter 06/Student_info.h" 5 | #include "../Chapter 06/median.h" 6 | #include "../Chapter 06/grade.h" 7 | #include "../Chapter 06/analysis.h" 8 | 9 | using std::ostream; 10 | using std::cout; 11 | using std::cin; 12 | using std::endl; 13 | using std::domain_error; 14 | using std::vector; 15 | using std::string; 16 | 17 | template 18 | double analysis_tmp(const vector& students, Func grade_function) 19 | { 20 | vector grades; 21 | 22 | transform(students.begin(), students.end(), 23 | back_inserter(grades), grade_function); 24 | return median(grades); 25 | } 26 | 27 | template 28 | void write_analysis_tmp(ostream& out, const string& name, 29 | Func grade_function, 30 | const vector& did, 31 | const vector& didnt) 32 | { 33 | out << name << ": median(did) = " << analysis_tmp(did, grade_function) 34 | << ", median(didnt) = " << analysis_tmp(didnt, grade_function) << endl; 35 | } 36 | 37 | int main() 38 | { 39 | // students who did and didn't do all their homework 40 | vector did, didnt; 41 | 42 | // read the student records and partition them 43 | Student_info student; 44 | // read all student data 45 | while (read(cin, student)) { 46 | if (did_all_hw(student)) 47 | did.push_back(student); 48 | else 49 | didnt.push_back(student); 50 | } 51 | 52 | // verify that the analyses will show us something 53 | if (did.empty()) { 54 | cout << "No student did all the homework!" << endl; 55 | return 1; 56 | } 57 | if (didnt.empty()) { 58 | cout << "Every student did all the homework!" << endl; 59 | return 1; 60 | } 61 | 62 | // do the analyses 63 | write_analysis_tmp(cout, "median", grade_aux, did, didnt); 64 | write_analysis_tmp(cout, "average", average_grade, did, didnt); 65 | write_analysis_tmp(cout, "median of homework turned in", 66 | optimistic_median, did, didnt); 67 | 68 | return 0; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /Chapter 08/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::domain_error; 10 | 11 | template 12 | T median(Ran b, Ran e) 13 | { 14 | size_t size = e - b; 15 | if (size == 0) 16 | throw domain_error("median of an empty container"); 17 | 18 | sort(b, e); 19 | 20 | size_t mid = size / 2; 21 | 22 | return size % 2 == 0 ? (*(b + mid) + *(b + mid - 1)) / 2.0 : *(b + mid); 23 | } 24 | 25 | int main() 26 | { 27 | vector vec; 28 | vec.push_back(1); 29 | vec.push_back(7); 30 | vec.push_back(8); 31 | vec.push_back(2); 32 | vec.push_back(5); 33 | vec.push_back(4); 34 | 35 | cout << "median is " << median(vec.begin(), vec.end()) << endl; 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /Chapter 08/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::vector; 7 | 8 | template void reverse(Bi begin, Bi end) 9 | { 10 | while (begin != end) { 11 | --end; 12 | if (begin != end) { 13 | Bi temp = begin; 14 | *begin = *end; 15 | *end = *temp; 16 | ++begin; 17 | } 18 | } 19 | } 20 | 21 | int main() 22 | { 23 | vector numbers; 24 | numbers.push_back(1); 25 | numbers.push_back(2); 26 | numbers.push_back(3); 27 | numbers.push_back(4); 28 | numbers.push_back(5); 29 | 30 | reverse(numbers.begin(), numbers.end()); 31 | 32 | cout << "Reversed numbers are: " << numbers[0]; 33 | 34 | for (vector::const_iterator it = numbers.begin() + 1; 35 | it != numbers.end(); ++it) 36 | cout << ", " << *it; 37 | 38 | cout << endl; 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /Chapter 08/q05-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "../Chapter 05/split.h" 7 | 8 | using std::map; 9 | using std::vector; 10 | using std::string; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::istream; 15 | using std::find; 16 | 17 | // find all the lines that refer to each word in the input 18 | template 19 | void xref(istream& in, Out os, 20 | vector find_words(const string&) = split) 21 | { 22 | string line; 23 | int line_number = 0; 24 | map > ret; 25 | 26 | // read the next line 27 | while (getline(in, line)) { 28 | ++line_number; 29 | 30 | // break the input line into words 31 | vector words = find_words(line); 32 | 33 | // remember that each word occurs on the current line 34 | for (vector::const_iterator it = words.begin(); 35 | it != words.end(); ++it) 36 | // push if it does not exist already 37 | if (find(ret[*it].begin(), ret[*it].end(), line_number) 38 | == ret[*it].end()) 39 | ret[*it].push_back(line_number); 40 | } 41 | 42 | // write results to output iterator 43 | for (map >::const_iterator it = ret.begin(); 44 | it != ret.end(); ++it) { 45 | *os = *it; 46 | } 47 | } 48 | 49 | // code is taken from §7.3/128 50 | int main() 51 | { 52 | // call xref using split by default 53 | map > ret; 54 | xref(cin, inserter(ret, ret.begin())); 55 | 56 | // write the results 57 | for (map >::const_iterator it = ret.begin(); 58 | it != ret.end(); ++it) { 59 | // write the word 60 | cout << it->first << " occurs on line" 61 | << (it->second.size() > 1 ? "s: " : ": "); 62 | 63 | // followed by one or more line numbers 64 | vector::const_iterator line_it = it->second.begin(); 65 | cout << *line_it; // write the first line number 66 | 67 | ++line_it; 68 | // write the rest of the line numbers, if any 69 | while (line_it != it->second.end()) { 70 | cout << ", " << *line_it; 71 | ++line_it; 72 | } 73 | // write a new line to separate each word from the next 74 | cout << endl; 75 | } 76 | 77 | return 0; 78 | } -------------------------------------------------------------------------------- /Chapter 09/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Reimplement the `Student_info` class so that it calculates the final grade when reading the student's record, and stores that grade in the object. Reimplement the `grade` function to use this precomputed value. 7 | The reimplementations of `Student_info` and `grade` can be found in [Student_info_ex.cpp](./Student_info_ex.cpp). The `grade` function of the `Student_info` now returns the final grade that is stored in the object. The calculation is done in the `read` function. The driver program can be found in [q01.cpp](./q01.cpp). 8 | 9 | ### Q2: If we define the `name` function as a plain, non`const` member function, what other functions in our system must change and why? 10 | If we define the `name` function as a non`const` function, we need to change the `compare` function as it uses `const Student_info&` references. 11 | 12 | ### Q3: Our `grade` function was written to throw an exception if a user tried to calculate a grade for a `Student_info` object whose values had not yet been read. Users who care are expected to catch this exception. Write a program that triggers the exception but does not catch it. Write a program that catches the exception. 13 | The program that triggers the exception but does not catch it can be found in [q03-1.cpp](./q03-1.cpp). The program that catches the exception can be found in [q03-2.cpp](./q03-2.cpp). 14 | 15 | ### Q4: Rewrite your program from the previous exercise to use the `valid` function, thereby avoiding the exception altogether. 16 | The program that uses `valid` can be found in [q04.cpp](./q04.cpp). 17 | 18 | ### Q5: Write a class and associated functions to generate grades for students who take the course for pass/fail credit. Assume that only the midterm and final grades matter, and that a student passes with an average exam score greater than 60. The report should list the students in alphabetical order, and indicate `P` or `F` as the grade. 19 | The created class can be found in [Student_info_pf.cpp](./Student_info_pf.cpp). The driver program can be found in [q05.cpp](./q05.cpp). 20 | 21 | ### Q6: Rewrite the grading program for the pass/fail students so that the report shows all the students who passed, followed by all students who failed. 22 | The rewritten grading program can be found in [q06.cpp](./q06.cpp). 23 | 24 | ### Q7: The `read_hw` function §4.1.3/57 solves a general problem (reading a sequence of values into a `vector`) even though its name suggests that it should be part of the implementation of `Student_info`. Of course, we could change its name—but suppose, instead, that you wanted to integrate it with the rest of the `Student_info` code, in order to clarify that it was not intended for public access despite its apparent generality? How would you do so? 25 | We could add the `read_hw` function as a `private` member function of the class `Student_info`, or we could put the definition of the `read_hw` function in the `Student_info.cpp` file without interfacing it to everyone. -------------------------------------------------------------------------------- /Chapter 09/Student_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 04/grade.h" 5 | 6 | using std::vector; 7 | using std::istream; 8 | 9 | Student_info::Student_info(): midterm(0), final(0) { } 10 | Student_info::Student_info(istream& is) { read(is); } 11 | 12 | // code is taken from §4.1.3/57 13 | istream& read_hw(istream& in, vector& hw) 14 | { 15 | if (in) { 16 | // get rid of previous contetns 17 | hw.clear(); 18 | 19 | // read homework grades 20 | double x; 21 | while (in >> x) 22 | hw.push_back(x); 23 | 24 | // clear the stream so that input will work for the next student 25 | in.clear(); 26 | } 27 | return in; 28 | } 29 | 30 | // code is taken from §9.2.1/157 31 | istream& Student_info::read(istream& in) 32 | { 33 | in >> n >> midterm >> final; 34 | read_hw(in, homework); 35 | return in; 36 | } 37 | 38 | // code is taken from §9.3.1/158 39 | double Student_info::grade() const 40 | { 41 | return ::grade(midterm, final, homework); 42 | } 43 | 44 | // code is taken from §9.3.1/162 45 | bool compare(const Student_info& x, const Student_info& y) 46 | { 47 | return x.name() < y.name(); 48 | } -------------------------------------------------------------------------------- /Chapter 09/Student_info.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | #include 6 | 7 | class Student_info { 8 | public: 9 | Student_info(); 10 | Student_info(std::istream&); 11 | std::string name() const { return n; } 12 | bool valid() const { return !homework.empty(); } 13 | std::istream& read(std::istream&); 14 | double grade() const; 15 | private: 16 | std::string n; 17 | double midterm, final; 18 | std::vector homework; 19 | }; 20 | 21 | bool compare(const Student_info&, const Student_info&); 22 | #endif -------------------------------------------------------------------------------- /Chapter 09/Student_info_ex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info_ex.h" 4 | #include "../Chapter 04/grade.h" 5 | 6 | using std::vector; 7 | using std::istream; 8 | 9 | Student_info::Student_info(): midterm(0), final(0) { } 10 | Student_info::Student_info(istream& is) { read(is); } 11 | 12 | // code is taken from §4.1.3/57 13 | istream& read_hw(istream& in, vector& hw) 14 | { 15 | if (in) { 16 | // get rid of previous contetns 17 | hw.clear(); 18 | 19 | // read homework grades 20 | double x; 21 | while (in >> x) 22 | hw.push_back(x); 23 | 24 | // clear the stream so that input will work for the next student 25 | in.clear(); 26 | } 27 | return in; 28 | } 29 | 30 | istream& Student_info::read(istream& in) 31 | { 32 | in >> n >> midterm >> final; 33 | read_hw(in, homework); 34 | g = ::grade(midterm, final, homework); 35 | return in; 36 | } 37 | 38 | // code is taken from §9.3.1/162 39 | bool compare(const Student_info& x, const Student_info& y) 40 | { 41 | return x.name() < y.name(); 42 | } -------------------------------------------------------------------------------- /Chapter 09/Student_info_ex.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | #include 6 | 7 | class Student_info { 8 | public: 9 | Student_info(); 10 | Student_info(std::istream&); 11 | std::string name() const { return n; } 12 | bool valid() const { return !homework.empty(); } 13 | std::istream& read(std::istream&); 14 | double grade() const { return g; }; 15 | private: 16 | std::string n; 17 | double g, midterm, final; 18 | std::vector homework; 19 | }; 20 | 21 | bool compare(const Student_info&, const Student_info&); 22 | #endif -------------------------------------------------------------------------------- /Chapter 09/Student_info_pf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Student_info_pf.h" 3 | 4 | using std::istream; 5 | 6 | Student_info::Student_info(): midterm(0), final(0) { } 7 | Student_info::Student_info(istream& is) { read(is); } 8 | 9 | istream& Student_info::read(istream& in) 10 | { 11 | in >> n >> midterm >> final; 12 | return in; 13 | } 14 | 15 | char Student_info::grade() const 16 | { 17 | return ((midterm + final) / 2) > 60 ? 'P' : 'F'; 18 | } 19 | 20 | // code is taken from §9.3.1/162 21 | bool compare(const Student_info& x, const Student_info& y) 22 | { 23 | return x.name() < y.name(); 24 | } -------------------------------------------------------------------------------- /Chapter 09/Student_info_pf.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | 6 | class Student_info { 7 | public: 8 | Student_info(); 9 | Student_info(std::istream&); 10 | std::string name() const { return n; } 11 | std::istream& read(std::istream&); 12 | char grade() const; 13 | private: 14 | std::string n; 15 | double midterm, final; 16 | }; 17 | 18 | bool compare(const Student_info&, const Student_info&); 19 | #endif -------------------------------------------------------------------------------- /Chapter 09/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info_ex.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::vector; 15 | using std::string; 16 | using std::max; 17 | using std::streamsize; 18 | using std::sort; 19 | 20 | // code is taken from §9.6/166 21 | int main() 22 | { 23 | vector students; 24 | Student_info record; 25 | string::size_type maxlen = 0; 26 | 27 | // read and store the data 28 | while (record.read(cin)) { 29 | maxlen = max(maxlen, record.name().size()); 30 | students.push_back(record); 31 | } 32 | 33 | // alphabetize the student records 34 | sort(students.begin(), students.end(), compare); 35 | 36 | // write the names and grades 37 | for (vector::size_type i = 0; 38 | i != students.size(); ++i) { 39 | cout << students[i].name() 40 | << string(maxlen + 1 - students[i].name().size(), ' '); 41 | try { 42 | double final_grade = students[i].grade(); 43 | streamsize prec = cout.precision(); 44 | cout << setprecision(3) << final_grade 45 | << setprecision(prec) << endl; 46 | } catch (domain_error e) { 47 | cout << e.what() << endl; 48 | } 49 | } 50 | return 0; 51 | } -------------------------------------------------------------------------------- /Chapter 09/q03-1.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | 3 | int main() 4 | { 5 | Student_info student; 6 | student.grade(); 7 | 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Chapter 09/q03-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::domain_error; 8 | 9 | int main() 10 | { 11 | Student_info student; 12 | 13 | try { 14 | student.grade(); 15 | } 16 | catch(domain_error e) { 17 | cout << e.what() << endl; 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 09/q04.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | 3 | int main() 4 | { 5 | Student_info student; 6 | 7 | if (student.valid()) 8 | student.grade(); 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter 09/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info_pf.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::vector; 15 | using std::string; 16 | using std::max; 17 | using std::streamsize; 18 | using std::sort; 19 | 20 | int main() 21 | { 22 | vector students; 23 | Student_info record; 24 | string::size_type maxlen = 0; 25 | 26 | // read and store the data 27 | while (record.read(cin)) { 28 | maxlen = max(maxlen, record.name().size()); 29 | students.push_back(record); 30 | } 31 | 32 | // alphabetize the student records 33 | sort(students.begin(), students.end(), compare); 34 | 35 | // write the names and grades 36 | for (vector::size_type i = 0; 37 | i != students.size(); ++i) { 38 | cout << students[i].name() 39 | << string(maxlen + 1 - students[i].name().size(), ' '); 40 | 41 | streamsize prec = cout.precision(); 42 | cout << setprecision(3) << students[i].grade() 43 | << setprecision(prec) << endl; 44 | } 45 | return 0; 46 | } -------------------------------------------------------------------------------- /Chapter 09/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info_pf.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::vector; 15 | using std::string; 16 | using std::max; 17 | using std::streamsize; 18 | using std::sort; 19 | 20 | int main() 21 | { 22 | vector students; 23 | Student_info record; 24 | string::size_type maxlen = 0; 25 | 26 | // read and store the data 27 | while (record.read(cin)) { 28 | maxlen = max(maxlen, record.name().size()); 29 | students.push_back(record); 30 | } 31 | 32 | // alphabetize the student records 33 | sort(students.begin(), students.end(), compare); 34 | 35 | 36 | vector passes, fails; 37 | for (vector::size_type i = 0; 38 | i != students.size(); ++i) { 39 | if (students[i].grade() == 'F') 40 | fails.push_back(students[i]); 41 | else 42 | (passes.push_back(students[i])); 43 | } 44 | 45 | // write the names and grades of passing students 46 | for (vector::size_type i = 0; 47 | i != passes.size(); ++i) { 48 | cout << passes[i].name() 49 | << string(maxlen + 1 - passes[i].name().size(), ' '); 50 | 51 | streamsize prec = cout.precision(); 52 | cout << setprecision(3) << passes[i].grade() 53 | << setprecision(prec) << endl; 54 | } 55 | 56 | // write the names and grades of failing students 57 | for (vector::size_type i = 0; 58 | i != fails.size(); ++i) { 59 | cout << fails[i].name() 60 | << string(maxlen + 1 - fails[i].name().size(), ' '); 61 | 62 | streamsize prec = cout.precision(); 63 | cout << setprecision(3) << fails[i].grade() 64 | << setprecision(prec) << endl; 65 | } 66 | return 0; 67 | } -------------------------------------------------------------------------------- /Chapter 10/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Rewrite the student-grading program from §9.6/166 to generate letter grades. 7 | The rewritten student-grading program can be found in [q01.cpp](./q01.cpp). 8 | 9 | ### Q2: Rewrite the `median` function from §8.1.1/140 so that we can call it with either a `vector` or a built-in array. The function should allow containers of any arithmetic type. 10 | The rewritten `median` function can be found in [q02.cpp](./q02.cpp). It allows arrays or `vector`s of any arithmetic type by accepting `Random-access iterator`s instead of `vector`. 11 | 12 | ### Q3: Write a test program to verify that the `median` function operates correctly. Ensure that calling `median` does not change the order of the elements in the container. 13 | The test program can be found in [q03.cpp](./q03.cpp). It is shown that calling `median` does not change the order of the elements in the container. 14 | 15 | ### Q4: Write a class that implements a list that holds `string`s. 16 | The `String_list` class implementation can be found in [String_list.cpp](./String_list.cpp). The driver program can be found in [q04.cpp](./q04.cpp). 17 | 18 | ### Q5: Write a bidirectional iterator for your `String_list` class. 19 | The bidirectional iterator is added to [String_list.h](./String_list.h). It is simply a `typedef` for the `string` pointer. The driver program can be found in [q05.cpp](./q05.cpp). 20 | 21 | ### Q6: Test the class by rewriting the `split` function to put its output into a `String_list`. 22 | The rewritten `split` function can be found in [split.cpp](./q02.cpp). The driver program can be found in [q06.cpp](./q06.cpp). -------------------------------------------------------------------------------- /Chapter 10/String_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "String_list.h" 3 | 4 | using std::string; 5 | using std::copy; 6 | 7 | String_list::String_list(): length(0), values(new string[0]) { } 8 | 9 | void String_list::push_back(string s) 10 | { 11 | string* old_values = values; 12 | 13 | // increment the length 14 | ++length; 15 | 16 | // create a new string array with the new length 17 | string* new_values = new string[length]; 18 | 19 | // copy and delete the old values 20 | copy(old_values, old_values + length - 1, new_values); 21 | delete[] old_values; 22 | 23 | // set the new values 24 | values = new_values; 25 | values[length - 1] = s; 26 | } 27 | 28 | string String_list::pop_back() 29 | { 30 | string* old_values = values; 31 | 32 | // decrement the length 33 | --length; 34 | 35 | // hold the return value 36 | string ret = *end(); 37 | 38 | // create a new string array with the new length 39 | string* new_values = new string[length]; 40 | 41 | // copy and delete the old values 42 | copy(old_values, old_values + length, new_values); 43 | delete[] old_values; 44 | 45 | // set the new values 46 | values = new_values; 47 | 48 | return ret; 49 | } -------------------------------------------------------------------------------- /Chapter 10/String_list.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_String_list 2 | #define GUARD_String_list 3 | 4 | #include 5 | 6 | class String_list { 7 | public: 8 | typedef size_t size_type; 9 | typedef std::string* iterator; // Question 5 10 | String_list(); 11 | std::string* begin() const { return values; } 12 | std::string* end() const { return values + length; } 13 | size_type size() const { return length; } 14 | void push_back(std::string); 15 | std::string pop_back(); 16 | private: 17 | std::string* values; 18 | size_type length; 19 | }; 20 | #endif -------------------------------------------------------------------------------- /Chapter 10/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../Chapter 09/Student_info.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::vector; 15 | using std::string; 16 | using std::max; 17 | using std::streamsize; 18 | 19 | // code is taken from §10.3/178 20 | string letter_grade(double grade) 21 | { 22 | // range posts for numeric grades 23 | static const double numbers[] = { 24 | 97, 94, 90, 87, 84, 80, 77, 74, 70, 60, 0 25 | }; 26 | 27 | // names for the letter grades 28 | static const char* const letters[] = { 29 | "A+", "A", "A-", "B+", "B", "B-", "C+", "C", "C-", "D", "F" 30 | }; 31 | 32 | // compute the number of grades given the size of the array 33 | // and the size of a single element 34 | static const size_t ngrades = sizeof(numbers)/sizeof(*numbers); 35 | 36 | // given a numeric grade, find and return the associated letter grade 37 | for (size_t i = 0; i < ngrades; ++i) { 38 | if (grade >= numbers[i]) 39 | return letters[i]; 40 | } 41 | 42 | return "?\?\?"; 43 | } 44 | 45 | int main() 46 | { 47 | vector students; 48 | Student_info record; 49 | string::size_type maxlen = 0; 50 | 51 | // read and store the data 52 | while (record.read(cin)) { 53 | maxlen = max(maxlen, record.name().size()); 54 | students.push_back(record); 55 | } 56 | 57 | // alphabetize the student records 58 | sort(students.begin(), students.end(), compare); 59 | 60 | // write the names and grades 61 | for (vector::size_type i = 0; 62 | i != students.size(); ++i) { 63 | cout << students[i].name() 64 | << string(maxlen + 1 - students[i].name().size(), ' '); 65 | try { 66 | double final_grade = students[i].grade(); 67 | streamsize prec = cout.precision(); 68 | cout << setprecision(3) << letter_grade(final_grade) 69 | << setprecision(prec) << endl; 70 | } catch (domain_error e) { 71 | cout << e.what() << endl; 72 | } 73 | } 74 | return 0; 75 | } -------------------------------------------------------------------------------- /Chapter 10/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::domain_error; 6 | using std::vector; 7 | using std::sort; 8 | 9 | template 10 | T median(Ran b, Ran e) 11 | { 12 | vector v(b, e); 13 | 14 | typedef typename vector::size_type vec_sz; 15 | 16 | vec_sz size = v.size(); 17 | if (size == 0) 18 | throw domain_error("median of an empty container"); 19 | 20 | sort(v.begin(), v.end()); 21 | 22 | size_t mid = size / 2; 23 | 24 | return size % 2 == 0 ? (v[mid] + v[mid - 1]) / 2 : v[mid]; 25 | } -------------------------------------------------------------------------------- /Chapter 10/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "q02.cpp" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::vector; 8 | 9 | int main() 10 | { 11 | // initialize the array 12 | double double_arr[] = { 13 | 7.5, 2.2, 1.5, 6.4, 4.9, 5.8, 9.4 14 | }; 15 | size_t double_arr_length = sizeof(double_arr) / sizeof(*double_arr); 16 | 17 | // initialize the vector from the array 18 | vector double_vec(double_arr, double_arr + double_arr_length); 19 | 20 | // print the initial values of the array 21 | cout << "Initial values of the array: " << double_arr[0]; 22 | for (size_t i = 1; i < double_arr_length; ++i) 23 | cout << ", " << double_arr[i]; 24 | 25 | // print the initial values of the vector 26 | cout << endl << "Initial values of the vector: " << double_vec[0]; 27 | for (size_t i = 1; i < double_vec.size(); ++i) 28 | cout << ", " << double_vec[i]; 29 | 30 | // print the median values 31 | cout << endl << "The median value for the array: " 32 | << median(double_arr, double_arr + double_arr_length); 33 | cout << endl << "The median value for the vector: " 34 | << median(double_vec.begin(), double_vec.end()) << endl; 35 | 36 | // print the final values of the array 37 | cout << "Final values of the array: " << double_arr[0]; 38 | for (size_t i = 1; i < double_arr_length; ++i) 39 | cout << ", " << double_arr[i]; 40 | 41 | // print the final values of the vector 42 | cout << endl << "Final values of the vector: " << double_vec[0]; 43 | for (size_t i = 1; i < double_vec.size(); ++i) 44 | cout << ", " << double_vec[i]; 45 | 46 | return 0; 47 | } -------------------------------------------------------------------------------- /Chapter 10/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "String_list.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | 8 | int main() 9 | { 10 | // initialize a list 11 | String_list list; 12 | list.push_back("test"); 13 | list.push_back("list"); 14 | list.push_back("string"); 15 | 16 | // print the values reversed 17 | cout << "values are: " << list.pop_back(); 18 | while (list.size() > 0) 19 | cout << ", " << list.pop_back(); 20 | 21 | cout << endl; 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /Chapter 10/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "String_list.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::string; 8 | 9 | int main() 10 | { 11 | // initialize a list 12 | String_list list; 13 | list.push_back("test"); 14 | list.push_back("list"); 15 | list.push_back("string"); 16 | 17 | // print the values 18 | String_list::iterator it = list.begin(); 19 | cout << "Values: " << *it; 20 | ++it; 21 | while (it != list.end()) { 22 | cout << ", " << *it; 23 | ++it; 24 | } 25 | cout << endl; 26 | 27 | // print the values reversed 28 | it = list.end(); 29 | cout << "Values: " << *--it; 30 | while (it > list.begin()) { 31 | cout << ", " << *--it; 32 | } 33 | cout << endl; 34 | 35 | return 0; 36 | } -------------------------------------------------------------------------------- /Chapter 10/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "String_list.h" 4 | #include "split.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::string; 9 | 10 | int main() 11 | { 12 | // split the sentence into a String_list 13 | string sentence = "string list test"; 14 | String_list list = split(sentence); 15 | 16 | // print the results 17 | String_list::iterator it = list.begin(); 18 | cout << "Values: " << *it; 19 | ++it; 20 | while (it != list.end()) { 21 | cout << ", " << *it; 22 | ++it; 23 | } 24 | cout << endl; 25 | } -------------------------------------------------------------------------------- /Chapter 10/split.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "String_list.h" 3 | 4 | using std::string; 5 | 6 | String_list split(const string& s) 7 | { 8 | String_list ret; 9 | typedef String_list::size_type string_size; 10 | string_size i = 0; 11 | 12 | // invariant: we have processed characters [original value of i, i) 13 | while (i != s.size()) { 14 | // ignore leading blanks 15 | // invariant: characters in range [original i, current i) are all spaces 16 | while (i != s.size() && isspace(s[i])) 17 | ++i; 18 | 19 | // find end of next word 20 | string_size j = i; 21 | // invariant: none of the characters in range [original j, current j) is a space 22 | while (j != s.size() && !isspace(s[j])) 23 | ++j; 24 | 25 | // if we found some nonwhitespace characters 26 | if (i != j) { 27 | // copy from s starting at i and taking j - i chars 28 | ret.push_back(s.substr(i, j - i)); 29 | i = j; 30 | } 31 | } 32 | return ret; 33 | } -------------------------------------------------------------------------------- /Chapter 10/split.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_split_h 2 | #define GUARD_split_h 3 | 4 | #include 5 | #include "String_list.h" 6 | 7 | String_list split(const std::string&); 8 | #endif -------------------------------------------------------------------------------- /Chapter 11/Lis.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Lis 2 | #define GUARD_Lis 3 | 4 | #include 5 | 6 | template class Node { 7 | public: 8 | T value; 9 | Node* next; 10 | Node* prev; 11 | 12 | Node() : value(0), next(0), prev(0) { } 13 | Node(T t) : value(t), next(0), prev(0) { } 14 | }; 15 | 16 | template class NodeItr { 17 | public: 18 | NodeItr& operator++(); 19 | NodeItr& operator--(); 20 | NodeItr operator++(int); 21 | NodeItr operator--(int); 22 | T& operator*() const { return node->value; } 23 | bool operator!=(const NodeItr& rhs) const { return node != rhs.node; } 24 | 25 | NodeItr(Node* n) : node(n) { } 26 | private: 27 | Node* node; 28 | }; 29 | 30 | template NodeItr& NodeItr::operator++() 31 | { 32 | node = node->next; 33 | return *this; 34 | } 35 | template NodeItr& NodeItr::operator--() 36 | { 37 | node = node->prev; 38 | return *this; 39 | } 40 | template NodeItr NodeItr::operator++(int) 41 | { 42 | NodeItr ret(node); 43 | node = node->next; 44 | return ret; 45 | } 46 | template NodeItr NodeItr::operator--(int) 47 | { 48 | NodeItr ret(node); 49 | node = node->prev; 50 | return ret; 51 | } 52 | 53 | template class Lis { 54 | public: 55 | typedef NodeItr iterator; 56 | typedef const NodeItr const_iterator; 57 | typedef size_t size_type; 58 | 59 | Lis() : b(0), e(0), s(0) { } 60 | explicit Lis(size_type n, const T& t = T()) { create(n, t); } 61 | Lis(const Lis& v) { create(v.begin(), v.end()); } 62 | Lis& operator=(const Lis&); 63 | ~Lis() { uncreate(); } 64 | 65 | void push_back(const T& t); 66 | size_type size() const { return s; } 67 | 68 | iterator begin() { return b; } 69 | const_iterator begin() const { return b; } 70 | 71 | iterator end() { return 0; } 72 | const_iterator end() const { return 0; } 73 | 74 | void clear() { uncreate(); } 75 | bool empty() const { return s == 0; } 76 | private: 77 | Node* b; 78 | Node* e; 79 | size_type s; 80 | 81 | // allocate and initialize the underlying array 82 | void create(size_type, const T&); 83 | void create(const_iterator, const_iterator); 84 | 85 | // destroy the elements in the array and free the memory 86 | void uncreate(); 87 | }; 88 | 89 | template 90 | void Lis::push_back(const T& t) 91 | { 92 | Node* node = new Node(t); 93 | 94 | if (s == 0) 95 | b = e = node; 96 | else { 97 | e->next = node; 98 | node->prev = e; 99 | e = node; 100 | } 101 | s++; 102 | } 103 | 104 | template 105 | void Lis::create(size_type s, const T& t) 106 | { 107 | for (size_type i = 0; i < s; i++) 108 | push_back(t); 109 | } 110 | 111 | template 112 | void Lis::create(iterator b, iterator e) 113 | { 114 | while (b != e) 115 | push_back(*b++); 116 | } 117 | 118 | template 119 | void Lis::uncreate() 120 | { 121 | Node* node = e; 122 | 123 | while (node != b) 124 | { 125 | Node* node_delete = node; 126 | node = node->prev; 127 | delete node_delete; 128 | } 129 | 130 | b = e = 0; 131 | s = 0; 132 | } 133 | #endif -------------------------------------------------------------------------------- /Chapter 11/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: The `Student_info` structure that we defined in Chapter 9 did not define a copy constructor, assignment operator, or destructor. Why not? 7 | As the synthesized operators for the class implemented the operations that we would implement, not defining them made no difference in the class behavior. Copying, destroying, and assigning the name and the grades were synthesized automatically by the compiler. 8 | 9 | ### Q2: That structure did define a default constructor. Why? 10 | If we did not have a default constructor, the `midterm` and `final` grades would be default-initialized, meaning they would have random data from the memory they were created in, resulting in unwanted errors. 11 | 12 | ### Q3: What does the synthesized assignment operator for `Student_info` objects do? 13 | The synthesized assignment operator copies the values of the `midterm`, `final`, and `n` to the assigned object. It also creates a new `vector` filled with the homework grades of the source object. 14 | 15 | ### Q4: How many members does the synthesized `Student_info` destructor destroy? 16 | Destructor destroys 4 members, `midterm`, `final`, `n`, an the entire `vector`. 17 | 18 | ### Q5: Instrument the `Student_info` class to count how often objects are created, copied, assigned, and destroyed. Use this instrumented class to execute the student record programs from Chapter 6. Using the instrumented `Student_info` class will let you see how you estimate what proportion of the cost differences we saw are accounted for by the use of each library class. Do this instrumentation and analysis. 19 | The instrumented `Student_info` class can be found in [Student_info.cpp](./Student_info.cpp). When creating, copying, assigning, and destroying a class, the respective operation is printed to `cout`. The modified programs from Chapter 6 can be found in [q05-1.cpp](./q05-1.cpp), [q05-2.cpp](./q05-2.cpp), [q05-3.cpp](./q05-3.cpp), and [q05-4.cpp](./q05-4.cpp). 20 | 21 | ### Q6: Add an operation to remove an element from a `Vec` and another to empty the entire `Vec`. These should behave analogously to the `erase` and `clear` options on `vector`s. 22 | `erase` and `clear` functions were added to [Vec.h](./Vec.h). 23 | 24 | ### Q7: Once you've added `erase` and `clear` to `Vec`, you can use that class instead of `vector` in most of the earlier programs in this book. Rewrite the `Student_info` programs from Chapter 9 and the programs that work with character pictures from Chapter 5 to use `Vec`s instead of `vector`s. 25 | The rewritten programs from Chapter 6 can be found in [q07-1.cpp](./q07-1.cpp), [q07-2.cpp](./q07-2.cpp), [q07-3.cpp](./q07-3.cpp), [q07-4.cpp](./q07-4.cpp), 26 | [q07-5.cpp](./q07-5.cpp), [q07-6.cpp](./q07-6.cpp), and [q07-7.cpp](./q07-7.cpp). 27 | 28 | ### Q8: Write a simplified version of the standard `list` class and its associated iterator. 29 | A simplified version of the `list` class can be found in [Lis.h](./Lis.h). The test function for the `Lis` class can be found in [q08.cpp](./q08.cpp). 30 | 31 | ### Q9: The `grow` function in §11.5.1/208 doubles the amount of memory each time it needs more. Estimate the efficiency gains of this strategy. Once you've predicted how much of a difference it makes, change the `grow` function appropriately and measure the difference. 32 | The difference of growing one by one and doubling the memory can be observed in [q09.cpp](./q09.cpp). For 10,000 integers, doubling the memory and pushing took 0.001 seconds. Growing memory one by one and pushing took 17.025 seconds. -------------------------------------------------------------------------------- /Chapter 11/Student_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 04/grade.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::istream; 9 | using std::vector; 10 | using std::copy; 11 | 12 | Student_info::Student_info(): midterm(0), final(0) 13 | { 14 | cout << "create" << endl; 15 | } 16 | Student_info::Student_info(istream& is) 17 | { 18 | cout << "create" << endl; 19 | read(is); 20 | } 21 | 22 | Student_info::Student_info(const Student_info& s) 23 | { 24 | cout << "copy" << endl; 25 | this->n = s.n; 26 | this->midterm = s.midterm; 27 | this->final = s.final; 28 | this->homework = s.homework; 29 | } 30 | 31 | Student_info& Student_info::operator=(const Student_info& rhs) 32 | { 33 | cout << "assign" << endl; 34 | this->n = rhs.n; 35 | this->midterm = rhs.midterm; 36 | this->final = rhs.final; 37 | copy(rhs.homework.begin(), rhs.homework.end(), this->homework.begin()); 38 | return *this; 39 | } 40 | 41 | Student_info::~Student_info() 42 | { 43 | cout << "destroy" << endl; 44 | } 45 | 46 | // code is taken from §4.1.3/57 47 | istream& read_hw(istream& in, vector& hw) 48 | { 49 | if (in) { 50 | // get rid of previous contetns 51 | hw.clear(); 52 | 53 | // read homework grades 54 | double x; 55 | while (in >> x) 56 | hw.push_back(x); 57 | 58 | // clear the stream so that input will work for the next student 59 | in.clear(); 60 | } 61 | return in; 62 | } 63 | 64 | // code is taken from §9.2.1/157 65 | istream& Student_info::read(istream& in) 66 | { 67 | in >> n >> midterm >> final; 68 | read_hw(in, homework); 69 | return in; 70 | } 71 | 72 | // code is taken from §9.3.1/158 73 | double Student_info::grade() const 74 | { 75 | return ::grade(midterm, final, homework); 76 | } 77 | 78 | // code is taken from §9.3.1/162 79 | bool compare(const Student_info& x, const Student_info& y) 80 | { 81 | return x.name() < y.name(); 82 | } -------------------------------------------------------------------------------- /Chapter 11/Student_info.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | #include 6 | 7 | class Student_info { 8 | public: 9 | Student_info(); 10 | Student_info(std::istream&); 11 | Student_info(const Student_info&); 12 | Student_info& operator=(const Student_info&); 13 | ~Student_info(); 14 | std::string name() const { return n; } 15 | bool valid() const { return !homework.empty(); } 16 | std::istream& read(std::istream&); 17 | double grade() const; 18 | private: 19 | std::string n; 20 | double midterm, final; 21 | std::vector homework; 22 | }; 23 | 24 | bool compare(const Student_info&, const Student_info&); 25 | #endif -------------------------------------------------------------------------------- /Chapter 11/Student_info_ex_vec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Student_info_ex_vec.h" 3 | #include "grade.h" 4 | 5 | using std::istream; 6 | 7 | Student_info::Student_info(): midterm(0), final(0) { } 8 | Student_info::Student_info(istream& is) { read(is); } 9 | 10 | istream& read_hw(istream& in, Vec& hw) 11 | { 12 | if (in) { 13 | // get rid of previous contetns 14 | hw.clear(); 15 | 16 | // read homework grades 17 | double x; 18 | while (in >> x) 19 | hw.push_back(x); 20 | 21 | // clear the stream so that input will work for the next student 22 | in.clear(); 23 | } 24 | return in; 25 | } 26 | 27 | istream& Student_info::read(istream& in) 28 | { 29 | in >> n >> midterm >> final; 30 | read_hw(in, homework); 31 | g = ::grade(midterm, final, homework); 32 | return in; 33 | } 34 | 35 | // code is taken from §9.3.1/162 36 | bool compare(const Student_info& x, const Student_info& y) 37 | { 38 | return x.name() < y.name(); 39 | } -------------------------------------------------------------------------------- /Chapter 11/Student_info_ex_vec.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include "Vec.h" 5 | #include 6 | 7 | class Student_info { 8 | public: 9 | Student_info(); 10 | Student_info(std::istream&); 11 | std::string name() const { return n; } 12 | bool valid() const { return !homework.empty(); } 13 | std::istream& read(std::istream&); 14 | double grade() const { return g; }; 15 | private: 16 | std::string n; 17 | double g, midterm, final; 18 | Vec homework; 19 | }; 20 | 21 | bool compare(const Student_info&, const Student_info&); 22 | #endif -------------------------------------------------------------------------------- /Chapter 11/Student_info_pf_vec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Student_info_pf_vec.h" 3 | 4 | using std::istream; 5 | 6 | Student_info::Student_info(): midterm(0), final(0) { } 7 | Student_info::Student_info(istream& is) { read(is); } 8 | 9 | istream& Student_info::read(istream& in) 10 | { 11 | in >> n >> midterm >> final; 12 | return in; 13 | } 14 | 15 | char Student_info::grade() const 16 | { 17 | return ((midterm + final) / 2) > 60 ? 'P' : 'F'; 18 | } 19 | 20 | // code is taken from §9.3.1/162 21 | bool compare(const Student_info& x, const Student_info& y) 22 | { 23 | return x.name() < y.name(); 24 | } -------------------------------------------------------------------------------- /Chapter 11/Student_info_pf_vec.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | 6 | class Student_info { 7 | public: 8 | Student_info(); 9 | Student_info(std::istream&); 10 | std::string name() const { return n; } 11 | std::istream& read(std::istream&); 12 | char grade() const; 13 | private: 14 | std::string n; 15 | double midterm, final; 16 | }; 17 | 18 | bool compare(const Student_info&, const Student_info&); 19 | #endif -------------------------------------------------------------------------------- /Chapter 11/Student_info_vec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vec.h" 3 | #include "Student_info_vec.h" 4 | #include "grade.h" 5 | 6 | using std::istream; 7 | 8 | Student_info::Student_info(): midterm(0), final(0) { } 9 | Student_info::Student_info(istream& is) { read(is); } 10 | 11 | istream& read_hw(istream& in, Vec& hw) 12 | { 13 | if (in) { 14 | // get rid of previous contetns 15 | hw.clear(); 16 | 17 | // read homework grades 18 | double x; 19 | while (in >> x) 20 | hw.push_back(x); 21 | 22 | // clear the stream so that input will work for the next student 23 | in.clear(); 24 | } 25 | return in; 26 | } 27 | 28 | // code is taken from §9.2.1/157 29 | istream& Student_info::read(istream& in) 30 | { 31 | in >> n >> midterm >> final; 32 | read_hw(in, homework); 33 | return in; 34 | } 35 | 36 | // code is taken from §9.3.1/158 37 | double Student_info::grade() const 38 | { 39 | return ::grade(midterm, final, homework); 40 | } 41 | 42 | // code is taken from §9.3.1/162 43 | bool compare(const Student_info& x, const Student_info& y) 44 | { 45 | return x.name() < y.name(); 46 | } -------------------------------------------------------------------------------- /Chapter 11/Student_info_vec.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include "Vec.h" 5 | #include 6 | 7 | class Student_info { 8 | public: 9 | Student_info(); 10 | Student_info(std::istream&); 11 | std::string name() const { return n; } 12 | bool valid() const { return !homework.empty(); } 13 | std::istream& read(std::istream&); 14 | double grade() const; 15 | private: 16 | std::string n; 17 | double midterm, final; 18 | Vec homework; 19 | }; 20 | 21 | bool compare(const Student_info&, const Student_info&); 22 | #endif -------------------------------------------------------------------------------- /Chapter 11/grade.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vec.h" 3 | #include "grade.h" 4 | #include "median.h" 5 | 6 | using std::domain_error; 7 | 8 | // code taken from §4.1/52 9 | // compute a student's overall grade from midterm and final exam grades and homework grade 10 | double grade(double midterm, double final, double homework) 11 | { 12 | return 0.2 * midterm + 0.4 * final + 0.4 * homework; 13 | } 14 | 15 | // compute a student's overall grade from midterm and final exam grades 16 | // and vector of homework grades. 17 | // this function does not copy its argument, because median does so for us. 18 | double grade(double midterm, double final, const Vec& hw) 19 | { 20 | if (hw.size() == 0) 21 | throw domain_error("student has done no homework"); 22 | return grade(midterm, final, median(hw)); 23 | } -------------------------------------------------------------------------------- /Chapter 11/grade.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_grade_h 2 | #define GUARD_grade_h 3 | 4 | #include "Vec.h" 5 | 6 | double grade(double, double, double); 7 | double grade(double, double, const Vec&); 8 | #endif -------------------------------------------------------------------------------- /Chapter 11/median.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "median.h" 4 | #include "Vec.h" 5 | 6 | using std::domain_error; 7 | using std::sort; 8 | 9 | // code is taken from §4.1.1/53 10 | // compute the median of a vector 11 | // note that calling this function copies the entire argument vector 12 | double median(Vec vec) 13 | { 14 | typedef Vec::size_type vec_sz; 15 | 16 | vec_sz size = vec.size(); 17 | if (size == 0) 18 | throw domain_error("median of an empty vector"); 19 | 20 | sort(vec.begin(), vec.end()); 21 | 22 | vec_sz mid = size/2; 23 | 24 | return size % 2 == 0 ? (vec[mid] + vec[mid-1]) / 2 : vec[mid]; 25 | } 26 | -------------------------------------------------------------------------------- /Chapter 11/median.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_median_h 2 | #define GUARD_median_h 3 | 4 | #include "Vec.h" 5 | 6 | double median(Vec); 7 | #endif -------------------------------------------------------------------------------- /Chapter 11/q05-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 06/analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | // code is taken from §6.2.2/114 12 | int main() 13 | { 14 | // students who did and didn't do all their homework 15 | vector did, didnt; 16 | 17 | // read the student records and partition them 18 | Student_info student; 19 | // read all student data 20 | while (student.read(cin)) { 21 | if (did_all_hw(student)) 22 | did.push_back(student); 23 | else 24 | didnt.push_back(student); 25 | } 26 | 27 | // verify that the analyses will show us something 28 | if (did.empty()) { 29 | cout << "No student did all the homework!" << endl; 30 | return 1; 31 | } 32 | if (didnt.empty()) { 33 | cout << "Every student did all the homework!" << endl; 34 | return 1; 35 | } 36 | 37 | // do the analyses 38 | write_analysis(cout, "median", median_analysis, did, didnt); 39 | write_analysis(cout, "average", average_analysis, did, didnt); 40 | write_analysis(cout, "median of homework turned in", 41 | optimistic_median_analysis, did, didnt); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter 11/q05-2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 06/analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | // code is taken from §6.2.2/114 12 | int main() 13 | { 14 | // students who did and didn't do all their homework 15 | vector did, didnt; 16 | 17 | // read the student records and partition them 18 | Student_info student; 19 | // read all student data 20 | while (student.read(cin)) { 21 | if (did_all_hw(student)) 22 | did.push_back(student); 23 | else 24 | didnt.push_back(student); 25 | } 26 | 27 | // verify that the analyses will show us something 28 | if (did.empty()) { 29 | cout << "No student did all the homework!" << endl; 30 | return 1; 31 | } 32 | if (didnt.empty()) { 33 | cout << "Every student did all the homework!" << endl; 34 | return 1; 35 | } 36 | 37 | // do the analyses 38 | write_analysis(cout, "median", grade_aux, did, didnt); 39 | write_analysis(cout, "average", average_grade, did, didnt); 40 | write_analysis(cout, "median of homework turned in", 41 | optimistic_median, did, didnt); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /Chapter 11/q05-3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 06/analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | vector extract_didnt(vector& students) 12 | { 13 | vector didnt; 14 | vector::iterator it = students.begin(); 15 | 16 | while (it != students.end()) { 17 | if (!did_all_hw(*it)) { 18 | didnt.push_back(*it); 19 | it = students.erase(it); 20 | } else 21 | ++it; 22 | } 23 | return didnt; 24 | } 25 | 26 | int main() 27 | { 28 | vector students; 29 | Student_info student; 30 | 31 | // read all student data 32 | while (student.read(cin)) 33 | students.push_back(student); 34 | 35 | // extract students who did not do their homework 36 | vector didnt = extract_didnt(students); 37 | 38 | // write the results 39 | cout << "Students who did all their homework are: "; 40 | for (vector::const_iterator it = students.begin(); 41 | it != students.end(); ++it) 42 | cout << it->name() << (it + 1 == students.end() ? "." : ", "); 43 | cout << endl; 44 | 45 | cout << "Students who did not do all their homework are: "; 46 | for (vector::const_iterator it = didnt.begin(); 47 | it != didnt.end(); ++it) 48 | cout << it->name() << (it + 1 == didnt.end() ? "." : ", "); 49 | cout << endl; 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 11/q05-4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | #include "../Chapter 06/analysis.h" 5 | 6 | using std::vector; 7 | using std::cout; 8 | using std::cin; 9 | using std::endl; 10 | 11 | bool fgrade(const Student_info& s) 12 | { 13 | return optimistic_median(s) < 60; 14 | } 15 | 16 | // code is taken from §5.3/62 17 | vector extract_fails(vector& students) 18 | { 19 | vector fail; 20 | vector::iterator iter = students.begin(); 21 | 22 | while (iter != students.end()) { 23 | if (fgrade(*iter)) { 24 | fail.push_back(*iter); 25 | iter = students.erase(iter); 26 | } else 27 | ++iter; 28 | } 29 | return fail; 30 | } 31 | 32 | int main() 33 | { 34 | vector students; 35 | Student_info student; 36 | 37 | // read all student data 38 | while (student.read(cin)) 39 | students.push_back(student); 40 | 41 | vector fails = extract_fails(students); 42 | 43 | // write the results 44 | cout << "Students who passed the class are: "; 45 | for (vector::const_iterator it = students.begin(); 46 | it != students.end(); ++it) 47 | cout << it->name() << (it + 1 == students.end() ? "." : ", "); 48 | cout << endl; 49 | 50 | cout << "Students who failed the class are: "; 51 | for (vector::const_iterator it = fails.begin(); 52 | it != fails.end(); ++it) 53 | cout << it->name() << (it + 1 == fails.end() ? "." : ", "); 54 | cout << endl; 55 | 56 | return 0; 57 | } -------------------------------------------------------------------------------- /Chapter 11/q07-1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Vec.h" 5 | #include 6 | #include 7 | #include "Student_info_ex_vec.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::string; 15 | using std::max; 16 | using std::streamsize; 17 | using std::sort; 18 | 19 | int main() 20 | { 21 | Vec students; 22 | Student_info record; 23 | string::size_type maxlen = 0; 24 | 25 | // read and store the data 26 | while (record.read(cin)) { 27 | maxlen = max(maxlen, record.name().size()); 28 | students.push_back(record); 29 | } 30 | 31 | // alphabetize the student records 32 | sort(students.begin(), students.end(), compare); 33 | 34 | // write the names and grades 35 | for (Vec::size_type i = 0; 36 | i != students.size(); ++i) { 37 | cout << students[i].name() 38 | << string(maxlen + 1 - students[i].name().size(), ' '); 39 | try { 40 | double final_grade = students[i].grade(); 41 | streamsize prec = cout.precision(); 42 | cout << setprecision(3) << final_grade 43 | << setprecision(prec) << endl; 44 | } catch (domain_error e) { 45 | cout << e.what() << endl; 46 | } 47 | } 48 | return 0; 49 | } -------------------------------------------------------------------------------- /Chapter 11/q07-2.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info_vec.h" 2 | 3 | int main() 4 | { 5 | Student_info student; 6 | student.grade(); 7 | 8 | return 0; 9 | } -------------------------------------------------------------------------------- /Chapter 11/q07-3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info_vec.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::domain_error; 8 | 9 | int main() 10 | { 11 | Student_info student; 12 | 13 | try { 14 | student.grade(); 15 | } 16 | catch(domain_error e) { 17 | cout << e.what() << endl; 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 11/q07-4.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info_vec.h" 2 | 3 | int main() 4 | { 5 | Student_info student; 6 | 7 | if (student.valid()) 8 | student.grade(); 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter 11/q07-5.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Vec.h" 5 | #include 6 | #include 7 | #include "Student_info_pf_vec.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::string; 15 | using std::max; 16 | using std::streamsize; 17 | using std::sort; 18 | 19 | int main() 20 | { 21 | Vec students; 22 | Student_info record; 23 | string::size_type maxlen = 0; 24 | 25 | // read and store the data 26 | while (record.read(cin)) { 27 | maxlen = max(maxlen, record.name().size()); 28 | students.push_back(record); 29 | } 30 | 31 | // alphabetize the student records 32 | sort(students.begin(), students.end(), compare); 33 | 34 | // write the names and grades 35 | for (Vec::size_type i = 0; 36 | i != students.size(); ++i) { 37 | cout << students[i].name() 38 | << string(maxlen + 1 - students[i].name().size(), ' '); 39 | 40 | streamsize prec = cout.precision(); 41 | cout << setprecision(3) << students[i].grade() 42 | << setprecision(prec) << endl; 43 | } 44 | return 0; 45 | } -------------------------------------------------------------------------------- /Chapter 11/q07-6.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Vec.h" 5 | #include 6 | #include 7 | #include "Student_info_pf_vec.h" 8 | 9 | using std::domain_error; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::endl; 13 | using std::cin; 14 | using std::string; 15 | using std::max; 16 | using std::streamsize; 17 | using std::sort; 18 | 19 | int main() 20 | { 21 | Vec students; 22 | Student_info record; 23 | string::size_type maxlen = 0; 24 | 25 | // read and store the data 26 | while (record.read(cin)) { 27 | maxlen = max(maxlen, record.name().size()); 28 | students.push_back(record); 29 | } 30 | 31 | // alphabetize the student records 32 | sort(students.begin(), students.end(), compare); 33 | 34 | 35 | Vec passes, fails; 36 | for (Vec::size_type i = 0; 37 | i != students.size(); ++i) { 38 | if (students[i].grade() == 'F') 39 | fails.push_back(students[i]); 40 | else 41 | (passes.push_back(students[i])); 42 | } 43 | 44 | // write the names and grades of passing students 45 | for (Vec::size_type i = 0; 46 | i != passes.size(); ++i) { 47 | cout << passes[i].name() 48 | << string(maxlen + 1 - passes[i].name().size(), ' '); 49 | 50 | streamsize prec = cout.precision(); 51 | cout << setprecision(3) << passes[i].grade() 52 | << setprecision(prec) << endl; 53 | } 54 | 55 | // write the names and grades of failing students 56 | for (Vec::size_type i = 0; 57 | i != fails.size(); ++i) { 58 | cout << fails[i].name() 59 | << string(maxlen + 1 - fails[i].name().size(), ' '); 60 | 61 | streamsize prec = cout.precision(); 62 | cout << setprecision(3) << fails[i].grade() 63 | << setprecision(prec) << endl; 64 | } 65 | return 0; 66 | } -------------------------------------------------------------------------------- /Chapter 11/q07-7.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Vec.h" 3 | #include 4 | 5 | using std::string; 6 | using std::max; 7 | using std::cout; 8 | using std::endl; 9 | 10 | // code taken from §5.8.1/92 11 | string::size_type width(const Vec& v) 12 | { 13 | string::size_type maxlen = 0; 14 | for (Vec::size_type i = 0; i != v.size(); ++i) 15 | maxlen = max(maxlen, v[i].size()); 16 | return maxlen; 17 | } 18 | 19 | // code taken from §5.8.3/95, modified to define s 20 | // outside the scope of the while 21 | Vec hcat(const Vec& left, const Vec& right) 22 | { 23 | Vec ret; 24 | 25 | // add 1 to leave a space between pictures 26 | string::size_type width1 = width(left) + 1; 27 | 28 | // indices to look at elements from left and right respectively 29 | Vec::size_type i = 0, j = 0; 30 | 31 | // define s here 32 | string s; 33 | 34 | while (i != left.size() || j != right.size()) { 35 | // copy a row from the left-hand side, if there is one 36 | if (i != left.size()) 37 | s = left[i++]; 38 | 39 | // pad to full width 40 | s += string(width1 - s.size(), ' '); 41 | 42 | // copy a row from the right-hand side, if there is one 43 | if (j != right.size()) 44 | s += right[j++]; 45 | 46 | // add s to the picture we're creating 47 | ret.push_back(s); 48 | } 49 | return ret; 50 | } 51 | 52 | int main() 53 | { 54 | Vec picture; 55 | // create a picture 56 | picture.push_back("*************"); 57 | picture.push_back("* hello *"); 58 | picture.push_back("* my name *"); 59 | picture.push_back("* is Altug! *"); 60 | picture.push_back("*************"); 61 | 62 | Vec another_picture; 63 | // create another picture to horizontally concatenate 64 | picture.push_back("***************"); 65 | picture.push_back("* I am *"); 66 | picture.push_back("* programming *"); 67 | picture.push_back("* in C++! *"); 68 | picture.push_back("***************"); 69 | 70 | // concatenate 71 | Vec result = hcat(picture, another_picture); 72 | // the code throws an exception if we switch the parameters 73 | // vector result = hcat(picture, another_picture); 74 | 75 | for (Vec::const_iterator line = result.begin(); 76 | line != result.end(); ++line) 77 | cout << *line << endl; 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /Chapter 11/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Lis.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Lis l; 10 | l.push_back(1); 11 | l.push_back(2); 12 | l.push_back(5); 13 | l.push_back(4); 14 | 15 | for (Lis::iterator it = l.begin(); 16 | it != l.end(); ++it) 17 | cout << *it << " "; 18 | cout << endl; 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 11/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vec.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | 8 | int main() 9 | { 10 | const Vec::size_type count = 100000; 11 | 12 | Vec v1, v2; 13 | 14 | // measure the time for doubling memory 15 | double begin = clock(); 16 | for (Vec::size_type i = 0; i < count; ++i) 17 | v1.push_back(i); 18 | double end = clock(); 19 | cout << "Doubling memory and pushing " << count << " integers took " 20 | << (end - begin) / CLOCKS_PER_SEC << " seconds." << endl; 21 | 22 | // measure the time for growing one by one 23 | begin = clock(); 24 | for (Vec::size_type i = 0; i < count; ++i) 25 | v2.push_back_grow_once(i); 26 | end = clock(); 27 | cout << "Growing memory one by one and pushing " << count 28 | << " integers took " << (end - begin) / CLOCKS_PER_SEC 29 | << " seconds." << endl; 30 | 31 | return 0; 32 | } -------------------------------------------------------------------------------- /Chapter 12/Str.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Str.h" 5 | 6 | using std::ostream; 7 | using std::istream; 8 | using std::ostream_iterator; 9 | using std::copy; 10 | 11 | // Q9 12 | ostream& operator<<(ostream& os, const Str& s) 13 | { 14 | copy(s.begin(), s.end(), ostream_iterator(os)); 15 | return os; 16 | } 17 | 18 | istream& operator>>(istream& is, Str& s) 19 | { 20 | // obliterate existing value(s) 21 | if (s.value != 0) 22 | delete[] s.value; 23 | 24 | // read and discard leading whitespace 25 | char c; 26 | while (is.get(c) && isspace(c)) 27 | ; // nothing to do, except testing the condition 28 | 29 | // if still something to read, do so until the next whitespace character 30 | if (is) { 31 | do s += c; 32 | while (is.get(c) && !isspace(c)); 33 | 34 | // if we read whitespace, then put it back on the stream 35 | if (is) 36 | is.unget(); 37 | } 38 | 39 | return is; 40 | } 41 | 42 | // code is taken from §12.3.3/219 43 | Str operator+(const Str& s, const Str& t) 44 | { 45 | Str r = s; 46 | r += t; 47 | return r; 48 | } 49 | 50 | // Q5 51 | Str operator+(const Str& s, const char* t) 52 | { 53 | Str r = s; 54 | r += t; 55 | return r; 56 | } 57 | 58 | // Q11 59 | Str operator+(const char* t, const Str& s) 60 | { 61 | Str r(t); 62 | r += s; 63 | return r; 64 | } 65 | 66 | // Q3 67 | bool operator<(const Str& lhs, const Str& rhs) 68 | { 69 | return strcmp(lhs.c_str(), rhs.c_str()) < 0; 70 | } 71 | 72 | // Q3 73 | bool operator>(const Str& lhs, const Str& rhs) 74 | { 75 | return strcmp(lhs.c_str(), rhs.c_str()) > 0; 76 | } 77 | 78 | // Q3 79 | bool operator<=(const Str& lhs, const Str& rhs) 80 | { 81 | return strcmp(lhs.c_str(), rhs.c_str()) <= 0; 82 | } 83 | 84 | // Q3 85 | bool operator>=(const Str& lhs, const Str& rhs) 86 | { 87 | return strcmp(lhs.c_str(), rhs.c_str()) >= 0; 88 | } 89 | 90 | // Q4 91 | bool operator==(const Str& lhs, const Str& rhs) 92 | { 93 | return strcmp(lhs.c_str(), rhs.c_str()) == 0; 94 | } 95 | 96 | // Q4 97 | bool operator!=(const Str& lhs, const Str& rhs) 98 | { 99 | return strcmp(lhs.c_str(), rhs.c_str()) != 0; 100 | } 101 | 102 | // Q8 103 | istream& getline(istream& is, Str& s) 104 | { 105 | // read until newline 106 | char c; 107 | while (is.get(c) && c != '\n') 108 | s += c; 109 | 110 | return is; 111 | } -------------------------------------------------------------------------------- /Chapter 12/Str_Vec.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Str_Vec.h" 5 | 6 | using std::ostream; 7 | using std::istream; 8 | 9 | // code is taken from §12.3.1/216 10 | ostream& operator<<(ostream& os, const Str& s) 11 | { 12 | for (Str::size_type i = 0; i != s.size(); ++i) 13 | os << s[i]; 14 | return os; 15 | } 16 | 17 | // code is taken from §12.3.2/216 18 | istream& operator>>(istream& is, Str& s) 19 | { 20 | // obliterate existing value(s) 21 | s.data.clear(); 22 | 23 | // read and discard leading whitespace 24 | char c; 25 | while (is.get(c) && isspace(c)) 26 | ; // nothing to do, except testing the condition 27 | 28 | // if still something to read, do so until the next whitespace character 29 | if (is) { 30 | do s.data.push_back(c); 31 | while (is.get(c) && !isspace(c)); 32 | 33 | // if we read whitespace, then put it back on the stream 34 | if (is) 35 | is.unget(); 36 | } 37 | 38 | return is; 39 | } 40 | 41 | // code is taken from §12.3.3/219 42 | Str operator+(const Str& s, const Str& t) 43 | { 44 | Str r = s; 45 | r += t; 46 | return r; 47 | } -------------------------------------------------------------------------------- /Chapter 12/Str_Vec.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Str 2 | #define GUARD_Str 3 | 4 | #include 5 | #include 6 | #include "Vec.h" 7 | 8 | class Str { 9 | friend std::istream& operator>>(std::istream&, Str&); 10 | 11 | public: 12 | typedef Vec::size_type size_type; 13 | typedef char* iterator; // Q12 14 | typedef const char* const_iterator; // Q12 15 | 16 | // default constructor; create an empty Str 17 | Str() { } 18 | 19 | // create a Str containing n copies of c 20 | Str(size_type n, char c): data(n, c) { } 21 | 22 | // create a Str from a null-terminated array of char 23 | Str(const char* cp) { 24 | std::copy(cp, cp + std::strlen(cp), std::back_inserter(data)); 25 | } 26 | 27 | // create a Str from range denoted by iterators b and e 28 | template Str(In b, In e) : data(b, e) { } // Q10 29 | 30 | char& operator[](size_type i) { return data[i]; } 31 | const char& operator[](size_type i) const { return data[i]; } 32 | 33 | size_type size() const { return data.size(); } 34 | 35 | Str& operator+=(const Str& s) { 36 | std::copy(s.data.begin(), s.data.end(), 37 | std::back_inserter(data)); 38 | return *this; 39 | } 40 | 41 | iterator begin() { return data.begin(); } // Q12 42 | iterator end() { return data.end(); } // Q12 43 | 44 | // Q12 45 | iterator insert(iterator d, iterator b, iterator e) { 46 | return data.insert(d, b, e); 47 | } 48 | 49 | private: 50 | Vec data; 51 | }; 52 | 53 | std::ostream& operator<<(std::ostream&, const Str&); 54 | Str operator+(const Str&, const Str&); 55 | #endif -------------------------------------------------------------------------------- /Chapter 12/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s = "Hello, world!"; 10 | cout << s << endl; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter 12/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s = "Hello, world!"; 10 | cout << s.c_str() << endl; 11 | cout << s.data() << endl; 12 | 13 | // copy the first 5 characters 14 | char msg[6]; 15 | s.copy(msg, 5); 16 | 17 | // add null terminating byte 18 | msg[5] = '\0'; 19 | cout << msg << endl; 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 12/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s1 = "a"; 10 | Str s2 = "b"; 11 | Str s3 = "c"; 12 | cout << "s1 is " << (s1 > s2 ? "larger" : "smaller") << " than s2" << endl; 13 | cout << "s3 is " << (s3 < s1 ? "smaller" : "larger") << " than s1" << endl; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /Chapter 12/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s1 = "Hello, world!"; 10 | Str s2 = "Goodbye, world!"; 11 | Str s3 = "Hello, world!"; 12 | cout << "s1 and s2 are " << (s1 == s2 ? "equal" : "not equal") << endl; 13 | cout << "s1 and s3 are " << (s1 == s3 ? "equal" : "not equal") << endl; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /Chapter 12/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s = "Hello,"; 10 | cout << s + " world!" << endl; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter 12/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s1; 10 | Str s2 = "Hello, world!"; 11 | cout << "s1 is " << (s1 ? "not empty" : "empty") << endl; 12 | cout << "s2 is " << (s2 ? "not empty" : "empty") << endl; 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter 12/q07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s = "Hello, world!"; 10 | 11 | // print one char at a time 12 | for (Str::const_iterator it = s.begin(); 13 | it != s.end(); ++it) 14 | cout << *it; 15 | cout << endl; 16 | return 0; 17 | } -------------------------------------------------------------------------------- /Chapter 12/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | using std::cin; 7 | 8 | int main() 9 | { 10 | Str s; 11 | getline(cin, s); 12 | cout << s << endl; 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter 12/q09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s = "New output operator!"; 10 | cout << s << endl; 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter 12/q10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str_Vec.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s1 = "Hello, world!"; 10 | 11 | // create new Str from iterators 12 | Str s2(&s1[0], &s1[5]); 13 | cout << s2 << endl; 14 | return 0; 15 | } -------------------------------------------------------------------------------- /Chapter 12/q12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str_Vec.h" 3 | 4 | using std::cout; 5 | using std::endl; 6 | 7 | int main() 8 | { 9 | Str s1 = "Hello, !"; 10 | Str s2 = "world"; 11 | s1.insert(s1.begin() + 7, s2.begin(), s2.end()); 12 | cout << s1 << endl; 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter 12/q13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vec.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | 8 | int main() 9 | { 10 | Vec v; 11 | char c[] = "Hello, world!"; 12 | v.assign(c, c + strlen(c)); 13 | 14 | // print all values 15 | for (Vec::const_iterator it = v.begin(); 16 | it != v.end(); ++it) 17 | cout << *it; 18 | cout << endl; 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 12/q14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Vec.h" 4 | 5 | using std::cout; 6 | using std::endl; 7 | using std::string; 8 | 9 | int main() 10 | { 11 | const string s = "Hello, world!"; 12 | Vec v(s.begin(), s.end()); 13 | 14 | // print all values 15 | for (Vec::const_iterator it = v.begin(); 16 | it != v.end(); ++it) 17 | cout << *it; 18 | cout << endl; 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 12/q15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Str.h" 3 | 4 | using std::cout; 5 | using std::cin; 6 | using std::endl; 7 | 8 | int main() 9 | { 10 | Str s; 11 | 12 | // read until end-of-file 13 | while (cin >> s) 14 | cout << "1: " << s << endl; 15 | 16 | // code will not enter the second loop 17 | while (cin >> s) 18 | cout << "2: " << s << endl; 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /Chapter 13/q01.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | 3 | int main() 4 | { 5 | Core* p1 = new Core; 6 | Core* p2 = new Grad; 7 | 8 | Core s1; 9 | Grad s2; 10 | 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter 13/q02.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | 3 | using std::domain_error; 4 | 5 | int main() 6 | { 7 | Core* p1 = new Core; 8 | Core* p2 = new Grad; 9 | Core s1; 10 | Grad s2; 11 | 12 | try { p1->grade(); } catch (domain_error e) { } 13 | try { p1->name(); } catch (domain_error e) { } 14 | 15 | try { p2->grade(); } catch (domain_error e) { } 16 | try { p2->name(); } catch (domain_error e) { } 17 | 18 | try { s1.grade(); } catch (domain_error e) { } 19 | try { s1.name(); } catch (domain_error e) { } 20 | 21 | try { s2.grade(); } catch (domain_error e) { } 22 | try { s2.name(); } catch (domain_error e) { } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter 13/q03.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | 3 | int main() 4 | { 5 | Core* p = new Grad; 6 | 7 | if (p->valid()) 8 | p->grade(); 9 | 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter 13/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info.h" 8 | 9 | using std::streamsize; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::vector; 15 | using std::string; 16 | using std::sort; 17 | using std::max; 18 | using std::domain_error; 19 | 20 | int main() 21 | { 22 | vector students; 23 | Student_info record; 24 | string::size_type maxlen = 0; 25 | 26 | // read and store the data 27 | while (record.read(cin)) { 28 | maxlen = max(maxlen, record.name().size()); 29 | students.push_back(record); 30 | } 31 | 32 | // alphabetize the student records 33 | sort(students.begin(), students.end(), Student_info::compare); 34 | 35 | // write the names and grades 36 | for (vector::size_type i = 0; 37 | i != students.size(); ++i) { 38 | cout << students[i].name() 39 | << string(maxlen + 1 - students[i].name().size(), ' '); 40 | try { 41 | string letter_grade = students[i].letter_grade(); 42 | streamsize prec = cout.precision(); 43 | cout << setprecision(3) << letter_grade 44 | << setprecision(prec) << endl; 45 | } catch (domain_error e) { 46 | cout << e.what() << endl; 47 | } 48 | } 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /Chapter 13/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Student_info.h" 4 | 5 | using std::cout; 6 | using std::cin; 7 | using std::endl; 8 | using std::vector; 9 | 10 | int main() 11 | { 12 | vector students; 13 | Student_info student; 14 | 15 | // read all student data 16 | while (student.read(cin)) 17 | students.push_back(student); 18 | 19 | for (vector::const_iterator it = students.begin(); 20 | it != students.end(); ++it) 21 | cout << it->name() << ":\t" 22 | << (it->meets_requirements() ? "meets requirements" 23 | : "does not meet requirements") << endl; 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Chapter 13/q08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info.h" 8 | 9 | using std::streamsize; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::vector; 15 | using std::string; 16 | using std::sort; 17 | using std::max; 18 | using std::domain_error; 19 | 20 | int main() 21 | { 22 | vector students; 23 | Student_info record; 24 | string::size_type maxlen = 0; 25 | 26 | // read and store the data 27 | while (record.read(cin)) { 28 | maxlen = max(maxlen, record.name().size()); 29 | students.push_back(record); 30 | } 31 | 32 | // alphabetize the student records 33 | sort(students.begin(), students.end(), Student_info::compare); 34 | 35 | // write the names and grades 36 | for (vector::size_type i = 0; 37 | i != students.size(); ++i) { 38 | cout << students[i].name() 39 | << string(maxlen + 1 - students[i].name().size(), ' '); 40 | try { 41 | double grade = students[i].grade(); 42 | string letter_grade = students[i].letter_grade(); 43 | streamsize prec = cout.precision(); 44 | cout << setprecision(3) << grade << "\t" << letter_grade 45 | << setprecision(prec) << endl; 46 | } catch (domain_error e) { 47 | cout << e.what() << endl; 48 | } 49 | } 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 13/student_list.txt: -------------------------------------------------------------------------------- 1 | UYNEFQ 78 88 97 64 30 2 | USHZ 71 74 64 23 87 3 | UJSU 99 100 99 97 94 4 | GPLLVK 65 92 78 26 65 64 5 | GXZC 74 92 88 90 59 33 6 | GMMYWW 99 97 79 98 72 88 7 | PYTBXM 54 88 74 72 38 8 | PRTDZL 20 50 40 40 30 9 | AWAU 60 85 74 70 73 10 | AQOPX 76 98 54 77 50 98 -------------------------------------------------------------------------------- /Chapter 14/Ptr.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Ptr 2 | #define GUARD_Ptr 3 | 4 | // code is taken from §14.3/263 5 | template class Ptr { 6 | public: 7 | void make_unique() { 8 | if (*refptr != 1) { 9 | --*refptr; 10 | refptr = new size_t(1); 11 | p = p? clone(p): 0; 12 | } 13 | } 14 | 15 | Ptr(): p(0), refptr(new size_t(1)) { } 16 | Ptr(T* t): p(t), refptr(new size_t(1)) { } 17 | Ptr(const Ptr& h): p(h.p), refptr(h.refptr) { ++*refptr; } 18 | 19 | Ptr& operator=(const Ptr&); 20 | ~Ptr() { 21 | if (--*refptr == 0) { 22 | delete refptr; 23 | delete p; 24 | } 25 | } 26 | operator bool() const { return p; } 27 | T& operator*() const { 28 | if (p) 29 | return *p; 30 | throw std::runtime_error("unbound Ptr"); 31 | } 32 | T* operator->() const { 33 | if (p) 34 | return p; 35 | throw std::runtime_error("unbound Ptr"); 36 | } 37 | 38 | private: 39 | T* p; 40 | std::size_t* refptr; 41 | }; 42 | 43 | // code is taken from §14.4.1/266 44 | template T* clone(const T* tp) 45 | { 46 | return tp->clone(); 47 | } 48 | 49 | // code is taken from §14.2/261, modified for Ptr 50 | template 51 | Ptr& Ptr::operator=(const Ptr& rhs) 52 | { 53 | ++*rhs.refptr; 54 | // free the left-hand side, destroying pointers if appropriate 55 | if (--*refptr == 0) { 56 | delete refptr; 57 | delete p; 58 | } 59 | 60 | // copy the values from right-hand side 61 | refptr = rhs.refptr; 62 | p = rhs.p; 63 | return *this; 64 | } 65 | #endif -------------------------------------------------------------------------------- /Chapter 14/Ptr_Ctr.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Ptr 2 | #define GUARD_Ptr 3 | 4 | typedef unsigned long long size_t; 5 | 6 | class Counter { 7 | public: 8 | Counter(): refptr(new size_t(1)) { } 9 | Counter(size_t s): refptr(new size_t(s)) { } 10 | Counter(const Counter& c): refptr(new size_t(*c.refptr)) { } 11 | ~Counter() { if (*--refptr == 0) delete refptr; } 12 | 13 | operator size_t() const { return *refptr; } 14 | 15 | Counter& operator=(const Counter& rhs) { 16 | if(refptr == 0) 17 | delete refptr; 18 | refptr = rhs.refptr; 19 | return *this; 20 | } 21 | 22 | Counter& operator++() { 23 | if(!refptr) 24 | refptr = new size_t(1); 25 | else 26 | ++*refptr; 27 | return *this; 28 | } 29 | 30 | Counter operator++(int) { 31 | Counter ret(*this); 32 | if(!refptr) 33 | refptr = new size_t(1); 34 | else 35 | ++*refptr; 36 | return ret; 37 | } 38 | 39 | Counter& operator--() { 40 | if(--*refptr == 0) 41 | delete refptr; 42 | return *this; 43 | } 44 | 45 | Counter operator--(int) { 46 | Counter ret(*this); 47 | if(--*refptr == 0) 48 | delete refptr; 49 | return ret; 50 | } 51 | private: 52 | size_t* refptr; 53 | }; 54 | 55 | // code is taken from §14.3/263 56 | template class Ptr { 57 | public: 58 | void make_unique() { 59 | if (ctr != 1) { 60 | --ctr; 61 | p = p? clone(p): 0; 62 | } 63 | } 64 | 65 | Ptr(): p(0), ctr(1) { } 66 | Ptr(T* t): p(t), ctr(1) { } 67 | Ptr(const Ptr& h): p(h.p), ctr(h.ctr) { ++ctr; } 68 | 69 | Ptr& operator=(const Ptr&); 70 | ~Ptr() { } 71 | operator bool() const { return p; } 72 | T& operator*() const { 73 | if (p) 74 | return *p; 75 | throw std::runtime_error("unbound Ptr"); 76 | } 77 | T* operator->() const { 78 | if (p) 79 | return p; 80 | throw std::runtime_error("unbound Ptr"); 81 | } 82 | 83 | bool operator==(const Ptr& rhs) { return rhs.p == this->p; } 84 | 85 | private: 86 | T* p; 87 | Counter ctr; 88 | }; 89 | 90 | // code is taken from §14.4.1/266 91 | template T* clone(const T* tp) 92 | { 93 | return tp->clone(); 94 | } 95 | 96 | template 97 | Ptr& Ptr::operator=(const Ptr& rhs) 98 | { 99 | // free the left-hand side, destroying pointers if appropriate 100 | if (--ctr == 0) { 101 | delete p; 102 | } 103 | 104 | // copy the values from right-hand side 105 | p = rhs.p; 106 | ctr = rhs.ctr; 107 | 108 | return *this; 109 | } 110 | #endif -------------------------------------------------------------------------------- /Chapter 14/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Implement the comparison operation that operates on `Ptr`. 7 | The implementation of the comparison operator can be found in [compare_Core_ptrs.cpp](./compare_Core_ptrs.cpp). The driver program can be found in [q01.cpp](./q01.cpp). 8 | 9 | ### Q2: Implement and test the student grading program using `Ptr` objects. 10 | The implemented student grading program can be found in [q02.cpp](./q02.cpp). 11 | 12 | ### Q3: Implement the `Student_info` class to use the final version of `Ptr`, and use that version to implement the grading program in §13.5/247. 13 | The implemented `Student_info` class can be found in [Student_info.h](./Student_info.h). The driver program can be found in [q02.cpp](./q02.cpp). 14 | 15 | ### Q4: Reimplement the `Str` class to use the final version of `Ptr`. 16 | The reimplemented `Str` class can be found in [Str.h](./Str.h). 17 | ### Q5: Test the reimplemented `Str` class by recompiling and rerunning programs that use `Str`, such as the version of `split` and the picture operations that use `Vec`. 18 | The driver function can be found in [q05.cpp](./q05.cpp). 19 | 20 | ### Q6: The `Ptr` class really solves two problems: maintaining reference counts, and allocating and deallocating objects. Define a class that does reference counting and nothing else; then use that class to implement the `Ptr` class. 21 | The reimplemented `Ptr` class can be found in [Ptr_Ctr.h](./Ptr_Ctr.h). The driver function can be found in [q06.cpp](./q06.cpp), which uses an `Str` class that uses the reimplemented `Ptr` class. -------------------------------------------------------------------------------- /Chapter 14/Str.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Str.h" 5 | 6 | using std::ostream; 7 | using std::istream; 8 | using std::ostream_iterator; 9 | using std::copy; 10 | 11 | // code is taken from §12.3.1/216 12 | ostream& operator<<(ostream& os, const Str& s) 13 | { 14 | for (Str::size_type i = 0; i != s.size(); ++i) 15 | os << s[i]; 16 | return os; 17 | } 18 | 19 | // code is taken from §12.3.2/216 20 | istream& operator>>(istream& is, Str& s) 21 | { 22 | // obliterate existing value(s) 23 | s.data->clear(); 24 | 25 | // read and discard leading whitespace 26 | char c; 27 | while (is.get(c) && isspace(c)) 28 | ; // nothing to do, except testing the condition 29 | 30 | // if still something to read, do so until next whitespace character 31 | if (is) { 32 | do s.data->push_back(c); 33 | while (is.get(c) && !isspace(c)); 34 | 35 | // if we read whitespace, then put it back on the stream 36 | if (is) 37 | is.unget(); 38 | } 39 | 40 | return is; 41 | } 42 | 43 | // code is taken from §12.3.3/219 44 | Str operator+(const Str& s, const Str& t) 45 | { 46 | Str r = s; 47 | r += t; 48 | return r; 49 | } 50 | 51 | // code is taken from §14.4.1/267 52 | // the key to making Ptr< Vec > work 53 | template<> 54 | Vec* clone(const Vec* vp) 55 | { 56 | return new Vec(*vp); 57 | } -------------------------------------------------------------------------------- /Chapter 14/Str.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Str 2 | #define GUARD_Str 3 | 4 | #include 5 | #include 6 | #include "../Chapter 12/Vec.h" 7 | #include "Ptr.h" 8 | 9 | class Str { 10 | friend std::istream& operator>>(std::istream&, Str&); 11 | 12 | public: 13 | Str& operator+=(const Str& s) { 14 | data.make_unique(); 15 | std::copy(s.data->begin(), s.data->end(), 16 | std::back_inserter(*data)); 17 | return *this; 18 | } 19 | 20 | // interface as before 21 | typedef Vec::size_type size_type; 22 | typedef Vec::iterator iterator; 23 | typedef Vec::const_iterator const_iterator; 24 | 25 | // reimplement constructors to create Ptrs 26 | Str(): data(new Vec) { } 27 | Str(const char* cp): data(new Vec) { 28 | std::copy(cp, cp + std::strlen(cp), 29 | std::back_inserter(*data)); 30 | } 31 | 32 | Str(size_type n, char c): data(new Vec(n, c)) { } 33 | template Str(In i, In j): data(new Vec) { 34 | std::copy(i, j, std::back_inserter(*data)); 35 | } 36 | 37 | // call make_unique as necessary 38 | char& operator[](size_type i) { 39 | data.make_unique(); 40 | return (*data)[i]; 41 | } 42 | const char& operator[](size_type i) const { return (*data)[i]; } 43 | size_type size() const { return data->size(); } 44 | iterator begin() { return data->begin(); }; 45 | const_iterator begin() const { return data->begin(); }; 46 | iterator end() { return data->end(); }; 47 | const_iterator end() const { return data->end(); }; 48 | 49 | private: 50 | // store a Ptr to a vector 51 | Ptr< Vec > data; 52 | }; 53 | 54 | std::ostream& operator<<(std::ostream&, const Str&); 55 | Str operator+(const Str&, const Str&); 56 | template<> Vec* clone(const Vec*); 57 | #endif -------------------------------------------------------------------------------- /Chapter 14/Str_Ctr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Str_Ctr.h" 5 | 6 | using std::ostream; 7 | using std::istream; 8 | using std::ostream_iterator; 9 | using std::copy; 10 | 11 | // code is taken from §12.3.1/216 12 | ostream& operator<<(ostream& os, const Str& s) 13 | { 14 | for (Str::size_type i = 0; i != s.size(); ++i) 15 | os << s[i]; 16 | return os; 17 | } 18 | 19 | // code is taken from §12.3.2/216 20 | istream& operator>>(istream& is, Str& s) 21 | { 22 | // obliterate existing value(s) 23 | s.data->clear(); 24 | 25 | // read and discard leading whitespace 26 | char c; 27 | while (is.get(c) && isspace(c)) 28 | ; // nothing to do, except testing the condition 29 | 30 | // if still something to read, do so until next whitespace character 31 | if (is) { 32 | do s.data->push_back(c); 33 | while (is.get(c) && !isspace(c)); 34 | 35 | // if we read whitespace, then put it back on the stream 36 | if (is) 37 | is.unget(); 38 | } 39 | 40 | return is; 41 | } 42 | 43 | // code is taken from §12.3.3/219 44 | Str operator+(const Str& s, const Str& t) 45 | { 46 | Str r = s; 47 | r += t; 48 | return r; 49 | } 50 | 51 | // code is taken from §14.4.1/267 52 | // the key to making Ptr< Vec > work 53 | template<> 54 | Vec* clone(const Vec* vp) 55 | { 56 | return new Vec(*vp); 57 | } -------------------------------------------------------------------------------- /Chapter 14/Str_Ctr.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Str 2 | #define GUARD_Str 3 | 4 | #include 5 | #include 6 | #include "../Chapter 12/Vec.h" 7 | #include "Ptr_Ctr.h" 8 | 9 | class Str { 10 | friend std::istream& operator>>(std::istream&, Str&); 11 | 12 | public: 13 | Str& operator+=(const Str& s) { 14 | data.make_unique(); 15 | std::copy(s.data->begin(), s.data->end(), 16 | std::back_inserter(*data)); 17 | return *this; 18 | } 19 | 20 | // interface as before 21 | typedef Vec::size_type size_type; 22 | typedef Vec::iterator iterator; 23 | typedef Vec::const_iterator const_iterator; 24 | 25 | // reimplement constructors to create Ptrs 26 | Str(): data(new Vec) { } 27 | Str(const char* cp): data(new Vec) { 28 | std::copy(cp, cp + std::strlen(cp), 29 | std::back_inserter(*data)); 30 | } 31 | 32 | Str(size_type n, char c): data(new Vec(n, c)) { } 33 | template Str(In i, In j): data(new Vec) { 34 | std::copy(i, j, std::back_inserter(*data)); 35 | } 36 | 37 | // call make_unique as necessary 38 | char& operator[](size_type i) { 39 | data.make_unique(); 40 | return (*data)[i]; 41 | } 42 | const char& operator[](size_type i) const { return (*data)[i]; } 43 | size_type size() const { return data->size(); } 44 | iterator begin() { return data->begin(); }; 45 | const_iterator begin() const { return data->begin(); }; 46 | iterator end() { return data->end(); }; 47 | const_iterator end() const { return data->end(); }; 48 | 49 | private: 50 | // store a Ptr to a vector 51 | Ptr< Vec > data; 52 | }; 53 | 54 | std::ostream& operator<<(std::ostream&, const Str&); 55 | Str operator+(const Str&, const Str&); 56 | template<> Vec* clone(const Vec*); 57 | #endif -------------------------------------------------------------------------------- /Chapter 14/Student_info.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Student_info.h" 5 | #include "../Chapter 04/grade.h" 6 | 7 | using std::istream; 8 | using std::cerr; 9 | using std::endl; 10 | using std::vector; 11 | using std::string; 12 | using std::min; 13 | 14 | // code is taken from §13.1.2/230 15 | string Core::name() const { return n; } 16 | 17 | // code is taken from §13.1.2/230 18 | double Core::grade() const 19 | { 20 | return ::grade(midterm, final, homework); 21 | } 22 | 23 | // code is taken from §13.1.2/230 24 | istream& Core::read_common(istream& in) 25 | { 26 | // read and store the student's name and exam grades 27 | in >> n >> midterm >> final; 28 | return in; 29 | } 30 | 31 | // code is taken from §13.1.2/230 32 | istream& Core::read(istream& in) 33 | { 34 | read_common(in); 35 | read_hw(in, homework); 36 | return in; 37 | } 38 | 39 | // code is taken from §13.1.2/230 40 | istream& Grad::read(istream& in) 41 | { 42 | Core::read_common(in); 43 | in >> thesis; 44 | read_hw(in, Core::homework); 45 | return in; 46 | } 47 | 48 | // code is taken from §13.1.2/230 49 | double Grad::grade() const 50 | { 51 | return min(Core::grade(), thesis); 52 | } 53 | 54 | istream& Student_info::read(istream& is) 55 | { 56 | char ch; 57 | is >> ch; // get record type 58 | 59 | if (ch == 'U') 60 | cp = new Core(is); 61 | else 62 | cp = new Grad(is); 63 | 64 | return is; 65 | } 66 | 67 | // code is taken from §4.1.3/57 68 | istream& read_hw(istream& in, vector& hw) 69 | { 70 | if (in) { 71 | // get rid of previous contetns 72 | hw.clear(); 73 | 74 | // read homework grades 75 | double x; 76 | while (in >> x) 77 | hw.push_back(x); 78 | 79 | // clear the stream so that input will work for the next student 80 | in.clear(); 81 | } 82 | return in; 83 | } 84 | 85 | // code is taken from §13.2/232 86 | bool compare(const Core& c1, const Core& c2) 87 | { 88 | return c1.name() < c2.name(); 89 | } 90 | 91 | // code is taken from §13.2.1/234 92 | bool compare_grades(const Core& c1, const Core& c2) 93 | { 94 | return c1.grade() < c2.grade(); 95 | } -------------------------------------------------------------------------------- /Chapter 14/Student_info.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_Student_info 2 | #define GUARD_Student_info 3 | 4 | #include 5 | #include 6 | #include 7 | #include "Ptr.h" 8 | 9 | class Core { 10 | friend class Student_info; 11 | public: 12 | Core(): midterm(0), final(0) { } 13 | Core(std::istream& is) { read(is); } 14 | virtual ~Core() { } 15 | std::string name() const; 16 | virtual double grade() const; 17 | virtual std::istream& read(std::istream&); 18 | protected: 19 | std::istream& read_common(std::istream&); 20 | double midterm, final; 21 | std::vector homework; 22 | virtual Core* clone() const { return new Core(*this); } 23 | private: 24 | std::string n; 25 | }; 26 | 27 | class Grad: public Core { 28 | public: 29 | Grad(): thesis(0) { } 30 | Grad(std::istream& is) { read(is); } 31 | double grade() const; 32 | std::istream& read(std::istream&); 33 | protected: 34 | Grad* clone() const { return new Grad(*this); } 35 | private: 36 | double thesis; 37 | }; 38 | 39 | class Student_info { 40 | public: 41 | // constructors and copy control 42 | Student_info(): cp(0) { } 43 | Student_info(std::istream& is): cp(0) { read(is); } 44 | 45 | // operations 46 | std::istream& read(std::istream&); 47 | 48 | // code is taken from §13.4/243 49 | std::string name() const { 50 | if (cp) return cp->name(); 51 | else throw std::runtime_error("uninitialized Student"); 52 | } 53 | 54 | // code is taken from §13.4/243 55 | double grade() const { 56 | if (cp) return cp->grade(); 57 | else throw std::runtime_error("uninitialized Student"); 58 | } 59 | 60 | // code is taken from §13.4/244 61 | static bool compare(const Student_info& s1, 62 | const Student_info& s2) { 63 | return s1.name() < s2.name(); 64 | } 65 | 66 | private: 67 | Ptr cp; // Q3 68 | }; 69 | 70 | std::istream& read_hw(std::istream&, std::vector&); 71 | bool compare(const Core&, const Core&); 72 | bool compare_grades(const Core& c1, const Core& c2); 73 | #endif -------------------------------------------------------------------------------- /Chapter 14/compare_Core_ptrs.cpp: -------------------------------------------------------------------------------- 1 | #include "Student_info.h" 2 | #include "Ptr.h" 3 | #include "compare_Core_ptrs.h" 4 | 5 | bool compare_Core_ptrs(const Ptr cp1, const Ptr cp2) 6 | { 7 | return cp1->name() < cp2->name(); 8 | } -------------------------------------------------------------------------------- /Chapter 14/compare_Core_ptrs.h: -------------------------------------------------------------------------------- 1 | #ifndef GUARD_compare_Core_ptr_h 2 | #define GUARD_compare_Core_ptr_h 3 | 4 | #include "Student_info.h" 5 | #include "Ptr.h" 6 | 7 | bool compare_Core_ptrs(const Ptr, const Ptr); 8 | #endif -------------------------------------------------------------------------------- /Chapter 14/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Student_info.h" 5 | #include "Ptr.h" 6 | #include "compare_Core_ptrs.h" 7 | 8 | using std::cout; 9 | using std::cin; 10 | using std::endl; 11 | using std::vector; 12 | using std::sort; 13 | 14 | int main() 15 | { 16 | vector< Ptr > students; // store Ptrs, not objects 17 | Ptr record; // temporary must be a Ptr as well 18 | char ch; 19 | 20 | // read and store the data 21 | while (cin >> ch) { 22 | if (ch == 'U') 23 | record = new Core; // allocate a Core object 24 | else 25 | record = new Grad; // allocate a Grad object 26 | record->read(cin); // virtual call 27 | students.push_back(record); 28 | } 29 | 30 | // pass the version of compare that works on Ptrs 31 | sort(students.begin(), students.end(), compare_Core_ptrs); 32 | 33 | // write the names 34 | for (vector< Ptr >::size_type i = 0; 35 | i != students.size(); ++i) { 36 | // students[i] is a pointer that we dereference to call the functions 37 | cout << students[i]->name() << endl; 38 | } 39 | 40 | return 0; 41 | } -------------------------------------------------------------------------------- /Chapter 14/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info.h" 8 | #include "Ptr.h" 9 | #include "compare_Core_ptrs.h" 10 | 11 | using std::streamsize; 12 | using std::setprecision; 13 | using std::cout; 14 | using std::cin; 15 | using std::endl; 16 | using std::vector; 17 | using std::string; 18 | using std::sort; 19 | using std::max; 20 | using std::domain_error; 21 | 22 | int main() 23 | { 24 | vector< Ptr > students; // store Ptrs, not objects 25 | Ptr record; // temporary must be a Ptr as well 26 | char ch; 27 | string::size_type maxlen = 0; 28 | 29 | // read and store the data 30 | while (cin >> ch) { 31 | if (ch == 'U') 32 | record = new Core; // allocate a Core object 33 | else 34 | record = new Grad; // allocate a Grad object 35 | record->read(cin); // virtual call 36 | maxlen = max(maxlen, record->name().size()); // dereference 37 | students.push_back(record); 38 | } 39 | 40 | // pass the version of compare that works on Ptrs 41 | sort(students.begin(), students.end(), compare_Core_ptrs); 42 | 43 | // write the names and grades 44 | for (vector< Ptr >::size_type i = 0; 45 | i != students.size(); ++i) { 46 | // students[i] is a pointer that we dereference to call the functions 47 | cout << students[i]->name() 48 | << string(maxlen + 1 - students[i]->name().size(), ' '); 49 | try { 50 | double final_grade = students[i]->grade(); 51 | streamsize prec = cout.precision(); 52 | cout << setprecision(3) << final_grade 53 | << setprecision(prec) << endl; 54 | } catch (domain_error e) { 55 | cout << e.what() << endl; 56 | } 57 | } 58 | return 0; 59 | } -------------------------------------------------------------------------------- /Chapter 14/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "Student_info.h" 8 | 9 | using std::streamsize; 10 | using std::setprecision; 11 | using std::cout; 12 | using std::cin; 13 | using std::endl; 14 | using std::vector; 15 | using std::string; 16 | using std::sort; 17 | using std::max; 18 | using std::domain_error; 19 | 20 | // code is taken from §13.5/247 21 | int main() 22 | { 23 | vector students; 24 | Student_info record; 25 | string::size_type maxlen = 0; 26 | 27 | // read and store the data 28 | while (record.read(cin)) { 29 | maxlen = max(maxlen, record.name().size()); 30 | students.push_back(record); 31 | } 32 | 33 | // alphabetize the student records 34 | sort(students.begin(), students.end(), Student_info::compare); 35 | 36 | // write the names and grades 37 | for (vector::size_type i = 0; 38 | i != students.size(); ++i) { 39 | cout << students[i].name() 40 | << string(maxlen + 1 - students[i].name().size(), ' '); 41 | try { 42 | double final_grade = students[i].grade(); 43 | streamsize prec = cout.precision(); 44 | cout << setprecision(3) << final_grade 45 | << setprecision(prec) << endl; 46 | } catch (domain_error e) { 47 | cout << e.what() << endl; 48 | } 49 | } 50 | 51 | return 0; 52 | } -------------------------------------------------------------------------------- /Chapter 15/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Test your system by writing a program that executes 7 | ``` 8 | Picture p = // some initial starting picture 9 | Picture q = frame(p); 10 | Picture r = hcat(p, q); 11 | Picture s = vcat(q, r); 12 | cout << frame(hcat(s, vcat(r, q))) << endl; 13 | ``` 14 | The test program can be found in [q01.cpp](./q01.cpp). 15 | 16 | ### Q2: Reimplement the `Frame_Pic` class so that the frame uses three different characters: one for the corners, another for the top and bottom borders, and a third for the side borders. 17 | The border characters were added to [Pic.h](./Pic.h). The `Frame_Pic::display` function in [Pic.cpp](./Pic.cpp) is also modified. The driver program can be found in [q02.cpp](./q02.cpp). 18 | 19 | ### Q3: Give users the option to specify what characters to use for these border characters. 20 | The `frame` function in [Pic.h](./Pic.h) is modified to accept specifications for border characters. The driver program can be found in [q03.cpp](./q03.cpp). 21 | 22 | ### Q4: Add an operation to `reframe` a `Picture`, which changes the frame characters. The operation should change all of the frames in the interior picture. 23 | The `reframe` function is added to the `Pic_base` class. The implementations for each derived class can be found in [Pic.cpp](./Pic.cpp). The driver program can be found in [q04.cpp](./q04.cpp). 24 | 25 | ### Q5: Reimplement `HCat_Pic` so that when pictures of a different size are concatenated, the shorter one is centered in the space consumed by the longer one. That is, if we horizontally concatenate two pictures, one of which is four lines long and the other is two lines long, the first and last rows of the output picture will be blank on the side of the shorter picture. What can we now conclude about the necessity of the tests between `row` and `0`. 26 | The reimplemented `HCat_Pic::display` can be found in [Pic.cpp](./Pic.cpp). The driver program can be found in [q05.cpp](./q05.cpp). Since we now supply a modified row number to the display function, tests between `row` and `0` are required. 27 | 28 | ### Q6: The `Vec` and `Str` classes that we developed in Chapters 11 and 12 are powerful enough to be used to implement `Pictures`. Reimplement the material in this chapter to use `Vec` instead of `vector` and test your implementation. 29 | The reimplemented classes can be found in [Pic_Re.h](./Pic_Re.h). The driver program can be found in [q06.cpp](./q06.cpp). -------------------------------------------------------------------------------- /Chapter 15/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Pic.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | // create the initial picture 14 | vector init; 15 | init.push_back("Hello,"); 16 | init.push_back("World!"); 17 | 18 | Picture p = init; 19 | Picture q = frame(p); 20 | Picture r = hcat(p, q); 21 | Picture s = vcat(q, r); 22 | cout << frame(hcat(s, vcat(r, q))) << endl; 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter 15/q02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Pic.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | // create the initial picture 14 | vector init; 15 | init.push_back("Hello,"); 16 | init.push_back("World!"); 17 | 18 | Picture p = init; 19 | cout << frame(p) << endl; 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter 15/q03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Pic.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | // create the initial picture 14 | vector init; 15 | init.push_back("Hello,"); 16 | init.push_back("World!"); 17 | 18 | Picture p = init; 19 | cout << frame(p, '-', '#', '@') << endl; 20 | 21 | return 0; 22 | } -------------------------------------------------------------------------------- /Chapter 15/q04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Pic.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | // create the initial picture 14 | vector init; 15 | init.push_back("Hello,"); 16 | init.push_back("World!"); 17 | 18 | Picture p = init; 19 | Picture q = frame(p); 20 | Picture r = hcat(p, q); 21 | Picture s = vcat(q, r); 22 | Picture t = frame(hcat(s, vcat(r, q))); 23 | cout << t << endl; 24 | 25 | t.reframe('#', '&', '<'); 26 | cout << t << endl; 27 | 28 | return 0; 29 | } -------------------------------------------------------------------------------- /Chapter 15/q05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Pic.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | using std::vector; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | // create the initial pictures 14 | vector init1; 15 | init1.push_back("Hello,"); 16 | init1.push_back("World!"); 17 | vector init2; 18 | init2.push_back("Greetings"); 19 | init2.push_back("to"); 20 | init2.push_back("planet"); 21 | init2.push_back("Earth!"); 22 | 23 | 24 | Picture p1 = frame(init1); 25 | Picture p2 = frame(init2); 26 | 27 | cout << hcat(p1, p2) << endl; 28 | cout << hcat(p2, p1) << endl; 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /Chapter 15/q06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../Chapter 12/Vec.h" 3 | #include "../Chapter 12/Str.h" 4 | #include "Pic_Re.h" 5 | 6 | using std::cout; 7 | using std::endl; 8 | 9 | int main() 10 | { 11 | // create the initial picture 12 | Vec init; 13 | init.push_back("Hello,"); 14 | init.push_back("World!"); 15 | 16 | Picture p = init; 17 | Picture q = frame(p); 18 | Picture r = hcat(p, q); 19 | Picture s = vcat(q, r); 20 | Picture t = frame(hcat(s, vcat(r, q))); 21 | cout << t << endl; 22 | 23 | t.reframe('#', '&', '<'); 24 | cout << t << endl; 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Chapter 16/README.md: -------------------------------------------------------------------------------- 1 | ## Questions and Solutions 2 | 3 | ### Q0: Compile, execute, and test the programs in this chapter. 4 | The programs in this chapter are compiled and tested. The programs can be found in the book. 5 | 6 | ### Q1: Write a self-reproducing program. Such a program is one that does no input, and that, when run, writes a copy of its own source text on the standard output stream. 7 | The self-reproducing program can be found in [q01.cpp](./q01.cpp). -------------------------------------------------------------------------------- /Chapter 16/q01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | char q = 34; 7 | std::string arr[] = { 8 | "#include ", 9 | "#include ", 10 | "", 11 | "int main()", 12 | "{", 13 | " char q = 34", 14 | " std::string arr[] = {", 15 | " ", 16 | " };", 17 | " ", 18 | " for (int i = 0; i < 7; ++i)", 19 | " std::cout << arr[i] << std::endl;", 20 | " for (int i = 0; i < 17; ++i)", 21 | " std::cout << arr[7] << q << arr[i] << q << ',' << std::endl;", 22 | " for (int i = 8; i < 17; ++i)", 23 | " std::cout << arr[i] << std::endl;", 24 | "}", 25 | }; 26 | 27 | for (int i = 0; i < 7; ++i) 28 | std::cout << arr[i] << std::endl; 29 | for (int i = 0; i < 17; ++i) 30 | std::cout << arr[7] << q << arr[i] << q << ',' << std::endl; 31 | for (int i = 8; i < 17; ++i) 32 | std::cout << arr[i] << std::endl; 33 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Altuğ Bakan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Accelerated C++ Solutions 2 | My solutions for the exercises in the book *[Accelerated C++: Practical Programming by Example](http://www.acceleratedcpp.com/) by Andrew Koenig and Barbara E. Moo*. 3 | 4 | Solutions for each chapter can be found in their respective folder. The compiler used for these solutions is *[g++ 10.3.0](https://gcc.gnu.org/), built by [MSYS2](https://www.msys2.org/)*. The IDE used is *[Visual Studio Code](https://github.com/microsoft/vscode)*. 5 | 6 | Note: These are my solutions and they might be incorrect, so use them with caution. 7 | --------------------------------------------------------------------------------