├── .clang-format ├── .gitignore ├── Graph_lib ├── CMakeLists.txt ├── Graph_lib │ ├── CMakeLists.txt │ ├── GUI.cpp │ ├── GUI.h │ ├── Graph.cpp │ ├── Graph.h │ ├── Point.h │ ├── Simple_window.h │ ├── Vector_ref.h │ ├── Window.cpp │ ├── Window.h │ └── fltk.h ├── cmb.bmp ├── cmb.gif ├── cmb.jpg ├── cmb.png ├── test.cpp ├── test_animation.cpp ├── test_automove.cpp ├── test_keyboard.cpp ├── test_move.cpp ├── test_thread.cpp └── test_vector_ref.cpp ├── README.md ├── examples ├── ex01 │ ├── ex01.cpp │ └── makefile ├── ex02 │ ├── CMakeLists.txt │ ├── ex02a.cpp │ ├── ex02b.cpp │ ├── ex02c.cpp │ ├── ex02d.cpp │ ├── ex02e.cpp │ ├── ex02f.cpp │ ├── ex02g.cpp │ ├── ex02h.cpp │ ├── ex02i.cpp │ ├── ex02j.cpp │ └── ex02k.cpp ├── ex03 │ ├── CMakeLists.txt │ ├── ascii_table.cpp │ ├── calc-0.1.cpp │ ├── calc-0.2.cpp │ ├── calc-0.3.cpp │ ├── calc-0.4.cpp │ ├── my_sqrt.cpp │ ├── pi_Archimedes_inner.cpp │ ├── pi_Liu_inner.cpp │ ├── prime_Eratosthenes.cpp │ ├── sort_vector_double.cpp │ ├── square_table_for.cpp │ ├── square_table_while.cpp │ ├── vector_numbers.cpp │ └── vector_words.cpp ├── ex04 │ ├── catch_exception.cpp │ ├── grammar_error.cpp │ ├── link_error │ │ ├── area.cpp │ │ └── main.cpp │ ├── logical_error.cpp │ ├── makefile │ ├── multiple_exceptions.cpp │ ├── post_condition.cpp │ ├── sqrt_error.cpp │ ├── sqrt_exception.cpp │ ├── sqrt_nan.cpp │ ├── type_error.cpp │ ├── vector_error.cpp │ ├── vector_range.cpp │ └── warning.cpp ├── ex05 │ ├── calc-1.x │ │ ├── CMakeLists.txt │ │ ├── calc-1.0.cpp │ │ └── calc-1.1.cpp │ ├── calc-2.0 │ │ ├── CMakeLists.txt │ │ └── calc-2.0.cpp │ ├── calc-2.1 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.1.cpp │ ├── calc-2.2-wrong │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.2.cpp │ ├── calc-2.2 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── calc-2.2.cbp │ │ ├── calc-2.2.cpp │ │ └── calc-2.2.xcodeproj │ │ │ └── project.pbxproj │ └── misc │ │ ├── CMakeLists.txt │ │ ├── factorial.cpp │ │ ├── hanoi.cpp │ │ └── test_token.cpp ├── ex06 │ ├── calc-2.3 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.3.cpp │ ├── calc-2.4 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.4.cpp │ ├── calc-2.5 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.5.cpp │ ├── calc-2.6 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ └── calc-2.6.cpp │ ├── calc-2.7 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── calc-2.7.cpp │ │ └── input1.txt │ ├── calc-3.0 │ │ ├── CMakeLists.txt │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── calc-3.0.cpp │ │ └── input1.txt │ └── misc │ │ ├── CMakeLists.txt │ │ ├── test_char.cpp │ │ └── test_map.cpp ├── ex07 │ ├── calc-3.0 │ │ ├── CMakeLists.txt │ │ ├── Calculator.cpp │ │ ├── Calculator.h │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── Variable.cpp │ │ ├── Variable.h │ │ ├── calc-3.0.cpp │ │ └── input1.txt │ └── misc │ │ ├── CMakeLists.txt │ │ └── test_scope.cpp ├── ex08 │ ├── calc-3.0 │ │ ├── CMakeLists.txt │ │ ├── Calculator.cpp │ │ ├── Calculator.h │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── Variable.cpp │ │ ├── Variable.h │ │ ├── calc-3.0.cpp │ │ └── input1.txt │ ├── chrono │ │ ├── CMakeLists.txt │ │ ├── Chrono.cpp │ │ ├── Chrono.h │ │ ├── test_date.cpp │ │ └── test_date.java │ ├── complex │ │ ├── CMakeLists.txt │ │ ├── Complex.cpp │ │ ├── Complex.h │ │ └── test_complex.cpp │ ├── misc │ │ ├── CMakeLists.txt │ │ └── test_copy.cpp │ └── rational │ │ ├── CMakeLists.txt │ │ ├── Rational.cpp │ │ ├── Rational.h │ │ └── test_rational.cpp ├── ex09 │ ├── Punct_stream │ │ ├── CMakeLists.txt │ │ ├── Punct_stream.cpp │ │ ├── Punct_stream.h │ │ ├── input.txt │ │ ├── test.csv │ │ ├── test_csv.cpp │ │ └── test_ps.cpp │ ├── calc-3.x │ │ ├── CMakeLists.txt │ │ ├── Calculator.cpp │ │ ├── Calculator.h │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── Variable.cpp │ │ ├── Variable.h │ │ ├── calc-3.0.cpp │ │ ├── calc-3.1.cpp │ │ ├── calc-3.2.cpp │ │ ├── calc-3.3.cpp │ │ ├── input1.txt │ │ └── input2.txt │ ├── complex │ │ ├── CMakeLists.txt │ │ ├── Complex.cpp │ │ ├── Complex.h │ │ └── test_complex.cpp │ ├── read_int │ │ ├── CMakeLists.txt │ │ ├── read_int.cpp │ │ └── read_int_new.cpp │ ├── read_vectors │ │ ├── CMakeLists.txt │ │ ├── generate_random_data.py │ │ ├── read_vectors.cpp │ │ └── vectors.txt │ ├── test_fstream │ │ ├── CMakeLists.txt │ │ ├── generate_random_data.py │ │ ├── raw_scores.txt │ │ └── test_fstream.cpp │ └── test_sstream │ │ ├── CMakeLists.txt │ │ └── test_sstream.cpp ├── ex10 │ ├── animals │ │ ├── Animal.cpp │ │ ├── Animal.h │ │ ├── CMakeLists.txt │ │ └── test.cpp │ ├── calc-4.0 │ │ ├── CMakeLists.txt │ │ ├── Calculator.cpp │ │ ├── Calculator.h │ │ ├── Graph_lib │ │ │ ├── CMakeLists.txt │ │ │ ├── GUI.cpp │ │ │ ├── GUI.h │ │ │ ├── Graph.cpp │ │ │ ├── Graph.h │ │ │ ├── Point.h │ │ │ ├── Simple_window.h │ │ │ ├── Vector_ref.h │ │ │ ├── Window.cpp │ │ │ ├── Window.h │ │ │ └── fltk.h │ │ ├── Token.h │ │ ├── Token_stream.cpp │ │ ├── Token_stream.h │ │ ├── Variable.cpp │ │ ├── Variable.h │ │ └── calc-4.0.cpp │ ├── test_fltk │ │ ├── CMakeLists.txt │ │ └── test_fltk.cpp │ └── test_wx │ │ ├── makefile │ │ └── test_wx.cpp ├── ex11 │ ├── List │ │ ├── CMakeLists.txt │ │ ├── List.cpp │ │ ├── List.h │ │ └── test_list.cpp │ ├── Vector │ │ ├── CMakeLists.txt │ │ ├── Vector.cpp │ │ ├── Vector.h │ │ └── test_vector.cpp │ ├── Vector_RAII │ │ ├── CMakeLists.txt │ │ ├── Vector.cpp │ │ ├── Vector.h │ │ └── test_vector.cpp │ └── Vector_better │ │ ├── CMakeLists.txt │ │ ├── Vector.cpp │ │ ├── Vector.h │ │ └── test_vector.cpp └── ex12 │ ├── Iterator │ ├── CMakeLists.txt │ ├── List.cpp │ ├── List.h │ ├── Vector.cpp │ ├── Vector.h │ └── test_iterator.cpp │ ├── Pointer_as_iterator │ ├── CMakeLists.txt │ ├── List.cpp │ ├── List.h │ ├── Vector.cpp │ ├── Vector.h │ └── test_pointer.cpp │ └── Vector_template │ ├── CMakeLists.txt │ ├── Vector.h │ └── test_vector.cpp └── just_for_fun ├── bouncing_ball ├── Ball.cpp ├── Ball.h ├── Block.cpp ├── Block.h ├── CMakeLists.txt ├── Graph_lib │ ├── CMakeLists.txt │ ├── GUI.cpp │ ├── GUI.h │ ├── Graph.cpp │ ├── Graph.h │ ├── Point.h │ ├── Simple_window.h │ ├── Vector_ref.h │ ├── Window.cpp │ ├── Window.h │ └── fltk.h ├── My_window.cpp ├── My_window.h ├── Paddle.cpp ├── Paddle.h ├── Scene.cpp ├── Scene.h ├── blue.jpg ├── bouncing_ball.cpp └── constants.h └── n_body ├── calc_2body.cpp ├── calc_3body.cpp ├── makefile ├── plot_2body.py └── plot_3body.py /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: WebKit 2 | IndentWidth: 2 3 | AccessModifierOffset: -2 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Xcode 35 | DerivedData 36 | project.xcworkspace 37 | xcuserdata 38 | 39 | # Code::Blocks 40 | bin 41 | obj 42 | *.depend 43 | *.layout 44 | 45 | # CLion 46 | .idea 47 | cmake-build-* 48 | 49 | # Vim 50 | *.swp 51 | 52 | # Java 53 | *.class 54 | 55 | # macOS 56 | .DS_Store 57 | *.dSYM 58 | 59 | -------------------------------------------------------------------------------- /Graph_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(test_graph_lib) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | find_package(FLTK REQUIRED) 10 | include_directories(${FLTK_INCLUDE_DIR}) 11 | link_directories(${FLTK_LIBRARY_DIR}) 12 | 13 | find_package(JPEG REQUIRED) 14 | find_package(PNG REQUIRED) 15 | 16 | find_package(Threads REQUIRED) 17 | 18 | add_subdirectory(Graph_lib) 19 | 20 | foreach(ex test test_animation test_automove test_keyboard test_move test_thread test_vector_ref) 21 | add_executable(${ex}.exe ${ex}.cpp ${GRAPH_LIB}) 22 | target_link_libraries(${ex}.exe ${FLTK_LIBRARIES} ${JPEG_LIBRARIES} ${PNG_LIBRARIES} 23 | ${CMAKE_THREAD_LIBS_INIT}) 24 | endforeach(ex) 25 | 26 | file(COPY cmb.png DESTINATION ${CMAKE_BINARY_DIR}) 27 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(GRAPH_LIB 2 | ${CMAKE_CURRENT_SOURCE_DIR}/fltk.h 3 | ${CMAKE_CURRENT_SOURCE_DIR}/Point.h 4 | ${CMAKE_CURRENT_SOURCE_DIR}/Vector_ref.h 5 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.h 7 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.h 9 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.cpp 10 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.h 11 | ${CMAKE_CURRENT_SOURCE_DIR}/Simple_window.h 12 | PARENT_SCOPE) 13 | 14 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef POINT_GUARD 2 | #define POINT_GUARD 3 | 4 | namespace Graph_lib { 5 | 6 | struct Point { 7 | int x, y; 8 | Point(int xx, int yy) 9 | : x { xx } 10 | , y { yy } 11 | { 12 | } 13 | }; 14 | 15 | inline bool operator==(Point a, Point b) { return a.x == b.x && a.y == b.y; } 16 | 17 | inline bool operator!=(Point a, Point b) { return !(a == b); } 18 | 19 | } // namespace Graph_lib 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/Simple_window.h: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "Point.h" 3 | #include "Window.h" 4 | 5 | // Simple_window is basic scaffolding for ultra-simple interaction with graphics 6 | // it provides one window with one "next" button for ultra-simple animation 7 | 8 | class Simple_window : public Graph_lib::Window { 9 | 10 | public: 11 | Simple_window(Graph_lib::Point xy, int w, int h, const std::string& title) 12 | : Graph_lib::Window { xy, w, h, title, false } 13 | , quit_button { Graph_lib::Point { x_max() - 70, 0 }, 70, 20, "Quit", cb_quit } 14 | , next_button { Graph_lib::Point { x_max() - 70, 20 }, 70, 20, "Next", cb_next } 15 | , next_pushed { false } 16 | { 17 | attach(quit_button); 18 | attach(next_button); 19 | } 20 | 21 | void wait_for_next() 22 | { 23 | while (!next_pushed && Fl::wait()) 24 | ; 25 | next_pushed = false; 26 | Fl::redraw(); 27 | } 28 | 29 | private: 30 | Graph_lib::Button quit_button; 31 | Graph_lib::Button next_button; 32 | 33 | bool next_pushed; 34 | 35 | // callback for quit_button 36 | static void cb_quit(void*, void* pw) 37 | { 38 | static_cast(pw)->quit(); 39 | } 40 | 41 | void quit() { hide(); } 42 | 43 | // callback for next_button 44 | static void cb_next(void*, void* pw) 45 | { 46 | static_cast(pw)->next(); 47 | } 48 | 49 | void next() { next_pushed = true; } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/Vector_ref.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_REF_GUARD 2 | #define VECTOR_REF_GUARD 3 | 4 | #include 5 | 6 | namespace Graph_lib { 7 | 8 | template 9 | class Vector_ref { 10 | public: 11 | Vector_ref() = default; 12 | explicit Vector_ref(T* t) 13 | { 14 | if (t) 15 | push_back(t); 16 | } 17 | ~Vector_ref() 18 | { 19 | for (auto p : owned) 20 | delete p; 21 | } 22 | 23 | void push_back(T& s) { v.push_back(&s); } 24 | void push_back(T* p) 25 | { 26 | v.push_back(p); 27 | owned.push_back(p); 28 | } 29 | 30 | T& operator[](int i) { return *v[i]; } 31 | const T& operator[](int i) const { return *v[i]; } 32 | size_t size() const { return v.size(); } 33 | 34 | private: 35 | std::vector v; 36 | std::vector owned; 37 | }; 38 | 39 | } // namespace Graph_lib 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/Window.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "GUI.h" 5 | #include "Graph.h" 6 | #include "Window.h" 7 | 8 | using std::string; 9 | 10 | namespace Graph_lib { 11 | 12 | Window::Window(int ww, int hh, const string& title, bool resizable) 13 | : Super { ww, hh, title.c_str() } 14 | , w { ww } 15 | , h { hh } 16 | { 17 | init(resizable); 18 | } 19 | 20 | Window::Window(Point xy, int ww, int hh, const string& title, bool resizable) 21 | : Super { xy.x, xy.y, ww, hh, title.c_str() } 22 | , w { ww } 23 | , h { hh } 24 | { 25 | init(resizable); 26 | } 27 | 28 | void Window::init(bool res) 29 | { 30 | if (res) 31 | resizable(this); 32 | Fl::visual(FL_DOUBLE | FL_INDEX); 33 | show(); 34 | } 35 | 36 | //---------------------------------------------------- 37 | 38 | void Window::resize(int ww, int hh) 39 | { 40 | w = ww; 41 | h = hh; 42 | size(ww, hh); 43 | } 44 | 45 | void Window::draw() 46 | { 47 | Super::draw(); 48 | for (auto shape : shapes) 49 | shape->draw(); 50 | } 51 | 52 | void Window::attach(Widget& w) 53 | { 54 | begin(); // FTLK: begin attaching new Fl_Widgets to this window 55 | w.attach(*this); // let the Widget create its Fl_Widget 56 | end(); // FTLK: stop attaching new Fl_Widgets to this window 57 | } 58 | 59 | void Window::detach(Widget& w) 60 | { 61 | w.hide(); 62 | } 63 | 64 | void Window::attach(const Shape& s) 65 | { 66 | // each shape should only be attached once 67 | detach(s); 68 | shapes.push_back(&s); 69 | } 70 | 71 | void Window::detach(const Shape& s) 72 | { 73 | auto it { std::find(shapes.begin(), shapes.end(), &s) }; 74 | if (it != shapes.end()) { 75 | shapes.erase(it); 76 | } 77 | } 78 | 79 | void Window::put_on_top(const Shape& s) 80 | { 81 | attach(s); 82 | } 83 | 84 | int gui_main() { return Fl::run(); } 85 | 86 | } // namespace Graph_lib 87 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/Window.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_GUARD 2 | #define WINDOW_GUARD 1 3 | 4 | #include 5 | #include 6 | 7 | #include "fltk.h" 8 | 9 | #include "Graph.h" 10 | #include "Point.h" 11 | 12 | using Graph_lib::Color; 13 | 14 | namespace Graph_lib { 15 | 16 | class Widget; 17 | 18 | class Window : public Fl_Double_Window { 19 | public: 20 | using Super = Fl_Double_Window; 21 | // let the system pick the location 22 | Window(int w, int h, const std::string& title, bool resizable = true); 23 | // top left corner in xy 24 | Window(Point xy, int w, int h, const std::string& title, bool resizable = true); 25 | 26 | ~Window() override = default; 27 | 28 | int x_max() const { return w; } 29 | int y_max() const { return h; } 30 | 31 | using Super::resize; // resize(int x, int y, int w, int h); 32 | 33 | void resize(int ww, int hh); 34 | 35 | void set_background_color(Color c) { color(static_cast(c)); } 36 | void set_label(const std::string& s) { label(s.c_str()); } 37 | 38 | void attach(Widget& w); // attach a widget 39 | void detach(Widget& w); // hide the widget (not really detached) 40 | 41 | void attach(const Shape& s); // add s to shapes 42 | void detach(const Shape& s); // remove s from shapes 43 | void put_on_top(const Shape& p); // put p on top of other shapes 44 | void detach_all_shapes() { shapes.clear(); } 45 | 46 | protected: 47 | void draw() override; 48 | 49 | private: 50 | std::vector shapes; // shapes attached to window 51 | int w, h; // window size 52 | 53 | void init(bool res); 54 | }; 55 | 56 | int gui_main(); // invoke GUI library's main event loop 57 | 58 | inline int x_max() { return Fl::w(); } // width of screen in pixels 59 | inline int y_max() { return Fl::h(); } // height of screen in pixels 60 | 61 | } // namespace Graph_lib 62 | #endif 63 | -------------------------------------------------------------------------------- /Graph_lib/Graph_lib/fltk.h: -------------------------------------------------------------------------------- 1 | #ifndef FLTK_GUARD 2 | #define FLTK_GUARD 1 3 | 4 | #include "FL/Enumerations.H" 5 | #include "FL/Fl.H" 6 | #include "FL/Fl_Button.H" 7 | #include "FL/Fl_Double_Window.H" 8 | #include "FL/Fl_Input.H" 9 | #include "FL/Fl_Output.H" 10 | #include "FL/Fl_Window.H" 11 | #include "FL/fl_draw.H" 12 | 13 | #include "FL/Fl_BMP_Image.H" 14 | #include "FL/Fl_GIF_Image.H" 15 | #include "FL/Fl_JPEG_Image.H" 16 | #include "FL/Fl_PNG_Image.H" 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /Graph_lib/cmb.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llyang/Computing/130254a9acace74d60274e21eda9566d18cfa816/Graph_lib/cmb.bmp -------------------------------------------------------------------------------- /Graph_lib/cmb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llyang/Computing/130254a9acace74d60274e21eda9566d18cfa816/Graph_lib/cmb.gif -------------------------------------------------------------------------------- /Graph_lib/cmb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llyang/Computing/130254a9acace74d60274e21eda9566d18cfa816/Graph_lib/cmb.jpg -------------------------------------------------------------------------------- /Graph_lib/cmb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llyang/Computing/130254a9acace74d60274e21eda9566d18cfa816/Graph_lib/cmb.png -------------------------------------------------------------------------------- /Graph_lib/test_vector_ref.cpp: -------------------------------------------------------------------------------- 1 | #include "Graph_lib/Graph.h" 2 | #include "Graph_lib/Simple_window.h" 3 | #include "Graph_lib/Vector_ref.h" 4 | 5 | using Graph_lib::Color; 6 | using Graph_lib::Point; 7 | 8 | int main() 9 | { 10 | Simple_window win { Point { 100, 100 }, 600, 400, "Colors" }; 11 | 12 | Graph_lib::Vector_ref vr; 13 | 14 | for (int i = 0; i < 16; ++i) { 15 | for (int j = 0; j < 16; ++j) { 16 | vr.push_back(new Graph_lib::Rectangle { Point { i * 20, j * 20 }, 20, 20 }); 17 | vr[vr.size() - 1].set_fill_color(static_cast(i * 16 + j)); 18 | win.attach(vr[vr.size() - 1]); 19 | } 20 | } 21 | 22 | return Graph_lib::gui_main(); 23 | } 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Computing -------------------------------------------------------------------------------- /examples/ex01/ex01.cpp: -------------------------------------------------------------------------------- 1 | // This is my first C++ program 2 | 3 | #include 4 | 5 | int main() 6 | { 7 | std::cout << "You shall not pass!" << '\n'; 8 | 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /examples/ex01/makefile: -------------------------------------------------------------------------------- 1 | ex01.exe: ex01.cpp 2 | g++ -std=c++14 -o ex01.exe ex01.cpp 3 | -------------------------------------------------------------------------------- /examples/ex02/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(ex02) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex ex02a ex02b ex02c ex02d ex02e ex02f ex02g ex02h ex02i ex02j ex02k) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex02/ex02a.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; // 使用cout、cin、string等标准库更方便 3 | 4 | int main() 5 | { 6 | cout << "Please input your first name (followed by 'enter'): "; 7 | string first_name; // 定义string型变量first_name;string代表字符串 8 | cin >> first_name; // 从键盘输入一个字符串到变量first_name 9 | 10 | cout << "Please input your last name (followed by 'enter'): "; 11 | string last_name; 12 | cin >> last_name; 13 | 14 | // 字符串连接用加号运算符+ 15 | // 变量初始化用花括号{} 16 | string full_name { first_name + " " + last_name }; 17 | 18 | cout << "Hello, " << full_name << "!\n"; 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /examples/ex02/ex02b.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | // 定义变量并初始化 9 | int number_of_apples { 10 }; // 整数 10 | double pi { 3.14 }; // 双精度浮点数 11 | char c { 'a' }; // 字符 12 | string name { "Voldemort" }; // 字符串 13 | bool is_holiday { false }; // 布尔型 14 | 15 | cout << number_of_apples << '\n'; 16 | cout << pi << '\n'; 17 | cout << c << '\n'; 18 | cout << name << '\n'; 19 | cout << boolalpha << is_holiday << '\n'; 20 | 21 | cout << '\n'; 22 | 23 | // 给变量赋值(改变数据) 24 | number_of_apples = 20; 25 | pi = 3.14159; 26 | c = 'b'; 27 | name = "Harry Potter"; 28 | is_holiday = true; 29 | 30 | cout << number_of_apples << '\n'; 31 | cout << pi << '\n'; 32 | cout << c << '\n'; 33 | cout << name << '\n'; 34 | cout << boolalpha << is_holiday << '\n'; 35 | 36 | cout << '\n'; 37 | 38 | cout << setprecision(18) << pi << '\n'; 39 | cout << setprecision(18) << pi + 0.02 - 0.01 - 0.01 << '\n'; 40 | } 41 | -------------------------------------------------------------------------------- /examples/ex02/ex02c.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() 5 | { 6 | cout << "Please input your first name and age (followed by 'enter'): "; 7 | string first_name { "???" }; 8 | int age { -1 }; 9 | cin >> first_name >> age; // 输入一个字符串和一个整数 10 | 11 | cout << "Hello, " << first_name << "! You are " << age << " years old!\n"; 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /examples/ex02/ex02d.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Please input your full name (followed by 'enter'): "; 8 | string first_name { "???" }; 9 | string last_name { "???" }; 10 | cin >> first_name >> last_name; 11 | 12 | string full_name { first_name + " " + last_name }; 13 | 14 | cout << "Hello, " << full_name << "!\n"; 15 | } 16 | -------------------------------------------------------------------------------- /examples/ex02/ex02e.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Please input your full name (followed by 'enter'): "; 8 | string full_name { "???" }; 9 | getline(cin, full_name); 10 | cout << "Hello, " << full_name << "!\n"; 11 | } 12 | -------------------------------------------------------------------------------- /examples/ex02/ex02f.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() 5 | { 6 | int heads { 35 }; 7 | int legs { 94 }; 8 | 9 | // cut two legs from everyone 10 | int legs_remain { legs - heads * 2 }; 11 | 12 | int rabbits { legs_remain / 2 }; 13 | int chickens { heads - rabbits }; 14 | 15 | cout << chickens << " chickens and " << rabbits << " rabbits" << '\n'; 16 | } 17 | -------------------------------------------------------------------------------- /examples/ex02/ex02g.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | cout << "Please enter a floating-point value: "; 9 | double x { 0 }; 10 | cin >> x; 11 | cout << "x = " << x << '\n'; 12 | cout << "x+1 = " << x + 1 << '\n'; 13 | cout << "3*x = " << 3 * x << '\n'; 14 | cout << "x squared = " << x * x << '\n'; 15 | cout << "half of x = " << x / 2 << '\n'; 16 | cout << "square root of x = " << sqrt(x) << '\n'; 17 | } 18 | -------------------------------------------------------------------------------- /examples/ex02/ex02h.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Please input two integers\n"; 8 | int first { 0 }; 9 | int second { 0 }; 10 | cin >> first >> second; 11 | if (first == second) { 12 | cout << "They are equal!\n"; 13 | } else if (first < second) { 14 | cout << first << " is smaller than " << second << "!\n"; 15 | } else { 16 | cout << first << " is larger than " << second << "!\n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ex02/ex02i.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | string previous { " " }; // 初始化 8 | string current; 9 | while (cin >> current) { // 遇到EOF就终止循环 10 | if (previous == current) { 11 | cout << "repeated word: " << current << '\n'; 12 | } 13 | previous = current; // 赋值 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/ex02/ex02j.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | int number_of_words { 0 }; 8 | string previous { " " }; 9 | string current; 10 | while (cin >> current) { 11 | ++number_of_words; 12 | if (previous == current) { 13 | cout << "word number " << number_of_words << " repeated: "; 14 | cout << current << '\n'; 15 | } 16 | previous = current; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/ex02/ex02k.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | double d { 0 }; 8 | while (cin >> d) { 9 | int i = d; 10 | char c = i; 11 | int i2 = c; 12 | cout << "d==" << d; 13 | cout << " i==" << i; 14 | cout << " i2==" << i2; 15 | cout << " char(" << c << ")\n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/ex03/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(ex03) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex ascii_table calc-0.1 calc-0.2 calc-0.3 calc-0.4 my_sqrt pi_Archimedes_inner pi_Liu_inner prime_Eratosthenes sort_vector_double square_table_for square_table_while vector_numbers vector_words) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex03/ascii_table.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | for (int i = 'a'; i <= 'z'; ++i) { 8 | cout << char(i) << '\t' << i << '\n'; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/ex03/calc-0.1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | string operation; 8 | double val1 { 0 }; 9 | double val2 { 0 }; 10 | 11 | cout << "Please enter an operation (+,-,*,/,plus,minus,mul,div) followed by two floating-point values:\n"; 12 | while (cin >> operation >> val1 >> val2) { 13 | double res { 0 }; 14 | if (operation == "+" || operation == "plus") { 15 | res = val1 + val2; 16 | } else if (operation == "-" || operation == "minus") { 17 | res = val1 - val2; 18 | } else if (operation == "*" || operation == "mul") { 19 | res = val1 * val2; 20 | } else { 21 | res = val1 / val2; 22 | } 23 | cout << val1 << " " << operation << " " << val2 << " = " << res << '\n'; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/ex03/calc-0.2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | string operation; 8 | double val1 { 0 }; 9 | double val2 { 0 }; 10 | 11 | cout << "Please enter an operation (+,-,*,/,plus,minus,mul,div) followed by two floating-point values:\n"; 12 | while (cin >> operation >> val1 >> val2) { 13 | double res { 0 }; 14 | if (operation == "+" || operation == "plus") { 15 | res = val1 + val2; 16 | } else if (operation == "-" || operation == "minus") { 17 | res = val1 - val2; 18 | } else if (operation == "*" || operation == "mul") { 19 | res = val1 * val2; 20 | } else if (operation == "/" || operation == "div") { 21 | res = val1 / val2; 22 | } else { 23 | cout << "unknown operator: " << operation << '\n'; 24 | return 1; 25 | } 26 | cout << val1 << " " << operation << " " << val2 << " = " << res << '\n'; 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /examples/ex03/calc-0.3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | string operation; 8 | double val1 { 0 }; 9 | double val2 { 0 }; 10 | 11 | cout << "Please enter an operation (+,-,*,/,plus,minus,mul,div) followed by two floating-point values:\n"; 12 | while (cin >> operation >> val1 >> val2) { 13 | double res { 0 }; 14 | if (operation == "+" || operation == "plus") { 15 | res = val1 + val2; 16 | } else if (operation == "-" || operation == "minus") { 17 | res = val1 - val2; 18 | } else if (operation == "*" || operation == "mul") { 19 | res = val1 * val2; 20 | } else if (operation == "/" || operation == "div") { 21 | if (val2 == 0) { 22 | cout << "divide by zero\n"; 23 | return 2; 24 | } 25 | res = val1 / val2; 26 | } else { 27 | cout << "unknown operator: " << operation << '\n'; 28 | return 1; 29 | } 30 | cout << val1 << " " << operation << " " << val2 << " = " << res << '\n'; 31 | } 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /examples/ex03/calc-0.4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | string operation; 9 | double val1 { 0 }; 10 | double val2 { 0 }; 11 | 12 | constexpr int plus { 1 }; 13 | constexpr int minus { 2 }; 14 | constexpr int mul { 3 }; 15 | constexpr int div { 4 }; 16 | 17 | const map operations { 18 | { "+", plus }, { "plus", plus }, { "-", minus }, { "minus", minus }, 19 | { "*", mul }, { "mul", mul }, { "/", div }, { "div", div } 20 | }; 21 | 22 | cout << "Please enter an operation (+,-,*,/,plus,minus,mul,div) followed by two floating-point values:\n"; 23 | while (cin >> operation >> val1 >> val2) { 24 | double res { 0 }; 25 | try { 26 | switch (operations.at(operation)) { 27 | case plus: 28 | res = val1 + val2; 29 | break; 30 | case minus: 31 | res = val1 - val2; 32 | break; 33 | case mul: 34 | res = val1 * val2; 35 | break; 36 | case div: 37 | if (val2 == 0) { 38 | cout << "divide by zero\n"; 39 | return 2; 40 | } 41 | res = val1 / val2; 42 | break; 43 | } 44 | } catch (out_of_range&) { 45 | cout << "unknown operator: " << operation << '\n'; 46 | return 1; 47 | } 48 | cout << val1 << " " << operation << " " << val2 << " = " << res << '\n'; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/ex03/my_sqrt.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | // 函数声明 7 | double my_sqrt(double); 8 | 9 | int main() 10 | { 11 | // 函数调用 12 | double x { my_sqrt(2) }; 13 | cout << x << '\t' << sqrt(2) << '\n'; 14 | cout << my_sqrt(10000) << '\t' << sqrt(10000) << '\n'; 15 | cout << my_sqrt(0.000001) << '\t' << sqrt(0.000001) << '\n'; 16 | } 17 | 18 | // 函数定义 19 | double my_sqrt(double x) 20 | { 21 | if (x < 0) { 22 | return nan("my_sqrt"); 23 | } 24 | 25 | const double error { 1e-6 }; 26 | double a { x }; 27 | double b { 1 }; 28 | while (abs((a - b) / min(a, b)) > error) { 29 | a = (a + b) / 2; 30 | b = x / a; 31 | } 32 | return a; 33 | } 34 | -------------------------------------------------------------------------------- /examples/ex03/pi_Archimedes_inner.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | int sides { 6 }; // 从六边形开始 10 | double edge { 1.0 }; // 六边形的边长为1 11 | for (int i = 0; i < 20; ++i) { 12 | // 设n边形的边长为edge,计算2n边形的边长 13 | const double new_edge { sqrt(2 * (1 - sqrt(1 - edge * edge / 4.0))) }; 14 | 15 | sides *= 2; // 2n边形 16 | double pi { new_edge * double(sides) / 2 }; // 用2n边形周长的一半来估计pi 17 | 18 | cout << setw(10) << setprecision(16) << sides << '\t' << pi << '\n'; 19 | 20 | edge = new_edge; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/ex03/pi_Liu_inner.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | int sides { 6 }; // 从六边形开始 10 | double edge { 1.0 }; // 六边形的边长为1 11 | for (int i = 0; i < 20; ++i) { 12 | // 设n边形的边长为edge,计算2n边形的边长 13 | const double new_edge { sqrt(2 * (1 - sqrt(1 - edge * edge / 4.0))) }; 14 | 15 | sides *= 2; // 2n边形 16 | const double area { (edge / 2) / 2 }; // 2n边形中每个小三角形的面积 17 | double pi { area * double(sides) }; // 用2n边形面积来估计pi 18 | 19 | cout << setw(10) << setprecision(16) << sides << '\t' << pi << '\n'; 20 | 21 | edge = new_edge; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/ex03/prime_Eratosthenes.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | constexpr int max { 100 }; 10 | vector is_prime(max + 1, true); 11 | 12 | for (int i = 2; i <= sqrt(max); ++i) { 13 | if (is_prime[i]) { 14 | for (int j = i * i; j <= max; j += i) { 15 | is_prime[j] = false; 16 | } 17 | } 18 | } 19 | 20 | for (int i = 2; i <= max; ++i) { 21 | if (is_prime[i]) { 22 | cout << i << '\n'; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/ex03/sort_vector_double.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | void sort_vector_double(vector& v) 7 | { 8 | bool finished { false }; 9 | while (!finished) { 10 | finished = true; 11 | for (size_t i = 0; i < v.size() - 1; ++i) { 12 | if (v[i] > v[i + 1]) { 13 | double temp { v[i] }; 14 | v[i] = v[i + 1]; 15 | v[i + 1] = temp; 16 | finished = false; 17 | } 18 | } 19 | } 20 | } 21 | 22 | int main() 23 | { 24 | vector temps; 25 | for (double temp = 0; cin >> temp;) { 26 | temps.push_back(temp); 27 | } 28 | 29 | sort_vector_double(temps); 30 | 31 | cout << "Lowest temperature: " << temps[0] << '\n'; 32 | cout << "Highest temperature: " << temps[temps.size() - 1] << '\n'; 33 | } 34 | -------------------------------------------------------------------------------- /examples/ex03/square_table_for.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | for (int i = 0; i < 100; ++i) { 8 | cout << i << '\t' << i * i << '\n'; 9 | // ++i 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /examples/ex03/square_table_while.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | int i { 0 }; 8 | while (i < 100) { 9 | cout << i << '\t' << i * i << '\n'; 10 | ++i; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/ex03/vector_numbers.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | vector temps; 10 | for (double temp = 0; cin >> temp;) { 11 | temps.push_back(temp); 12 | } 13 | 14 | double sum { 0 }; 15 | for (double x : temps) { 16 | sum += x; 17 | } 18 | cout << "Average temperature: " << sum / temps.size() << '\n'; 19 | 20 | sort(temps.begin(), temps.end()); 21 | cout << "Lowest temperature: " << temps[0] << '\n'; 22 | cout << "Highest temperature: " << temps[temps.size() - 1] << '\n'; 23 | } 24 | -------------------------------------------------------------------------------- /examples/ex03/vector_words.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | vector words; 10 | for (string temp; cin >> temp;) { 11 | words.push_back(temp); 12 | } 13 | cout << "Number of words: " << words.size() << '\n'; 14 | 15 | sort(words.begin(), words.end()); 16 | 17 | for (size_t i = 0; i < words.size(); ++i) { 18 | if (i == 0 || words[i - 1] != words[i]) { 19 | cout << words[i] << '\n'; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/ex04/catch_exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | class some_error { 7 | }; 8 | 9 | int some_function(int x) 10 | { 11 | if (x < 0) { 12 | throw runtime_error { "error: x < 0" }; 13 | } 14 | if (x > 100) { 15 | throw out_of_range { "error: x > 100" }; 16 | } 17 | if (x == 10) { 18 | throw some_error {}; 19 | } 20 | return x; 21 | } 22 | 23 | int main() 24 | { 25 | for (int x = 0; cin >> x;) { 26 | try { 27 | int y { some_function(x) }; 28 | cout << y << '\n'; 29 | } catch (exception& e) { 30 | cerr << e.what() << '\n'; 31 | } catch (...) { 32 | cerr << "There's something wrong but I don't know why\n"; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /examples/ex04/grammar_error.cpp: -------------------------------------------------------------------------------- 1 | int area(int length, int width) 2 | { 3 | return length * width; 4 | } 5 | 6 | int main() 7 | { 8 | Int s1 = area(7); 9 | int s2 = area(7; 10 | int s3 = area(7) 11 | int s4 = area('7); 12 | } 13 | -------------------------------------------------------------------------------- /examples/ex04/link_error/area.cpp: -------------------------------------------------------------------------------- 1 | int area(int length, int width) 2 | { 3 | return length * width; 4 | } 5 | 6 | -------------------------------------------------------------------------------- /examples/ex04/link_error/main.cpp: -------------------------------------------------------------------------------- 1 | int area(int, int); 2 | 3 | int main() 4 | { 5 | int x { area(2, 3) }; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /examples/ex04/logical_error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | vector temps; 9 | 10 | for (double temp = 0; cin >> temp;) { 11 | temps.push_back(temp); 12 | } 13 | 14 | double sum { 0 }; 15 | double high_temp { 0 }; 16 | double low_temp { 0 }; 17 | 18 | for (double x : temps) { 19 | if (x > high_temp) { 20 | high_temp = x; 21 | } 22 | if (x < low_temp) { 23 | low_temp = x; 24 | } 25 | sum += x; 26 | } 27 | 28 | cout << "High temperature: " << high_temp << '\n'; 29 | cout << "Low temperature: " << low_temp << '\n'; 30 | cout << "Average temperature: " << sum / temps.size() << '\n'; 31 | } 32 | -------------------------------------------------------------------------------- /examples/ex04/makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -std=c++11 3 | 4 | .PHONY: default all 5 | 6 | default: all 7 | 8 | all: vector_error.exe sqrt_error.exe sqrt_nan.exe \ 9 | sqrt_exception.exe vector_range.exe multiple_exceptions.exe \ 10 | catch_exception.exe logical_error.exe post_condition.exe 11 | 12 | %.exe: %.cpp 13 | $(CXX) $(CXXFLAGS) -o $@ $< 14 | 15 | clean: 16 | $(RM) *.exe 17 | -------------------------------------------------------------------------------- /examples/ex04/multiple_exceptions.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | class my_sqrt_error { 9 | }; 10 | 11 | double my_sqrt(double x) 12 | { 13 | if (x < 0) { 14 | throw my_sqrt_error {}; 15 | } 16 | const double error { 1e-6 }; 17 | double a { x }; 18 | double b { 1 }; 19 | while (abs((a - b) / min(a, b)) > error) { 20 | a = (a + b) / 2; 21 | b = x / a; 22 | } 23 | return a; 24 | } 25 | 26 | int main() 27 | { 28 | vector v { 1, 2, -3, -4, 5 }; 29 | int i { 0 }; 30 | cin >> i; 31 | try { 32 | double x { my_sqrt(v.at(i)) }; 33 | cout << "sqrt(v[" << i << "]) = " << x << '\n'; 34 | } catch (out_of_range&) { 35 | cerr << "out of range: i = " << i << '\n'; 36 | } catch (my_sqrt_error&) { 37 | cerr << "my_sqrt_error\n"; 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /examples/ex04/post_condition.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | double some_function(double a, double b, double c, double d) 8 | { 9 | double r { asin(a + sqrt((b + log(c)) / d)) }; 10 | if (isnan(r)) { 11 | throw runtime_error { "bad arguments in some_function" }; 12 | } 13 | return r; 14 | } 15 | 16 | int main() 17 | { 18 | try { 19 | cout << some_function(1, 2, 3, 4) << '\n'; 20 | } catch (runtime_error& e) { 21 | cerr << e.what() << '\n'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ex04/sqrt_error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | double my_sqrt(double x) 6 | { 7 | const double error { 1e-6 }; 8 | double a { x }; 9 | double b { 1 }; 10 | while (abs((a - b) / min(a, b)) > error) { 11 | a = (a + b) / 2; 12 | b = x / a; 13 | } 14 | return a; 15 | } 16 | 17 | int main() 18 | { 19 | double x { 0 }; 20 | cin >> x; 21 | cout << my_sqrt(x) << '\n'; 22 | } 23 | -------------------------------------------------------------------------------- /examples/ex04/sqrt_exception.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class my_sqrt_error { 6 | }; 7 | 8 | double my_sqrt(double x) 9 | { 10 | if (x < 0) { 11 | throw my_sqrt_error {}; 12 | } 13 | const double error { 1e-6 }; 14 | double a { x }; 15 | double b { 1 }; 16 | while (abs((a - b) / min(a, b)) > error) { 17 | a = (a + b) / 2; 18 | b = x / a; 19 | } 20 | return a; 21 | } 22 | 23 | double sqrt_wrapper(double x) 24 | { 25 | return my_sqrt(x); // 这里可能会甩出一口锅 26 | // 这里没有try-catch:我不想背锅 27 | } 28 | 29 | int main() 30 | { 31 | double x { 0 }; 32 | cin >> x; 33 | try { 34 | cout << sqrt_wrapper(x) << '\n'; 35 | } catch (my_sqrt_error) { // 锅甩到了这里才被接住 36 | cout << "my_sqrt_error\n"; 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /examples/ex04/sqrt_nan.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | double my_sqrt(double x) 7 | { 8 | if (x < 0) { 9 | return nan("my_sqrt"); 10 | } 11 | 12 | const double error { 1e-6 }; 13 | double a { x }; 14 | double b { 1 }; 15 | while (abs((a - b) / min(a, b)) > error) { 16 | a = (a + b) / 2; 17 | b = x / a; 18 | } 19 | return a; 20 | } 21 | 22 | int main() 23 | { 24 | double x { 0 }; 25 | cin >> x; 26 | double y { my_sqrt(x) }; 27 | if (isnan(y)) { 28 | cout << "my_sqrt error!\n"; 29 | return 1; 30 | } 31 | cout << y << '\n'; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /examples/ex04/type_error.cpp: -------------------------------------------------------------------------------- 1 | int area(int length, int width) 2 | { 3 | return length * width; 4 | } 5 | 6 | int main() 7 | { 8 | int x0 = arena(7); 9 | int x1 = area(7); 10 | int x2 = area("seven", 2); 11 | } 12 | -------------------------------------------------------------------------------- /examples/ex04/vector_error.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | vector v { 1, 2, 3, 4, 5 }; 9 | int i { 0 }; 10 | cin >> i; 11 | // cout << v[i] << '\n'; 12 | cout << v.at(i) << '\n'; 13 | } 14 | -------------------------------------------------------------------------------- /examples/ex04/vector_range.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | vector v { 1, 2, 3, 4, 5 }; 10 | int i { 0 }; 11 | cin >> i; 12 | try { 13 | int n { v.at(i) }; 14 | cout << "v[" << i << "] = " << n << '\n'; 15 | } catch (out_of_range&) { 16 | cout << "out of range: i = " << i << '\n'; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /examples/ex04/warning.cpp: -------------------------------------------------------------------------------- 1 | int area(int length, int width) 2 | { 3 | return length * width; 4 | } 5 | 6 | int main() 7 | { 8 | int x4 = area(10, -7); 9 | int x5 = area(10.7, 9.3); 10 | char x6 = area(100, 9999); 11 | } 12 | -------------------------------------------------------------------------------- /examples/ex05/calc-1.x/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(calc-1.x) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex calc-1.0 calc-1.1) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex05/calc-1.x/calc-1.0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Expression: "; 8 | 9 | double lval { 0 }; 10 | double rval { 0 }; 11 | char op { ' ' }; 12 | cin >> lval >> op >> rval; 13 | if (!cin) { 14 | throw runtime_error { "input error" }; 15 | } 16 | 17 | double res { 0 }; 18 | switch (op) { 19 | case '+': 20 | res = lval + rval; 21 | break; 22 | case '-': 23 | res = lval - rval; 24 | break; 25 | case '*': 26 | res = lval * rval; 27 | break; 28 | case '/': 29 | res = lval / rval; 30 | break; 31 | default: 32 | throw runtime_error { "unknown operator" }; 33 | } 34 | 35 | cout << "Result: " << res << '\n'; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /examples/ex05/calc-1.x/calc-1.1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace std; 5 | 6 | int main() 7 | { 8 | cout << "Expression (end with ';'): "; 9 | 10 | double lval { 0 }; 11 | cin >> lval; 12 | if (!cin) { 13 | throw runtime_error { "no first operand" }; 14 | } 15 | 16 | for (char op = ' '; cin >> op;) { 17 | double rval { 0 }; 18 | if (op != ';') { 19 | cin >> rval; 20 | } 21 | if (!cin) { 22 | throw runtime_error { "no second operand" }; 23 | } 24 | switch (op) { 25 | case '+': 26 | lval += rval; 27 | break; 28 | case '-': 29 | lval -= rval; 30 | break; 31 | case '*': 32 | lval *= rval; 33 | break; 34 | case '/': 35 | lval /= rval; 36 | break; 37 | default: 38 | cout << "Result: " << lval << '\n'; 39 | return 0; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.0) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | add_executable(${MAIN}.exe ${MAIN}.cpp) 11 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.1/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.1) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.1/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.1/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case '(': 30 | case ')': 31 | case '+': 32 | case '-': 33 | case '*': 34 | case '/': 35 | return Token { ch }; 36 | case '.': 37 | case '0': 38 | case '1': 39 | case '2': 40 | case '3': 41 | case '4': 42 | case '5': 43 | case '6': 44 | case '7': 45 | case '8': 46 | case '9': { 47 | cin.putback(ch); 48 | double val { 0 }; 49 | cin >> val; 50 | return Token { '6', val }; 51 | } 52 | default: 53 | throw runtime_error { "Bad token" }; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.1/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.1/calc-2.1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token.h" 5 | #include "Token_stream.h" 6 | 7 | // A global variable, not preferred, just for now 8 | Token_stream ts; 9 | 10 | double expression(); 11 | double term(); 12 | double primary(); 13 | 14 | using std::cerr; 15 | using std::cin; 16 | using std::cout; 17 | using std::exception; 18 | using std::runtime_error; 19 | 20 | int main() 21 | { 22 | try { 23 | while (cin) { 24 | double val { expression() }; 25 | cout << "= " << val << '\n'; 26 | } 27 | } catch (exception& e) { 28 | cerr << e.what() << '\n'; 29 | return 1; 30 | } catch (...) { 31 | cerr << "unknown error\n"; 32 | return 2; 33 | } 34 | } 35 | 36 | // return the value of the next expression 37 | double expression() 38 | { 39 | double left { term() }; 40 | while (true) { 41 | Token t { ts.get() }; 42 | switch (t.kind) { 43 | case '+': 44 | left += term(); 45 | break; 46 | case '-': 47 | left -= term(); 48 | break; 49 | default: 50 | ts.putback(t); 51 | return left; 52 | } 53 | } 54 | } 55 | 56 | // return the value of the next term 57 | double term() 58 | { 59 | double left { primary() }; 60 | while (true) { 61 | Token t { ts.get() }; 62 | switch (t.kind) { 63 | case '*': 64 | left *= primary(); 65 | break; 66 | case '/': { 67 | double d { primary() }; 68 | if (d == 0) { 69 | throw runtime_error { "divide by zero" }; 70 | } 71 | left /= d; 72 | break; 73 | } 74 | default: 75 | ts.putback(t); 76 | return left; 77 | } 78 | } 79 | } 80 | 81 | // return the value of the next primary 82 | double primary() 83 | { 84 | Token t { ts.get() }; 85 | switch (t.kind) { 86 | case '(': { 87 | double d { expression() }; 88 | t = ts.get(); 89 | if (t.kind != ')') { 90 | throw runtime_error { "')' expected" }; 91 | } 92 | return d; 93 | } 94 | case '6': 95 | return t.value; 96 | default: 97 | throw runtime_error { "primary expected" }; 98 | } 99 | } 100 | 101 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2-wrong/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.2) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2-wrong/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2-wrong/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case ';': 30 | case 'q': 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | return Token { ch }; 38 | case '.': 39 | case '0': 40 | case '1': 41 | case '2': 42 | case '3': 43 | case '4': 44 | case '5': 45 | case '6': 46 | case '7': 47 | case '8': 48 | case '9': { 49 | cin.putback(ch); 50 | double val { 0 }; 51 | cin >> val; 52 | return Token { '6', val }; 53 | } 54 | default: 55 | throw runtime_error { "Bad token" }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2-wrong/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.2) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case ';': 30 | case 'q': 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | return Token { ch }; 38 | case '.': 39 | case '0': 40 | case '1': 41 | case '2': 42 | case '3': 43 | case '4': 44 | case '5': 45 | case '6': 46 | case '7': 47 | case '8': 48 | case '9': { 49 | cin.putback(ch); 50 | double val { 0 }; 51 | cin >> val; 52 | return Token { '6', val }; 53 | } 54 | default: 55 | throw runtime_error { "Bad token" }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex05/calc-2.2/calc-2.2.cbp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 45 | 46 | -------------------------------------------------------------------------------- /examples/ex05/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(misc) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex factorial hanoi test_token) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex05/misc/factorial.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cout; 5 | using std::runtime_error; 6 | 7 | int factorial(int n) 8 | { 9 | if (n < 0) { 10 | throw runtime_error { "factorial: n < 0" }; 11 | } else if (n == 0) { 12 | return 1; 13 | } else { 14 | return n * factorial(n - 1); 15 | } 16 | } 17 | 18 | int factorial2(int n) 19 | { 20 | if (n < 0) { 21 | throw runtime_error { "factorial: n < 0" }; 22 | } else { 23 | int r { 1 }; 24 | for (int i = 1; i <= n; ++i) { 25 | r *= i; 26 | } 27 | return r; 28 | } 29 | } 30 | 31 | int main() 32 | { 33 | cout << factorial(0) << " " << factorial2(0) << '\n'; 34 | cout << factorial(1) << " " << factorial2(1) << '\n'; 35 | cout << factorial(10) << " " << factorial2(10) << '\n'; 36 | } 37 | -------------------------------------------------------------------------------- /examples/ex05/misc/hanoi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cout; 4 | using std::string; 5 | 6 | void hanoi(int n, string from, string to, string other) 7 | { 8 | if (n < 1) { 9 | return; 10 | } 11 | hanoi(n - 1, from, other, to); 12 | cout << "Move disc " << n << " from " << from << " to " << to << '\n'; 13 | hanoi(n - 1, other, to, from); 14 | } 15 | 16 | int main() 17 | { 18 | hanoi(3, "A", "B", "C"); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/ex05/misc/test_token.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class Token { 4 | public: 5 | char kind; // '+', '-', '*', '/', '%', '6' 6 | double value; 7 | }; 8 | 9 | using std::cout; 10 | 11 | int main() 12 | { 13 | Token t1 { '+' }; // t1.kind = '+' 14 | cout << "t1: " << t1.kind << " " << t1.value << '\n'; 15 | 16 | Token t2 { '6', 3.2 }; // t2.kind = '6', t2.value = 3.2 17 | cout << "t2: " << t2.kind << " " << t2.value << '\n'; 18 | 19 | Token t3 { t2 }; 20 | cout << "t3: " << t3.kind << " " << t3.value << '\n'; 21 | 22 | t3 = t1; 23 | cout << "t3 is now the same as t1: "; 24 | cout << t3.kind << " " << t3.value << '\n'; 25 | 26 | t1.kind = '6'; 27 | t1.value = 5.4; 28 | cout << "t1 is now: " << t1.kind << " " << t1.value << '\n'; 29 | } 30 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.3) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.3/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.3/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case ';': 30 | case 'q': 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | return Token { ch }; 38 | case '.': 39 | case '0': 40 | case '1': 41 | case '2': 42 | case '3': 43 | case '4': 44 | case '5': 45 | case '6': 46 | case '7': 47 | case '8': 48 | case '9': { 49 | cin.putback(ch); 50 | double val { 0 }; 51 | cin >> val; 52 | return Token { '6', val }; 53 | } 54 | default: 55 | throw runtime_error { "Bad token" }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.3/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.4/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.4) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.4/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | #endif 11 | 12 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.4/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case ';': 30 | case 'q': 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | return Token { ch }; 38 | case '.': 39 | case '0': 40 | case '1': 41 | case '2': 42 | case '3': 43 | case '4': 44 | case '5': 45 | case '6': 46 | case '7': 47 | case '8': 48 | case '9': { 49 | cin.putback(ch); 50 | double val { 0 }; 51 | cin >> val; 52 | return Token { '6', val }; 53 | } 54 | default: 55 | throw runtime_error { "Bad token" }; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.4/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.4/calc-2.4.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token.h" 5 | #include "Token_stream.h" 6 | 7 | // A global variable, not preferred, just for now 8 | Token_stream ts; 9 | 10 | double expression(); 11 | double term(); 12 | double primary(); 13 | 14 | using std::cerr; 15 | using std::cin; 16 | using std::cout; 17 | using std::exception; 18 | using std::runtime_error; 19 | 20 | int main() 21 | { 22 | try { 23 | while (cin) { 24 | cout << "> "; 25 | Token t { ts.get() }; 26 | while (t.kind == ';') { 27 | t = ts.get(); 28 | } 29 | if (t.kind == 'q') { // quit 30 | break; 31 | } 32 | ts.putback(t); 33 | cout << "= " << expression() << '\n'; 34 | } 35 | } catch (exception& e) { 36 | cerr << e.what() << '\n'; 37 | return 1; 38 | } catch (...) { 39 | cerr << "unknown error\n"; 40 | return 2; 41 | } 42 | } 43 | 44 | // return the value of the next expression 45 | double expression() 46 | { 47 | double left { term() }; 48 | while (true) { 49 | Token t { ts.get() }; 50 | switch (t.kind) { 51 | case '+': 52 | left += term(); 53 | break; 54 | case '-': 55 | left -= term(); 56 | break; 57 | default: 58 | ts.putback(t); 59 | return left; 60 | } 61 | } 62 | } 63 | 64 | // return the value of the next term 65 | double term() 66 | { 67 | double left { primary() }; 68 | while (true) { 69 | Token t { ts.get() }; 70 | switch (t.kind) { 71 | case '*': 72 | left *= primary(); 73 | break; 74 | case '/': { 75 | double d { primary() }; 76 | if (d == 0) { 77 | throw runtime_error { "divide by zero" }; 78 | } 79 | left /= d; 80 | break; 81 | } 82 | default: 83 | ts.putback(t); 84 | return left; 85 | } 86 | } 87 | } 88 | 89 | // return the value of the next primary 90 | double primary() 91 | { 92 | Token t { ts.get() }; 93 | switch (t.kind) { 94 | case '(': { 95 | double d { expression() }; 96 | t = ts.get(); 97 | if (t.kind != ')') { 98 | throw runtime_error { "')' expected" }; 99 | } 100 | return d; 101 | } 102 | case '6': 103 | return t.value; 104 | default: 105 | throw runtime_error { "primary expected" }; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.5/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.5) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.5/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | constexpr char number { '6' }; 11 | constexpr char quit { 'q' }; 12 | constexpr char print { ';' }; 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.5/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case print: 30 | case quit: 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | case '%': 38 | return Token { ch }; 39 | case '.': 40 | case '0': 41 | case '1': 42 | case '2': 43 | case '3': 44 | case '4': 45 | case '5': 46 | case '6': 47 | case '7': 48 | case '8': 49 | case '9': { 50 | cin.putback(ch); 51 | double val { 0 }; 52 | cin >> val; 53 | return Token { number, val }; 54 | } 55 | default: 56 | throw runtime_error { "Bad token" }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.5/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.6/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.6) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.6/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | constexpr char number { '6' }; 11 | constexpr char quit { 'q' }; 12 | constexpr char print { ';' }; 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.6/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case print: 30 | case quit: 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | case '%': 38 | return Token { ch }; 39 | case '.': 40 | case '0': 41 | case '1': 42 | case '2': 43 | case '3': 44 | case '4': 45 | case '5': 46 | case '6': 47 | case '7': 48 | case '8': 49 | case '9': { 50 | cin.putback(ch); 51 | double val { 0 }; 52 | cin >> val; 53 | return Token { number, val }; 54 | } 55 | default: 56 | throw runtime_error { "Bad token" }; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.6/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | 11 | private: 12 | bool full { false }; 13 | Token buffer; 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.7/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-2.7) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.7/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | class Token { 5 | public: 6 | char kind; 7 | double value; 8 | }; 9 | 10 | constexpr char number { '6' }; 11 | constexpr char quit { 'q' }; 12 | constexpr char print { ';' }; 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.7/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | 9 | void Token_stream::putback(Token t) 10 | { 11 | if (full) { 12 | throw runtime_error { "putback() into a full buffer" }; 13 | } 14 | buffer = t; 15 | full = true; 16 | } 17 | 18 | Token Token_stream::get() 19 | { 20 | if (full) { 21 | full = false; 22 | return buffer; 23 | } 24 | 25 | char ch { ' ' }; 26 | cin >> ch; 27 | 28 | switch (ch) { 29 | case print: 30 | case quit: 31 | case '(': 32 | case ')': 33 | case '+': 34 | case '-': 35 | case '*': 36 | case '/': 37 | case '%': 38 | return Token { ch }; 39 | case '.': 40 | case '0': 41 | case '1': 42 | case '2': 43 | case '3': 44 | case '4': 45 | case '5': 46 | case '6': 47 | case '7': 48 | case '8': 49 | case '9': { 50 | cin.putback(ch); 51 | double val { 0 }; 52 | cin >> val; 53 | return Token { number, val }; 54 | } 55 | default: 56 | throw runtime_error { "Bad token" }; 57 | } 58 | } 59 | 60 | void Token_stream::ignore(char c) 61 | // ignore the inputs until the character c 62 | { 63 | // look into the buffer first 64 | if (full && c == buffer.kind) { 65 | full = false; 66 | return; 67 | } 68 | 69 | full = false; // clear the buffer 70 | 71 | // search for the character c 72 | char ch { ' ' }; 73 | while (cin >> ch) { 74 | if (ch == c) 75 | return; 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.7/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | void ignore(char c); 11 | 12 | private: 13 | bool full { false }; 14 | Token buffer; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /examples/ex06/calc-2.7/input1.txt: -------------------------------------------------------------------------------- 1 | 1.2+3.6*2-0.4; 2 | 8; 3 | 10-8-1; 4 | 1; 5 | (1.2+3.6)*(2.3-0.3)+0.4; 6 | 10; 7 | 3.9/1.3/1.5*2.5+5; 8 | 10; 9 | -2*3+5;;; 10 | -1; 11 | 12 | 1/0; 13 | (1+); 14 | (); 15 | 1+; 16 | 1++; 17 | q 18 | -------------------------------------------------------------------------------- /examples/ex06/calc-3.0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-3.0) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp) 11 | 12 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/calc-3.0/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | #include 5 | class Token { 6 | public: 7 | char kind; 8 | double value; 9 | std::string name; 10 | 11 | Token() {} 12 | 13 | Token(char ch) 14 | : kind { ch } 15 | , value { 0 } 16 | { 17 | } 18 | 19 | Token(char ch, double val) 20 | : kind { ch } 21 | , value { val } 22 | { 23 | } 24 | 25 | Token(char ch, const std::string& n) 26 | : kind { ch } 27 | , value { 0 } 28 | , name { n } 29 | { 30 | } 31 | }; 32 | 33 | constexpr char number { '6' }; 34 | constexpr char quit { 'q' }; 35 | constexpr char print { ';' }; 36 | 37 | constexpr char name { 'a' }; 38 | constexpr char let { 'L' }; 39 | const std::string declkey { "let" }; 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /examples/ex06/calc-3.0/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | using std::string; 9 | 10 | void Token_stream::putback(Token t) 11 | { 12 | if (full) { 13 | throw runtime_error { "putback() into a full buffer" }; 14 | } 15 | buffer = t; 16 | full = true; 17 | } 18 | 19 | Token Token_stream::get() 20 | { 21 | if (full) { 22 | full = false; 23 | return buffer; 24 | } 25 | 26 | char ch { ' ' }; 27 | cin >> ch; 28 | 29 | if (!cin) 30 | return Token { quit }; 31 | 32 | switch (ch) { 33 | case print: 34 | case quit: 35 | case '(': 36 | case ')': 37 | case '+': 38 | case '-': 39 | case '*': 40 | case '/': 41 | case '%': 42 | case '=': 43 | return Token { ch }; 44 | case '.': 45 | case '0': 46 | case '1': 47 | case '2': 48 | case '3': 49 | case '4': 50 | case '5': 51 | case '6': 52 | case '7': 53 | case '8': 54 | case '9': { 55 | cin.putback(ch); 56 | double val { 0 }; 57 | cin >> val; 58 | if (!cin) { 59 | cin.clear(); 60 | throw runtime_error { "illegal floating point number" }; 61 | } 62 | return Token { number, val }; 63 | } 64 | default: 65 | if (isalpha(ch)) { 66 | string s { ch }; 67 | while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) { 68 | s += ch; 69 | } 70 | cin.putback(ch); 71 | if (s == declkey) { 72 | return Token { let }; 73 | } 74 | return Token { name, s }; 75 | } 76 | throw runtime_error { "Bad token" }; 77 | } 78 | } 79 | 80 | void Token_stream::ignore(char c) 81 | // ignore the inputs until the character c 82 | { 83 | // look into the buffer first 84 | if (full && c == buffer.kind) { 85 | full = false; 86 | return; 87 | } 88 | 89 | full = false; // clear the buffer 90 | 91 | // search for the character c 92 | char ch { ' ' }; 93 | while (cin >> ch) { 94 | if (ch == c) 95 | return; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /examples/ex06/calc-3.0/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | class Token_stream { 7 | public: 8 | Token get(); 9 | void putback(Token t); 10 | void ignore(char c); 11 | 12 | private: 13 | bool full { false }; 14 | Token buffer; 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /examples/ex06/calc-3.0/input1.txt: -------------------------------------------------------------------------------- 1 | 1.2+3.6*2-0.4; 2 | 8; 3 | 10-8-1; 4 | 1; 5 | (1.2+3.6)*(2.3-0.3)+0.4; 6 | 10; 7 | 3.9/1.3/1.5*2.5+5; 8 | 10; 9 | -2*3+5;;; 10 | -1; 11 | let x = 3; 12 | 3; 13 | let y = 4; 14 | 4; 15 | let z = 2; 16 | 2; 17 | (x+y)*5-z; 18 | 33; 19 | 20 | 1/0; 21 | (1+); 22 | (); 23 | 1+; 24 | 1++; 25 | (2; 26 | 2+3); 27 | let x = 5; 28 | w*6; 29 | -------------------------------------------------------------------------------- /examples/ex06/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(misc) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex test_char test_map) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex06/misc/test_char.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using std::cin; 5 | using std::cout; 6 | 7 | int main() 8 | { 9 | while (cin) { 10 | char ch; 11 | cin.get(ch); 12 | cout << ch << '\t' << int { ch } << '\t' 13 | << "isalpha: " << isalpha(ch) << '\t' 14 | << "isdigit: " << isdigit(ch) << '\t' 15 | << "isspace: " << isspace(ch) << '\t' 16 | << '\n'; 17 | } 18 | } 19 | 20 | -------------------------------------------------------------------------------- /examples/ex06/misc/test_map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cerr; 6 | using std::cout; 7 | using std::map; 8 | using std::out_of_range; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | map var_table { 14 | { "x", 1.2 }, 15 | { "y", -2.5 }, 16 | { "z", 4.8 } 17 | }; 18 | 19 | for (auto& var : var_table) { 20 | cout << var.first << " = " << var.second << '\n'; 21 | } 22 | 23 | cout << "x = " << var_table["x"] << '\n'; 24 | 25 | cout << "w = " << var_table["w"] << '\n'; 26 | 27 | var_table["t"] = 10.9; 28 | cout << "t = " << var_table["t"] << '\n'; 29 | 30 | try { 31 | double a = var_table.at("a"); 32 | cout << "a = " << a << '\n'; 33 | } catch (out_of_range& e) { 34 | cerr << e.what() << '\n'; 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-3.0) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp Calculator.h Calculator.cpp 11 | Variable.h Variable.cpp) 12 | 13 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 14 | 15 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Calculator.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALCULATOR_H 2 | #define _CALCULATOR_H 3 | 4 | #include "Token_stream.h" 5 | 6 | namespace Calc { 7 | 8 | void calculate(Token_stream& ts); 9 | void clean_up_mess(Token_stream& ts); 10 | 11 | double statement(Token_stream& ts); 12 | double declaration(Token_stream& ts); 13 | double expression(Token_stream& ts); 14 | double term(Token_stream& ts); 15 | double primary(Token_stream& ts); 16 | 17 | } 18 | 19 | #endif 20 | 21 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Token { 9 | public: 10 | char kind; 11 | double value; 12 | std::string name; 13 | 14 | Token() {} 15 | 16 | Token(char ch) 17 | : kind { ch } 18 | , value { 0 } 19 | { 20 | } 21 | 22 | Token(char ch, double val) 23 | : kind { ch } 24 | , value { val } 25 | { 26 | } 27 | 28 | Token(char ch, const std::string& n) 29 | : kind { ch } 30 | , value { 0 } 31 | , name { n } 32 | { 33 | } 34 | }; 35 | 36 | constexpr char number { '6' }; 37 | constexpr char quit { 'q' }; 38 | constexpr char print { ';' }; 39 | 40 | constexpr char name { 'a' }; 41 | constexpr char let { 'L' }; 42 | const std::string declkey { "let" }; 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | using std::string; 9 | 10 | namespace Calc { 11 | 12 | void Token_stream::putback(Token t) 13 | { 14 | if (full) { 15 | throw runtime_error { "putback() into a full buffer" }; 16 | } 17 | buffer = t; 18 | full = true; 19 | } 20 | 21 | Token Token_stream::get() 22 | { 23 | if (full) { 24 | full = false; 25 | return buffer; 26 | } 27 | 28 | char ch { ' ' }; 29 | cin >> ch; 30 | 31 | if (!cin) 32 | return Token { quit }; 33 | 34 | switch (ch) { 35 | case print: 36 | case quit: 37 | case '(': 38 | case ')': 39 | case '+': 40 | case '-': 41 | case '*': 42 | case '/': 43 | case '%': 44 | case '=': 45 | return Token { ch }; 46 | case '.': 47 | case '0': 48 | case '1': 49 | case '2': 50 | case '3': 51 | case '4': 52 | case '5': 53 | case '6': 54 | case '7': 55 | case '8': 56 | case '9': { 57 | cin.putback(ch); 58 | double val { 0 }; 59 | cin >> val; 60 | if (!cin) { 61 | cin.clear(); 62 | throw runtime_error { "illegal floating point number" }; 63 | } 64 | return Token { number, val }; 65 | } 66 | default: 67 | if (isalpha(ch)) { 68 | string s { ch }; 69 | while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) { 70 | s += ch; 71 | } 72 | cin.putback(ch); 73 | if (s == declkey) { 74 | return Token { let }; 75 | } 76 | return Token { name, s }; 77 | } 78 | throw runtime_error { "Bad token" }; 79 | } 80 | } 81 | 82 | void Token_stream::ignore(char c) 83 | // ignore the inputs until the character c 84 | { 85 | // look into the buffer first 86 | if (full && c == buffer.kind) { 87 | full = false; 88 | return; 89 | } 90 | 91 | full = false; // clear the buffer 92 | 93 | // search for the character c 94 | char ch { ' ' }; 95 | while (cin >> ch) { 96 | if (ch == c) 97 | return; 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | namespace Calc { 7 | 8 | class Token_stream { 9 | public: 10 | Token get(); 11 | void putback(Token t); 12 | void ignore(char c); 13 | 14 | private: 15 | bool full { false }; 16 | Token buffer; 17 | }; 18 | 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Variable.h" 6 | 7 | using std::map; 8 | using std::out_of_range; 9 | using std::runtime_error; 10 | using std::string; 11 | 12 | namespace Calc { 13 | 14 | // still not ideal, just for now 15 | map var_table; 16 | 17 | double get_value(const string& var) 18 | { 19 | try { 20 | return var_table.at(var); 21 | } catch (out_of_range&) { 22 | throw runtime_error { "get: undefined variable " + var }; 23 | } 24 | } 25 | 26 | void set_value(const string& var, double val) 27 | { 28 | try { 29 | var_table.at(var) = val; 30 | } catch (out_of_range&) { 31 | throw runtime_error { "set: undefined variable " + var }; 32 | } 33 | } 34 | 35 | bool is_declared(const string& var) 36 | { 37 | if (var_table.count(var) > 0) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | 44 | double define_name(const string& var, double val) 45 | { 46 | if (is_declared(var)) { 47 | throw runtime_error { "variable " + var + " is already declared" }; 48 | } 49 | var_table[var] = val; 50 | return val; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/Variable.h: -------------------------------------------------------------------------------- 1 | #ifndef _VARIABLE_H 2 | #define _VARIABLE_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | double get_value(const std::string&); 9 | void set_value(const std::string&, double); 10 | bool is_declared(const std::string&); 11 | double define_name(const std::string&, double); 12 | } 13 | 14 | #endif 15 | 16 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/calc-3.0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Calculator.h" 5 | #include "Token_stream.h" 6 | 7 | using std::cerr; 8 | 9 | int main() 10 | { 11 | // a local variable, passed by reference between functions 12 | Calc::Token_stream ts; 13 | 14 | try { 15 | Calc::calculate(ts); 16 | return 0; 17 | } catch (...) { 18 | cerr << "unknown error\n"; 19 | return 2; 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /examples/ex07/calc-3.0/input1.txt: -------------------------------------------------------------------------------- 1 | 1.2+3.6*2-0.4; 2 | 8; 3 | 10-8-1; 4 | 1; 5 | (1.2+3.6)*(2.3-0.3)+0.4; 6 | 10; 7 | 3.9/1.3/1.5*2.5+5; 8 | 10; 9 | -2*3+5;;; 10 | -1; 11 | let x = 3; 12 | 3; 13 | let y = 4; 14 | 4; 15 | let z = 2; 16 | 2; 17 | (x+y)*5-z; 18 | 33; 19 | 20 | 1/0; 21 | (1+); 22 | (); 23 | 1+; 24 | 1++; 25 | (2; 26 | 2+3); 27 | let x = 5; 28 | w*6; 29 | -------------------------------------------------------------------------------- /examples/ex07/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(misc) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex test_scope) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex07/misc/test_scope.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cout; 4 | 5 | int x { 1 }; 6 | 7 | namespace haha { 8 | int x { 2 }; 9 | } 10 | 11 | class A { 12 | public: 13 | void f() 14 | { 15 | cout << "global x: " << ::x << '\n'; 16 | cout << "x in namespace haha: " << haha::x << '\n'; 17 | cout << "x in class A: " << x << '\n'; 18 | int x { 4 }; 19 | cout << "x in function f(): " << x << '\n'; 20 | for (int x = 5; x < 6; ++x) { 21 | cout << "x in the for statement: " << x << '\n'; 22 | { 23 | int x { 6 }; 24 | cout << "x in the curly braket: " << x << '\n'; 25 | cout << "global x: " << ::x << '\n'; 26 | cout << "x in namespace haha: " << haha::x << '\n'; 27 | cout << "x in class A: " << this->x << '\n'; 28 | } 29 | } 30 | } 31 | 32 | private: 33 | int x { 3 }; 34 | }; 35 | 36 | int main() 37 | { 38 | A a; 39 | a.f(); 40 | } 41 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN calc-3.0) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | set(SOURCES Token.h Token_stream.h Token_stream.cpp Calculator.h Calculator.cpp 11 | Variable.h Variable.cpp) 12 | 13 | add_executable(${MAIN}.exe ${MAIN}.cpp ${SOURCES}) 14 | 15 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Calculator.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALCULATOR_H 2 | #define _CALCULATOR_H 3 | 4 | #include "Token_stream.h" 5 | #include "Variable.h" 6 | 7 | namespace Calc { 8 | 9 | class Calculator { 10 | public: 11 | void calculate(); 12 | 13 | private: 14 | Token_stream ts; 15 | Var_table vt; 16 | 17 | void clean_up_mess(); 18 | 19 | double statement(); 20 | double declaration(); 21 | double expression(); 22 | double term(); 23 | double primary(); 24 | }; 25 | } 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Token { 9 | public: 10 | char kind; 11 | double value; 12 | std::string name; 13 | 14 | Token() {} 15 | 16 | Token(char ch) 17 | : kind { ch } 18 | , value { 0 } 19 | { 20 | } 21 | 22 | Token(char ch, double val) 23 | : kind { ch } 24 | , value { val } 25 | { 26 | } 27 | 28 | Token(char ch, const std::string& n) 29 | : kind { ch } 30 | , value { 0 } 31 | , name { n } 32 | { 33 | } 34 | }; 35 | 36 | constexpr char number { '6' }; 37 | constexpr char quit { 'q' }; 38 | constexpr char print { ';' }; 39 | 40 | constexpr char name { 'a' }; 41 | constexpr char let { 'L' }; 42 | const std::string declkey { "let" }; 43 | 44 | } 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::cin; 7 | using std::runtime_error; 8 | using std::string; 9 | 10 | namespace Calc { 11 | 12 | void Token_stream::putback(Token t) 13 | { 14 | if (full) { 15 | throw runtime_error { "putback() into a full buffer" }; 16 | } 17 | buffer = t; 18 | full = true; 19 | } 20 | 21 | Token Token_stream::get() 22 | { 23 | if (full) { 24 | full = false; 25 | return buffer; 26 | } 27 | 28 | char ch { ' ' }; 29 | cin >> ch; 30 | 31 | if (!cin) 32 | return Token { quit }; 33 | 34 | switch (ch) { 35 | case print: 36 | case quit: 37 | case '(': 38 | case ')': 39 | case '+': 40 | case '-': 41 | case '*': 42 | case '/': 43 | case '%': 44 | case '=': 45 | return Token { ch }; 46 | case '.': 47 | case '0': 48 | case '1': 49 | case '2': 50 | case '3': 51 | case '4': 52 | case '5': 53 | case '6': 54 | case '7': 55 | case '8': 56 | case '9': { 57 | cin.putback(ch); 58 | double val { 0 }; 59 | cin >> val; 60 | if (!cin) { 61 | cin.clear(); 62 | throw runtime_error { "illegal floating point number" }; 63 | } 64 | return Token { number, val }; 65 | } 66 | default: 67 | if (isalpha(ch)) { 68 | string s { ch }; 69 | while (cin.get(ch) && (isalpha(ch) || isdigit(ch))) { 70 | s += ch; 71 | } 72 | cin.putback(ch); 73 | if (s == declkey) { 74 | return Token { let }; 75 | } 76 | return Token { name, s }; 77 | } 78 | throw runtime_error { "Bad token" }; 79 | } 80 | } 81 | 82 | void Token_stream::ignore(char c) 83 | // ignore the inputs until the character c 84 | { 85 | // look into the buffer first 86 | if (full && c == buffer.kind) { 87 | full = false; 88 | return; 89 | } 90 | 91 | full = false; // clear the buffer 92 | 93 | // search for the character c 94 | char ch { ' ' }; 95 | while (cin >> ch) { 96 | if (ch == c) 97 | return; 98 | } 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include "Token.h" 5 | 6 | namespace Calc { 7 | 8 | class Token_stream { 9 | public: 10 | Token get(); 11 | void putback(Token t); 12 | void ignore(char c); 13 | 14 | private: 15 | bool full { false }; 16 | Token buffer; 17 | }; 18 | 19 | } 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Variable.h" 6 | 7 | using std::map; 8 | using std::out_of_range; 9 | using std::runtime_error; 10 | using std::string; 11 | 12 | namespace Calc { 13 | 14 | double Var_table::get_value(const string& var) 15 | { 16 | try { 17 | return table.at(var); 18 | } catch (out_of_range&) { 19 | throw runtime_error { "get: undefined variable " + var }; 20 | } 21 | } 22 | 23 | void Var_table::set_value(const string& var, double val) 24 | { 25 | try { 26 | table.at(var) = val; 27 | } catch (out_of_range&) { 28 | throw runtime_error { "set: undefined variable " + var }; 29 | } 30 | } 31 | 32 | bool Var_table::is_declared(const string& var) 33 | { 34 | if (table.count(var) > 0) { 35 | return true; 36 | } else { 37 | return false; 38 | } 39 | } 40 | 41 | double Var_table::define_name(const string& var, double val) 42 | { 43 | if (is_declared(var)) { 44 | throw runtime_error { "variable " + var + " is already declared" }; 45 | } 46 | table[var] = val; 47 | return val; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/Variable.h: -------------------------------------------------------------------------------- 1 | #ifndef _VARIABLE_H 2 | #define _VARIABLE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Calc { 8 | 9 | class Var_table { 10 | public: 11 | double get_value(const std::string&); 12 | void set_value(const std::string&, double); 13 | double define_name(const std::string&, double); 14 | 15 | private: 16 | std::map table; 17 | bool is_declared(const std::string&); 18 | }; 19 | } 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/calc-3.0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Calculator.h" 5 | 6 | using std::cerr; 7 | 8 | int main() 9 | { 10 | Calc::Calculator calc; // contains ts and vt 11 | 12 | try { 13 | calc.calculate(); 14 | return 0; 15 | } catch (...) { 16 | cerr << "unknown error\n"; 17 | return 2; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/ex08/calc-3.0/input1.txt: -------------------------------------------------------------------------------- 1 | 1.2+3.6*2-0.4; 2 | 8; 3 | 10-8-1; 4 | 1; 5 | (1.2+3.6)*(2.3-0.3)+0.4; 6 | 10; 7 | 3.9/1.3/1.5*2.5+5; 8 | 10; 9 | -2*3+5;;; 10 | -1; 11 | let x = 3; 12 | 3; 13 | let y = 4; 14 | 4; 15 | let z = 2; 16 | 2; 17 | (x+y)*5-z; 18 | 33; 19 | 20 | 1/0; 21 | (1+); 22 | (); 23 | 1+; 24 | 1++; 25 | (2; 26 | 2+3); 27 | let x = 5; 28 | w*6; 29 | -------------------------------------------------------------------------------- /examples/ex08/chrono/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(chrono) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Chrono.h Chrono.cpp) 10 | 11 | add_executable(test_date.exe test_date.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex08/chrono/Chrono.h: -------------------------------------------------------------------------------- 1 | #ifndef _CHRONO_H 2 | #define _CHRONO_H 3 | 4 | #include 5 | 6 | namespace Chrono { 7 | 8 | enum class Month { 9 | Jan = 1, 10 | Feb, 11 | Mar, 12 | Apr, 13 | May, 14 | Jun, 15 | Jul, 16 | Aug, 17 | Sep, 18 | Oct, 19 | Nov, 20 | Dec 21 | }; 22 | 23 | enum class Day { 24 | Sun, 25 | Mon, 26 | Tue, 27 | Wed, 28 | Thu, 29 | Fri, 30 | Sat 31 | }; 32 | 33 | std::ostream& operator<<(std::ostream& os, Month m); 34 | std::ostream& operator<<(std::ostream& os, Day d); 35 | 36 | Month& operator++(Month& m); 37 | 38 | class Date { 39 | public: 40 | class Invalid { 41 | }; 42 | Date(int y, Month m, int d); 43 | Date(); 44 | Date(const Date& dd) 45 | : y { dd.y } 46 | , m { dd.m } 47 | , d { dd.d } 48 | { 49 | } 50 | 51 | Date& operator=(const Date& dd); 52 | 53 | int day() const { return d; } 54 | Month month() const { return m; } 55 | int year() const { return y; } 56 | 57 | void add_day(int n); 58 | void add_month(int n); 59 | void add_year(int n); 60 | 61 | private: 62 | int y; // year 63 | Month m; // month 64 | int d; // day of month 65 | }; 66 | 67 | const Date& default_date(); 68 | 69 | int days_in_month(int y, Month m); 70 | bool is_date(int y, Month m, int d); 71 | bool leapyear(int y); 72 | 73 | Day day_of_week(const Date& dd); 74 | 75 | bool operator==(const Date& a, const Date& b); 76 | bool operator!=(const Date& a, const Date& b); 77 | 78 | std::ostream& operator<<(std::ostream& os, const Date& d); 79 | } 80 | 81 | #endif 82 | 83 | -------------------------------------------------------------------------------- /examples/ex08/chrono/test_date.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Chrono.h" 4 | 5 | using std::cout; 6 | 7 | int main() 8 | { 9 | cout << "The default date is " << Chrono::default_date() << '\n'; 10 | 11 | Chrono::Date d1 { 1900, Chrono::Month::Feb, 28 }; 12 | cout << "d1 = " << d1 << '\n'; 13 | Chrono::Date d2 { 2000, Chrono::Month::Feb, 29 }; 14 | cout << "d2 = " << d2 << '\n'; 15 | 16 | Chrono::Date d3 { d1 }; 17 | cout << "Testing copy constructor: d3 = " << d3 << '\n'; 18 | 19 | d3 = d2; 20 | cout << "Testing copy assignment: d3 = " << d3 << '\n'; 21 | 22 | cout << std::boolalpha; 23 | cout << "Testing == operator: d3 == d1? " << (d3 == d1) << '\n'; 24 | cout << "Testing != operator: d3 != d1? " << (d3 != d1) << '\n'; 25 | 26 | d3.add_year(5); 27 | cout << "Testing add_year: d3 = " << d3 << '\n'; 28 | 29 | d3.add_month(100); 30 | cout << "Testing add_month: d3 = " << d3 << '\n'; 31 | 32 | d3.add_day(1000); 33 | cout << "Testing add_day: d3 = " << d3 << '\n'; 34 | 35 | Chrono::Day dow = Chrono::day_of_week(Chrono::default_date()); 36 | cout << "Testing day_of_week: " << dow << '\n'; 37 | 38 | dow = Chrono::day_of_week(Chrono::Date { 2017, Chrono::Month::Nov, 16 }); 39 | cout << "Testing day_of_week: " << dow << '\n'; 40 | } 41 | -------------------------------------------------------------------------------- /examples/ex08/chrono/test_date.java: -------------------------------------------------------------------------------- 1 | import java.util.Calendar; 2 | 3 | public class test_date { 4 | 5 | public static void main(String[] args) 6 | { 7 | Calendar cal = Calendar.getInstance(); 8 | cal.set(2000, 2 - 1, 29); 9 | 10 | int year = cal.get(Calendar.YEAR); 11 | int month = cal.get(Calendar.MONTH); 12 | int day = cal.get(Calendar.DAY_OF_MONTH); 13 | System.out.printf("%4d-%02d-%02d\n", year, month + 1, day); 14 | 15 | cal.add(Calendar.YEAR, 5); 16 | year = cal.get(Calendar.YEAR); 17 | month = cal.get(Calendar.MONTH); 18 | day = cal.get(Calendar.DAY_OF_MONTH); 19 | System.out.printf("%4d-%02d-%02d\n", year, month + 1, day); 20 | 21 | cal.add(Calendar.MONTH, 100); 22 | year = cal.get(Calendar.YEAR); 23 | month = cal.get(Calendar.MONTH); 24 | day = cal.get(Calendar.DAY_OF_MONTH); 25 | System.out.printf("%4d-%02d-%02d\n", year, month + 1, day); 26 | 27 | cal.add(Calendar.DAY_OF_MONTH, 1000); 28 | year = cal.get(Calendar.YEAR); 29 | month = cal.get(Calendar.MONTH); 30 | day = cal.get(Calendar.DAY_OF_MONTH); 31 | System.out.printf("%4d-%02d-%02d\n", year, month + 1, day); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/ex08/complex/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(complex) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Complex.h Complex.cpp) 10 | 11 | add_executable(test_complex.exe test_complex.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex08/complex/Complex.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALC_COMPLEX_H 2 | #define _CALC_COMPLEX_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Complex { 9 | public: 10 | class Divide_by_zero { 11 | }; 12 | 13 | constexpr Complex(double re = 0.0, double im = 0.0) 14 | : x { re } 15 | , y { im } 16 | { 17 | } 18 | 19 | double real() const { return x; } 20 | double imag() const { return y; } 21 | 22 | Complex conj() const; 23 | double norm() const; 24 | double abs() const; 25 | double arg() const; 26 | 27 | Complex& operator+=(Complex z); 28 | Complex& operator-=(Complex z); 29 | Complex& operator*=(Complex z); 30 | Complex& operator/=(Complex z); 31 | 32 | private: 33 | double x, y; 34 | }; 35 | 36 | Complex operator+(Complex z); 37 | Complex operator-(Complex z); 38 | 39 | Complex operator+(Complex z1, Complex z2); 40 | Complex operator-(Complex z1, Complex z2); 41 | Complex operator*(Complex z1, Complex z2); 42 | Complex operator/(Complex z1, Complex z2); 43 | 44 | bool operator==(Complex z1, Complex z2); 45 | bool operator!=(Complex z1, Complex z2); 46 | 47 | std::ostream& operator<<(std::ostream& os, Complex z); 48 | 49 | Complex exp(Complex z); 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /examples/ex08/complex/test_complex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Complex.h" 5 | 6 | using std::cout; 7 | 8 | int main() 9 | { 10 | Calc::Complex z1 { 3, 4 }; 11 | Calc::Complex z2 { 4, 3 }; 12 | 13 | cout << "z1 == " << z1 << '\n'; 14 | cout << "z2 == " << z2 << '\n'; 15 | 16 | cout << "+z1 == " << +z1 << '\n'; 17 | cout << "-z1 == " << -z1 << '\n'; 18 | cout << "z1+z2 == " << z1 + z2 << '\n'; 19 | cout << "z1-z2 == " << z1 - z2 << '\n'; 20 | cout << "z1*z2 == " << z1 * z2 << '\n'; 21 | cout << "z1/z2 == " << z1 / z2 << '\n'; 22 | cout << "2+z1 == " << 2 + z1 << '\n'; 23 | cout << "2-z1 == " << 2 - z1 << '\n'; 24 | cout << "2*z1 == " << 2 * z1 << '\n'; 25 | cout << "2/z1 == " << 2 / z1 << '\n'; 26 | 27 | cout << "z1.conj() == " << z1.conj() << '\n'; 28 | cout << "exp(z1) == " << exp(z1) << '\n'; 29 | // 这里编译器会自动找到正确的exp函数! 30 | cout << "exp(2.0) == " << exp(2.0) << '\n'; 31 | cout << "z1.norm() == " << z1.norm() << '\n'; 32 | cout << "z1.abs() == " << z1.abs() << '\n'; 33 | cout << "z1.arg() == " << z1.arg() << '\n'; 34 | 35 | z1 += z2; 36 | cout << z1 << '\n'; 37 | z1 -= z2; 38 | cout << z1 << '\n'; 39 | z1 *= z2; 40 | cout << z1 << '\n'; 41 | z1 /= z2; 42 | cout << z1 << '\n'; 43 | } 44 | -------------------------------------------------------------------------------- /examples/ex08/misc/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(misc) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex test_copy) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex08/rational/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(rational) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Rational.h Rational.cpp) 10 | 11 | add_executable(test_rational.exe test_rational.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex08/rational/Rational.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Rational.h" 4 | 5 | namespace Calc { 6 | 7 | Rational::Rational(int nn, int dd) 8 | { 9 | } 10 | 11 | int gcd(int m, int n) 12 | { 13 | } 14 | 15 | Rational operator+(Rational r) 16 | { 17 | } 18 | 19 | Rational operator-(Rational r) 20 | { 21 | } 22 | 23 | Rational operator+(Rational r1, Rational r2) 24 | { 25 | } 26 | 27 | Rational operator-(Rational r1, Rational r2) 28 | { 29 | } 30 | 31 | Rational operator*(Rational r1, Rational r2) 32 | { 33 | } 34 | 35 | Rational operator/(Rational r1, Rational r2) 36 | { 37 | } 38 | 39 | bool operator==(Rational r1, Rational r2) 40 | { 41 | } 42 | 43 | bool operator!=(Rational r1, Rational r2) 44 | { 45 | } 46 | 47 | bool operator>(Rational r1, Rational r2) 48 | { 49 | } 50 | 51 | bool operator<(Rational r1, Rational r2) 52 | { 53 | } 54 | 55 | bool operator>=(Rational r1, Rational r2) 56 | { 57 | } 58 | 59 | bool operator<=(Rational r1, Rational r2) 60 | { 61 | } 62 | 63 | ///////////////////////////////////////////////////////////////////////////// 64 | // WARNING: do NOT modify the following unless you know what you are doing // 65 | ///////////////////////////////////////////////////////////////////////////// 66 | 67 | std::ostream& operator<<(std::ostream& os, Rational r) 68 | { 69 | return os << r.num() << '/' << r.den(); 70 | } 71 | 72 | std::istream& operator>>(std::istream& is, Rational& r) 73 | { 74 | char ch; 75 | int n, d; 76 | is >> n >> ch >> d; 77 | if (!is) 78 | return is; 79 | if (ch != '/') { 80 | is.clear(std::ios_base::failbit); 81 | return is; 82 | } 83 | try { 84 | r = Rational { n, d }; 85 | } catch (Rational::Invalid) { 86 | is.clear(std::ios_base::failbit); 87 | } 88 | return is; 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /examples/ex08/rational/Rational.h: -------------------------------------------------------------------------------- 1 | #ifndef _RATIONAL_H 2 | #define _RATIONAL_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Rational { 9 | public: 10 | class Invalid { 11 | }; 12 | class Divide_by_zero { 13 | }; 14 | Rational(int nn = 0, int dd = 1); 15 | int num() const { return n; } 16 | int den() const { return d; } 17 | 18 | private: 19 | // 提示:每个有理数应该有一个唯一的表示,例如可以约定d>0,且不能再约分 20 | int n; // 分子 21 | int d; // 分母 22 | }; 23 | 24 | int gcd(int m, int n); // |m|和|n|的最大公约数 25 | 26 | Rational operator+(Rational r); // 正号 +r 27 | Rational operator-(Rational r); // 负号 -r 28 | 29 | Rational operator+(Rational r1, Rational r2); // 加法 r1+r2 30 | Rational operator-(Rational r1, Rational r2); // 减法 r1-r2 31 | Rational operator*(Rational r1, Rational r2); // 乘法 r1*r2 32 | Rational operator/(Rational r1, Rational r2); // 除法 r1/r2 33 | 34 | bool operator==(Rational r1, Rational r2); // 相等 r1==r2 35 | bool operator!=(Rational r1, Rational r2); // 不等 r1!=r2 36 | bool operator>(Rational r1, Rational r2); // 大于 r1>r2 37 | bool operator<(Rational r1, Rational r2); // 小于 r1=(Rational r1, Rational r2); // 大于等于 r1>=r2 39 | bool operator<=(Rational r1, Rational r2); // 小于等于 f1<=r2 40 | 41 | std::ostream& operator<<(std::ostream& os, Rational r); // 输出 os << r 42 | std::istream& operator>>(std::istream& is, Rational& r); // 输入 is >> r 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /examples/ex08/rational/test_rational.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Rational.h" 6 | 7 | using std::cerr; 8 | using std::cin; 9 | using std::cout; 10 | using std::vector; 11 | 12 | void test1() 13 | { 14 | cout << "Please input two rational numbers: "; 15 | 16 | Calc::Rational r1; 17 | Calc::Rational r2; 18 | cin >> r1 >> r2; 19 | if (!cin) { 20 | cerr << "wrong inputs\n"; 21 | return; 22 | } 23 | 24 | cout << "r1 == " << r1 << '\n'; 25 | cout << "r2 == " << r2 << '\n'; 26 | 27 | cout << "+r1 == " << +r1 << '\n'; 28 | cout << "-r1 == " << -r1 << '\n'; 29 | cout << "r1+r2 == " << r1 + r2 << '\n'; 30 | cout << "r1-r2 == " << r1 - r2 << '\n'; 31 | cout << "r1*r2 == " << r1 * r2 << '\n'; 32 | cout << "r1/r2 == " << r1 / r2 << '\n'; 33 | cout << "2+r1 == " << 2 + r1 << '\n'; 34 | cout << "2-r1 == " << 2 - r1 << '\n'; 35 | cout << "2*r1 == " << 2 * r1 << '\n'; 36 | cout << "2/r1 == " << 2 / r1 << '\n'; 37 | 38 | cout << std::boolalpha; 39 | cout << "r1==r2: " << (r1 == r2) << '\n'; 40 | cout << "r1!=r2: " << (r1 != r2) << '\n'; 41 | cout << "r1>r2: " << (r1 > r2) << '\n'; 42 | cout << "r1=r2: " << (r1 >= r2) << '\n'; 44 | cout << "r1<=r2: " << (r1 <= r2) << '\n'; 45 | } 46 | 47 | void test2() 48 | { 49 | vector vr { { 2, 3 }, { 3, 2 }, { 3, 4 }, { 4, 3 }, { 4, 5 }, { 5, 4 } }; 50 | std::sort(vr.begin(), vr.end()); 51 | for (const auto& r : vr) { 52 | cout << r << " "; 53 | } 54 | cout << '\n'; 55 | } 56 | 57 | int main() 58 | { 59 | test1(); 60 | test2(); 61 | } 62 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(Punct_stream) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Punct_stream.h Punct_stream.cpp) 10 | 11 | foreach(ex test_csv test_ps) 12 | add_executable(${ex}.exe ${ex}.cpp ${SOURCES}) 13 | endforeach(ex) 14 | 15 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/Punct_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Punct_stream.h" 5 | 6 | using std::string; 7 | 8 | Punct_stream& Punct_stream::operator>>(string& s) 9 | { 10 | while (!(buffer >> s)) { 11 | if (buffer.bad() || !source.good()) 12 | return *this; 13 | buffer.clear(); 14 | 15 | string line; 16 | getline(source, line); 17 | 18 | for (char& ch : line) { 19 | if (is_whitespace(ch)) 20 | ch = ' '; 21 | else if (!sensitive) 22 | ch = tolower(ch); 23 | } 24 | 25 | buffer.str(line); 26 | } 27 | return *this; 28 | } 29 | 30 | Punct_stream& Punct_stream::operator>>(int& n) 31 | { 32 | while (!(buffer >> n)) { 33 | if (buffer.bad() || !source.good()) 34 | return *this; 35 | buffer.clear(); 36 | 37 | string line; 38 | getline(source, line); 39 | 40 | for (char& ch : line) { 41 | if (is_whitespace(ch)) 42 | ch = ' '; 43 | else if (!sensitive) 44 | ch = tolower(ch); 45 | } 46 | 47 | buffer.str(line); 48 | } 49 | return *this; 50 | } 51 | 52 | bool Punct_stream::is_whitespace(char c) 53 | { 54 | for (char w : white) { 55 | if (c == w) 56 | return true; 57 | } 58 | return false; 59 | } 60 | 61 | Punct_stream::operator bool() const 62 | { 63 | return !(buffer.fail() || buffer.bad()) && source.good(); 64 | } 65 | 66 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/Punct_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _PUNCT_STREAM_H 2 | #define _PUNCT_STREAM_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class Punct_stream { 9 | public: 10 | explicit Punct_stream(std::istream& is) 11 | : source { is } 12 | , sensitive { true } 13 | { 14 | } 15 | 16 | void whitespace(const std::string& s) { white = s; } 17 | void add_white(char c) { white += c; } 18 | bool is_whitespace(char c); 19 | void case_sensitive(bool b) { sensitive = b; } 20 | bool is_case_sensitive() const { return sensitive; } 21 | 22 | Punct_stream& operator>>(std::string& s); 23 | Punct_stream& operator>>(int& n); 24 | explicit operator bool() const; 25 | 26 | private: 27 | std::istream& source; 28 | std::istringstream buffer; 29 | std::string white; 30 | bool sensitive; 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/input.txt: -------------------------------------------------------------------------------- 1 | There are only two kinds of languages: languages that people complain about, and languages that people don't use. 2 | 3 | Only two things are infinite, the universe and human stupidity, and I'm not sure about the former. 4 | 5 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/test.csv: -------------------------------------------------------------------------------- 1 | 09804001,100,100 2 | 09804070,100,100 3 | 09804071,100,100 4 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/test_csv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Punct_stream.h" 6 | 7 | using std::cout; 8 | using std::string; 9 | 10 | int main() 11 | { 12 | std::ifstream ifs { "test.csv" }; 13 | Punct_stream ps { ifs }; 14 | ps.whitespace(","); 15 | 16 | string id; 17 | int mid_score; 18 | int final_score; 19 | 20 | while (ps >> id >> mid_score >> final_score) { 21 | cout << id << '\t' << mid_score << '\t' << final_score << '\n'; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ex09/Punct_stream/test_ps.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "Punct_stream.h" 8 | 9 | using std::cin; 10 | using std::cout; 11 | using std::string; 12 | using std::vector; 13 | 14 | int main() 15 | { 16 | std::ifstream ifs { "input.txt" }; 17 | Punct_stream ps { ifs }; 18 | ps.whitespace(";:,.?!()\"{}<>/&$@#%^*|~"); 19 | ps.case_sensitive(false); 20 | 21 | vector vs; 22 | for (string word; ps >> word;) { 23 | if (!ps) { 24 | } 25 | vs.push_back(word); 26 | } 27 | 28 | std::sort(vs.begin(), vs.end()); 29 | for (size_t i = 0; i < vs.size(); ++i) { 30 | if (i == 0 || vs[i] != vs[i - 1]) 31 | cout << vs[i] << '\n'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(calc-3.x) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Token.h Token_stream.h Token_stream.cpp Calculator.h Calculator.cpp 10 | Variable.h Variable.cpp) 11 | 12 | foreach(ex calc-3.0 calc-3.1 calc-3.2 calc-3.3) 13 | add_executable(${ex}.exe ${ex}.cpp ${SOURCES}) 14 | endforeach(ex) 15 | 16 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Calculator.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALCULATOR_H 2 | #define _CALCULATOR_H 3 | 4 | #include 5 | 6 | #include "Token_stream.h" 7 | #include "Variable.h" 8 | 9 | namespace Calc { 10 | 11 | class Calculator { 12 | public: 13 | explicit Calculator(std::istream& is = std::cin) 14 | : ts { is } 15 | { 16 | } 17 | 18 | void calculate(); 19 | 20 | private: 21 | Token_stream ts; 22 | Var_table vt; 23 | 24 | void clean_up_mess(); 25 | 26 | double statement(); 27 | double declaration(); 28 | double expression(); 29 | double term(); 30 | double primary(); 31 | }; 32 | } 33 | 34 | #endif 35 | 36 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Token { 9 | public: 10 | char kind; 11 | double value; 12 | std::string name; 13 | 14 | Token() {} 15 | 16 | Token(char ch) 17 | : kind { ch } 18 | , value { 0 } 19 | { 20 | } 21 | 22 | Token(char ch, double val) 23 | : kind { ch } 24 | , value { val } 25 | { 26 | } 27 | 28 | Token(char ch, const std::string& n) 29 | : kind { ch } 30 | , value { 0 } 31 | , name { n } 32 | { 33 | } 34 | }; 35 | 36 | constexpr char number { '6' }; 37 | constexpr char quit { 'q' }; 38 | constexpr char print { ';' }; 39 | 40 | constexpr char name { 'a' }; 41 | constexpr char let { 'L' }; 42 | const std::string declkey { "let" }; 43 | 44 | } 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::runtime_error; 7 | using std::string; 8 | 9 | namespace Calc { 10 | 11 | void Token_stream::putback(Token t) 12 | { 13 | if (full) { 14 | throw runtime_error { "putback() into a full buffer" }; 15 | } 16 | buffer = t; 17 | full = true; 18 | } 19 | 20 | Token Token_stream::get() 21 | { 22 | if (full) { 23 | full = false; 24 | return buffer; 25 | } 26 | 27 | char ch { ' ' }; 28 | ist >> ch; 29 | 30 | if (!ist) 31 | return Token { quit }; 32 | 33 | switch (ch) { 34 | case print: 35 | case quit: 36 | case '(': 37 | case ')': 38 | case '+': 39 | case '-': 40 | case '*': 41 | case '/': 42 | case '%': 43 | case '=': 44 | return Token { ch }; 45 | case '.': 46 | case '0': 47 | case '1': 48 | case '2': 49 | case '3': 50 | case '4': 51 | case '5': 52 | case '6': 53 | case '7': 54 | case '8': 55 | case '9': { 56 | ist.putback(ch); 57 | double val { 0 }; 58 | ist >> val; 59 | if (!ist) { 60 | ist.clear(); 61 | throw runtime_error { "illegal floating point number" }; 62 | } 63 | return Token { number, val }; 64 | } 65 | default: 66 | if (isalpha(ch)) { 67 | string s { ch }; 68 | while (ist.get(ch) && (isalpha(ch) || isdigit(ch))) { 69 | s += ch; 70 | } 71 | ist.putback(ch); 72 | if (s == declkey) { 73 | return Token { let }; 74 | } 75 | return Token { name, s }; 76 | } 77 | throw runtime_error { "Bad token" }; 78 | } 79 | } 80 | 81 | void Token_stream::ignore(char c) 82 | // ignore the inputs until the character c 83 | { 84 | // look into the buffer first 85 | if (full && c == buffer.kind) { 86 | full = false; 87 | return; 88 | } 89 | 90 | full = false; // clear the buffer 91 | 92 | // search for the character c 93 | char ch { ' ' }; 94 | while (ist >> ch) { 95 | if (ch == c) 96 | return; 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include 5 | 6 | #include "Token.h" 7 | 8 | namespace Calc { 9 | 10 | class Token_stream { 11 | public: 12 | explicit Token_stream(std::istream& is) 13 | : ist { is } 14 | { 15 | } 16 | 17 | Token get(); 18 | void putback(Token t); 19 | void ignore(char c); 20 | 21 | explicit operator bool() const { return bool(ist); } 22 | 23 | private: 24 | std::istream& ist; 25 | bool full { false }; 26 | Token buffer; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Variable.h" 6 | 7 | using std::map; 8 | using std::out_of_range; 9 | using std::runtime_error; 10 | using std::string; 11 | 12 | namespace Calc { 13 | 14 | double Var_table::get_value(const string& var) 15 | { 16 | try { 17 | return table.at(var); 18 | } catch (out_of_range&) { 19 | throw runtime_error { "get: undefined variable " + var }; 20 | } 21 | } 22 | 23 | void Var_table::set_value(const string& var, double val) 24 | { 25 | try { 26 | table.at(var) = val; 27 | } catch (out_of_range&) { 28 | throw runtime_error { "set: undefined variable " + var }; 29 | } 30 | } 31 | 32 | bool Var_table::is_declared(const string& var) 33 | { 34 | if (table.count(var) > 0) { 35 | return true; 36 | } else { 37 | return false; 38 | } 39 | } 40 | 41 | double Var_table::define_name(const string& var, double val) 42 | { 43 | if (is_declared(var)) { 44 | throw runtime_error { "variable " + var + " is already declared" }; 45 | } 46 | table[var] = val; 47 | return val; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/Variable.h: -------------------------------------------------------------------------------- 1 | #ifndef _VARIABLE_H 2 | #define _VARIABLE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Calc { 8 | 9 | class Var_table { 10 | public: 11 | double get_value(const std::string&); 12 | void set_value(const std::string&, double); 13 | double define_name(const std::string&, double); 14 | 15 | private: 16 | std::map table; 17 | bool is_declared(const std::string&); 18 | }; 19 | } 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/calc-3.0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Calculator.h" 5 | 6 | using std::cerr; 7 | 8 | int main() 9 | { 10 | Calc::Calculator calc; // by default ist = cin 11 | 12 | try { 13 | calc.calculate(); 14 | return 0; 15 | } catch (...) { 16 | cerr << "unknown error\n"; 17 | return 2; 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/calc-3.1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Calculator.h" 6 | 7 | using std::cerr; 8 | using std::ifstream; 9 | using std::string; 10 | 11 | int main() 12 | { 13 | string fname { "input1.txt" }; 14 | ifstream ifs { fname }; 15 | if (!ifs) { 16 | cerr << "cannot open file " + fname << '\n'; 17 | return 1; 18 | } 19 | 20 | Calc::Calculator calc { ifs }; 21 | 22 | try { 23 | calc.calculate(); 24 | return 0; 25 | } catch (...) { 26 | cerr << "unknown error\n"; 27 | return 2; 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/calc-3.2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Calculator.h" 6 | 7 | using std::cerr; 8 | using std::cin; 9 | using std::cout; 10 | using std::ifstream; 11 | using std::string; 12 | 13 | int main() 14 | { 15 | cout << "Please enter the name of the input file: "; 16 | string fname; 17 | cin >> fname; 18 | 19 | ifstream ifs { fname }; 20 | if (!ifs) { 21 | cerr << "cannot open file " + fname << '\n'; 22 | return 1; 23 | } 24 | 25 | Calc::Calculator calc { ifs }; 26 | 27 | try { 28 | calc.calculate(); 29 | return 0; 30 | } catch (...) { 31 | cerr << "unknown error\n"; 32 | return 2; 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/calc-3.3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "Calculator.h" 7 | 8 | using std::cerr; 9 | using std::cin; 10 | using std::cout; 11 | using std::ifstream; 12 | using std::string; 13 | using std::vector; 14 | 15 | int main() 16 | { 17 | cout << "Please enter the name of the input files (end with EOF): "; 18 | vector fnames; 19 | for (string fname; cin >> fname;) { 20 | fnames.push_back(fname); 21 | } 22 | 23 | for (const auto& fname : fnames) { 24 | ifstream ifs { fname }; 25 | if (!ifs) { 26 | cerr << "cannot open file " + fname << '\n'; 27 | continue; // skip the file and start with the next one 28 | } 29 | 30 | Calc::Calculator calc { ifs }; 31 | 32 | try { 33 | calc.calculate(); 34 | } catch (...) { 35 | cerr << "unknown error\n"; 36 | return 2; 37 | } 38 | } 39 | 40 | return 0; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/input1.txt: -------------------------------------------------------------------------------- 1 | 1.2+3.6*2-0.4; 2 | 8; 3 | 10-8-1; 4 | 1; 5 | (1.2+3.6)*(2.3-0.3)+0.4; 6 | 10; 7 | 3.9/1.3/1.5*2.5+5; 8 | 10; 9 | -2*3+5;;; 10 | -1; 11 | let x = 3; 12 | 3; 13 | let y = 4; 14 | 4; 15 | let z = 2; 16 | 2; 17 | (x+y)*5-z; 18 | 33; 19 | -------------------------------------------------------------------------------- /examples/ex09/calc-3.x/input2.txt: -------------------------------------------------------------------------------- 1 | 1/0; 2 | (1+); 3 | (); 4 | 1+; 5 | 1++; 6 | (2; 7 | 2+3); 8 | let x = 5; 9 | let x = 5; 10 | w*6; 11 | -------------------------------------------------------------------------------- /examples/ex09/complex/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(complex) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Complex.h Complex.cpp) 10 | 11 | add_executable(test_complex.exe test_complex.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex09/complex/Complex.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALC_COMPLEX_H 2 | #define _CALC_COMPLEX_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Complex { 9 | public: 10 | class Divide_by_zero { 11 | }; 12 | 13 | constexpr Complex(double re = 0.0, double im = 0.0) 14 | : x { re } 15 | , y { im } 16 | { 17 | } 18 | 19 | double real() const { return x; } 20 | double imag() const { return y; } 21 | 22 | Complex conj() const; 23 | double norm() const; 24 | double abs() const; 25 | double arg() const; 26 | 27 | Complex& operator+=(Complex z); 28 | Complex& operator-=(Complex z); 29 | Complex& operator*=(Complex z); 30 | Complex& operator/=(Complex z); 31 | 32 | private: 33 | double x, y; 34 | }; 35 | 36 | Complex operator+(Complex z); 37 | Complex operator-(Complex z); 38 | 39 | Complex operator+(Complex z1, Complex z2); 40 | Complex operator-(Complex z1, Complex z2); 41 | Complex operator*(Complex z1, Complex z2); 42 | Complex operator/(Complex z1, Complex z2); 43 | 44 | bool operator==(Complex z1, Complex z2); 45 | bool operator!=(Complex z1, Complex z2); 46 | 47 | std::ostream& operator<<(std::ostream& os, Complex z); 48 | std::istream& operator>>(std::istream& is, Complex& z); 49 | 50 | Complex exp(Complex z); 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /examples/ex09/complex/test_complex.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Complex.h" 5 | 6 | using std::cerr; 7 | using std::cin; 8 | using std::cout; 9 | 10 | int main() 11 | { 12 | cout << "Please enter two complex numbers in the form (x,y): \n"; 13 | Calc::Complex z1; 14 | Calc::Complex z2; 15 | cin >> z1 >> z2; 16 | if (!cin) { 17 | cerr << "wrong input\n"; 18 | return 1; 19 | } 20 | 21 | cout << "z1 == " << z1 << '\n'; 22 | cout << "z2 == " << z2 << '\n'; 23 | 24 | cout << "+z1 == " << +z1 << '\n'; 25 | cout << "-z1 == " << -z1 << '\n'; 26 | cout << "z1+z2 == " << z1 + z2 << '\n'; 27 | cout << "z1-z2 == " << z1 - z2 << '\n'; 28 | cout << "z1*z2 == " << z1 * z2 << '\n'; 29 | cout << "z1/z2 == " << z1 / z2 << '\n'; 30 | cout << "2+z1 == " << 2 + z1 << '\n'; 31 | cout << "2-z1 == " << 2 - z1 << '\n'; 32 | cout << "2*z1 == " << 2 * z1 << '\n'; 33 | cout << "2/z1 == " << 2 / z1 << '\n'; 34 | 35 | cout << "z1.conj() == " << z1.conj() << '\n'; 36 | cout << "exp(z1) == " << exp(z1) << '\n'; 37 | // 这里编译器会自动找到正确的exp函数! 38 | cout << "exp(2.0) == " << exp(2.0) << '\n'; 39 | cout << "z1.norm() == " << z1.norm() << '\n'; 40 | cout << "z1.abs() == " << z1.abs() << '\n'; 41 | cout << "z1.arg() == " << z1.arg() << '\n'; 42 | 43 | z1 += z2; 44 | cout << z1 << '\n'; 45 | z1 -= z2; 46 | cout << z1 << '\n'; 47 | z1 *= z2; 48 | cout << z1 << '\n'; 49 | z1 /= z2; 50 | cout << z1 << '\n'; 51 | } 52 | -------------------------------------------------------------------------------- /examples/ex09/read_int/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(read_int) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | foreach(ex read_int read_int_new) 10 | add_executable(${ex}.exe ${ex}.cpp) 11 | endforeach(ex) 12 | 13 | 14 | -------------------------------------------------------------------------------- /examples/ex09/read_int/read_int.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using std::cin; 4 | using std::cout; 5 | using std::runtime_error; 6 | 7 | int main() 8 | { 9 | cout << "Please enter an integer in the range [1,10]:\n"; 10 | int n { 0 }; 11 | while (true) { 12 | cin >> n; 13 | if (cin) { // 成功读入一个整数!下面检查范围 14 | if (1 <= n && n <= 10) 15 | break; // 成功!跳出循环 16 | cout << "out of range; try again\n"; 17 | } else if (cin.fail()) { // 不是整数 18 | cin.clear(); 19 | cout << "not a number; try again\n"; 20 | for (char ch; cin >> ch && !isdigit(ch);) 21 | ; // 忽略非数字 22 | if (!cin) 23 | throw runtime_error { "你逗我?" }; 24 | cin.unget(); 25 | } else { 26 | throw runtime_error { "no input" }; 27 | } 28 | } 29 | cout << n << '\n'; 30 | } 31 | -------------------------------------------------------------------------------- /examples/ex09/read_int/read_int_new.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cerr; 6 | using std::cin; 7 | using std::cout; 8 | using std::exception; 9 | using std::runtime_error; 10 | using std::string; 11 | 12 | void skip_to_int() 13 | { 14 | if (cin.fail()) { 15 | cin.clear(); 16 | for (char ch = ' '; cin >> ch;) { 17 | if (isdigit(ch) || ch == '-') { 18 | cin.unget(); 19 | return; 20 | } 21 | } 22 | } 23 | throw runtime_error { "no input" }; 24 | } 25 | 26 | int get_int() 27 | { 28 | int n { 0 }; 29 | while (true) { 30 | if (cin >> n) 31 | return n; 32 | cout << "not a number; try again\n"; 33 | skip_to_int(); 34 | } 35 | } 36 | 37 | int get_int(int low, int high, 38 | const string& greeting, const string& sorry) 39 | { 40 | cout << greeting << ": [" << low << ',' << high << "]\n"; 41 | 42 | while (true) { 43 | int n { get_int() }; 44 | if (low <= n && n <= high) 45 | return n; 46 | cout << sorry << ": [" << low << ',' << high << "]\n"; 47 | } 48 | } 49 | 50 | int main() 51 | { 52 | const string greeting { "Please enter an integer in the range" }; 53 | const string sorry { "out of range; try again" }; 54 | try { 55 | int n { get_int(1, 10, greeting, sorry) }; 56 | cout << n << '\n'; 57 | } catch (exception& e) { 58 | cerr << e.what() << '\n'; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /examples/ex09/read_vectors/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(read_vectors) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | add_executable(read_vectors.exe read_vectors.cpp) 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/ex09/read_vectors/generate_random_data.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | from random import randrange 4 | 5 | for i in range(100): 6 | n = randrange(10) 7 | f = "{}\t" * n + "*" 8 | v = [randrange(10) for j in range(n)] 9 | print(f.format(*v)) 10 | -------------------------------------------------------------------------------- /examples/ex09/read_vectors/read_vectors.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using std::cerr; 7 | using std::cout; 8 | using std::ifstream; 9 | using std::istream; 10 | using std::runtime_error; 11 | using std::vector; 12 | 13 | vector read_vector(istream& ist, char terminator) 14 | { 15 | vector v; 16 | for (int i; ist >> i;) 17 | v.push_back(i); 18 | 19 | if (ist.bad()) { 20 | throw runtime_error { "这一定是机关的阴谋! El Psy Congroo!" }; 21 | } 22 | 23 | if (ist.eof()) { 24 | return v; 25 | } 26 | 27 | if (ist.fail()) { 28 | ist.clear(); // 将状态设为good 29 | char c; 30 | ist >> c; 31 | if (c != terminator) { 32 | cerr << "error reading vector\n"; 33 | ist.unget(); // 放回上一次读入的字符 34 | ist.clear(std::ios_base::failbit); // 将状态设为fail 35 | } 36 | } 37 | 38 | return v; 39 | } 40 | 41 | int main() 42 | { 43 | ifstream ifs { "vectors.txt" }; 44 | if (!ifs) { 45 | cerr << "cannot open file: vectors.txt for reading\n"; 46 | return 1; 47 | } 48 | 49 | while (ifs) { 50 | vector v { read_vector(ifs, '*') }; 51 | if (ifs && !v.empty()) 52 | cout << v.size() << '\n'; 53 | } 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /examples/ex09/read_vectors/vectors.txt: -------------------------------------------------------------------------------- 1 | 2 4 3 5 6 8 * 2 | * 3 | 1 5 0 2 2 1 * 4 | 4 9 3 1 0 2 8 9 * 5 | 6 3 * 6 | 3 0 9 3 7 7 6 * 7 | 4 * 8 | 5 9 6 2 1 2 2 * 9 | 6 8 7 7 9 6 9 * 10 | 3 * 11 | 3 * 12 | * 13 | 0 7 * 14 | 1 1 8 2 5 9 3 7 * 15 | 5 6 * 16 | 1 9 0 6 4 * 17 | 7 8 * 18 | 7 5 4 7 8 2 * 19 | 2 8 0 1 3 * 20 | 0 2 4 9 5 5 8 * 21 | 0 6 9 0 9 4 4 8 8 * 22 | 1 6 * 23 | 4 0 5 7 3 * 24 | 9 5 1 2 * 25 | 8 8 * 26 | 7 5 0 6 7 0 5 6 7 * 27 | 2 8 2 1 7 * 28 | 8 1 5 2 8 5 6 4 * 29 | * 30 | 1 5 6 1 8 3 4 1 7 * 31 | 4 0 5 8 9 6 * 32 | 3 9 1 2 6 5 * 33 | 9 8 5 9 * 34 | 6 * 35 | 4 6 8 9 9 3 9 3 * 36 | 4 6 6 3 * 37 | 0 5 8 0 5 1 * 38 | 7 9 6 0 * 39 | 8 7 5 0 * 40 | 8 5 9 6 7 4 8 3 * 41 | 3 6 2 3 * 42 | 1 9 0 3 3 1 6 4 9 * 43 | 0 5 6 8 1 8 6 * 44 | 1 9 3 4 * 45 | 2 1 2 8 * 46 | 6 6 0 9 0 9 5 7 * 47 | 2 * 48 | 8 5 4 2 2 * 49 | 2 0 8 9 2 0 5 * 50 | 9 7 5 * 51 | * 52 | 1 9 1 2 9 2 9 9 1 * 53 | 0 9 6 2 * 54 | 5 7 4 0 1 5 8 * 55 | 3 6 5 0 * 56 | 3 7 4 4 0 6 8 * 57 | 7 3 3 8 * 58 | 5 6 9 6 6 6 * 59 | 2 1 0 1 * 60 | 8 8 8 6 * 61 | 7 5 6 5 * 62 | * 63 | 0 0 1 9 4 7 1 9 3 * 64 | 4 * 65 | 6 9 1 7 3 8 3 9 2 * 66 | 1 * 67 | 8 * 68 | 6 * 69 | * 70 | 2 4 * 71 | 6 5 * 72 | 9 1 0 6 0 9 9 * 73 | 3 4 9 * 74 | * 75 | 9 3 2 6 7 7 4 5 0 * 76 | 4 3 7 9 * 77 | 5 1 6 9 6 1 8 6 7 * 78 | * 79 | 2 8 5 6 1 0 * 80 | 7 3 * 81 | * 82 | 7 4 2 1 7 9 8 * 83 | * 84 | 7 0 * 85 | 3 2 * 86 | 9 8 0 * 87 | 7 3 2 0 8 3 7 1 * 88 | 7 9 6 6 4 9 * 89 | 2 3 3 1 9 * 90 | 1 3 3 * 91 | 9 3 7 6 * 92 | 9 3 * 93 | 0 9 * 94 | 5 0 0 9 1 9 * 95 | 6 * 96 | 0 9 6 4 7 1 3 0 * 97 | 9 9 1 6 5 7 2 * 98 | 0 * 99 | * 100 | 5 3 6 101 | -------------------------------------------------------------------------------- /examples/ex09/test_fstream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN test_fstream) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | add_executable(${MAIN}.exe ${MAIN}.cpp) 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/ex09/test_fstream/generate_random_data.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import random 4 | 5 | for i in range(90): 6 | print("09804{:03d}\t{:3d}\t{:3d}".format(i, random.randrange(50, 100), 7 | random.randrange(50, 100))) 8 | -------------------------------------------------------------------------------- /examples/ex09/test_fstream/raw_scores.txt: -------------------------------------------------------------------------------- 1 | 09804000 69 83 2 | 09804001 80 86 3 | 09804002 92 82 4 | 09804003 99 50 5 | 09804004 72 87 6 | 09804005 95 96 7 | 09804006 91 70 8 | 09804007 69 85 9 | 09804008 75 67 10 | 09804009 97 90 11 | 09804010 65 74 12 | 09804011 78 63 13 | 09804012 84 86 14 | 09804013 65 71 15 | 09804014 59 59 16 | 09804015 61 77 17 | 09804016 72 87 18 | 09804017 98 80 19 | 09804018 84 78 20 | 09804019 53 80 21 | 09804020 94 87 22 | 09804021 96 63 23 | 09804022 68 65 24 | 09804023 71 79 25 | 09804024 97 59 26 | 09804025 96 54 27 | 09804026 95 87 28 | 09804027 76 99 29 | 09804028 51 84 30 | 09804029 69 97 31 | 09804030 77 90 32 | 09804031 78 76 33 | 09804032 82 99 34 | 09804033 78 92 35 | 09804034 92 52 36 | 09804035 98 88 37 | 09804036 97 81 38 | 09804037 50 68 39 | 09804038 55 63 40 | 09804039 74 90 41 | 09804040 68 73 42 | 09804041 55 55 43 | 09804042 63 86 44 | 09804043 60 75 45 | 09804044 75 78 46 | 09804045 90 96 47 | 09804046 80 65 48 | 09804047 84 93 49 | 09804048 68 83 50 | 09804049 78 95 51 | 09804050 50 52 52 | 09804051 84 67 53 | 09804052 70 62 54 | 09804053 70 96 55 | 09804054 77 67 56 | 09804055 79 98 57 | 09804056 80 85 58 | 09804057 73 99 59 | 09804058 62 84 60 | 09804059 83 54 61 | 09804060 84 67 62 | 09804061 74 53 63 | 09804062 89 86 64 | 09804063 74 75 65 | 09804064 77 95 66 | 09804065 50 52 67 | 09804066 79 88 68 | 09804067 91 75 69 | 09804068 96 52 70 | 09804069 97 77 71 | 09804070 86 85 72 | 09804071 89 88 73 | 09804072 79 77 74 | 09804073 59 69 75 | 09804074 91 98 76 | 09804075 64 98 77 | 09804076 64 65 78 | 09804077 68 73 79 | 09804078 93 62 80 | 09804079 54 65 81 | 09804080 73 58 82 | 09804081 84 72 83 | 09804082 76 90 84 | 09804083 56 94 85 | 09804084 51 55 86 | 09804085 83 80 87 | 09804086 51 67 88 | 09804087 98 60 89 | 09804088 99 64 90 | 09804089 66 72 91 | -------------------------------------------------------------------------------- /examples/ex09/test_fstream/test_fstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cerr; 6 | using std::ifstream; 7 | using std::ofstream; 8 | using std::string; 9 | 10 | int main() 11 | { 12 | ifstream ifs { "raw_scores.txt" }; 13 | if (!ifs) { 14 | cerr << "cannot open file: raw_scores.txt for reading\n"; 15 | return 1; 16 | } 17 | ofstream ofs { "total_scores.txt" }; 18 | if (!ofs) { 19 | cerr << "cannot open file: final_scores.txt for writing\n"; 20 | return 2; 21 | } 22 | while (ifs) { 23 | string id; 24 | int mid_score; 25 | int final_score; 26 | ifs >> id >> mid_score >> final_score; 27 | if (ifs) { 28 | int total_score { int(round(mid_score * 0.4 + final_score * 0.6)) }; 29 | ofs << id << '\t' << total_score << '\n'; 30 | } 31 | } 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /examples/ex09/test_sstream/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | set(MAIN test_sstream) 3 | project(${MAIN}) 4 | 5 | set(CMAKE_CXX_STANDARD 14) 6 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 7 | 8 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 9 | 10 | add_executable(${MAIN}.exe ${MAIN}.cpp) 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/ex09/test_sstream/test_sstream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using std::cout; 6 | using std::string; 7 | 8 | double str_to_double(string s) 9 | { 10 | std::istringstream iss { s }; 11 | double d; 12 | iss >> d; 13 | if (!iss) 14 | throw std::runtime_error { "cannot convert to double: " + s }; 15 | return d; 16 | } 17 | 18 | int main() 19 | { 20 | std::ostringstream oss; 21 | oss << 3.14 << " " << 3.4 << " haha"; 22 | string s { oss.str() }; 23 | cout << s << '\n'; 24 | double d { str_to_double(s) }; 25 | cout << d << '\n'; 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /examples/ex10/animals/Animal.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Animal.h" 4 | 5 | using std::cout; 6 | 7 | void Animal::eat() 8 | { 9 | ++weight_; 10 | } 11 | 12 | void Cat::eat() 13 | { 14 | Animal::eat(); 15 | cout << name_ << " is eating cat food...\n"; 16 | } 17 | 18 | void Cat::talk() 19 | { 20 | cout << name_ << " says: meow~~~ meow~~~\n"; 21 | } 22 | 23 | void Dog::eat() 24 | { 25 | Animal::eat(); 26 | cout << name_ << " is eating dog food\n"; 27 | } 28 | 29 | void Dog::talk() 30 | { 31 | cout << name_ << " says: woof woof\n"; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /examples/ex10/animals/Animal.h: -------------------------------------------------------------------------------- 1 | #ifndef _ANIMAL_H 2 | #define _ANIMAL_H 3 | 4 | #include 5 | 6 | class Animal { 7 | public: 8 | virtual void eat(); 9 | virtual void talk() = 0; 10 | 11 | std::string name() const { return name_; } 12 | int weight() const { return weight_; } 13 | 14 | virtual ~Animal() {} 15 | 16 | protected: 17 | Animal(const std::string& name, int weight) 18 | : name_ { name } 19 | , weight_ { weight } 20 | { 21 | } 22 | 23 | protected: 24 | std::string name_; 25 | int weight_; 26 | }; 27 | 28 | class Cat : public Animal { 29 | public: 30 | void eat() override; 31 | void talk() override; 32 | 33 | Cat(const std::string& name, int weight) 34 | : Animal { name, weight } 35 | { 36 | } 37 | }; 38 | 39 | class Dog : public Animal { 40 | public: 41 | void eat() override; 42 | void talk() override; 43 | 44 | Dog(const std::string& name, int weight) 45 | : Animal { name, weight } 46 | { 47 | } 48 | }; 49 | 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /examples/ex10/animals/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(Animal) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Animal.h Animal.cpp) 10 | 11 | add_executable(test.exe test.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex10/animals/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Animal.h" 5 | 6 | using std::cout; 7 | using std::vector; 8 | 9 | int main() 10 | { 11 | Cat a { "Bob", 20 }; 12 | Dog b { "Bolt", 10 }; 13 | Cat c { "Tom", 40 }; 14 | Dog d { "Spike", 30 }; 15 | vector animals { &a, &b, &c, &d }; 16 | for (auto p : animals) { 17 | cout << "The weight of " << p->name() << " is " << p->weight() << '\n'; 18 | p->eat(); 19 | cout << "The weight of " << p->name() << " is now " << p->weight() << '\n'; 20 | p->talk(); 21 | cout << '\n'; 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(calc-4.0) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | find_package(FLTK REQUIRED) 10 | include_directories(${FLTK_INCLUDE_DIR}) 11 | link_directories(${FLTK_LIBRARY_DIR}) 12 | 13 | find_package(JPEG REQUIRED) 14 | find_package(PNG REQUIRED) 15 | 16 | add_subdirectory(Graph_lib) 17 | 18 | set(SOURCES calc-4.0.cpp Calculator.h Calculator.cpp 19 | Token.h Token_stream.h Token_stream.cpp Variable.h Variable.cpp) 20 | 21 | add_executable(calc-4.0.exe ${SOURCES} ${GRAPH_LIB}) 22 | target_link_libraries(calc-4.0.exe ${FLTK_LIBRARIES} 23 | ${JPEG_LIBRARIES} ${PNG_LIBRARIES}) 24 | 25 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Calculator.h: -------------------------------------------------------------------------------- 1 | #ifndef _CALCULATOR_H 2 | #define _CALCULATOR_H 3 | 4 | #include 5 | 6 | #include "Token_stream.h" 7 | #include "Variable.h" 8 | 9 | namespace Calc { 10 | 11 | class Calculator { 12 | public: 13 | explicit Calculator(std::istream& is = std::cin) 14 | : ts { is } 15 | { 16 | } 17 | 18 | void calculate(); 19 | 20 | double calculate1(); 21 | 22 | private: 23 | Token_stream ts; 24 | Var_table vt; 25 | 26 | void clean_up_mess(); 27 | 28 | double statement(); 29 | double declaration(); 30 | double expression(); 31 | double term(); 32 | double primary(); 33 | }; 34 | } 35 | 36 | #endif 37 | 38 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(GRAPH_LIB 2 | ${CMAKE_CURRENT_SOURCE_DIR}/fltk.h 3 | ${CMAKE_CURRENT_SOURCE_DIR}/Point.h 4 | ${CMAKE_CURRENT_SOURCE_DIR}/Vector_ref.h 5 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.h 7 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.h 9 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.cpp 10 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.h 11 | ${CMAKE_CURRENT_SOURCE_DIR}/Simple_window.h 12 | PARENT_SCOPE) 13 | 14 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef POINT_GUARD 2 | #define POINT_GUARD 3 | 4 | namespace Graph_lib { 5 | 6 | struct Point { 7 | int x, y; 8 | Point(int xx, int yy) 9 | : x { xx } 10 | , y { yy } 11 | { 12 | } 13 | }; 14 | 15 | inline bool operator==(Point a, Point b) { return a.x == b.x && a.y == b.y; } 16 | 17 | inline bool operator!=(Point a, Point b) { return !(a == b); } 18 | 19 | } // namespace Graph_lib 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/Simple_window.h: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "Point.h" 3 | #include "Window.h" 4 | 5 | // Simple_window is basic scaffolding for ultra-simple interaction with graphics 6 | // it provides one window with one "next" button for ultra-simple animation 7 | 8 | class Simple_window : public Graph_lib::Window { 9 | 10 | public: 11 | Simple_window(Graph_lib::Point xy, int w, int h, const std::string& title) 12 | : Graph_lib::Window { xy, w, h, title, false } 13 | , quit_button { Graph_lib::Point { x_max() - 70, 0 }, 70, 20, "Quit", cb_quit } 14 | , next_button { Graph_lib::Point { x_max() - 70, 20 }, 70, 20, "Next", cb_next } 15 | , next_pushed { false } 16 | { 17 | attach(quit_button); 18 | attach(next_button); 19 | } 20 | 21 | void wait_for_next() 22 | { 23 | while (!next_pushed && Fl::wait()) 24 | ; 25 | next_pushed = false; 26 | Fl::redraw(); 27 | } 28 | 29 | private: 30 | Graph_lib::Button quit_button; 31 | Graph_lib::Button next_button; 32 | 33 | bool next_pushed; 34 | 35 | // callback for quit_button 36 | static void cb_quit(void*, void* pw) 37 | { 38 | static_cast(pw)->quit(); 39 | } 40 | 41 | void quit() { hide(); } 42 | 43 | // callback for next_button 44 | static void cb_next(void*, void* pw) 45 | { 46 | static_cast(pw)->next(); 47 | } 48 | 49 | void next() { next_pushed = true; } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/Vector_ref.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_REF_GUARD 2 | #define VECTOR_REF_GUARD 3 | 4 | #include 5 | 6 | namespace Graph_lib { 7 | 8 | template 9 | class Vector_ref { 10 | public: 11 | Vector_ref() = default; 12 | explicit Vector_ref(T* t) 13 | { 14 | if (t) 15 | push_back(t); 16 | } 17 | ~Vector_ref() 18 | { 19 | for (auto p : owned) 20 | delete p; 21 | } 22 | 23 | void push_back(T& s) { v.push_back(&s); } 24 | void push_back(T* p) 25 | { 26 | v.push_back(p); 27 | owned.push_back(p); 28 | } 29 | 30 | T& operator[](int i) { return *v[i]; } 31 | const T& operator[](int i) const { return *v[i]; } 32 | size_t size() const { return v.size(); } 33 | 34 | private: 35 | std::vector v; 36 | std::vector owned; 37 | }; 38 | 39 | } // namespace Graph_lib 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/Window.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "GUI.h" 5 | #include "Graph.h" 6 | #include "Window.h" 7 | 8 | using std::string; 9 | 10 | namespace Graph_lib { 11 | 12 | Window::Window(int ww, int hh, const string& title, bool resizable) 13 | : Super { ww, hh, title.c_str() } 14 | , w { ww } 15 | , h { hh } 16 | { 17 | init(resizable); 18 | } 19 | 20 | Window::Window(Point xy, int ww, int hh, const string& title, bool resizable) 21 | : Super { xy.x, xy.y, ww, hh, title.c_str() } 22 | , w { ww } 23 | , h { hh } 24 | { 25 | init(resizable); 26 | } 27 | 28 | void Window::init(bool res) 29 | { 30 | if (res) 31 | resizable(this); 32 | Fl::visual(FL_DOUBLE | FL_INDEX); 33 | show(); 34 | } 35 | 36 | //---------------------------------------------------- 37 | 38 | void Window::resize(int ww, int hh) 39 | { 40 | w = ww; 41 | h = hh; 42 | size(ww, hh); 43 | } 44 | 45 | void Window::draw() 46 | { 47 | Super::draw(); 48 | for (auto shape : shapes) 49 | shape->draw(); 50 | } 51 | 52 | void Window::attach(Widget& w) 53 | { 54 | begin(); // FTLK: begin attaching new Fl_Widgets to this window 55 | w.attach(*this); // let the Widget create its Fl_Widget 56 | end(); // FTLK: stop attaching new Fl_Widgets to this window 57 | } 58 | 59 | void Window::detach(Widget& w) 60 | { 61 | w.hide(); 62 | } 63 | 64 | void Window::attach(const Shape& s) 65 | { 66 | // each shape should only be attached once 67 | detach(s); 68 | shapes.push_back(&s); 69 | } 70 | 71 | void Window::detach(const Shape& s) 72 | { 73 | auto it { std::find(shapes.begin(), shapes.end(), &s) }; 74 | if (it != shapes.end()) { 75 | shapes.erase(it); 76 | } 77 | } 78 | 79 | void Window::put_on_top(const Shape& s) 80 | { 81 | attach(s); 82 | } 83 | 84 | int gui_main() { return Fl::run(); } 85 | 86 | } // namespace Graph_lib 87 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/Window.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_GUARD 2 | #define WINDOW_GUARD 1 3 | 4 | #include 5 | #include 6 | 7 | #include "fltk.h" 8 | 9 | #include "Graph.h" 10 | #include "Point.h" 11 | 12 | using Graph_lib::Color; 13 | 14 | namespace Graph_lib { 15 | 16 | class Widget; 17 | 18 | class Window : public Fl_Double_Window { 19 | public: 20 | using Super = Fl_Double_Window; 21 | // let the system pick the location 22 | Window(int w, int h, const std::string& title, bool resizable = true); 23 | // top left corner in xy 24 | Window(Point xy, int w, int h, const std::string& title, bool resizable = true); 25 | 26 | ~Window() override = default; 27 | 28 | int x_max() const { return w; } 29 | int y_max() const { return h; } 30 | 31 | using Super::resize; // resize(int x, int y, int w, int h); 32 | 33 | void resize(int ww, int hh); 34 | 35 | void set_background_color(Color c) { color(static_cast(c)); } 36 | void set_label(const std::string& s) { label(s.c_str()); } 37 | 38 | void attach(Widget& w); // attach a widget 39 | void detach(Widget& w); // hide the widget (not really detached) 40 | 41 | void attach(const Shape& s); // add s to shapes 42 | void detach(const Shape& s); // remove s from shapes 43 | void put_on_top(const Shape& p); // put p on top of other shapes 44 | void detach_all_shapes() { shapes.clear(); } 45 | 46 | protected: 47 | void draw() override; 48 | 49 | private: 50 | std::vector shapes; // shapes attached to window 51 | int w, h; // window size 52 | 53 | void init(bool res); 54 | }; 55 | 56 | int gui_main(); // invoke GUI library's main event loop 57 | 58 | inline int x_max() { return Fl::w(); } // width of screen in pixels 59 | inline int y_max() { return Fl::h(); } // height of screen in pixels 60 | 61 | } // namespace Graph_lib 62 | #endif 63 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Graph_lib/fltk.h: -------------------------------------------------------------------------------- 1 | #ifndef FLTK_GUARD 2 | #define FLTK_GUARD 1 3 | 4 | #include "FL/Enumerations.H" 5 | #include "FL/Fl.H" 6 | #include "FL/Fl_Button.H" 7 | #include "FL/Fl_Double_Window.H" 8 | #include "FL/Fl_Input.H" 9 | #include "FL/Fl_Output.H" 10 | #include "FL/Fl_Window.H" 11 | #include "FL/fl_draw.H" 12 | 13 | #include "FL/Fl_BMP_Image.H" 14 | #include "FL/Fl_GIF_Image.H" 15 | #include "FL/Fl_JPEG_Image.H" 16 | #include "FL/Fl_PNG_Image.H" 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Token.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_H 2 | #define _TOKEN_H 3 | 4 | #include 5 | 6 | namespace Calc { 7 | 8 | class Token { 9 | public: 10 | char kind; 11 | double value; 12 | std::string name; 13 | 14 | Token() {} 15 | 16 | Token(char ch) 17 | : kind { ch } 18 | , value { 0 } 19 | { 20 | } 21 | 22 | Token(char ch, double val) 23 | : kind { ch } 24 | , value { val } 25 | { 26 | } 27 | 28 | Token(char ch, const std::string& n) 29 | : kind { ch } 30 | , value { 0 } 31 | , name { n } 32 | { 33 | } 34 | }; 35 | 36 | constexpr char number { '6' }; 37 | constexpr char quit { 'q' }; 38 | constexpr char print { ';' }; 39 | 40 | constexpr char name { 'a' }; 41 | constexpr char let { 'L' }; 42 | const std::string declkey { "let" }; 43 | 44 | } 45 | 46 | #endif 47 | 48 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Token_stream.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Token_stream.h" 5 | 6 | using std::runtime_error; 7 | using std::string; 8 | 9 | namespace Calc { 10 | 11 | void Token_stream::putback(Token t) 12 | { 13 | if (full) { 14 | throw runtime_error { "putback() into a full buffer" }; 15 | } 16 | buffer = t; 17 | full = true; 18 | } 19 | 20 | Token Token_stream::get() 21 | { 22 | if (full) { 23 | full = false; 24 | return buffer; 25 | } 26 | 27 | char ch { ' ' }; 28 | ist >> ch; 29 | 30 | if (!ist) 31 | return Token { quit }; 32 | 33 | switch (ch) { 34 | case print: 35 | case quit: 36 | case '(': 37 | case ')': 38 | case '+': 39 | case '-': 40 | case '*': 41 | case '/': 42 | case '%': 43 | case '=': 44 | return Token { ch }; 45 | case '.': 46 | case '0': 47 | case '1': 48 | case '2': 49 | case '3': 50 | case '4': 51 | case '5': 52 | case '6': 53 | case '7': 54 | case '8': 55 | case '9': { 56 | ist.putback(ch); 57 | double val { 0 }; 58 | ist >> val; 59 | if (!ist) { 60 | ist.clear(); 61 | throw runtime_error { "illegal floating point number" }; 62 | } 63 | return Token { number, val }; 64 | } 65 | default: 66 | if (isalpha(ch)) { 67 | string s { ch }; 68 | while (ist.get(ch) && (isalpha(ch) || isdigit(ch))) { 69 | s += ch; 70 | } 71 | ist.putback(ch); 72 | if (s == declkey) { 73 | return Token { let }; 74 | } 75 | return Token { name, s }; 76 | } 77 | throw runtime_error { "Bad token" }; 78 | } 79 | } 80 | 81 | void Token_stream::ignore(char c) 82 | // ignore the inputs until the character c 83 | { 84 | // look into the buffer first 85 | if (full && c == buffer.kind) { 86 | full = false; 87 | return; 88 | } 89 | 90 | full = false; // clear the buffer 91 | 92 | // search for the character c 93 | char ch { ' ' }; 94 | while (ist >> ch) { 95 | if (ch == c) 96 | return; 97 | } 98 | } 99 | 100 | } 101 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Token_stream.h: -------------------------------------------------------------------------------- 1 | #ifndef _TOKEN_STREAM_H 2 | #define _TOKEN_STREAM_H 3 | 4 | #include 5 | 6 | #include "Token.h" 7 | 8 | namespace Calc { 9 | 10 | class Token_stream { 11 | public: 12 | explicit Token_stream(std::istream& is) 13 | : ist { is } 14 | { 15 | } 16 | 17 | Token get(); 18 | void putback(Token t); 19 | void ignore(char c); 20 | 21 | explicit operator bool() const { return bool(ist); } 22 | 23 | private: 24 | std::istream& ist; 25 | bool full { false }; 26 | Token buffer; 27 | }; 28 | 29 | } 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Variable.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Variable.h" 6 | 7 | using std::map; 8 | using std::out_of_range; 9 | using std::runtime_error; 10 | using std::string; 11 | 12 | namespace Calc { 13 | 14 | double Var_table::get_value(const string& var) 15 | { 16 | try { 17 | return table.at(var); 18 | } catch (out_of_range&) { 19 | throw runtime_error { "get: undefined variable " + var }; 20 | } 21 | } 22 | 23 | void Var_table::set_value(const string& var, double val) 24 | { 25 | try { 26 | table.at(var) = val; 27 | } catch (out_of_range&) { 28 | throw runtime_error { "set: undefined variable " + var }; 29 | } 30 | } 31 | 32 | bool Var_table::is_declared(const string& var) 33 | { 34 | if (table.count(var) > 0) { 35 | return true; 36 | } else { 37 | return false; 38 | } 39 | } 40 | 41 | double Var_table::define_name(const string& var, double val) 42 | { 43 | if (is_declared(var)) { 44 | throw runtime_error { "variable " + var + " is already declared" }; 45 | } 46 | table[var] = val; 47 | return val; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/Variable.h: -------------------------------------------------------------------------------- 1 | #ifndef _VARIABLE_H 2 | #define _VARIABLE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace Calc { 8 | 9 | class Var_table { 10 | public: 11 | double get_value(const std::string&); 12 | void set_value(const std::string&, double); 13 | double define_name(const std::string&, double); 14 | 15 | private: 16 | std::map table; 17 | bool is_declared(const std::string&); 18 | }; 19 | } 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /examples/ex10/calc-4.0/calc-4.0.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Calculator.h" 5 | 6 | #include "Graph_lib/GUI.h" 7 | #include "Graph_lib/Graph.h" 8 | #include "Graph_lib/Window.h" 9 | 10 | using std::exception; 11 | using std::istringstream; 12 | using std::ostringstream; 13 | using std::string; 14 | 15 | using Graph_lib::Point; 16 | 17 | class My_window : public Graph_lib::Window { 18 | 19 | public: 20 | My_window(Point xy, int w, int h, const string& title); 21 | 22 | private: 23 | Graph_lib::Button quit_button; 24 | Graph_lib::Button calc_button; 25 | Graph_lib::In_box inbox; 26 | Graph_lib::Out_box outbox; 27 | istringstream iss; 28 | Calc::Calculator calc; 29 | 30 | // callback for quit_button 31 | static void cb_quit(void*, void* pw) 32 | { 33 | static_cast(pw)->quit(); 34 | } 35 | 36 | void quit() { hide(); } 37 | 38 | // callback for calc_button 39 | static void cb_calc(void*, void* pw) 40 | { 41 | static_cast(pw)->do_calc(); 42 | } 43 | 44 | void do_calc(); 45 | }; 46 | 47 | My_window::My_window(Point xy, int w, int h, const string& title) 48 | : Graph_lib::Window { xy, w, h, title } 49 | , quit_button { Point { x_max() - 70, 0 }, 70, 20, "Quit", cb_quit } 50 | , calc_button { Point { 255, 50 }, 80, 20, "Calculate", cb_calc } 51 | , inbox { Point { 50, 50 }, 200, 20, "" } 52 | , outbox { Point { 50, 100 }, 200, 20, "" } 53 | , calc { iss } 54 | { 55 | attach(quit_button); 56 | attach(calc_button); 57 | attach(inbox); 58 | attach(outbox); 59 | } 60 | 61 | void My_window::do_calc() 62 | { 63 | string s { inbox.get_string() }; 64 | iss.str(s + ";"); 65 | iss.clear(); 66 | try { 67 | ostringstream oss; 68 | oss << calc.calculate1(); 69 | outbox.put(oss.str()); 70 | } catch (exception& e) { 71 | outbox.put(e.what()); 72 | } 73 | } 74 | 75 | int main() 76 | { 77 | My_window win { Point { 100, 100 }, 600, 400, "Calculator" }; 78 | 79 | return Graph_lib::gui_main(); 80 | } 81 | -------------------------------------------------------------------------------- /examples/ex10/test_fltk/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(test_fltk) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | find_package(FLTK REQUIRED) 10 | include_directories(${FLTK_INCLUDE_DIR}) 11 | link_directories(${FLTK_LIBRARY_DIR}) 12 | 13 | add_executable(test_fltk.exe test_fltk.cpp) 14 | target_link_libraries(test_fltk.exe ${FLTK_LIBRARIES}) 15 | 16 | -------------------------------------------------------------------------------- /examples/ex10/test_fltk/test_fltk.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace std; 7 | 8 | struct myWindow : Fl_Window 9 | { 10 | myWindow(int w, int h, const string& title) 11 | : Fl_Window(w, h, title.c_str()) 12 | { 13 | color(FL_WHITE); 14 | resizable(this); 15 | show(); 16 | } 17 | 18 | void draw() override { 19 | Fl_Window::draw(); 20 | 21 | fl_color(FL_BLUE); 22 | 23 | fl_line_style(FL_SOLID, 5); 24 | fl_line(100, 100, 200, 200); 25 | fl_rectf(100, 300, 100, 100); 26 | 27 | fl_font(FL_HELVETICA, 24); 28 | fl_draw("I don't know what to say", 300, 500); 29 | } 30 | 31 | }; 32 | 33 | int main (int argc, char** argv) 34 | { 35 | myWindow win {800, 600, "What?"}; 36 | return Fl::run(); 37 | } 38 | -------------------------------------------------------------------------------- /examples/ex10/test_wx/makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -g -std=c++11 $(shell wx-config --cxxflags) 3 | LDFLAGS = $(shell wx-config --libs) 4 | 5 | test_wx.exe: test_wx.cpp 6 | $(CXX) $(CXXFLAGS) -o $@ $< $(LDFLAGS) 7 | 8 | clean: 9 | rm -rf *.exe *.o *.dSYM 10 | 11 | -------------------------------------------------------------------------------- /examples/ex10/test_wx/test_wx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | class BasicDrawPane : public wxPanel { 5 | public: 6 | explicit BasicDrawPane(wxFrame* parent); 7 | 8 | void paintEvent(wxPaintEvent& evt); 9 | 10 | DECLARE_EVENT_TABLE() 11 | }; 12 | 13 | class MyApp : public wxApp { 14 | public: 15 | MyApp() 16 | : frame { nullptr } 17 | , drawPane { nullptr } 18 | { 19 | } 20 | 21 | private: 22 | bool OnInit(); 23 | 24 | wxFrame* frame; 25 | BasicDrawPane* drawPane; 26 | }; 27 | 28 | IMPLEMENT_APP(MyApp) 29 | 30 | bool MyApp::OnInit() 31 | { 32 | wxBoxSizer* sizer { new wxBoxSizer { wxHORIZONTAL } }; 33 | frame = new wxFrame { nullptr, -1, wxT("我是谁?我从哪里来?我要去哪里?"), 34 | wxPoint { 400, 300 }, wxSize { 800, 600 } }; 35 | 36 | drawPane = new BasicDrawPane { frame }; 37 | sizer->Add(drawPane, 1, wxEXPAND); 38 | 39 | frame->SetSizer(sizer); 40 | frame->SetAutoLayout(true); 41 | 42 | frame->Show(); 43 | return true; 44 | } 45 | 46 | BEGIN_EVENT_TABLE(BasicDrawPane, wxPanel) 47 | EVT_PAINT(BasicDrawPane::paintEvent) 48 | END_EVENT_TABLE() 49 | 50 | BasicDrawPane::BasicDrawPane(wxFrame* parent) 51 | : wxPanel { parent } 52 | { 53 | } 54 | 55 | void BasicDrawPane::paintEvent(wxPaintEvent& evt) 56 | { 57 | wxPaintDC dc { this }; 58 | 59 | // draw some text 60 | wxFont font; 61 | font.SetNativeFontInfoUserDesc("Sans 14"); 62 | dc.SetFont(font); 63 | dc.DrawText(wxT("红圆圈,蓝方块,黑线条"), 100, 400); 64 | 65 | // draw a circle 66 | dc.SetBrush(*wxRED_BRUSH); // green filling 67 | dc.SetPen(wxPen { wxColor { 255, 0, 0 }, 1 }); // 5-pixels-thick red outline 68 | dc.DrawCircle(wxPoint { 200, 100 }, 50 /* radius */); 69 | 70 | // draw a rectangle 71 | dc.SetBrush(*wxBLUE_BRUSH); // blue filling 72 | dc.SetPen(wxPen { wxColor { 0, 0, 255 }, 1 }); // 10-pixels-thick pink outline 73 | dc.DrawRectangle(300, 100, 200, 200); 74 | 75 | // draw a line 76 | dc.SetPen(wxPen { wxColor { 0, 0, 0 }, 3 }); // black line, 3 pixels thick 77 | dc.DrawLine(500, 500, 700, 300); // draw line across the rectangle 78 | } 79 | 80 | -------------------------------------------------------------------------------- /examples/ex11/List/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(list) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES List.h List.cpp) 10 | 11 | add_executable(test_list.exe test_list.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex11/List/List.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | 5 | List::List(std::initializer_list lst) 6 | : head { nullptr } 7 | , tail { nullptr } 8 | { 9 | for (auto x : lst) { 10 | push_back(x); 11 | } 12 | } 13 | 14 | List::~List() 15 | { 16 | while (head) { 17 | erase(head); 18 | } 19 | } 20 | 21 | Link* List::insert(Link* l, double val) 22 | { 23 | Link* p = new Link { val, nullptr, l }; 24 | if (l == nullptr) { // insert after the tail 25 | p->prev = tail; 26 | if (tail) { 27 | tail->succ = p; 28 | } else { 29 | head = p; // was empty List 30 | } 31 | tail = p; 32 | return p; 33 | } 34 | // normal insertion 35 | p->prev = l->prev; 36 | l->prev = p; 37 | if (p->prev) { 38 | p->prev->succ = p; 39 | } else { 40 | head = p; // l was head 41 | } 42 | return p; 43 | } 44 | 45 | Link* List::erase(Link* l) 46 | { 47 | if (l == nullptr) 48 | return l; 49 | if (l->succ) { 50 | l->succ->prev = l->prev; 51 | } else { 52 | tail = l->prev; // l was tail 53 | } 54 | if (l->prev) { 55 | l->prev->succ = l->succ; 56 | } else { 57 | head = l->succ; // l was head 58 | } 59 | Link* p = l->succ; 60 | delete l; 61 | return p; 62 | } 63 | 64 | void List::push_back(double val) 65 | { 66 | insert(end(), val); 67 | } 68 | 69 | void List::push_front(double val) 70 | { 71 | insert(begin(), val); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /examples/ex11/List/List.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H 2 | #define _LIST_H 3 | 4 | #include 5 | 6 | struct Link { 7 | double val; 8 | Link* prev; 9 | Link* succ; 10 | }; 11 | 12 | class List { 13 | public: 14 | List() 15 | : head { nullptr } 16 | , tail { nullptr } 17 | { 18 | } 19 | List(std::initializer_list lst); 20 | ~List(); 21 | 22 | Link* begin() const { return head; } 23 | Link* end() const { return nullptr; } 24 | 25 | Link* insert(Link* l, double val); 26 | Link* erase(Link* l); 27 | void push_back(double val); 28 | void push_front(double val); 29 | 30 | List(const List&) = delete; 31 | List& operator=(const List&) = delete; 32 | List(List&&) = delete; 33 | List& operator=(List&&) = delete; 34 | 35 | private: 36 | Link* head; 37 | Link* tail; 38 | }; 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /examples/ex11/List/test_list.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | 5 | using std::cout; 6 | 7 | void print_list(const List& l) 8 | { 9 | for (Link* p = l.begin(); p != l.end(); p = p->succ) { 10 | cout << p->val << '\n'; 11 | } 12 | cout << '\n'; 13 | } 14 | 15 | int main() 16 | { 17 | List l1 { 10, 11, 12 }; 18 | print_list(l1); 19 | 20 | l1.push_back(13); 21 | l1.push_front(8); 22 | l1.insert(l1.begin()->succ, 9); 23 | print_list(l1); 24 | 25 | l1.erase(l1.begin()->succ->succ); 26 | print_list(l1); 27 | } 28 | 29 | -------------------------------------------------------------------------------- /examples/ex11/Vector/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(vector) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Vector.h Vector.cpp) 10 | 11 | add_executable(test_vector.exe test_vector.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex11/Vector/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Vector.h" 5 | 6 | Vector::Vector() 7 | : sz { 0 } 8 | , elem { nullptr } 9 | { 10 | } 11 | 12 | Vector::Vector(size_t s, double d) 13 | : sz { s } 14 | , elem { sz > 0 ? new double[sz] : nullptr } 15 | { 16 | for (size_t i = 0; i < sz; ++i) 17 | elem[i] = d; 18 | } 19 | 20 | Vector::Vector(std::initializer_list lst) 21 | : sz { lst.size() } 22 | , elem { sz > 0 ? new double[sz] : nullptr } 23 | { 24 | std::copy(lst.begin(), lst.end(), elem); 25 | } 26 | 27 | Vector::Vector(const Vector& v) 28 | : sz { v.sz } 29 | , elem { sz > 0 ? new double[sz] : nullptr } 30 | { 31 | std::cout << "copy constructor\n"; 32 | std::copy(v.elem, v.elem + sz, elem); 33 | } 34 | 35 | Vector& Vector::operator=(const Vector& v) 36 | { 37 | std::cout << "copy assignment\n"; 38 | if (this == &v) 39 | return *this; 40 | double* p { nullptr }; 41 | if (v.sz > 0) { 42 | p = new double[v.sz]; 43 | std::copy(v.elem, v.elem + v.sz, p); 44 | } 45 | delete[] elem; 46 | elem = p; 47 | sz = v.sz; 48 | return *this; 49 | } 50 | 51 | Vector::Vector(Vector&& v) noexcept 52 | : sz { v.sz } 53 | , elem { v.elem } 54 | { 55 | std::cout << "move constructor\n"; 56 | v.sz = 0; 57 | v.elem = nullptr; 58 | } 59 | 60 | Vector& Vector::operator=(Vector&& v) noexcept 61 | { 62 | std::cout << "move assignment\n"; 63 | if (this == &v) 64 | return *this; 65 | delete[] elem; 66 | sz = v.sz; 67 | elem = v.elem; 68 | v.sz = 0; 69 | v.elem = nullptr; 70 | return *this; 71 | } 72 | -------------------------------------------------------------------------------- /examples/ex11/Vector/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOR_H 2 | #define _VECTOR_H 3 | 4 | #include 5 | 6 | class Vector { 7 | public: 8 | Vector(); 9 | explicit Vector(std::size_t s, double d = 0.0); 10 | Vector(std::initializer_list lst); 11 | 12 | ~Vector() 13 | { 14 | delete[] elem; 15 | } 16 | 17 | std::size_t size() const { return sz; } 18 | double* data() { return elem; } 19 | const double* data() const { return elem; } 20 | 21 | double& operator[](std::size_t i) { return elem[i]; } 22 | double operator[](std::size_t i) const { return elem[i]; } 23 | 24 | Vector(const Vector& v); 25 | Vector& operator=(const Vector& v); 26 | 27 | Vector(Vector&& v) noexcept; 28 | Vector& operator=(Vector&& v) noexcept; 29 | 30 | private: 31 | std::size_t sz; 32 | double* elem; 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /examples/ex11/Vector/test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Vector.h" 6 | 7 | using std::cin; 8 | using std::cout; 9 | using std::string; 10 | 11 | Vector f1(); 12 | Vector f2(int); 13 | 14 | void info_vector(const Vector&, const string&); 15 | 16 | int main() 17 | { 18 | cout << "//////// test default contructor\n"; 19 | Vector v1; 20 | info_vector(v1, "v1"); 21 | 22 | cout << "//////// test (int, double) contructor\n"; 23 | Vector v2(3, 3.14); 24 | info_vector(v2, "v2"); 25 | 26 | cout << "//////// test (initializer_list) contructor\n"; 27 | Vector v3 { 1, 1, 2, 3, 5, 8 }; 28 | info_vector(v3, "v3"); 29 | 30 | cout << "//////// test copy contructor v4{v3}\n"; 31 | Vector v4 { v3 }; 32 | info_vector(v4, "v4"); 33 | 34 | cout << "//////// test copy assignment v1=v3\n"; 35 | v1 = v3; 36 | info_vector(v1, "v1"); 37 | 38 | cout << "//////// test move constructor v5{std::move(v1)}\n"; 39 | Vector v5 { std::move(v1) }; 40 | info_vector(v1, "v1"); 41 | info_vector(v5, "v5"); 42 | 43 | cout << "//////// test move assignment v4=std::move(v5)\n"; 44 | v4 = std::move(v5); 45 | info_vector(v4, "v4"); 46 | info_vector(v5, "v5"); 47 | 48 | cout << "//////// test return-by-move\n"; 49 | cout << "Please input an integer: "; 50 | int n; 51 | cin >> n; 52 | Vector v6 { f2(n) }; 53 | info_vector(v6, "v6"); 54 | } 55 | 56 | Vector f1() 57 | { 58 | std::random_device rd; 59 | std::default_random_engine ran(rd()); 60 | std::uniform_real_distribution ud(0.0, 1.0); 61 | 62 | Vector v(3, ud(ran)); 63 | 64 | return v; 65 | } 66 | 67 | Vector f2(int n) 68 | { 69 | Vector v1_in_f2 { f1() }; 70 | Vector v2_in_f2 { f1() }; 71 | if (n > 0) { 72 | info_vector(v1_in_f2, "v1_in_f2"); 73 | return v1_in_f2; 74 | } else { 75 | info_vector(v2_in_f2, "v2_in_f2"); 76 | return v2_in_f2; 77 | } 78 | } 79 | 80 | void info_vector(const Vector& v, const string& n) 81 | { 82 | cout << n << ".size() = " << v.size() << '\n'; 83 | cout << n << ".data() = " << v.data() << '\n'; 84 | if (v.size() > 0) { 85 | cout << n << " = {"; 86 | for (size_t i = 0; i < v.size(); ++i) { 87 | cout << v[i]; 88 | if (i != v.size() - 1) 89 | cout << ", "; 90 | else 91 | cout << "}\n"; 92 | } 93 | } 94 | cout << '\n'; 95 | } 96 | -------------------------------------------------------------------------------- /examples/ex11/Vector_RAII/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(vector) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Vector.h Vector.cpp) 10 | 11 | add_executable(test_vector.exe test_vector.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex11/Vector_RAII/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOR_H 2 | #define _VECTOR_H 3 | 4 | #include 5 | #include 6 | 7 | class Vector_base { 8 | public: 9 | explicit Vector_base(std::size_t sp); 10 | 11 | Vector_base(const Vector_base&) = delete; 12 | Vector_base& operator=(const Vector_base&) = delete; 13 | 14 | Vector_base(Vector_base&& v) noexcept; 15 | Vector_base& operator=(Vector_base&& v) noexcept; 16 | 17 | ~Vector_base() 18 | { 19 | delete[] elem; 20 | } 21 | 22 | double* elem; 23 | std::size_t space; 24 | }; 25 | 26 | class Vector : private Vector_base { 27 | public: 28 | Vector(); 29 | explicit Vector(std::size_t s, double d = 0.0); 30 | Vector(std::initializer_list lst); 31 | 32 | std::size_t size() const { return sz; } 33 | double* data() { return elem; } 34 | const double* data() const { return elem; } 35 | 36 | double& operator[](std::size_t i) { return elem[i]; } 37 | double operator[](std::size_t i) const { return elem[i]; } 38 | 39 | Vector(const Vector& v); 40 | Vector& operator=(const Vector& v); 41 | 42 | Vector(Vector&& v) noexcept; 43 | Vector& operator=(Vector&& v) noexcept; 44 | 45 | void reserve(std::size_t newalloc); 46 | std::size_t capacity() const { return space; } 47 | void resize(std::size_t newsize, double d = 0.0); 48 | void push_back(double d); 49 | 50 | private: 51 | std::size_t sz; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /examples/ex11/Vector_RAII/test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Vector.h" 6 | 7 | using std::cin; 8 | using std::cout; 9 | using std::string; 10 | 11 | void info_vector(const Vector&, const string&); 12 | 13 | int main() 14 | { 15 | std::random_device rd; 16 | std::default_random_engine ran(rd()); 17 | std::uniform_real_distribution ud(0.0, 1.0); 18 | 19 | cout << "//////// test push_back\n"; 20 | Vector v1; 21 | for (int i = 0; i < 2; ++i) { 22 | v1.push_back(ud(ran)); 23 | } 24 | info_vector(v1, "v1"); 25 | 26 | cout << "//////// test resize\n"; 27 | v1.resize(5, ud(ran)); 28 | info_vector(v1, "v1"); 29 | 30 | cout << "//////// test initializer_list\n"; 31 | Vector v2 { ud(ran), ud(ran), ud(ran) }; 32 | info_vector(v2, "v2"); 33 | 34 | cout << "//////// copy assignment v2=v1\n"; 35 | v2 = v1; 36 | info_vector(v1, "v1"); 37 | info_vector(v2, "v2"); 38 | 39 | cout << "//////// move assignment v2=std::move(v1)\n"; 40 | v2 = std::move(v1); 41 | info_vector(v1, "v1"); 42 | info_vector(v2, "v2"); 43 | } 44 | 45 | void info_vector(const Vector& v, const std::string& n) 46 | { 47 | std::cout << n << ".size() = " << v.size() << '\n'; 48 | std::cout << n << ".data() = " << v.data() << '\n'; 49 | std::cout << n << ".capacity() = " << v.capacity() << '\n'; 50 | if (v.size() > 0) { 51 | cout << n << " = {"; 52 | for (size_t i = 0; i < v.size(); ++i) { 53 | cout << v[i]; 54 | if (i != v.size() - 1) 55 | cout << ", "; 56 | else 57 | cout << "}\n"; 58 | } 59 | } 60 | cout << '\n'; 61 | } 62 | -------------------------------------------------------------------------------- /examples/ex11/Vector_better/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(vector) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Vector.h Vector.cpp) 10 | 11 | add_executable(test_vector.exe test_vector.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex11/Vector_better/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Vector.h" 5 | 6 | Vector::Vector() 7 | : sz { 0 } 8 | , elem { nullptr } 9 | , space { 0 } 10 | { 11 | } 12 | 13 | Vector::Vector(size_t s, double d) 14 | : sz { s } 15 | , elem { sz > 0 ? new double[sz] : nullptr } 16 | , space { sz } 17 | { 18 | for (size_t i = 0; i < sz; ++i) 19 | elem[i] = d; 20 | } 21 | 22 | Vector::Vector(std::initializer_list lst) 23 | : sz { lst.size() } 24 | , elem { sz > 0 ? new double[sz] : nullptr } 25 | , space { sz } 26 | { 27 | std::copy(lst.begin(), lst.end(), elem); 28 | } 29 | 30 | Vector::Vector(const Vector& v) 31 | : sz { v.sz } 32 | , elem { sz > 0 ? new double[sz] : nullptr } 33 | , space { sz } 34 | { 35 | std::copy(v.elem, v.elem + sz, elem); 36 | } 37 | 38 | Vector& Vector::operator=(const Vector& v) 39 | { 40 | if (this == &v) 41 | return *this; 42 | 43 | if (v.sz > space) 44 | reserve(v.sz); 45 | 46 | std::copy(v.elem, v.elem + v.sz, elem); 47 | sz = v.sz; 48 | return *this; 49 | } 50 | 51 | Vector::Vector(Vector&& v) noexcept 52 | : sz { v.sz } 53 | , elem { v.elem } 54 | , space { v.space } 55 | { 56 | v.sz = 0; 57 | v.elem = nullptr; 58 | v.space = 0; 59 | } 60 | 61 | Vector& Vector::operator=(Vector&& v) noexcept 62 | { 63 | if (this == &v) 64 | return *this; 65 | 66 | delete[] elem; 67 | sz = v.sz; 68 | elem = v.elem; 69 | space = v.space; 70 | 71 | v.sz = 0; 72 | v.elem = nullptr; 73 | v.space = 0; 74 | 75 | return *this; 76 | } 77 | 78 | void Vector::reserve(size_t newalloc) 79 | { 80 | if (newalloc <= space) 81 | return; 82 | double* p { new double[newalloc] }; 83 | for (size_t i = 0; i < sz; ++i) 84 | p[i] = elem[i]; 85 | delete[] elem; 86 | elem = p; 87 | space = newalloc; 88 | } 89 | 90 | void Vector::resize(size_t newsize, double d) 91 | { 92 | reserve(newsize); 93 | for (size_t i = sz; i < newsize; ++i) 94 | elem[i] = d; 95 | sz = newsize; 96 | } 97 | 98 | void Vector::push_back(double d) 99 | { 100 | if (space == 0) 101 | reserve(8); 102 | else if (sz == space) 103 | reserve(2 * space); 104 | elem[sz] = d; 105 | ++sz; 106 | } 107 | -------------------------------------------------------------------------------- /examples/ex11/Vector_better/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOR_H 2 | #define _VECTOR_H 3 | 4 | #include 5 | #include 6 | 7 | class Vector { 8 | public: 9 | Vector(); 10 | explicit Vector(std::size_t s, double d = 0.0); 11 | Vector(std::initializer_list lst); 12 | 13 | ~Vector() 14 | { 15 | delete[] elem; 16 | } 17 | 18 | std::size_t size() const { return sz; } 19 | double* data() { return elem; } 20 | const double* data() const { return elem; } 21 | 22 | double& operator[](std::size_t i) { return elem[i]; } 23 | double operator[](std::size_t i) const { return elem[i]; } 24 | 25 | Vector(const Vector& v); 26 | Vector& operator=(const Vector& v); 27 | 28 | Vector(Vector&& v) noexcept; 29 | Vector& operator=(Vector&& v) noexcept; 30 | 31 | void reserve(std::size_t newalloc); 32 | std::size_t capacity() const { return space; } 33 | void resize(std::size_t newsize, double d = 0.0); 34 | void push_back(double d); 35 | 36 | private: 37 | std::size_t sz; 38 | double* elem; 39 | std::size_t space; 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /examples/ex11/Vector_better/test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "Vector.h" 6 | 7 | using std::cin; 8 | using std::cout; 9 | using std::string; 10 | 11 | void info_vector(const Vector&, const string&); 12 | 13 | int main() 14 | { 15 | std::random_device rd; 16 | std::default_random_engine ran(rd()); 17 | std::uniform_real_distribution ud(0.0, 1.0); 18 | 19 | cout << "//////// test push_back\n"; 20 | Vector v1; 21 | for (int i = 0; i < 2; ++i) { 22 | v1.push_back(ud(ran)); 23 | } 24 | info_vector(v1, "v1"); 25 | 26 | cout << "//////// test resize\n"; 27 | v1.resize(5, ud(ran)); 28 | info_vector(v1, "v1"); 29 | 30 | cout << "//////// test initializer_list\n"; 31 | Vector v2 { ud(ran), ud(ran), ud(ran) }; 32 | info_vector(v2, "v2"); 33 | 34 | cout << "//////// copy assignment v2=v1\n"; 35 | v2 = v1; 36 | info_vector(v1, "v1"); 37 | info_vector(v2, "v2"); 38 | 39 | cout << "//////// move assignment v2=std::move(v1)\n"; 40 | v2 = std::move(v1); 41 | info_vector(v1, "v1"); 42 | info_vector(v2, "v2"); 43 | } 44 | 45 | void info_vector(const Vector& v, const std::string& n) 46 | { 47 | std::cout << n << ".size() = " << v.size() << '\n'; 48 | std::cout << n << ".data() = " << v.data() << '\n'; 49 | std::cout << n << ".capacity() = " << v.capacity() << '\n'; 50 | if (v.size() > 0) { 51 | cout << n << " = {"; 52 | for (size_t i = 0; i < v.size(); ++i) { 53 | cout << v[i]; 54 | if (i != v.size() - 1) 55 | cout << ", "; 56 | else 57 | cout << "}\n"; 58 | } 59 | } 60 | cout << '\n'; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(iterator) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Vector.h Vector.cpp List.h List.cpp) 10 | 11 | add_executable(test_iterator.exe test_iterator.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/List.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | 5 | List::List(std::initializer_list lst) 6 | : head { nullptr } 7 | , tail { nullptr } 8 | { 9 | for (auto x : lst) { 10 | push_back(x); 11 | } 12 | } 13 | 14 | List::~List() 15 | { 16 | while (begin() != end()) { 17 | erase(begin()); 18 | } 19 | } 20 | 21 | List::iterator List::begin() 22 | { 23 | return iterator { head }; 24 | } 25 | 26 | List::iterator List::end() 27 | { 28 | return iterator { nullptr }; 29 | } 30 | 31 | List::iterator List::begin() const 32 | { 33 | return iterator { head }; 34 | } 35 | 36 | List::iterator List::end() const 37 | { 38 | return iterator { nullptr }; 39 | } 40 | 41 | List::iterator List::insert(List::iterator it, double val) 42 | { 43 | Link* l { it.curr }; 44 | Link* p { new Link { val, nullptr, l } }; 45 | if (it == end()) { // insert after the tail 46 | p->prev = tail; 47 | if (tail) { 48 | tail->succ = p; 49 | } else { 50 | head = p; // was empty List 51 | } 52 | tail = p; 53 | return iterator { p }; 54 | } 55 | // normal insertion 56 | p->prev = l->prev; 57 | l->prev = p; 58 | if (p->prev) { 59 | p->prev->succ = p; 60 | } else { 61 | head = p; // l was head 62 | } 63 | return iterator { p }; 64 | } 65 | 66 | List::iterator List::erase(List::iterator it) 67 | { 68 | if (it == end()) 69 | return it; 70 | Link* l { it.curr }; 71 | if (l->succ) { 72 | l->succ->prev = l->prev; 73 | } else { 74 | tail = l->prev; // l was tail 75 | } 76 | if (l->prev) { 77 | l->prev->succ = l->succ; 78 | } else { 79 | head = l->succ; // l was head 80 | } 81 | Link* p { l->succ }; 82 | delete l; 83 | return iterator { p }; 84 | } 85 | 86 | void List::push_back(double val) 87 | { 88 | insert(end(), val); 89 | } 90 | 91 | void List::push_front(double val) 92 | { 93 | insert(begin(), val); 94 | } 95 | 96 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/List.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H 2 | #define _LIST_H 3 | 4 | #include 5 | 6 | struct Link { 7 | double val; 8 | Link* prev; 9 | Link* succ; 10 | }; 11 | 12 | class List { 13 | public: 14 | class iterator; 15 | 16 | List() 17 | : head { nullptr } 18 | , tail { nullptr } 19 | { 20 | } 21 | List(std::initializer_list lst); 22 | ~List(); 23 | 24 | iterator begin(); 25 | iterator end(); 26 | iterator begin() const; 27 | iterator end() const; 28 | 29 | iterator insert(iterator it, double val); 30 | iterator erase(iterator it); 31 | void push_back(double val); 32 | void push_front(double val); 33 | 34 | List(const List&) = delete; 35 | List& operator=(const List&) = delete; 36 | List(List&&) = delete; 37 | List& operator=(List&&) = delete; 38 | 39 | private: 40 | Link* head; 41 | Link* tail; 42 | }; 43 | 44 | class List::iterator { 45 | public: 46 | friend class List; // allow List to access curr 47 | 48 | explicit iterator(Link* p) 49 | : curr { p } 50 | { 51 | } 52 | 53 | iterator& operator++() 54 | { 55 | curr = curr->succ; 56 | return *this; 57 | } 58 | 59 | double& operator*() { return curr->val; } 60 | 61 | bool operator==(const iterator& it) const { return curr == it.curr; } 62 | bool operator!=(const iterator& it) const { return curr != it.curr; } 63 | 64 | private: 65 | Link* curr; 66 | }; 67 | 68 | #endif 69 | 70 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Vector.h" 5 | 6 | Vector::Vector() 7 | : sz { 0 } 8 | , elem { nullptr } 9 | { 10 | } 11 | 12 | Vector::Vector(size_t s, double d) 13 | : sz { s } 14 | , elem { sz > 0 ? new double[sz] : nullptr } 15 | { 16 | for (size_t i = 0; i < sz; ++i) 17 | elem[i] = d; 18 | } 19 | 20 | Vector::Vector(std::initializer_list lst) 21 | : sz { lst.size() } 22 | , elem { sz > 0 ? new double[sz] : nullptr } 23 | { 24 | std::copy(lst.begin(), lst.end(), elem); 25 | } 26 | 27 | Vector::Vector(const Vector& v) 28 | : sz { v.sz } 29 | , elem { sz > 0 ? new double[sz] : nullptr } 30 | { 31 | std::cout << "copy constructor\n"; 32 | std::copy(v.elem, v.elem + sz, elem); 33 | } 34 | 35 | Vector& Vector::operator=(const Vector& v) 36 | { 37 | std::cout << "copy assignment\n"; 38 | if (this == &v) 39 | return *this; 40 | double* p { nullptr }; 41 | if (v.sz > 0) { 42 | p = new double[v.sz]; 43 | std::copy(v.elem, v.elem + v.sz, p); 44 | } 45 | delete[] elem; 46 | elem = p; 47 | sz = v.sz; 48 | return *this; 49 | } 50 | 51 | Vector::Vector(Vector&& v) noexcept 52 | : sz { v.sz } 53 | , elem { v.elem } 54 | { 55 | std::cout << "move constructor\n"; 56 | v.sz = 0; 57 | v.elem = nullptr; 58 | } 59 | 60 | Vector& Vector::operator=(Vector&& v) noexcept 61 | { 62 | std::cout << "move assignment\n"; 63 | if (this == &v) 64 | return *this; 65 | delete[] elem; 66 | sz = v.sz; 67 | elem = v.elem; 68 | v.sz = 0; 69 | v.elem = nullptr; 70 | return *this; 71 | } 72 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOR_H 2 | #define _VECTOR_H 3 | 4 | #include 5 | 6 | class Vector { 7 | public: 8 | using iterator = double*; 9 | 10 | Vector(); 11 | explicit Vector(std::size_t s, double d = 0.0); 12 | Vector(std::initializer_list lst); 13 | 14 | ~Vector() 15 | { 16 | delete[] elem; 17 | } 18 | 19 | std::size_t size() const { return sz; } 20 | double* data() { return elem; } 21 | const double* data() const { return elem; } 22 | 23 | double& operator[](std::size_t i) { return elem[i]; } 24 | double operator[](std::size_t i) const { return elem[i]; } 25 | 26 | iterator begin() { return elem; } 27 | iterator end() { return elem + sz; } 28 | 29 | Vector(const Vector& v); 30 | Vector& operator=(const Vector& v); 31 | 32 | Vector(Vector&& v) noexcept; 33 | Vector& operator=(Vector&& v) noexcept; 34 | 35 | private: 36 | std::size_t sz; 37 | double* elem; 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /examples/ex12/Iterator/test_iterator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | #include "Vector.h" 5 | 6 | using std::cout; 7 | 8 | template 9 | Iter high(Iter b, Iter e) 10 | { 11 | Iter high { b }; 12 | for (auto p = b; p != e; ++p) { 13 | if (*p > *high) 14 | high = p; 15 | } 16 | return high; 17 | } 18 | 19 | int main() 20 | { 21 | double a[5] { 2.3, 4.5, 8.9, 0.6, 7.4 }; 22 | auto ha { high(a, a + 5) }; 23 | if (ha) 24 | cout << *ha << '\n'; 25 | 26 | Vector b { 2.3, 4.5, 8.9, 0.6, 7.4 }; 27 | auto hb { high(b.begin(), b.end()) }; 28 | cout << *hb << '\n'; 29 | 30 | List c { 12.3, 14.5, 18.9, 10.6, 17.4 }; 31 | auto hc { high(c.begin(), c.end()) }; 32 | cout << *hc << '\n'; 33 | 34 | cout << '\n'; 35 | 36 | for (auto x : b) 37 | cout << x << ' '; 38 | cout << '\n'; 39 | 40 | for (auto x : c) 41 | cout << x << ' '; 42 | cout << '\n'; 43 | } 44 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(pointer) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | set(SOURCES Vector.h Vector.cpp List.h List.cpp) 10 | 11 | add_executable(test_pointer.exe test_pointer.cpp ${SOURCES}) 12 | 13 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/List.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | 5 | List::List(std::initializer_list lst) 6 | : head { nullptr } 7 | , tail { nullptr } 8 | { 9 | for (auto x : lst) { 10 | push_back(x); 11 | } 12 | } 13 | 14 | List::~List() 15 | { 16 | while (head) { 17 | erase(head); 18 | } 19 | } 20 | 21 | Link* List::insert(Link* l, double val) 22 | { 23 | Link* p = new Link { val, nullptr, l }; 24 | if (l == nullptr) { // insert after the tail 25 | p->prev = tail; 26 | if (tail) { 27 | tail->succ = p; 28 | } else { 29 | head = p; // was empty List 30 | } 31 | tail = p; 32 | return p; 33 | } 34 | // normal insertion 35 | p->prev = l->prev; 36 | l->prev = p; 37 | if (p->prev) { 38 | p->prev->succ = p; 39 | } else { 40 | head = p; // l was head 41 | } 42 | return p; 43 | } 44 | 45 | Link* List::erase(Link* l) 46 | { 47 | if (l == nullptr) 48 | return l; 49 | if (l->succ) { 50 | l->succ->prev = l->prev; 51 | } else { 52 | tail = l->prev; // l was tail 53 | } 54 | if (l->prev) { 55 | l->prev->succ = l->succ; 56 | } else { 57 | head = l->succ; // l was head 58 | } 59 | Link* p = l->succ; 60 | delete l; 61 | return p; 62 | } 63 | 64 | void List::push_back(double val) 65 | { 66 | insert(end(), val); 67 | } 68 | 69 | void List::push_front(double val) 70 | { 71 | insert(begin(), val); 72 | } 73 | 74 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/List.h: -------------------------------------------------------------------------------- 1 | #ifndef _LIST_H 2 | #define _LIST_H 3 | 4 | #include 5 | 6 | struct Link { 7 | double val; 8 | Link* prev; 9 | Link* succ; 10 | }; 11 | 12 | class List { 13 | public: 14 | List() 15 | : head { nullptr } 16 | , tail { nullptr } 17 | { 18 | } 19 | List(std::initializer_list lst); 20 | ~List(); 21 | 22 | Link* begin() const { return head; } 23 | Link* end() const { return nullptr; } 24 | 25 | Link* insert(Link* l, double val); 26 | Link* erase(Link* l); 27 | void push_back(double val); 28 | void push_front(double val); 29 | 30 | List(const List&) = delete; 31 | List& operator=(const List&) = delete; 32 | List(List&&) = delete; 33 | List& operator=(List&&) = delete; 34 | 35 | private: 36 | Link* head; 37 | Link* tail; 38 | }; 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/Vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "Vector.h" 5 | 6 | Vector::Vector() 7 | : sz { 0 } 8 | , elem { nullptr } 9 | { 10 | } 11 | 12 | Vector::Vector(size_t s, double d) 13 | : sz { s } 14 | , elem { sz > 0 ? new double[sz] : nullptr } 15 | { 16 | for (size_t i = 0; i < sz; ++i) 17 | elem[i] = d; 18 | } 19 | 20 | Vector::Vector(std::initializer_list lst) 21 | : sz { lst.size() } 22 | , elem { sz > 0 ? new double[sz] : nullptr } 23 | { 24 | std::copy(lst.begin(), lst.end(), elem); 25 | } 26 | 27 | Vector::Vector(const Vector& v) 28 | : sz { v.sz } 29 | , elem { sz > 0 ? new double[sz] : nullptr } 30 | { 31 | std::cout << "copy constructor\n"; 32 | std::copy(v.elem, v.elem + sz, elem); 33 | } 34 | 35 | Vector& Vector::operator=(const Vector& v) 36 | { 37 | std::cout << "copy assignment\n"; 38 | if (this == &v) 39 | return *this; 40 | double* p { nullptr }; 41 | if (v.sz > 0) { 42 | p = new double[v.sz]; 43 | std::copy(v.elem, v.elem + v.sz, p); 44 | } 45 | delete[] elem; 46 | elem = p; 47 | sz = v.sz; 48 | return *this; 49 | } 50 | 51 | Vector::Vector(Vector&& v) noexcept 52 | : sz { v.sz } 53 | , elem { v.elem } 54 | { 55 | std::cout << "move constructor\n"; 56 | v.sz = 0; 57 | v.elem = nullptr; 58 | } 59 | 60 | Vector& Vector::operator=(Vector&& v) noexcept 61 | { 62 | std::cout << "move assignment\n"; 63 | if (this == &v) 64 | return *this; 65 | delete[] elem; 66 | sz = v.sz; 67 | elem = v.elem; 68 | v.sz = 0; 69 | v.elem = nullptr; 70 | return *this; 71 | } 72 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/Vector.h: -------------------------------------------------------------------------------- 1 | #ifndef _VECTOR_H 2 | #define _VECTOR_H 3 | 4 | #include 5 | 6 | class Vector { 7 | public: 8 | Vector(); 9 | explicit Vector(std::size_t s, double d = 0.0); 10 | Vector(std::initializer_list lst); 11 | 12 | ~Vector() 13 | { 14 | delete[] elem; 15 | } 16 | 17 | std::size_t size() const { return sz; } 18 | double* data() { return elem; } 19 | const double* data() const { return elem; } 20 | 21 | double& operator[](std::size_t i) { return elem[i]; } 22 | double operator[](std::size_t i) const { return elem[i]; } 23 | 24 | Vector(const Vector& v); 25 | Vector& operator=(const Vector& v); 26 | 27 | Vector(Vector&& v) noexcept; 28 | Vector& operator=(Vector&& v) noexcept; 29 | 30 | private: 31 | std::size_t sz; 32 | double* elem; 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /examples/ex12/Pointer_as_iterator/test_pointer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "List.h" 4 | #include "Vector.h" 5 | 6 | using std::cout; 7 | 8 | double* Vector_high(double* b, double* e) 9 | // just for demonstration, no error detection! 10 | // would fail if b==nullptr || e==nullptr || e *high) 15 | high = p; 16 | } 17 | return high; 18 | } 19 | 20 | Link* List_high(Link* b, Link* e) 21 | // e must be nullptr, b must not be nullptr! 22 | { 23 | Link* high { b }; 24 | for (Link* p = b; p != e; p = p->succ) { 25 | if (p->val > high->val) 26 | high = p; 27 | } 28 | return high; 29 | } 30 | 31 | int main() 32 | { 33 | double a[5] { 2.3, 4.5, 8.9, 0.6, 7.4 }; 34 | double* ha { Vector_high(a, a + 5) }; 35 | if (ha) 36 | cout << *ha << '\n'; 37 | 38 | Vector b { 2.3, 4.5, 8.9, 0.6, 7.4 }; 39 | double* hb { Vector_high(&b[0], &b[0] + b.size()) }; 40 | if (hb) 41 | cout << *hb << '\n'; 42 | 43 | List c { 2.3, 4.5, 8.9, 0.6, 7.4 }; 44 | Link* hc { List_high(c.begin(), c.end()) }; 45 | if (hc) 46 | cout << hc->val << '\n'; 47 | } 48 | -------------------------------------------------------------------------------- /examples/ex12/Vector_template/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | project(vector) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | add_executable(test_vector.exe test_vector.cpp Vector.h) 10 | 11 | -------------------------------------------------------------------------------- /examples/ex12/Vector_template/test_vector.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "Vector.h" 4 | 5 | using std::cout; 6 | using std::string; 7 | 8 | class A { 9 | public: 10 | A() { cout << "A::A()\n"; } 11 | A(const A&) { cout << "A::A(const A&)\n"; } 12 | A& operator=(const A&) 13 | { 14 | cout << "A::operator=(const A&)\n"; 15 | return *this; 16 | } 17 | ~A() { cout << "A::~A()\n"; } 18 | }; 19 | 20 | int main() 21 | { 22 | Vector v1 { 3, 4, 5 }; 23 | Vector v2 { 3.3, 4.4, 5.5 }; 24 | Vector v3 { "haha", "hehe", "hoho" }; 25 | cout << v1[0] << '\n'; 26 | cout << v2[1] << '\n'; 27 | cout << v3[2] << '\n'; 28 | 29 | cout << '\n'; 30 | 31 | //Vector v4(5); 32 | } 33 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Ball.cpp: -------------------------------------------------------------------------------- 1 | #include "Ball.h" 2 | #include "constants.h" 3 | 4 | using Graph_lib::Color; 5 | using Graph_lib::Line_style; 6 | using Graph_lib::Point; 7 | using Graph_lib::Stroke; 8 | 9 | Ball::Ball() 10 | : c { Point { init_x, init_y }, r } 11 | , speed_x { default_speed } 12 | , speed_y { default_speed } 13 | { 14 | c.set_line_style(Line_style { 1, Color::red, Stroke::solid }); 15 | c.set_fill_color(Color::red); 16 | } 17 | 18 | void Ball::reset() 19 | { 20 | Point p { c.center() }; 21 | c.move(init_x - p.x, init_y - p.y); 22 | speed_x = default_speed; 23 | speed_y = default_speed; 24 | } 25 | 26 | void Ball::move() 27 | { 28 | c.move(speed_x, speed_y); 29 | Point p { c.center() }; 30 | if (p.x - r <= 0 || p.x + r >= window_width) { 31 | speed_x = -speed_x; 32 | } 33 | if (p.y - r <= 0 || p.y + r >= window_height) { 34 | speed_y = -speed_y; 35 | } 36 | }; 37 | 38 | using Graph_lib::Rectangle; 39 | 40 | bool Ball::collide(const Graph_lib::Rectangle& rect) 41 | { 42 | // just for illustration, definitely not the correct way to detect collision 43 | 44 | int upper { rect.point(0).y }; 45 | int lower { upper + rect.height() }; 46 | int left { rect.point(0).x }; 47 | int right { left + rect.width() }; 48 | 49 | int x { c.center().x }; 50 | int y { c.center().y }; 51 | int r { c.radius() }; 52 | 53 | if (x >= left && x <= right) { 54 | if ((y < upper && upper - y <= r) || (y > lower && y - lower <= r)) { 55 | speed_y = -speed_y; 56 | return true; 57 | } 58 | } 59 | 60 | if (y >= upper && y <= lower) { 61 | if ((x < left && left - x <= r) || (x > right && x - right <= r)) { 62 | speed_x = -speed_x; 63 | return true; 64 | } 65 | } 66 | 67 | return false; 68 | } 69 | 70 | void Ball::collide(const Paddle& paddle) 71 | { 72 | auto rect { dynamic_cast(paddle.get_shape()) }; 73 | collide(*rect); 74 | } 75 | 76 | void Ball::collide(Block& block) 77 | { 78 | auto rect { dynamic_cast(block.get_shape()) }; 79 | if (collide(*rect)) 80 | block.die(); 81 | } -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Ball.h: -------------------------------------------------------------------------------- 1 | #ifndef _BALL_H 2 | #define _BALL_H 3 | 4 | #include "Graph_lib/Graph.h" 5 | 6 | #include "Block.h" 7 | #include "Paddle.h" 8 | 9 | class Ball { 10 | public: 11 | Ball(); 12 | 13 | void reset(); 14 | 15 | void move(); 16 | 17 | const Graph_lib::Shape* get_shape() const { return &c; } 18 | 19 | void collide(const Paddle& paddle); 20 | void collide(Block& block); 21 | 22 | private: 23 | bool collide(const Graph_lib::Rectangle& rect); 24 | 25 | private: 26 | Graph_lib::Circle c; 27 | int speed_x; 28 | int speed_y; 29 | static constexpr int init_x { 200 }; 30 | static constexpr int init_y { 400 }; 31 | static constexpr int r { 10 }; 32 | static constexpr int default_speed { 5 }; 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Block.cpp: -------------------------------------------------------------------------------- 1 | #include "Block.h" 2 | #include "constants.h" 3 | 4 | using Graph_lib::Color; 5 | using Graph_lib::Point; 6 | 7 | Block::Block(int x, int y) 8 | : r { Point { x, y }, block_width, block_height } 9 | , alive { true } 10 | { 11 | r.set_line_color(background); 12 | r.set_fill_color(Color::magenta); 13 | } 14 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Block.h: -------------------------------------------------------------------------------- 1 | #ifndef _BLOCK_H 2 | #define _BLOCK_H 3 | 4 | #include "Graph_lib/Graph.h" 5 | #include "constants.h" 6 | 7 | class Block { 8 | public: 9 | Block(int x, int y); 10 | 11 | bool is_alive() { return alive; } 12 | 13 | void reset() 14 | { 15 | alive = true; 16 | r.set_fill_visibility(true); 17 | } 18 | 19 | void die() 20 | { 21 | alive = false; 22 | r.set_fill_visibility(false); 23 | } 24 | 25 | const Graph_lib::Shape* get_shape() const { return &r; } 26 | 27 | private: 28 | Graph_lib::Rectangle r; 29 | bool alive; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.11) 2 | project(bouncing_ball) 3 | 4 | set(CMAKE_CXX_STANDARD 14) 5 | set(CMAKE_CXX_STANDARD_REQUIRED YES) 6 | 7 | set(CMAKE_EXPORT_COMPILE_COMMANDS YES) 8 | 9 | find_package(FLTK REQUIRED) 10 | include_directories(${FLTK_INCLUDE_DIR}) 11 | link_directories(${FLTK_LIBRARY_DIR}) 12 | 13 | find_package(JPEG REQUIRED) 14 | find_package(PNG REQUIRED) 15 | 16 | add_subdirectory(Graph_lib) 17 | 18 | set(SOURCES bouncing_ball.cpp constants.h 19 | My_window.cpp My_window.h Scene.cpp Scene.h 20 | Ball.cpp Ball.h Paddle.cpp Paddle.h Block.cpp Block.h) 21 | 22 | add_executable(bouncing_ball.exe ${SOURCES} ${GRAPH_LIB}) 23 | target_link_libraries(bouncing_ball.exe ${FLTK_LIBRARIES} 24 | ${JPEG_LIBRARIES} ${PNG_LIBRARIES}) 25 | 26 | file(COPY blue.jpg DESTINATION ${CMAKE_BINARY_DIR}) 27 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(GRAPH_LIB 2 | ${CMAKE_CURRENT_SOURCE_DIR}/fltk.h 3 | ${CMAKE_CURRENT_SOURCE_DIR}/Point.h 4 | ${CMAKE_CURRENT_SOURCE_DIR}/Vector_ref.h 5 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.cpp 6 | ${CMAKE_CURRENT_SOURCE_DIR}/GUI.h 7 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.cpp 8 | ${CMAKE_CURRENT_SOURCE_DIR}/Graph.h 9 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.cpp 10 | ${CMAKE_CURRENT_SOURCE_DIR}/Window.h 11 | ${CMAKE_CURRENT_SOURCE_DIR}/Simple_window.h 12 | PARENT_SCOPE) 13 | 14 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/Point.h: -------------------------------------------------------------------------------- 1 | #ifndef POINT_GUARD 2 | #define POINT_GUARD 3 | 4 | namespace Graph_lib { 5 | 6 | struct Point { 7 | int x, y; 8 | Point(int xx, int yy) 9 | : x { xx } 10 | , y { yy } 11 | { 12 | } 13 | }; 14 | 15 | inline bool operator==(Point a, Point b) { return a.x == b.x && a.y == b.y; } 16 | 17 | inline bool operator!=(Point a, Point b) { return !(a == b); } 18 | 19 | } // namespace Graph_lib 20 | 21 | #endif 22 | 23 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/Simple_window.h: -------------------------------------------------------------------------------- 1 | #include "GUI.h" 2 | #include "Point.h" 3 | #include "Window.h" 4 | 5 | // Simple_window is basic scaffolding for ultra-simple interaction with graphics 6 | // it provides one window with one "next" button for ultra-simple animation 7 | 8 | class Simple_window : public Graph_lib::Window { 9 | 10 | public: 11 | Simple_window(Graph_lib::Point xy, int w, int h, const std::string& title) 12 | : Graph_lib::Window { xy, w, h, title, false } 13 | , quit_button { Graph_lib::Point { x_max() - 70, 0 }, 70, 20, "Quit", cb_quit } 14 | , next_button { Graph_lib::Point { x_max() - 70, 20 }, 70, 20, "Next", cb_next } 15 | , next_pushed { false } 16 | { 17 | attach(quit_button); 18 | attach(next_button); 19 | } 20 | 21 | void wait_for_next() 22 | { 23 | while (!next_pushed && Fl::wait()) 24 | ; 25 | next_pushed = false; 26 | Fl::redraw(); 27 | } 28 | 29 | private: 30 | Graph_lib::Button quit_button; 31 | Graph_lib::Button next_button; 32 | 33 | bool next_pushed; 34 | 35 | // callback for quit_button 36 | static void cb_quit(void*, void* pw) 37 | { 38 | static_cast(pw)->quit(); 39 | } 40 | 41 | void quit() { hide(); } 42 | 43 | // callback for next_button 44 | static void cb_next(void*, void* pw) 45 | { 46 | static_cast(pw)->next(); 47 | } 48 | 49 | void next() { next_pushed = true; } 50 | }; 51 | 52 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/Vector_ref.h: -------------------------------------------------------------------------------- 1 | #ifndef VECTOR_REF_GUARD 2 | #define VECTOR_REF_GUARD 3 | 4 | #include 5 | 6 | namespace Graph_lib { 7 | 8 | template 9 | class Vector_ref { 10 | public: 11 | Vector_ref() = default; 12 | explicit Vector_ref(T* t) 13 | { 14 | if (t) 15 | push_back(t); 16 | } 17 | ~Vector_ref() 18 | { 19 | for (auto p : owned) 20 | delete p; 21 | } 22 | 23 | void push_back(T& s) { v.push_back(&s); } 24 | void push_back(T* p) 25 | { 26 | v.push_back(p); 27 | owned.push_back(p); 28 | } 29 | 30 | T& operator[](int i) { return *v[i]; } 31 | const T& operator[](int i) const { return *v[i]; } 32 | size_t size() const { return v.size(); } 33 | 34 | private: 35 | std::vector v; 36 | std::vector owned; 37 | }; 38 | 39 | } // namespace Graph_lib 40 | 41 | #endif 42 | 43 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/Window.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "GUI.h" 5 | #include "Graph.h" 6 | #include "Window.h" 7 | 8 | using std::string; 9 | 10 | namespace Graph_lib { 11 | 12 | Window::Window(int ww, int hh, const string& title, bool resizable) 13 | : Super { ww, hh, title.c_str() } 14 | , w { ww } 15 | , h { hh } 16 | { 17 | init(resizable); 18 | } 19 | 20 | Window::Window(Point xy, int ww, int hh, const string& title, bool resizable) 21 | : Super { xy.x, xy.y, ww, hh, title.c_str() } 22 | , w { ww } 23 | , h { hh } 24 | { 25 | init(resizable); 26 | } 27 | 28 | void Window::init(bool res) 29 | { 30 | if (res) 31 | resizable(this); 32 | Fl::visual(FL_DOUBLE | FL_INDEX); 33 | show(); 34 | } 35 | 36 | //---------------------------------------------------- 37 | 38 | void Window::resize(int ww, int hh) 39 | { 40 | w = ww; 41 | h = hh; 42 | size(ww, hh); 43 | } 44 | 45 | void Window::draw() 46 | { 47 | Super::draw(); 48 | for (auto shape : shapes) 49 | shape->draw(); 50 | } 51 | 52 | void Window::attach(Widget& w) 53 | { 54 | begin(); // FTLK: begin attaching new Fl_Widgets to this window 55 | w.attach(*this); // let the Widget create its Fl_Widget 56 | end(); // FTLK: stop attaching new Fl_Widgets to this window 57 | } 58 | 59 | void Window::detach(Widget& w) 60 | { 61 | w.hide(); 62 | } 63 | 64 | void Window::attach(const Shape& s) 65 | { 66 | // each shape should only be attached once 67 | detach(s); 68 | shapes.push_back(&s); 69 | } 70 | 71 | void Window::detach(const Shape& s) 72 | { 73 | auto it { std::find(shapes.begin(), shapes.end(), &s) }; 74 | if (it != shapes.end()) { 75 | shapes.erase(it); 76 | } 77 | } 78 | 79 | void Window::put_on_top(const Shape& s) 80 | { 81 | attach(s); 82 | } 83 | 84 | int gui_main() { return Fl::run(); } 85 | 86 | } // namespace Graph_lib 87 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/Window.h: -------------------------------------------------------------------------------- 1 | #ifndef WINDOW_GUARD 2 | #define WINDOW_GUARD 1 3 | 4 | #include 5 | #include 6 | 7 | #include "fltk.h" 8 | 9 | #include "Graph.h" 10 | #include "Point.h" 11 | 12 | using Graph_lib::Color; 13 | 14 | namespace Graph_lib { 15 | 16 | class Widget; 17 | 18 | class Window : public Fl_Double_Window { 19 | public: 20 | using Super = Fl_Double_Window; 21 | // let the system pick the location 22 | Window(int w, int h, const std::string& title, bool resizable = true); 23 | // top left corner in xy 24 | Window(Point xy, int w, int h, const std::string& title, bool resizable = true); 25 | 26 | ~Window() override = default; 27 | 28 | int x_max() const { return w; } 29 | int y_max() const { return h; } 30 | 31 | using Super::resize; // resize(int x, int y, int w, int h); 32 | 33 | void resize(int ww, int hh); 34 | 35 | void set_background_color(Color c) { color(static_cast(c)); } 36 | void set_label(const std::string& s) { label(s.c_str()); } 37 | 38 | void attach(Widget& w); // attach a widget 39 | void detach(Widget& w); // hide the widget (not really detached) 40 | 41 | void attach(const Shape& s); // add s to shapes 42 | void detach(const Shape& s); // remove s from shapes 43 | void put_on_top(const Shape& p); // put p on top of other shapes 44 | void detach_all_shapes() { shapes.clear(); } 45 | 46 | protected: 47 | void draw() override; 48 | 49 | private: 50 | std::vector shapes; // shapes attached to window 51 | int w, h; // window size 52 | 53 | void init(bool res); 54 | }; 55 | 56 | int gui_main(); // invoke GUI library's main event loop 57 | 58 | inline int x_max() { return Fl::w(); } // width of screen in pixels 59 | inline int y_max() { return Fl::h(); } // height of screen in pixels 60 | 61 | } // namespace Graph_lib 62 | #endif 63 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Graph_lib/fltk.h: -------------------------------------------------------------------------------- 1 | #ifndef FLTK_GUARD 2 | #define FLTK_GUARD 1 3 | 4 | #include "FL/Enumerations.H" 5 | #include "FL/Fl.H" 6 | #include "FL/Fl_Button.H" 7 | #include "FL/Fl_Double_Window.H" 8 | #include "FL/Fl_Input.H" 9 | #include "FL/Fl_Output.H" 10 | #include "FL/Fl_Window.H" 11 | #include "FL/fl_draw.H" 12 | 13 | #include "FL/Fl_BMP_Image.H" 14 | #include "FL/Fl_GIF_Image.H" 15 | #include "FL/Fl_JPEG_Image.H" 16 | #include "FL/Fl_PNG_Image.H" 17 | 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/My_window.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "My_window.h" 5 | #include "constants.h" 6 | 7 | using Graph_lib::Color; 8 | using Graph_lib::Point; 9 | 10 | My_window::My_window() 11 | : Graph_lib::Window { window_width, window_height, "ball", false } 12 | , scene_title {} 13 | , scene_play {} 14 | , current_scene { &scene_title } 15 | { 16 | set_background_color(background); 17 | current_scene->attach_to_window(*this); 18 | Fl::add_timeout(1. / fps, cb_timeout, this); 19 | } 20 | 21 | void My_window::switch_to(Scene* s) 22 | { 23 | current_scene->detach_from_window(); 24 | s->reset(); 25 | s->attach_to_window(*this); 26 | current_scene = s; 27 | } 28 | 29 | void My_window::start() 30 | { 31 | switch_to(&scene_play); 32 | keydown_handlers.clear(); 33 | keydown_handlers["r"] = [this]() { title(); }; 34 | } 35 | 36 | void My_window::title() 37 | { 38 | switch_to(&scene_title); 39 | keydown_handlers.clear(); 40 | } 41 | 42 | void My_window::loop() 43 | { 44 | current_scene->update(); 45 | redraw(); 46 | Fl::repeat_timeout(1. / fps, cb_timeout, this); 47 | } 48 | 49 | int My_window::handle(int event) 50 | { 51 | int ret { Graph_lib::Window::handle(event) }; 52 | if (ret == 1) 53 | return ret; 54 | switch (event) { 55 | case FL_FOCUS: 56 | case FL_UNFOCUS: 57 | ret = 1; 58 | break; 59 | case FL_SHORTCUT: 60 | if (current_scene == &scene_play && Fl::event_key() == FL_Escape) 61 | title(); 62 | ret = 1; 63 | break; 64 | // TODO: need to deal with cases where two keys are pressed at the same time 65 | case FL_KEYDOWN: { 66 | std::string key { Fl::event_text() }; 67 | if (handle_keydown(key)) 68 | ret = 1; 69 | else if (current_scene->handle_keydown(key)) 70 | ret = 1; 71 | break; 72 | } 73 | case FL_KEYUP: { 74 | std::string key { Fl::event_text() }; 75 | if (current_scene->handle_keyup(key)) 76 | ret = 1; 77 | break; 78 | } 79 | default: 80 | break; 81 | } 82 | return ret; 83 | } 84 | 85 | bool My_window::handle_keydown(const std::string& key) 86 | { 87 | try { 88 | keydown_handlers.at(key)(); 89 | return true; 90 | } catch (std::out_of_range&) { 91 | return false; 92 | } 93 | } -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/My_window.h: -------------------------------------------------------------------------------- 1 | #ifndef _MY_WINDOW_H 2 | #define _MY_WINDOW_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "Graph_lib/Window.h" 9 | 10 | #include "Scene.h" 11 | 12 | class My_window : public Graph_lib::Window { 13 | 14 | public: 15 | My_window(); 16 | 17 | ~My_window() override = default; 18 | 19 | void switch_to(Scene* s); 20 | 21 | void start(); 22 | 23 | void title(); 24 | 25 | void loop(); 26 | 27 | static void cb_timeout(void* pw) { static_cast(pw)->loop(); } 28 | 29 | int handle(int event) override; 30 | 31 | bool handle_keydown(const std::string& key); 32 | 33 | private: 34 | Scene_title scene_title; 35 | Scene_play scene_play; 36 | Scene* current_scene; 37 | std::map> keydown_handlers; 38 | }; 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Paddle.cpp: -------------------------------------------------------------------------------- 1 | #include "Paddle.h" 2 | #include "constants.h" 3 | 4 | using Graph_lib::Color; 5 | using Graph_lib::Line_style; 6 | using Graph_lib::Point; 7 | using Graph_lib::Stroke; 8 | 9 | Paddle::Paddle() 10 | : r { Point { init_x, init_y }, w, h } 11 | , speed_x { 0 } 12 | { 13 | r.set_line_style(Line_style { 1, Color::blue, Stroke::solid }); 14 | r.set_fill_color(Color::blue); 15 | } 16 | 17 | void Paddle::reset() 18 | { 19 | int x { r.point(0).x }; 20 | r.move(init_x - x, 0); 21 | speed_x = 0; 22 | } 23 | 24 | void Paddle::set_speed(int speed) 25 | { 26 | if (speed > 0) 27 | speed_x = default_speed; 28 | else if (speed < 0) 29 | speed_x = -default_speed; 30 | else 31 | speed_x = 0; 32 | } 33 | 34 | void Paddle::move() 35 | { 36 | int x { r.point(0).x }; 37 | if ((x > 0 && speed_x < 0) || (x + w < window_width && speed_x > 0)) 38 | r.move(speed_x, 0); 39 | }; -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Paddle.h: -------------------------------------------------------------------------------- 1 | #ifndef _PADDLE_H 2 | #define _PADDLE_H 3 | 4 | #include "Graph_lib/Graph.h" 5 | #include "constants.h" 6 | 7 | class Paddle { 8 | public: 9 | Paddle(); 10 | 11 | void reset(); 12 | 13 | void move(); 14 | 15 | void set_speed(int speed); 16 | 17 | const Graph_lib::Shape* get_shape() const { return &r; } 18 | 19 | private: 20 | Graph_lib::Rectangle r; 21 | int speed_x; 22 | static constexpr int w { 100 }; 23 | static constexpr int h { 20 }; 24 | static constexpr int init_x { window_width / 2 - w }; 25 | static constexpr int init_y { window_height - h }; 26 | static constexpr int default_speed { 10 }; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/Scene.h: -------------------------------------------------------------------------------- 1 | #ifndef _SCENE_H 2 | #define _SCENE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "Graph_lib/GUI.h" 10 | #include "Graph_lib/Graph.h" 11 | #include "Graph_lib/Window.h" 12 | 13 | #include "Ball.h" 14 | #include "Block.h" 15 | #include "Paddle.h" 16 | 17 | class Scene { 18 | public: 19 | Scene(); 20 | 21 | virtual void reset() {} 22 | 23 | virtual void update() {} 24 | 25 | virtual ~Scene(); 26 | 27 | virtual void attach_to_window(Graph_lib::Window& w); 28 | virtual void detach_from_window(); 29 | 30 | virtual bool handle_keydown(const std::string& key) { return false; } 31 | virtual bool handle_keyup(const std::string& key) { return false; } 32 | 33 | protected: 34 | Graph_lib::Window* win; 35 | std::vector shapes; 36 | std::vector widgets; 37 | }; 38 | 39 | class Scene_title : public Scene { 40 | public: 41 | Scene_title(); 42 | 43 | private: 44 | Graph_lib::Image image; 45 | }; 46 | 47 | class Scene_play : public Scene { 48 | public: 49 | Scene_play(); 50 | ~Scene_play() override; 51 | 52 | void reset() override; 53 | void update() override; 54 | 55 | bool handle_keydown(const std::string& key) override; 56 | bool handle_keyup(const std::string& key) override; 57 | 58 | private: 59 | Ball ball; 60 | Paddle paddle; 61 | std::vector blocks; 62 | std::map> keydown_handlers; 63 | std::map> keyup_handlers; 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/blue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/llyang/Computing/130254a9acace74d60274e21eda9566d18cfa816/just_for_fun/bouncing_ball/blue.jpg -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/bouncing_ball.cpp: -------------------------------------------------------------------------------- 1 | #include "My_window.h" 2 | #include "Scene.h" 3 | 4 | //////////////////////////////////////// 5 | 6 | int main() 7 | { 8 | My_window win; 9 | 10 | return Graph_lib::gui_main(); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /just_for_fun/bouncing_ball/constants.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONSTANTS_H 2 | #define _CONSTANTS_H 3 | 4 | #include "Graph_lib/Graph.h" 5 | 6 | constexpr int window_width { 800 }; 7 | constexpr int window_height { 600 }; 8 | constexpr int blocks_per_row { 10 }; 9 | constexpr int block_width { window_width / blocks_per_row }; 10 | constexpr int block_height { 20 }; 11 | 12 | constexpr int fps { 60 }; 13 | 14 | constexpr Graph_lib::Color background { Graph_lib::Color::white }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /just_for_fun/n_body/calc_2body.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | constexpr double GM { 0.00028 }; 10 | constexpr double delta_t { 1 }; 11 | const valarray r0 { 1, 0 }; 12 | const valarray v0 { 0, 0.017 }; 13 | 14 | valarray r { r0 }; 15 | valarray v { v0 }; 16 | for (int i = 0; i < 1000; ++i) { 17 | cout << setprecision(16) << r[0] << '\t' << r[1] << '\n'; 18 | double r2 { r[0] * r[0] + r[1] * r[1] }; 19 | valarray a { -(GM / r2) * (r / sqrt(r2)) }; 20 | v += a * delta_t; 21 | r += v * delta_t; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /just_for_fun/n_body/calc_3body.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | int main() 8 | { 9 | constexpr double GM { 0.00028 }; 10 | constexpr double delta_t { 1 }; 11 | const valarray p1 { -1, 0 }; 12 | const valarray p2 { 1, 0 }; 13 | const valarray r0 { 0, 0.5 }; 14 | const valarray v0 { 0.01, 0.01 }; 15 | 16 | valarray r { r0 }; 17 | valarray v { v0 }; 18 | for (int i = 0; i < 10000; ++i) { 19 | cout << setprecision(16) << r[0] << '\t' << r[1] << '\n'; 20 | const valarray r1 { r - p1 }; 21 | const valarray r2 { r - p2 }; 22 | double r12 { r1[0] * r1[0] + r1[1] * r1[1] }; 23 | double r22 { r2[0] * r2[0] + r2[1] * r2[1] }; 24 | valarray a { -(GM / r12) * (r1 / sqrt(r12)) - (GM / r22) * (r2 / sqrt(r22)) }; 25 | v += a * delta_t; 26 | r += v * delta_t; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /just_for_fun/n_body/makefile: -------------------------------------------------------------------------------- 1 | CXX = g++ 2 | CXXFLAGS = -std=c++11 3 | 4 | .PHONY: default all clean 5 | 6 | default: all 7 | 8 | all: calc_2body.exe calc_3body.exe 9 | 10 | %.exe: %.cpp 11 | $(CXX) $(CXXFLAGS) -o $@ $< 12 | 13 | clean: 14 | $(RM) *.exe 15 | -------------------------------------------------------------------------------- /just_for_fun/n_body/plot_2body.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import sys 4 | import numpy as np 5 | from matplotlib import pyplot as plt 6 | from matplotlib import animation 7 | 8 | 9 | def do_plot(fn): 10 | fig = plt.figure() 11 | ax = plt.axes(xlim=(-1.2, 1.2), ylim=(-1.2, 1.2)) 12 | line, = ax.plot([], [], linewidth=2, color='blue') 13 | ball, = ax.plot([], [], marker='o', markersize=12, color='black') 14 | 15 | def init(): 16 | line.set_data([], []) 17 | ball.set_data([], []) 18 | return line, ball 19 | 20 | def animate(i): 21 | line.set_data(data[:i, 0], data[:i, 1]) 22 | ball.set_data(data[i - 1, 0], data[i - 1, 1]) 23 | return line, ball 24 | 25 | data = np.loadtxt(fn) 26 | 27 | anim = animation.FuncAnimation( 28 | fig, 29 | animate, 30 | init_func=init, 31 | frames=len(data), 32 | interval=1, 33 | repeat=False, 34 | blit=True) 35 | 36 | plt.show() 37 | 38 | 39 | if __name__ == '__main__': 40 | 41 | if len(sys.argv) > 1: 42 | do_plot(sys.argv[1]) 43 | else: 44 | print('require a filename') 45 | -------------------------------------------------------------------------------- /just_for_fun/n_body/plot_3body.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python3 2 | 3 | import sys 4 | import numpy as np 5 | from matplotlib import pyplot as plt 6 | from matplotlib import animation 7 | 8 | 9 | def do_plot(fn): 10 | fig = plt.figure() 11 | ax = plt.axes(xlim=(-2, 2), ylim=(-2, 2)) 12 | line, = ax.plot([], [], linewidth=2, color='blue') 13 | ball, = ax.plot([], [], marker='o', markersize=12, color='black') 14 | 15 | def init(): 16 | line.set_data([], []) 17 | ball.set_data([], []) 18 | return line, ball 19 | 20 | def animate(i): 21 | line.set_data(data[:i, 0], data[:i, 1]) 22 | ball.set_data(data[i - 1, 0], data[i - 1, 1]) 23 | return line, ball 24 | 25 | data = np.loadtxt(fn) 26 | 27 | anim = animation.FuncAnimation( 28 | fig, 29 | animate, 30 | init_func=init, 31 | frames=len(data), 32 | interval=1, 33 | repeat=False, 34 | blit=True) 35 | 36 | plt.show() 37 | 38 | 39 | if __name__ == '__main__': 40 | 41 | if len(sys.argv) > 1: 42 | do_plot(sys.argv[1]) 43 | else: 44 | print('require a filename') 45 | --------------------------------------------------------------------------------