├── Chapter 1 ├── 1-1 │ └── hello.c ├── 1-10 │ └── copy.c ├── 1-12 │ └── onewpl.c ├── 1-13 │ └── wordlength.c ├── 1-14 │ └── charfreq.c ├── 1-15 │ └── ftoc.c ├── 1-16 │ └── longestline.c ├── 1-17 │ └── longlines.c ├── 1-19 │ └── reverse.c ├── 1-2 │ └── escapes.c ├── 1-20 │ └── detab.c ├── 1-21 │ └── entab.c ├── 1-22 │ └── fold.c ├── 1-23 │ └── rmcomments.c ├── 1-3 │ └── ftoc.c ├── 1-4 │ └── ctof.c ├── 1-5 │ └── rftoc.c ├── 1-6 │ └── eof.c ├── 1-7 │ └── eof.c ├── 1-8 │ └── count.c └── 1-9 │ └── copy.c ├── Chapter 2 ├── 2-1 │ └── ranges.c ├── 2-10 │ └── lower.c ├── 2-2 │ └── loop.c ├── 2-3 │ └── htoi.c ├── 2-4 │ └── squeeze.c ├── 2-5 │ └── any.c ├── 2-6 │ └── setbits.c ├── 2-7 │ └── invert.c ├── 2-8 │ └── rightrot.c └── 2-9 │ └── bitcount.c ├── Chapter 3 ├── 3-1 │ └── binsearch.c ├── 3-2 │ └── escape.c ├── 3-3 │ └── expand.c ├── 3-4 │ └── itoa.c ├── 3-5 │ └── itob.c └── 3-6 │ └── itoa.c ├── Chapter 4 ├── 4-1 │ ├── strindex.c │ └── strrindex.c ├── 4-2 │ └── atof.c ├── 4-3 │ └── polishcalc.c ├── 4-4 │ └── polishcalc.c └── 4-5 │ ├── 4-5.c │ └── polishcalc.c ├── Chapter 5 ├── 5-1 │ ├── getch.c │ ├── getch.h │ ├── getint.c │ ├── getint.h │ └── main.c ├── 5-2 │ ├── getch.c │ ├── getch.h │ └── getfloat.c ├── 5-3 │ └── strcat.c ├── 5-4 │ └── strend.c ├── 5-5 │ ├── strncat.c │ ├── strncmp.c │ └── strncpy.c └── 5-6 │ ├── atoi.c │ ├── getline.c │ ├── getop.c │ ├── itoa.c │ ├── reverse.c │ └── strindex.c ├── Chapter 7 ├── 7-1 │ └── convert.c └── 7-3 │ └── minprintf.c ├── Chapter 8 ├── 8-1 │ └── cat.c └── 8-2 │ ├── bitops │ ├── _fillbuf.c │ ├── fopen.c │ └── syscalls.h │ └── fields │ ├── _fillbuf.c │ ├── fopen.c │ └── syscalls.h └── README /Chapter 1/1-1/hello.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: hello.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-1, page 8 10 | * 11 | * Run the "Hello, world" program on your system. Experiment with 12 | * leaving out parts of the program, to see what error messages you get. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int main(void) 19 | { 20 | printf("Hello world!\n"); 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /Chapter 1/1-10/copy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: copy.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-10, page 20 10 | * 11 | * Write a program to copy its input to its output, replacing each tab 12 | * by \t, each backspace by \b, and each backslash by \\. This makes 13 | * tabs and backspaces visible in a unambiguous way. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | int main(void) 20 | { 21 | int c; 22 | 23 | while ((c = getchar()) != EOF) { 24 | if (c == '\t') 25 | printf("\\t"); 26 | if (c == '\b') 27 | printf("\\b"); 28 | if (c == '\\') 29 | printf("\\\\"); 30 | else 31 | printf("%c", c); 32 | } 33 | return EXIT_SUCCESS; 34 | } 35 | -------------------------------------------------------------------------------- /Chapter 1/1-12/onewpl.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: onewpl.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-12, page 21 10 | * 11 | * Write a program that prints its input one word per line. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #define TRUE 1 18 | #define FALSE 0 19 | 20 | int main(void) 21 | { 22 | int c, prevblank; 23 | 24 | prevblank = FALSE; 25 | while ((c = getchar()) != EOF) { 26 | if (c == ' ' || c == '\t' || c == '\n') { 27 | if (prevblank == FALSE) 28 | putchar('\n'); 29 | prevblank = TRUE; 30 | } else { 31 | prevblank = FALSE; 32 | putchar(c); 33 | } 34 | } 35 | return EXIT_SUCCESS; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Chapter 1/1-13/wordlength.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: wordlength.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-13, page 24 10 | * 11 | * Write a program to print a histogram of the lengths of words in it's 12 | * input. It is easy to draw a histogram with the bars horizontal; a 13 | * vertical orientation is more challenging. 14 | * 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | * I created both a horizontal and a vertical histogram. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #define IN 1 /* inside a word */ 23 | #define OUT 0 /* inside a word */ 24 | #define MAXWORDLEN 15 25 | 26 | int main(void) 27 | { 28 | int i, j; 29 | int c, wl, state, maxval; 30 | int length[MAXWORDLEN+1]; 31 | 32 | for (i = 0; i <= MAXWORDLEN; ++i) 33 | length[i] = 0; 34 | 35 | state = OUT; 36 | while ((c = getchar()) != EOF) { 37 | if (c == ' ' || c == '\t' || c == '\n') { 38 | if (state == IN) { 39 | if (wl <= MAXWORDLEN) 40 | length[wl-1] += 1; 41 | else 42 | length[MAXWORDLEN] += 1; 43 | state = OUT; 44 | } 45 | } else { 46 | if (state == OUT) { 47 | wl = 0; 48 | state = IN; 49 | } 50 | wl +=1; 51 | } 52 | } 53 | 54 | /* Horizontal histogram */ 55 | 56 | printf("Horizontal histogram\n\n"); 57 | 58 | for (i = 0; i <= MAXWORDLEN; ++i) { 59 | if (i != MAXWORDLEN) 60 | printf(" %2d: ", i+1); 61 | else 62 | printf(">%d: ", MAXWORDLEN); 63 | 64 | for (j = 0; j < length[i]; ++j) 65 | putchar('#'); 66 | putchar('\n'); 67 | } 68 | 69 | /* Vertical histogram */ 70 | 71 | printf("\nVertical histogram\n\n"); 72 | 73 | /* get maximum wordlength count */ 74 | maxval = 0; 75 | for (i = 0; i <= MAXWORDLEN; ++i) 76 | if (length[i] > maxval) 77 | maxval = length[i]; 78 | 79 | /* print a line per count result */ 80 | for (i = 0; i < maxval; ++i) { 81 | printf(" %2d |", maxval - i); 82 | for (j = 0; j <= MAXWORDLEN; ++j) { 83 | if (length[j] >= maxval - i) 84 | printf(" #"); 85 | else 86 | printf(" "); 87 | } 88 | printf("\n"); 89 | } 90 | 91 | /* print bottom line */ 92 | printf(" "); 93 | for (i = 0; i <= MAXWORDLEN; ++i) 94 | printf("---"); 95 | printf("-\n"); 96 | 97 | /* print the word lengths */ 98 | printf(" "); 99 | for (i = 0; i <= MAXWORDLEN; ++i) 100 | if (i != MAXWORDLEN) 101 | printf(" %2d", i+1); 102 | else 103 | printf(" %2d>", i); 104 | printf("\n"); 105 | 106 | return EXIT_SUCCESS; 107 | } 108 | -------------------------------------------------------------------------------- /Chapter 1/1-14/charfreq.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: charfreq.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-14, page 24 10 | * 11 | * Write a program to print a histogram of the frequencies of different 12 | * characters in its input. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #define NUMCHARS 128 /* number of characters in ASCII-I */ 19 | 20 | int main(void) 21 | { 22 | int c, chars[NUMCHARS]; 23 | 24 | for (c = 0; c < NUMCHARS; ++c) 25 | chars[c] = 0; 26 | 27 | while ((c = getchar()) != EOF) 28 | chars[c] += 1; 29 | 30 | /* horizontal histogram */ 31 | for (c = 0; c < NUMCHARS; ++c) { 32 | if (chars[c] > 0) { 33 | if (c == '\b') /* backspace */ 34 | printf("\\b"); 35 | else if (c == '\n') /* new line*/ 36 | printf("\\n"); 37 | else if (c == '\t') /* (horizontal) tab */ 38 | printf("\\t)"); 39 | else /* all other chars */ 40 | printf("%2c", c); 41 | /* ASCII code & frequency */ 42 | printf(" (%3d): %3d\n", c, chars[c]); 43 | } 44 | } 45 | return EXIT_SUCCESS; 46 | } 47 | -------------------------------------------------------------------------------- /Chapter 1/1-15/ftoc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: ftoc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-15, page 27 10 | * 11 | * Rewrite the temperature conversion program of Section 1.2 to use a 12 | * function for conversion. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | float ftoc(float f); 19 | 20 | int main(void) 21 | { 22 | float fahr, celsius; 23 | int lower, upper, step; 24 | 25 | lower = 0; /* lower limit of temperature table */ 26 | upper = 300; /* upper limit */ 27 | step = 20; /* step size */ 28 | 29 | printf(" F C \n"); 30 | printf("----------\n"); 31 | 32 | fahr = lower; 33 | while (fahr <= upper) { 34 | celsius = ftoc(fahr); 35 | printf("%3.0f %6.1f\n", fahr, celsius); 36 | fahr = fahr + step; 37 | } 38 | return EXIT_SUCCESS; 39 | } 40 | 41 | /* ftoc: return Celsius conversion of a Fahrenheit temperature */ 42 | float ftoc(float f) 43 | { 44 | float c; 45 | c = (5.0/9.0) * (f-32.0); 46 | return c; 47 | } 48 | -------------------------------------------------------------------------------- /Chapter 1/1-16/longestline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: longestline.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-16, page 30 10 | * 11 | * Revise the main routine of the longest-line program so it will 12 | * correctly print the length of arbitrarily long input lines, and as 13 | * much as possible of the text. 14 | * 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | * This program will print the first MAXLINE-1 characters and the length 17 | * of the longest line. 18 | */ 19 | 20 | #include 21 | #include 22 | 23 | #define MAXLINE 3 /* maximum input line size */ 24 | 25 | int get_line(char line[], int maxline); 26 | void copy(char to[], char from[]); 27 | 28 | int main(void) 29 | { 30 | int len; /* current line length */ 31 | int max; /* maximum length seen so far */ 32 | int prevlen; /* length of line before we ran out of mem */ 33 | char line[MAXLINE]; /* current input line */ 34 | char longest[MAXLINE]; /* longest line saved here */ 35 | char temp[MAXLINE]; /* start of line before we ran out of mem */ 36 | 37 | max = prevlen = 0; 38 | while ((len = get_line(line, MAXLINE)) > 0) { 39 | if (prevlen + len > max) { 40 | max = prevlen + len; 41 | if (!prevlen) 42 | copy(longest, line); 43 | else 44 | copy(longest, temp); 45 | } 46 | if (line[len-1] != '\n') { 47 | if (!prevlen) /* copy start of line to temp */ 48 | copy(temp, line); 49 | prevlen += len; 50 | } else 51 | prevlen = 0; 52 | } 53 | if (max > 0) { /* there was a line */ 54 | printf("%s", longest); 55 | if (longest[max-1] != '\n') 56 | putchar('\n'); 57 | printf("%d characters\n", max); 58 | } 59 | return EXIT_SUCCESS; 60 | } 61 | 62 | /* get_line: read a line into s, return length */ 63 | int get_line(char s[], int lim) 64 | { 65 | int c, i; 66 | 67 | for (i=0; i 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-17, page 31 10 | * 11 | * Write a program to print all input lines that are longer than 80 12 | * characters. 13 | * 14 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | * I assumed the length of an input line is including the \n at the end. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define TRUE 1 22 | #define FALSE 0 23 | #define PRINTLEN 80 24 | 25 | int get_line(char line[], int maxline); 26 | 27 | int main(void) 28 | { 29 | char line[PRINTLEN+1]; /* current input line */ 30 | int len, longline; 31 | 32 | longline = FALSE; 33 | while ((len = get_line(line, PRINTLEN+1)) > 0) { 34 | if (line[len-1] != '\n') { 35 | /* line is longer that PRINTLEN chars */ 36 | printf("%s", line); 37 | longline = TRUE; 38 | } else if (longline){ 39 | /* print the rest of this long line */ 40 | printf("%s", line); 41 | longline = FALSE; 42 | } 43 | } 44 | return EXIT_SUCCESS; 45 | } 46 | 47 | /* get_line: read a line into s, return length */ 48 | int get_line(char s[], int lim) 49 | { 50 | int c, i; 51 | 52 | for (i=0; i 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-19, page 31 10 | * 11 | * Write a function reverse(s) that reverses the character string s. Use 12 | * it to write a program that reverses its input a line at a time. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #define MAXLINE 1000 19 | 20 | int get_line(char s[], int lim); 21 | void reverse(char s[]); 22 | 23 | int main(void) 24 | { 25 | int len; /* current line length */ 26 | char line[MAXLINE]; /* current input line */ 27 | 28 | while ((len = get_line(line, MAXLINE)) > 0) { 29 | reverse(line); 30 | printf("%s", line); 31 | } 32 | return EXIT_SUCCESS; 33 | } 34 | 35 | /* get_line: read a line into s, return length */ 36 | int get_line(char s[], int lim) 37 | { 38 | int c, i; 39 | 40 | for (i=0; i 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-2, page 8 10 | * 11 | * Experiment to find out what happens when printf's argument string 12 | * contains \c, where c is some character not listed above. 13 | * 14 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | * The following are legal escape sequences: 16 | * (description, ASCII char, escape sequense, decimal ASCII code) 17 | * 18 | * audible alert (bell) BEL \a 7 19 | * backspace BS \b 8 20 | * horizontal tab HT \t 9 21 | * newline LF \n 10 22 | * vertical tab VT \v 11 23 | * formfeed FF \f 12 24 | * carriage return CR \r 13 25 | * double quote " \" 34 26 | * single quote ' \' 39 27 | * question mark ? \? 63 28 | * backslash \ \\ 92 29 | * octal number ooo \ooo 30 | * hexadecimal number hh \xhh 31 | * 32 | * Using a non-specified escape sequence invokes undefined behaviour 33 | * (behavior, upon use of a nonportable or erroneous program construct 34 | * or of erroneous data, for which this International Standard imposes 35 | * no requirements). 36 | */ 37 | 38 | #include 39 | #include 40 | 41 | int main(void) 42 | { 43 | /* legal escape sequences */ 44 | printf("audible alert (bell) BEL \\a %d\n" , '\a'); 45 | printf("backspace BS \\b %d\n" , '\b'); 46 | printf("horizontal tab HT \\t %d\n" , '\t'); 47 | printf("newline LF \\n %d\n" , '\n'); 48 | printf("vertical tab VT \\v %d\n" , '\v'); 49 | printf("formfeed FF \\f %d\n" , '\f'); 50 | printf("carriage return CR \\r %d\n" , '\r'); 51 | printf("double quote \" \\\" %d\n", '\"'); 52 | printf("single quote \' \\\' %d\n", '\''); 53 | printf("question mark ? \\? %d\n" , '\?'); 54 | printf("backslash \\ \\\\ %d\n", '\\'); 55 | printf("\n"); 56 | printf("forty-two in octal 0%o \\52 %d\n" , '\52' , '\52'); 57 | printf("forty-two in hex 0x%X \\x2A %d\n" , '\x2A', '\x2A'); 58 | printf("\n"); 59 | /* illegal escape sequence */ 60 | printf("invalid escape sequence \\c %d (%c)\n" , '\c', '\c'); 61 | return EXIT_SUCCESS; 62 | } 63 | -------------------------------------------------------------------------------- /Chapter 1/1-20/detab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: detab.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-20, page 34 10 | * 11 | * Write a program detab that replaces tabs in the input with the proper 12 | * number of blanks to space to the next tab stop. Assume a fixed set of 13 | * tab stops, say every n columns. Should n be a variable or a symbolic 14 | * parameter? 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define TABWIDTH 8 21 | 22 | int main(void) 23 | { 24 | int i; 25 | int c, col, spaces; 26 | 27 | col = 0; 28 | while((c = getchar()) != EOF) { 29 | if (c == '\t') { 30 | spaces = TABWIDTH - col % TABWIDTH; 31 | for (i = 0; i < spaces; ++i) 32 | putchar(' '); 33 | col = col + spaces; 34 | } else { 35 | putchar(c); 36 | col = col + 1; 37 | if (c == '\n') 38 | col = 0; 39 | } 40 | } 41 | return EXIT_SUCCESS; 42 | } 43 | -------------------------------------------------------------------------------- /Chapter 1/1-21/entab.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: entab.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-21, page 34 10 | * 11 | * Write a program entab that replaces strings of blanks with the 12 | * minimum number of tabs and blanks to achieve the same spacing. Use 13 | * the same stops as for detab. When either a tab or a single blank 14 | * would suffice to reach a tab stop, which should be given preference? 15 | * 16 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 | * This program will print a tab if either a tab or a single blank would 18 | * suffice, except if the single space is between two words. 19 | */ 20 | 21 | #include 22 | #include 23 | 24 | #define TRUE 1 25 | #define FALSE 0 26 | #define TABWIDTH 4 27 | 28 | int main(void) 29 | { 30 | int i; 31 | int c, col, blanks, numtabs; 32 | 33 | col = blanks = 0; 34 | while((c = getchar()) != EOF) { 35 | if (c == ' ') { 36 | blanks = blanks + 1; 37 | col = col + 1; 38 | } else { 39 | if (blanks == 1) 40 | putchar(' '); 41 | else if (blanks > 1) { 42 | numtabs = col/TABWIDTH - (col-blanks)/TABWIDTH; 43 | for (i = 0; i < numtabs; ++i) 44 | putchar('\t'); 45 | if (numtabs >= 1) 46 | blanks = col - (col/TABWIDTH)*TABWIDTH; 47 | for (i = 0; i < blanks; ++i) 48 | putchar(' '); 49 | } 50 | blanks = 0; 51 | putchar(c); 52 | col = col + 1; 53 | if (c == '\n') 54 | col = 0; 55 | } 56 | } 57 | return EXIT_SUCCESS; 58 | } 59 | -------------------------------------------------------------------------------- /Chapter 1/1-22/fold.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: fold.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-22, page 34 10 | * 11 | * Write a program to "fold" long input lines into two or more shorter 12 | * lines after the last non-blank character that occurs before the n-th 13 | * column of input. Make sure your program does something intelligent 14 | * with very long lines, and if there are no blanks or tabs before the 15 | * specified column. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define TABWIDTH 4 22 | #define LINELENGTH 40 23 | 24 | int main(void) 25 | { 26 | int i; 27 | int c, linelen, wordlen, wslen; 28 | char wordbuf[LINELENGTH]; 29 | 30 | linelen = wordlen = wslen = 0; 31 | while ((c = getchar()) != EOF) { 32 | if (c == ' ' || c == '\t') { 33 | wordbuf[wordlen] = '\0'; 34 | wslen = c == '\t' ? TABWIDTH : 1; 35 | if (linelen + wordlen > LINELENGTH){ 36 | putchar('\n'); 37 | linelen = wordlen; 38 | } else { 39 | linelen = linelen + wordlen; 40 | } 41 | printf("%s", wordbuf); 42 | if (linelen + wslen > LINELENGTH) { 43 | putchar('\n'); 44 | putchar(c); 45 | linelen = wslen; 46 | } else { 47 | putchar(c); 48 | linelen = linelen + wslen; 49 | } 50 | wordlen = 0; 51 | } else if (c == '\n') { 52 | wordbuf[wordlen] = '\0'; 53 | if (linelen + wordlen > LINELENGTH) 54 | putchar('\n'); 55 | printf("%s", wordbuf); 56 | putchar(c); 57 | linelen = wordlen = 0; 58 | } else { 59 | if (wordlen == LINELENGTH) { 60 | for (i = 0; i < LINELENGTH-1; ++i) 61 | putchar(wordbuf[i]); 62 | putchar('-'); 63 | putchar('\n'); 64 | wordbuf[0] = wordbuf[LINELENGTH-1]; 65 | wordlen = 1; 66 | linelen = 0; 67 | } 68 | wordbuf[wordlen] = c; 69 | wordlen = wordlen + 1; 70 | } 71 | } 72 | return EXIT_SUCCESS; 73 | } 74 | -------------------------------------------------------------------------------- /Chapter 1/1-23/rmcomments.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: rmcomments.c 3 | * Author: Thomas van der Burgt 4 | * Date: 27-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-23, page 34 10 | * 11 | * Write a program to remove all comments from a C program. Don't forget 12 | * to handle quoted strings and character constants properly. C comments 13 | * do not nest. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #define PROGRAM 0 20 | #define COMMENT 1 21 | #define QUOTE 2 22 | #define SLASH 3 23 | #define STAR 4 24 | #define LITERAL 5 25 | 26 | int main(void) 27 | { 28 | int c, state; 29 | char quote; 30 | 31 | state = PROGRAM; 32 | while ((c = getchar()) != EOF) { 33 | if (state == PROGRAM) { 34 | /* Within the program code. */ 35 | if (c == '/') 36 | state = SLASH; 37 | else { 38 | if (c == '"' || c == '\'') { 39 | /* Start of a quote of character constant */ 40 | state = QUOTE; 41 | quote = c; 42 | } 43 | putchar(c); 44 | } 45 | } else if (state == COMMENT) { 46 | /* Within a comment. */ 47 | if (c == '*') 48 | state = STAR; 49 | } else if (state == QUOTE) { 50 | /* Within a quote. */ 51 | if (c == '\\') 52 | state = LITERAL; 53 | else if (c == quote) 54 | state = PROGRAM; 55 | putchar(c); 56 | } else if (state == SLASH) { 57 | /* Following a slash (/). */ 58 | if (c == '*') 59 | state = COMMENT; 60 | else if (c == '"' || c == '\'') { 61 | /* Start of a quote of character constant */ 62 | state = QUOTE; 63 | quote = c; 64 | } else { 65 | state = PROGRAM; 66 | putchar('/'); 67 | putchar(c); 68 | } 69 | } else if (state == STAR) { 70 | if (c == '/') 71 | state = PROGRAM; 72 | else if (state != '*') 73 | state = COMMENT; 74 | } else if (state == LITERAL) { 75 | /* Within quoted string or char constant, following \.*/ 76 | putchar(c); 77 | state = QUOTE; 78 | } 79 | } 80 | return EXIT_SUCCESS; 81 | } 82 | 83 | -------------------------------------------------------------------------------- /Chapter 1/1-3/ftoc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: ftoc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-3, page 13 10 | * 11 | * Modify the temparature conversion program to print a heading above 12 | * the table. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int main(void) 19 | { 20 | float fahr, celsius; 21 | int lower, upper, step; 22 | 23 | lower = 0; /* lower limit of temperature table */ 24 | upper = 300; /* upper limit */ 25 | step = 20; /* step size */ 26 | 27 | printf(" F C \n"); 28 | printf("----------\n"); 29 | 30 | fahr = lower; 31 | while (fahr <= upper) { 32 | celsius = (5.0/9.0) * (fahr-32.0); 33 | printf("%3.0f %6.1f\n", fahr, celsius); 34 | fahr = fahr + step; 35 | } 36 | return EXIT_SUCCESS; 37 | } 38 | -------------------------------------------------------------------------------- /Chapter 1/1-4/ctof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: ctof.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-4, page 13 10 | * 11 | * Write a program to print the corresponding Celsius to Fahrenheit 12 | * table. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int main(void) 19 | { 20 | float fahr, celsius; 21 | int lower, upper, step; 22 | 23 | lower = 0; /* lower limit of temperature table */ 24 | upper = 300; /* upper limit */ 25 | step = 20; /* step size */ 26 | 27 | printf(" C F \n"); 28 | printf("----------\n"); 29 | 30 | celsius = lower; 31 | while (celsius <= upper) { 32 | fahr = celsius * (9.0/5.0) + 32.0; 33 | printf("%3.0f %6.1f\n", celsius, fahr); 34 | celsius = celsius + step; 35 | } 36 | return EXIT_SUCCESS; 37 | } 38 | -------------------------------------------------------------------------------- /Chapter 1/1-5/rftoc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: rftoc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-5, page 14 10 | * 11 | * Modify the temparature conversion program to print the table in 12 | * reverse order, that is, from 300 degrees to 0. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int main(void) 19 | { 20 | float fahr, celsius; 21 | int lower, upper, step; 22 | 23 | lower = 0; /* lower limit of temperature table */ 24 | upper = 300; /* upper limit */ 25 | step = 20; /* step size */ 26 | 27 | printf(" F C \n"); 28 | printf("----------\n"); 29 | 30 | fahr = upper; 31 | while (fahr >= lower) { 32 | celsius = (5.0/9.0) * (fahr-32.0); 33 | printf("%3.0f %6.1f\n", fahr, celsius); 34 | fahr = fahr - step; 35 | } 36 | return EXIT_SUCCESS; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Chapter 1/1-6/eof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: eof.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-6, page 17 10 | * 11 | * Verify that the expression getchar() != EOF is 0 or 1. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | int main(void) 18 | { 19 | printf("Enter a char\n"); 20 | printf("getchar() != EOF : %d\n", getchar() != EOF); 21 | return EXIT_SUCCESS; 22 | } 23 | -------------------------------------------------------------------------------- /Chapter 1/1-7/eof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: eof.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-7, page 17 10 | * 11 | * Write a program to print the value of EOF. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | int main(void) 18 | { 19 | printf("%d\n", EOF); 20 | return EXIT_SUCCESS; 21 | } 22 | -------------------------------------------------------------------------------- /Chapter 1/1-8/count.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: count.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-8, page 20 10 | * 11 | * Write a program to count blanks, tabs, and newlines. 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | int main(void) 18 | { 19 | int c, nb, nt, nl; 20 | 21 | nb = nt = nl = 0; 22 | while ((c = getchar()) != EOF) { 23 | if (c == ' ') 24 | ++nb; 25 | else if (c == '\t') 26 | ++nt; 27 | else if (c == '\n') 28 | ++nl; 29 | } 30 | printf("%d %d %d\n", nb, nt, nl); 31 | return EXIT_SUCCESS; 32 | } 33 | -------------------------------------------------------------------------------- /Chapter 1/1-9/copy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: copy.c 3 | * Author: Thomas van der Burgt 4 | * Date: 25-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 1-9, page 20 10 | * 11 | * Write a program to copy its input to its output, replacing each string 12 | * of one or more blanks by a sinle blank. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | #define TRUE 1 19 | #define FALSE 0 20 | 21 | int main(void) 22 | { 23 | int c, prevblank; 24 | 25 | prevblank = FALSE; 26 | while ((c = getchar()) != EOF) { 27 | if (c == ' ') { 28 | if (prevblank == FALSE) { 29 | putchar(c); 30 | prevblank = TRUE; 31 | } 32 | } 33 | if (c != ' ') { 34 | putchar(c); 35 | prevblank = FALSE; 36 | } 37 | } 38 | return EXIT_SUCCESS; 39 | } 40 | -------------------------------------------------------------------------------- /Chapter 2/2-1/ranges.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: ranges.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-1, page 34 10 | * 11 | * Write a program to determine the ranges of char, short, int, and long 12 | * variables, both signed and unsigned, by printing appropriate values 13 | * from standard headers and by direct computation. Harder if you 14 | * compute them: determine the ranges of the various floating-point 15 | * types. 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | int main(void) 23 | { 24 | printf("\nchar:\n"); 25 | printf("Size of char: %d bits\n", CHAR_BIT); 26 | printf("Maximum value of char: %d\n", CHAR_MAX); 27 | printf("Minimum value of char: %d\n", CHAR_MIN); 28 | printf("Maximum value of signed char: %d\n", SCHAR_MAX); 29 | printf("Minimum value of signed char: %d\n", SCHAR_MIN); 30 | printf("Maximum value of unsigned char: %u\n", UCHAR_MAX); 31 | printf("\nint:\n"); 32 | printf("Maximum value of int: %d\n", INT_MAX); 33 | printf("Minimum value of int: %d\n", INT_MIN); 34 | printf("Maximum value of unsigned int: %u\n", UINT_MAX); 35 | printf("\nlong:\n"); 36 | printf("Maximum value of long: %ld\n", LONG_MAX); 37 | printf("Minimum value of long: %ld\n", LONG_MIN); 38 | printf("Maximum value of unsigned long: %lu\n", ULONG_MAX); 39 | printf("\nshort:\n"); 40 | printf("Maximum value of short: %d\n", SHRT_MAX); 41 | printf("Minimum value of short: %d\n", SHRT_MIN); 42 | printf("Maximum value of unsigned short: %u\n", USHRT_MAX); 43 | return EXIT_SUCCESS; 44 | } 45 | -------------------------------------------------------------------------------- /Chapter 2/2-10/lower.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: rightrot.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-9, page 51 10 | * 11 | * Rewrite the function lower, which converts upper case letters to 12 | * lower case, with a conditional expression instead of if-else. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | int lower(int c); 19 | 20 | int main(void) 21 | { 22 | putchar(lower('R')); 23 | putchar('\n'); 24 | return EXIT_SUCCESS; 25 | } 26 | 27 | /* lower: convert c to lower case; ASCII only */ 28 | int lower(int c) 29 | { 30 | return ('A' <= c && c <= 'Z') ? c - 'A' + 'a' : c; 31 | } 32 | -------------------------------------------------------------------------------- /Chapter 2/2-2/loop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: loop.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-2, page 42 10 | * 11 | * Write a loop equivalent to the for loop above without using && or ||. 12 | * 13 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 14 | * The original loop: 15 | * for (i=0;i 20 | #include 21 | 22 | #define LIMIT 512 23 | 24 | int main(void) 25 | { 26 | int i; 27 | int c, lim; 28 | char s[LIMIT]; 29 | 30 | lim = LIMIT; 31 | i = 0; 32 | while(i < lim-1) { 33 | c = getchar(); 34 | if (c == '\n') 35 | lim = 0; /* We haven't encountered breaks yet. */ 36 | else if (c == EOF) 37 | lim = 0; 38 | else 39 | s[i++] = c; 40 | } 41 | s[i] = '\0'; /* Terminate the string, */ 42 | printf("%s\n", s); /* and print it. */ 43 | 44 | return EXIT_SUCCESS; 45 | } 46 | -------------------------------------------------------------------------------- /Chapter 2/2-3/htoi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: htoi.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-3, page 46 10 | * 11 | * Write the function htoi(s), which converts a string of hexadecimal 12 | * digits (including an optional 0x or 0X) into its equivalent integer 13 | * value. The allowable digits are 0 through 9, a through f, and A 14 | * through F. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | int htoi(char s[]); 21 | 22 | int main(void) 23 | { 24 | char s[1024]; 25 | int i, c; 26 | for (i=0; (c = getchar()) != '\n'; i++) 27 | s[i] = c; 28 | s[i] = '\0'; 29 | printf("%s: %d\n", s, htoi(s)); 30 | return EXIT_SUCCESS; 31 | } 32 | 33 | /* htoi: convert hexdicimal string s to integer */ 34 | int htoi(char s[]) 35 | { 36 | int i; 37 | int c, n; 38 | 39 | n = 0; 40 | for (i = 0; (c = s[i]) != '\0'; ++i) { 41 | n *= 16; 42 | if (i == 0 && c == '0') { 43 | /* Drop the 0x of 0X from the start of the string. */ 44 | c = s[++i]; 45 | if (c != 'x' && c != 'X') 46 | --i; 47 | } else if (c >= '0' && c <= '9') 48 | /* c is a numerical digit. */ 49 | n += c - '0'; 50 | else if (c >= 'a' && c <= 'f') 51 | /* c is a letter in the range 'a'-'f' */ 52 | n += 10 + (c - 'a'); 53 | else if (c >= 'A' && c <= 'F') 54 | /* c is a letter in the range 'A'-'F' */ 55 | n += 10 + (c - 'A'); 56 | else 57 | /* invalid input */ 58 | return n; 59 | } 60 | return n; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /Chapter 2/2-4/squeeze.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: squeeze.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-4, page 48 10 | * 11 | * Write an alternate version of squeeze(s1,s2) that deletes each 12 | * character in the string s1 that matches any character in the string 13 | * s2. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #define TRUE 1 20 | #define FALSE 0 21 | 22 | void squeeze(char s1[], char s2[]); 23 | 24 | int main(void) 25 | { 26 | char s1[] = "abcdef"; 27 | char s2[] = "bdf"; 28 | squeeze(s1, s2); 29 | printf("%s\n", s1); 30 | 31 | return EXIT_SUCCESS; 32 | } 33 | 34 | /* squeeze: delete all characters from s1 that match any in s2 */ 35 | void squeeze(char s1[], char s2[]) 36 | { 37 | int i, j, k; 38 | int instr2; 39 | 40 | for (i = j = 0; s1[i] != '\0'; i++) { 41 | instr2 = FALSE; 42 | for (k = 0; s2[k] != '\0' && !instr2; k++) 43 | if (s2[k] == s1[i]) 44 | instr2 = TRUE; 45 | if (!instr2) 46 | s1[j++] = s1[i]; 47 | } 48 | s1[j] = '\0'; 49 | } 50 | -------------------------------------------------------------------------------- /Chapter 2/2-5/any.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: any.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-5, page 48 10 | * 11 | * Write the function any(s1,s2), which returns the first location in 12 | * the string s1 where any character from the string s2 occurs, or -1 if 13 | * s1 contains no characters from s2. (The standard library function 14 | * strpbrk does the same job but returns a pointer to the location.) 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | int any(char s1[], char s2[]); 21 | 22 | int main(void) 23 | { 24 | char s1[] = "abcdef"; 25 | char s2[] = "def"; 26 | printf("%d\n", any(s1, s2)); 27 | 28 | return EXIT_SUCCESS; 29 | } 30 | 31 | /* any: returns the first location in s1 where any character from s2 32 | occurs, or -1 if s1 contains no characters from s2. */ 33 | int any(char s1[], char s2[]) 34 | { 35 | int i, k; 36 | 37 | for (i = 0; s1[i] != '\0'; i++) 38 | for (k = 0; s2[k] != '\0'; k++) 39 | if (s1[i] == s2[k]) 40 | return i; 41 | return -1; /* s1 contains no characters from s2 */ 42 | } 43 | -------------------------------------------------------------------------------- /Chapter 2/2-6/setbits.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: setbits.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-6, page 49 10 | * Answer to Exercise 2-6, page 49 11 | * 12 | * Write a function setbits(x,p,n,y) that returns x with the n bits that 13 | * begin at position p set to the rightmost n bits of y, leaving the 14 | * other bits unchanged. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | unsigned setbits(unsigned x, int p, int n, int y); 21 | 22 | int main(void) 23 | { 24 | printf("%u\n", setbits(170, 4, 3, 7)); 25 | return EXIT_SUCCESS; 26 | } 27 | 28 | /* getbits: place n rightmost bits from position p at position y */ 29 | unsigned setbits(unsigned x, int p, int n, int y) 30 | { 31 | int i, mask, j; 32 | /* The rightmost n bits of y. */ 33 | i = (x >> (y+1-n)) & ~(~0 << n); 34 | /* A mask with zeros at the rightmost n bits of p. */ 35 | mask = ~(((1 << n)-1) << (p+1-n)); 36 | /* Make rightmost n bits of p zero ... */ 37 | j = mask & x; 38 | /* ... and replace them with the rightmost n bits of y. */ 39 | return j | i << (p+1-n); 40 | } 41 | 42 | -------------------------------------------------------------------------------- /Chapter 2/2-7/invert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: invert.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-7, page 49 10 | * 11 | * Write a function invert(x,p,n) that returns x with the n bits that 12 | * begin at position p inverted (i.e., 1 changed into 0 and vice versa), 13 | * leaving the others unchanged. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | unsigned invert(unsigned x, int p, int n); 20 | 21 | int main(void) 22 | { 23 | printf("%u\n", invert(240, 4, 3)); 24 | return EXIT_SUCCESS; 25 | } 26 | 27 | /* invert: returns x with n bits that begin at position p inverted */ 28 | unsigned invert(unsigned x, int p, int n) 29 | { 30 | int mask; 31 | /* Mask with leftmost n bits of p set */ 32 | mask = (~(~0U << n)) << (p-n+1); 33 | return mask ^ x; 34 | } 35 | -------------------------------------------------------------------------------- /Chapter 2/2-8/rightrot.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: rightrot.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-8, page 49 10 | * 11 | * Write a function rightrot(x,n) that returns the value of the integer 12 | * x rotated to the right by n bit positions. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | unsigned rightrot(unsigned x, unsigned n); 19 | 20 | int main(void) 21 | { 22 | printf("%u\n", rightrot(3, 1)); 23 | return EXIT_SUCCESS+; 24 | } 25 | 26 | /*rightrot: rotates x to the right by n bit positions */ 27 | unsigned rightrot(unsigned x, unsigned n) 28 | { 29 | while (n > 0) { 30 | if(x & 1) /* rightmost bit of x is 1 */ 31 | x = (x >> 1) | ~(~0U >> 1); 32 | else /* rightmost bit of x is 0 */ 33 | x = x >> 1; 34 | --n; 35 | } 36 | return x; 37 | } 38 | 39 | -------------------------------------------------------------------------------- /Chapter 2/2-9/bitcount.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: rightrot.c 3 | * Author: Thomas van der Burgt 4 | * Date: 23-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 2-9, page 51 10 | * 11 | * In a two's complement number system, x &= (x-1) deletes the rightmost 12 | * 1-bit in x. Explain why. Use this observation to write a faster 13 | * version of bitcount. 14 | * 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | * TODO 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | int bitcount(unsigned x); 23 | 24 | int main(void) 25 | { 26 | printf("%d\n", bitcount(0777)); 27 | return EXIT_SUCCESS; 28 | } 29 | 30 | /* bitcount: count set bits in x */ 31 | int bitcount(unsigned x) 32 | { 33 | int b; 34 | for (b = 0; x != 0; x &= (x-1)) 35 | b++; 36 | return b; 37 | } 38 | -------------------------------------------------------------------------------- /Chapter 3/3-1/binsearch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: binsearch.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-1, page 58 10 | * 11 | * Our binary search makes two tests inside the loop, when one would 12 | * suffice (at the price of more tests outside). Write a version with 13 | * only one test inside the loop and measure the difference in run-time. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ 20 | int binsearch(int x, int v[], int n) 21 | { 22 | int low, high, mid; 23 | 24 | low = 0; 25 | high = n-1; 26 | while(low < high) { 27 | mid = (low + high) / 2; 28 | if(x <= v[mid]) 29 | high = mid; 30 | else 31 | low = mid+1; 32 | } 33 | return (x == v[low]) ? low : -1; 34 | } 35 | 36 | int main(void) 37 | { 38 | int v[5] = {3, 6, 9, 12, 4}; 39 | int x = 36; 40 | printf("%d\n", binsearch(x, v, 5)); 41 | return EXIT_SUCCESS; 42 | } 43 | -------------------------------------------------------------------------------- /Chapter 3/3-2/escape.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: escape.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-2, page 60 10 | * 11 | * Write a function escape(s,t) that converts characters like newline 12 | * and tab into visible escape sequences like \n and \t as it copies the 13 | * string t to s. Use a switch. Write a function for the other direction 14 | * as well, converting escape sequences into the real characters. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #define TRUE 1 21 | #define FALSE 0 22 | 23 | /* escape: converts newlines and tabs into visible escape sequenes as 24 | it copies the string t into s */ 25 | void escape(char s[], char t[]) 26 | { 27 | int i, j; 28 | 29 | for (i = j = 0; t[i] != '\0'; ++i) { 30 | switch (t[i]) { 31 | case '\n': 32 | s[j++] = '\\'; 33 | s[j++] = 'n'; 34 | break; 35 | case '\t': 36 | s[j++] = '\\'; 37 | s[j++] = 't'; 38 | break; 39 | default: 40 | s[j++] = t[i]; 41 | break; 42 | } 43 | } 44 | s[j] = '\0'; 45 | } 46 | 47 | /* unescape: converts escape sequenes '\n' and '\t' into newlines and 48 | tabs into as it copies the string t into s */ 49 | void unescape(char s[], char t[]) 50 | { 51 | int i, j; 52 | int slash; 53 | 54 | slash = FALSE; 55 | for (i = j = 0; t[i] != '\0'; ++i) { 56 | switch (t[i]) { 57 | case '\\': 58 | slash = TRUE; 59 | break; 60 | case 'n': 61 | if (slash) { 62 | s[j++] = '\n'; 63 | slash = FALSE; 64 | break; 65 | } 66 | case 't': 67 | if (slash) { 68 | s[j++] = '\t'; 69 | slash = FALSE; 70 | break; 71 | } 72 | default: 73 | s[j++] = t[i]; 74 | break; 75 | } 76 | } 77 | s[j] = '\0'; 78 | } 79 | 80 | int main(void) 81 | { 82 | int i; 83 | char c, s[1024], t[1024]; 84 | 85 | i = 0; 86 | while ((c = getchar()) != EOF) 87 | t[i++] = c; 88 | t[i] = '\0'; 89 | 90 | printf(">%s\n", t); 91 | escape(s, t); 92 | printf(">%s\n", s); 93 | unescape(t, s); 94 | printf(">%s\n", t); 95 | 96 | return EXIT_SUCCESS; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /Chapter 3/3-3/expand.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: expand.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-3, page 63 10 | * 11 | * Write a function expand(s1,s2) that expands shorthand notations like 12 | * a-z in the string s1 into the equivalent complete list abc...xyz in 13 | * s2. Allow for letters of either case and digits, and be prepared to 14 | * handle cases like a-b-c and a-z0-9 and -a-z. Arrange that a leading 15 | * or trailing - is taken literally. 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define TRUE 1 22 | #define FALSE 0 23 | 24 | void expand(char s1[], char s2[]); 25 | int validrange(char c1, char c2); 26 | 27 | int main(void) 28 | { 29 | char s1[512] = "-a-z 0-9 a-d-f -0-2 some text 1-1 WITH CAPITALS! 0-0 5-3 -"; 30 | char s2[512]; 31 | expand(s1, s2); 32 | printf("%s\n", s2); 33 | 34 | return EXIT_SUCCESS; 35 | } 36 | 37 | /* expand: expands shorthand notations in the string s1 into the 38 | equivalent complete list in s2 */ 39 | void expand(char s1[], char s2[]) 40 | { 41 | int i, j; 42 | char tmp; 43 | int dash; 44 | 45 | dash = 0; 46 | for (i = j = 0; s1[i] != '\0'; ++i) { 47 | if (s1[i] == '-') { 48 | if (i == 0 || s1[i+1] == '\0') { 49 | /* '-' is leading or trailing, so just copy it. */ 50 | s2[j++] = s1[i]; 51 | } else { 52 | /* check if this is a valid range. */ 53 | if (validrange(s1[i-1], s1[i+1])) { 54 | while (s2[j-1] < s1[i+1]) { 55 | s2[j] = s2[j-1] + 1; 56 | j++; 57 | } 58 | /* skip next character we already printed it. */ 59 | ++i; 60 | } else { 61 | s2[j++] = s1[i]; 62 | } 63 | } 64 | } else { 65 | s2[j++] = s1[i]; 66 | } 67 | } 68 | /* End the string with a NUL byte */ 69 | s2[j] = '\0'; 70 | } 71 | 72 | /* validrange: returns non-zero if c1-c2 is a valid range. */ 73 | int validrange(char c1, char c2) 74 | { 75 | if (('a' <= c1 && c1 <= 'z') && /* valid range in a-z */ 76 | (c1 <= c2 && c2 <= 'z')) 77 | return TRUE; 78 | if (('A' <= c1 && c1 <= 'Z') && /* valid range in A-Z */ 79 | (c1 <= c2 && c2 <= 'Z')) 80 | return TRUE; 81 | if (('0' <= c1 && c1 <= '9') && /* valid range in 0-9 */ 82 | (c1 <= c2 && c2 <= '9')) 83 | return TRUE; 84 | 85 | return FALSE; /* not a valid range */ 86 | } 87 | -------------------------------------------------------------------------------- /Chapter 3/3-4/itoa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itoa.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-4, page 64 10 | * 11 | * In a two's complement number representation, our version of itoa does 12 | * not handle the largest negative number, that is, the value of n equal 13 | * to -(2^(wordsize - 1)). Explain why not. Modify it to print that 14 | * value correctly regardless of the machine on which it runs. 15 | * 16 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 17 | * It does not handle the largest negative number because it does not 18 | * have a positive equivalent; -n where n is the largest negative number 19 | * gives n; because n is still negative n%10 gives negative values 20 | * instead of the desired positive ones. If we take the asbolute value 21 | * of n%10 we get the correct value and character. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | void itoa(int n, char s[]); 30 | void reverse(char s[]); 31 | 32 | int main(void) 33 | { 34 | int n = INT_MIN; 35 | char s[16]; 36 | 37 | itoa(1337, s); 38 | printf("%s\n", s); 39 | itoa(n, s); 40 | printf("%s\n", s); 41 | 42 | return EXIT_SUCCESS; 43 | } 44 | 45 | /* itoa: convert n to characters in s */ 46 | void itoa(int n, char s[]) 47 | { 48 | int i, sign; 49 | 50 | sign = n; 51 | i = 0; 52 | do { /* generate digits in reverse order */ 53 | s[i++] = abs(n % 10) + '0'; /* get next digit */ 54 | } while (n /= 10); /* delete it */ 55 | if (sign < 0) 56 | s[i++] = '-'; 57 | s[i] = '\0'; 58 | reverse(s); 59 | } 60 | 61 | /* reverse: reverse string s in place */ 62 | void reverse(char s[]) 63 | { 64 | int c, i, j; 65 | 66 | for (i = 0, j = strlen(s)-1; i < j; i++, j--) { 67 | c = s[i]; 68 | s[i] = s[j]; 69 | s[j] = c; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /Chapter 3/3-5/itob.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itob.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-5, page 64 10 | * 11 | * Write the function itob(n,s,b) that converts the integer n into a 12 | * base b character representation in the string s. In particular, 13 | * itob(n,s,16) formats n as a hexadecimal integer in s. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | void itob(int n, char s[], int b); 21 | void reverse(char s[]); 22 | 23 | int main(void) 24 | { 25 | char s[64]; 26 | itob(-255, s, 8); 27 | printf("%s\n", s); 28 | 29 | return EXIT_SUCCESS; 30 | } 31 | 32 | /* itob: comvert n to characters in base b in s */ 33 | void itob(int n, char s[], int b) 34 | { 35 | int i, sign; 36 | char symbols[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 37 | 38 | if (2 > b || b > strlen(symbols) ) 39 | return; /* not a valid base */ 40 | 41 | sign = n; 42 | i = 0; 43 | do { /* generate symbols in reverse order */ 44 | s[i++] = symbols[abs(n % b)]; /* get next symbols */ 45 | } while (n /= b); /* delete it */ 46 | if (sign < 0) 47 | s[i++] = '-'; 48 | s[i] = '\0'; 49 | reverse(s); 50 | } 51 | 52 | /* reverse: reverse string s in place */ 53 | void reverse(char s[]) 54 | { 55 | int c, i, j; 56 | 57 | for (i = 0, j = strlen(s)-1; i < j; i++, j--) { 58 | c = s[i]; 59 | s[i] = s[j]; 60 | s[j] = c; 61 | } 62 | } 63 | 64 | -------------------------------------------------------------------------------- /Chapter 3/3-6/itoa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itob.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-FEB-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 3-6, page 64 10 | * 11 | * Write a version of itoa that accepts three arguments instead of two. 12 | * The third argument is a minimum field width; the converted number 13 | * must be padded with blanks on the left if necessary to make it wide 14 | * enough. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | void itoa(int n, char s[], int w); 23 | void reverse(char s[]); 24 | 25 | int main(void) 26 | { 27 | int n = INT_MIN; 28 | char s[16]; 29 | 30 | itoa(1337, s, 8); 31 | printf("%s\n", s); 32 | itoa(n, s, 16); 33 | printf("%s\n", s); 34 | 35 | return EXIT_SUCCESS; 36 | } 37 | 38 | /* itoa: comvert n to characters in s, s is w width */ 39 | void itoa(int n, char s[], int w) 40 | { 41 | int i, sign; 42 | 43 | sign = n; 44 | i = 0; 45 | do { /* generate digits in reverse order */ 46 | s[i++] = abs(n % 10) + '0'; /* get next digit */ 47 | } while (n /= 10); /* delete it */ 48 | 49 | if (sign < 0) 50 | s[i++] = '-'; 51 | while (i < w) /* pad with blanks if necessary*/ 52 | s[i++] = ' '; 53 | 54 | s[i] = '\0'; 55 | reverse(s); 56 | } 57 | 58 | /* reverse: reverse string s in place */ 59 | void reverse(char s[]) 60 | { 61 | int c, i, j; 62 | 63 | for (i = 0, j = strlen(s)-1; i < j; i++, j--) { 64 | c = s[i]; 65 | s[i] = s[j]; 66 | s[j] = c; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Chapter 4/4-1/strindex.c: -------------------------------------------------------------------------------- 1 | /* strrindex: return index of rightmost t in s, -1 if none */ 2 | int strrindex(char s[], char t[]) 3 | { 4 | int i, j, k, rindex; 5 | 6 | rindex = -1; 7 | for (i = 0; s[i] != '\0'; i++) { 8 | for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++) 9 | ; 10 | if (k > 0 && t[k] == '\0' && i > rindex) 11 | rindex = i; 12 | } 13 | return rindex; 14 | } 15 | -------------------------------------------------------------------------------- /Chapter 4/4-1/strrindex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strrindex.c 3 | * Author: Thomas van der Burgt 4 | * Date: 08-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 4-1, page 71 10 | * 11 | * Write the function strrindex(s,t), which returns the position of the 12 | * rightmost occurrence of t in s, or -1 if there is none. 13 | */ 14 | 15 | /* strrindex: return index of rightmost t in s, -1 if none */ 16 | int strrindex(char s[], char t[]) 17 | { 18 | int i, j, k, rindex; 19 | 20 | rindex = -1; 21 | for (i = 0; s[i] != '\0'; i++) { 22 | /* check if t starts at this index in s */ 23 | for (j=i, k=0; t[k] != '\0' && s[j] == t[k]; j++, k++); 24 | if (k > 0 && t[k] == '\0') /* if it does ...*/ 25 | rindex = i; /* replace rindex with our find */ 26 | } 27 | return rindex; 28 | } 29 | -------------------------------------------------------------------------------- /Chapter 4/4-2/atof.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: atof.c 3 | * Author: Thomas van der Burgt 4 | * Date: 08-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 4-2, page 73 10 | * 11 | * Extend atof to handle scientific notation of the form 123.45e-6 12 | * where a floating-point number may be followed by e or E and an 13 | * optionally signed exponent. 14 | */ 15 | 16 | #include /* isspace() & isdigit() */ 17 | #include /* pow() */ 18 | 19 | /* atof: convert string s to double */ 20 | float atof(char s[]) 21 | { 22 | double val, power, exp; 23 | int i, sign, esign; 24 | 25 | for (i = 0; isspace(s[i]); i++) /* skip white space */ 26 | ; 27 | sign = (s[i] =='-') ? -1 : 1; 28 | if (s[i] == '+' || s[i] == '-') 29 | i++; 30 | for (val = 0.0; isdigit(s[i]); i++) /* integer */ 31 | val = 10.0 * val + (s[i] - '0'); 32 | if (s[i] == '.') { /* fraction */ 33 | i++; 34 | for (power = 1.0; isdigit(s[i]); i++) { 35 | val = 10.0 * val + (s[i] - '0'); 36 | power *= 10.0; 37 | } 38 | val *= sign / power; 39 | } 40 | if (s[i] == 'e' || s[i] == 'E') { /* exponent*/ 41 | esign = (s[++i] == '-') ? -1 : 1; 42 | if (s[i] == '+' || s[i] == '-') 43 | i++; 44 | for (exp = 0.0; isdigit(s[i]); i++) 45 | exp = 10.0 * exp + (s[i] - '0'); 46 | val *= pow(10, esign * exp); 47 | } 48 | return val; 49 | } 50 | -------------------------------------------------------------------------------- /Chapter 4/4-3/polishcalc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: polishcalc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 08-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 4-3, page 79 10 | * 11 | * Given the basic framework, it's straightforward to extend the 12 | * calculator. Add the modulus (%) operator and provisions for 13 | * negative numbers. 14 | */ 15 | 16 | #include 17 | #include /* EXIT_SUCCESS, atof() */ 18 | #include /* fmod() */ 19 | 20 | #define MAXOP 100 /* max size of operand or operator */ 21 | #define NUMBER '0' /* signal that a number was found */ 22 | 23 | int getop(char []); 24 | void push(double); 25 | double pop(void); 26 | 27 | /* reverse Polish calculator */ 28 | int main(void) 29 | { 30 | int type; 31 | double op2; 32 | char s[MAXOP]; 33 | 34 | while ((type = getop(s)) != EOF) { 35 | switch (type) { 36 | case NUMBER: 37 | push(atof(s)); 38 | break; 39 | case '+': 40 | push(pop() + pop()); 41 | break; 42 | case '*': 43 | push(pop() * pop()); 44 | break; 45 | case '-': 46 | op2 = pop(); 47 | push(pop() - op2); 48 | break; 49 | case '/': 50 | op2 = pop(); 51 | if (op2 != 0.0) 52 | push(pop() / op2); 53 | else 54 | printf("error: zero devisor\n"); 55 | break; 56 | case '%': 57 | op2 = pop(); 58 | if (op2 != 0.0) 59 | push(fmod(pop(), op2)); 60 | else 61 | printf("error: zero devisor\n"); 62 | break; 63 | case '\n': 64 | printf("\t%.8g\n", pop()); 65 | break; 66 | default: 67 | printf("error: unknown command %s\n", s); 68 | break; 69 | } 70 | } 71 | return EXIT_SUCCESS; 72 | } 73 | 74 | #define MAXVAL 100 /* maximum depth of val stack*/ 75 | 76 | int sp = 0; /* next free stack position */ 77 | double val[MAXVAL]; /* value stack */ 78 | 79 | /* push: push f onto stack */ 80 | void push(double f) 81 | { 82 | if (sp < MAXVAL) 83 | val[sp++] = f; 84 | else 85 | printf("error: stack full, can't push %g\n", f); 86 | } 87 | 88 | /* pop: pop and return top value from stack */ 89 | double pop(void) 90 | { 91 | if (sp > 0) 92 | return val[--sp]; 93 | else { 94 | printf("error: stack empty\n"); 95 | return 0.0; 96 | } 97 | } 98 | 99 | #include 100 | 101 | int getch(void); 102 | void ungetch(int); 103 | 104 | /* getop: get next operator or numeric operand */ 105 | int getop(char s[]) 106 | { 107 | int i, c; 108 | 109 | while ((s[0] = c = getch()) == ' ' || c == '\t'); 110 | s[1] = '\0'; 111 | if (!isdigit(c) && c != '.' && c != '-') 112 | return c; /* not a number */ 113 | i = 0; 114 | if (isdigit(c) || c == '-') /* collect integer part */ 115 | while (isdigit(s[++i] = c = getch())); 116 | if (c == '.') /* collect fraction part */ 117 | while (isdigit(s[++i] = c = getch())); 118 | s[i] = '\0'; /* terminate string */ 119 | if (c != EOF) 120 | ungetch(c); 121 | return NUMBER; 122 | } 123 | 124 | #define BUFSIZE 100 125 | 126 | char buf[BUFSIZE]; /* buffer for ungetch */ 127 | int bufp = 0; /* next free position in buf */ 128 | 129 | int getch(void) /* get a (possibly pushed back) character */ 130 | { 131 | return (bufp > 0) ? buf[--bufp] : getchar(); 132 | } 133 | 134 | void ungetch(int c) /* push character back on input */ 135 | { 136 | if (bufp >= BUFSIZE) 137 | printf("ungetch: too many characters\n"); 138 | else 139 | buf[bufp++] = c; 140 | } 141 | -------------------------------------------------------------------------------- /Chapter 4/4-4/polishcalc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: polishcalc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 08-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 4-4, page 79 10 | * 11 | * Add commands to print the top element of the stack without popping, 12 | * to duplicate it, and to swap the top two elements. Add a command to 13 | * clear the stack. 14 | * 15 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | * I added the following functions: 17 | * - void show_top(void); 18 | * - void duplicate_top(void); 19 | * - void swap_top(void); 20 | * - void clear(void); 21 | */ 22 | 23 | #include 24 | #include 25 | 26 | #define MAXOP 100 /* max size of operand or operator */ 27 | #define NUMBER '0' /* signal that a number was found */ 28 | 29 | int getop(char []); 30 | void push(double); 31 | double pop(void); 32 | void show_top(void); 33 | void duplicate_top(void); 34 | void swap_top(void); 35 | void clear(void); 36 | 37 | /* reverse Polish calculator */ 38 | int main(void) 39 | { 40 | int type; 41 | double op2; 42 | char s[MAXOP]; 43 | 44 | while ((type = getop(s)) != EOF) { 45 | switch (type) { 46 | case NUMBER: 47 | push(atof(s)); 48 | break; 49 | case '+': 50 | push(pop() + pop()); 51 | break; 52 | case '*': 53 | push(pop() * pop()); 54 | break; 55 | case '-': 56 | op2 = pop(); 57 | push(pop() - op2); 58 | break; 59 | case '/': 60 | op2 = pop(); 61 | if (op2 != 0.0) 62 | push(pop() / op2); 63 | else 64 | printf("error: zero devisor\n"); 65 | break; 66 | case '%': 67 | op2 = pop(); 68 | if (op2 != 0.0) 69 | push(fmod(pop(), op2)); 70 | else 71 | printf("error: zero devisor\n"); 72 | break; 73 | case '\n': 74 | printf("\t%.8g\n", pop()); 75 | break; 76 | default: 77 | printf("error: unknown command %s\n", s); 78 | break; 79 | } 80 | } 81 | return EXIT_SUCCESS; 82 | } 83 | 84 | #define MAXVAL 100 /* maximum depth of val stack*/ 85 | 86 | int sp = 0; /* next free stack position */ 87 | double val[MAXVAL]; /* value stack */ 88 | 89 | /* push: push f onto stack */ 90 | void push(double f) 91 | { 92 | if (sp < MAXVAL) 93 | val[sp++] = f; 94 | else 95 | printf("error: stack full, can't push %g\n", f); 96 | } 97 | 98 | /* pop: pop and return top value from stack */ 99 | double pop(void) 100 | { 101 | if (sp > 0) 102 | return val[--sp]; 103 | else { 104 | printf("error: stack empty\n"); 105 | return 0.0; 106 | } 107 | } 108 | 109 | /* show_top: prints the top element of the stack without popping */ 110 | void show_top(void) 111 | { 112 | if (sp > 0) 113 | printf("top element of stack: %g\n", val[sp-1]); 114 | else 115 | printf("error: stack empty\n"); 116 | } 117 | 118 | /* duplicate: duplicates the top element of the stack */ 119 | void duplicate_top(void) 120 | { 121 | double tmp = pop(); 122 | push(tmp); 123 | push(tmp); 124 | } 125 | 126 | /* swap: swap the two top elements of the stack */ 127 | void swap_top(void) 128 | { 129 | double tmp1 = pop(); 130 | double tmp2 = pop(); 131 | push(tmp1); 132 | push(tmp2); 133 | } 134 | 135 | /* clear: clear the stack */ 136 | void clear(void) 137 | { 138 | sp = 0; 139 | } 140 | 141 | #include 142 | 143 | int getch(void); 144 | void ungetch(int); 145 | 146 | /* getop: get next operator or numeric operand */ 147 | int getop(char s[]) 148 | { 149 | int i, c; 150 | 151 | while ((s[0] = c = getch()) == ' ' || c == '\t'); 152 | s[1] = '\0'; 153 | if (!isdigit(c) && c != '.' && c != '-') 154 | return c; /* not a number */ 155 | i = 0; 156 | if (isdigit(c) || c == '-') /* collect integer part */ 157 | while (isdigit(s[++i] = c = getch())); 158 | if (c == '.') /* collect fraction part */ 159 | while (isdigit(s[++i] = c = getch())); 160 | s[i] = '\0'; /* terminate string */ 161 | if (c != EOF) 162 | ungetch(c); 163 | return NUMBER; 164 | } 165 | 166 | #define BUFSIZE 100 167 | 168 | char buf[BUFSIZE]; /* buffer for ungetch */ 169 | int bufp = 0; /* next free position in buf */ 170 | 171 | int getch(void) /* get a (possibly pushed back) character */ 172 | { 173 | return (bufp > 0) ? buf[--bufp] : getchar(); 174 | } 175 | 176 | void ungetch(int c) /* push character back on input */ 177 | { 178 | if (bufp >= BUFSIZE) 179 | printf("ungetch: too many characters\n"); 180 | else 181 | buf[bufp++] = c; 182 | } 183 | -------------------------------------------------------------------------------- /Chapter 4/4-5/4-5.c: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | 3 | filename: polishcalc.c 4 | 5 | author: Thomas van der Burgt 6 | date: 2010-02-25 7 | 8 | description: 9 | 10 | The C Programming Language, second edition, 11 | by Brian Kernighan and Dennis Ritchie 12 | 13 | Exercise 4-5, page 79 14 | 15 | Add access to library functions like sin, exp , and pow. See 16 | in Appendix B, Section 4. 17 | 18 | comments: 19 | 20 | ***********************************************************************/ 21 | 22 | #include 23 | #include 24 | 25 | #define MAXOP 100 /* max size of operand or operator */ 26 | #define NUMBER '0' /* signal that a number was found */ 27 | 28 | int getop(char []); 29 | void push(double); 30 | double pop(void); 31 | 32 | /* reverse Polish calculator */ 33 | int main(void) 34 | { 35 | int type; 36 | double op2; 37 | char s[MAXOP]; 38 | 39 | while ((type = getop(s)) != EOF) { 40 | switch (type) { 41 | case NUMBER: 42 | push(atof(s)); 43 | break; 44 | case '+': 45 | push(pop() + pop()); 46 | break; 47 | case '*': 48 | push(pop() * pop()); 49 | break; 50 | case '-': 51 | op2 = pop(); 52 | push(pop() - op2); 53 | break; 54 | case '/': 55 | op2 = pop(); 56 | if (op2 != 0.0) 57 | push(pop() / op2); 58 | else 59 | printf("error: zero devisor\n"); 60 | break; 61 | case '\n': 62 | printf("\t%.8g\n", pop()); 63 | break; 64 | default: 65 | printf("error: unknown command %s\n", s); 66 | break; 67 | } 68 | } 69 | return EXIT_SUCCESS; 70 | } 71 | 72 | 73 | #define MAXVAL 100 /* maximum depth of val stack*/ 74 | 75 | int sp = 0; /* next free stack position */ 76 | double val[MAXVAL]; /* value stack */ 77 | 78 | /* push: push f onto stack */ 79 | void push(double f) 80 | { 81 | if (sp < MAXVAL) 82 | val[sp++] = f; 83 | else 84 | printf("error: stack full, can't push %g\n", f); 85 | } 86 | 87 | 88 | /* pop: pop and return top value from stack */ 89 | double pop(void) 90 | { 91 | if (sp > 0) 92 | return val[--sp]; 93 | else { 94 | printf("error: stack empty\n"); 95 | return 0.0; 96 | } 97 | } 98 | 99 | #include 100 | 101 | int getch(void); 102 | void ungetch(int); 103 | 104 | /* getop: get next operator or numeric operand */ 105 | int getop(char s[]) 106 | { 107 | int i, c; 108 | 109 | while ((s[0] = c = getch()) == ' ' || c == '\t') 110 | ; 111 | s[1] = '\0'; 112 | if (!isdigit(c) && c != '.') 113 | return c; /* not a number */ 114 | i = 0; 115 | if (isdigit(c)) /* collect integer part */ 116 | while (isdigit(s[++i] = c = getch())) 117 | ; 118 | if (c == '.') /* collect fraction part */ 119 | while (isdigit(s[++i] = c = getch())) 120 | ; 121 | s[i] = '\0'; 122 | if (c != EOF) 123 | ungetch(c); 124 | return NUMBER; 125 | } 126 | 127 | #define BUFSIZE 100 128 | 129 | char buf[BUFSIZE]; /* buffer for ungetch */ 130 | int bufp = 0; /* next free position in buf */ 131 | 132 | int getch(void) /* get a (possibly pushed back) character */ 133 | { 134 | return (bufp > 0) ? buf[--bufp] : getchar(); 135 | } 136 | 137 | void ungetch(int c) /* push character back on input */ 138 | { 139 | if (bufp >= BUFSIZE) 140 | printf("ungetch: too many characters\n"); 141 | else 142 | buf[bufp++] = c; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /Chapter 4/4-5/polishcalc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: polishcalc.c 3 | * Author: Thomas van der Burgt 4 | * Date: 08-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 4-5, page 79 10 | * 11 | * Add access to library functions like sin, exp, and pow. See 12 | * in Appendix B, Section 4. 13 | */ 14 | 15 | #include 16 | #include 17 | #include /* strcmp */ 18 | #include /* sin, exp & pow */ 19 | 20 | #define MAXOP 100 /* max size of operand or operator */ 21 | #define NUMBER '0' /* signal that a number was found */ 22 | #define LIBFUNC '1' /* signal that a library function was found */ 23 | 24 | void dofunc(char []); 25 | int getop(char []); 26 | void push(double); 27 | double pop(void); 28 | 29 | /* reverse Polish calculator */ 30 | int main(void) 31 | { 32 | int type; 33 | double op2; 34 | char s[MAXOP]; 35 | 36 | while ((type = getop(s)) != EOF) { 37 | switch (type) { 38 | case NUMBER: 39 | push(atof(s)); 40 | break; 41 | case LIBFUNC: 42 | dofunc(s); 43 | break; 44 | case '+': 45 | push(pop() + pop()); 46 | break; 47 | case '*': 48 | push(pop() * pop()); 49 | break; 50 | case '-': 51 | op2 = pop(); 52 | push(pop() - op2); 53 | break; 54 | case '/': 55 | op2 = pop(); 56 | if (op2 != 0.0) 57 | push(pop() / op2); 58 | else 59 | printf("error: zero devisor\n"); 60 | break; 61 | case '\n': 62 | printf("\t%.8g\n", pop()); 63 | break; 64 | default: 65 | printf("error: unknown command %s\n", s); 66 | break; 67 | } 68 | } 69 | return EXIT_SUCCESS; 70 | } 71 | 72 | /* dofunc: execute the function in s, push answer. */ 73 | void dofunc(char s[]) 74 | { 75 | double op1, op2; 76 | if (strcmp(s, "sin") == 0) /* sine*/ 77 | push(sin(pop())); 78 | else if (strcmp(s, "cos") == 0) /* cosine */ 79 | push(cos(pop())); 80 | else if (strcmp(s, "tan") == 0) /* tangent */ 81 | push(cos(pop())); 82 | else if (strcmp(s, "exp") == 0) /* exponential function */ 83 | push(exp(pop())); 84 | else if (strcmp(s, "pow") == 0) { /* x to the power of y */ 85 | op2 = pop(); 86 | op1 = pop(); 87 | if (op1 == 0 && op2 <= 0) 88 | printf("error: domain (%g^%g)\n", op1, op2); 89 | else 90 | push(pow(pop(), op2)); 91 | } else { 92 | printf("error: unknown command %s\n", s); 93 | } 94 | } 95 | 96 | #define MAXVAL 100 /* maximum depth of val stack*/ 97 | 98 | int sp = 0; /* next free stack position */ 99 | double val[MAXVAL]; /* value stack */ 100 | 101 | /* push: push f onto stack */ 102 | void push(double f) 103 | { 104 | if (sp < MAXVAL) 105 | val[sp++] = f; 106 | else 107 | printf("error: stack full, can't push %g\n", f); 108 | } 109 | 110 | 111 | /* pop: pop and return top value from stack */ 112 | double pop(void) 113 | { 114 | if (sp > 0) 115 | return val[--sp]; 116 | else { 117 | printf("error: stack empty\n"); 118 | return 0.0; 119 | } 120 | } 121 | 122 | #include 123 | 124 | int getch(void); 125 | void ungetch(int); 126 | 127 | /* getop: get next operator or numeric operand */ 128 | int getop(char s[]) 129 | { 130 | int i, c; 131 | 132 | while ((s[0] = c = getch()) == ' ' || c == '\t'); 133 | s[1] = '\0'; 134 | i = 0; 135 | if (isalpha(c)) { 136 | while (isalpha(s[++i] = c = getch())); 137 | s[i] = '\0'; 138 | if (c != EOF) 139 | ungetch(c); 140 | return LIBFUNC; 141 | } 142 | if (!isdigit(c) && c != '.' && c != '-') 143 | return c; /* not a number */ 144 | if (isdigit(c) || c == '-') /* collect integer part */ 145 | while (isdigit(s[++i] = c = getch())); 146 | if (c == '.') /* collect fraction part */ 147 | while (isdigit(s[++i] = c = getch())); 148 | s[i] = '\0'; /* terminate string */ 149 | if (c != EOF) 150 | ungetch(c); 151 | return NUMBER; 152 | } 153 | 154 | #define BUFSIZE 100 155 | 156 | char buf[BUFSIZE]; /* buffer for ungetch */ 157 | int bufp = 0; /* next free position in buf */ 158 | 159 | int getch(void) /* get a (possibly pushed back) character */ 160 | { 161 | return (bufp > 0) ? buf[--bufp] : getchar(); 162 | } 163 | 164 | void ungetch(int c) /* push character back on input */ 165 | { 166 | if (bufp >= BUFSIZE) 167 | printf("ungetch: too many characters\n"); 168 | else 169 | buf[bufp++] = c; 170 | } 171 | -------------------------------------------------------------------------------- /Chapter 5/5-1/getch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getch.c 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | #include 17 | 18 | #define BUFSIZE 100 19 | 20 | char buf[BUFSIZE]; /* buffer for ungetch */ 21 | int bufp = 0; /* next free position in buf */ 22 | 23 | int getch(void) /* get a (possibly pushed-back) character */ 24 | { 25 | return (bufp > 0) ? buf[--bufp] : getchar(); 26 | } 27 | 28 | void ungetch(int c) /* push character back on input */ 29 | { 30 | if (bufp >= BUFSIZE) 31 | printf("ungetch: too many characters\n"); 32 | else 33 | buf[bufp++] = c; 34 | } 35 | -------------------------------------------------------------------------------- /Chapter 5/5-1/getch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getch.h 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | int getch(void); 17 | void ungetch(int c); 18 | -------------------------------------------------------------------------------- /Chapter 5/5-1/getint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getint.c 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | #include 17 | #include 18 | #include "getch.h" 19 | 20 | /* getint: get next integer from input into *pn */ 21 | int getint(int *pn) 22 | { 23 | int c, sign; 24 | 25 | while (isspace(c = getch())) /* skip white space */ 26 | ; 27 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 28 | ungetch(c); /* it's not a number */ 29 | return 0; 30 | } 31 | sign = (c == '-') ? -1 : 1; 32 | if (c == '+' || c == '-') { 33 | c = getch(); 34 | if (!isdigit(c)) { /* + or - not followed by a digit */ 35 | ungetch(c); /* ungetch non-digit */ 36 | ungetch(sign == 1 ? '+' : '-'); /* ungetch + or - */ 37 | return 0; 38 | } 39 | } 40 | for (*pn = 0; isdigit(c); c = getch()) 41 | *pn = 10 * *pn + (c - '0'); 42 | *pn *= sign; 43 | if (c != EOF) 44 | ungetch(c); 45 | return c; 46 | } 47 | -------------------------------------------------------------------------------- /Chapter 5/5-1/getint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getint.h 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | int getint(int *pn); 17 | -------------------------------------------------------------------------------- /Chapter 5/5-1/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: main.c 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | #include 17 | #include 18 | #include "getint.h" 19 | 20 | /* sample implementation of getint */ 21 | int main(void) 22 | { 23 | int i, r; 24 | 25 | r = getint(&i); 26 | if (r > 0) 27 | printf("%d\n", i); 28 | else if (r == 0) 29 | printf("not a number\n"); 30 | else if (r == EOF) 31 | printf("end of file\n"); 32 | else 33 | printf("wtf happend?\n"); 34 | return EXIT_SUCCESS; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter 5/5-2/getch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getch.c 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | #include 17 | 18 | #define BUFSIZE 100 19 | 20 | char buf[BUFSIZE]; /* buffer for ungetch */ 21 | int bufp = 0; /* next free position in buf */ 22 | 23 | int getch(void) /* get a (possibly pushed-back) character */ 24 | { 25 | return (bufp > 0) ? buf[--bufp] : getchar(); 26 | } 27 | 28 | void ungetch(int c) /* push character back on input */ 29 | { 30 | if (bufp >= BUFSIZE) 31 | printf("ungetch: too many characters\n"); 32 | else 33 | buf[bufp++] = c; 34 | } 35 | -------------------------------------------------------------------------------- /Chapter 5/5-2/getch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getch.h 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-1, page 97 10 | * 11 | * As written, getint treats a + or - not followed by a digit as a valid 12 | * representation of zero. Fix it to push such a character back on the 13 | * input. 14 | */ 15 | 16 | int getch(void); 17 | void ungetch(int c); 18 | -------------------------------------------------------------------------------- /Chapter 5/5-2/getfloat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getfloat.c 3 | * Author: Thomas van der Burgt 4 | * Date: 01-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-2, page 97 10 | * 11 | * Write getfloat, the floating-point analog of getint. What type does 12 | * getfloat return as its function value? 13 | * 14 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | * The function returns an int 16 | */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "getch.h" 24 | 25 | /* getfloat: get next float from input into *pn */ 26 | int getfloat(float *pn) 27 | { 28 | double power; 29 | int c, sign, exp, esign, bigE; 30 | 31 | while (isspace(c = getch())) /* skip white space */ 32 | ; 33 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 34 | ungetch(c); /* it's not a number */ 35 | return 0; 36 | } 37 | sign = (c == '-') ? -1 : 1; 38 | if (c == '+' || c == '-') { 39 | c = getch(); 40 | if (!isdigit(c)) { /* + or - not followed by a digit */ 41 | ungetch(c); /* ungetch non-digit */ 42 | ungetch(sign == 1 ? '+' : '-'); /* ungetch + or - */ 43 | return 0; 44 | } 45 | } 46 | for (*pn = 0.0; isdigit(c); c = getch()) /* integer part */ 47 | *pn = 10.0 * *pn + (c - '0'); 48 | if (c == '.') 49 | c = getchar(); 50 | for (power = 1.0; isdigit(c); c = getch()) { /* fractional part */ 51 | *pn = 10.0 * *pn + (c - '0'); 52 | power *= 10.0; 53 | } 54 | bigE = (c == 'E') ? 1 : 0; 55 | if (c == 'e' || c == 'E') { 56 | c = getch(); 57 | esign = (c == '-') ? -1 : 1; 58 | if (c == '+' || c == '-') { 59 | c = getch(); 60 | if (!isdigit(c)) { /* + or - not followed by a digit */ 61 | ungetch(c); 62 | ungetch(sign == 1 ? '+' : '-'); 63 | } 64 | } else if (!isdigit(c)) { /* e or E not followed by an int */ 65 | ungetch(c); 66 | ungetch(bigE == 0 ? 'e' : 'E'); 67 | } 68 | for (exp = 0; isdigit(c); c = getch()) /* exponent part */ 69 | exp = 10 * exp + (c - '0'); 70 | *pn *= (sign / power) * pow(10, esign * exp); 71 | } else { 72 | *pn *= (sign / power); 73 | } 74 | if (c != EOF) 75 | ungetch(c); 76 | return c; 77 | } 78 | 79 | /* sample implementation of getfloat */ 80 | int main(void) 81 | { 82 | float f; 83 | int r; 84 | 85 | r = getfloat(&f); 86 | if (r > 0) 87 | printf("(%c) %g\n", r, f); 88 | else if (r == 0) 89 | printf("not a number\n"); 90 | else if (r == EOF) 91 | printf("end of file\n"); 92 | else 93 | printf("wtf happend?\n"); 94 | return EXIT_SUCCESS; 95 | } 96 | -------------------------------------------------------------------------------- /Chapter 5/5-3/strcat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strcat.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-3, page 107 10 | * 11 | * Write a pointer version of the function strcat that we showed in 12 | * Chapter 2: strcat(s,t) copies the string t to the end of s. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | /* strcat: concatenate t to end of s; s must be big enough */ 19 | void strcat(char *s, const char *t) 20 | { 21 | while (*s) /* find end of s */ 22 | s++; 23 | while (*t) /* copy t */ 24 | *s++ = *t++; 25 | *s = '\0'; 26 | } 27 | 28 | int main(void) 29 | { 30 | char s[100] = "ab\0c"; 31 | char t[100] = "def"; 32 | strcat(s, t); 33 | puts(s); 34 | return EXIT_SUCCESS; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter 5/5-4/strend.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strend.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-4, page 107 10 | * 11 | * Write the function strend(s,t), which returns 1 if the string t 12 | * occurs at the end of the string s, and zero otherwise. 13 | */ 14 | 15 | #include 16 | #include 17 | 18 | /* strend: returns 1 if the string t occurs at the end of the string s, 19 | and zero otherwise */ 20 | int strend(const char *s, const char *t) 21 | { 22 | int ls, lt; 23 | 24 | for (ls = 0; *(s+ls); ++ls); /* find length of s */ 25 | for (lt = 0; *(t+lt); ++lt); /* find length of t */ 26 | if (ls >= lt) { /* check if t can fit in s */ 27 | s += ls - lt; /* point s to where t should start */ 28 | while (*s++ == *t++) 29 | if (!*s) /* we found end of s and therefore t */ 30 | return 1; /* so return 1 */ 31 | } 32 | return 0; 33 | } 34 | 35 | int main(void) 36 | { 37 | char s[100] = "abcdef\0xyz"; 38 | char t[100] = "def\0klm"; 39 | printf("%d\n", strend(s, t)); 40 | return EXIT_SUCCESS; 41 | } 42 | -------------------------------------------------------------------------------- /Chapter 5/5-5/strncat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strncat.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-5, page 107 10 | * 11 | * Write versions of the library functions strncpy, strncat and strncmp, 12 | * which operate on at most the first n characters of their argument 13 | * strings. For example, strncpy(s,t,n) copies at most n characters of 14 | * t to s. Full descriptions are in Appendix B. 15 | */ 16 | 17 | /* strcat: concatenate at most n characters of t to the end of s; s 18 | must be big enough */ 19 | void strcat(char *s, const char *t, int n) 20 | { 21 | while (*s) /* find end of s */ 22 | s++; 23 | while (*t && n-- > 0) /* copy at most n characters of t */ 24 | *s++ = *t++; 25 | *s = '\0'; 26 | } 27 | -------------------------------------------------------------------------------- /Chapter 5/5-5/strncmp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strncmp.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-5, page 107 10 | * 11 | * Write versions of the library functions strncpy, strncat and strncmp, 12 | * which operate on at most the first n characters of their argument 13 | * strings. For example, strncpy(s,t,n) copies at most n characters of 14 | * t to s. Full descriptions are in Appendix B. 15 | */ 16 | 17 | /* strncmp: compare at most n characters of s and t, return <0 if s0 if s>t */ 19 | int strncmp(char *s, const char *t, int n) 20 | { 21 | for (; *s == *t && n-- > 0; s++, t++) 22 | if (*s == '\0' || n == 0) 23 | return 0; 24 | return *s - *t; 25 | } 26 | -------------------------------------------------------------------------------- /Chapter 5/5-5/strncpy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: strncpy.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-5, page 107 10 | * 11 | * Write versions of the library functions strncpy, strncat and strncmp, 12 | * which operate on at most the first n characters of their argument 13 | * strings. For example, strncpy(s,t,n) copies at most n characters of 14 | * t to s. Full descriptions are in Appendix B. 15 | */ 16 | 17 | /* strncpy: copy at most n characters of t to s */ 18 | void strncpy(char *s, const char *t, int n) 19 | { 20 | while (*t && n-- > 0) 21 | *s++ = *t++; 22 | *s = '\0'; 23 | } 24 | -------------------------------------------------------------------------------- /Chapter 5/5-6/atoi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: atoi.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-6, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | #include 19 | 20 | /* atoi: convert string s to integer */ 21 | int atoi(const char *s) 22 | { 23 | int n, sign; 24 | 25 | while (isspace(*s)) 26 | s++; /* skip whitespace */ 27 | sign = (*s == '-') ? -1 : 1; 28 | if (*s == '+' || *s == '-') /* skip sign */ 29 | s++; 30 | for (n = 0; isdigit(*s); s++) 31 | n = 10 * n + (*s -'0'); 32 | return sign * n; 33 | } 34 | -------------------------------------------------------------------------------- /Chapter 5/5-6/getline.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: getline.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-5, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | #include 19 | 20 | /* getline: get line into s, return length */ 21 | int getline(char *s, int lim) 22 | { 23 | char c, *p; 24 | 25 | p = s; /* point p to s */ 26 | while (--lim > 0 && (c = getchar()) != EOF && c != '\n') 27 | *s++ = c; 28 | if (c == '\n') 29 | *s++ = c; 30 | *s = '\0'; 31 | return s - p; 32 | } 33 | -------------------------------------------------------------------------------- /Chapter 5/5-6/getop.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itoa.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-6, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | #include 19 | #include 20 | 21 | #define NUMBER '0' /* signal that a number was found */ 22 | 23 | int getch(void); 24 | void ungetch(int); 25 | 26 | /* getop: get next operator or numeric operand */ 27 | int getop(char *s) 28 | { 29 | char c; 30 | 31 | while ((*s = c = getch()) == ' ' || c == '\t'); 32 | *++s = '\0'; 33 | if (!isdigit(c) && c != '.') 34 | return c; /* not a number */ 35 | --s; /* remove the \0 */ 36 | if (isdigit(c)) /* collect intiger part */ 37 | while (isdigit(*++s = c = getch())); 38 | if (c == '.') /* collect fraction part */ 39 | while (isdigit(*++s = c = getch())); 40 | *s = '\0'; 41 | if (c != EOF) 42 | ungetch(c); 43 | return NUMBER; 44 | } 45 | 46 | #define BUFSIZE 100 47 | 48 | char buf[BUFSIZE]; /* buffer for ungetch */ 49 | int bufp = 0; /* next free position in buf */ 50 | 51 | int getch(void) /* get a (possibly pushed back) character */ 52 | { 53 | return (bufp > 0) ? buf[--bufp] : getchar(); 54 | } 55 | 56 | void ungetch(int c) /* push character back on input */ 57 | { 58 | if (bufp >= BUFSIZE) 59 | printf("ungetch: too many characters\n"); 60 | else 61 | buf[bufp++] = c; 62 | } 63 | -------------------------------------------------------------------------------- /Chapter 5/5-6/itoa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itoa.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-6, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | #include /* abs() */ 19 | #include "reverse.c" 20 | 21 | /* itoa: convert n to characters in s */ 22 | void itoa(int n, char *s) 23 | { 24 | int sign; 25 | char *p; 26 | 27 | p = s; 28 | sign = n; 29 | do { /* generate digits in reverse order */ 30 | *p++ = abs(n % 10) + '0'; /* get next digit */ 31 | } while (n /= 10); /* delete it */ 32 | if (sign < 0) 33 | *p++ = '-'; 34 | *p = '\0'; 35 | reverse(s); 36 | } 37 | -------------------------------------------------------------------------------- /Chapter 5/5-6/reverse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itoa.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-6, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | #include 19 | 20 | /* reverse: reverse string s in place */ 21 | void reverse(char *s) 22 | { 23 | char tmp, *p; 24 | p = s + strlen(s) - 1; 25 | while (p > s) { 26 | tmp = *s; 27 | *s++ = *p; 28 | *p-- = tmp; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter 5/5-6/strindex.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: itoa.c 3 | * Author: Thomas van der Burgt 4 | * Date: 04-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 5-6, page 107 10 | * 11 | * Rewrite appropriate programs from earlier chapters and exercises with 12 | * pointers instead of array indexing. Good possibilities include 13 | * getline (Chapters 1 and 4), atoi, itoa, and their variants 14 | * (Chapters 2, 3, and 4), reverse (Chapter 3), and strindex and getop 15 | * (Chapter 4). 16 | */ 17 | 18 | /* strindex: return index of t in s, -1 if none */ 19 | int strindex(const char *s, const char *t) 20 | { 21 | const char *i, *j, *k; 22 | 23 | for (i = s; *i != '\0'; i++) { /* for each character in s */ 24 | j = i, k = t; 25 | while(*k != '\0' && *j++ == *k++); 26 | if (k-t > 0 && *k == '\0') /* if it is the start of t */ 27 | return i-s; /* return its index */ 28 | } 29 | return -1; /* t was not found return -1 */ 30 | } 31 | -------------------------------------------------------------------------------- /Chapter 7/7-1/convert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: convert.c 3 | * Author: Thomas van der Burgt 4 | * Date: 18-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 7-1, page 153 10 | * 11 | * Write a program that converts upper case to lower or lower case to 12 | * upper, depending on the name it is invoked with, as found in argv[0]. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define SLASH '/' 21 | 22 | char *splitpath(const char *); 23 | 24 | int main(int argc, char **argv) 25 | { 26 | char *name, c; 27 | 28 | if (argc <= 0) 29 | exit(-1); 30 | 31 | name = splitpath(argv[0]); 32 | 33 | if (strcmp(name, "lower") == 0) 34 | while ((c = getchar()) != EOF) 35 | putchar(tolower(c)); 36 | else if (strcmp(name, "upper") == 0) 37 | while ((c = getchar()) != EOF) 38 | putchar(toupper(c)); 39 | else { 40 | printf("Unknown name. I'm confused.\n"); 41 | exit(-1); 42 | } 43 | return EXIT_SUCCESS; 44 | } 45 | 46 | /* splitpath: returns file-name of without path */ 47 | char *splitpath(const char *file) 48 | { 49 | int n, i; 50 | for (i = n = 0 ; file[i] != '\0'; ++i) 51 | if (file[i] == SLASH) 52 | n = i + 1; 53 | return strdup(file + n); 54 | } 55 | -------------------------------------------------------------------------------- /Chapter 7/7-3/minprintf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: minprintf.c 3 | * Author: Thomas van der Burgt 4 | * Date: 19-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 7-3, page 156 10 | * 11 | * Revise minprintf to handle more of the other facilities of printf. 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | 18 | /* minprintf: minimal printf with variable argument list */ 19 | void minprintf(char *fmt, ...) 20 | { 21 | va_list ap; /* points to each unnamed arg in turn */ 22 | char *p, *sval; 23 | int ival; 24 | double dval; 25 | 26 | va_start(ap, fmt); /* make ap point to 1st unnamed arg */ 27 | for (p = fmt; *p; p++) { 28 | if (*p != '%') { 29 | putchar(*p); 30 | continue; 31 | } 32 | switch (*++p) { 33 | case 'd': 34 | case 'i': 35 | ival = va_arg(ap, int); 36 | printf("%d", ival); 37 | break; 38 | case 'o': 39 | ival = va_arg(ap, int); 40 | printf("%o", ival); 41 | break; 42 | case 'x': 43 | ival = va_arg(ap, int); 44 | printf("%x", ival); 45 | break; 46 | case 'X': 47 | ival = va_arg(ap, int); 48 | printf("%X", ival); 49 | break; 50 | case 'u': 51 | ival = va_arg(ap, int); 52 | printf("%u", ival); 53 | break; 54 | case 'c': 55 | ival = va_arg(ap, int); 56 | printf("%c", ival); 57 | break; 58 | case 'f': 59 | dval = va_arg(ap, double); 60 | printf("%f", dval); 61 | break; 62 | case 'e': 63 | dval = va_arg(ap, double); 64 | printf("%e", dval); 65 | break; 66 | case 'E': 67 | dval = va_arg(ap, double); 68 | printf("%E", dval); 69 | break; 70 | case 's': 71 | for (sval = va_arg(ap, char *); *sval; sval++) 72 | putchar(*sval); 73 | break; 74 | default: 75 | putchar(*p); 76 | break; 77 | } 78 | } 79 | va_end(ap); 80 | } 81 | -------------------------------------------------------------------------------- /Chapter 8/8-1/cat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: cat.c 3 | * Author: Thomas van der Burgt 4 | * Date: 24-MAR-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-1, page 174 10 | * 11 | * Rewrite the program cat from Chapter 7 using read, write, open and 12 | * close instead of their standard library equivalents. Perform 13 | * experiments to determine the relative speeds of the two versions. 14 | */ 15 | 16 | #include 17 | #include 18 | #include /* File Control Operations */ 19 | #include /* Symbolic Constants */ 20 | 21 | /* cat: concatenate files */ 22 | int main(int argc, char *argv[]) 23 | { 24 | int fd; 25 | void filecopy(int ifd, int ofd); 26 | char *prog = argv[0]; /* program name for errors */ 27 | 28 | if (argc == 1) /* no args; copy standard input */ 29 | filecopy(0, 1); 30 | else 31 | while (--argc > 0) 32 | if ((fd = open(*++argv, O_RDONLY, 0)) == -1) { 33 | fprintf(stderr, "%s: can't open %s\n", prog, *argv); 34 | exit(1); 35 | } else { 36 | filecopy(fd, 1); 37 | close(fd); 38 | } 39 | exit(EXIT_SUCCESS); 40 | } 41 | 42 | /* filecopy: copy file ifd to file ofd */ 43 | void filecopy(int ifd, int ofd) 44 | { 45 | char buf[BUFSIZ]; 46 | int c; 47 | 48 | while ((c = read(ifd, buf, BUFSIZ)) > 0) /* read from ifd */ 49 | write (ofd, buf, c); /* write to ofd */ 50 | } 51 | -------------------------------------------------------------------------------- /Chapter 8/8-2/bitops/_fillbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: _fillbuf.c 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #include "syscalls.h" 16 | #include 17 | 18 | /* _fillbuf: allocate and fill input buffer */ 19 | int _fillbuf(FILE *fp) 20 | { 21 | int bufsize; 22 | 23 | if ((fp->flag&(_READ|_EOF|_ERR)) != _READ) 24 | return EOF; 25 | bufsize = (fp->flag & _UNBUF) ? 1 : BUFSIZ; 26 | if (fp->base == NULL) /* no buffer yet */ 27 | if ((fp->base = (char *) malloc(bufsize)) == NULL) 28 | return EOF; /* can't get buffer */ 29 | fp->ptr = fp->base; 30 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 31 | if (--fp->cnt < 0) { 32 | if (fp->cnt == -1) 33 | fp->flag |= _EOF; 34 | else 35 | fp->flag |= _ERR; 36 | fp->cnt = 0; 37 | return EOF; 38 | } 39 | return (unsigned char) *fp->ptr++; 40 | } 41 | -------------------------------------------------------------------------------- /Chapter 8/8-2/bitops/fopen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: fopen.c 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #include 16 | #include "syscalls.h" 17 | #define PERMS 0666 /* RW for owner, group, others*/ 18 | 19 | /* fopen: open file, return file ptr */ 20 | FILE *fopen(char *name, char *mode) 21 | { 22 | int fd; 23 | FILE *fp; 24 | 25 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 26 | return NULL; 27 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 28 | if ((fp->flag & (_READ | _WRITE)) == 0) 29 | break; /* found free slot */ 30 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 31 | return NULL; 32 | 33 | if (*mode == 'w') 34 | fd = creat(name, PERMS); 35 | else if (*mode == 'a') { 36 | if ((fd = open(name, O_WRONLY, 0)) == -1) 37 | fd = creat(name, PERMS); 38 | lseek(fd, 0L, 2); 39 | } else 40 | fd = open(name, O_RDONLY, 0); 41 | if (fd == -1) /* couldn't access name */ 42 | return NULL; 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | fp->flag = (*mode == 'r') ? _READ : _WRITE; 47 | return fp; 48 | } 49 | 50 | int main(void) 51 | { 52 | FILE *fp; 53 | char mode; 54 | mode = 'w'; 55 | fp = fopen("foo", &mode); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /Chapter 8/8-2/bitops/syscalls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: syscalls.h 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #define NULL 0 16 | #define EOF (-1) 17 | #define BUFSIZ 1024 18 | #define OPEN_MAX 20 /* max #files open at once */ 19 | 20 | typedef struct _iobuf { 21 | int cnt; /* characters left */ 22 | char *ptr; /* next character position */ 23 | char *base; /* location of buffer */ 24 | int flag; /* mode of file access */ 25 | int fd; /* file descriptor */ 26 | } FILE; 27 | extern FILE _iob[OPEN_MAX]; 28 | #define stdin (&iob[0]) 29 | #define stdout (&iob[1]) 30 | #define stderr (&iob[2]) 31 | 32 | enum _flags { 33 | _READ = 01, /* file open for reading */ 34 | _WRITE = 02, /* file open for writing */ 35 | _UNBUF = 04, /* file is unbuffered */ 36 | _EOF = 010, /* EOF has occurred on this file */ 37 | _ERR = 020 /* error occurred on this file */ 38 | }; 39 | 40 | int _fillbuf(FILE *); 41 | int _flushbuf(int, FILE *); 42 | 43 | #define feof(p) (((p)->flag & _EOF) != 0) 44 | #define ferror(p) (((p)->flag & _ERR) != 0) 45 | #define fileno(p) ((p)->fd) 46 | 47 | #define getc(p) (--(p)->cnt >= 0 \ 48 | ? (unsigned char) *(p)->ptr++ : _fillbuff(p)) 49 | #define putc(p) (--(p)->cnt >= 0 \ 50 | ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 51 | 52 | #define getchar() getc(stdin) 53 | #define putchar(x) putc(x), stdout) 54 | 55 | FILE _iob[OPEN_MAX] = { /* stdin, stdout, stderr: */ 56 | { 0, (char *) 0, (char *) 0, _READ, 0 }, 57 | { 0, (char *) 0, (char *) 0, _WRITE, 1 }, 58 | { 0, (char *) 0, (char *) 0, _WRITE | _UNBUF, 2 } 59 | }; 60 | -------------------------------------------------------------------------------- /Chapter 8/8-2/fields/_fillbuf.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: _fillbuf.c 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #include "syscalls.h" 16 | #include 17 | 18 | /* _fillbuf: allocate and fill input buffer */ 19 | int _fillbuf(FILE *fp) 20 | { 21 | int bufsize; 22 | 23 | if (fp->flags.read == 1 && fp->flags.eof == 0 && fp->flags.err == 0) 24 | return EOF; 25 | bufsize = (fp->flags.unbuf == 1) ? 1 : BUFSIZ; 26 | if (fp->base == NULL) /* no buffer yet */ 27 | if ((fp->base = (char *) malloc(bufsize)) == NULL) 28 | return EOF; /* can't get buffer */ 29 | fp->ptr = fp->base; 30 | fp->cnt = read(fp->fd, fp->ptr, bufsize); 31 | if (--fp->cnt < 0) { 32 | if (fp->cnt == -1) 33 | fp->flags.eof = 1; 34 | else 35 | fp->flags.err = 1; 36 | fp->cnt = 0; 37 | return EOF; 38 | } 39 | return (unsigned char) *fp->ptr++; 40 | } 41 | -------------------------------------------------------------------------------- /Chapter 8/8-2/fields/fopen.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: fopen.c 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #include 16 | #include "syscalls.h" 17 | #define PERMS 0666 /* RW for owner, group, others*/ 18 | 19 | /* fopen: open file, return file ptr */ 20 | FILE *fopen(char *name, char *mode) 21 | { 22 | int fd; 23 | FILE *fp; 24 | 25 | if (*mode != 'r' && *mode != 'w' && *mode != 'a') 26 | return NULL; 27 | for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 28 | if (fp->flags.read == 0 || fp->flags.write == 0) 29 | break; /* found free slot */ 30 | if (fp >= _iob + OPEN_MAX) /* no free slots */ 31 | return NULL; 32 | 33 | if (*mode == 'w') 34 | fd = creat(name, PERMS); 35 | else if (*mode == 'a') { 36 | if ((fd = open(name, O_WRONLY, 0)) == -1) 37 | fd = creat(name, PERMS); 38 | lseek(fd, 0L, 2); 39 | } else 40 | fd = open(name, O_RDONLY, 0); 41 | if (fd == -1) /* couldn't access name */ 42 | return NULL; 43 | fp->fd = fd; 44 | fp->cnt = 0; 45 | fp->base = NULL; 46 | if (*mode == 'r') 47 | fp->flags.read = 1; 48 | else 49 | fp->flags.write = 1; 50 | return fp; 51 | } 52 | 53 | int main(void) 54 | { 55 | FILE *fp; 56 | char mode; 57 | mode = 'w'; 58 | fp = fopen("foo", &mode); 59 | return 0; 60 | } 61 | -------------------------------------------------------------------------------- /Chapter 8/8-2/fields/syscalls.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Filename: syscalls.h 3 | * Author: Thomas van der Burgt 4 | * Date: 03-MAY-2010 5 | * 6 | * The C Programming Language, second edition, 7 | * by Brian Kernighan and Dennis Ritchie 8 | * 9 | * Exercise 8-2, page 178 10 | * 11 | * Rewrite fopen and _fillbuf with fields instead of explicit bit operations. 12 | * Compare code size and execution speed. 13 | */ 14 | 15 | #define NULL 0 16 | #define EOF (-1) 17 | #define BUFSIZ 1024 18 | #define OPEN_MAX 20 /* max #files open at once */ 19 | 20 | typedef struct _iobuf { 21 | int cnt; /* characters left */ 22 | char *ptr; /* next character position */ 23 | char *base; /* location of buffer */ 24 | struct { /* mode of file access */ 25 | unsigned int read : 1; 26 | unsigned int write : 1; 27 | unsigned int unbuf : 1; 28 | unsigned int eof : 1; 29 | unsigned int err : 1; 30 | } flags; 31 | int fd; /* file descriptor */ 32 | } FILE; 33 | extern FILE _iob[OPEN_MAX]; 34 | #define stdin (&iob[0]) 35 | #define stdout (&iob[1]) 36 | #define stderr (&iob[2]) 37 | 38 | int _fillbuf(FILE *); 39 | int _flushbuf(int, FILE *); 40 | 41 | #define feof(p) (((p)->flag & _EOF) != 0) 42 | #define ferror(p) (((p)->flag & _ERR) != 0) 43 | #define fileno(p) ((p)->fd) 44 | 45 | #define getc(p) (--(p)->cnt >= 0 \ 46 | ? (unsigned char) *(p)->ptr++ : _fillbuff(p)) 47 | #define putc(p) (--(p)->cnt >= 0 \ 48 | ? *(p)->ptr++ = (x) : _flushbuf((x), p)) 49 | 50 | #define getchar() getc(stdin) 51 | #define putchar(x) putc(x), stdout) 52 | 53 | FILE _iob[OPEN_MAX] = { /* stdin, stdout, stderr: */ 54 | { 0, (char *) 0, (char *) 0, {1,0,0,0,0}, 0 }, 55 | { 0, (char *) 0, (char *) 0, {0,1,0,0,0}, 1 }, 56 | { 0, (char *) 0, (char *) 0, {0,1,1,0,0}, 2 } 57 | }; 58 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | My solutions to the exercises in the book "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie (K&R) 2 | --------------------------------------------------------------------------------