THIS IS NOT THE LAB FOR THE CURRENT QUARTER!!!!

If you are in one of Conrad's CS16 sections, please visit foo.cs.ucsb.edu/16wiki for information on the current quarter of CS16.

CS16, Spring 2010

lab03: ("lab three")
atoi, Command Line arguments, ASCII art


Goals for this lab

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

You'll also get more practice with:

Skills Needed

By now, we expect that you are comfortable with these basic skills from lab00, lab01, lab02, so we will no longer describe them in as much detail as we did previously:

This is a pair programming lab!

Work with your assigned pair programming partner on this lab—the same one as for lab02. If you do not have one, consult the TA for your lab and/or your instructor for advice prior to starting.

Keep the evaluation criteria in mind

As you work with your pair partner, keep in mind that part of your grade will be determined by how he/she answers these questions. So try to be a good partner!

1. Did your partner read the lab assignment and preparatory materials before coming to the scheduled lab?
2. Did your partner do a fair share of the work?
3. Did your partner cooperatively follow the pair programming model
(rotating roles of driver and navigator)?
4. Did your partner make contributions to the completion of the lab assignment?
5. Did your partner cooperate?

What we'll be doing in this lab:
ASCII Art, and command line arguments

There was a time when laser printers either hadn't been invented yet, or were not yet widely available. Thus, the only kind of printer most folks had access to was something called a "line printer", which printed only from left to right, top to bottom, and could only print the kinds of characters you find on a typewriter keyboard.

