On this page

Values and Types

In module 1 every value was typed straight into a call: circle(260, 170, 15, "green");. This lesson shows how a program works a value out, gives it a name, and changes it. It also shows why C++ wants to know what kind of value each name holds.

C++ as a calculator

A program can do arithmetic. Write the sum where a value would go, and the result is used.

#include <iostream>

int main() {
    std::cout << 2 + 3;
    std::cout << "\n";
    std::cout << 10 - 4 * 2;
    std::cout << "\n";
    std::cout << (10 - 4) * 2;
    std::cout << "\n";
}
5
2
12

2 + 3 is an expression: something the computer works out to get one value. + adds, - subtracts and * multiplies. The expression is worked out first, and then its value is printed. The output is 5, not 2 + 3.

There are no quotes around 2 + 3. Quotes would make it text, and text is printed exactly as it is written.

Look at the second and third lines of output. The order follows the rules you know from school.

  • * is worked out before + and -. So 10 - 4 * 2 is 10 - 8, which is 2.
  • Anything in parentheses is worked out first. So (10 - 4) * 2 is 6 * 2, which is 12.
  • Otherwise, the work goes from left to right.

A variable is a type, a name and a value

A variable is a named place that holds one value. This statement makes one.

int side = 120;
Part What it is
int the type: what kind of value the variable holds. int means a whole number
side the name
= "starts with this value"
120 the value

A statement that makes a variable is a declaration. After it, the name can be used wherever a value of that type could be written.

#include "scimigo.h"
using namespace scimigo;

int main() {
    int side = 120;
    canvas(600, 400);
    rectangle(100, 140, side, side, "teal");
    rectangle(380, 140, side, side, "teal");
    circle(300, 200, side - 90, "gold");
}

The value 120 is written once and used five times. Change the declaration to int side = 100; and both squares change together. The circle changes too, because its radius is worked out from side: a variable can be part of an expression.

Three rules about variables.

  • Declare before use. Statements run from the top, so the declaration must come before the first statement that uses the name.
  • The type is fixed. A variable declared as int holds a whole number for as long as it exists. It can never hold text.
  • You choose the name. A name is made of letters, digits and _, and does not start with a digit. Capital and small letters are different: side and Side are two names. Choose a name that says what the value means.

The compiler checks the type. This program asks for text to be put in an int.

#include <iostream>

int main() {
    int age = "twenty";
    std::cout << age;
}

It does not compile. The message is like this one.

your_program.cpp:4:9: error: cannot initialize a variable of type 'int' with an lvalue of type 'const char[7]'

Most of the words are for later modules. Read the part you know: line 4, and "a variable of type 'int'" was given something that is not an int.

Printing values

std::cout prints the value of a variable in the same way as it prints text. One statement can also send several things, each after its own <<. They are printed in order, from left to right, with nothing added between them.

#include <iostream>

int main() {
    int score = 90;
    std::cout << "score" << "\n";
    std::cout << score << "\n";
    std::cout << "Score: " << score << " out of " << 100 << "\n";
    std::cout << "Twice the score: " << score * 2 << "\n";
}
score
90
Score: 90 out of 100
Twice the score: 180

Compare the first two lines. "score" in quotes is text: five letters. score without quotes is the name of the variable, so its value is printed.

In the third statement, the spaces around the numbers are there because they are inside the quotes: "Score: " ends with a space, and " out of " starts and ends with one. << never adds a space.

From now on a line is usually ended with << "\n" at the end of the statement.

A new value for an old name

A variable can be given a new value after it has been declared. This is an assignment.

#include <iostream>

int main() {
    int price = 20;
    int old_price = price;
    price = 25;
    std::cout << "Now: " << price << "\n";
    std::cout << "Before: " << old_price << "\n";
}
Now: 25
Before: 20

Read price = 25; as "store 25 in price". The old value, 20, is gone from price.

= does not mean "is equal to", as it does in mathematics. It is an instruction, carried out once, at the moment the statement runs. The right side is worked out, and the result is stored in the variable on the left.

That explains old_price. The statement int old_price = price; ran when price held 20, so 20 was copied into old_price. The two variables are separate places. When price changed later, old_price kept its own copy.

