COMP1911 23T2 Introduction to Programming

Objectives

In this lab, you will practise:

Preparation

Before the lab you should re-read the functions notes and accompanying examples

You should also read the first few slides in arrays and accompanying examples

Arrays are also covered in chapters 7.1 and 7.2 of Moffat.

You should also have read the lab assessment guide.

Getting Started

Login and run following commands inside a Unix terminal

Create a new directory for this lab called lab04 by typing:

mkdir lab04
Change to this directory by typing:
cd lab04

Exercise 1: Leap Year

Write a C program leapYearFunction.c that reads a year and then uses a function to calculate whether that year is a leap year (click here to see the algorithm). The function prototype must be int isLeapYear(int year).

Your function should return 0 if it is not a leap year, and 1 if it is a leap year.

Your leap year function must not print anything.

You should call this function from your main function, which is where you print the result.

Your function must be named isLeapYear.
It must exactly match the function prototype given above.

Match the examples below exactly

For example:

$ dcc -o leapYearFunction leapYearFunction.c
$ ./leapYearFunction
Enter year: 2017
2017 is not a leap year.
$ ./leapYearFunction
Enter year: 2016
2016 is a leap year.
$ ./leapYearFunction
Enter year: 2000
2000 is a leap year.
$ ./leapYearFunction
Enter year: 3000
3000 is not a leap year.
When you think you have leapYearFunction.c working use autotest to test it further:
1911 autotest lab04 leapYearFunction.c

Beware: autotest will not use your main function. It will call your isLeapYear function directly.

Exercise 2: Arrays and Runtime Errors

For this lab question, you will run some experiments and discuss your results and conclusions in a blog post.

Make a blog post called "Arrays and Runtime Errors"

To make a Blog

  1. Go to the COMP1911 Home Page (On WebCMS)
  2. Log in with your zid and zpass
  3. Click on the speech bubble icon at the bottom of the side navigation panel near your name.
  4. Click on "Create Post"
  5. Select the "Course Staff" option in the Viewable by selection box.

Background Information

Once we start programming with arrays it is easy to accidentally create runtime errors. (We have seen runtime errors before such as divide by zero errors).

Runtime errors mean that your code compiles, but when you run it something will cause the program to stop execution and 'crash'. There may also be other times where errors are more subtle and your program runs and does NOT 'crash' but you do not get the output you want.

Make a file named badArray1.c and copy and paste the following code into it and save it

#include <stdio.h>
// This is a bad program
int main(void) {
    int i;
    int numbers[] = {2,4,6,8};
    
    i = 0;
       
    while(i <= 4){
        printf("%d\n",numbers[i]);
        i = i + 1;
    }    
    
    i = i*1000;
    
    numbers[i] = 3;
    return 0;
}

We are now going to compile and then execute (if it compiles) this program using different compilers and different compiler options and note whether you see any of the following:

  1. Compile time error: ie the code does not compile
  2. Runtime error: the code 'crashes' and does not fully execute until completion
  3. Incorrect output : the code prints wrong/garbage output

and try to explain the results you get.

Note: In some cases you may get incorrect output AND a crash. The compiler options you should use are:

Repeat the proccess for the following program badArray2.c:

#include <stdio.h>

#define SIZE 10

// This is a bad program
int main(void) {
    int numbers[SIZE];
    int i;
    i = 0;
    
    //initialise array
    while(i < SIZE){
        numbers[i] = i;
        i = i + 2;
    }    
    
    //print array
    i = 0;
    while(i < SIZE){
        printf("%d: %d\n",i, numbers[i]);
        i = i + 1;
    }  
       
    return 0;
}

Discuss the differences between the errors in both programs. Did you come to any conclusions about the different types of errors dcc finds compared to gcc?

Exercise 3: Vector Match

Write a program called vectorMatch.c that reads 2 vectors of 10 positive integers the prints a count of how many times the 2 vectors have the same value in the same position.

It must be possible by changing a single #define to change the length of the vectors your program reads. You must use arrays, not 20 separate variables

Your program can assume it is given correct input (20 positive integers).

