Where we left off
coutandcin- Debugging with
gdb - Constants
- Type casting
- Basic compiling and arithmetic
#include <iostream>
using namespace std;
#define PI 3.14159
int main() {
double r;
cout << "Enter the radius: ";
cin >> r;
cout << "The area is " << PI * r * r << endl;
return 0;
}
Today’s topics
- Predefined functions in C++
- Function calls
- Declaring and defining functions
- Separate compilation (briefly)
Textbook Sections 4.1-4.5
Program execution
The requisite
mainfunction is the program entry pointCode in
mainis executed one line at a time from top to bottommainshould be reserved for the program’s main logic, with various sub-tasks delegated to other functionsint main() { double a, b; cout << "Enter the two side lengths of a right angle triangle: "; cin >> a >> b; cout << "The hypotenuse length is " << hypoteneuse(a, b) << endl; return 0; }
Predefined functions
- C++ includes a standard library
, such as
<iostream>- Caution: Many libraries say C++ 11 or similar, but we are using C++ 98
- To use a library, include its header file at the top of your program:
#include <iostream> - Just like Python’s
import, this now gives access to all the functions iniostream
Remember how you needed to access Python functions with
.syntax, such asrandom.randint? C++ is similar, using::instead of., and theusing namespace stdstatement lets you skip thestd::part.
<cmath> functions
| Function | Description |
|---|---|
fabs(x) | Absolute value of x |
pow(x, y) | x to the power of y |
sqrt(x) | Square root of x |
ceil(x) | Smallest integer greater than or equal to x |
floor(x) | Largest integer less than or equal to x |
round(x) | Nearest integer to x |
sin(x) | Sine of x (and other trig functions) |
Review: Calling functions 1/2
Given a function pow(int x, int y) that returns $x^y$, what output do you think the following code will produce? Assume the code is part of a complete program.
- No output
- 8
- 9
- 27
- Error
int x = 2;
int y = 3;
cout << pow(y, x) << endl;
Review: Calling functions 2/2
Given a function pow(int x, int y) that returns $x^y$, what output do you think the following code will produce? Assume the code is part of a complete program.
- No output
- 8
- 9
- 27
- Error
int x = 2;
int y = 3;
pow(x, y);
cout << pow << endl;
Main takeaway: function calls
General form is similar to Python:
return_val = function_name(argument1, argument2, ...);
- Whatever is returned from the function is assigned to
return_val - Arguments are passed to the function in the parentheses
- Data type and order matters, names do not!
- Arguments can be literals, variables, or expressions
Example: formatted output
print(f"Total: ${bill:.2f}")
cout.precision(2);
cout << fixed;
cout << "Total: $" << bill << endl;
- Calling
cout.precision(n)sets the number of decimal places ton fixedprints a decimal like308.24- alternatively,
scientificprints a decimal like3.08e+02
- alternatively,
- These are called format flags
Formatting output: field width
print(f"Total: ${bill:8.2f}")
print(f"With GST: ${bill*1.05:8.2f}")
#include <iomanip>
cout.precision(2);
cout << fixed;
cout << "Total: $" << setw(8)
<< bill << endl;
cout << "With GST: $" << setw(8)
<< bill*1.05 << endl;
- The
iomaniplibrary provides more functions for formatting output setw(n)sets the field width toncharacters- Unlike
precision,setwonly affects the next output
Remember abstraction?
- Abstraction lets us hide the implementation from the interface
- To call a function, we only need to know:
- What values to pass in
- What it will return
- A general idea of what it does
- Similarly, you can write a function without ever knowing how it will be used
- This lets us break big problems into smaller ones, and reuse useful bits of code
Declaring functions
Just like variables, C++ requires functions to be declared before they are used
This tells the compiler that the function exists and how it behaves
Similar to a function header in Python:
def func_name(args) -> return_typereturn_type func_name(args);A function declaration is also called a prototype
All function declarations must be placed before
main, and ideally in a separate header file
Defining functions
def func_name(args) -> return_type:
# function body
return return_val
return_type func_name(args) {
// function body
return return_val;
}
- The declaration and function header are almost identical except:
- No semicolon after the function header
- Variable names are required
void functions
What if you don’t want to return anything?
def say_hello() -> None:
print("Hello!")
void say_hello() {
cout << "Hello!" << endl;
}
voidis an explicit return type that means “no return value”- The
returnstatement is optional - Otherwise, just like Python!
Caution: Python’s return types are just a suggestion, while in C++ they are strictly enforced.
Complete program example with functions
#include <iostream>
#include <cmath>
using namespace std;
double hypoteneuse(double a, double b); // function declaration
int main() {
double a, b;
cout << "Enter the two side lengths of a right angle triangle: ";
cin >> a >> b;
cout << "The hypotenuse length is " << hypoteneuse(a, b) << endl;
return 0
}
double hypoteneuse(double a, double b) { // function definition
return sqrt(a*a + b*b);
}
A brief preview of Separate Compilation
- We can separate the main logic from other logical groupings
- Problem:
mainneeds to know about the existence of other functions - Solution: put all the declarations in a header file (
.h), then#includeit - Header files should only contain:
- function prototypes
- type definitions (e.g.
structs) - named constants
- No variables or function definitions should go in header files!
Separate Compilation
- New project structure:
defs.hdefs.cpp-#include "defs.h"main.cpp-#include "defs.h"
- Prevents duplication of the code in
defs.h, keeps main logic clear - Compile in multiple steps:
g++ -c defs.cpp- compilesdefs.cppintodefs.og++ -c main.cpp- compilesmain.cppintomain.og++ -o main main.o defs.o- links the two object files
make
Compiling in multiple steps is a tedious process, so we automate it with a makefile
# This is "Makefile". Notice that comments begin with "#"
program: defs.o main.o
g++ main.o defs.o βo program
main.o: main.cpp
g++ -c main.cpp
defs.o: defs.cpp
g++ -c defs.cpp
- Instead of running
g++to compile, runmake(with no arguments) - This allows me to do autograded labs! For now, I’ll provide makefiles and all you have to do is run
make. You can ignore the contents of the makefile for now.
Tangent: Curly brace convention
The curly braces
{}are required to define blocks, but indentation is notThe convention is to indent the contents of a block by 4 spaces
Up to you whether the first
{is on the same line or the next:int main() { // ... }int main() { // ... }As usual, be consistent!
Refresher: Variable scope
As in Python, variables defined in a function (including parameters) are only accessible within that function:
int main() {
int x = 5;
int y = some_func();
return 0;
}
int some_func() {
return x * 2; // Error: x is not defined
}
We’ll talk more about scope next lecture
Coming up next
- Lab: Functions π - first lab with actual tests
- Lecture: Pass by reference, scope
Textbook 4.5, 5.1-5.2