1. Due Date
Complete lab: Due by 11:59 pm, Monday, Feb. 15, 2021
Unlike the other lab assignments in this class, you will complete this lab on your own without a lab partner.
2. Lab Overview and Goals
This lab implements a program that is designed to give you practice with some C programming basics, including some program design and problem solving.
Make sure that you use only the C features that we specify in this lab and that you are not using features of C that you may know from other courses. Look at Section 5 (Details) and Section 6 (Requirements) to ensure you are solving the lab the way in which we intend. In Section 7 (Tips) are some implementation tips to help you.
You are also required to use the vim editor to implement this program.
2.1. Lab Goals
Practice with C programming basics: declaring variables, types, constants, loops, conditionals, functions
Practice writing and using C functions, function prototypes, pass-by-value
Practice with nested
Using some C library functions (random nubmers and output)
Using a Makefile
gitto clone a repository and to submit your lab solution
3. Starting Point Code
3.1. Getting Your Lab Repo
First, clone your Lab 1 repo into your
get your Lab 1 ssh-URL from the CS31 git org. The repository to clone is named Lab1-yourUserID with your user name.
cd into your
$ cd ~/cs31/labs $ pwd
clone your repo
git clone [the ssh url to your your repo] cd Lab1-yourUserID
There are more detailed instructions about getting your lab repo from the "Getting Lab Starting Point Code" section of the Using Git for CS31 Labs page.
3.2. Starting Point files
Cloning the repository will give you the following starting point code files (note: the exact number of floatsX.txt files in your repo may differ from this example listing):
$ ls Makefile README.md prog.c
These files are:
Makefile: A Makefile simplifies the process of compiling your program. We’ll look at these in more detail later in the course. You’re welcome to look over this one, but you shouldn’t need to edit it for this lab. If you are interested, take a look at the reference in Section 9 for more information about make and makefiles.
prog.c: the file into which you will add your C solution, using good C style and complete comments. With the starting point code, is one helper function already implemented for you:
read_int: takes a prompt string and returns and int value entered by the user. You can look at the function code, but it uses some C language syntax that we will not cover until later. It is not important now that you know how it is implemented, just how to call it from code you write. There is an example call to it from 'main'.
README.adoc: some instructions for compiling and running the program.
4. Compiling and Running
To compile your program run
make, which will use the Makefile to
compile the binary executable,
make lists the
gcc compiler output, which you should
examine for errors and warnings.
To run the
prog executable binary:
4.1. Sample Output
The following shows a few example runs of a working program, including different control flows and error handling. Your program’s output should be identical to this when given the same input, with the exception of the specific average result since the exact set of random values will differ from run to run. However, you should evaluate the result, and ensure that it makes sense as an average for the range you give.
5. Lab Details
You will implement a program that does the following:
Computes the average of a set of randomly generated values, whose range and cardinality are entered by the user.
Repeatedly draws a pictures of a mountain, until the user chooses to quit. Each mountain’s size is determined by the user.
The main parts of the lab involve writing code using C functions, loops,
if statements, and nested loops. It includes some error handling for
input values out of a specified range, but you are not required to handle
bad input (such as the user entering an invalid int value like
prompted to enter an int).
You may want to start by looking at the sample output from several program runs in Section 4.1 to get a sense of what this program does.
5.1. Starting point code details
The starting point code includes the start of a
main function, and
includes all C libraries your need in this program (
#include at the
top of the file).
It also includes a function that we have already implemented for you.
The function named
read_int takes a
prompt string and returns an int value read in from the user. This function
uses some features of C that we have not yet discussed, so it not important
that you know how it is implemented right now, but you should know how to
call it. Here are some example calls that show how to use this function:
int num, age; num = read_int("How many values do you want: "); age = read_int("Enter your age: ");
Also, in the
main fuction we have included a call to the
function, which is used to seed C’s random number generator:
5.2. Part 1: Computing Average of Set of Random values
main program should start by printing out a short message about what
the program does, and then compute the average of a set of randomly
generate int values, in the following way:
Prompt the user to enter a number of values to average over, and read in the value entered by the user (call
read_intto do this). Check that the value returned by
read_int(the value entered by the user) is positive, and if not print out an error message and repeat this step.
Prompt the user to enter the high end of the range of values, and read in the value entered by the user (call
read_intto do this). Check that the user enters a positive value for the number, and if not, print out an error message and repeat this step.
compute_averagefunction that returns the average of a number of randomly generated int values in a specified range.
Print out the results (print out in similar way as shown in the sample output in Section 4.1).
For this part, you will need to implement a
The function should take as input:
num: the number of values to average over
high: the high value in the random range [0, high]
And should return the average (as a float) of
num randomly generated
int values in the range
[0, high]. Its function prototype should
float compute_average(int num, int high);
5.2.1. rand function
rand function, from the C
stdlib, returns a random int value
between 0 and
RAND_MAX (some large int value). Here is an example call:
int val; val = rand(); // get next pseudo-random int value in range [0,RAND_MAX]
5.3. Part 2: Drawing a Pretty Picture(s)
After your program computes average, it should draw a pretty picture of some size specified by the user, and possibly draw more pictures for the user based on thier input. The main control flow is:
Get the size of the picture to draw between
MAX(constant value in the program) from the user (by calling your
draw_picturefunction to draw a picture of the user entered size
Ask the user if they want to see another picture, and get their response of 0 or 1 (0 for no, 1 for yes).
if they enter 1 (for yes), repeat these steps
if they enter 0 (for no) print out a good bye message
For this part, you will implement two functions that you should call from
main (within code that implements the control flow for this part
listed above). These two functions are:
int get_in_range(int lo, int hi); void draw_picture(int size); /* void return type: function does not return a value */
Prints message to user to enter a value between
Prompts user to enter a value and reads it in (by calling
Checks to see if value entered is in the range between
if so, return it
if not, print out an error message and repeat from step 2
This function, given a passed
size value, draws a picture of a mountain
(a pyramid of stars). For example, it would draw the following for
a size value of 8:
* *** ***** ******* ********* *********** ************* ***************
and this for a size value of 5:
* *** ***** ******* *********
See Section 4.1 for more examples.
Your code will print out the pattern by making calls to only the
printf(" "); // print a single space (a single space string: type one space between "": " ") printf("*"); // print a single star printf("\n"); // print a new line
draw_picture function requires a solution that uses a doubly nested
for loop (you may have more than one inner loop, but don’t have a nesting
depth deeper than doubly nested). Look at the example output and see how the
pattern of what is drawn changes based on the passed size value. For example,
How many total lines are printed?
How many spaces are printed on each line, and how does it change with each subsequent line printed?
How many stars are printed each line, and how does the number change with each subsequent line printed?
See the Tips section (Section 7) for some recommendations for how to solve this.
6. Lab Requirements
For full credit, your solution should meet the following requirements:
When run, your program’s output should look like the example output shown in Section 4.1.
You should implement at least the three required functions, including adding their function prototypes to the top of the
prog.cfile and their implementations at the bottom (like
You should only use parts of the C programming language that we have covered in class to solve this lab. Specifically, if you have taken CS35 (or have prior experience in C or C++), and if you are familiar with C string, array, or pointer variables, you may NOT use any of these in your solution.
Your picture drawing must use nested
forloops, and must be done by making calls to print a single space, a single star, or a single new line:
printf(" "); printf("*"); printf("\n");
Your code must be well-commented, modular, robust, and use meaningful variable and function names. Each function should include a brief description of its behavior, and a description of each parameter and what it returns. Also, do not wrap lines and follow C-code conventions with local variable declarations and function prototypes.
Look at the C code style guide for examples of complete comments, tips on how not to wrap lines, good indenting styles and suggestions for meaningful variable and function names in your program. Also, declare all local variables at the top of each function body before the set of statements in the function body.
Your code should compile cleanly with no errors or warnings and should not crash unexpectedly during execution.
Code you submit should have my "TODO" comments removed (these are my notes to you, as you implement them remove the "TODO").
Any debugging output should be removed (or commented out) from your submission for grading; again, your program’s output should match Section 4.1
You should use
vimeditor for editing your
7. Tips and Hints
Start early on this. We strongly recommend not using any of your late days on this lab assignment.
CNTL-Cin the terminal to kill a program stuck in an infinite loop.
read_intis not super robust to bad user input, such as the user entering
hello thereinstead of a valid int value. As a result, it could trigger an infinite loop, as could any loop code you add.
Start by implementing and testing the
compute_avefunction, and test for several input values to ensure correctness. To verify that your function is correct, think about what you expect the average of a set of random values in the range you pass to be. Your result should be close to this. Since the values are randomly generated, and since the program calls
srandto seed the random number generator each run, two runs of your program using the exact same user input may produce slightly different average results.
The C mod operator (
%) can be applied to two int operands and evaluates to the remainder part of int division. For example,
num % 5returns a result in the set
[0,4]depending on the remainder of the value of num divided by 5 (
10 % 5evaluates to 0, and
102 % 5evaluates to 2).
Think carefully about type in C, and the effects on how operators are evaluated. For example, if both operands to
/does int division. If at least one is a float (or double),
/does float (or double) division.
printftakes a format string that can include placeholders for argument values.
%gis a placeholder for a float or double, and
%dis a placeholder for an int value. Make sure that the type of the placeholder you use matches the type of the argument you pass for it. If not, your program’s output may be incorrect only because of this mismatch (i.e. you are computing the correct result, you are just printing it out incorrectly).
int get_in_range(int lo, int hi);can be used for both questions related to the picture drawing part of your program. After printing out a message with the range of value to input, it should call
read_int("value: ")to get the input value entered by the user. It should not return until the user enters a valid input value (one in the specified range). Look at the example runs in Section 4.1 to get a sense of what this function does and prints out when the user enters a value not in range and it repeats reading in a value until the user does enter one in range.
draw_picturefunction, you can have more than one inner loop in the outer loop, but you do not need more than double nesting. It is worth thinking about the pattern on paper a bit before coding. Consider that the outer loop controls how many lines are printed, and the inner loop(s) what is printed each line. If what is printed each line changes (and it does), come up with a pattern for how many stars (and how many spaces) are printed based on which line is being printed (which
ivalue for the outer loop variable).
As a first step in determining how to implement the
draw_picture, you can start by solving an easier drawing problem, and then modify it bit by bit to draw more complicated patterns until you draw the mountain pattern. For example, you could start first by drawing a box of stars based on
value: 3 *** *** *** value: 8 ******** ******** ******** ******** ******** ******** ******** ********
Next, try drawing a triangle of stars, the number of stars and number of lines printed depend on the value of size:
value: 3 * ** *** value: 8 * ** *** **** ***** ****** ******* ********
Once you get that, then think about creating this picture next, by figuring out the pattern for the number of spaces that are printed before the stars on each line:
value: 3 * ** *** value: 8 * ** *** **** ***** ****** ******* ********
From here, you can add in another part to draw "the other side of the mountain" to look like the examples in Section 4.1.
Start on this early, and post on Piazza, attend ninja sessions, and/or come to office hours if you have questions!
8. Submitting your Lab
Please remove any debugging output prior to submitting.
To submit your code, commit your changes locally using
git add and
git commit. Then run
git push while in your lab directory.
Only one partner needs to run the final
git push, but make sure both
partners have pulled and merged each others changes.
Also, it is good practice to run
make clean before doing a git add and
commit; you do not want to add to the repo any files that are built by gcc
(e.g. executable files). Included in your lab git repo is a .gitignore file
telling git to ignore these files, so you likely won’t add these types of files
by accident. However, if you have other gcc compiled binary files in your
repo, please be careful about this.
Here are the commands to submit your solution in the sorter.c file (from
one of you or your partner’s
$ make clean $ git add prog.c $ git commit -m "correct and well commented Lab1 solution" $ git push
Verify that the results appear (e.g., by viewing the the repository on CS31-S21). You will receive deductions for submitting code that does not run or repos with merge conflicts. Also note that the time stamp of your final submission is used to verify you submitted by the due date or by the number of late days that you used on this lab, so please do not update your repo after you submit your final version for grading.
If you have difficulty pushing your changes, see the "Troubleshooting" section and "can’t push" sections at the end of the Using Git for CS31 Labs page. And for more information and help with using git, see the git help page.
After you submit your solution for grading, you should fill out and submit the required Lab 1 Questionnaire.