Your program must match the examples below perfectly.

$ ./vectorMatch
Enter vector 1 of 10 positive numbers: 42 1 2 3 4 5 6 7 8 9
Enter vector 2 of 10 positive numbers: 42 1 2 3 4 5 6 7 8 9
Vectors match in 10 positions.
$ ./vectorMatch
Enter vector 1 of 10 positive numbers: 42 1 2 3 4 5 6 7 8 9
Enter vector 2 of 10 positive numbers: 3 42 1 2 3 4 5 6 7 8
Vectors match in 0 positions.
$ ./vectorMatch
Enter vector 1 of 10 positive numbers: 4 3 2 1 8 7 6 9 9 9
Enter vector 2 of 10 positive numbers: 2 4 2 6 8 7 6 5 4 3
Vectors match in 4 positions.

You must create and use a function to read the values into your array.
You may create and use other functions too.

Hint: remember to compile with dcc to get a clear message immediately if any array reference is wrong when you run your program. For example:

$ dcc vectorMatch.c -o vectorMatch

As usual autotest is available to test your program.

$ 1911 autotest lab04 vectorMatch

Exercise 4: Noughts and Crosses - Input

Write a program called tttBoard.c that reads in a 3x3 noughts and crosses (Tic-Tac-Toe) board, stores it in a 2D array and then prints it out. You can assume that the user enters valid input only. You should assume that 0 stands for noughts and 1 for crosses and 2 for an empty square. You can assume that the input is valid.

Your program should behave like the following:

$ ./tttBoard
Please enter the board:
0 1 0
0 1 1
2 0 2
Here is the board:

O X O
O X X
. O .

Hint

Start off with something like the code below and implement readBoard with a scanf inside a nested loop and printBoard as a printf inside a nested loop. You should store the board as 2d array of ints.
#include <stdio.h>

#define SIZE 3

void readBoard(int board[SIZE][SIZE]);
void printBoard(int board[SIZE][SIZE]);

int main(void) {
   int i, j;
   int board[SIZE][SIZE];
   ....
   return 0;
}

For a first step when you print the board out, just try and print out the ints like below.

Please enter the board:
0 1 0
0 1 1
2 0 2
Here is the board:

0 1 0
0 1 1
2 0 2
Then modify your printing code to print it out with O, X and . instead of the 0,1 and 2s.

As usual autotest is available to test your program.
$ 1911 autotest lab04 tttBoard

(Optional) Challenge Exercise 1: Noughts and Crosses - Detecting a Winner

Make a copy of tttBoard.c and call it tttCheck.c. Now add code to tttCheck.c to check to see if there is a winner and print a suitable message.

To do this you must write a function with the following prototype

int winner(int board[SIZE][SIZE]);

You should #define constants to represent the winner, such as NOUGHT, CROSS, NO_WINNER and DRAW and return these values from your function.

You may write and use additional functions if you require.

There is a winner if there are 3 X's or 3 O's in a row or a column or diagonal. It is a draw if there is no winner and there are no empty positions left on the board.

Match the output below exactly. For example:

$ ./tttCheck
Please enter the board:
0 1 0
0 1 1
2 0 2
Here is the board:

O X O
O X X
. O .

There are no winners
$ ./tttCheck
Please enter the board:
0 1 0
0 1 1
1 0 0
Here is the board:

O X O
O X X
X O O

It is a draw
$ ./tttCheck
Please enter the board:
0 0 2
1 1 1
0 0 1
Here is the board:

O O .
X X X
O O X

Crosses win
$ ./tttCheck
Please enter the board:
0 1 1
0 1 1
0 0 2
Here is the board:

O X X
O X X
O O .

Noughts win
$ ./tttCheck
Please enter the board:
2 1 0
2 0 1
0 1 2
Here is the board:

. X O
. O X
O X .

Noughts win

You can assume there are not 2 winners as this would not happen in a real game.

Your code to check for a winner must use loops.

Your code to check for a winner must not depend on the board (array) being of size 3.

It must use a constant for the board size (e.g. SIZE).

