C Handin 1

From Juneday education
Jump to: navigation, search

Topics covered in this handin

  • Error handling / Return value
  • Functions
  • struct
  • Pointers

Introduction

You should write a simple command line calculator, called calc. Your program shall accept simple calculator commands such as calc 1 + 2. In this example the program shall respond by printing 3 on stdout and return 0.

The program shall not be interactive, that is the program shall not be asking you to enter data while running. Instead the program shall be given input the same way as gcc is given data om the command line, e g gcc -pedantic file.c.

General syntax

calc value operator value

Supported operators:

  • + addition
  • - subtraction
  • / division
  • x multiplication (with '*' you'll see interesting result)
  •  % remainder

Bad input

Your program shall manage (most) all kinds of bad input. Examples of misuses are:

  • calc "(i" e shall return 2 (missing arguments)
  • calc 1 + shall return 2 (missing arguments)
  • calc liverpool fc as roma shall return 1 (syntax error)
  • calc 1 + a shall return 1 (syntax error)

Return values

Your program shall signal the user if successful execution or not. This shall be done by using return values (from the program). A user (could be another program) should have a way of knowing the difference between:

  • 0 - success
  • 1 - syntax error
  • 2 - missing arguments

Examples

calc 13 + 12

Shall print 25 on stdout and return 0

calc 13 - 12

Shall print 1 on stdout and return 0


Code structure

Together with this assignment you're getting source code that you can, actually you're encouraged to, use as a basis for your calculator. This source code is located at

You can find complete source code to the suggested solutions below in the hand-in/calculator directory in this zip file or in the git repository.. With this source code you get:

  • a file/directory structure (see below) that is an example of division of code into smaller modules (parse, expression and test)
  • unit test code (using assert)
  • test suite of the program calc

Directory layout

The directory of the code you get together with this exercise is as follow:

.
|-- Doxyfile
|-- expression.c
|-- expression.h
|-- main.c
|-- Makefile
|-- parser.c
|-- parser.h
`-- test
    |-- test-expr.c
    |-- test-parse.c
    `-- test-suite.sh

Introducing the files:

./main.c - a c file containg the main function and a small "error handler"

./parser.h - header file for the parser

./expression.c - a c file with code managing expressions (defined in expression.h)

./expression.h - header file for the expression.c file. Also defininfg the data structure expr

./Makefile - In case you want to build quick and easy you can use this (see below).

./parser.c - the parser

./Doxyfile - file used when building the API documentation

./test/test-parse.c - c file with Unit tests for parser

./test/test-suite.sh - bash script for Black-box_testing the program

./test/test-expr.c - c file with Unit tests for expression

So, in short we have four different components.

  • expression defining and handling expression. This component knows NOTHING about parser and main.
  • parser reads user input and converts this input to a expr struct. This module uses the functionality and declarations in expression.
  • main the main program, invoking parser and expression functions
  • test directory with test code

For now, this is a good enough structure. We separate functionality from each other and at the same time easily find all the files. Separating the parser, main and expression from each other means we can write a GUI (graphical user interface) and use the expression functionality as is. Adding a web interface can also use the expression.

Building the program

We use quite a few flags/options to gcc. Read more about the flags in our FAQ: C_FAQ#Q:_Can_I_ask_gcc_to_check_for_more_possible_errors_when_compiling.3F

Using GCC

gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. expression.c -o expression.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. parser.c -o parser.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. main.c -o main.o 
gcc expression.o parser.o main.o -o calc

Using a Makefile

We have prepared a Makefile which you can use while working on this assignment. With a makefile you need not care about which file you need to recompile. This is handled by the program make (reading the file Makefile). GNU/Linux and most likely MacOS comes with the make program installed. Under Windows you need to install it using Cygwin's setu program.

To compile:

make

To clean up (remove binaries etc):

make clean

Testing the program

We provide two ways to test your program.

Unit tests

Expression

To compile the test file test/test-expr.c:

gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. expression.c -o expression.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. parser.c -o parser.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. test/test-expr.c -o test/test-expr.o 
gcc expression.o parser.o test/test-expr.o -o test/test-expr

To execute the tests:

./test/test-expr

Parser

To compile the test file test/test-pars.c:

gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. expression.c -o expression.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. parser.c -o parser.o 
gcc -c -pedantic -Wconversion -Wall -Werror  -Wextra -Wstrict-prototypes -g -I. test/test-parse.c -o test/test-parse.o 
gcc expression.o parser.o test/test-parse.o -o test/test-parse

To execute the tests:

./test/test-parse

Black box test

You can black-box test your program in two different ways.

Manually

We suggest you (at least) test your program with the following input:

./calc 1 + 1
./calc 1 - 1
./calc 1 / 1
./calc 1 x 1
./calc 1 % 1
./calc 3 + 7
./calc 3 - 7
./calc 3 / 7
./calc 3 x 7
./calc 3 % 7

... and some tests to make sure bad input is handled:

./calc 1 + a
./calc 1 a 1
./calc a + a
./calc a a 1
./calc a a a
./calc 1
./calc 1 +


If you want a taste of a coming hand in assignment you can execute some tests that we know will fail. The tests are passing data to the program that we have no support for yet.

./calc 1 / 0

Using shell script

If you're using GNU/Linux or MacOS you can use the script straight away. If you're running Windows you need cygwin to execute the test script. The script tests the program with several different inputs. To execture the test script:

./test/test-suite.sh

If you want a taste of a coming hand in assignment you can execute some tests that we know will fail. The tests are passing data to the program that we have no support for yet.

./test/test-suite.sh --all


Information on Wikipedia about Black-box_testing.

Your task

The program is almost ready. All you need to do is implementing two function properly. Both functions are located in expression.c.

  • void print_expr(expr *e)
  • int calc_expression(expr *e, int *result)

Follow the instructions in the file expression.c. The text /* YOUR CODE GOES HERE */ tells you where to add your code. You should find two such strings.

Errata

2016-11-16

Embarrasing mistake. Always return 1 on error