Presentation is loading. Please wait.

Presentation is loading. Please wait.

Homework K&R chapter 4.

Similar presentations


Presentation on theme: "Homework K&R chapter 4."— Presentation transcript:

1 Homework K&R chapter 4

2 Multi-Module Programs (Glass & Ables Linux Book p. 411)
To compile all .c files and create executable gcc main.c getop.c stack.c getch.c –o calcit To compile only one and create executable with objects of previously compiled files gcc main.c getop.o stack.o getch.o –o calcit To build an executable from a complex set of separate files skipping any unneeded steps make –f makefile (makefile documents build rules) (-f option allows you to specify makefile name) I will explain MAKE to you briefly You don’t need to compile all of the programs again If I modify a file, I don’t need to know which files modified, the makefile will find them based on the timestamp of the files. For big companies they need to compile just the new edited files.

3 Dependency Tree for a Build
calcit main.o getop.o stack.o getch.o main.c getop.c stack.c getch.c Dependency list getop.h stack.h getch.h

4 Make (Glass & Ables p. 412) makefile rule format
target: dependency list for needed files command list to create target Example: calcit: main.o getop.o stack.o getch.o gcc main.o getop.o stack.o getch.o -o calcit main.o: main.c getop.h stack.h gcc -c main.c ….. First you need to have the dependency list, then you would use make. Make has 2 rules: 1. to specify the dependency list. 2. how to build it For example the target here is calcit. Then you expand the file to other dependencies. Here I want to stop at the compilation step to have the main.o It’s your make file which tells the computer how to make your target and what are its dependencies So it makes the dependencies first and then the target It looks at the timestamp and check your c file and if it has not changed since then, it would not compile it again Just compile, no linking

5 Macros in Make Macro CC is defined early in the makefile with the line: CC = gcc Then using $(CC) causes substitution calcit: main.o getop.o stack.o getch.o $(CC) main.o getop.o stack.o getch.o -o calcit You can override the macro in the make command line make CC=gccx86 Suppose you are making your program for a particular platform (for example intel) and then you decide to make your files for another platform. So I want to be able to use different compilers. So you can create a macro. The makefile automatically substitute the CC with gcc and compile your code accordingly But some time later I want to build my program for another platform, So I just override the CC to use what ever compiler I want. You can change it in your makefile or just type make CC= … So you put one makefile there but by overriding you can build for different platforms

6 Make The user can type the command "make", or make with a named target, for example: “make getop.o” to cause the rules leading up to the target getop.o to be executed, if needed. When user types "make" without a target name, the FIRST rule listed will be the default target constructed. Thus, the "calcit" rule should be the first rule in the makefile You can just make some intermediate files. For example getop.o

