├── Exercise 1-1 └── main.c ├── Exercise 1-10 └── main.c ├── Exercise 1-11 └── main.c ├── Exercise 1-12 └── main.c ├── Exercise 1-13 ├── horizontal.c ├── lorem_ipsum.txt └── vertical.c ├── Exercise 1-14 ├── histogram.c └── lorem_ipsum.txt ├── Exercise 1-15 └── main.c ├── Exercise 1-16 ├── lorem_ipsum.txt └── main.c ├── Exercise 1-17 ├── lorem_ipsum.txt └── main.c ├── Exercise 1-18 ├── lorem_ipsum.txt └── main.c ├── Exercise 1-19 ├── lorem_ipsum_reverse.txt └── main.c ├── Exercise 1-2 └── main.c ├── Exercise 1-20 ├── detab.c └── lorem_ipsum.txt ├── Exercise 1-21 ├── entab.c └── lorem_ipsum.txt ├── Exercise 1-22 ├── fold.c └── lorem_ipsum.txt ├── Exercise 1-23 ├── main.c └── test_file.c ├── Exercise 1-24 ├── main.c └── test_file.c ├── Exercise 1-3 └── main.c ├── Exercise 1-4 └── main.c ├── Exercise 1-5 └── main.c ├── Exercise 1-6 └── main.c ├── Exercise 1-7 └── main.c ├── Exercise 1-8 └── main.c ├── Exercise 1-9 └── main.c ├── Exercise 2-1 ├── computed.c └── limits.c ├── Exercise 2-10 └── ternary.c ├── Exercise 2-2 └── loop.c ├── Exercise 2-3 └── htoi.c ├── Exercise 2-4 └── squeeze.c ├── Exercise 2-5 └── any.c ├── Exercise 2-6 └── setbits.c ├── Exercise 2-7 └── invert.c ├── Exercise 2-8 └── rightrot.c ├── Exercise 2-9 └── bitcount.c ├── Exercise 3-1 ├── binsearch.c └── binsearch2.c ├── Exercise 3-2 └── escape.c ├── Exercise 3-3 └── expand.c ├── Exercise 3-4 └── itoa.c ├── Exercise 3-5 └── itob.c ├── Exercise 3-6 └── itoa.c ├── Exercise 4-1 └── strindex.c ├── Exercise 4-10 └── calculator.c ├── Exercise 4-11 ├── calc.h ├── calc.h.gch ├── getch.c ├── getop.c ├── main.c └── stack.c ├── Exercise 4-12 └── itoa.c ├── Exercise 4-13 └── reverse.c ├── Exercise 4-14 └── swap.c ├── Exercise 4-2 └── atof.c ├── Exercise 4-3 └── calculator.c ├── Exercise 4-4 └── calculator.c ├── Exercise 4-5 └── calculator.c ├── Exercise 4-6 └── calculator.c ├── Exercise 4-7 └── ungets.c ├── Exercise 4-8 └── ungetch.c ├── Exercise 4-9 └── ungetch.c ├── Exercise 5-1 └── getint.c ├── Exercise 5-10 └── expr.c ├── Exercise 5-11 ├── detab.c ├── entab.c ├── lorem_ipsum_detab.txt ├── lorem_ipsum_entab.txt ├── settab.c └── tabpos.c ├── Exercise 5-12 ├── detab.c ├── entab.c ├── lorem_ipsum_detab.txt ├── lorem_ipsum_entab.txt ├── settab.c └── tabpos.c ├── Exercise 5-13 ├── lorem_ipsum.txt └── tail.c ├── Exercise 5-14 └── sort.c ├── Exercise 5-15 └── sort.c ├── Exercise 5-16 └── sort.c ├── Exercise 5-17 └── sort.c ├── Exercise 5-18 └── decl.c ├── Exercise 5-19 └── undecl.c ├── Exercise 5-2 └── getfloat.c ├── Exercise 5-20 └── decl.c ├── Exercise 5-3 └── strcat.c ├── Exercise 5-4 └── strend.c ├── Exercise 5-5 └── strn_functions.c ├── Exercise 5-6 ├── atoi_1.c ├── atoi_2.c ├── get_line.c ├── getop.c ├── itoa.c ├── recursive_itoa.c ├── recursive_reverse.c └── strindex.c ├── Exercise 5-7 ├── lines.txt ├── qsort_book.c └── qsort_exercise.c ├── Exercise 5-8 └── days_conversions.c ├── Exercise 5-9 └── days_conversion.c ├── Exercise 6-1 └── getword.c ├── Exercise 6-2 └── var_group.c ├── Exercise 6-3 ├── cross_referencer.c └── cs_poetry.txt ├── Exercise 6-4 ├── cs_poetry.txt └── distinct_word_count.c ├── Exercise 6-5 └── undef.c ├── Exercise 6-6 └── preprocessor.c ├── Exercise 7-1 ├── conversion.c └── lines.txt ├── Exercise 7-2 └── print_arbitrary.c ├── Exercise 7-3 └── minprintf.c ├── Exercise 7-4 └── minscanf.c ├── Exercise 7-5 └── calculator.c ├── Exercise 7-6 ├── diff_first.c ├── file1.txt └── file2.txt ├── Exercise 7-7 ├── file1.txt ├── file2.txt ├── file3.txt └── pattern_matching_files.c ├── Exercise 7-8 ├── Poem ├── Poems └── print_file.c ├── Exercise 7-9 └── is_upper.c ├── Exercise 8-1 ├── cat.c └── lorem_ipsum.txt ├── Exercise 8-2 ├── bitop │ ├── _fillbuf.c │ ├── lorem_ipsum.txt │ └── syscall.h └── fields │ ├── _fillbuf.c │ ├── lorem_ipsum.txt │ └── syscall.h ├── Exercise 8-3 ├── _flushbuf.c ├── lorem_ipsum.txt └── syscall.h ├── Exercise 8-4 ├── fseek.c ├── lorem_ipsum.txt └── syscall.h ├── Exercise 8-5 └── inode_info.c ├── Exercise 8-6 └── calloc.c ├── Exercise 8-7 └── malloc_check.c ├── Exercise 8-8 └── bfree.c ├── LICENSE └── README.md /Exercise 1-1/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Run the “hello, world” program on your system. Experiment with leaving out 3 | * parts of the program, to see what error messages you get. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | printf("hello, world\n"); 10 | } 11 | -------------------------------------------------------------------------------- /Exercise 1-10/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-10 3 | * Write a program to copy its input to its output, replacing each tab by \t, 4 | * each backspace by \b, and each backslash by \\. This makes tabs and 5 | * backspaces visible in an unambiguous way. 6 | */ 7 | 8 | #define IN 1 9 | #define OUT 0 10 | 11 | #include 12 | 13 | main() { 14 | int c; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (c == '\t') { 18 | putchar('\\'); 19 | putchar('t'); 20 | } else if (c == '\b') { 21 | putchar('\\'); 22 | putchar('b'); 23 | } else if (c == '\\') { 24 | putchar('\\'); 25 | putchar('\\'); 26 | } else 27 | putchar(c); 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Exercise 1-11/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-11 3 | * How would you test the word count program? What kinds of input are most 4 | * likely to uncover bugs if there are any? 5 | * 6 | * Empty word 7 | * Is R2D2 a word? 8 | * Is #2_2 a word? 9 | * Is un- 10 | * usual one word or two? 11 | * Is short-out one word or two? 12 | * Is a sequence of non alphanumeric characters a word? e.g. !"§$%&/()=? 13 | * Is the dot (or question mark) at the end a word ? 14 | * ... 15 | * 16 | */ 17 | 18 | #include 19 | 20 | #define IN 1 /* inside a word */ 21 | #define OUT 0 /* outside a word */ 22 | 23 | /* count lines, words and characters in input */ 24 | main() { 25 | int c, nl, nw, nc, state; 26 | 27 | state = OUT; 28 | nl = nw = nc = 0; 29 | while ((c = getchar()) != EOF) { 30 | ++nc; 31 | if (c == '\n') 32 | ++nl; 33 | if (c == ' ' || c == '\n' || c == '\t') 34 | state = OUT; 35 | else if (state == OUT) { 36 | state = IN; 37 | ++nw; 38 | } 39 | } 40 | printf("%d %d %d\n", nl, nw, nc); 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Exercise 1-12/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-12 3 | * Write a program that prints its input one word per line. 4 | */ 5 | 6 | #include 7 | 8 | #define IN 1 /* inside a word */ 9 | #define OUT 0 /* outside a word */ 10 | 11 | main() { 12 | int c, state; 13 | 14 | state = OUT; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (c == '\n' || c == '\t' || c == ' ') { 18 | if (state == IN) 19 | putchar('\n'); 20 | state = OUT; 21 | } else { 22 | state = IN; 23 | putchar(c); 24 | } 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /Exercise 1-13/horizontal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-13 Horizontal 3 | * Write a program to print a histogram of the lengths of words in its input. 4 | * It is easy to draw the histogram with the bars horizontal; a vertical 5 | * orientation is more challenging. 6 | */ 7 | 8 | #include 9 | 10 | int main() { 11 | int i, c, lcounter = 0; 12 | int histo[11]; 13 | 14 | for (i = 0; i < 11; i++) histo[i] = 0; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) { 18 | if (lcounter >= 11) lcounter = 10; 19 | histo[lcounter] = histo[lcounter] + 1; 20 | lcounter = 0; 21 | } else { 22 | ++lcounter; 23 | } 24 | } 25 | 26 | for (i = 1; i < 11; i++) { 27 | int j; 28 | printf("%2d ", i); 29 | for (j = 0; j < histo[i]; j++) printf("X"); 30 | printf("\n"); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /Exercise 1-13/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 2 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At v 3 | ero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, 4 | no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit am 5 | et, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labor 6 | e et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et ju 7 | sto duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus 8 | est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscin 9 | g elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquy 10 | am erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea re 11 | bum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor si 12 | t amet. 13 | -------------------------------------------------------------------------------- /Exercise 1-13/vertical.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-13 Horizontal 3 | * Write a program to print a histogram of the lengths of words in its input. 4 | * It is easy to draw the histogram with the bars horizontal; a vertical 5 | * orientation is more challenging. 6 | */ 7 | 8 | #include 9 | 10 | int main() { 11 | int i, j, c, max = 0, lcounter = 0; 12 | int histo[11]; 13 | 14 | for (i = 0; i < 11; i++) histo[i] = 0; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z')) { 18 | if (lcounter >= 11) lcounter = 10; 19 | histo[lcounter] = histo[lcounter] + 1; 20 | if (histo[lcounter] > max) max = histo[lcounter]; 21 | lcounter = 0; 22 | } else { 23 | ++lcounter; 24 | } 25 | } 26 | 27 | printf("\n"); 28 | for (i = max; i > 0; i--) { 29 | for (j = 1; j < 11; j++) { 30 | if (i <= histo[j]) 31 | printf("%3c", 'X'); 32 | else 33 | printf("%3c", ' '); 34 | } 35 | printf("\n"); 36 | } 37 | for (i = 1; i<11; i++) printf("%3d", i); 38 | 39 | printf("\n"); 40 | } 41 | -------------------------------------------------------------------------------- /Exercise 1-14/histogram.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-14 3 | * Write a program to print a histogram of the frequencies of different 4 | * characters in its input. 5 | */ 6 | 7 | #include 8 | 9 | int main() { 10 | int i, c, lcounter = 0; 11 | int histo['z'-'a']; 12 | 13 | for (i = 0; i <= 'z'-'a'; i++) histo[i] = 0; 14 | 15 | // A = 65 16 | // Z = 90 17 | // a = 97 18 | // z = 122 19 | while ((c = getchar()) != EOF) { 20 | if (c >= 'a' && c <= 'z') { 21 | histo[c-'a'] += 1; 22 | } else if (c >= 'A' && c <= 'Z') { 23 | histo[c-'A'] += 1; 24 | } 25 | } 26 | 27 | printf("\n"); 28 | for (i = 0; i <= 'z'-'a'; i++) { 29 | int j; 30 | printf("%2c ", i+'a'); 31 | for (j = 0; j < histo[i]; j++) printf("X"); 32 | printf("\n"); 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Exercise 1-14/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 2 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At v 3 | ero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, 4 | no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit am 5 | et, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labor 6 | e et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et ju 7 | sto duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus 8 | est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscin 9 | g elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquy 10 | am erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea re 11 | bum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor si 12 | t amet. 13 | -------------------------------------------------------------------------------- /Exercise 1-15/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-15 3 | * Rewrite the temperature conversion program of Section 1.2 to use a function 4 | * for conversion. 5 | */ 6 | 7 | #include 8 | 9 | void displayTemperatureTable(float fahr, float max, float step) { 10 | float celsius; 11 | printf("%10s %10s\n", "Fahrenheit", "Celsius"); 12 | printf("%10s %10s\n", "----------", "-------"); 13 | while (fahr <= max) { 14 | celsius = (5.0 / 9.0) * (fahr - 32.0); 15 | printf("%10.0f %10.1f\n", fahr, celsius); 16 | fahr = fahr + step; 17 | } 18 | } 19 | 20 | main() { 21 | displayTemperatureTable(0, 300, 20); 22 | } -------------------------------------------------------------------------------- /Exercise 1-16/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorizzle ipsizzle da bomb ghetto fizzle, ghetto adipiscing fo shizzle. Da bomb that's the shizzle velit, shizzle my nizzle crocodizzle volutpizzle, suscipit shiznit, shit vel, arcu. Pellentesque hizzle tortizzle. Bling bling erizzle. Shit izzle dolizzle dapibus turpis tempizzle shizznit. Maurizzle pellentesque the bizzle izzle turpizzle. Vestibulum in tortizzle. Pellentesque things rhoncizzle nisi. In hizzle yo platea dictumst. Boofron dapibizzle. Cool tellus urna, pretizzle fo shizzle mah nizzle fo rizzle, mah home g-dizzle, mattis ac, fo shizzle mah nizzle fo rizzle, mah home g-dizzle vitae, get down get down. Tellivizzle suscipit. Integer for sure sure sizzle purus. Sizzle ullamcorper. Aliquam sagittis massa a maurizzle. Vestibulizzle crackalackin ipsum primizzle crackalackin faucibizzle crunk luctizzle et ultricizzle boofron own yo' Curae; Aenizzle vestibulum. Pellentesque habitant shizzlin dizzle ass senectizzle own yo' i'm in the shizzle fo shizzle tellivizzle uhuh ... yih! ac shizzle my nizzle crocodizzle own yo'. tempizzle ass velizzle. Break it down erat shizzlin dizzle. Vivamus we gonna chung enizzle, 2 | scelerisque izzle, dignissizzle phat, fringilla vel, arcu. Funky fresh for sure. Donizzle fermentizzle, est uhuh ... yih! pharetra shiz, break yo neck, yall shizzlin dizzle ultricies boom shackalack, nizzle ullamcorper urna dolor quis nibh. Vivamizzle tellus neque, ultricizzle ut, ornare at, boom shackalack nizzle, yo. Shiz purus sizzle, get down get down sizzle amet, ghetto vehicula, crazy cool, arcu. Aenean eget fizzle izzle phat ullamcorpizzle funky fresh. Shizznit quizzle. Maurizzle mofo urna, tempizzle izzle, go to hizzle venenatis, sodales gangsta, felis. Etiam dang. Maecenizzle crazy mi. Nizzle eros. Crazy condimentum, turpis nizzle shut the shizzle up consectetuer, metus libero tellivizzle purizzle, egizzle ullamcorper dui mi non quizzle. Break yo neck, yall faucibus elit. Dizzle ass gangsta, consequizzle go to hizzle, volutpizzle, dang izzle, uhuh ... yih!. Dizzle sed urna. Tellivizzle shizzlin dizzle i saw beyonces tizzles and my pizzle went crizzle own yo' sizzle. Pellentesque hendrerit euismizzle shut the shizzle up. crackalackin nisl crazy erat. Etizzle posuere ma nizzle mi. Check it out gizzle. Sizzle nisl my shizz, euismizzle break yo neck, yall, you son of a bizzle daahng dawg, malesuada vel, nisi. Vivamus vulputate black nisl. 3 | -------------------------------------------------------------------------------- /Exercise 1-16/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-16 3 | * Revise the main routine of the longest-line program so it will correctly 4 | * print the length of arbitrarily long input lines, and as much as possible 5 | * of the text. 6 | * 7 | */ 8 | 9 | #include 10 | #define MAXLINE 1000 11 | 12 | int get_line(char line[], int maxline); 13 | void copy(char to[], char from[]); 14 | 15 | main() { 16 | int len, temp_len = 0; 17 | int max; 18 | int overflow = 0; 19 | char line[MAXLINE]; 20 | char longest[MAXLINE]; 21 | char temp_line[MAXLINE]; 22 | 23 | max = 0; 24 | while ((len = get_line(line, MAXLINE)) > 0) { 25 | if (len < MAXLINE - 1 || line[len - 1] == '\n') { 26 | if (overflow == 0) { 27 | if (len > max) { 28 | max = len; 29 | copy(longest, line); 30 | } 31 | } else { 32 | temp_len += len; 33 | if (temp_len > max) { 34 | max = temp_len; 35 | copy(longest, temp_line); 36 | 37 | } 38 | } 39 | temp_len = 0; 40 | overflow = 0; 41 | } else { 42 | if (temp_len == 0) copy(temp_line, line); 43 | temp_len += len; 44 | overflow = 1; 45 | } 46 | 47 | } 48 | if (max > 0) { 49 | printf("\nMax length: %d\nText: %s\n", max, longest); 50 | } 51 | return 0; 52 | } 53 | 54 | int get_line(char s[], int lim) { 55 | int c, i; 56 | 57 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 58 | s[i] = c; 59 | if (c == '\n') s[i++] = c; 60 | s[i] = '\0'; 61 | return i; 62 | } 63 | 64 | void copy(char to[], char from[]) { 65 | int i; 66 | 67 | i = 0; 68 | while ((to[i] = from[i]) != '\0') 69 | ++i; 70 | } 71 | -------------------------------------------------------------------------------- /Exercise 1-17/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 2 | At vero eos et accusam et justo duo dolores et ea rebum. 3 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 4 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 5 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, 6 | sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 7 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 8 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 9 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 10 | At vero eos et accusam et justo duo dolores et ea rebum. 11 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 12 | 13 | -------------------------------------------------------------------------------- /Exercise 1-17/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-17 3 | * Write a program to print all input lines that are longer than 80 characters. 4 | */ 5 | 6 | #include 7 | #define MAXLINE 1000 8 | 9 | #define MAX 80 10 | 11 | int get_line(char line[], int maxline); 12 | void copy(char to[], char from[]); 13 | 14 | main() { 15 | int len; 16 | char line[MAXLINE]; 17 | 18 | while ((len = get_line(line, MAXLINE)) > 0) 19 | if (len > MAX) 20 | printf("%s", line); 21 | 22 | return 0; 23 | } 24 | 25 | int get_line(char s[], int lim) { 26 | int c, i; 27 | 28 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 29 | s[i] = c; 30 | if (c == '\n') s[i++] = c; 31 | s[i] = '\0'; 32 | return i; 33 | } 34 | 35 | void copy(char to[], char from[]) { 36 | int i; 37 | 38 | i = 0; 39 | while ((to[i] = from[i]) != '\0') 40 | ++i; 41 | } 42 | -------------------------------------------------------------------------------- /Exercise 1-18/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 2 | At vero eos et accusam et justo duo dolores et ea rebum. 3 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 4 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 5 | 6 | 7 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, 8 | sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 9 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 10 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 11 | 12 | 13 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 14 | At vero eos et accusam et justo duo dolores et ea rebum. 15 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 16 | 17 | -------------------------------------------------------------------------------- /Exercise 1-18/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-18 3 | * Write a program to remove trailing blanks and tabs from each line of input, 4 | * and to delete entirely blank lines. 5 | */ 6 | 7 | #include 8 | 9 | #define MAXLINE 1000 10 | 11 | int get_line(char line[], int maxline); 12 | void trim(char s[], int length); 13 | 14 | main() { 15 | int len; 16 | char line[MAXLINE]; 17 | 18 | while ((len = get_line(line, MAXLINE)) > 0) { 19 | trim(line, len); 20 | if (line[0] != '\n') 21 | printf("%s", line); 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | int get_line(char s[], int lim) { 28 | int c, i; 29 | 30 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 31 | s[i] = c; 32 | if (c == '\n') s[i++] = c; 33 | s[i] = '\0'; 34 | return i; 35 | } 36 | 37 | void trim(char line[], int length) { 38 | int i; 39 | 40 | for (i = length - 2; i >= 0 && (line[i] == ' ' || line[i] == '\t'); i--) 41 | ; 42 | line[++i] = '\n'; 43 | line[++i] = '\0'; 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Exercise 1-19/lorem_ipsum_reverse.txt: -------------------------------------------------------------------------------- 1 | domrie ymunon maid des ,rtile gnicspidas rutetesnoc ,tema tis rolod muspi meroL 2 | tA .autpulov maid des ,tare mayuqila angam erolod te erobal tu tnudivni ropmet 3 | ,nergrebug dsak atilc tetS .muber ae te serolod oud otsuj te masucca te soe orev 4 | ,tema tis rolod muspi meroL .tema tis rolod muspi meroL tse sutcnas atamikat aes on 5 | te erobal tu tnudivni ropmet domrie ymunon maid des ,rtile gnicspidas rutetesnoc 6 | otsuj te masucca te soe orev tA .autpulov maid des ,tare mayuqila angam erolod 7 | sutcnas atamikat aes on ,nergrebug dsak atilc tetS .muber ae te serolod oud 8 | gnicspidas rutetesnoc ,tema tis rolod muspi meroL .tema tis rolod muspi meroL tse 9 | mayuqila angam erolod te erobal tu tnudivni ropmet domrie ymunon maid des ,rtile 10 | .muber ae te serolod oud otsuj te masucca te soe orev tA .autpulov maid des ,tare 11 | .tema tis rolod muspi meroL tse sutcnas atamikat aes on ,nergrebug dsak atilc tetS 12 | -------------------------------------------------------------------------------- /Exercise 1-19/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-19 3 | * Write a function reverse(s) that reverses the character string s. Use it to 4 | * write a program that reverses its input a line at a time. 5 | * 6 | */ 7 | 8 | #include 9 | #define MAXLINE 1000 10 | 11 | int get_line(char line[], int maxline); 12 | void reverse(char s[]); 13 | 14 | main() { 15 | int len; 16 | char line[MAXLINE]; 17 | 18 | while ((len = get_line(line, MAXLINE)) > 0) { 19 | reverse(line); 20 | printf("%s", line); 21 | } 22 | return 0; 23 | } 24 | 25 | int get_line(char s[], int lim) { 26 | int c, i; 27 | 28 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 29 | s[i] = c; 30 | if (c == '\n') s[i++] = c; 31 | s[i] = '\0'; 32 | return i; 33 | } 34 | 35 | /* s must end with newline character */ 36 | void reverse(char s[]) { 37 | char c; 38 | int length = 0; 39 | int i; 40 | 41 | for (i = 0; s[i] != '\n'; i++) 42 | length++; 43 | 44 | for (i = 0; i < length / 2; i++) { 45 | c = s[length - i - 1]; 46 | s[length - i - 1] = s[i]; 47 | s[i] = c; 48 | } 49 | } -------------------------------------------------------------------------------- /Exercise 1-2/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-2 3 | * Experiment to find out what happens when printf’s argument string contains 4 | * \c, where c is some character not listed above. 5 | * 6 | */ 7 | 8 | #include 9 | 10 | /* 11 | * https://en.wikipedia.org/wiki/Escape_sequences_in_C 12 | * 13 | * \z - might give a warning. prints the letter z. 14 | * \x - will not compile. 15 | * \0 - no warning. compiles. 16 | * ... 17 | * 18 | */ 19 | main() { 20 | printf("hello, world\z"); 21 | } 22 | -------------------------------------------------------------------------------- /Exercise 1-20/detab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-20 3 | * Write a program detab that replaces tabs in the input with the proper number 4 | * of blanks to space to the next tab stop. Assume a fixed set of tab stops, say 5 | * every n columns. Should n be a variable or a symbolic parameter? 6 | * 7 | */ 8 | 9 | #include 10 | 11 | #define MAXLINE 1000 12 | 13 | #define TABSTOP 8 //change this to your system's tabstop size 14 | 15 | int get_line(char line[], int maxline); 16 | void detab(char to[], char from[]); 17 | 18 | main() { 19 | int len; 20 | char line[MAXLINE]; 21 | char detabbed_line[MAXLINE]; 22 | 23 | while ((len = get_line(line, MAXLINE)) > 0) { 24 | detab(detabbed_line, line); 25 | printf("%s", detabbed_line); 26 | } 27 | return 0; 28 | } 29 | 30 | int get_line(char s[], int lim) { 31 | int c, i; 32 | 33 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 34 | s[i] = c; 35 | if (c == '\n') s[i++] = c; 36 | s[i] = '\0'; 37 | return i; 38 | } 39 | 40 | void detab(char to[], char from[]) { 41 | int c, i, j, k, spaces; 42 | 43 | for (i = 0, k = 0; (c = from[i]) != EOF && c != '\n'; ++i, ++k) { 44 | if (c == '\t') { 45 | spaces = TABSTOP - k % TABSTOP; 46 | for (j = 1; j <= spaces; ++j) { 47 | to[k++] = ' '; 48 | } 49 | --k; 50 | } else 51 | to[k] = c; 52 | } 53 | if (c == '\n') 54 | to[k++] = c; 55 | to[k] = '\0'; 56 | } 57 | -------------------------------------------------------------------------------- /Exercise 1-20/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 2 | sed diam nonumy eirmod 3 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 4 | At vero eos et accusam et justo duo dolores et ea rebum. 5 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 6 | 7 | -------------------------------------------------------------------------------- /Exercise 1-21/entab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-21 3 | * Write a program entab that replaces strings of blanks by the minimum number 4 | * of tabs and blanks to achieve the same spacing. Use the same tab stops as for 5 | * detab. When either a tab or a single blank would suffice to reach a tab stop, 6 | * which should be given preference? 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #define MAXLINE 1000 13 | #define TABSTOP 8 //change this to your system's tabstop size 14 | 15 | int get_line(char line[], int maxline); 16 | void entab(char to[], char from[]); 17 | 18 | main() { 19 | int len; 20 | char line[MAXLINE]; 21 | char entabbed_line[MAXLINE]; 22 | 23 | while ((len = get_line(line, MAXLINE)) > 0) { 24 | entab(entabbed_line, line); 25 | printf("%s", entabbed_line); 26 | } 27 | return 0; 28 | } 29 | 30 | int get_line(char s[], int lim) { 31 | int c, i; 32 | 33 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 34 | s[i] = c; 35 | if (c == '\n') s[i++] = c; 36 | s[i] = '\0'; 37 | return i; 38 | } 39 | 40 | void entab(char to[], char from[]) { 41 | int c, i, j, tabs, spaces, pos; 42 | 43 | spaces = tabs = 0; 44 | for (i = j = pos = 0; (c = from[i]) != EOF && c != '\n'; i++, pos++) { 45 | if (c == ' ') { 46 | if ((pos + 1) % TABSTOP == 0) { 47 | tabs++; 48 | spaces = 0; 49 | } else { 50 | spaces++; 51 | } 52 | } 53 | if (c != ' ') { 54 | for (; tabs > 0; tabs--, j++) 55 | to[j] = '\t'; 56 | tabs = 0; 57 | if (c == '\t') { 58 | spaces = 0; 59 | pos = pos + (TABSTOP - pos % TABSTOP) - 1; 60 | } 61 | for (; spaces > 0; spaces--, j++) 62 | to[j] = ' '; 63 | to[j++] = c; 64 | } 65 | } 66 | if (c == '\n') { 67 | to[j++] = c; 68 | } 69 | to[j] = '\0'; 70 | } 71 | -------------------------------------------------------------------------------- /Exercise 1-21/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 2 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 3 | At vero eos et accusam et justo duo dolores et ea rebum. 4 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 5 | 6 | -------------------------------------------------------------------------------- /Exercise 1-22/fold.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-22 3 | * Write a program to “fold” long input lines into two or more shorter lines 4 | * after the last non-blank character that occurs before the n-th column of 5 | * input. Make sure your program does something intelligent with very long 6 | * lines, and if there are no blanks or tabs before the specified column. 7 | * 8 | */ 9 | 10 | #include 11 | 12 | #define MAXLINE 1000 13 | #define TABSTOP 8 //change this to your system's tabstop size 14 | #define FOLD_COL 80 //adapt n-th column to fold at 15 | 16 | int get_line(char line[], int maxline); 17 | int detab(char to[], char from[]); 18 | void fold(char to[], char from[]); 19 | 20 | main() { 21 | int len; 22 | char line[MAXLINE]; 23 | char folded_line[MAXLINE]; 24 | char detabbed_line[MAXLINE]; 25 | 26 | while ((len = get_line(line, MAXLINE)) > 0) { 27 | len = detab(detabbed_line, line); 28 | if (len < FOLD_COL) { 29 | printf("%s", detabbed_line); 30 | } else { 31 | fold(folded_line, detabbed_line); 32 | printf("%s", folded_line); 33 | } 34 | } 35 | return 0; 36 | } 37 | 38 | int get_line(char s[], int lim) { 39 | int c, i; 40 | 41 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 42 | s[i] = c; 43 | if (c == '\n') s[i++] = c; 44 | s[i] = '\0'; 45 | return i; 46 | } 47 | 48 | 49 | void fold(char dest[], char source[]) { 50 | int c, i, j, k; 51 | int counter = 0; 52 | 53 | for (i = j = 0; (c = source[i]) != EOF && c != '\n'; i++) { 54 | counter++; 55 | if (counter == FOLD_COL) { /* fold text here */ 56 | if (c == ' ') { /* fole at white space */ 57 | dest[j++] = '\n'; 58 | counter = 0; 59 | for (; isspace(source[i]); i++) /* start next line without white space ? */ 60 | ; 61 | i--; 62 | continue; 63 | } else { 64 | for (k = j + 1; dest[k] != ' ' && dest[k] != '\t' && k > 0; k--) /* find first white space backwards */ 65 | for (; dest[k] == ' ' && dest[k] == '\t'; k--) 66 | ; 67 | if (k != 0) { // text has white space, fold line 68 | dest[k] = '\n'; 69 | counter = j - k; 70 | } else { /* long contiguous text without white space */ 71 | for ( ; !isspace(source[i]) ; i++) /* ignore text until next non white space */ 72 | ; 73 | dest[j] = '.'; 74 | dest[j-1] = '.'; 75 | dest[j-2] = '.'; 76 | j++; 77 | continue; 78 | } 79 | } 80 | } 81 | dest[j++] = c; 82 | } 83 | if (c == '\n') { 84 | dest[j++] = c; 85 | } 86 | dest[j] = '\0'; 87 | } 88 | 89 | 90 | int detab(char to[], char from[]) { 91 | int c, i, j, k, spaces; 92 | 93 | for (i = 0, k = 0; (c = from[i]) != EOF && c != '\n'; ++i, ++k) { 94 | if (c == '\t') { 95 | spaces = TABSTOP - k % TABSTOP; 96 | for (j = 1; j <= spaces; ++j) { 97 | to[k++] = ' '; 98 | } 99 | --k; 100 | } else 101 | to[k] = c; 102 | } 103 | if (c == '\n') 104 | to[k++] = c; 105 | to[k] = '\0'; 106 | return k-1; 107 | } 108 | -------------------------------------------------------------------------------- /Exercise 1-22/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 2 | At vero eos et accusam et justo duo dolores et ea rebum. 3 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 4 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, 5 | 6 | sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 7 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 8 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 9 | 10 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. 11 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 12 | 13 | Loremipsumdolorsitamet,consetetursadipscingelitr,seddiamnonumyeirmodtemporinviduntutlaboreetdoloremagnaaliquyamerat,seddiamvoluptua. 14 | 15 | -------------------------------------------------------------------------------- /Exercise 1-23/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define P 0 // Program 5 | #define PC 1 // Program - Comment 6 | #define S 2 // String 7 | #define E 3 // Escape (in Strings) 8 | #define CS 4 // Comment (simple) 9 | #define CM 5 // Comment (multiple lines) 10 | #define CMP 6 // Comment (multiple lines) - Program 11 | 12 | void update_transition(char c); 13 | 14 | //global STATE; start in state P 15 | int STATE = P; 16 | 17 | int main(int argc, char** argv) { 18 | 19 | int c; 20 | 21 | while ((c = getchar()) != EOF) { 22 | update_transition(c); 23 | } 24 | 25 | return 0; 26 | } 27 | 28 | void update_transition(char c) { 29 | 30 | if (STATE == P) { 31 | if (c == '/') { 32 | STATE = PC; 33 | return; 34 | } 35 | if (c == '"') { 36 | STATE = S; 37 | printf("%c", c); 38 | return; 39 | } 40 | printf("%c", c); 41 | return; 42 | } else if (STATE == PC) { 43 | if (c != '/' && c != '*') { 44 | STATE = P; 45 | printf("/%c", c); 46 | return; 47 | } 48 | if (c == '/') STATE = CS; 49 | if (c == '*') STATE = CM; 50 | return; 51 | } else if (STATE == CS) { 52 | if (c == '\n') { 53 | STATE = P; 54 | printf("%c", c); 55 | } 56 | return; 57 | } else if (STATE == CM) { 58 | if (c == '*') STATE = CMP; 59 | return; 60 | } else if (STATE == CMP) { 61 | if (c == '/') STATE = P; 62 | if (c != '/' && c != '*') STATE = CM; 63 | return; 64 | } else if (STATE == S) { 65 | if (c == '"') STATE = P; 66 | if (c == '\\') STATE = E; 67 | printf("%c", c); 68 | return; 69 | } else if (STATE == E) { 70 | STATE = S; 71 | printf("%c", c); 72 | return; 73 | } 74 | 75 | } 76 | -------------------------------------------------------------------------------- /Exercise 1-23/test_file.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: test_file.c 3 | * Author: Prog Rammer 4 | * 5 | * Created on January 1, 1970, 00:00:00 UTC 6 | */ 7 | 8 | // Include standard input/output header 9 | #include 10 | // Include standard library header 11 | #include 12 | 13 | /* 14 | * This is a function. 15 | */ 16 | int printf_strings(int argc, char** argv) { 17 | 18 | // This are quoted strings, not comments 19 | char *s1 = "//This comment is a quoted string"; 20 | char *s2 = "/* This is another quoted string */"; 21 | 22 | //print the strings 23 | printf("%s\n", s1); 24 | printf("%s\n", s2); 25 | 26 | // return success 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Exercise 1-24/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * File: main.c 3 | * Author: elyasin 4 | * 5 | * Created on July 30, 2015, 9:00 AM 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #define P 0 // Program 12 | #define PC 1 // Program - Comment 13 | #define S 2 // String 14 | #define E 3 // Escape (in Strings) 15 | #define CS 4 // Comment (simple) 16 | #define CM 5 // Comment (multiple lines) 17 | #define CMP 6 // Comment (multiple lines) - Program 18 | #define C 7 // Character 19 | #define E2 8 // Escape (in Characters) 20 | 21 | void update_transition(char c); 22 | void countParens(char c); 23 | 24 | //global STATE; start in state P 25 | int STATE = P; 26 | 27 | //counter for braces, brackets, parentheses 28 | int braces = 0; 29 | int brackets = 0; 30 | int parentheses = 0; 31 | 32 | //for unblanced symbols like )( 33 | int BRACES_UNB = 0; 34 | int BRACKETS_UNB = 0; 35 | int PARENTHESES_UNB = 0; 36 | 37 | 38 | int main(int argc, char** argv) { 39 | 40 | int c; 41 | 42 | while ((c = getchar()) != EOF) { 43 | update_transition(c); 44 | } 45 | 46 | if (braces != 0 || BRACES_UNB == 1) 47 | puts("Unbalanced braces"); 48 | if (brackets != 0 || BRACKETS_UNB == 1) 49 | puts("Unbalanced brackets"); 50 | if (parentheses != 0 || PARENTHESES_UNB == 1) 51 | puts("Unbalanced parentheses"); 52 | if (STATE != P && STATE != CS) 53 | puts("Unbalanced quotes (double, single)"); 54 | 55 | if (braces + brackets + parentheses == 0 56 | && (BRACES_UNB + BRACKETS_UNB + PARENTHESES_UNB == 0) 57 | && (STATE == P || STATE == CS)) 58 | puts("All good"); 59 | 60 | return 0; 61 | } 62 | 63 | void update_transition(char c) { 64 | 65 | if (STATE == P) { 66 | if (c == '/') { 67 | STATE = PC; 68 | return; 69 | } 70 | if (c == '"') { 71 | STATE = S; 72 | return; 73 | } 74 | if (c == '\'') { 75 | STATE = C; 76 | return; 77 | } 78 | countParens(c); 79 | return; 80 | } else if (STATE == PC) { 81 | if (c != '/' && c != '*') { 82 | STATE = P; 83 | countParens(c); 84 | return; 85 | } 86 | if (c == '/') STATE = CS; 87 | if (c == '*') STATE = CM; 88 | return; 89 | } else if (STATE == CS) { 90 | if (c == '\n') STATE = P; 91 | return; 92 | } else if (STATE == CM) { 93 | if (c == '*') STATE = CMP; 94 | return; 95 | } else if (STATE == CMP) { 96 | if (c == '/') STATE = P; 97 | if (c != '/' && c != '*') STATE = CM; 98 | return; 99 | } else if (STATE == S) { 100 | if (c == '"') STATE = P; 101 | if (c == '\\') STATE = E; 102 | return; 103 | } else if (STATE == E) { 104 | STATE = S; 105 | return; 106 | } else if (STATE == C) { 107 | if (c == '\'') STATE = P; 108 | if (c == '\\') STATE = E2; 109 | return; 110 | } else if (STATE == E2) { 111 | STATE = C; 112 | return; 113 | } 114 | 115 | } 116 | 117 | void countParens(char c) { 118 | if (c == '(') parentheses++; 119 | if (c == ')') parentheses--; 120 | if (c == '[') brackets++; 121 | if (c == ']') brackets--; 122 | if (c == '{') braces++; 123 | if (c == '}') braces--; 124 | if (parentheses < 0) 125 | PARENTHESES_UNB = 1; 126 | if (brackets < 0) 127 | BRACKETS_UNB = 1; 128 | if (braces < 0) 129 | BRACES_UNB = 1; 130 | } 131 | -------------------------------------------------------------------------------- /Exercise 1-24/test_file.c: -------------------------------------------------------------------------------- 1 | /* 2 | ( File: main.c 3 | ( Author: elyasin 4 | ( 5 | ( Created on July 30, 2015, 9:00 AM 6 | */ 7 | 8 | // Include (standard) input/output header 9 | #include 10 | // Include (standard) library header 11 | #include 12 | 13 | /* 14 | * This is a the main function. 15 | */ 16 | int printf_strings(int argc, char** argv) { 17 | 18 | // This are quoted strings, not comments 19 | char *s1 = "// This comment is a \"quoted\" string :-)"; 20 | char *s2 = "/* This is another \'quoted\' string */ :-]"; 21 | char *s3 = "/* This is another \'quoted\' string */ :-}"; 22 | 23 | //print the strings 24 | printf("%s\n", s1); 25 | printf("%s\n", s2); 26 | printf("%s\n", s2); 27 | 28 | // return success :-) 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /Exercise 1-3/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-3 3 | * Modify the temperature conversion program to print a heading above the table. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | float fahr, celsius; 10 | float lower, upper, step; 11 | 12 | lower = 0; 13 | upper = 300; 14 | step = 20; 15 | 16 | fahr = lower; 17 | printf("%10s %10s\n", "Fahrenheit", "Celsius"); 18 | printf("%10s %10s\n", "----------", "-------"); 19 | while (fahr <= upper) { 20 | celsius = (5.0 / 9.0) * (fahr - 32.0); 21 | printf("%10.0f %10.1f\n", fahr, celsius); 22 | fahr = fahr + step; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Exercise 1-4/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-4 3 | * Write a program to print the corresponding Celsius to Fahrenheit table. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | float fahr, celsius; 10 | float lower, upper, step; 11 | 12 | lower = 0; 13 | upper = 150; 14 | step = 10; 15 | 16 | celsius = lower; 17 | printf("%7s %10s\n", "Celsius", "Fahrenheit"); 18 | printf("%7s %10s\n", "-------", "----------"); 19 | while (celsius <= upper) { 20 | fahr = (celsius * 9.0 / 5.0) + 32.0; 21 | printf("%7.0f %10.1f\n", celsius, fahr); 22 | celsius = celsius + step; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /Exercise 1-5/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-5 3 | * Modify the temperature conversion program to print the table in reverse 4 | * order, that is, from 300 degrees to 0. 5 | */ 6 | 7 | #include 8 | 9 | main() { 10 | int fahr; 11 | 12 | printf("%10s %10s\n", "Fahrenheit", "Celsius"); 13 | printf("%10s %10s\n", "----------", "-------"); 14 | for (fahr = 300; fahr >= 0; fahr = fahr - 20) 15 | printf("%10d %10.1f\n", fahr, (5.0 / 9.0)*(fahr - 32)); 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Exercise 1-6/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-6 3 | * Verify that the expression getchar() != EOF is 0 or 1. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | int c = getchar(); 10 | printf("getchar() != EOF? %d\n", c != EOF); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /Exercise 1-7/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-7 3 | * Write a program to print the value of EOF. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | printf("%d\n", EOF); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /Exercise 1-8/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-8 3 | * Write a program to count blanks, tabs, and newlines. 4 | */ 5 | 6 | #include 7 | 8 | main() { 9 | int c, nlc, tc, bc; 10 | 11 | nlc = tc = bc = 0; 12 | 13 | while ((c = getchar()) != EOF) { 14 | if (c == '\n') nlc++; 15 | if (c == '\t') tc++; 16 | if (c == ' ') bc++; 17 | } 18 | printf("\n"); 19 | printf("\\n : %d\n", nlc); 20 | printf("\\t : %d\n", tc); 21 | printf("\' \': %d\n", bc); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Exercise 1-9/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Exercise 1-9 3 | * Write a program to copy its input to its output, replacing each string of 4 | * one or more blanks by a single blank. 5 | */ 6 | 7 | #define IN 1 8 | #define OUT 0 9 | 10 | #include 11 | 12 | main() { 13 | int c; 14 | int wflag = OUT; 15 | 16 | while ((c = getchar()) != EOF) { 17 | if (c == ' ') { 18 | if (wflag == OUT) { 19 | putchar(c); 20 | wflag = IN; 21 | } 22 | } else { 23 | putchar(c); 24 | wflag = OUT; 25 | } 26 | 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /Exercise 2-1/computed.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | 7 | printf("--------Assuming 2-complement--------\n"); 8 | printf("-----------Computed limits-----------\n"); 9 | 10 | printf("Unsigned Char max : %d\n", (unsigned char) ~0); 11 | printf("Unsigned short max : %d\n", (unsigned short) ~0); 12 | printf("Unsigned int max : %u\n", (unsigned int) ~0); 13 | printf("Unsigned long max : %lu\n", (unsigned long) ~0); 14 | 15 | printf("Signed char max : %d\n", (char) ((unsigned char) ~0 >> 1)); 16 | printf("Signed char min : %d\n", -(char) (unsigned char) 1 << ((sizeof(unsigned char) * CHAR_BIT) - 1)); 17 | printf("Signed short max : %d\n", (short) ((unsigned short) ~0 >> 1)); 18 | printf("Signed short min : %d\n", -(short) (unsigned short) 1 << ((sizeof(unsigned short) * CHAR_BIT) - 1)); 19 | printf("Signed int max : %d\n", (int) ((unsigned int) ~0 >> 1)); 20 | printf("Signed int min : %d\n", -(int) (unsigned int) 1 << ((sizeof(unsigned int) * CHAR_BIT) - 1)); 21 | printf("Signed long max : %ld\n", (long) ((unsigned long) ~0 >> 1)); 22 | printf("Signed long min : %ld\n", -(long) (unsigned long) 1 << ((sizeof(unsigned long) * CHAR_BIT) - 1)); 23 | 24 | 25 | int i; 26 | 27 | union { 28 | int i; 29 | float f; 30 | } uf; 31 | float f; 32 | for (f = 1; f < INFINITY; uf.f = f, f *= 1e1); 33 | unsigned int i1 = (unsigned int) ~0; 34 | float f1 = (float) i1; 35 | for (i = 2, f = uf.f; f * i < INFINITY; uf.f = f * i, i++); 36 | uf.i = uf.i | 0x7FFFFFu; // Mantissa for float is 23 bit on my machine 37 | printf("FLT max : %g (float)\n", uf.f); 38 | printf("-FLT max : %g (float)\n", -uf.f); 39 | uf.i = uf.i & 0u; 40 | uf.i = uf.i | 0x7FFFFFu; 41 | printf("FLT min : %g (float)\n", uf.f); 42 | printf("-FLT min : %g (float)\n", -uf.f); 43 | 44 | union { 45 | long int i; 46 | double d; 47 | } ud; 48 | double d; 49 | for (d = 1; d < INFINITY; ud.d = d, d *= 1e1); 50 | for (i = 2, d = ud.d; d * i < INFINITY; ud.d = d * i, i++); 51 | ud.i = ud.i | 0xFFFFFFFFFFFFFlu; // Mantissa for double is 52 bit on my machine 52 | printf("DBL max : %g (double) \n", ud.d); 53 | printf("-DBL max : %g (double)\n", -ud.d); 54 | ud.i = ud.i & 0u; 55 | ud.i = ud.i | 0xFFFFFFFFFFFFFlu; 56 | printf("DBL min : %g (double)\n", ud.d); 57 | printf("-DBL min : %g (double)\n", -ud.d); 58 | 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /Exercise 2-1/limits.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | 7 | printf("-----------Limits Header-----------\n"); 8 | 9 | printf("CHAR_BIT : %d\n", CHAR_BIT); 10 | printf("CHAR_MAX : %d\n", CHAR_MAX); 11 | printf("CHAR_MIN : %d\n", CHAR_MIN); 12 | printf("INT_MAX : %d\n", INT_MAX); 13 | printf("INT_MIN : %d\n", INT_MIN); 14 | printf("LONG_MAX : %ld\n", (long) LONG_MAX); 15 | printf("LONG_MIN : %ld\n", (long) LONG_MIN); 16 | printf("SCHAR_MAX : %d\n", SCHAR_MAX); 17 | printf("SCHAR_MIN : %d\n", SCHAR_MIN); 18 | printf("SHRT_MAX : %d\n", SHRT_MAX); 19 | printf("SHRT_MIN : %d\n", SHRT_MIN); 20 | printf("UCHAR_MAX : %d\n", UCHAR_MAX); 21 | printf("UINT_MAX : %u\n", (unsigned int) UINT_MAX); 22 | printf("ULONG_MAX : %lu\n", (unsigned long) ULONG_MAX); 23 | printf("USHRT_MAX : %d\n", (unsigned short) USHRT_MAX); 24 | printf("FLT_MAX : %g\n", (float) FLT_MAX); 25 | printf("-FLT_MAX : %g\n", (float) -FLT_MAX); 26 | printf("FLT_MIN : %g\n", (float) FLT_MIN); 27 | printf("-FLT_MIN : %g\n", (float) -FLT_MIN); 28 | printf("DBL_MAX : %g\n", (double) DBL_MAX); 29 | printf("-DBL_MAX : %g\n", (double) -DBL_MAX); 30 | printf("DBL_MIN : %g\n", (double) DBL_MIN); 31 | printf("-DBL_MIN : %g\n", (double) -DBL_MIN); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /Exercise 2-10/ternary.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int lower(char c); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | char c; 8 | 9 | c = lower('A'); 10 | printf("%c\n", c); 11 | 12 | c = lower('b'); 13 | printf("%c\n", c); 14 | 15 | return 0; 16 | } 17 | 18 | int lower(char c) { 19 | return (c >= 'A' && c <= 'Z') ? (c + 'a' - 'A') : c; 20 | } 21 | -------------------------------------------------------------------------------- /Exercise 2-2/loop.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | int get_line(char s[], int lim); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | char s[MAXLINE]; 10 | get_line(s, MAXLINE); 11 | printf("%s", s); 12 | 13 | return 0; 14 | } 15 | 16 | int get_line(char s[], int lim) { 17 | int c, i, LOOP; 18 | 19 | i = 0; 20 | LOOP = 1; 21 | while ( LOOP ) { 22 | if (i >= lim-1) 23 | LOOP = 0; 24 | else if ((c = getchar()) == EOF) 25 | LOOP = 0; 26 | else if (c == '\n') 27 | LOOP = 0; 28 | else { 29 | s[i] = c; 30 | i++; 31 | } 32 | } 33 | 34 | if (c == '\n') { 35 | s[i] = c; 36 | ++i; 37 | } 38 | s[i] = '\0'; 39 | return i; 40 | } 41 | -------------------------------------------------------------------------------- /Exercise 2-3/htoi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int htoi(char s[]); 5 | 6 | int main(int argc, char** argv) { 7 | 8 | int a = htoi("0x17F"); 9 | printf("0x17F = %d\n", a); 10 | 11 | a = htoi("0Xf71"); 12 | printf("0Xf71 = %d\n", a); 13 | 14 | a = htoi("fff"); 15 | printf("fff = %d\n", a); 16 | 17 | a = htoi("ABC"); 18 | printf("ABC = %d\n", a); 19 | 20 | return 0; 21 | } 22 | 23 | // a - 97 24 | // f - 102 25 | // 0 - 48 26 | // 9 - 57 27 | // A - 65 28 | // F - 70 29 | 30 | int htoi(char s[]) { 31 | int i, n; 32 | 33 | if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) 34 | i = 2; 35 | else 36 | i = 0; 37 | 38 | n = 0; 39 | for (; isxdigit(s[i]); ++i) { 40 | if (isalpha(s[i])) 41 | n = 16 * n + (tolower(s[i]) - 'a' + 10); // don't digits 0-9 42 | else 43 | n = 16 * n + (s[i] - '0'); 44 | 45 | } 46 | 47 | return n; 48 | } 49 | -------------------------------------------------------------------------------- /Exercise 2-4/squeeze.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | void squeeze(char s1[], char s2[]); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | char s1[MAXLINE] = "Tbhcids figs jak ltmesotp, qirsunv'wt xiytz?"; 10 | char s2[] = "bcdfgjklmopqruvwxyz"; 11 | 12 | squeeze(s1, s2); 13 | printf("%s\n", s1); 14 | 15 | return 0; 16 | } 17 | 18 | void squeeze(char s1[], char s2[]) { 19 | 20 | short bool = 0; 21 | int i, j, k; 22 | 23 | for (i = j = 0; s1[i] != '\0'; i++) { 24 | for (k = 0; s2[k] != '\0'; k++) 25 | if (s1[i] == s2[k]) { 26 | bool = 1; 27 | break; 28 | } 29 | if (bool == 0) 30 | s1[j++] = s1[i]; 31 | bool = 0; 32 | } 33 | 34 | s1[j] = '\0'; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Exercise 2-5/any.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | int any(char s1[], char s2[]); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | char s1[MAXLINE] = "This is a test."; 10 | char s_ok[] = "b.ac"; 11 | char s_ko[] = "yxz"; 12 | char s_empty[] = ""; 13 | int pos; 14 | 15 | pos = any(s1, s_ok); 16 | if (pos == -1) 17 | printf("Nothing found\n"); 18 | else 19 | printf("Found at position %d\n", pos); 20 | 21 | pos = any(s1, s_ko); 22 | if (pos == -1) 23 | printf("Nothing found\n"); 24 | else 25 | printf("Found at position %d\n", pos); 26 | 27 | pos = any(s1, s_empty); 28 | if (pos == -1) 29 | printf("Nothing found\n"); 30 | else 31 | printf("Found at position %d\n", pos); 32 | 33 | return 0; 34 | } 35 | 36 | int any(char s1[], char s2[]) { 37 | 38 | int i, j; 39 | 40 | for (i = 0; s1[i] != '\0'; i++) 41 | for (j = 0; s2[j] != '\0'; j++) 42 | if (s1[i] == s2[j]) 43 | return i; 44 | 45 | return -1; 46 | } 47 | -------------------------------------------------------------------------------- /Exercise 2-6/setbits.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned setbits(unsigned x, int p, int n, unsigned y); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | unsigned x = 255; 8 | unsigned y = 205; 9 | unsigned r; 10 | 11 | r = setbits(x, 5, 2, y); 12 | printf("%u\n", r); 13 | 14 | return 0; 15 | } 16 | 17 | unsigned setbits(unsigned x, int p, int n, unsigned y) { 18 | 19 | unsigned mask = ~(~0 << n) << (p - n + 1); 20 | x = x & ~mask; 21 | y = (y & ~(~0 << n)) << (p - n + 1); 22 | x = x | y; 23 | 24 | return x; 25 | } 26 | -------------------------------------------------------------------------------- /Exercise 2-7/invert.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned invert2(unsigned x, int p, int n); 4 | unsigned invert(unsigned x, int p, int n); 5 | 6 | int main(int argc, char** argv) { 7 | 8 | unsigned x = ~0; 9 | unsigned r; 10 | 11 | printf("x = %u\n", x); 12 | 13 | printf("Invert 16 bits from 32nd position on\n"); 14 | r = invert(x, 31, 16); 15 | printf("%u\n", r); 16 | 17 | printf("Invert 16 bits from 16th position on\n"); 18 | r = invert2(x, 15, 16); 19 | printf("%u\n", r); 20 | 21 | return 0; 22 | } 23 | 24 | unsigned invert(unsigned x, int p, int n) { 25 | 26 | unsigned mask = ~(~0 << n) << (p - n + 1); 27 | x = x ^ mask; 28 | 29 | 30 | return x; 31 | } 32 | 33 | 34 | /* without using xor */ 35 | unsigned invert2(unsigned x, int p, int n) { 36 | 37 | unsigned y = ((~(x >> (p - n + 1)) & ~(~0 << n)) << (p - n + 1)); 38 | unsigned mask = ~(~0 << n) << (p - n + 1); 39 | x = x & ~mask; 40 | x = x | y; 41 | 42 | return x; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /Exercise 2-8/rightrot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | unsigned rightrot(unsigned x, int n); 5 | 6 | int main(int argc, char** argv) { 7 | 8 | unsigned x = 170; 9 | 10 | x = rightrot(x, 2); 11 | printf("%u\n", x); 12 | 13 | return 0; 14 | } 15 | 16 | unsigned rightrot(unsigned x, int n) { 17 | 18 | unsigned x_right = x >> n; 19 | unsigned x_left = x << ((sizeof (unsigned) * CHAR_BIT) - n); 20 | x = x_right | x_left; 21 | 22 | return x; 23 | } 24 | -------------------------------------------------------------------------------- /Exercise 2-9/bitcount.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int bitcount(unsigned x); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | int x = 2576980377; 8 | int b; 9 | 10 | b = bitcount(x); 11 | printf("%d\n", b); 12 | 13 | return 0; 14 | } 15 | 16 | int bitcount(unsigned x) { 17 | 18 | int b; 19 | 20 | for (b = 0; x != 0; x &= (x - 1)) 21 | b++; 22 | 23 | return b; 24 | } 25 | -------------------------------------------------------------------------------- /Exercise 3-1/binsearch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Adjust MAXSIZE to your computer's capacities 4 | #define MAXSIZE 600000000 5 | 6 | int binsearch(int x, int v[], int n); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | 11 | static int v[MAXSIZE]; //allocate array on the heap by making it static 12 | int x = MAXSIZE; // not in the array - out of bounds 13 | int r, i; 14 | 15 | for (i = 0; i < MAXSIZE; i++) 16 | v[i] = i; 17 | 18 | r = binsearch(x, v, MAXSIZE); 19 | printf("Element at position: %d\n", r); 20 | 21 | return 0; 22 | } 23 | 24 | int binsearch(int x, int v[], int n) { 25 | 26 | int low, high, mid; 27 | 28 | low = 0; 29 | high = n - 1; 30 | 31 | while (low <= high) { 32 | mid = (low + high) / 2; 33 | if (x < v[mid]) 34 | high = mid - 1; 35 | else if (x > v[mid]) 36 | low = mid + 1; 37 | else 38 | return mid; 39 | } 40 | return -1; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /Exercise 3-1/binsearch2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Adjust MAXSIZE to your computer's capacities 4 | #define MAXSIZE 600000000 5 | 6 | int binsearch2(int x, int v[], int n); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | static int v[MAXSIZE]; //allocate array on the heap by making it static 11 | int x = MAXSIZE; // not in the array - out of bounds 12 | int r, i; 13 | 14 | for (i = 0; i < MAXSIZE; i++) 15 | v[i] = i; 16 | 17 | r = binsearch2(x, v, MAXSIZE); 18 | printf("Element at position: %d\n", r); 19 | 20 | return 0; 21 | } 22 | 23 | 24 | int binsearch2(int x, int v[], int n) { 25 | 26 | int low, high, mid; 27 | 28 | low = 0; 29 | high = n - 1; 30 | 31 | while (low < high) { 32 | mid = ((low + high) / 2) + 1; 33 | if (x < v[mid]) 34 | high = mid - 1; 35 | else 36 | low = mid; 37 | } 38 | 39 | return x == v[low] ? low : -1; 40 | 41 | } 42 | -------------------------------------------------------------------------------- /Exercise 3-2/escape.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | #define TEXT 0 6 | #define ESCAPE 1 7 | 8 | char STATUS = TEXT; 9 | 10 | void escape(char s[], char t[]); 11 | void descape(char s[], char t[]); 12 | 13 | int main(int argc, char** argv) { 14 | 15 | char t[MAXLINE] = "This is a small test.\n\tIt contains \"\'\\ escaped \n\t characters.\n"; 16 | char s[MAXLINE] = "Before test"; 17 | 18 | printf("%s\n", t); 19 | escape(s, t); 20 | printf("%s\n", s); 21 | descape(t, s); 22 | printf("%s\n", t); 23 | 24 | return 0; 25 | } 26 | 27 | void escape(char s[], char t[]) { 28 | 29 | int i, j; 30 | 31 | for (i = 0, j = 0; t[i] != '\0'; i++) { 32 | switch (t[i]) { 33 | case '\n': 34 | s[j++] = '\\'; 35 | s[j++] = 'n'; 36 | break; 37 | case '\t': 38 | s[j++] = '\\'; 39 | s[j++] = 't'; 40 | break; 41 | default: 42 | s[j++] = t[i]; 43 | break; 44 | } 45 | } 46 | s[j] = '\0'; 47 | } 48 | 49 | void descape(char s[], char t[]) { 50 | 51 | int i, j; 52 | 53 | for (i = 0, j = 0; t[i] != '\0'; i++) { 54 | switch (STATUS) { 55 | case TEXT: 56 | if (t[i] == '\\') STATUS = ESCAPE; 57 | else s[j++] = t[i]; 58 | break; 59 | case ESCAPE: 60 | if (t[i] == 'n') s[j++] = '\n'; 61 | else if (t[i] == 't') s[j++] = '\t'; 62 | else s[j++] = t[--i]; 63 | STATUS = TEXT; 64 | break; 65 | } 66 | } 67 | s[j] = '\0'; 68 | } 69 | -------------------------------------------------------------------------------- /Exercise 3-3/expand.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | void expand(char s1[], char s2[]); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | char s1[MAXLINE] = "This is a simple test for -a-z (leading minus) and\n0-9-(trailing minus) and\na-n-z or\nsimpler a-b-c\nor even a-z0-9.\n"; 10 | char s2[MAXLINE]; 11 | 12 | printf("%s\n", s1); 13 | expand(s1, s2); 14 | printf("%s\n", s2); 15 | 16 | return 0; 17 | } 18 | 19 | void expand(char s1[], char s2[]) { 20 | 21 | int i, j, k, start, end; 22 | 23 | for (i = 0, j = 0; s1[i] != '\0'; i++) { 24 | if (s1[i] == '-' && isalnum(s1[i - 1]) && isalnum(s1[i + 1])) { 25 | start = s1[i - 1], end = s1[++i]; 26 | for (k = start + 1; k <= end; k++) 27 | s2[j++] = k; 28 | } else 29 | s2[j++] = s1[i]; 30 | } 31 | 32 | s2[j] = '\0'; 33 | } 34 | -------------------------------------------------------------------------------- /Exercise 3-4/itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 100 4 | 5 | void reverse(char s[]); 6 | void itoa(int n, char s[]); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | char s[MAXLINE]; 11 | int n = -2147483648; 12 | 13 | itoa(n, s); 14 | printf("%s\n", s); 15 | 16 | return 0; 17 | } 18 | 19 | void itoa(int n, char s[]) { 20 | 21 | int i, sign; 22 | 23 | sign = n; 24 | 25 | i = 0; 26 | do { 27 | s[i++] = abs(n % 10) + '0'; 28 | } while (n /= 10); 29 | 30 | if (sign < 0) 31 | s[i++] = '-'; 32 | 33 | s[i] = '\0'; 34 | 35 | reverse(s); 36 | } 37 | 38 | void reverse(char s[]) { 39 | 40 | int i; 41 | int length = 0; 42 | 43 | for (i = 0; s[i] != '\0'; i++) 44 | length++; 45 | 46 | char temp[length]; 47 | for (i = 0; i < length; i++) 48 | temp[i] = s[i]; 49 | 50 | for (i = 0; i < length; i++) 51 | s[i] = temp[length - 1 - i]; 52 | 53 | } 54 | -------------------------------------------------------------------------------- /Exercise 3-5/itob.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 100 4 | 5 | void reverse(char s[]); 6 | void itob(int n, char s[], int b); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | char s[MAXLINE]; 11 | int n = 26; 12 | printf("Number in decimal: %d\n", n); 13 | 14 | int b = 16; 15 | itob(n, s, b); 16 | printf("Number in base %d: %s\n", b, s); 17 | 18 | b = 2; 19 | itob(n, s, b); 20 | printf("Number in base %d: %s\n", b, s); 21 | 22 | return 0; 23 | } 24 | 25 | void itob(int n, char s[], int b) { 26 | 27 | int i, sign; 28 | 29 | sign = n; 30 | 31 | i = 0; 32 | do { 33 | char x = abs(n % b); 34 | if (x < 10) 35 | x = x + '0'; 36 | else 37 | x = x - 10 + 'A'; 38 | s[i++] = x; 39 | } while (n /= b); 40 | 41 | if (sign < 0) 42 | s[i++] = '-'; 43 | 44 | s[i] = '\0'; 45 | 46 | reverse(s); 47 | } 48 | 49 | void reverse(char s[]) { 50 | 51 | int i; 52 | int length = 0; 53 | 54 | for (i = 0; s[i] != '\0'; i++) 55 | length++; 56 | 57 | char temp[length]; 58 | for (i = 0; i < length; i++) 59 | temp[i] = s[i]; 60 | 61 | for (i = 0; i < length; i++) 62 | s[i] = temp[length - 1 - i]; 63 | 64 | } 65 | -------------------------------------------------------------------------------- /Exercise 3-6/itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 100 4 | 5 | void reverse(char s[]); 6 | void itoa(int n, char s[], int p); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | char s[MAXLINE]; 11 | int n = 26; 12 | 13 | itoa(n, s, 10); 14 | printf(":%s:\n", s); 15 | 16 | return 0; 17 | } 18 | 19 | void itoa(int n, char s[], int p) { 20 | 21 | int i, sign, count; 22 | 23 | sign = n; 24 | 25 | i = 0; 26 | count = 0; 27 | do { 28 | s[i++] = abs(n % 10) + '0'; 29 | count++; 30 | } while (n /= 10); 31 | 32 | if (sign < 0) 33 | s[i++] = '-', count++; 34 | 35 | for (; count < p; count++) 36 | s[i++] = ' '; 37 | 38 | s[i] = '\0'; 39 | 40 | reverse(s); 41 | } 42 | 43 | void reverse(char s[]) { 44 | 45 | int i; 46 | int length = 0; 47 | 48 | for (i = 0; s[i] != '\0'; i++) 49 | length++; 50 | 51 | char temp[length]; 52 | for (i = 0; i < length; i++) 53 | temp[i] = s[i]; 54 | 55 | for (i = 0; i < length; i++) 56 | s[i] = temp[length - 1 - i]; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /Exercise 4-1/strindex.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | 5 | int get_line(char line[], int max); 6 | int strindex(char source[], char searchfor[]); 7 | int strrindex(char source[], char searchfor[]); 8 | 9 | char pattern[] = "ould"; 10 | 11 | int main(int argc, char** argv) { 12 | 13 | char line[MAXLINE]; 14 | int found = 0; 15 | int pos; 16 | 17 | while (get_line(line, MAXLINE) > 0) 18 | if ((pos = strrindex(line, pattern)) >= 0) { 19 | printf("Position: %d\n", pos); 20 | printf("%s", line); 21 | found++; 22 | } 23 | 24 | return found; 25 | } 26 | 27 | int get_line(char s[], int lim) { 28 | 29 | int c, i; 30 | 31 | i = 0; 32 | while (--lim > 0 && (c = getchar()) != EOF && c != '\n') 33 | s[i++] = c; 34 | if (c == '\n') 35 | s[i++] = c; 36 | s[i] = '\0'; 37 | 38 | return i; 39 | } 40 | 41 | int strindex(char s[], char t[]) { 42 | 43 | int i, j, k; 44 | 45 | for (i = 0; s[i] != '\0'; i++) { 46 | for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++) 47 | ; 48 | if (k > 0 && t[k] == '\0') 49 | return i; 50 | } 51 | 52 | return -1; 53 | } 54 | 55 | int strrindex(char s[], char t[]) { 56 | 57 | int i, j, k, length; 58 | 59 | length = 0; 60 | while (s[length++] != '\0') 61 | ; 62 | 63 | for (i = length - 1; i >= 0; i--) { 64 | for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; j++, k++) 65 | ; 66 | if (k > 0 && t[k] == '\0') 67 | return i; 68 | } 69 | 70 | return -1; 71 | } 72 | -------------------------------------------------------------------------------- /Exercise 4-11/calc.h: -------------------------------------------------------------------------------- 1 | #define NUMBER '0' /* signal that a number was found */ 2 | #define SINUS '~' 3 | #define EXP '\"' 4 | #define POW '^' 5 | #define PRINT '?' 6 | #define DUPL ':' 7 | #define SWAP '#' 8 | #define CLEAR '_' 9 | #define SET_VAR '8' // capital characters set values 10 | #define GET_VAR '9' // small characters read values 11 | 12 | #define ALPHA 26 13 | 14 | int getch(void); 15 | int getop(char []); 16 | void push(double); 17 | double pop(void); 18 | double top(void); 19 | void swap(void); 20 | void clear(void); 21 | -------------------------------------------------------------------------------- /Exercise 4-11/calc.h.gch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Elyasin/K-and-R-solutions/b8e530c680e864352beead39ae73e5eb5fc2a31d/Exercise 4-11/calc.h.gch -------------------------------------------------------------------------------- /Exercise 4-11/getch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define BUFSIZE 100 4 | 5 | char buf[BUFSIZE]; /* buffer for ungetch */ 6 | int bufp = 0; /* next free position in buffer */ 7 | 8 | 9 | int getch(void) /* get a (possibly pushed back) character */ { 10 | 11 | return (bufp > 0) ? buf[--bufp] : getchar(); 12 | 13 | } 14 | 15 | -------------------------------------------------------------------------------- /Exercise 4-11/getop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "calc.h" 4 | 5 | 6 | /* getop: get next operator or numeric operand */ 7 | int getop(char s[]) { 8 | int i, c; 9 | 10 | /* use static internal variable as buffer */ 11 | static int c_buf = 0; 12 | 13 | if (c_buf == 0) 14 | c = getch(); 15 | else { 16 | c = c_buf; 17 | c_buf = 0; 18 | } 19 | 20 | while ((s[0] = c) == ' ' || c == '\t') 21 | c = getch(); 22 | s[1] = '\0'; 23 | 24 | if ('A' <= c && c <= 'Z') 25 | return SET_VAR; 26 | if ('a' <= c && c <= 'z') 27 | return GET_VAR; 28 | 29 | if (!isdigit(c) && c != '.' && c != '-') 30 | return c; 31 | if (c == '-') { // possible negative number 32 | if (!isdigit(s[0] = c = getch())) { // minus operator 33 | if (c != EOF) 34 | c_buf = c; 35 | s[0] = c = '-'; 36 | return c; 37 | } else { // negative number 38 | s[0] = '-'; 39 | s[1] = c; 40 | i = 1; 41 | } 42 | } else 43 | i = 0; // positive number 44 | if (isdigit(c)) /* collect integer part */ 45 | while (isdigit(s[++i] = c = getch())) 46 | ; 47 | if (c == '.') /* collect fraction part */ 48 | while (isdigit(s[++i] = c = getch())) 49 | ; 50 | s[i] = '\0'; 51 | if (c != EOF) 52 | c_buf = c; 53 | 54 | return NUMBER; 55 | } 56 | -------------------------------------------------------------------------------- /Exercise 4-11/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* for atof */ 3 | #include 4 | #include 5 | #include "calc.h" 6 | 7 | #define MAXOP 100 /* max size of operand or operator */ 8 | 9 | /* reverse Polish calculator */ 10 | main() { 11 | int type, i; 12 | double op2; 13 | char s[MAXOP]; 14 | double var[ALPHA]; 15 | 16 | for (i = 0; i < ALPHA; i++) 17 | var[i] = 0.0; 18 | 19 | while ((type = getop(s)) != EOF) { 20 | switch (type) { 21 | case NUMBER: 22 | push(atof(s)); 23 | break; 24 | case SET_VAR: // set the variable to stack's top value 25 | op2 = top(); 26 | var[s[0] - 'A'] = op2; 27 | break; 28 | case GET_VAR: // replace variable by its value 29 | push(var[s[0] - 'a']); 30 | break; 31 | case '+': 32 | push(pop() + pop()); 33 | break; 34 | case '*': 35 | push(pop() * pop()); 36 | break; 37 | case '-': 38 | op2 = pop(); 39 | push(pop() - op2); 40 | break; 41 | case '/': 42 | op2 = pop(); 43 | if (op2 != 0.0) 44 | push(pop() / op2); 45 | else 46 | printf("error: zero divisor\n"); 47 | break; 48 | case '%': 49 | op2 = pop(); 50 | if (op2 != 0.0) 51 | push((int) pop() % (int) op2); 52 | else 53 | printf("error: zero divisor\n"); 54 | break; 55 | case SINUS: 56 | push(sin(pop())); 57 | break; 58 | case EXP: 59 | op2 = exp(pop()); 60 | if (op2 != HUGE_VAL && op2 != -HUGE_VAL && errno != ERANGE) 61 | push(op2); 62 | else 63 | printf("range error: result is out of range: %g\n", op2), errno = 0; 64 | break; 65 | case POW: 66 | op2 = pop(); 67 | op2 = pow(op2, pop()); 68 | if (errno == EDOM) 69 | printf("domain error: see domain of pow function\n"), errno = 0; 70 | else if (errno == ERANGE && (op2 == HUGE_VAL || op2 == -HUGE_VAL)) 71 | printf("range error: result is out of range: %g\n", op2), errno = 0; 72 | else 73 | push(op2); 74 | break; 75 | case PRINT: 76 | printf("\t%.8g\n", top()); 77 | break; 78 | case DUPL: 79 | push(top()); 80 | break; 81 | case SWAP: 82 | swap(); 83 | break; 84 | case CLEAR: 85 | clear(); 86 | break; 87 | case '\n': 88 | printf("\t%.8g\n", var['r' - 'a'] = pop()); 89 | break; 90 | default: 91 | printf("error: unknown command %s\n", s); 92 | break; 93 | } 94 | 95 | } 96 | return 0; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /Exercise 4-11/stack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "calc.h" 3 | 4 | #define MAXVAL 100 /* maximum depth of val stack */ 5 | 6 | int sp = 0; 7 | /* next free stack position */ 8 | double val[MAXVAL]; 9 | /* value stack */ 10 | 11 | /* push: push f onto value stack */ 12 | void push(double f) { 13 | if (sp < MAXVAL) 14 | val[sp++] = f; 15 | else 16 | printf("error: stack full, can′t push %g\n", f); 17 | } 18 | 19 | /* pop: pop and return top value from stack */ 20 | double pop(void) { 21 | if (sp > 0) 22 | return val[--sp]; 23 | else { 24 | printf("error: stack empty\n"); 25 | return 0.0; 26 | } 27 | } 28 | 29 | /* top: return top value from stack */ 30 | double top(void) { 31 | if (sp > 0) { 32 | return val[sp - 1]; 33 | } else { 34 | printf("error: stack empty\n"); 35 | return 0.0; 36 | } 37 | } 38 | 39 | /* swap two top values */ 40 | void swap(void) { 41 | if (sp > 1) { 42 | double t1 = pop(); 43 | double t2 = pop(); 44 | push(t1); 45 | push(t2); 46 | } else 47 | printf("error: stack empty or not enough values\n"); 48 | } 49 | 50 | /* clear the stack */ 51 | void clear(void) { 52 | sp = 0; 53 | } 54 | -------------------------------------------------------------------------------- /Exercise 4-12/itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINE 20 5 | 6 | void itoa(int n, char s[]); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | int n; 11 | char s[MAXLINE]; 12 | 13 | n = -2147483648; 14 | itoa(n, s); 15 | printf("%s\n", s); 16 | n = 2147483647; 17 | itoa(n, s); 18 | printf("%s\n", s); 19 | 20 | return 0; 21 | } 22 | 23 | 24 | void itoa(int n, char s[]) { 25 | 26 | int static i = 0; 27 | 28 | if (n / 10) 29 | itoa(n / 10, s); 30 | else { 31 | i = 0; 32 | if (n < 0) 33 | s[i++] = '-'; 34 | } 35 | 36 | s[i++] = abs(n % 10) + '0'; 37 | s[i] = '\0'; 38 | } 39 | -------------------------------------------------------------------------------- /Exercise 4-13/reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void reverse(char s[]); 5 | 6 | int main(int argc, char** argv) { 7 | 8 | char s[] = ".esrever rof tset elpmis a si sihT"; 9 | char t[] = "KO"; 10 | 11 | printf("Reversing '%s': ", s); 12 | reverse(s); 13 | printf("%s\n", s); 14 | printf("Reversing '%s': ", t); 15 | reverse(t); 16 | printf("%s\n", t); 17 | 18 | return 0; 19 | } 20 | 21 | void reverse(char s[]) { 22 | 23 | char c1, c2; 24 | int len = strlen(s); 25 | 26 | if (len < 2) 27 | return; 28 | 29 | c1 = s[0]; 30 | c2 = s[len - 1]; 31 | s[len - 1] = '\0'; 32 | reverse(s + 1); 33 | s[0] = c2; 34 | s[len - 1] = c1; 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Exercise 4-14/swap.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define swap(t,x,y) { t var_t; var_t = x; x = y; y = var_t; } 4 | main() { 5 | 6 | int i1 = 1, i2 = 2; 7 | float f1 = 0.1, f2 = 0.2; 8 | double d1 = 1.1, d2 = 9.9; 9 | 10 | printf("Before: %d, %d\n", i1, i2); 11 | swap(int, i1, i2); 12 | printf("Swapped: %d, %d\n", i1, i2); 13 | 14 | printf("Before: %f, %f\n", f1, f2); 15 | swap(float, f1, f2); 16 | printf("Swapped: %f, %f\n", f1, f2); 17 | 18 | printf("Before: %lf, %lf\n", d1, d2); 19 | swap(double, d1, d2); 20 | printf("Swapped: %lf, %lf\n", d1, d2); 21 | 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /Exercise 4-2/atof.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 100 4 | 5 | double a_to_f(char s[]); 6 | 7 | main() { 8 | 9 | char s[MAXLINE] = "-1.95e-2"; 10 | printf("Converting %s\n", s); 11 | 12 | double d = a_to_f(s); 13 | printf("%g\n", d); 14 | 15 | return 0; 16 | } 17 | 18 | #include 19 | 20 | /* atof: convert string s to double */ 21 | double a_to_f(char s[]) { 22 | 23 | double val, power, exp_val; 24 | int i, j, sign, exp_sign, exp_int; 25 | 26 | for (i = 0; isspace(s[i]); i++) /* skip white space */ 27 | ; 28 | sign = (s[i] == '-') ? -1 : 1; 29 | if (s[i] == '+' || s[i] == '-') 30 | i++; 31 | for (val = 0.0; isdigit(s[i]); i++) 32 | val = 10.0 * val + (s[i] - '0'); 33 | if (s[i] == '.') 34 | i++; 35 | for (power = 1.0; isdigit(s[i]); i++) { 36 | val = 10.0 * val + (s[i] - '0'); 37 | power *= 10.0; 38 | } 39 | 40 | if (s[i] == 'e' || s[i] == 'E') 41 | i++; 42 | exp_sign = (s[i] == '-') ? -1 : 1; 43 | if (s[i] == '+' || s[i] == '-') 44 | i++; 45 | for (exp_int = 0; isdigit(s[i]); i++) 46 | exp_int = 10 * exp_int + (s[i] - '0'); 47 | if (exp_sign == -1) 48 | for (j = 0, exp_val = 1; j < exp_int; j++) 49 | exp_val /= 10.0; 50 | else 51 | for (j = 0, exp_val = 1; j < exp_int; j++) 52 | exp_val *= 10.0; 53 | 54 | return sign * val / power * exp_val; 55 | } 56 | -------------------------------------------------------------------------------- /Exercise 4-3/calculator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* for atof */ 3 | 4 | #define MAXOP 100 /* max size of operand or operator */ 5 | #define NUMBER '0' /* signal that a number was found */ 6 | 7 | int getop(char []); 8 | void push(double); 9 | double pop(void); 10 | 11 | /* reverse Polish calculator */ 12 | main() { 13 | int type; 14 | double op2; 15 | char s[MAXOP]; 16 | 17 | while ((type = getop(s)) != EOF) { 18 | switch (type) { 19 | case NUMBER: 20 | push(atof(s)); 21 | break; 22 | case '+': 23 | push(pop() + pop()); 24 | break; 25 | case '*': 26 | push(pop() * pop()); 27 | break; 28 | case '-': 29 | op2 = pop(); 30 | push(pop() - op2); 31 | break; 32 | case '/': 33 | op2 = pop(); 34 | if (op2 != 0.0) 35 | push(pop() / op2); 36 | else 37 | printf("error: zero divisor\n"); 38 | break; 39 | case '%': 40 | op2 = pop(); 41 | if (op2 != 0.0) 42 | push((int) pop() % (int) op2); 43 | else 44 | printf("error: zero divisor\n"); 45 | 46 | break; 47 | case '\n': 48 | printf("\t%.8g\n", pop()); 49 | break; 50 | default: 51 | printf("error: unknown command %s\n", s); 52 | break; 53 | 54 | } 55 | 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | 62 | #define MAXVAL 100 /* maximum depth of val stack */ 63 | 64 | int sp = 0; 65 | /* next free stack position */ 66 | double val[MAXVAL]; 67 | /* value stack */ 68 | 69 | /* push: push f onto value stack */ 70 | void push(double f) { 71 | if (sp < MAXVAL) 72 | val[sp++] = f; 73 | else 74 | printf("error: stack full, can′t push %g\n", f); 75 | } 76 | 77 | /* pop: pop and return top value from stack */ 78 | double pop(void) { 79 | if (sp > 0) 80 | return val[--sp]; 81 | else { 82 | printf("error: stack empty\n"); 83 | return 0.0; 84 | 85 | } 86 | } 87 | 88 | 89 | #include 90 | 91 | int getch(void); 92 | void ungetch(int); 93 | 94 | /* getop: get next operator or numeric operand */ 95 | int getop(char s[]) { 96 | int i, c; 97 | 98 | while ((s[0] = c = getch()) == ' ' || c == '\t') 99 | ; 100 | s[1] = '\0'; 101 | if (!isdigit(c) && c != '.' && c != '-') 102 | return c; 103 | if (c == '-') { // possible negative number 104 | if (!isdigit(s[0] = c = getch())) { // minus operator 105 | if (c != EOF) 106 | ungetch(c); 107 | s[0] = c = '-'; 108 | return c; 109 | } else { // negative number 110 | s[0] = '-'; 111 | s[1] = c; 112 | i = 1; 113 | } 114 | } else 115 | i = 0; // positive number 116 | if (isdigit(c)) /* collect integer part */ 117 | while (isdigit(s[++i] = c = getch())) 118 | ; 119 | if (c == '.') /* collect fraction part */ 120 | while (isdigit(s[++i] = c = getch())) 121 | ; 122 | s[i] = '\0'; 123 | if (c != EOF) 124 | ungetch(c); 125 | 126 | return NUMBER; 127 | } 128 | 129 | #define BUFSIZE 100 130 | 131 | char buf[BUFSIZE]; /* buffer for ungetch */ 132 | int bufp = 0; /* next free position in buf */ 133 | 134 | int getch(void) /* get a (possibly pushed back) character */ { 135 | return (bufp > 0) ? buf[--bufp] : getchar(); 136 | } 137 | 138 | void ungetch(int c) /* push character back on input */ { 139 | if (bufp >= BUFSIZE) 140 | printf("ungetch: too many characters\n"); 141 | else 142 | buf[bufp++] = c; 143 | } 144 | -------------------------------------------------------------------------------- /Exercise 4-7/ungets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINE 1000 5 | 6 | int getch(void); 7 | void ungetch(int); 8 | void ungets(char*); 9 | 10 | main() { 11 | 12 | int i, c; 13 | char s[MAXLINE]; 14 | char t[MAXLINE]; 15 | 16 | i = 0; 17 | while ((s[i++] = getch()) != '\n') 18 | ; 19 | s[i] = '\0'; 20 | 21 | printf("Reading: %s", s); 22 | ungets(s); 23 | printf("ungets called\n"); 24 | i = 0; 25 | while ((t[i++] = getch()) != '\n') 26 | ; 27 | printf("Reading again: %s", s); 28 | 29 | return 0; 30 | } 31 | 32 | 33 | #define BUFSIZE 100 34 | 35 | char buf[BUFSIZE]; /* buffer for ungets */ 36 | int bufp = 0; /* next free position in buf */ 37 | 38 | int getch(void) { 39 | return (bufp > 0) ? buf[--bufp] : getchar(); 40 | } 41 | 42 | void ungetch(int c) { 43 | if (bufp >= BUFSIZE) 44 | printf("ungetch: too many characters\n"); 45 | else 46 | buf[bufp++] = c; 47 | } 48 | 49 | void ungets(char s[]) { 50 | int len; 51 | 52 | len = strlen(s); 53 | 54 | for (;len > 0;) 55 | ungetch(s[--len]); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /Exercise 4-8/ungetch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int getch(void); 4 | void ungetch(int); 5 | 6 | main() { 7 | 8 | int c, p; 9 | 10 | printf("Type in one character: "); 11 | c = getch(); 12 | printf("Reading: %c\n", c); 13 | ungetch(c); 14 | printf("ungetch called\n"); 15 | printf("Reading again: %c\n", getch()); 16 | 17 | return 0; 18 | } 19 | 20 | 21 | char b = 0; /* push back character for ungetch */ 22 | 23 | int getch(void) /* get a (possibly pushed back) character */ { 24 | if (b == 0) 25 | getchar(); 26 | else { 27 | int c = b; 28 | b = 0; 29 | return c; 30 | } 31 | } 32 | 33 | void ungetch(int c) /* push character back on input */ { 34 | if (b != 0) 35 | printf("ungetch: too many characters\n"); 36 | else 37 | b = c; 38 | } 39 | 40 | 41 | -------------------------------------------------------------------------------- /Exercise 4-9/ungetch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int getch(void); 4 | void ungetch(int); 5 | 6 | main() { 7 | 8 | int c, p; 9 | 10 | printf("Type Ctrl-d\n"); 11 | c = getch(); 12 | printf("Reading: %d\n", c); 13 | ungetch(c); 14 | printf("ungetch called\n"); 15 | printf("Reading again: %d\n", getch()); 16 | 17 | return 0; 18 | } 19 | 20 | 21 | 22 | #define BUFSIZE 100 23 | 24 | int buf[BUFSIZE]; /* buffer for ungetch */ 25 | int bufp = 0; /* next free position in buf */ 26 | 27 | int getch(void) /* get a (possibly pushed back) character */ { 28 | return (bufp > 0) ? buf[--bufp] : getchar(); 29 | } 30 | 31 | void ungetch(int c) /* push character back on input */ { 32 | if (bufp >= BUFSIZE) 33 | printf("ungetch: too many characters\n"); 34 | else 35 | buf[bufp++] = c; 36 | } 37 | 38 | 39 | -------------------------------------------------------------------------------- /Exercise 5-1/getint.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SIZE 10 4 | 5 | void ungetch(int c); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | int n, array[SIZE], getint(int*); 10 | 11 | for (n=0; n < SIZE && getint(&array[n]) != EOF; n++) 12 | printf("%d\n", array[n]); 13 | 14 | return 0; 15 | } 16 | 17 | 18 | #include 19 | 20 | int getint(int *pn); 21 | int getch(void); 22 | 23 | /* getint: get next integer from input into *pn */ 24 | int getint(int *pn) { 25 | 26 | int c, sign; 27 | 28 | while (isspace(c = getch())) /* skip white space */ 29 | ; 30 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 31 | ungetch(c); /*it's not a number */ 32 | return 0; 33 | } 34 | sign = (c == '-') ? -1 : 1; 35 | if (c == '+' || c == '-') { 36 | int ch = getch(); 37 | if (!isdigit(ch)) { 38 | if (ch != EOF) 39 | ungetch(ch); 40 | ungetch(c); 41 | return c; 42 | } 43 | c = ch; 44 | } 45 | for (*pn = 0; isdigit(c); c = getch()) 46 | *pn = 10 * *pn + (c - '0'); 47 | *pn *= sign; 48 | if (c != EOF) 49 | ungetch(c); 50 | return c; 51 | } 52 | 53 | 54 | #define BUFSIZE 100 55 | 56 | char buf[BUFSIZE]; /* buffer for ungetch */ 57 | int bufp = 0; /* next free position in buf */ 58 | 59 | int getch(void) /* get a (possibly pushed back) character */ { 60 | return (bufp > 0) ? buf[--bufp] : getchar(); 61 | } 62 | 63 | void ungetch(int c) /* push character back on input */ { 64 | if (bufp >= BUFSIZE) 65 | printf("ungetch: too many characters\n"); 66 | else 67 | buf[bufp++] = c; 68 | } 69 | -------------------------------------------------------------------------------- /Exercise 5-10/expr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* for atof() */ 3 | 4 | #define MAXOP 100 /* max size of operand or operator */ 5 | #define NUMBER '0' /* signal that a number was found */ 6 | 7 | int getop(char []); 8 | void push(double); 9 | double pop(void); 10 | 11 | /* reverse Polish calculator */ 12 | int main(int argc, char *argv[]) { 13 | int type, i; 14 | double op2; 15 | char s[MAXOP]; 16 | 17 | if (argc == 1) 18 | return 0; 19 | 20 | i = 1; 21 | while (argv[i] != NULL) { 22 | 23 | type = getop(argv[i]); 24 | 25 | switch (type) { 26 | case NUMBER: 27 | push(atof(argv[i])); 28 | break; 29 | case '+': 30 | push(pop() + pop()); 31 | break; 32 | case '*': 33 | push(pop() * pop()); 34 | break; 35 | case '-': 36 | op2 = pop(); 37 | push(pop() - op2); 38 | break; 39 | case '/': 40 | op2 = pop(); 41 | if (op2 != 0.0) 42 | push(pop() / op2); 43 | else 44 | printf("error: zero divisor\n"); 45 | break; 46 | default: 47 | printf("error: unknown command %s\n", s); 48 | break; 49 | } 50 | i++; 51 | } 52 | 53 | printf("\t%.8g\n", pop()); 54 | 55 | return 0; 56 | } 57 | 58 | #define MAXVAL 100 /* maximum depth of val stack */ 59 | 60 | int sp = 0; /* next free stack position */ 61 | double val[MAXVAL]; /* value stack */ 62 | 63 | /* push: push f onto value stack */ 64 | void push(double f) { 65 | if (sp < MAXVAL) 66 | val[sp++] = f; 67 | else 68 | printf("error: stack full, can't push %g\n", f); 69 | } 70 | 71 | /* pop: pop and return top value from stack */ 72 | double pop(void) { 73 | if (sp > 0) 74 | return val[--sp]; 75 | else { 76 | printf("error: stack empty\n"); 77 | return 0.0; 78 | } 79 | } 80 | 81 | /* getop: get next operator or numeric operand */ 82 | int getop(char s[]) { 83 | if (isdigit(s[0]) || (s[0] == '-' && s[1] != '\0')) 84 | /* number */ 85 | return NUMBER; 86 | else 87 | /* not a number */ 88 | return s[0]; 89 | } 90 | -------------------------------------------------------------------------------- /Exercise 5-11/detab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | void settab(int argc, char *argv[], char *tab); 9 | int tabpos(int pos, char *tab); 10 | int get_line(char line[], int maxline); 11 | void detab(char to[], char from[]); 12 | 13 | char tab[MAXLINE]; 14 | 15 | main(int argc, char *argv[]) { 16 | int len; 17 | char line[MAXLINE]; 18 | char detabbed_line[MAXLINE]; 19 | 20 | settab(argc, argv, tab); 21 | 22 | while ((len = get_line(line, MAXLINE)) > 0) { 23 | detab(detabbed_line, line); 24 | printf("%s", detabbed_line); 25 | } 26 | return 0; 27 | } 28 | 29 | int get_line(char s[], int lim) { 30 | int c, i; 31 | 32 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 33 | s[i] = c; 34 | if (c == '\n') s[i++] = c; 35 | s[i] = '\0'; 36 | return i; 37 | } 38 | 39 | void detab(char to[], char from[]) { 40 | int c, i, k, pos, spaces; 41 | 42 | pos = 0; 43 | for (i = 0, k = 0; (c = from[i]) != EOF && c != '\n'; ++i, ++k) { 44 | if (c == '\t') { 45 | do 46 | to[k++] = ' '; 47 | while (tabpos(++pos, tab) == NO); 48 | k--; 49 | } else { 50 | to[k] = c; 51 | ++pos; 52 | } 53 | } 54 | if (c == '\n') 55 | to[k++] = c; 56 | to[k] = '\0'; 57 | } 58 | -------------------------------------------------------------------------------- /Exercise 5-11/entab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | void settab(int argc, char *argv[], char *tab); 9 | int tabpos(int pos, char *tab); 10 | int get_line(char line[], int maxline); 11 | void entab(char to[], char from[]); 12 | 13 | char tab[MAXLINE]; 14 | 15 | main(int argc, char *argv[]) { 16 | int len; 17 | char line[MAXLINE]; 18 | char entabbed_line[MAXLINE]; 19 | 20 | settab(argc, argv, tab); 21 | 22 | while ((len = get_line(line, MAXLINE)) > 0) { 23 | entab(entabbed_line, line); 24 | printf("%s", entabbed_line); 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | int get_line(char s[], int lim) { 31 | int c, i; 32 | 33 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 34 | s[i] = c; 35 | if (c == '\n') s[i++] = c; 36 | s[i] = '\0'; 37 | return i; 38 | } 39 | 40 | void entab(char to[], char from[]) { 41 | int c, i, j, tabs, spaces, pos; 42 | 43 | spaces = tabs = 0; 44 | for (i = j = pos = 0; (c = from[i]) != EOF && c != '\n'; i++, pos++) { 45 | if (c == ' ') { 46 | //if ((pos + 1) % TABSTOP == 0) { 47 | if ( tabpos(pos+1, tab) == YES ) { 48 | tabs++; 49 | spaces = 0; 50 | } else { 51 | spaces++; 52 | } 53 | } 54 | if (c != ' ') { 55 | for (; tabs > 0; tabs--, j++) 56 | to[j] = '\t'; 57 | tabs = 0; 58 | if (c == '\t') { 59 | spaces = 0; 60 | //pos = pos + (TABSTOP - pos % TABSTOP) - 1; 61 | for ( ; tab[pos+1] != YES; pos++, j++) { 62 | to[j] = ' '; 63 | } 64 | } 65 | for (; spaces > 0; spaces--, j++) 66 | to[j] = ' '; 67 | to[j++] = c; 68 | } 69 | } 70 | if (c == '\n') { 71 | to[j++] = c; 72 | } 73 | to[j] = '\0'; 74 | } 75 | -------------------------------------------------------------------------------- /Exercise 5-11/lorem_ipsum_detab.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, 2 | consetetur sadipscing elitr, sed diam nonumy eirmod 3 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 4 | At vero eos et accusam et justo duo dolores et ea rebum. 5 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 6 | 7 | -------------------------------------------------------------------------------- /Exercise 5-11/lorem_ipsum_entab.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, 2 | consetetur sadipscing elitr, sed diam nonumy eirmod 3 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 4 | At vero eos et accusam et justo duo dolores et ea rebum. 5 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 6 | 7 | -------------------------------------------------------------------------------- /Exercise 5-11/settab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | 9 | void settab(int argc, char *argv[], char *tab) { 10 | 11 | int i, pos; 12 | 13 | if (argc <= 1) 14 | for (i = 1; i < MAXLINE; i++) 15 | if ( i % TABSTOP == 0) 16 | tab[i] = YES; 17 | else 18 | tab[i] = NO; 19 | else { 20 | for (i = 1; i < MAXLINE; i++) 21 | tab[i] = NO; 22 | while (--argc > 0) { 23 | pos = atoi(*++argv); 24 | if ( pos > 0 && pos <= MAXLINE) 25 | tab[pos] = YES; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Exercise 5-11/tabpos.c: -------------------------------------------------------------------------------- 1 | #define MAXLINE 1000 2 | #define YES 1 3 | 4 | int tabpos(int pos, char *tab) { 5 | 6 | if (pos >= MAXLINE) 7 | return YES; 8 | else 9 | return tab[pos]; 10 | } 11 | -------------------------------------------------------------------------------- /Exercise 5-12/detab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | void settab(int argc, char *argv[], char *tab); 9 | int tabpos(int pos, char *tab); 10 | int get_line(char line[], int maxline); 11 | void detab(char to[], char from[]); 12 | 13 | char tab[MAXLINE]; 14 | 15 | main(int argc, char *argv[]) { 16 | int len; 17 | char line[MAXLINE]; 18 | char detabbed_line[MAXLINE]; 19 | 20 | settab(argc, argv, tab); 21 | 22 | while ((len = get_line(line, MAXLINE)) > 0) { 23 | detab(detabbed_line, line); 24 | printf("%s", detabbed_line); 25 | } 26 | return 0; 27 | } 28 | 29 | int get_line(char s[], int lim) { 30 | int c, i; 31 | 32 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 33 | s[i] = c; 34 | if (c == '\n') s[i++] = c; 35 | s[i] = '\0'; 36 | return i; 37 | } 38 | 39 | void detab(char to[], char from[]) { 40 | int c, i, k, pos, spaces; 41 | 42 | pos = 0; 43 | for (i = 0, k = 0; (c = from[i]) != EOF && c != '\n'; ++i, ++k) { 44 | if (c == '\t') { 45 | do 46 | to[k++] = ' '; 47 | while (tabpos(++pos, tab) == NO); 48 | k--; 49 | } else { 50 | to[k] = c; 51 | ++pos; 52 | } 53 | } 54 | if (c == '\n') 55 | to[k++] = c; 56 | to[k] = '\0'; 57 | } 58 | -------------------------------------------------------------------------------- /Exercise 5-12/entab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | void settab(int argc, char *argv[], char *tab); 9 | int tabpos(int pos, char *tab); 10 | int get_line(char line[], int maxline); 11 | void entab(char to[], char from[]); 12 | 13 | char tab[MAXLINE]; 14 | 15 | main(int argc, char *argv[]) { 16 | int len; 17 | char line[MAXLINE]; 18 | char entabbed_line[MAXLINE]; 19 | 20 | settab(argc, argv, tab); 21 | 22 | while ((len = get_line(line, MAXLINE)) > 0) { 23 | entab(entabbed_line, line); 24 | printf("%s", entabbed_line); 25 | } 26 | 27 | return 0; 28 | } 29 | 30 | int get_line(char s[], int lim) { 31 | int c, i; 32 | 33 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 34 | s[i] = c; 35 | if (c == '\n') s[i++] = c; 36 | s[i] = '\0'; 37 | return i; 38 | } 39 | 40 | void entab(char to[], char from[]) { 41 | int c, i, j, tabs, spaces, pos; 42 | 43 | spaces = tabs = 0; 44 | for (i = j = pos = 0; (c = from[i]) != EOF && c != '\n'; i++, pos++) { 45 | if (c == ' ') { 46 | //if ((pos + 1) % TABSTOP == 0) { 47 | if ( tabpos(pos+1, tab) == YES ) { 48 | tabs++; 49 | spaces = 0; 50 | } else { 51 | spaces++; 52 | } 53 | } 54 | if (c != ' ') { 55 | for (; tabs > 0; tabs--, j++) 56 | to[j] = '\t'; 57 | tabs = 0; 58 | if (c == '\t') { 59 | spaces = 0; 60 | //pos = pos + (TABSTOP - pos % TABSTOP) - 1; 61 | for ( ; tab[pos+1] != YES; pos++, j++) { 62 | to[j] = ' '; 63 | } 64 | } 65 | for (; spaces > 0; spaces--, j++) 66 | to[j] = ' '; 67 | to[j++] = c; 68 | } 69 | } 70 | if (c == '\n') { 71 | to[j++] = c; 72 | } 73 | to[j] = '\0'; 74 | } 75 | -------------------------------------------------------------------------------- /Exercise 5-12/lorem_ipsum_detab.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, 2 | consetetur sadipscing elitr, sed diam nonumy eirmod 3 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 4 | At vero eos et accusam et justo duo dolores et ea rebum. 5 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 6 | 7 | -------------------------------------------------------------------------------- /Exercise 5-12/lorem_ipsum_entab.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, 2 | consetetur sadipscing elitr, sed diam nonumy eirmod 3 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. 4 | At vero eos et accusam et justo duo dolores et ea rebum. 5 | Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 6 | 7 | -------------------------------------------------------------------------------- /Exercise 5-12/settab.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 4 | #define TABSTOP 8 5 | #define YES 1 6 | #define NO 0 7 | 8 | 9 | void settab(int argc, char *argv[], char *tab) { 10 | 11 | int i, pos, inc; 12 | 13 | if (argc <= 1) 14 | for (i = 1; i < MAXLINE; i++) 15 | if ( i % TABSTOP == 0) 16 | tab[i] = YES; 17 | else 18 | tab[i] = NO; 19 | else if (argc == 3 && *argv[1] == '-' && *argv[2] == '+') { 20 | pos = atoi(&(*++argv)[1]); 21 | inc = atoi(&(*++argv)[1]); 22 | for (i = 1; i < MAXLINE; i++) 23 | if (i!=pos) 24 | tab[pos] = NO; 25 | else 26 | tab[i] = YES, pos += inc; 27 | } else { 28 | for (i = 1; i < MAXLINE; i++) 29 | tab[i] = NO; 30 | while (--argc > 0) { 31 | pos = atoi(*++argv); 32 | if ( pos > 0 && pos <= MAXLINE) 33 | tab[pos] = YES; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Exercise 5-12/tabpos.c: -------------------------------------------------------------------------------- 1 | #define MAXLINE 1000 2 | #define YES 1 3 | 4 | int tabpos(int pos, char *tab) { 5 | 6 | if (pos >= MAXLINE) 7 | return YES; 8 | else 9 | return tab[pos]; 10 | } 11 | -------------------------------------------------------------------------------- /Exercise 5-13/lorem_ipsum.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod 2 | tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At v 3 | ero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, 4 | no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit am 5 | et, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labor 6 | e et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et ju 7 | sto duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus 8 | est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscin 9 | g elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquy 10 | am erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea re 11 | bum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor si 12 | t amet. 13 | -------------------------------------------------------------------------------- /Exercise 5-13/tail.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINES 5000 5 | 6 | char *lineptr[MAXLINES]; 7 | 8 | int readlines(char *lineptr[], int maxlines); 9 | 10 | int main(int argc, char** argv) { 11 | 12 | int n = 10; // default value for optional parameter 13 | int nlines; 14 | 15 | if (argc > 2) 16 | printf("Usage: tail [-n] where n is a number\n"); 17 | else { 18 | 19 | if (argc == 2) 20 | n = atoi(++argv[1]); 21 | if (n == 0) 22 | n = 10; 23 | 24 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 25 | 26 | int i; 27 | 28 | if (nlines <= n) { 29 | printf("nlines (%d) <= n (%d): print all lines\n", nlines, n); 30 | for (i = 0; i < nlines; i++) 31 | printf("%s\n", lineptr[i]); 32 | } else { 33 | printf("nlines (%d) > n (%d): print last %d lines\n", nlines, n, n); 34 | for (i = nlines - n; i < nlines; i++) 35 | printf("%s\n", lineptr[i]); 36 | } 37 | } else { 38 | printf("too many input lines\n"); 39 | return 1; 40 | } 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | 47 | 48 | #define MAXLEN 1000 49 | 50 | int get_line(char line[], int maxline); 51 | char *alloc(int); 52 | 53 | int readlines(char *lineptr[], int maxlines) { 54 | 55 | int len, nlines; 56 | char *p, line[MAXLEN]; 57 | 58 | nlines = 0; 59 | while ((len = get_line(line, MAXLEN)) > 0) 60 | if (nlines >= MAXLINES || (p = alloc(len)) == NULL) 61 | return -1; 62 | else { 63 | line[len - 1] = '\0'; 64 | strcpy(p, line); 65 | lineptr[nlines++] = p; 66 | } 67 | 68 | return nlines; 69 | 70 | } 71 | 72 | int get_line(char s[], int lim) { 73 | int c, i; 74 | 75 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 76 | s[i] = c; 77 | if (c == '\n') s[i++] = c; 78 | s[i] = '\0'; 79 | return i; 80 | } 81 | 82 | 83 | 84 | #define ALLOCSIZE 10000 85 | 86 | static char allocbuf[ALLOCSIZE]; 87 | static char *allocp = allocbuf; 88 | 89 | char *alloc(int n) { 90 | if (allocbuf + ALLOCSIZE - allocp >= n) { 91 | allocp += n; 92 | return allocp - n; 93 | } else 94 | return 0; 95 | } 96 | 97 | void afree(char *p) { 98 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 99 | allocp = p; 100 | } 101 | -------------------------------------------------------------------------------- /Exercise 5-14/sort.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXLINES 5000 6 | 7 | char *lineptr[MAXLINES]; 8 | 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines, int reverse); 11 | 12 | void q_sort(void *lineptr[], int left, int right, 13 | int (*comp)(void *, void *)); 14 | int numcmp(char *, char *); 15 | 16 | main(int argc, char *argv[]) { 17 | 18 | int nlines; 19 | int numeric = 0; 20 | int reverse = 0; 21 | 22 | while (--argc > 0 && (*++argv)[0] == '-') { 23 | int c; 24 | while (c = *++argv[0]) 25 | switch (c) { 26 | case 'n': 27 | numeric = 1; 28 | break; 29 | case 'r': 30 | reverse = 1; 31 | break; 32 | default: 33 | printf("Illegal option: %c\n", c); 34 | break; 35 | } 36 | } 37 | 38 | if (argc != 0) 39 | printf("Usage: sort -n -r\n"); 40 | 41 | printf(numeric ? "Numerical sort\n" : "Lexicographic sort\n"); 42 | printf(reverse ? "Reverse sort\n" : "Normal sort\n"); 43 | 44 | 45 | if ((nlines = readlines(lineptr, MAXLINES)) > 0) { 46 | if (numeric) 47 | q_sort((void **) lineptr, 0, nlines - 1, 48 | (int (*)(void *, void *)) numcmp); 49 | else 50 | q_sort((void **) lineptr, 0, nlines - 1, 51 | (int (*)(void *, void *)) strcmp); 52 | writelines(lineptr, nlines, reverse); 53 | return 0; 54 | } else { 55 | printf("input too big to sort\n"); 56 | return 1; 57 | } 58 | } 59 | 60 | void q_sort(void *v[], int left, int right, 61 | int (*comp)(void *, void *)) { 62 | 63 | int i, last; 64 | void swap(void *v[], int, int); 65 | 66 | if (left >= right) 67 | return; 68 | swap(v, left, (left + right) / 2); 69 | last = left; 70 | for (i = left + 1; i <= right; i++) 71 | if ((*comp)(v[i], v[left]) < 0) 72 | swap(v, ++last, i); 73 | swap(v, left, last); 74 | q_sort(v, left, last - 1, comp); 75 | q_sort(v, last + 1, right, comp); 76 | } 77 | 78 | int numcmp(char *s1, char *s2) { 79 | 80 | double v1, v2; 81 | 82 | v1 = atof(s1); 83 | v2 = atof(s2); 84 | 85 | if (v1 < v2) 86 | return -1; 87 | else if (v1 > v2) 88 | return 1; 89 | else 90 | return 0; 91 | } 92 | 93 | void swap(void *v[], int i, int j) { 94 | 95 | void *temp; 96 | 97 | temp = v[i]; 98 | v[i] = v[j]; 99 | v[j] = temp; 100 | } 101 | 102 | 103 | #define MAXLEN 1000 104 | 105 | int get_line(char line[], int maxline); 106 | char *alloc(int); 107 | 108 | int readlines(char *lineptr[], int maxlines) { 109 | 110 | int len, nlines; 111 | char *p, line[MAXLEN]; 112 | 113 | nlines = 0; 114 | while ((len = get_line(line, MAXLEN)) > 0) 115 | if (nlines >= MAXLINES || (p = alloc(len)) == NULL) 116 | return -1; 117 | else { 118 | line[len - 1] = '\0'; 119 | strcpy(p, line); 120 | lineptr[nlines++] = p; 121 | } 122 | 123 | return nlines; 124 | 125 | } 126 | 127 | void writelines(char * lineptr[], int nlines, int reverse) { 128 | 129 | int i; 130 | 131 | if (reverse) 132 | for (i = nlines-1; i >= 0; i--) 133 | printf("%s\n", lineptr[i]); 134 | else 135 | for (i = 0; i < nlines; i++) 136 | printf("%s\n", lineptr[i]); 137 | } 138 | 139 | int get_line(char s[], int lim) { 140 | int c, i; 141 | 142 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 143 | s[i] = c; 144 | if (c == '\n') s[i++] = c; 145 | s[i] = '\0'; 146 | return i; 147 | } 148 | 149 | 150 | 151 | #define ALLOCSIZE 10000 152 | 153 | static char allocbuf[ALLOCSIZE]; 154 | static char *allocp = allocbuf; 155 | 156 | char *alloc(int n) { 157 | if (allocbuf + ALLOCSIZE - allocp >= n) { 158 | allocp += n; 159 | return allocp - n; 160 | } else 161 | return 0; 162 | } 163 | 164 | void afree(char *p) { 165 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 166 | allocp = p; 167 | } 168 | -------------------------------------------------------------------------------- /Exercise 5-18/decl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXTOKEN 100 6 | 7 | enum { 8 | NAME, PARENS, BRACKETS, ERROR 9 | }; 10 | 11 | void dcl(void); 12 | void dirdcl(void); 13 | 14 | int gettoken(void); 15 | int tokentype; // type of last token 16 | char token[MAXTOKEN]; // last token string 17 | char name[MAXTOKEN]; // identifier name 18 | char datatype[MAXTOKEN]; // datatype: char, int, short, long, float, double, void 19 | char out[1000]; // output string 20 | 21 | main() { 22 | 23 | while (gettoken() != EOF) { 24 | strcpy(datatype, token); 25 | if (!is_valid_datatype(datatype)) { 26 | printf("error: datatype unknown %s\n", datatype); 27 | while (gettoken() != '\n') 28 | ; 29 | } else { 30 | out[0] = '\0'; 31 | dcl(); 32 | if (tokentype != '\n') { 33 | printf("syntax error: %c\n", tokentype); 34 | while (gettoken() != '\n') 35 | ; 36 | } else 37 | printf("%s %s %s\n", name, out, datatype); 38 | } 39 | } 40 | return 0; 41 | } 42 | 43 | void dcl(void) { 44 | 45 | int ns; 46 | 47 | for (ns = 0; gettoken() == '*';) 48 | ns++; 49 | dirdcl(); 50 | while (ns-- > 0) 51 | strcat(out, " pointer to"); 52 | } 53 | 54 | void dirdcl(void) { 55 | 56 | int type; 57 | 58 | if (tokentype == '(') { 59 | dcl(); 60 | if (tokentype != ')') 61 | printf("error: missing )\n"); 62 | } else if (tokentype == NAME) 63 | strcpy(name, token); 64 | else 65 | printf("error: expected name or (dcl)\n"); 66 | 67 | while ((type = gettoken()) == PARENS || type == BRACKETS) 68 | if (type == PARENS) 69 | strcat(out, " function returning"); 70 | else { 71 | strcat(out, " array"); 72 | strcat(out, token); 73 | strcat(out, " of"); 74 | } 75 | } 76 | 77 | int gettoken(void) { 78 | 79 | int c, getch(void); 80 | void ungetch(int); 81 | char *p = token; 82 | 83 | while ((c = getch()) == ' ' || c == '\t') 84 | ; 85 | if (c == '(') { 86 | 87 | // consume blanks after opening parenthesis 88 | while ((c = getch()) == ' ' || c == '\t') 89 | ; 90 | 91 | if (c == ')') { 92 | strcpy(token, "()"); 93 | return tokentype = PARENS; 94 | } else { 95 | ungetch(c); 96 | return tokentype = '('; 97 | } 98 | } else if (c == '[') { 99 | 100 | // consume blanks after opening bracket 101 | while ((c = getch()) == ' ' || c == '\t') 102 | ; 103 | ungetch(c); 104 | 105 | for (*p++ = '['; (*p++ = getch()) != ']';) 106 | ; 107 | *p = '\0'; 108 | return tokentype = BRACKETS; 109 | } else if (isalpha(c)) { 110 | for (*p++ = c; isalnum(c = getch());) 111 | *p++ = c; 112 | *p = '\0'; 113 | ungetch(c); 114 | return tokentype = NAME; 115 | } else 116 | return tokentype = c; 117 | } 118 | 119 | int is_valid_datatype(char *datatype) { 120 | return strcmp(datatype, "char") == 0 || 121 | strcmp(datatype, "short") == 0 || 122 | strcmp(datatype, "int") == 0 || 123 | strcmp(datatype, "long") == 0 || 124 | strcmp(datatype, "float") == 0 || 125 | strcmp(datatype, "double") == 0 || 126 | strcmp(datatype, "void") == 0; 127 | } 128 | 129 | 130 | #define BUFSIZE 100 131 | 132 | char buf[BUFSIZE]; /* buffer for ungetch */ 133 | int bufp = 0; /* next free position in buf */ 134 | 135 | int getch(void) /* get a (possibly pushed back) character */ { 136 | return (bufp > 0) ? buf[--bufp] : getchar(); 137 | } 138 | 139 | void ungetch(int c) /* push character back on input */ { 140 | if (bufp >= BUFSIZE) 141 | printf("ungetch: too many characters\n"); 142 | else 143 | buf[bufp++] = c; 144 | } 145 | -------------------------------------------------------------------------------- /Exercise 5-19/undecl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXTOKEN 100 6 | 7 | enum { 8 | NAME, PARENS, BRACKETS, ERROR 9 | }; 10 | 11 | enum { 12 | NO, YES 13 | }; 14 | 15 | void dcl(void); 16 | void dirdcl(void); 17 | 18 | int gettoken(void); 19 | int next_token(void); 20 | 21 | int tokentype; // type of last token 22 | char token[MAXTOKEN]; // last token string 23 | char name[MAXTOKEN]; // identifier name 24 | char datatype[MAXTOKEN]; // datatype: char, int, short, long, float, double, void 25 | char out[1000]; // output string 26 | 27 | int prev_token = NO; 28 | 29 | main() { 30 | 31 | int type; 32 | char temp[MAXTOKEN]; 33 | 34 | while (gettoken() != EOF) { 35 | strcpy(out, token); 36 | while ((type = gettoken()) != '\n') { 37 | if (type == PARENS || type == BRACKETS) 38 | strcat(out, token); 39 | else if (type == '*') { 40 | if ( (type = next_token()) != PARENS && type != BRACKETS) 41 | sprintf(temp, "*%s", out); 42 | else 43 | sprintf(temp, "(*%s)", out); 44 | strcpy(out, temp); 45 | } else if (type == NAME) { 46 | sprintf(temp, "%s %s", token, out); 47 | strcpy(out, temp); 48 | } else 49 | printf("invalid input at %s\n", token); 50 | } 51 | printf("%s\n", out); 52 | } 53 | return 0; 54 | } 55 | 56 | void dcl(void) { 57 | 58 | int ns; 59 | 60 | for (ns = 0; gettoken() == '*';) 61 | ns++; 62 | dirdcl(); 63 | while (ns-- > 0) 64 | strcat(out, " pointer to"); 65 | } 66 | 67 | void dirdcl(void) { 68 | 69 | int type; 70 | 71 | if (tokentype == '(') { 72 | dcl(); 73 | if (tokentype != ')') 74 | printf("error: missing )\n"); 75 | } else if (tokentype == NAME) 76 | strcpy(name, token); 77 | else 78 | printf("error: expected name or (dcl)\n"); 79 | 80 | while ((type = gettoken()) == PARENS || type == BRACKETS) 81 | if (type == PARENS) 82 | strcat(out, " function returning"); 83 | else { 84 | strcat(out, " array"); 85 | strcat(out, token); 86 | strcat(out, " of"); 87 | } 88 | } 89 | 90 | int next_token(void) { 91 | 92 | int type; 93 | prev_token; 94 | 95 | type = gettoken(); 96 | prev_token = YES; 97 | return type; 98 | } 99 | 100 | int gettoken(void) { 101 | 102 | int c, getch(void); 103 | void ungetch(int); 104 | char *p = token; 105 | 106 | if (prev_token == YES) { 107 | prev_token = NO; 108 | return tokentype; 109 | } 110 | 111 | while ((c = getch()) == ' ' || c == '\t') 112 | ; 113 | if (c == '(') { 114 | 115 | // consume blanks after opening parenthesis 116 | while ((c = getch()) == ' ' || c == '\t') 117 | ; 118 | 119 | if (c == ')') { 120 | strcpy(token, "()"); 121 | return tokentype = PARENS; 122 | } else { 123 | ungetch(c); 124 | return tokentype = '('; 125 | } 126 | } else if (c == '[') { 127 | 128 | // consume blanks after opening bracket 129 | while ((c = getch()) == ' ' || c == '\t') 130 | ; 131 | ungetch(c); 132 | 133 | for (*p++ = '['; (*p++ = getch()) != ']';) 134 | ; 135 | *p = '\0'; 136 | return tokentype = BRACKETS; 137 | } else if (isalpha(c)) { 138 | for (*p++ = c; isalnum(c = getch());) 139 | *p++ = c; 140 | *p = '\0'; 141 | ungetch(c); 142 | return tokentype = NAME; 143 | } else 144 | return tokentype = c; 145 | } 146 | 147 | int is_valid_datatype(char *datatype) { 148 | return strcmp(datatype, "char") != 0 && 149 | strcmp(datatype, "short") != 0 && 150 | strcmp(datatype, "int") != 0 && 151 | strcmp(datatype, "long") != 0 && 152 | strcmp(datatype, "float") != 0 && 153 | strcmp(datatype, "double") != 0 && 154 | strcmp(datatype, "void") != 0; 155 | } 156 | 157 | 158 | #define BUFSIZE 100 159 | 160 | char buf[BUFSIZE]; /* buffer for ungetch */ 161 | int bufp = 0; /* next free position in buf */ 162 | 163 | int getch(void) /* get a (possibly pushed back) character */ { 164 | return (bufp > 0) ? buf[--bufp] : getchar(); 165 | } 166 | 167 | void ungetch(int c) /* push character back on input */ { 168 | if (bufp >= BUFSIZE) 169 | printf("ungetch: too many characters\n"); 170 | else 171 | buf[bufp++] = c; 172 | } 173 | -------------------------------------------------------------------------------- /Exercise 5-2/getfloat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SIZE 10 4 | 5 | 6 | int main(int argc, char** argv) { 7 | 8 | int n, getfloat(float*); 9 | float array[SIZE]; 10 | 11 | for (n=0; n < SIZE && getfloat(&array[n]) != EOF; n++) 12 | printf("n = %g\n", array[n]); 13 | 14 | return 0; 15 | } 16 | 17 | 18 | int getch(void); 19 | void ungetch(int); 20 | 21 | /* getfloat: get next float from input into *pf */ 22 | int getfloat(float *pf) { 23 | 24 | int c, sign, i; 25 | float fraction; 26 | 27 | while (isspace(c = getch())) /* skip white space */ 28 | ; 29 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 30 | ungetch(c); /*it's not a number */ 31 | return 0; 32 | } 33 | sign = (c == '-') ? -1 : 1; 34 | if (c == '+' || c == '-') { 35 | int ch = getch(); 36 | if (!isdigit(ch)) { 37 | if (ch != EOF) 38 | ungetch(ch); 39 | ungetch(c); 40 | return c; 41 | } 42 | c = ch; 43 | } 44 | for (*pf = 0; isdigit(c); c = getch()) 45 | *pf = 10 * *pf + (c - '0'); 46 | if (c == '.') 47 | c = getch(); 48 | for (i = 10; isdigit(c); c = getch(), i *= 10) 49 | fraction += ((c - '0') / (float) i); 50 | *pf += fraction; 51 | *pf *= sign; 52 | if (c != EOF) 53 | ungetch(c); 54 | return c; 55 | } 56 | 57 | #define BUFSIZE 100 58 | 59 | char buf[BUFSIZE]; /* buffer for ungetch */ 60 | int bufp = 0; /* next free position in buf */ 61 | 62 | int getch(void) /* get a (possibly pushed back) character */ { 63 | return (bufp > 0) ? buf[--bufp] : getchar(); 64 | } 65 | 66 | void ungetch(int c) /* push character back on input */ { 67 | if (bufp >= BUFSIZE) 68 | printf("ungetch: too many characters\n"); 69 | else 70 | buf[bufp++] = c; 71 | } 72 | -------------------------------------------------------------------------------- /Exercise 5-3/strcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void strcat2(char s[], char t[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | char s[100] = "This is the first sentence."; 8 | char t[] = "This is the second sentence."; 9 | 10 | strcat2(s, " "); 11 | strcat2(s, t); 12 | printf("%s\n", s); 13 | 14 | return 0; 15 | } 16 | 17 | /* strcat: concatenate t to end of s; s must be long enough */ 18 | void strcat2(char s[], char t[]) { 19 | 20 | while (*s) /* find end of s */ 21 | s++; 22 | while (*s++ = *t++) /* copy t */ 23 | ; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /Exercise 5-4/strend.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int strend(char s[], char t[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | char s[] = "This is a test."; 8 | char t[] = "a test"; 9 | char u[] = "a test."; 10 | char v[] = "This is"; 11 | 12 | printf("S[] = %s\n", s); 13 | printf("t[] = %s\n", t); 14 | printf("u[] = %s\n", u); 15 | printf("v[] = %s\n", v); 16 | 17 | int ret = strend(s, t); 18 | printf("t sub string at end of s? %d\n", ret); 19 | ret = strend(s, u); 20 | printf("u sub string at end of s? %d\n", ret); 21 | ret = strend(s, v); 22 | printf("v sub string at end of s? %d\n", ret); 23 | 24 | return 0; 25 | } 26 | 27 | int strend(char s[], char t[]) { 28 | 29 | for (; *s; s++) { 30 | if (*s == *t) { 31 | char *s1 = s; 32 | char *t1 = t; 33 | while (*s1 == *t1 && *s1 != '\0') 34 | s1++, t1++; 35 | /* The C Programming Language, page 245 36 | * "There is one exception: The address of the first element of the 37 | * past the end element can be used in pointer arithmetic." 38 | */ 39 | if (*s1 == '\0' && *t1 == '\0') 40 | return 1; 41 | } 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /Exercise 5-5/strn_functions.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void strn_cpy(char *s, char *t, size_t n); 4 | int strn_cmp(char *s, char *t, size_t n); 5 | char* strn_cat(char s[], char t[], size_t n); 6 | 7 | int main(int argc, char** argv) { 8 | 9 | char s[100] = "This is the first test string."; 10 | char *ps; 11 | int r; 12 | 13 | printf("Test string s:\n%s\n", s); 14 | 15 | printf("\n"); 16 | 17 | strn_cpy(s, "This is the ", 12); 18 | printf("strn_cpy(s, \"This is the \", 12):\ns: %s\n", s); 19 | strn_cpy(s, "This is the ", 30); 20 | printf("strn_cpy(s, \"This is the \", 30):\ns: %s\n", s); 21 | printf("Should be padded with 0s. Test s[12] == 0? %d\n", s[12] == '\0' ? 1 : 0); 22 | printf("Should be padded with 0s. Test s[16] == 0? %d\n", s[16] == '\0' ? 1 : 0); 23 | printf("Should be padded with 0s. Test s[29] == 0? %d\n", s[29] == '\0' ? 1 : 0); 24 | 25 | ps = strn_cat(s, "concatenated string.", 20); 26 | printf("strn_cat(s, \"concatenated string. But this sentence must not be copied.\", 20):\ns: %s\n", ps); 27 | printf("\n"); 28 | 29 | r = strn_cmp(s, "This is the", 5); 30 | printf("strn_cmp(s, \"This is the\", 5) returns %d\n", r); 31 | r = strn_cmp(s, "This is the", 11); 32 | printf("strn_cmp(s, \"This is the\", 11) returns %d\n", r); 33 | r = strn_cmp(s, "This is the", 15); 34 | printf("strn_cmp(s, \"This is the\", 15) returns %d\n", r); 35 | r = strn_cmp(s, "UVWXYZ", 6); 36 | printf("strn_cmp(s, \"UVWXYZ\", 6) returns %d\n", r); 37 | 38 | return 0; 39 | } 40 | 41 | /* 42 | * strn_cpy: copy at most n characters of string ct to s; return s. 43 | * Pad with '\0's if t has fewer than n characters. 44 | */ 45 | void strn_cpy(char *s, char *ct, size_t n) { 46 | int i = 0; 47 | while ((*s++ = *ct++) && (i++ < n)) 48 | ; 49 | while (i++ < n) 50 | *s++ = '\0'; 51 | *--s = '\0'; 52 | } 53 | 54 | /* 55 | * strncmp: compare at most n characters of string cs to string ct; 56 | * return <0 if cs0 if cs>ct. 57 | */ 58 | int strn_cmp(char *cs, char *ct, size_t n) { 59 | int i = 0; 60 | for (; (*cs == *ct) && (i++ < n); cs++, ct++) 61 | if (*cs == '\0' || i == n) 62 | return 0; 63 | return *cs - *ct; 64 | } 65 | 66 | /* 67 | * strncat: concatenate at most n characters of string ct to string s, 68 | * terminate s with '\0'; return s. 69 | */ 70 | char* strn_cat(char *s, char *ct, size_t n) { 71 | 72 | int i = 0; 73 | char *p = s; 74 | while (*s) /* find end of s */ 75 | s++; 76 | while ((*s++ = *ct++) && (i++ < n)) /* copy ct */ 77 | ; 78 | *s = '\0'; 79 | return p; 80 | } 81 | -------------------------------------------------------------------------------- /Exercise 5-6/atoi_1.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a_to_i(char s[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | int n; 8 | char s[] = "123456789"; 9 | 10 | n = a_to_i(s); 11 | printf("%d\n", n); 12 | 13 | return 0; 14 | } 15 | 16 | /* atoi: convert s to integer */ 17 | int a_to_i(char s[]) { 18 | 19 | int n = 0; 20 | 21 | for (; *s >= '0' && *s <= '9'; ++s) 22 | n = 10 * n + (*s - '0'); 23 | return n; 24 | } 25 | -------------------------------------------------------------------------------- /Exercise 5-6/atoi_2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int a_to_i(char s[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | int n; 8 | char s[] = "-12345"; 9 | 10 | n = a_to_i(s); 11 | printf("%d\n", n); 12 | 13 | return 0; 14 | } 15 | 16 | #include 17 | 18 | /* atoi: convert s to integer; version 2 */ 19 | int a_to_i(char s[]) { 20 | int n, sign; 21 | 22 | for (; isspace(*s); s++) /* skip white space */ 23 | ; 24 | sign = (*s == '-') ? -1 : 1; 25 | if (*s == '+' || *s == '-') /* skip sign */ 26 | s++; 27 | for (n = 0; isdigit(*s); s++) 28 | n = 10 * n + (*s - '0'); 29 | return sign * n; 30 | } 31 | -------------------------------------------------------------------------------- /Exercise 5-6/get_line.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define MAXLINE 1000 /* maximum input line size */ 3 | 4 | int get_line(char line[], int maxline); 5 | void copy(char to[], char from[]); 6 | 7 | /* print longest input line */ 8 | main() { 9 | int len; /* current line length */ 10 | int max; /* maximum length seen so far */ 11 | char line[MAXLINE]; /* current input line */ 12 | char longest[MAXLINE]; /* longest line saved here */ 13 | 14 | max = 0; 15 | while ((len = get_line(line, MAXLINE)) > 0) 16 | if (len > max) { 17 | max = len; 18 | copy(longest, line); 19 | } 20 | if (max > 0) /* there was a line */ 21 | printf("%s", longest); 22 | return 0; 23 | } 24 | 25 | /* getline: read a line into s, return length */ 26 | int get_line(char s[], int lim) { 27 | int c, i; 28 | 29 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; i++) 30 | *s++ = c; 31 | if (c == '\n') 32 | *s++ = c, i++; 33 | *s = '\0'; 34 | return i; 35 | } 36 | 37 | /* copy: copy 'from' into 'to'; assume to is big enough */ 38 | void copy(char to[], char from[]) { 39 | while (*to++ = *from++) 40 | ; 41 | } 42 | -------------------------------------------------------------------------------- /Exercise 5-6/getop.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include /* for atof() */ 3 | 4 | #define MAXOP 100 /* max size of operand or operator */ 5 | #define NUMBER '0' /* signal that a number was found */ 6 | 7 | int getop(char []); 8 | void push(double); 9 | double pop(void); 10 | 11 | /* reverse Polish calculator */ 12 | main() 13 | { 14 | int type; 15 | double op2; 16 | char s[MAXOP]; 17 | 18 | while ((type = getop(s)) != EOF) { 19 | switch (type) { 20 | case NUMBER: 21 | push(atof(s)); 22 | break; 23 | case '+': 24 | push(pop() + pop()); 25 | break; 26 | case '*': 27 | push(pop() * pop()); 28 | break; 29 | case '-': 30 | op2 = pop(); 31 | push(pop() - op2); 32 | break; 33 | case '/': 34 | op2 = pop(); 35 | if (op2 != 0.0) 36 | push(pop() / op2); 37 | else 38 | printf("error: zero divisor\n"); 39 | break; 40 | case '\n': 41 | printf("\t%.8g\n", pop()); 42 | break; 43 | default: 44 | printf("error: unknown command %s\n", s); 45 | break; 46 | } 47 | } 48 | return 0; 49 | } 50 | 51 | 52 | #define MAXVAL 100 /* maximum depth of val stack */ 53 | 54 | int sp = 0; /* next free stack position */ 55 | double val[MAXVAL]; /* value stack */ 56 | 57 | /* push: push f onto value stack */ 58 | void push(double f) 59 | { 60 | if (sp < MAXVAL) 61 | val[sp++] = f; 62 | else 63 | printf("error: stack full, can't push %g\n", f); 64 | } 65 | 66 | 67 | /* pop: pop and return top value from stack */ 68 | double pop(void) 69 | { 70 | if (sp > 0) 71 | return val[--sp]; 72 | else { 73 | printf("error: stack empty\n"); 74 | return 0.0; 75 | } 76 | } 77 | 78 | 79 | int getch(void); 80 | void ungetch(int); 81 | 82 | /* getop: get next operator or numeric operand */ 83 | int getop(char s[]) 84 | { 85 | int c; 86 | 87 | while ((*s = c = getch()) == ' ' || c == '\t') 88 | ; 89 | *(s+1) = '\0'; 90 | if (!isdigit(c) && c != '.') 91 | return c; /* not a number */ 92 | 93 | if (isdigit(c)) /* collect integer part */ 94 | while (isdigit(*++s = c = getch())) 95 | ; 96 | if (c == '.') /* collect fraction part */ 97 | while (isdigit(*++s = c = getch())) 98 | ; 99 | *s = '\0'; 100 | if (c != EOF) 101 | ungetch(c); 102 | return NUMBER; 103 | } 104 | 105 | 106 | #define BUFSIZE 100 107 | 108 | char buf[BUFSIZE]; /* buffer for ungetch */ 109 | int bufp = 0; /* next free position in buf */ 110 | 111 | int getch(void) /* get a (possibly pushed back) character */ 112 | { 113 | return (bufp > 0) ? buf[--bufp] : getchar(); 114 | } 115 | 116 | void ungetch(int c) /* push character back on input */ 117 | { 118 | if (bufp >= BUFSIZE) 119 | printf("ungetch: too many characters\n"); 120 | else 121 | buf[bufp++] = c; 122 | } 123 | -------------------------------------------------------------------------------- /Exercise 5-6/itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void itoa(int n, char s[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | char s[20]; 8 | int n = -123456789; 9 | 10 | itoa(n, s); 11 | printf("%s\n", s); 12 | 13 | return 0; 14 | } 15 | 16 | void reverse(char s[]); 17 | 18 | /* itoa: convert n to characters in s */ 19 | void itoa(int n, char s[]) { 20 | 21 | int sign; 22 | char *p = s; 23 | 24 | if ((sign = n) < 0) /* record sign */ 25 | n = -n; /* make n positive */ 26 | 27 | do { /* generate digits in reverse order */ 28 | *s++ = n % 10 + '0'; /* get next digit */ 29 | } while ((n /= 10) > 0); /* delete it */ 30 | if (sign < 0) 31 | *s++ = '-'; 32 | *s = '\0'; 33 | reverse(p); 34 | } 35 | 36 | #include 37 | 38 | /* reverse: reverse string s in place */ 39 | void reverse(char s[]) { 40 | int c; 41 | char *p, *q; 42 | for (p = s, q = s + strlen(s) - 1; p < q; p++, q--) 43 | c = *p, *p = *q, *q = c; 44 | } 45 | -------------------------------------------------------------------------------- /Exercise 5-6/recursive_itoa.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINE 20 5 | 6 | void itoa(int n, char s[]); 7 | 8 | int main(int argc, char** argv) { 9 | 10 | int n; 11 | char s[MAXLINE]; 12 | 13 | n = -2147483648; 14 | itoa(n, s); 15 | printf("%s\n", s); 16 | n = 2147483647; 17 | itoa(n, s); 18 | printf("%s\n", s); 19 | 20 | return 0; 21 | } 22 | 23 | 24 | void itoa(int n, char s[]) { 25 | 26 | int static i = 0; 27 | 28 | if (n / 10) 29 | itoa(n / 10, s); 30 | else { 31 | i = 0; 32 | if (n < 0) 33 | s[i++] = '-'; 34 | } 35 | 36 | s[i++] = abs(n % 10) + '0'; 37 | s[i] = '\0'; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Exercise 5-6/recursive_reverse.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void reverse(char s[]); 4 | 5 | int main(int argc, char** argv) { 6 | 7 | char s[] = "This is a simple test for reverse."; 8 | 9 | reverse(s); 10 | printf("%s\n", s); 11 | reverse(s); 12 | printf("%s\n", s); 13 | 14 | return 0; 15 | } 16 | 17 | #include 18 | 19 | void reverse(char s[]) { 20 | 21 | char c1, c2; 22 | int len = strlen(s); 23 | 24 | if (len < 2) 25 | return; 26 | 27 | c1 = *s; 28 | c2 = *(s + len - 1); 29 | *(s + len - 1) = '\0'; 30 | reverse(s + 1); 31 | *s = c2; 32 | *(s + len - 1) = c1; 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Exercise 5-6/strindex.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define MAXLINE 1000 /* maximum input line length */ 4 | 5 | int get_line(char line[], int max); 6 | int strindex(char source[], char searchfor[]); 7 | 8 | char pattern[] = "ould"; 9 | /* pattern to search for */ 10 | 11 | /* find all lines matching pattern */ 12 | main() { 13 | char line[MAXLINE]; 14 | int found = 0; 15 | 16 | while (get_line(line, MAXLINE) > 0) 17 | if (strindex(line, pattern) >= 0) { 18 | printf("%s", line); 19 | found++; 20 | } 21 | return found; 22 | } 23 | 24 | /* getline: get line into s, return length */ 25 | int get_line(char s[], int lim) { 26 | int c; 27 | char *p; 28 | 29 | p = s; 30 | while (--lim > 0 && (c = getchar()) != EOF && c != '\n') 31 | *s++ = c; 32 | if (c == '\n') 33 | *s++ = c; 34 | *s = '\0'; 35 | return s - p; 36 | } 37 | 38 | /* strindex: return index of t in s, −1 if none */ 39 | int strindex(char s[], char t[]) { 40 | char *p, *q, *r; 41 | 42 | for (p = s; *s; s++) { 43 | for (q = s, r = t; *t != '\0' && *q == *t; q++, t++) 44 | ; 45 | if ((t - r) > 0 && *t == '\0') 46 | return s - p; 47 | 48 | } 49 | return -1; 50 | } 51 | -------------------------------------------------------------------------------- /Exercise 5-7/lines.txt: -------------------------------------------------------------------------------- 1 | Computer science is abbreviated as "comp sci." 2 | Comp sci is so hard it gives you a sigh. 3 | Computing is everywhere in the world of sci-fi. 4 | Network is so prevalent these days you can't get by without a wi-fi. 5 | When I said so to a Scotsman, all he said was "aye." 6 | He's such a jolly, handsome, agreeable, but sometimes nervous guy. 7 | He's a sincere, honest, and serious person, and never tells a lie. 8 | One weakness he has is that when he's with a girl, he gets shy. 9 | As a student he worked part-time working in a pigsty. 10 | After getting used to the smelly pigs, he learned to work with them under a clear, blue sky. 11 | At the end of work each day, he cheerfully says to the pigs goodbye. 12 | Once he came up with an idea of a prank, and he entered into the pigsty on the sly. 13 | The hay and everything else there was really dry. 14 | Usually they ought to be slightly wet, and he wondered why. 15 | Maybe it was because of something done by an international spy. 16 | That, he thought, was something nobody can ever deny. 17 | My Scots friend was so poor he had a hard time in getting by. 18 | There was even a time he was so desperate that when I talked to him he didn't even reply. 19 | I was so shocked at his destitute state I could not help but cry. 20 | At the sight of my response, he could not help but say, "Oh, my!" 21 | 22 | My Scottish friend once lived very far and decided to live nigh. 23 | Near his new place was a little shop that sold everything made of rye. 24 | He bought a splendid piece of bread there on the Fourth of July. 25 | There he also bought something he always wanted to give me: an apple pie. 26 | He just had to give all that to me although there was a risk of oversupply. 27 | He also thought the merchandise looked so delicious he thought it was a good buy. 28 | When he came to my place with that small gifts, I was with a Thai. 29 | And also, I was wearing what I usually don't wear: a beautiful tie. 30 | It was so brilliant something came flying to my tie, 31 | and I realized it was something I don't care for very much: a fly. 32 | Right at that moment, somebody I never expected slowly came by. 33 | The stranger looked wicked, with a crooked mouth, and with an evil eye. 34 | My Scottish friend, my Thai friend, and I together got into a fight with the wicked guy. 35 | Then my final punch gave him a black eye. 36 | The crooked man left immediately, without any intention again to drop by. 37 | He uttered a word just before leaving, but I don't think he had anything to imply. 38 | He was some Westerner doing some business with a gangster in Shanghai. 39 | -------------------------------------------------------------------------------- /Exercise 5-7/qsort_book.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #define MAXLINES 5000 /* max #lines to be sorted */ 6 | 7 | char *lineptr[MAXLINES]; /* pointers to text lines */ 8 | 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); 11 | 12 | void qsort(char *lineptr[], int left, int right); 13 | 14 | /* sort input lines */ 15 | main() { 16 | int nlines; /* number of input lines read */ 17 | 18 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 19 | qsort(lineptr, 0, nlines - 1); 20 | writelines(lineptr, nlines); 21 | return 0; 22 | } else { 23 | printf("error: input too big to sort\n"); 24 | return 1; 25 | } 26 | } 27 | 28 | 29 | 30 | #define MAXLEN 1000 /* max length of any input line */ 31 | 32 | int get_line(char *, int); 33 | char *alloc(int); 34 | 35 | /* readlines: read input lines */ 36 | int readlines(char *lineptr[], int maxlines) { 37 | int len, nlines; 38 | char *p, line[MAXLEN]; 39 | 40 | nlines = 0; 41 | while ((len = get_line(line, MAXLEN)) > 0) 42 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 43 | return -1; 44 | else { 45 | line[len - 1] = '\0'; /* delete newline */ 46 | strcpy(p, line); 47 | lineptr[nlines++] = p; 48 | } 49 | return nlines; 50 | } 51 | 52 | /* writelines: write output lines */ 53 | void writelines(char *lineptr[], int nlines) { 54 | 55 | while (nlines-- >0) 56 | printf("%s\n", *lineptr++); 57 | } 58 | 59 | /* getline: read a line into s, return length */ 60 | int get_line(char s[], int lim) { 61 | int c, i; 62 | 63 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 64 | s[i] = c; 65 | if (c == '\n') { 66 | s[i] = c; 67 | ++i; 68 | } 69 | s[i] = '\0'; 70 | return i; 71 | } 72 | 73 | 74 | 75 | void swap(char *v[], int i, int j); 76 | 77 | /* qsort: sort v[left]...v[right] into increasing order */ 78 | void qsort(char *v[], int left, int right) { 79 | int i, last; 80 | void swap(char *v[], int i, int j); 81 | 82 | if (left >= right) /* do nothing if array contains */ 83 | return; /* fewer than two elements */ 84 | swap(v, left, (left + right) / 2); 85 | last = left; 86 | for (i = left + 1; i <= right; i++) 87 | if (strcmp(v[i], v[left]) < 0) 88 | swap(v, ++last, i); 89 | swap(v, left, last); 90 | qsort(v, left, last - 1); 91 | qsort(v, last + 1, right); 92 | } 93 | 94 | /* swap: interchange v[i] and v[j] */ 95 | void swap(char *v[], int i, int j) { 96 | char *temp; 97 | 98 | temp = v[i]; 99 | v[i] = v[j]; 100 | v[j] = temp; 101 | } 102 | 103 | 104 | 105 | #define ALLOCSIZE 10000 /* size of available space */ 106 | 107 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 108 | static char *allocp = allocbuf; /* next free position */ 109 | 110 | char *alloc(int n) /* return pointer to n characters */ 111 | { 112 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 113 | allocp += n; 114 | return allocp - n; /* old p */ 115 | } else /* not enough room */ 116 | return 0; 117 | } 118 | 119 | void afree(char *p) /* free storage pointed to by p */ 120 | { 121 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 122 | allocp = p; 123 | } 124 | -------------------------------------------------------------------------------- /Exercise 5-7/qsort_exercise.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #define MAXLINES 5000 /* max #lines to be sorted */ 6 | #define MAXLEN 1000 /* max length of any input line */ 7 | 8 | char *lineptr[MAXLINES]; /* pointers to text lines */ 9 | 10 | int readlines(char *lineptr[], char lines[], int nlines); 11 | void writelines(char *lineptr[], int nlines); 12 | 13 | void qsort(char *lineptr[], int left, int right); 14 | 15 | /* sort input lines */ 16 | main() { 17 | int nlines; /* number of input lines read */ 18 | char lines[MAXLINES * MAXLEN]; /* one large array for lines */ 19 | 20 | if ((nlines = readlines(lineptr, lines, MAXLINES)) >= 0) { 21 | qsort(lineptr, 0, nlines - 1); 22 | writelines(lineptr, nlines); 23 | return 0; 24 | } else { 25 | printf("error: input too big to sort\n"); 26 | return 1; 27 | } 28 | } 29 | 30 | 31 | 32 | int get_line(char *, int); 33 | char *alloc(int); 34 | 35 | /* readlines: read input lines */ 36 | int readlines(char *lineptr[], char lines[], int maxlines) { 37 | int len, nlines; 38 | char *p, line[MAXLEN]; 39 | char *lineend = lines + MAXLINES * MAXLEN; /* point to the end of lines array */ 40 | 41 | nlines = 0; 42 | while ((len = get_line(line, MAXLEN)) > 0) 43 | if (nlines >= maxlines || lines + len >= lineend) 44 | return -1; 45 | else { 46 | line[len - 1] = '\0'; /* delete newline */ 47 | strcpy(lines, line); 48 | lineptr[nlines++] = lines; 49 | lines += len; 50 | } 51 | return nlines; 52 | } 53 | 54 | /* writelines: write output lines */ 55 | void writelines(char *lineptr[], int nlines) { 56 | while (nlines-- > 0) 57 | printf("%s\n", *lineptr++); 58 | } 59 | 60 | /* getline: read a line into s, return length */ 61 | int get_line(char s[], int lim) { 62 | int c, i; 63 | 64 | for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) 65 | s[i] = c; 66 | if (c == '\n') { 67 | s[i] = c; 68 | ++i; 69 | } 70 | s[i] = '\0'; 71 | return i; 72 | } 73 | 74 | 75 | 76 | void swap(char *v[], int i, int j); 77 | 78 | /* qsort: sort v[left]...v[right] into increasing order */ 79 | void qsort(char *v[], int left, int right) { 80 | int i, last; 81 | void swap(char *v[], int i, int j); 82 | 83 | if (left >= right) /* do nothing if array contains */ 84 | return; /* fewer than two elements */ 85 | swap(v, left, (left + right) / 2); 86 | last = left; 87 | for (i = left + 1; i <= right; i++) 88 | if (strcmp(v[i], v[left]) < 0) 89 | swap(v, ++last, i); 90 | swap(v, left, last); 91 | qsort(v, left, last - 1); 92 | qsort(v, last + 1, right); 93 | } 94 | 95 | /* swap: interchange v[i] and v[j] */ 96 | void swap(char *v[], int i, int j) { 97 | char *temp; 98 | 99 | temp = v[i]; 100 | v[i] = v[j]; 101 | v[j] = temp; 102 | } 103 | 104 | 105 | 106 | #define ALLOCSIZE 10000 /* size of available space */ 107 | 108 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 109 | static char *allocp = allocbuf; /* next free position */ 110 | 111 | char *alloc(int n) /* return pointer to n characters */ { 112 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 113 | allocp += n; 114 | return allocp - n; /* old p */ 115 | } else /* not enough room */ 116 | return 0; 117 | } 118 | 119 | void afree(char *p) /* free storage pointed to by p */ { 120 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 121 | allocp = p; 122 | } 123 | -------------------------------------------------------------------------------- /Exercise 5-8/days_conversions.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char daytab[2][13] = { 4 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 5 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 6 | }; 7 | 8 | int day_of_year(int year, int month, int day); 9 | void month_day(int year, int yearday, int *pmonth, int *pday); 10 | 11 | int main() { 12 | int month, day, yearday, ret; 13 | 14 | ret = day_of_year(2015, 13, 1); 15 | printf("13th month exists? %d\n", ret); 16 | 17 | ret = day_of_year(2015, 1, 32); 18 | printf("32nd day exists? %d\n", ret); 19 | 20 | month_day(2015, 370, &month, &day); 21 | printf("370th yearday exists? day = %d, month = %d\n", day, month); 22 | 23 | ret = day_of_year(1981, 1, 1); 24 | printf("1st day of 1st month exists? %d\n", ret); 25 | 26 | ret = day_of_year(2015, 12, 31); 27 | printf("31st of 12th month exists? %d\n", ret); 28 | 29 | month_day(2015, 90, &month, &day); 30 | printf("90th day of year exists? day = %d, month = %d\n", day, month); 31 | 32 | 33 | return 0; 34 | } 35 | 36 | /* day_of_year: set day of year from month & day */ 37 | int day_of_year(int year, int month, int day) { 38 | int i, leap; 39 | 40 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 41 | 42 | if (month < 1 || month > 12) 43 | return -1; 44 | else { 45 | if (day < 1 || day > daytab[leap][month]) 46 | return -1; 47 | } 48 | 49 | for (i = 1; i < month; i++) 50 | day += daytab[leap][i]; 51 | return day; 52 | } 53 | 54 | /* month_day: set month, day from day of year */ 55 | void month_day(int year, int yearday, int *pmonth, int *pday) { 56 | int i, leap, days; 57 | 58 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 59 | 60 | days = 0; 61 | for (i = 1; daytab[leap][i]; i++) 62 | days += daytab[leap][i]; 63 | 64 | if (yearday > days) { 65 | *pmonth = 0; 66 | *pday = 0; 67 | return; 68 | } 69 | 70 | for (i = 1; yearday > daytab[leap][i]; i++) 71 | yearday -= daytab[leap][i]; 72 | *pmonth = i; 73 | *pday = yearday; 74 | } 75 | -------------------------------------------------------------------------------- /Exercise 5-9/days_conversion.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static char months_no_leap[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 4 | static char months_leap[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 5 | static char* daytab[2] = {months_no_leap, months_leap}; 6 | 7 | int day_of_year(int year, int month, int day); 8 | void month_day(int year, int yearday, int *pmonth, int *pday); 9 | 10 | int main() { 11 | int month, day, yearday, year, ret; 12 | 13 | day = 15; 14 | month = 13; 15 | year = 1981; 16 | ret = day_of_year(year, month, day); 17 | printf("13th month exists? %d\n", ret); 18 | 19 | day = 32; 20 | month = 6; 21 | ret = day_of_year(year, month, day); 22 | printf("32nd day exists? %d\n", ret); 23 | 24 | day = 15; 25 | month = 1; 26 | ret = day_of_year(year, month, day); 27 | printf("15th of January 1981 valid? Day of year = %d\n", ret); 28 | 29 | yearday = 370; 30 | month_day(year, yearday, &month, &day); 31 | printf("370th yearday in 1981 exists? day = %d, month = %d\n", day, month); 32 | 33 | yearday = 15; 34 | month_day(year, yearday, &month, &day); 35 | printf("15th yearday in 1981 is on %d/%d/%d\n", day, month, year); 36 | 37 | 38 | return 0; 39 | } 40 | 41 | /* day_of_year: set day of year from month & day */ 42 | int day_of_year(int year, int month, int day) { 43 | int leap; 44 | char *p; 45 | 46 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 47 | p = daytab[leap]; 48 | 49 | if (month < 1 || month > 12) 50 | return -1; 51 | else { 52 | if (day < 1 || day > p[month]) 53 | return -1; 54 | } 55 | 56 | for ( ;--month; ) 57 | day += *++p; 58 | 59 | return day; 60 | } 61 | 62 | /* month_day: set month, day from day of year */ 63 | void month_day(int year, int yearday, int *pmonth, int *pday) { 64 | int leap, days; 65 | char *p, *q; 66 | 67 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 68 | 69 | days = 0; 70 | q = daytab[leap]; 71 | for (; *++q;) 72 | days += *q; 73 | 74 | if (yearday > days) { 75 | *pmonth = 0; 76 | *pday = 0; 77 | return; 78 | } 79 | 80 | p = daytab[leap]; 81 | for (; yearday > *++p; ) 82 | yearday -= *p; 83 | 84 | *pmonth = p - *(daytab + leap); 85 | *pday = yearday; 86 | } 87 | -------------------------------------------------------------------------------- /Exercise 6-1/getword.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXWORD 100 6 | #define NKEYS (sizeof keytab / sizeof keytab[0]) 7 | 8 | // keywords must be ordered lexicographically 9 | 10 | struct key { 11 | char *word; 12 | int count; 13 | } keytab[] = { 14 | "auto", 0, 15 | "break", 0, 16 | "case", 0, 17 | "char", 0, 18 | "const", 0, 19 | "continue", 0, 20 | "default", 0, 21 | "do", 0, 22 | "double", 0, 23 | "else", 0, 24 | "enum", 0, 25 | "extern", 0, 26 | "float", 0, 27 | "for", 0, 28 | "goto", 0, 29 | "if", 0, 30 | "int", 0, 31 | "long", 0, 32 | "register", 0, 33 | "return", 0, 34 | "short", 0, 35 | "signed", 0, 36 | "sizeof", 0, 37 | "static", 0, 38 | "struct", 0, 39 | "switch", 0, 40 | "typedef", 0, 41 | "union", 0, 42 | "unsigned", 0, 43 | "void", 0, 44 | "volatile", 0, 45 | "while", 0 46 | }; 47 | 48 | 49 | int getword(char *, int); 50 | int binsearch(char *, struct key *, int); 51 | 52 | main() { 53 | 54 | int n; 55 | char word[MAXWORD]; 56 | 57 | while (getword(word, MAXWORD) != EOF) { 58 | //printf("Word: %s\n", word); 59 | if (isalpha(word[0]) || word[0] == '_') 60 | if ((n = binsearch(word, keytab, NKEYS)) >= 0) 61 | keytab[n].count++; 62 | } 63 | 64 | for (n = 0; n < NKEYS; ++n) 65 | if (keytab[n].count > 0) 66 | printf("%4d %s\n", keytab[n].count, keytab[n].word); 67 | 68 | return 0; 69 | 70 | } 71 | 72 | int binsearch(char *word, struct key tab[], int n) { 73 | 74 | int cond; 75 | int low, high, mid; 76 | 77 | low = 0; 78 | high = n - 1; 79 | while (low <= high) { 80 | mid = (low + high) / 2; 81 | if ((cond = strcmp(word, tab[mid].word)) < 0) 82 | high = mid - 1; 83 | else if (cond > 0) 84 | low = mid + 1; 85 | else 86 | return mid; 87 | } 88 | 89 | return -1; 90 | } 91 | 92 | int getword(char *word, int lim) { 93 | 94 | int c, getch(void); 95 | void ungetch(int); 96 | char *w = word; 97 | 98 | while (isspace(c = getch())) 99 | ; 100 | if (c != EOF) 101 | *w++ = c; 102 | //Consume string constants 103 | if (c == '\"') { 104 | for (; --lim > 0; w++) 105 | if ((*w = getch()) == '\"') 106 | break; 107 | *++w = '\0'; 108 | return word[0]; 109 | } 110 | //Consume comments 111 | if (c == '/') { 112 | c = getch(); 113 | //Single line comments 114 | if (c == '/') { 115 | for ((*w++ = c) && (--lim > 0); --lim > 0; w++) 116 | if ((*w = getch()) == '\n') { 117 | *++w = '\0'; 118 | return word[0]; 119 | } 120 | } else if (c == '*') { 121 | for ((*w++ = c) && (--lim > 0); --lim > 0; w++) 122 | if ((*w = getch()) == '/') 123 | if (*(w - 1) == '*') { 124 | *++w = '\0'; 125 | return word[0]; 126 | } 127 | } else { 128 | ungetch(c); 129 | *w = '\0'; 130 | return '/'; 131 | } 132 | } 133 | //Consume preprocessor control lines 134 | if (c == '#') { 135 | //Simple assumption: starts with '#' and ends with '\n' 136 | for (; --lim > 0; w++) 137 | if ((*w = getch()) == '\n') 138 | break; 139 | 140 | } 141 | if (!isalpha(c) && c != '_') { 142 | *w = '\0'; 143 | return c; 144 | } 145 | for (; --lim > 0; w++) { 146 | if (!isalnum(*w = getch()) && *w != '_') { 147 | ungetch(*w); 148 | break; 149 | } 150 | } 151 | *w = '\0'; 152 | return word[0]; 153 | } 154 | 155 | #define BUFSIZE 100 156 | 157 | char buf[BUFSIZE]; 158 | int bufp = 0; 159 | 160 | int getch(void) { 161 | return (bufp > 0) ? buf[--bufp] : getchar(); 162 | } 163 | 164 | void ungetch(int c) { 165 | if (bufp >= BUFSIZE) 166 | printf("ungetch: too many characters\n"); 167 | else 168 | buf[bufp++] = c; 169 | } 170 | -------------------------------------------------------------------------------- /Exercise 6-3/cross_referencer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAXWORD 100 7 | #define MAX_WORD_COUNT 100 8 | 9 | #define NOISEWORDS_SIZE (sizeof noisewords / sizeof noisewords[0]) 10 | 11 | // words in noisewords must be ordered lexicographically 12 | 13 | char *noisewords[] = { 14 | "a", "an", "and", "are", "at", "be", "by", "can", "did", "do", "done", 15 | "for", "from", "have", "he", "her", "his", "if", "in", "into", "is", "it", 16 | "its", "many", "must", "no", "none", "not", "of", "off", "on", "or", 17 | "our", "ours", "so", "such", "that", "the", "them", "they", "their", 18 | "this", "to", "too", "us", "was", "we", "were", "what", "who", "with", 19 | "without" 20 | }; 21 | 22 | struct tnode { 23 | char *word; 24 | int lines[MAX_WORD_COUNT]; 25 | int index; 26 | struct tnode *left; 27 | struct tnode *right; 28 | }; 29 | 30 | struct tnode *addtree(struct tnode *, char *); 31 | void treeprint(struct tnode *); 32 | int getword(char *, int); 33 | int binsearch(char *, char * noisewords[], int); 34 | 35 | int LINE_NUMBER = 1; 36 | 37 | /* word frequency count */ 38 | main() { 39 | 40 | struct tnode *root; 41 | char word[MAXWORD]; 42 | 43 | root = NULL; 44 | while (getword(word, MAXWORD) != EOF) 45 | if (isalpha(word[0])) 46 | if (binsearch(word, noisewords, NOISEWORDS_SIZE) == -1) 47 | root = addtree(root, word); 48 | treeprint(root); 49 | 50 | return 0; 51 | } 52 | 53 | struct tnode *talloc(void); 54 | 55 | /* addtree: add a node with w, at or below p */ 56 | struct tnode *addtree(struct tnode *p, char *w) { 57 | 58 | int cond; 59 | 60 | if (p == NULL) { 61 | p = talloc(); 62 | p->word = strdup(w); 63 | p->lines[p->index++] = LINE_NUMBER; 64 | p->left = p->right = NULL; 65 | } else if ((cond = strcmp(w, p->word)) == 0) { 66 | if (p->lines[p->index - 1] != LINE_NUMBER) 67 | p->lines[p->index++] = LINE_NUMBER; 68 | } else if (cond < 0) 69 | p->left = addtree(p->left, w); 70 | else 71 | p->right = addtree(p->right, w); 72 | 73 | return p; 74 | } 75 | 76 | /* treeprint: in-order print of tree */ 77 | void treeprint(struct tnode *p) { 78 | 79 | int i; 80 | 81 | if (p != NULL) { 82 | treeprint(p->left); 83 | printf("%s - ", p->word); 84 | for (i = 0; i < p->index; i++) 85 | printf("%d, ", p->lines[i]); 86 | printf("\n"); 87 | treeprint(p->right); 88 | } 89 | } 90 | 91 | int binsearch(char *word, char *noisewords[], int n) { 92 | 93 | int cond; 94 | int low, high, mid; 95 | 96 | low = 0; 97 | high = n - 1; 98 | while (low <= high) { 99 | mid = (low + high) / 2; 100 | // use strcasecmp from string.h - case-insensitive comparison 101 | if ((cond = strcasecmp(word, noisewords[mid])) < 0) 102 | high = mid - 1; 103 | else if (cond > 0) 104 | low = mid + 1; 105 | else 106 | return mid; 107 | } 108 | 109 | return -1; 110 | } 111 | 112 | int getword(char *word, int lim) { 113 | 114 | int c, getch(void); 115 | void ungetch(int); 116 | char *w = word; 117 | 118 | while (isspace(c = getch()) && c != '\n') 119 | ; 120 | if (c != EOF) 121 | *w++ = c; 122 | if (!isalpha(c)) { 123 | if (c == '\n') 124 | LINE_NUMBER++; 125 | *w = '\0'; 126 | return c; 127 | } 128 | for (; --lim > 0; w++) { 129 | if (!isalnum(*w = getch())) { 130 | ungetch(*w); 131 | break; 132 | } 133 | } 134 | *w = '\0'; 135 | return word[0]; 136 | } 137 | 138 | #define BUFSIZE 100 139 | 140 | char buf[BUFSIZE]; 141 | int bufp = 0; 142 | 143 | int getch(void) { 144 | return (bufp > 0) ? buf[--bufp] : getchar(); 145 | } 146 | 147 | void ungetch(int c) { 148 | if (bufp >= BUFSIZE) 149 | printf("ungetch: too many characters\n"); 150 | else 151 | buf[bufp++] = c; 152 | } 153 | 154 | /* talloc: make a node */ 155 | struct tnode *talloc(void) { 156 | struct tnode *p = (struct tnode *) malloc(sizeof (struct tnode)); 157 | p->index = 0; 158 | return p; 159 | } 160 | -------------------------------------------------------------------------------- /Exercise 6-3/cs_poetry.txt: -------------------------------------------------------------------------------- 1 | The huge sky overseeing the emerald and bluish earth... 2 | wouldn't be the only sky in our incredibly diverse Universe, 3 | if limited sight weren't the obstacle to the awesome images that surprise 4 | couldn't conceal; 5 | but many more galaxies hiding their splendid suns and planets,, 6 | are still unknown and Man, overtaken by such a magnificence, expresses 7 | himself in more atheistic ways not to compromise his own foolishness! 8 | If we declare faith non-existent, cupidity can become our fetish... 9 | filling us with more rampant pride to enforce its hypocritical seal! 10 | 11 | 12 | 13 | 14 | More universes, like ours, lay dormant in their stillness, 15 | " And will life be found on them? " is a question too inconclusive 16 | that we can only answer by being so compellingly delusive; 17 | more universes await the discoveries of the intelligent mind, 18 | to lay out their awsomeness and beauty to discard the thought of finding life, 19 | impelling us to preserve ours, not to destroy it by valiance or insanity! 20 | Search history's events, are we capable of pursuing happiness... 21 | without conquering and proclaiming our power with mighty armies? 22 | 23 | 24 | 25 | 26 | In ancient days, they created unrealistic gods and goddesses... 27 | not conceiving that the Supreme One wasn't a god in human form, 28 | but rather the Invisible One, who often scolded them for their wickedness; 29 | so in stone and marble they continued to sculpture divine faces 30 | that the common people hailed and worshipped, and would they refuse 31 | to obey their tyrant's wishes: their worthless lives would be taken... 32 | and did Paul, the follower of Christ, go back to that cult so perverse? 33 | We know, from the Holy Scriptures, he was converted and put down his sword... 34 | 35 | 36 | 37 | 38 | More universes more magnificent than this one, 39 | can be discovered and inhabited if they are livable; 40 | and scientists are working hard along with astronauts to accomplish our dream, 41 | and who isn't excited and show interest to take a voyage into the outer space? 42 | Navigators ventured on perilous seas to attest that their concept was solid 43 | and real; 44 | we, with more sophisticated computer science, are groped by the unthinkable! 45 | Persuaded or not, discouraged or doubtful, researches must continue at our 46 | expense; 47 | and what if we were successful, wouldn't everyone be taken by shock? 48 | 49 | -------------------------------------------------------------------------------- /Exercise 6-4/cs_poetry.txt: -------------------------------------------------------------------------------- 1 | The huge sky overseeing the emerald and bluish earth... 2 | wouldn't be the only sky in our incredibly diverse Universe, 3 | if limited sight weren't the obstacle to the awesome images that surprise 4 | couldn't conceal; 5 | but many more galaxies hiding their splendid suns and planets,, 6 | are still unknown and Man, overtaken by such a magnificence, expresses 7 | himself in more atheistic ways not to compromise his own foolishness! 8 | If we declare faith non-existent, cupidity can become our fetish... 9 | filling us with more rampant pride to enforce its hypocritical seal! 10 | 11 | 12 | 13 | 14 | More universes, like ours, lay dormant in their stillness, 15 | " And will life be found on them? " is a question too inconclusive 16 | that we can only answer by being so compellingly delusive; 17 | more universes await the discoveries of the intelligent mind, 18 | to lay out their awsomeness and beauty to discard the thought of finding life, 19 | impelling us to preserve ours, not to destroy it by valiance or insanity! 20 | Search history's events, are we capable of pursuing happiness... 21 | without conquering and proclaiming our power with mighty armies? 22 | 23 | 24 | 25 | 26 | In ancient days, they created unrealistic gods and goddesses... 27 | not conceiving that the Supreme One wasn't a god in human form, 28 | but rather the Invisible One, who often scolded them for their wickedness; 29 | so in stone and marble they continued to sculpture divine faces 30 | that the common people hailed and worshipped, and would they refuse 31 | to obey their tyrant's wishes: their worthless lives would be taken... 32 | and did Paul, the follower of Christ, go back to that cult so perverse? 33 | We know, from the Holy Scriptures, he was converted and put down his sword... 34 | 35 | 36 | 37 | 38 | More universes more magnificent than this one, 39 | can be discovered and inhabited if they are livable; 40 | and scientists are working hard along with astronauts to accomplish our dream, 41 | and who isn't excited and show interest to take a voyage into the outer space? 42 | Navigators ventured on perilous seas to attest that their concept was solid 43 | and real; 44 | we, with more sophisticated computer science, are groped by the unthinkable! 45 | Persuaded or not, discouraged or doubtful, researches must continue at our 46 | expense; 47 | and what if we were successful, wouldn't everyone be taken by shock? 48 | 49 | -------------------------------------------------------------------------------- /Exercise 6-5/undef.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define HASHSIZE 101 6 | 7 | static struct nlist *hashtab[HASHSIZE]; /* pointer table */ 8 | 9 | struct nlist { /* table entry: */ 10 | struct nlist *next; /* next entry in chain */ 11 | char *name; /* defined name */ 12 | char *defn; /* replacement text */ 13 | }; 14 | 15 | unsigned hash(char *); 16 | struct nlist *lookup(char *); 17 | struct nlist *install(char *, char *); 18 | void undef(char *); 19 | 20 | int main(int argc, char** argv) { 21 | 22 | printf("hash(\"IN\") == 18? : %d\n", hash("IN") == 18); 23 | struct nlist *p = lookup("IN"); 24 | printf("lookup(\"IN\") == NULL? : %d\n", p == NULL); 25 | p = install("IN", "TEXT"); 26 | printf("install(\"IN\", \"TEXT\") == NULL? : %d\n", p == NULL); 27 | p = lookup("IN"); 28 | printf("lookup(\"IN\" == NULL? : %d\n", p == NULL); 29 | undef(p->name); 30 | printf("undef(\"IN\")\n"); 31 | p = lookup("IN"); 32 | printf("lookup(\"IN\") == NULL? : %d\n", p == NULL); 33 | 34 | return 0; 35 | } 36 | 37 | /* hash: form hash value from string s */ 38 | unsigned hash(char *s) { 39 | unsigned hashval; 40 | 41 | for (hashval = 0; *s != '\0'; s++) 42 | hashval = *s + 31 * hashval; 43 | 44 | return hashval % HASHSIZE; 45 | } 46 | 47 | /* lookup: look for s in hashtab */ 48 | struct nlist *lookup(char *s) { 49 | struct nlist *np; 50 | 51 | for (np = hashtab[hash(s)]; np != NULL; np = np->next) 52 | if (strcmp(np->name, s) == 0) 53 | return np; /* found */ 54 | return NULL; /* not found */ 55 | } 56 | 57 | /* install: put (name, defn) in hashtab */ 58 | struct nlist *install(char *name, char* defn) { 59 | struct nlist *np; 60 | unsigned hashval; 61 | 62 | if ((np = lookup(name)) == NULL) { /* not found */ 63 | np = (struct nlist *) malloc(sizeof (*np)); 64 | if (np == NULL || (np->name = strdup(name)) == NULL) 65 | return NULL; 66 | hashval = hash(name); 67 | np->next = hashtab[hashval]; 68 | hashtab[hashval] = np; 69 | } else /* already there */ 70 | free((void *) np->defn); /* free previous defn */ 71 | if ((np->defn = strdup(defn)) == NULL) 72 | return NULL; 73 | return np; 74 | } 75 | 76 | /* undef: from s from hashtab */ 77 | void undef(char *s) { 78 | struct nlist *currentPtr, *previousPtr; 79 | 80 | for (previousPtr = NULL, currentPtr = hashtab[hash(s)]; 81 | currentPtr != NULL; 82 | previousPtr = currentPtr, currentPtr = currentPtr->next) { 83 | 84 | if (strcmp(currentPtr->name, s) == 0) { 85 | if (previousPtr == NULL) /* first element */ 86 | hashtab[hash(s)] = currentPtr->next; 87 | else /* element in the middle or at the end */ 88 | previousPtr->next = currentPtr->next; 89 | /* free memory */ 90 | free(currentPtr->name); 91 | free(currentPtr->defn); 92 | free(currentPtr); 93 | return; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Exercise 7-1/conversion.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char** argv) { 6 | 7 | int c; 8 | 9 | //In Netbeans argv[0] is the program name 10 | 11 | if (argc < 2) { 12 | printf("No argument given (tolower or toupper)\n"); 13 | return 1; 14 | } else if (strcmp(argv[1], "tolower") != 0 && strcmp(argv[1], "toupper") != 0) { 15 | printf("Argument must be either 'tolower' or 'toupper'\n"); 16 | return 1; 17 | } 18 | 19 | if (!strcmp("tolower", argv[1])) 20 | while ((c = getchar()) != EOF) 21 | putchar(tolower(c)); 22 | else if (!strcmp("toupper", argv[1])) 23 | while ((c = getchar()) != EOF) 24 | putchar(toupper(c)); 25 | else 26 | printf("Argument must be 'tolwer' or 'toupper'\n"); 27 | 28 | return 0; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Exercise 7-1/lines.txt: -------------------------------------------------------------------------------- 1 | Computer science is abbreviated as "comp sci." 2 | Comp sci is so hard it gives you a sigh. 3 | Computing is everywhere in the world of sci-fi. 4 | Network is so prevalent these days you can't get by without a wi-fi. 5 | When I said so to a Scotsman, all he said was "aye." 6 | He's such a jolly, handsome, agreeable, but sometimes nervous guy. 7 | He's a sincere, honest, and serious person, and never tells a lie. 8 | One weakness he has is that when he's with a girl, he gets shy. 9 | As a student he worked part-time working in a pigsty. 10 | After getting used to the smelly pigs, he learned to work with them under a clear, blue sky. 11 | At the end of work each day, he cheerfully says to the pigs goodbye. 12 | Once he came up with an idea of a prank, and he entered into the pigsty on the sly. 13 | The hay and everything else there was really dry. 14 | Usually they ought to be slightly wet, and he wondered why. 15 | Maybe it was because of something done by an international spy. 16 | That, he thought, was something nobody can ever deny. 17 | My Scots friend was so poor he had a hard time in getting by. 18 | There was even a time he was so desperate that when I talked to him he didn't even reply. 19 | I was so shocked at his destitute state I could not help but cry. 20 | At the sight of my response, he could not help but say, "Oh, my!" 21 | 22 | My Scottish friend once lived very far and decided to live nigh. 23 | Near his new place was a little shop that sold everything made of rye. 24 | He bought a splendid piece of bread there on the Fourth of July. 25 | There he also bought something he always wanted to give me: an apple pie. 26 | He just had to give all that to me although there was a risk of oversupply. 27 | He also thought the merchandise looked so delicious he thought it was a good buy. 28 | When he came to my place with that small gifts, I was with a Thai. 29 | And also, I was wearing what I usually don't wear: a beautiful tie. 30 | It was so brilliant something came flying to my tie, 31 | and I realized it was something I don't care for very much: a fly. 32 | Right at that moment, somebody I never expected slowly came by. 33 | The stranger looked wicked, with a crooked mouth, and with an evil eye. 34 | My Scottish friend, my Thai friend, and I together got into a fight with the wicked guy. 35 | Then my final punch gave him a black eye. 36 | The crooked man left immediately, without any intention again to drop by. 37 | He uttered a word just before leaving, but I don't think he had anything to imply. 38 | He was some Westerner doing some business with a gangster in Shanghai. 39 | -------------------------------------------------------------------------------- /Exercise 7-2/print_arbitrary.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_COL 80 6 | 7 | #define TAB_SIZE 8 //tab space on my system 8 | 9 | int main(int argc, char** argv) { 10 | 11 | int c; 12 | short col = 0; 13 | 14 | if (argc < 2) { 15 | printf("No argument given\n"); 16 | return 1; 17 | } else if (strcmp(argv[1], "hex") != 0 && strcmp(argv[1], "oct") != 0) { 18 | printf("Argument must be either 'hex' or 'oct'\n"); 19 | return 1; 20 | } 21 | 22 | while ((c = getchar()) != EOF) { 23 | if (!isprint(c) && !iscntrl(c)) { 24 | if (strcmp(argv[1], "hex") == 0) 25 | printf("%#.2x", c); 26 | else 27 | printf("%#.3o", c); 28 | col += 4; 29 | } else { 30 | putchar(c); 31 | col++; 32 | if (col >= MAX_COL - TAB_SIZE) 33 | col = 0, putchar('\n'); 34 | if (c == '\n') 35 | col = 0; 36 | if (c == '\t') 37 | col += TAB_SIZE; 38 | } 39 | } 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /Exercise 7-3/minprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAXLINE 100 7 | 8 | /* minprintf: minimal printf with variable argument list */ 9 | void minprintf(char *fmt, ...) { 10 | va_list ap; /* points to each unnamed arg in turn */ 11 | char fmt_chars[MAXLINE]; 12 | int n; 13 | char *p, *sval; 14 | int ival; 15 | unsigned uval; 16 | double dval; 17 | 18 | va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 19 | for (p = fmt; *p; p++) { 20 | if (*p != '%') { 21 | putchar(*p); 22 | continue; 23 | } 24 | n = 0; 25 | fmt_chars[n++] = '%'; 26 | while ( *(p+1) && !isalpha(*(p+1)) ) 27 | fmt_chars[n++] = *++p; 28 | fmt_chars[n++] = *(p+1); 29 | fmt_chars[n] = '\0'; 30 | switch (*++p) { 31 | case 'd': 32 | case 'i': 33 | case 'c': 34 | ival = va_arg(ap, int); 35 | printf(fmt_chars, ival); 36 | break; 37 | case 'u': 38 | uval = va_arg(ap, unsigned); 39 | printf(fmt_chars, uval); 40 | break; 41 | case 'f': 42 | dval = va_arg(ap, double); 43 | printf(fmt_chars, dval); 44 | break; 45 | case 's': 46 | for (sval = va_arg(ap, char *); *sval; sval++) 47 | putchar(*sval); 48 | break; 49 | case 'o': 50 | case 'O': 51 | case 'x': 52 | case 'X': 53 | ival = va_arg(ap, int); 54 | printf(fmt_chars, ival); 55 | break; 56 | case 'e': 57 | case 'E': 58 | case 'g': 59 | case 'G': 60 | dval = va_arg(ap, double); 61 | printf(fmt_chars, dval); 62 | break; 63 | default: 64 | printf("%s", fmt_chars+1); 65 | break; 66 | } 67 | } 68 | va_end(ap); /* clean up when done */ 69 | } 70 | 71 | int main() { 72 | 73 | minprintf("Integers: %d, %i\n", 1, 2); 74 | minprintf("Unsigned: %u\n", ~0); 75 | minprintf("Float: %f\n", 1.23456789); 76 | minprintf("String: %s\n", "Hello World!"); 77 | minprintf("Octal: %o\n", 63); 78 | minprintf("Hexadecimal: %x\n", 255); 79 | minprintf("Hexadecimal: %X\n", 255); 80 | minprintf("Char (newline): %c", '\n'); 81 | minprintf("Exponential: %e\n", 300e6); 82 | minprintf("Exponential: %E\n", 6626e-37); 83 | minprintf("%%g: %g\n", 300000000.); 84 | minprintf("%%G: %G\n", 0.000005); 85 | minprintf("Percentage symbol: %%\n"); 86 | 87 | return 0; 88 | } 89 | 90 | -------------------------------------------------------------------------------- /Exercise 7-4/minscanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define MAXLINE 100 7 | 8 | void minscanf(char *fmt, ...) { 9 | va_list ap; /* points to each unnamed arg in turn */ 10 | char fmt_chars[MAXLINE]; 11 | char *p, *sval, *cval; 12 | int *ival, i; 13 | unsigned int *uval; 14 | float *fval; 15 | 16 | va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 17 | i = 0; 18 | for (p = fmt; *p; p++) { 19 | if (*p != '%') { 20 | fmt_chars[i++] = *p; 21 | continue; 22 | } 23 | fmt_chars[i++] = '%'; 24 | while ( *(p+1) && !isalpha(*(p+1)) ) 25 | fmt_chars[i++] = *++p; 26 | fmt_chars[i++] = *(p+1); 27 | fmt_chars[i] = '\0'; 28 | switch (*++p) { 29 | case 'd': 30 | case 'i': 31 | ival = va_arg(ap, int*); 32 | scanf(fmt_chars, ival); 33 | break; 34 | case 'u': 35 | case 'x': 36 | case 'X': 37 | case 'o': 38 | uval = va_arg(ap, unsigned int *); 39 | scanf(fmt_chars, uval); 40 | break; 41 | case 'f': 42 | fval = va_arg(ap, float*); 43 | scanf(fmt_chars, fval); 44 | break; 45 | case 's': 46 | sval = va_arg(ap, char *); 47 | scanf(fmt_chars, sval); 48 | break; 49 | case 'c': 50 | cval = va_arg(ap, char*); 51 | scanf(fmt_chars, cval); 52 | break; 53 | case 'e': 54 | fval = va_arg(ap, float*); 55 | scanf(fmt_chars, fval); 56 | break; 57 | case 'E': 58 | fval = va_arg(ap, float*); 59 | scanf(fmt_chars, fval); 60 | break; 61 | case 'g': 62 | fval = va_arg(ap, float*); 63 | scanf(fmt_chars, fval); 64 | break; 65 | case 'G': 66 | fval = va_arg(ap, float*); 67 | scanf(fmt_chars, fval); 68 | break; 69 | default: 70 | scanf("", fmt_chars); 71 | break; 72 | } 73 | i = 0; //reset 74 | } 75 | va_end(ap); /* clean up when done */ 76 | } 77 | 78 | int main(int argc, char** argv) { 79 | 80 | unsigned int u; 81 | int i1, i2; 82 | float f1, f2; 83 | double d; 84 | char c; 85 | char s[1000]; 86 | 87 | 88 | printf("Type in two integers. The second integer can be octal or hexadecimal.\n"); 89 | minscanf("%d %i", &i1, &i2); 90 | printf("Integer: %d %i\n", i1, i2); 91 | 92 | printf("Type in an unsigned integers\n"); 93 | minscanf("%u", &u); 94 | printf("Unsigned: %u\n", u); 95 | 96 | printf("Type in two floating point numbers\n"); 97 | minscanf("%f %f", &f1, &f2); 98 | printf("Float: %f %f\n", f1, f2); 99 | 100 | printf("Type in a string. A string is read until the next white space.\n"); 101 | minscanf("%s", s); 102 | printf("String: %s\n", s); 103 | 104 | printf("Type in an octal number\n"); 105 | minscanf("%o", &i1); 106 | printf("Octal: %d\n", i1); 107 | 108 | printf("Type in a hexadecimal number\n"); 109 | minscanf("%x", &i1); 110 | printf("Hexadecimal: %d\n", i1); 111 | 112 | printf("Type in a hexadecimal number\n"); 113 | minscanf("%X", &i1); 114 | printf("Hexadecimal: %d\n", i1); 115 | 116 | printf("Type in a character"); 117 | minscanf("%c", &c); 118 | printf("(Newline consumed)\n"); 119 | minscanf("%c", &c); 120 | printf("Char: %c\n", c); 121 | 122 | printf("Type in two exponential numbers\n"); 123 | minscanf("%e %E", &f1, &f2); 124 | printf("Exponentials: %e %E\n", f1, f2); 125 | 126 | printf("Type in two exponential numbers\n"); 127 | minscanf("%g %G", &f1, &f2); 128 | printf("Exponentials: %g %G\n", f1, f2); 129 | 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /Exercise 7-5/calculator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXOP 100 /* max size of operand or operator */ 5 | 6 | int getop(char[]); 7 | void push(double); 8 | double pop(void); 9 | double top(void); 10 | 11 | /* 12 | * scanf is used to read a string until EOF is returned. 13 | * The string is scanned with sscanf. First to see if the string 14 | * represents a number. If the string is not a number then sscanf is used 15 | * to see if it is an operator. 16 | * The result is not automatically printed when a newline is read. Instead the 17 | * user has to type p to print the result from the stack. 18 | * The function top is used to retrieve the top of the stack. 19 | */ 20 | 21 | /* reverse Polish calculator */ 22 | main() { 23 | double op1, op2; 24 | char s[MAXOP], c; 25 | 26 | while (scanf("%s", s) != EOF) { 27 | if (sscanf(s, "%lf", &op1) == 1) { 28 | push(op1); 29 | } else if (sscanf(s, "%c", &c) == 1) { 30 | switch (c) { 31 | case '+': 32 | push(pop() + pop()); 33 | break; 34 | case '*': 35 | push(pop() * pop()); 36 | break; 37 | case '-': 38 | op2 = pop(); 39 | push(pop() - op2); 40 | break; 41 | case '/': 42 | op2 = pop(); 43 | if (op2 != 0.0) 44 | push(pop() / op2); 45 | else 46 | printf("error: zero divisor\n"); 47 | break; 48 | case 'p': 49 | printf("\t%.8g\n", top()); 50 | break; 51 | default: 52 | printf("error: unknown command %s\n", s); 53 | break; 54 | } 55 | } 56 | } 57 | 58 | return 0; 59 | } 60 | 61 | 62 | #define MAXVAL 100 /* maximum depth of val stack */ 63 | 64 | int sp = 0; 65 | /* next free stack position */ 66 | double val[MAXVAL]; 67 | /* value stack */ 68 | 69 | /* push: push f onto value stack */ 70 | void push(double f) { 71 | if (sp < MAXVAL) 72 | val[sp++] = f; 73 | else 74 | printf("error: stack full, can′t push %g\n", f); 75 | 76 | } 77 | 78 | /* pop: pop and return top value from stack */ 79 | double pop(void) { 80 | if (sp > 0) 81 | return val[--sp]; 82 | else { 83 | printf("error: stack empty\n"); 84 | return 0.0; 85 | } 86 | } 87 | 88 | /* top: return top value from stack */ 89 | double top(void) { 90 | if (sp > 0) 91 | return val[sp - 1]; 92 | else { 93 | printf("error: stack empty\n"); 94 | return 0.0; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Exercise 7-6/diff_first.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINE 1000 5 | 6 | int main(int argc, char** argv) { 7 | 8 | FILE *fp1, *fp2; 9 | char line1[MAXLINE], line2[MAXLINE]; 10 | char *filename1, *filename2; 11 | 12 | if (argc != 3) { 13 | printf("error: program must be called with two arguments\n"); 14 | return 1; 15 | } 16 | 17 | 18 | filename1 = *++argv; 19 | filename2 = *++argv; 20 | if ((fp1 = fopen(filename1, "r")) == NULL) { 21 | fprintf(stderr, "can't open %s\n", filename1); 22 | return 1; 23 | } 24 | if ((fp2 = fopen(filename2, "r")) == NULL) { 25 | fprintf(stderr, "can't open %s\n", filename2); 26 | return 1; 27 | } 28 | 29 | while (fgets(line1, MAXLINE, fp1) != NULL && 30 | fgets(line2, MAXLINE, fp2) != NULL) { 31 | if (strcmp(line1, line2) != 0) { 32 | printf("%s: %s", filename1, line1); 33 | printf("%s: %s", filename2, line2); 34 | break; 35 | } 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /Exercise 7-6/file1.txt: -------------------------------------------------------------------------------- 1 | Oh, Marcia, 2 | I want your long blonde beauty 3 | to be taught in high school, 4 | so kids will learn that God 5 | lives like music in the skin 6 | and sounds like a sunshine harpsicord. 7 | 8 | I want high school report cards 9 | to look like this: 10 | 11 | Playing with Gentle Glass Things 12 | A 13 | 14 | Computer Magic 15 | A 16 | 17 | Writing Letters to Those You Love 18 | A 19 | 20 | Finding out about Fish 21 | A 22 | 23 | Marcia's Long Blonde Beauty 24 | A+! -------------------------------------------------------------------------------- /Exercise 7-6/file2.txt: -------------------------------------------------------------------------------- 1 | Oh, Marcia, 2 | I want your long blonde beauty 3 | to be taught in high school, 4 | so kids will learn that God 5 | lives like music in the skin 6 | and sounds like a sunshine harpsicord. 7 | 8 | I want high school report cards 9 | to look like this: 10 | 11 | Playing with Gentle Glass Things 12 | A 13 | 14 | Computer Science 15 | A 16 | 17 | Writing Letters to Those You Love 18 | A 19 | 20 | Finding out about Fish 21 | A 22 | 23 | Marcia's Long Blonde Beauty 24 | A+! -------------------------------------------------------------------------------- /Exercise 7-7/file1.txt: -------------------------------------------------------------------------------- 1 | Still I Rise 2 | by Maya Angelou 3 | 4 | You may write me down in history 5 | With your bitter, twisted lies, 6 | You may trod me in the very dirt 7 | But still, like dust, I'll rise. 8 | 9 | 10 | Does my sassiness upset you? 11 | Why are you beset with gloom? 12 | 'Cause I walk like I've got oil wells 13 | Pumping in my living room. 14 | 15 | 16 | Just like moons and like suns, 17 | With the certainty of tides, 18 | Just like hopes springing high, 19 | Still I'll rise. 20 | 21 | 22 | Did you want to see me broken? 23 | Bowed head and lowered eyes? 24 | Shoulders falling down like teardrops. 25 | 26 | Weakened by my soulful cries. 27 | 28 | 29 | Does my haughtiness offend you? 30 | Don't you take it awful hard 31 | 'Cause I laugh like I've got gold mines 32 | Diggin' in my own back yard. 33 | 34 | 35 | You may shoot me with your words, 36 | You may cut me with your eyes, 37 | You may kill me with your hatefulness, 38 | But still, like air, I'll rise. 39 | 40 | 41 | Does my sexiness upset you? 42 | Does it come as a surprise 43 | That I dance like I've got diamonds 44 | At the meeting of my thighs? 45 | 46 | Out of the huts of history's shame 47 | I rise 48 | Up from a past that's rooted in pain 49 | I rise 50 | I'm a black ocean, leaping and wide, 51 | Welling and swelling I bear in the tide. 52 | 53 | Leaving behind nights of terror and fear 54 | I rise 55 | Into a daybreak that's wondrously clear 56 | I rise 57 | Bringing the gifts that my ancestors gave, 58 | I am the dream and the hope of the slave. 59 | 60 | I rise 61 | I rise 62 | I rise. -------------------------------------------------------------------------------- /Exercise 7-7/file2.txt: -------------------------------------------------------------------------------- 1 | Im nobody! Who are you? 2 | by Emily Dickinson 3 | 4 | I'm nobody! Who are you? 5 | Are you nobody, too? 6 | Then there's a pair of us -- don't tell! 7 | They'd advertise -- you know! 8 | 9 | How dreary to be somebody! 10 | How public like a frog 11 | To tell one's name the livelong day 12 | To an admiring bog! -------------------------------------------------------------------------------- /Exercise 7-7/file3.txt: -------------------------------------------------------------------------------- 1 | A Red Red Rose 2 | by Robert Burns 3 | 4 | O, my Luve's like a red, red rose, 5 | That's newly sprung in June. 6 | 7 | O, my Luve's like a melodie 8 | That's sweetly play'd in tune. 9 | 10 | 11 | As fair as thou, my bonnie lass, 12 | So deep in luve am I; 13 | And I will love thee still, my dear, 14 | Till a' the seas gang dry. 15 | 16 | 17 | Till a' the seas gang dry, my dear, 18 | And the rocks melt wi' the sun: 19 | I will love thess till, my dear, 20 | While the sands o' life shall run: 21 | 22 | And fare thee well, my only luve! 23 | And fare thee weel, a while! 24 | And I will come again, my luve, 25 | Tho' it ware ten thousand mile. -------------------------------------------------------------------------------- /Exercise 7-7/pattern_matching_files.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAXLINE 1000 5 | 6 | /* find: print lines that match pattern from 1st arg */ 7 | int main(int argc, char** argv) { 8 | 9 | FILE *fp; 10 | char *text; 11 | char line[MAXLINE]; 12 | long lineno = 0; 13 | int c, except = 0, number = 0, found = 0; 14 | 15 | while (--argc > 0 && (*++argv)[0] == '-') 16 | while (c = *++argv[0]) 17 | switch (c) { 18 | case 'x': 19 | except = 1; 20 | break; 21 | case 'n': 22 | number = 1; 23 | break; 24 | default: 25 | printf("find: illegal option %c\n", c); 26 | argc = 0; 27 | found = -1; 28 | } 29 | 30 | if (argc <= 1) 31 | printf("Usage: find -x -n pattern [file1] [file2] [...]\n"); 32 | else { 33 | text = *argv; 34 | while ((--argc > 0) && (fp = fopen(*++argv, "r")) != NULL) { 35 | lineno = 0; 36 | while (fgets(line, MAXLINE, fp) > 0) { 37 | lineno++; 38 | if ((strstr(line, text) != NULL) != except) { 39 | if (number) 40 | printf("%ld:", lineno); 41 | printf("%s: %s", *argv, line); 42 | found++; 43 | } 44 | } 45 | if (ferror(fp)) 46 | fprintf(stderr, "%s: file error\n", *argv); 47 | fclose(fp); 48 | } 49 | } 50 | 51 | 52 | 53 | return found; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /Exercise 7-8/Poem: -------------------------------------------------------------------------------- 1 | By Steve Jackson, 2 | with apologies to Robert Frost. 3 | 4 | Whose code this is I think I know 5 | he’s on a different project, though 6 | he will not see me working here 7 | to simplify the data flow 8 | 9 | My oldest friends would think it queer 10 | that I allow my own career 11 | to keep me till such hours awake 12 | so many evenings of the year 13 | 14 | I save my changes, then run make 15 | and give my wrists a little shake 16 | The only other sound’s the beep 17 | that says I’ve made a small mistake. 18 | 19 | Bed would be lovely, soft and deep, 20 | but I’ve a deadline I must keep 21 | and much to write before I sleep, 22 | and much to write before I sleep. 23 | 24 | -------------------------------------------------------------------------------- /Exercise 7-8/Poems: -------------------------------------------------------------------------------- 1 | Basic Principles 2 | 3 | Coupling, Cohesion 4 | Antagonistic forces 5 | Tradeoffs to be made. 6 | 7 | Chaining 8 | 9 | Solvers in a chain 10 | Requests passed one to the next 11 | Only one reacts. 12 | 13 | The Stand-in 14 | 15 | Looks like the real thing 16 | But really hides it from view 17 | Protect, remote, smart. 18 | 19 | Sharing 20 | 21 | Actions are the same 22 | Processes come together 23 | Continue apart. 24 | 25 | Timed Systems 26 | 27 | Time passes freely 28 | Ticks never inconsistent 29 | The system runs true. 30 | 31 | Real-Time Systems 32 | 33 | Time is essential 34 | On time, not late, not early 35 | Fail predictably. 36 | 37 | Object Behavior 38 | 39 | States and transitions 40 | Statechart defines behavior 41 | Or hide it in code. 42 | 43 | A Watchdog 44 | 45 | Waiting for the strokes 46 | Stroke, something is working, stroke 47 | No stroke comes, woof, woof. 48 | -------------------------------------------------------------------------------- /Exercise 7-8/print_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MAX_PAGE_LINES 30 5 | #define MAXLINE 1000 6 | 7 | void print_file(char *); 8 | 9 | int main(int argc, char** argv) { 10 | 11 | if (argc == 1) { 12 | printf("No files specified\n"); 13 | return 1; 14 | } 15 | 16 | while (--argc > 0) { 17 | print_file(*++argv); 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | void print_file(char *file) { 24 | FILE *fp; 25 | char line[MAXLINE]; 26 | int lineno = 0; 27 | int page = 1; 28 | 29 | if ((fp = fopen(file, "r")) == NULL) { 30 | printf("%s: error opening file\n", file); 31 | return; 32 | } 33 | 34 | printf("----------New file----------\n"); 35 | printf("Title: %s\n\n", file); 36 | 37 | while (fgets(line, MAXLINE, fp) != NULL) { 38 | if (lineno % MAX_PAGE_LINES == 0) { 39 | printf("Page %d\n", page); 40 | page++; 41 | } 42 | printf("%s", line); 43 | lineno++; 44 | } 45 | 46 | if (ferror(fp)) { 47 | fprintf(stderr, "%s: error in file\n", file); 48 | } 49 | 50 | fclose(fp); 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Exercise 7-9/is_upper.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Macro. Suitable only for ASCII character set 4 | * Faster, but takes more space for program code 5 | * due to macro expansion. 6 | * 7 | * Can be problematic if c has side effects. 8 | * It appears twice. 9 | */ 10 | #define isupper_macro(c) ((c >= 'A') && (c <= 'Z') ? 1 : 0) 11 | 12 | /* Function declaration */ 13 | int isupper_function(char); 14 | 15 | 16 | int main(int argc, char** argv) { 17 | 18 | char c = 'B'; 19 | 20 | printf("isupper_macro(%c): %d\n", c, isupper_macro(c)); 21 | printf("isupper_function(%c): %d\n", c, isupper_function(c)); 22 | c = 'b'; 23 | printf("isupper_macro(%c): %d\n", c, isupper_macro(c)); 24 | printf("isupper_function(%c): %d\n", c, isupper_function(c)); 25 | 26 | return 0; 27 | } 28 | 29 | 30 | /* 31 | * Function: Suitable only for ASCII character set. 32 | * Takes less space for program code, but slower due 33 | * to function call overhead 34 | */ 35 | int isupper_function(char c) { 36 | return (c >= 'A' && c <= 'Z'); 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Exercise 8-1/cat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "syscall.h" 3 | #include 4 | 5 | void error(char *fmt, ...); 6 | 7 | /* cat: concatenate file */ 8 | int main(int argc, char** argv) { 9 | 10 | int fd; 11 | void filecopy(int, int); 12 | char *prog = argv[0]; /* program name for errors */ 13 | 14 | if (argc == 1) 15 | filecopy(0, 1); 16 | else 17 | while (--argc > 0) 18 | if ((fd = open(*++argv, O_RDONLY, 0)) == -1) 19 | error("%s: can't open %s\n", prog, *argv); 20 | else { 21 | filecopy(fd, 1); 22 | close(fd); 23 | } 24 | 25 | return 0; 26 | } 27 | 28 | /* filecopy: copy file ifp to file ofp */ 29 | void filecopy(int fdin, int fdout) { 30 | char buf[BUFSIZ]; 31 | int n; 32 | 33 | while ((n = read(fdin, buf, BUFSIZ)) > 0) 34 | write(fdout, buf, n); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Exercise 8-2/bitop/_fillbuf.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | FILE _iob[OPEN_MAX] = {/* stdin, stdout, stderr: */ 4 | { 0, (char *) 0, (char *) 0, _READ, 0}, 5 | { 0, (char *) 0, (char *) 0, _WRITE, 1}, 6 | { 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2} 7 | }; 8 | 9 | #include 10 | 11 | #define PERMS 0666 /* RW for owner, group, other */ 12 | 13 | long int lseek(int fd, long int offset, int whence); 14 | 15 | /* fopen: open file, return file ptr */ 16 | FILE* fopen(char* name, char* mode) { 17 | 18 | int fd; 19 | FILE *fp; 20 | 21 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 22 | return NULL; 23 | 24 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 25 | if ((fp->flag & (_READ | _WRITE)) == 0) 26 | break; /* found free slot */ 27 | 28 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 29 | return NULL; 30 | 31 | if ((*mode == 'w')) 32 | fd = creat(name, PERMS); 33 | else if ((*mode == 'a')) { 34 | if ((fd = open(name, O_WRONLY, 0)) == -1) 35 | fd = creat(name, PERMS); 36 | lseek(fd, 0L, 2); 37 | } else 38 | fd = open(name, O_RDONLY, 0); 39 | 40 | if (fd == -1) /* couldn't access name */ 41 | return NULL; 42 | 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | fp->flag = (*mode == 'r') ? _READ : _WRITE; 47 | 48 | return fp; 49 | } 50 | 51 | void *malloc (long unsigned int size); 52 | long int read (int fd, void *buf, long unsigned int nbytes); 53 | 54 | /* _fillbuf: allocate and fill input buffer */ 55 | int _fillbuf(FILE *fp) { 56 | 57 | int bufsize; 58 | 59 | if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) 60 | return EOF; 61 | 62 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 63 | 64 | if (fp->base == NULL) /* no buffer yet */ 65 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 66 | return EOF; /* can't get buffer */ 67 | 68 | fp->ptr = fp->base; 69 | 70 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 71 | 72 | if (--fp->cnt < 0) { 73 | if (fp->cnt == -1) 74 | fp->flag |= _EOF; 75 | else 76 | fp->flag |= _ERR; 77 | fp->cnt = 0; 78 | return EOF; 79 | } 80 | 81 | return (unsigned char) *fp->ptr++; 82 | 83 | } 84 | 85 | long int write(int fd, void *bf, long unsigned int nbytes); 86 | 87 | int main(int argc, char *argv[]) { 88 | FILE *fp; 89 | char c; 90 | if ( (fp = fopen("lorem_ipsum.txt", "r")) == NULL ) 91 | return 1; 92 | else { 93 | while ( (c = getc(fp)) != EOF) 94 | write(1, &c, 1); 95 | } 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /Exercise 8-2/bitop/syscall.h: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | #define EOF (-1) 3 | #define BUFSIZ 1024 4 | #define OPEN_MAX 20 /* max #files open at once */ 5 | 6 | typedef struct _iofbuf { 7 | int cnt; /* character left */ 8 | char* ptr; /* next character position */ 9 | char* base; /* location of buffer */ 10 | int flag; /* mode of file access */ 11 | int fd; /* file descriptor */ 12 | } FILE; 13 | extern FILE _iob[OPEN_MAX]; 14 | 15 | #define stdin (&_iob[0]) 16 | #define stdout (&_iob[1]) 17 | #define stderr (&_iob[2]) 18 | 19 | enum _flags { 20 | _READ = 01, /* file open for reading */ 21 | _WRITE = 02, /* file open for writing */ 22 | _UNBUF = 04, /* file is unbuffered */ 23 | _EOF = 010, /* EOF has occured in this file */ 24 | _ERR = 020 /* error occured in this file */ 25 | }; 26 | 27 | int _fillbuf(FILE *); 28 | int _flushbuf(int, FILE *); 29 | 30 | #define feof(p) (((p)->flag & _EOF) != 0) 31 | #define ferror(p) (((p)->flag & _ERR) != 0) 32 | #define fileno(p) ((p)->fd) 33 | #define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) 34 | #define putc(x,p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 35 | #define getchar() getc(stdin) 36 | #define putchar(x) putc((x), stdout) 37 | 38 | -------------------------------------------------------------------------------- /Exercise 8-2/fields/_fillbuf.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | FILE _iob[OPEN_MAX] = {/* stdin, stdout, stderr: */ 4 | { 0, (char *) 0, (char *) 0, {1,0,0,0,0}, 0}, 5 | { 0, (char *) 0, (char *) 0, {0,1,0,0,0}, 1}, 6 | { 0, (char *) 0, (char *) 0, {0,1,1,0,0}, 2} 7 | }; 8 | 9 | #include 10 | 11 | #define PERMS 0666 /* RW for owner, group, other */ 12 | 13 | long int lseek(int fd, long int offset, int whence); 14 | 15 | /* fopen: open file, return file ptr */ 16 | FILE* fopen(char* name, char* mode) { 17 | 18 | int fd; 19 | FILE *fp; 20 | 21 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 22 | return NULL; 23 | 24 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 25 | if ((fp->flag._READ == 0) && (fp->flag._WRITE == 0)) 26 | break; /* found free slot */ 27 | 28 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 29 | return NULL; 30 | 31 | if ((*mode == 'w')) 32 | fd = creat(name, PERMS); 33 | else if ((*mode == 'a')) { 34 | if ((fd = open(name, O_WRONLY, 0)) == -1) 35 | fd = creat(name, PERMS); 36 | lseek(fd, 0L, 2); 37 | } else 38 | fd = open(name, O_RDONLY, 0); 39 | 40 | if (fd == -1) /* couldn't access name */ 41 | return NULL; 42 | 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | fp->flag._UNBUF = 0; 47 | fp->flag._EOF = 0; 48 | fp->flag._ERR = 0; 49 | if ( *mode == 'r' ) { 50 | fp->flag._READ = 1; 51 | fp->flag._WRITE = 0; 52 | } else { 53 | fp->flag._READ = 0; 54 | fp->flag._WRITE = 1; 55 | } 56 | 57 | return fp; 58 | } 59 | 60 | void *malloc (long unsigned int size); 61 | long int read (int fd, void *buf, long unsigned int nbytes); 62 | 63 | /* _fillbuf: allocate and fill input buffer */ 64 | int _fillbuf(FILE *fp) { 65 | 66 | int bufsize; 67 | 68 | if (fp->flag._READ == 0 || fp->flag._EOF == 1 || fp->flag._ERR == 1) 69 | return EOF; 70 | 71 | bufsize = (fp->flag._UNBUF == 1) ? 1 : BUFSIZ; 72 | 73 | if (fp->base == NULL) /* no buffer yet */ 74 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 75 | return EOF; /* can't get buffer */ 76 | 77 | fp->ptr = fp->base; 78 | 79 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 80 | 81 | if (--fp->cnt < 0) { 82 | if (fp->cnt == -1) 83 | fp->flag._EOF = 1; 84 | else 85 | fp->flag._ERR = 1; 86 | fp->cnt = 0; 87 | return EOF; 88 | } 89 | 90 | return (unsigned char) *fp->ptr++; 91 | 92 | } 93 | 94 | long int write(int, void*, long unsigned int); 95 | 96 | int main(int argc, char *argv[]) { 97 | FILE *fp; 98 | char c; 99 | if ( (fp = fopen("lorem_ipsum.txt", "r")) == NULL ) { 100 | return 1; 101 | } else { 102 | while ( (c = getc(fp)) != EOF) 103 | write(1, &c, 1); 104 | } 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /Exercise 8-2/fields/syscall.h: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | #define EOF (-1) 3 | #define BUFSIZ 1024 4 | #define OPEN_MAX 20 /* max #files open at once */ 5 | 6 | typedef struct _iofbuf { 7 | int cnt; /* character left */ 8 | char* ptr; /* next character position */ 9 | char* base; /* location of buffer */ 10 | struct { 11 | unsigned int _READ :1; 12 | unsigned int _WRITE :1; 13 | unsigned int _UNBUF :1; 14 | unsigned int _EOF :1; 15 | unsigned int _ERR :1; 16 | } flag; /* mode of file access */ 17 | int fd; /* file descriptor */ 18 | } FILE; 19 | extern FILE _iob[OPEN_MAX]; 20 | 21 | #define stdin (&_iob[0]) 22 | #define stdout (&_iob[1]) 23 | #define stderr (&_iob[2]) 24 | 25 | int _fillbuf(FILE *); 26 | int _flushbuf(int, FILE *); 27 | 28 | #define feof(p) (((p)->flag & _EOF) != 0) 29 | #define ferror(p) (((p)->flag & _ERR) != 0) 30 | #define fileno(p) ((p)->fd) 31 | #define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) 32 | #define putc(x,p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 33 | #define getchar() getc(stdin) 34 | #define putchar(x) putc((x), stdout) 35 | 36 | -------------------------------------------------------------------------------- /Exercise 8-3/_flushbuf.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | FILE _iob[OPEN_MAX] = {/* stdin, stdout, stderr: */ 4 | { 0, (char *) 0, (char *) 0, _READ, 0}, 5 | { 0, (char *) 0, (char *) 0, _WRITE, 1}, 6 | { 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2} 7 | }; 8 | 9 | #include 10 | 11 | #define PERMS 0666 /* RW for owner, group, other */ 12 | 13 | long int lseek(int, long int, int); 14 | 15 | /* fopen: open file, return file ptr */ 16 | FILE* fopen(char* name, char* mode) { 17 | 18 | int fd; 19 | FILE *fp; 20 | 21 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 22 | return NULL; 23 | 24 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 25 | if ((fp->flag & (_READ | _WRITE)) == 0) 26 | break; /* found free slot */ 27 | 28 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 29 | return NULL; 30 | 31 | if ((*mode == 'w')) 32 | fd = creat(name, PERMS); 33 | else if ((*mode == 'a')) { 34 | if ((fd = open(name, O_WRONLY, 0)) == -1) 35 | fd = creat(name, PERMS); 36 | lseek(fd, 0L, 2); 37 | } else 38 | fd = open(name, O_RDONLY, 0); 39 | 40 | if (fd == -1) /* couldn't access name */ 41 | return NULL; 42 | 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | fp->flag = (*mode == 'r') ? _READ : _WRITE; 47 | 48 | return fp; 49 | } 50 | 51 | void *malloc (long unsigned int); 52 | long int read (int, void *, long unsigned int); 53 | 54 | /* _fillbuf: allocate and fill input buffer */ 55 | int _fillbuf(FILE *fp) { 56 | 57 | int bufsize; 58 | 59 | if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) 60 | return EOF; 61 | 62 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 63 | 64 | if (fp->base == NULL) /* no buffer yet */ 65 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 66 | return EOF; /* can't get buffer */ 67 | 68 | fp->ptr = fp->base; 69 | 70 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 71 | 72 | if (--fp->cnt < 0) { 73 | if (fp->cnt == -1) 74 | fp->flag |= _EOF; 75 | else 76 | fp->flag |= _ERR; 77 | fp->cnt = 0; 78 | return EOF; 79 | } 80 | 81 | return (unsigned char) *fp->ptr++; 82 | } 83 | 84 | long int write(int, void *, long unsigned int); 85 | 86 | /* _flushbuf: allocate and flush output buffer */ 87 | int _flushbuf(int c, FILE *fp) { 88 | 89 | int bufsize; 90 | 91 | if ((fp->flag & (_WRITE | _ERR)) != _WRITE) 92 | return EOF; 93 | 94 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 95 | 96 | if (fp->base == NULL) { /* no buffer yet */ 97 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 98 | return EOF; /* can't get buffer */ 99 | } else { 100 | unsigned nchar = fp->ptr - fp->base; 101 | if ( (write(fp->fd, fp->base, nchar) != nchar) ) { 102 | fp->flag |= _ERR; 103 | return EOF; 104 | } 105 | } 106 | fp->ptr = fp->base; 107 | *fp->ptr++ = (char) c; 108 | fp->cnt = bufsize - 1; 109 | return c; 110 | } 111 | 112 | /* fflush: flush file buffer */ 113 | int fflush(FILE *fp) { 114 | if ( (fp->flag & _WRITE) != _WRITE) { 115 | fp->flag |= _ERR; 116 | write(2, "Error at fflush 1\n", 18); 117 | return EOF; 118 | } 119 | if ( _flushbuf('0', fp) == EOF ) { 120 | write(2, "Error at fflush 2\n", 18); 121 | return EOF; 122 | } 123 | fp->ptr = fp->base; 124 | fp->cnt = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 125 | return 0; 126 | } 127 | 128 | void free (void *); 129 | int close(int); 130 | 131 | /* fclose: close file */ 132 | int fclose(FILE *fp) { 133 | if ( fflush(fp) == EOF ) 134 | return EOF; 135 | free(fp->base); 136 | fp->base = fp->ptr = NULL; 137 | fp->cnt = 0; 138 | close(fp->fd); 139 | return 0; 140 | } 141 | 142 | int main(int argc, char *argv[]) { 143 | FILE *fpin, *fpout; 144 | char c; 145 | if ( (fpin = fopen("lorem_ipsum.txt", "r")) == NULL ) 146 | return 1; 147 | if ( (fpout = fopen("result.txt", "w")) == NULL ) 148 | return 1; 149 | while ( (c = getc(fpin)) != EOF ) 150 | putc(c, fpout); 151 | fclose(fpout); 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /Exercise 8-3/syscall.h: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | #define EOF (-1) 3 | #define BUFSIZ 1024 4 | #define OPEN_MAX 20 /* max #files open at once */ 5 | 6 | typedef struct _iofbuf { 7 | int cnt; /* character left */ 8 | char* ptr; /* next character position */ 9 | char* base; /* location of buffer */ 10 | int flag; /* mode of file access */ 11 | int fd; /* file descriptor */ 12 | } FILE; 13 | extern FILE _iob[OPEN_MAX]; 14 | 15 | #define stdin (&_iob[0]) 16 | #define stdout (&_iob[1]) 17 | #define stderr (&_iob[2]) 18 | 19 | enum _flags { 20 | _READ = 01, /* file open for reading */ 21 | _WRITE = 02, /* file open for writing */ 22 | _UNBUF = 04, /* file is unbuffered */ 23 | _EOF = 010, /* EOF has occured in this file */ 24 | _ERR = 020 /* error occured in this file */ 25 | }; 26 | 27 | int _fillbuf(FILE *); 28 | int _flushbuf(int, FILE *); 29 | 30 | #define feof(p) (((p)->flag & _EOF) != 0) 31 | #define ferror(p) (((p)->flag & _ERR) != 0) 32 | #define fileno(p) ((p)->fd) 33 | #define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) 34 | #define putc(x,p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 35 | #define getchar() getc(stdin) 36 | #define putchar(x) putc((x), stdout) 37 | 38 | -------------------------------------------------------------------------------- /Exercise 8-4/fseek.c: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | FILE _iob[OPEN_MAX] = {/* stdin, stdout, stderr: */ 4 | { 0, (char *) 0, (char *) 0, _READ, 0}, 5 | { 0, (char *) 0, (char *) 0, _WRITE, 1}, 6 | { 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2} 7 | }; 8 | 9 | #include 10 | 11 | #define PERMS 0666 /* RW for owner, group, other */ 12 | 13 | long int lseek(int, long int, int); 14 | 15 | /* fopen: open file, return file ptr */ 16 | FILE* fopen(char* name, char* mode) { 17 | 18 | int fd; 19 | FILE *fp; 20 | 21 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 22 | return NULL; 23 | 24 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 25 | if ((fp->flag & (_READ | _WRITE)) == 0) 26 | break; /* found free slot */ 27 | 28 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 29 | return NULL; 30 | 31 | if ((*mode == 'w')) 32 | fd = creat(name, PERMS); 33 | else if ((*mode == 'a')) { 34 | if ((fd = open(name, O_WRONLY, 0)) == -1) 35 | fd = creat(name, PERMS); 36 | lseek(fd, 0L, 2); 37 | } else 38 | fd = open(name, O_RDONLY, 0); 39 | 40 | if (fd == -1) /* couldn't access name */ 41 | return NULL; 42 | 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | fp->flag = (*mode == 'r') ? _READ : _WRITE; 47 | 48 | return fp; 49 | } 50 | 51 | void *malloc (long unsigned int); 52 | long int read (int, void *, long unsigned int); 53 | 54 | /* _fillbuf: allocate and fill input buffer */ 55 | int _fillbuf(FILE *fp) { 56 | 57 | int bufsize; 58 | 59 | if ((fp->flag & (_READ | _EOF | _ERR)) != _READ) 60 | return EOF; 61 | 62 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 63 | 64 | if (fp->base == NULL) /* no buffer yet */ 65 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 66 | return EOF; /* can't get buffer */ 67 | 68 | fp->ptr = fp->base; 69 | 70 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 71 | 72 | if (--fp->cnt < 0) { 73 | if (fp->cnt == -1) 74 | fp->flag |= _EOF; 75 | else 76 | fp->flag |= _ERR; 77 | fp->cnt = 0; 78 | return EOF; 79 | } 80 | 81 | return (unsigned char) *fp->ptr++; 82 | } 83 | 84 | long int write(int, void *, long unsigned int); 85 | 86 | /* _flushbuf: allocate and flush output buffer */ 87 | int _flushbuf(int c, FILE *fp) { 88 | 89 | int bufsize; 90 | 91 | if ((fp->flag & (_WRITE | _ERR)) != _WRITE) 92 | return EOF; 93 | 94 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 95 | 96 | if (fp->base == NULL) { /* no buffer yet */ 97 | if ((fp->base = (char*) malloc(bufsize)) == NULL) 98 | return EOF; /* can't get buffer */ 99 | } else { 100 | unsigned nchar = fp->ptr - fp->base; 101 | if ( (write(fp->fd, fp->base, nchar) != nchar) ) { 102 | fp->flag |= _ERR; 103 | return EOF; 104 | } 105 | } 106 | fp->ptr = fp->base; 107 | *fp->ptr++ = (char) c; 108 | fp->cnt = bufsize - 1; 109 | return c; 110 | } 111 | 112 | /* fflush: flush file buffer */ 113 | int fflush(FILE *fp) { 114 | if ( (fp->flag & _WRITE) != _WRITE) { 115 | fp->flag |= _ERR; 116 | return EOF; 117 | } 118 | if ( _flushbuf('0', fp) == EOF ) 119 | return EOF; 120 | fp->ptr = fp->base; 121 | fp->cnt = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 122 | return 0; 123 | } 124 | 125 | void free (void *); 126 | int close(int); 127 | 128 | /* fclose: close file */ 129 | int fclose(FILE *fp) { 130 | if ( fflush(fp) == EOF ) 131 | return EOF; 132 | free(fp->base); 133 | fp->base = fp->ptr = NULL; 134 | fp->cnt = 0; 135 | close(fp->fd); 136 | return 0; 137 | } 138 | 139 | int fseek(FILE *fp, long offset, int origin) { 140 | 141 | if ( (fp->flag & _READ) == _READ ) { 142 | if (offset == 1) 143 | offset -= fp->cnt; 144 | if (lseek(fp->fd, offset, origin) == -1) { 145 | fp->cnt = 0; 146 | return -1; 147 | } 148 | } else if ( (fp->flag & _WRITE) == _WRITE ) { 149 | if ( fflush(fp) == EOF ) 150 | return -1; 151 | if (lseek(fp->fd, offset, origin) == -1) 152 | return -1; 153 | } 154 | return 0; 155 | } 156 | 157 | int main(int argc, char *argv[]) { 158 | FILE *fp; 159 | char c; 160 | if ( (fp = fopen("lorem_ipsum.txt", "r")) == NULL ) 161 | return 1; 162 | if (fseek(fp, 1048000, 1) == -1) 163 | return 1; 164 | while ( (c = getc(fp)) != EOF ) 165 | putchar(c); 166 | fclose(stdout); 167 | return 0; 168 | } 169 | -------------------------------------------------------------------------------- /Exercise 8-4/syscall.h: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | #define EOF (-1) 3 | #define BUFSIZ 1024 4 | #define OPEN_MAX 20 /* max #files open at once */ 5 | 6 | typedef struct _iofbuf { 7 | int cnt; /* character left */ 8 | char* ptr; /* next character position */ 9 | char* base; /* location of buffer */ 10 | int flag; /* mode of file access */ 11 | int fd; /* file descriptor */ 12 | } FILE; 13 | extern FILE _iob[OPEN_MAX]; 14 | 15 | #define stdin (&_iob[0]) 16 | #define stdout (&_iob[1]) 17 | #define stderr (&_iob[2]) 18 | 19 | enum _flags { 20 | _READ = 01, /* file open for reading */ 21 | _WRITE = 02, /* file open for writing */ 22 | _UNBUF = 04, /* file is unbuffered */ 23 | _EOF = 010, /* EOF has occured in this file */ 24 | _ERR = 020 /* error occured in this file */ 25 | }; 26 | 27 | int _fillbuf(FILE *); 28 | int _flushbuf(int, FILE *); 29 | 30 | #define feof(p) (((p)->flag & _EOF) != 0) 31 | #define ferror(p) (((p)->flag & _ERR) != 0) 32 | #define fileno(p) ((p)->fd) 33 | #define getc(p) (--(p)->cnt >= 0 ? (unsigned char) *(p)->ptr++ : _fillbuf(p)) 34 | #define putc(x,p) (--(p)->cnt >= 0 ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 35 | #define getchar() getc(stdin) 36 | #define putchar(x) putc((x), stdout) 37 | 38 | -------------------------------------------------------------------------------- /Exercise 8-5/inode_info.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include /* flags for read and write */ 4 | #include /* typedefs */ 5 | #include /* structure returned by stat */ 6 | #include /* use C library for directory interface */ 7 | 8 | void fsize(char *); 9 | 10 | /* printf file sizes */ 11 | int main(int argc, char *argv[]) { 12 | 13 | if (argc == 1) 14 | fsize("."); 15 | else 16 | while (--argc > 0) 17 | fsize(*++argv); 18 | 19 | return 0; 20 | } 21 | 22 | void dirwalk(char *, void (*fcn)(char *)); 23 | 24 | /* fsize: print size of file name */ 25 | void fsize(char *name) { 26 | 27 | struct stat stbuf; 28 | 29 | if (stat(name, &stbuf) == -1) { 30 | fprintf(stderr, "fsize: can't access %s\n", name); 31 | return; 32 | } 33 | if ( (stbuf.st_mode & S_IFMT) == S_IFDIR ) 34 | dirwalk(name, fsize); 35 | printf("%8ld ", stbuf.st_ino); 36 | printf("%8ld ", stbuf.st_size); 37 | printf("%3lu ", (unsigned long int) stbuf.st_nlink); /* to avoid warning on my architecture */ 38 | printf("%4d ", stbuf.st_uid); 39 | printf("%4d ", stbuf.st_gid); 40 | printf("%c", ((stbuf.st_mode & S_IFMT) == S_IFDIR) ? 'd' : '-' ); 41 | printf("%c", (stbuf.st_mode & S_IRUSR) ? 'r' : '-'); 42 | printf("%c", (stbuf.st_mode & S_IWUSR) ? 'w' : '-'); 43 | printf("%c", (stbuf.st_mode & S_IXUSR) ? 'x' : '-'); 44 | printf("%c", (stbuf.st_mode & S_IRGRP) ? 'r' : '-'); 45 | printf("%c", (stbuf.st_mode & S_IWGRP) ? 'w' : '-'); 46 | printf("%c", (stbuf.st_mode & S_IXGRP) ? 'x' : '-'); 47 | printf("%c", (stbuf.st_mode & S_IROTH) ? 'r' : '-'); 48 | printf("%c", (stbuf.st_mode & S_IWOTH) ? 'w' : '-'); 49 | printf("%c", (stbuf.st_mode & S_IXOTH) ? 'x' : '-'); 50 | printf(" %s\n", name); 51 | 52 | } 53 | 54 | #define MAX_PATH 1024 55 | 56 | /* dirwalk: apply fcn to all files in dir */ 57 | void dirwalk(char *dir, void (*fcn)(char *)) { 58 | 59 | char name[MAX_PATH]; 60 | struct dirent *dp; 61 | DIR *dfd; 62 | 63 | if ( (dfd = opendir(dir)) == NULL) { 64 | fprintf(stderr, "dirwalk: can't open %s\n", dir); 65 | return; 66 | } 67 | 68 | while ( (dp = readdir(dfd)) != NULL ) { 69 | if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) 70 | continue; 71 | if ( strlen(dir) + strlen(dp->d_name) + 2 > sizeof(name) ) 72 | fprintf(stderr, "dirwalk: name %s %s too long\n", dir, dp->d_name); 73 | else { 74 | sprintf(name, "%s/%s", dir, dp->d_name); 75 | (*fcn)(name); 76 | } 77 | } 78 | closedir(dfd); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /Exercise 8-6/calloc.c: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | 3 | 4 | typedef long Align; /* for alignment to long boundary */ 5 | 6 | union header { /* block header */ 7 | struct { 8 | union header *ptr; /* next block if on free list */ 9 | unsigned size; /* size of this block */ 10 | } s; 11 | Align x; /* force alignment of blocks */ 12 | }; 13 | 14 | typedef union header Header; 15 | 16 | 17 | 18 | static Header base; /* empty list to get started */ 19 | static Header *freep = NULL; /* start of free list */ 20 | 21 | void Free(void *); 22 | void *Malloc(unsigned); 23 | void *Calloc(unsigned, unsigned); 24 | 25 | int main(int argc, char *argv[]) { 26 | 27 | int r = 36; 28 | int *p = (int *) Malloc(sizeof(int)); 29 | *p = 36; 30 | if (r != *p) 31 | return 1; 32 | Free(p); 33 | 34 | int *arr = (int *) Calloc(10, sizeof(int)); 35 | int i; 36 | for (i=0; i<10; i++) 37 | arr[i] = i+1; 38 | 39 | return ((arr[0] == 1) && (arr[9] == 10)) ? 0 : 1; 40 | 41 | } 42 | 43 | 44 | static Header *Morecore(unsigned); 45 | 46 | /* Malloc: general-purpose storage allocator */ 47 | void *Malloc(unsigned nbytes) { 48 | 49 | Header *p, *prevp; 50 | Header *Morecore(unsigned); 51 | unsigned nunits; 52 | 53 | nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; 54 | if ((prevp = freep) == NULL) { /* no free list yet */ 55 | base.s.ptr = freep = prevp = &base; 56 | base.s.size = 0; 57 | } 58 | for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { 59 | if (p->s.size >= nunits) { /* big enough */ 60 | if (p->s.size == nunits) /* exactly */ 61 | prevp->s.ptr = p->s.ptr; 62 | else { /* allocate tail end */ 63 | p->s.size -= nunits; 64 | p += p->s.size; 65 | p->s.size = nunits; 66 | } 67 | freep = prevp; 68 | return (void *)(p + 1); 69 | } 70 | if (p == freep) /* wrapped around free list */ 71 | if ( (p = Morecore(nunits)) == NULL ) 72 | return NULL; /* none left */ 73 | } 74 | } 75 | 76 | 77 | void *Calloc(unsigned n, unsigned size) { 78 | 79 | unsigned len = n * size; 80 | char *p = Malloc(len); 81 | if (p == NULL) 82 | return NULL; 83 | 84 | char *q = p; 85 | int i; 86 | for (i=0; is.size = nu; 108 | Free((void *)(up + 1)); 109 | return freep; 110 | } 111 | 112 | 113 | 114 | /* free: put block ap in free list */ 115 | void Free(void *ap) { 116 | 117 | Header *bp, *p; 118 | 119 | bp = (Header *)ap - 1; /* point to block header */ 120 | for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) 121 | break; /* freed block at start or end of arena */ 122 | 123 | if (bp + bp->s.size == p->s.ptr) { /* join to upper nbr */ 124 | bp->s.size += p->s.ptr->s.size; 125 | bp->s.ptr = p->s.ptr->s.ptr; 126 | } else 127 | bp->s.ptr = p->s.ptr; 128 | if (p + p->s.size == bp) { 129 | p->s.size += bp->s.size; 130 | p->s.ptr = bp->s.ptr; 131 | } else 132 | p->s.ptr = bp; 133 | freep = p; 134 | } 135 | -------------------------------------------------------------------------------- /Exercise 8-7/malloc_check.c: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | 3 | typedef long Align; /* for alignment to long boundary */ 4 | 5 | union header { /* block header */ 6 | struct { 7 | union header *ptr; /* next block if on free list */ 8 | unsigned size; /* size of this block */ 9 | } s; 10 | Align x; /* force alignment of blocks */ 11 | }; 12 | 13 | typedef union header Header; 14 | 15 | void Free(void *); 16 | void *Malloc(unsigned); 17 | 18 | int main(int argc, char *argv[]) { 19 | 20 | int r = 36; 21 | int *p = (int *) Malloc(sizeof(int)); 22 | *p = 36; 23 | if (r != *p) 24 | return 1; 25 | Free(p); 26 | 27 | void *q = Malloc(1024*1024+1); 28 | if (q == NULL) 29 | return 1; 30 | 31 | return 0; 32 | } 33 | 34 | 35 | 36 | static unsigned max_allocated = 0; /* largest allocated size */ 37 | static Header base; /* empty list to get started */ 38 | static Header *freep = NULL; /* start of free list */ 39 | 40 | static Header *Morecore(unsigned); 41 | 42 | #define MAXALLOC (1024*1024) 43 | 44 | /* Malloc: general-purpose storage allocator */ 45 | /* user can ask for maximum of 1024*1024 bytes in one call */ 46 | void *Malloc(unsigned nbytes) { 47 | 48 | Header *p, *prevp; 49 | Header *Morecore(unsigned); 50 | unsigned nunits; 51 | 52 | nunits = (nbytes + sizeof(Header) - 1) / sizeof(Header) + 1; 53 | 54 | if (nbytes > MAXALLOC) 55 | return NULL; 56 | if ((prevp = freep) == NULL) { /* no free list yet */ 57 | base.s.ptr = freep = prevp = &base; 58 | base.s.size = 0; 59 | } 60 | for (p = prevp->s.ptr; ; prevp = p, p = p->s.ptr) { 61 | if (p->s.size >= nunits) { /* big enough */ 62 | if (p->s.size == nunits) /* exactly */ 63 | prevp->s.ptr = p->s.ptr; 64 | else { /* allocate tail end */ 65 | p->s.size -= nunits; 66 | p += p->s.size; 67 | p->s.size = nunits; 68 | } 69 | freep = prevp; 70 | return (void *)(p + 1); 71 | } 72 | if (p == freep) /* wrapped around free list */ 73 | if ( (p = Morecore(nunits)) == NULL ) 74 | return NULL; /* none left */ 75 | } 76 | } 77 | 78 | 79 | 80 | #define NALLOC 1024 /* minimum #units to request */ 81 | 82 | /* Morecore: ask system for more memory */ 83 | static Header *Morecore(unsigned nu) { 84 | 85 | char *cp, *sbrk(int); 86 | Header *up; 87 | 88 | if (nu < NALLOC) 89 | nu = NALLOC; 90 | cp = sbrk(nu * sizeof(Header)); 91 | if (cp == (char *) -1) /* no space at all */ 92 | return NULL; 93 | up = (Header *) cp; 94 | up->s.size = nu; 95 | max_allocated = (up->s.size > max_allocated) ? up->s.size : max_allocated; 96 | Free((void *)(up + 1)); 97 | return freep; 98 | } 99 | 100 | 101 | 102 | /* free: put block ap in free list */ 103 | void Free(void *ap) { 104 | 105 | Header *bp, *p; 106 | 107 | bp = (Header *)ap - 1; /* point to block header */ 108 | if ( (bp->s.size <= 0) && (bp->s.size >= max_allocated) ) 109 | return; 110 | for (p = freep; !(bp > p && bp < p->s.ptr); p = p->s.ptr) 111 | break; /* freed block at start or end of arena */ 112 | 113 | if (bp + bp->s.size == p->s.ptr) { /* join to upper nbr */ 114 | bp->s.size += p->s.ptr->s.size; 115 | bp->s.ptr = p->s.ptr->s.ptr; 116 | } else 117 | bp->s.ptr = p->s.ptr; 118 | if (p + p->s.size == bp) { 119 | p->s.size += bp->s.size; 120 | p->s.ptr = bp->s.ptr; 121 | } else 122 | p->s.ptr = bp; 123 | freep = p; 124 | } 125 | -------------------------------------------------------------------------------- /Exercise 8-8/bfree.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char *argv[]) { 4 | 5 | printf("ToDo: Exercise 8-8\n"); 6 | 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Elyas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # K-and-R-solutions 2 | 3 | Exercise solutions for The C Programming Language, 2nd edition 4 | 5 | You will find sometimes a file named lorem_ipsum.txt (or similar) that you can use for testing. 6 | 7 | For example, if `a.out` is the executable then you could do something like `./a.out < lorem_ipsum.txt`. 8 | 9 | ## Exercise 4-5, 4-6, 4-10 and 4-11 10 | This program uses the math library functions `sin`, `exp` and `pow`; make sure you link with the math library, e.g. `gcc calculator.c -lm`. 11 | 12 | ## Exercise 5-7 13 | You can test the program like this `./a.out < lines.txt`. `lines.txt` is a long computer science poetry. 14 | You can time it like so `time ./a.out < lines.txt`. 15 | 16 | ## Exercise 5-11 and 5-12 17 | Similar to 5-7, but you'll find two files; one for testing `detab` and one for `entab`. 18 | 19 | ## Exercise 5-13 20 | Similar to 5-7. 21 | 22 | ## Exercise 6-1 23 | You can test by giving the getword.c program itself as input: `./a.out < getword.c` 24 | 25 | ## Exercise 6-3 and 6-4 26 | You can use a long Computer Science poem as input for test: `./a.out < cs_poetry.txt` (or the source code as in 6-1) 27 | 28 | ## Exercise 6-5 29 | You can test by giving the source code as input: `./a.out < preprocessor.c` 30 | 31 | ## Exercise 7-1 32 | You can test with the text file as input: `./a.out tolower < lines.txt` (or `toupper` for upper case conversion) 33 | 34 | ## Exercise 7-5 35 | I opted for a little unusual solution. The result is only displayed when requested via the character 'p' (print). 36 | 37 | ## Exercise 7-7 38 | You can use one or all the three files for testing: file1.txt, file2.txt, file3.txt 39 | 40 | ## Exercise 7-8 41 | You'll find two Computer Science poems in the folder. 42 | 43 | ## Exercise 8-1 44 | You can use the lorem_ipsum.txt file and compare the system's `cat` with this program. 45 | 46 | ## Exercise 8-2 47 | Using bit fields results in a larger source code size; bit fields operations are more explicit. 48 | Compiled code size was equal on my architecture. 49 | The run time for the code using bit fields was slower. 50 | 51 | You can use the `time` program on for timing and test, e.g. `/usr/bin/time a.out`. (The file `lorem_ipsum.txt` is read in the program.) 52 | 53 | ## Exercise 8-3 54 | The program reads the file `lorem_ipsum.txt` and creates a file name `result.txt`. 55 | 56 | ## Exercise 8-4 57 | The program opens the file `lorem_ipsum.txt`, uses `fseek` to _fast forward_ close to the end of file and prints the content until the end of file. 58 | 59 | 60 | --------------------------------------------------------------------------------