=============================== WEEK 3 ======================================== Overview: - Structures - Unions - Defining types - Input / output I. Structures - a structure is a "collection of one or more variables, possibly of different types, grouped together under a single name for convenient handling" (K&R, p. 127) - tremendously useful for creting and organising large and complicated data types - the closest thing C has to Java classes and objects - structure definitions Example: struct point { int x; int y; }; - structure variable declarations and usage Example: struct point p; p.x = 10; p.y = 5; - we can nest different structures Example: struct line { struct point p1; struct point p2; }; - using structures Example: get the slope of a line slope = (p1.y - p2.y) / (p1.x - p2.x) - self-referential structures: - can not next a structure within itself - no recursive data types! - must use pointers Example: struct linked_list { int value; struct linked_list *next; } - legal operations on structures: * Copying a structure * accessing its members: e.g., p1.x * assigning something to it as a unit * passing it to functions * returning it from functions - do not pass large structures to functions, but pointers to them (why??) - be aware of the sgorthand pp-> used for (*pp).x - arrays of structures: struct key { char * word; int count; } keytable[NKEYS]; this defines an array "keytable" of key structures. Alternatively: struct key { char * word; int count; }; struct key keytable[NKEYS]; - initialization: struct key { char * word; int count; } keytable[] = { {"char",0}, {"break",0}, ... {"while",0}, }; - pointers to structures: struct key { char * word; int count; } *keytable[NKEYS]; - accessing components of structures tha are pointed to: Example (read sample program in K&R, Section 6.4): struct key *p; for (p = keytable; p < keytable + NKEYS; p++) if (p->count > 0) printf("%4d %s", p->count, p->word); note that this small program encompass many things that you must be very confortable with in C: * accessing a structure component a pointer, say p, is pointing to * using pointer arithmetic * using "printf" with appropriate format etc II. Unions - a union is a "variable that may hold (at different times) [items] of different types and sizes." (K&R) See the difference with structures: structure: "at the same time" union: "at different times" - Example: union tag { int ival; float fval; char * sval; } tag1; "tag1" is large enough to hold "fval" which is the largest of the three types in "tag" - at any time, "tag1" holds one of the 3 types. It's up to the programmer to keep track of what has been most recently stored in "tag1" - as with structures, nesting is possible III. Defining types - the typedef command can be used to simplify declarations Example: typedef struct linked_list LINKED_LIST; typedef struct line LINE; - usage: LINKED_LIST llint; LINE line1; LINE line2; IV. Input/Output - single character input/output: getchar/putchar - int getchar(); - gets next character from stdin - takes int because EOF == -1 - int putchar(int c); - writes character to stdout - how to read in a line of input: getline int getline(char *line, int maxlen) { int c, i; for (i = 0; i < maxlen-1 && (c=getchar() != EOF) && c != '\n'; i++) line[i] = c; line[i] = '\0'; return i; } - C has built in functions to input/output a line - char *gets(char *s); - int puts(const char *s); - but gets is unsafe and should not be used - formatted input/output: scanf/printf - formatted output: printf Example: int lineno, linelength; double wordsize; printf("Line %d has %d words with avg length %.2f\n", lineno, linelength, wordsize); - the % is a place holder indicating that the spot in the string is to be filled by the next parameter - % conversions %d = int as decimal %x = int as hexadecimal %c = int as character %s = char * - prints as string until '\0' encountered %f = double in decimal notation m.ddddd %e,E = double in scientific notation m.ddde+xx %g,G = double using either f or e %% = % %.10 -> trucate output after 10 characters %10 -> use at least 10 characters in output %-10 -> use at least 10 characters, flush left - formatted input: scanf Example: int day, year; char month[20]; scanf("%d of %s in %d", &day, month, &year); - scanf will skip over white space to match the format string - scanf returns number of items matched - % conversions for scanf are same as for printf EXCEPT: %e,%f,%g read in a float in any format the numbers have no meaning for scanf - can input/output to strings sscanf(char *string, "%d %d", &x, &y); sprintf(char *string, "hello there\n"); - can input/output to files FILE *fp - a file pointer fprintf(fp, "Dear %s\n", name); fscanf(fp, "Rating %c", &c); - SEE EXAMPLE filecopy.c - there are 3 standard C files - stdin, stdout, stderr - printf(...) == fprintf(stdout, ...); - scanf(...) == fscanf(stdin, ...); - Example: fprintf(stderr, "Error in data\n"); - fgets(), fputs() are safe versions of gets() and puts()