Back

Activity 1.9: Type Conversion

divider

Activity 1.9

Type Conversion

Key Concepts

Text Into Numbers

Reading Inside Out

Making It Readable

When It Cannot

We Left This Broken

int gradeLevel = Console.ReadLine();
Terminal window
1-8-registration.cs(2,20): error CS0029: Cannot implicitly convert type 'string' to 'int'
The build failed. Fix the build errors and run again.

You collected the number. You could not use it.

One Word Fixes It

int gradeLevel = int.Parse(Console.ReadLine());
Terminal window
Grade level: 8 [Enter]
Next year you'll be in grade 9.

int.Parse takes text and hands back a number.

The text is not changed. A second thing is made from it.

Read It Inside Out

int.Parse(Console.ReadLine())

Console.ReadLine runs first and hands back text.

int.Parse takes that text and hands back a number.

The variable catches the number.

Innermost first, then outward.

Decimals Have Their Own

double average = double.Parse(Console.ReadLine());
Terminal window
Average raised per student? 18.4 [Enter]
Average 18.4 raised

int.Parse for whole numbers. double.Parse for anything with a decimal point.

Now Do Some Arithmetic With It

double average = 18.4;
double threeFundraisers = average * 3;
Console.WriteLine($"Three fundraisers: {threeFundraisers}");
Terminal window
Three fundraisers: 55.199999999999996

Three fundraisers at 18.4 each is 55.2. Nobody wants to read that.

Now Do Some Arithmetic With It

Terminal window
Three fundraisers: 55.199999999999996

It is not a bug and your code is not wrong.

Computers store decimals approximately, and the error only becomes visible when you show it to somebody.

Two Characters Fix It

Console.WriteLine($"Three fundraisers: {threeFundraisers:F2}");
Terminal window
Three fundraisers: 55.20

:F2 inside the braces. Fixed to two decimal places.

It Pads, Too

Console.WriteLine($"Average: {average} raised");
Console.WriteLine($"Average: {average:F2} raised");
Terminal window
Average: 18.4 raised
Average: 18.40 raised

18.4 becomes 18.40. Two decimal places means two, even when the second one is a zero.

That is what makes a column of money line up.

The Number Did Not Change

Console.WriteLine($"Rounded: {threeFundraisers:F2}");
Console.WriteLine($"Raw: {threeFundraisers}");
Terminal window
Rounded: 55.20
Raw: 55.199999999999996

:F2 changes how it is printed. It does not touch what is stored.

Do the arithmetic on the real number. Format only where you display it.

What If They Do Not Type a Number?

int students = int.Parse(Console.ReadLine());

Nothing stops them. The program has already started.

What If They Do Not Type a Number?

Terminal window
How many students signed up? seven [Enter]
Unhandled exception. System.FormatException: The input string 'seven' was not in a correct format.
at System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
at System.Int32.Parse(String s)
at Program.<Main>$(String[] args) in 1-9-planner.cs:line 2

The program stops where it stood.

Read the Last Line First

Terminal window
How many students signed up? seven [Enter]
Unhandled exception. System.FormatException: The input string 'seven' was not in a correct format.
at System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
at System.Int32.Parse(String s)
at Program.<Main>$(String[] args) in 1-9-planner.cs:line 2

It names your file and the exact line that failed.

Everything above it is C#'s own machinery. Ignore it.

Two Kinds of Mistake

You have now seen both. They are not the same kind of problem.

Two Kinds of Mistake

Last session
1-8-registration.cs(2,20): error CS0029: Cannot implicitly convert type 'string' to 'int'
The build failed. Fix the build errors and run again.

Refused before it ran.

This session
How many students signed up? seven [Enter]
Unhandled exception. System.FormatException: The input string 'seven' was not in a correct format.
at System.Number.ThrowFormatException[TChar](ReadOnlySpan`1 value)
at System.Int32.Parse(String s)
at Program.<Main>$(String[] args) in 1-9-planner.cs:line 2

Built fine. Ran fine. Then somebody typed a word.

The one on the left could never reach a user. The one on the right only reaches a user.

Why That Is Worse

A mistake the compiler catches is found by you, once.

A mistake it cannot catch is found by whoever uses your program.

Handling it needs a decision, and decisions arrive at session 12.

Today's Objectives

  • Converting input with int.Parse and double.Parse
  • Reading a call inside another call
  • Explaining why input has to be converted at all
  • Formatting a number for display with :F2
  • Recognizing a run-time error and finding the line that caused it

Key Terms

Conversion
Making a value of one type from a value of another.
Format specifier
An instruction after a colon inside braces, changing how a value is printed but not what it is.
Compile-time error
Found by reading the code, before it runs.
Run-time error
Found only while the program is running, and only sometimes.
Exception
A run-time error that stops the program and names its cause.

'F' → Fullscreen

divider

Build

Open your 1-8-registration program for Task 1. Everything after that goes in a new program named 1-9-planner.

How to read the code blocks. Each task's code block shows your whole program, from line 1, as it should look when that task is finished.

You never start a new file and you never delete your work. The green lines marked with a + are the ones you add or change for that task — everything else is already in your file. Do not type the + sign.

This activity uses two programs. Each block is titled with the file it belongs to, so check the title before you type.


Task 1: Finish Last Session

  • Uncomment the two lines you left broken at the end of Activity 1.8.
  • Add int.Parse around the Console.ReadLine call and run it.
  • Compare it with the guess you wrote down. Being wrong costs nothing; not having guessed costs the session.
1-8-registration (from Activity 1.8)
Console.Write("Grade level: ");
int gradeLevel = int.Parse(Console.ReadLine());
Console.WriteLine($"Next year you'll be in grade {gradeLevel + 1}.");

Task 2: The Field Trip Planner

  • Start 1-9-planner empty. Ask for the number of students and the bus size, then work out the buses.
  • This is the same division-and-remainder shape as Activity 1.6's raid math, taken out of hardcoded numbers and into input. Run it with 47 and 6 first and check you still get 7 and 5.
  • Then run it again with numbers of your own choosing.
1-9-planner
Console.Write("How many students signed up? ");
int students = int.Parse(Console.ReadLine());
Console.Write("How many per bus? ");
int perBus = int.Parse(Console.ReadLine());
int fullBuses = students / perBus;
int leftOver = students % perBus;
Console.WriteLine();
Console.WriteLine("=== FIELD TRIP PLAN ===");
Console.WriteLine($"Students: {students}");
Console.WriteLine($"Full buses: {fullBuses}");
Console.WriteLine($"Left over: {leftOver}");

Task 3: Two More Questions, and Making Them Readable

  • Ask for a bus fee and compute the total cost.
  • Ask for an average amount raised per student, which is not a whole number. Use double.Parse for that one.
  • Work out what three fundraisers like that would raise in total, and print that too.
  • Run it with no :F2 anywhere first. Type 18.4 for the average. Write down exactly what the three-fundraiser number looks like — all of it.
  • Then add :F2 to the average and the projection, and run it again. Write down what each one says now.
  • Note: the green lines marked with a + sign are new. Do not type the + sign.
1-9-planner
Console.Write("How many students signed up? ");
int students = int.Parse(Console.ReadLine());
Console.Write("How many per bus? ");
int perBus = int.Parse(Console.ReadLine());
Console.Write("Bus fee? ");
int busFee = int.Parse(Console.ReadLine());
Console.Write("Average raised per student? ");
double average = double.Parse(Console.ReadLine());
int fullBuses = students / perBus;
int leftOver = students % perBus;
double threeFundraisers = average * 3;
Console.WriteLine();
Console.WriteLine("=== FIELD TRIP PLAN ===");
Console.WriteLine($"Students: {students}");
Console.WriteLine($"Full buses: {fullBuses}");
Console.WriteLine($"Left over: {leftOver}");
Console.WriteLine($"Bus cost: {fullBuses * busFee}");
Console.WriteLine($"Average: {average:F2} raised");
Console.WriteLine($"Three fundraisers: {threeFundraisers:F2}");

Task 4: Break It on Purpose

Five runs of your finished planner. Write down exactly what happens each time, copied from the screen.

  1. For the number of students, type seven instead of 7.
  2. For the number of students, press Enter without typing anything.
  3. For the number of students, type 3.5.
  4. For the number of students, type 47 with a space before and after it.
  5. For the average raised per student, type 3.5.

Three of these stop the program and two do not. For each one that stops, write down the line number it names.


Challenge (Optional): Where Would You Put the Check?

  • You cannot fix Task 4 yet. Deciding what to do about bad input needs an if, and that is session 12.
  • Write a comment saying where in your program a check would have to go, and what it would have to ask.
  • Describing it in plain English is the exercise. No code.
divider

Checkpoint

Your finished planner should run like this.

Example Output
How many students signed up? 47 [Enter]
How many per bus? 6 [Enter]
Bus fee? 25 [Enter]
Average raised per student? 18.4 [Enter]
=== FIELD TRIP PLAN ===
Students: 47
Full buses: 7
Left over: 5
Bus cost: 175
Average: 18.40 raised
Three fundraisers: 55.20
  • Every number in the summary came from an answer, not from your code.
  • 47 and 6 still produce 7 and 5.
  • The average uses double.Parse, and the rest use int.Parse.
  • Both decimal lines print with exactly two decimal places, and you have the unformatted three-fundraiser number written down.
  • All five Task 4 results are written down, with line numbers where the program stopped.
divider

Reflection

Answer the following questions before submitting your work.

  1. Describe what happens in int.Parse(Console.ReadLine()), in the order it happens. Name what each part hands to the next.
  2. Activity 1.8's mistake was refused before the program ran. This session's only appears when somebody types the wrong thing. Which is more dangerous, and why?
  3. Typing 3.5 for the number of students stopped the program, even though 3.5 is obviously a number. Explain why int.Parse refused it.
divider

Submit

Submit five things to the dropbox:

  1. Your 1-9-planner program file.
  2. A copy of one full run with 47 students and buses of 6.
  3. The three-fundraiser number as it printed before you added :F2, and as it printed after.
  4. Your five Task 4 results, with the line numbers.
  5. Your three reflection answers.

Activity Complete