So, you might find folks making pictures like this one, found at http://chris.com/ascii/

                                 .ze$$e.
              .ed$$$eee..      .$$$$$$$P""
           z$$$$$$$$$$$$$$$$$ee$$$$$$"
        .d$$$$$$$$$$$$$$$$$$$$$$$$$"
      .$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$e..
    .$$****""""***$$$$$$$$$$$$$$$$$$$$$$$$$$$be.
                     ""**$$$$$$$$$$$$$$$$$$$$$$$L
                       z$$$$$$$$$$$$$$$$$$$$$$$$$
                     .$$$$$$$$P**$$$$$$$$$$$$$$$$
                    d$$$$$$$"              4$$$$$
                  z$$$$$$$$$                $$$P"
                 d$$$$$$$$$F                $P"
                 $$$$$$$$$$F 
                  *$$$$$$$$"
                    "***""  Gilo94'

For now, we'll be keeping things much simpler: we are going to do some very simple ASCII art of letters, numbers and symbols, in order to practice with if/else and for loops.

The first few exercises will be very simple, but they get progressively more challenging.

As an example, we will write a C function that

The function will have the following function prototype:

void starL(int width, int height);

The following table shows various calls to this function, along with their output. The rule is that the L should have height at least 2, and width at least 2, otherwise, it should print no output at all.

Function call Output   Function call Output   Function call Output
starL(3,4)
*
*
*
***
 
  starL(3,5)

* * * * ***
  starL(4,3)
*
*
****
    
starL(2,2)
*
**
  starL(2,5)
*
*
*
*
**
    
  starL(5,5)
*
*
*
*
*****
    
starL(1,1)
 
  
  starL(1,2)
 
    
  starL(2,1)
 
    
starL(4,1)
 
  
  starL(2,4)
*
*
*
**
    
  starL(4,2)

*
****
    

 

So, this is a fairly easy function to write. This will do the job:

void starL(int width, int height)
{ int i; // check if parameters are valid
if ((width<2) || (height < 2))
return; // return without printing anything // print height-1 rows of *\n for (i=0; i<height-1; i++)
printf("*\n"); // print width stars, followed by a final \n for (i=0; i<width; i++) printf("*"); printf("\n"); return; // we are finished
}

To test this function though, we might have to write a tedious kind of main (you can find this in the starLDemo.c program which is part of this week's example code.)

int main()
{
  printf("Output of starL(3,4) appears between lines below:\n");
  printf("========================\n");
  starL(3,4);
  printf("========================\n\n");

  printf("Output of starL(4,3) appears between lines below:\n");
  printf("========================\n");
  starL(4,3);
  printf("========================\n");
 

etc...

Of course, we can do better that this—here are two ways that use things we already know how to do:

Those are both reasonable choices. Instead, though, we are going to learn another new skill—the skill of using command line arguments.

We are going to write a main program called starL.c that allows us to put extra stuff on the command line after the name of the program, and access those values inside the program.

That is, when we compile and run the program starL.c, instead of typing this at the Unix prompt:

./starL

... instead, we are going to type something like this:

./starL 4 5


Inside the program, we'll be able to grab the 4 and the 5 and store those values in int variables called width and height. Then, if we want to test with a new values for width and height, it is as simple as running the program again with different values on the command line.

Ok, that's the general game plan—now lets get started.

Step by Step Instructions

Step 0: If you are still unpaired, or if your pair is more than 5 minutes late, or is absent from lab this week, get a new pair assignment from your TA.

Your TA will tell you who are are assigned to—or you may get your assignment by email.

Please be patient—depending on who shows up, there may have to be some slight adjustments to pair assignments.

We will try to avoid the situation where someone in a group of three, but if may be necessary depending on circumstances.

Step 1: If you are with a new partner, complete a new version of Worksheet W01, and make a
new post to the lab02/lab03 pair partner forum on Gauchospace.

(Otherwise, you can move on to step 2).

If you are with a new partner, we'd like to ask you to complete another copy of W01 and turn it in—along with making the forum post that it calls for—for three reasons:

Turn this in to your TA during your assigned lab section—at the top and in your forum post indicate that it is a "new" pairing for lab03.

You only need to turn in one copy per pair.

Step 2: Decide whose account you are going to work in

Remember: don't share passwords. Instead, use scp or email to share files with each other at the end of each work session. (See lab02, step 2 for details of how to use scp.)

How to share your work with each other

Again for emphasis, I will say it:

Sharing passwords is a violation of your account agreement, and can result in suspension of your computing privileges at UCSB.

Instead, what you should do is:

 

 

Step 3: Log on to CSIL, bring up a terminal window, and create a ~/cs16/lab03 directory.

If you've forgotten how, consult steps 1 and 2 from lab01.

Step 4: Copying some programs from my directory

Visit the following web link—you may want to use "right click" (or "control-click" on Mac) to bring up a window where you can open this in a new window or tab:

You should see a listing of several C programs. We are going to copy those into your ~/cs16/lab03 directory all at once with the following command:

cp ~pconrad/public_html/cs16/10S/labs/lab03/code/* ~/cs16/lab03

The * symbol in this command is a "wildcard"—it means that we want all of the files from the source directory copy be copied into the destination directory namely ~/cs16/lab03.

After doing this command, if you cd into ~/cs16/lab03 and use the ls command, you should see several files in your ~/cs16/lab03 directory—the same ones that you see if you visit the link http://www.cs.ucsb.edu/~pconrad/cs16/10S/labs/lab03/code

If so, you are ready to move on to the next step.

 

Step 5: Experimenting with atoi() in Ch

We won't be working with the C files we copied until a later step in the lab.

First, we are going to use the Ch program to experiment with a function that is part of the standard library, stdlib.h.

This function is called atoi(), and we'll need it for a later step in this week's lab.

In a regular C program, if you want to use these functions, you need to use

#include <stdlib.h>

to pull in the definitions of these functions. In Ch, though, we can just type in some sample function calls and see what happens.

Step 5a: Bringing up Ch

When logged in at a terminal session in the Cooper lab or on CSIL, type ch at the Unix prompt.

You should see something like this (except the directory will be different)

-bash-3.2$ ch
Ch Professional edition, version 6.1.0.13751 (C) Copyright 2001-2009 SoftIntegration, Inc. http://www.softintegration.com /cs/faculty/pconrad/cs16/lab03>
The very long prompt is an indication of what directory you are in. In lab02, we just used cd to go back to our home directory, shortening the prompt:
/cs/faculty/pconrad/cs16/lab03> cd
/cs/faculty/pconrad>

But there is an even better way, which we'll discuss next:

Step 5b: Customizing the Ch prompt

While in Ch, type the following command: _prompt = "Ch> "

This will change your prompt to Ch>

Note the following important details:

Here's what doing that may look like:

/cs/faculty/pconrad> _prompt = "Ch> "
Ch>

Now, your prompt is Ch> (with a space after it).

Step 5c: Experimenting with atoi()

The atoi function converts from a string such as "3" into an int value like 3. We can see how this works at the Ch prompt:

Ch> atoi("3")
3
Ch> atoi("5")
5
Ch> atoi("-42")
-42
Ch>

Note that the argument to atoi must be a string—something in "" such as "3" or "-42". If we use a single character, in single quotes such as '3', we will get an error:

Ch> atoi('4')
WARNING: found char where pointer to char is expected
Ch> 

The error message is saying the atoi found a char ('4') but what it expected was a "pointer to char" such as "4". Here's what "pointer to char" means in this context:

Here's another thing we cannot do with atoi()—we can't pass in an int or a double. Try both of these and see what you get:

atoi(4)
atoi(4.5)

Read the error messages and see if they make sense to you.

Here's a couple of other things to try. These will not result in error messages—instead, you'll get to see what atoi() does when the argument is a string, but does not contain an int—at least not an int all by itself:

atoi("six")
atoi("Go Gauchos")
atoi("4ever")
atoi("d4")
atoi("3.14")
atoi("7.99")
atoi("      5")

Based on what you see here, see if you can discover answers to the following questions. Type in more examples if you need to, in order to find the general rules:

In case you are wondering, the name atoi() comes from "ASCII to integer". ASCII is the code that is used to convert individual characters into binary so they can be stored in the computers memory. In ASCII, each character takes up 8 bits. In this code:

So, this function converts, for example,

(Letters and punctuation also have ASCII values—of course those can't be converted effectively into integer values. The capital letter 'A' is ASCII value 65, the lowercase 'a' is 97, and the '?' symbol is 63.)

Once you are satisfied that you understand how atoi works, you are ready for some programming. Use the exit command get out of Ch and return to the regular Unix prompt.

Ch> exit
-bash-3.2$

Step 6: Working with command line arguments

So far, if we wanted to get input into a program, we could only do it by using scanf.

This week, we'll see another way of getting input into a program: using command line arguments.

As an example, consider two programs that you'll find among the files you copied into your lab03 directory:

The first of these two files, computeAreaOfSquare.c is a traditional interactive program of the type you've seen before.

Now, contrast that with areaOfSquare.c. Look at this one with your pair partner. Notice:

  1. The difference on the first line of the main:
    int main(int argc, char *argv[]) instead of int main()
    • argc is a variable that indicates the number of things on the command line, and argv is an array (or "vector") of the those things.
    • For example, if we type ./areaOfSquare 4, that is two things on the command line
      • ./areaOfSquare is the first thing, and will appear in argv[0]
      • 4 is the second thing and will appear in argv[1]
    • This has been, or will be, discussed further in lecture

  2. The check of argc to make sure it is 2, and the error message that prints if it isn't.
    • If argc is not exactly 2, then we don't have the right number of things on the command line.
    • Either there are too many, which means the user is confused, or there are too few, and if we try to convert argv[1], there won't be anything there to convert.
    • So if argc isn't 2, we print an error message.
    • The standard error message for Unix progams is called a "Usage" message, and it shows the correct usage of the program—i.e. an example of what the command line arguments should be.
  3. The conversion of argv[1] using atoi(), so that it can be stored in the int variable side

Now, compile the program in the usual way ( make areaOfSquare ) and then run it, but when you run it, try these various ways of running it. Based on your understanding of the code you read, and how argc and atoi work, can you explain what happens in each case?

./areaOfSquare
./areaOfSquare 4
./areaOfSquare 6
./areaOfSquare 4 6
./areaOfSquare two
./areaOfSquare 4ever
./areaOfSquare 4.9

 

As you can see one nice thing about command line arguments is that we can test our program with a lot of different values very efficiently.

Optional: If you'd like to see another example of a program that uses interactive input vs. command line arguments, you may also look at the following files, which should also be in your lab03 directory:

Once you've experimented with computeAreaOfSquare.c and areaOfSquare.c and feel you understand how they work, you can move on to step 7.

Step 7: Practicing with the starL program

Now, look at the starL.c program that you have in this week's directory. You'll see that it has the same kind of first line in the main that areaOfSquare.c did:

int main(int argc, char *argv[])

and it has an extra #include, which is needed for the atoi function:

#include <stdlib.h>

This allows us to make the kinds of ASCII Art L's constructed with stars that are shown in the introduction to this week's lab.

Try compiling starL.c, and then run it with various command lines:

./starL 3 4
./starL 4 3
./starL
./starL 2 1
./starL foo bar fum
./starL foo bar

Try to understand what is happening in each case.

When you understand this, move on to step 8.

Step 8: Writing the starT program.

Your job now is to start with the starL.c program as an example, and write a new program called starT.c

It should do roughtly what the starL program does, but instead of having a function starL to make making L's with stars, it will have a function starT that makes the letter T according to these rules:

Here is sample output:

Function call Output   Function call Output   Function call Output
starT(3,4)
***
 *
 *
 *  
  starT(3,5)
***
 *
 *
 *
 *   
  starT(5,3)
*****
  *
  *
    
starT(3,2)
***
 *
  
  starT(5,2)
*****
  *
    
  starT(5,4)
*****
* * *
starT(5,1)
 
  
  starT(6,5)
 
    
  starT(7,3)
*******
   *
   *
    

Another hint: you may find the logic of your printKSpacesNXs() function from one of your homework assignments is useful here for printing the "stem" of the T.

Test your program by running it on all of the values shown in this table, plus at least two others of your own choosing.

e.g.

./starT 3 4
./starT 3 5
./starT 5 3
./starT 3 2
./starT 5 2
./starT 5 4
./starT 5 1
./starT 6 5
./starT 7 3
... and then two more of your own choosing.

Also test it on cases where you don't have exactly two command line arguments. In those cases, there should be code in the main program (not the function starT) that prints the following message, and returns 1 (instead of 0):

Usage: ./starT width height

When your starT.c program can do all of that, you are ready to move on to the next step.

Step 9: Automated Testing

In your directory, there are three test scripts that are designed to help you find bugs in your programs—they are called: test_starL.sh test_starT.sh and test_starZ.sh.

These are examples of shell scripts—programs that are written not in C, or Java, or Python—but in the language of the bash shell. That is, the commands in these programs are the same ones that you can type interactively at the Unix shell prompt.

These programs are not compiled—rather than are "interpreted"—the shell reads commands from the file, and the directly executes those commands. The shell is the program written in machine language that "understand" the language of the bash shell.

To prepare a shell script to be executable, we only have to change its "permission modes" with the command chmod, like this:

-bash-4.1$ chmod 755 test_starT.sh
-bash-4.1$

chmod? shell scripts? What's all this?

Note: there is a follow-on to lab03 called lab03a in which permission modes and shell scripts are discussed in more detail. In that follow-up lab, you'll learn:

For now, don't worry about those details—just follow the instructions. The point here is to use a shell script to partially automate the testing of your program starT program. For now, you don't need to know how to write your own shell scripts, at least not yet. :-)



Once the permission mode is set for a shell script—in this case, test_starL.sh—we run a shell script the same way we run an executable compiled C program. For instance, to run the program test_starL.sh , we type the name of the file preceeded by "dot slash", like this:

-bash-4.1$ ./test_starL.sh
make: `starL' is up to date.
Test passed for ./starL
Test passed for ./starL 3 4
Test passed for ./starL 3 5
Test passed for ./starL 5 3
Test passed for ./starL 3 2
Test passed for ./starL 5 2
Test passed for ./starL 5 4
Test passed for ./starL 5 1
Test passed for ./starL 1 5
Test passed for ./starL 6 5
Test passed for ./starL 7 3
-bash-4.1$ 

The idea behind the test script is that you can use it to determine whether the output of your program matches the expected output for certain values. The script is looking at a directory of files that contain the output we expect for each of the command lines shown here, i.e.

./starL
./starL 3 4
./starL 3 5

etc.

and in each case where the output matches what is in the test file, the test passes.If the test doesn't pass, we get output like this:

Test FAILED: for ./starL 3 4
=============expected output==========
*
*
*
***
==============actual output===========
****** 
======================================
This is an error that might occur, for example if we left out a \n in a crucial place.

Note that sometimes the expected output and the actual output might LOOK identical, but the difference might be extra spaces that can't be seen at the ends of lines. For example:

Test FAILED: for ./starL 7 3
=============expected output==========
*
*
*******
==============actual output===========
*
*
******* 
======================================  
  

This test failure would be particularly frustrating, because you'd look at it and say—my goodness, they look exactly the same to me?!

But fortunately. the test script takes care of this case—it checks to see if the only difference between the expected output and the actual output is white space—and if so, it prints the expected and actual output again, with an extra $ character at the end of each line, like this:

NOTE: expected matches actual except for whitespace
Here are the expected and actual with $ at the end of each line:
=============expected output with $ at end of line==========
*$
*$
*******$
==============actual output with $ at end of line===========
*$
*$
******* $
============================================================

With these extra $ symbols at the end of each line, now we can see the difference—the last line of the actual output has an extra space at the end that should not be there. That's because the programmer accidentaly wrote: printf(" \n"); instead of printf("\n");—and if we fix that, the test case passes!

Ok, your job is now to run the test script for the starT program you wrote.

How to use the test script test_starT.sh to test the starT.c program:

  1. cd into your ~/cs16/lab03 directory

  2. Run the following unix commands (you only have to do this one once per test script)

    chmod u+x ./test_starT.sh

  3. The output you are hoping for is something like this:

     -bash-3.2$ ./test_starT.sh
      make: `starT' is up to date.
      Test passed for ./starT
      Test passed for ./starT 3 4
      Test passed for ./starT 3 5
      Test passed for ./starT 5 3
      Test passed for ./starT 3 2
      Test passed for ./starT 5 2
      Test passed for ./starT 5 4
      Test passed for ./starT 5 1
      Test passed for ./starT 6 5
      Test passed for ./starT 7 3
      -bash-3.2$

    If so, you are in good shape.

  4. The output you might see instead is something like this:

    Test FAILED: for ./starT
    =============expected output==========
    Usage: ./starT width height
    ==============actual output===========
    Usage: ./starL width height
    ======================================
    

    which shows that you forgot to change your "usage" message (starL vs starT)

    Or:

    Test FAILED: for ./starT 3 4
    =============expected output==========
    ***
     *
     *
     *
    ==============actual output===========
    ***
     *
     *
     *
     *
    ======================================
    

    which shows that you didn't quite count the height of the vertical bar correctly (remember that the top row already contributes one star to the height.)

    Finally, if you get an error like this one:

     /cs/faculty/pconrad/public_html/cs16/10S/labs/lab03/tests/checkit.sh:
    line 20: 25243 Segmentation fault (core dumped) $@

    It probably means that you are trying to do something like:

     width = atoi(argv[1]);
    before you check the value of argc, which is a no-no.

    Always check argc first to make sure that argv[1], argv[2], etc actually exist before doing anything with the argv[1], argv[2], etc. values.

    Otherwise, you may get the infamous "segmentation fault" error that occurs when you try to access a piece of memory that isn't really there, or that you aren't allowed to see...

  5. If you find errors, and you already submitted, no worries---just fix the errors, and submit again, as long as it is before the deadline. The "turnin" program is configured to allow multiple submissions per lab at the moment.

  6. If you find any problems with the testing script itself, please let me know.

    Keep in mind that it is always possible for the tests themselves to contain errors. I'm pretty sure they are accurate, but if you think you've found a bug in the test script, come to office hours for your instructor or TA, or send email, and we'll investigate.

Happy testing!

Step 10: Writing the starZ program.

Your job now is to start with either the starL.c or starT.c programs as an example, and write a new program called starZ.c

This one is like the other two, except that it will draw the letter Z with stars, according to the following rules:

Here is sample output:

Function call Output   Function call Output   Function call Output
starZ(3);
   
  starZ(4);
****
  *
 *
**** 
  starZ(5);
*****
   *
  *
 *
*****
starZ(6);
******
    *
   *
  *
 *
******
  starZ(2);
 
    
  starT(-2)
 
    

Test your program by running it on all of the values shown in this table, plus at least two others of your own choosing.

Also test it on cases where you don't have exactly two command line arguments. In those cases, there should be code in the main program (not the function starT) that prints the following message, and returns 1 (instead of 0):

Usage: ./starZ width

When your starZ.c program can do all of that—try the automated test script:

-bash-4.1$ chmod 744 test_starZ.sh
-bash-4.1$ ./test_starZ.sh 
...  

When everything passes, you are ready to script and submit!

If you are stuck—if need some hints:

If you need a hint as to how to make the middle part of the Z, you might consider the program backslash.c which is in your directory. Take a look at the source code for backslash.c, and then try compiling and running it.

As you can see, it produces a backslash of a given width, as shown here. Look at the source code, and consider how you might turn backslash.c into forwardslash.c—in fact, that might be a good warm-up exercise for making the starZ.c program.

-bash-4.1$ ./backslash
Usage: ./backslash width
-bash-4.1$ ./backslash 3
*
 *
  *
-bash-4.1$ ./backslash 5
*
 *
  *
   *
    *
-bash-4.1$ ./backslash 2
*
 *
-bash-4.1$ ./backslash 4
*
 *
  *
   *
-bash-4.1$ 
  

 

Step 11: Scripting your assignment

Before doing the transcript—look over the grading rubric at the bottom of this page. Make sure you've done everything properly to maximize your grade.

In this step, we create a "transcript" of your work. We only do this after everything else is finished, and you are sure you have a good working product.

Now, to create your script:

  1. Use the proper form of the cd command to put yourself in your ~/cs16/lab03 directory
    (if you aren't already there)
  2. Type script lab03.txt
    You'll get back a regular looking unix prompt, but something is different now—everything you type, and everything that comes back from the computer is being recorded into a file called lab03.txt. It's like turning on the video camera.
  3. Type pwd to show what directory you are in.
  4. Type ls to show what files you have.
  5. Carefully—type rm starT to remove the starT excutable.
    • We do this so that when you type "make starT" in a later step, we'll see your program compining instead of the message "make: `starT' is up to date."
    • Don't accidentally remove the starT.c file or you'll be starting over from scratch!)
  6. Now, type make starT to compile your program. There should be no warnings and no errors.
  7. Next, run through all the commands listed in Step 8 to show that your program works properly, e.g.

    ./starT 3 4
    ./starT 3 5
    ./starT 5 3

    etc.

    Don't forget to include the commands that show that it works when you don't have the right number of command line parameters.

    (OR as an alternative, you can run the testing script described in step 9.)

  8. Now, repeat steps 5, 6, 7 for the starZ program—that is, rm starZ, make starZ and then show tests passing for the starZ program.
  9. Type exit to stop the recording of commands and responses into lab03.txt

When finished, type ls one more time, and you should see a new file in your lab03 directory called lab03.txt.

Use this command to list out the contents of that file:

cat lab03.txt

You should see your life flashing before your eyes, so to speak—a feeling of déjà vu should come over you—because everything in the file will be what you just typed and what came back over the last few minutes.

If so, you are ready to submit!

Step 12. Submit your assignment using the turnin program on CSIL

To submit your assignment, you need to be in the ~/cs16 directory—one level higher than the previous step (use cd ..)

When you are in inside your cs16 directory, you are ready for the turnin step.

Type the following at the prompt:

turnin lab03@cs16 lab03

If you need detailed information about how turnin works, consult the instructions in lab00 through lab02.


Evaluation and Grading (300 pts total)

Due Date: This lab is for the discussion section on 04/16/2010, however you may start on it (with your assigned pair partner) as soon as you have finished lab02.

You should try to complete this assignment by the end of the discussion section for which it was assigned, i.e. by 9:50am, 10:50am, 11:50am or 12:50pm on 04/16/2010.

If you are unable to complete it by then you may continue to work on it through Tuesday 04/20—it will be accepted without late penalty until 5pm on Tuesday 04/20.

Late assignments will only be accepted (with 20 point penalty) through Midnight on Thursday 04/23
but you are strongly encouraged to finish it before the midterm exam on Wednesday 04/21

After midnight Thursday 04/23, a zero will be recorded for everyone that has not yet submitted, and the only option will be to make up the points via extra credit.


Copyright 2010, Phillip T. Conrad, CS Dept, UC Santa Barbara. Permission to copy for non-commercial, non-profit, educational purposes granted, provided appropriate credit is given; all other rights reserved.