An assignment has no type in front of it. The type is written once, in the declaration. Writing int price = 25; a second time would be a second declaration of the same name, and the compiler refuses it.

Read, work out, store

The right side of an assignment may use the variable that is on the left.

#include <iostream>

int main() {
    int balance = 100;
    balance = balance - 30;
    balance = balance * 2;
    balance = balance + 1;
    std::cout << balance << "\n";
}
141

In mathematics, "balance = balance - 30" could never be true. In C++ it is three moves, always in this order.

  1. Read the value the variable holds now: 100.
  2. Work out the right side with that value: 100 - 30 is 70.
  3. Store the result in the variable: balance now holds 70.

Each statement starts from the value the one before it left behind. A table with one row for each statement shows this. Making such a table is called tracing a program by hand.

Statement Read Work out balance afterwards
int balance = 100; 100
balance = balance - 30; 100 100 - 30 70
balance = balance * 2; 70 70 * 2 140
balance = balance + 1; 140 140 + 1 141

Whole numbers and numbers with a fraction

An int holds a whole number and nothing else. For a number with a fractional part, such as 0.75, use the type double. The fraction is written after a point.

#include <iostream>

int main() {
    double litres = 0.75;
    int bottles = 3;
    double total = litres * bottles;
    std::cout << "Total: " << total << "\n";
    std::cout << "Four bottles: " << litres * 4 << "\n";

    int whole_litres = total;
    std::cout << "Whole litres: " << whole_litres << "\n";
}
Total: 2.25
Four bottles: 3
Whole litres: 2

Notice three things.

  • litres * bottles mixes a double and an int. When an expression mixes the two, the int value is turned into a double first, and the result is a double. So 0.75 times 3 is 2.25, and the fraction is kept.
  • A double with nothing after the point prints without one. 0.75 times 4 is 3.0, and it is printed as 3. It is still a double.
  • An int has no room for a fraction. int whole_litres = total; stores 2.25 in an int. The fraction is cut off, and 2 is stored. The value is cut, not rounded: 2.99 would also become 2. The compiler does not stop you, and it may not warn you.

Choose int for things you count (bottles, people, pixels) and double for things you measure (litres, prices, averages).

std::cout prints at most six digits of a double. Module 3 shows how to choose the number of digits.

Dividing whole numbers

/ divides. With two whole numbers, the result is a whole number: the fraction is dropped. % gives what is left over, the remainder.

#include <iostream>

int main() {
    std::cout << 17 / 5 << "\n";
    std::cout << 17 % 5 << "\n";
    std::cout << 17.0 / 5 << "\n";
}
3
2
3.4

5 goes into 17 three times, with 2 left over. So 17 / 5 is 3 and 17 % 5 is 2. Again the fraction is cut, not rounded: 19 / 5 is 3 as well.

The third line is different because 17.0 is a double. One double in a division is enough: the other number is turned into a double, and the fraction is kept.

/ and % are worked out before + and -, as * is.

The two together split a quantity into larger and smaller units.

#include <iostream>

int main() {
    int days = 45;
    int weeks = days / 7;
    int days_left = days % 7;
    std::cout << days << " days is " << weeks << " weeks and " << days_left << " days\n";
}
45 days is 6 weeks and 3 days

% also tells odd from even: a number % 2 is 0 when the number is even and 1 when it is odd.

Two cautions.

Storing the result in a double does not bring the fraction back. The right side is worked out first, and only then stored.

#include <iostream>

int main() {
    int sweets = 17;
    int children = 5;

    double each = sweets / children;
    std::cout << each << "\n";

    double sweets_exact = sweets;
    double each_exact = sweets_exact / children;
    std::cout << each_exact << "\n";
}
3
3.4

sweets / children is an int divided by an int, so it is 3. Then 3 is stored in each. By the time the double is involved, the fraction is already gone. In the second pair of statements one side of the division is a double, so the answer is 3.4. With a number written in the program, a point does the same job: sweets / 5.0.

Do not divide a whole number by zero. There is no answer, and the program stops.

Text in a variable

Text has a type as well: std::string. A program that uses it has the line #include <string> at the top.

#include <iostream>
#include <string>

int main() {
    std::string city = "Paris";
    std::string country = "France";
    std::string place = city + ", " + country;
    std::cout << place << "\n";
    std::cout << city + country << "\n";
}
Paris, France
ParisFrance