7 Make At the end of the makefile, there is a rule with a target name "clean". clean: rm *.o Since "clean" is not a file: There is no dependency list (ages of files don't matter) It is called when you give the command "make clean". It deletes .o files to reduce the clutter in the directory. Sometimes you want to remove all of the .o files. Because they are intermediate files

8 Implicit Build Rules calcit: main.o getop.o stack.o getch.o
makefile can use implicit rule to build intermediate files, e.g. calcit: main.o getop.o stack.o getch.o gcc main.o getop.o stack.o getch.o -o calcit main.o: main.c getop.h stack.h getop.o: getop.c getop.h getch.h …… Since there is no explicit rule, the files main.o, getop.o … will be built using built-in implicit rules. For C, it is using a compiler named CC with options CFLAGS, e.g CC= gcc CFLAGS = -m32 calcit: main.o getop.o stack.o getch.o $(CC) $(CFLAGS) main.o getop.o stack.o getch.o -o calcit main.o: …. You can bypass the implicit rules by defining pattern rules (see for details) No build rules Target should have the build rule. If you have CC and CFLAGS defined in your makefile, then you can just type the dependencies for the intermediate files.

9 Header Files Principles for contents of .h files
Each .h file includes all of the function prototypes and symbolic constants needed to invoke those functions int function (int ); /* no code for function */ #define VALUE0_FOR_ARGUMENT 0 No statements that allocate memory in .h files!! Don’t use a single “calc.h” file (K&R, pg 82) A reusable solution shown in “Dependency Tree” An xxx.h file for each xxx.c source file of functions #include getop.h in getop.c and all source files that call functions provided in the getop.c source file (i.e. main) We used stdio.h You can not say int i = 0; It’s not good to have just one header file. Because each time you changed a small part of this single header file, the compiler will compile it again

10 Header Files – Math Library
When you want to use math functions Example: SIN( ) or SQRT( ) Write #include <math.h> But also invoke compiler with special flag: gcc lm (lm means library, math) *Note: -lm has to be at the end

11 Reverse Polish Notation(RPN)
For hw4, you need to know how to convert an algebraic (infix) expression to RPN Some calculators work this way, e.g H-P Algebraic ( ) * (567 – 432) RPN * Operand1 Operand2 Operator They used RPN to avoid typing parentheses Less number of keys you need to push on the calculator

12 Reverse Polish Notation(RPN)
Read from left and push the numbers in to the stack. When you read an operator, then pop 1 (or 2) number(s) from stack and do the operation and push the result in to the stack … − ÷ 3 × − = 5 They used RPN to avoid typing parentheses

13 Reverse Polish Notation
Enter: * Stack States: 123 21 144 567 432 135 19440 Empty 123 144 567 144 144

14 RPN Calculator Program
Pseudo-code for RPN calculator (See K&R, pg 75) while (next the character is not an EOF) if (number) push it on the stack else if (operator) pop operand(s) /* may be one or two */ do operation push result back on the stack else if (newline) pop and print value from top of stack else error

15 RPN Calculator Program
See K&R, page 76 and then page 78 Operand order is not important for some ops + , *, &, | Operand order is important for some ops! -, /, % There is only one operand for some ops ~, !

16 RPN Calculator Program
Break down the pseudo-code into functions push / pop get next number or operator, i.e. get op ( ) getch / ungetch Both push and pop access a set of variables for the stack  static external Both getch and ungetch access a buffer for characters from stdin  static external The codes I provided for you works with floating point numbers. We want to work with just int numbers. So modify to int. And also you have to add some operators that have not implemented

17 Communication Between Functions
Sometimes closely related functions need to share access to variables in situations where they never call each other and therefore can’t pass arguments to the shared variables Ex: push and pop share the stack variables Declare “static” variables inside source file for the functions (before / outside the braces for any of the functions)  “Static External” per K&R Makes them “globally” accessible to all functions in the source file

18 Back to RPN Calculator Program
Look at getop, getch, ungetch functions In getop( ), we try to input a char string for a number. It uses getch() to read a char. If it is a number, how do we know where the number ends? But if the next char is an operator (e.g. '+'), then we know the string of numbers has ended. But, we have to put the operator back in stdin. We do this with ungetch( ) Next invocation of getch() will read the operator from stdin.

19 getop.c /* * getop.c * * gets next token: operator or numeric operand
*/ #include <stdio.h> #include <ctype.h> #include "calc.h" int getop(char s[]) { int i, c; while ((s[0] = c = getch()) = = ' ' || c = = '\t') ; s[1] = '\0'; if (!isdigit(c) && c != '.') return c; /* not a number */ Isdigit() is a library function.

20 getop.c (cont’d) /* collect integer part in string s */ i = 0;
if (isdigit(c)) while (isdigit(s[++i] = c = getch())) ; /* collect fractional part in string s */ if (c = = '.') s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; } Ungetch(c) -> You put the previously read in to temporary buffer. So the next time you do getch() it reads from the buffer first before reading from stdin When you use getchar() you pass the character you read and you can’t go back

21 getch.c #define BUFSIZE 100
static char buf[BUFSIZE]; /* buffer for ungetch */ static int bufp = 0; /* next free position in buf */ /* get a possibly pushed back char from stdin */ int getch(void) { return (bufp > 0) ? buf[--bufp] : getchar( ); } Getch() reads both from stdin and the buffer It has a buffer to remembers what the previous operator was.

22 ungetch.c /* push char back for getch later */ void ungetch(int c) {
if (bufp >= BUFSIZE) printf("ungetch: too many characters in buffer.\n"); else buf[bufp++] = c; }


Download ppt "Homework K&R chapter 4."

Similar presentations


Ads by Google