CS-211 Lab 2 -- Using Command Line Parameters

Background

This week, we are going to write a C program that uses command line parameters. We briefly talked about command line arguments and parameters in the L03 Functions lecture on slide 15. We almost always code the main function as:

  int main(int argc,char **argv) {
	...
  }

Then, inside the main function, the argc parameter contains the number of command line arguments, including the command itself, and argv can be thought of as an array of arguments - with one entry in the array for each blank-delimited "word" on the command line.

Today's lab consists of writing a program that reads two command line arguments (other than the command itself), and treating those arguments as the width and height of a rectangle. The program then computes the area of the rectangle and returns the result.

Getting Started

After you have logged on to one of the Linux Lab machines, open a terminal window like you did last week. (Go back to last week's lab if you forgot how.) Then, make a lab2 sub-directory of your cs211 directory. Create and edit a file called area.c.

We will use the C library function called printf to write to the terminal, so we need to include the system library stdio.h file. We will also use another C library function called atof, so we also need to include the stdlib.h file which defines the prototype for atof. At the top of your area.c file, add:


#include <stdio.h>
#include <stdlib.h>
Next, we need to create a main function as specified later. For now, just put the following instruction in your main function:

  return 0;
Remember, main returns a return-code, and the operating system interprets a return code of 0 to mean "the program worked".

We will add more code into this file later, but that's the minimum we need to compile. I always like to run the compiler at this point just to make sure I have typed everything correctly so far. To run the compiler, use the command: gcc -g -Wall -o area area.c If you didn't have any typos, you should not get any error or warning messages. If you want, you can even run the program with a command like: ./area 3 4, but the program doesn't do anything yet.

Checking the Number of Command Line Arguments

It's almost always a good idea to check to make sure your user is running your program correctly, and part of running the program correctly is to specify valid command line arguments. If your user does not specify valid command line arguments, you should write a message that tells her what is wrong, and how to fix the problem, and then return a non-zero return code.

The first check we can make is whether your user specified the correct number of arguments. For instance, if your user invokes your program as ./area or ./area 3 or even ./area 3 4 5, then something is wrong. Since the argc parameter has the number of arguments, this is pretty easy to check. In this case, I would recommend the following code:

	if (argc !=3) {
		printf("Invoke as: %s <width> <height>\n",argv[0]);
		printf("   where <width> and <height> are the width and height of a rectangle.\n");
		return 1;
	}  

To explain how this code works... First, there is an if statement which specifies the condition argc !=3. This tests to see if the value of the argc parameter is not equal to 3. Remember, argc counts the number of words on the invocation command line, including the name of the program itself, so the only valid invocation of this program is something like ./area 3 4, which has 3 blank delimited words. If the condition is true, in other words, if the user has specified something other than 3 blank delimited words, then C will execute the block of statements enclosed by the curly braces. If argc is 3, then C just skips the entire block.

Inside the block, there are two printf statements to write messages to the terminal, followed by a return statement. The printf statements tell the user how to invoke your program. In the first printf statement, the characters %s are replaced by the value of argv[0], which references the first word on the command line. Instead of putting this %s in the code, you could have just written "./area" - but that would only be correct if your user is invoking the area program from the current directory. Using argv[0] repeats back to the user the exact syntax he used to invoke your program, so it's a little more "user friendly". The return statement in this block returns from the main function back to the operating system. Once the return statement is executed, your program is done. (Some programmers don't like functions with multiple return statements, but often, in cases like this, it makes the code a lot easier to read.)

Save your code with the above changes, compile it, and run it with various different numbers of command line arguments to make sure everything is working, including your check. You might even want to add a temporary printf statement after the block you just added that says something like

  printf("Everything seems copacetic so far...\n");

Just so you know you made it past the check successfully.

Converting and Checking the width Parameter

Once you know the user has specified the correct number of arguments, the next step is to look at the width parameter - the first argument after the command itself. The C infrastructure puts the characters that make up the first blank delimited word into variable argv[1]. Unfortunately, in order to use this as a number, you have to convert these characters into some numeric data type recognized by C. We could use an integer data type, but it would be nice to support rectangles with widths like 1.7 which are not integers, but real numbers. So it would be nice to convert the characters to floating point numbers. If you look at the C Library Guide (same as the link from the class web page), you will find documentation for the C Library Guide : atof library function which does exactly what we want it to. The library guide says that the atof function takes an argument of type const char *. We will learn more later, but it turns out that argv[1] is a valid argument for atof. Note that I need to declare a variable to hold the result of the atof function, so I can code the following in C:

  double width;
  width=atof(argv[1]);

Note that if atof can't recognize a number in argv[1], it will return a value of zero. Luckily for us, we can assume that the width of a rectangle is always some positive number. Therefore, we can check the width with a condition such as:

  	if (width <=0) {
		printf("Invoke as: %s <width> <height>\n",argv[0]);
		printf("  The width specified, %s, evaluates to an invalid value of %f\n",argv[1],width);
		return 1;
	}

These exact same conversions and checks can be applied to the second parameter - the height - as well as the width. Write the code for both height and width, save your edits, recompile, and check again with various different values for width and height to make sure you code works correctly.

Calculating the Area

The area of a rectangle is just the width times the height. Declare a new variable called area, and set it equal to the value width * height. (In C, an asterisk - * - is used to multiply two numbers.) Finally, print out your results. (If you added an "everything is copacetic" printf, you can delete it now... we no longer need this.) Please use the following printf statement to print your results. (That way your code will be easy to grade.)

  printf("Rectangle with width=%f height=%f area=%f\n",width,height,area);

Once this is done, save your area.c program, and compile. Clean up any compile errors or warnings produced by the compiler, and test your code to make sure it works correctly.

Lab Submission

Go to MyCourses, and open the page associated with this course. Choose the "Content" hyperlink on the left list of options. You will see a "Lab 02 Submission" icon. Click on the lab 02 submission hyperlink and upload your area.c file. Make this submission before the due date of Friday, September 15 at 11:59 PM. You may submit as many times as you want before the due date, but only the latest submission will be graded.

Lab Grading

This lab is worth 10 points. You will get deductions as follows:

Extra Credit

The atof function does a great job of converting character strings to floating point numbers, and it almost works perfectly every time. For instance, try the invocation ./area 3 inf. In this case, atof interprets the character string inf to mean infinity, and floating point arithmetic can handle that correctly! There is a case where the atof results are not exactly correct. Try the invocation ./area 3 4hundred. This should probably reject the height of 4hundred as being an invalid number, but atof returns 4.0 in this case. I will run this case on your code, and if you print an error message about an invalid height (or width), then I will add up to 3 points to your grade, as long as the result is less than or equal to 10. (If you treat the argument 4hundred as 4.0, I will not deduct any points.)