Between pieces of text, + means join: the second text is put straight after the first. Nothing is added between them. The comma and the space in the first line of output are there because ", " was joined in.

Two limits on +.

  • At least one side of each + must be a std::string variable. "Paris" + ", France", with quoted text on both sides, does not compile.
  • + joins text with text. It does not join text and a number. To print text and a number together, send each with its own <<.

A std::string variable can be used wherever a call expects text. Here the same variable is drawn and printed.

#include "scimigo.h"
#include <iostream>
#include <string>
using namespace scimigo;

int main() {
    std::string colour = "purple";
    std::string label = "This is " + colour;
    canvas(600, 400);
    circle(300, 170, 80, colour);
    text(210, 320, label, 28);
    std::cout << label << "\n";
}
This is purple

Values that must not change

Some values are fixed for the whole program: the number of days in a week, a rate of tax. Put the word const in front of the declaration, and the compiler will not let any later statement change the variable.

#include <iostream>

int main() {
    const double pi = 3.14159;
    double radius = 10;
    std::cout << "Distance round the circle: " << 2 * pi * radius << "\n";
}
Distance round the circle: 62.8318

A const variable is read like any other. It cannot be assigned to.

#include <iostream>

int main() {
    const double pi = 3.14159;
    pi = 3;
    std::cout << pi << "\n";
}

The compiler answers with a message like this one.

your_program.cpp:5:8: error: cannot assign to variable 'pi' with const-qualified type 'const double'

It names line 5, the assignment. The mistake is found before the program runs, which is the point of const. Without it, the program would run and print wrong answers, and you would have to search for the reason.

const goes in front of any type: const int days_in_week = 7;.

How big can an int get?

An int is stored in a fixed amount of memory, so it has a largest and a smallest value.

#include <iostream>

int main() {
    int largest = 2147483647;
    std::cout << largest << "\n";
}
2147483647

That is a little more than two billion. The smallest value is about minus two billion. If a calculation goes past either limit, the result is wrong, and there is no message of any kind. The numbers in this part of the course stay far below the limit. For now it is enough to know that the limit exists.

One more rule. C++ lets you declare a variable without a value.

int count;

count does not start at 0. It holds whatever happened to be in that part of memory, so a program that reads it can do something different each time it runs. Give every variable a value in its declaration.

Your turn

Now try it yourself

Predict what a program will do, run it, and step through it line by line. The checks tell you when your own code works.

Loading the lab…

