Tuesday, 4 January 2011

The C Programming Language (K&R) 01x02—Convert Celsius to Fahrenheit While Loop (p. 12)—Exercises 1-3, 1-4


My second blog entry as I work my way through the book “The C Programming Language” by Brian Kernighan and Dennis Ritchie aka K&R. .

The reasons I’m doing it? To learn the language. To show others I know something about the C. To create notes for future reference where, on a blog, I can easily find an answer on something I did previously. To practice my writing of documentation and in general.

I am using Visual C++ 2010 and creating the code as a console application. At some point I will try other compilers, but that’s for another day.

Commenting Code

Commenting code is a way to show readers what’s going on. It’s a way to remind the coder what he wrote or to note what to add as in “insert code to save the world here.”

The essence of good coding is to write it in such a way that commenting would be redundant, but since that’s not always possible, comments are added.

In C, there’s one way to write comments in your source code. You start with a slash and an asterisk: /* and end with an asterisk and a slash */. Anything between these markers is ignored by the compiler. It doesn’t matter how many lines the comment takes up, the compiler ignores everything from /* to */.

The same commenting method works in C++, but they’ve added an inline commenting feature with double slashes: // It doesn’t matter where you start the comment—at the start of the line or after a statement—the compiler ignores everything from // to the end of the line. You can achieve the same result with /* comment */ on a line, but it’s easier to type //.

If you want to comment over multiply lines, use /* */ or use // at the start of each line. I prefer to use // and that’s possible because I’m using a C & C++ compiler.

Coding Style.

When it comes to C and C++, there is no universally accepted style guide. Some people prefer one method over another. Sometimes there are battles over what should be done and what shouldn’t be done. The objective in all instances is to write code that is effective (i.e., the program does what it’s supposed to do) with readability coming a distant second. To make matters worse, what’s readable to one person could be unreadable to someone else because each reader brings a level of knowledge that is unique. But there are some things that we can agree on.

A simple Print World program code looks like this to the compiler: int main(){printf("hello, world\n");return 0;}. To us, that’s difficult to read. Imagine all the source code written as character after character as if it were some ancient scroll.

To make it more readable, we break it up into chunks.

int main()
{
  printf("hello, world\n");

  return 0;
}

The main function encompasses everything from the opening curly bracket to the closing one. K&R like to put them on at the start of a line and by themselves. It helps to mark what is included in the function or statement.

The other tradition is to indent statements. The statements inside the main function are indented. The sample code to follow uses a while statement and a pair of curly brackets mark the statements controlled by the statement. Indenting those statements make it more readable.

“we will always indent the statements controlled by the while by one tab stop (which we have shown as four spaces) so you can see at a glance which statements are inside the loop. The indentation emphasizes the logical structure of the program. Although C compilers do not care about how a program looks, proper indentation and spacing are critical in making programs easy for people to read.”


K&R p. 12 Convert Celsius to Fahrenheit.

Write a program that takes a known Fahrenheit temperature and convert it to Celsius.


Attempt #1

int main()
{
     int fahr, celsius;
     int lower, upper, step;

     lower = 0; /* lower limit of temperature scale */
     upper = 300; /* upper limit */
     step = 20; /* step size */

     fahr = lower;

     while (fahr <= upper) {
           celsius = 5 * (fahr-32) / 9;
           printf("%d\t%d\n", fahr, celsius);
           fahr = fahr + step;
     }

     // keep console windown open
     system("pause");

     // return some value
    return 0;
}

Here’s the console window.



Attempt #2

int main()
{
     float fahr, celsius;
     float lower, upper, step;

     lower = 0; /* lower limit of temperature scale */
     upper = 300; /* upper limit */
     step = 20; /* step size */

     fahr = lower;

     while (fahr <= upper) {
           celsius = (5.0/9.0) * (fahr-32);
           printf("%3.0f\t%6.1f\n", fahr, celsius);
           fahr = fahr + step;
     }

     // keep console windown open
     system("pause");

     // return some value
    return 0;
}


The first code declares five variables of type integer (i.e., whole numbers).

int fahr, celsius;
int lower, upper, step;

Given the calculations required, using floating-point numbers makes more sense. The float declaration is now used. It gives 6 decimal precision.

Note the use of integer literals (constants) in the conversion equation: celsius = (5.0/9.0) * (fahr-32); If it had been written: 5 / 9 * (F-32), the results would have been erroneous because when C divides one integer by another it returns an integer. Any fraction is ignored. Using floating-point numbers for the literals (5.0 / 9.0) and variables fixes this problem. In C, 5 is an integer and 5.0 is a floating point number. Yes. No one said learning a new language would be easy.

So our variables in this version have more precise Celsius values because of the float type, but using the printf function with “%d” results in junk.

“%d” is for integers. “%f” is for floating point numbers. These formatting specifications can be modified to specify the width of the display and number of decimals.

printf("%d\t%d\n", fahr, celsius);

becomes

printf("%3.0f\t%6.1f\n", fahr, celsius);

“%3.0f” means 3 characters wide and no decimals.

“\t” is the tab escape sequence.

“%6.1f” means 6 characters wide and 1 decimal.

C and C++ are case sensitive. This rule applies to the specifications for the printf function. Use f and d, not F or D.

Here’s the new output.


 
Notice how the Fahrenheit numbers are aligned with the decimal point.

In non-English speaking Europe, numbers are often written: 123.456,78 instead of 123,456.78. Same value but different format. If I were working strictly in the Windows environment, I could tap into the international settings and get a different formatting, but that doesn’t work at this level. I’ll have to come back to this issue at another time.

K&R Exercise 1-3

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

K&R Exercise 1-4

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

Add a heading to the output and convert Celsius to Fahrenheit.

int main()
{
     float fahr, celsius;
     float lower, upper, step;

     lower = 0; /* lower limit of temperature scale */
     upper = 300; /* upper limit */
     step = 20; /* step size */

     celsius = lower;

     // Add heading.
     printf("My Heading: K&R C\n\n");

     while (celsius <= upper) {
           fahr = celsius * (9.0/5.0) + 32;
           printf("%6.1f\t%3.1f\n", celsius, fahr);
           celsius = celsius + step;
     }

     // keep console windown open
     system("pause");

     // return some value
    return 0;
}

Adding a header is straight forward.

Changing the conversion requires more changes and some simple algebra.

Here’s how it looks on my computer.
 


No comments:

Post a Comment