K&R Challenge 3 and 4: Fiddling With Formatting Strings

Today I’ll be doing things a bit differently. Since exercise 3 and 4 are quite trivial, and because the Haskell implementation will differ significantly from the C solution, I’m going to break them up into separate posts. In this post, I will implement the C solution to problems 3 and 4, and another day I’ll implement the Haskell solution.

The problem for exercise 3 is:

Modify the temperature conversion program to print a heading above the table

The program in question is as follows:

int main (int argc, char ** argv) { float fahr, celsius; int lower, upper, step; lower = 0; upper = 300; step = 20; fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf("%3.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } return 0; }

If compiled and executed, this will print the following:

0 -17.8 20 -6.7 40 4.4 ... 280 137.8 300 148.9

Strictly speaking, this is a trivial problem. The solution is to add the following line before the while loop:

printf("F C\n");

Now, we have our header:

F C 0 -17.8 20 -6.7 ... 280 137.8 300 148.9

Problem 4 is as follows:

Write a program to print the corresponding Celsius to Fahrenheit table.

This can be implemented by simply changing the line…

celsius = (5.0/9.0) * (fahr-32.0)

…to…

fahr = (9.0/5.0) * celsius+32;

…and changing the corresponding printf calls to swap the pairs. Nothing groundbreaking here. Now, let’s talk about my combined solution.

The Solutions

First, we tackle exercise 3. Technically, my previous answer fit the requirements, but I wouldn’t call it “good”. Clearly some pretty printing is in order. Additionally, I’d like to make a table with four columns to print the Fahrenheit to Celsius conversion next to the Celsius to Fahrenheit conversion. To that end, let’s add the following above the loop:

printf("Celsius <- Fahrenheit | Celsius -> Fahrenheit\n"); printf("----------------------|----------------------\n");

This is pretty self-explanatory. We Make some nice pretty columns with a horizontal line between the header and the data. On the left is the Fahrenheit to Celsius conversion, and the right is the Celsius to Fahrenheit conversion. Next, the table.

We’ll need to add extra variables to store the exercise 3 and 4 temperatures. Let’s modify our variables:

float fahr_ex3, celsius_ex3, fahr_ex4, celsius_ex4;

Now we need to calculate both conversions given the same interval:

celsius_ex3 = (5.0/9.0) * (fahr_ex3-32.0); fahr_ex4 = (9.0/5.0) * celsius_ex4+32;

After that’s done, we need to print the table row we just calculated:

printf("%7.1f <- %-10.1f | %7.1f -> %-10.1f\n", celsius_ex3, fahr_ex3, celsius_ex4, fahr_ex4);

Here we’ve updated our printf statement. We now print all four variables on one line. Additionally we’ve updated the formatting options to line the entries up neatly within the columns.

Finally, we need to modify some loop bookkeeping:

fahr_ex3 = lower; celsius_ex4 = lower; while (fahr_ex3 <= upper && celsius_ex4 <= upper) { /*Do Stuff*/ fahr_ex3 = fahr_ex3 + step; celsius_ex4 = celsius_ex4 + step; }

And we’re done! If you compile and execute this new program, the following should print to the terminal:

Celsius <- Fahrenheit | Celsius -> Fahrenheit ----------------------|---------------------- -17.8 <- 0.0 | 0.0 -> 32.0 -6.7 <- 20.0 | 20.0 -> 68.0 4.4 <- 40.0 | 40.0 -> 104.0 15.6 <- 60.0 | 60.0 -> 140.0 26.7 <- 80.0 | 80.0 -> 176.0 37.8 <- 100.0 | 100.0 -> 212.0 48.9 <- 120.0 | 120.0 -> 248.0 60.0 <- 140.0 | 140.0 -> 284.0 71.1 <- 160.0 | 160.0 -> 320.0 82.2 <- 180.0 | 180.0 -> 356.0 93.3 <- 200.0 | 200.0 -> 392.0 104.4 <- 220.0 | 220.0 -> 428.0 115.6 <- 240.0 | 240.0 -> 464.0 126.7 <- 260.0 | 260.0 -> 500.0 137.8 <- 280.0 | 280.0 -> 536.0 148.9 <- 300.0 | 300.0 -> 572.0

Aside from just looking nicer, I’d say this is more in line with the spirit of the exercise. After all, when faced with a requirements document, you can either give a customer exactly what they asked for, or you can give them what they actually want. Which is more likely to get sent back for rework?

The complete source for this solution:

#include <stdio.h> int main (int argc, char ** argv) { float fahr_ex3, celsius_ex3, fahr_ex4, celsius_ex4; int lower, upper, step; lower = 0; upper = 300; step = 20; fahr_ex3 = lower; celsius_ex4 = lower; printf("Celsius <- Fahrenheit | Celsius -> Fahrenheit\n"); printf("----------------------|----------------------\n"); while (fahr_ex3 <= upper && celsius_ex4 <= upper) { celsius_ex3 = (5.0/9.0) * (fahr_ex3-32.0); fahr_ex4 = (9.0/5.0) * celsius_ex4+32; printf("%7.1f <- %-10.1f | %7.1f -> %-10.1f\n", celsius_ex3, fahr_ex3, celsius_ex4, fahr_ex4); fahr_ex3 = fahr_ex3 + step; celsius_ex4 = celsius_ex4 + step; } return 0; }

UPDATE: The Haskell solution can be found here.

2 responses to “K&R Challenge 3 and 4: Fiddling With Formatting Strings”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: