C Handin 3

From Juneday education
Jump to: navigation, search

Description

This hand in is based on C_Handin_1 and C_Handin_2. This time we're going to add an interactive mode.

This means that it should be possible to start the program with no arguments:

$ ./calc

the program shall introduce the user to the program (by printing to stderr) and then wait for the user to write exxpression like the ones we handled on the command line in the previous hand ins.

A session might like like this:

$ ./calc
Welcome to the calculator... 
12 + 34
46

Strategy

We suggest you write a separate file, interactive.c with a coresponding header file. The file shall have functions like the below

  • void welcome_messge
  • void leave_messge
  • int read_from_user
  • int interactive_loop

You can find some skeleton code here: calculator-III

void welcome_messge

A function simply writing a welcome message to stderr.

void leave_messge

A function simply writing a leave message to stderr.

int read_from_user

  • Reads a string from the user.
  • This string shall be split into three strings (operand 1, operator, operand 2)
  • Use the three strings to fill in an expression (passed as a pointer) using the function args_to_expr (expression.h). See how this function is used in the file parser.c
  • If the user types "quit" return -1

int interactive_loop

  • loop and read from user, using read_from_user, until not 0 is returned. If not 0:
    • if -1 it means that the user typed "quit", so we should close down with a good bye message using leave_message :)
    • if 1, 2..... it means something went wrong. Close down and make sure the program returns an error code (not 0)

Testing the program

Manually

Make sure that the program can handle data from the user by running the program an enter data and verify the result.

Using a file

The following works only with bash.

We can prepare a file with expressions (such as 1 + 2) followed by "quit" in it. Exmaple file (indata.txt:

$ cat indata.txt 
1 + 1
24 / 12
26 % 12
quit

In the file above we have three expression that we want to be calculated. Instead of the program, reading from stdin, reading from the "keyboard" we can redirect stdin to instead "point" to the indata file ( < indata.txt).

$ ./calc < indata.txt 
Welcome to the calculator
2
2
2
bye bye

We can verify that the calculations done by the calculator (2, 2, 2) are correct by manually reading. Wouldn't it be nice to be able to test this as well - of course it is. So let's do that. Let's create a file (expeected.txt with expected values):

$ cat expected.txt 
2
2
2

And now run the calculator with the indata file as stdin and redirect the calculator's output to file (outfile.txt).

$ ./calc < indata.txt > outfile.txt
Welcome to the calculator
bye bye

Note: the messages printed to stderrare not redirected. Only stdout is redirected. It is possible to redirect stderr as well, but not now :).

And finally compare the file expeected.txt with the file outfile.txt. We can do with the program diff.

$ diff expected.txt outfile.txt ; echo $?

If we see 0 printed we can be pretty sure the program has run correctly.

We will provide two files (indata.txt and expected.txt) with a bit more expression and expected values in them in case you want to test. To test your program with these two files, simply type:

 ./calc < indata.txt > outfile.txt && diff expected.txt outfile.txt ; echo $?


Note: if you're curious on how we generated the data in the two files you can play around with the command line here: rm indata.txt expected.txt ; CNT=1000 ; while [ $CNT -ge 0 ] ; do OP1=$(( $RANDOM % 1000)) ; OP2=$(( $RANDOM % 1000)); for op in + - x / % ; do echo $OP1 $op $OP2 >> indata.txt ; BASH_OP=$(echo $op| sed 's,x,\*,g'); BASH_RES=$(( $OP1 $BASH_OP $OP2 )) ; echo $BASH_RES >> expected.txt ; CNT=$(( $CNT -1 )) ; done; done && echo "quit">> indata.txt