CSC161 2011S Imperative Problem Solving

Laboratory: Input/Output in C

Summary: This laboratory exercise provides practice with reading data, computing, and printing within a C program.

Prerequisites: Basic familiarity with Emacs and the bash shell (terminal window).

Preparation

a. Create a new directory for this laboratory. I would recommend something like ~/courses/csc161/labs/io, but the particular name that you choose is up to you.

b. Start Emacs.

c. In the directory for this laboratory, create a Makefile with the line

CFLAGS=-Wall

Exercises

Exercise 1: Converting Case

Consider the following program from K&R 1.


/**
 * lower - Convert input to lowercase.  Based on a program from section
 * 7.1 of K&R.
 */

#include <stdio.h> 
#include <ctype.h>

int
main() 
{
  int c;

  // Read characters until you hit the end of the file.
  while ((c = getchar ()) != EOF)
    {
      // Convert to lowercase and output
      putchar (tolower (c));
    } // while
  return 0;
} // main


a. Copy the file lower.c into your account. (An easy way to do this is to right-click on the link and select "Save Link As...".) Please make sure you understand the code, and then compile and run it to be sure it works.

b. Make a new program, upper, that works like lower, but converts letters to uppercase.

c. As you've seen, characters in C are just integers. Write a program, sub1, that reads in all the input characters, subtracts 1 from the character, and then prints the output.

Exercise 2: Quarts to Liters

Consider the following program for converting quartes to liters (or litres, if you prefer).


#include <stdio.h>

/**
 * q2l.c - Convert quarts to liters.
 */

#define QUARTS_PER_LITER 1.056710

int main ()
{
  int q; // Number of quarts.  Note: we only support whole numbers of quartz.
  double l; // Number of liters.
  int s;

  // Read in the number of quarts.
  printf ("Enter the number of quarts or whatever: ");
  s = scanf ("%d", &q);

  // Convert to liters.
  l = q / QUARTS_PER_LITER;

  // Print out the result
  if (s == 0)
    {
      printf ("I'm sorry, but that response was just plain stupid.\n");
      return 1;
    }

  printf ("%d quarts is %f liters.\n", q, l);
  printf ("Not that you care, but scanf returned %d.\n", s);

  // And we're done.
  return 0;
} // main


a. Copy the file q2l.c into your account. (An easy way to do this is to right-click on the link and select "Save Link As...".) Please make sure you understand the code, and then compile and run it to be sure it works.

b. Revise the program so that it uses a double value for quarts.

c. Change the printf function call, so that quarts and liters are printed to 1 decimal-place accuracy.

