Skip to content

Commit 9f7ce0d

Browse files
committed
2024
1 parent e3f1a85 commit 9f7ce0d

11 files changed

Lines changed: 200 additions & 52 deletions

_toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ sections:
44
- file: part_one/intro
55
sections:
66
- file: part_one/01_running
7+
title: Running C++ code
78
- file: part_one/02_hello_world
9+
810
- file: part_one/03_simple_math
911
- file: part_one/04_input-output
1012
- file: part_one/05_troubleshooting

part_one/01_running.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# Compiling & Running
1+
# Compiling & Running C++ Code
22
```{index} compiling
33
```
44

5-
Whereas Python is mostly fairly simple to get working with straight away, especially in interactive mode, C & C++ have a few extra hurdles before you can get the computer to run your code. Your program must be compiled (and sometimes linked to other external standard or third party libraries) to produce a separate executable file, before that file can be run to solve your problem. In this section we present a number of ways of approaching this, listed in order of ease of use.
5+
Whereas Python is mostly fairly simple to get working with straight away, especially when working in interactive mode in a terminal interpretter session or a Jupyter notebook, C & C++ have a few extra hurdles before you can get the computer to run your code. Your program must be compiled (and sometimes linked to other external standard or third party libraries) to produce a separate executable file containing native machine instructions for your system, before that file can be run to finaly solve your problem. In this section we present a number of ways of approaching this, listed in order of ease of use.
66

77
## Web based solutions
88
```{index} compiling:web-based
@@ -21,13 +21,13 @@ On each of these platforms you can cut & paste code from the examples in this pr
2121
```{index} compiling: via docker
2222
```
2323

24-
A more local option is to take advantage of the combined power of Docker and Visual studio code to provide files which you can often compile with one click.
24+
A more local option is to take advantage of the combined power of Docker and Visual Studio Code to provide files which again you can often compile with one click.
2525

2626
![](images/vscode.png)
2727

2828
To begin, fork the accompanying [examples repository](https://github.com/ese-msc/c-examples) and download it, then with Docker desktop running, open your local repository in VS code. You will be presented with a query banner "Folder contains a Dev Container configuration file. Reopen folder to develop in a container (learn more).". Select "Reopen in Container". This will restart the VS Code editor window, while connecting to a Docker container build from the repository [C examples Dockerfile](https://ese-msc/c-examples/.devcontainer/Dockerfile). This container has `git` and `Python` installed, together a working linux C++ compiler (the GNU compiler) and some useful VS Code extensions installed.
2929

30-
For simple non-interactive C++ files, you can now build & run them with the Run Code button (ctrl+alt+N). For interactive files, you will need to run the program yourself using (for a file `hello.cpp` in the current directory) a command like:
30+
For simple, non-interactive C++ programmes contained in a single file, you can now build & run them with the Run Code button (ctrl+alt+N). For interactive files, you will need to run the program yourself using (for a file `hello.cpp` in the current directory) a command like:
3131

3232
```
3333
g++ -o hello hello.cpp
@@ -62,29 +62,29 @@ Most Mac users on the course will already have Homebrew installed, but for those
6262
brew install gcc
6363
```
6464

65-
will install a recent version of `gcc` (version 13 as of early December 2023) as well as placing it in your standard path. Once installed, (and having openned a new terminal) you can confirm that things work by running the following command in a terminal
65+
will install a recent version of `gcc` (version 14 as of early December 2024) as well as placing it in your standard path. Once installed, (and having openned a new terminal) you can confirm that things work by running the following command in a terminal
6666

6767
```
68-
gcc-13 --version
68+
gcc-14 --version
6969
```
7070

7171
You should see a response something like
7272

7373
```
74-
gcc-13 (Homebrew GCC 13.2.0) 13.2.0
75-
Copyright (C) 2023 Free Software Foundation, Inc.
74+
gcc-14 (Homebrew GCC 14.2.0) 13.4.0
75+
Copyright (C) 2024 Free Software Foundation, Inc.
7676
This is free software; see the source for copying conditions. There is NO
7777
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7878
```
7979

8080
To compile a C++ file called `hello.cpp` into an exectuable called `hello`, then run it, use a command like
8181

8282
```
83-
g++-13 -o hello hello.cpp
83+
g++-14 -o hello hello.cpp
8484
./hello
8585
```
8686

87-
Here `g++-13` is the name of your new GNU C++ compiler (version number 13), the `-o` option specifies the name of the output file (the default is `a.out`) and we must list the `.cpp` source file to compile into it. The second line then runs our new executable file which we have just compiled.
87+
Here `g++-14` is the name of your new GNU C++ compiler (specifically, version number 14), the `-o` option specifies the name of the output file (the default is `a.out`) and we must list the `.cpp` source file to compile into it. The second line then runs our new executable file which we have just compiled.
8888

8989
Remember, we only need to compile once, and then we can run the executable as many times as we like. If we make any changes to the source code, we must recompile before we can run the new version and see the results.
9090

@@ -101,7 +101,7 @@ cc --version
101101
You should see a response something like
102102

103103
```
104-
Apple clang version 14.0.0 (clang-1400.0.29.202)
104+
Apple clang version 19.1.4 (clang-1900.1.4.202)
105105
Target: arm64-apple-darwin21.6.0
106106
Thread model: posix
107107
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

part_one/02_hello_world.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Hello World!
1+
# A "Hello World!" Program in C++
22

33
## Introduction
44

@@ -40,7 +40,7 @@ Finally, in C/C++ we **must** use the double quotes `"` to indicate a string (th
4040
4141
## Hello World in C++
4242
43-
A C++ based hello world function might look something like the following:
43+
A canonical C++ based hello world function might look something like the following:
4444
4545
_hello.cpp_:
4646
```c++
@@ -52,14 +52,14 @@ _hello.cpp_:
5252
}
5353
```
5454

55-
You'll see that in this case, the code looks very similar to the C example. In fact, most C code is valid C++ code (possibly with a few small changes). The only thing that looks different is that rather than using a function like `printf` we are using the special `<<` operator (i.e. a token which works a bit like `+` or `-`) to send our message to `std::cout`, an "output stream" which in this case represents printing to the screen.
55+
You'll see that in this case, the code looks very similar to the C example. In fact, most C code is valid C++ code (possibly with a few small changes). The only major thing that looks different is that rather than using a function like `printf` we are using the special `<<` operator (i.e. a token which works a bit like `+` or `-`) to stream our message to `std::cout`, an "output stream" which in this case represents printing to the screen. We could have used `"\n"` again to end the line, but in C++ we can also use `std::endl` to do the same thing, as well as flushing the output buffer (which can be useful in some cases).
5656

5757
## Some key differences from Python
5858

59-
1. Whitespace doesn't matter (although it still makes things easier to read when code is nicely formatted).
60-
2. Individual statements *must* end with a `;`.
61-
3. The code starts running at the top of the `main` function. There can only be one `main` in a given programme.
62-
4. Functions (and variables) have a fixed data type associated with them.
59+
1. Whitespace in your doesn't matter (although it still makes things easier to read when code is nicely formatted). Instead `{}` are used to define blocks of code.
60+
2. Individual statements *must* end with a `;`. It's easy to forget this at first, but the compiler will remind you (often in a way that's hard to understand until you are used to it).
61+
3. Rather than starting at the top of the file, the code starts running at the top of the `main` function. There can only be one `main` function in a given programme.
62+
4. Functions (and variables) _must_ have a fixed data type associated with them the first time they are declared.
6363

6464

6565
## Exercise: Run the Hello World programs
@@ -70,7 +70,7 @@ Run the three different programs in Python, C and C++. You already know how to r
7070

7171
Once you can run the programs, try using the variable based version to try changing the message:
7272
- What happens if you leave out the `\n` instruction in the C example?
73-
- Can you add a second line of text, first in the same variable, then in a second one?
73+
- Can you add a second line of text, fist in the same call to `printf`/`std::cout`, then by adding a second one?
7474

7575

7676
## Summary

part_one/03_simple_math.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Note that unlike in Python, plotting in C++ is hard work, so we're just printing
135135
136136
## Quadrature
137137
138-
Now we'll implement two quadrature methods, the midpoint and the trapezium rules. We'll start with the Python code (see the Computational Mathematics course for the annotated versions):
138+
Now we'll implement two quadrature methods, the midpoint and the trapezium rules. We'll start with the Python code again (see the Computational Mathematics course notes for the annotated versions):
139139
140140
```python
141141
@@ -170,11 +170,11 @@ print(midpoint_rule(0, np.pi, f))
170170
print(trapezium_rule(0, np.pi, f))
171171
```
172172

