├── .gitignore ├── Chapter1 ├── Exercise 1-01 │ └── helloworld.c ├── Exercise 1-02 │ └── escape_sequence.c ├── Exercise 1-03 │ └── temperature.c ├── Exercise 1-04 │ └── ctof.c ├── Exercise 1-05 │ └── reverse_temperature.c ├── Exercise 1-06 │ └── eof.c ├── Exercise 1-07 │ └── eof.c ├── Exercise 1-08 │ └── count.c ├── Exercise 1-09 │ └── blank.c ├── Exercise 1-10 │ └── replace.c ├── Exercise 1-12 │ └── one_word_per_line.c ├── Exercise 1-13 │ └── word_length.c ├── Exercise 1-14 │ └── frequency.c ├── Exercise 1-15 │ └── temperature.c ├── Exercise 1-16 │ └── longest_line.c ├── Exercise 1-17 │ └── lines.c ├── Exercise 1-18 │ └── lines.c ├── Exercise 1-19 │ └── reverse.c ├── Exercise 1-20 │ └── detab.c ├── Exercise 1-21 │ └── entab.c ├── Exercise 1-22 │ └── fold.c └── Exercise 1-23 │ └── comments.c ├── Chapter2 ├── Exercise 2-01 │ └── ranges.c ├── Exercise 2-02 │ └── loop.c ├── Exercise 2-03 │ └── htoi.c ├── Exercise 2-04 │ └── squeeze.c ├── Exercise 2-05 │ └── any.c ├── Exercise 2-06 │ └── setbits.c ├── Exercise 2-07 │ └── invert.c ├── Exercise 2-08 │ └── rightrot.c ├── Exercise 2-09 │ └── bitcount.c └── Exercise 2-10 │ └── lower.c ├── Chapter3 ├── Exercise 3-01 │ └── binsearch.c ├── Exercise 3-02 │ └── escape.c ├── Exercise 3-03 │ └── expand.c ├── Exercise 3-04 │ └── itoa.c ├── Exercise 3-05 │ └── itob.c └── Exercise 3-06 │ └── itoa.c ├── Chapter4 ├── Exercise 4-01 │ └── strindex.c ├── Exercise 4-02 │ └── atof.c ├── Exercise 4-03 │ └── calculator.c ├── Exercise 4-04 │ └── stack.c ├── Exercise 4-05 │ └── calculator.c ├── Exercise 4-06 │ └── calculator.c ├── Exercise 4-07 │ └── ungets.c ├── Exercise 4-08 │ └── buf.c ├── Exercise 4-09 │ └── buf.c ├── Exercise 4-10 │ └── getline.c ├── Exercise 4-11 │ └── getop.c ├── Exercise 4-12 │ └── itoa.c ├── Exercise 4-13 │ └── reverse.c └── Exercise 4-14 │ └── swap.c ├── Chapter5 ├── Exercise 5-01 │ ├── getch.c │ ├── getch.h │ └── main.c ├── Exercise 5-02 │ ├── getch.c │ ├── getch.h │ └── main.c ├── Exercise 5-03 │ └── strcat.c ├── Exercise 5-04 │ └── strend.c ├── Exercise 5-05 │ ├── strncat.c │ ├── strncmp.c │ └── strncpy.c ├── Exercise 5-07 │ ├── lines.c │ ├── lines.h │ ├── main.c │ ├── qsort.c │ └── qsort.h ├── Exercise 5-08 │ └── daytab.c ├── Exercise 5-09 │ └── daytab.c ├── Exercise 5-10 │ └── expr.c ├── Exercise 5-11 │ ├── detab.c │ └── entab.c ├── Exercise 5-12 │ ├── detab.c │ └── entab.c ├── Exercise 5-13 │ ├── alloc.c │ ├── alloc.h │ ├── lines.c │ ├── lines.h │ └── main.c ├── Exercise 5-14 │ ├── alloc.c │ ├── alloc.h │ ├── lines.c │ ├── lines.h │ ├── main.c │ ├── numcmp.c │ ├── numcmp.h │ ├── qsort.c │ └── qsort.h ├── Exercise 5-15 │ ├── alloc.c │ ├── alloc.h │ ├── cmp.c │ ├── cmp.h │ ├── lines.c │ ├── lines.h │ ├── main.c │ ├── qsort.c │ └── qsort.h └── Exercise 5-16 │ ├── alloc.c │ ├── alloc.h │ ├── cmp.c │ ├── cmp.h │ ├── lines.c │ ├── lines.h │ ├── main.c │ ├── qsort.c │ └── qsort.h └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | 4 | # Libraries 5 | *.lib 6 | *.a 7 | 8 | # Shared objects (inc. Windows DLLs) 9 | *.dll 10 | *.so 11 | *.so.* 12 | *.dylib 13 | 14 | # Executables 15 | *.exe 16 | *.out 17 | *.app 18 | -------------------------------------------------------------------------------- /Chapter1/Exercise 1-01/helloworld.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-1, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | printf("hello world!\n"); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-02/escape_sequence.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-2, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | printf("tab: \t\n"); 10 | printf("backslash: \\\n"); 11 | printf("single quote: \'\n"); 12 | printf("double quote: \"\n"); 13 | return 0; 14 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-03/temperature.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-3, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | float fahr, celsius; 10 | float lower, upper, step; 11 | 12 | lower = 0; /* lower limit of temperatuire scale */ 13 | upper = 300; /* upper limit */ 14 | step = 20; /* step size */ 15 | 16 | printf(" F C\n"); 17 | 18 | fahr = lower; 19 | while (fahr <= upper) { 20 | celsius = (5.0 / 9.0) * (fahr - 32.0); 21 | printf("%3.0f %6.1f\n", fahr, celsius); 22 | fahr = fahr + step; 23 | } 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-04/ctof.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-4, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | float fahr, celsius; 10 | float lower, upper, step; 11 | 12 | lower = -20; /* lower limit of temperatuire scale */ 13 | upper = 150; /* upper limit */ 14 | step = 10; /* step size */ 15 | 16 | printf(" C F\n"); 17 | 18 | celsius = lower; 19 | while (celsius <= upper) { 20 | fahr = celsius * (9.0 / 5.0) + 32.0; 21 | printf("%3.0f %6.1f\n", celsius, fahr); 22 | celsius = celsius + step; 23 | } 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-05/reverse_temperature.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-5, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | float fahr, celsius; 10 | float lower, upper, step; 11 | 12 | lower = 0; /* lower limit of temperatuire scale */ 13 | upper = 300; /* upper limit */ 14 | step = 20; /* step size */ 15 | 16 | printf(" F C\n"); 17 | 18 | fahr = upper; 19 | while (fahr >= lower) { 20 | celsius = (5.0 / 9.0) * (fahr - 32.0); 21 | printf("%3.0f %6.1f\n", fahr, celsius); 22 | fahr = fahr - step; 23 | } 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-06/eof.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-6, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | printf("Please enter a character:\n"); 10 | printf("The expression \"getchar() != EOF\" is %d.\n", getchar() != EOF); 11 | return 0; 12 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-07/eof.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-7, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | printf("The value of EOF is %d.\n", EOF); 10 | return 0; 11 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-08/count.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-8, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | int c, bl, tl, nl; 10 | bl = 0; 11 | tl = 0; 12 | nl = 0; 13 | 14 | printf("Input some characters, then press Ctrl+D.\n"); 15 | while ((c = getchar()) != EOF) 16 | if (c == ' ') 17 | ++bl; 18 | else if (c == '\t') 19 | ++tl; 20 | else if (c == '\n') 21 | ++nl; 22 | 23 | printf("Count of blanks is %d, count of tabs is %d, count of newlines is %d.\n", bl, tl, nl); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-09/blank.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-9, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | int c, blank_recieved; 10 | blank_recieved = 0; 11 | printf("Input some characters, when you finishes, press Ctrl+D.\n"); 12 | while ((c = getchar()) != EOF) 13 | if (c == ' ') { 14 | if (!blank_recieved) { 15 | blank_recieved = 1; 16 | putchar(c); 17 | } 18 | } else { 19 | blank_recieved = 0; 20 | putchar(c); 21 | } 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-10/replace.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-10, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | int c; 10 | 11 | printf("Input some characters, then press Ctrl+D.\n"); 12 | while ((c = getchar()) != EOF) 13 | if (c == '\t') 14 | printf("\\t"); 15 | else if (c == '\b') 16 | printf("\\b"); 17 | else if (c == '\\') 18 | printf("\\\\"); 19 | else 20 | printf("%c", c); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-12/one_word_per_line.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-12, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | int main(void) 8 | { 9 | int c, linestarted; 10 | 11 | linestarted = 0; 12 | printf("Input some characters, then press Ctrl+D.\n"); 13 | while ((c = getchar()) != EOF) 14 | if (c == ' ' || c == '\t' || c == '\n') { 15 | if (!linestarted) { 16 | putchar('\n'); 17 | linestarted = 1; 18 | } 19 | } else { 20 | putchar(c); 21 | linestarted = 0; 22 | } 23 | 24 | return 0; 25 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-13/word_length.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-13, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAX_LENGTH 15 8 | #define IN_WORD 1 9 | #define OUT_WORD 0 10 | 11 | int main(void) 12 | { 13 | int c, word_in_out; 14 | int word_length[MAX_LENGTH + 1]; 15 | int l; 16 | int i, j; 17 | unsigned int max_count; 18 | 19 | for (i = 0; i <= MAX_LENGTH; ++i) 20 | word_length[i] = 0; 21 | 22 | word_in_out = OUT_WORD; 23 | printf("Input some characters, then press Ctrl+D.\n"); 24 | while (1) { 25 | c = getchar(); 26 | if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { 27 | if (word_in_out == OUT_WORD) { 28 | l = 0; 29 | word_in_out = IN_WORD; 30 | } 31 | ++l; 32 | } else { 33 | if (word_in_out == IN_WORD) { 34 | if (l <= MAX_LENGTH) 35 | ++word_length[l - 1]; 36 | else 37 | ++word_length[MAX_LENGTH]; 38 | word_in_out = OUT_WORD; 39 | } 40 | if (c == EOF) 41 | break; 42 | } 43 | } 44 | 45 | printf("\nHorizontal histogram:\n\n"); 46 | printf(" length | graph\n"); 47 | for (i = 0; i <= MAX_LENGTH; ++i) { 48 | if (i != MAX_LENGTH) 49 | printf(" %2d | ", i + 1); 50 | else 51 | printf(" >%2d | ", MAX_LENGTH); 52 | for (j = 0; j < word_length[i]; ++j) 53 | putchar('+'); 54 | putchar('\n'); 55 | } 56 | 57 | printf("\nVertical histogram:\n\n"); 58 | max_count = 0; 59 | for (i = 0; i <= MAX_LENGTH; ++i) 60 | if (word_length[i] > max_count) 61 | max_count = word_length[i]; 62 | 63 | for (i = 0; i < max_count; ++i) { 64 | printf(" %2u | ", max_count - i); 65 | for (j = 0; j <= MAX_LENGTH; ++j) 66 | if (word_length[j] >= max_count - i) 67 | printf(" +"); 68 | else 69 | printf(" "); 70 | printf("\n"); 71 | } 72 | 73 | printf(" ------"); 74 | for (i = 0; i <= MAX_LENGTH; ++i) 75 | printf("---"); 76 | printf("--\n"); 77 | 78 | printf(" "); 79 | for (i = 0; i < MAX_LENGTH;) 80 | printf(" %2u", ++i); 81 | printf(" >%2u", MAX_LENGTH); 82 | printf("\n"); 83 | 84 | return 0; 85 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-14/frequency.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-14, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define NUM_CHARS 128 8 | #define IN_WORD 1 9 | #define OUT_WORD 0 10 | 11 | int main(void) 12 | { 13 | int c; 14 | int char_frequencies[NUM_CHARS + 1]; 15 | int i; 16 | 17 | for (i = 0; i <= NUM_CHARS; ++i) 18 | char_frequencies[i] = 0; 19 | 20 | printf("Input some characters, then press Ctrl+D.\n"); 21 | while ((c = getchar()) != EOF) 22 | ++char_frequencies[c]; 23 | 24 | printf("\n ASCII | Count\n"); 25 | for (i = 0; i <= NUM_CHARS; ++i) 26 | if (char_frequencies[i] > 0) 27 | printf(" %5d : %5d\n", i, char_frequencies[i]); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-15/temperature.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-15, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | float ftoc(float fahr); 8 | 9 | int main(void) 10 | { 11 | float fahr, celsius; 12 | float lower, upper, step; 13 | lower = 0; /* lower limit of temperatuire scale */ 14 | upper = 300; /* upper limit */ 15 | step = 20; /* step size */ 16 | fahr = lower; 17 | 18 | while (fahr <= upper) { 19 | celsius = ftoc(fahr); 20 | printf("%3.0f %6.1f\n", fahr, celsius); 21 | fahr = fahr + step; 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | float ftoc(float fahr) 28 | { 29 | float celsius; 30 | celsius = (5.0 / 9.0) * (fahr - 32.0); 31 | return celsius; 32 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-16/longest_line.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-16, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 /* maximum input line length */ 8 | 9 | int get_line(char line[], int maxline); 10 | void copy(char to[], char from[]); 11 | 12 | /* print the longest input line */ 13 | int main(void) 14 | { 15 | int len; /* current line length */ 16 | int max; /* maximum length seen so far */ 17 | char line[MAXLINE]; /* current input line */ 18 | char longest[MAXLINE]; /* longest line saved here */ 19 | 20 | max = 0; 21 | while ((len = get_line(line, MAXLINE)) > 0) 22 | if (len > max) { 23 | max = len; 24 | copy(longest, line); 25 | } 26 | if (max > 0) { 27 | printf("The longest line is:\n"); 28 | printf("%s\n", longest); 29 | printf("The length of it is %d.\n", max); 30 | } 31 | 32 | 33 | return 0; 34 | } 35 | 36 | /* get_line: read a line into s, return length */ 37 | int get_line(char s[], int lim) 38 | { 39 | int c, i, l; 40 | 41 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) { 42 | if (i < lim - 1) 43 | s[l++] = c; 44 | } 45 | if (c == '\n') { 46 | if (l < lim - 1) 47 | s[l++] = c; 48 | ++i; 49 | } 50 | s[l] = '\0'; 51 | 52 | return i; 53 | } 54 | 55 | /* copy: copy 'from' into 'to'; assume to is big enough */ 56 | void copy(char to[], char from[]) 57 | { 58 | int i; 59 | 60 | i = 0; 61 | while ((to[i] = from[i]) != '\0') 62 | ++i; 63 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-17/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-17, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | #define MAXLENGTH 10 9 | 10 | int get_line(char line[], int maxline); 11 | 12 | int main(void) 13 | { 14 | int len; /* current line length */ 15 | char line[MAXLINE]; /* current input line */ 16 | 17 | while ((len = get_line(line, MAXLINE)) > 0) 18 | if (len > MAXLENGTH) 19 | printf("%s\n", line); 20 | 21 | return 0; 22 | } 23 | 24 | /* get_line: read a line into s, return length */ 25 | int get_line(char s[], int lim) 26 | { 27 | int c, i, l; 28 | 29 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) { 30 | if (i < lim - 1) 31 | s[l++] = c; 32 | } 33 | if (c == '\n') 34 | if (l < lim - 1) 35 | s[l++] = c; 36 | s[l] = '\0'; 37 | 38 | return l; 39 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-18/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-18, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int get_line(char line[], int maxline); 10 | 11 | int main(void) 12 | { 13 | int len; /* current line length */ 14 | char line[MAXLINE]; /* current input line */ 15 | 16 | while ((len = get_line(line, MAXLINE)) > 0) { 17 | if (len == 1 && line[0] == '\n') 18 | continue; 19 | printf("%s\n", line); 20 | } 21 | 22 | return 0; 23 | } 24 | 25 | int get_line(char s[], int lim) 26 | { 27 | int c, i, l; 28 | 29 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 30 | if (i < lim - 1) 31 | s[l++] = c; 32 | if (c == '\n' && l < lim - 1) 33 | s[l++] = c; 34 | s[l] = '\0'; 35 | 36 | return l; 37 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-19/reverse.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-19, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int get_line(char line[], int maxline); 10 | void reverse(char s[]); 11 | 12 | int main(void) 13 | { 14 | char line[MAXLINE]; /* current input line */ 15 | 16 | while (get_line(line, MAXLINE) > 0) { 17 | reverse(line); 18 | printf("%s\n", line); 19 | } 20 | 21 | return 0; 22 | } 23 | 24 | int get_line(char s[], int lim) 25 | { 26 | int c, i, l; 27 | 28 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 29 | if (i < lim - 1) 30 | s[l++] = c; 31 | if (c == '\n' && l < lim - 1) 32 | s[l++] = c; 33 | s[l] = '\0'; 34 | 35 | return l; 36 | } 37 | 38 | void reverse(char s[]) 39 | { 40 | int i, j; 41 | int tmp; 42 | 43 | for (j = 0; s[j] != '\0'; ++j) 44 | ; 45 | --j; 46 | if (s[j - 1] == '\n') 47 | --j; 48 | 49 | for (i = 0; i < j; ++i, --j) { 50 | tmp = s[i]; 51 | s[i] = s[j]; 52 | s[j] = tmp; 53 | } 54 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-20/detab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-20, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | #define TAB_WIDTH 4 9 | 10 | int getchars(char s[], int maxline); 11 | void detab(char s1[], char s2[], int tabwidth); 12 | 13 | int main(void) 14 | { 15 | char s1[MAXLINE]; 16 | char s2[MAXLINE]; 17 | 18 | printf("Input some characters, then press enter:\n"); 19 | while (getchars(s1, MAXLINE) == 0) 20 | ; 21 | 22 | detab(s1, s2, TAB_WIDTH); 23 | printf("detab result:\n%s\n", s2); 24 | 25 | return 0; 26 | } 27 | 28 | int getchars(char s[], int lim) 29 | { 30 | int c, i, l; 31 | 32 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 33 | if (i < lim - 1) 34 | s[l++] = c; 35 | s[l] = '\0'; 36 | 37 | return l; 38 | } 39 | 40 | // copy characters in s1 to s2 and replace tabs with proper number of blanks 41 | void detab(char s1[], char s2[], int w) 42 | { 43 | int i, j, l, c, blanks; 44 | 45 | i = 0; 46 | l = 0; 47 | while ((c = s1[i++]) != '\0') { 48 | if (c == '\t') { 49 | blanks = w - l % w; 50 | for (j = 0; j < blanks; ++j) 51 | s2[l++] = ' '; 52 | } else { 53 | s2[l++] = c; 54 | } 55 | } 56 | s2[l] = '\0'; 57 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-21/entab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-21, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | #define TAB_WIDTH 8 9 | 10 | int getchars(char s[], int maxline); 11 | void entab(char s1[], char s2[], int tabwidth); 12 | 13 | int main(void) 14 | { 15 | char s1[MAXLINE]; 16 | char s2[MAXLINE]; 17 | 18 | printf("Input some characters, then press enter:\n"); 19 | while (getchars(s1, MAXLINE) == 0) 20 | ; 21 | 22 | entab(s1, s2, TAB_WIDTH); 23 | printf("entab result:\n%s\n", s2); 24 | 25 | return 0; 26 | } 27 | 28 | int getchars(char s[], int lim) 29 | { 30 | int c, i, l; 31 | 32 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 33 | if (i < lim - 1) 34 | s[l++] = c; 35 | s[l] = '\0'; 36 | 37 | return l; 38 | } 39 | 40 | // copy characters in s1 to s2 and replace blanks with tabs 41 | void entab(char s1[], char s2[], int w) 42 | { 43 | int i, j, l, c, blanks; 44 | int blanksenough; 45 | 46 | i = 0; 47 | l = 0; 48 | while ((c = s1[i]) != '\0') { 49 | if (c == ' ') { 50 | blanksenough = 1; 51 | blanks = w - i % w; 52 | for (j = 1; j < blanks; ++j) 53 | if (s1[i + j] != ' ') { 54 | blanksenough = 0; 55 | break; 56 | } 57 | if (blanksenough) { 58 | s2[l++] = '\t'; 59 | i += blanks - 1; 60 | } else { 61 | s2[l++] = c; 62 | } 63 | } else { 64 | s2[l++] = c; 65 | } 66 | ++i; 67 | } 68 | s2[l] = '\0'; 69 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-22/fold.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-22, Chapter1. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | #define TAB_WIDTH 8 9 | #define LINE_WIDTH 10 10 | 11 | int getchars(char s[], int maxline); 12 | void fold(char s1[], char s2[], int linewidth, int tabwidth); 13 | 14 | int main(void) 15 | { 16 | char s1[MAXLINE]; 17 | char s2[MAXLINE]; 18 | 19 | printf("Input some characters, then press enter:\n"); 20 | while (getchars(s1, MAXLINE) == 0) 21 | ; 22 | 23 | fold(s1, s2, LINE_WIDTH, TAB_WIDTH); 24 | printf("\nfold result:\n%s\n", s2); 25 | 26 | return 0; 27 | } 28 | 29 | int getchars(char s[], int lim) 30 | { 31 | int c, i, l; 32 | 33 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 34 | if (i < lim - 1) 35 | s[l++] = c; 36 | s[l] = '\0'; 37 | 38 | return l; 39 | } 40 | 41 | void fold(char s1[], char s2[], int lw, int tw) 42 | { 43 | int i, l, c, k, w; 44 | 45 | w = 0; 46 | k = -1; 47 | i = l = 0; 48 | while ((c = s1[i]) != '\0') { 49 | if (c == ' ') { 50 | if (w + 1 == lw) { 51 | s2[l++] = '\n'; 52 | w = 0; 53 | i = k; 54 | } else { 55 | s2[l++] = ' '; 56 | ++w; 57 | } 58 | } else if (c == '\t') { 59 | if (w + tw - w % tw >= lw) { 60 | s2[l++] = '\n'; 61 | w = 0; 62 | i = k; 63 | } else { 64 | s2[l++] = '\t'; 65 | w += tw; 66 | } 67 | } else { 68 | s2[l++] = c; 69 | if (w + 1 == lw) { 70 | s2[l++] = '\n'; 71 | w = 0; 72 | } else { 73 | k = i; 74 | ++w; 75 | } 76 | } 77 | ++i; 78 | } 79 | s2[l++] = '\0'; 80 | } -------------------------------------------------------------------------------- /Chapter1/Exercise 1-23/comments.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 1-23, Chapter1. 3 | */ 4 | 5 | /** 6 | * Test text, replace '@' with '/' 7 | 8 | @** 9 | * Hello World 10 | *@ 11 | #include // for printf 12 | 13 | int main(void) 14 | { 15 | char s[] = "// hello \ 16 | world!\n"; 17 | printf("%s\n", s); 18 | 19 | return 0; 20 | } 21 | 22 | */ 23 | 24 | 25 | #include 26 | 27 | #define MAXLENGTH 5000 28 | 29 | int _getline(char s[], int max); 30 | 31 | int main(void) 32 | { 33 | int len, i; 34 | char s[MAXLENGTH]; 35 | 36 | 37 | printf("Input code, then press Ctrl+D:\n"); 38 | while ((len = _getline(s, MAXLENGTH)) > 0) { 39 | printf("\nResult:\n=========================\n"); 40 | i = 0; 41 | while (s[i] != '\0') { 42 | if (s[i] == '/' && s[i+1] == '/') { 43 | i += 2; 44 | while (s[i] != '\n' && s[i] != '\0') 45 | ++i; 46 | } else if (s[i] == '/' && s[i+1] == '*') { 47 | i += 2; 48 | while (s[i] != '\0' && s[i+1] != '\0' && (s[i] != '*' || s[i+1] != '/')) 49 | ++i; 50 | if (s[i] != '\0' && s[i+1] == '\0') 51 | ++i; 52 | if (s[i] == '*') 53 | i += 2; 54 | } else if (s[i] == '\"') { 55 | putchar('\"'); 56 | ++i; 57 | while (s[i] != '\0' && (s[i-1] == '\\' || s[i] != '\"')) 58 | putchar(s[i++]); 59 | } else { 60 | putchar(s[i++]); 61 | } 62 | } 63 | } 64 | 65 | return 0; 66 | } 67 | 68 | int _getline(char s[], int max) 69 | { 70 | int c, i, l; 71 | 72 | for (i = 0, l = 0; (c = getchar()) != EOF; ++i) 73 | if (i < max - 1) 74 | s[l++] = c; 75 | s[l] = '\0'; 76 | 77 | return l; 78 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-01/ranges.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-01, Chapter2. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int main(void) 9 | { 10 | printf("Range of signed char is [%d, %d].\n", SCHAR_MIN, SCHAR_MAX); 11 | printf("Range of unsigned char is [%u, %u].\n", 0, UCHAR_MAX); 12 | printf("Range of char is [%d, %d].\n", CHAR_MIN, CHAR_MAX); 13 | 14 | printf("Range of signed short int is [%hd, %hd].\n", SHRT_MIN, SHRT_MAX); 15 | printf("Range of unsigned short int is [%hu, %hu].\n", 0, USHRT_MAX); 16 | 17 | printf("Range of signed int is [%d, %d].\n", INT_MIN, INT_MAX); 18 | printf("Range of unsigned int is [%u, %u].\n", 0, UINT_MAX); 19 | 20 | printf("Range of signed long int is [%ld, %ld].\n", LONG_MIN, LONG_MAX); 21 | printf("Range of unsigned long int is [%lu, %lu].\n", 0, ULONG_MAX); 22 | 23 | return 0; 24 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-02/loop.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-02, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int main(void) 10 | { 11 | char line[MAXLINE]; 12 | int c, i; 13 | 14 | i = 0; 15 | while (i < MAXLINE - 1) { 16 | if ((c=getchar()) == EOF) 17 | break; 18 | line[i++] = c; 19 | if (c == '\n') 20 | break; 21 | } 22 | line[i] = '\0'; 23 | 24 | printf("%s\n", line); 25 | 26 | return 0; 27 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-03/htoi.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-03, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int get_line(char line[], int maxline); 10 | unsigned long htoi(char s[]); 11 | 12 | int main(void) 13 | { 14 | int len; 15 | char line[MAXLINE]; 16 | 17 | while ((len = get_line(line, MAXLINE)) > 0) 18 | printf("%lu\n", htoi(line)); 19 | 20 | return 0; 21 | } 22 | 23 | int get_line(char s[], int lim) 24 | { 25 | int c, i, l; 26 | 27 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 28 | if (i < lim - 1) 29 | s[l++] = c; 30 | // if (c == '\n' && l < lim - 1) 31 | // s[l++] = c; 32 | s[l] = '\0'; 33 | 34 | return l; 35 | } 36 | 37 | unsigned long htoi(char s[]) 38 | { 39 | unsigned long n; 40 | int i, c; 41 | 42 | n = 0; 43 | for (i = 0; s[i] != '\0'; ++i) { 44 | c = s[i]; 45 | if (i == 0 && c == '0' && (s[1] == 'x' || s[1] == 'X')) { 46 | i = 1; 47 | continue; 48 | } 49 | n *= 16; 50 | if (c >= '0' && c <= '9') 51 | n += c - '0'; 52 | else if (c >= 'a' && c <= 'f') 53 | n += c - 'a'; 54 | else if (c >= 'A' && c <= 'F') 55 | n += c - 'A'; 56 | } 57 | 58 | return n; 59 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-04/squeeze.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-04, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int get_line(char line[], int maxline); 10 | void squeeze(char s1[], char s2[]); 11 | 12 | int main(void) 13 | { 14 | int len; 15 | char s1[MAXLINE]; 16 | char s2[MAXLINE]; 17 | 18 | printf("Input string s1:\n"); 19 | while ((len = get_line(s1, MAXLINE)) == 0) 20 | ; 21 | 22 | printf("Input string s2:\n"); 23 | while ((len = get_line(s2, MAXLINE)) == 0) 24 | ; 25 | 26 | squeeze(s1, s2); 27 | printf("Result is %s\n", s1); 28 | 29 | return 0; 30 | } 31 | 32 | int get_line(char s[], int lim) 33 | { 34 | int c, i, l; 35 | 36 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 37 | if (i < lim - 1) 38 | s[l++] = c; 39 | s[l] = '\0'; 40 | 41 | return l; 42 | } 43 | 44 | /* This implementation is a bit more complicated*/ 45 | void squeeze(char s1[], char s2[]) 46 | { 47 | int i, j, k; 48 | 49 | i = 0; 50 | while (s2[i] != '\0') { 51 | j = 0; 52 | while (s1[j] != '\0') { 53 | if (s1[j] == s2[i]) { 54 | k = j; 55 | while ((s1[k] = s1[++k]) != '\0') 56 | ; 57 | } else 58 | ++j; 59 | } 60 | ++i; 61 | } 62 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-05/any.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-05, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int get_line(char line[], int maxline); 10 | int any(char s1[], char s2[]); 11 | 12 | int main(void) 13 | { 14 | int len; 15 | char s1[MAXLINE]; 16 | char s2[MAXLINE]; 17 | 18 | printf("Input string s1:\n"); 19 | while ((len = get_line(s1, MAXLINE)) == 0) 20 | ; 21 | 22 | printf("Input string s2:\n"); 23 | while ((len = get_line(s2, MAXLINE)) == 0) 24 | ; 25 | 26 | printf("The first location is %d\n", any(s1, s2)); 27 | 28 | return 0; 29 | } 30 | 31 | int get_line(char s[], int lim) 32 | { 33 | int c, i, l; 34 | 35 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 36 | if (i < lim - 1) 37 | s[l++] = c; 38 | s[l] = '\0'; 39 | 40 | return l; 41 | } 42 | 43 | int any(char s1[], char s2[]) 44 | { 45 | int i, j; 46 | 47 | i = 0; 48 | while (s2[i] != '\0') { 49 | j = 0; 50 | while (s1[j] != '\0') { 51 | if (s1[j] == s2[i]) 52 | return j; 53 | ++j; 54 | } 55 | ++i; 56 | } 57 | 58 | return -1; 59 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-06/setbits.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-06, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | unsigned setbits(unsigned x, int p, int n, unsigned y); 8 | 9 | int main(void) 10 | { 11 | printf("%u\n", setbits(5732, 6, 3, 9823)); 12 | return 0; 13 | } 14 | 15 | unsigned setbits(unsigned x, int p, int n, unsigned y) 16 | { 17 | // xxxxx00000xxxxx 18 | unsigned a = x & ~(~(~0U << n) << (p + 1 - n)); 19 | 20 | // 00000yyyyy00000 21 | unsigned b = (y & ~(~0U << n)) << (p + 1 - n); 22 | 23 | // xxxxxyyyyyxxxxx 24 | return a | b; 25 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-07/invert.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-07, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | unsigned invert(unsigned x, int p, int n); 8 | 9 | int main(void) 10 | { 11 | printf("%u\n", invert(5732, 6, 3)); 12 | return 0; 13 | } 14 | 15 | unsigned invert(unsigned x, int p, int n) 16 | { 17 | // 000001111100000 18 | unsigned mask = ~(~0U << n) << (p + 1 - n); 19 | 20 | // xxxxx^^^^^xxxxx 21 | return x ^ mask; 22 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-08/rightrot.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-08, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | unsigned rightroc(unsigned x, int n); 8 | 9 | int main(void) 10 | { 11 | printf("%u\n", rightroc(5732, 3)); 12 | return 0; 13 | } 14 | 15 | unsigned rightroc(unsigned x, int n) 16 | { 17 | while (n-- > 0) 18 | if(x & 1) 19 | x = (x >> 1) | ~(~0U >> 1); 20 | else 21 | x = x >> 1; 22 | return x; 23 | } -------------------------------------------------------------------------------- /Chapter2/Exercise 2-09/bitcount.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-09, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | int bitcount(unsigned x); 8 | 9 | int main(void) 10 | { 11 | printf("%d\n", bitcount(011111)); 12 | return 0; 13 | } 14 | 15 | /* bitcount: count 1 bits in x */ 16 | int bitcount(unsigned x) 17 | { 18 | int b; 19 | 20 | for (b = 0; x != 0; x &= (x - 1)) 21 | b++; 22 | return b; 23 | } 24 | -------------------------------------------------------------------------------- /Chapter2/Exercise 2-10/lower.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 2-10, Chapter2. 3 | */ 4 | 5 | #include 6 | 7 | int lower(int c); 8 | 9 | int main(void) 10 | { 11 | char s[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 12 | int i; 13 | 14 | i = 0; 15 | while (s[i] != '\0') { 16 | printf("%c -> %c\n", s[i], lower(s[i])); 17 | i++; 18 | } 19 | 20 | return 0; 21 | } 22 | 23 | int lower(int c) 24 | { 25 | return (c >= 'A' && c<= 'Z') ? c + 'a' - 'A' : c; 26 | } 27 | -------------------------------------------------------------------------------- /Chapter3/Exercise 3-01/binsearch.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-01, Chapter3. 3 | */ 4 | 5 | #include 6 | 7 | int binsearch(int x, int v[], int n); 8 | 9 | int main(void) 10 | { 11 | int x = 12, n = 10; 12 | int v[10] = {2, 3, 7, 10, 11, 12, 15, 18, 20, 21}; 13 | printf("binsearch result: %d\n", binsearch(x, v, n)); 14 | return 0; 15 | } 16 | 17 | /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ 18 | int binsearch(int x, int v[], int n) 19 | { 20 | int low, high, mid; 21 | 22 | low = 0; 23 | high = n - 1; 24 | while (low < high) { 25 | mid = (low + high) / 2; 26 | if (x <= v[mid]) 27 | high = mid; 28 | else 29 | low = mid + 1; 30 | } 31 | return (x == v[low]) ? low : -1; 32 | } 33 | -------------------------------------------------------------------------------- /Chapter3/Exercise 3-02/escape.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-02, Chapter3. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int getchars(char line[], int maxline); 10 | void escape(char s[], char t[]); 11 | void unescape(char s[], char t[]); 12 | 13 | int main(void) 14 | { 15 | char t[MAXLINE]; 16 | char s1[MAXLINE]; 17 | char s2[MAXLINE]; 18 | 19 | printf("Input some characters, then press Ctrl+D:\n"); 20 | while (getchars(t, MAXLINE) == 0) 21 | ; 22 | 23 | escape(s1, t); 24 | printf("\nescape result:\n%s\n", s1); 25 | 26 | unescape(s2, s1); 27 | printf("unescape result:\n%s\n", s2); 28 | 29 | return 0; 30 | } 31 | 32 | int getchars(char s[], int lim) 33 | { 34 | int c, i, l; 35 | 36 | for (i = 0, l = 0; (c = getchar()) != EOF; ++i) 37 | if (i < lim - 1) 38 | s[l++] = c; 39 | s[l] = '\0'; 40 | 41 | return l; 42 | } 43 | 44 | void escape(char s[], char t[]) 45 | { 46 | int i, j; 47 | 48 | for (i = 0, j = 0; t[i] != '\0'; ++i) { 49 | switch (t[i]) { 50 | case '\n': 51 | s[j++] = '\\'; 52 | s[j++] = 'n'; 53 | break; 54 | case '\t': 55 | s[j++] = '\\'; 56 | s[j++] = 't'; 57 | break; 58 | case '\v': 59 | s[j++] = '\\'; 60 | s[j++] = 'v'; 61 | break; 62 | case '\b': 63 | s[j++] = '\\'; 64 | s[j++] = 'b'; 65 | break; 66 | case '\r': 67 | s[j++] = '\\'; 68 | s[j++] = 'r'; 69 | break; 70 | case '\f': 71 | s[j++] = '\\'; 72 | s[j++] = 'f'; 73 | break; 74 | case '\a': 75 | s[j++] = '\\'; 76 | s[j++] = 'a'; 77 | break; 78 | case '\\': 79 | s[j++] = '\\'; 80 | s[j++] = '\\'; 81 | break; 82 | case '\?': 83 | s[j++] = '\\'; 84 | s[j++] = '\?'; 85 | break; 86 | case '\'': 87 | s[j++] = '\\'; 88 | s[j++] = '\''; 89 | break; 90 | case '\"': 91 | s[j++] = '\\'; 92 | s[j++] = '\"'; 93 | break; 94 | default: 95 | s[j++] = t[i]; 96 | break; 97 | } 98 | } 99 | s[j] = '\0'; 100 | } 101 | 102 | void unescape(char s[], char t[]) 103 | { 104 | int i, j; 105 | 106 | for (i = 0, j = 0; t[i] != '\0'; ++i) { 107 | if (t[i] == '\\') { 108 | switch (t[++i]) { 109 | case 'n': 110 | s[j++] = '\n'; 111 | break; 112 | case 't': 113 | s[j++] = '\t'; 114 | break; 115 | case 'v': 116 | s[j++] = '\v'; 117 | break; 118 | case 'b': 119 | s[j++] = '\b'; 120 | break; 121 | case 'r': 122 | s[j++] = '\r'; 123 | break; 124 | case 'f': 125 | s[j++] = '\f'; 126 | break; 127 | case 'a': 128 | s[j++] = '\a'; 129 | break; 130 | case '\\': 131 | s[j++] = '\\'; 132 | break; 133 | case '\?': 134 | s[j++] = '\?'; 135 | break; 136 | case '\'': 137 | s[j++] = '\''; 138 | break; 139 | case '\"': 140 | s[j++] = '\"'; 141 | break; 142 | // actually, cases below should never happen if the input string is correct. 143 | case '\0': 144 | default: 145 | s[j++] = '\\'; 146 | --i; 147 | break; 148 | } 149 | } else { 150 | s[j++] = t[i]; 151 | } 152 | } 153 | s[j] = '\0'; 154 | } -------------------------------------------------------------------------------- /Chapter3/Exercise 3-03/expand.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-03, Chapter3. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int getchars(char line[], int maxline); 10 | void expand(char s1[], char s2[]); 11 | 12 | int main(void) 13 | { 14 | char s1[MAXLINE]; 15 | char s2[MAXLINE]; 16 | 17 | printf("Input some characters, then press enter:\n"); 18 | while (getchars(s1, MAXLINE) == 0) 19 | ; 20 | 21 | expand(s1, s2); 22 | printf("\nThe expanded result is:\n%s\n", s2); 23 | 24 | return 0; 25 | } 26 | 27 | int getchars(char s[], int lim) 28 | { 29 | int c, i, l; 30 | 31 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 32 | if (i < lim - 1) 33 | s[l++] = c; 34 | s[l] = '\0'; 35 | 36 | return l; 37 | } 38 | 39 | void expand(char s1[], char s2[]) 40 | { 41 | int i, j, k; 42 | int c; 43 | 44 | for (i = 0, j = 0; s1[i] != '\0'; ++i) { 45 | if (s1[i+1] == '-' && (c = s1[i+2]) != '\0' && 46 | (('a' <= s1[i] && s1[i] <= 'z' && s1[i] <= c && c <= 'z') || 47 | ('A' <= s1[i] && s1[i] <= 'Z' && s1[i] <= c && c <= 'Z') || 48 | ('0' <= s1[i] && s1[i] <= '9' && s1[i] <= c && c <= '9'))) { 49 | k = 0; 50 | while (k <= c - s1[i]) 51 | s2[j++] = s1[i] + k++; 52 | i += 2; 53 | } else { 54 | s2[j++] = s1[i]; 55 | } 56 | } 57 | s2[j] = '\0'; 58 | } -------------------------------------------------------------------------------- /Chapter3/Exercise 3-04/itoa.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-04, Chapter3. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | void itoa(int n, char s[]); 11 | void reverse(char s[]); 12 | 13 | int main(void) 14 | { 15 | char s[MAXLINE]; 16 | 17 | itoa(INT_MIN, s); 18 | printf("%d is converted to %s.\n", INT_MIN, s); 19 | itoa(826, s); 20 | printf("%d is converted to %s.\n", 826, s); 21 | itoa(-2093, s); 22 | printf("%d is converted to %s.\n", -2093, s); 23 | 24 | return 0; 25 | } 26 | 27 | void itoa(int n, char s[]) 28 | { 29 | int i, sign, remainder; 30 | 31 | sign = n; 32 | i = 0; 33 | do { 34 | remainder = n % 10; 35 | s[i++] = ((sign < 0) ? -remainder : remainder) + '0'; 36 | } while (n /= 10); 37 | if (sign < 0) 38 | s[i++] = '-'; 39 | s[i] = '\0'; 40 | reverse(s); 41 | } 42 | 43 | void reverse(char s[]) 44 | { 45 | int i, j; 46 | int tmp; 47 | 48 | for (j = 0; s[j] != '\0'; ++j) 49 | ; 50 | --j; 51 | 52 | for (i = 0; i < j; ++i, --j) { 53 | tmp = s[i]; 54 | s[i] = s[j]; 55 | s[j] = tmp; 56 | } 57 | } -------------------------------------------------------------------------------- /Chapter3/Exercise 3-05/itob.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-05, Chapter3. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | void itob(int n, char s[], int b); 11 | void reverse(char s[]); 12 | 13 | int main(void) 14 | { 15 | char s[MAXLINE]; 16 | 17 | itob(INT_MIN, s, 16); 18 | printf("%d in base %d is %s.\n", INT_MIN, 16, s); 19 | itob(826, s, 10); 20 | printf("%d in base %d is %s.\n", 826, 10, s); 21 | itob(-2093, s, 5); 22 | printf("%d in base %d is %s.\n", -2093, 5, s); 23 | 24 | return 0; 25 | } 26 | 27 | void itob(int n, char s[], int b) 28 | { 29 | int i, sign, remainder; 30 | char bases[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 31 | 32 | if (b < 2 || b > 36) 33 | return; 34 | 35 | sign = n; 36 | i = 0; 37 | do { 38 | remainder = n % b; 39 | s[i++] = ((sign < 0) ? -remainder : remainder) + '0'; 40 | } while (n /= b); 41 | if (sign < 0) 42 | s[i++] = '-'; 43 | s[i] = '\0'; 44 | reverse(s); 45 | } 46 | 47 | void reverse(char s[]) 48 | { 49 | int i, j; 50 | int tmp; 51 | 52 | for (j = 0; s[j] != '\0'; ++j) 53 | ; 54 | --j; 55 | 56 | for (i = 0; i < j; ++i, --j) { 57 | tmp = s[i]; 58 | s[i] = s[j]; 59 | s[j] = tmp; 60 | } 61 | } -------------------------------------------------------------------------------- /Chapter3/Exercise 3-06/itoa.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 3-06, Chapter3. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | void itoa(int n, char s[], int w); 11 | void reverse(char s[]); 12 | 13 | int main(void) 14 | { 15 | char s[MAXLINE]; 16 | int width; 17 | 18 | width = 11; 19 | itoa(INT_MIN, s, width); 20 | printf("%12d is converted to %s.\n", INT_MIN, s); 21 | itoa(826, s, width); 22 | printf("%12d is converted to %s.\n", 826, s); 23 | itoa(-2093, s, width); 24 | printf("%12d is converted to %s.\n", -2093, s); 25 | 26 | return 0; 27 | } 28 | 29 | void itoa(int n, char s[], int w) 30 | { 31 | int i, sign, remainder, k, j; 32 | 33 | sign = n; 34 | i = 0; 35 | do { 36 | remainder = n % 10; 37 | s[i++] = ((sign < 0) ? -remainder : remainder) + '0'; 38 | } while (n /= 10); 39 | if (sign < 0) 40 | s[i++] = '-'; 41 | 42 | while (i < w) 43 | s[i++] = ' '; 44 | 45 | s[i] = '\0'; 46 | reverse(s); 47 | } 48 | 49 | void reverse(char s[]) 50 | { 51 | int i, j; 52 | int tmp; 53 | 54 | for (j = 0; s[j] != '\0'; ++j) 55 | ; 56 | --j; 57 | 58 | for (i = 0; i < j; ++i, --j) { 59 | tmp = s[i]; 60 | s[i] = s[j]; 61 | s[j] = tmp; 62 | } 63 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-01/strindex.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-01, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | int getchars(char s[], int max); 11 | int strindex(char source[], char searchfor[]); 12 | 13 | int main(void) 14 | { 15 | char source[MAXLINE]; 16 | char pattern[MAXLINE]; 17 | 18 | printf("Input source, then press enter:\n"); 19 | while (getchars(source, MAXLINE) == 0) 20 | ; 21 | 22 | printf("Input pattern, then press enter:\n"); 23 | while (getchars(pattern, MAXLINE) == 0) 24 | ; 25 | 26 | printf("The position is: %d\n", strindex(source, pattern)); 27 | 28 | return 0; 29 | } 30 | 31 | int getchars(char s[], int max) 32 | { 33 | int c, i, l; 34 | 35 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 36 | if (i < max - 1) 37 | s[l++] = c; 38 | s[l] = '\0'; 39 | 40 | return l; 41 | } 42 | 43 | int strindex(char s[], char t[]) 44 | { 45 | int sl, tl; 46 | int i, j, k; 47 | int c; 48 | 49 | sl = strlen(s); 50 | tl = strlen(t); 51 | i = sl - tl; 52 | while (i >= 0) { 53 | for (j = i, k = 0; t[k] != '\0' && s[j] == t[k]; ++j, ++k) 54 | ; 55 | if (k > 0 && t[k] == '\0') 56 | return i; 57 | --i; 58 | } 59 | return -1; 60 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-02/atof.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-02, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | int getchars(char s[], int max); 11 | double atof(char s[]); 12 | 13 | int main(void) 14 | { 15 | char s[MAXLINE]; 16 | 17 | printf("Input a floating-point number, then press enter:\n"); 18 | while (getchars(s, MAXLINE) == 0) 19 | ; 20 | 21 | printf("The number is: %lf\n", atof(s)); 22 | 23 | return 0; 24 | } 25 | 26 | int getchars(char s[], int max) 27 | { 28 | int c, i, l; 29 | 30 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 31 | if (i < max - 1) 32 | s[l++] = c; 33 | s[l] = '\0'; 34 | 35 | return l; 36 | } 37 | 38 | /* atof: convert string s to double */ 39 | double atof(char s[]) 40 | { 41 | double val, power, base, epower; 42 | int i, sign, exponent; 43 | 44 | for (i = 0; isspace(s[i]); i++) /* skip white space */ 45 | ; 46 | sign = (s[i] == '-') ? -1 : 1; 47 | if (s[i] == '+' || s[i] == '-') 48 | i++; 49 | for (val = 0.0; isdigit(s[i]); i++) 50 | val = 10.0 * val + (s[i] - '0'); 51 | if (s[i] == '.') 52 | i++; 53 | for (power = 1.0; isdigit(s[i]); i++) { 54 | val = 10.0 * val + (s[i] - '0'); 55 | power *= 10; 56 | } 57 | epower = 1; 58 | if (s[i] == 'e' || s[i] == 'E') { 59 | i++; 60 | base = s[i] == '-' ? 0.1 : 10.0; 61 | if (s[i] == '-' || s[i] == '+') 62 | i++; 63 | for (exponent = 0; isdigit(s[i]); i++) { 64 | exponent = 10 * exponent + (s[i] - '0'); 65 | } 66 | while (exponent-- > 0) 67 | epower *= base; 68 | } 69 | return sign * val / power * epower; 70 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-03/calculator.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-03, Chapter4. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | 9 | #define MAXLINE 1000 10 | #define MAXOP 100 /* max size of operand or operator */ 11 | #define NUMBER '0' /* signal that a number was found */ 12 | 13 | int getop(char []); 14 | void push(double); 15 | double pop(void); 16 | 17 | int main(void) 18 | { 19 | int type; 20 | double op2; 21 | char s[MAXOP]; 22 | 23 | while ((type = getop(s)) != EOF) { 24 | switch (type) { 25 | case NUMBER: 26 | push(atof(s)); 27 | break; 28 | case '+': 29 | push(pop() + pop()); 30 | break; 31 | case '*': 32 | push(pop() * pop()); 33 | break; 34 | case '-': 35 | op2 = pop(); 36 | push(pop() - op2); 37 | break; 38 | case '/': 39 | op2 = pop(); 40 | if (op2 != 0.0) 41 | push(pop() / op2); 42 | else 43 | printf("error: zero divisor\n"); 44 | break; 45 | case '%': 46 | op2 = pop(); 47 | if (op2 != 0.0) 48 | push(fmod(pop(), op2)); 49 | else 50 | printf("error: zero divisor\n"); 51 | break; 52 | case '\n': 53 | printf("= %g\n", pop()); 54 | break; 55 | default: 56 | printf("error: unknown command %s\n", s); 57 | break; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | #define MAXVAL 100 /* maximum depth of val stack */ 65 | 66 | int sp = 0; /* next free stack position */ 67 | double val[MAXVAL]; /* value stack */ 68 | 69 | /* push: push f onto value stack */ 70 | void push(double f) 71 | { 72 | if (sp < MAXVAL) 73 | val[sp++] = f; 74 | else 75 | printf("error: stack full, can't push %g\n", f); 76 | } 77 | 78 | /* pop: pop and return top value from stack */ 79 | double pop(void) 80 | { 81 | if (sp > 0) 82 | return val[--sp]; 83 | else { 84 | printf("error: stack empty\n"); 85 | return 0.0; 86 | } 87 | } 88 | 89 | #include 90 | 91 | int getch(void); 92 | void ungetch(int); 93 | 94 | /* getop: get next character or numeric operand */ 95 | int getop(char s[]) 96 | { 97 | int i, c, c2; 98 | 99 | while ((s[0] = c = getch()) == ' ' || c == '\t') 100 | ; 101 | s[1] = '\0'; 102 | if (!isdigit(c) && c != '.' && c != '-') 103 | return c; /* not a number */ 104 | i = 0; 105 | if (c == '-') { 106 | c2 = getch(); 107 | if (c2 != EOF) 108 | ungetch(c2); 109 | if (!isdigit(c2) && c2 != '.') 110 | return c; 111 | } 112 | if (isdigit(c) || c == '-') /* collect integer part */ 113 | while (isdigit(s[++i] = c = getch())) 114 | ; 115 | if (c == '.') /* collect fraction part */ 116 | while (isdigit(s[++i] = c = getch())) 117 | ; 118 | s[i] = '\0'; 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 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-04/stack.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-04, Chapter4. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | 9 | #define MAXLINE 1000 10 | #define MAXOP 100 /* max size of operand or operator */ 11 | #define NUMBER '0' /* signal that a number was found */ 12 | 13 | int getop(char []); 14 | void push(double); 15 | double pop(void); 16 | void printtop(void); 17 | void duplicate(void); 18 | void swap(void); 19 | void clear(void); 20 | 21 | int main(void) 22 | { 23 | push(9.545); 24 | push(23.761); 25 | duplicate(); 26 | printtop(); 27 | swap(); 28 | clear(); 29 | 30 | return 0; 31 | } 32 | 33 | #define MAXVAL 100 /* maximum depth of val stack */ 34 | 35 | int sp = 0; /* next free stack position */ 36 | double val[MAXVAL]; /* value stack */ 37 | 38 | /* push: push f onto value stack */ 39 | void push(double f) 40 | { 41 | if (sp < MAXVAL) 42 | val[sp++] = f; 43 | else 44 | printf("error: stack full, can't push %g\n", f); 45 | } 46 | 47 | /* pop: pop and return top value from stack */ 48 | double pop(void) 49 | { 50 | if (sp > 0) 51 | return val[--sp]; 52 | else { 53 | printf("error: stack empty\n"); 54 | return 0.0; 55 | } 56 | } 57 | 58 | /* printtop: print the top element of the stack */ 59 | void printtop(void) 60 | { 61 | if (sp > 0) 62 | printf("%g\n", val[sp - 1]); 63 | else 64 | printf("error: stack empty\n"); 65 | } 66 | 67 | /* duplicate: duplicate the top element of the stack */ 68 | void duplicate(void) 69 | { 70 | double top = pop(); 71 | push(top); 72 | push(top); 73 | } 74 | 75 | /* swap: swap the top two elements of the stack */ 76 | void swap(void) 77 | { 78 | double top1 = pop(); 79 | double top2 = pop(); 80 | push(top1); 81 | push(top2); 82 | } 83 | 84 | /* clear: clear stack */ 85 | void clear(void) 86 | { 87 | sp = 0; 88 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-05/calculator.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-05, Chapter4. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | #include 9 | 10 | #define MAXLINE 1000 11 | #define MAXOP 100 /* max size of operand or operator */ 12 | #define NUMBER '0' /* signal that a number was found */ 13 | #define MATHLIB '1' /* signal that a library function in math.h was found */ 14 | 15 | int getop(char []); 16 | void push(double); 17 | double pop(void); 18 | 19 | int main(void) 20 | { 21 | int type; 22 | double op2; 23 | char s[MAXOP]; 24 | 25 | while ((type = getop(s)) != EOF) { 26 | switch (type) { 27 | case NUMBER: 28 | push(atof(s)); 29 | break; 30 | case MATHLIB: 31 | if (strcmp(s, "sin") == 0) 32 | push(sin(pop())); 33 | else if (strcmp(s, "cos") == 0) 34 | push(cos(pop())); 35 | else if (strcmp(s, "pow") == 0) { 36 | op2 = pop(); 37 | push(pow(pop(), op2)); 38 | } else 39 | printf("error: unknown command %s\n", s); 40 | break; 41 | case '+': 42 | push(pop() + pop()); 43 | break; 44 | case '*': 45 | push(pop() * pop()); 46 | break; 47 | case '-': 48 | op2 = pop(); 49 | push(pop() - op2); 50 | break; 51 | case '/': 52 | op2 = pop(); 53 | if (op2 != 0.0) 54 | push(pop() / op2); 55 | else 56 | printf("error: zero divisor\n"); 57 | break; 58 | case '%': 59 | op2 = pop(); 60 | if (op2 != 0.0) 61 | push(fmod(pop(), op2)); 62 | else 63 | printf("error: zero divisor\n"); 64 | break; 65 | case '\n': 66 | printf("= %g\n", pop()); 67 | break; 68 | default: 69 | printf("error: unknown command %s\n", s); 70 | break; 71 | } 72 | } 73 | 74 | return 0; 75 | } 76 | 77 | #define MAXVAL 100 /* maximum depth of val stack */ 78 | 79 | int sp = 0; /* next free stack position */ 80 | double val[MAXVAL]; /* value stack */ 81 | 82 | /* push: push f onto value stack */ 83 | void push(double f) 84 | { 85 | if (sp < MAXVAL) 86 | val[sp++] = f; 87 | else 88 | printf("error: stack full, can't push %g\n", f); 89 | } 90 | 91 | /* pop: pop and return top value from stack */ 92 | double pop(void) 93 | { 94 | if (sp > 0) 95 | return val[--sp]; 96 | else { 97 | printf("error: stack empty\n"); 98 | return 0.0; 99 | } 100 | } 101 | 102 | #include 103 | 104 | int getch(void); 105 | void ungetch(int); 106 | 107 | /* getop: get next character or numeric operand */ 108 | int getop(char s[]) 109 | { 110 | int i, c, c2; 111 | 112 | while ((s[0] = c = getch()) == ' ' || c == '\t') 113 | ; 114 | s[1] = '\0'; 115 | 116 | i = 0; 117 | if (isalpha(c)) { 118 | while (isalpha(s[++i] = c = getch())) 119 | ; 120 | s[i] = '\0'; 121 | if (c != EOF) 122 | ungetch(c); 123 | return MATHLIB; 124 | } 125 | 126 | if (!isdigit(c) && c != '.' && c != '-') 127 | return c; /* not a number */ 128 | 129 | if (c == '-') { 130 | c2 = getch(); 131 | if (c2 != EOF) 132 | ungetch(c2); 133 | if (!isdigit(c2) && c2 != '.') 134 | return c; 135 | } 136 | 137 | if (isdigit(c) || c == '-') /* collect integer part */ 138 | while (isdigit(s[++i] = c = getch())) 139 | ; 140 | if (c == '.') /* collect fraction part */ 141 | while (isdigit(s[++i] = c = getch())) 142 | ; 143 | s[i] = '\0'; 144 | if (c != EOF) 145 | ungetch(c); 146 | return NUMBER; 147 | } 148 | 149 | #define BUFSIZE 100 150 | 151 | char buf[BUFSIZE]; /* buffer for ungetch */ 152 | int bufp = 0; /* next free position in buf */ 153 | 154 | int getch(void) /* get a (possibly pushed-back) character */ 155 | { 156 | return (bufp > 0) ? buf[--bufp] : getchar(); 157 | } 158 | 159 | void ungetch(int c) /* push character back on input */ 160 | { 161 | if (bufp >= BUFSIZE) 162 | printf("ungetch: too many characters\n"); 163 | else 164 | buf[bufp++] = c; 165 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-06/calculator.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-06, Chapter4. 3 | */ 4 | 5 | /** 6 | * Use string pattern like below: 7 | * 3 5 + =t last 7 4 - * =m last 8 | */ 9 | 10 | #include 11 | #include /* for atof() */ 12 | #include 13 | #include 14 | #include 15 | 16 | #define MAXLINE 1000 17 | #define MAXOP 100 /* max size of operand or operator */ 18 | #define NUMBER '0' /* signal that a number was found */ 19 | #define MATHLIB '1' /* signal that a library function in math.h was found */ 20 | #define VARIABLE '2' 21 | 22 | int getop(char []); 23 | void push(double); 24 | double pop(void); 25 | 26 | double vars[26]; 27 | double last; 28 | 29 | int main(void) 30 | { 31 | int type, v; 32 | double op2; 33 | char s[MAXOP]; 34 | 35 | while ((type = getop(s)) != EOF) { 36 | switch (type) { 37 | case NUMBER: 38 | push(atof(s)); 39 | break; 40 | case MATHLIB: 41 | if (strcmp(s, "sin") == 0) 42 | push(sin(pop())); 43 | else if (strcmp(s, "cos") == 0) 44 | push(cos(pop())); 45 | else if (strcmp(s, "pow") == 0) { 46 | op2 = pop(); 47 | push(pow(pop(), op2)); 48 | } else if (strcmp(s, "last") == 0) { 49 | printf("the most recently printed value is %g\n", last); 50 | } else 51 | printf("error: unknown command %s\n", s); 52 | break; 53 | case '+': 54 | push(pop() + pop()); 55 | break; 56 | case '*': 57 | push(pop() * pop()); 58 | break; 59 | case '-': 60 | op2 = pop(); 61 | push(pop() - op2); 62 | break; 63 | case '/': 64 | op2 = pop(); 65 | if (op2 != 0.0) 66 | push(pop() / op2); 67 | else 68 | printf("error: zero divisor\n"); 69 | break; 70 | case '%': 71 | op2 = pop(); 72 | if (op2 != 0.0) 73 | push(fmod(pop(), op2)); 74 | else 75 | printf("error: zero divisor\n"); 76 | break; 77 | case VARIABLE: 78 | v = tolower(s[0]); 79 | last = vars[v - 'a'] = pop(); 80 | push(last); 81 | break; 82 | case '\n': 83 | printf("= %g\n", pop()); 84 | break; 85 | default: 86 | printf("error: unknown command %s\n", s); 87 | break; 88 | } 89 | } 90 | 91 | return 0; 92 | } 93 | 94 | #define MAXVAL 100 /* maximum depth of val stack */ 95 | 96 | int sp = 0; /* next free stack position */ 97 | double val[MAXVAL]; /* value stack */ 98 | 99 | /* push: push f onto value stack */ 100 | void push(double f) 101 | { 102 | if (sp < MAXVAL) 103 | val[sp++] = f; 104 | else 105 | printf("error: stack full, can't push %g\n", f); 106 | } 107 | 108 | /* pop: pop and return top value from stack */ 109 | double pop(void) 110 | { 111 | if (sp > 0) 112 | return val[--sp]; 113 | else { 114 | printf("error: stack empty\n"); 115 | return 0.0; 116 | } 117 | } 118 | 119 | #include 120 | 121 | int getch(void); 122 | void ungetch(int); 123 | 124 | /* getop: get next character or numeric operand */ 125 | int getop(char s[]) 126 | { 127 | int i, c, c2; 128 | 129 | while ((s[0] = c = getch()) == ' ' || c == '\t') 130 | ; 131 | s[1] = '\0'; 132 | 133 | i = 0; 134 | if (isalpha(c)) { 135 | while (isalpha(s[++i] = c = getch())) 136 | ; 137 | s[i] = '\0'; 138 | if (c != EOF) 139 | ungetch(c); 140 | return MATHLIB; 141 | } 142 | 143 | if (!isdigit(c) && c != '.' && c != '-') { 144 | if (c == '=') { 145 | if (isalpha(c2 = getch())) { 146 | s[0] = c2; 147 | return VARIABLE; 148 | } else if (c2 != EOF) { 149 | ungetch(c2); 150 | } 151 | } 152 | return c; /* not a number */ 153 | } 154 | 155 | if (c == '-') { 156 | c2 = getch(); 157 | if (c2 != EOF) 158 | ungetch(c2); 159 | if (!isdigit(c2) && c2 != '.') 160 | return c; 161 | } 162 | 163 | if (isdigit(c) || c == '-') /* collect integer part */ 164 | while (isdigit(s[++i] = c = getch())) 165 | ; 166 | if (c == '.') /* collect fraction part */ 167 | while (isdigit(s[++i] = c = getch())) 168 | ; 169 | s[i] = '\0'; 170 | if (c != EOF) 171 | ungetch(c); 172 | return NUMBER; 173 | } 174 | 175 | #define BUFSIZE 100 176 | 177 | char buf[BUFSIZE]; /* buffer for ungetch */ 178 | int bufp = 0; /* next free position in buf */ 179 | 180 | int getch(void) /* get a (possibly pushed-back) character */ 181 | { 182 | return (bufp > 0) ? buf[--bufp] : getchar(); 183 | } 184 | 185 | void ungetch(int c) /* push character back on input */ 186 | { 187 | if (bufp >= BUFSIZE) 188 | printf("ungetch: too many characters\n"); 189 | else 190 | buf[bufp++] = c; 191 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-07/ungets.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-07, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | int getch(void); 9 | void ungetch(int); 10 | void ungets(char s[]); 11 | 12 | int main(void) 13 | { 14 | ungets("testring"); 15 | putchar(getch()); 16 | putchar(getch()); 17 | putchar(getch()); 18 | putchar(getch()); 19 | putchar(getch()); 20 | putchar(getch()); 21 | putchar(getch()); 22 | putchar(getch()); 23 | 24 | return 0; 25 | } 26 | 27 | #define BUFSIZE 100 28 | 29 | char buf[BUFSIZE]; /* buffer for ungetch */ 30 | int bufp = 0; /* next free position in buf */ 31 | 32 | int getch(void) /* get a (possibly pushed-back) character */ 33 | { 34 | return (bufp > 0) ? buf[--bufp] : getchar(); 35 | } 36 | 37 | void ungetch(int c) /* push character back on input */ 38 | { 39 | if (bufp >= BUFSIZE) 40 | printf("ungetch: too many characters\n"); 41 | else 42 | buf[bufp++] = c; 43 | } 44 | 45 | void ungets(char s[]) 46 | { 47 | int l = strlen(s); 48 | 49 | while (l) 50 | ungetch(s[--l]); 51 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-08/buf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-08, Chapter4. 3 | */ 4 | 5 | #include 6 | 7 | int getch(void); 8 | void ungetch(int); 9 | 10 | int main(void) 11 | { 12 | ungetch('a'); 13 | ungetch('t'); 14 | putchar(getch()); 15 | 16 | return 0; 17 | } 18 | 19 | int buf = -1; /* buffer for ungetch */ 20 | 21 | int getch(void) /* get a (possibly pushed-back) character */ 22 | { 23 | int b = buf; 24 | if (b > -1) { 25 | buf = -1; 26 | return b; 27 | } 28 | return getchar(); 29 | } 30 | 31 | void ungetch(int c) /* push character back on input */ 32 | { 33 | buf = c; 34 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-09/buf.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-09, Chapter4. 3 | */ 4 | 5 | #include 6 | 7 | int getch(void); 8 | void ungetch(int); 9 | 10 | int main(void) 11 | { 12 | ungetch('t'); 13 | ungetch(EOF); 14 | putchar(getch()); 15 | 16 | return 0; 17 | } 18 | 19 | #define BUFSIZE 100 20 | 21 | char buf[BUFSIZE]; /* buffer for ungetch */ 22 | int bufp = 0; /* next free position in buf */ 23 | 24 | int getch(void) /* get a (possibly pushed-back) character */ 25 | { 26 | return (bufp > 0) ? buf[--bufp] : getchar(); 27 | } 28 | 29 | void ungetch(int c) /* push character back on input */ 30 | { 31 | if (bufp >= BUFSIZE) 32 | printf("ungetch: too many characters\n"); 33 | else if (c != EOF) 34 | buf[bufp++] = c; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter4/Exercise 4-10/getline.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-10, Chapter4. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAXLINE 1000 12 | #define MAXOP 100 /* max size of operand or operator */ 13 | #define NUMBER '0' /* signal that a number was found */ 14 | #define MATHLIB '1' /* signal that a library function in math.h was found */ 15 | #define VARIABLE '2' 16 | 17 | #define MAXLINE 1000 18 | 19 | int get_line(char line[], int max); 20 | 21 | char line[MAXLINE]; 22 | int linep = 0; 23 | 24 | int getop(char []); 25 | void push(double); 26 | double pop(void); 27 | 28 | double vars[26]; 29 | double last; 30 | 31 | int main(void) 32 | { 33 | int type, v; 34 | double op2; 35 | char s[MAXOP]; 36 | 37 | while (get_line(line, MAXLINE) > 0) { 38 | linep = 0; 39 | 40 | while ((type = getop(s)) != '\0') { 41 | switch (type) { 42 | case NUMBER: 43 | push(atof(s)); 44 | break; 45 | case MATHLIB: 46 | if (strcmp(s, "sin") == 0) 47 | push(sin(pop())); 48 | else if (strcmp(s, "cos") == 0) 49 | push(cos(pop())); 50 | else if (strcmp(s, "pow") == 0) { 51 | op2 = pop(); 52 | push(pow(pop(), op2)); 53 | } else if (strcmp(s, "last") == 0) { 54 | printf("the most recently printed value is %g\n", last); 55 | } else 56 | printf("error: unknown command %s\n", s); 57 | break; 58 | case '+': 59 | push(pop() + pop()); 60 | break; 61 | case '*': 62 | push(pop() * pop()); 63 | break; 64 | case '-': 65 | op2 = pop(); 66 | push(pop() - op2); 67 | break; 68 | case '/': 69 | op2 = pop(); 70 | if (op2 != 0.0) 71 | push(pop() / op2); 72 | else 73 | printf("error: zero divisor\n"); 74 | break; 75 | case '%': 76 | op2 = pop(); 77 | if (op2 != 0.0) 78 | push(fmod(pop(), op2)); 79 | else 80 | printf("error: zero divisor\n"); 81 | break; 82 | case VARIABLE: 83 | v = tolower(s[0]); 84 | last = vars[v - 'a'] = pop(); 85 | push(last); 86 | break; 87 | case '\n': 88 | printf("= %g\n", pop()); 89 | break; 90 | default: 91 | printf("error: unknown command %s\n", s); 92 | break; 93 | } 94 | } 95 | } 96 | 97 | 98 | return 0; 99 | } 100 | 101 | #define MAXVAL 100 /* maximum depth of val stack */ 102 | 103 | int sp = 0; /* next free stack position */ 104 | double val[MAXVAL]; /* value stack */ 105 | 106 | /* push: push f onto value stack */ 107 | void push(double f) 108 | { 109 | if (sp < MAXVAL) 110 | val[sp++] = f; 111 | else 112 | printf("error: stack full, can't push %g\n", f); 113 | } 114 | 115 | /* pop: pop and return top value from stack */ 116 | double pop(void) 117 | { 118 | if (sp > 0) 119 | return val[--sp]; 120 | else { 121 | printf("error: stack empty\n"); 122 | return 0.0; 123 | } 124 | } 125 | 126 | #include 127 | 128 | /* getop: get next character or numeric operand */ 129 | int getop(char s[]) 130 | { 131 | int i, c, c2; 132 | 133 | while ((s[0] = c = line[linep++]) == ' ' || c == '\t') 134 | ; 135 | s[1] = '\0'; 136 | 137 | i = 0; 138 | if (isalpha(c)) { 139 | while (isalpha(s[++i] = c = line[linep++])) 140 | ; 141 | s[i] = '\0'; 142 | if (c != '\0') 143 | --linep; 144 | return MATHLIB; 145 | } 146 | 147 | if (!isdigit(c) && c != '.' && c != '-') { 148 | if (c == '=') { 149 | if (isalpha(c2 = line[linep++])) { 150 | s[0] = c2; 151 | return VARIABLE; 152 | } else if (c2 != '\0') { 153 | --linep; 154 | } 155 | } 156 | return c; /* not a number */ 157 | } 158 | 159 | if (c == '-') { 160 | c2 = line[linep++]; 161 | if (c2 != '\0') 162 | --linep; 163 | if (!isdigit(c2) && c2 != '.') 164 | return c; 165 | } 166 | 167 | if (isdigit(c) || c == '-') /* collect integer part */ 168 | while (isdigit(s[++i] = c = line[linep++])) 169 | ; 170 | if (c == '.') /* collect fraction part */ 171 | while (isdigit(s[++i] = c = line[linep++])) 172 | ; 173 | s[i] = '\0'; 174 | if (c != '\0') 175 | --linep; 176 | return NUMBER; 177 | } 178 | 179 | int get_line(char s[], int max) 180 | { 181 | int c, i, l; 182 | 183 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 184 | if (i < max - 1) 185 | s[l++] = c; 186 | if (c == '\n') 187 | s[l++] = c; 188 | s[l] = '\0'; 189 | 190 | return l; 191 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-11/getop.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-11, Chapter4. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | #include 9 | #include 10 | 11 | #define MAXLINE 1000 12 | #define MAXOP 100 /* max size of operand or operator */ 13 | #define NUMBER '0' /* signal that a number was found */ 14 | #define MATHLIB '1' /* signal that a library function in math.h was found */ 15 | #define VARIABLE '2' 16 | 17 | int getop(char []); 18 | void push(double); 19 | double pop(void); 20 | 21 | double vars[26]; 22 | double last; 23 | 24 | int main(void) 25 | { 26 | int type, v; 27 | double op2; 28 | char s[MAXOP]; 29 | 30 | while ((type = getop(s)) != EOF) { 31 | switch (type) { 32 | case NUMBER: 33 | push(atof(s)); 34 | break; 35 | case MATHLIB: 36 | if (strcmp(s, "sin") == 0) 37 | push(sin(pop())); 38 | else if (strcmp(s, "cos") == 0) 39 | push(cos(pop())); 40 | else if (strcmp(s, "pow") == 0) { 41 | op2 = pop(); 42 | push(pow(pop(), op2)); 43 | } else if (strcmp(s, "last") == 0) { 44 | printf("the most recently printed value is %g\n", last); 45 | } else 46 | printf("error: unknown command %s\n", s); 47 | break; 48 | case '+': 49 | push(pop() + pop()); 50 | break; 51 | case '*': 52 | push(pop() * pop()); 53 | break; 54 | case '-': 55 | op2 = pop(); 56 | push(pop() - op2); 57 | break; 58 | case '/': 59 | op2 = pop(); 60 | if (op2 != 0.0) 61 | push(pop() / op2); 62 | else 63 | printf("error: zero divisor\n"); 64 | break; 65 | case '%': 66 | op2 = pop(); 67 | if (op2 != 0.0) 68 | push(fmod(pop(), op2)); 69 | else 70 | printf("error: zero divisor\n"); 71 | break; 72 | case VARIABLE: 73 | v = tolower(s[0]); 74 | last = vars[v - 'a'] = pop(); 75 | push(last); 76 | break; 77 | case '\n': 78 | printf("= %g\n", pop()); 79 | break; 80 | default: 81 | printf("error: unknown command %s\n", s); 82 | break; 83 | } 84 | } 85 | 86 | return 0; 87 | } 88 | 89 | #define MAXVAL 100 /* maximum depth of val stack */ 90 | 91 | int sp = 0; /* next free stack position */ 92 | double val[MAXVAL]; /* value stack */ 93 | 94 | /* push: push f onto value stack */ 95 | void push(double f) 96 | { 97 | if (sp < MAXVAL) 98 | val[sp++] = f; 99 | else 100 | printf("error: stack full, can't push %g\n", f); 101 | } 102 | 103 | /* pop: pop and return top value from stack */ 104 | double pop(void) 105 | { 106 | if (sp > 0) 107 | return val[--sp]; 108 | else { 109 | printf("error: stack empty\n"); 110 | return 0.0; 111 | } 112 | } 113 | 114 | #include 115 | 116 | int getch(void); 117 | 118 | /* getop: get next character or numeric operand */ 119 | int getop(char s[]) 120 | { 121 | static int buf = EOF; 122 | int i, c, c2; 123 | 124 | // if (buf == EOF) 125 | // c = getch(); 126 | // else { 127 | // c = buf; 128 | // buf = EOF; 129 | // } 130 | 131 | while ((s[0] = c = (buf == EOF ? getch() : buf)) == ' ' || c == '\t') 132 | buf = EOF; 133 | buf = EOF; 134 | s[1] = '\0'; 135 | 136 | i = 0; 137 | if (isalpha(c)) { 138 | while (isalpha(s[++i] = c = (buf == EOF ? getch() : buf))) 139 | buf = EOF; 140 | buf = EOF; 141 | s[i] = '\0'; 142 | if (c != EOF) 143 | buf = c; 144 | return MATHLIB; 145 | } 146 | 147 | if (!isdigit(c) && c != '.' && c != '-') { 148 | if (c == '=') { 149 | c2 = (buf == EOF ? getch() : buf); 150 | buf = EOF; 151 | if (isalpha(c2)) { 152 | s[0] = c2; 153 | return VARIABLE; 154 | } else if (c2 != EOF) { 155 | buf = c2; 156 | } 157 | } 158 | return c; /* not a number */ 159 | } 160 | 161 | if (c == '-') { 162 | c2 = (buf == EOF ? getch() : buf); 163 | buf = EOF; 164 | if (c2 != EOF) 165 | buf = c2; 166 | if (!isdigit(c2) && c2 != '.') 167 | return c; 168 | } 169 | if (isdigit(c) || c == '-') /* collect integer part */ 170 | while (isdigit(s[++i] = c = (buf == EOF ? getch() : buf))) { 171 | buf = EOF; 172 | } 173 | buf = EOF; 174 | if (c == '.') /* collect fraction part */ 175 | while (isdigit(s[++i] = c = (buf == EOF ? getch() : buf))) 176 | buf = EOF; 177 | buf = EOF; 178 | s[i] = '\0'; 179 | if (c != EOF) 180 | buf = c; 181 | return NUMBER; 182 | } 183 | 184 | int getch(void) /* get a (possibly pushed-back) character */ 185 | { 186 | return getchar(); 187 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-12/itoa.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-12, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #define MAXLINE 1000 10 | 11 | void itoa(int n, char s[]); 12 | void itoa_r(int n, char s[]); 13 | 14 | int main(void) 15 | { 16 | char s[MAXLINE]; 17 | 18 | itoa(INT_MIN, s); 19 | printf("%d is converted to %s.\n", INT_MIN, s); 20 | itoa(826, s); 21 | printf("%d is converted to %s.\n", 826, s); 22 | itoa(-2093, s); 23 | printf("%d is converted to %s.\n", -2093, s); 24 | 25 | return 0; 26 | } 27 | 28 | void itoa(int n, char s[]) 29 | { 30 | s[0] = '\0'; 31 | itoa_r(n, s); 32 | } 33 | 34 | void itoa_r(int n, char s[]) 35 | { 36 | int remainder, l; 37 | 38 | if (n / 10) 39 | itoa(n / 10, s); 40 | 41 | l = strlen(s); 42 | if (n / 10 == 0 && n < 0) 43 | s[l++] = '-'; 44 | remainder = n % 10; 45 | s[l++] = ((n < 0) ? -remainder : remainder) + '0'; 46 | s[l++] = '\0'; 47 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-13/reverse.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-13, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define MAXLINE 1000 9 | 10 | int getchars(char line[], int max); 11 | void reverse(char s[]); 12 | void reverse_r(char s[], int i, int j); 13 | 14 | int main(void) 15 | { 16 | char s[MAXLINE]; 17 | 18 | while (getchars(s, MAXLINE)) { 19 | reverse(s); 20 | printf("reverse: %s\n", s); 21 | } 22 | 23 | return 0; 24 | } 25 | 26 | void reverse(char s[]) 27 | { 28 | reverse_r(s, 0, strlen(s) - 1); 29 | } 30 | 31 | void reverse_r(char s[], int i, int j) 32 | { 33 | int tmp; 34 | 35 | tmp = s[i]; 36 | s[i] = s[j]; 37 | s[j] = tmp; 38 | 39 | if (i < j) 40 | reverse_r(s, ++i, --j); 41 | } 42 | 43 | int getchars(char s[], int max) 44 | { 45 | int c, i, l; 46 | 47 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 48 | if (i < max - 1) 49 | s[l++] = c; 50 | s[l] = '\0'; 51 | 52 | return l; 53 | } -------------------------------------------------------------------------------- /Chapter4/Exercise 4-14/swap.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 4-14, Chapter4. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | #define swap(t, x, y) {t tmp; tmp = x; x = y; y = tmp;} 9 | 10 | int main(void) 11 | { 12 | int ia = 20, ib = 35; 13 | printf("before swap: %d, %d\n", ia, ib); 14 | swap(int, ia, ib) 15 | printf(" after swap: %d, %d\n", ia, ib); 16 | 17 | double da = 0.3563, db = 348.34; 18 | printf("before swap: %6g, %6g\n", da, db); 19 | swap(double, da, db) 20 | printf(" after swap: %6g, %6g\n", da, db); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-01/getch.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-01, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define BUFSIZE 100 8 | 9 | char buf[BUFSIZE]; /* buffer for ungetch */ 10 | int bufp = 0; /* next free position in buf */ 11 | 12 | int getch(void) /* get a (possibly pushed-back) character */ 13 | { 14 | return (bufp > 0) ? buf[--bufp] : getchar(); 15 | } 16 | 17 | void ungetch(int c) /* push character back on input */ 18 | { 19 | if (bufp >= BUFSIZE) 20 | printf("ungetch: too many characters\n"); 21 | else 22 | buf[bufp++] = c; 23 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-01/getch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-01, Chapter5. 3 | */ 4 | 5 | int getch(void); 6 | void ungetch(int); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-01/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-01, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "getch.h" 8 | 9 | #define SIZE 10 10 | 11 | int getint(int *); 12 | 13 | int main(void) 14 | { 15 | int n, array[SIZE], r; 16 | 17 | for (n = 0; n < SIZE && (r = getint(&array[n])) != EOF; n++) { 18 | if (r) 19 | printf("you input a number: %d\n", array[n]); 20 | else 21 | printf("it is not a number.\n"); 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | /* getint: get next integer from input into *pn */ 28 | int getint(int *pn) 29 | { 30 | int c, sign, c2; 31 | 32 | while (isspace(c = getch())) /* skip white space */ 33 | ; 34 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 35 | ungetch(c); /* it is not a number */ 36 | return 0; 37 | } 38 | sign = (c == '-') ? -1 : 1; 39 | if (c == '+' || c == '-') { 40 | if (!isdigit(c2 = getch())) { 41 | ungetch(c2); 42 | ungetch(c); 43 | return 0; 44 | } else 45 | c = c2; 46 | } 47 | for (*pn = 0; isdigit(c); c = getch()) 48 | *pn = 10 * *pn + (c - '0'); 49 | *pn *= sign; 50 | if (c != EOF) 51 | ungetch(c); 52 | return c; 53 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-02/getch.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-02, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define BUFSIZE 100 8 | 9 | char buf[BUFSIZE]; /* buffer for ungetch */ 10 | int bufp = 0; /* next free position in buf */ 11 | 12 | int getch(void) /* get a (possibly pushed-back) character */ 13 | { 14 | return (bufp > 0) ? buf[--bufp] : getchar(); 15 | } 16 | 17 | void ungetch(int c) /* push character back on input */ 18 | { 19 | if (bufp >= BUFSIZE) 20 | printf("ungetch: too many characters\n"); 21 | else 22 | buf[bufp++] = c; 23 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-02/getch.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-02, Chapter5. 3 | */ 4 | 5 | int getch(void); 6 | void ungetch(int); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-02/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-02, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "getch.h" 8 | 9 | #define SIZE 10 10 | 11 | int getfloat(double *); 12 | 13 | int main(void) 14 | { 15 | int n; 16 | double array[SIZE], r; 17 | 18 | for (n = 0; n < SIZE && (r = getfloat(&array[n])) != EOF; n++) { 19 | if (r) 20 | printf("you input a number: %g\n", array[n]); 21 | else 22 | printf("it is not a number.\n"); 23 | } 24 | 25 | return 0; 26 | } 27 | 28 | /* getfloat: get next float number from input into *pn */ 29 | int getfloat(double *pn) 30 | { 31 | double power, base, epower; 32 | int c, sign, c2, emark, exponent; 33 | 34 | while (isspace(c = getch())) /* skip white space */ 35 | ; 36 | if (!isdigit(c) && c != EOF && c != '+' && c != '-') { 37 | ungetch(c); /* it is not a number */ 38 | return 0; 39 | } 40 | sign = (c == '-') ? -1 : 1; 41 | if (c == '+' || c == '-') { 42 | if (!isdigit(c2 = getch())) { 43 | ungetch(c2); 44 | ungetch(c); 45 | return 0; 46 | } else 47 | c = c2; 48 | } 49 | for (*pn = 0.0; isdigit(c); c = getch()) 50 | *pn = 10.0 * *pn + (c - '0'); 51 | if (c == '.') 52 | c = getch(); 53 | for (power = 1.0; isdigit(c); c = getch()) { 54 | *pn = 10.0 * *pn + (c - '0'); 55 | power *= 10.0; 56 | } 57 | epower = 1; 58 | if (c == 'e' || c == 'E') { 59 | emark = c; 60 | c = getch(); 61 | base = c == '-' ? 0.1 : 10.0; 62 | if (c == '+' || c == '-') { 63 | if (!isdigit(c2 = getch())) { 64 | ungetch(c2); 65 | ungetch(c); 66 | } else 67 | c = c2; 68 | } else if (!isdigit(c)){ 69 | ungetch(c); 70 | ungetch(emark); 71 | } 72 | for (exponent = 0; isdigit(c); c = getch()) { 73 | exponent = 10 * exponent + (c- '0'); 74 | } 75 | while (exponent-- > 0) 76 | epower *= base; 77 | } 78 | *pn *= sign / power * epower; 79 | if (c != EOF) 80 | ungetch(c); 81 | return c; 82 | } 83 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-03/strcat.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-03, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | void str_cat(char *s, char *t); 10 | int getchars(char *s, int max); 11 | 12 | int main(void) 13 | { 14 | char *s, *t; 15 | 16 | printf("input string s: \n"); 17 | while (getchars(s, MAXLINE) == 0) 18 | ; 19 | printf("input string t: \n"); 20 | while (getchars(t, MAXLINE) == 0) 21 | ; 22 | 23 | str_cat(s, t); 24 | printf("cat: %s\n", s); 25 | 26 | return 0; 27 | } 28 | 29 | void str_cat(char *s, char *t) 30 | { 31 | while (*s) 32 | ++s; 33 | while (*s++ = *t++) 34 | ; 35 | } 36 | 37 | int getchars(char *s, int max) 38 | { 39 | int c, i, l; 40 | 41 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 42 | if (i < max - 1) { 43 | *s++ = c; 44 | ++l; 45 | } 46 | *s = '\0'; 47 | 48 | return l; 49 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-04/strend.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-04, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define MAXLINE 1000 8 | 9 | int strend(char *s, char *t); 10 | int getchars(char *s, int max); 11 | 12 | int main(void) 13 | { 14 | char *s, *t; 15 | 16 | printf("input string s: \n"); 17 | while (getchars(s, MAXLINE) == 0) 18 | ; 19 | printf("input string t: \n"); 20 | while (getchars(t, MAXLINE) == 0) 21 | ; 22 | 23 | printf("string t is%s at the end of the string s.\n", strend(s, t) ? "" : " not"); 24 | 25 | return 0; 26 | } 27 | 28 | int strend(char *s, char *t) 29 | { 30 | int sl, tl; 31 | 32 | sl = tl = 0; 33 | while (*s++) 34 | sl++; 35 | while (*t++) 36 | tl++; 37 | 38 | if (sl >= tl) { 39 | s -= tl; 40 | t -= tl; 41 | while (*s++ == *t++) 42 | if (!*s) 43 | return 1; 44 | } 45 | 46 | return 0; 47 | 48 | } 49 | 50 | int getchars(char *s, int max) 51 | { 52 | int c, i, l; 53 | 54 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 55 | if (i < max - 1) { 56 | *s++ = c; 57 | ++l; 58 | } 59 | *s = '\0'; 60 | 61 | return l; 62 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-05/strncat.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-05, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | void _strncat(char *s, char *t, int n); 8 | 9 | int main(void) 10 | { 11 | char *s, *t; 12 | 13 | s = "test"; 14 | t = "ring1234"; 15 | 16 | _strncat(s, t, 4); 17 | printf("cat: %s\n", s); 18 | 19 | return 0; 20 | } 21 | 22 | void _strncat(char *s, char *t, int n) 23 | { 24 | while (*s) 25 | ++s; 26 | while (n-- > 0 && *t) 27 | *s++ = *t++; 28 | *s = '\0'; 29 | } 30 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-05/strncmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-05, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | int _strncmp(char *s, char *t, int n); 8 | 9 | int main(void) 10 | { 11 | char *s, *t; 12 | 13 | s = "testabc"; 14 | t = "testddc"; 15 | 16 | printf("%s cmp %s: %d\n", s, t, _strncmp(s, t, 5)); 17 | 18 | return 0; 19 | } 20 | 21 | int _strncmp(char *s, char *t, int n) 22 | { 23 | for (; n-- > 0 && *s == *t; ++s, ++t) 24 | if (*s == '\0' || n == 0) 25 | return 0; 26 | return *s - *t; 27 | } 28 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-05/strncpy.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-05, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | void _strncpy(char *s, char *t, int n); 8 | int getchars(char *s, int max); 9 | 10 | int main(void) 11 | { 12 | char *t = "testring1234"; 13 | char *s; 14 | 15 | _strncpy(s, t, 8); 16 | printf("strncpy: %s\n", s); 17 | 18 | return 0; 19 | } 20 | 21 | void _strncpy(char *s, char *t, int n) 22 | { 23 | while (n-- > 0 && (*s++ = *t++)) 24 | ; 25 | *s = '\0'; 26 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-07/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-07, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "lines.h" 8 | 9 | /* readlines: read input lines */ 10 | int readlines(char *lineptr[], int maxlines) 11 | { 12 | int len, nlines; 13 | char line[MAXLEN]; 14 | 15 | nlines = 0; 16 | while ((len = _getline(line, MAXLEN)) > 0) 17 | if (nlines >= maxlines) 18 | return -1; 19 | else { 20 | line[len-1] = '\0'; /* delete newline */ 21 | strcpy(lineptr[nlines++], line); 22 | } 23 | return nlines; 24 | } 25 | 26 | /* writelines: write output lines */ 27 | void writelines(char *lineptr[], int nlines) 28 | { 29 | int i; 30 | for (i = 0; i < nlines; i++) 31 | printf("%s\n", lineptr[i]); 32 | } 33 | 34 | int _getline(char s[], int max) 35 | { 36 | int c, i, l; 37 | 38 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 39 | if (i < max - 1) 40 | s[l++] = c; 41 | if (c == '\n' && l < max - 1) 42 | s[l++] = c; 43 | s[l] = '\0'; 44 | 45 | return l; 46 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-07/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-07, Chapter5. 3 | */ 4 | 5 | #define MAXLINES 50 /* max #lines to be sorted */ 6 | #define MAXLEN 100 /* max length of any input line */ 7 | 8 | int _getline(char *, int); 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-07/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-07, Chapter5. 3 | */ 4 | 5 | #include 6 | #include "lines.h" 7 | #include "qsort.h" 8 | 9 | char *lineptr[MAXLINES]; /* pointers to text lines */ 10 | 11 | /* sort input lines */ 12 | int main(void) 13 | { 14 | int nlines; /* number of input lines read */ 15 | int i; 16 | 17 | char s[MAXLINES][MAXLEN]; 18 | 19 | for (i = 0; i < MAXLINES; ++i) { 20 | *(lineptr + i) = s[i]; 21 | } 22 | 23 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 24 | qsort(lineptr, 0, nlines-1); 25 | writelines(lineptr, nlines); 26 | return 0; 27 | } else { 28 | printf("error: input too big to sort\n"); 29 | return 1; 30 | } 31 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-07/qsort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-07, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* qsort: sort v[left]...v[right] into increasing order */ 8 | void qsort(char *v[], int left, int right) 9 | { 10 | int i, last; 11 | void swap(char *v[], int i, int j); 12 | 13 | if (left >= right) /* do nothing if array contains */ 14 | return; /* fewer than two elements */ 15 | swap(v, left, (left + right)/2); 16 | last = left; 17 | for (i = left+1; i <= right; i++) 18 | if (strcmp(v[i], v[left]) < 0) 19 | swap(v, ++last, i); 20 | swap(v, left, last); 21 | qsort(v, left, last-1); 22 | qsort(v, last+1, right); 23 | } 24 | 25 | /* swap: interchange v[i] and v[j] */ 26 | void swap(char *v[], int i, int j) 27 | { 28 | char *temp; 29 | 30 | temp = v[i]; 31 | v[i] = v[j]; 32 | v[j] = temp; 33 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-07/qsort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-07, Chapter5. 3 | */ 4 | 5 | void qsort(char *lineptr[], int left, int right); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-08/daytab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-08, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | static char daytab[2][13] = { 8 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 9 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 10 | }; 11 | 12 | int day_of_year(int year, int month, int day); 13 | int month_day(int year, int yearday, int *pmonth, int *pday); 14 | 15 | int main(void) 16 | { 17 | int year, month, day, yearday; 18 | int doy, pmonth, pday; 19 | 20 | year = 2012; 21 | month = 2; 22 | day = 29; 23 | doy = day_of_year(year, month, day); 24 | if (doy) 25 | printf("%d-%d-%d: day %dth of the year.\n", year, month, day, doy); 26 | else 27 | printf("%d-%d-%d: invalid!\n", year, month, day); 28 | 29 | year = 2012; 30 | month = 6; 31 | day = 31; 32 | doy = day_of_year(year, month, day); 33 | if (doy) 34 | printf("%d-%d-%d: day %dth of the year.\n", year, month, day, doy); 35 | else 36 | printf("%d-%d-%d: invalid!\n", year, month, day); 37 | 38 | year = 2012; 39 | yearday = 60; 40 | doy = month_day(year, yearday, &pmonth, &pday); 41 | if (doy) 42 | printf("day %dth of year %d is %d-%d.\n", yearday, year, pmonth, pday); 43 | else 44 | printf("day %dth of year %d do not exsits!\n", yearday, year); 45 | 46 | year = 2012; 47 | yearday = 367; 48 | doy = month_day(year, yearday, &pmonth, &pday); 49 | if (doy) 50 | printf("day %dth of year %d is %d-%d.\n", yearday, year, pmonth, pday); 51 | else 52 | printf("day %dth of year %d do not exsits!\n", yearday, year); 53 | 54 | return 0; 55 | } 56 | 57 | /* day_of_year: set day of year from month & day */ 58 | int day_of_year(int year, int month, int day) 59 | { 60 | int i, leap; 61 | 62 | if (month < 1 || month > 12 || day < 1) 63 | return 0; 64 | 65 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 66 | if (day > daytab[leap][month]) 67 | return 0; 68 | for (i = 1; i < month; i++) 69 | day += daytab[leap][i]; 70 | return day; 71 | } 72 | 73 | /* month_day: set month, day from day of year */ 74 | int month_day(int year, int yearday, int *pmonth, int *pday) 75 | { 76 | int i, leap; 77 | 78 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 79 | if (yearday < 1 || yearday > (leap ? 366 : 365)) 80 | return 0; 81 | for (i = 1; yearday > daytab[leap][i]; i++) 82 | yearday -= daytab[leap][i]; 83 | *pmonth = i; 84 | *pday = yearday; 85 | return 1; 86 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-09/daytab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-09, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | static char daytab[2][13] = { 8 | {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 9 | {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 10 | }; 11 | 12 | int day_of_year(int year, int month, int day); 13 | int month_day(int year, int yearday, int *pmonth, int *pday); 14 | 15 | int main(void) 16 | { 17 | int year, month, day, yearday; 18 | int doy, pmonth, pday; 19 | 20 | year = 2012; 21 | month = 2; 22 | day = 29; 23 | doy = day_of_year(year, month, day); 24 | if (doy) 25 | printf("%d-%d-%d: day %dth of the year.\n", year, month, day, doy); 26 | else 27 | printf("%d-%d-%d: invalid!\n", year, month, day); 28 | 29 | year = 2012; 30 | month = 6; 31 | day = 31; 32 | doy = day_of_year(year, month, day); 33 | if (doy) 34 | printf("%d-%d-%d: day %dth of the year.\n", year, month, day, doy); 35 | else 36 | printf("%d-%d-%d: invalid!\n", year, month, day); 37 | 38 | year = 2012; 39 | yearday = 60; 40 | doy = month_day(year, yearday, &pmonth, &pday); 41 | if (doy) 42 | printf("day %dth of year %d is %d-%d.\n", yearday, year, pmonth, pday); 43 | else 44 | printf("day %dth of year %d do not exsits!\n", yearday, year); 45 | 46 | year = 2012; 47 | yearday = 367; 48 | doy = month_day(year, yearday, &pmonth, &pday); 49 | if (doy) 50 | printf("day %dth of year %d is %d-%d.\n", yearday, year, pmonth, pday); 51 | else 52 | printf("day %dth of year %d do not exsits!\n", yearday, year); 53 | 54 | return 0; 55 | } 56 | 57 | /* day_of_year: set day of year from month & day */ 58 | int day_of_year(int year, int month, int day) 59 | { 60 | int i, leap; 61 | 62 | if (month < 1 || month > 12 || day < 1) 63 | return 0; 64 | 65 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 66 | if (day > *(*(daytab + leap) + month)) 67 | return 0; 68 | for (i = 1; i < month; i++) 69 | day += *(*(daytab + leap) + i); 70 | return day; 71 | } 72 | 73 | /* month_day: set month, day from day of year */ 74 | int month_day(int year, int yearday, int *pmonth, int *pday) 75 | { 76 | int i, leap; 77 | 78 | leap = year % 4 == 0 && year % 100 != 0 || year % 400 == 0; 79 | if (yearday < 1 || yearday > (leap ? 366 : 365)) 80 | return 0; 81 | for (i = 1; yearday > *(*(daytab + leap) + i); i++) 82 | yearday -= *(*(daytab + leap) + i); 83 | *pmonth = i; 84 | *pday = yearday; 85 | return 1; 86 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-10/expr.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-09, Chapter5. 3 | */ 4 | 5 | #include 6 | #include /* for atof() */ 7 | #include 8 | #include 9 | #include 10 | 11 | #define NUMBER '0' /* signal that a number was found */ 12 | 13 | void push(double); 14 | double pop(void); 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | int type, c; 19 | double op2; 20 | 21 | printf("Usage example: expr 2 3 4 + p\n"); 22 | 23 | while (--argc > 0) { 24 | if (!isdigit(c = **++argv) && strlen(*argv) == 1) 25 | type = c; 26 | else 27 | type = NUMBER; 28 | 29 | switch (type) { 30 | case NUMBER: 31 | push(atof(*argv)); 32 | break; 33 | case '+': 34 | push(pop() + pop()); 35 | break; 36 | case 'p': 37 | push(pop() * pop()); 38 | break; 39 | case '-': 40 | op2 = pop(); 41 | push(pop() - op2); 42 | break; 43 | case '/': 44 | op2 = pop(); 45 | if (op2 != 0.0) 46 | push(pop() / op2); 47 | else 48 | printf("error: zero divisor\n"); 49 | break; 50 | case '%': 51 | op2 = pop(); 52 | if (op2 != 0.0) 53 | push(fmod(pop(), op2)); 54 | else 55 | printf("error: zero divisor\n"); 56 | break; 57 | default: 58 | printf("error: unknown command\n"); 59 | break; 60 | } 61 | } 62 | 63 | printf("= %g\n", pop()); 64 | 65 | return 0; 66 | } 67 | 68 | #define MAXVAL 100 /* maximum depth of val stack */ 69 | 70 | int sp = 0; /* next free stack position */ 71 | double val[MAXVAL]; /* value stack */ 72 | 73 | /* push: push f onto value stack */ 74 | void push(double f) 75 | { 76 | if (sp < MAXVAL) 77 | val[sp++] = f; 78 | else 79 | printf("error: stack full, can't push %g\n", f); 80 | } 81 | 82 | /* pop: pop and return top value from stack */ 83 | double pop(void) 84 | { 85 | if (sp > 0) 86 | return val[--sp]; 87 | else { 88 | printf("error: stack empty\n"); 89 | return 0.0; 90 | } 91 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-11/detab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-11, Chapter5. 3 | */ 4 | 5 | #include 6 | #include /* for atoi() */ 7 | 8 | #define MAXLINE 1000 9 | #define DEFAULTTABWIDTH 4 10 | #define MAXTABSTOPS 10 11 | 12 | int getchars(char *s, int max); 13 | void detab(char *s1, char *s2, int tabwidth[]); 14 | 15 | int main(int argc, char **argv) 16 | { 17 | char s1[MAXLINE]; 18 | char s2[MAXLINE]; 19 | 20 | int w[MAXTABSTOPS + 1]; 21 | int i, tab, j; 22 | 23 | if (argc > MAXTABSTOPS) 24 | argc = MAXTABSTOPS; 25 | j = 0; 26 | for (i = 2; i <= argc; ++i) { 27 | tab = atoi(*++argv); 28 | if (tab > 0) 29 | w[j++] = tab; 30 | } 31 | if (i == 2) 32 | w[j++] = DEFAULTTABWIDTH; 33 | w[j] = 0; 34 | 35 | printf("Usage example: detab 2 4 6\n"); 36 | 37 | printf("Input some characters, then press enter:\n"); 38 | while (getchars(s1, MAXLINE) == 0) 39 | ; 40 | 41 | detab(s1, s2, w); 42 | printf("detab result:\n%s\n", s2); 43 | 44 | return 0; 45 | } 46 | 47 | int getchars(char *s, int max) 48 | { 49 | int c, i, l; 50 | 51 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 52 | if (i < max - 1) { 53 | *s++ = c; 54 | l++; 55 | } 56 | *s = '\0'; 57 | 58 | return l; 59 | } 60 | 61 | // copy characters in s1 to s2 and replace tabs with proper number of blanks 62 | void detab(char *s1, char *s2, int w[]) 63 | { 64 | int j, l, c, blanks, k; 65 | 66 | l = 0; 67 | k = 0; 68 | while ((c = *s1++) != '\0') { 69 | if (c == '\t') { 70 | if (w[k] == 0) 71 | k = 0; 72 | blanks = w[k] - l % w[k]; 73 | k++; 74 | for (j = 0; j < blanks; ++j) { 75 | *s2++ = ' '; 76 | l++; 77 | } 78 | } else { 79 | *s2++ = c; 80 | l++; 81 | } 82 | } 83 | *s2 = '\0'; 84 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-11/entab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-11, Chapter5. 3 | */ 4 | 5 | #include 6 | #include /* for atoi() */ 7 | 8 | #define MAXLINE 1000 9 | #define DEFAULTTABWIDTH 8 10 | #define MAXTABSTOPS 10 11 | 12 | int getchars(char *s, int max); 13 | void entab(char *s1, char *s2, int tabwidth[]); 14 | 15 | int main(int argc, char **argv) 16 | { 17 | char s1[MAXLINE]; 18 | char s2[MAXLINE]; 19 | 20 | int w[MAXTABSTOPS + 1]; 21 | int i, tab, j; 22 | 23 | if (argc > MAXTABSTOPS) 24 | argc = MAXTABSTOPS; 25 | j = 0; 26 | for (i = 2; i <= argc; ++i) { 27 | tab = atoi(*++argv); 28 | if (tab > 0) 29 | w[j++] = tab; 30 | } 31 | if (i == 2) 32 | w[j++] = DEFAULTTABWIDTH; 33 | w[j] = 0; 34 | 35 | printf("Usage example: entab 2 4 6\n"); 36 | 37 | printf("Input some characters, then press enter:\n"); 38 | while (getchars(s1, MAXLINE) == 0) 39 | ; 40 | 41 | entab(s1, s2, w); 42 | printf("entab result:\n%s\n", s2); 43 | 44 | return 0; 45 | } 46 | 47 | int getchars(char *s, int max) 48 | { 49 | int c, i, l; 50 | 51 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 52 | if (i < max - 1) { 53 | *s++ = c; 54 | l++; 55 | } 56 | *s = '\0'; 57 | 58 | return l; 59 | } 60 | 61 | // copy characters in s1 to s2 and replace blanks with tabs 62 | void entab(char *s1, char *s2, int w[]) 63 | { 64 | int i, j, c, blanks, k; 65 | int blanksenough; 66 | 67 | i = 0; 68 | k = 0; 69 | while ((c = *s1) != '\0') { 70 | if (c == ' ') { 71 | blanksenough = 1; 72 | if (w[k] == 0) 73 | k = 0; 74 | blanks = w[k] - i % w[k]; 75 | k++; 76 | for (j = 1; j < blanks; ++j){ 77 | if (*(s1 + j) != ' ') { 78 | blanksenough = 0; 79 | break; 80 | } 81 | } 82 | if (blanksenough) { 83 | *s2++ = '\t'; 84 | s1 += blanks; 85 | i += blanks; 86 | } else { 87 | *s2++ = c; 88 | i++; 89 | ++s1; 90 | } 91 | } else { 92 | *s2++ = c; 93 | i++; 94 | ++s1; 95 | } 96 | } 97 | *s2++ = '\0'; 98 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-12/detab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-12, Chapter5. 3 | */ 4 | 5 | #include 6 | #include /* for atoi() */ 7 | 8 | #define MAXLINE 1000 9 | #define DEFAULTSTARTCOL 1 10 | #define DEFAULTTABWIDTH 8 11 | 12 | int getchars(char *s, int max); 13 | void detab(char *s1, char *s2, int startcol, int tabwidth); 14 | 15 | int main(int argc, char **argv) 16 | { 17 | char s1[MAXLINE]; 18 | char s2[MAXLINE]; 19 | 20 | int m, n, m2, n2; 21 | 22 | m = DEFAULTSTARTCOL; 23 | n = DEFAULTTABWIDTH; 24 | 25 | while (--argc > 0) { 26 | argv++; 27 | if (**argv == '-') { 28 | if ((m2 = atoi(++*argv)) > 0) 29 | m = m2; 30 | } else if (**argv == '+') { 31 | if ((n2 = atoi(++*argv)) > 0) 32 | n = n2; 33 | } 34 | } 35 | 36 | printf("Usage example: detab -2 +8\n"); 37 | 38 | printf("Input some characters, then press enter:\n"); 39 | while (getchars(s1, MAXLINE) == 0) 40 | ; 41 | 42 | detab(s1, s2, m, n); 43 | printf("detab result:\n%s\n", s2); 44 | 45 | return 0; 46 | } 47 | 48 | int getchars(char *s, int max) 49 | { 50 | int c, i, l; 51 | 52 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 53 | if (i < max - 1) { 54 | *s++ = c; 55 | l++; 56 | } 57 | *s = '\0'; 58 | 59 | return l; 60 | } 61 | 62 | void detab(char *s1, char *s2, int col, int w) 63 | { 64 | int j, l, c, blanks; 65 | 66 | l = 0; 67 | while ((c = *s1++) != '\0') { 68 | if (c == '\t') { 69 | blanks = w - l % w; 70 | if (l >= col - 1) { 71 | for (j = 0; j < blanks; ++j) { 72 | *s2++ = ' '; 73 | l++; 74 | } 75 | } else { 76 | *s2++ = c; 77 | l += blanks; 78 | } 79 | } else { 80 | *s2++ = c; 81 | l++; 82 | } 83 | } 84 | *s2 = '\0'; 85 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-12/entab.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-12, Chapter5. 3 | */ 4 | 5 | #include 6 | #include /* for atoi() */ 7 | 8 | #define MAXLINE 1000 9 | #define DEFAULTSTARTCOL 1 10 | #define DEFAULTTABWIDTH 8 11 | 12 | int getchars(char *s, int max); 13 | void entab(char *s1, char *s2, int startcol, int tabwidth); 14 | 15 | int main(int argc, char **argv) 16 | { 17 | char s1[MAXLINE]; 18 | char s2[MAXLINE]; 19 | 20 | int m, n, m2, n2; 21 | 22 | m = DEFAULTSTARTCOL; 23 | n = DEFAULTTABWIDTH; 24 | 25 | while (--argc > 0) { 26 | argv++; 27 | if (**argv == '-') { 28 | if ((m2 = atoi(++*argv)) > 0) 29 | m = m2; 30 | } else if (**argv == '+') { 31 | if ((n2 = atoi(++*argv)) > 0) 32 | n = n2; 33 | } 34 | } 35 | 36 | printf("Usage example: entab -2 +8\n"); 37 | 38 | printf("Input some characters, then press enter:\n"); 39 | while (getchars(s1, MAXLINE) == 0) 40 | ; 41 | 42 | entab(s1, s2, m, n); 43 | printf("entab result:\n%s\n", s2); 44 | 45 | return 0; 46 | } 47 | 48 | int getchars(char *s, int max) 49 | { 50 | int c, i, l; 51 | 52 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 53 | if (i < max - 1) { 54 | *s++ = c; 55 | l++; 56 | } 57 | *s = '\0'; 58 | 59 | return l; 60 | } 61 | 62 | void entab(char *s1, char *s2, int col, int w) 63 | { 64 | int i, j, c, blanks; 65 | int blanksenough; 66 | 67 | i = 0; 68 | while ((c = *s1) != '\0') { 69 | if (c == ' ' && i >= col - 1) { 70 | blanksenough = 1; 71 | blanks = w - i % w; 72 | for (j = 1; j < blanks; ++j){ 73 | if (*(s1 + j) != ' ') { 74 | blanksenough = 0; 75 | break; 76 | } 77 | } 78 | if (blanksenough) { 79 | *s2++ = '\t'; 80 | s1 += blanks; 81 | i += blanks; 82 | } else { 83 | *s2++ = c; 84 | i++; 85 | ++s1; 86 | } 87 | } else if (c == '\t') { 88 | *s2++ = c; 89 | i += w - i % w; 90 | ++s1; 91 | } else { 92 | *s2++ = c; 93 | i++; 94 | ++s1; 95 | } 96 | } 97 | *s2++ = '\0'; 98 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-13/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-13, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define ALLOCSIZE 10000 /* size of available space */ 8 | 9 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 10 | static char *allocp = allocbuf; /* next free position */ 11 | 12 | char *alloc(int n) /* return pointer to n characters */ 13 | { 14 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 15 | allocp += n; 16 | return allocp - n; /* old p */ 17 | } else /* not enough room */ 18 | return 0; 19 | } 20 | 21 | void afree(char *p) /* free storage pointed to by p */ 22 | { 23 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 24 | allocp = p; 25 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-13/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-13, Chapter5. 3 | */ 4 | 5 | char *alloc(int); 6 | void afree(char *p); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-13/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-13, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "alloc.h" 8 | #include "lines.h" 9 | 10 | /* readlines: read input lines */ 11 | int readlines(char *lineptr[], int maxlines) 12 | { 13 | int len, nlines; 14 | char *p, line[MAXLEN]; 15 | 16 | nlines = 0; 17 | while ((len = _getline(line, MAXLEN)) > 0) 18 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 19 | return -1; 20 | else { 21 | line[len-1] = '\0'; /* delete newline */ 22 | strcpy(p, line); 23 | lineptr[nlines++] = p; 24 | } 25 | return nlines; 26 | } 27 | 28 | /* writelines: write output lines */ 29 | void writelines(char *lineptr[], int nlines) 30 | { 31 | int i; 32 | for (i = 0; i < nlines; i++) 33 | printf("%s\n", lineptr[i]); 34 | } 35 | 36 | int _getline(char s[], int max) 37 | { 38 | int c, i, l; 39 | 40 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 41 | if (i < max - 1) 42 | s[l++] = c; 43 | if (c == '\n' && l < max - 1) 44 | s[l++] = c; 45 | s[l] = '\0'; 46 | 47 | return l; 48 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-13/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-13, Chapter5. 3 | */ 4 | 5 | #define MAXLINES 50 /* max #lines to be sorted */ 6 | #define MAXLEN 100 /* max length of any input line */ 7 | 8 | int _getline(char *, int); 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-13/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-13, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "lines.h" 8 | 9 | #define DEFAULTTAILNUM 10 10 | 11 | char *lineptr[MAXLINES]; /* pointers to text lines */ 12 | 13 | int main(int argc, char **argv) 14 | { 15 | int nlines; /* number of input lines read */ 16 | int tailnum, p; 17 | 18 | tailnum = DEFAULTTAILNUM; 19 | if (argc > 1 && **++argv == '-') { 20 | if ((p = atoi(++(*argv))) > 0) 21 | tailnum = p; 22 | } 23 | 24 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 25 | if (nlines < tailnum) 26 | tailnum = nlines; 27 | writelines(lineptr + nlines - tailnum, tailnum); 28 | return 0; 29 | } else { 30 | printf("error: input too big\n"); 31 | return 1; 32 | } 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define ALLOCSIZE 10000 /* size of available space */ 8 | 9 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 10 | static char *allocp = allocbuf; /* next free position */ 11 | 12 | char *alloc(int n) /* return pointer to n characters */ 13 | { 14 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 15 | allocp += n; 16 | return allocp - n; /* old p */ 17 | } else /* not enough room */ 18 | return 0; 19 | } 20 | 21 | void afree(char *p) /* free storage pointed to by p */ 22 | { 23 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 24 | allocp = p; 25 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | char *alloc(int); 6 | void afree(char *p); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "alloc.h" 8 | #include "lines.h" 9 | 10 | /* readlines: read input lines */ 11 | int readlines(char *lineptr[], int maxlines) 12 | { 13 | int len, nlines; 14 | char *p, line[MAXLEN]; 15 | 16 | nlines = 0; 17 | while ((len = _getline(line, MAXLEN)) > 0) 18 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 19 | return -1; 20 | else { 21 | line[len-1] = '\0'; /* delete newline */ 22 | strcpy(p, line); 23 | lineptr[nlines++] = p; 24 | } 25 | return nlines; 26 | } 27 | 28 | /* writelines: write output lines */ 29 | void writelines(char *lineptr[], int nlines) 30 | { 31 | int i; 32 | for (i = 0; i < nlines; i++) 33 | printf("%s\n", lineptr[i]); 34 | } 35 | 36 | int _getline(char s[], int max) 37 | { 38 | int c, i, l; 39 | 40 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 41 | if (i < max - 1) 42 | s[l++] = c; 43 | if (c == '\n' && l < max - 1) 44 | s[l++] = c; 45 | s[l] = '\0'; 46 | 47 | return l; 48 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #define MAXLINES 50 /* max #lines to be sorted */ 6 | #define MAXLEN 100 /* max length of any input line */ 7 | 8 | int _getline(char *, int); 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #include 6 | #include "string.h" 7 | #include "lines.h" 8 | #include "qsort.h" 9 | #include "numcmp.h" 10 | 11 | char *lineptr[MAXLINES]; /* pointers to text lines */ 12 | 13 | int main(int argc, char **argv) 14 | { 15 | int nlines; /* number of input lines read */ 16 | int numeric = 0; /* 1 if numeric sort */ 17 | int order = 1; /* 1 if sorting in increasing order*/ 18 | 19 | int c; 20 | while (--argc > 0 && *(*++argv) == '-') { 21 | while ((c = *++(*argv)) != '\0') { 22 | switch (c) { 23 | case 'n': 24 | numeric = 1; 25 | break; 26 | case 'r': 27 | order = 0; 28 | break; 29 | default: 30 | break; 31 | } 32 | } 33 | } 34 | 35 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 36 | qsort((void**) lineptr, 0, nlines-1, 37 | (int (*)(void*,void*))(numeric ? numcmp : strcmp), order); 38 | writelines(lineptr, nlines); 39 | return 0; 40 | } else { 41 | printf("error: input too big to sort\n"); 42 | return 1; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/numcmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* numcmp: compare s1 and s2 numerically */ 8 | int numcmp(char *s1, char *s2) 9 | { 10 | double v1, v2; 11 | 12 | v1 = atof(s1); 13 | v2 = atof(s2); 14 | if (v1 < v2) 15 | return -1; 16 | else if (v1 > v2) 17 | return 1; 18 | else 19 | return 0; 20 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/numcmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | int numcmp(char *, char *); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/qsort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* qsort: sort v[left]...v[right] into increasing/decreasing order */ 8 | void qsort(void *v[], int left, int right, int (*comp)(void *, void *), int order) 9 | { 10 | int i, last; 11 | void swap(void *v[], int, int); 12 | 13 | if (left >= right) /* do nothing if array contains */ 14 | return; /* fewer than two elements */ 15 | swap(v, left, (left + right)/2); 16 | last = left; 17 | for (i = left+1; i <= right; i++) 18 | if (order && (*comp)(v[i], v[left]) < 0) 19 | swap(v, ++last, i); 20 | else if (!order && (*comp)(v[i], v[left]) > 0) 21 | swap(v, ++last, i); 22 | swap(v, left, last); 23 | qsort(v, left, last-1, comp, order); 24 | qsort(v, last+1, right, comp, order); 25 | } 26 | 27 | /* swap: interchange v[i] and v[j] */ 28 | void swap(void *v[], int i, int j) 29 | { 30 | void *temp; 31 | 32 | temp = v[i]; 33 | v[i] = v[j]; 34 | v[j] = temp; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-14/qsort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-14, Chapter5. 3 | */ 4 | 5 | void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *), int order); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define ALLOCSIZE 10000 /* size of available space */ 8 | 9 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 10 | static char *allocp = allocbuf; /* next free position */ 11 | 12 | char *alloc(int n) /* return pointer to n characters */ 13 | { 14 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 15 | allocp += n; 16 | return allocp - n; /* old p */ 17 | } else /* not enough room */ 18 | return 0; 19 | } 20 | 21 | void afree(char *p) /* free storage pointed to by p */ 22 | { 23 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 24 | allocp = p; 25 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | char *alloc(int); 6 | void afree(char *p); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/cmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | /* numcmp: compare s1 and s2 numerically */ 9 | int numcmp(char *s1, char *s2) 10 | { 11 | double v1, v2; 12 | 13 | v1 = atof(s1); 14 | v2 = atof(s2); 15 | if (v1 < v2) 16 | return -1; 17 | else if (v1 > v2) 18 | return 1; 19 | else 20 | return 0; 21 | } 22 | 23 | int strcmpignore(char *s1, char *s2) 24 | { 25 | for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) 26 | if (*s1 == '\0') 27 | return 0; 28 | return tolower(*s1) - tolower(*s2); 29 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/cmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | int numcmp(char *, char *); 6 | int strcmpignore(char *, char *); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "alloc.h" 8 | #include "lines.h" 9 | 10 | /* readlines: read input lines */ 11 | int readlines(char *lineptr[], int maxlines) 12 | { 13 | int len, nlines; 14 | char *p, line[MAXLEN]; 15 | 16 | nlines = 0; 17 | while ((len = _getline(line, MAXLEN)) > 0) 18 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 19 | return -1; 20 | else { 21 | line[len-1] = '\0'; /* delete newline */ 22 | strcpy(p, line); 23 | lineptr[nlines++] = p; 24 | } 25 | return nlines; 26 | } 27 | 28 | /* writelines: write output lines */ 29 | void writelines(char *lineptr[], int nlines) 30 | { 31 | int i; 32 | for (i = 0; i < nlines; i++) 33 | printf("%s\n", lineptr[i]); 34 | } 35 | 36 | int _getline(char s[], int max) 37 | { 38 | int c, i, l; 39 | 40 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 41 | if (i < max - 1) 42 | s[l++] = c; 43 | if (c == '\n' && l < max - 1) 44 | s[l++] = c; 45 | s[l] = '\0'; 46 | 47 | return l; 48 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #define MAXLINES 50 /* max #lines to be sorted */ 6 | #define MAXLEN 100 /* max length of any input line */ 7 | 8 | int _getline(char *, int); 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #include 6 | #include "string.h" 7 | #include "lines.h" 8 | #include "qsort.h" 9 | #include "cmp.h" 10 | 11 | char *lineptr[MAXLINES]; /* pointers to text lines */ 12 | 13 | int main(int argc, char **argv) 14 | { 15 | int nlines; /* number of input lines read */ 16 | int numeric = 0; /* 1 if numeric sort */ 17 | int order = 1; /* 1 if sorting in increasing order */ 18 | int ignorecase = 0; /* 1 if case insensitive */ 19 | int c; 20 | 21 | while (--argc > 0 && *(*++argv) == '-') { 22 | while ((c = *++(*argv)) != '\0') { 23 | switch (c) { 24 | case 'n': 25 | numeric = 1; 26 | break; 27 | case 'r': 28 | order = 0; 29 | break; 30 | case 'f': 31 | ignorecase = 1; 32 | break; 33 | default: 34 | break; 35 | } 36 | } 37 | } 38 | 39 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 40 | qsort((void**) lineptr, 0, nlines-1, 41 | (int (*)(void*,void*))(numeric ? numcmp : (ignorecase ? strcmpignore : strcmp)), order); 42 | writelines(lineptr, nlines); 43 | return 0; 44 | } else { 45 | printf("error: input too big to sort\n"); 46 | return 1; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/qsort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* qsort: sort v[left]...v[right] into increasing/decreasing order */ 8 | void qsort(void *v[], int left, int right, int (*comp)(void *, void *), int order) 9 | { 10 | int i, last; 11 | void swap(void *v[], int, int); 12 | 13 | if (left >= right) /* do nothing if array contains */ 14 | return; /* fewer than two elements */ 15 | swap(v, left, (left + right)/2); 16 | last = left; 17 | for (i = left+1; i <= right; i++) 18 | if (order && (*comp)(v[i], v[left]) < 0) 19 | swap(v, ++last, i); 20 | else if (!order && (*comp)(v[i], v[left]) > 0) 21 | swap(v, ++last, i); 22 | swap(v, left, last); 23 | qsort(v, left, last-1, comp, order); 24 | qsort(v, last+1, right, comp, order); 25 | } 26 | 27 | /* swap: interchange v[i] and v[j] */ 28 | void swap(void *v[], int i, int j) 29 | { 30 | void *temp; 31 | 32 | temp = v[i]; 33 | v[i] = v[j]; 34 | v[j] = temp; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-15/qsort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-15, Chapter5. 3 | */ 4 | 5 | void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *), int order); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/alloc.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | #define ALLOCSIZE 10000 /* size of available space */ 8 | 9 | static char allocbuf[ALLOCSIZE]; /* storage for alloc */ 10 | static char *allocp = allocbuf; /* next free position */ 11 | 12 | char *alloc(int n) /* return pointer to n characters */ 13 | { 14 | if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ 15 | allocp += n; 16 | return allocp - n; /* old p */ 17 | } else /* not enough room */ 18 | return 0; 19 | } 20 | 21 | void afree(char *p) /* free storage pointed to by p */ 22 | { 23 | if (p >= allocbuf && p < allocbuf + ALLOCSIZE) 24 | allocp = p; 25 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/alloc.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | char *alloc(int); 6 | void afree(char *p); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/cmp.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* numcmp: compare s1 and s2 numerically */ 8 | int numcmp(char *s1, char *s2) 9 | { 10 | double v1, v2; 11 | 12 | v1 = atof(s1); 13 | v2 = atof(s2); 14 | if (v1 < v2) 15 | return -1; 16 | else if (v1 > v2) 17 | return 1; 18 | else 19 | return 0; 20 | } 21 | 22 | int strcmpignore(char *s1, char *s2) 23 | { 24 | for (; tolower(*s1) == tolower(*s2); ++s1, ++s2) 25 | if (*s1 == '\0') 26 | return 0; 27 | return tolower(*s1) - tolower(*s2); 28 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/cmp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | int numcmp(char *, char *); 6 | int strcmpignore(char *, char *); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/lines.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "alloc.h" 8 | #include "lines.h" 9 | 10 | /* readlines: read input lines */ 11 | int readlines(char *lineptr[], int maxlines) 12 | { 13 | int len, nlines; 14 | char *p, line[MAXLEN]; 15 | 16 | nlines = 0; 17 | while ((len = _getline(line, MAXLEN)) > 0) 18 | if (nlines >= maxlines || (p = alloc(len)) == NULL) 19 | return -1; 20 | else { 21 | line[len-1] = '\0'; /* delete newline */ 22 | strcpy(p, line); 23 | lineptr[nlines++] = p; 24 | } 25 | return nlines; 26 | } 27 | 28 | /* writelines: write output lines */ 29 | void writelines(char *lineptr[], int nlines) 30 | { 31 | int i; 32 | for (i = 0; i < nlines; i++) 33 | printf("%s\n", lineptr[i]); 34 | } 35 | 36 | int _getline(char s[], int max) 37 | { 38 | int c, i, l; 39 | 40 | for (i = 0, l = 0; (c = getchar()) != EOF && c != '\n'; ++i) 41 | if (i < max - 1) 42 | s[l++] = c; 43 | if (c == '\n' && l < max - 1) 44 | s[l++] = c; 45 | s[l] = '\0'; 46 | 47 | return l; 48 | } -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/lines.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #define MAXLINES 50 /* max #lines to be sorted */ 6 | #define MAXLEN 100 /* max length of any input line */ 7 | 8 | int _getline(char *, int); 9 | int readlines(char *lineptr[], int nlines); 10 | void writelines(char *lineptr[], int nlines); -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/main.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "lines.h" 9 | #include "qsort.h" 10 | #include "cmp.h" 11 | 12 | int strcompare(char *s1, char *s2); 13 | int isdirectory(char *s); 14 | 15 | char *lineptr[MAXLINES]; /* pointers to text lines */ 16 | 17 | int ignorecase = 0; /* 1 if case insensitive */ 18 | int directory = 0; /* 1 if sorting in directory order */ 19 | 20 | int main(int argc, char **argv) 21 | { 22 | int nlines; /* number of input lines read */ 23 | int numeric = 0; /* 1 if numeric sort */ 24 | int order = 1; /* 1 if sorting in increasing order*/ 25 | 26 | int c, i; 27 | char *t; 28 | 29 | while (--argc > 0 && *(*++argv) == '-') { 30 | while ((c = *++(*argv)) != '\0') { 31 | switch (c) { 32 | case 'n': 33 | numeric = 1; 34 | break; 35 | case 'r': 36 | order = 0; 37 | break; 38 | case 'f': 39 | ignorecase = 1; 40 | break; 41 | case 'd': 42 | directory = 1; 43 | break; 44 | default: 45 | break; 46 | } 47 | } 48 | } 49 | 50 | if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { 51 | qsort((void**) lineptr, 0, nlines-1, 52 | (int (*)(void*,void*))(numeric ? numcmp : strcompare), order); 53 | writelines(lineptr, nlines); 54 | return 0; 55 | } else { 56 | printf("error: input too big to sort\n"); 57 | return 1; 58 | } 59 | } 60 | 61 | int strcompare(char *s1, char *s2) 62 | { 63 | if (directory) { 64 | while(*s1 != '\0' && !isdirectory(s1)) 65 | s1++; 66 | while(*s2 != '\0' && !isdirectory(s2)) 67 | s2++; 68 | if (ignorecase) { 69 | while (tolower(*s1) == tolower(*s2)) { 70 | if (*s1 == '\0') 71 | return 0; 72 | s1++; 73 | s2++; 74 | while(*s1 != '\0' && !isdirectory(s1)) 75 | s1++; 76 | while(*s2 != '\0' && !isdirectory(s2)) 77 | s2++; 78 | } 79 | return tolower(*s1) - tolower(*s2); 80 | } else { 81 | printf("dsdsd\n"); 82 | while (*s1 == *s2) { 83 | if (*s1 == '\0') 84 | return 0; 85 | s1++; 86 | s2++; 87 | while(*s1 != '\0' && !isdirectory(s1)) 88 | s1++; 89 | while(*s2 != '\0' && !isdirectory(s2)) 90 | s2++; 91 | } 92 | return *s1 - *s2; 93 | } 94 | } else { 95 | if (ignorecase) { 96 | return strcmpignore(s1, s2); 97 | } else { 98 | return strcmp(s1, s2); 99 | } 100 | } 101 | } 102 | 103 | int isdirectory(char *s) 104 | { 105 | return isdigit(*s) || isalpha(*s) || isspace(*s); 106 | } 107 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/qsort.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | #include 6 | 7 | /* qsort: sort v[left]...v[right] into increasing/decreasing order */ 8 | void qsort(void *v[], int left, int right, int (*comp)(void *, void *), int order) 9 | { 10 | int i, last; 11 | void swap(void *v[], int, int); 12 | 13 | if (left >= right) /* do nothing if array contains */ 14 | return; /* fewer than two elements */ 15 | swap(v, left, (left + right)/2); 16 | last = left; 17 | for (i = left+1; i <= right; i++) 18 | if (order && (*comp)(v[i], v[left]) < 0) 19 | swap(v, ++last, i); 20 | else if (!order && (*comp)(v[i], v[left]) > 0) 21 | swap(v, ++last, i); 22 | swap(v, left, last); 23 | qsort(v, left, last-1, comp, order); 24 | qsort(v, last+1, right, comp, order); 25 | } 26 | 27 | /* swap: interchange v[i] and v[j] */ 28 | void swap(void *v[], int i, int j) 29 | { 30 | void *temp; 31 | 32 | temp = v[i]; 33 | v[i] = v[j]; 34 | v[j] = temp; 35 | } 36 | -------------------------------------------------------------------------------- /Chapter5/Exercise 5-16/qsort.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Solution for Exercise 5-16, Chapter5. 3 | */ 4 | 5 | void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *), int order); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | the-c-programming-language-second-edition-solutions 2 | =================================================== 3 | 4 | Solutions for all exercises in the book "The C Programming Language - Second Edition"(referred to as K&R, after its authors' initials) by Brian W. Kernighan and Dennis M. Ritchie. --------------------------------------------------------------------------------