CS16, Summer 2012

Lab02:
Learn about integers, formatted
printing, and getting user data


Goals for this lab

By the time you have completed this lab, you should be able to

Step by Step Instructions

Step 0: Get together with your assigned lab partner

Carefully choose the first pilot. Let the person who was the pilot for the shortest duration in lab01 be the pilot first this time. Switch roles after awhile, before the pilot gets tired, and before the navigator gets bored or distracted.

If your assigned partner is more than 5 minutes late, ask the TA to pair you with someone else for this week.

Step 1: Create a directory for this lab in the pilot's account

This lab's pilot should log in. You will (both) work in this account for the rest of the lab.

Create a ~/cs16/lab02 directory and make it your current directory:

mkdir ~/cs16/lab02
cd ~/cs16/lab02

Step 2: Use ch with printf to display integers in different ways

Start ch. As a reminder, here is what it looks like started from kyledewey's account:

-bash-4.2$ ch
                                   Ch
                Professional edition, version 6.1.0.13751
              (C) Copyright 2001-2009 SoftIntegration, Inc.
                     http://www.softintegration.com
/cs/student/kyledewey/cs16/lab02>

Now accomplish the following steps in order (we show you exactly how to do the first few steps, but after that you are mostly on your own):

  1. Declare an int (variable) named x. Note: the ; (semicolon) is optional in ch, but it is mandatory in Standard C.
    /cs/student/kyledewey/cs16/lab02> int x;
  2. Assign the value 341 to x. Notice how this assignment statement actually results in a value that ch displays, unlike the declaration statement in part a.
    /cs/student/kyledewey/cs16/lab02> x = 341;
    341
  3. Print and label the decimal (base 10) value of this variable, using printf and the %d (for decimal) conversion specifier. Print a newline character too. Normally the format string of our printf statements will end with a \n (newline) character, but we can omit it now since ch prints its own newline whenever it executes a statement that is not a declaration.
    /cs/student/kyledewey/cs16/lab02> printf("decimal: %d", x);
    decimal: 341
  4. Now print and label this same value in three different bases. First print it in hexadecimal (base 16) using %x as the conversion specifier. [Note: the up arrow repeats the previous command, but you can edit it before entering.] Second print and label the octal (base 8) representation - use %o for octal. Finally print it in binary (base 2) - ONLY IN CH - there is a %b conversion specifier, but this is not available in Standard C.

    Verify the results exactly match the following before going to part e:

    hex: 155
    octal: 525
    binary: 101010101
  5. Hey, did you notice the binary representation requires nine digits? Keeping in mind that the char data type (usually) occupies just eight bits, let's see what happens if we declare a char named c and initialize it with the value of x:
    /cs/student/kyledewey/cs16/lab02> char c = x;
    Hmmm ... apparently that is okay, but let's find out what really happened.
    1. Print the value of c in binary form. Verify it has fewer digits than x.
    2. Before continuing in ch, try to figure out the decimal value of c by hand. Sum the products of the binary digits times associated powers of two, starting with the rightmost digit times 20 (1 times 1, equals 1 in this case), then the second digit from the right times 21, the third digit times 22, and so on.
    3. Now check your answer: print the value of c in decimal form.
    4. Recall that the ASCII code for 'A' is 65 (in decimal form). Try to figure out the ASCII code associated with the current value of the variable c. You can check your answer two ways. For this part, print it with printf using %c as the conversion specifier.
    5. Now just type c at the ch prompt. Since this variable was declared as char, ch will display it that way. Notice also that a variable all by itself is an expression, so ch displays it.
    6. Jot down these results on a piece of paper in case the TA asks you about them later.

Step 3: Use ch to learn how scanf gets data from a user

The scanf function uses (mostly) the same conversion specifiers as printf does, but its purpose is to store the value of user input data into the memory locations of variables.

The memory location of a variable means the (numerical) address where the first byte of the variable is stored in memory. The C operator & is known as the "address of" operator. Assuming x was already declared (e.g., as int above), then ch will actually display this address in hexadecimal form if you type the expression:

/cs/student/kyledewey/cs16/lab02> &x
0x9c95534

The address of your variable probably will be different than the one in the example. But it doesn't matter, right? What matters is that you get to refer to that address with &x.

Now use scanf to let the user (you in this case) enter a new value of x in decimal form, and then display x to verify it worked. For example:

/cs/student/kyledewey/cs16/lab02> scanf("%d", &x);
17
/cs/student/kyledewey/cs16/lab02>
/cs/student/kyledewey/cs16/lab02> x
17

Curiously, ch seems to enter an extra newline when scanf is used. Don't worry about that, and know that it won't happen in Standard C. The main thing is we can store user data in a memory location for later use.

In fact, scanf does return a result - the count of values that it converts - in addition to storing user values in the specified memory locations. To verify, initialize a new int named count with the result of scanf (input 17 again), then let ch display count:

/cs/student/kyledewey/cs16/lab02> int count = scanf("%d", &x);
17
/cs/student/kyledewey/cs16/lab02>
/cs/student/kyledewey/cs16/lab02> count
1