173-
Now let's convert it into a C++ version
173+
Now let's convert it into a C++ version:
174174

175175
```c++
176-
#include <iostream>
177-
#include <cmath>
176+
#include <iostream> // for std::cout
177+
#include <cmath> // for std::sin
178178

179179
double midpoint_rule(double a, double b, double (*func)(double), int number_intervals=10) {
180180
double interval_size = (b - a)/number_intervals;
@@ -214,9 +214,9 @@ int main(void) {
214214
}
215215
```
216216
217-
Note that we've had to include the `cmath` header to get access to the `sin` function. We've also had to declare the function `f` as taking a double and returning a double, and then pass it as an argument to the quadrature functions. This is because C++ doesn't have a built-in `sin` function, but instead has a `sin` function for each of the floating point types (e.g. `float`, `double`, `long double`), and the compiler needs to know which one we want to use.
217+
Note that we've had to include the `cmath` header to get access to the `sin` function. We've also had to declare the function `f` as taking a double as input and returning a double, and then pass it in as an argument to the quadrature functions. This is because C++ doesn't have a single unique built-in `sin` function, but instead has a `sin` function for each of the floating point types (e.g. `float`, `double`, `long double`) in its `cmath` library, and the compiler needs to know which one we want to use.
218218
219-
The declaration and use of function pointers in the C++ versions of the `midpoint_rule` and `trapezium_rule` is more complicated than the Python version, but it's not too bad once you get used to it. We'll talk more about this in a later section.
219+
The declaration and use of function pointers in the C++ versions of the `midpoint_rule` and `trapezium_rule` is more complicated than the Python version, but it's not too impossible to remember once you get used to it. We'll talk more about this in a later section.
220220
221221
## Exercises
222222

part_one/04_input-output.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# Programs with input
1+
# C++ Programs accepting inputs
22

33
Since C++ programmes are compiled, we don't have the same flexibility to change the behaviour of the program at runtime as we do with Python. However, we can still take input data from the user in a number of ways.
44

55
## Taking input from the keyboard
66

7-
The counterpart to `std::cout` is `std::cin`. It's usage is similar but "in the other direction". For example:
7+
The counterpart to `std::cout` is `std::cin`, just as the counterpart to `print()` in Python is `input()`. The usage of `std::cin` is similar to `std::cout` but "in the other direction", using the `>>` operator. For example, the following C++ program asks for the user's name and then greets them:
88

