Exam / Homework • Exam 1 – Solutions Posted – Questions? • Starting K&R chapter 4 tonight • Read Glass and Ables Section on MAKE • Start on HW4 - Due Class 13 1 Functions and C Program Structure • • • • • • C makes functions efficient and easy to use Program != a few big functions Program == many small functions Functions may reside in separate source files Source files compiled and loaded separately An Introduction to MAKEFILE is coming (A process that K&R does not go into) 2 C Program File Structure • In file main.c: /* function prototypes */ #include “function.h” /* indirect */ int foobar(int, float); /* directly */ int main() { int n = foobar(function(), 1.0); } int foobar(int i, float j) { /* statements using i and j */ return (some integer expression); } 3 C Program File Structure • In file function.h: /* function.h: function prototype */ int function(void); • In file function.c: /* function.c: function code */ #include “function.h” int function() { /* function code */ } 4 Function Prototypes • Special case for null argument lists • Always code function prototype as: int foo (void); • Keeps compiler parameter checking enabled • Demonstration of bad example: int foo (); x = foo (i, j, k); /* compiler won’t catch! */ 5 Post-fix Notation • For hw4, you need to know how to convert an algebraic (in-fix) expression to post-fix • Some calculators work this way, e.g H-P • Algebraic (123 + 21) * (567 – 432) • Post-fix 123 21 + 567 432 - * • No parentheses are needed! • How’s that work? 6 Post-fix Implementation with a Stack Enter: 123 Stack States: 21 + 567 432 123 21 123 144 567 144 Empty 432 567 144 - 135 144 * 19440 7 Post-fix Calculator Program • Pseudo-code for In-fix 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 8 Post-fix 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 ~, !, 9 Post-fix 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 10 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 (similar to Java class variables) 11 Multi-Module Programs Glass & Ables, pg 397(3 ed.) • 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) 12 Dependency Tree for a Build calcit main.o main.c getop.o stack.o getop.c getop.h getch.o stack.c stack.h getch.c getch.h 13 Make (Glass, pg 347) • 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 … getch.o -o calcit • Note: Must use tabs to indent – not spaces 14 Make • 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 15 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 16 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. 17 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)18 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) 19 Back to Post-fix Calculator Program • Look at getop, getch, ungetch functions • In getop( ), we try to input a char string for a number. But if the string ends with a '+', we want to put that back in stdin, somehow, for a successive invocation of getch • We do this with ungetch( ) 20 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( ); } 21 getch.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; } 22