This count is scanf's way of reporting success. Try it again (without declaring count again), but this time, enter something that is not a number. BE PREPARED though, as this operation likely will confuse ch - enter ctrl-d (hold the ctrl button and touch d) to return to normal ch mode. Then display the values of count, to verify it equals 0, and x to verify it still equals 17:

/cs/student/kyledewey/cs16/lab02> count = scanf("%d", &x);
cat
0        <-- here ch printed result of scanf, and echoed bad input on next line
/cs/student/kyledewey/cs16/lab02> cat     <-- after this, ch got stuck until ctrl-d
/cs/student/kyledewey/cs16/lab02> count
0
/cs/student/kyledewey/cs16/lab02> x
17

Do one more exercise before proceeding to Step 4, to find out what happens when the user enters a floating point number where an int is expected. Repeat the last few steps, but enter 92.5 or another value with a decimal point in it. Try to understand the results, and at least jot down what happened in case the TA asks you about it later.

Step 4: Use ch to get integers in different bases from a user

First: switch roles between pilot and navigator if you did not already do that.
Always stay logged into the original pilot's account.

Accomplish each of the following steps in ch (using the int variable named x):

  1. Invoke scanf to let the user enter the value of x in hexadecimal form (hint: replace %d with %x). Do enter a hexadecimal number like beef, and then display x (should be decimal 48879 if you entered beef).
  2. Let the user enter the value of x in octal (contains only digits 0 to 7), and display x.
  3. EASY ONLY IN CH - let the user enter the value of x in binary form, and display x again.
  4. Another conversion specifier for integers that we haven't used in this lab yet is %i which allows the user to enter the value as any legitimate C constant for integers. That is, the value can be entered either in decimal form (the default), or octal (has a leading 0), or hexadecimal (has 0x at the beginning). Use the following statement and display the resulting value of x at least three times to find out how it works:
    scanf("%i", &x);
    First enter a decimal value such as 59, then an octal value such as 0100 (verify it equals decimal 64), and finally a hexadecimal value such as 0xbeef.

Note: in CH ONLY, you may also specify an integer constant in binary form by leading it with 0b as in 0b11110, but it doesn't seem to work with the %i conversion specifier, and it is not available in Standard C. This should work though: try typing such a constant at the ch prompt and watch as the decimal value is displayed:

/cs/student/kyledewey/cs16/lab02> 0b11110
30

After you finish these exercises, exit ch and proceed to Step 5.

Step 5: Complete a C program to display a user's input value in various bases

Save a copy of this bases.c skeleton as bases.c in the original pilot's lab02 directory. You can cp a copy from the instructor's account:

cp ~kyledewey/cs16/lab02/bases.c ~/cs16/lab02

Add the following features to this file using emacs (or another editor of your choice). Then save, and quit the editor.

  1. Replace "YOUR NAME(S)" inside the comment at the top with your names. [Probably we won't give this instruction explicitly in future labs, but you should ALWAYS DO IT.] All other changes will be inside the main function - insert the statements immediately after each informative comment in the file.
  2. Declare an integer variable to store the user's input.
  3. Let the user know he/she should enter an integer by using printf to display an appropriate "prompt" to the screen. See the sample run in Step 6 below for an example prompt - notice how there is a space after the : (colon), but there is no newline printed in this example. Try to mimic that behavior.
  4. Use scanf to get the integer in the user's chosen base (see Step 4, part d).
  5. Display the value three times on separate lines with labels to indicate the bases used: first in decimal, then in octal, and finally in hexadecimal form. Make sure to print a newline after the last line too.
  6. Finish by returning a value that indicates the program run is successful.

Step 6: Run and test the program

You can use ch to test your program without starting a ch session. Here is a test of our solution (note the user entered the value in hexadecimal form this time, but it should work with other C constants too):

-bash-4.2$ ch ./bases.c
enter an integer: 0x1ff
decimal: 511
octal: 777
hex: 1ff
-bash-4.2$

If errors occur: (a) don't panic, and (b) don't immediately ask the TA for help! Instead, take a deep breath, and then actually read the message that comes up. It will often give a line number, and some hint as to what might be wrong.

If you've really looked, and are still stumped after two or three tries, then you might ask the TA for help. But try to fix it on your own first.

When you are satisfied it works, make an executable version of it. Then run that version to show the TA:

-bash-4.2$ make bases
cc     bases.c   -o bases
-bash-4.2$ ./bases
enter an integer: 755
decimal: 755
octal: 1363
hex: 2f3
-bash-4.2$

If no errors, proceed to Step 7. Otherwise try to figure out the problem and fix it yourselves before asking for help.

Step 7: Show off your work and get credit for the lab

Submit the assignment with the turnin program. You MUST have both your name and your partner's name in the file in order to receive credit. Remember that the original pilot needs to do this step, since that is whose account you have been using in Cooper Lab.

Bring up a terminal window on CSIL, and cd into the original pilot's cs16 directory, and cd again into the lab02 directory. Then type the following:

turnin lab02@cs16 bases.c

Respond "yes" when the program asks if you want to turn in (be sure to read the list of files you are turning in), and then wait for the message indicating success.


Evaluation and Grading

Each student must accomplish the following to earn full credit for this lab:

Deadline for lab submission: Friday, July 13 (11:59pm)


Optional Extra Challenge


Adapted by Kyle Dewey from the work of Michael Costanzo.