├── .gitignore ├── README.md ├── docker ├── Dockerfile ├── build.sh ├── pull.sh └── push.sh └── units ├── .gitignore ├── 010_get_started ├── get_started.cppmd └── overflow.cppmd ├── 015_conventions ├── .gitignore └── conventions.cppmd ├── 020_stages_hello_world ├── .gitignore ├── Makefile └── stages_hello_world.cppmd ├── 030_types_and_ops ├── .gitignore ├── Makefile ├── logical_operators.jpg ├── op_precedence_1.jpg ├── relational_operators.jpg └── types_and_ops.cppmd ├── 035_printing ├── .gitignore └── printing.cppmd ├── 040_decisions ├── .gitignore ├── Makefile ├── compound_assign.jpg ├── decisions.cppmd └── incr_decr.jpg ├── 050_arrays ├── .gitignore └── arrays.cppmd ├── 060_chars_strings ├── .gitignore ├── Makefile └── chars_strings.cppmd ├── 065_reading_input ├── .gitignore └── reading_input.cppmd ├── 070_command_line_args ├── .gitignore └── command_line_args.cppmd ├── 080_assertions ├── .gitignore └── assertions.cppmd ├── 090_math ├── .gitignore └── math.cppmd ├── 100_compile_link ├── .gitignore └── compile_link.cppmd ├── 110_functions ├── .gitignore └── functions.cppmd ├── 120_program_structure ├── .gitignore └── program_structure.cppmd ├── 130_makefiles ├── .gitignore └── makefiles.cppmd ├── 140_memory ├── .gitignore ├── figs.key └── memory.cppmd ├── 150_pointers ├── .gitignore ├── figs.key └── pointers.cppmd ├── 160_ptrs_arrays ├── .gitignore └── ptrs_arrays.cppmd ├── 170_lifetime_scope ├── .gitignore └── lifetime_scope.cppmd ├── 180_stack_heap ├── .gitignore ├── stack1.key └── stack_heap.cppmd ├── 190_dynamic_mem ├── .gitignore └── dynamic_mem.cppmd ├── 200_valgrind ├── .gitignore └── valgrind.cppmd ├── 210_gdb ├── .gitignore └── gdb.cppmd ├── 220_structs ├── .gitignore └── structs.cppmd ├── 230_beyond_1d ├── .gitignore ├── beyond_1d.cppmd └── figs.key ├── 240_binary_io ├── .gitignore └── binary_io.cppmd ├── 250_numeric_types ├── .gitignore ├── casting_promotion.cppmd └── numeric_types.cppmd ├── 260_casting_promotion ├── .gitignore └── casting_promotion.cppmd ├── 270_bitwise_ops ├── .gitignore └── bitwise_ops.cppmd ├── 280_linked_lists ├── .gitignore ├── figs.key └── linked_lists.cppmd ├── 500_cpp_intro ├── .gitignore └── cpp_intro.cppmd ├── 510_io_namespaces ├── .gitignore └── io_namespaces.cppmd ├── 520_strings ├── .gitignore └── strings.cppmd ├── 530_stl_intro ├── .gitignore └── stl_intro.cppmd ├── 540_vector_iter ├── .gitignore └── vector_iter.cppmd ├── 550_map ├── .gitignore └── map.cppmd ├── 560_more_iterators ├── .gitignore └── more_iterators.cppmd ├── 570_pair_tuple ├── .gitignore └── pair_tuple.cppmd ├── 580_references ├── .gitignore └── references.cppmd ├── 600_classes ├── .gitignore └── classes.cppmd ├── 610_constructors ├── .gitignore └── constructors.cppmd ├── 620_new_delete ├── .gitignore └── new_delete.cppmd ├── 630_non_default_ctors ├── .gitignore └── non_default_ctors.cppmd ├── 640_destructors ├── .gitignore └── destructors.cppmd ├── 650_pass_by_ref ├── .gitignore └── pass_by_ref.cppmd ├── 660_inheritance ├── .gitignore ├── figs.key └── inheritance.cppmd ├── 670_polymorphism ├── .gitignore └── polymorphism.cppmd ├── 675_virt_dtors ├── .gitignore └── virt_dtors.cppmd ├── 680_overloading ├── .gitignore └── overloading.cppmd ├── 690_enum ├── .gitignore └── enum.cppmd ├── 700_static_members ├── .gitignore └── static_members.cppmd ├── 710_design_principles ├── .gitignore └── design_principles.cppmd ├── 720_stringstream ├── .gitignore └── stringstream.cppmd ├── 730_fstream ├── .gitignore └── fstream.cppmd ├── 740_exceptions ├── .gitignore └── exceptions.cppmd ├── 750_ruleof3 ├── .gitignore └── ruleof3.cppmd ├── 760_template_funcs ├── .gitignore └── template_funcs.cppmd ├── 770_template_classes ├── .gitignore └── template_classes.cppmd ├── 780_abstract_classes ├── .gitignore └── abstract_classes.cppmd ├── 790_writing_containers ├── .gitignore └── writing_containers.cppmd ├── 800_auto ├── .gitignore └── auto.cppmd ├── 810_ranged_for ├── .gitignore └── ranged_for.cppmd ├── 820_override ├── .gitignore └── override.cppmd ├── Makefile.slides ├── build.sh ├── build_full.sh ├── clean_all.bash ├── cppmd_render.py ├── header.cppmd ├── header.yml ├── images ├── Valgrind_logo.png ├── acct_hier.png ├── arithmetic_ops.png ├── arr_string.png ├── ascii.png ├── binary-finger-numbers-blank.png ├── binary-finger-numbers.png ├── business.jpg ├── call_stack1.png ├── call_stack2.png ├── cc_by.png ├── checkers.jpg ├── compile_run.png ├── compile_run_just_compile.png ├── compile_run_just_edit.png ├── design_patterns.jpg ├── exception_classes.jpg ├── fahrenheit_celsius.jpg ├── float.png ├── hello_garbage.png ├── houses.png ├── inheritence_hierarchy.png ├── interest_header.png ├── interest_structure.png ├── ioclasses.pdf ├── jhu_vertical_blue.png ├── linked_list.png ├── ll_abcde.png ├── ll_abde.png ├── ll_abde_1.png ├── ll_abde_2.png ├── ll_abde_3.png ├── ll_abde_4.png ├── ll_bcde1.png ├── ll_bcde2.png ├── ll_bcde3.png ├── ll_bcde4.png ├── mailboxes.png ├── mem_fc.png ├── mem_fc2.png ├── new_docs.png ├── pointer_diag.png ├── pointer_mem.png ├── pointers_xkcd.png ├── rowcol.png ├── rowcol2.png ├── slicing.jpg ├── stack_heap.png ├── swap.png ├── tictactoe.png ├── tilde.jpg ├── tiobe.png ├── tiobe_20.png ├── twos_comp.png ├── university.small.vertical.blue.eps ├── vtbl.png ├── wse_vertical_blue.png └── y2k.jpg ├── make_all.bash └── make_full_set.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C & C++ programming notes 2 | 3 | [![License: CC BY 4.0](https://img.shields.io/badge/License-CC%20BY%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by/4.0/) 4 | 5 | * Author: Ben Langmead 6 | 7 | These are lecture notes and example code for teaching C & C++. The slides themselves are written in a custom "runnable Markdown" dialect for C/C++. These files have extension `.cppmd`. The script that "compiles" `.cppmd` files is `units/cppmd_render.py`. This script: 8 | 9 | * Generates C/C++ source files based on specially-formatted comments in the Markdown (``) 10 | * Runs shell commands based on specially-formatted comments in the Markdown (``), often in order to compile and run the source code 11 | * Possibly integrates the output from the shell back into the slides, so that output can be included in final rendered doc 12 | * Uses `pandoc` & `beamer` to render a PDF 13 | 14 | Outputs consist of (a) a PDF of the slides, (b) source files for all the examples. 15 | 16 | All the shell commands are run within a Docker image. We use this image from Docker Hub: 17 | 18 | * [`benlangmead/fedora-cpp-slides`](https://hub.docker.com/r/benlangmead/fedora-cpp-slides/) 19 | 20 | And the corresponding `Dockerfile` and scripts used to build/pull/push are available in the `docker` subdirectory. The base image is Fedora 27. The most relevant software versions are: 21 | 22 | ``` 23 | gcc-7.2.1 24 | g++-7.2.1 25 | gdb: Fedora 8.0.1-33.fc27 26 | valgrind-3.13.0 27 | git v2.14.3 28 | ``` 29 | 30 | ### Philosophy 31 | 32 | The reality of programming in C and C++ can seem divorced from the conceptual discussions in texts. In these notes, explaining concepts is always intertwined with showing examples. When examples are shown, I give exact code and exact command lines, executed in a predictable environment, so that students can recreate the conditions exactly. I show examples that do work and others that don't. The idea is never to stray too far from a code example. 33 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # Author: Ben Langmead 2 | # Date: 1/21/2018 3 | 4 | FROM fedora:27 5 | 6 | RUN yum install -y valgrind 7 | RUN yum install -y gdb 8 | RUN yum install -y gcc 9 | RUN yum install -y gcc-c++ 10 | RUN yum install -y emacs-nox 11 | RUN yum install -y git 12 | 13 | RUN dnf -y debuginfo-install glibc-2.26-15.fc27.x86_64 -------------------------------------------------------------------------------- /docker/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | docker build -t benlangmead/c-cpp-notes . 4 | -------------------------------------------------------------------------------- /docker/pull.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | docker pull benlangmead/c-cpp-notes 4 | -------------------------------------------------------------------------------- /docker/push.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | docker push benlangmead/c-cpp-notes 4 | -------------------------------------------------------------------------------- /units/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.cpp 3 | *.h 4 | *.md 5 | *.o 6 | *.pdf 7 | .*.cppmd 8 | a.out 9 | full 10 | -------------------------------------------------------------------------------- /units/010_get_started/get_started.cppmd: -------------------------------------------------------------------------------- 1 | # Course goals 2 | 3 | *Write complex, correct programs in C and C++* 4 | 5 | Leverage programming ecosystem 6 | 7 | * Linux 8 | * Compiler (`gcc`, `g++`) 9 | * Debugger (`gdb`) 10 | * Build system (`make`) 11 | 12 | Learn basic principles of software design and engineering 13 | 14 | # Prerequisites 15 | 16 | Experience with Java, Python or similar 17 | 18 | C/C++ experience *not* a prerequisite 19 | 20 | # Goals 21 | 22 | Learn C 23 | 24 | * Language features 25 | * Pointers & dynamic memory allocation 26 | * "Low-level" programming 27 | 28 | Learn C++ 29 | 30 | * How is it different from C? 31 | * Object-oriented programming 32 | * Generic programing 33 | 34 | # Goals 35 | 36 | Gain proficiency in Linux & related programming tools 37 | 38 | * Basic command-line tools 39 | * Compilers, debuggers, profilers 40 | 41 | Grow as a programmer & software engineer 42 | 43 | # Why C/C++? 44 | 45 | Why C/C++? 46 | 47 | * Ubiquitous 48 | * Efficient 49 | * Mature 50 | 51 | # Ubiquitous 52 | 53 | Much of the world's crucial software is in C 54 | 55 | * Used Java? JVM is written in C++, as are many libraries 56 | * Used Python? CPython interpreter written in C 57 | * Used the Internet? Network stacks, routers, web servers, ... 58 | * Like science? 59 | * https://github.com/collections/software-in-science 60 | * My lab members & I program in C/C++ a lot 61 | 62 | # Ubiquitous 63 | 64 | \centerline{\includegraphics[width=4.75in]{../images/tiobe.png}} 65 | 66 | \centering 67 | \scriptsize 68 | 69 | [www.tiobe.com/tiobe-index/](https://www.tiobe.com/tiobe-index/) 70 | 71 | \raggedright 72 | 73 | \normalsize 74 | 75 | Based on search engine hits for `" programming"` 76 | 77 | # Efficient 78 | 79 | Higher-level languages like Java & Python present a trade-off: 80 | 81 | * High-level languages "take care of things" for you 82 | 83 | * Source code is more concise, abstract 84 | * Harder to make mistakes 85 | 86 | * ...but also hide things from you 87 | 88 | * How variables are laid out in memory 89 | * When memory is allocated and de-allocated 90 | * Hardware features, especially non-portable features 91 | 92 | # Mature 93 | 94 | Around since the 1970s (C) and 80s (C++) 95 | 96 | Undergraduates have learned it for decades 97 | 98 | Software jobs often require it; "we need someone who... 99 | 100 | * ...can make something really fast if needed" 101 | * ...knows how to program all kinds of weird hardware" 102 | * ...knows how to interact with the operating system" 103 | * ...can handle our large codebase, written in C" 104 | 105 | # Why C/C++? 106 | 107 | Newer ``systems languages'' aim for a similar level of efficiency as C/C++ 108 | 109 | * But with simpler language 110 | * Less "burdened" by long history & by need to stay backward-compatible 111 | 112 | Examples 113 | 114 | * Swift -- [developer.apple.com/swift](https://developer.apple.com/swift) 115 | * Go -- [golang.org](https://golang.org) 116 | * Rust -- [rust-lang.org](https://www.rust-lang.org/) 117 | 118 | # Why C/C++? 119 | 120 | On efficiency, they approach C/C++ 121 | 122 | But they do not approach C/C++ in maturity/ubiquity 123 | 124 | * Some, like Swift, are associated with (& tied to) particular companies 125 | 126 | # Why C/C++? 127 | 128 | \vspace{5mm} 129 | 130 | \centerline{\includegraphics[width=3.5in]{../images/tiobe_20.png}} 131 | 132 | \centering 133 | \scriptsize 134 | 135 | [www.tiobe.com/tiobe-index/](https://www.tiobe.com/tiobe-index/) 136 | -------------------------------------------------------------------------------- /units/010_get_started/overflow.cppmd: -------------------------------------------------------------------------------- 1 | # Unix / Linux 2 | 3 | * You will need to get familiar with 4 | * How to log into a Unix/Linux system 5 | * `ssh` if you're on a Max or Linux system 6 | * PuTTY if you're on Windows 7 | * Basic command line 8 | * Navigating directory structure 9 | * Making / removing directories 10 | * Copying, moving files 11 | * How to edit files 12 | * With `emacs` 13 | 14 | # Unix / Linux: Tutorial 15 | 16 | Short link: [bit.ly/linuxbootcamp](http://bit.ly/linuxbootcamp) 17 | 18 | Long link: [http://rik.smith-unna.com/command_line_bootcamp](http://rik.smith-unna.com/command_line_bootcamp) 19 | 20 | Through section 22, "Viewing files cat" 21 | 22 | # Unix / Linux: Alternate tutorial 23 | 24 | The previous one goes down sometimes. Here's another version: 25 | 26 | Short link: [bit.ly/linuxbootcamp2](http://bit.ly/linuxbootcamp2) 27 | 28 | Long link: [korflab.ucdavis.edu/bootcamp.html](http://korflab.ucdavis.edu/bootcamp.html) 29 | 30 | Through section 23, "Viewing files with cat" 31 | 32 | # Administrative: C/C++ programming 33 | 34 | We will be programming! 35 | 36 | * In class 37 | * For homeworks 38 | * For projects 39 | 40 | Important that the *environment* you use to test your programs is the same environment we use to grade them 41 | 42 | # Administrative: C/C++ programming 43 | 44 | Environment where you test your programs must be the same as the environment we use to grade them 45 | 46 | Environment = 47 | 48 | * version of `gcc` - C compiler 49 | * version of `g++` - C++ compiler 50 | * version of `make`, `gdb`, `valgrind`, other tools 51 | * parameters specified when running those tools 52 | * etc 53 | 54 | # Administrative: C/C++ programming 55 | 56 | To ensure the environments match: 57 | 58 | * Test your programs on the CS dept Linux undergraduate cluster (more on this later) 59 | * Use prescribed parameters for `gcc`, `g++` & friends 60 | * `gcc -std=c99 -Wall -Wextra -pedantic` 61 | * `g++ -std=c++11 -Wall -Wextra -pedantic` 62 | 63 | -------------------------------------------------------------------------------- /units/015_conventions/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/015_conventions/conventions.cppmd: -------------------------------------------------------------------------------- 1 | # Course conventions 2 | 3 | C standard used is [C99](https://en.wikipedia.org/wiki/C99) 4 | 5 | * I will explicitly discourage use of variable length arrays 6 | 7 | C++ standard: [C++11](https://en.wikipedia.org/wiki/C%2B%2B11) 8 | 9 | * I will delay introducing some C++11 features like `auto` and ranged-`for` 10 | 11 | # Editing 12 | 13 | When I code live in the classroom, I use `emacs` 14 | 15 | These slides will provide occasional `emacs` tips 16 | 17 | Feel free to use your preferred editor; you might choose one with: 18 | 19 | * Syntax highlighting (different colors denote different parts of the program) 20 | * Integration with `git` 21 | * Stronger integrations with the compiler 22 | 23 | * E.g. highlighting compiler warnings & errors 24 | 25 | # Code 26 | 27 | Slides will often present source code 28 | 29 | Where possible, code for full program will be shown: 30 | 31 | 41 | 42 | # Code 43 | 44 | When code is too long to fit, I use `...` to denote elided code 45 | 46 | \footnotesize 47 | 48 | ```c 49 | class GradeList { 50 | public: 51 | ... 52 | void add(double grade) { 53 | grades.push_back(grade); 54 | } 55 | ... 56 | private: 57 | std::vector grades; 58 | ... 59 | }; 60 | ``` 61 | 62 | # Shell / compiling 63 | 64 | Slides will also sometimes present shell commands: 65 | 66 | 74 | 75 | 79 | 80 | `$` prefixes a command you would enter at the shell prompt (excluding the prompt `$` itself) 81 | 82 | Output is shown just after the command that generates it 83 | 84 | * `./a.out` prints `Hello, world!` 85 | 86 | # Shell / compiling 87 | 88 | Slides do not assume much Linux proficiency 89 | 90 | * I assume you know something about *standard streams*... 91 | 92 | * Standard input 93 | * Standard output 94 | * Standard error 95 | 96 | * ...and input and output redirection, e.g.: 97 | 98 | * `cat file.txt | ./a.out` 99 | * `echo "Hello world" | ./a.out` 100 | * `./a.out > /dev/null` 101 | 102 | # Shell / compiling 103 | 104 | Commands and outputs are run in / transcribed from a shell session run in a Fedora 27 Docker container 105 | 106 | You can use the same image, but it's not necessary 107 | 108 | * Available at: [`hub.docker.com/r/benlangmead/c-cpp-notes/`](https://hub.docker.com/r/benlangmead/c-cpp-notes/) 109 | * Software versions: 110 | * `gcc-7.2.1` 111 | * `g++-7.2.1` 112 | * `gdb: Fedora 8.0.1-33.fc27` 113 | * `valgrind-3.13.0` 114 | * `git v2.14.3` 115 | 116 | # Shell / compiling 117 | 118 | If you are using a different software setup than the one described on the previous slide, you may see different compiler warnings and errors than we show 119 | 120 | You may also experience different error messages or symptoms at runtime 121 | 122 | -------------------------------------------------------------------------------- /units/020_stages_hello_world/.gitignore: -------------------------------------------------------------------------------- 1 | convert_fc_badprec.c 2 | convert_fc_var2.c 3 | convert_fc_var3.c 4 | convert_fc.c 5 | mysterious.c 6 | convert_digit_7.c 7 | convert_digit_0.c 8 | hello_world.c 9 | convert_fc_var1.c 10 | hello_world_err.c 11 | a.out 12 | *.pdf 13 | *.md 14 | -------------------------------------------------------------------------------- /units/020_stages_hello_world/Makefile: -------------------------------------------------------------------------------- 1 | #!gmake 2 | 3 | CPPMD=python ../cppmd_render.py 4 | 5 | all: $(basename $(wildcard *.cppmd)).pdf 6 | 7 | %.pdf: %.cppmd 8 | $(CPPMD) --prefix $(@:%.pdf=%) --beamer-theme=metropolis --force < $< 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f *.pdf *.md *.c *.cpp *.h *.hpp a.out *~ 13 | -------------------------------------------------------------------------------- /units/020_stages_hello_world/stages_hello_world.cppmd: -------------------------------------------------------------------------------- 1 | # Stages of compilation & Hello, world 2 | 3 | \centerline{\includegraphics[width=4in]{../images/compile_run.png}} 4 | 5 | # Basic C/C++ programming workflow 6 | 7 | \vspace{0.25in} 8 | \centerline{\includegraphics[width=2in]{../images/compile_run_just_edit.png}} 9 | 10 | * `emacs dna_search.c` (then edit, save, exit) 11 | * `emacs string_match.c` (then edit, save, exit) 12 | * `emacs parse_input.c` (then edit, save, exit) 13 | 14 | # Basic C/C++ programming workflow 15 | 16 | \vspace{0.25in} 17 | \centerline{\includegraphics[width=3in]{../images/compile_run_just_compile.png}} 18 | 19 | * `gcc dna_search.c string_match.c, parse_input.c -std=c99 -pedantic -Wall -Wextra` 20 | 21 | # Inside the compiler 22 | 23 | Step 1: preprocessor 24 | 25 | * Gather relevant source code 26 | 27 | * Could be spread across source files that ``include'' & depend on each other 28 | 29 | * Process the directives that start with `#` 30 | 31 | * We'll see `#define`, `#include` 32 | 33 | Step 2: compiler 34 | 35 | * Turn human-readable *source code* into *object code* 36 | * Might yield warnings & errors if your code has mistakes 37 | 38 | # Inside the compiler 39 | 40 | Step 3: linker 41 | 42 | * Gather relevant *object code* into a single executable file 43 | * Might yield warnings & errors if relevant code is missing, there's a naming conflict, etc 44 | 45 | # Inside the compiler 46 | 47 | Between source code and machine code is a human-readable version of the machine code called "assembly language" 48 | 49 | \scriptsize 50 | \centering 51 | 52 | ``` 53 | _main: ## @main 54 | .cfi_startproc 55 | ## BB#0: 56 | pushq %rbp 57 | Ltmp0: 58 | .cfi_def_cfa_offset 16 59 | Ltmp1: 60 | .cfi_offset %rbp, -16 61 | movq %rsp, %rbp 62 | Ltmp2: 63 | .cfi_def_cfa_register %rbp 64 | subq $16, %rsp 65 | leaq L_.str(%rip), %rdi 66 | movl $0, -4(%rbp) 67 | callq _puts 68 | ``` 69 | 70 | # Hello world 71 | 72 | Create a directory where you will store your work for today 73 | 74 | Go to that directory and type `emacs hello_world.c` 75 | 76 | * Or use your favorite `emacs` alternative 77 | 78 | # Hello world 79 | 80 | 89 | 90 | After `emacs hello_world.c`, type above into the editor 91 | 92 | `Ctrl-x` `Ctrl-s` to save 93 | 94 | `Ctrl-x` `Ctrl-c` to quit 95 | 96 | # Hello world 97 | 98 | Compile: 99 | 100 | 104 | 105 | The result is an executable program called `a.out` 106 | 107 | (Later we'll see how to give it a better name) 108 | 109 | # Hello world 110 | 111 | If `a.out` is in our current directory, we run it by typing `./a.out` 112 | 113 | 116 | 117 | # Hello world 118 | 119 | 128 | 129 | `#include` is a preprocessor directive 130 | 131 | * Indicates a library to use, like `import` in Java or Python 132 | 133 | `main` is a function, every program has exactly one `main` 134 | 135 | `int` is its return type 136 | 137 | `()` says that `main` takes no parameters 138 | 139 | # Hello world 140 | 141 | 150 | 151 | 152 | `printf` prints a string to the terminal 153 | 154 | * `\n` indicates a "newline" -- goes to next line 155 | 156 | `return 0` means program completed with no errors 157 | 158 | Explanatory commenting (`// Print ...`) is good practice 159 | 160 | # Hello world 161 | 162 | What if we omit `#include `?: 163 | 164 | 171 | 172 | # Hello world 173 | 174 | Compiler prints a *compiler error* and does not generate `a.out` 175 | 176 | \scriptsize 177 | 178 | 181 | 182 | -------------------------------------------------------------------------------- /units/030_types_and_ops/.gitignore: -------------------------------------------------------------------------------- 1 | sizes 2 | *.c 3 | a.out 4 | *.pdf 5 | *.md 6 | -------------------------------------------------------------------------------- /units/030_types_and_ops/Makefile: -------------------------------------------------------------------------------- 1 | #!gmake 2 | 3 | CPPMD=python ../cppmd_render.py 4 | 5 | all: $(basename $(wildcard *.cppmd)).pdf 6 | 7 | %.pdf: %.cppmd 8 | $(CPPMD) --prefix $(@:%.pdf=%) --beamer-theme=metropolis --force < $< 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f *.pdf *.md *.c *.cpp *.h *.hpp a.out *~ 13 | -------------------------------------------------------------------------------- /units/030_types_and_ops/logical_operators.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/030_types_and_ops/logical_operators.jpg -------------------------------------------------------------------------------- /units/030_types_and_ops/op_precedence_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/030_types_and_ops/op_precedence_1.jpg -------------------------------------------------------------------------------- /units/030_types_and_ops/relational_operators.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/030_types_and_ops/relational_operators.jpg -------------------------------------------------------------------------------- /units/035_printing/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/035_printing/printing.cppmd: -------------------------------------------------------------------------------- 1 | # Printing messages 2 | 3 | `printf` prints a message to screen 4 | 5 | \footnotesize 6 | 7 | 16 | 17 | 21 | 22 | \normalsize 23 | 24 | `\n` at the end is a "newline" character, so subsequent output appears on the next line 25 | 26 | # Printing 27 | 28 | `printf` can handle numbers and other types 29 | 30 | \footnotesize 31 | 32 | 42 | 43 | 47 | 48 | # Printing 49 | 50 | `printf` is a function taking one or more *arguments* 51 | 52 | Arguments are comma-separated & specified between parentheses 53 | 54 | \footnotesize 55 | 56 | ```c 57 | printf("Hello, world!\n"); // one argument 58 | 59 | double y = 3.33; 60 | printf("%.2lf\n", y); // 2 arguments 61 | 62 | printf("%d items left; price: $%.2lf\n", 10, 44.44); // 3 args 63 | ``` 64 | 65 | # Printing 66 | 67 | First argument is a *format string* 68 | 69 | ``` 70 | "%d items left; price: $%.2f" 71 | ``` 72 | 73 | Format string contain format specifiers that start with `%` 74 | 75 | * Each specifies *type* of an item to print 76 | 77 | # Printing 78 | 79 | \begin{table}[ht] 80 | \centering 81 | \begin{tabular}{rrr} 82 | \hline 83 | Specifier & Type & Example output \\ 84 | \hline 85 | \texttt{\%d} & \texttt{int} & \texttt{-43} \\ 86 | \texttt{\%u} & \texttt{unsigned} & \texttt{77} \\ 87 | \texttt{\%f} & \texttt{float} & \texttt{3.333333} \\ 88 | \texttt{\%c} & \texttt{char} & \texttt{P} \\ 89 | \texttt{\%s} & string & \texttt{Hello, world!} \\ 90 | \hline 91 | \end{tabular} 92 | \end{table} 93 | 94 | Putting `l` just after the `%` modifies the type to be longer 95 | 96 | * `%ld` for `long` (instead of `int`) 97 | * `%lu` for `unsigned long` (instead of `unsigned`) 98 | * `%lf` for `double` (instead of `float`) 99 | 100 | 110 | 111 | 115 | 116 | # Printing 117 | 118 | ```c 119 | printf("Hello, world!\n"); 120 | ``` 121 | 122 | ``` 123 | Hello, world! 124 | ``` 125 | 126 | ```c 127 | printf("%d\n%d\n%d\n%c\n", 3, 2, 1, '!'); 128 | ``` 129 | 130 | ``` 131 | 3 132 | 2 133 | 1 134 | ! 135 | ``` 136 | 137 | ```c 138 | printf("%f rounded is %.2f\n", 10.0/3, 10.0/3); 139 | ``` 140 | 141 | ``` 142 | 3.333333 rounded is 3.33 143 | ``` 144 | 145 | # Printing 146 | 147 | Questions about types? 148 | 149 | * What is the difference between `int` and `long`? 150 | * How large are they? 151 | * How are they represented in the computer? 152 | * When and how can we convert between them? 153 | 154 | We will answer these when we discuss numeric representations 155 | 156 | -------------------------------------------------------------------------------- /units/040_decisions/.gitignore: -------------------------------------------------------------------------------- 1 | for_example* 2 | grading* 3 | if1* 4 | if2* 5 | if3* 6 | *.c 7 | a.out 8 | *.md 9 | *.pdf 10 | -------------------------------------------------------------------------------- /units/040_decisions/Makefile: -------------------------------------------------------------------------------- 1 | #!gmake 2 | 3 | CPPMD=python ../cppmd_render.py 4 | 5 | all: $(basename $(wildcard *.cppmd)).pdf 6 | 7 | %.pdf: %.cppmd 8 | $(CPPMD) --prefix $(@:%.pdf=%) --beamer-theme=metropolis --force < $< 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f *.pdf *.md *.c *.cpp *.h *.hpp a.out *~ 13 | -------------------------------------------------------------------------------- /units/040_decisions/compound_assign.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/040_decisions/compound_assign.jpg -------------------------------------------------------------------------------- /units/040_decisions/incr_decr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/040_decisions/incr_decr.jpg -------------------------------------------------------------------------------- /units/050_arrays/.gitignore: -------------------------------------------------------------------------------- 1 | string_copy_2.c 2 | count_chars.c 3 | count_bases_1.c 4 | string_copy_1.c 5 | string_indexing_1.c 6 | convert_digit_7.c 7 | convert_digit_0.c 8 | *.pdf 9 | *.md 10 | a.out 11 | array_eg_4.c 12 | array_eg_1.c 13 | count_bases_1.c 14 | string_copy_1.c 15 | convert_digit_0.c 16 | array_eg_6.c 17 | array_eg_3.c 18 | array_eg_2.c 19 | count_chars.c 20 | string_copy_2.c 21 | string_indexing_1.c 22 | convert_digit_7.c 23 | array_eg_5.c 24 | convert_digit_7.c 25 | array_4.c 26 | string_copy_1.c 27 | count_bases_1.c 28 | string_indexing_1.c 29 | array_1.c 30 | convert_digit_0.c 31 | array_5.c 32 | array_6.c 33 | string_copy_2.c 34 | array_8.c 35 | count_chars.c 36 | array_3.c 37 | array_2.c 38 | array_7.c 39 | convert_digit_7.c 40 | array_4.c 41 | string_copy_1.c 42 | sizeof.c 43 | count_bases_1.c 44 | string_indexing_1.c 45 | array_1.c 46 | convert_digit_0.c 47 | array_5.c 48 | array_6.c 49 | string_copy_2.c 50 | array_8.c 51 | count_chars.c 52 | array_3.c 53 | array_2.c 54 | array_7.c 55 | -------------------------------------------------------------------------------- /units/050_arrays/arrays.cppmd: -------------------------------------------------------------------------------- 1 | # Arrays 2 | 3 | \centering 4 | \Large 5 | 6 | `int c[12];` 7 | 8 | \raggedright 9 | \normalsize 10 | \vspace{5mm} 11 | 12 | An *array* variable consists of several elements laid out consecutively in memory 13 | 14 | All elements have same type; `int` in this example 15 | 16 | Individual elements accessed with `[]` notation 17 | 18 | `[0]` refers to first element 19 | 20 | # Arrays 21 | 22 | 32 | 33 | 37 | 38 | # Arrays 39 | 40 | Square brackets go after the variable name, not after the type 41 | 42 | * Unlike Java! 43 | 44 | \footnotesize 45 | 46 | 52 | 53 | \scriptsize 54 | 55 | 58 | 59 | # Arrays 60 | 61 | *Danger*: Elements are undefined until explicitly initialized 62 | 63 | One way to initialize is with a loop: 64 | 65 | \footnotesize 66 | 67 | 78 | 79 | 83 | 84 | # Arrays 85 | 86 | Can initialize to a specified sequence of values 87 | 88 | Comma separated within `{` ... `}`: 89 | 90 | \footnotesize 91 | 92 | 100 | 101 | 105 | 106 | # Arrays 107 | 108 | When initializing with `{` ... `}`, array size can be omitted 109 | 110 | Compiler figures it out 111 | 112 | \footnotesize 113 | 114 | 123 | 124 | 128 | 129 | # Arrays 130 | 131 | \footnotesize 132 | 133 | 145 | 146 | 150 | 151 | \normalsize 152 | 153 | What would happen of some elements of `data` were `3`? 154 | 155 | # Arrays 156 | 157 | Typical array-related mistakes: 158 | 159 | * Failing to initialize 160 | 161 | * Element values are unpredictable (*undefined*) until initialized 162 | 163 | * Trying to access an element *out of bounds* 164 | 165 | * Later we will diagnose using `valgrind` 166 | 167 | # Arrays 168 | 169 | \footnotesize 170 | 171 | 183 | 184 | 188 | 189 | \normalsize 190 | 191 | Going out of bounds might not yield an explicit error (unlike Java & Python) and might not crash 192 | 193 | # Arrays 194 | 195 | \footnotesize 196 | 197 | 210 | 211 | 215 | 216 | ``` 217 | Segmentation fault: 11 218 | ``` 219 | 220 | \normalsize 221 | 222 | Going farther out of bounds increases chance that program will crash 223 | 224 | # Arrays 225 | 226 | `sizeof(x)` returns the number of bytes used to store `x` as an `unsigned long` 227 | 228 | \footnotesize 229 | 230 | 240 | 241 | 245 | 246 | \normalsize 247 | 248 | # Arrays 249 | 250 | Unlike Python, no "slicing" in C 251 | 252 | * E.g. can't access several elements at once using `c[1:4]` 253 | 254 | More discussion of arrays later: 255 | 256 | * How to pass them to and from functions 257 | * Their relationship to pointers 258 | 259 | -------------------------------------------------------------------------------- /units/060_chars_strings/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/060_chars_strings/Makefile: -------------------------------------------------------------------------------- 1 | #!gmake 2 | 3 | CPPMD=python ../cppmd_render.py 4 | 5 | all: $(basename $(wildcard *.cppmd)).pdf 6 | 7 | %.pdf: %.cppmd 8 | $(CPPMD) --prefix $(@:%.pdf=%) --beamer-theme=metropolis --force < $< 9 | 10 | .PHONY: clean 11 | clean: 12 | rm -f *.pdf *.md *.c *.cpp *.h *.hpp a.out *~ 13 | -------------------------------------------------------------------------------- /units/065_reading_input/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/065_reading_input/reading_input.cppmd: -------------------------------------------------------------------------------- 1 | # Reading input 2 | 3 | `printf` writes formatted output strings 4 | 5 | `scanf` reads formatted *input* strings 6 | 7 | Both use "format tags" we've already seen 8 | 9 | * `%d`: `int` 10 | * `%u`: `unsigned int` 11 | * `%f`: `float` or `double` 12 | * `%.3f`: `float` / `double`, up to 3 decimal places 13 | * `%e`: `float` / `double`, scientific notation 14 | 15 | # `scanf` 16 | 17 | \footnotesize 18 | 19 | 31 | 32 | 36 | 37 | # `scanf` 38 | 39 | `scanf("%d%f", &a, &b)`: read an integer and a floating-point number separated by whitespace; store integer in `a` and floating-point in `b` 40 | 41 | "Whitespace" means spaces, tabs & newlines. `scanf` allows any whitespace characters to separate items. 42 | 43 | We write `&a, &b` instead of `a, b` because `scanf` *modifies* them 44 | 45 | * `&` means "address-of"; more on this when we discuss pointers 46 | 47 | # `scanf` 48 | 49 | What does `echo "7 99.9" | ./a.out` do? 50 | 51 | \footnotesize 52 | 53 | 57 | 58 | \normalsize 59 | 60 | Prints "7 99.9" and runs `./a.out`, sending "7 99.9" to its "standard in" file 61 | 62 | # `scanf` 63 | 64 | `scanf` returns number of items successfully parsed 65 | 66 | It's good practice to *check this*; if it's not what you expect, something's wrong: 67 | 68 | \footnotesize 69 | 70 | ```c 71 | // if result is not 2, something unexpected happened 72 | if(scanf("%d%f", &a, &b) != 2) { 73 | puts("Parsing error"); 74 | return 1; // non-zero return value 75 | } 76 | ``` 77 | 78 | # `scanf` 79 | 80 | Reading a string with `scanf("%s", array)` is *unsafe* because the string may be longer than the array 81 | 82 | \footnotesize 83 | 84 | 99 | 100 | # `scanf` 101 | 102 | This is fine: 103 | 104 | 108 | 109 | This overflows the buffer: 110 | 111 | 114 | 115 | Unpredictable things can happen when you overflow a buffer 116 | 117 | * On my computer, it crashes 118 | * Can also result in security vulnerabilities 119 | 120 | # `scanf` 121 | 122 | Instead, include a number between `%` and `s` to put a limit on how many characters to read 123 | 124 | \footnotesize 125 | 126 | 141 | 142 | # `scanf` 143 | 144 | 148 | 149 | `"%9s"` means "read the string up to the ninth character" 150 | 151 | We use `"%9s"` instead of `"%10s"` because the number doesn't count the null terminator, which `scanf` also writes 152 | 153 | # `scanf` 154 | 155 | More `scanf` details: [`en.wikipedia.org/wiki/Scanf_format_string`](https://en.wikipedia.org/wiki/Scanf_format_string) 156 | 157 | # Character-by-character 158 | 159 | `putchar` writes a single character to standard output 160 | 161 | `getchar` reads a single character from standard input 162 | 163 | # Character-by-character 164 | 165 | \footnotesize 166 | 167 | 181 | 182 | 186 | 187 | # Line-by-line 188 | 189 | We'll defer discussion of line-by-line input until we discuss reading and writing from files 190 | 191 | 192 | -------------------------------------------------------------------------------- /units/070_command_line_args/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/070_command_line_args/command_line_args.cppmd: -------------------------------------------------------------------------------- 1 | # Command line arguments 2 | 3 | We talked about how to read input from standard in 4 | 5 | * `scanf` & `getchar` 6 | 7 | Another way to get input is with *command-line arguments* 8 | 9 | # Command-line arguments 10 | 11 | You are used to running programs with command-line arguments: 12 | 13 | * `mkdir cs220` -- makes a directory called `cs220` 14 | * `ls *.txt` -- lists all the files ending in `.txt` 15 | * `cd $HOME/programming` -- changes to the `$HOME/programming` directory 16 | 17 | C programs can take command-line arguments, but we must tell the `main` function how to receive them 18 | 19 | # Command-line arguments 20 | 21 | 32 | 33 | \footnotesize 34 | 35 | 39 | 40 | # Command-line arguments 41 | 42 | `main(int argc, char* argv[])` 43 | 44 | * `int argc` equals the number of command-line arguments. Program name (e.g. `./a.out`) is always included first. 45 | 46 | * `char* argv[]` is an array of strings, one per command-line argument. 47 | * Sometimes written as `char **argv`; means the same thing 48 | 49 | # Command-line arguments 50 | 51 | \footnotesize 52 | 53 | 68 | 69 | 73 | 74 | -------------------------------------------------------------------------------- /units/080_assertions/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/080_assertions/assertions.cppmd: -------------------------------------------------------------------------------- 1 | # Assertions 2 | 3 | Help to: 4 | 5 | * Catch bugs as close to the source as possible 6 | * Document and enforce *assumptions* and *invariants* 7 | 8 | # Assertions 9 | 10 | ```c 11 | #include 12 | 13 | assert(true/false expression); 14 | ``` 15 | 16 | If `boolean expression` is false: 17 | 18 | * Program exits immediately 19 | * Exit level is non-zero, like when `main` returns non-zero 20 | * Message is printed like: 21 | 22 | \footnotesize 23 | 24 | ``` 25 | Assertion failed: (denom != 0), function main, file foo.c, line 95. 26 | ``` 27 | 28 | # Assertions 29 | 30 | Document your assumptions: 31 | 32 | ```c 33 | int sum = a*a + b*b; 34 | assert(sum >= 0); 35 | ``` 36 | 37 | \vspace{8mm} 38 | 39 | ```c 40 | if(isalpha(c)) { 41 | assert(c >= 'A'); 42 | printf("%d\n", c - 'A'); 43 | } 44 | ``` 45 | 46 | # Assertions 47 | 48 | `assert` is not for typical error checking 49 | 50 | \footnotesize 51 | 52 | ```c 53 | FILE* input = fopen("numbers.txt", "r"); 54 | if(input == NULL) { 55 | printf("Error: could not open input file\n"); 56 | return 1; // indicate error 57 | } 58 | ``` 59 | 60 | # Assertions 61 | 62 | If checking for bad user input, or something else that is *strange but not impossible*: 63 | 64 | * Use `if`, 65 | * print a meaningful message, and 66 | * if you must exit, return non-zero from `main` to indicate failure 67 | 68 | For conditions that imply *your program is incorrect*, use `assert` 69 | 70 | # Assertions 71 | 72 | \scriptsize 73 | 74 | 92 | 93 | # Assertions 94 | 95 | \footnotesize 96 | 97 | 101 | 102 | 105 | 106 | 109 | 110 | ``` 111 | $ echo 200000000 | ./a.out 112 | Assertion failed: (n_sq >= n), function main, 113 | file assert_eg.c, line 12. 114 | ``` 115 | 116 | \normalsize 117 | 118 | Due to overflow of `int`! 119 | 120 | * We'll talk more about overflow later 121 | 122 | -------------------------------------------------------------------------------- /units/090_math/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/090_math/math.cppmd: -------------------------------------------------------------------------------- 1 | # Math functions 2 | 3 | `#include math.h` **and** compile with `-lm` option to gain access to these basic mathematical functions: 4 | 5 | * `sqrt(x)`: square root 6 | * `pow(x, y)`: $x^y$ 7 | * `exp(x)`: $e^x$ 8 | * `log(x)`: natural log 9 | * `log10(x)`: log base 10 10 | * `ceil(x)` / `floor(x)`: round up / down to nearest integer 11 | * `sin(x)`: sine (other trigonometric functions available) 12 | 13 | # Math functions 14 | 15 | $x$ and $y$ arguments have type `double` 16 | 17 | It's also OK to pass another numeric type, like `int` 18 | 19 | * Argument type promotion: `int` -> `float` -> `double` 20 | 21 | `-lm` includes the math library when *linking* 22 | 23 | # Math functions 24 | 25 | \scriptsize 26 | 27 | 41 | 42 | \footnotesize 43 | 44 | 48 | 49 | 52 | 53 | -------------------------------------------------------------------------------- /units/100_compile_link/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/100_compile_link/compile_link.cppmd: -------------------------------------------------------------------------------- 1 | # Compiling and linking 2 | 3 | We've seen: 4 | 5 | * How to compile with `gcc`, creating an executable `a.out` 6 | * How to use libraries by adding `#include` to the source 7 | * How to use libraries by adding `-l` to the `gcc command` 8 | * E.g. `-lm` for math library 9 | * The difference between *declaring* and *defining* a variable 10 | 11 | These ideas come into sharper focus when we think about all that happens when we run `gcc` 12 | 13 | # Compiling and linking 14 | 15 | What `gcc` does can be divided into three phases: 16 | 17 | 1. *Preprocessing*: bring all the relevant code together 18 | 2. *Compiling*: turn the human-readable source code into machine-readable object files 19 | 3. *Linking*: bring all relevant object files together into a binary executable 20 | 21 | -------------------------------------------------------------------------------- /units/110_functions/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | a.out 3 | *.pdf 4 | *.md 5 | -------------------------------------------------------------------------------- /units/120_program_structure/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | a.out 4 | *.pdf 5 | *.md 6 | -------------------------------------------------------------------------------- /units/120_program_structure/program_structure.cppmd: -------------------------------------------------------------------------------- 1 | # Program structure 2 | 3 | Big C projects are split across many `.c` source files 4 | 5 | Header (`.h`) are part of the "glue" for combining `.c` files 6 | 7 | # Program structure 8 | 9 | \centerline{\includegraphics[width=4.3in]{../images/interest_structure.png}} 10 | 11 | `main` calls `compound`; `compound` is defined in a different `.c` file 12 | 13 | Two problems: 14 | 15 | * `main` needs to be preceded by a prototype for `compound` 16 | * `main.c` and `interest.c` need to be compiled *together* somehow 17 | 18 | # Headers 19 | 20 | \vspace{4mm} 21 | 22 | \centerline{\includegraphics[width=4.3in]{../images/interest_header.png}} 23 | 24 | Header (`.h`) files contain prototypes & declarations allowing code in one `.c` file to use functions & variables in another 25 | 26 | `interest.h` has a prototype for `compound` 27 | 28 | * `#include "interest.h"` allows us to use it 29 | 30 | # Headers 31 | 32 | When `#include`'ing a `.h` *you created*, use `"` `"` instead of `<` `>` 33 | 34 | ```c 35 | #include // provided by C 36 | #include // provided by C 37 | #include "interest.h" // I wrote this 38 | ``` 39 | 40 | # Headers 41 | 42 | 46 | 47 | 55 | 56 | 66 | 67 | Compile the two `.c` files together by simply specifying both as arguments to `gcc`: 68 | 69 | \footnotesize 70 | 71 | 75 | 76 | \normalsize 77 | 78 | You don't have to tell `gcc` about the `.h` files; the `#include` statements take care of that 79 | 80 | # Headers 81 | 82 | What if we forget to `#include "interest.h"`? 83 | 84 | 93 | 94 | \footnotesize 95 | 96 | 100 | 101 | \normalsize 102 | 103 | A compiler warning and a wrong answer; what happened? 104 | 105 | * Hint: look back at notes on functions 106 | 107 | # Steps of compilation 108 | 109 | We discussed compilation steps when we first saw ``Hello, World!'' 110 | 111 | 1. Preprocessor 112 | 113 | * Gather relevant source code 114 | * Handle `#include`'s and `#define`'s 115 | 116 | 2. Compiler 117 | 118 | * Gather preproessed code and compile to object code 119 | * If using `-c`, stop here and output `.o` files 120 | 121 | 3. Linker 122 | 123 | * Gather *object code* into a single executable file 124 | 125 | # Steps of compilation 126 | 127 | Steps 1/2 and 3 can be separate 128 | 129 | \footnotesize 130 | 131 | ``` 132 | # Steps 1 & 2 -- preprocess and compile to separate .o's 133 | gcc main.c -c -std=c99 -pedantic -Wall -Wextra -lm 134 | gcc interest.c -c -std=c99 -pedantic -Wall -Wextra -lm 135 | 136 | # Step 3 -- combine .o's into single executable 137 | gcc -o main main.o interest.o 138 | ``` 139 | 140 | \normalsize 141 | 142 | Or they can all happen at once 143 | 144 | \footnotesize 145 | 146 | ``` 147 | # Steps 1, 2 & 3 148 | gcc -o main main.c interest.c -c -std=c99 -pedantic -Wall -Wextra -lm 149 | ``` 150 | 151 | -------------------------------------------------------------------------------- /units/130_makefiles/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | Makefile 8 | interest-example -------------------------------------------------------------------------------- /units/130_makefiles/makefiles.cppmd: -------------------------------------------------------------------------------- 1 | # Makefiles 2 | 3 | For programs spread across many `.c` & `.h` files and executables, `make` and `Makefile`s tie things together 4 | 5 | `Makefile` expresses *dependence relationships* between files 6 | 7 | Defines *rules* for building one file from others 8 | 9 | # Makefiles 10 | 11 | 15 | 16 | 23 | 24 | 34 | 35 | Example that performs 3 steps (preprocess, compile, link) at once: 36 | 37 | * Some `gcc` arguments omitted for conciseness 38 | 39 | 43 | 44 | First line says `interest-example` depends on `interest.c`, `interest.h` and `main.c` 45 | 46 | Second line gives command for building `interest-example` 47 | 48 | # Makefiles 49 | 50 | 54 | 55 | # Makefiles 56 | 57 | This version performs steps 1 & 2 (preprocess and compile) separately from step 3 (link) 58 | 59 | 62 | 63 | 74 | 75 | # Makefiles 76 | 77 | 80 | 81 | 85 | 86 | # Makefiles 87 | 88 | `Makefile`s can get repetitive, e.g. if we re-write the `gcc` arguments for every rule. Use *variables* to simplify: 89 | 90 | \footnotesize 91 | 92 | ``` 93 | CC = gcc 94 | CFLAGS = -std=c99 -Wall -Wextra -pedantic 95 | 96 | interest-example: interest.c interest.h main.c 97 | $(CC) -o interest-example interest.c main.c $(CFLAGS) -lm 98 | ``` 99 | 100 | \normalsize 101 | 102 | `$(CC)` is replaced by `gcc` 103 | 104 | `$(CFLAGS)` is replaced by `-std=c99 -Wall -Wextra -pedantic` 105 | 106 | # Vocabulary 107 | 108 | \footnotesize 109 | 110 | ``` 111 | interest-example: interest.c interest.h main.c 112 | $(CC) -o interest-example interest.c main.c $(CFLAGS) -lm 113 | ``` 114 | 115 | \normalsize 116 | 117 | `interest-example` is the *target* 118 | 119 | `interest.c interest.h main.c` are the *prerequisites* 120 | 121 | `$(CC) -o interest-example ...` is the *command * 122 | 123 | All these together make up a *rule* 124 | 125 | # Makefiles 126 | 127 | \footnotesize 128 | 129 | ``` 130 | interest-example: interest.c interest.h main.c 131 | $(CC) $(CFLAGS) -o interest-example interest.c main.c 132 | ``` 133 | 134 | \normalsize 135 | 136 | `make interest-example` asks `make` to build `interest-example` target, **if...** 137 | 138 | \footnotesize 139 | 140 | * `interest-example` doesn't exist, *or* 141 | * `interest.c` has changed more recently than `interest-example`, *or* 142 | * `interest.h` has changed more recently than `interest-example`, *or* 143 | * `main.c` has changed more recently than `interest-example` 144 | 145 | \normalsize 146 | 147 | If *any* are true, corresponding command is run 148 | 149 | # Makefiles 150 | 151 | `make` looks at the ``whole picture'' of how targets are interrelated when deciding what to build 152 | 153 | If you want to build target `A` **and** 154 | 155 | * `A` depends on `B` *and* 156 | * `B` depends on `C` *and* 157 | * `B` is out of date (i.e. `C` is newer than `B`) 158 | 159 | ...then `make` builds `B` first, then builds `A` 160 | 161 | # Makefiles 162 | 163 | For `make` to work, you must be in the same directory with the `Makefile` 164 | 165 | * Advanced: use `make -C` if in a different directory 166 | 167 | `Makefile` has to be called `Makefile` 168 | 169 | * Advanced: use `make -f ` if it's not called `Makefile` 170 | 171 | Typing `make` without specifying a target builds the *default target*; whichever appears first in the `Makefile` 172 | 173 | # Makefiles 174 | 175 | A *very* common mistake is to use spaces instead of tabs 176 | 177 | \footnotesize 178 | 179 | 186 | 187 | \normalsize 188 | 189 | You can't tell by looking, but I put 4 spaces instead of a tab before the `$(CC)` command 190 | 191 | # Makefiles 192 | 193 | \footnotesize 194 | 195 | 198 | 199 | \normalsize 200 | 201 | "`missing separator`" usually means you used spaces instead of tab 202 | 203 | `emacs` *should* notice you're editing a `Makefile` and use tabs where appropriate; you can force `emacs` to use tab with `Ctrl-q ` 204 | 205 | # Makefile tutorials 206 | 207 | [`mrbook.org/blog/tutorials/make/`](http://mrbook.org/blog/tutorials/make/) 208 | 209 | * Uses `g++`/`.cpp` instead of `gcc`/`.c`, but ideas are the same 210 | 211 | [`www.cs.bu.edu/teaching/cpp/writing-makefiles/`](http://www.cs.bu.edu/teaching/cpp/writing-makefiles/) 212 | 213 | * Uses `g++`/`.cpp` instead of `gcc`/`.c`, but ideas are the same 214 | 215 | [`cslibrary.stanford.edu/107/UnixProgrammingTools.pdf`](http://cslibrary.stanford.edu/107/UnixProgrammingTools.pdf) 216 | 217 | * Section 2 218 | 219 | -------------------------------------------------------------------------------- /units/140_memory/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | Makefile 8 | interest-example -------------------------------------------------------------------------------- /units/140_memory/figs.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/140_memory/figs.key -------------------------------------------------------------------------------- /units/140_memory/memory.cppmd: -------------------------------------------------------------------------------- 1 | # Memory 2 | 3 | Variables live in memory 4 | 5 | Each variable has an ``address'' in memory, like a house address 6 | 7 | \vspace{5mm} 8 | 9 | \centerline{\includegraphics[width=3in]{../images/houses.png}} 10 | 11 | \centering 12 | \tiny 13 | 14 | [commons.wikimedia.org/wiki/File:South-Los-Angeles-subdivision-houses-near-Darby-Park-Aerial-view-from-north-August-2014.jpg](https://commons.wikimedia.org/wiki/File:South-Los-Angeles-subdivision-houses-near-Darby-Park-Aerial-view-from-north-August-2014.jpg) 15 | 16 | # Memory 17 | 18 | Or like a post-office box: 19 | 20 | \vspace{5mm} 21 | 22 | \centerline{\includegraphics[width=3in]{../images/mailboxes.png}} 23 | 24 | # Memory 25 | 26 | In this example, `fahrenheit` and `celsius` are variables that live at addresses in memory 27 | 28 | \footnotesize 29 | 30 | 40 | 41 | # Memory 42 | 43 | Memory is like a large array of bytes, like `char[]` 44 | 45 | * An *address* is an *offset* into the array 46 | * When a variable occupies >1 byte, address points to *first* byte 47 | 48 | # Memory 49 | 50 | `int` and `float` both take 4 bytes, so we might picture them in memory like this: 51 | 52 | \vspace{3mm} 53 | 54 | \centerline{\includegraphics[width=4in]{../images/mem_fc.png}} 55 | 56 | We'll see diagrams like this frequently 57 | 58 | Imagine the leftmost slot's address is 0, the next is 1, etc 59 | 60 | In this figure, `fahrenheit` is at address 3 and `celsius` us at 7 61 | 62 | # Memory 63 | 64 | We can't generally predict what addresses our variables will be at 65 | 66 | E.g. any of these would have been possible: 67 | 68 | \vspace{5mm} 69 | 70 | \centerline{\includegraphics[width=4in]{../images/mem_fc2.png}} 71 | 72 | # Memory 73 | 74 | Putting `&` before a variable name *takes its address* 75 | 76 | * We can print an address with `printf`: 77 | 78 | \footnotesize 79 | 80 | 91 | 92 | 96 | 97 | # Memory 98 | 99 | Two unfamiliar things here: 100 | 101 | * The `(void*)` before `&fahrenheit`; we will talk more about this when we cover pointers (soon) 102 | * The address itself: `0x7ffd56b72dcc` 103 | 104 | `0x7ffd56b72dcc` is just a number! 105 | 106 | * `0x` at beginning indicates it's base-16, or *hexadecimal* 107 | * In base-16, digits `0` -- `9` aren't enough so use `a` -- `f` as well 108 | * This number is 140,726,058,298,828 in decimal 109 | 110 | # Pointers 111 | 112 | \centerline{\includegraphics[width=2.75in]{../images/pointers_xkcd.png}} 113 | 114 | \centering 115 | \scriptsize 116 | 117 | [xkcd.com/138/](https://xkcd.com/138/) 118 | 119 | -------------------------------------------------------------------------------- /units/150_pointers/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | swap? 8 | ptr_eg? 9 | decay1 10 | ptr_null_eg2 11 | ptr_sizeof_eg1 12 | Makefile 13 | interest-example -------------------------------------------------------------------------------- /units/150_pointers/figs.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/150_pointers/figs.key -------------------------------------------------------------------------------- /units/160_ptrs_arrays/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | Makefile 8 | decay1 9 | ptr_sizeof_eg1 10 | -------------------------------------------------------------------------------- /units/160_ptrs_arrays/ptrs_arrays.cppmd: -------------------------------------------------------------------------------- 1 | # Pointers & arrays 2 | 3 | Pointers and arrays are closely related 4 | 5 | Say we have array `int a[]`. 6 | 7 | * `a[0]` and `*a` are equivalent 8 | * `[`...`]` is a combination of dereferencing and pointer addition 9 | * `*(a + 3)` is a synonym for `a[3]` 10 | * `(a + 3)` is a synonym for `&a[3]` 11 | 12 | # Pointers & arrays 13 | 14 | You'll notice the differences between arrays and pointers when using `sizeof` 15 | 16 | \footnotesize 17 | 18 | 28 | 29 | 34 | 35 | # Pointers & arrays 36 | 37 | Passing array as argument *converts it to a pointer*, losing any information about how long it is 38 | 39 | * Sometimes called ``array decaying'' 40 | 41 | # Pointers & arrays 42 | 43 | \footnotesize 44 | 45 | 61 | 62 | # Pointers & arrays 63 | 64 | \tiny 65 | 66 | 70 | 71 | \normalsize 72 | 73 | Compiler warns you 74 | 75 | # Pointers & arrays 76 | 77 | This fits with what we know 78 | 79 | * Passing an array is "pass by pointer," since arrays decay into pointers when passed 80 | * This is also why we can modify an array in the callee and see the changes in the caller 81 | 82 | -------------------------------------------------------------------------------- /units/170_lifetime_scope/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | 8 | scope2 9 | -------------------------------------------------------------------------------- /units/170_lifetime_scope/lifetime_scope.cppmd: -------------------------------------------------------------------------------- 1 | # Lifetime & scope 2 | 3 | Variable's *lifetime* is the period when it exists in memory 4 | 5 | * When lifetime ends, memory is reclaimed and can be reused for other variables 6 | 7 | Variable's *scope* is the part of the program where you can use it 8 | 9 | * Lifetime and scope are *often* the same *but not always* 10 | 11 | # Lifetime & scope 12 | 13 | Scope and lifetime of a variable declared in a block `{`...`}` ends at terminal brace `}` 14 | 15 | ```c 16 | if(a == 7) { 17 | int c = 70; 18 | printf("%d\n", c); 19 | } 20 | ``` 21 | 22 | When program reaches `}`, `c` is both *out of scope* (we can't refer to it anymore) and *dead* (memory reclaimed) 23 | 24 | # Lifetime & scope 25 | 26 | For `for` loop index variable, scope is the loop body 27 | 28 | ```c 29 | for(int i = 0; i < 10; i++) { 30 | sum += i; 31 | } 32 | // after }, i is "dead" and "out of scope" 33 | ``` 34 | 35 | # Lifetime & scope 36 | 37 | Variables in scope at the time of a function call are *not* in scope in the callee 38 | 39 | \footnotesize 40 | 41 | 55 | 56 | # Lifetime & scope 57 | 58 | Pointers give a way around this: 59 | 60 | \footnotesize 61 | 62 | 75 | 76 | 80 | 81 | -------------------------------------------------------------------------------- /units/180_stack_heap/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | 8 | scope2 9 | -------------------------------------------------------------------------------- /units/180_stack_heap/stack1.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/180_stack_heap/stack1.key -------------------------------------------------------------------------------- /units/180_stack_heap/stack_heap.cppmd: -------------------------------------------------------------------------------- 1 | # Stack & heap 2 | 3 | We think of scope and lifetime in the context of *the stack* (or the *call stack*), which grows upwards as: 4 | 5 | * New local variables are declared 6 | * Functions call other functions 7 | 8 | The bottom of the call stack is always `main` and its local variables 9 | 10 | # Stack 11 | 12 | \centerline{\includegraphics[width=4in]{../images/call_stack1.png}} 13 | 14 | Upon function call, caller saves a "bookmark" for where to return to when callee finishes. Then room is made on the stack for the callee and its variables. 15 | 16 | # Stack 17 | 18 | When functions return or when scopes are exited, stack shrinks 19 | 20 | *Stack overflow* is when the stack grows so large it exhausts available memory 21 | 22 | * E.g. because of a recursive function that never returns 23 | 24 | # Stack 25 | 26 | Explains why a function can't return a locally-declared array: 27 | 28 | \centerline{\includegraphics[width=4in]{../images/call_stack2.png}} 29 | 30 | # Stack arrays 31 | 32 | When we declare an array, its size must be a "compile-time constant" 33 | 34 | \vspace{3mm} 35 | 36 | ```c 37 | int array[400]; // we can do this 38 | ``` 39 | 40 | \vspace{1mm} 41 | 42 | ```c 43 | #define ARRAY_SIZE 400 44 | int array[ARRAY_SIZE]; // this is also fine 45 | ``` 46 | 47 | \vspace{3mm} 48 | 49 | `#define X Y` just means that everytime `X` appears in the program, it should be replaced with `Y`. It's a "macro" rather than a variable because the substitution happens in the "preprocessing" step, prior to compilation. 50 | 51 | # Stack arrays 52 | 53 | 54 | ```c 55 | int n = get_length_of_array(); 56 | int array[n]; // we shouldn't do this 57 | ``` 58 | 59 | \vspace{7mm} 60 | 61 | C99 lets you do this, but earlier versions of C don't 62 | 63 | It's considered bad style because it's easy to accidentally overflow the stack 64 | 65 | * This is the only time you'll see it in these slides 66 | 67 | # Dynamic memory allocation 68 | 69 | We're about to discuss dynamic memory allocation, where many of these issues are addressed: 70 | 71 | * Flexible lifetime; we decide when allocated memory is allocated and deallocated (reclaimed) 72 | * Allocated memory is *not* on the stack, can't cause stack overflow 73 | * Allocation size need not be known at compile time 74 | * Can be a function of variables in the program 75 | 76 | # Stack vs. heap 77 | 78 | So far, our variables and functions have used *the stack* to store data 79 | 80 | We will soon be using a different area called *the heap* 81 | 82 | \vspace{4mm} 83 | 84 | \centerline{\includegraphics[width=3.5in]{../images/stack_heap.png}} 85 | 86 | # Stack vs. heap 87 | 88 | Stack: We declare variables; lifetime same as scope 89 | 90 | * C takes care of allocating/deallocating memory as variables enter/exit scope 91 | 92 | Heap: Lifetime is under our control 93 | 94 | * We explicitly allocate and deallocate 95 | 96 | * E.g. with `malloc` and `free`, discussed later 97 | 98 | * Operating System is places variables in memory in a non-overlapping way 99 | 100 | -------------------------------------------------------------------------------- /units/190_dynamic_mem/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | realloc_eg1 8 | scale_dynamic 9 | sizeof_all 10 | -------------------------------------------------------------------------------- /units/200_valgrind/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | buggy_strcpy 8 | fixed_strcpy 9 | valgrind_eg1 10 | -------------------------------------------------------------------------------- /units/210_gdb/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | str_rev 8 | str_rev2 9 | -------------------------------------------------------------------------------- /units/210_gdb/gdb.cppmd: -------------------------------------------------------------------------------- 1 | # Debugging with `gdb` 2 | 3 | `gdb`: GNU debugger 4 | 5 | `gdb` helps you run your program in a way that allows you to: 6 | 7 | * flexibly *pause* and *resume* 8 | * print out the values of variables mid-stream 9 | * see where severe errors like `Segmentation Fault`s happen 10 | 11 | When using `gdb` (or `valgrind`) we compile with `-g`, which packages up the source code ("debug symbols") along with the executable 12 | 13 | # `gdb` 14 | 15 | Keep this "cheat sheet" nearby as you read on: 16 | 17 | [bit.ly/gdb_cheat](http://bit.ly/gdb_cheat) 18 | 19 | 20 | 21 | # `gdb` 22 | 23 | Buggy program: 24 | 25 | \scriptsize 26 | 27 | 46 | 47 | # `gdb` 48 | 49 | We are trying to reverse a string by starting at the left and right extremes, swapping the characters, then continuing inward, swapping as we go until we've reversed the whole thing. 50 | 51 | \footnotesize 52 | 53 | 57 | 58 | \normalsize 59 | 60 | Oops, I expected output to be `BBBAAA` 61 | 62 | `valgrind` gives clean report, so likely not an issue with mishandled pointers 63 | 64 | # `gdb` 65 | 66 | We'll use `gdb` to investigate 67 | 68 | Since the problem would seem to be in the `string_reverse` function, I am going to start my program at the beginning and then take small steps forward until I get to the loop. 69 | 70 | # `gdb` 71 | 72 | \footnotesize 73 | 74 | ``` 75 | (gdb) break main 76 | Breakpoint 1 at 0x4005ad: file str_rev.c, line 13. 77 | (gdb) run 78 | Starting program: /app/str_rev 79 | 80 | Breakpoint 1, main () at str_rev.c:13 81 | 13 char reverse_me[] = "AAABBB"; 82 | ``` 83 | 84 | \normalsize 85 | 86 | `break main` because I want to debugger to pause as soon I as get to the beginning of the program, i.e. the `main` function 87 | 88 | `run` to start the program, which immediately pauses at top of `main` 89 | 90 | After running a command, `gdb` prints out the next line of code in the program 91 | 92 | # `gdb` 93 | 94 | \footnotesize 95 | 96 | ``` 97 | (gdb) next 98 | 14 string_reverse(reverse_me); 99 | (gdb) step 100 | string_reverse (str=0x7fffffffe629 "AAABBB") at str_rev.c:5 101 | 5 const int len = strlen(str); 102 | ``` 103 | 104 | \normalsize 105 | 106 | `next` executes the statement on the current line and moves onto the next. If the statement contains a function call, `gdb` executes it without pausing. 107 | 108 | `step` begins to execute the statement on the current line. If the statement contains a function call, it *steps into* the function and pauses there. Otherwise, it behaves like `next`. 109 | 110 | Now we're at the beginning of `string_reverse` 111 | 112 | # `gdb` 113 | 114 | \footnotesize 115 | 116 | ``` 117 | (gdb) n 118 | 6 for(int i = 0; i < len; i++) { 119 | (gdb) print len 120 | $2 = 6 121 | ``` 122 | 123 | \normalsize 124 | 125 | `n` is short for `next` 126 | 127 | `print` prints out the value of a variable. `len` is `6` -- that's what we expected. So far so good. 128 | 129 | We're about to enter the loop. 130 | 131 | # `gdb` 132 | 133 | \footnotesize 134 | 135 | ``` 136 | (gdb) n 137 | 7 str[i] = str[len-i-1]; // swap characters 138 | (gdb) p i 139 | $3 = 0 140 | (gdb) p str[i] 141 | $4 = 65 'A' 142 | (gdb) p str[len-i-1] 143 | $5 = 66 'B' 144 | ``` 145 | 146 | \normalsize 147 | 148 | `p` is short for `print` 149 | 150 | `i`'s initial value is 0, as expected 151 | 152 | The elements we're swapping really are the first `A` and the last `B`, as expected 153 | 154 | # `gdb` 155 | 156 | Let's execute the swap: 157 | 158 | \footnotesize 159 | 160 | ``` 161 | (gdb) n 162 | 8 str[len-i-1] = str[i]; 163 | (gdb) n 164 | 6 for(int i = 0; i < len; i++) { 165 | (gdb) p i 166 | $6 = 0 167 | ``` 168 | 169 | \normalsize 170 | 171 | Just finished the first iteration; `i` still equals `0` 172 | 173 | # `gdb` 174 | 175 | Let's see if the swap was successful: 176 | 177 | \footnotesize 178 | 179 | ``` 180 | (gdb) p str[i] 181 | $7 = 66 'B' 182 | (gdb) p str[len-i-1] 183 | $8 = 66 'B' 184 | ``` 185 | 186 | \normalsize 187 | 188 | No -- the swap fails because I overwrite `str[i]` with the value of `str[len-i-1]` *before* copying it into `str[len-i-1]` 189 | 190 | This explains why the result is `BBBBBB` 191 | 192 | I need to use a temporary variable like we did previously with `swap` 193 | 194 | # `gdb` 195 | 196 | Fixed?: 197 | 198 | \scriptsize 199 | 200 | 220 | 221 | # `gdb` 222 | 223 | \footnotesize 224 | 225 | 229 | 230 | \normalsize 231 | 232 | Still not working! I expected output to be `BBBAAA` 233 | 234 | Exercise: use `gdb` to find lingering bug. 235 | 236 | Hint 1: examine results of the swaps through *several* loop iterations 237 | 238 | Hint 2: Instead of `break main`, use `break str_rev2.c:7`, replacing `str_rev2.c` with the name of your source file and `7` with the line number of the first statement in the loop body. That way `run` will advance directly there. (If you already set the `main` breakpoint, remove it with `delete`.) 239 | 240 | # `gdb` help 241 | 242 | Type `help` at the `(gdb)` prompt for help 243 | 244 | * `(gdb) help running` -- for advancing thru program 245 | * `(gdb) help show` -- for printing commands 246 | 247 | There are *many* `gdb` commands, so I prefer brief "cheat sheets": 248 | 249 | * [darkdust.net/files/GDB%20Cheat%20Sheet.pdf](http://darkdust.net/files/GDB%20Cheat%20Sheet.pdf) 250 | 251 | -------------------------------------------------------------------------------- /units/220_structs/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | nested_struct 8 | sizeof_plane 9 | sizeof_receipt 10 | struct_array 11 | struct_eg1 12 | struct_next_day_1 13 | struct_next_day_2 14 | struct_sizeof 15 | struct_sizeof_album 16 | struct_sizeof_receipt 17 | tennis 18 | -------------------------------------------------------------------------------- /units/230_beyond_1d/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | -------------------------------------------------------------------------------- /units/230_beyond_1d/beyond_1d.cppmd: -------------------------------------------------------------------------------- 1 | # Beyond 1D arrays 2 | 3 | We've already seen `char* argv[]`: an array of strings 4 | 5 | \footnotesize 6 | 7 | 18 | 19 | 23 | 24 | # Arrays of strings 25 | 26 | \footnotesize 27 | 28 | 46 | 47 | # Arrays of strings 48 | 49 | 53 | 54 | # Arrays of strings 55 | 56 | ```c 57 | char *message1[] = { "Hello", "world!" }; 58 | char *message2[] = { "Have", "a", "nice", "day" }; 59 | ``` 60 | 61 | \vspace{6mm} 62 | 63 | \centerline{\includegraphics[width=3in]{../images/arr_string.png}} 64 | 65 | # Two-dimensional arrays 66 | 67 | Say we want to represent a tic tac toe board 68 | 69 | \vspace{4mm} 70 | 71 | \centerline{\includegraphics[width=1.4in]{../images/tictactoe.png}} 72 | 73 | An array seems appropriate, but we want a *two-dimensional* array 74 | 75 | For each element, we'll use a `char`: (`'X'`, `'O'` or `'-''`) 76 | 77 | # Two-dimensional arrays 78 | 79 | Option 1: 80 | 81 | ```c 82 | char board[9]; 83 | ``` 84 | 85 | `board` is a *one-dimensional* array with 9 elements, but we use it to represent a 3x3 board 86 | 87 | To access element at row `i`, column `j`, use `board[i * 3 + j]` 88 | 89 | \vspace{4mm} 90 | 91 | \centerline{\includegraphics[width=2.75in]{../images/rowcol.png}} 92 | 93 | This is *row-major* order; it is common in practice 94 | 95 | # Two-dimensional arrays 96 | 97 | \scriptsize 98 | 99 | 119 | 120 | # Two-dimensional arrays 121 | 122 | \footnotesize 123 | 124 | 128 | 129 | # Two-dimensional arrays 130 | 131 | Option 2: 132 | 133 | ```c 134 | char board[3][3]; 135 | ``` 136 | 137 | `board` is a *two-dimensional* array with 3 rows and 3 columns 138 | 139 | C "understands" the rows and columns; to access element at row `i`, column `j`, use `board[i][j]` 140 | 141 | \vspace{4mm} 142 | 143 | \centerline{\includegraphics[width=2.75in]{../images/rowcol2.png}} 144 | 145 | # Two-dimensional arrays 146 | 147 | \scriptsize 148 | 149 | 169 | 170 | # Two-dimensional arrays 171 | 172 | \footnotesize 173 | 174 | 178 | 179 | # Two-dimensional arrays 180 | 181 | Type of the array parameter is important; we *must* specify the parameter type along with 182 | 183 | ```c 184 | void print_board(char board[][3]) { 185 | // ... 186 | } 187 | ``` 188 | 189 | -------------------------------------------------------------------------------- /units/230_beyond_1d/figs.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/230_beyond_1d/figs.key -------------------------------------------------------------------------------- /units/240_binary_io/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | bio_eg1.bin 8 | -------------------------------------------------------------------------------- /units/240_binary_io/binary_io.cppmd: -------------------------------------------------------------------------------- 1 | # Binary I/O 2 | 3 | When reading from a filehandle, we have used `fgets` and `fscanf` 4 | 5 | These are for *parsing text*, i.e. turning strings like "0.435" and "999" into `float`s, `int`s, etc 6 | 7 | But you can also read and write data (`float`s, `int`s, `struct`s etc) as *binary* data, without turning them into strings first 8 | 9 | For midterm project, we will read and write PPM files, using binary I/O 10 | 11 | # `fwrite` 12 | 13 | ```c 14 | size_t fwrite(const void *data, size_t size, 15 | size_t nitems, FILE *stream); 16 | ``` 17 | 18 | * `data`: pointer to data to be written 19 | * `size`: size of 1 item 20 | * `nitems`: # items to write 21 | * `stream`: filehandle to write to 22 | * Must have been opened in `"wb"` mode 23 | 24 | Returns the number of items successfully written 25 | 26 | * If return value `!= nitems`, there was an error; check `ferror` 27 | 28 | # `fread` 29 | 30 | ```c 31 | size_t fread(void *data, size_t size, 32 | size_t nitems, FILE * stream); 33 | ``` 34 | 35 | * `data`: data should be copied to here 36 | * There needs to be enough space! `size * nitems` bytes 37 | * `size`: size of 1 item 38 | * `nitems`: # items to read 39 | * `stream`: filehandle to read from 40 | * Must have been opened in `"rb"` mode 41 | 42 | Returns the number of items successfully read 43 | 44 | * If return value `!= nitems`, there was an error; check `ferror` 45 | 46 | # Binary I/O 47 | 48 | \tiny 49 | 50 | 79 | 80 | # Binary I/O 81 | 82 | \footnotesize 83 | 84 | 88 | 89 | -------------------------------------------------------------------------------- /units/250_numeric_types/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | overflow 8 | -------------------------------------------------------------------------------- /units/250_numeric_types/casting_promotion.cppmd: -------------------------------------------------------------------------------- 1 | # Numeric types 2 | 3 | In computers, all data are stored in binary 4 | 5 | Binary is the number system where each digit is a power of 2 6 | 7 | We are used to powers of 10 (decimal) 8 | 9 | \vspace{5mm} 10 | 11 | \centerline{\includegraphics[width=3in]{../images/binary-finger-numbers.png}} 12 | 13 | \centering 14 | \tiny 15 | 16 | https://biscitmx.com/category/unplugged/ 17 | 18 | # Bits and binary 19 | 20 | If we used our fingers to count in binary, we could count to $2^{10}-1 = 1023$ 21 | 22 | \vspace{5mm} 23 | 24 | \centerline{\includegraphics[width=3in]{../images/binary-finger-numbers-blank.png}} 25 | 26 | \centering 27 | \tiny 28 | 29 | https://biscitmx.com/category/unplugged/ 30 | 31 | # Bits and binary 32 | 33 | \vspace{3mm} 34 | 35 | \centerline{\includegraphics[width=4in]{../images/binary_to_dec.png}} 36 | 37 | Digits correspond to powers of 2; value is the sum 38 | 39 | Integer is like an array of bits, but we can't use `[]` for individual bits 40 | 41 | * Instead, we need *bitwise operators*, discussed later 42 | 43 | # Bits and binary 44 | 45 | C integers use "two's complement" representation for signed integers. Illustration with 4 bits: 46 | 47 | \vspace{3mm} 48 | 49 | \centerline{\includegraphics[width=2in]{../images/twos_comp.png}} 50 | 51 | \centering 52 | \tiny 53 | 54 | http://www.bogotobogo.com/cplusplus/quiz_bit_manipulation.php 55 | 56 | \vspace{3mm} 57 | 58 | \normalsize 59 | \raggedright 60 | 61 | When a two's complement number overflows, it wraps around to a negative number 62 | 63 | # Bits and binary 64 | 65 | \footnotesize 66 | 67 | 77 | 78 | 83 | 84 | # Bits and binary 85 | 86 | Floating point numbers use their bits to store a few different things: 87 | 88 | * Sign: 1 bit, positive or negative 89 | * Exponent 90 | * Mantissa 91 | 92 | \vspace{5mm} 93 | 94 | \centerline{\includegraphics[width=2.6in]{../images/float.png}} 95 | 96 | \centering 97 | \tiny 98 | 99 | https://aha.betterexplained.com/t/8bit-floating-point-representation/1121 100 | 101 | # Bits and binary 102 | 103 | Integer and floating-point representations differ: 104 | 105 | * Integers have limited range, but integers in the range can be represented precisely. Floating point have limited range and can only approximate most numbers in the range. 106 | * Integers use all available bits for two's-complement representation. Floating point have separate sets of bits for sign, exponent and mantissa. 107 | 108 | # Bits and binary 109 | 110 | `float a = 1` or `int i = 3.0`, it's not as simple as copying bits 111 | 112 | When going from integer types to to `float` (or `double`), we are getting an approximation, not the exact integer 113 | 114 | -------------------------------------------------------------------------------- /units/250_numeric_types/numeric_types.cppmd: -------------------------------------------------------------------------------- 1 | # Numeric types 2 | 3 | In computers, all data are stored in binary 4 | 5 | Binary is the number system where each digit is a power of 2 6 | 7 | We are used to powers of 10 (decimal) 8 | 9 | \vspace{5mm} 10 | 11 | \centerline{\includegraphics[width=3in]{../images/binary-finger-numbers.png}} 12 | 13 | \centering 14 | \tiny 15 | 16 | https://biscitmx.com/category/unplugged/ 17 | 18 | # Bits and binary 19 | 20 | If we used our fingers to count in binary, we could count to $2^{10}-1 = 1023$ 21 | 22 | \vspace{5mm} 23 | 24 | \centerline{\includegraphics[width=3in]{../images/binary-finger-numbers-blank.png}} 25 | 26 | \centering 27 | \tiny 28 | 29 | https://biscitmx.com/category/unplugged/ 30 | 31 | # Bits and binary 32 | 33 | \vspace{3mm} 34 | 35 | \centerline{\includegraphics[width=4in]{../images/binary_to_dec.png}} 36 | 37 | Digits correspond to powers of 2; value is the sum 38 | 39 | Integer is like an array of bits, but we can't use `[]` for individual bits 40 | 41 | * Instead, we need *bitwise operators*, discussed later 42 | 43 | # Bits and binary 44 | 45 | C integers use "two's complement" representation for signed integers. Illustration with 4 bits: 46 | 47 | \vspace{3mm} 48 | 49 | \centerline{\includegraphics[width=2in]{../images/twos_comp.png}} 50 | 51 | \centering 52 | \tiny 53 | 54 | http://www.bogotobogo.com/cplusplus/quiz_bit_manipulation.php 55 | 56 | \vspace{3mm} 57 | 58 | \normalsize 59 | \raggedright 60 | 61 | When a two's complement number overflows, it wraps around to a negative number 62 | 63 | # Bits and binary 64 | 65 | \footnotesize 66 | 67 | 77 | 78 | 83 | 84 | # Bits and binary 85 | 86 | Floating point numbers use their bits to store a few different things: 87 | 88 | * Sign: 1 bit, positive or negative 89 | * Exponent 90 | * Mantissa 91 | 92 | \vspace{5mm} 93 | 94 | \centerline{\includegraphics[width=2.6in]{../images/float.png}} 95 | 96 | \centering 97 | \tiny 98 | 99 | https://aha.betterexplained.com/t/8bit-floating-point-representation/1121 100 | 101 | # Bits and binary 102 | 103 | Integer and floating-point representations differ: 104 | 105 | * Integers have limited range, but integers in the range can be represented precisely. Floating point have limited range and can only approximate most numbers in the range. 106 | * Integers use all available bits for two's-complement representation. Floating point have separate sets of bits for sign, exponent and mantissa. 107 | 108 | # Bits and binary 109 | 110 | `float a = 1` or `int i = 3.0`, it's not as simple as copying bits 111 | 112 | When going from integer types to to `float` (or `double`), we are getting an approximation, not the exact integer 113 | 114 | -------------------------------------------------------------------------------- /units/260_casting_promotion/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | casting_1 8 | casting_3 9 | casting_4 10 | casting_5 11 | casting_6 12 | float_literal 13 | float_literal2 14 | int_literal 15 | int_literal2 16 | narrow_1 17 | narrow_2 18 | promotion_1 19 | promotion_2 20 | ptr_cast 21 | ptr_eg3 22 | -------------------------------------------------------------------------------- /units/270_bitwise_ops/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | -------------------------------------------------------------------------------- /units/270_bitwise_ops/bitwise_ops.cppmd: -------------------------------------------------------------------------------- 1 | # Bitwise operators 2 | 3 | We saw that integers can be used as *boolean* values with 0 = false and non-0 = true 4 | 5 | Also saw logical operators for combining booleans 6 | 7 | \scriptsize 8 | 9 | \begin{table}[ht] 10 | \centering 11 | \begin{tabular}{clcr} 12 | \hline 13 | Operator & Function & Example & Result \\ 14 | \hline 15 | \texttt{\&\&} & Both true (\textit{AND}) & \texttt{1 \&\& 0} & false (0) \\ 16 | \texttt{||} & Either true (\textit{OR}) & \texttt{1 || 0} & true (non-0) \\ 17 | \texttt{!} & Opposite (\textit{NOT}) & \texttt{!(1 || 0)} & false (0) \\ 18 | \hline 19 | \end{tabular} 20 | \end{table} 21 | 22 | # Bitwise operators 23 | 24 | Saw that integer types consist of bits 25 | 26 | *Each* bit could be considered a boolean true/false value 27 | 28 | \vspace{4mm} 29 | 30 | \begin{table}[ht] 31 | \centering 32 | \begin{tabular}{rrrrrrrrr} 33 | Binary: & 0 & 0 & 1 & 1 & 0 & 1 & 0 & 1 \\ 34 | Place value: & $2^7$ & $2^6$ & $2^5$ & $2^4$ & $2^3$ & $2^2$ & $2^1$ & $2^0$ \\ 35 | \end{tabular} 36 | \end{table} 37 | 38 | \centering 39 | 40 | $2^5$ + $2^4$ + $2^2$ + $2^0$ = 32 + 16 + 4 + 1 = 53 41 | 42 | # Bitwise operators 43 | 44 | Bitwise operators performs a function across all bits in integer operands, treating them as boolean true/false values 45 | 46 | Bitwise AND (`&`) performs logical AND (`&&`) across all bits: 47 | 48 | ``` 49 | 12 = 00001100 (In Binary) 50 | 25 = 00011001 (In Binary) 51 | 52 | Bit Operation of 12 and 25 53 | 00001100 54 | & 00011001 55 | ________ 56 | 00001000 = 8 (In decimal) 57 | ``` 58 | 59 | # Bitwise operators 60 | 61 | 70 | 71 | 75 | 76 | # Bitwise operators 77 | 78 | Since `int`s are 32-bit (4-byte) values, this is a more accurate picture: 79 | 80 | ``` 81 | 00000000000000000000000000001100 = 12 82 | & 00000000000000000000000000011001 = 25 83 | ________________________________ 84 | 00000000000000000000000000001000 = 8 (In decimal) 85 | ``` 86 | 87 | # Bitwise operators 88 | 89 | Bitwise OR (`|`) performs logical OR (`||`): 90 | 91 | ``` 92 | 12 = 00001100 (In Binary) 93 | 25 = 00011001 (In Binary) 94 | 95 | Bitwise OR Operation of 12 and 25 96 | 00001100 97 | | 00011001 98 | ________ 99 | 00011101 = 29 (In decimal) 100 | ``` 101 | 102 | # Bitwise operators 103 | 104 | 113 | 114 | 118 | 119 | # Bitwise operators 120 | 121 | `x << n` shifts bits of `x` the left `N` positions 122 | 123 | `N` 0s are "shifted in" at right-hand side 124 | 125 | `N` bits "fall off" left-hand side 126 | 127 | ``` 128 | 25 = 00011001 (In Binary) 129 | 130 | Bitwise left-shift of 25 by 5 positions (25 << 5) 131 | 11001 132 | << 5 133 | __________ 134 | 1100100000 = 800 (In decimal) 135 | ``` 136 | 137 | # Bitwise operators 138 | 139 | \footnotesize 140 | 141 | 150 | 151 | 155 | 156 | # Bitwise operators 157 | 158 | Similar for bitwise right shift (`>>`) 159 | 160 | ``` 161 | 25 = 00011001 (In Binary) 162 | 163 | Bitwise right-shift of 25 by 4 positions (25 >> 4) 164 | 00011001 165 | >> 4 166 | ________ 167 | 00000001 = 1 168 | ``` 169 | 170 | # Bitwise operators 171 | 172 | \footnotesize 173 | 174 | 183 | 184 | 188 | 189 | # Bitwise operators 190 | 191 | \scriptsize 192 | 193 | 211 | 212 | # Bitwise operators 213 | 214 | 218 | 219 | -------------------------------------------------------------------------------- /units/280_linked_lists/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | ll1 8 | ll_insert 9 | ll_insert_head 10 | ll_ordered 11 | music_collection 12 | music_collection_2 13 | music_collection_dyn 14 | -------------------------------------------------------------------------------- /units/280_linked_lists/figs.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/280_linked_lists/figs.key -------------------------------------------------------------------------------- /units/500_cpp_intro/.gitignore: -------------------------------------------------------------------------------- 1 | *.c 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | hello_world 8 | hello_world.cpp 9 | hello_world_2.cpp 10 | ll_insert 11 | -------------------------------------------------------------------------------- /units/500_cpp_intro/cpp_intro.cppmd: -------------------------------------------------------------------------------- 1 | # C++ Introduction 2 | 3 | If learning C is like learning "business English," learning C++ is like learning the rest of English 4 | 5 | \vspace{5mm} 6 | 7 | \centerline{\includegraphics[width=3.5in]{../images/business.jpg}} 8 | 9 | \scriptsize 10 | \centering 11 | 12 | [www.businessenglishpod.com](https://www.businessenglishpod.com) 13 | 14 | # C++ 15 | 16 | Sometimes programming in C is the best or only option 17 | 18 | * You "inherited" C code 19 | * No C++ compiler is available for system you're targeting 20 | * Your software must work closely with the Linux kernel, or other C-based software 21 | 22 | If we started a new project today, especially if it was big or involved many people, we'd probably choose C++ 23 | 24 | # C++ 25 | 26 | Classes -- like Java classes 27 | 28 | Templates -- like Java generics 29 | 30 | Standard Template Library -- like `java.util` 31 | 32 | More convenient text input & output 33 | 34 | # C++ 35 | 36 | C++ is not a "superset" of C; many C programs don't immediately work in C++ 37 | 38 | Think of C and C++ as closely related but different languages 39 | 40 | # C++ 41 | 42 | Most concepts and constructs in C work *the same way* in C++: 43 | 44 | * Types: `int`, `char`, `char *`, etc 45 | * C++ adds `bool` (equals either `true` or `false`) 46 | * Numeric representations & properties 47 | * Arrays, pointers, `*` and `&`, pointer arithmetic 48 | * `if/else if/else`, `switch/case`, `for`, `while`, `do/while` 49 | * Pass by value (still the default), pass by pointer 50 | * Stack vs. heap, scope & lifetime 51 | * Operators: arithmetic, relational, logical, assignment, bitwise 52 | * `struct` (minor differences) 53 | * Casting (minor differences) 54 | 55 | # C++ 56 | 57 | Our favorite tools work just as well with C++: 58 | 59 | * `git` 60 | * `make` 61 | * `gdb` 62 | * `valgrind` 63 | 64 | # C++ 65 | 66 | 77 | 78 | \footnotesize 79 | 80 | 85 | 86 | # C++ 87 | 88 | Programming stages same as for C: edit -> compile -> execute 89 | 90 | When compiling: 91 | 92 | * `g++` instead of `gcc` 93 | * `-std=c++11` instead of `-std=c99` 94 | * `.cpp` instead of `.c` 95 | 96 | \footnotesize 97 | 98 | 103 | 104 | # C++ 105 | 106 | Options we used with `gcc` work with `g++` too 107 | 108 | * `-o` to set name of executable 109 | * `-c` to compile to `.o` file 110 | * `-g` to include debug symbols 111 | * `-Wall -Wextra -pedantic` for sensitive warnings & errors 112 | 113 | # C++: libraries 114 | 115 | ```c 116 | #include 117 | ``` 118 | 119 | As with C, C++ library headers are included with `<` angle brackets `>` 120 | 121 | For standard C++ headers, *omit the trailing `.h`* 122 | 123 | * ``, not `` 124 | 125 | \vspace{5mm} 126 | 127 | ```c 128 | #include "linked_list.h" 129 | ``` 130 | 131 | User-defined headers use `"` quotes `"` and end with `.h` as usual 132 | 133 | * You'll sometimes see `.hpp` instead of `.h`, but we'll use `.h` 134 | 135 | # C++: libraries 136 | 137 | Can use familiar C headers: `assert.h`, `math.h`, `ctype.h`, `stdlib.h`, ... 138 | 139 | When `#include`'ing, drop `.h` & add `c` at the beginning: 140 | 141 | \footnotesize 142 | 143 | 156 | 157 | -------------------------------------------------------------------------------- /units/510_io_namespaces/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | cpp_io_1 8 | cpp_io_2 9 | cpp_io_3 10 | hello_world_2 11 | smallest_word 12 | uppercase_cpp 13 | -------------------------------------------------------------------------------- /units/520_strings/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | cpp_io_1 8 | cpp_io_2 9 | cpp_io_3 10 | hello_world_2 11 | smallest_word 12 | uppercase_cpp 13 | string_at 14 | -------------------------------------------------------------------------------- /units/520_strings/strings.cppmd: -------------------------------------------------------------------------------- 1 | # C++ Strings 2 | 3 | C++ strings have similar user-friendliness of Java/Python strings 4 | 5 | Spare us from details like null terminators 6 | 7 | (We will still need C strings sometimes, e.g. `char *argv[]`) 8 | 9 | # C++: `string` 10 | 11 | Use `#include ` to use C++ strings 12 | 13 | Full name is `std::string`; or put `using std::string;` at the top of `.cpp` file 14 | 15 | # C++: `string` 16 | 17 | `s[5]` accesses 6th character in string 18 | 19 | `s.at(5)` does the same, additionally doing a "bounds check" 20 | 21 | * Like Java's `ArrayIndexOutOfBounds` or Python's `IndexError` 22 | 23 | # C++: `string` 24 | 25 | \footnotesize 26 | 27 | 44 | 45 | # C++: `string` 46 | 47 | \scriptsize 48 | 49 | 54 | 55 | \normalsize 56 | 57 | \vspace{2mm} 58 | 59 | Better to use `assert(...)` to check that you're in-bounds. But `s.at(x)` (instead of `s[x]`) is another way to be cautious. 60 | 61 | # C++: `string` 62 | 63 | Some ways to initialize a new string variable: 64 | 65 | ```c 66 | string s1 = "world"; // initializes to "world" 67 | string s2("hello"); // just like s2 = "hello" 68 | string s3(3, 'a'); // s3 gets "aaa" 69 | string s4; // s4 gets "" (empty) 70 | string s5(s2); // copies s2 into s5 71 | ``` 72 | 73 | # C++: `string` 74 | 75 | `string`s can be arbitrarily long 76 | 77 | The C++ library worries about the memory 78 | 79 | * Dynamically allocated and adjusted as needed 80 | * When `string` goes out of scope, memory is freed 81 | 82 | Automatic handling of heap memory is a major advantage of C++ 83 | 84 | * We will leverage it for our own `class`es later 85 | 86 | # C++: `string` 87 | 88 | Assuming `s`, `s1` and `s2` are `std::string`'s: 89 | 90 | \footnotesize 91 | 92 | ```c 93 | s = "wow" // assign literal to string 94 | cin >> s // put one whitespace-delimited input word in s 95 | cout << s // write s to standard out 96 | getline(cin, s) // read to end of line from stdin, store in s 97 | s1 = s2 // copy contents of s2 into s1 98 | s1 + s2 // return new string: s1 concatenated with s2 99 | s1 += s2 // same as s1 = s1 + s2, also same as s1.append(s2) 100 | == != < > <= >= // relational operators; alphabetical order 101 | ``` 102 | 103 | # C++: `string` 104 | 105 | ```c 106 | string s = "hello"; 107 | cout << s.length() << endl; // prints 5 108 | 109 | // prints bytes of memory allocated 110 | cout << s.capacity() << endl; 111 | 112 | // s.substr(offset, howmany) gives substring of s 113 | cout << s.substr(1, 3) << endl; // prints "ell" 114 | 115 | // s.c_str() returns C-style "const char *" version 116 | cout << strlen(s.c_str()) << endl; // prints 5 117 | ``` 118 | 119 | # C++: `string` 120 | 121 | See C++ reference for more `string` functionality 122 | 123 | * [www.cplusplus.com/reference/string/string/](http://www.cplusplus.com/reference/string/string/) 124 | 125 | Commonly used member functions (click for links): 126 | 127 | * [`length` -- return # of characters (ignoring terminator)](http://www.cplusplus.com/reference/string/string/length/) 128 | * [`empty` -- return true when there is at least 1 character](http://www.cplusplus.com/reference/string/string/empty/) 129 | * [`append` -- like `+=`](http://www.cplusplus.com/reference/string/string/append/) 130 | * [`push_back` -- like `append` for a single character](http://www.cplusplus.com/reference/string/string/push_back/) 131 | * [`clear` -- set to empty string](http://www.cplusplus.com/reference/string/string/clear/) 132 | * [`insert` -- insert one string in middle of another](http://www.cplusplus.com/reference/string/string/insert/) 133 | * [`erase` -- remove stretch of characters from string](http://www.cplusplus.com/reference/string/string/erase/) 134 | * [`replace` -- replace a substring with a given string](http://www.cplusplus.com/reference/string/string/replace/) 135 | 136 | -------------------------------------------------------------------------------- /units/530_stl_intro/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | ll_template_cpp 8 | -------------------------------------------------------------------------------- /units/530_stl_intro/stl_intro.cppmd: -------------------------------------------------------------------------------- 1 | # C++ STL Introduction 2 | 3 | Standard Template Library (STL) is C++'s library of useful data structures & algorithms 4 | 5 | * Like `java.util`/`java.lang` 6 | * Like Python sets, dictionaries, `collections` 7 | 8 | Templates are covered in detail later in the course; we'll give them a quick look now 9 | 10 | # C++: Templates 11 | 12 | Templates are a way of writing an object (`Node`) or function (`print_list`) to work with *any* type 13 | 14 | You simultaneously define a *family* of related objects/functions 15 | 16 | # C++: Templates 17 | 18 | \footnotesize 19 | 20 | ```c 21 | struct Node { 22 | T payload; // 'T' is placeholder for a type 23 | Node *next; 24 | }; 25 | 26 | void print_list(Node *head) { 27 | Node *cur = head; 28 | while(cur != NULL) { 29 | cout << cur->payload << " "; 30 | cur = cur->next; 31 | } 32 | cout << endl; 33 | } 34 | ``` 35 | 36 | \normalsize 37 | 38 | We could replace `T` with `int`, `float`, `char`, or `std::string` and this would compile & work 39 | 40 | # C++: Templates 41 | 42 | \scriptsize 43 | 44 | ```c 45 | template 46 | struct Node { 47 | T payload; 48 | Node *next; 49 | }; 50 | 51 | template 52 | void print_list(Node *head) { 53 | Node *cur = head; 54 | while(cur != NULL) { 55 | cout << cur->payload << " "; 56 | cur = cur->next; 57 | } 58 | cout << endl; 59 | } 60 | ``` 61 | 62 | \normalsize 63 | 64 | Same example, using templates 65 | 66 | One `struct`/function, works for (almost) *any* type `T` 67 | 68 | # C++: Template primer 69 | 70 | \footnotesize 71 | 72 | ```c 73 | int main() { 74 | Node f3 = {95.1f, NULL}; // float payload 75 | Node f2 = {48.7f, &f3}; // float payload 76 | Node f1 = {24.3f, &f2}; // float payload 77 | print_list(&f1); 78 | 79 | Node i2 = {239, NULL}; // int payload 80 | Node i1 = {114, &i2}; // int payload 81 | print_list(&i1); 82 | 83 | return 0; 84 | } 85 | ``` 86 | 87 | 122 | 123 | 128 | 129 | # C++: STL 130 | 131 | With STL we use types like `vector` 132 | 133 | We read that type as "a vector *of* strings" 134 | 135 | * `vector` -- a vector of `std::string`s 136 | * `vector` -- a vector of `float`s 137 | * `map` -- a structure that maps `std::string`s to `int`s 138 | 139 | Similar to Java generics 140 | 141 | -------------------------------------------------------------------------------- /units/540_vector_iter/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | names_1 8 | names_3 9 | names_2 10 | -------------------------------------------------------------------------------- /units/550_map/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | names_1 8 | names_3 9 | names_2 10 | jhed_map 11 | jhed_map_0 12 | -------------------------------------------------------------------------------- /units/550_map/map.cppmd: -------------------------------------------------------------------------------- 1 | # C++: `map` 2 | 3 | Collection of *keys*, each with an associated *value* 4 | 5 | * Like Java's `java.util.HashMap` or `TreeMap` 6 | * Like Python's `dict` (dictionary) type 7 | 8 | Value can be any type you wish (even another container) 9 | 10 | Key can be any type where `<` can be used to compare values 11 | 12 | * All numeric types, `char`, `std::string`, etc 13 | 14 | # C++: `map` 15 | 16 | Declare a map: 17 | 18 | \footnotesize 19 | 20 | ```c 21 | map jhed_to_name; 22 | ``` 23 | 24 | \normalsize 25 | 26 | Add a key + value to a map: 27 | 28 | \footnotesize 29 | 30 | ```c 31 | jhed_to_name[92394] = "Alex Hamilton"; 32 | ``` 33 | 34 | \normalsize 35 | 36 | Print a key and associated value: 37 | 38 | \footnotesize 39 | 40 | ```c 41 | const int k = 92394; 42 | cout << "Key=" << k << ", Value=" << jhed_to_name[k] << endl; 43 | ``` 44 | 45 | # C++: `map` 46 | 47 | A map can only associate 1 value with a key 48 | 49 | \footnotesize 50 | 51 | ```c 52 | const int k = 92394; 53 | jhed_to_name[k] = "Alex Hamilton"; 54 | jhed_to_name[k] = "George Washington"; // Alex is replaced 55 | cout << k << ": " << jhed_to_name[k] << endl; 56 | ``` 57 | 58 | 77 | 78 | 83 | 84 | # C++: `map` 85 | 86 | Get number of keys: 87 | 88 | \footnotesize 89 | 90 | ```c 91 | jhed_to_name.size(); 92 | ``` 93 | 94 | \normalsize 95 | 96 | Check if `map` contains (has a value for) a given key: 97 | 98 | \footnotesize 99 | 100 | ```c 101 | if(jhed_to_name.find(92394) != jhed_to_name.end()) { 102 | cout << "Found it" << endl; 103 | } else { 104 | cout << "Didn't find it" << endl; 105 | } 106 | ``` 107 | # C++: `vector` 108 | 109 | To get all the elements of the map, use an *iterator*: 110 | 111 | \footnotesize 112 | 113 | ```c 114 | for(map::iterator it = jhed_to_name.begin(); 115 | it != jhed_to_name.end(); 116 | ++it) 117 | { 118 | cout << " " << it->first << ": " << it->second << endl; 119 | } 120 | ``` 121 | 122 | \normalsize 123 | 124 | Iterator type: `map::iterator` 125 | 126 | Loop is similar to the loop for `vector` 127 | 128 | Keys iterated over *in ascending order* (increasing id in this case) 129 | 130 | # C++: `vector` 131 | 132 | Looking at the body: 133 | 134 | \footnotesize 135 | 136 | ```c 137 | cout << " " << it->first << ": " << it->second << endl; 138 | ``` 139 | 140 | \normalsize 141 | 142 | Dereferenced `map` iterator type is `std::pair` 143 | 144 | * `it->first` is the key (`int` here) 145 | * `it->second` is the value (`string` here) 146 | 147 | More on `pair` later 148 | 149 | # C++: `map` 150 | 151 | \scriptsize 152 | 153 | 176 | 177 | # C++: `map` 178 | 179 | \footnotesize 180 | 181 | 186 | 187 | \normalsize 188 | 189 | Note again: the keys are printed *in ascending order* 190 | 191 | Can use `reverse_iterator`, `.rbegin()` and `.rend()` to get keys in *descending* order 192 | 193 | -------------------------------------------------------------------------------- /units/560_more_iterators/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | prefix_sum_iter 8 | jhed_map 9 | jhed_map_0 10 | -------------------------------------------------------------------------------- /units/560_more_iterators/more_iterators.cppmd: -------------------------------------------------------------------------------- 1 | # C++: More on iterators 2 | 3 | Consider these `map` iterator types: 4 | 5 | * `map::iterator` -- iterator over a `map` 6 | * `map >::iterator` -- iterator over a `map` *where the values are themselves `map`s* 7 | 8 | `typedef` can help by: 9 | 10 | * Reducing clutter 11 | * Bringing related type declarations closer together in your code: 12 | 13 | ```c 14 | typedef map TMap; // map type 15 | typedef TMap::iterator TMapItr; // map iterator type 16 | ``` 17 | 18 | # C++: Iterators 19 | 20 | With `iterator` (or `reverse_iterator`) you can modify the data structure via the dereferenced iterator: 21 | 22 | \scriptsize 23 | 24 | ```c 25 | typedef vector::iterator TItr; 26 | 27 | void prefix_sum(TItr begin, TItr end) { 28 | int sum = 0; 29 | for(TItr it = begin; it != end; ++it) { 30 | *it += sum; 31 | sum += *it; 32 | } 33 | } 34 | ``` 35 | 36 | 69 | 70 | 75 | 76 | # C++: Iterators 77 | 78 | `const_iterator` *does not* allow modifications 79 | 80 | \scriptsize 81 | 82 | ```c 83 | typedef vector::const_iterator TItr; 84 | // ^^^^^ 85 | 86 | void prefix_sum(TItr begin, TItr end) { 87 | int sum = 0; 88 | for(TItr it = begin; it != end; ++it) { 89 | *it += sum; 90 | sum += *it; 91 | } 92 | } 93 | ``` 94 | 95 | 127 | 128 | 131 | 132 | 133 | # C++: Iterators 134 | 135 | \scriptsize 136 | 137 | | Type | `++it` | `--it` | Get with | *it type | 138 | | ------------------------ |:--------:| --------:| ----------------------:|---------:| 139 | | `iterator` | forward | back | `.begin()`/`end()` | - | 140 | | `const_iterator` | forward | back | `.cbegin()`/`cend()` | `const` | 141 | | `reverse_iterator` | back | forward | `.rbegin()`/`rend()` | - | 142 | | `const_reverse_iterator` | back | forward | `.crbegin()`/`crend()` | `const` | 143 | 144 | \normalsize 145 | 146 | Reminder: When using a variant of `.begin()`/`.end()`, always initialize the the iterator with `.begin()` and stop as soon as it `== .end()`. Don't switch the two, even if you're *trying* to go backwards. Use the `reverse_` version instead. 147 | 148 | -------------------------------------------------------------------------------- /units/570_pair_tuple/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | quo_rem_tuple 8 | prefix_sum_iter 9 | -------------------------------------------------------------------------------- /units/570_pair_tuple/pair_tuple.cppmd: -------------------------------------------------------------------------------- 1 | # C++: `pair` and `tuple` 2 | 3 | We want a function that takes integers `a` & `b` and returns both `a/b` (quotient) and `a%b` (remainder) 4 | 5 | * `divmod(10, 5)` returns `2`, `0` 6 | * `divmod(10, 3)` returns `3`, `1` 7 | 8 | Functions only return *one* thing 9 | 10 | # C++: `pair` 11 | 12 | One solution: pass-by-pointer arguments: 13 | 14 | \footnotesize 15 | 16 | ```c 17 | void divmod(int a, int b, int *quo, int *rem) { 18 | *quo = a / b; 19 | *rem = a % b; 20 | } 21 | ``` 22 | 23 | \normalsize 24 | 25 | Another: define `struct` for `divmod`'s return type: 26 | 27 | \footnotesize 28 | 29 | ```c 30 | struct quo_rem { 31 | int quotient; 32 | int remainder; 33 | }; 34 | 35 | quo_rem divmod(int a, int b) { ... } 36 | ``` 37 | 38 | \tiny 39 | 40 | 65 | 66 | # C++: `pair` 67 | 68 | STL solution: return `pair`, a pair with items of types `int` & `int`: 69 | 70 | \scriptsize 71 | 72 | ```c 73 | pair divmod(int a, int b) { 74 | return make_pair(a/b, a%b); 75 | } 76 | 77 | int main() { 78 | pair qr_10_5 = divmod(10, 5); 79 | pair qr_10_3 = divmod(10, 3); 80 | cout << "10/5 quotient=" << qr_10_5.first 81 | << ", remainder=" << qr_10_5.second << endl; 82 | cout << "10/3 quotient=" << qr_10_3.first 83 | << ", remainder=" << qr_10_3.second << endl; 84 | return 0; 85 | } 86 | ``` 87 | 88 | \tiny 89 | 90 | 113 | 114 | # C++: `pair` 115 | 116 | We've used `pair` already; dereferenced `map` iterator is a pair: 117 | 118 | \footnotesize 119 | 120 | ```c 121 | for(map::iterator it = jhed_to_name.begin(); 122 | it != jhed_to_name.end(); 123 | ++it) 124 | { 125 | // it->first has type int 126 | // it->second has type string 127 | cout << " " << it->first << ": " << it->second << endl; 128 | } 129 | ``` 130 | 131 | # C++: `pair` 132 | 133 | Relational operators for `pair` work as expected: 134 | 135 | * Compares first field first... 136 | * ...if there's a tie, compares second field 137 | 138 | `make_pair(2, 3) < make_pair(3, 2)` is true 139 | 140 | # C++: `tuple` 141 | 142 | `tuple` is like `pair` but with as many fields as you like 143 | 144 | \footnotesize 145 | 146 | ```c 147 | #include 148 | using std::tuple; using std::make_tuple; 149 | 150 | tuple divmod(int a, int b) { 151 | return make_tuple(a/b, a%b, (float)a/b); 152 | } 153 | ``` 154 | 155 | \normalsize 156 | 157 | `std::get(tup)` gets the Nth field of `tuple` called `tup`: 158 | 159 | \footnotesize 160 | 161 | ```c 162 | using std::get; 163 | tuple tup = divmod(10, 3); 164 | cout << "10/3 quotient=" << get<0>(tup) 165 | << ", remainder=" << get<1>(tup) 166 | << ", decimal quotient=" << get<2>(tup) << endl; 167 | ``` 168 | 169 | # C++: `tuple` 170 | 171 | \footnotesize 172 | 173 | 193 | 194 | 199 | 200 | -------------------------------------------------------------------------------- /units/580_references/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | divmod_ref 8 | ref_addr 9 | ref_min 10 | ref_ptr_1 11 | ref_ptr_2 12 | ref_reset 13 | ref_swap 14 | -------------------------------------------------------------------------------- /units/600_classes/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | rect_class 8 | rectangle1 9 | -------------------------------------------------------------------------------- /units/600_classes/classes.cppmd: -------------------------------------------------------------------------------- 1 | # Classes & object-oriented programming 2 | 3 | We saw `struct`s, which bundle variables that describe different aspects of the same thing: 4 | 5 | ```c 6 | struct Rectangle { 7 | double width; 8 | double height; 9 | }; 10 | ``` 11 | 12 | We might additionally define functions that work with `Rectangle`s: 13 | 14 | # C++ classes & object-oriented programming 15 | 16 | \scriptsize 17 | 18 | 41 | 42 | # C++ classes & object-oriented programming 43 | 44 | \footnotesize 45 | 46 | 51 | 52 | # C++ classes & object-oriented programming 53 | 54 | As "object-oriented" programmers, we prefer to have related functionality (`print_rectangle`, `area`) be *part of the object* 55 | 56 | We couldn't do this in C, but C++ allows us to define `class`es... 57 | 58 | # C++ `class` 59 | 60 | \scriptsize 61 | 62 | 85 | 86 | # C++ `class` 87 | 88 | \tiny 89 | 90 | 115 | 116 | # C++: Object oriented programming 117 | 118 | \footnotesize 119 | 120 | 125 | 126 | # C++ classes 127 | 128 | C++ `class`es have *fields* (like `struct`) and *member functions* (unlike `struct`) 129 | 130 | Member functions can access/modify fields, and can call other member functions 131 | 132 | In previous example: 133 | 134 | * `width` and `height` are fields 135 | * `print`, `area` and `set` are member functions 136 | * `area` uses `width` and `height` in its calculation 137 | * `set` modifies `width` and `height` 138 | * `print` uses `width` & `height` and calls `area()` 139 | 140 | # C++ classes 141 | 142 | In Java: 143 | 144 | * What we call "member functions" Java calls "methods" 145 | * What we call "fields" Java sometimes calls "instance variables" 146 | 147 | We use the generic term "members" to refer to both fields and member functions 148 | 149 | # C++ classes 150 | 151 | Like in Java, fields and member functions can be `public` or `private` 152 | 153 | * (or `protected`, discussed later) 154 | 155 | Labels `public:` or `private:` divide the class definition into sections according to whether members are `public` or `private` 156 | 157 | * E.g. all members declared after the `public:` label are public until the end of the class or until `private:` 158 | 159 | Members are `private` by default 160 | 161 | # C++ classes 162 | 163 | Functions can be declared *and defined* inside `class { ... };` 164 | 165 | * We only do this if it's *very short* 166 | * Otherwise, we put a *prototype* in the class definition and we define the member function in a `.cpp` file 167 | 168 | For example, this might appear in `grade_list.h`: 169 | 170 | \footnotesize 171 | 172 | ```c 173 | class GradeList { 174 | ... 175 | void add(double grade) 176 | { 177 | // definition inside class 178 | grades.push_back(grade); 179 | } 180 | }; 181 | ``` 182 | 183 | # C++ classes 184 | 185 | Or (more often) we put this in `grade_list.h`: 186 | 187 | \footnotesize 188 | 189 | ```c 190 | class GradeList { 191 | ... 192 | void add(double grade); 193 | ... 194 | }; 195 | ``` 196 | 197 | \normalsize 198 | 199 | ...and this in `grade_list.cpp`: 200 | 201 | \vspace{3mm} 202 | 203 | \footnotesize 204 | 205 | ```c 206 | #include "grade_list.h" 207 | 208 | // definition outside class 209 | void GradeList::add(double grade) { 210 | grades.push_back(grade); 211 | } 212 | ``` 213 | 214 | # C++ classes 215 | 216 | Note that when defining a member function, you must prefix the function name with the class name followed by `::` 217 | 218 | ```c 219 | void GradeList::add(double grade) { 220 | grades.push_back(grade); 221 | } 222 | ``` 223 | 224 | # C++ classes 225 | 226 | A private member can be accessed from other member functions in the class, but *not* by the user 227 | 228 | ```c 229 | class GradeList { 230 | public: 231 | ... 232 | void add(double grade) { 233 | grades.push_back(grade); // OK 234 | } 235 | ... 236 | private: 237 | std::vector grades; 238 | }; 239 | ``` 240 | 241 | # C++ classes 242 | 243 | ```c 244 | class GradeList { 245 | ... 246 | private: 247 | std::vector grades; 248 | }; 249 | 250 | int main() { 251 | GradeList gl; 252 | cout << gl.grades.size() << endl; // not OK! 253 | return 0; 254 | } 255 | ``` 256 | 257 | # C++ classes 258 | 259 | `public` fields and member function can be accessed freely 260 | 261 | \scriptsize 262 | 263 | ```c 264 | class GradeList { 265 | public: 266 | void add(double grade) 267 | { 268 | grades.push_back(grade); 269 | } 270 | void add7() { add(7.0); } // OK! 271 | ... 272 | }; 273 | 274 | int main() { 275 | GradeList gl; 276 | gl.add(45.0); // also OK! 277 | return 0; 278 | } 279 | ``` 280 | 281 | # C++ classes 282 | 283 | You might want to initialize a field when it's declared: 284 | 285 | ```c 286 | class GradeList { 287 | ... 288 | 289 | bool is_sorted = false; 290 | }; 291 | ``` 292 | 293 | This is common in Java but was not allowed in C++ before C++11 294 | 295 | * Called a *default member initializer* 296 | * We will avoid it, preferring to initialize using constructors & initializer lists, discussed later 297 | 298 | -------------------------------------------------------------------------------- /units/610_constructors/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | def_ctor_1 8 | grade_list_2 9 | -------------------------------------------------------------------------------- /units/610_constructors/constructors.cppmd: -------------------------------------------------------------------------------- 1 | # Constructors 2 | 3 | What are the fields of a class set to if we don't explicitly initialize them? 4 | 5 | # C++ classes 6 | 7 | \footnotesize 8 | 9 | 28 | 29 | # C++ classes 30 | 31 | ```c 32 | int main() { 33 | GradeList gl; 34 | ``` 35 | 36 | What are the values of `gl.grades` & `gl.is_sorted` right now? 37 | 38 | I haven't set them to anything; are they set to reasonable defaults? 39 | 40 | **Not in general** 41 | 42 | * `gl.grades` *is* initialized properly via its *default constructor* (discussed soon) 43 | * According to C++11 standard, `gl.is_sorted` is *uninitialized*! 44 | 45 | # Constructors 46 | 47 | When we define a `class`, we can define one or more *constructors* 48 | 49 | Each constructor is a way to build a valid instance of that `class`, with fields sensibly initialized 50 | 51 | If you define no constructors, an *implicit default constructor* is automatically added by the compiler 52 | 53 | # Constructors 54 | 55 | ```c 56 | int main() { 57 | // behind the scenes, GradeList's implicit 58 | // default constructor is called... 59 | GradeList gl; 60 | 61 | // ...but it does not initialize gl.is_sorted! 62 | ... 63 | } 64 | ``` 65 | 66 | We will prefer to define the constructor ourselves 67 | 68 | # Constructors 69 | 70 | Terminology: 71 | 72 | * *Default constructor* is a constructor that takes no arguments 73 | 74 | * We will see non-default constructors later 75 | 76 | * *Implicit* default constructor is the default constructor that the compiler adds when no constructors are specified 77 | 78 | # Constructors 79 | 80 | A constructor is a `public` member function with the same name as the `class` 81 | 82 | ```c 83 | class GradeList { 84 | public: 85 | // default constructor for GradeList 86 | GradeList() { ... } 87 | ... 88 | } 89 | ``` 90 | 91 | It has no return type; it doesn't return anything 92 | 93 | # Constructors 94 | 95 | We've used default constructors already: 96 | 97 | \footnotesize 98 | 99 | ```c 100 | // vector's default constructor initializes empty vector 101 | vector my_ints; 102 | 103 | // string's default constructor initializes empty string 104 | string word; 105 | ``` 106 | 107 | # Constructors 108 | 109 | We cannot call a constructor directly. Constructor is called automatically when a new object is declared, or created using `new` 110 | 111 | ```c 112 | int main() { 113 | // calls default constructor for gl 114 | GradeList gl; 115 | 116 | // calls default constructor for *glp 117 | GradeList *glp = new GradeList(); 118 | } 119 | ``` 120 | 121 | (`new` discussed later) 122 | 123 | # Constructors 124 | 125 | Constructors often use a special syntax called an *initializer list*: 126 | 127 | \footnotesize 128 | 129 | ```c 130 | class GradeList { 131 | public: 132 | // Define our own "default constructor," 133 | GradeList() : grades(), is_sorted(false) { } 134 | 135 | ... 136 | 137 | private: 138 | std::vector grades; 139 | bool is_sorted; 140 | }; 141 | ``` 142 | 143 | # Constructors 144 | 145 | \scriptsize 146 | 147 | ```c 148 | class GradeList { 149 | public: 150 | // Define our own "default constructor," 151 | GradeList() : grades(), is_sorted(false) { } 152 | // ^^^^^^^^ ^^^^^^^^^^^^^^^^ 153 | // Initializes grades by calling 154 | // std::vector's default constructor 155 | // 156 | // Initializes is_sorted by setting it to 157 | // false 158 | 159 | ... 160 | 161 | private: 162 | std::vector grades; 163 | bool is_sorted; 164 | }; 165 | ``` 166 | 167 | # Constructors 168 | 169 | These default constructors have the same effect: 170 | 171 | \scriptsize 172 | 173 | 193 | 194 | # Constructors 195 | 196 | \scriptsize 197 | 198 | 212 | 213 | 218 | 219 | # Constructors 220 | 221 | Initializer list is the better choice and we will prefer it 222 | 223 | * Works as expected both for normal and for reference variables 224 | * Works both for using default and non-default constructors when initializing fields 225 | 226 | \footnotesize 227 | 228 | ```c 229 | IntAndString() : i(7), s("hello") { } 230 | 231 | IntAndString() { 232 | i = 7; 233 | s = "hello"; 234 | } 235 | ``` 236 | 237 | \normalsize 238 | 239 | Neither Java nor Python have initializer list syntax: 240 | 241 | * [stackoverflow.com/questions/7154654](http://stackoverflow.com/questions/7154654/why-doesnt-java-have-initializer-lists-like-in-c) 242 | in this course; it is clearer & less error-prone to initialize only in constructors 243 | 244 | -------------------------------------------------------------------------------- /units/620_new_delete/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | new_eg1 8 | new_eg2 9 | -------------------------------------------------------------------------------- /units/620_new_delete/new_delete.cppmd: -------------------------------------------------------------------------------- 1 | # C++ dynamic memory allocation 2 | 3 | `new` and `delete` are C++ versions of `malloc` and `free` 4 | 5 | Big difference: `new` allocates memory *and calls the appropriate constructor* 6 | 7 | Small difference: `new` and `delete` are "keywords" rather than functions, so we don't use `(...)` when calling them 8 | 9 | # C++ dynamic memory allocation 10 | 11 | \scriptsize 12 | 13 | 34 | 35 | # C++ dynamic memory allocation 36 | 37 | \footnotesize 38 | 39 | 44 | 45 | \normalsize 46 | 47 | `new` called the default constructor for us in both cases 48 | 49 | # C++ dynamic memory allocation 50 | 51 | `delete` deletes something allocated with `new` 52 | 53 | ```c 54 | int main() { 55 | DefaultSeven *sptr = new DefaultSeven(); 56 | ... // use sptr 57 | delete sptr; 58 | // note: new and delete don't use parentheses, 59 | // unlike malloc() / free() 60 | return 0; 61 | } 62 | ``` 63 | 64 | # C++ dynamic memory allocation 65 | 66 | `T * fresh = new T[n]` allocates an array of `n` elements of type `T` 67 | 68 | Use `delete[] fresh` to deallocate -- always use `delete[]` (not `delete`) to deallocate a pointer returned by `new T[n]` 69 | 70 | \vspace{5mm} 71 | 72 | If `T` is a `class`, then `T`'s default constructor is called for *each* element allocated 73 | 74 | If `T` is a "built-in" type (`int`, `float`, `char`, etc), then the values are *not initialized*, like with `malloc` 75 | 76 | # C++ dynamic memory allocation 77 | 78 | \scriptsize 79 | 80 | 102 | 103 | # C++ dynamic memory allocation 104 | 105 | \footnotesize 106 | 107 | 112 | 113 | \normalsize 114 | 115 | Default constructor was indeed called for all 10 elements 116 | 117 | -------------------------------------------------------------------------------- /units/630_non_default_ctors/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | new_eg3 8 | -------------------------------------------------------------------------------- /units/630_non_default_ctors/non_default_ctors.cppmd: -------------------------------------------------------------------------------- 1 | # Non-default constructors 2 | 3 | Constructors can take parameters, giving the caller more control over how to initialize the object 4 | 5 | \footnotesize 6 | 7 | ```c 8 | // Uses non-default constructor to initialize s1 to a copy 9 | // of the argument 10 | string s1("hello"); 11 | 12 | // Same here 13 | string s2 = "world"; 14 | ``` 15 | 16 | # Non-default constructors 17 | 18 | \tiny 19 | 20 | 50 | 51 | # Non-default constructors 52 | 53 | \footnotesize 54 | 55 | 60 | 61 | \normalsize 62 | 63 | Even `DefaultSeven s2 = 20;` declaration calls non-default constructor 64 | 65 | # Non-default constructors 66 | 67 | If the only constructors provided are non-default, *no implicit default constructor is added* by the compiler 68 | 69 | Attempt to use default constructor will yield compiler error 70 | 71 | # Non-default constructors 72 | 73 | \scriptsize 74 | 75 | 94 | 95 | # Non-default constructors 96 | 97 | \scriptsize 98 | 99 | 102 | 103 | # Non-default constructors 104 | 105 | \footnotesize 106 | 107 | ```c 108 | int main() { 109 | NoDefault *s = new NoDefault[10]; 110 | cout << "s[9].get_i() = " << s[9].get_i() << endl; 111 | delete[] s; 112 | return 0; 113 | } 114 | ``` 115 | 116 | \normalsize 117 | 118 | This won't work either; `new` tries to call default constructor on each allocated `NoDefault` 119 | 120 | 140 | 141 | # Non-default constructors 142 | 143 | \scriptsize 144 | 145 | 148 | 149 | -------------------------------------------------------------------------------- /units/640_destructors/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | sequence_main 8 | -------------------------------------------------------------------------------- /units/640_destructors/destructors.cppmd: -------------------------------------------------------------------------------- 1 | # Destructors 2 | 3 | \scriptsize 4 | 5 | 26 | 27 | # Destructors 28 | 29 | \scriptsize 30 | 31 | 46 | 47 | 52 | 53 | # Destructors 54 | 55 | 56 | 83 | 84 | \tiny 85 | 86 | 89 | 90 | # Destructors 91 | 92 | Allocates `new int[sz]` in constructor, but never `delete[]`s it 93 | 94 | It's common for a constructor to obtain a resource (allocate memory, open a file, etc) that should be released when object is destroyed 95 | 96 | *Destructor* is a function called by C++ when the object goes out of scope or is otherwise deallocated (i.e. with `delete`) 97 | 98 | # Destructors 99 | 100 | \scriptsize 101 | 102 | 125 | 126 | # Destructors 127 | 128 | \footnotesize 129 | 130 | 135 | 136 | \vspace{4mm} 137 | 138 | \centerline{\includegraphics[width=2.75in]{../images/tilde.jpg}} 139 | 140 | # Destructors 141 | 142 | 160 | 161 | \scriptsize 162 | 163 | 166 | 167 | # Destructors 168 | 169 | Destructors are better than having a special member function for releasing resources; e.g.: 170 | 171 | \footnotesize 172 | 173 | 184 | 185 | # Destructors 186 | 187 | Here, user forgets to call `clean_up`: 188 | 189 | \footnotesize 190 | 191 | ```c 192 | { 193 | Sequence s(40); 194 | // ... (no call to s.clean_up()) 195 | } // s goes out of scope and memory is leaked 196 | ``` 197 | 198 | \normalsize 199 | 200 | More subtly: 201 | 202 | \footnotesize 203 | 204 | ```c 205 | { 206 | Sequence s(40); 207 | if(some_condition) { 208 | return 0; // memory leaked! 209 | } 210 | s.clean_up(); 211 | } 212 | ``` 213 | 214 | -------------------------------------------------------------------------------- /units/650_pass_by_ref/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | sequence_main 8 | -------------------------------------------------------------------------------- /units/650_pass_by_ref/pass_by_ref.cppmd: -------------------------------------------------------------------------------- 1 | # Passing by reference 2 | 3 | We've seen pass-by-reference versus pass-by-value 4 | 5 | In C++, when passing objects (`class` or `struct` variables), we usually choose to pass by reference 6 | 7 | * `const` reference if modification is not permitted 8 | * Normal reference otherwise 9 | 10 | # Passing by reference 11 | 12 | What's the difference? 13 | 14 | \vspace{3mm} 15 | 16 | ```c 17 | int sum(vector vec) { ... }; 18 | 19 | int sum(const vector& vec) { ... }; 20 | ``` 21 | 22 | # Passing by reference 23 | 24 | ```c 25 | // Creates a copy of vec 26 | int sum(vector vec) { ... }; 27 | 28 | // *Does not* create a copy of vec 29 | int sum(const vector& vec) { ... }; 30 | ``` 31 | 32 | \vspace{3mm} 33 | 34 | Second form avoids making a (potentially expensive) copy 35 | 36 | We also pass by reference for *dynamic binding*, as we'll discuss later 37 | 38 | -------------------------------------------------------------------------------- /units/660_inheritance/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | account_main1 8 | account_main2 9 | -------------------------------------------------------------------------------- /units/660_inheritance/figs.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/660_inheritance/figs.key -------------------------------------------------------------------------------- /units/670_polymorphism/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | account_main3 8 | account_main4 9 | account_main5 10 | shapes 11 | -------------------------------------------------------------------------------- /units/675_virt_dtors/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | virt_dtor 8 | virt_dtor2 9 | -------------------------------------------------------------------------------- /units/675_virt_dtors/virt_dtors.cppmd: -------------------------------------------------------------------------------- 1 | # Virtual destructors 2 | 3 | \scriptsize 4 | 5 | 26 | 27 | # Virtual destructors 28 | 29 | 39 | 40 | `new Derived()` calls `Derived` default constructor, which in turn calls `Base` default constructor; that's good 41 | 42 | Which destructor is called? 43 | 44 | * Destructor is not `virtual` 45 | * Does that mean `~Base` is called but not `~Derived`? 46 | 47 | # Virtual destructors 48 | 49 | \tiny 50 | 51 | 55 | 56 | \normalsize 57 | 58 | `~Derived` is *not* called; `derived_memory` is leaked 59 | 60 | # Virtual destructors 61 | 62 | \scriptsize 63 | 64 | 87 | 88 | # Virtual destructors 89 | 90 | 100 | 101 | # Virtual destructors 102 | 103 | \tiny 104 | 105 | 109 | 110 | \normalsize 111 | 112 | Fixed; thanks to dynamic binding, `delete obj` calls `~Derived`, which in turn calls `~Base` 113 | 114 | Derived-class destructor always implicitly calls base-class destructor at the end 115 | 116 | # Virtual destructors 117 | 118 | To avoid this in general: *Any `class` with virtual member functions* should also have a `virtual` destructor, even if the destructor does nothing 119 | 120 | -------------------------------------------------------------------------------- /units/680_overloading/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | complex 8 | complex2 9 | compound 10 | hello_world 11 | insertion_eg2 12 | print_type 13 | -------------------------------------------------------------------------------- /units/690_enum/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | card_int 8 | cards 9 | enum_1 10 | -------------------------------------------------------------------------------- /units/690_enum/enum.cppmd: -------------------------------------------------------------------------------- 1 | # `enum class` 2 | 3 | We have often used integers to describe *categorical* data 4 | 5 | ```c 6 | #include 7 | 8 | int main() { 9 | void *memory = malloc(1000000); 10 | if(memory == NULL) { 11 | return 1; // failure 12 | } 13 | // do something with memory 14 | return 0; // success 15 | } 16 | ``` 17 | 18 | Returning 0 means "success", 1 means "failure" 19 | 20 | # `enum class` 21 | 22 | ```c 23 | struct Card { 24 | int rank; // 1=ace, 2=two, ..., 10=ten 25 | // 11=jack, 12=queen, 13=king 26 | int suit; // 0=heart, 1=club, 2=diamond, 3=spade 27 | 28 | Card(int r, int s) : rank(r), suit(s) { } 29 | }; 30 | ``` 31 | 32 | `int` has advantages; e.g. we can compare ranks with `<` 33 | 34 | Also has disadvantages: 35 | 36 | * Mapping between `int`s and suits is arbitrary 37 | * If we mix up `rank` and `suit` -- e.g. `Card c(3, 13)` -- compiler can't catch it 38 | 39 | 58 | 59 | 64 | 65 | # `enum class` 66 | 67 | `enum class` creates a *categorical* type 68 | 69 | (C & C++ have an older mechanism called simply `enum` that we won't discuss here) 70 | 71 | # `enum class` 72 | 73 | \scriptsize 74 | 75 | 97 | 98 | # `enum class` 99 | 100 | \footnotesize 101 | 102 | 107 | 108 | \normalsize 109 | 110 | Behind the scenes, an `enum class` is really an `int` 111 | 112 | * Starts at 0, so `HEART=0`, `CLUB=1`, `DIAMOND=2`, `SPADE=3` 113 | 114 | C++ will refuse to implicitly convert between `enum class` and `int`; we had to explicitly cast for `cout` 115 | 116 | \footnotesize 117 | 118 | ```c 119 | cout << "c.suit = " << (int)c.suit << endl; 120 | ``` 121 | 122 | # `enum class` 123 | 124 | \footnotesize 125 | 126 | 144 | 145 | # `enum class` 146 | 147 | \scriptsize 148 | 149 | 165 | 166 | 171 | 172 | # `enum class` 173 | 174 | We get a compiler error if we mix up rank & suit 175 | 176 | \footnotesize 177 | 178 | 190 | 191 | # `enum class` 192 | 193 | \scriptsize 194 | 195 | 198 | 199 | -------------------------------------------------------------------------------- /units/700_static_members/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | circle_main 8 | temp 9 | -------------------------------------------------------------------------------- /units/700_static_members/static_members.cppmd: -------------------------------------------------------------------------------- 1 | # `static` class members 2 | 3 | A `class` member marked `static` behaves like a "global" variable or function 4 | 5 | * Typical members are associated with an *instance* of the `class`; a field takes up space in every `class` variable 6 | * `static` members are associated with the `class`, but not with instances 7 | * `this` pointer is not available in `static` member functions 8 | 9 | # `static` class members 10 | 11 | \tiny 12 | 13 | 40 | 41 | # `static` class members 42 | 43 | Static 44 | 45 | * `fahrenheit_to_celcius` 46 | * `celcius_to_kelvin` 47 | * `fahrenheit_to_kelvin` 48 | * `FREEZING` 49 | * Stored once & doesn't take space in `Temperature` variables 50 | 51 | Non-static 52 | 53 | * Constructor 54 | * `as_fahrenheit`, `as_celcius`, `as_kelvin` 55 | * `is_freezing` 56 | * `fahrenheit` 57 | * Only this takes space in `Temperature` variables 58 | 59 | # `static` class members 60 | 61 | \footnotesize 62 | 63 | 77 | 78 | 83 | 84 | # `static` class members 85 | 86 | From outside the `class` member functions, use `A::B` to access `static` member `B` of `class` `A` 87 | 88 | * `Temperature::fahrenheit_to_celcius(33)` 89 | 90 | `static const` fields with integer type can be initialized immediately: 91 | 92 | * `static const int FREEZING = 32` 93 | * Typical convention is to capitalize `static const` fields 94 | 95 | Otherwise, they are declared in the `class` definition but defined later in a `.cpp` file 96 | 97 | # `static` class members 98 | 99 | \scriptsize 100 | 101 | 116 | 117 | 125 | 126 | # `static` class members 127 | 128 | \footnotesize 129 | 130 | 141 | 142 | \scriptsize 143 | 144 | 150 | 151 | -------------------------------------------------------------------------------- /units/710_design_principles/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | -------------------------------------------------------------------------------- /units/710_design_principles/design_principles.cppmd: -------------------------------------------------------------------------------- 1 | # Design principles 2 | 3 | Learning to program and learning to be a software *designer* & *engineer* are different things 4 | 5 | Here we focus on programming, but some C/C++ concepts are best understood in light of design & engineering 6 | 7 | Let's contrast programming & software engineering: 8 | 9 | # Design principles 10 | 11 | Programming project (e.g. for this class) 12 | 13 | * Start with: formal algorithm, detailed requirements 14 | * Work: by yourself or on small team 15 | * Phases: just do it 16 | * Expected software lifetime: often brief 17 | 18 | Software engineering 19 | 20 | * Start with: human input, vague requirements 21 | * Work: on large team 22 | * Phases: user interviews, design documents, prototype, product 23 | * Expected software lifetime: years, decades 24 | * E.g. Y2K bug; that software was decades old 25 | 26 | # Design principles 27 | 28 | \centerline{\includegraphics[width=2.75in]{../images/y2k.jpg}} 29 | 30 | \centering 31 | \tiny 32 | 33 | https://en.wikipedia.org/wiki/Year_2000_problem 34 | 35 | \normalsize 36 | 37 | \raggedright 38 | 39 | An electronic sign displaying the year incorrectly as 1900 on 3 January 2000; example of [Y2K bug](https://en.wikipedia.org/wiki/Year_2000_problem) 40 | 41 | # Design principles 42 | 43 | *Readability*: easy to read and understand code 44 | 45 | *Conciseness*: no needlessly complex code, little repetition 46 | 47 | *Robustness*: modifying one aspect shouldn't break another 48 | 49 | # Design principles 50 | 51 | To achieve these goals: 52 | 53 | * *Separation of concerns*: distinct code units address distinct problems 54 | * *Encapsulation*: implementation details are hidden; only a simple interface is exposed 55 | 56 | # Separation of concerns 57 | 58 | Distinct code units address distinct problems 59 | 60 | * Code units: source files, functions, `class`es, etc 61 | * Also called *modularity* 62 | 63 | # Separation of concerns 64 | 65 | Advantages: 66 | 67 | * Promotes re-use 68 | * Easier to develop separate code units separately 69 | * Robust 70 | 71 | Caveats: 72 | 73 | * Concerns are often not perfectly separable 74 | * Chess: *some* part of the code needs to understand both `Board` and `Piece` to check if a move is legal 75 | * Combining concerns can make code more efficient 76 | * Chess: say we want to determine whether a king is "in check" without iterating over all the pieces. Hard to do without substantially mixing `Piece` and `Board` concerns. 77 | 78 | # Encapsulation 79 | 80 | Modular programming is an exercise in creating independent code units with good "interfaces": 81 | 82 | * `class`es have `public` members and `protected`/`private` members 83 | * Functions have parameters, but they also have local variables 84 | 85 | Part of the code unit is accessible (`public` members, arguments), part is hidden (`protected`/`private`, local variables) 86 | 87 | # Encapsulation 88 | 89 | I'm writing a `class`, but I don't like to spend time debugging and dealing with compiler errors. Why not make everything `public`? 90 | 91 | \footnotesize 92 | 93 | 104 | 105 | # Encapsulation 106 | 107 | A prime duty of `GradeList` is to control when and how `grades` is sorted: 108 | 109 | * If `grades` is sorted, it's easy to answer percentile queries 110 | * If it's already sorted, it's wasteful to try to sort it again 111 | 112 | Once `grades` & `is_sorted` are `public`, user can modify them and there's no guaranteed relationship between `is_sorted` & `grades` 113 | 114 | # Encapsulation 115 | 116 | Also, say we decide to switch from `vector` to `multiset` 117 | 118 | * `multiset` can always be iterated over in sorted order 119 | * ... so we can also get rid of `is_sorted` 120 | 121 | Now user code that depended on `grades` being a `vector` (or that depended on `is_sorted` existing) won't compile 122 | 123 | # Encapsulation 124 | 125 | An interface should be "as simple as possible, but no simpler" 126 | 127 | * Have a few `public` members that handle everything users need 128 | * Keep all details `private` 129 | * These can change later without breaking user code 130 | * `class` can maintain *invariants* over its private members (`is_sorted` is `true` if and only if `grades` is sorted) without fear that user will break them 131 | 132 | # Encapsulation 133 | 134 | Scott Meyers, a great C++ programmer & communicator, expresses prime design principle as: "Make interfaces easy to use correctly and hard to use incorrectly" 135 | 136 | * [bit.ly/meyers_iface](http://bit.ly/meyers_iface) 137 | 138 | # C++ design 139 | 140 | \centerline{For specific C++ design strategies:} 141 | 142 | \vspace{5mm} 143 | 144 | \centerline{\includegraphics[height=2.5in]{../images/design_patterns.jpg}} 145 | 146 | -------------------------------------------------------------------------------- /units/720_stringstream/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | extract 8 | ss1 9 | ss2 10 | -------------------------------------------------------------------------------- /units/720_stringstream/stringstream.cppmd: -------------------------------------------------------------------------------- 1 | # `stringstream` 2 | 3 | `std::stringstream` and its specialized cousins `std::istringstream` and `std::ostringstream` help you get data into and out of strings 4 | 5 | First, let's see an example of overloading the extraction (`>>`) operator 6 | 7 | # `stringstream` 8 | 9 | \footnotesize 10 | 11 | ```c 12 | std::istream& operator>>(std::istream& is, Complex& c) { 13 | // Assume format "3.0 + 4.0 i" 14 | string tmp; 15 | is >> c.real; // parse real coefficient 16 | is >> tmp; // skip the + 17 | is >> c.imaginary; // parse imaginary coefficient 18 | is >> tmp; // parse the i 19 | assert(tmp == "i"); // sanity check 20 | return is; 21 | } 22 | ``` 23 | 24 | 75 | 76 | 81 | 82 | \normalsize 83 | 84 | Similar to `operator<<` but with `istream` instead of `ostream` and `>>` instead of `<<` 85 | 86 | Second argument must be non-`const` reference so we can modify 87 | 88 | # `stringstream` 89 | 90 | `std::stringstream` is a stream, like `std::cout` or `std::cin` 91 | 92 | Instead of reading or writing to console, it reads and writes to a temporary string ("buffer") stored inside 93 | 94 | The string buffer can be accessed with `.str()` 95 | 96 | \scriptsize 97 | 98 | 113 | 114 | # `stringstream` 115 | 116 | \footnotesize 117 | 118 | 123 | 124 | \normalsize 125 | 126 | Why not use `std::string` and `+` operator instead? 127 | 128 | `+` operator overload for `std::string` only handles `std::string` or `char` arguments; often we want other types too 129 | 130 | `stringstream` works with `operator<<` and `operator>>`; an operator overload for either will work with `stringstream` just as well as with `cin`/`cout` 131 | 132 | # `stringstream` 133 | 134 | \scriptsize 135 | 136 | 155 | 156 | # `stringstream` 157 | 158 | \footnotesize 159 | 160 | 165 | 166 | # `stringstream` 167 | 168 | \scriptsize 169 | 170 | 193 | 194 | # `stringstream` 195 | 196 | \footnotesize 197 | 198 | 207 | 208 | 213 | 214 | # `stringstream` 215 | 216 | Whoa! What was that `for(int i : vec)` business? 217 | 218 | ```c 219 | for(int i : vec) { os << i << ' '; } 220 | ``` 221 | 222 | That's a "ranged `for`", a convenience added in C++11 that we will discuss more later 223 | 224 | # `stringstream` 225 | 226 | `stringstream` is an example of *multiple inheritance* 227 | 228 | Inherits from: 229 | 230 | * `istringstream`, which handles input and overloads extraction operator 231 | * `ostringstream`, which handles output and overloads insertion operator 232 | 233 | If you only need one or the other, you can use `istringstream` or `ostringstream` 234 | 235 | # `stringstream` 236 | 237 | `stringstream` can be especially useful for testing, especially if you have designed your code to handle input and output as streams 238 | 239 | Example like today's exercise: 240 | 241 | ```c 242 | // Only using for input 243 | istringstream ss("Eight of Hearts " 244 | "Ten of Hearts " 245 | "Jack of Hearts " 246 | "Nine of Hearts " 247 | "Queen of Hearts"); 248 | assert(straight_flush(ss)); 249 | ``` 250 | 251 | -------------------------------------------------------------------------------- /units/730_fstream/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | hello.txt 8 | hello2.txt 9 | ifs1 10 | ofs1 11 | seek 12 | -------------------------------------------------------------------------------- /units/730_fstream/fstream.cppmd: -------------------------------------------------------------------------------- 1 | # `fstream` 2 | 3 | In C, `printf` wrote `stdout` and `scanf` read from `stdin` 4 | 5 | `fprintf` and `fscanf` were their counterparts for working with named files 6 | 7 | In C++, we have `std::cout` and `std::cin` 8 | 9 | `std::ofstream` and `std::ifstream` are their counterparts for working with named files 10 | 11 | * `#include ` 12 | 13 | # `ofstream` / `ifstream` 14 | 15 | \footnotesize 16 | 17 | 37 | 38 | # `ofstream` / `ifstream` 39 | 40 | \footnotesize 41 | 42 | 47 | 48 | # `ofstream` / `ifstream` 49 | 50 | \scriptsize 51 | 52 | 75 | 76 | # `ofstream` / `ifstream` 77 | 78 | \footnotesize 79 | 80 | 84 | 85 | # `ofstream` / `ifstream` 86 | 87 | Could have explicitly closed the file: 88 | 89 | ```c 90 | if(ifile) { 91 | string word; 92 | while(ifile >> word) { cout << word << ' '; } 93 | cout << endl; 94 | ifile.close(); // *** explicitly close *** 95 | } 96 | } 97 | ``` 98 | 99 | Not necessary; if you don't close explicitly *the `fstream` destructor closes it for you* 100 | 101 | # `ofstream` / `ifstream` 102 | 103 | Unlike *streams* (`std::ostream`, `std::istream`), you can move *forward and backward* through a file 104 | 105 | \tiny 106 | 107 | 131 | 132 | # `ofstream` / `ifstream` 133 | 134 | \scriptsize 135 | 136 | 153 | 154 | # `ofstream` / `ifstream` 155 | 156 | \footnotesize 157 | 158 | 164 | 165 | # `ofstream` / `ifstream` 166 | 167 | To summarize: 168 | 169 | \scriptsize 170 | 171 | ```c 172 | std::ifstream is("filename"); // open file for reading 173 | if(is) { // check that open was successful 174 | is >> xyz; // read from file 175 | is.seekg(0, is.end); // move to *end* of file 176 | length = is.tellg(); // get my offset into file 177 | is.seekg(0, is.beg); // move to *beginning* of file 178 | is.read(buffer, length); // read from file (binary, like fread) 179 | is.close(); // close (alternately, let destructor do it) 180 | } 181 | 182 | std::ofstream os("filename2"); // open file for writing 183 | if(os) { // check that open was successful 184 | os << xyz; // write to file (text) 185 | os.write(buffer, length); // write to file (binary, like fwrite) 186 | } // destructor closes file 187 | ``` 188 | 189 | # `ofstream` / `ifstream` 190 | 191 | \vspace{4mm} 192 | 193 | \centerline{\includegraphics[height=2.5in]{../images/ioclasses.pdf}} 194 | 195 | -------------------------------------------------------------------------------- /units/740_exceptions/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | card_game_main1 8 | card_game_main2 9 | card_game_main3 10 | exc_spec 11 | except_unwind 12 | except_unwind2 13 | exceptions1 14 | exceptions2 15 | exceptions3 16 | -------------------------------------------------------------------------------- /units/750_ruleof3/.gitignore: -------------------------------------------------------------------------------- 1 | *.cpp 2 | *.h 3 | *.o 4 | a.out 5 | *.pdf 6 | *.md 7 | complex_main 8 | image_fixed 9 | image_main 10 | image_main2 11 | -------------------------------------------------------------------------------- /units/760_template_funcs/.gitignore: -------------------------------------------------------------------------------- 1 | seo_vec_list_1 2 | seo_vec_list_2 3 | -------------------------------------------------------------------------------- /units/770_template_classes/.gitignore: -------------------------------------------------------------------------------- 1 | ll_temp2.inc 2 | ll_temp_main 3 | ll_temp_main3 4 | ll_temp_main_cpp 5 | ll_template_cpp 6 | -------------------------------------------------------------------------------- /units/780_abstract_classes/.gitignore: -------------------------------------------------------------------------------- 1 | shape_virt 2 | -------------------------------------------------------------------------------- /units/780_abstract_classes/abstract_classes.cppmd: -------------------------------------------------------------------------------- 1 | # Abstract classes 2 | 3 | What does the `= 0` mean here? 4 | 5 | \footnotesize 6 | 7 | ```c 8 | class Piece { 9 | public: 10 | ... 11 | virtual bool legal_move_shape(CharPair, CharPair) const = 0; 12 | // ^^^^ 13 | 14 | virtual bool legal_capture_shape(CharPair start, 15 | CharPair end) const 16 | { 17 | return legal_move_shape(start, end); 18 | } 19 | ... 20 | }; 21 | ``` 22 | 23 | # Pure virtual functions 24 | 25 | Declaring a virtual member function and adding `= 0` makes it a *pure `virtual`* function 26 | 27 | When we declare a pure virtual function: 28 | 29 | * We do not give it an implementation 30 | * It makes the class it's declared in an *abstract class* 31 | 32 | * We cannot create a new object with the type, though we may be able create an object with a derived *type* 33 | 34 | # Pure virtual functions 35 | 36 | \scriptsize 37 | 38 | ```c 39 | class Shape { 40 | public: 41 | virtual double size() const = 0; 42 | ... 43 | }; 44 | 45 | class Shape2D : public Shape { 46 | ... 47 | }; 48 | 49 | class Circle : public Shape2D { 50 | public: 51 | virtual double size() const { 52 | return 3.14 * r * r; 53 | } 54 | ... 55 | private: 56 | double r; 57 | ... 58 | }; 59 | ``` 60 | 61 | # Pure virtual functions 62 | 63 | 88 | 89 | 96 | 97 | \footnotesize 98 | 99 | 104 | 105 | # Pure virtual functions 106 | 107 | 132 | 133 | 139 | 140 | \tiny 141 | 142 | 145 | 146 | 171 | 172 | # Pure virtual functions 173 | 174 | 180 | 181 | \tiny 182 | 183 | 186 | 187 | # Pure virtual functions 188 | 189 | "Cannot declare variable `s` to be of abstract type `Shape`" 190 | 191 | When a `class` has one or more pure virtual functions, it cannot be instantiated; it is *abstract* 192 | 193 | * Similar to `abstract class` and `interface` in Java 194 | 195 | The derived `Circle` class *can* be instantiated because it provides an implementation for the (only) pure virtual, `size()` 196 | 197 | # Abstract classes 198 | 199 | Another way to make a `class` abstract is give it only non-`public` constructors 200 | 201 | \footnotesize 202 | 203 | ```c 204 | class Piece { 205 | public: 206 | ... 207 | protected: 208 | // This is the only constructor 209 | Piece( bool is_white ) : _is_white( is_white ){ } 210 | ... 211 | }; 212 | ``` 213 | 214 | \normalsize 215 | 216 | Can't instantiate `Piece` because constructor can't be called from the outside 217 | 218 | # Abstract classes 219 | 220 | Derived class can still use `protected` constructor in base class: 221 | 222 | ```c 223 | class Knight : public Piece { 224 | ... 225 | public: 226 | // Knight constructor calls Piece constructor 227 | // OK because it's protected 228 | Knight( bool is_white ) : Piece( is_white ) {} 229 | ... 230 | }; 231 | ``` 232 | 233 | -------------------------------------------------------------------------------- /units/790_writing_containers/.gitignore: -------------------------------------------------------------------------------- 1 | iter_eg 2 | vec_iter 3 | vec_iter2 4 | -------------------------------------------------------------------------------- /units/800_auto/.gitignore: -------------------------------------------------------------------------------- 1 | auto1 2 | auto2 3 | -------------------------------------------------------------------------------- /units/800_auto/auto.cppmd: -------------------------------------------------------------------------------- 1 | # `auto` 2 | 3 | Use `auto` in a place where you would otherwise have written a type: 4 | 5 | ```c 6 | for(auto it = vc.begin(); it != vc.end(); it++) { 7 | ... 8 | } 9 | ``` 10 | 11 | Doing so leaves type unspecified; up to the C++ compiler to *infer* appropriate type 12 | 13 | # `auto` 14 | 15 | Sometimes, this is an easy inference to make: 16 | 17 | ```c 18 | int a = 7; 19 | auto b = a; // b clearly an int 20 | ``` 21 | 22 | Made slightly trickier by type promotion: 23 | 24 | ```c 25 | int c = 7; 26 | double d = 11.1; 27 | auto e = c * d; // e is a double 28 | ``` 29 | 30 | # `auto` 31 | 32 | `auto` variable must be initialized; compiler must be able to infer type immediately 33 | 34 | ```c 35 | auto x = 0; 36 | // above is OK 37 | 38 | auto y; 39 | y = 7; 40 | // compile error: 41 | // declaration of ‘auto y’ has no initializer 42 | ``` 43 | 44 | # `auto` 45 | 46 | \footnotesize 47 | 48 | 66 | 67 | # `auto` 68 | 69 | \footnotesize 70 | 71 | 76 | 77 | # `auto` 78 | 79 | We saw `auto` in the context of iterators: 80 | 81 | ```c 82 | int sum_every_other(const vector& ls) { 83 | int total = 0; 84 | for(vector::const_iterator it = ls.cbegin(); 85 | it != ls.cend(); it++) 86 | { 87 | total += *it; 88 | if(++it == ls.cend()) { break; } 89 | } 90 | return total; 91 | } 92 | ``` 93 | 94 | # `auto` 95 | 96 | ```c 97 | int sum_every_other(const vector& ls) { 98 | int total = 0; 99 | // using auto instead 100 | for(auto it = ls.cbegin(); it != ls.cend(); it++) { 101 | total += *it; 102 | if(++it == ls.cend()) { break; } 103 | } 104 | return total; 105 | } 106 | ``` 107 | 108 | # `auto` 109 | 110 | Con: types aren't as clear from the source code 111 | 112 | Pro: Source is more concise and, arguably, easier to maintain 113 | 114 | * Changes to types on right-hand side propagate to left: 115 | 116 | ```c 117 | int c = 7; 118 | double d = 11.1; 119 | // changing d to int would also change e to int! 120 | auto e = c * d; 121 | ``` 122 | 123 | # `auto` 124 | 125 | E.g., changing parameter type from `vector` to `list` automatically propagates to iterator type: 126 | 127 | ```c 128 | int sum_every_other(const list& ls) { 129 | int total = 0; 130 | // it *was* vector::const_iterator 131 | // *now* it's list::const_iterator 132 | for(auto it = ls.cbegin(); it != ls.cend(); it++) { 133 | total += *it; 134 | if(++it == ls.cend()) { break; } 135 | } 136 | return total; 137 | } 138 | ``` 139 | 140 | # `auto` 141 | 142 | Caution: compiler-inferred type can be unexpected: 143 | 144 | ```c 145 | vector vec = {1, 2, 3}; 146 | const vector& vec_ref; 147 | auto vec2 = vec_ref; 148 | ``` 149 | 150 | Is `vec2` a *copy* of `vec`, or an alias? 151 | 152 | # `auto` 153 | 154 | \footnotesize 155 | 156 | 175 | 176 | # `auto` 177 | 178 | \footnotesize 179 | 180 | 185 | 186 | \normalsize 187 | 188 | It's a copy 189 | 190 | Compiler inferred type `vector` for `vec2`, *not* `const vector&` 191 | 192 | -------------------------------------------------------------------------------- /units/810_ranged_for/.gitignore: -------------------------------------------------------------------------------- 1 | ranged_for1 2 | ranged_for2 3 | ranged_for3 4 | -------------------------------------------------------------------------------- /units/810_ranged_for/ranged_for.cppmd: -------------------------------------------------------------------------------- 1 | # Ranged `for` 2 | 3 | C++11 gives us a concise loop syntax, similar to Java for-each loops: 4 | 5 | 18 | 19 | # Ranged `for` 20 | 21 | \footnotesize 22 | 23 | 28 | 29 | # Ranged `for` 30 | 31 | Works on our favorite STL containers: 32 | 33 | \footnotesize 34 | 35 | 51 | 52 | # Ranged `for` 53 | 54 | \footnotesize 55 | 56 | 61 | 62 | # Ranged `for` 63 | 64 | Often combined with `auto` 65 | 66 | \scriptsize 67 | 68 | 89 | 90 | # Ranged `for` 91 | 92 | \footnotesize 93 | 94 | 99 | 100 | \normalsize 101 | 102 | Avoided writing either the iterator type or the type of the dereferenced iterator 103 | 104 | * Iterator type: `map::iterator` 105 | * Dereferenced iterator type: `pair` 106 | 107 | # Ranged `for` 108 | 109 | Works with pretty much any data structure with `begin()` & `end()` returning appropriate iterators 110 | 111 | Including all STL containers we've discussed in class 112 | 113 | -------------------------------------------------------------------------------- /units/820_override/.gitignore: -------------------------------------------------------------------------------- 1 | override 2 | override_fix 3 | override_fix2 4 | -------------------------------------------------------------------------------- /units/820_override/override.cppmd: -------------------------------------------------------------------------------- 1 | # `override` 2 | 3 | \scriptsize 4 | 5 | 27 | 28 | # `override` 29 | 30 | \footnotesize 31 | 32 | 37 | 38 | \normalsize 39 | 40 | Sometimes you *intend* to override a function in the base class... 41 | 42 | ...but you fail 43 | 44 | # `override` 45 | 46 | In this case, it was just a matter of missing a `const` 47 | 48 | \footnotesize 49 | 50 | ```c 51 | class Account { 52 | public: 53 | virtual std::string type() const { return "Account"; } 54 | }; 55 | class CheckingAccount : public Account { 56 | public: 57 | virtual std::string type() { return "CheckingAccount"; } 58 | // ^^^^^ oops 59 | }; 60 | ``` 61 | 62 | 84 | 85 | # `override` 86 | 87 | \footnotesize 88 | 89 | 94 | 95 | \normalsize 96 | 97 | That's better 98 | 99 | This is a typical mistake, often because we: 100 | 101 | * fail to match `const` status 102 | * fail to exactly match parameter & return types 103 | 104 | # `override` 105 | 106 | The `override` keyword helps 107 | 108 | When you *intend* to override a function, add the `override` modifier: 109 | 110 | \scriptsize 111 | 112 | ```c 113 | class Account { 114 | public: 115 | virtual std::string type() const { return "Account"; } 116 | }; 117 | class CheckingAccount : public Account { 118 | public: 119 | virtual std::string type() override { return "CheckingAccount"; } 120 | // ^^^^^ oops 121 | }; 122 | ``` 123 | 124 | 146 | 147 | # `override` 148 | 149 | \footnotesize 150 | 151 | 154 | 155 | # `override` 156 | 157 | Now we combine it with `const` to fix the problem: 158 | 159 | \scriptsize 160 | 161 | ```c 162 | class Account { 163 | public: 164 | virtual std::string type() const { return "Account"; } 165 | }; 166 | class CheckingAccount : public Account { 167 | public: 168 | virtual std::string type() const override { return "CheckingAccount"; } 169 | }; 170 | ``` 171 | 172 | 194 | 195 | 200 | 201 | \normalsize 202 | 203 | No warnings or errors because override was successful 204 | 205 | -------------------------------------------------------------------------------- /units/Makefile.slides: -------------------------------------------------------------------------------- 1 | #!gmake 2 | 3 | CPPMD=python ../cppmd_render.py 4 | 5 | all: $(addsuffix .pdf,$(basename $(wildcard *.cppmd))) 6 | 7 | %.pdf: %.cppmd 8 | cat ../header.yml > .$< 9 | head -n 1 $< >> .$< 10 | cat ../header.cppmd >> .$< 11 | cat $< >> .$< 12 | $(CPPMD) --prefix .$(@:%.pdf=%) --beamer-theme=metropolis --force --dont-update-gitignore < .$< 13 | mv .$@ $@ 14 | 15 | .PHONY: clean 16 | clean: 17 | rm -f *.pdf *.md *.c *.cpp *.h *.hpp *.o a.out *~ 18 | -------------------------------------------------------------------------------- /units/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | d=`pwd` 4 | d=`basename $d` 5 | 6 | cat >.build.sh < full/full.cppmd 7 | 8 | cd full && ../build.sh && cd .. 9 | -------------------------------------------------------------------------------- /units/clean_all.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | for i in */*.cppmd ; do 6 | pushd `dirname $i` 7 | make -f ../Makefile.slides clean 8 | popd 9 | done 10 | -------------------------------------------------------------------------------- /units/header.cppmd: -------------------------------------------------------------------------------- 1 | 2 | \centering 3 | 4 | \Large 5 | 6 | Ben Langmead 7 | 8 | ben.langmead@gmail.com 9 | 10 | www.langmead-lab.org 11 | 12 | \centerline{\includegraphics[width=2in]{../images/jhu_vertical_blue.png} \includegraphics[width=2in]{../images/wse_vertical_blue.png}} 13 | 14 | \centerline{\includegraphics[width=0.75in]{../images/cc_by.png}} 15 | 16 | \footnotesize 17 | 18 | Source markdown available at [github.com/BenLangmead/c-cpp-notes](https://github.com/BenLangmead/c-cpp-notes) 19 | 20 | -------------------------------------------------------------------------------- /units/header.yml: -------------------------------------------------------------------------------- 1 | --- 2 | urlcolor: blue 3 | header-includes: | 4 | \usepackage[T1]{fontenc} 5 | \usepackage{inconsolata} 6 | \usepackage{listings} 7 | \lstset{backgroundcolor=\color{lstgrey}} 8 | --- 9 | -------------------------------------------------------------------------------- /units/images/Valgrind_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/Valgrind_logo.png -------------------------------------------------------------------------------- /units/images/acct_hier.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/acct_hier.png -------------------------------------------------------------------------------- /units/images/arithmetic_ops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/arithmetic_ops.png -------------------------------------------------------------------------------- /units/images/arr_string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/arr_string.png -------------------------------------------------------------------------------- /units/images/ascii.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ascii.png -------------------------------------------------------------------------------- /units/images/binary-finger-numbers-blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/binary-finger-numbers-blank.png -------------------------------------------------------------------------------- /units/images/binary-finger-numbers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/binary-finger-numbers.png -------------------------------------------------------------------------------- /units/images/business.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/business.jpg -------------------------------------------------------------------------------- /units/images/call_stack1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/call_stack1.png -------------------------------------------------------------------------------- /units/images/call_stack2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/call_stack2.png -------------------------------------------------------------------------------- /units/images/cc_by.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/cc_by.png -------------------------------------------------------------------------------- /units/images/checkers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/checkers.jpg -------------------------------------------------------------------------------- /units/images/compile_run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/compile_run.png -------------------------------------------------------------------------------- /units/images/compile_run_just_compile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/compile_run_just_compile.png -------------------------------------------------------------------------------- /units/images/compile_run_just_edit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/compile_run_just_edit.png -------------------------------------------------------------------------------- /units/images/design_patterns.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/design_patterns.jpg -------------------------------------------------------------------------------- /units/images/exception_classes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/exception_classes.jpg -------------------------------------------------------------------------------- /units/images/fahrenheit_celsius.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/fahrenheit_celsius.jpg -------------------------------------------------------------------------------- /units/images/float.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/float.png -------------------------------------------------------------------------------- /units/images/hello_garbage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/hello_garbage.png -------------------------------------------------------------------------------- /units/images/houses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/houses.png -------------------------------------------------------------------------------- /units/images/inheritence_hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/inheritence_hierarchy.png -------------------------------------------------------------------------------- /units/images/interest_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/interest_header.png -------------------------------------------------------------------------------- /units/images/interest_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/interest_structure.png -------------------------------------------------------------------------------- /units/images/ioclasses.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ioclasses.pdf -------------------------------------------------------------------------------- /units/images/jhu_vertical_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/jhu_vertical_blue.png -------------------------------------------------------------------------------- /units/images/linked_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/linked_list.png -------------------------------------------------------------------------------- /units/images/ll_abcde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abcde.png -------------------------------------------------------------------------------- /units/images/ll_abde.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abde.png -------------------------------------------------------------------------------- /units/images/ll_abde_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abde_1.png -------------------------------------------------------------------------------- /units/images/ll_abde_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abde_2.png -------------------------------------------------------------------------------- /units/images/ll_abde_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abde_3.png -------------------------------------------------------------------------------- /units/images/ll_abde_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_abde_4.png -------------------------------------------------------------------------------- /units/images/ll_bcde1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_bcde1.png -------------------------------------------------------------------------------- /units/images/ll_bcde2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_bcde2.png -------------------------------------------------------------------------------- /units/images/ll_bcde3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_bcde3.png -------------------------------------------------------------------------------- /units/images/ll_bcde4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/ll_bcde4.png -------------------------------------------------------------------------------- /units/images/mailboxes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/mailboxes.png -------------------------------------------------------------------------------- /units/images/mem_fc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/mem_fc.png -------------------------------------------------------------------------------- /units/images/mem_fc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/mem_fc2.png -------------------------------------------------------------------------------- /units/images/new_docs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/new_docs.png -------------------------------------------------------------------------------- /units/images/pointer_diag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/pointer_diag.png -------------------------------------------------------------------------------- /units/images/pointer_mem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/pointer_mem.png -------------------------------------------------------------------------------- /units/images/pointers_xkcd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/pointers_xkcd.png -------------------------------------------------------------------------------- /units/images/rowcol.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/rowcol.png -------------------------------------------------------------------------------- /units/images/rowcol2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/rowcol2.png -------------------------------------------------------------------------------- /units/images/slicing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/slicing.jpg -------------------------------------------------------------------------------- /units/images/stack_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/stack_heap.png -------------------------------------------------------------------------------- /units/images/swap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/swap.png -------------------------------------------------------------------------------- /units/images/tictactoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/tictactoe.png -------------------------------------------------------------------------------- /units/images/tilde.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/tilde.jpg -------------------------------------------------------------------------------- /units/images/tiobe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/tiobe.png -------------------------------------------------------------------------------- /units/images/tiobe_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/tiobe_20.png -------------------------------------------------------------------------------- /units/images/twos_comp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/twos_comp.png -------------------------------------------------------------------------------- /units/images/university.small.vertical.blue.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/university.small.vertical.blue.eps -------------------------------------------------------------------------------- /units/images/vtbl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/vtbl.png -------------------------------------------------------------------------------- /units/images/wse_vertical_blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/wse_vertical_blue.png -------------------------------------------------------------------------------- /units/images/y2k.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BenLangmead/c-cpp-notes/4f8d0e7c464d6799c24026c075ce2835da4145ed/units/images/y2k.jpg -------------------------------------------------------------------------------- /units/make_all.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | for i in */*.cppmd ; do 6 | pushd `dirname $i` 7 | ../build.sh 8 | popd 9 | done 10 | -------------------------------------------------------------------------------- /units/make_full_set.py: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | import os 4 | import shutil 5 | 6 | inputs = [('010', 'get_started', 'Course goals'), 7 | ('015', 'conventions', 'Course conventions'), 8 | ('020', 'stages_hello_world', 'Stages of compilation & Hello, world'), 9 | ('030', 'types_and_ops', 'Variables, types, operators'), 10 | ('035', 'printing', 'Printing messages'), 11 | ('040', 'decisions', 'Decisions'), 12 | ('050', 'arrays', 'Arrays'), 13 | ('060', 'chars_strings', 'Characters & strings'), 14 | ('065', 'reading_input', 'Reading input'), 15 | ('070', 'command_line_args', 'Command line arguments'), 16 | ('080', 'assertions', 'Assertions'), 17 | ('090', 'math', 'Math'), 18 | ('100', 'compile_link', 'Compiling and linking'), 19 | ('110', 'functions', 'Functions'), 20 | ('120', 'program_structure', 'Program structure'), 21 | ('130', 'makefiles', 'Makefiles'), 22 | ('140', 'memory', 'Memory'), 23 | ('150', 'pointers', 'Pointers'), 24 | ('160', 'ptrs_arrays', 'Pointers & arrays'), 25 | ('170', 'lifetime_scope', 'Lifetime & scope'), 26 | ('180', 'stack_heap', 'Stack & heap'), 27 | ('190', 'dynamic_mem', 'Dynamic memory allocation'), 28 | ('200', 'valgrind', 'Debugging with valgrind'), 29 | ('210', 'gdb', 'Debugging with gdb'), 30 | ('220', 'structs', 'Structures'), 31 | ('230', 'beyond_1d', 'Beyond 1D arrays'), 32 | ('240', 'binary_io', 'Binary input/output'), 33 | ('250', 'numeric_types', 'Numeric types'), 34 | ('260', 'casting_promotion', 'Type casting & promotion'), 35 | ('270', 'bitwise_ops', 'Bitwise operators'), 36 | ('280', 'linked_lists', 'Linked lists, part 1'), 37 | ('290', 'linked_lists_2', 'Linked lists, part 2'), 38 | ('500', 'cpp_intro', 'C++ intro'), 39 | ('510', 'io_namespaces', 'C++ I/O and namespaces'), 40 | ('520', 'strings', 'C++ strings'), 41 | ('530', 'stl_intro', 'Standard Template Library (STL)'), 42 | ('540', 'vector_iter', 'STL vector & iterators'), 43 | ('550', 'map', 'STL map'), 44 | ('560', 'more_iterators', 'More about iterators'), 45 | ('570', 'pair_tuple', 'STL pairs and tuples'), 46 | ('580', 'references', 'References'), 47 | ('600', 'classes', 'Classes'), 48 | ('610', 'constructors', 'Constructors'), 49 | ('620', 'new_delete', 'new and delete'), 50 | ('630', 'non_default_ctors', 'Non-default constructors'), 51 | ('640', 'destructors', 'Destructors'), 52 | ('650', 'pass_by_ref', 'Passing by reference'), 53 | ('660', 'inheritance', 'Inheritance'), 54 | ('670', 'polymorphism', 'Polymorphism'), 55 | ('675', 'virt_dtors', 'Virtual destructors'), 56 | ('680', 'overloading', 'Overloading'), 57 | ('690', 'enum', 'Enumerations'), 58 | ('700', 'static_members', 'Static members'), 59 | ('710', 'design_principles', 'Object oriented design principles'), 60 | ('720', 'stringstream', 'Building strings with stringstream'), 61 | ('730', 'fstream', 'File I/O with fstream'), 62 | ('740', 'exceptions', 'Exceptions'), 63 | ('750', 'ruleof3', 'The Rule of 3'), 64 | ('760', 'template_funcs', 'Template functions'), 65 | ('770', 'template_classes', 'Template classes'), 66 | ('780', 'abstract_classes', 'Abstract classes'), 67 | ('790', 'writing_containers', 'Writing a container class'), 68 | ('800', 'auto', 'auto type'), 69 | ('810', 'ranged_for', 'ranged_for loops'), 70 | ('820', 'override', 'Override keyword') 71 | ] 72 | 73 | if os.path.exists('full_set'): 74 | raise RuntimeError("full_set output dir already exists") 75 | 76 | os.mkdir('full_set') 77 | 78 | manifest = os.path.join('full_set', 'manifest.txt') 79 | with open(manifest, 'wt') as manifest_fh: 80 | 81 | for num, short, long in inputs: 82 | combined = num + '_' + short 83 | input_pdf_name = short + '.pdf' 84 | input_pdf_path = os.path.join(combined, input_pdf_name) 85 | if not os.path.exists(input_pdf_path): 86 | raise RuntimeError('"%s" does not exist' % input_pdf_path) 87 | 88 | output_pdf_path = os.path.join('full_set', combined + '.pdf') 89 | shutil.copyfile(input_pdf_path, output_pdf_path) 90 | url = 'http://www.cs.jhu.edu/~langmea/resources/lecture_notes/' + combined + '.pdf' 91 | manifest_fh.write('\t'.join([combined, long, url]) + '\n') 92 | --------------------------------------------------------------------------------