├── ch11 ├── ex02.txt ├── ex07.txt ├── ex08.txt ├── ex09.txt ├── ex10.txt ├── ex11.txt ├── ex20.cpp ├── ex13.cpp ├── ex01.cpp ├── ex03.cpp ├── ex14.txt └── ex21.cpp ├── ch09 ├── ex05.h ├── ex08 │ ├── Makefile │ ├── dc.h │ ├── error.cpp │ ├── math.h │ ├── error.h │ ├── main.cpp │ ├── math.cpp │ ├── lexer.h │ └── parser.h ├── ex02.txt ├── ex09.txt ├── ex01.txt ├── ex05.cpp └── ex06.txt ├── ch12 ├── ex11.txt ├── evtsim │ ├── Makefile │ ├── queue.h │ ├── scheduler.h │ ├── task.h │ └── task.cpp ├── gfxlib │ ├── tests.h │ ├── Makefile │ ├── dot.cpp │ ├── text.cpp │ ├── point.h │ ├── dot.h │ ├── rect.cpp │ ├── main.cpp │ ├── circle.h │ ├── rect.h │ ├── window.h │ ├── text.h │ └── line.h ├── ex02-ex08.txt ├── ex01.cpp ├── ex09.cpp └── ex12.cpp ├── xxd ├── ex18.txt ├── ex12.txt ├── ex11.txt ├── ex10.txt ├── ex08.txt ├── ex09.txt ├── ex13.txt └── ex04.cpp ├── xxe ├── ex13.txt ├── ex14.txt ├── ex12.txt ├── ex09.cpp ├── ex01.txt ├── ex21.txt ├── ex16.txt ├── ex17.txt ├── ex18.txt ├── ex15.cpp ├── ex20.txt └── ex02.txt ├── xxb ├── ex08.txt ├── ex05.txt ├── ex06.txt ├── ex03.cpp ├── ex04.cpp ├── ex07.cpp └── ex02.txt ├── ch08 ├── ex02.cpp ├── ex07.txt ├── ex02.h ├── ex04.cpp ├── ex08.cpp ├── ex05.cpp └── ex06.cpp ├── ch04 ├── ex01.cpp ├── ex07.txt ├── ex04.cpp ├── ex06.txt ├── ex05.cpp ├── ex02.cpp └── ex03.cpp ├── ch15 ├── ex03-ex04.txt ├── othello │ ├── Makefile │ ├── common.h │ ├── iplayerinput.h │ ├── aiplayer.h │ ├── cboard.h │ ├── humanplayer.cpp │ ├── humanplayer.h │ ├── game.h │ ├── player.h │ ├── gboard.h │ ├── aiplayer.cpp │ ├── main.cpp │ └── board.h ├── ex08.cpp ├── ex10.txt ├── ex01.cpp ├── ex07.txt ├── ex06.cpp └── ex09.txt ├── ch10 ├── ex16 │ ├── Makefile │ ├── error.cpp │ ├── math.h │ ├── error.h │ ├── math.cpp │ ├── lexer.h │ └── main.cpp ├── ex07 │ ├── Makefile │ ├── dc.h │ ├── error.cpp │ ├── math.h │ ├── error.h │ ├── main.cpp │ ├── math.cpp │ ├── lexer.h │ └── parser.h ├── ex15.cpp ├── ex04.txt ├── ex20.cpp ├── ex17.cpp ├── ex05.cpp └── ex01.txt ├── ch06 ├── ex23.txt ├── ex04.txt ├── ex22test.cpp ├── ex05.txt ├── ex09.cpp ├── ex11.cpp ├── ex14.cpp ├── ex07.cpp ├── ex08.cpp ├── ex01.cpp ├── ex13.cpp ├── ex06.cpp ├── ex10.cpp ├── ex17.cpp ├── ex02.cpp ├── ex16.cpp ├── ex03.cpp └── ex15.cpp ├── ch07 ├── ex15test.cpp ├── ex03.cpp ├── ex01.cpp ├── ex04.cpp ├── ex12.cpp ├── ex18.cpp ├── ex02.cpp ├── ex16.cpp ├── ex05.cpp ├── ex09.cpp ├── ex14.cpp ├── ex13.cpp ├── ex08.cpp └── ex11.cpp ├── ch05 ├── ex05.txt ├── ex02.cpp ├── ex09.cpp ├── ex03.cpp ├── ex01.cpp ├── ex10.cpp ├── ex04.cpp ├── ex13.cpp ├── ex11.cpp ├── ex08.cpp ├── ex12.cpp ├── ex07.cpp └── ex06.cpp ├── ch18 ├── ex14.cpp ├── ex22.cpp ├── ex15.cpp ├── ex05.cpp ├── ex01.txt ├── ex16.cpp ├── ex03.cpp ├── ex08.cpp ├── ex18.cpp └── ex11.cpp ├── ch17 ├── ex11.cpp ├── ex35.cpp ├── ex25.txt ├── ex22.cpp ├── ex33.cpp ├── ex14.cpp ├── ex30.txt ├── ex24.txt ├── ex34.cpp ├── ex06.cpp ├── ex03.cpp ├── ex21.cpp ├── ex19.cpp └── ex20.cpp ├── ch21 ├── ex27.cpp ├── ex11.txt ├── ex01.cpp ├── ex07.cpp ├── ex24.cpp ├── ex19.cpp ├── ex25.cpp ├── ex12.cpp ├── ex02.cpp ├── ex13.cpp ├── ex09.cpp └── ex16.cpp ├── ch14 ├── ex09.cpp ├── ex07.cpp └── ex01.cpp ├── ch22 ├── ex13.cpp ├── ex04.cpp ├── ex02.cpp └── ex01.cpp ├── ch16 ├── ex01.cpp ├── ex02.cpp ├── ex03.cpp ├── ex04.cpp ├── ex05.cpp └── ex06.cpp ├── ch19 ├── ex01.cpp ├── ex02.cpp ├── ex04.cpp └── ex05.cpp ├── ch25 ├── ex07.cpp ├── ex08.cpp ├── ex19.cpp └── ex09.cpp ├── ch20 ├── ex10.txt ├── ex11.cpp ├── ex16.cpp ├── ex13.cpp ├── ex05.cpp ├── ex08.txt └── ex01.cpp ├── README └── ch13 ├── ex07.cpp ├── ex13.cpp ├── ex12.cpp └── ex10.cpp /ch11/ex02.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch11/ex07.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch11/ex08.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch11/ex09.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch11/ex10.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch11/ex11.txt: -------------------------------------------------------------------------------- 1 | See string.cpp 2 | -------------------------------------------------------------------------------- /ch09/ex05.h: -------------------------------------------------------------------------------- 1 | enum Hello { World }; 2 | -------------------------------------------------------------------------------- /ch12/ex11.txt: -------------------------------------------------------------------------------- 1 | See evtsim/ folder. 2 | -------------------------------------------------------------------------------- /xxd/ex18.txt: -------------------------------------------------------------------------------- 1 | I learned Pig Latin. 2 | -------------------------------------------------------------------------------- /xxe/ex13.txt: -------------------------------------------------------------------------------- 1 | See notes on previous exercise. 2 | -------------------------------------------------------------------------------- /xxb/ex08.txt: -------------------------------------------------------------------------------- 1 | See notes for exercises 5 and 6. 2 | -------------------------------------------------------------------------------- /xxe/ex14.txt: -------------------------------------------------------------------------------- 1 | No comparison is possible since the functions do not exist. 2 | -------------------------------------------------------------------------------- /xxd/ex12.txt: -------------------------------------------------------------------------------- 1 | On my system, locales are available under /usr/share/i18n/locales 2 | -------------------------------------------------------------------------------- /ch08/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include "ex02.h" 2 | 3 | int main() 4 | { 5 | SayHelloWorld(); 6 | } 7 | -------------------------------------------------------------------------------- /ch04/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "Hello, world!\n"; 6 | } 7 | -------------------------------------------------------------------------------- /ch15/ex03-ex04.txt: -------------------------------------------------------------------------------- 1 | See the "othello" folder. 2 | 3 | Exercise 3 implements the game. 4 | 5 | Exercise 4 implements a GUI. 6 | -------------------------------------------------------------------------------- /ch12/evtsim/Makefile: -------------------------------------------------------------------------------- 1 | dc: main.o scheduler.o task.o 2 | g++ -o evtsim main.o scheduler.o task.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm evtsim 7 | -------------------------------------------------------------------------------- /ch10/ex16/Makefile: -------------------------------------------------------------------------------- 1 | dc: main.o error.o lexer.o parser.o math.o 2 | g++ -o dc main.o error.o lexer.o parser.o math.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm dc 7 | -------------------------------------------------------------------------------- /ch06/ex23.txt: -------------------------------------------------------------------------------- 1 | There are many different style conventions for C++, here is one prominent one: 2 | http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml 3 | -------------------------------------------------------------------------------- /ch09/ex08/Makefile: -------------------------------------------------------------------------------- 1 | dc: main.o dc.o error.o lexer.o parser.o math.o 2 | g++ -o dc main.o dc.o error.o lexer.o parser.o math.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm dc 7 | -------------------------------------------------------------------------------- /ch10/ex07/Makefile: -------------------------------------------------------------------------------- 1 | dc: main.o dc.o error.o lexer.o parser.o math.o 2 | g++ -o dc main.o dc.o error.o lexer.o parser.o math.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm dc 7 | -------------------------------------------------------------------------------- /xxb/ex05.txt: -------------------------------------------------------------------------------- 1 | Rather than include someone else's code rewritten here, I'm going to skip this 2 | one and refer the reader to appendix C for the general principles involved. 3 | -------------------------------------------------------------------------------- /xxb/ex06.txt: -------------------------------------------------------------------------------- 1 | Ditto the previous exercise; finding some program converted to C++ and fixing 2 | it up and/or critisizing it should involve many of the issues discussed in 3 | appendix C. 4 | -------------------------------------------------------------------------------- /ch07/ex15test.cpp: -------------------------------------------------------------------------------- 1 | #define PI 3.14159 2 | #define MAX(a,b) (a>b?a:b) 3 | #define DBL(a) (a*2) 4 | 5 | int main() 6 | { 7 | double d = PI; 8 | int a = MAX(1,3); 9 | int b = DBL(a); 10 | } 11 | -------------------------------------------------------------------------------- /xxd/ex11.txt: -------------------------------------------------------------------------------- 1 | The "locale -a" command produces the following: 2 | C 3 | C.UTF-8 4 | en_US.utf8 5 | POSIX 6 | 7 | Most distributions have scripts to install additional language packs, which 8 | would add to this list. 9 | -------------------------------------------------------------------------------- /ch05/ex05.txt: -------------------------------------------------------------------------------- 1 | char str[] = "a short string"; 2 | 3 | The length of the string itself, not including null termination, is 14, but 4 | the size of the array is 15 because the string is terminated with a 0 5 | character. 6 | -------------------------------------------------------------------------------- /ch12/gfxlib/tests.h: -------------------------------------------------------------------------------- 1 | #ifndef __TESTS_H__ 2 | #define __TESTS_H__ 3 | 4 | #include 5 | #include 6 | #include "window.h" 7 | 8 | void run_tests(gfxlib::Window *w); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /ch06/ex04.txt: -------------------------------------------------------------------------------- 1 | 0 & 0 = 0 2 | 0 & 1 = 0 3 | 1 & 0 = 0 4 | 1 & 1 = 1 5 | 0 | 0 = 0 6 | 0 | 1 = 1 7 | 1 | 0 = 1 8 | 1 | 1 = 1 9 | 0 ^ 0 = 0 10 | 0 ^ 1 = 1 11 | 1 ^ 0 = 1 12 | 1 ^ 1 = 0 13 | ~0 = 1 14 | ~1 = 0 15 | -------------------------------------------------------------------------------- /ch08/ex07.txt: -------------------------------------------------------------------------------- 1 | If main() calls get_token in an error state, get_token can throw yet another 2 | exception when it tries to continue parsing input. The input is in an invalid 3 | state since its processing was abruptly stopped. 4 | -------------------------------------------------------------------------------- /ch12/gfxlib/Makefile: -------------------------------------------------------------------------------- 1 | dc: shape.o dot.o line.o rect.o circle.o text.o window.o main.o tests.o 2 | g++ -lX11 -o gfxlib shape.o dot.o line.o rect.o circle.o text.o window.o main.o tests.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm gfxlib 7 | -------------------------------------------------------------------------------- /ch12/gfxlib/dot.cpp: -------------------------------------------------------------------------------- 1 | #include "dot.h" 2 | #include "window.h" 3 | 4 | namespace gfxlib 5 | { 6 | void Dot::draw(Window& s) const 7 | { 8 | s.draw_dot(pos, thickness(), stroke()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch12/gfxlib/text.cpp: -------------------------------------------------------------------------------- 1 | #include "text.h" 2 | #include "window.h" 3 | 4 | namespace gfxlib 5 | { 6 | void Text::draw(Window& s) const 7 | { 8 | s.draw_text(m_p1, m_p2, m_str, stroke()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /ch15/othello/Makefile: -------------------------------------------------------------------------------- 1 | dc: aiplayer.o board.o cboard.o game.o gboard.o humanplayer.o main.o 2 | g++ -lncurses -lX11 -o othello aiplayer.o board.o cboard.o game.o gboard.o humanplayer.o main.o 3 | 4 | clean: 5 | rm -f *.o 6 | rm othello 7 | -------------------------------------------------------------------------------- /xxe/ex12.txt: -------------------------------------------------------------------------------- 1 | I can't think of a way to do this without involving some temporary copy of the 2 | vector. Inserting at any place other than the end necessarily requires moving 3 | existing elements. Any of the copy constructors could throw. 4 | -------------------------------------------------------------------------------- /xxe/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct Test { }; 4 | 5 | int main() { 6 | std::allocator a1; 7 | std::allocator a2(a1); 8 | // I copied it without using an assignment operator, do I win a prize? 9 | } 10 | -------------------------------------------------------------------------------- /ch07/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | for(int i = 1; i < argc; i++) 8 | { 9 | cout << "Hello, " << argv[i] << endl; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch09/ex08/dc.h: -------------------------------------------------------------------------------- 1 | #ifndef DESKCALC_H 2 | #define DESKCALC_H 3 | 4 | #include 5 | 6 | namespace DeskCalc 7 | { 8 | int run(std::istream *input, std::ostream *output, std::ostream *error); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ch10/ex07/dc.h: -------------------------------------------------------------------------------- 1 | #ifndef DESKCALC_H 2 | #define DESKCALC_H 3 | 4 | #include 5 | 6 | namespace DeskCalc 7 | { 8 | int run(std::istream *input, std::ostream *output, std::ostream *error); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /ch10/ex16/error.cpp: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | void Error::skip(istream* input) 4 | { 5 | char ch; 6 | while(input->get(ch)) 7 | { 8 | if(ch == '\n' || ch == ';') 9 | return; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /xxd/ex10.txt: -------------------------------------------------------------------------------- 1 | I don't feel like I'm getting much from this particular exercise other than a 2 | lot of potential bugs. My advice: if you want lots of date formatting 3 | flexibility, use a library. Otherwise, you will spend a lot of time fixing 4 | bugs. 5 | -------------------------------------------------------------------------------- /ch06/ex22test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void main() // sldjfslkjfslkjf 4 | { 5 | int x = 0; // blah 6 | string s = "test test //test test /*test test*/"; 7 | /* testing 8 | testing 9 | testing */ 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /xxe/ex01.txt: -------------------------------------------------------------------------------- 1 | bad_alloc 2 | any exception thrown by the default or copy ctor of X. 3 | any exception thrown by operator= of X. 4 | any exception thrown by operator< of X. 5 | 6 | Is the complete list of possible exceptions simply "all exceptions"? Am I 7 | missing something here? 8 | -------------------------------------------------------------------------------- /xxe/ex21.txt: -------------------------------------------------------------------------------- 1 | The implementation on my machine has the following guarantees: 2 | 3 | - operator= provides the strong guarantee if copy doesn't throw 4 | - multi-elem insert appears to provide the strong guarantee if copy doesn't 5 | throw 6 | - resize provides a strong guarantee 7 | -------------------------------------------------------------------------------- /ch09/ex08/error.cpp: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | // Prints a syntax error message 4 | void Error::skip(istream* input) 5 | { 6 | while(char ch = static_cast(input->get())) 7 | { 8 | if(ch == '\n' || ch == ';') 9 | return; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /ch10/ex07/error.cpp: -------------------------------------------------------------------------------- 1 | #include "error.h" 2 | 3 | // Prints a syntax error message 4 | void Error::skip(istream* input) 5 | { 6 | while(char ch = static_cast(input->get())) 7 | { 8 | if(ch == '\n' || ch == ';') 9 | return; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /xxb/ex03.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | #include 3 | 4 | struct X { 5 | int x; 6 | }; 7 | 8 | int main() { 9 | X* p = (X*)malloc(sizeof(X)); 10 | free(p); 11 | } 12 | */ 13 | 14 | struct X { 15 | int x; 16 | }; 17 | 18 | int main() { 19 | X* p = new X(); 20 | delete p; 21 | } -------------------------------------------------------------------------------- /ch09/ex08/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | namespace Math 5 | { 6 | double check(double); 7 | double plus(double,double); 8 | double minus(double,double); 9 | double mul(double,double); 10 | double div(double,double); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /ch10/ex07/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | namespace Math 5 | { 6 | double check(double); 7 | double plus(double,double); 8 | double minus(double,double); 9 | double mul(double,double); 10 | double div(double,double); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /ch10/ex16/math.h: -------------------------------------------------------------------------------- 1 | #ifndef MATH_H 2 | #define MATH_H 3 | 4 | namespace Math 5 | { 6 | double check(double); 7 | double plus(double,double); 8 | double minus(double,double); 9 | double mul(double,double); 10 | double div(double,double); 11 | } 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /ch06/ex05.txt: -------------------------------------------------------------------------------- 1 | Undefined: 2 | a[-1]; 3 | a[i++] = i++; 4 | int i; i++; 5 | char *p = 0; *p; 6 | long x = -1; char ch = (char)x; 7 | 8 | Implementation specific: 9 | -1 << 2; 10 | sizeof(long long) > sizeof(long); 11 | sizeof(wchar_t); 12 | int s$; 13 | int x = numeric_limits::max()+1 14 | -------------------------------------------------------------------------------- /xxb/ex04.cpp: -------------------------------------------------------------------------------- 1 | /* Stuff like: 2 | #define X 5 3 | 4 | void f(void* p) { 5 | int x = *((int*)p); 6 | } 7 | 8 | becomes: 9 | */ 10 | 11 | const int x = 5; 12 | 13 | template 14 | void f(T* val) { 15 | T x = *val; 16 | } 17 | 18 | int main() { 19 | } 20 | 21 | /* so on and so forth... */ -------------------------------------------------------------------------------- /ch05/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | // little endian platforms supporting non-aligned ints would print FFFF FF 5 | // x86 is such a platform 6 | int x[2] = { 0xffff, 0 }; 7 | int *px = (int*)((char*)x+1); 8 | std::cout << std::hex << x[0] << " " << *px << std::endl; 9 | } 10 | -------------------------------------------------------------------------------- /ch15/othello/common.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMON_H__ 2 | #define __COMMON_H__ 3 | 4 | namespace othello 5 | { 6 | struct Position 7 | { 8 | int x; 9 | int y; 10 | Position() : x(0), y(0) {} 11 | Position(int x, int y) : x(x), y(y) {} 12 | }; 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /xxe/ex16.txt: -------------------------------------------------------------------------------- 1 | I don't believe this is possible or even worth the attempt. If a destructor 2 | fails, then what? Keep going and try to destruct the rest of the elements and 3 | hope that's "close enough"? There's no feasible way to put the object back 4 | into a valid state if your tools for "backing out" of an operation can also 5 | throw. 6 | -------------------------------------------------------------------------------- /ch04/ex07.txt: -------------------------------------------------------------------------------- 1 | Standard: 2 | bool -> char -> short -> int -> long -> long long 3 | float -> double -> long double 4 | 5 | GCC x64: 6 | bool -> char -> short -> int -> long <-> long long 7 | float -> double -> long double 8 | 9 | Visual C++ (x86): 10 | bool -> char -> short -> int <-> long -> long long 11 | float -> double <-> long double 12 | -------------------------------------------------------------------------------- /ch18/ex14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) { 5 | using namespace std; 6 | 7 | if(argc < 2) 8 | return 1; 9 | 10 | string s(argv[1]); 11 | sort(s.begin(), s.end()); 12 | cout << s << endl; 13 | 14 | while(next_permutation(s.begin(), s.end())) { 15 | cout << s << endl; 16 | } 17 | } -------------------------------------------------------------------------------- /ch04/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | void print_char_vals (char start, char end) { 5 | for(char ch = start; ch <= end; ch++) { 6 | cout << ch << " = " << (int)ch << hex << " 0x" << (int)ch << dec << endl; 7 | } 8 | } 9 | 10 | int main() 11 | { 12 | print_char_vals('a', 'z'); 13 | print_char_vals('0', '9'); 14 | } 15 | -------------------------------------------------------------------------------- /ch05/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | // This question is a bit unclear. 9 | // You might refer to the name of a type, for example, when 10 | // using a pointer to the same type inside itself (e.g. a linked list). 11 | struct node { 12 | node *next; 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /ch07/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void func01(const char *a1, int &a2); 6 | typedef void (*pfunc01)(const char*,int&); 7 | void func02(pfunc01 a1); 8 | pfunc01 func03(); 9 | pfunc01 func04(pfunc01 p) 10 | { 11 | int i = 0; 12 | p("", i); 13 | return p; 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | } 19 | -------------------------------------------------------------------------------- /ch15/othello/iplayerinput.h: -------------------------------------------------------------------------------- 1 | #ifndef __IPLAYERINPUT_H__ 2 | #define __IPLAYERINPUT_H__ 3 | 4 | #include 5 | 6 | #include "common.h" 7 | 8 | namespace othello 9 | { 10 | class IPlayerInput 11 | { 12 | public: 13 | virtual Position get_move() = 0; 14 | virtual void alert(std::string msg) = 0; 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /ch08/ex02.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace HelloWorld 4 | { 5 | void SayHelloWorld(); 6 | } 7 | 8 | void HelloWorld::SayHelloWorld() 9 | { 10 | std::cout << "Hello world" << std::endl; 11 | } 12 | 13 | // This line would be added to make ex02.h backward-compatible with a program 14 | // that didn't know about namespaces. 15 | using HelloWorld::SayHelloWorld; 16 | -------------------------------------------------------------------------------- /ch07/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main(int argc, char* argv[]) 7 | { 8 | for(int i = 1; i < argc; i++) 9 | { 10 | ifstream from(argv[i], ifstream::in); 11 | while (from.good()) 12 | { 13 | cout << (char)from.get(); 14 | } 15 | from.close(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /ch15/othello/aiplayer.h: -------------------------------------------------------------------------------- 1 | #ifndef __AIPLAYER_H__ 2 | #define __AIPLAYER_H__ 3 | 4 | #include "player.h" 5 | 6 | namespace othello 7 | { 8 | class AIPlayer : public Player 9 | { 10 | public: 11 | AIPlayer(Board& board, Board::Color color) 12 | : Player(board, color, "computer") {} 13 | 14 | void take_turn(); 15 | }; 16 | } 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /ch07/ex12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Some people prefix the type with func_ or F. 4 | typedef int (*func_compare)(int a, int b); 5 | typedef int (*Fcompare)(int a, int b); 6 | 7 | // To make it clear that it's a type, some people 8 | // postfix _t. 9 | typedef int (*Fcomparer_t)(int a, int b); 10 | 11 | using namespace std; 12 | 13 | int main(int argc, char* argv[]) 14 | { 15 | } 16 | -------------------------------------------------------------------------------- /ch10/ex15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class AppInit 4 | { 5 | public: 6 | AppInit(); 7 | ~AppInit(); 8 | } oAppInit; 9 | 10 | AppInit::AppInit() 11 | { 12 | std::cout << "Initialize" << std::endl; 13 | } 14 | 15 | AppInit::~AppInit() 16 | { 17 | std::cout << "Clean up" << std::endl; 18 | } 19 | 20 | int main() 21 | { 22 | std::cout << "Hello, world!\n"; 23 | } 24 | -------------------------------------------------------------------------------- /ch05/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | typedef unsigned char uChar; 9 | typedef const unsigned char cuChar; 10 | typedef int* pInt; 11 | typedef char** ppChar; 12 | typedef char (*parrChar)[]; 13 | typedef int* a7pInt[7]; 14 | typedef int* (*pa7pInt)[7]; 15 | typedef int* a8a7pInt[7][8]; 16 | } 17 | -------------------------------------------------------------------------------- /xxe/ex17.txt: -------------------------------------------------------------------------------- 1 | As with the previos exercise, I don't believe this is feasible or worth the 2 | attempt. If an operation requires forward iteration and it fails, then either 3 | forward iteration (again) is required to clean it up, or backward iteration. 4 | You'll have no idea what state the iterator is in. You'd be left using a 5 | fresh copy of the iterator (from a function arg?) and hoping that it won't 6 | throw again at some other point. 7 | -------------------------------------------------------------------------------- /ch05/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | const char* a = "a"; 9 | int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 10 | int (&c)[10] = b; 11 | 12 | char *(*d)[10]; 13 | char *d1[10]; 14 | d = &d1; 15 | 16 | char** e = 0; 17 | const int f = 1; 18 | const int* g; 19 | 20 | int h; 21 | int *const h1 = &h; 22 | } 23 | -------------------------------------------------------------------------------- /ch17/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void print_bits(int n) 6 | { 7 | std::bitset b(n); 8 | std::cout << n << " = " << b << std::endl; 9 | } 10 | 11 | int main() 12 | { 13 | using namespace std; 14 | 15 | print_bits(0); 16 | print_bits(1); 17 | print_bits(-1); 18 | print_bits(18); 19 | print_bits(-18); 20 | print_bits(numeric_limits::max()); 21 | } 22 | -------------------------------------------------------------------------------- /ch07/ex18.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int factorial_(int num) 7 | { 8 | int res = num; 9 | for(int i = 2; i < num; i++) 10 | { 11 | res *= i; 12 | } 13 | return res; 14 | } 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | if(argc<2) return -1; 19 | int num = atoi(argv[1]); 20 | cout << "factorial for " << num << " is " << factorial_(num) << endl; 21 | } 22 | -------------------------------------------------------------------------------- /ch07/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // Defines a reference to a function. It behaves the same way as 6 | // any other reference. Once initialized, it cannot be changed or 7 | // pointed to another function. 8 | typedef int(&rifi) (int,int); 9 | 10 | int func01(int a, int b) 11 | { 12 | return a + b; 13 | } 14 | 15 | int main(int argc, char* argv[]) 16 | { 17 | rifi r = func01; 18 | cout << r(1,2) << endl; 19 | } 20 | -------------------------------------------------------------------------------- /ch06/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | struct mystruct_t { char *m; }; 8 | mystruct_t* p = new mystruct_t; 9 | mystruct_t p1; 10 | int* a[4]; 11 | int i = 0; 12 | 13 | (*(p++)); 14 | cout << p << endl; 15 | *(--p); 16 | cout << p << endl; 17 | // (++(a--)); // not valid; prefix increment requires lvalue 18 | ((int*)(p->m)); 19 | (*(p1.m)); 20 | (*(a[i])); 21 | } 22 | -------------------------------------------------------------------------------- /ch06/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void f(int a, int b) 6 | { 7 | // this assigns 3 to a and always evaluates true 8 | if ( a = 3 ) cout << "test 1: true" << endl; 9 | 10 | // always evaluates false. 077 == 0 is false (0). No matter what a is, a & 0 is 0. 11 | if (a&077==0) cout << "test 2: true" << endl; 12 | 13 | // a := b + 1; // compiler error 14 | } 15 | 16 | int main() 17 | { 18 | f(1, 2); 19 | } 20 | -------------------------------------------------------------------------------- /ch21/ex27.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // This was a 2.5 point exercise, but it was really easy; did I miss something in the question? 4 | namespace ch21 { 5 | std::ios_base& general(std::ios_base& s) { 6 | s.unsetf(std::ios_base::floatfield); 7 | } 8 | } 9 | 10 | int main() { 11 | using namespace std; 12 | using namespace ch21; 13 | 14 | cout << 12.345 << ' ' << scientific << 12.345 << ' ' << fixed << 12.345 << ' ' << general << 12.345 << endl; 15 | } 16 | -------------------------------------------------------------------------------- /ch15/othello/cboard.h: -------------------------------------------------------------------------------- 1 | #ifndef __CONSOLEBOARD_H__ 2 | #define __CONSOLEBOARD_H__ 3 | 4 | #include "board.h" 5 | #include "iplayerinput.h" 6 | 7 | namespace othello 8 | { 9 | class ConsoleBoard : public Board 10 | { 11 | void draw_space(Color c); 12 | public: 13 | ConsoleBoard(); 14 | ~ConsoleBoard(); 15 | void draw(); 16 | Position get_move(); 17 | void alert(std::string msg); 18 | }; 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /ch12/gfxlib/point.h: -------------------------------------------------------------------------------- 1 | #ifndef __POINT_H__ 2 | #define __POINT_H__ 3 | 4 | namespace gfxlib 5 | { 6 | class Point 7 | { 8 | int m_x; 9 | int m_y; 10 | 11 | public: 12 | int x() const { return m_x; } 13 | void x(int x) { m_x = x; } 14 | int y() const { return m_y; } 15 | void y(int y) { m_y = y; } 16 | Point() : m_x(0), m_y(0) {} 17 | Point(int x, int y) : m_x(x), m_y(y) {} 18 | }; 19 | } 20 | #endif 21 | -------------------------------------------------------------------------------- /ch15/othello/humanplayer.cpp: -------------------------------------------------------------------------------- 1 | #include "humanplayer.h" 2 | 3 | namespace othello 4 | { 5 | void HumanPlayer::take_turn() 6 | { 7 | int flips = 0; 8 | while(!flips) 9 | { 10 | Position p = input.get_move(); 11 | if ((flips = get_board().play(color(), p)) < 1) 12 | { 13 | input.alert("That is not a valid move."); 14 | } 15 | } 16 | add_points(flips+1); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ch06/ex14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | void rev(char* s) 6 | { 7 | char *p=s; 8 | while(*p)p++; 9 | while(--p > s) 10 | { 11 | // the old clever xor trick again, clearer to use a temp variable. 12 | *p ^= *s; 13 | *s ^= *p; 14 | *p ^= *s++; 15 | } 16 | } 17 | 18 | int main(int argc, char* argv[]) 19 | { 20 | if(argc < 2) return -1; 21 | rev(argv[1]); 22 | cout << argv[1] << endl; 23 | } 24 | -------------------------------------------------------------------------------- /xxd/ex08.txt: -------------------------------------------------------------------------------- 1 | Date outputs are formatted using a string, so it's quite flexible, but the 2 | "standard" formatting (format 'x') is also the format expected for inputs. On 3 | my system, the only format seems to be the following: 4 | 5 | MM/DD/YYYY or MM/DD/YY 6 | 7 | It's very strict about the length; MM and DD both have to be two digits, so 8 | it's necessary to pad it with zeros: 9 | 01/05/84 or 01/05/1984 10 | 11 | On output, the year seems to always be truncated to two digits. Didn't we 12 | learn a lesson about that? 13 | -------------------------------------------------------------------------------- /ch08/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct MyException 5 | { 6 | std::string msg; 7 | MyException(std::string s) 8 | { 9 | msg = s; 10 | } 11 | }; 12 | 13 | void doThrow() 14 | { 15 | throw MyException("My exception!"); 16 | } 17 | 18 | int main() 19 | { 20 | try 21 | { 22 | doThrow(); 23 | } 24 | catch(MyException ex) 25 | { 26 | std::cout << "Caught exception: " << ex.msg << std::endl; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ch15/othello/humanplayer.h: -------------------------------------------------------------------------------- 1 | #ifndef __HUMANPLAYER_H__ 2 | #define __HUMANPLAYER_H__ 3 | 4 | #include "player.h" 5 | #include "iplayerinput.h" 6 | 7 | namespace othello 8 | { 9 | class HumanPlayer : public Player 10 | { 11 | IPlayerInput& input; 12 | public: 13 | HumanPlayer(Board& board, Board::Color color, std::string name, IPlayerInput& input) 14 | : Player(board, color, name), input(input) {} 15 | 16 | void take_turn(); 17 | }; 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /ch09/ex08/error.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_H 2 | #define ERROR_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Error 8 | { 9 | using std::string; 10 | using std::istream; 11 | 12 | struct SyntaxError 13 | { 14 | string errMsg; 15 | SyntaxError(string msg) 16 | { 17 | errMsg = msg; 18 | } 19 | }; 20 | 21 | struct DivideByZeroError { }; 22 | struct OverflowError { }; 23 | 24 | void skip(istream*); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ch10/ex07/error.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_H 2 | #define ERROR_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Error 8 | { 9 | using std::string; 10 | using std::istream; 11 | 12 | struct SyntaxError 13 | { 14 | string errMsg; 15 | SyntaxError(string msg) 16 | { 17 | errMsg = msg; 18 | } 19 | }; 20 | 21 | struct DivideByZeroError { }; 22 | struct OverflowError { }; 23 | 24 | void skip(istream*); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ch10/ex16/error.h: -------------------------------------------------------------------------------- 1 | #ifndef ERROR_H 2 | #define ERROR_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Error 8 | { 9 | using std::string; 10 | using std::istream; 11 | 12 | struct SyntaxError 13 | { 14 | string errMsg; 15 | SyntaxError(string msg) 16 | { 17 | errMsg = msg; 18 | } 19 | }; 20 | 21 | struct DivideByZeroError { }; 22 | struct OverflowError { }; 23 | 24 | void skip(istream*); 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ch14/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | void handle_error() { 7 | abort(); 8 | } 9 | 10 | using namespace std; 11 | 12 | int main() try 13 | { 14 | set_unexpected(handle_error); 15 | 16 | // do stuff here 17 | return 0; 18 | } 19 | catch(exception& ex) 20 | { 21 | cout << "exception: " << ex.what() << endl; 22 | abort(); 23 | } 24 | catch(...) 25 | { 26 | cout << "unknown exception" << endl; 27 | abort(); 28 | } 29 | -------------------------------------------------------------------------------- /ch15/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // my first attempt was this: 4 | class A 5 | { 6 | }; 7 | 8 | extern const unsigned long volatile int operator +(A a, int y); 9 | 10 | // But I couldn't get to 10 keywords. Here's an actual solution stolen from the 11 | // web: 12 | 13 | // Copied from http://www.vandevoorde.com/C++Solutions/challenge.shtml 14 | int f() 15 | { 16 | if(true) 17 | return 1; 18 | else return throw sizeof new unsigned long int const volatile(), 0; 19 | } 20 | 21 | int main() 22 | { 23 | } 24 | -------------------------------------------------------------------------------- /ch15/othello/game.h: -------------------------------------------------------------------------------- 1 | #ifndef __GAME_H__ 2 | #define __GAME_H__ 3 | 4 | #include "board.h" 5 | #include "player.h" 6 | 7 | namespace othello 8 | { 9 | class Game 10 | { 11 | Board& b; 12 | Player* p1; 13 | Player* p2; 14 | Player* currentPlayer; 15 | 16 | void change_player(); 17 | 18 | public: 19 | class PlayerColorError {}; 20 | 21 | Game(Board& board, Player& player1, Player& player2); 22 | 23 | void play(); 24 | }; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /xxe/ex18.txt: -------------------------------------------------------------------------------- 1 | I took a look at QVector from the Qt library. It provides an interface 2 | extremely similar to the standard vector. 3 | 4 | Qt containers are exception neutral (transparent). 5 | 6 | As with standard vector, a valid internal state is always guaranteed (Qt 7 | provides the basic guarantee). However, according to the documentation, for 8 | ALL containers, assignment and copy operations are expected not to throw or 9 | the contents of the container may be unexpected to the user. 10 | 11 | In summary, pretty much the same as the standard library. 12 | -------------------------------------------------------------------------------- /ch06/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int i = 1, j = 1; 6 | int f1() { return ::i++; } 7 | int f2() { return ::i = 0; } 8 | void f3(int a, int b) {} 9 | 10 | int main() 11 | { 12 | ++::i = ::i++; cout << ::i << endl; 13 | f3(f1(),f2()); cout << ::i << endl; 14 | 15 | int a[4] = {1, 2, 3, 4}; 16 | int x = 0,y = 0; 17 | a[x] = x++; cout << a[x] << endl; 18 | 19 | int a1[4], *p = a1; 20 | *p++ = *p++ = 0; cout << a1[0] << endl; 21 | 22 | x = ++x + 1; cout << x << endl; 23 | } 24 | -------------------------------------------------------------------------------- /ch07/ex16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void print(int i, int base = 10) 7 | { 8 | string s; 9 | 10 | do 11 | { 12 | int digit = i % base; 13 | s.push_back(digit > 10 ? 'A' + digit - 10 : '0' + digit); 14 | i /= base; 15 | } while (i > 0); 16 | 17 | cout << string(s.rbegin(),s.rend()) << endl; 18 | } 19 | 20 | int main(int argc, char* argv[]) 21 | { 22 | print(31); 23 | print(31,10); 24 | print(31,16); 25 | print(31,2); 26 | } 27 | -------------------------------------------------------------------------------- /ch22/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | // Uniform distribution between 0 and n. 7 | int main() { 8 | using namespace std; 9 | 10 | srand(57); 11 | int n = 10; 12 | vector v(10); 13 | for(int i = 0; i < 1000000; i++) { 14 | double d = (double(rand())/RAND_MAX) * n; 15 | if(d < 10.0) 16 | v[d]++; 17 | } 18 | for(int i = 0; i < 10; i++) { 19 | cout.width(6); 20 | cout << i << ' ' << string(v[i] / 10000,'#') << '\n'; 21 | } 22 | } -------------------------------------------------------------------------------- /ch07/ex05.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | #include 3 | #include 4 | 5 | #define HELLO_WORLD "Hello world!" 6 | 7 | int main(void) 8 | { 9 | void *p = malloc(13); 10 | 11 | printf("%s\n", HELLO_WORLD); 12 | return 0; 13 | 14 | free(p); 15 | } 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | 23 | const string HelloWorld("Hello, world!"); 24 | 25 | int main(void) 26 | { 27 | char *p = new char[13]; 28 | 29 | cout << HelloWorld << endl; 30 | 31 | delete[] p; 32 | } 33 | -------------------------------------------------------------------------------- /ch06/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | // compiled with g++ 9 | unsigned int ui = numeric_limits::max() + 1; 10 | cout << ui << endl; // 0 11 | ui = 0 - 1; 12 | cout << ui << endl; // 4 billion 13 | 14 | signed int i = numeric_limits::max() + 1; 15 | cout << i << endl; // -2 billion 16 | i = 0 - 1; 17 | cout << i << endl; // -1 18 | 19 | cout << i / 0 << endl; // compiler warning; floating point exception at runtime 20 | } 21 | -------------------------------------------------------------------------------- /ch05/ex10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | const int NUM_MONTHS = 12; 7 | 8 | void printMonths(string months[]) 9 | { 10 | for(int i = 0; i < NUM_MONTHS; i++) 11 | { 12 | cout << months[i] << endl; 13 | } 14 | } 15 | 16 | int main() 17 | { 18 | string months[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; 19 | 20 | for(int i = 0; i < NUM_MONTHS; i++) 21 | { 22 | cout << months[i] << endl; 23 | } 24 | 25 | printMonths(months); 26 | } 27 | -------------------------------------------------------------------------------- /ch09/ex02.txt: -------------------------------------------------------------------------------- 1 | As noted in the previous answer, includes are located under /usr/include. Most 2 | of the include files on a GNU/Linux system are C includes; which can cover 3 | everything from Qt/GTK to X11 to openSSL (cryptography) and much more. 4 | 5 | The POSIX APIs are important on *nix-based systems. Those headers are included 6 | under /usr/include - e.g. /usr/include/unistd.h and /usr/include/pwd.h. 7 | 8 | A program using POSIX sockets would include: 9 | = /usr/include/x86_64-linux-gnu/sys/types.h 10 | = /usr/include/x86_64-linux-gnu/sys/socket.h 11 | -------------------------------------------------------------------------------- /ch06/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | const int max_length = 10; 8 | const char* input_line = "abc?def?gh"; 9 | int quest_count = 0; 10 | 11 | for(int i=0; i < max_length; i++) 12 | { 13 | if (input_line[i] == '?') quest_count++; 14 | } 15 | 16 | cout << quest_count << endl; 17 | quest_count = 0; 18 | 19 | const char* p = input_line; 20 | while (*p != 0) 21 | { 22 | if (*p++=='?') quest_count++; 23 | } 24 | 25 | cout << quest_count << endl; 26 | } 27 | -------------------------------------------------------------------------------- /ch16/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | using namespace std; 7 | 8 | const char* letters = "abcdefghijklmnopqrstuvwxyz"; 9 | 10 | typedef vector CharVec; 11 | 12 | CharVec v(&letters[0],&letters[26]); 13 | 14 | for(CharVec::const_iterator i = v.begin(); i != v.end(); i++) 15 | { 16 | cout << *i; 17 | } 18 | cout << endl; 19 | 20 | for(CharVec::const_reverse_iterator i = v.rbegin(); i != v.rend(); i++) 21 | { 22 | cout << *i; 23 | } 24 | cout << endl; 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /ch09/ex09.txt: -------------------------------------------------------------------------------- 1 | In the version of the DeskCalc that used error() instead of exceptions, all pieces 2 | of the calculator are defined in a single file. However, separate namespaces are 3 | used to represent the modules. 4 | 5 | 6 | 7 | 8 | ^ 9 | ----------------------------|------------------------------- 10 | dc.cpp | 11 | | 12 | Error <---------- Lexer 13 | ^^------Parser-----^ 14 | | ^ 15 | --------Driver 16 | -------------------------------------------------------------------------------- /ch18/ex22.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ch18 { 7 | template 8 | void remove(C& c, typename C::iterator first, typename C::iterator last, const T& value) { 9 | c.erase(std::remove(first, last, value)); 10 | } 11 | } 12 | 13 | int main() { 14 | using namespace std; 15 | 16 | vector v; 17 | for(int i = 0; i < 10; i++) 18 | v.push_back(i); 19 | 20 | ch18::remove(v, v.begin(), v.end(), 8); 21 | copy(v.begin(), v.end(), ostream_iterator(cout, " ")); 22 | cout << endl; 23 | } 24 | -------------------------------------------------------------------------------- /ch12/ex02-ex08.txt: -------------------------------------------------------------------------------- 1 | See the gfxlib folder for implementation. 2 | 3 | Exercise 2 defines the graphics library and the classes that go with it. 4 | 5 | Exercise 3 adds support for line thickness and style. 6 | 7 | Exercise 4 adds support for line arrowheads. 8 | 9 | Exercise 5 prevents drawing outside the bounds of the surface (even though this was already supported 10 | by the graphics subsystem). 11 | 12 | Exercise 6 adds support for drawing text. 13 | 14 | Exercise 7 adds the ability to connect two shapes via their closest connect points. 15 | 16 | Exercise 8 adds color: backround, shape outline (stroke) and closed shape inside (fill). 17 | -------------------------------------------------------------------------------- /ch18/ex15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char** argv) { 8 | using namespace std; 9 | 10 | if(argc < 2) 11 | return 1; 12 | 13 | vector words; 14 | istringstream in(argv[1]); 15 | copy(istream_iterator(in), istream_iterator(), back_inserter(words)); 16 | sort(words.begin(), words.end()); 17 | 18 | do { 19 | copy(words.begin(), words.end(), ostream_iterator(cout, " ")); 20 | cout << endl; 21 | } while (next_permutation(words.begin(), words.end())); 22 | } 23 | -------------------------------------------------------------------------------- /ch09/ex08/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dc.h" 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | using namespace std; 8 | 9 | istream* input; 10 | int no_of_errors = 0; 11 | 12 | switch(argc) 13 | { 14 | case 1: 15 | input = &cin; 16 | break; 17 | case 2: 18 | input = new istringstream(argv[1]); 19 | break; 20 | default: 21 | cerr << "too many arguments" << endl; 22 | return 1; 23 | } 24 | 25 | DeskCalc::run(input, &cout, &cerr); 26 | 27 | if (input != &cin) delete input; 28 | return no_of_errors; 29 | } 30 | -------------------------------------------------------------------------------- /ch10/ex07/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dc.h" 4 | 5 | int main(int argc, char* argv[]) 6 | { 7 | using namespace std; 8 | 9 | istream* input; 10 | int no_of_errors = 0; 11 | 12 | switch(argc) 13 | { 14 | case 1: 15 | input = &cin; 16 | break; 17 | case 2: 18 | input = new istringstream(argv[1]); 19 | break; 20 | default: 21 | cerr << "too many arguments" << endl; 22 | return 1; 23 | } 24 | 25 | DeskCalc::run(input, &cout, &cerr); 26 | 27 | if (input != &cin) delete input; 28 | return no_of_errors; 29 | } 30 | -------------------------------------------------------------------------------- /ch06/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int strlen_(const char *s) 6 | { 7 | const char *p = s; 8 | while(*p) p++; 9 | return p - s; 10 | } 11 | 12 | char* cat_(const char* s1, const char* s2) 13 | { 14 | char* s = new char[strlen_(s1)+strlen_(s2)+1]; 15 | int i = 0; 16 | while(*s1) 17 | { 18 | s[i++]=*s1++; 19 | } 20 | while(*s2) 21 | { 22 | s[i++]=*s2++; 23 | } 24 | s[i] = 0; 25 | return s; 26 | } 27 | 28 | int main(int argc, char* argv[]) 29 | { 30 | if(argc < 3) return -1; 31 | 32 | cout << cat_(argv[1],argv[2]) << endl; 33 | } 34 | -------------------------------------------------------------------------------- /ch19/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch19 { 6 | template void reverse(Bi first, Bi last) { 7 | // two checks necessary to handle even and odd lengths 8 | while((first != last) && (first != --last)) { 9 | std::swap(*first++, *last); 10 | } 11 | } 12 | } 13 | 14 | int main() { 15 | using namespace ch19; 16 | using namespace std; 17 | 18 | string s("Hello World!"); 19 | ch19::reverse(s.begin(), s.end()); 20 | cout << s << endl; 21 | string s1("Hello World"); 22 | ch19::reverse(s1.begin(), s1.end()); 23 | cout << s1 << endl; 24 | } 25 | -------------------------------------------------------------------------------- /ch04/ex06.txt: -------------------------------------------------------------------------------- 1 | For GCC/G++, there is no documented limit for local or external variable 2 | names, but specific platforms may impose a limit. Allowed characters are 3 | consistent with the C++ standard, unless non-standard language extensions are 4 | enabled. 5 | 6 | For MSVC: Longest local variable name = 2048 significant chars, extra chars 7 | ignored. The mangled (compiled) name cannot be longer than 2048. Longest 8 | external variable name = 2047 significant chars, extra chars ignored. Length 9 | can be decreased via compiler flag. No char restrictions beyond standard C++ 10 | restrictions. 11 | 12 | http://msdn.microsoft.com/en-us/library/565w213d(VS.71).aspx 13 | -------------------------------------------------------------------------------- /ch09/ex01.txt: -------------------------------------------------------------------------------- 1 | On Ubuntu server (Precise) include files are installed under /usr/include. C++ 2 | standard include headers are under /usr/include/c++/4.6 (for GCC 4.6). Both 3 | paths are included in the header search list. Standard headers reside in the 4 | c++ folder, while C headers and non-standard headers reside anywhere under 5 | /usr/include. 6 | 7 | Example of standard headers: 8 | /usr/include/c++/4.6/cstdlib (C++ version) 9 | /usr/include/stdlib.h (C version) 10 | 11 | Platform specific headers are in a folder named after the "platform triple", 12 | e.g.: 13 | /usr/include/x86_64-linux-gnu/sys/time.h 14 | 15 | Non-standard example: 16 | /usr/include/libpng/png.h 17 | -------------------------------------------------------------------------------- /ch05/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void swap(int* a, int* b) 7 | { 8 | // the xor trick is a neat old trick, but using clever 9 | // tricks in real code may be unwise. 10 | *a ^= *b; 11 | *b ^= *a; 12 | *a ^= *b; 13 | } 14 | 15 | void swap2(int& a, int& b) 16 | { 17 | a ^= b; 18 | b ^= a; 19 | a ^= b; 20 | } 21 | 22 | int main() 23 | { 24 | int a = 3, b = 5; 25 | cout << "a = " << a << ", b = " << b << endl; 26 | swap(&a, &b); 27 | cout << "a = " << a << ", b = " << b << endl; 28 | swap2(a, b); 29 | cout << "a = " << a << ", b = " << b << endl; 30 | } 31 | -------------------------------------------------------------------------------- /ch21/ex11.txt: -------------------------------------------------------------------------------- 1 | To use both of the C and C++ libraries together, it would be necessary to get 2 | the underlying file handle of the stream buffers in the C++ library and use 3 | them with C library functions. Also, it would be necessary to use unbuffered 4 | C++ streams to prevent a call to a C function from reading/writing data out of 5 | order. 6 | 7 | If one combined exercise 8 with exercise 10, turned off buffering (by 8 | supplying a null buffer pointer to streambuf) and exposed the underlying fd 9 | (file descriptor), a user could use fdopen() to get a FILE structure for the 10 | same fd that the streambuf uses. At that point, standard stream operations 11 | (<< and >>) could be used alongside functions like fprintf. 12 | -------------------------------------------------------------------------------- /ch10/ex04.txt: -------------------------------------------------------------------------------- 1 | The SetDefault function is a static member function of the Date class. It can be accessed in several ways: 2 | 3 | First, it can be accessed directly using the namespace and class name: 4 | Calendar::Date::SetDefault(2008, Calendar::Date::Month(1), 31); 5 | 6 | Second, it can be accessed with the assistance of a using directive: 7 | using namespace Calendar; --or-- using Calendar::Date; 8 | Date::SetDefault(2008, Date::Month(1), 31); 9 | 10 | Or it can be accessed from within the Date class; for example, it could 11 | be called from within the Date class--either from a static function, or an instance 12 | function. In this case, it can be called without any qualifying names: 13 | SetDefault(2008, Month(1), 31); 14 | -------------------------------------------------------------------------------- /ch16/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | using namespace std; 9 | 10 | string fruit; 11 | vector fruits; 12 | 13 | cout << "enter some types of fruit, blank line to end:" << endl; 14 | getline(cin, fruit); 15 | while(fruit.size() > 0) 16 | { 17 | fruits.push_back(fruit); 18 | getline(cin, fruit); 19 | } 20 | 21 | cout << "sorted fruits:" << endl; 22 | sort(fruits.begin(),fruits.end()); 23 | for(vector::const_iterator i = fruits.begin(); i != fruits.end(); i++) 24 | { 25 | cout << *i << endl; 26 | } 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /ch22/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void readitems(map& m) { 8 | string word; 9 | int val = 0; 10 | while(cin >> word >> val) 11 | m[word] += val; 12 | } 13 | 14 | int tally_word(int total, const pair& p) { 15 | cout << p.first << '\t' << p.second << '\n'; 16 | return total += p.second; 17 | } 18 | 19 | int main() { 20 | map tbl; 21 | readitems(tbl); 22 | 23 | int total = 0; 24 | typedef map::const_iterator CI; 25 | total = accumulate(tbl.begin(), tbl.end(), 0, tally_word); 26 | cout << "----------------\ntotal\t" << total << '\n'; 27 | return !cin; 28 | } 29 | -------------------------------------------------------------------------------- /ch22/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ch22 { 7 | using std::valarray; 8 | 9 | template 10 | void apply(valarray& src, Op f) { 11 | std::transform(&src[0], &src[src.size()], &src[0], f); 12 | } 13 | 14 | template 15 | struct Incr { 16 | T operator()(const T& x) { return x + 1; } 17 | }; 18 | } 19 | 20 | int main() { 21 | using namespace std; 22 | using namespace ch22; 23 | 24 | int arr[] = { 0, 1, 2, 3, 4 }; 25 | valarray va(arr, 5); 26 | apply(va, Incr()); 27 | copy(&va[0], &va[va.size()], ostream_iterator(cout, " ")); 28 | cout << endl; 29 | } 30 | -------------------------------------------------------------------------------- /xxe/ex15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace xxe { 5 | // just taking a wild guess here. 6 | template 7 | void safe_insert(T& container, const typename T::value_type& x) { 8 | try { 9 | container.insert(x); 10 | } 11 | catch(...) { 12 | container.erase(x.first); 13 | } 14 | } 15 | } 16 | 17 | int main() { 18 | using namespace std; 19 | 20 | int arr[] = { 0, 1, 2, 3, 4 }; 21 | map m; 22 | 23 | for(int i = 0; i < 5; i++) 24 | xxe::safe_insert(m, std::make_pair(i, i)); 25 | for(map::iterator i = m.begin(); i != m.end(); i++) { 26 | cout << i->first << ' '; 27 | } 28 | cout << endl; 29 | } -------------------------------------------------------------------------------- /ch21/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch21 { 4 | using namespace std; 5 | 6 | struct complex { 7 | float re; 8 | float im; 9 | 10 | complex() : re(0), im(0) { } 11 | complex(float re, float im) : re(re), im(im) { } 12 | }; 13 | 14 | ostream& operator<<(ostream& out, const complex& c) { 15 | return out << '(' << c.re << ',' << c.im << ')'; 16 | } 17 | 18 | istream& operator>>(istream& in, complex& c) { 19 | float re = 0, im = 0; 20 | if(in >> re && in >> im) 21 | c = complex(re, im); 22 | return in; 23 | } 24 | } 25 | 26 | int main() { 27 | using namespace ch21; 28 | 29 | complex c; 30 | while(cin >> c) 31 | cout << c << endl; 32 | } -------------------------------------------------------------------------------- /ch18/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ch18 { 7 | void print_int(const int& x) { 8 | std::cout << x << std::endl; 9 | } 10 | } 11 | 12 | // The question may be hinting at something else (some use of inplace_merge?) 13 | int main() { 14 | using namespace std; 15 | using namespace ch18; 16 | 17 | list lst; 18 | lst.push_back(4); 19 | lst.push_back(2); 20 | lst.push_back(3); 21 | lst.push_back(1); 22 | lst.push_back(5); 23 | 24 | vector v; 25 | copy(lst.begin(), lst.end(), back_inserter(v)); 26 | sort(v.begin(), v.end()); 27 | copy(v.begin(), v.end(), lst.begin()); 28 | for_each(lst.begin(), lst.end(), print_int); 29 | } -------------------------------------------------------------------------------- /ch15/othello/player.h: -------------------------------------------------------------------------------- 1 | #ifndef __PLAYER_H__ 2 | #define __PLAYER_H__ 3 | 4 | #include "board.h" 5 | 6 | namespace othello 7 | { 8 | class Player 9 | { 10 | Board& b; 11 | Board::Color c; 12 | std::string n; 13 | int points; 14 | 15 | protected: 16 | Board& get_board() { return b; } 17 | 18 | public: 19 | Player(Board& board, Board::Color color, std::string name) : b(board), c(color), n(name), points(0) {} 20 | 21 | Board::Color color() const { return c; } 22 | const std::string& name() const { return n; } 23 | virtual void take_turn() = 0; 24 | void add_points(int n) { points += n; } 25 | int score() { return points; } 26 | }; 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /xxd/ex09.txt: -------------------------------------------------------------------------------- 1 | Rather than implement the answer as directed, I'm going to talk about why this 2 | is a bad idea. I don't believe programs should "guess" the intent of the user 3 | or input; rather, the user should be guided to produce a valid input. For 4 | example, a month drop-down or a field with immediate feedback when something 5 | invalid is input. 6 | 7 | Even when dealing with an input such as a text file, trying to guess the 8 | correct meaning of values and catching "most" of the mistakes is a bad idea. 9 | It's only going to lead to trouble. It could be worth writing something to 10 | assist with cleaning up ambiguous dates, but I don't believe this is 11 | appropriate for a locale facet. It would result in surprises, and stream input 12 | functions should not result in surprises. 13 | -------------------------------------------------------------------------------- /ch07/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | string encrypt(string key, string s) 7 | { 8 | if(key.size()<1) return 0; 9 | string ret; 10 | int k = 0; 11 | for(int i = 0; i < s.size(); i++) 12 | { 13 | ret.push_back(s[i] ^ key[k++]); 14 | if (k >= key.size()) k = 0; 15 | } 16 | return ret; 17 | } 18 | 19 | int main(int argc, char* argv[]) 20 | { 21 | if(argc < 2) return -1; 22 | 23 | string s(argv[1]); 24 | if (argc < 3) { 25 | cout << s << endl; 26 | return 0; 27 | } 28 | string key(argv[2]); 29 | 30 | string enc = encrypt(key,s); 31 | cout << enc << endl; 32 | enc = encrypt(key,enc); 33 | cout << enc << endl; 34 | } 35 | -------------------------------------------------------------------------------- /ch05/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | struct Date { 7 | 8 | Date(int y, int m, int d) 9 | { 10 | year = y; 11 | month = m; 12 | day = d; 13 | } 14 | 15 | int year; 16 | int month; 17 | int day; 18 | }; 19 | 20 | void printDate(Date d) 21 | { 22 | cout << d.year << "-" << d.month << "-" << d.day << endl; 23 | } 24 | 25 | Date readDate() 26 | { 27 | int y, m, d; 28 | cin >> y >> m >> d; 29 | return Date(y, m, d); 30 | } 31 | 32 | int main() 33 | { 34 | Date d = Date(2008, 12, 31); 35 | printDate(d); 36 | cout << "Enter a date (YYYY mm dd): "; 37 | d = readDate(); 38 | cout << "You entered: "; 39 | printDate(d); 40 | } 41 | -------------------------------------------------------------------------------- /xxb/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class X { 5 | T x; 6 | T2 y; 7 | 8 | public: 9 | template 10 | void f(T3 z) { 11 | } 12 | }; 13 | 14 | namespace test { 15 | class Y { }; 16 | void f(Y y) { 17 | } 18 | } 19 | 20 | int main() { 21 | for(int i = 0; i < 10; i++) { 22 | } 23 | // Uncomment the following to test for-loop variable scoping. 24 | // On a compliant compiler, it will produce an error. With GCC, 25 | // you can suppress the error using -fpermissive 26 | // std::cout << i << '\n'; 27 | 28 | // Test default template args. 29 | X x; 30 | 31 | // Test member templates. 32 | x.f(0.0); 33 | 34 | // Test argument namespace lookup 35 | f(test::Y()); 36 | } 37 | -------------------------------------------------------------------------------- /ch07/ex14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // There should not be an = sign in there. It would be awkward to use 6 | // this macro: double d PI; 7 | #define PI = 3.141593; 8 | 9 | // This one creates problems with operator precedence. It should be 10 | // wrapped in parens. If used like so: cout << 3 + MAX(x,y); 11 | // it will result in a compile time error. 12 | #define MAX(a,b) a>b?a:b 13 | 14 | // Firstly, it would be a good idea to wrap the whole thing in parens. 15 | // However, the main problem is that macros cannot call themselves 16 | // recursively. Using this macro e.g. fac(5) will result in a compiler 17 | // error that the symbol fac is not found. 18 | #define fac(a) (a)*fac((a)-1) 19 | 20 | int main(int argc, char* argv[]) 21 | { 22 | } 23 | -------------------------------------------------------------------------------- /ch15/othello/gboard.h: -------------------------------------------------------------------------------- 1 | #ifndef __GUIBOARD_H__ 2 | #define __GUIBOARD_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "board.h" 8 | #include "iplayerinput.h" 9 | 10 | namespace othello 11 | { 12 | class GuiBoard : public Board 13 | { 14 | static const int WinWidth = 480; 15 | static const int WinHeight = 500; 16 | static const int TextHeight = 20; 17 | 18 | Display* m_display; 19 | Window m_window; 20 | int m_screen; 21 | XFontStruct* m_font; 22 | 23 | public: 24 | GuiBoard(); 25 | ~GuiBoard(); 26 | void draw(); 27 | Position get_move(); 28 | void alert(std::string msg); 29 | void end_game(); 30 | }; 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /ch25/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch25 { 4 | template 5 | inline void Assert(A assertion) { 6 | if(!assertion) 7 | throw X(); 8 | } 9 | 10 | template 11 | class Range { 12 | T val; 13 | public: 14 | class Error { }; 15 | Range(T i) { Assert(low <= i && i < high); val = i; } 16 | Range operator=(T i) { return *this=Range(i); } 17 | operator T() { return val; } 18 | }; 19 | } 20 | 21 | int main() { 22 | using namespace ch25; 23 | using namespace std; 24 | 25 | Range r(5); 26 | try { 27 | r = 11; 28 | } 29 | catch(Range::Error) { 30 | cout << "caught Range::Error" << endl; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /ch07/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // The Google style guide located at: 6 | // http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Naming 7 | // has some good naming convention rules for C++. 8 | // In reality, a number of different styles are used. 9 | 10 | struct MixedCase 11 | { 12 | int lowercase; 13 | int pascalCase; 14 | int multi_word; 15 | }; 16 | 17 | const int ALL_CAPS_CONST = 5; 18 | const int kMyConstant = 5; 19 | 20 | enum MyEnum 21 | { 22 | ALL_CAPS_ENUM_VALUE 23 | }; 24 | 25 | void SomeFunction() 26 | { 27 | } 28 | 29 | void set_variable() 30 | { 31 | } 32 | 33 | void someFunction() 34 | { 35 | } 36 | 37 | int main(int argc, char* argv[]) 38 | { 39 | char* szHungarianNotation; 40 | } 41 | -------------------------------------------------------------------------------- /ch20/ex10.txt: -------------------------------------------------------------------------------- 1 | This question is extremely vague. Text processing could include a lot of 2 | things. I suppose these facilities would be handy: 3 | 4 | - Regex matching using a variety of different options (line-by-line, global, 5 | case insensitivity, etc.) This could include regular expression substring 6 | matches (captures) to assist with extracting values from a parsed string. 7 | - If we want to parse the text as if it were a delimited data file, it would 8 | be nice to have functions to split the text into rows and columns using a 9 | viariety of delimiters (either basic strings or regular expressions). 10 | - Text parsing functions to output a stream of tokens, useful for parsing 11 | things like JSON, YAML, XML. The text processor could convert a basic string 12 | of characters into a token stream. 13 | -------------------------------------------------------------------------------- /ch09/ex08/math.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.h" 3 | #include "error.h" 4 | 5 | double Math::check(double x) 6 | { 7 | if (x == std::numeric_limits::infinity() || 8 | x == -std::numeric_limits::infinity()) 9 | { 10 | throw Error::OverflowError(); 11 | } 12 | return x; 13 | } 14 | 15 | double Math::plus(double a, double b) 16 | { 17 | double x = a + b; 18 | return check(x); 19 | } 20 | 21 | double Math::minus(double a, double b) 22 | { 23 | double x = a - b; 24 | return check(x); 25 | } 26 | 27 | double Math::mul(double a, double b) 28 | { 29 | double x = a * b; 30 | return check(x); 31 | } 32 | 33 | double Math::div(double a, double b) 34 | { 35 | double x = a / b; 36 | return check(x); 37 | } 38 | -------------------------------------------------------------------------------- /ch10/ex07/math.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.h" 3 | #include "error.h" 4 | 5 | double Math::check(double x) 6 | { 7 | if (x == std::numeric_limits::infinity() || 8 | x == -std::numeric_limits::infinity()) 9 | { 10 | throw Error::OverflowError(); 11 | } 12 | return x; 13 | } 14 | 15 | double Math::plus(double a, double b) 16 | { 17 | double x = a + b; 18 | return check(x); 19 | } 20 | 21 | double Math::minus(double a, double b) 22 | { 23 | double x = a - b; 24 | return check(x); 25 | } 26 | 27 | double Math::mul(double a, double b) 28 | { 29 | double x = a * b; 30 | return check(x); 31 | } 32 | 33 | double Math::div(double a, double b) 34 | { 35 | double x = a / b; 36 | return check(x); 37 | } 38 | -------------------------------------------------------------------------------- /ch10/ex16/math.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "math.h" 3 | #include "error.h" 4 | 5 | double Math::check(double x) 6 | { 7 | if (x == std::numeric_limits::infinity() || 8 | x == -std::numeric_limits::infinity()) 9 | { 10 | throw Error::OverflowError(); 11 | } 12 | return x; 13 | } 14 | 15 | double Math::plus(double a, double b) 16 | { 17 | double x = a + b; 18 | return check(x); 19 | } 20 | 21 | double Math::minus(double a, double b) 22 | { 23 | double x = a - b; 24 | return check(x); 25 | } 26 | 27 | double Math::mul(double a, double b) 28 | { 29 | double x = a * b; 30 | return check(x); 31 | } 32 | 33 | double Math::div(double a, double b) 34 | { 35 | double x = a / b; 36 | return check(x); 37 | } 38 | -------------------------------------------------------------------------------- /ch11/ex20.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // It's not clear to me exactly what the exercise was after. 4 | // This seems to be a reasonable implementation, as long as 5 | // an instance of C doesn't outlive the instances of S and T. 6 | namespace ch11 7 | { 8 | struct S { int x, y; }; 9 | struct T { const char* p; const char* q; }; 10 | 11 | class C 12 | { 13 | public: 14 | int& x; 15 | const char*& p; 16 | 17 | C(S s, T t) : x(s.x), p(t.p) 18 | { 19 | } 20 | }; 21 | } 22 | 23 | int main() 24 | { 25 | using namespace std; 26 | using namespace ch11; 27 | 28 | S s = { 1, 2 }; 29 | T t = { "hello", "" }; 30 | C c(s, t); 31 | 32 | cout << c.x << ' ' << c.p << endl; 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ch18/ex01.txt: -------------------------------------------------------------------------------- 1 | See http://en.wikipedia.org/wiki/Big_O_notation 2 | 3 | In order for an O(N^2) algorithm to be faster than O(N) for some N > 10, there 4 | would have to be a hefty constant cost associated with the O(N) algorithm. For 5 | example, perhaps the O(N) algorithm requires excessive amounts of memory that 6 | the O(N^2) algorithm does not, which comes with an associated performance 7 | penalty. 8 | 9 | With an N = 11, the O(N) algorithm would have to have a constant cost of more 10 | than 11 times that of the O(N^2)'s constant cost. Practically speaking, if the 11 | O(N^2)'s operations can be optimized and use only CPU cache, but the O(N) 12 | algorithm could not, then it would not be entirely unreasonable to have that 13 | constant cost difference. However, the advantage would quickly evaporate as N 14 | grows. 15 | -------------------------------------------------------------------------------- /ch12/evtsim/queue.h: -------------------------------------------------------------------------------- 1 | #ifndef __QUEUE_H__ 2 | #define __QUEUE_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace evtsim 9 | { 10 | struct Message 11 | { 12 | int msg; 13 | void* data; 14 | 15 | Message(int msg, void* data) : msg(msg), data(data) {} 16 | }; 17 | 18 | class Queue 19 | { 20 | std::queue messages; 21 | 22 | public: 23 | bool has_message() { return messages.size() > 0; } 24 | void enqueue(const Message& m) { messages.push(m); } 25 | Message dequeue() { Message m = messages.front(); messages.pop(); return m; } 26 | Message peek() { return messages.front(); } 27 | }; 28 | 29 | typedef std::vector QueueList; 30 | } 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /ch18/ex16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // I couldn't think of a good way to combine the two functions 4 | // without introducing ambiguity or restrictions on the arguments. 5 | namespace ch18 { 6 | template 7 | In find_if(In first, In last, Pred pred) { 8 | while(first < last) { 9 | if(pred(*first)) 10 | break; 11 | first++; 12 | } 13 | return first; 14 | } 15 | 16 | template 17 | In find(In first, In last, const T& value) { 18 | return find_if(first, last, bind2nd(std::equal_to(), value)); 19 | } 20 | } 21 | 22 | int main() { 23 | using namespace std; 24 | 25 | int arr[] = { 1, 2, 3, 4, 5 }; 26 | int* p = ch18::find(arr, arr + 5, 3); 27 | cout << *p << endl; 28 | } 29 | -------------------------------------------------------------------------------- /ch15/ex10.txt: -------------------------------------------------------------------------------- 1 | In this example, the Storable class actually has a field called store. 2 | However, since virtual inheritance is used, there is still only one base 3 | class. Therefore, there is only one vtable: 4 | 5 | Radio's layout looks like this: 6 | Pointer to vtable (Transmitter::Storable) 7 | Pointer to vtable (Receiver::Storable) 8 | const char* store 9 | 10 | Radio's vtable would look like this: 11 | vtable: (Storable) 12 | Ptr to Radio::get_file() 13 | Ptr to Radio::read() 14 | Ptr to Radio::write() 15 | 16 | The method of invoking the virtual function is much simpler. 17 | 18 | 1. Get the index for the Storable::read() function in the vtable. 19 | 2. Get the pointer located at that index in the vtable. 20 | 3. The pointer points to Radio::read(), so call it. 21 | -------------------------------------------------------------------------------- /ch21/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch21 { 6 | char alnum_incr(char ch) { 7 | if(ch == 'z') 8 | return 'a'; 9 | else if (ch == '9') 10 | return '0'; 11 | else if (::isalnum(ch)) 12 | return ch + 1; 13 | else 14 | return ch; 15 | } 16 | } 17 | 18 | const int BufSize = 80; 19 | 20 | int main() { 21 | using namespace std; 22 | 23 | char buf[BufSize + 1]; 24 | while(cin.getline(buf, BufSize)) { 25 | size_t n = cin.gcount(); 26 | char* end = buf + n; 27 | end = remove_if(buf, end, ::isspace); 28 | transform(buf, end, buf, ch21::alnum_incr); 29 | *end = 0; // null terminate so we can print 30 | std::cout << buf << std::endl; 31 | } 32 | } -------------------------------------------------------------------------------- /ch25/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch25 { 4 | template 5 | inline void Assert(A assertion) { 6 | if(!assertion) 7 | throw X(); 8 | } 9 | 10 | template 11 | class Range { 12 | T low, high; 13 | T val; 14 | public: 15 | class Error { }; 16 | Range(T low, T high, T i = T()) { Assert(low <= i && i < high); val = i; } 17 | Range operator=(T i) { return *this=Range(low, high, i); } 18 | operator T() { return val; } 19 | }; 20 | } 21 | 22 | int main() { 23 | using namespace ch25; 24 | using namespace std; 25 | 26 | Range r(0, 10, 5); 27 | try { 28 | r = 11; 29 | } 30 | catch(Range::Error) { 31 | cout << "caught Range::Error" << endl; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /ch22/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ch22 { 7 | using std::valarray; 8 | 9 | template 10 | valarray apply(const valarray& src, Op f) { 11 | valarray dst(src.size()); 12 | std::transform(&src[0], &src[src.size()], &dst[0], f); 13 | return dst; 14 | } 15 | 16 | template 17 | struct Incr { 18 | T operator()(const T& x) { return x + 1; } 19 | }; 20 | } 21 | 22 | int main() { 23 | using namespace std; 24 | using namespace ch22; 25 | 26 | int arr[] = { 0, 1, 2, 3, 4 }; 27 | valarray va(arr, 5); 28 | valarray va2 = apply(va, Incr()); 29 | copy(&va2[0], &va2[va.size()], ostream_iterator(cout, " ")); 30 | cout << endl; 31 | } 32 | -------------------------------------------------------------------------------- /ch09/ex08/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_H 2 | #define LEXER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Lexer 9 | { 10 | using std::string; 11 | using std::istream; 12 | using std::queue; 13 | 14 | // Token definition 15 | enum Token_value 16 | { 17 | NAME, NUMBER, END, FUNC = '%', 18 | PLUS='+', MINUS='-', MUL='*', DIV='/', 19 | PRINT=';', ASSIGN='=', LP='(', RP=')', 20 | SEP=',' 21 | }; 22 | 23 | struct Token 24 | { 25 | Token_value curr_tok; 26 | double number_value; 27 | string string_value; 28 | }; 29 | 30 | Token_value get_token(istream*); 31 | 32 | extern Token curr_sym; 33 | extern queue token_queue; 34 | extern int curr_line; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ch10/ex07/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_H 2 | #define LEXER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Lexer 9 | { 10 | using std::string; 11 | using std::istream; 12 | using std::queue; 13 | 14 | // Token definition 15 | enum Token_value 16 | { 17 | NAME, NUMBER, END, FUNC = '%', 18 | PLUS='+', MINUS='-', MUL='*', DIV='/', 19 | PRINT=';', ASSIGN='=', LP='(', RP=')', 20 | SEP=',' 21 | }; 22 | 23 | struct Token 24 | { 25 | Token_value curr_tok; 26 | double number_value; 27 | string string_value; 28 | }; 29 | 30 | Token_value get_token(istream*); 31 | 32 | extern Token curr_sym; 33 | extern queue token_queue; 34 | extern int curr_line; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /ch15/othello/aiplayer.cpp: -------------------------------------------------------------------------------- 1 | #include "aiplayer.h" 2 | 3 | namespace othello 4 | { 5 | void AIPlayer::take_turn() 6 | { 7 | Board& b = get_board(); 8 | 9 | Position p; 10 | int score = 0; 11 | 12 | // find the "best" move 13 | for(int y = 0; y < Board::NumberOfRows; y++) 14 | { 15 | for(int x = 0; x < Board::NumberOfColumns; x++) 16 | { 17 | Position candidate(x,y); 18 | int potentialScore = get_board().simulate_play(color(), candidate); 19 | if(potentialScore > score) 20 | { 21 | score = potentialScore; 22 | p = candidate; 23 | } 24 | } 25 | } 26 | 27 | add_points(b.play(color(), p) + 1); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /ch05/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | string s; 11 | vector words; 12 | set sortedWords; 13 | 14 | cin >> s; 15 | while (s != "Quit") 16 | { 17 | if (sortedWords.insert(s).second) 18 | { 19 | words.push_back(s); 20 | } 21 | cin >> s; 22 | } 23 | 24 | cout << "In entered order:" << endl; 25 | for(vector::const_iterator i = words.begin(); i != words.end(); i++) 26 | { 27 | cout << *i << endl; 28 | } 29 | 30 | cout << "In sorted order: " << endl; 31 | for(set::const_iterator i = sortedWords.begin(); i != sortedWords.end(); i++) 32 | { 33 | cout << *i << endl; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /ch12/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch12 4 | { 5 | using std::cout; 6 | using std::endl; 7 | 8 | class Base 9 | { 10 | public: 11 | virtual void iam() { cout << "Base" << endl; } 12 | }; 13 | 14 | class Derived1 : public Base 15 | { 16 | public: 17 | void iam() { cout << "Derived1" << endl; } 18 | }; 19 | 20 | class Derived2 : public Base 21 | { 22 | public: 23 | void iam() { cout << "Derived2" << endl; } 24 | }; 25 | } 26 | 27 | int main() 28 | { 29 | using namespace std; 30 | using namespace ch12; 31 | 32 | Base b; 33 | Derived1 d1; 34 | Derived2 d2; 35 | 36 | b.iam(); 37 | d1.iam(); 38 | d2.iam(); 39 | 40 | Base* p; 41 | p = &b; p->iam(); 42 | p = &d1; p->iam(); 43 | p = &d2; p->iam(); 44 | } 45 | -------------------------------------------------------------------------------- /ch05/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | int arr[] = { 1, 2, 3, 4, 5 }; 9 | 10 | cout << arr[2] << endl; 11 | /* 12 | * compiled with -O0 13 | movl -24(%rbp), %eax 14 | movl %eax, %esi 15 | movl $_ZSt4cout, %edi 16 | call _ZNSolsEi 17 | */ 18 | /* 19 | * compmiled with -O2 20 | movl $3, %esi 21 | movl $_ZSt4cout, %edi 22 | call _ZNSolsEi 23 | */ 24 | 25 | cout << *(arr+2) << endl; 26 | /* 27 | * compiled with -O0 28 | movl -24(%rbp), %eax 29 | movl %eax, %esi 30 | movl $_ZSt4cout, %edi 31 | call _ZNSolsEi 32 | */ 33 | /* 34 | * compiled with -O2 35 | movl $3, %esi 36 | movl $_ZSt4cout, %edi 37 | call _ZNSolsEi 38 | */ 39 | } 40 | -------------------------------------------------------------------------------- /ch04/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | template void printMax(const T max, const char *tName) 7 | { 8 | cout << "max " << tName << " = " << max << hex << " 0x" << max << dec << endl; 9 | } 10 | template <> void printMax(const char max, const char *tName) 11 | { 12 | cout << "max " << tName << " = " << (short)max << hex << " 0x" << (short)max << dec << endl; 13 | } 14 | 15 | template void limit(const char* tName) 16 | { 17 | printMax(std::numeric_limits::max(), tName); 18 | }; 19 | 20 | int main() 21 | { 22 | limit("char"); 23 | limit("short"); 24 | limit("int"); 25 | limit("long"); 26 | limit("float"); 27 | limit("double"); 28 | limit("long double"); 29 | limit("unsigned"); 30 | } 31 | -------------------------------------------------------------------------------- /ch12/gfxlib/dot.h: -------------------------------------------------------------------------------- 1 | #ifndef __DOT_H__ 2 | #define __DOT_H__ 3 | 4 | #include "shape.h" 5 | #include "window.h" 6 | 7 | namespace gfxlib 8 | { 9 | class Dot : public Shape 10 | { 11 | Point pos; 12 | public: 13 | Dot(const Point& pos) : pos(pos) {} 14 | virtual void draw(Window&) const; 15 | virtual const Point n() const { return pos; } 16 | virtual const Point s() const { return pos; } 17 | virtual const Point w() const { return pos; } 18 | virtual const Point e() const { return pos; } 19 | virtual const Point nw() const { return pos; } 20 | virtual const Point ne() const { return pos; } 21 | virtual const Point sw() const { return pos; } 22 | virtual const Point se() const { return pos; } 23 | virtual const Point c() const { return pos; } 24 | }; 25 | } 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /ch20/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch20 { 5 | int isalpha(unsigned char c) { 6 | return std::isalpha(c); 7 | } 8 | 9 | int isalpha(signed char c) { 10 | return std::isalpha(static_cast(c)); 11 | } 12 | 13 | int isalpha(char c) { 14 | return std::isalpha(static_cast(c)); 15 | } 16 | 17 | int isdigit(unsigned char c) { 18 | return std::isdigit(c); 19 | } 20 | 21 | int isdigit(signed char c) { 22 | return std::isdigit(static_cast(c)); 23 | } 24 | 25 | int isdigit(char c) { 26 | return std::isdigit(static_cast(c)); 27 | } 28 | } 29 | 30 | int main() { 31 | using namespace std; 32 | 33 | signed char c = 255; 34 | 35 | int x = c, y = static_cast(c); 36 | cout << x << ' ' << y << endl; 37 | } -------------------------------------------------------------------------------- /ch05/ex12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | const char* FIND_CHARS = "ab"; 11 | 12 | string s; 13 | int count = 0; 14 | 15 | cout << "Enter a string, occurrences of 'ab' will be counted." << endl; 16 | cin >> s; 17 | 18 | if (s.length() == 0) 19 | return -1; 20 | 21 | for(string::const_iterator i = s.begin(); i + 1 != s.end(); i++) 22 | { 23 | if (*i == FIND_CHARS[0] && *(i+1) == FIND_CHARS[1]) 24 | count++; 25 | } 26 | cout << count << endl; 27 | count = 0; 28 | 29 | const char* cstr = s.c_str(); 30 | for(const char* c = cstr; *(c+1) != 0; c++) 31 | { 32 | if (*c == FIND_CHARS[0] && *(c+1) == FIND_CHARS[1]) 33 | count++; 34 | } 35 | cout << count << endl; 36 | } 37 | -------------------------------------------------------------------------------- /ch12/evtsim/scheduler.h: -------------------------------------------------------------------------------- 1 | #ifndef __SCHEDULER_H__ 2 | #define __SCHEDULER_H__ 3 | 4 | #include 5 | #include 6 | 7 | #include "task.h" 8 | #include "queue.h" 9 | #include "ucontext.h" 10 | 11 | namespace evtsim 12 | { 13 | typedef std::map QueueMap; 14 | 15 | class Scheduler 16 | { 17 | TaskList tasks; 18 | QueueMap queues; 19 | int vTime; 20 | ucontext_t context; 21 | 22 | public: 23 | Scheduler() : vTime(0) {} 24 | 25 | // called by consumers 26 | void add_task(Task *task); 27 | int elapsed() { return vTime; } 28 | void run(); 29 | 30 | // called by tasks 31 | Queue* get_queue(std::string name) { return &queues[name]; } 32 | void yield_return(Task *t); 33 | void add_time(int t) { vTime += t; } 34 | }; 35 | } 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /xxd/ex13.txt: -------------------------------------------------------------------------------- 1 | The second implementation of Season_io shifts some of the responibility for 2 | maintaining the names of seasons to the system rather than the application 3 | developer. I have mixed feelings on whether this is an appropriate use of the 4 | messages interface. The ability to display seasons seems like a very 5 | application-dependent requirement. Unlike dates, numbers, currency, etc., I've 6 | never seen the requirement before. 7 | 8 | It's likely that if an application needs to localize the names of seasons, it 9 | will need to localize a lot of other things too. It may be more appropriate to 10 | use some custom localized string database that can be deployed alongside each 11 | localized version of the app. Strings could be pulled in there and used with a 12 | season facet. I dislike applications that have to change the system 13 | configuration, such as localization files. It's less portable and more prone 14 | to trouble. 15 | -------------------------------------------------------------------------------- /ch14/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "vector.h" 4 | 5 | // Exceptions should be used to report circumstances where some library function (or 6 | // other code) can't do what it is meant to do. In this case, reading past the end 7 | // of a vector can't be done, so an exception is rightly thrown. However, the calling 8 | // code can easily avoid asking the library to do something it can't. It is both 9 | // clearer and faster to avoid a completely avoidable exception. 10 | int main() 11 | { 12 | using namespace std; 13 | using namespace ch14; 14 | 15 | Vector v; 16 | v.push_back(1); 17 | v.push_back(2); 18 | v.push_back(3); 19 | 20 | int i = 0; 21 | try 22 | { 23 | for(;;) 24 | { 25 | cout << v.at(i++) << endl; 26 | } 27 | } 28 | catch(Vector::RangeError) 29 | { 30 | } 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | This is a collection of my answers to exercises from "The C++ Programming Language" by Bjarne Stroustrup. 2 | 3 | I do NOT claim to be a master of C++, so you may find some these answers to be incomplete, buggy or wrong. My goal was to learn and be comfortable with all facets of the language, but that was balanced by not wanting to spend the rest of my career on these exercises. Consequently, most of them contain only a few simple tests. I consider this repository a work in progress and would gladly accept new and better answers to any of the questions. 4 | 5 | Please note that many of the answers do not conform to best practice because not all principles were introduced at that point in the material. Some things could use much better techniques introduced at later points in the book. I felt it best to leave these as-is. 6 | 7 | My execution environment was Linux, so a number of the answers require GCC and X11 (and libraries not found on Windows). 8 | -------------------------------------------------------------------------------- /ch20/ex16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch20 { 6 | using std::string; 7 | using std::reverse; 8 | 9 | string itos(int i) { 10 | int b = 10; 11 | if(i == 0) 12 | return "0"; 13 | bool neg = false; 14 | if(i < 0) { 15 | neg = true; 16 | i = -i; 17 | } 18 | string s; 19 | while(i) { 20 | int r = i % b; 21 | s.push_back('0' + r); 22 | i /= b; 23 | } 24 | if(neg) 25 | s.push_back('-'); 26 | reverse(s.begin(), s.end()); 27 | return s; 28 | } 29 | } 30 | 31 | int main() { 32 | using namespace std; 33 | using namespace ch20; 34 | 35 | cout << itos(0) << endl; 36 | cout << itos(1) << endl; 37 | cout << itos(12345) << endl; 38 | cout << itos(2000001) << endl; 39 | cout << itos(-54321) << endl; 40 | } 41 | -------------------------------------------------------------------------------- /ch16/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class initial 7 | { 8 | char c; 9 | public: 10 | initial(char c) : c(c) {} 11 | bool operator()(std::string s) { return s.size() > 0 && s[0] == c; } 12 | }; 13 | 14 | int main() 15 | { 16 | using namespace std; 17 | 18 | string fruit; 19 | vector fruits; 20 | 21 | cout << "enter some types of fruit, blank line to end:" << endl; 22 | getline(cin,fruit); 23 | while(fruit.size() > 0) 24 | { 25 | fruits.push_back(fruit); 26 | getline(cin, fruit); 27 | } 28 | 29 | sort(fruits.begin(),fruits.end()); 30 | initial pred('a'); 31 | vector::const_iterator i = find_if(fruits.begin(),fruits.end(),pred); 32 | while(i != fruits.end() && pred(*i)) 33 | { 34 | cout << *i << endl; 35 | i++; 36 | } 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /ch07/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void invert(int* arr, int d1, int d2) 7 | { 8 | int* tmp = new int[d1*d2]; 9 | for(int i=0; i < d1*d2; i++) tmp[i] = arr[i]; 10 | 11 | int idx = 0; 12 | for(int i=0; i < d2; i++) 13 | { 14 | for(int j = 0; j < d1; j++) 15 | { 16 | arr[idx++] = tmp[j*d2+i]; 17 | } 18 | } 19 | cout << endl; 20 | delete tmp; 21 | } 22 | 23 | int main(int argc, char* argv[]) 24 | { 25 | int arr[3][5] = { 26 | {1,2,3,4,5}, 27 | {11,12,13,14,15}, 28 | {21,22,23,24,25} 29 | }; 30 | int* p = &arr[0][0]; 31 | for(int i = 0; i < 15; i++) 32 | { 33 | cout << *(p+i) << " "; 34 | } 35 | cout << endl; 36 | 37 | invert(p, 3, 5); 38 | for(int i = 0; i < 15; i++) 39 | { 40 | cout << *(p+i) << " "; 41 | } 42 | cout << endl; 43 | } 44 | -------------------------------------------------------------------------------- /ch18/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch18 { 4 | template 5 | std::pair match(In1 first1, In1 last1, In2 first2) { 6 | while(first1 != last1 && *first1 != *first2) { 7 | first1++; first2++; 8 | } 9 | return std::make_pair(first1, first2); 10 | } 11 | 12 | template 13 | std::pair match(In1 first1, In1 last1, In2 first2, BinPred pred) { 14 | while(first1 != last1 && !pred(*first1, *first2)) { 15 | first1++; first2++; 16 | } 17 | return std::make_pair(first1, first2); 18 | } 19 | } 20 | 21 | int main() { 22 | using namespace std; 23 | 24 | int v1[] = { 1, 2, 3, 4, 5 }; 25 | int v2[] = { 'a', 'b', 3, 4, 5 }; 26 | 27 | int* p = ch18::match(v1, v1 + 5, v2).first; 28 | cout << *p << endl; 29 | p = ch18::match(v1, v1 + 5, v2, std::equal_to()).first; 30 | cout << *p << endl; 31 | } -------------------------------------------------------------------------------- /xxb/ex02.txt: -------------------------------------------------------------------------------- 1 | This one is far more trouble than it's worth. It requires either writing a 2 | simple C lexer or using some really gnarly regular expressions. To do 3 | efficient regex replace on my system, I'd have to link boost and stuff. 4 | Insted, I'm just going to describe a general (messy) approach here: 5 | 6 | - Replace C++ keywords with some kind of prefix. For example, replace "new" 7 | with "c_new". One would need to capture possible surrounding chars. For 8 | example: 9 | [ \(\[,=]](new)[ \)\],=] -> replace () match with c_new 10 | 11 | - Replace (\w+)\s*\s(\w+)=\s*malloc\s\(.*\) with $1* $2 = new $1() 12 | This of course assumes that only a single object is being allocated with 13 | malloc and not an array. 14 | 15 | There are far too many corner cases to make this even remotely useful. Without 16 | writing a really advanced tool, it's much better for a human being to do this. 17 | Otherwise, you're going to spend more time fixing bugs than doing the 18 | conversion. 19 | -------------------------------------------------------------------------------- /ch19/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // A sink might be useful in situations where some iterator could be passed 4 | // into a library function designed to write some kind of output. For example, 5 | // say a library function takes an output iterator to write log entries to. 6 | // If the consumer of the library does not wish to persist log entries, then 7 | // a Sink may be passed in to perform a task without writing log output. 8 | namespace ch19 { 9 | using namespace std; 10 | 11 | template 12 | class Sink : public iterator { 13 | public: 14 | Sink& operator++() { return *this; } 15 | Sink operator++(int) { return *this; } 16 | Sink& operator*() { return *this; } 17 | Sink& operator=(const T& x) { return *this; } 18 | }; 19 | } 20 | 21 | int main() { 22 | using namespace std; 23 | using namespace ch19; 24 | 25 | int arr[] = { 1, 2, 3, 4, 5 }; 26 | copy(arr, arr + 5, Sink()); 27 | } 28 | -------------------------------------------------------------------------------- /ch06/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // 5 4 | // #include 5 | 6 | using namespace std; 7 | 8 | int main() 9 | { 10 | // 1 11 | int a[4] = {1, 2, 3, 4}; 12 | char* p = (char *)a; 13 | cout << (int)*(p+4) << endl; // two? 14 | 15 | // 2 16 | struct mystruct_t 17 | { 18 | char x; 19 | int y; 20 | } mystruct = {'a',2}; 21 | p = (char*)&mystruct; 22 | cout << (int)*(p+4) << endl; // two? 23 | 24 | // 3 25 | char charr[4] = {2,0,0,0}; 26 | int* pi = reinterpret_cast(charr); 27 | cout << *pi; // two? 28 | 29 | // 4 30 | signed char ch = 130; 31 | cout << ch; 32 | 33 | // 6 34 | // void _tmain(int argc, TCHAR* argv[]) { } 35 | 36 | // 7 37 | // Pre-compiled headers; e.g. #include "stdafx.h" 38 | 39 | // 8 40 | asm("nop"); 41 | 42 | // 9 43 | // BOOL x = FALSE; 44 | 45 | // 10 46 | // void __cdecl func(); 47 | } 48 | -------------------------------------------------------------------------------- /ch14/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch14 5 | { 6 | template class STC 7 | { 8 | // Made private to prevent instantiation of this template. 9 | STC(); 10 | }; 11 | 12 | template class STC 13 | { 14 | Tfunc* old; 15 | Tset* set; 16 | public: 17 | STC(Tset* set, Tfunc* f) : set(set), old(set(f)) { } 18 | ~STC() { set(old); } 19 | }; 20 | } 21 | 22 | void f() 23 | { 24 | std::cout << "I got called!" << std::endl; 25 | abort(); 26 | } 27 | 28 | int main() 29 | { 30 | using namespace std; 31 | using namespace ch14; 32 | 33 | typedef std::new_handler (*SetNewHandler)(new_handler); 34 | STC stc(std::set_new_handler, f); 35 | 36 | for(;;) 37 | { 38 | void* p = new char[1000000000]; 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /ch06/ex10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int strlen_(const char *s) 6 | { 7 | const char *p = s; 8 | while(*p) p++; 9 | return p - s; 10 | } 11 | 12 | void strcpy_(char *dest, const char* src) 13 | { 14 | while (*src) { 15 | *dest++ = *src++; 16 | } 17 | } 18 | 19 | int strcmp_(const char *s1, const char *s2) 20 | { 21 | while (*s1 && *s2) { 22 | if (int d = *s1++ - *s2++) 23 | return d; 24 | } 25 | return *s1 - *s2; 26 | } 27 | 28 | int main() 29 | { 30 | cout << strlen_("") << endl; 31 | cout << strlen_("hello") << endl; 32 | 33 | char dest[10]; 34 | strcpy_(dest, ""); 35 | cout << dest << endl; 36 | 37 | strcpy_(dest,"hello"); 38 | cout << dest << endl; 39 | 40 | cout << strcmp_("", "hello") << endl; 41 | cout << strcmp_("hello", "") << endl; 42 | cout << strcmp_("abc", "abc") << endl; 43 | cout << strcmp_("abc","abd") << endl; 44 | } 45 | -------------------------------------------------------------------------------- /ch17/ex35.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hash_map.h" 3 | 4 | // This is ultra-simplistic, but matches the characteristics of the 5 | // data specified in the question (uniformly distributed integers). 6 | // Given integers that are already uniformly-distributed, the hash 7 | // function doesn't really need to do much. In this case, we'll just 8 | // uniformly distribute the integers to the buckets. 9 | // 10 | // Did I miss something in the question? 11 | class SimpleIntHash { 12 | public: 13 | int operator()(int x) { 14 | return x % 1024; 15 | } 16 | }; 17 | 18 | int main() { 19 | using namespace ch17; 20 | using namespace std; 21 | 22 | hash_map hm(0, (size_t)1024); 23 | 24 | int j = 1; 25 | // Generates 1024 values that have the same hash value and check utilization 26 | // to confirm. 27 | for(int i = 0; i < 1024; i++) { 28 | hm[j] = i; 29 | j += 1024; 30 | } 31 | 32 | cout << hm.bucket_utilization() << endl; 33 | } 34 | -------------------------------------------------------------------------------- /xxe/ex20.txt: -------------------------------------------------------------------------------- 1 | Normal invariants: 2 | - v must point to an allocated area of memory 3 | - alloc must be a valid allocator for T 4 | - space must be equal to or greater than v 5 | - last must be equal to or greater than v and must point to one past the last 6 | properly constructed element (or v if there are no elements) 7 | - all elements between v and last-1 must be valid 8 | 9 | Modified v = 0 variants: 10 | - v must be zero or point to an allocated area of memory 11 | - alloc must be a valid allocator for T 12 | - space must be equal to or greater than v, or zero if v is zero 13 | - last must be equal to or greater than v and must point to one past the last 14 | properly constructed element, or v if there are no elements - or zero if v is zero 15 | - if v != 0, all elements between v and last-1 must be valid 16 | - if v == 0, the size of the container is 0 and there must be no constructed 17 | elements 18 | - It is an error to access or modify elements when v = 0; begin() and end() 19 | iterators must both return 0. 20 | -------------------------------------------------------------------------------- /ch08/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | // Using an exception to return the value is far slower than returning it directly. 8 | 9 | int throwOrReturn(int x, bool throwIt) 10 | { 11 | if(throwIt) throw x; 12 | else return x; 13 | } 14 | 15 | int main(int argc, char* argv[]) 16 | { 17 | int x = 1, y; 18 | 19 | int start = clock(); 20 | for(int i = 0; i < 1000000; i++) 21 | { 22 | y = throwOrReturn(x, false); 23 | } 24 | int end = clock(); 25 | cout << "direct return, elapsed clock ticks: " << end-start << endl; 26 | 27 | start = clock(); 28 | for(int i = 0; i < 1000000; i++) 29 | { 30 | try 31 | { 32 | throwOrReturn(x, true); 33 | } 34 | catch(int err) 35 | { 36 | y = err; 37 | } 38 | } 39 | end = clock(); 40 | cout << "exceptions, elapsed clock ticks: " << end-start << endl; 41 | } 42 | -------------------------------------------------------------------------------- /ch15/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch15 5 | { 6 | class A 7 | { 8 | public: 9 | virtual ~A() {} 10 | }; 11 | 12 | class B : public A 13 | { 14 | }; 15 | 16 | class A1 17 | { 18 | public: 19 | virtual ~A1() {} 20 | }; 21 | 22 | class C : public A1 23 | { 24 | }; 25 | 26 | template T ptr_cast(Tfrom p) 27 | { 28 | T r = dynamic_cast(p); 29 | if(!r) throw std::bad_cast(); 30 | return r; 31 | } 32 | } 33 | 34 | int main() 35 | { 36 | using namespace std; 37 | using namespace ch15; 38 | 39 | A* a = new B; 40 | A1* c = new C; 41 | 42 | B* b = ptr_cast(a); 43 | try 44 | { 45 | b = ptr_cast(c); 46 | } 47 | catch(bad_cast) 48 | { 49 | cout << "caught bad_cast" << endl; 50 | } 51 | 52 | delete a; 53 | delete c; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /ch12/gfxlib/rect.cpp: -------------------------------------------------------------------------------- 1 | #include "rect.h" 2 | #include "line.h" 3 | 4 | namespace gfxlib 5 | { 6 | void Rect::draw(Window& s) const 7 | { 8 | Color stroke = this->stroke(); 9 | 10 | draw_side(s,nw(),m_sw); 11 | draw_side(s,nw(),m_ne); 12 | draw_side(s,m_ne,se()); 13 | draw_side(s,m_sw,se()); 14 | 15 | draw_fill(s); 16 | } 17 | 18 | void Rect::draw_side(Window& s, Point p1, Point p2) const 19 | { 20 | Line side(p1,p2); 21 | side.thickness(thickness()); 22 | side.outline(outline()); 23 | side.stroke(stroke()); 24 | side.draw(s); 25 | } 26 | 27 | void Rect::draw_fill(Window& s) const 28 | { 29 | int fill = this->fill(); 30 | for(int i = m_sw.x()+thickness(); i < m_ne.x(); i++) 31 | { 32 | for(int j = m_ne.y()+thickness(); j < m_sw.y(); j++) 33 | { 34 | s.set_pixel(Point(i,j),fill); 35 | } 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /ch17/ex25.txt: -------------------------------------------------------------------------------- 1 | Space overhead for hash_map is composed of the following (on an x64 system): 2 | - Constant 16 bytes (to store max_load, grow, and no_of_erased). 3 | - 48 bytes for the two vectors (the entry vector and the buckets) 4 | - 8 * size of bucket table (one pointer per entry) 5 | - 17 bytes for each actual entry (for the Entry struct) + the size of the 6 | key and value itself. 7 | 8 | So an empty hash_map with 101 buckets would take 872 bytes + 17 bytes per each 9 | added item. 10 | 11 | My implmenetation's map class is hard to decipher, but it appears to use a 12 | red-black tree where each node has 28 bytes overhead (plus the key and value). 13 | Obviously the map will have much less memory overhead because it doesn't need 14 | to maintain all that empty space in the hash table. A hash table will almost 15 | always have empty entries because of the load factor vs. performance 16 | trade-off. If space is at a premium, one would probably want to use map; 17 | however, if lookup time is paramount, then hash_map may be the better choice. 18 | -------------------------------------------------------------------------------- /ch17/ex22.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() { 7 | using namespace std; 8 | 9 | vector v; 10 | deque d; 11 | list l; 12 | 13 | // Constant overhead: required no matter how many elements are present. 14 | // Note that there will be additional overhead for the backing store 15 | // if it is not used to capacity (empty storage not yet used). 16 | 17 | // My implementation is GCC on an x64 system 18 | cout << "Constant overhead:" << endl; 19 | cout << "vector: " << sizeof(v) << endl; // 24 bytes for me 20 | cout << "deque: " << sizeof(d) << endl; // 80 bytes for me 21 | cout << "list: " << sizeof(l) << endl; // 16 bytes for me 22 | 23 | // List has an additional overhead for each node. For me, this is 16 bytes 24 | // or two 64-bit pointers for the previous and next data node. Therefore, 25 | // each element will consume 16 bytes of additional overhead beyond the user 26 | // data. 27 | } 28 | -------------------------------------------------------------------------------- /ch12/gfxlib/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "window.h" 4 | #include "tests.h" 5 | 6 | using namespace std; 7 | 8 | int main() { 9 | using gfxlib::Window; 10 | 11 | Display *display = XOpenDisplay(NULL); 12 | if(!display) { 13 | cerr << "Unable to open display."; 14 | return 1; 15 | } 16 | 17 | Window w(display, 640, 480, 0xfff0f0ff); 18 | run_tests(&w); 19 | 20 | XEvent event; 21 | 22 | Atom wm_delete = XInternAtom(display, "WM_DELETE_WINDOW", false); 23 | XSetWMProtocols(display, w.handle(), &wm_delete, 1); 24 | XSelectInput(display, w.handle(), ExposureMask | KeyPressMask | ButtonPressMask); 25 | 26 | while(1) { 27 | XNextEvent(display, &event); 28 | if(event.type == KeyPress) 29 | break; 30 | else if (event.type == Expose) 31 | w.paint(); 32 | else if (event.xclient.data.l[0] == wm_delete) 33 | break; 34 | } 35 | 36 | XCloseDisplay(display); 37 | } 38 | -------------------------------------------------------------------------------- /ch06/ex17.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void rev(char* s) 8 | { 9 | char *p=s; 10 | while(*p)p++; 11 | while(--p > s) 12 | { 13 | *p ^= *s; 14 | *s ^= *p; 15 | *p ^= *s++; 16 | } 17 | } 18 | 19 | char* itoa_(int i, char result[], int base) 20 | { 21 | if (!base) base = 10; 22 | 23 | int idx = 0; 24 | do 25 | { 26 | int digit = i % base; 27 | result[idx++] = digit > 10 ? 'A' + digit - 10 : '0' + digit; 28 | i /= base; 29 | } while (i > 0); 30 | result[idx] = 0; 31 | rev(result); 32 | return result; 33 | } 34 | 35 | int main(int argc, char* argv[]) 36 | { 37 | if (argc < 2) 38 | return -1; 39 | 40 | char b[255]; 41 | 42 | int i = atoi(argv[1]); 43 | cout << "0x" << itoa_(i, b, 16) << endl; 44 | cout << itoa_(i, b, 10) << endl; 45 | cout << "0" << itoa_(i, b, 8) << endl; 46 | cout << itoa_(i, b, 2) << endl; 47 | } 48 | -------------------------------------------------------------------------------- /ch05/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | const char* monthNames[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}; 9 | int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 10 | 11 | for(int i = 0; i < 12; i++) 12 | { 13 | cout << monthNames[i] << ": " << days[i] << " days" << endl; 14 | } 15 | 16 | struct month 17 | { 18 | const char *name; 19 | int days; 20 | }; 21 | 22 | month months[] = { 23 | {"Jan", 31}, 24 | {"Feb", 28}, 25 | {"Mar", 31}, 26 | {"Apr", 30}, 27 | {"May", 31}, 28 | {"Jun", 30}, 29 | {"Jul", 31}, 30 | {"Aug", 31}, 31 | {"Sep", 30}, 32 | {"Oct", 31}, 33 | {"Nov", 30}, 34 | {"Dec", 31} 35 | }; 36 | 37 | for(int i = 0; i < 12; i++) 38 | { 39 | cout << months[i].name << ": " << months[i].days << " days" << endl; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /ch17/ex33.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch17 { 4 | template 5 | class Hash 6 | { 7 | typedef size_t (*hash_func)(const T& key); 8 | hash_func hash; 9 | public: 10 | Hash(hash_func hf) : hash(hf) {} 11 | 12 | size_t operator()(const T& key) const { 13 | size_t res = 0; 14 | while(size_t v = hash(key)) res = (res << 3) ^ v; 15 | return res; 16 | }; 17 | }; 18 | 19 | // Seems a little scary to have to store the position in a static field. 20 | // Very thread-unsafe. Did I miss something the exercise was hinting at? 21 | typedef const char* Pchar; 22 | size_t hash_cstr(const Pchar& s) { 23 | static int pos = 0; 24 | if(s[pos]) 25 | return s[pos++]; 26 | else { 27 | pos = 0; 28 | return 0; 29 | } 30 | } 31 | } 32 | 33 | int main() { 34 | using namespace std; 35 | using namespace ch17; 36 | 37 | Hash h(hash_cstr); 38 | cout << h("Hello World") << endl; 39 | } 40 | -------------------------------------------------------------------------------- /ch18/ex08.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ch18 { 9 | double square(double x) { 10 | return x * x; 11 | } 12 | 13 | double square_root(double x) { 14 | return sqrt(x); 15 | } 16 | 17 | class Print_nth : public std::unary_function { 18 | int i; 19 | public: 20 | Print_nth() : i(1) { } 21 | int operator()(double x) { 22 | std::cout << i++ << ':' << x << ' '; 23 | return x; 24 | } 25 | }; 26 | } 27 | 28 | int main() { 29 | using namespace ch18; 30 | using namespace std; 31 | 32 | vector v(100); 33 | for(int i = 1; i <= 100; i++) 34 | v[i-1] = i; 35 | 36 | transform(v.begin(), v.end(), v.begin(), square); 37 | for_each(v.begin(), v.end(), Print_nth()); 38 | cout << endl; 39 | transform(v.begin(), v.end(), v.begin(), square_root); 40 | for_each(v.begin(), v.end(), Print_nth()); 41 | cout << endl; 42 | } -------------------------------------------------------------------------------- /ch17/ex14.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // create a copy of the stack so that we don't need to change it 5 | // then "reverse" that stack into yet another stack, and print out those values in order 6 | // this method is still O(n) but has a higher per-element cost because of the multiple 7 | // copies that need to be made. to make this faster, some implementations support the 8 | // ability to get the underlying collection. however, any technique that relied on this 9 | // would not be portable. so i'll do it the straightforward way here. 10 | template 11 | void print_reverse(std::stack s) { 12 | using namespace std; 13 | stack s2; 14 | while(!s.empty()) { 15 | s2.push(s.top()); 16 | s.pop(); 17 | } 18 | while(!s2.empty()) { 19 | cout << s2.top() << endl; 20 | s2.pop(); 21 | } 22 | } 23 | 24 | int main() 25 | { 26 | using namespace std; 27 | 28 | stack s; 29 | s.push(1); 30 | s.push(2); 31 | s.push(3); 32 | 33 | print_reverse(s); 34 | } 35 | -------------------------------------------------------------------------------- /ch16/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | class initial 7 | { 8 | char c; 9 | public: 10 | initial(char c) : c(c) {} 11 | bool operator()(std::string s) { return s.size() > 0 && s[0] == c; } 12 | }; 13 | 14 | int main() 15 | { 16 | using namespace std; 17 | 18 | typedef vector StringVec; 19 | 20 | string fruit; 21 | vector fruits; 22 | 23 | cout << "enter some types of fruit, blank line to end:" << endl; 24 | getline(cin,fruit); 25 | while(fruit.size() > 0) 26 | { 27 | fruits.push_back(fruit); 28 | getline(cin, fruit); 29 | } 30 | 31 | // the sort is just carried over from the last few exercises 32 | sort(fruits.begin(),fruits.end()); 33 | 34 | fruits.erase(remove_if(fruits.begin(),fruits.end(),initial('a')),fruits.end()); 35 | 36 | for(StringVec::const_iterator i = fruits.begin(); i != fruits.end(); i++) 37 | { 38 | cout << *i << endl; 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /ch15/ex07.txt: -------------------------------------------------------------------------------- 1 | These are the C++ keywords I was able to think of without using a reference. I 2 | consider only standard C++ keywords (no extensions) and I do not include 3 | preprocessor directives. 4 | 5 | new (includes new[]) 6 | delete (includes delete[]) 7 | virtual 8 | static 9 | auto (not used until C++0x) 10 | class 11 | struct 12 | enum 13 | public 14 | private 15 | protected 16 | volatile 17 | explicit 18 | extern 19 | export 20 | template 21 | using (includes using namespace) 22 | namespace 23 | const 24 | this 25 | operator 26 | 27 | return 28 | if 29 | for 30 | else 31 | goto 32 | while 33 | do 34 | try 35 | catch 36 | case 37 | switch 38 | continue 39 | break 40 | 41 | typeid 42 | typename 43 | sizeof 44 | static_cast 45 | dynamic_cast 46 | reinterpret_cast 47 | const_cast 48 | 49 | signed 50 | unsigned 51 | void 52 | int 53 | float 54 | double 55 | long 56 | char 57 | bool 58 | true 59 | false 60 | short 61 | 62 | Here are the keywords I missed: 63 | friend 64 | default 65 | inline 66 | mutable 67 | register 68 | typedef 69 | union 70 | wchar_t 71 | -------------------------------------------------------------------------------- /ch16/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | bool citrus_filter(std::string s) { 7 | static const char* names[] = { "orange", "grapefruit", "lemon", "lime", "tangerine" }; 8 | int end = sizeof(names) / sizeof(char*); 9 | return find(&names[0], &names[end], s) < &names[end]; 10 | } 11 | 12 | int main() 13 | { 14 | using namespace std; 15 | 16 | string fruit; 17 | vector fruits; 18 | 19 | cout << "enter some types of fruit, blank line to end:" << endl; 20 | getline(cin,fruit); 21 | while(fruit.size() > 0) 22 | { 23 | fruits.push_back(fruit); 24 | getline(cin, fruit); 25 | } 26 | 27 | // the sort is just carried over from the last few exercises 28 | sort(fruits.begin(),fruits.end()); 29 | 30 | fruits.erase(remove_if(fruits.begin(),fruits.end(),citrus_filter),fruits.end()); 31 | 32 | for(vector::const_iterator i = fruits.begin(); i != fruits.end(); i++) 33 | { 34 | cout << *i << endl; 35 | } 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ch08/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | const int maxLevel = 10; 8 | int throwLevel; 9 | 10 | struct LevelReachedError 11 | { 12 | string funcName; 13 | 14 | LevelReachedError(string f) 15 | { 16 | funcName=f; 17 | } 18 | }; 19 | 20 | void b(int level); 21 | 22 | void a(int level) 23 | { 24 | if(level==throwLevel) 25 | throw LevelReachedError("a"); 26 | if(level >= maxLevel) return; 27 | b(level+1); 28 | } 29 | 30 | void b(int level) 31 | { 32 | if(level==throwLevel) 33 | throw LevelReachedError("b"); 34 | if(level >= maxLevel) return; 35 | a(level+1); 36 | } 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | if(argc<2) return -1; 41 | throwLevel = atoi(argv[1]); 42 | 43 | try 44 | { 45 | if(throwLevel==0) throw LevelReachedError("main"); 46 | a(1); 47 | } 48 | catch(LevelReachedError err) 49 | { 50 | cout << "calling level reached in function " + err.funcName << endl; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ch10/ex20.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | enum Type {S, I}; 4 | 5 | class Entry 6 | { 7 | char* name; 8 | Type t; 9 | union { 10 | const char* s; 11 | int i; 12 | }; 13 | public: 14 | class InvalidOperationError {}; 15 | 16 | Entry() {} 17 | Entry(const char* s) : t(S), s(s) {} 18 | Entry(int i) : t(I), i(i) {} 19 | const char* get_s() 20 | { 21 | if(t != S) 22 | throw InvalidOperationError(); 23 | return s; 24 | } 25 | int get_i() 26 | { 27 | if(t != I) 28 | throw InvalidOperationError(); 29 | return i; 30 | } 31 | void set(const char* str) 32 | { 33 | t = S; 34 | s = str; 35 | } 36 | void set(int num) 37 | { 38 | t = I; 39 | i = num; 40 | } 41 | }; 42 | 43 | int main() 44 | { 45 | using namespace std; 46 | 47 | Entry e1("hello"); 48 | Entry e2(4); 49 | cout << e1.get_s() << endl; 50 | cout << e2.get_i() << endl; 51 | e2.set("goodbye"); 52 | cout << e2.get_s() << endl; 53 | } 54 | -------------------------------------------------------------------------------- /ch21/ex24.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch21 { 6 | using std::ios; 7 | using std::ios_base; 8 | 9 | class Error_all { 10 | ios* s; 11 | ios::iostate old_state; 12 | 13 | public: 14 | explicit Error_all(ios* s) : s(s) { 15 | old_state = s->exceptions(); 16 | s->exceptions(ios::eofbit | ios::failbit | ios::badbit); 17 | } 18 | ~Error_all() { 19 | s->exceptions(old_state); 20 | s->clear(); 21 | } 22 | }; 23 | 24 | void readints(std::vector& s) { 25 | Error_all err(&std::cin); 26 | 27 | for(;;) { 28 | try { 29 | int i; 30 | std::cin >> i; 31 | s.push_back(i); 32 | } 33 | catch(ios::failure) { 34 | std::cout << "caught ios::failure" << std::endl; 35 | break; 36 | } 37 | } 38 | } 39 | } 40 | 41 | int main() { 42 | using namespace std; 43 | using namespace ch21; 44 | vector v; 45 | readints(v); 46 | } -------------------------------------------------------------------------------- /ch20/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Compile with: 6 | // g++ -o ex13 ex13.cpp -lrt 7 | 8 | unsigned long diff(timespec start, timespec end) { 9 | timespec tmp; 10 | if((end.tv_nsec-start.tv_nsec)<0) { 11 | tmp.tv_sec = end.tv_sec-start.tv_sec-1; 12 | tmp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; 13 | } else { 14 | tmp.tv_sec = end.tv_sec-start.tv_sec; 15 | tmp.tv_nsec = end.tv_nsec-start.tv_nsec; 16 | } 17 | return tmp.tv_sec * 1000000000 + tmp.tv_nsec; 18 | } 19 | 20 | int main() { 21 | using namespace std; 22 | string s(1024, 'x'); 23 | 24 | timespec start, end; 25 | clock_gettime(CLOCK_REALTIME, &start); 26 | for(int i = 0; i < 1000000; i++) { 27 | string s2(s); 28 | } 29 | clock_gettime(CLOCK_REALTIME, &end); 30 | cout << "fast: " << diff(start, end) << endl; 31 | clock_gettime(CLOCK_REALTIME, &start); 32 | for(int i = 0; i < 1000000; i++) { 33 | string s2(s, 0, s.size()); 34 | } 35 | clock_gettime(CLOCK_REALTIME, &end); 36 | cout << "slow: " << diff(start, end) << endl;} 37 | -------------------------------------------------------------------------------- /ch12/gfxlib/circle.h: -------------------------------------------------------------------------------- 1 | #ifndef __CIRCLE_H__ 2 | #define __CIRCLE_H__ 3 | 4 | #include "shape.h" 5 | #include "window.h" 6 | 7 | namespace gfxlib 8 | { 9 | class Circle : public Shape 10 | { 11 | Point m_c; 12 | int m_r; 13 | public: 14 | Circle(const Point& c, const int r) : m_c(c),m_r(r) {} 15 | virtual void draw(Window& s) const; 16 | virtual const Point n() const { return Point(m_c.x(),m_c.y()-m_r); } 17 | virtual const Point s() const { return Point(m_c.x(),m_c.y()+m_r); } 18 | virtual const Point w() const { return Point(m_c.x()-m_r,m_c.y()); } 19 | virtual const Point e() const { return Point(m_c.x()+m_r,m_c.y()); } 20 | virtual const Point nw() const { return Point(m_c.x()-m_r,m_c.y()-m_r); } 21 | virtual const Point ne() const { return Point(m_c.x()+m_r,m_c.y()-m_r); } 22 | virtual const Point sw() const { return Point(m_c.x()-m_r,m_c.y()+m_r); } 23 | virtual const Point se() const { return Point(m_c.x()+m_r,m_c.y()+m_r); } 24 | virtual const Point c() const { return m_c; } 25 | }; 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /ch21/ex19.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // This isn't portable and it's also a bit crude because it only works for stdin. 6 | // Using it with anything but cin will have no effect. 7 | namespace ch21 { 8 | void set_echo(bool enable) { 9 | termios tty; 10 | tcgetattr(STDIN_FILENO, &tty); 11 | if(enable) 12 | tty.c_lflag |= ECHO; 13 | else 14 | tty.c_lflag &= ~ECHO; 15 | tcsetattr(STDIN_FILENO, TCSANOW, &tty); 16 | } 17 | 18 | std::istream& echo_on(std::istream& in) { 19 | if(in == std::cin) 20 | set_echo(true); 21 | return in; 22 | } 23 | 24 | std::istream& echo_off(std::istream& in) { 25 | if(in == std::cin) 26 | set_echo(false); 27 | return in; 28 | } 29 | } 30 | 31 | int main() { 32 | using namespace std; 33 | using namespace ch21; 34 | 35 | cout << "Enter hidden integer: "; 36 | string s; 37 | cin >> echo_off >> s; 38 | cout << "\nYou entered: " << s << endl; 39 | cout << "Enter shown integer: "; 40 | cin >> echo_on >> s; 41 | } 42 | -------------------------------------------------------------------------------- /ch17/ex30.txt: -------------------------------------------------------------------------------- 1 | I don't really get this question, but I'll give it a shot. 2 | 3 | 1. Rebuild the table, ignoring erased elements (the original implementation 4 | does this already). 5 | 2. Use a loop on each vector bucket to deallocate erased nodes and link the 6 | previous node to the next node (it's just a linked list). 7 | 3. If the buckets are implemented using a data structure for which standard 8 | iterators are available, the remove_if function could be used with a predicate 9 | to remove all erased nodes to the end and then erase them from there. This 10 | would avoid a loop. 11 | 4. Erased nodes could be removed immediately when they are erased. This avoids 12 | a loop later. This again depends on the data structure used for the buckets. 13 | With the simple linked list, it's just a matter of linking the previous node 14 | to the next node and deallocating the erased node (or changing the root node 15 | in the hash table if it's the first one). 16 | 17 | It would not be advisable to use an iterator over the whole hash_map container 18 | and some algorithm function to remove erased nodes because a changing 19 | container may cause active iterators to blow up. 20 | -------------------------------------------------------------------------------- /ch21/ex25.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | using namespace std; 7 | 8 | locale loc; 9 | if(argc > 1) { 10 | // use "locale -a" to find valid locales for your system 11 | // e.g.: en_US.utf8 12 | // default is usually "C" 13 | loc = locale(argv[1]); 14 | } 15 | string s; 16 | tm t; 17 | t.tm_year = 2012; 18 | t.tm_mday = 31; 19 | t.tm_mon = 1; 20 | cout << "Enter a date (e.g. "; 21 | const time_put& tmput = use_facet >(loc); 22 | tmput.put(ostreambuf_iterator(cout), cout, ' ', &t, 'x', 0); 23 | cout << "): "; 24 | 25 | const time_get& tmget = use_facet >(loc); 26 | ios::iostate state; 27 | tmget.get_date(istreambuf_iterator(cin), istreambuf_iterator(), cin, state, &t); 28 | 29 | if(state != ios::goodbit) 30 | cout << "error parsing date" << endl; 31 | else { 32 | cout << "You entered: "; 33 | tmput.put(ostreambuf_iterator(cout), cout, ' ', &t, 'x', 0); 34 | cout << endl; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /ch17/ex24.txt: -------------------------------------------------------------------------------- 1 | To make equal_range trivial to implement, it seems to me that the easiest 2 | approach is a chained one, where all key/value pairs with the same key are 3 | stored in a single linked list. This makes it very easy to get the first and 4 | last elements because they are all in the same place. In fact, the list need 5 | not be traversed since equal_range's second result is one beyond the final 6 | value for the given key. 7 | 8 | So, equal_range's first result for key K would be the first node in the list 9 | for K. Then, equal_range's second result would simply be the first node of the 10 | following list in the hash table (or end() if there are no further entries). 11 | 12 | The main problem with this approach is that the hash table entries may have to 13 | be traversed to find the next used entry, and this could be a O(n) search in 14 | the hash table in the worst case, where n is the number of hash table entries 15 | (not the number of key/value pairs). The exercise didn't say anything about 16 | efficiency, so I'm not going to worry too much about that. Hash maps are 17 | designed for fast lookup, insert, etc. - not necessarily the fastest 18 | iteration. 19 | -------------------------------------------------------------------------------- /ch21/ex12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch21 { 5 | class File_random_access { 6 | std::ifstream f; 7 | 8 | public: 9 | File_random_access(const char* file) : f(file) { 10 | f.exceptions(std::ios::failbit | std::ios::eofbit); 11 | } 12 | char operator[](std::streampos pos) { 13 | f.seekg(pos, std::ios::beg); 14 | return f.peek(); 15 | } 16 | }; 17 | } 18 | 19 | int main() { 20 | using namespace std; 21 | using namespace ch21; 22 | 23 | ofstream out("ex12.txt"); 24 | out << "abcdefghijklmnopqrstuvwxyz"; 25 | out.close(); 26 | 27 | File_random_access f("ex12.txt"); 28 | cout << "char 5 = " << f[5] << endl; 29 | cout << "char 10 = " << f[10] << endl; 30 | cout << "char 0 = " << f[0] << endl; 31 | try { 32 | cout << "char 50 = " << f[50] << endl; 33 | } 34 | catch(ios::failure) { 35 | cout << "caught ios::failure" << endl; 36 | } 37 | try { 38 | cout << "char -1 = " << f[-1] << endl; 39 | } 40 | catch(ios::failure) { 41 | cout << "caught ios::failure" << endl; 42 | } 43 | } -------------------------------------------------------------------------------- /ch20/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // back_inserter already works with basic_string, am I missing something here? 6 | // Anyway, here's a reimplementation of basic_string. 7 | namespace ch20 { 8 | using namespace std; 9 | 10 | template 11 | class Back_inserter : public iterator { 12 | protected: 13 | Cont* c; 14 | public: 15 | typedef Cont container_type; 16 | explicit Back_inserter(Cont& x) : c(&x) { } 17 | Back_inserter& operator=(typename Cont::const_reference val) { c->push_back(val); return *this; } 18 | Back_inserter& operator*() { return *this; } 19 | Back_inserter& operator++() { return *this; } 20 | Back_inserter& operator++(int) { return *this; } 21 | }; 22 | 23 | template 24 | Back_inserter back_inserter(Cont& x) { 25 | return ch20::Back_inserter(x); 26 | } 27 | } 28 | 29 | int main() { 30 | using namespace ch20; 31 | 32 | string s("Hello"); 33 | const char* p = " world!"; 34 | copy(p, p + 7, ch20::back_inserter(s)); 35 | cout << s << endl; 36 | } -------------------------------------------------------------------------------- /ch04/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template struct complex { T x, y; }; 5 | 6 | /////////////////////////////////////////////// 7 | char ch1; 8 | char ch2 = 'a'; 9 | 10 | std::string s1; 11 | std::string s2 = "hello"; 12 | 13 | int count1; 14 | int count2 = 1; 15 | 16 | // const can't be declared without declaration. 17 | const double pi2 = 3.14; 18 | 19 | extern int error_number1; 20 | int error_number2 = 5; 21 | 22 | const char* name1; 23 | const char* name2 = "Brett"; 24 | 25 | const char* season1[4]; 26 | const char* season2[] = {"spring","summer","fall","winter"}; 27 | 28 | struct Date; 29 | struct Date { int d, m, y; }; 30 | 31 | int day(Date*); 32 | int day(Date* p){return p->d;} 33 | 34 | double sqrt(double); 35 | double sqrt(double d){return pow(d,0.5);} 36 | 37 | template T abs1(T a) { return a < 0?-a : a; } 38 | 39 | typedef complex Point1; 40 | 41 | struct User; 42 | struct User { std::string name, password; }; 43 | 44 | enum Beer { Carlsberg, Tuborg, Thor }; 45 | enum Beer; 46 | 47 | // namespace requires definition. 48 | namespace NS2 { int a; } 49 | 50 | int main() 51 | { 52 | } 53 | -------------------------------------------------------------------------------- /ch20/ex08.txt: -------------------------------------------------------------------------------- 1 | There are many operations missing from the previous exercise. Implementing 2 | them all would be a full time job, as regular expressions are a complex 3 | mini-language. Seems excessive for a 2.5-point exercise. I'll just outline the 4 | major things here: 5 | - Instead of basic glob matching, '.' should refer to any character, and '?' 6 | '+' and '*' should be modifiers that specify the number of characters to match 7 | (zero/one, one, zero/many). 8 | - Regex captures and "or" syntax, e.g. (foo|bar) 9 | - Match specific numbers of a sub-pattern or character, e.g. '{3,2}' 10 | - Character classes like \w, \s, etc. 11 | - Ranges, like [A-Za-z0-9] 12 | - "Not" character set, like [^A-Z] 13 | - Anchors: ^ and $ 14 | - Escaping: \. 15 | - Pattern modifiers like /pattern/g or /pattern/gi for global or case-insensitive matching. 16 | - Non-greedy * matching 17 | 18 | It's likely that the implementation from the previous exercise is much faster 19 | than a full regex implementation simply because it's incredibly simple. 20 | However, regex libraries can do more optimization to make up for this (for 21 | example, in many environments, regular expressions actually compile to 22 | bytecode or machine code). 23 | -------------------------------------------------------------------------------- /ch25/ex19.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch25 { 5 | template 6 | class Compose : public std::unary_function { 7 | F f; 8 | G g; 9 | public: 10 | Compose(const F& f, const G& g) : f(f), g(g) { } 11 | typename F::result_type operator()(const typename G::argument_type& x) { 12 | return f(g(x)); 13 | } 14 | }; 15 | 16 | template 17 | Compose compose(const F& f, const G& g) { 18 | return Compose(f, g); 19 | } 20 | 21 | class Func_incr : public std::unary_function { 22 | public: 23 | int operator()(int x) { 24 | return x + 1; 25 | } 26 | }; 27 | 28 | class Func_mult : public std::unary_function { 29 | int f; 30 | public: 31 | Func_mult(int factor) : f(factor) { } 32 | int operator()(int x) { 33 | return x * f; 34 | } 35 | }; 36 | } 37 | 38 | int main() { 39 | using namespace std; 40 | using namespace ch25; 41 | 42 | cout << compose(Func_mult(2),Func_incr())(7) << endl; 43 | } 44 | -------------------------------------------------------------------------------- /ch12/evtsim/task.h: -------------------------------------------------------------------------------- 1 | #ifndef __TASK_H__ 2 | #define __TASK_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "queue.h" 9 | 10 | namespace evtsim 11 | { 12 | class Scheduler; 13 | 14 | class Task 15 | { 16 | public: 17 | enum State { RUNNING, IDLE, DONE, ERR }; 18 | 19 | State state; 20 | Scheduler* sched; 21 | friend class Scheduler; 22 | 23 | private: 24 | ucontext_t context; 25 | void *stack; 26 | QueueList queues; 27 | 28 | protected: 29 | Task(Scheduler* s); 30 | void set_state(State s) { state = s; } 31 | void subscribe(std::string queueName); 32 | void unsubscribe(std::string queueName); 33 | void send_message(std::string queueName, const Message& m); 34 | void wait_message(); 35 | Message get_message(std::string queueName); 36 | void delay(int vTime); 37 | 38 | public: 39 | State get_state() { return state; } 40 | void schedule(); 41 | 42 | virtual void run() = 0; 43 | }; 44 | 45 | typedef std::queue TaskList; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /ch15/othello/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "game.h" 5 | #include "cboard.h" 6 | #include "gboard.h" 7 | #include "humanplayer.h" 8 | #include "aiplayer.h" 9 | 10 | using namespace othello; 11 | using namespace std; 12 | 13 | int main(int argc, char* argv[]) 14 | { 15 | using namespace std; 16 | 17 | Board* b; 18 | Player* p1; 19 | Player* p2; 20 | 21 | std::string p1name; 22 | std::string p2name; 23 | 24 | cout << "Enter player 1's name: "; 25 | getline(cin, p1name); 26 | cout << "Enter player 2's name (blank for computer): "; 27 | getline(cin, p2name); 28 | 29 | if(argc > 1 && strncmp(argv[1],"-g",2) == 0) 30 | b = new GuiBoard(); 31 | else 32 | b = new ConsoleBoard(); 33 | 34 | p1 = new HumanPlayer(*b, Board::Black, p1name, *b); 35 | if(p2name.size() == 0) 36 | p2 = new AIPlayer(*b, Board::White); 37 | else 38 | p2 = new HumanPlayer(*b, Board::White, p2name, *b); 39 | 40 | Game* g = new Game(*b, *p1, *p2); 41 | g->play(); 42 | 43 | delete g; 44 | delete b; 45 | delete p1; 46 | delete p2; 47 | 48 | return 0; 49 | }; 50 | -------------------------------------------------------------------------------- /ch06/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int f(int x, int y){return x+y;} 6 | 7 | int main() 8 | { 9 | // assumption: we're supposed to add parens to show the associativity of the different 10 | // operators, without changing the meaning of the statement. this shows that a number 11 | // of the expressions are nonsensical. 12 | int a, b, c, d, x, i; 13 | a = b = c = d = x = i = 1; 14 | 15 | a = b + c * d << 2 & 8; 16 | a = (((b + (c * d)) << 2) & 8); 17 | 18 | a & 077 != 3; 19 | (a & (077 != 3)); 20 | 21 | a == b || a == c && c < 5; 22 | ((a == b) || ((a == c) && (c < 5))); 23 | 24 | c = x != 0; 25 | (c = (x != 0)); 26 | 27 | 0 <= i < 7; 28 | ((0 <= i) < 7); 29 | 30 | f(1,2)+3; 31 | ((f(1,2))+3); 32 | 33 | a = -1 + +b-- - 5; 34 | a = ((-1) + (+(b--)) - 5); 35 | 36 | a = b == c++; 37 | (a = (b == (c++))); 38 | 39 | a = b = c = 0; 40 | (a = (b = (c = 0))); 41 | 42 | int a1[4][2] = { { 1, 2 }, { 3, 4, }, { 5, 6, }, { 7, 8 } }; 43 | int* b1 = &a, *d1 = &b; 44 | 45 | a1[3][1] *= *b1 ? c : *d1 * 2; 46 | (((a1[3])[1]) *= ((*b1) ? c : ((*d1) * 2))); 47 | } 48 | -------------------------------------------------------------------------------- /ch12/gfxlib/rect.h: -------------------------------------------------------------------------------- 1 | #ifndef __RECT_H__ 2 | #define __RECT_H__ 3 | 4 | #include "shape.h" 5 | #include "window.h" 6 | 7 | namespace gfxlib 8 | { 9 | class Rect : public Shape 10 | { 11 | Point m_sw; 12 | Point m_ne; 13 | 14 | void draw_side(Window&, Point, Point) const; 15 | void draw_fill(Window&) const; 16 | public: 17 | Rect(const Point& sw, const Point& ne) : m_sw(sw), m_ne(ne) {} 18 | virtual void draw(Window&) const; 19 | virtual const Point n() const { return Point(c().x(),m_ne.y()); } 20 | virtual const Point s() const { return Point(c().x(),m_sw.y()); } 21 | virtual const Point w() const { return Point(m_sw.x(),c().y()); } 22 | virtual const Point e() const { return Point(m_ne.x(),c().y()); } 23 | virtual const Point nw() const { return Point(m_sw.x(),m_ne.y()); } 24 | virtual const Point ne() const { return m_ne; } 25 | virtual const Point sw() const { return m_sw; } 26 | virtual const Point se() const { return Point(m_ne.x(),m_sw.y()); } 27 | virtual const Point c() const { return Point((m_sw.x()+m_ne.x())/2,(m_sw.y()+m_ne.y())/2); } 28 | }; 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /xxd/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace xxd { 5 | class numpunct_es : public std::numpunct { 6 | public: 7 | explicit numpunct_es(int i = 0) : std::numpunct(i) { } 8 | 9 | std::string do_truename() const { return "verdad"; } 10 | std::string do_falsename() const { return "falso"; } 11 | }; 12 | } 13 | 14 | int main() { 15 | using namespace std; 16 | using namespace xxd; 17 | 18 | bool b; 19 | cout << "Enter bool as number: "; 20 | cin >> b; 21 | if(!cin) { 22 | cout << "invalid" << endl; 23 | return 1; 24 | } 25 | cout << "You entered: " << b << endl; 26 | 27 | cout << "Enter bool as English word: "; 28 | cin >> boolalpha >> b; 29 | if(!cin) { 30 | cout << "invalid" << endl; 31 | return 1; 32 | } 33 | cout << "You entered: " << boolalpha << b << endl; 34 | 35 | locale loc(locale(), new xxd::numpunct_es()); 36 | cin.imbue(loc); 37 | cout.imbue(loc); 38 | cout << "Enter a bool as Spanish word: "; 39 | cin >> b; 40 | if(!cin) { 41 | cout << "invalid" << endl; 42 | return 1; 43 | } 44 | cout << "You entered: " << b << endl; 45 | } 46 | -------------------------------------------------------------------------------- /ch12/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace ch12 4 | { 5 | class Char_vec { 6 | int sz; 7 | char element[1]; 8 | public: 9 | static Char_vec* new_char_vec(int s); 10 | char& operator[](int i) { return element[i]; } 11 | }; 12 | 13 | // Evil. 14 | // This will severely break if the order of fields change, new fields are added, 15 | // virtual methods are added (because there would then be a vtable pointer and maybe 16 | // other fields from derived classes) and for any number of other reasons that I may 17 | // not be thinking of right now. 18 | // 19 | // You can also tell from the fact that there are two uses of reinterpret_cast that 20 | // this function is entirely evil. 21 | Char_vec* Char_vec::new_char_vec(int s) 22 | { 23 | char* p = new char[sizeof(int)+s]; 24 | int* csz = reinterpret_cast(p); 25 | *csz = s; 26 | return reinterpret_cast(p); 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | using namespace std; 33 | using namespace ch12; 34 | 35 | Char_vec* cv = Char_vec::new_char_vec(10); 36 | (*(cv))[9] = 'x'; 37 | cout << (*(cv))[9] << endl; 38 | } 39 | -------------------------------------------------------------------------------- /ch12/gfxlib/window.h: -------------------------------------------------------------------------------- 1 | #ifndef __WINDOW_H__ 2 | #define __WINDOW_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "point.h" 11 | #include "shape.h" 12 | #include "text.h" 13 | 14 | namespace gfxlib 15 | { 16 | class Window 17 | { 18 | Point m_current; 19 | Color m_background; 20 | 21 | int m_w; 22 | int m_h; 23 | Display *m_display; 24 | ::Window m_window; 25 | ::GC m_gc; 26 | ::XImage *m_img; 27 | std::vector m_text; 28 | 29 | public: 30 | Window(Display *display, int w, int h, Color background); 31 | ~Window(); 32 | 33 | ::Window handle() const { return m_window; } 34 | void paint(); 35 | const Point& current() const { return m_current; } 36 | void current(const Point& p) { m_current = p; } 37 | void draw(Shape* s); 38 | Line connect(Shape* s1, Shape* s2); 39 | void set_pixel(Point p, Color c); 40 | void draw_dot(Point p, int thickness, Color c); 41 | void draw_text(Point p1, Point p2, const std::string& str, Color c); 42 | }; 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /ch05/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void f(char c) 7 | { 8 | cout << "f called with " << (int)c << endl; 9 | } 10 | 11 | void g(char& c) 12 | { 13 | cout << "g called with " << (int)c << endl; 14 | } 15 | 16 | void h(const char& c) 17 | { 18 | cout << "h called with " << (int)c << endl; 19 | } 20 | 21 | int main() 22 | { 23 | char c = 'a'; 24 | unsigned char uc = 'b'; 25 | signed char sc = 'c'; 26 | 27 | f('a'); 28 | f(49); 29 | f(3300); // overflow warning, but legal 30 | f(c); 31 | f(uc); 32 | f(sc); 33 | 34 | // g('a'); // Illegal, can't pass constant to non-const reference 35 | // g(49); // Illegal, can't pass constant to non-const reference 36 | // g(3300); // Illegal, can't pass constant to non-const reference 37 | g(c); 38 | // g(uc); // Illegal, type must match reference 39 | // g(sc); // Illegal, type must match reference 40 | 41 | h('a'); // temp variable created 42 | h(49); // temp variable created 43 | h(3300); // temp variable created, overflow warning 44 | h(c); 45 | h(uc); // temp var created only if char is signed 46 | h(sc); // temp var created only if char is unsigned 47 | } 48 | -------------------------------------------------------------------------------- /ch11/ex13.cpp: -------------------------------------------------------------------------------- 1 | // it won't win any obfuscation contests (especially since a preprocessor 2 | // can clean up the mess) but it's sufficiently rage-inducing. 3 | #include 4 | #include 5 | #define aa int32_t(24) 6 | #define qq char 7 | #define bb int32_t(16) 8 | #define jc class INT{int32_t i;public:INT(const long ii) : 9 | #define rr int pp 10 | #define ja(x) i;}INT& operator--(int){i^=0x77777777 11 | #define zz (qq) 12 | #define ee(x) <<((qq)(x)) 13 | #define ff(x) ;std::cout ee(x) 14 | #define jb i(ii) {}operator const int32_t() const {return 15 | #define gg(x) x--; 16 | #define hh(x,y) x+=y; 17 | #define cc int32_t(8) 18 | #define dd int32_t(0) 19 | #define jj(x) int32_t x 20 | #define kk(x,y) jj(x) = ll(y); 21 | #define j0 this;}INT operator-(const INT& x){return (i >> (int32_t)x) & 0xff;}}; 22 | #define ll(x) x; 23 | #define mm(x) x(){ 24 | #define oo } 25 | #define jr ; return *this;}INT& operator+=(const int32_t x){i|=(x<<16); return * 26 | #define pp mm(main) 27 | jc jb ja(0x77777777) jr j0 28 | #define int32_t INT 29 | rr;kk(a,0x1b1b)hh(a,0x1f12)gg(a)kk(b,0x0018)hh(b, 0x1857)gg(b)kk(c,0x1356)hh(c,0x051b) 30 | gg(c)ff(a-aa)ee(a-bb)ee(a-cc)ee(a-dd)ff(b-aa)ee(b-bb)ee(b-cc)ee(b-dd)ff(c-aa)ee(c-bb) 31 | ee(c-cc)ee(c-dd);return 0;oo 32 | -------------------------------------------------------------------------------- /ch09/ex05.cpp: -------------------------------------------------------------------------------- 1 | // An external include guard surrounds any include directives. 2 | // Wherever this include exists, the guard must be placed around it. 3 | #ifndef EX05_H 4 | #include "ex05.h" 5 | #define EX05_H 6 | #endif 7 | 8 | // The include (with external guard) is put here a second time to 9 | // test that it works. If the guard did not work, the compiler would 10 | // complain that the type Hello was declared twice. 11 | #ifndef EX05_H 12 | #include "ex05.h" 13 | #define EX05_H 14 | #endif 15 | 16 | // Advantages to the external include guard: 17 | // - The same include file would not be opened twice. 18 | // - The same include file would not be parsed twice, even if it was only to process 19 | // its internal include guard. 20 | // Disadvantages: 21 | // - Every instance of the include must be surrounded by the guard. 22 | // - Much copy/pasting would be required, leading to potential hard-to-diagnose errors. 23 | // - Even includes inside includes would have to hold the guard, duplicating the guard 24 | // over and over instead of centralizing it. 25 | // - A change to the name of the include file would require all guards to be carefully 26 | // replaced. Getting them out of sync would result in hard-to-diagnose errors. 27 | int main() 28 | { 29 | } 30 | -------------------------------------------------------------------------------- /ch19/ex04.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch19 { 6 | using namespace std; 7 | 8 | template > 9 | class ostream_iterator : public iterator { 10 | public: 11 | typedef Ch char_type; 12 | typedef Tr traits_type; 13 | typedef basic_ostream ostream_type; 14 | 15 | ostream_iterator(ostream_type& s) : s(s) { } 16 | ostream_iterator(ostream_type& s, const Ch* delim) : s(s), delim(delim) { } 17 | ostream_iterator(const ostream_iterator& x) : s(x.s), delim(x.delim) { } 18 | ~ostream_iterator() { } 19 | 20 | ostream_iterator& operator=(const T& val) { s << val; if (delim) s << delim; } 21 | 22 | ostream_iterator& operator*() { return *this; } 23 | ostream_iterator& operator++() { return *this; } 24 | ostream_iterator& operator++(int) { return *this; } 25 | private: 26 | ostream_type& s; 27 | const Ch* delim; 28 | }; 29 | } 30 | 31 | int main() { 32 | using namespace std; 33 | 34 | int arr[] = { 1, 2, 3, 4, 5 }; 35 | copy(arr, arr + 5, ch19::ostream_iterator(cout, " ")); 36 | cout << endl; 37 | } -------------------------------------------------------------------------------- /ch13/ex07.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch13 6 | { 7 | // The type T must have a default constructor that initializes it to zero. 8 | // T must also implement the += operator with another T. 9 | // K must have a compare operator (<) and equality (==). 10 | // Both types must have stream input operators (>>). 11 | template void sum_inputs() 12 | { 13 | using namespace std; 14 | 15 | map store; 16 | 17 | cout << "Enter key value pairs, one per line, separated by a space. Type `.' when done." << endl; 18 | K key; 19 | T val; 20 | 21 | for(;;) 22 | { 23 | cin >> key; 24 | if(key==".") break; 25 | cin >> val; 26 | store[key] += val; 27 | } 28 | 29 | cout << "Here are the sums:" << endl; 30 | for(typename map::const_iterator i = store.begin(); i != store.end(); i++) 31 | { 32 | cout << i->first << ": " << i->second << endl; 33 | } 34 | } 35 | } 36 | 37 | int main() 38 | { 39 | using namespace std; 40 | using namespace ch13; 41 | 42 | sum_inputs(); 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /ch11/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | struct X 6 | { 7 | int i; 8 | X(int i) : i(i) { } 9 | X operator+(int i) { return X(this->i + i); } 10 | }; 11 | 12 | struct Y 13 | { 14 | int i; 15 | Y(X x) : i(x.i) { }; 16 | Y operator+(X x) { return Y(i+x.i); } 17 | operator int() { return i; }; 18 | }; 19 | 20 | X operator*(X x,Y y) { return X(x.i*y.i); } 21 | int f(X x) { return x.i; } 22 | 23 | X x = 1; 24 | Y y = x; 25 | int i = 2; 26 | 27 | int main() 28 | { 29 | using namespace std; 30 | 31 | cout << (i + 10) << endl; // Built in int+int 32 | // cout << (y + 10) << endl; // Invalid: ambiguity, could mean (int)y + 10 or y + X(10) 33 | // cout << y + 10 * y << endl; // Invalid: ambiguity, could mean y + (10 * (int)y) or y + (X(10) * y) 34 | cout << (x + y + i).i << endl; // Y's int(), then built in int+int, then X operator+(int) 35 | cout << (x * x + i).i << endl; // Y(X), then X operator*(X,Y), then X operator+(int) 36 | cout << (f(7)) << endl; // X(int) 37 | // cout << (f(y)) << endl; // Invalid: no implicit conversion from type Y to X 38 | cout << (y + y) << endl; // Y's int(), Y's int(), built in int+int 39 | cout << (106 + y) << endl; // Y's int(), built in int+int 40 | } 41 | -------------------------------------------------------------------------------- /ch06/ex16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int atoi_(const char *s) 7 | { 8 | int num = 0; 9 | int base = 10; 10 | 11 | // assumption: 'character constant notation' means accepting, e.g. "'a'" and returning the numeric value 12 | // for the character 'a'. 13 | // short circuit and null termination guards against reading past the end. 14 | if(s[0] == '\'' && s[1] && s[2] == '\'') { 15 | return s[1]; 16 | } 17 | 18 | // null termination guards against reading past the end. 19 | if(s[0] == '0') { 20 | base = 8; 21 | if(s[1] == 'x') { 22 | s += 2; 23 | base = 16; 24 | } 25 | } 26 | 27 | char c; 28 | while ((c = *s++) && 29 | (isdigit(c) && (c - '0' <= base) // must be valid digit for base 30 | || ((c = toupper(c)) && base > 10 && c > 'A' && c < 'A' + (base-10))) // or letter <= base - 10 31 | ) { 32 | num *= base; 33 | num += isalpha(c) ? (c - 'A' + 10) : c - '0'; 34 | } 35 | return num; 36 | } 37 | 38 | int main(int argc, char* argv[]) 39 | { 40 | if (argc < 2) 41 | return -1; 42 | 43 | int i = atoi_(argv[1]); 44 | cout << i << endl; 45 | } 46 | -------------------------------------------------------------------------------- /ch17/ex34.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "hash_set.h" 3 | #include "hash_multimap.h" 4 | #include "hash_multiset.h" 5 | 6 | int main() { 7 | using namespace ch17; 8 | using namespace std; 9 | 10 | hash_set hs; 11 | for(int i = 0; i < 5; i++) 12 | hs.insert(i); 13 | 14 | hs.insert(4); 15 | hs.insert(10); 16 | 17 | for(hash_set::iterator i = hs.begin(); i != hs.end(); i++) { 18 | cout << *i << endl; 19 | } 20 | 21 | cout << endl; 22 | 23 | 24 | hash_multimap hmm; 25 | for(int i = 0; i < 5; i++) { 26 | hmm.insert(std::make_pair(i, i)); 27 | } 28 | hmm.insert(std::make_pair(4, 10)); 29 | hmm.insert(std::make_pair(1, 22)); 30 | hmm.erase(3); 31 | 32 | for(hash_multimap::iterator i = hmm.begin(); i != hmm.end(); i++) { 33 | cout << i->first << " = " << i->second << endl; 34 | } 35 | 36 | cout << endl; 37 | 38 | 39 | hash_multiset hms; 40 | for(int i = 0; i < 5; i++) { 41 | hms.insert(i); 42 | } 43 | hms.insert(1); 44 | hms.insert(2); 45 | hms.insert(2); 46 | hms.erase(4); 47 | hms.erase(1); 48 | 49 | for(hash_multiset::iterator i = hms.begin(); i != hms.end(); i++) { 50 | cout << *i << endl; 51 | } 52 | } -------------------------------------------------------------------------------- /ch18/ex18.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch18 { 6 | using std::less; 7 | using std::ostream_iterator; 8 | using std::iterator_traits; 9 | using std::cout; 10 | using std::endl; 11 | using std::swap; 12 | 13 | template 14 | void sort(Ran first, Ran last, Cmp cmp) { 15 | const size_t n = last - first; 16 | for(int gap = n/2; 0 < gap; gap /= 2) { 17 | for(int i = gap; i < n; i++) { 18 | for(int j = i-gap; 0 <= j; j -= gap) { 19 | if (cmp(*(first + (j+gap)), *(first + j))) { 20 | swap(*(first + j), *(first + (j+gap))); 21 | copy(first, last, ostream_iterator::value_type>(cout, " ")); 22 | cout << endl; 23 | } 24 | else 25 | break; 26 | } 27 | } 28 | } 29 | } 30 | 31 | template 32 | void sort(Ran first, Ran last) { 33 | ch18::sort(first, last, less::value_type>()); 34 | } 35 | } 36 | 37 | int main() { 38 | using namespace ch18; 39 | 40 | int arr[] = { 4, 6, 3, 2, 5, 1 }; 41 | ch18::sort(arr, arr + 6); 42 | } 43 | -------------------------------------------------------------------------------- /ch10/ex16/lexer.h: -------------------------------------------------------------------------------- 1 | #ifndef LEXER_H 2 | #define LEXER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace ch10 9 | { 10 | using std::string; 11 | using std::istream; 12 | using std::queue; 13 | 14 | struct Token 15 | { 16 | enum TokenValue { 17 | NAME, NUMBER, END, FUNC = '%', 18 | PLUS='+', MINUS='-', MUL='*', DIV='/', 19 | PRINT=';', ASSIGN='=', LP='(', RP=')', 20 | SEP=',' 21 | }; 22 | 23 | TokenValue Type; 24 | double NumberValue; 25 | string StringValue; 26 | 27 | Token(TokenValue type) : Type(type) {} 28 | Token(TokenValue type, double value) : Type(type), NumberValue(value) {} 29 | Token(TokenValue type, string value) : Type(type), StringValue(value) {} 30 | }; 31 | 32 | class Lexer 33 | { 34 | istream* input; 35 | int line; 36 | queue m_queue; 37 | 38 | Token read_token(); 39 | 40 | public: 41 | Lexer(istream* input) : input(input), line(1) {} 42 | Token pop(); 43 | Token peek(); 44 | void push(Token); 45 | int get_line() { return line; } 46 | void clear() { m_queue = std::queue(); } 47 | }; 48 | } 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /ch17/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch17 5 | { 6 | template 7 | class Queue 8 | { 9 | private: 10 | std::stack s1; 11 | std::stack s2; 12 | public: 13 | class UnderflowError {}; 14 | 15 | Queue() {} 16 | void push_back(T x) { s1.push(x); } 17 | T pop_front(); 18 | bool empty() const { return s1.empty() && s2.empty(); } 19 | }; 20 | 21 | template 22 | T Queue::pop_front() 23 | { 24 | if(s2.empty()) 25 | { 26 | if(s1.empty()) throw UnderflowError(); 27 | for(int i = s1.size(); i > 0; --i) 28 | { 29 | s2.push(s1.top()); 30 | s1.pop(); 31 | } 32 | } 33 | 34 | T x = s2.top(); 35 | s2.pop(); 36 | return x; 37 | } 38 | } 39 | 40 | int main() 41 | { 42 | using namespace std; 43 | using namespace ch17; 44 | 45 | Queue q; 46 | q.push_back(1); 47 | q.push_back(2); 48 | q.push_back(3); 49 | 50 | cout << q.pop_front() << endl; 51 | q.push_back(4); 52 | q.push_back(5); 53 | 54 | while(!q.empty()) 55 | { 56 | cout << q.pop_front() << endl; 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /ch10/ex17.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct MemberA 4 | { 5 | public: 6 | int x; 7 | MemberA(); 8 | }; 9 | 10 | struct MemberB 11 | { 12 | int x; 13 | public: 14 | MemberB(); 15 | }; 16 | 17 | class ClassA 18 | { 19 | public: 20 | static MemberA x; 21 | }; 22 | 23 | class ClassB 24 | { 25 | public: 26 | static MemberB x; 27 | }; 28 | 29 | MemberA::MemberA() 30 | { 31 | x = ClassB::x.x; // <- not yet constructed! 32 | std::cout << "MemberA constructor called!" << std::endl; 33 | } 34 | 35 | MemberB::MemberB() 36 | { 37 | x = ClassA::x.x; 38 | std::cout << "MemberB constructor called!" << std::endl; 39 | } 40 | 41 | MemberA ClassA::x; 42 | MemberB ClassB::x; 43 | 44 | // At the time when MemberA's constructor is called, MemberB's 45 | // constructor will not yet have been called. This means that 46 | // Class A's member's constructor may reference Class B's member, 47 | // but Class B's member is NOT yet initialized. 48 | // Since ClassA and ClassB are in the same compilation unit, their 49 | // static members will be constructed in the order they are defined. 50 | // 51 | // This is why dependencies between static fields should be avoided 52 | // without careful attention to the order in which they are run. 53 | // In general: don't do it! 54 | int main() 55 | { 56 | } 57 | -------------------------------------------------------------------------------- /ch21/ex02.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch21 { 5 | using namespace std; 6 | 7 | // Only supports US-style addresses, e.g. 8 | // John Smith 9 | // 123 Fake St. Suite 45 10 | // Seattle, WA 98101 11 | struct Name_and_address { 12 | string name; 13 | string address; 14 | string city; 15 | string state; 16 | unsigned int zip; 17 | }; 18 | 19 | ostream& operator<<(ostream& out, const Name_and_address& x) { 20 | out << x.name << '\n' << x.address << '\n' << x.city << ", " << x.state << ' ' << x.zip; 21 | } 22 | 23 | istream& operator>>(istream& in, Name_and_address& x) { 24 | Name_and_address tmp; 25 | if (getline(in, tmp.name) 26 | && getline(in, tmp.address) 27 | && getline(in, tmp.city, ',') 28 | && (in >> tmp.state) 29 | && (in >> tmp.zip) 30 | && in.ignore(80, '\n')) 31 | { 32 | if(tmp.state.size() == 2) { 33 | tmp.state[0] = toupper(tmp.state[0]); 34 | tmp.state[1] = toupper(tmp.state[1]); 35 | } 36 | x = tmp; 37 | } 38 | return in; 39 | } 40 | } 41 | 42 | int main() { 43 | using namespace ch21; 44 | 45 | Name_and_address x; 46 | while(cin >> x) 47 | cout << x << endl; 48 | } 49 | -------------------------------------------------------------------------------- /ch12/gfxlib/text.h: -------------------------------------------------------------------------------- 1 | #ifndef __TEXT_H__ 2 | #define __TEXT_H__ 3 | 4 | #include 5 | 6 | #include "shape.h" 7 | #include "point.h" 8 | 9 | namespace gfxlib 10 | { 11 | class Text : public Shape 12 | { 13 | private: 14 | Point m_p1; 15 | Point m_p2; 16 | std::string m_str; 17 | 18 | public: 19 | Text(const Point& p1, const Point& p2, const std::string str) : m_p1(p1), m_p2(p2), m_str(str) {} 20 | virtual void draw(Window&) const; 21 | virtual const Point n() const { return Point(c().x(),m_p1.y()m_p2.y()?m_p1.y():m_p2.y()); } 23 | virtual const Point w() const { return Point(m_p1.x()m_p2.x()?m_p1.x():m_p2.x(),c().y()); } 25 | virtual const Point nw() const { return Point(w().x(),n().y()); } 26 | virtual const Point ne() const { return Point(e().x(),n().y()); } 27 | virtual const Point sw() const { return Point(w().x(),s().y()); } 28 | virtual const Point se() const { return Point(e().x(),s().y()); } 29 | virtual const Point c() const { return Point((m_p1.x()+m_p2.x())/2, (m_p1.y()+m_p2.y())/2); } 30 | }; 31 | } 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /ch06/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | typedef vector ValueList; 9 | typedef map Matrix; 10 | typedef pair MatrixPair; 11 | 12 | double getSum(ValueList list) 13 | { 14 | double sum = 0; 15 | for(ValueList::const_iterator i = list.begin(); i != list.end(); i++) 16 | sum += *i; 17 | return sum; 18 | } 19 | 20 | void printStats(Matrix data) 21 | { 22 | cout << "Here are the stats so far:" << endl; 23 | for(Matrix::const_iterator i = data.begin(); i != data.end(); i++) 24 | { 25 | double sum = getSum((*i).second); 26 | cout << "Name = " << (*i).first << ", Sum = " << sum << ", Avg = " << sum / (*i).second.size() << endl; 27 | } 28 | } 29 | 30 | int main() 31 | { 32 | char *n; 33 | string name; 34 | double value; 35 | Matrix data; 36 | 37 | for(;;) 38 | { 39 | cout << "Enter 'name value':" << endl; 40 | 41 | name.clear(); 42 | cin >> name; 43 | cin >> value; 44 | 45 | if (!data.count(name)) 46 | { 47 | ValueList v; 48 | data.insert(MatrixPair(name,v)); 49 | } 50 | data[name].push_back(value); 51 | 52 | printStats(data); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /ch09/ex08/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_H 2 | #define PARSER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "error.h" 9 | #include "lexer.h" 10 | 11 | namespace Parser 12 | { 13 | using std::string; 14 | using std::vector; 15 | using std::map; 16 | using std::istream; 17 | using Lexer::Token; 18 | using Lexer::curr_sym; 19 | using Lexer::get_token; 20 | 21 | typedef vector ParamList; 22 | typedef vector ArgumentList; 23 | typedef vector TokenList; 24 | typedef double (*Function_ptr)(double); 25 | 26 | enum Function_type 27 | { 28 | FUNC_STANDARD, 29 | FUNC_BUILTIN 30 | }; 31 | 32 | struct Function 33 | { 34 | ParamList params; 35 | TokenList tokens; 36 | Function_type type; 37 | Function_ptr ptr; 38 | }; 39 | 40 | extern map table; 41 | extern map functions; 42 | 43 | void createFunc(string, Function_ptr); 44 | 45 | ParamList parameters(istream*); 46 | ArgumentList arguments(istream*); 47 | double call(istream*, string); 48 | double expr(istream*, bool); 49 | double func(istream*, bool); 50 | double prim(istream*, bool); 51 | double term(istream*, bool); 52 | } 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /ch17/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | char tolower_func(char ch) { 8 | return tolower(ch); 9 | } 10 | 11 | int main(int argc, char* argv[]) 12 | { 13 | using namespace std; 14 | 15 | if(argc < 2) 16 | { 17 | cerr << "please supply a filename" << endl; 18 | return -1; 19 | } 20 | 21 | ifstream f(argv[1]); 22 | if(!f.is_open()) 23 | { 24 | cerr << "could not open file" << endl; 25 | return -1; 26 | } 27 | 28 | set words; 29 | string word; 30 | 31 | while(f) 32 | { 33 | word.clear(); 34 | 35 | char ch; 36 | do { 37 | f.get(ch); 38 | } while (f && !isalpha(ch)); 39 | 40 | if(!f) break; 41 | 42 | word.push_back(ch); 43 | while(f.get(ch) && isalpha(ch)) 44 | word.push_back(ch); 45 | 46 | // commented out simplistic approach in favor of new approach above 47 | // f >> word; 48 | 49 | // transform all words to lowercase 50 | transform(word.begin(), word.end(), word.begin(), tolower_func); 51 | 52 | words.insert(word); 53 | } 54 | 55 | for(set::const_iterator i = words.begin(); i != words.end(); i++) 56 | cout << *i << endl; 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /ch18/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // Use only alphanumeric characters in a word (ignore punctuation). 9 | bool test_word(const std::string& x, const std::string& y) { 10 | std::string::const_iterator i1 = x.begin(); 11 | std::string::const_iterator i2 = y.begin(); 12 | for(;;) { 13 | while(i1 != x.end() && !isalnum(*i1)) i1++; 14 | while(i2 != y.end() && !isalnum(*i2)) i2++; 15 | if (i1 == x.end() || i2 == y.end()) 16 | break; 17 | if(*i1++ != *i2++) 18 | return false; 19 | } 20 | if(i1 != x.end()) { 21 | while(i1 != x.end() && !isalnum(*i1)) i1++; 22 | return i1 == x.end(); 23 | } 24 | if(i2 != y.end()) { 25 | while(i2 != y.end() && !isalnum(*i2)) i2++; 26 | return i2 == y.end(); 27 | } 28 | return true; 29 | } 30 | 31 | int main(int argc, char** argv) { 32 | using namespace std; 33 | 34 | if(argc != 2) 35 | return 1; 36 | ifstream in(argv[1]); 37 | if(!in) 38 | return 1; 39 | 40 | vector v; 41 | copy(istream_iterator(in), istream_iterator(), back_inserter(v)); 42 | v.erase(unique(v.begin(),v.end(),test_word), v.end()); 43 | copy(v.begin(), v.end(), ostream_iterator(cout, " ")); 44 | cout << endl; 45 | } 46 | -------------------------------------------------------------------------------- /ch12/ex12.cpp: -------------------------------------------------------------------------------- 1 | namespace ch12 2 | { 3 | class Monster; 4 | class Object; 5 | 6 | class Warrior 7 | { 8 | virtual void move(int,int) = 0; 9 | virtual void pick_up(Object*) = 0; 10 | virtual void drop(Object*) = 0; 11 | virtual void equip(Object*) = 0; // e.g. equip sword, shield, etc. 12 | virtual void use(Object*) = 0; // e.g. scroll, potion 13 | virtual void use(Object*,Object*) = 0; // e.g. use key on door 14 | virtual void use(Object*,Monster*) = 0; // e.g. use scroll's spell on monster 15 | virtual void attack(Monster*) = 0; 16 | virtual void take_damage(int) = 0; 17 | }; 18 | 19 | class Monster 20 | { 21 | virtual void move(int,int) = 0; 22 | virtual void attack(Warrior*) = 0; 23 | virtual void take_damage(int) = 0; 24 | }; 25 | 26 | class Object 27 | { 28 | virtual void use(Object*) = 0; // e.g. use key on door (called by Warrior::Use(Object*,Object*)) 29 | virtual void use(Warrior*) = 0; // e.g. use on warrior (might decrease number of "charges" left, etc., called by Warrior::Use(Object*)0) 30 | virtual void use(Monster*) = 0; // e.g. use on monster (called by Warrior::Use(Object*,Monster*)) 31 | virtual void degrade(int) = 0; // e.g. degrade a sword by 1 for each attack 32 | }; 33 | } 34 | 35 | int main() 36 | { 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /ch10/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "ex05.h" 3 | 4 | int main() 5 | { 6 | using namespace ch10; 7 | using namespace std; 8 | 9 | try 10 | { 11 | IntervalSet intervals; 12 | intervals.insert(1); 13 | intervals.insert(10); 14 | intervals.insert(20); 15 | intervals.insert(30); 16 | intervals.insert(40); 17 | intervals.insert(50); 18 | intervals.insert(60); 19 | intervals.insert(70); 20 | intervals.insert(80); 21 | intervals.insert(90); 22 | intervals.insert(100); 23 | 24 | Histogram hist(intervals); 25 | 26 | cout << "Histogram output with fixed numbers:" << endl; 27 | hist.add(1).add(10).add(11).add(19).add(20).add(11).add(89).add(89).add(89).add(90).add(95).add(100); 28 | hist.print_formatted(std::cout); 29 | 30 | cout << endl << "Histogram with random numbers:" << endl; 31 | hist = Histogram(intervals); 32 | srand(clock()); 33 | for(int i = 0; i < 100; i++) 34 | { 35 | hist.add(rand() % 100 + 1); 36 | } 37 | hist.print_formatted(std::cout); 38 | } 39 | catch(Histogram::OutOfRangeError) 40 | { 41 | cerr << "The value was out of range." << endl; 42 | } 43 | catch(Histogram::InvalidIntervalSetError) 44 | { 45 | cerr << "Invalid interval." << endl; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ch10/ex07/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef PARSER_H 2 | #define PARSER_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "error.h" 9 | #include "lexer.h" 10 | #include "table.h" 11 | 12 | namespace Parser 13 | { 14 | using std::string; 15 | using std::vector; 16 | using std::map; 17 | using std::istream; 18 | using Lexer::Token; 19 | using Lexer::curr_sym; 20 | using Lexer::get_token; 21 | 22 | typedef vector ParamList; 23 | typedef vector ArgumentList; 24 | typedef vector TokenList; 25 | typedef double (*Function_ptr)(double); 26 | typedef Table::Table ValueTable; 27 | 28 | enum Function_type 29 | { 30 | FUNC_STANDARD, 31 | FUNC_BUILTIN 32 | }; 33 | 34 | struct Function 35 | { 36 | ParamList params; 37 | TokenList tokens; 38 | Function_type type; 39 | Function_ptr ptr; 40 | }; 41 | 42 | extern ValueTable table; 43 | extern map functions; 44 | 45 | void createFunc(string, Function_ptr); 46 | 47 | ParamList parameters(istream*); 48 | ArgumentList arguments(istream*); 49 | double call(istream*, string); 50 | double expr(istream*, bool); 51 | double func(istream*, bool); 52 | double prim(istream*, bool); 53 | double term(istream*, bool); 54 | } 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /ch17/ex21.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | int main() { 9 | using namespace std; 10 | cout << "Enter name value pairs (blank to finish)" << endl; 11 | 12 | typedef map > DataList; 13 | DataList data; 14 | 15 | for(;;) 16 | { 17 | string s; 18 | getline(cin, s); 19 | if(s.size() == 0) 20 | break; 21 | istringstream parts(s); 22 | string name; 23 | int val; 24 | parts >> name; 25 | parts >> val; 26 | data[name].push_back(val); 27 | } 28 | 29 | for(DataList::const_iterator i = data.begin(); i != data.end(); i++) { 30 | vector v = i->second; 31 | sort(v.begin(), v.end()); 32 | int sum = 0; 33 | for(vector::const_iterator j = v.begin(); j != v.end(); j++) { 34 | sum += *j; 35 | cout << *j << endl; 36 | } 37 | double mean = (double)sum / v.size(); 38 | double median; 39 | if(v.size() % 2 == 0) 40 | median = (v[v.size() / 2] + v[v.size() / 2 + 1]) / 2.0; 41 | else 42 | median = v[v.size() / 2]; 43 | cout << "name: " << i->first 44 | << " total: " << sum 45 | << " mean: " << mean 46 | << " median: " << median 47 | << endl; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ch04/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | std::cout << "bool = " << sizeof(bool) << std::endl; 6 | std::cout << "signed char = " << sizeof(signed char) << std::endl; 7 | std::cout << "unsigned char = " << sizeof(unsigned char) << std::endl; 8 | std::cout << "signed short = " << sizeof(signed short) << std::endl; 9 | std::cout << "unsigned short = " << sizeof(unsigned short) << std::endl; 10 | std::cout << "signed int = " << sizeof(signed int) << std::endl; 11 | std::cout << "unsigned int = " << sizeof(unsigned int) << std::endl; 12 | std::cout << "signed long = " << sizeof(signed long) << std::endl; 13 | std::cout << "unsigned long = " << sizeof(unsigned long) << std::endl; 14 | std::cout << "signed long long = " << sizeof(signed long long) << std::endl; 15 | std::cout << "unsigned long long = " << sizeof(signed long long) << std::endl; 16 | std::cout << "float = " << sizeof(float) << std::endl; 17 | std::cout << "double = " << sizeof(double) << std::endl; 18 | std::cout << "long double = " << sizeof(long double) << std::endl; 19 | std::cout << "wchar_t = " << sizeof(wchar_t) << std::endl; 20 | std::cout << "char * = " << sizeof(char *) << std::endl; 21 | std::cout << "int * = " << sizeof(int *) << std::endl; 22 | 23 | enum Enum1 { a }; 24 | enum Enum2 { b, c, d, e }; 25 | 26 | std::cout << "Enum1 = " << sizeof(Enum1) << std::endl; 27 | std::cout << "Enum2 = " << sizeof(Enum2) << std::endl; 28 | } 29 | -------------------------------------------------------------------------------- /ch13/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch13 6 | { 7 | using std::cin; 8 | using std::cout; 9 | 10 | struct Count 11 | { 12 | int qty; 13 | }; 14 | 15 | struct Price 16 | { 17 | // just an example, never use double for currency :) 18 | double dollarsAndCents; 19 | }; 20 | 21 | struct Item 22 | { 23 | std::string name; 24 | Count count; 25 | Price price; 26 | }; 27 | 28 | template void readline(T& x) 29 | { 30 | cin >> x; 31 | } 32 | 33 | template<> void readline(Count& x) 34 | { 35 | cout << "Enter the count: "; 36 | cin >> x.qty; 37 | } 38 | 39 | template<> void readline(Price& x) 40 | { 41 | cout << "Enter the price: "; 42 | cin >> x.dollarsAndCents; 43 | } 44 | 45 | template<> void readline(Item& x) 46 | { 47 | cout << "Enter the item description: "; 48 | std::getline(cin,x.name); 49 | readline(x.count); 50 | readline(x.price); 51 | } 52 | } 53 | 54 | int main() 55 | { 56 | using namespace std; 57 | using namespace ch13; 58 | 59 | Item i; 60 | readline(i); 61 | 62 | cout << "Name: " << i.name << endl; 63 | cout << "Qty: " << i.count.qty << endl; 64 | cout << "Price: " << i.price.dollarsAndCents << endl; 65 | 66 | return 0; 67 | } 68 | -------------------------------------------------------------------------------- /ch07/ex11.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | void error(string s, ...) 8 | { 9 | istringstream in(s); 10 | char ch; 11 | int i = 0; 12 | va_list args; 13 | va_start(args, s); 14 | 15 | char *s_arg; 16 | double d_arg; 17 | char c_arg; 18 | 19 | while (in.get(ch)) 20 | { 21 | if(ch=='%') 22 | { 23 | switch(in.peek()) 24 | { 25 | case '%': 26 | cout << in.get(); 27 | break; 28 | case 's': 29 | s_arg = va_arg(args,char *); 30 | cout << s_arg; 31 | in.get(); 32 | break; 33 | case 'd': 34 | d_arg = va_arg(args,int); 35 | cout << d_arg; 36 | in.get(); 37 | break; 38 | case 'c': 39 | c_arg = static_cast(va_arg(args, int)); 40 | cout << c_arg; 41 | in.get(); 42 | break; 43 | default: 44 | cout << ch; 45 | break; 46 | } 47 | } 48 | else 49 | cout << ch; 50 | } 51 | 52 | cout << endl; 53 | va_end(args); 54 | } 55 | 56 | int main() 57 | { 58 | error("Hello %s", "world"); 59 | error("Hello %d %s", 5, "world"); 60 | error("Hello %c %d %s", 'a', 5, "world"); 61 | } 62 | -------------------------------------------------------------------------------- /ch20/ex01.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace ch20 { 7 | using namespace std; 8 | 9 | string combine(const string& s1, const string& s2) { 10 | // could also have done: string res = s1 + '.' + s2; 11 | string res(s1); 12 | res.push_back('.'); 13 | res.append(s2); 14 | return res; 15 | } 16 | 17 | // This method is a lot more prone to error, the developer has to take care to 18 | // allocate exactly the right number of bytes. it would be easy to forget the 19 | // null terminator. Also, the memory allocated cannot be freed inside the 20 | // function, so the caller would have to free it after it's finished with 21 | // the result. This is a recipe for memory leaks. 22 | // Determining the string length requires traversing the string more than 23 | // once (to find the null terminator). This is likely slower than a string 24 | // implementation because strings store their length explicitly. 25 | char* combine_c(const char* s1, const char* s2) { 26 | int len = strlen(s1); 27 | char* res = (char*)malloc(len + strlen(s2) + 2); 28 | strcpy(res, s1); 29 | res[len] = '.'; 30 | strcpy(res + len + 1, s2); 31 | return res; 32 | } 33 | } 34 | 35 | int main() { 36 | using namespace ch20; 37 | cout << combine("file", "write") << endl; 38 | char* res = combine_c("file", "write"); 39 | cout << res << endl; 40 | free(res); 41 | } 42 | -------------------------------------------------------------------------------- /ch21/ex13.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch21 { 5 | class File_random_access { 6 | std::fstream f; 7 | 8 | public: 9 | class File_pos_ref { 10 | std::fstream* f; 11 | std::streampos p; 12 | public: 13 | File_pos_ref(std::fstream* f, std::streampos p) : f(f), p(p) { } 14 | 15 | operator char() { 16 | f->seekg(p, std::ios::beg); 17 | return f->peek(); 18 | } 19 | 20 | File_pos_ref& operator=(char c) { 21 | f->seekp(p, std::ios::beg); 22 | f->put(c); 23 | } 24 | }; 25 | 26 | File_random_access(const char* file) : f(file) { 27 | f.exceptions(std::ios::failbit | std::ios::eofbit); 28 | } 29 | 30 | File_pos_ref operator[](std::streampos pos) { 31 | return File_pos_ref(&f, pos); 32 | } 33 | }; 34 | } 35 | 36 | int main() { 37 | using namespace std; 38 | using namespace ch21; 39 | 40 | ofstream out("ex13.txt"); 41 | out << "abcdefghijklmnopqrstuvwxyz"; 42 | out.close(); 43 | 44 | File_random_access f("ex13.txt"); 45 | f[4] = 'X'; 46 | cout << "char 3 = " << f[3] << endl; 47 | cout << "char 4 = " << f[4] << endl; 48 | cout << "char 5 = " << f[5] << endl; 49 | try { 50 | cout << "char 50 = " << f[50] << endl; 51 | } 52 | catch(ios::failure) { 53 | cout << "caught ios::failure" << endl; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch17/ex19.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch17 { 5 | template 6 | void merge(Coll1& c1, Coll2& c2) { 7 | typename Coll1::iterator ipos = c1.begin(); 8 | typename Coll2::iterator first = c2.begin(); 9 | typename Coll2::iterator last = c2.begin(); 10 | 11 | while(first != c2.end()) 12 | { 13 | while(ipos != c1.end() && *ipos < *first) { 14 | ++ipos; 15 | } 16 | do { 17 | ipos = c1.insert(ipos, *first++); 18 | } while (first != c2.end() && *first < *ipos); 19 | } 20 | c2.clear(); 21 | } 22 | } 23 | 24 | int main() { 25 | using namespace std; 26 | using namespace ch17; 27 | 28 | vector c1; 29 | c1.push_back(1); 30 | c1.push_back(3); 31 | c1.push_back(5); 32 | c1.push_back(5); 33 | c1.push_back(6); 34 | c1.push_back(7); 35 | c1.push_back(9); 36 | c1.push_back(9); 37 | 38 | vector c2; 39 | c2.push_back(2); 40 | c2.push_back(4); 41 | c2.push_back(6); 42 | c2.push_back(7); 43 | c2.push_back(8); 44 | c2.push_back(10); 45 | 46 | merge(c1,c2); 47 | 48 | // expect: 1 2 3 4 5 5 6 6 7 7 8 9 9 10 49 | for(vector::const_iterator i = c1.begin(); i != c1.end(); i++) { 50 | cout << *i << endl; 51 | } 52 | if(c2.empty()) { 53 | cout << "c2 is empty as expected" << endl; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ch16/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::vector; 7 | using std::string; 8 | 9 | class ContainsFilter 10 | { 11 | vector& names; 12 | public: 13 | ContainsFilter(vector& names) : names(names) {} 14 | 15 | bool operator()(std::string s) 16 | { 17 | return find(names.begin(),names.end(),s) < names.end(); 18 | } 19 | }; 20 | 21 | int main() 22 | { 23 | using namespace std; 24 | 25 | string fruit; 26 | vector fruitsYouDontLike; 27 | 28 | cout << "enter the names of some fruits you don't like, blank line to end:" << endl; 29 | getline(cin,fruit); 30 | while(fruit.size() > 0) 31 | { 32 | fruitsYouDontLike.push_back(fruit); 33 | getline(cin,fruit); 34 | } 35 | 36 | vector fruits; 37 | cout << "enter some types of fruit, blank line to end:" << endl; 38 | getline(cin,fruit); 39 | while(fruit.size() > 0) 40 | { 41 | fruits.push_back(fruit); 42 | getline(cin, fruit); 43 | } 44 | 45 | // the sort is just carried over from the last few exercises 46 | sort(fruits.begin(),fruits.end()); 47 | 48 | fruits.erase(remove_if(fruits.begin(),fruits.end(),ContainsFilter(fruitsYouDontLike)),fruits.end()); 49 | 50 | for(vector::const_iterator i = fruits.begin(); i != fruits.end(); i++) 51 | { 52 | cout << *i << endl; 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /ch15/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch15 5 | { 6 | class Arena 7 | { 8 | public: 9 | virtual void* alloc(size_t sz) = 0; 10 | virtual void free(void*) = 0; 11 | 12 | template void destroy(T* o) 13 | { 14 | o->~T(); 15 | free(o); 16 | } 17 | }; 18 | 19 | // a very simplistic arena that just wraps the C malloc and free functions, 20 | // meant simply to illustrate custom allocation. 21 | class CArena : public Arena 22 | { 23 | public: 24 | void* alloc(size_t sz) 25 | { 26 | return malloc(sz); 27 | } 28 | 29 | void free(void* p) 30 | { 31 | ::free(p); 32 | } 33 | }; 34 | 35 | class A 36 | { 37 | int m_x; 38 | public: 39 | A() : m_x(0) {} 40 | A(int x) : m_x(x) {} 41 | 42 | A* clone(Arena* a) 43 | { 44 | return new(a) A(*this); 45 | } 46 | 47 | void* operator new(size_t, Arena* a) 48 | { 49 | return a->alloc(sizeof(A)); 50 | } 51 | 52 | int x() { return m_x; } 53 | }; 54 | } 55 | 56 | int main() 57 | { 58 | using namespace std; 59 | using namespace ch15; 60 | 61 | CArena arena; 62 | 63 | A a(5); 64 | A* a1 = a.clone(&arena); 65 | cout << a1->x() << endl; // should print 5 66 | arena.destroy(a1); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /ch08/ex06.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | const int maxLevel = 65535; 9 | int throwLevel; 10 | 11 | // on my box, using g++, and based on highly unscientific measurements, 12 | // it appears to take about 0.01 seconds per additional 1000 levels of stack 13 | // to unwind the stack when an exception is thrown. 14 | 15 | struct LevelReachedError 16 | { 17 | string funcName; 18 | int start; 19 | 20 | LevelReachedError(string f) 21 | { 22 | funcName=f; 23 | start = clock(); 24 | } 25 | }; 26 | 27 | void b(int level); 28 | 29 | void a(int level) 30 | { 31 | if(level==throwLevel) 32 | throw LevelReachedError("a"); 33 | if(level >= maxLevel) return; 34 | b(level+1); 35 | } 36 | 37 | void b(int level) 38 | { 39 | if(level==throwLevel) 40 | throw LevelReachedError("b"); 41 | if(level >= maxLevel) return; 42 | a(level+1); 43 | } 44 | 45 | int main(int argc, char* argv[]) 46 | { 47 | if(argc<2) return -1; 48 | throwLevel = atoi(argv[1]); 49 | 50 | cout << "Clocks per sec: " << CLOCKS_PER_SEC << endl; 51 | try 52 | { 53 | if(throwLevel==0) throw LevelReachedError("main"); 54 | a(1); 55 | } 56 | catch(LevelReachedError err) 57 | { 58 | cout << "calling level reached in function " + err.funcName << endl; 59 | cout << "unwind time was " << clock() - err.start << endl; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /ch11/ex03.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class INT 4 | { 5 | int i; 6 | 7 | public: 8 | INT(const int ii) : i(ii) {} 9 | operator int() {return i;} 10 | INT operator++(int){INT i2=*this;i++;return i2;} 11 | INT& operator++(){i++; return *this;} 12 | INT operator--(int){INT i2=*this;i--;return i2;} 13 | INT& operator--(){i--; return *this;} 14 | INT& operator+=(const int x){i+=x; return *this;} 15 | INT& operator-=(const int x){i-=x; return *this;} 16 | friend std::istream& operator>>(std::istream&, INT&); 17 | }; 18 | 19 | std::istream& operator>>(std::istream& input, INT& x) 20 | { 21 | input >> x.i; 22 | return input; 23 | } 24 | 25 | void main() 26 | { 27 | using namespace std; 28 | 29 | INT x = 2; 30 | INT y = 3; 31 | cout << x + 1 << endl; 32 | cout << 1 + x << endl; 33 | cout << x + y << endl; 34 | cout << x * y << endl; 35 | cout << x / y << endl; 36 | cout << x % y << endl; 37 | cout << x << endl; 38 | x = 4 + 4; 39 | cout << x << endl; 40 | int z = 8; 41 | x = z; 42 | cout << x << endl; 43 | x++; 44 | z = x; 45 | cout << z << endl; 46 | cout << x++ << endl; 47 | cout << ++x << endl; 48 | cout << x-- << endl; 49 | cout << --x << endl; 50 | x += 1; 51 | cout << x << endl; 52 | x -= 1; 53 | cout << x << endl; 54 | cout << -x << endl; 55 | cin >> y; // Reference parameters must be exact, so the overload is required! 56 | cout << y + 1 << endl; 57 | } 58 | -------------------------------------------------------------------------------- /ch06/ex15.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | // This is Duff's device. It "unrolls" a loop by performing 8 work items per iteration instead of one. 6 | // The "remainder" of the count is handled by potentially starting in the middle of the loop on the first 7 | // go (this is what the switch statement is for). Then the do/while loop takes over and performs the rest 8 | // of the work, doing 8 copies at a time. 9 | // Loop unrolling has speed benefits because executing sequential instructions that copy values is faster 10 | // than doing many conditional jumps, which is what a loop does. This loop has to do up to 8 times fewer 11 | // conditional jumps to perform the same work. 12 | // Some compilers unroll loops automatically when feasible and when that optimization is enabled. 13 | void send(int* to, int* from, int count) 14 | { 15 | int n = (count+7)/8; 16 | switch(count%8) 17 | { 18 | case 0: do { *to++ = *from++; 19 | case 7: *to++ = *from++; 20 | case 6: *to++ = *from++; 21 | case 5: *to++ = *from++; 22 | case 4: *to++ = *from++; 23 | case 3: *to++ = *from++; 24 | case 2: *to++ = *from++; 25 | case 1: *to++ = *from++; 26 | } while (--n>0); 27 | } 28 | } 29 | 30 | int main(int argc, char* argv[]) 31 | { 32 | int a[20] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; 33 | int b[20]; 34 | 35 | send(b, a, 20); 36 | 37 | for(int i = 0; i < 20; i++) 38 | cout << b[i] << endl; 39 | } 40 | -------------------------------------------------------------------------------- /ch21/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // Implementing all of stdio.h is a lot more work than I want to do 6 | // for one exercise, so here are a few basic C I/O operations. I'll 7 | // use the non-file (console) versions, but it wouldn't be much harder 8 | // to use the file versions of the functions (e.g., fputs) by passing 9 | // in a struct that references an fstream. 10 | // 11 | // For the adventurous, you could translate a printf format string into 12 | // a series of mutator operations and writes to a stream. 13 | namespace ch21 { 14 | int getchar() { 15 | char ch; 16 | return (std::cin >> ch) ? ch : EOF; 17 | } 18 | 19 | // danger! beware buffer overflows! 20 | char* gets(char* str) { 21 | return std::cin.getline(str, std::numeric_limits::max()) ? str : 0; 22 | } 23 | 24 | int putchar(int ch) { 25 | return (std::cout << static_cast(ch)) ? ch : EOF; 26 | } 27 | 28 | int puts(const char* str) { 29 | return (std::cout << str) ? 1 : EOF; 30 | } 31 | } 32 | 33 | int main() { 34 | using std::cout; 35 | using std::endl; 36 | using namespace ch21; 37 | 38 | cout << "Enter a char: "; 39 | int ch = ch21::getchar(); 40 | cout << "You entered: "; 41 | ch21::putchar(ch); 42 | cout << endl; 43 | std::cin.getline(0, 0); // eat the newline; 44 | 45 | cout << "Enter a string: "; 46 | char str[512]; 47 | ch21::gets(str); 48 | cout << "You entered: "; 49 | ch21::puts(str); 50 | cout << endl; 51 | } -------------------------------------------------------------------------------- /ch25/ex09.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // One advantage of separating the checked interface is that users get to decide 4 | // whether they want to use it or not. Checking has performance considerations 5 | // and may not be appropriate in all circumstances. On the other hand, there are 6 | // many scenarios where checking is desirable and performance micro-optimization 7 | // is not a concern. 8 | namespace ch25 { 9 | // Readonly 10 | class String { 11 | const char* s; 12 | size_t sz; 13 | public: 14 | String(const char* s, size_t sz) : s(s), sz(sz) { } 15 | char operator[](size_t pos) const { return s[pos]; } 16 | size_t size() const { return sz; } 17 | }; 18 | 19 | class String_checked { 20 | String s; 21 | 22 | public: 23 | class Out_of_range { }; 24 | String_checked(const char* s, size_t sz) : s(s, sz) { } 25 | String_checked(String& s) : s(s) { } 26 | char operator[](size_t pos) const { check(pos); return s[pos]; } 27 | size_t size() const { return s.size(); } 28 | private: 29 | void check(size_t pos) const { 30 | if(pos < 0 || pos >= s.size()) 31 | throw Out_of_range(); 32 | } 33 | }; 34 | } 35 | 36 | int main() { 37 | using namespace std; 38 | using namespace ch25; 39 | 40 | String_checked s("foo bar", 7); 41 | char c = s[6]; 42 | try { 43 | c = s[7]; 44 | } 45 | catch(String_checked::Out_of_range) { 46 | cout << "caught String_checked::Out_of_range" << endl; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ch10/ex01.txt: -------------------------------------------------------------------------------- 1 | The add_year function (10.2.2) has a bug whenever the date becomes invalid if the year is increased. This can occur 2 | if the existing date is February 29 on a leap year (e.g. Feb 29, 2004). Increasing the year by one makes 3 | the date Feb 29, 2005 which is invalid. 4 | 5 | When adding years, the day of the month needs to be checked to ensure that it is still valid, much like when 6 | months are added. 7 | 8 | The add_year function in (10.2.7) attempts to deal with this scenario, but still has a couple of issues. First, 9 | if the existing year is negaitve (e.g. -1 for 1 BC) then add 1 year, the function results in a year of 0. This is 10 | not valid. The function should check to see if the operation crosses the BC/AD boundary and adjust by one year 11 | as necessary. 12 | 13 | Secnod, setting the date to March 1 when the old date was Feb 29 on a leap year is not consistent with many 14 | implementations, both in their handling of years and their handling of months. For example, if the date is Mar 31 15 | and one month is added, the resulting date should be Apr 30 (the excess should be truncated). 16 | 17 | It is an edge case where the month is changed in addition to the date. For better consistency, the date should be 18 | changed to be Feb 28, not Mar 1 when a Feb 29 date is modified from a leap year to a non-leap year. 19 | 20 | One additional issue (although not really a bug) is the extra check of m == 2 to determine if the date is a leap day. 21 | This is unnecessary, since d == 29 means that the day is a leap day; it must be in February unless the invariant 22 | was broken. -------------------------------------------------------------------------------- /ch11/ex14.txt: -------------------------------------------------------------------------------- 1 | "Programs are meant to be read by humans, and only incidentally. for computers 2 | to execute." 3 | - Donald Knuth 4 | 5 | I gave my program from exercise 13 to a friend who took one look at it and 6 | groaned. He ultimately figured out what it did by pre-processing the macros 7 | away and then stepping through with a debugger. 8 | 9 | There are multiple levels of evil demonstrated by the previous exercise. 10 | First, macros should not be used unless there's a damned good reason. If you 11 | need constant values...use constants. Rarely do macros add anything 12 | worthwhile, even if they seem to simplify certain pieces of code. Of course, 13 | exercise 13 is an extreme example, but it's easy to get into a situation where 14 | other programmers have to search high and low to discover what your code is 15 | really doing. 16 | 17 | Operator overloading can be used to good effect, but should always be used 18 | appropriately. Defining mathematical symbols to do things that have nothing to 19 | do with their original meaning only creates confusion. For example, having the 20 | ++ operator of an iterator move forward one position (increment) makes sense. 21 | However, if the ++ operator were instead used to skip ahead 3 places or reset 22 | the iterator to the beginning, the reader would not only be misled, but would 23 | have to dig through your source to discover what was really happening. 24 | 25 | In summary: 26 | Don't use macros. 27 | Use operator overloads appropriately; don't change their meaning. 28 | Don't intentionally hide things or be too "clever." Write clear code. 29 | -------------------------------------------------------------------------------- /ch12/evtsim/task.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "task.h" 6 | #include "scheduler.h" 7 | 8 | namespace evtsim 9 | { 10 | Task::Task(Scheduler *s) : state(RUNNING), sched(s) 11 | { 12 | } 13 | 14 | void Task::subscribe(std::string queueName) 15 | { 16 | Queue* q = sched->get_queue(queueName); 17 | queues.push_back(q); 18 | } 19 | 20 | void Task::unsubscribe(std::string queueName) 21 | { 22 | Queue* q = sched->get_queue(queueName); 23 | queues.erase(find(queues.begin(),queues.end(),q)); 24 | } 25 | 26 | void Task::send_message(std::string queueName, const Message& m) 27 | { 28 | Queue* q = sched->get_queue(queueName); 29 | q->enqueue(m); 30 | } 31 | 32 | void Task::wait_message() 33 | { 34 | state = IDLE; 35 | sched->yield_return(this); 36 | } 37 | 38 | Message Task::get_message(std::string queueName) 39 | { 40 | Queue* q = sched->get_queue(queueName); 41 | Message m = q->dequeue(); 42 | return m; 43 | } 44 | 45 | void Task::delay(int vTime) 46 | { 47 | sched->add_time(vTime); 48 | } 49 | 50 | void Task::schedule() 51 | { 52 | state = IDLE; 53 | for(QueueList::const_iterator i = queues.begin(); i != queues.end(); i++) 54 | { 55 | if((*i)->has_message()) 56 | { 57 | state = RUNNING; 58 | break; 59 | } 60 | } 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /ch09/ex06.txt: -------------------------------------------------------------------------------- 1 | On Linux-based systems, dynamic linking is achieved through the use of .so 2 | (shared object) files, the *nix equivalent of DLL files on windows. The .so 3 | files may be used in one of two ways: 4 | 5 | 1) The lib may be referenced during compilation and loaded at startup. This is 6 | the most common case, and it means that the linker is capable of verifying 7 | that the library is used appropriately (that the used functions exist 8 | and are called with appropriate parameters). When the program is executed, the 9 | .so is loaded into memory and called by the program. 10 | 2) The lib may be dynamically loaded during execution. At compile-time, the 11 | linker is not aware of the lib and cannot enforce correctness of usage. A 12 | common example would be a plugin for a browser or a custom module for a web 13 | server. 14 | 15 | Dynamic or shared libraries should be built with the -fPIC GCC option, which 16 | indicates that position independent code should be emitted. This means that 17 | the library may be properly loaded at different locations in memory. Other 18 | flags are required as well; see documentation. 19 | 20 | When defining functions for export from a shared library, use the extern "C" 21 | designator. Consumers of the library will expect to call library functions 22 | using C calling conventions. 23 | 24 | The ld.so (or ld-linux.so) library is responsible for locating and loading 25 | shared libs. It searches a number of paths, typically defined in ld.so.conf 26 | and associated files. Search paths can also be added by using the environment 27 | variable LD_LIBRARY_PATH (colon separated). 28 | -------------------------------------------------------------------------------- /ch10/ex16/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "parser.h" 6 | 7 | using namespace std; 8 | using namespace ch10; 9 | 10 | void interactive() 11 | { 12 | Calculator calc; 13 | calc.eval(&cin, &cout, &cerr); 14 | } 15 | 16 | string fromString(string expr) 17 | { 18 | istringstream istr(expr); 19 | ostringstream ostr; 20 | Calculator calc; 21 | calc.eval(&istr, &ostr, &ostr); 22 | ostr.flush(); 23 | return ostr.str(); 24 | } 25 | 26 | void fromFile(char* inFileName, char* outFileName) 27 | { 28 | ifstream infile(inFileName); 29 | ostream* out = &cout; 30 | if(outFileName) 31 | { 32 | out = new ofstream(outFileName); 33 | } 34 | Calculator calc; 35 | calc.eval(&infile, out, out); 36 | if (out != &cout) delete out; 37 | } 38 | 39 | // Usage: 40 | // -- Interactive mode 41 | // -- Takes input from command line 42 | // - inFile -- Takes input from file 43 | // - inFile outFile -- Takes input from file, sends output to file 44 | int main(int argc, char* argv[]) 45 | { 46 | if(argc == 1) 47 | { 48 | interactive(); 49 | } 50 | else if(argc == 2) 51 | { 52 | string output = fromString(argv[1]); 53 | cout << output; 54 | } 55 | else if (argc >= 3 && strcmp(argv[1],"-")==0) 56 | { 57 | fromFile(argv[2], argc==4?argv[3]:0); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /ch17/ex20.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | bool is_palindrome(const char* start, const char* end) { 5 | while(end > start) { 6 | while(isspace(*end)) end--; 7 | while(isspace(*start)) start++; 8 | if(end <= start) 9 | return true; 10 | if (*(end--) != *(start++)) 11 | return false; 12 | } 13 | 14 | return true; 15 | } 16 | 17 | bool is_palindrome(const char* s) { 18 | const char* end = s; 19 | while(*end) 20 | end++; 21 | end--; 22 | return is_palindrome(s, end); 23 | } 24 | 25 | bool is_palindrome_at_least_three_words(const char* s) { 26 | const char* end = s; 27 | while(*end) 28 | end++; 29 | end--; 30 | 31 | int word = 0; 32 | const char* i = s; 33 | while(*i && isspace(*(i++))); 34 | if(!*i++) 35 | return false; 36 | for(;;) { 37 | if(!*i || isspace(*i)) { 38 | if(++word >= 3 && is_palindrome(s, i-1)) 39 | return true; 40 | } 41 | if(!*i++) 42 | break; 43 | } 44 | return false; 45 | } 46 | 47 | int main() { 48 | using namespace std; 49 | 50 | cout << is_palindrome("a bcdefedcba") << endl; 51 | cout << is_palindrome("abcdee dcba") << endl; 52 | cout << is_palindrome("abc") << endl; 53 | 54 | cout << is_palindrome_at_least_three_words("abc def fed cba") << endl; 55 | cout << is_palindrome_at_least_three_words("abcba") << endl; 56 | cout << is_palindrome_at_least_three_words("abc def frd cba") << endl; 57 | cout << is_palindrome_at_least_three_words("abc cba") << endl; 58 | } 59 | -------------------------------------------------------------------------------- /ch21/ex16.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | // The exercise is too vague; it doesn't say whether values captured from 6 | // the match operation need to be preserved or what. Is it just a match or 7 | // no match thing, or more like fscanf? 8 | namespace ch21 { 9 | bool match(std::istream& in, const char* fmt) { 10 | in >> std::noskipws; 11 | const char* p = fmt; 12 | char ch; 13 | while(in && *p) { 14 | if(*p == '%') { 15 | int i; 16 | std::string s; 17 | switch(*(++p)) { 18 | case 'd': 19 | in >> i; 20 | p++; 21 | continue; 22 | case 's': 23 | in >> s; 24 | p++; 25 | continue; 26 | default: 27 | --p; 28 | } 29 | } 30 | 31 | if(in >> ch && ch != *p) 32 | break; 33 | p++; 34 | } 35 | return !*p; 36 | } 37 | 38 | void test_match(const char* fmt) { 39 | std::string s("foo 1234 bar 555baz"); 40 | std::istringstream in(s); 41 | std::cout << "testing \"" << fmt << "\" = " << std::boolalpha << match(in, fmt) << std::endl; 42 | } 43 | } 44 | 45 | int main() { 46 | using namespace ch21; 47 | 48 | test_match("foo %d %s %dbaz"); 49 | test_match("%s %s %s %s"); 50 | test_match("%s %d %s %d%s"); 51 | test_match("foo %d bar 554baz"); 52 | test_match("foo 1%d bar 5%dbaz"); 53 | } 54 | -------------------------------------------------------------------------------- /xxe/ex02.txt: -------------------------------------------------------------------------------- 1 | void f(vector& v, const X& g) { 2 | v[2] = g; 3 | v.push_back(g); 4 | sort(v.begin(), v.end()); 5 | vector u = v; 6 | } 7 | 8 | * What happens if the assignment throws an exception while trying to copy g? 9 | The assignment will halt and an exception will propagate. 10 | 11 | * Will v be left with an invalid element? 12 | Only if the operator= method left the element in an invalid state. A properly 13 | written operator= will leave the element in a valid state, and preferrably and 14 | unmodified state. 15 | 16 | * What happens if the ctor that v.push_back() uses to copy g throws 17 | std::bad_alloc? 18 | The new element is not constructed, nothing is done to the vector, and an 19 | exception propagates. push_back() offers the strong guarantee. 20 | 21 | * Has the number of elements changed? 22 | No 23 | 24 | * Has an invalid element been added to the container? 25 | No 26 | 27 | * What happens if X's less-than operator throws an exception during the sort? 28 | The sort operation will stop and an exception will propagate. 29 | 30 | * Have the elements been partially sorted? 31 | Possibly; the only guarantee is that the container and elements are in a valid 32 | state, but not necessarily the desired valid state. They may be sorted, mostly 33 | sorted, or not sorted at all. 34 | 35 | * Could an element have been removed from the container by the sorting algorithm 36 | and not put back? 37 | Algorithms do not remove elements from containers, but they may move them 38 | around or change their values. In this case, it's possible, for example, that 39 | the container may end up with a duplicated element. 40 | -------------------------------------------------------------------------------- /ch12/gfxlib/line.h: -------------------------------------------------------------------------------- 1 | #ifndef __LINE_H__ 2 | #define __LINE_H__ 3 | 4 | #include "shape.h" 5 | #include "window.h" 6 | 7 | namespace gfxlib 8 | { 9 | class Line : public Shape 10 | { 11 | public: 12 | enum ArrowStyle { ARROW_NONE, ARROW_IN, ARROW_OUT }; 13 | enum ArrowPosition { ARROW_START, ARROW_END }; 14 | 15 | private: 16 | Point p1; 17 | Point p2; 18 | ArrowStyle a1; 19 | ArrowStyle a2; 20 | void draw_arrowhead(Window& s, const Point p1, const Point p2, ArrowStyle style) const; 21 | public: 22 | Line(const Point& p1, const Point& p2) : p1(p1), p2(p2), a1(ARROW_NONE), a2(ARROW_NONE) {} 23 | virtual void draw(Window&) const; 24 | virtual const Point n() const { return Point(c().x(),p1.y()p2.y()?p1.y():p2.y()); } 26 | virtual const Point w() const { return Point(p1.x()p2.x()?p1.x():p2.x(),c().y()); } 28 | virtual const Point nw() const { return Point(w().x(),n().y()); } 29 | virtual const Point ne() const { return Point(e().x(),n().y()); } 30 | virtual const Point sw() const { return Point(w().x(),s().y()); } 31 | virtual const Point se() const { return Point(e().x(),s().y()); } 32 | virtual const Point c() const { return Point((p1.x()+p2.x())/2, (p1.y()+p2.y())/2); } 33 | 34 | void arrowhead(ArrowPosition pos, ArrowStyle style); 35 | }; 36 | } 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /ch13/ex12.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | namespace ch13 6 | { 7 | // The type T must have a default constructor that initializes it to zero. 8 | // T must also implement the += operator with another T. 9 | // K must have a compare operator (<) and equality (==). 10 | // Both types must have stream input operators (>>). 11 | // In this enhancement, key must have an explicit conversion from std::string. 12 | template void sum_inputs() 13 | { 14 | using namespace std; 15 | 16 | map store; 17 | 18 | cout << "Enter key value pairs, one per line, in the form key=value. Type a single `.' when done." << endl; 19 | K key; 20 | T val; 21 | 22 | string tmp; 23 | for(;;) 24 | { 25 | char ch; 26 | tmp.clear(); 27 | while(cin.get(ch) && ch == '\n') continue; 28 | cin.putback(ch); 29 | while(cin.get(ch) && ch != '=' && ch != '.') tmp.push_back(ch); 30 | if(ch=='.') break; 31 | key = K(tmp); 32 | cin >> val; 33 | store[key] += val; 34 | } 35 | 36 | cout << "Here are the sums:" << endl; 37 | for(typename map::const_iterator i = store.begin(); i != store.end(); i++) 38 | { 39 | cout << i->first << ": " << i->second << endl; 40 | } 41 | } 42 | } 43 | 44 | int main() 45 | { 46 | using namespace std; 47 | using namespace ch13; 48 | 49 | sum_inputs(); 50 | 51 | return 0; 52 | } 53 | -------------------------------------------------------------------------------- /ch13/ex10.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "map.h" 7 | 8 | // For this exercise, I implement a red-black tree in map.h (thanks to Wikipedia for the 9 | // general algorithm). It is many, many times faster than the previous exercise. 10 | int main(int argc, char* argv[]) 11 | { 12 | using namespace std; 13 | using namespace ch13; 14 | 15 | if(argc != 2) 16 | { 17 | cerr << "Must supply a filename." << endl; 18 | return -1; 19 | } 20 | 21 | ifstream inFile(argv[1]); 22 | 23 | clock_t t = clock(); 24 | 25 | Map wordcounts; 26 | 27 | string w; 28 | while(inFile) 29 | { 30 | inFile >> w; 31 | wordcounts[w]++; 32 | } 33 | 34 | cout << "Unique words: " << wordcounts.count() << endl; 35 | cout << "Tree depth: " << wordcounts.depth() << endl; 36 | cout << "Elapsed time: " << clock() - t << endl; 37 | 38 | cout << "Press any key to iterate:" << endl; 39 | cin.get(); 40 | 41 | for(Map::Iterator i = wordcounts.begin(); i != wordcounts.end(); i++) 42 | { 43 | cout << i->key << ' ' << i->val << endl; 44 | } 45 | 46 | cout << "Press any key to reverse iterate: " << endl; 47 | cin.get(); 48 | 49 | Map::Iterator beg = wordcounts.begin(); 50 | Map::Iterator i = wordcounts.end(); 51 | i--; 52 | 53 | for(;;i--) 54 | { 55 | cout << i->key << ' ' << i->val << endl; 56 | if(i == beg) break; 57 | } 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /ch15/othello/board.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOARD_H__ 2 | #define __BOARD_H__ 3 | 4 | #include 5 | 6 | #include "common.h" 7 | #include "iplayerinput.h" 8 | 9 | namespace othello 10 | { 11 | class Board : public IPlayerInput 12 | { 13 | public: 14 | enum Color 15 | { 16 | Empty, 17 | Black, 18 | White 19 | }; 20 | class OutOfRangeError {}; 21 | 22 | static const int NumberOfRows = 8; 23 | static const int NumberOfColumns = 8; 24 | 25 | private: 26 | Color spaces[NumberOfRows][NumberOfColumns]; 27 | std::string m_prompt; 28 | 29 | void check_range(Position p) const; 30 | 31 | protected: 32 | const std::string& prompt() const { return m_prompt; } 33 | 34 | public: 35 | Board(); 36 | virtual ~Board() {} 37 | Color space(Position p) const; 38 | Color& space(Position p); 39 | void update(const std::string& m_prompt); 40 | virtual void draw() = 0; 41 | 42 | int find_path(Color c, Position p, int xDelta, int yDelta) const; 43 | int flip_path(Color c, Position p, int xDelta, int yDelta); 44 | int simulate_play(Color c, Position p) const; 45 | int play(Color c, Position p); 46 | bool has_legal_move(Color c); 47 | virtual void end_game() {} 48 | }; 49 | 50 | inline void Board::check_range(Position p) const 51 | { 52 | if(p.y < 0 || p.y >= NumberOfRows || p.x < 0 || p.x >= NumberOfRows) 53 | throw OutOfRangeError(); 54 | } 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /ch19/ex05.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace ch19 { 8 | using namespace std; 9 | 10 | template, class Dist = ptrdiff_t> 11 | class istream_iterator : public iterator { 12 | public: 13 | typedef Ch char_type; 14 | typedef Tr traits_type; 15 | typedef basic_istream istream_type; 16 | 17 | istream_iterator() : s(0) { } 18 | istream_iterator(istream_type& s) : s(&s) { if(*this->s) *this->s >> val; if (!*this->s) end = true; } 19 | istream_iterator(const istream_iterator& x) : s(x.s), val(x.val) { } 20 | ~istream_iterator() { } 21 | 22 | const T& operator*() const { return val; } 23 | const T* operator->() const { return &val; } 24 | istream_iterator& operator++() { *s >> val; if(!*s) end = true; return *this; } 25 | istream_iterator operator++(int) { istream_iterator tmp = *this; ++*this; return tmp; } 26 | bool operator==(const istream_iterator& x) { return end && x.end || s == x.s; } 27 | bool operator!=(const istream_iterator& x) { return !(*this == x); } 28 | private: 29 | istream_type* s; 30 | T val; 31 | bool end; 32 | }; 33 | } 34 | 35 | int main() { 36 | using namespace std; 37 | 38 | string s("1 2 3 4 5 6 7 8 9 10"); 39 | istringstream in(s); 40 | copy(ch19::istream_iterator(in), ch19::istream_iterator(), std::ostream_iterator(cout, " ")); 41 | cout << endl; 42 | } 43 | -------------------------------------------------------------------------------- /ch15/ex09.txt: -------------------------------------------------------------------------------- 1 | Since the Radio object has no fields, its memory layout probably 2 | consists of only a vtable. Pointers to class-specific functions 3 | are not stored in an object (they are really just regular functions 4 | with a hidden "this" parameter). Specific versions of the functions 5 | get stored in the vtable depending on the inheritance hierarchy. 6 | 7 | Radio's layout looks like this: 8 | Pointer to vtable part 1 (Transmitter::Storable) 9 | Pointer to vtable part 2 (Receiver::Storable) 10 | 11 | Radio's vtable would look like this: 12 | vtable part 1: (Transmitter::Storable) 13 | Ptr to Radio::get_file() 14 | Ptr to Radio::read() 15 | Ptr to Radio::write() 16 | vtable part 2: (Receiver::Storable) 17 | Ptr to Radio::get_file() 18 | Ptr to Radio::read() 19 | Ptr to Radio::write() 20 | 21 | Radio overrides all three functions supplied by Storable, so 22 | all three functions in the vtable point to Radio's version. 23 | It is not possible to store a Storable* pointer to a Radio object 24 | because that would be ambiguous. Which path (Transmitter or Receiver) 25 | would be used for overridden functions? 26 | 27 | However, storing either a Transmitter or a Receiver pointer 28 | to a Radio object would result in the following process when 29 | a virtual call is made: 30 | 31 | 1. Get the correct vtable pointer for the inheritance path 32 | (Transmitter vs. Receiver). 33 | 1. Find the correct index for the function read() in the 34 | selected vtable. 35 | 2. Access the vtable entry at that index. 36 | 3. Call that function - which is Radio::read() in either case. 37 | -------------------------------------------------------------------------------- /ch11/ex21.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | namespace ch11 5 | { 6 | // For this implementation, I use a wrapper class that responds to multiplication 7 | // by a double. The wrapper class is returned by the unary * operator on Index. 8 | // I could have done this with only one class with Index's * operator returning a 9 | // reference to itself, but I wanted to guard against someone doing simply 2 * I, 10 | // which would perform the same operation. 11 | class Index; 12 | double mypow(const double x, const Index y); 13 | 14 | class Index 15 | { 16 | double v; 17 | public: 18 | class IndexWrapper; 19 | 20 | Index(const double v) : v(v) {} 21 | double val() const { return v; } 22 | IndexWrapper operator*() const; 23 | }; 24 | 25 | class Index::IndexWrapper 26 | { 27 | friend class Index; 28 | 29 | Index i; 30 | IndexWrapper(Index i) : i(i) {} 31 | friend double operator*(const double, const IndexWrapper&); 32 | }; 33 | 34 | Index::IndexWrapper Index::operator*() const 35 | { 36 | return IndexWrapper(*this); 37 | } 38 | 39 | double operator*(const double n, const Index::IndexWrapper& i) 40 | { 41 | return mypow(n, i.i); 42 | } 43 | 44 | double mypow(const double x, const Index y) 45 | { 46 | return pow(x, y.val()); 47 | } 48 | } 49 | 50 | int main() 51 | { 52 | using namespace std; 53 | using namespace ch11; 54 | 55 | Index I(8); 56 | cout << 2 ** I << endl; // expect: 256 57 | 58 | return 0; 59 | } 60 | --------------------------------------------------------------------------------