Goals

In this assignment you will learn the basics of compiling programs and the most fundamental aspects of the C language.

Getting set up

We are providing you with instructions for setting up a virtual machine (VM) running Ubuntu Linux in which you should write all of your code. (See this page for information on how to set up the VM.) You are not required to do this (the setup page also describes some alternatives) but we expect that you will be able to set up a Unix-like environment (either a Mac, a Linux VM, or a Windows Linux environment like WSL or Cygwin), and use this environment when you run and test your programs.

You will also need to know basic Linux commands (particularly terminal commands). If you’ve taken CS 1, you should already have this knowledge, but if not, you can consult any online tutorial on Linux terminal use.

Language concepts covered this week

  • basic input/output using printf and scanf

  • conditionals (if statements)

  • loops (for statements)

  • numeric types and conversions (int to double)

  • C strings

  • preprocessor directives (#include)

  • using standard libraries

  • the main() function

  • compiling code using gcc

Suggested Reading

  • Darnell and Margolis, chapter 3.

  • K&R, chapter 1 (all) and chapter 7 (pp. 153-159). Some of the material on scanf presupposes an understanding of pointers. Since you haven’t seen pointers yet, I’ve included an "aside on scanf" below to help you out.

  • If you don’t understand the C compilation process, take a moment and read this page now. Also review lecture 1.

Programs to write

  • hello1

Write a program called hello1 to print hello, world! to the terminal. Use the printf function to do the printing. Make sure there is a newline at the end of the message. Compile it using the command:

$ gcc -Wall -Wstrict-prototypes -ansi -pedantic hello1.c -o hello1

($ is the unix shell prompt.) gcc is the GNU C Compiler, whose job it is to convert the file hello1.c (called source code; this is the file you create) into a binary executable. hello1 is the name of the binary program; the -o option tells the compiler that the next argument is the name of the output file. Don’t worry about the -Wall; it turns on compiler warnings so that the compiler will warn you about anything it considers dubious but which is still legal. It’s a good habit to use -Wall whenever you use gcc. Note that although almost all C compilers have some option for enabling or suppressing warnings, there is no standard command-line option for these, so -Wall will only work for gcc. Make sure that your main function returns 0 or the compiler will issue a warning. The options -Wstrict-prototypes -ansi -pedantic ensure that your program is ANSI-compliant and that your prototypes have been declared correctly. Don’t worry about this for now, but do use it; it will make your life much easier later on.

  • hello2

Modify hello1.c so that the program (now called hello2, corresponding to the source code file hello2.c) prints a prompt string (e.g. Enter your name: ), after which you enter your name and it prints hello, <your name>! to the terminal (with your name substituted for <your name>, of course). Make sure your program prints a prompt string before reading the input (a lot of people forget to do this). The name you enter should be a single word only (say, your first name). Use the library function scanf to read the string from standard input (also known as stdin) and print to standard output (also known as stdout). stdin and stdout both represent input and output from the terminal (as opposed to, say, a file).

Aside on scanf: scanf should be invoked as follows:

    char s[100];  /* N.B. strings are arrays of chars in C */
    /* ... maybe some intervening code ... */
    scanf("%99s", s);

When run, the program will pause while executing the scanf until you enter a string and hit return, or until 99 characters have been entered (whichever comes first). [1] Then it will continue. The character array s will then contain the string you entered, and can be passed to printf. I will discuss this in more detail in later lectures. Note that scanf used as above will also ignore anything past the first whitespace character (space or tab). There are ways to get around this, but they aren’t important now. That’s why your name should just be a single word.

  • hello3

Modify hello2 so that the program prints a prompt, you enter your name, the computer generates a single random number n between 1 and 10 and prints that many messages. The format of each message that you will print is: <n>: hello, <your name>! or: <n>: hi there, <your name>!, where <n> is the random number you generated and <your name> is, well, your name. Print the first message when <n> (not the loop index variable) is even and the second message when <n> is odd. All the messages for a single run of the program will thus be identical.

I repeat: All the messages for a single run of the program are identical. Pay attention to this! Every term, some students print a different message depending on whether the loop index variable is odd or even instead of n, or don’t print the number n at all. If you do this, you’ll lose marks.

By "loop index variable" I mean e.g. i in: for (i = 0; i < n; i++) ....

Use the rand library function to generate the random numbers; this function is found in the stdlib.h header file, so be sure to add:

#include <stdlib.h>

to the top of your program source code. You will also need to "seed" the random number generator to get it started; the best way to do this is to include this line:

srand(time(0));

at the beginning of the program. srand is also in stdlib.h, but time is in the time.h header file, so you should #include that as well. Be aware that there is not always 100% standardization on the locations of functions in header files among different operating systems. You should also look at the man pages for rand and srand, which will contain useful information. To do this, type: man 3 rand at the unix prompt (it’s in section 3 of the online manuals; just man rand will not work, because there is another rand that has a man page).

A slightly tricky part of this task is converting from the return value of rand(), which returns an int between 0 and RAND_MAX (which is a large integer constant defined in <stdlib.h>) into a random number between 1 and 10. There’s more than one way to do this.

ASIDE ON NUMERIC CONVERSIONS: You can convert an integer to a real number (double or float) as follows:

int i = 10;
double d = (double)i;  /* Convert int to double. */
float f = (float)f;    /* Convert int to float.  */

Recall that doubles are double-precision while floats are single-precision. Similarly, you can convert real numbers (doubles or floats) to integers as follows:

double d = 12.3;
int i = (int)d;    /* Convert double to int. */

In this case, the conversion to integers throws away everything to the right of the decimal point (the fractional part). I’ll talk about this more in lecture 2.

To hand in

The hello1.c, hello2.c, and hello3.c programs. Before you hand them in, make sure that you run the style checking program on all of them to catch obvious style mistakes. See the style guide for more information on this.


1. The reason you can’t enter 100 characters with this code will be explained in a later lecture.