220 likes | 348 Views
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. Functions and C Program Structure. C makes functions efficient and easy to use Program != a few big functions
E N D
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
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)
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); }
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 */ }
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! */
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?
Post-fix Implementation with a Stack Enter: 123 21 + 567 432 - * Stack States: 123 21 144 567 432 135 19440 Empty 123 144 567 144 144
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
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 ~, !,
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
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)
Multi-Module ProgramsGlass & 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)
Dependency Tree for a Build calcit main.o getop.o stack.o getch.o main.c getop.c stack.c getch.c getop.h stack.h getch.h
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
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
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
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.
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)
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)
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( )
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.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; }