In this lab

  1. Which is worked out first?

    This program prints two numbers, each on its own line. The two expressions differ only in a pair of parentheses. Decide both answers before you run it.

  2. A name for a value

    This program declares one variable and then uses it in an expression.

  3. One number, three places

    The robot's two eyes and its nose all have radius 15, and the number 15 is typed three times. To make all three bigger you would have to edit three statements.

    Change the program so that the size is written once.

    1. As the first statement in main, declare int feature_size = 15;
    2. Use feature_size in place of the radius in all three circle calls.

    Then change the 15 in your declaration to 25 and run again. All three should grow together.

    The checks run your program again with other values in feature_size.

  4. Text and numbers on one line

    Each of the two output statements sends three things, one after each <<. The statements differ in one pair of quotes.

  5. Does the other one follow?

    b is given the value of a. Then a is changed. Decide what each variable holds at the end.

  6. Read, work out, store

    Before you answer, trace this program on paper. Write one row for each of the four statements that give count a value, and in each row write the value count holds after that statement.

  7. Whole or with a fraction?

    One variable is a double and the other is an int. The program prints their product.

  8. Seven halves

    Three lines, three divisions of seven by two. Each prints a different value.

  9. What survives?

    Three variables are declared. In each declaration the type on the left and the value on the right do not match exactly. Decide what each variable ends up holding.

  10. Text in a variable

    This program greets the robot twice: once drawn above its head, and once printed. The name Robo is typed in two places, so renaming the robot takes two edits.

    Change the program so that the name is written once.

    1. As the first statement in main, declare std::string name = "Robo";
    2. Declare a second std::string called greeting, made by joining "Hello, " and name with +.
    3. Use greeting in the text call and in the output statement. The printed line still ends with \n.

    The checks run your program again with other names.

  11. A value that must not change

    This program works out the cost of four tickets, with tax at a rate of 0.08. Run it. Four tickets at 12.5 come to 50, and 0.08 times 50 is 4, so the total should be 54. The program prints 90.

    Somewhere a statement changes the tax rate. Do not look for it yourself: let the compiler find it.

    1. Put const in front of the declaration of tax_rate.
    2. Run the program. It no longer compiles. Read the message and note the line it names.
    3. Delete the statement on that line, and run again.
  12. A sunset from three variables

    The sky and the sea are drawn. The sea begins at y = 250: that line is the horizon. Three variables say where the sun is and how big it is.

    Add three circles. Every position and size must be worked out from sun_x, sun_y and sun_radius.

    1. A glow: a "gold" circle with the same centre as the sun and twice its radius.
    2. The sun: an "orangered" circle with its centre at (sun_x, sun_y) and radius sun_radius.
    3. A reflection on the sea: an "orange" circle the same size as the sun and directly below it. Its centre is as far below the horizon as the sun's centre is above it.

    Order matters. The sun is in front of its glow. The sea hides whatever part of the glow hangs below the horizon, so the glow and the sun are drawn before the sea. The reflection lies on the sea.

    With the values given, the sun's centre is 70 above the horizon. Work out on paper where the reflection goes, then write an expression that gives the same answer.

    The checks run your program again with other values in the three variables.

  13. A receipt

    A shop sells quantity items at price each, and adds tax at tax_rate. Print a receipt of three lines.

    • The subtotal is the price times the quantity.
    • The tax is the subtotal times the tax rate.
    • The total is the subtotal plus the tax.

    With the values given, the output is exactly:

    Subtotal: 12.75
    Tax: 1.02
    Total: 13.77
    

    Work each number out from the three variables. Think about the type of every variable you declare.

    The checks run your program again with other prices, quantities and tax rates.

  14. Minutes to hours and minutes

    A film lasts total_minutes minutes. Print its length as whole hours and the minutes left over.

    With total_minutes at 135, the output is exactly:

    2 h 15 min
    

    There is one space between each part, and the line ends with \n.

    The checks run your program again with other lengths, including one shorter than an hour.

  15. Swap

    Exchange the values of left and right, so that each variable ends up holding what the other one started with.

    Write your statements between the declarations and the two output statements. Leave the declarations and the output statements exactly as they are.

    With the values given, the program must print:

    left: 8
    right: 3
    

    Try the obvious two assignments first, and trace them by hand to see what goes wrong.

    The checks run your program again with other values in left and right.

  16. Average of three

    Three test scores are whole numbers. Work out their average, keep it in a double variable called average, and print one line.

    With the scores given, the output is exactly:

    Average: 82.3333
    

    The sum is 247, and 247 divided by 3 is 82.333... If your program prints Average: 82, read the last part of the lesson section again.

    The checks run your program again with other scores.

  17. Seconds on a clock

    A stopwatch counts in seconds. Print total_seconds as hours, minutes and seconds. The minutes and the seconds are always less than 60.

    With total_seconds at 3725, the output is exactly:

    1 h 2 min 5 s
    

    The checks run your program again with other numbers of seconds.

  18. Name badge

    Draw a name badge. Two std::string variables hold the first name and the last name, and two int variables say where the badge's top-left corner is.

    1. The frame: a "navy" rectangle, 300 wide and 160 high, with its top-left corner at (badge_x, badge_y).
    2. The card: a "white" rectangle inside the frame, leaving 10 of navy showing on all four sides.
    3. The name: one text call, in letters of size 28. The words are the first name, one space, and the last name. It starts 30 to the right of the frame's left edge and 90 below its top edge.

    With the values given, the badge reads Ada Lovelace.

    The checks run your program again with other names and with the badge in another place.

  19. A trace table by hand

    Do the first part on paper, without running anything.

    The program below has six statements. Draw a table with one row for each statement and one column for each of a and b. In each row, write the value each variable holds after that statement has run. Leave a cell empty if the variable does not exist yet.

    Then check your table. After each of the six statements, add an output statement that prints both variables (after the first statement, only a), and run the program. Compare the output with your table, row by row.

    Nothing checks this one. When you have finished, go through the list below.