99
```c++
1010
#include <iostream>
@@ -28,7 +28,7 @@ To run this using Docker plus VS code, you will need to run the compile command
2828
```
2929
```
3030

31-
The `>>` operator will automatically convert the input into an appropriate form for the datatype (as long as it's one of the defaults). In the example above, this is just to a string, but we can also convert to integers or floating point numbers. Let's have an example, for example a program to calculate the mean of a sequence of floating point numbers.
31+
The `>>` operator will automatically convert the input into an appropriate form for the datatype (as long as it's one of the standard C++ types like `int`, `float`, `double` etc. ). In the example above, this is just to a string, but we can also convert to integers or floating point numbers. Let's have an example, for example a program to calculate the mean of a sequence of floating point numbers.
3232

3333
```c++
3434
#include <iostream>
@@ -92,15 +92,15 @@ int main()
9292
{
9393
FILE *fptr;
9494
95-
fptr = fopen("example.txt","w"); // A lot like the Python open function
95+
fptr = fopen("example.txt", "w"); // A lot like the Python open function
9696
9797
if(fptr == NULL) // We have to do our own error checks
9898
{
99-
printf("Error!");
99+
printf("File read error!");
100100
exit(1);
101101
}
102102
103-
fprintf(fptr,"%d", 1000); // Write a number
103+
fprintf(fptr,"%d", 1000); // Write a number
104104
fclose(fptr);
105105
106106
return 0;
@@ -110,22 +110,23 @@ int main()
110110
to read a file we'd use
111111
```c
112112
int num;
113-
fptr = fopen("example.txt","r");
113+
fptr = fopen("example.txt", "r");
114114
fscanf(fptr,"%d", &num);
115115
```
116116
instead. We'll explain the use of `*` and `&` in the code above in Part III.
117117
118118
For C++ we can treat files like we do the screen by treating them as _streams_ and reading or writing with the `<<` and `>>` operators. So to write ouput
119119
120120
```c++
121+
#include <iostream>
121122
#include <fstream>
122123
123124
int main () {
124125
125126
std::fstream fs;
126127
fs.open ("example.txt", std::fstream::out);
127128
128-
fs << 1000; // write 1000 to example.txt
129+
fs << 1000 << std::endl; // write 1000 to example.txt
129130
fs.close();
130131
131132
return 0;

part_three/01_pointers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ b = a
1313
b[0] = 1
1414
print(a)
1515
```
16-
Running the above code in the Python interpretter gives the output `[1]`. This is because the names `a` and `b` have both been bound to the same list object, and updating the list via one name updates it via the other. C and C++ allow similar behaviour usuing a concept called "pointer"s.
16+
Running the above code in the Python interpretter gives the output `[1]`. This is because the names `a` and `b` have both been bound to the same list object, and updating the list via one name updates it via the other. C and C++ allow similar behaviour using a concept called "pointers".
1717

1818
A C style pointer holds a location (usually called an address) in your computer's memory, along with an attached data type. This address can be looked up ("dereferenced") to get hold of the underlying value to:
1919
1. use in an expression

part_two/01_datatypes.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ int main() {
8080
since it is permissible (though definitely not advisable) to declare variables anew in a new block.
8181

8282
## Type conversion
83+
```{index} type conversion
84+
```
8385

8486
C-like languages have a number of inbuilt rules which they use to convert values from one type to another. Typically they are converted into whatever type has the larger range, and the expression is then evaluated in that type. This means that code such as
8587

part_two/02_operators.md

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,36 @@ Like Python, C-like languages support the core mathematical operations on numeri
1616
| * | Multiplication|
1717
| / | Division |
1818

19-
Unlike Python there is no exponentiation operator (i.e. no `**`), which requires a function call instead.
19+
Unlike Python there is no exponentiation operator (i.e. no `**`), which requires making a function call instead.
20+
21+
### Operations on mixed types
22+
```{index} type conversion
23+
```
24+
25+
Remember that in C++, the type of the result of an operation is determined by the types of the operands. If the operands are of different types, the compiler may automatically convert one of them to the type of the other. This is called _type conversion_ or _type casting_. For example, if you divide an integer by a floating point number, the integer will be converted to a float before the division is performed. Generally speaking, the compiler will try to convert the "smaller" type (the one with a smaller range or less precision) to the "larger" type, but you can also force the conversion by using a _type cast_.
26+
27+
One key difference from modern Python is that C++ does not automatically convert between integer and floating point types when performing division on integers with the `\` operator. This means that if you divide two integers, the result will be an integer, with any fractional part truncated. To get a floating point result, you must convert one of the operands to a floating point type first.
28+
29+
```c++
30+
31+
#include <iostream>
32+
33+
34+
int main() {
35+
int a = 5;
36+
int b = 2;
37+
38+
// This will print 2
39+
std::cout << a/b << std::endl;
40+
41+
// This will print 2.5
42+
std::cout << (float)a/b << std::endl;
43+
44+
return 0;
45+
}
46+
```
47+
48+
The code above demonstrates this behaviour, as well as the syntax for casting a variable to a different type . The `(float)` in the second `std::cout` statement is a _type cast_ which converts the integer `a` to a floating point number before the division is performed, refer back to the previous section for more information on type casting.
2049

2150
## Logical Operators
2251
```{index} operators: logical
@@ -36,7 +65,7 @@ Again, as with Python, all the binary logical operators below work in C/C++
3665
| `a && b` | and |
3766
| `a \|\| b` | or |
3867

39-
In C++ these functions return a `bool` data type which can be equal to `true` or `false` (note the capitalization differs from Python). However, thanks to an implicit type conversion rule, _all_ positive integers evaluate to true and the value zero evaluates to false.
68+
In C++ these functions return a `bool` data type which can be equal to `true` or `false` (note the capitalization differs from Python). However, thanks to an implicit type conversion rule, _all_ positive integers evaluate to true and the value zero evaluates to false. As in Python, using comparisons with floating point numbers can be tricky due to the way they are stored in memory, and you should be careful when using them to test for equality.
4069

4170
## Other Useful Operators
4271
```{index} operators: other

0 commit comments

Comments
 (0)