d. Run the revised program twice, entering 2.44 and 2.47 as the value of quarts. In printing, are these values rounded, or is the value truncated (ignoring the hundreds' digit)?

e. Change the printing, so that quarts is printed in one printf statement and liters in a second printf statement.

f. In the call to scanf, drop the ampersand before the quarts variable. What effect do you expect this change to have? Confirm your answer experimentally, and then restore the ampersand.

Exercise 3: More Conversions to Metric

Write a program that reads a person's weight in pounds and computes (and prints) the weight in grams (1 pound avoirdupois = approximately 453.59 grams).

Run your program with a few test cases. What values might you test? (Ideally, they should exercise the program's capabilities but be easy for you as programmer to check.)

Exercise 4: Even More Support for Americans Who Must Communicate With Everyone Else in the World

Write a program to read a person's height in feet and inches and print the person's height in centimeters (1 inch is approximately 2.54 centimeters). The output of the program should present an equation of the form:

5 feet 6.2 inches is approximately 168.15 centimeters

That is, the number of feet should be represented as an integer, the number of inches as a real which is printed with one decimal place of accuracy, and the number of centimeters as a real which is printed with two decimal places of accuracy. One space should separate each number from text or the comparison text.

Exercise 5: Circular Reasoning (or perhaps just reasoning about circles)

Write a program that reads the radius of a circle and prints the circle's area and circumference in a format like that illustrated below:

     radius    area     circumference
       2.5    19.63         15.71

That is, the radius, area, and circumference should appear under headings, the radius should be printed to 1 decimal place, and the area and circumference to 2 decimal places.

Exercise 6: More Sophisticated Patterns

We have primarily used scanf with only patterns for the values read (e.g., "%d%f%d"). However, like printf, scanf can include characters in the pattern string.

a. Build a program that contains the following lines. You will need to figure out types and accompanying code.

s = scanf ("%d is %d", &x, &y);
printf ("Read %d values.\n", s);

b. What do you expect to have happen when you run your program with the following inputs? After predicting a result, check your prediction experimentally before moving on to the next input.

i. 3 is 4

ii. 3is4

iii. 3 is not 4

iv. 3 is 3

v. 3.1 is 3.1

Exercise 7: Exploring Complex Patterns

a. Build a program that contains the following lines. You will need to figure out types and accompanying code.

  s1 = scanf ("= %d", &i);
  s2 = scanf ("%c", &c);
  printf ("s1=%d, s2=%d, i=%d, c='%c'\n", s1, s2, i, c);

b. What do you expect to have happen when you run your program with the following inputs? After predicting a result, check your prediction experimentally before moving on to the next input.

i. = 3a

ii. = 3 a

iii. =3a

iv. = ab

c. Summarize what these examples have taught you about the behavior of scanf with more complex patterns.

For Those With Extra Time

Extra 1: Checksums

As you may know, when we transmit information, there is a small but non-zero chance that the information may be corrupted along the way. One way to handle these problems is to compute a checksum for the information - a small number whose computation is likely to result in a different value if the information is corrupted.

An easy way to compute a checksum is to sum all of the characters read (after all, in C every character is an integer) and then take that sum modulo some number.

If we use 64 as the modulus and add 32 to the result, we should get a printable character.

For example, if the input is hello (104, 101, 108, 108, 111) the sum is 532. 532 mod 64 is 20. Character 52 is '4'. hello4.

a. Write a program that reads in a word of exactly five characters and prints out the five characters followed by their check characters. For the example above, we would print out hello4.

b. Write a program that reads in five characters plus a check character as computed above and determines whether the check character indicates that the chararacter is okay.

Extra 2: Alternate Checksums

As you may have noted, the checksum scheme we described above is fairly easy to break.

a. Give two simple changes we might make to an input word that will lead to the same checksum.

b. Come up with a better checksum routine.

Be preparted to share the deficiencies and the better routine with your colleagues.

 

History

May 1998 [Henry M. Walker]

  • Created.

January 2009 [Henry M. Walker]

  • Revised.

September 2009 [Marge Coahran]

  • Revised.
  • Very minor modifications.
  • Also, I provide a code link to an example quarts.c that I will write as an in-class demo, rather than to Henry's example from the "Annotated programs" document.

Monday, 6 September 2010 [Samuel A. Rebelsky]

  • Added an int->float problem in the first exercise.
  • Deleted the exercises in King.

Tuesday, 7 September 2010 [Samuel A. Rebelsky]

  • Added exercise titles.
  • Added preparation section.
  • Changed name of the primary quarts conversion file to q2l.c.
  • Dropped quadratic roots problem.
  • Lots of rewording of other problems.
  • Added "for those with extra time" section.
  • Added sub-exercises on forgetting ampersands.
  • Added exercises on more sophisticated patterns.
  • This version available at http://www.cs.grinnell.edu/~rebelsky/Courses/CSC161/2010F/Labs/io-lab.html

Tuesday, 8 February 2011 [Samuel A. Rebelsky]

 

Disclaimer: I usually create these pages on the fly, which means that I rarely proofread them and they may contain bad grammar and incorrect details. It also means that I tend to update them regularly (see the history for more details). Feel free to contact me with any suggestions for changes.

This document was generated by Siteweaver on Tue Feb 8 11:32:46 2011.
The source to the document was last modified on Tue Feb 8 11:32:44 2011.
This document may be found at http://www.cs.grinnell.edu/~rebelsky/Courses/CSC161/2011S/Labs/io-lab.html.

Samuel A. Rebelsky, rebelsky@grinnell.edu