Lab 0: First C Programs

Before attempting this, perhaps you should read a little about pointers, files and return values here

And you should lookup the man pages for printf and scanf with
$ man 3 printf
$ man 3 scanf
And you should look up printf and scanf in your text.

Getting Organized

Go to your home directory with the command
cd
Then make a directory where you will work on Lab 0.
mkdir -p Courses/2031/Labs/0
The -p option to mkdir (make directory), will force the creation of all the directories in between. Now go to the directory for lab 0.
cd Courses/2031/Labs/0
Make sure you are where you think you are:
pwd
You should see
/cs/home/cse12345/Courses/2031/Labs/0
(Aside: now would be a good time to try "man mkdir" and "man pwd".)
And this is where you'll do the work. If you want, you can make separate subdirectories for each of the questions, but - since there are no naming conflicts among the programs you will write - it's not really necessary.

The Task

Your task here is to write, compile and run your first C programs. Feel free to use the text and notes, but you should avoid the temptation to just copy stuff; you know it when you can make it up yourself without help - except perhaps for looking up something very specific.

Submitting Your Work

Whenever you are finished creating and testing a program, say called program.c, submit it with the command
submit 2031 lab0 program.c
The submit directory will open at the start of the lab and be closed at the end of the lab. We will not (in general) be mailing out comments on the submitted programs. The TAs (and sometimes the instructor) are available during the lab to comment on your work. Take advantage of this!

Editors

Learning a modern IDE like Eclipse is a great idea, but for this course we would like you to use a plain (but syntax aware) editor to write your programs. You will have a second window open, where you will use the command line to compile and run your programs.

A very good choice for a syntax aware editor is vi or vim (vi-improved). There is also a graphical version available as gvim. See www.vim.org.

Compiling

Be sure to compile your programs using the -Wall flag to show all warnings. And, of course, where necessary, change your program so that it does not produce any warnings.
When you compile a program called someProgram.c, let the name of the executable be someProgram, i.e. the same name, but without the .c at the end.

The Programs

  1. Write an ansi C program called hello.c that prints out Hello World! on a line.
  2. Write an ansi C program called output.c. It should contain the following declarations:
    char c = 'a';
    short s = 55;
    int n = 5;
    long int nn = 22L; /* Can also use = 22l, but the l (ell) looks like a 1 (one) */
    long long int nnn = 33LL /* can also use = 33ll */
    float x = 7.5f;
    double y = 99.1234567;
    long double z = 99.5L;
    char someString[] = "This is some string.";
    		
    BUT DO NOT copy and paste. Type it in.

    It should use printf() to produce exactly the following output:
    c as an integer: 97
    c as a character: a
    s is 55
    n is 5
    nn is 22
    nnn is 33
    x is 7.500
    y is   99.12
    z is 99.500000
    someString is This is some string.
    "someString" is "This is some string."
    		
    The last item output, like all the others, should end with a newline character.
    Recall that the printf() function is invoked as printf(format string, additional arguments). In the printf() statements, use the variable names for the additional arguments, not the value of the variable. For example, use printf(" ... ", n), not printf(" ... ", 55).

    Get used to specifying what you expect the output of your program to be BEFORE you write the program. For this program, you want the output to be like this


    Download this file. Compile your program to have the name output and run it, saving the outut to a file called myOut1. Then use diff to compare your output with the expected output as follows:
    $ output > myOut1
    $ diff myOut1 out1
    $
    
    If the two files are byte-for-byte the same, diff will return silently. If not, fix it.


  3. Write an ansi C program called input.c. It should contain the following declarations:
    int a, b, c;
    int scanfReturnValue; 
    		
    Write code to read in values for a, b and c from standard input and then print out the values read. First print out the value returned by scanf in each case. The statement to read in the values and assign them to a, b and c would look like this:
    scanfReturnValue = scanf("%d %d %d", &a, &b, &c);
    printf("scanf returned %d\n", scanfReturnValue);
    printf("a = %d, b = %d, c = %d\n", a, b, c);
    		
    Look at the scanf() statement. The "%d" says you're expecting to read in an int (in decimal/base 10) and the "&" before the a, b and c indicates the address where a, b, c are stored and scanf reads the input values entered and stores them at these addresses. (Remember that C, like java, is pass by value.) Running your program might produce results like this:
    $ 
    $ input
        45
            33
      22
    scanf returned 3
    a = 45, b = 33, c = 22
    $ 
    $ 
    		
    The first 3 lines are echoed program input; the last 2 are program output.

    Again, specify expected output, this time with a given input. (This should actually have been done before the program was written.) Download these files
    Run and test your program as follows:
    $ input < in2 > myOut2
    $ diff myOut2 out2
    $
    
    diff should return silently. Try putting some numbers into a file and then redirecting standard input to come from the file, as in:
    $ input < fileName
    		
    What happens if there are ...
    more than 3 numbers in the file?
    fewer than 3?
    none?
    2 integers and then a double like 5 7 15.75?
    some text like 5 7 hello?
    or 5 7 99hello?

  4. In the last exercise, you saw how to use scanf() to read in an integer. Of course, you'll want to use it to read in all kinds of values. In this exercise, you'll redo the first exercise, but instead of the variable values being given explicitly with numeric or string literals, they'll be assigned using scanf(). Before, you had
    char c = 'a';
    short s = 55;
    int n = 5;
    long int nn = 22L;
    long long int nnn = 33LL;
    float x = 7.5f;
    double y = 99.1234567;
    long double z = 99.5L;
    char someString[] = "This is some string.";
    
    Now, instead, you'll start with
    char c;
    short s;
    int n;
    long int nn;
    long long int nnn;
    float x;
    double y;
    long double z;
    char someString[128];
    
    We've just removed the r.h.s. of the original declarations/initializations. Except for char someString. This array of char was previously declared with
    char someString[] = "This is some string.";
    
    The r.h.s. tells the compiler to set aside 21 bytes for the char array someString - that's 20 for the characters in the string and one for the null char '\0' that marks the end of the string. Now, we instead declare someString as an array of size 128 (or whatever) so it will have room to hold the string being read in.

    And: we'll input a value of This-is-some-string., since scanf reads tokens (except for %c) and would just grab the "This" instead of the entire "This is some string."

    Here are the 2 input files and the expected output (the same for both).

    As before, use diff to compare your output with the expected output.

    in3a looks like this, except for the dashed lines:

    -----------------
           97
        55
            5
      22  33
    7.5
    99.1234567
    
    99.5
    This-is-some-string.
    -----------------
    
    in3b is identical to in3a except for the first line
    -----------------
    a
        55
            5
      22  33
    7.5
    99.1234567
    
    99.5
    This-is-some-string.
    -----------------
    

    Some comments on the input files, compared to the original declarations and to each other.

    Also: when reading in the value for someString note that an array name (someString) functions as a pointer to the beginning of the array, so we use
    scanf("%s", someString);
    
    and not
    scanf("%s", &someString);
    

    Write a program called inputOutputa.c. It should be just like the program output.c, except that

    Test your program as follows:
    $ inputOutputa < in3a > myOut3a
    $ diff myOut3a out3
    $
    
    Now copy inputOutput3a.c to inputOutput3b.c. Change only the first scanf statement, so that it uses character oriented input instead of token oriented input. Then test it with
    $ inputOutputb < in3b > myOut3b
    $ diff myOut3b out3
    $
    
    As always, we want diff to return silently.

End of the exercise