As usual autotest is available to test your program.

$ 1911 autotest lab04 tttCheck

(Optional) Challenge Exercise 2: Box Fun

Credits: This was taken from a COMP1511 lab

For this challenge, make a program called boxFun.c which reads in a number and then draws that many square boxes inside each other using the character #.

You are only permitted to use C language features covered in weeks 1-3 lectures. In particular, you are not permitted to use array(s).

For example:

$ ./boxFun
How many boxes: 1
###
# #
###
$ ./boxFun
How many boxes: 2
#######
#     #
# ### #
# # # #
# ### #
#     #
#######
$ ./boxFun
How many boxes: 5
###################
#                 #
# ############### #
# #             # #
# # ########### # #
# # #         # # #
# # # ####### # # #
# # # #     # # # #
# # # # ### # # # #
# # # # # # # # # #
# # # # ### # # # #
# # # #     # # # #
# # # ####### # # #
# # #         # # #
# # ########### # #
# #             # #
# ############### #
#                 #
###################
As usual autotest is available to test your program.
$ 1911 autotest lab04 boxFun

(Optional) Challenge Exercise 3: Spiral

Credits: This was taken from a COMP1511 lab

Note: This is very difficult to solve. This is an optional challenge. You do not need to attempt this to get A for the lab.

Write a program called spiral.c that reads an integer n from standard input. and prints an nxn pattern of asterisks and dashes in the shape of a spiral. You can assume n is odd and >= 5.

You are only permitted to use C language features covered in weeks 1-3 lectures. In particular, you are not permitted to use array(s).

Make your program match the examples below exactly.

$ ./spiral
Enter size: 7
*******
------*
*****-*
*---*-*
*-***-*
*-----*
*******
$ ./spiral
Enter size: 9
*********
--------*
*******-*
*-----*-*
*-***-*-*
*-*---*-*
*-*****-*
*-------*
*********
$ ./spiral
Enter size: 17
*****************
----------------*
***************-*
*-------------*-*
*-***********-*-*
*-*---------*-*-*
*-*-*******-*-*-*
*-*-*-----*-*-*-*
*-*-*-***-*-*-*-*
*-*-*-*---*-*-*-*
*-*-*-*****-*-*-*
*-*-*-------*-*-*
*-*-*********-*-*
*-*-----------*-*
*-*************-*
*---------------*
*****************

As usual autotest is available to test your program.
$ 1911 autotest lab04 spiral

(Optional) Challenge Exercise 4: Noughts and Crosses Move

Now make a copy of your tttCheck.c and name it tttMove.c that instead of printing out "There are no winners" prompts the user to make a move. You must read in the players move, check that the move is valid and then print out the updated board. You can assume that it is Noughts turn. A valid move is two integers between 0 and 2 inclusive that represent a row and column on the board that is currently empty.

$ ./tttMove
Please enter the board:
2 2 2
2 0 1
0 1 2
Here is the board:

. . .
. O X
O X .

Please enter your move Noughts: 0 2
Here is the board:

. . O
. O X
O X .

Noughts win
$ ./tttMove
Please enter the board:
2 2 2
2 0 1
0 1 2
Here is the board:

. . .
. O X
O X .

Please enter your move Noughts: 2 0
Invalid Move
$ ./tttMove
Please enter the board:
2 2 2
2 0 1
0 1 2
Here is the board:

. . .
. O X
O X .

Please enter your move Noughts: 0 3
Invalid Move

Submission/Assessment

When you are satisfied with your work, ask your tutor to assess it. You are to submit it electronically by typing (run this command in your lab04 directory):
give cs1911 lab04 leapYearFunction.c vectorMatch.c tttBoard.c tttCheck.c boxFun.c spiral.c tttMove.c
Submit advanced exercises only if you attempt the advanced exercise.

Remember the lab assessment guidelines - if you don't finish the exercises you can finish them in your own time, submit them by 19:59:59 Sunday using give and ask ask tutor to assess them at the start of the following lab.

You can also just run the autotests without submitting by typing

1911 autotest lab04