├── ch02 ├── README.md └── projects │ ├── 01.c │ ├── 04.c │ ├── 02-03.c │ ├── 06.c │ ├── 05.c │ ├── 07.c │ └── 08.c ├── ch10 ├── 7_segment_display.png ├── README.md └── projects │ ├── 03-05.c │ ├── 02.c │ ├── stack_char.h │ ├── stack_int.h │ ├── poker_02.h │ ├── poker_01.h │ ├── 06.c │ ├── stack_char.c │ ├── 01.c │ └── stack_int.c ├── ch05 ├── README.md ├── exercises │ ├── 05-06.c │ ├── 04.c │ ├── 10.c │ └── 03.c └── projects │ ├── 01.c │ ├── 07.c │ ├── 04.c │ ├── 02.c │ ├── 10.c │ ├── 05.c │ ├── 09.c │ └── 03.c ├── ch03 ├── exercises │ ├── 01.c │ ├── 04.c │ ├── 05.c │ ├── 06.c │ ├── 02.c │ └── 03.c ├── projects │ ├── 01.c │ ├── 04.c │ ├── 06.c │ ├── 03.c │ ├── 02.c │ └── 05.c └── README.md ├── ch06 ├── exercises │ ├── 13.c │ ├── 08.c │ ├── 03.c │ └── 12.c ├── projects │ ├── create_files.sh │ ├── 01.c │ ├── gcd.h │ ├── 03.c │ ├── 07.c │ ├── 02.c │ ├── gcd.c │ ├── 06.c │ ├── 05.c │ ├── 11.c │ ├── 12.c │ ├── 09.c │ ├── 08.c │ └── 04.c └── README.md ├── ch07 ├── projects │ ├── create_files.sh │ ├── 06.c │ ├── 03.c │ ├── 01.c │ ├── gcd.h │ ├── 10.c │ ├── 11.c │ ├── 09.c │ ├── 02.c │ ├── 12.c │ ├── 13.c │ ├── 05.c │ ├── 04.c │ └── 14.c └── README.md ├── ch04 ├── exercises │ └── 02.c ├── projects │ ├── 03.c │ ├── 01-02.c │ ├── 04.c │ ├── 06.c │ └── 05.c └── README.md ├── ch08 ├── projects │ ├── 04.c │ ├── 01.c │ ├── 07.c │ ├── 05.c │ ├── 13.c │ ├── 02-03.c │ ├── 15.c │ ├── 14.c │ ├── 16.c │ ├── 11.c │ ├── 12.c │ ├── 17.c │ ├── 06.c │ └── 08.c ├── exercises │ ├── 11.c │ └── 10.c ├── deal.c └── README.md ├── ch16 ├── README.md ├── readline.c └── readline.h ├── ch09 ├── projects │ ├── 06.c │ ├── 07.c │ ├── 02.c │ ├── 04.c │ ├── 01.c │ ├── 08.c │ └── 05.c └── README.md ├── .gitignore ├── ch12 ├── projects │ ├── 01_03.c │ ├── 07.c │ ├── 05.c │ ├── 02_04.c │ └── 06.c └── README.md ├── textbook_code_snippets ├── pun.c ├── pun2.c ├── stack.h ├── countdown.c ├── length2.c ├── tprintf.c ├── tcasemap.c ├── length.c ├── readline.c ├── square2.c ├── numdigits.c ├── stackADT.h ├── stackADT2.h ├── reverse.c ├── sum.c ├── square.c ├── xor.c ├── reverse3.c ├── sum2.c ├── celsius.c ├── square3.c ├── word.c ├── addfrac.c ├── canopen.c ├── dweight.c ├── average.c ├── quadratic.c ├── word.h ├── readline.h ├── trand.c ├── reverse2.c ├── prime.c ├── repdigit.c ├── dweight2.c ├── justify.c ├── tsetjmp.c ├── planet.c ├── stackclient.c ├── upc.c ├── maxmin.c ├── fcopy.c ├── stack1.c ├── tsignal.c ├── broker.c ├── tclassify.c ├── invclear.c ├── interest.c ├── datetime.c ├── deal.c ├── stack2.c ├── checking.c ├── stackADT.c ├── date.c ├── viewmemory.c ├── line.c ├── qsort.c ├── tnumconv.c ├── tabulate.c ├── stackADT2.c ├── remind.c ├── stackADT3.c ├── line.h └── remind2.c ├── ch11 ├── README.md ├── exercises │ ├── 05.c │ ├── 08.c │ ├── 06.c │ └── 07.c └── projects │ ├── 01.c │ ├── 04.c │ ├── 03.c │ └── poker.h ├── README.md └── ch13 └── README.md /ch02/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 2: C Fundamentals 2 | 3 | Programming projects -------------------------------------------------------------------------------- /ch10/7_segment_display.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/m1nhtu99-hoan9/c-programming-a-modern-approach/HEAD/ch10/7_segment_display.png -------------------------------------------------------------------------------- /ch05/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 5: Selection Statements 2 | 3 | ## Exercise Notes 4 | 5 | - The most significant projects: [Project 06](./projects/06.c); [Project 08](./projects/08.c) -------------------------------------------------------------------------------- /ch03/exercises/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("%6d,%4d\n", 86, 1040); 5 | printf("%12.5e\n", 30.253); 6 | printf("%.4f\n", 83.162); 7 | printf("%-6.2g\n", .000000009979); 8 | } -------------------------------------------------------------------------------- /ch06/exercises/13.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int n, m; 6 | 7 | for (n = 0; m > 0; n++, m /= 2) 8 | { 9 | } 10 | 11 | printf("n = %d; m = %d\n", n, m); 12 | return 0; 13 | } -------------------------------------------------------------------------------- /ch06/exercises/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | for (int i = 10; i >= 1; i /= 2) 6 | printf("%d", i++); 7 | 8 | return 0; 9 | } 10 | 11 | /* Output: Infinite loop 12 | 1053211111111111111... 13 | */ -------------------------------------------------------------------------------- /ch02/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf(" *\n"); 6 | printf(" * \n"); 7 | printf(" * \n"); 8 | printf("* * \n"); 9 | printf(" * * \n"); 10 | printf(" * \n"); 11 | } 12 | -------------------------------------------------------------------------------- /ch06/exercises/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i, j; 6 | 7 | for (i = 5, j = i - 1; i > 0, j > 0; --i, j = i - 1) 8 | printf("%d", i); 9 | 10 | return 0; 11 | } 12 | 13 | /* Output: 14 | 5432% 15 | */ -------------------------------------------------------------------------------- /ch03/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int m, d, y; 5 | printf("Enter a date (mm/dd/yyyy): "); 6 | scanf("%d/%d/%d", &d, &m, &y); 7 | printf("You entered the date %4d%.2d%2d\n", y, m, d); 8 | 9 | return 0; 10 | } -------------------------------------------------------------------------------- /ch06/projects/create_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in $(seq -f "%02g" 1 12) 4 | do 5 | touch $i.c 6 | echo "#include " >> $i.c 7 | echo "" >> $i.c 8 | echo "int main()" >> $i.c 9 | echo "{" >> $i.c 10 | echo "}" >> $i.c 11 | done -------------------------------------------------------------------------------- /ch07/projects/create_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for i in $(seq -f "%02g" 1 15) 4 | do 5 | touch $i.c 6 | echo "#include " >> $i.c 7 | echo "" >> $i.c 8 | echo "int main()" >> $i.c 9 | echo "{" >> $i.c 10 | echo "}" >> $i.c 11 | done -------------------------------------------------------------------------------- /ch05/exercises/05-06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int n; 6 | 7 | n = 0; 8 | if (n >= 1 <= 10) 9 | printf("n is between 1 and 10\n"); // logically wrong 10 | 11 | n = 5; 12 | printf("%d\n", n == 1 - 10); 13 | 14 | return 0; 15 | } -------------------------------------------------------------------------------- /ch02/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | float amount, result, tax = 5.0f / 100.0f; 6 | 7 | printf("Enter an amount: "); 8 | scanf("%f", &amount); 9 | 10 | result = (1 + tax) * amount; 11 | printf("With tax added: $%.2f\n", result); 12 | 13 | return 0; 14 | } -------------------------------------------------------------------------------- /ch05/exercises/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i, j; 6 | 7 | printf("Input two integers: "); 8 | scanf("%d %d", &i, &j); 9 | 10 | printf( 11 | "Result of the comparison of i to j: %d\n", 12 | (i < j) ? -1 : ((i == j) ? 0 : 1) 13 | ); 14 | 15 | return 0; 16 | } -------------------------------------------------------------------------------- /ch05/exercises/10.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i; 6 | 7 | i = 1; 8 | switch (i % 3) { 9 | case 0: printf("zero"); 10 | case 1: printf("one"); 11 | case 2: printf("two"); 12 | } 13 | printf("\n"); 14 | 15 | return 0; 16 | } 17 | 18 | /* Output: "onetwo" */ -------------------------------------------------------------------------------- /ch03/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int prefix, body1, body2; 6 | 7 | printf("Enter phone number [(xxx) xxx-xxxx]: "); 8 | scanf("(%3d) %3d-%4d", &prefix, &body1, &body2); 9 | 10 | printf("You entered %3d.%3d.%4d\n", prefix, body1, body2); 11 | 12 | return 0; 13 | } -------------------------------------------------------------------------------- /ch06/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | float max = 0, n; 6 | 7 | while (n) { 8 | printf("Enter a number: "); 9 | scanf("%f", &n); 10 | 11 | if (n > max) max = n; 12 | } 13 | 14 | printf("The largest number entered was %.2f\n", max); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /ch04/exercises/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int i, j; 6 | 7 | printf("Input 2 positive integers: "); 8 | scanf("%d%d", &i, &j); 9 | 10 | printf("(-i)/j = %d\n", -i / j); 11 | printf("-(i/j) = %d\n", -(i / j)); 12 | 13 | /* CONCLUSION: 14 | These two result values are the same 15 | */ 16 | 17 | return 0; 18 | } -------------------------------------------------------------------------------- /ch03/exercises/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | After the `scanf` call, `x` will be 10, `i` will be 0.3 and `y` will be 5 5 | */ 6 | 7 | int main() 8 | { 9 | int i, j; 10 | float x; 11 | 12 | printf("Please input: "); 13 | scanf("%d%f%d", &i, &x, &j); 14 | printf("first one = %d; second one = %f; third one = %d\n", i, x, j); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /ch03/exercises/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | After the `scanf` call, `x` will be 12.3, `i` will be 45 and `y` will be 0.6 5 | */ 6 | 7 | int main() 8 | { 9 | float x, y; 10 | int i; 11 | 12 | printf("Please input: "); 13 | scanf("%f%d%f", &x, &i, &y); 14 | printf("first one = %f; second one = %d; third one = %f\n", x, i, y); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /ch06/projects/gcd.h: -------------------------------------------------------------------------------- 1 | /** Euclid's Algorithm to Find the Greatest Common Divisor (GCD) 2 | @return when this procedure ends, *a hold the GCD value 3 | */ 4 | void process_find_gcd(int *const a, int *const b); 5 | 6 | /** Pure Function Implementing Euclid's Algorithm Recursively to 7 | * Find the Greatest Common Divisor (GCD) 8 | */ 9 | const int find_gcd(int a, int b); 10 | -------------------------------------------------------------------------------- /ch06/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gcd.h" 3 | 4 | /* Ask the user to input a fraction, return the fraction to lowest terms */ 5 | 6 | int main() 7 | { 8 | int m, n, gcd; 9 | printf("Enter the fraction: "); 10 | scanf("%d/%d", &m, &n); 11 | 12 | gcd = find_gcd(m, n); 13 | 14 | printf("In lowest terms: %d/%d\n", m / gcd, n / gcd); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /ch07/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("`int` size: %zu\n", sizeof(int)); 6 | printf("`short` size: %zu\n", sizeof(short)); 7 | printf("`long` size: %zu\n", sizeof(long)); 8 | printf("`float` size: %zu\n", sizeof(float)); 9 | printf("`double` size: %zu\n", sizeof(double)); 10 | printf("`long double` size: %zu\n", sizeof(long double)); 11 | 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /ch05/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Calculate the number of digits of a input integer */ 4 | 5 | int main () { 6 | int n, i = 0; 7 | 8 | printf("Enter a nummber: "); 9 | scanf("%d", &n); 10 | // `printf` this line first before `n` is mutated 11 | printf("The number %d has ", n); 12 | 13 | while (n != 0) { 14 | ++i; 15 | n /= 10; 16 | } 17 | printf("%d digits\n", i); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /ch06/exercises/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Prime-testing */ 4 | 5 | int main() 6 | { 7 | int n, d; 8 | 9 | printf("Input an integer N: "); 10 | scanf("%d", &n); 11 | 12 | for (d = 2; d * d <= n; d++) 13 | { 14 | if (n % d == 0) 15 | break; 16 | } 17 | 18 | if (d * d < n) 19 | printf("%d is divisible by %d.\n", n, d); 20 | else 21 | printf("%d is a prime.\n", n); 22 | 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /ch08/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* modified version of `reverse.c` */ 4 | 5 | int main() 6 | { 7 | int a[10], i; 8 | int len = (int)(sizeof(a) / sizeof(a[0])); 9 | 10 | printf("Enter %d numbers: ", len); 11 | for (i = 0; i < len; i++) 12 | scanf("%d", &a[i]); 13 | 14 | printf("In reverse order:"); 15 | for (i = len - 1; i >= 0; i--) 16 | printf(" %d", a[i]); 17 | printf("\n"); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /ch03/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 3: Formatted Input/Output 2 | 3 | ## Reading Notes 4 | 5 | ### Conversion specifications 6 | - General: `%m.pX` or `%-m.pX` 7 | - Side notes: for exponential notation, see [`./exercises/02.c`](./exercises/02.c) 8 | 9 | ### Trivias 10 | - To print a `%` character, type `%%` 11 | 12 | ## Relating Chapters 13 | 14 | Chapter 22 15 | 16 | ## Exercises Notes 17 | 18 | - The most challenging prolem: [Project 05](./projects/05.c) 19 | -------------------------------------------------------------------------------- /ch08/exercises/11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DIMENSION 8 5 | 6 | int main() 7 | { 8 | char checker_board[DIMENSION][DIMENSION] = {}; 9 | 10 | for (int i = 0; i < DIMENSION; i++) 11 | { 12 | for (int j = 0; j < DIMENSION; j++) 13 | { 14 | checker_board[i][j] = ((i + j) % 2 == 0) ? 'B' : 'R'; 15 | printf("%c ", checker_board[i][j]); 16 | } 17 | printf("\n"); 18 | } 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /ch06/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int i, n, odd, square; 6 | 7 | printf("This program prints a table of squares.\n"); 8 | printf("Enter a number of entries in table: "); 9 | scanf("%d", &n); 10 | 11 | for (odd = 3, 12 | square = 1, 13 | i = 1; 14 | i <= n; i++, square += odd, odd += 2) 15 | // because (n+1)^2 = (n^2) + (2n + 1) 16 | printf("%5d%8d\n", i, square); 17 | 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /ch16/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 16: Structures, Unions and Enumerations 2 | 3 | ## Reading Notes 4 | 5 | - Initialise new struct instance: 6 | - _Designated Initialisers_ 7 | - _Compound Literals_ to create structs on the fly 8 | - Initialise an array of structs: 9 | 10 | - Example: 11 | 12 | ```C 13 | struct Part inventory[10] = { [0].number = 528, [0].on_hand = 10, [0].name[0] = '\0' } 14 | ``` 15 | 16 | ### Related Chapters 17 | 18 | ## Exercising Notes 19 | -------------------------------------------------------------------------------- /ch03/projects/06.c: -------------------------------------------------------------------------------- 1 | /* addfrac.c modified */ 2 | #include 3 | 4 | int main(void) 5 | { 6 | int nums[2], denoms[2], result_num, result_denom; 7 | 8 | printf("Enter two fractions seperated by a plus sign: "); 9 | scanf("%d/%d+%d/%d", &nums[0], &denoms[0], &nums[1], &denoms[1]); 10 | 11 | result_num = nums[0] * denoms[1] + nums[1] * denoms[0]; 12 | result_denom = denoms[0] * denoms[1]; 13 | 14 | printf("The sum is %d/%d\n", result_num, result_denom); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /ch04/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Using a `scanf` trick to reverse a 3-digit number */ 4 | 5 | int main() 6 | { 7 | int digits[3], i = 0; 8 | 9 | printf("Please input a 3-digit number: "); 10 | for (; i < 3; i++) { 11 | scanf("%1d", &digits[i]); 12 | } 13 | printf("\n"); 14 | 15 | printf("The reversed number is: "); 16 | // print these 3 digits in reverse 17 | for (i = 2; i >= 0; i--) { 18 | printf("%d", digits[i]); 19 | } 20 | printf("\n"); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /ch07/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | double n, sum = 0.0; 6 | 7 | printf("This program sums a series of doubles.\n"); 8 | printf("Enter number [0 to terminate]: "); 9 | scanf("%lf", &n); 10 | 11 | while (n != 0.0) { 12 | sum += n; 13 | printf("Enter number [0 to terminate]: "); 14 | scanf("%lf", &n); 15 | } 16 | printf("\n"); 17 | 18 | // "%f" can be used to `printf` both float and double 19 | printf("The sum is: %f\n", sum); 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /ch16/readline.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "readline.h" 4 | 5 | int read_line(char str[], int n) 6 | { 7 | int ch, i = 0; 8 | 9 | // skip all the leading white spaces 10 | for (;;) 11 | { 12 | if (!isspace(ch = getchar())) 13 | break; 14 | } 15 | 16 | while (ch != '\n' && ch != EOF) 17 | // read input and store them into `str` 18 | { 19 | if (i < n) 20 | str[i++] = ch; 21 | ch = getchar(); 22 | } 23 | 24 | str[i] = '\0'; 25 | return i; 26 | } -------------------------------------------------------------------------------- /ch03/exercises/06.c: -------------------------------------------------------------------------------- 1 | /* addfrac.c modified */ 2 | #include 3 | 4 | int main(void) 5 | { 6 | int num1, denom1, num2, denom2, result_num, result_denom; 7 | 8 | printf("Enter first fraction: "); 9 | scanf("%d / %d", &num1, &denom1); 10 | 11 | printf("Enter second fraction: "); 12 | scanf("%d / %d", &num2, &denom2); 13 | 14 | result_num = num1 * denom2 + num2 * denom1; 15 | result_denom = denom1 * denom2; 16 | 17 | printf("The sum is %d/%d\n", result_num, result_denom); 18 | 19 | return 0; 20 | } -------------------------------------------------------------------------------- /ch06/projects/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "gcd.h" 3 | 4 | /* to compile, add both this file, `gcd.c` and `gcd.h` to list of executables */ 5 | 6 | int main() 7 | { 8 | int m, n; 9 | 10 | printf("Enter two integers: "); 11 | scanf("%d%d", &m, &n); 12 | 13 | if (n == 0) 14 | { 15 | printf("Invalid input! \n"); 16 | return 1; 17 | } 18 | else 19 | { 20 | process_find_gcd(&m, &n); 21 | printf("Greatest common divisor: %d\n", m); 22 | return 0; 23 | } 24 | } 25 | 26 | 27 | -------------------------------------------------------------------------------- /ch02/projects/02-03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // directive for declaring global constant 5 | #define PI acos(-1.0) 6 | 7 | int main() 8 | { 9 | float r, coefficient = 4.0f / 3.0f; 10 | 11 | printf("Enter the radius: "); 12 | scanf("%f", &r); 13 | 14 | float volOfSphere = coefficient * PI * pow(r, 3); 15 | printf("Result: %f\n", volOfSphere); 16 | 17 | return 0; 18 | } 19 | 20 | /* To compile this file on Ubuntu: 21 | `gcc ./02-03.c -lm` 22 | `-lm` option helps to link with `libm.a` 23 | */ -------------------------------------------------------------------------------- /ch02/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Implementing Horner's Rule */ 4 | int main() 5 | { 6 | float x, result = 1.0f; 7 | int coeffs[] = {-6, 7, -1, -5, 2, 3}; 8 | printf("Input x: "); 9 | scanf("%f", &x); 10 | 11 | result = coeffs[5]; 12 | /* for (initialisationStatement; testExpression; updateStatement) */ 13 | for (int i = 5; i > 0; i--) 14 | { 15 | result = result * x + coeffs[i-1]; 16 | } 17 | 18 | printf("Result of 3x^5 + 2x^4 - 5x^3 - x^2 + 7x - 6: %.2f\n", result); 19 | 20 | return 0; 21 | } -------------------------------------------------------------------------------- /ch16/readline.h: -------------------------------------------------------------------------------- 1 | #ifndef READLINE_H 2 | #define READLINE_H 3 | 4 | /*********************************************************** 5 | * Skips leading white-space characters, then reads the 6 | * remainder of the input line and store its in `str`. 7 | * Truncates the line if its length exceeds `n`. 8 | * Return the number of characters stored. 9 | ***********************************************************/ 10 | int read_line(char str[], int n); 11 | 12 | #endif -------------------------------------------------------------------------------- /ch03/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int gsi_prefix, group_id, publisher_code, item_num, check_degit; 6 | 7 | printf("Enter ISBN: "); 8 | scanf("%d-%d-%d-%d-%d", &gsi_prefix, &group_id, &publisher_code, &item_num, &check_degit); 9 | 10 | printf("\nGSI prefix: %d\n", gsi_prefix); 11 | printf("Group identifier: %d\n", group_id); 12 | printf("Publisher code: %d\n", publisher_code); 13 | printf("Item number: %d\n", item_num); 14 | printf("Check digit: %d\n", check_degit); 15 | 16 | return 0; 17 | } -------------------------------------------------------------------------------- /ch06/projects/gcd.c: -------------------------------------------------------------------------------- 1 | #include "gcd.h" 2 | 3 | void process_find_gcd(int *const a, int *const b) 4 | { 5 | int temp; 6 | 7 | while (*b != 0) 8 | { 9 | temp = *a % *b; 10 | *a = *b; 11 | *b = temp; 12 | 13 | /* to see visualisation of this process, uncomment the next line */ 14 | // printf("first num = %d, second num = %d\n", *a, *b); 15 | } 16 | 17 | // at this point, *a is the GCD 18 | } 19 | 20 | const int find_gcd(int a, int b) 21 | { 22 | int temp = a % b; 23 | return (temp == 0) ? b : find_gcd(b, temp); 24 | } 25 | -------------------------------------------------------------------------------- /ch07/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* modified version of `../../ch06/projects/07.c` */ 4 | 5 | int main() 6 | { 7 | short int i, n; 8 | long int odd, square; 9 | 10 | printf("This program prints a table of squares.\n"); 11 | printf("Enter a number of entries in table: "); 12 | scanf("%hd", &n); 13 | 14 | for (odd = 3, 15 | square = 1, 16 | i = 1; 17 | i <= n; i++, square += odd, odd += 2) 18 | // because (n+1)^2 = (n^2) + 2n + 1 19 | printf("%5hd%8ld\n", i, square); 20 | 21 | return 0; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /ch10/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 10: Program Organisation 2 | 3 | ## Reading Notes 4 | 5 | - Local variables have 2 properties: *automatic storage duration* & *block scope*. 6 | - To make a local variable to have *static storage duration*, use `static` keyword. 7 | - External variables (global variables) have 2 properties: *static storage duration* & *file scope*. 8 | 9 | ## Exercising Notes 10 | 11 | - Both project 3, project 4 and project 5 have been done in only [code file](./projects/03-05.c). 12 | - Illustration for project 7: ![7 segment display](./7_segment_display.png) 13 | -------------------------------------------------------------------------------- /ch05/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Find the largest and smallest of four integers entered by user */ 4 | 5 | int main () { 6 | int nums[4], max, min, i; 7 | 8 | printf("Enter four integers: "); 9 | for (i = 0; i < 4; i++) { 10 | scanf("%d", &nums[i]); 11 | } 12 | 13 | max = min = nums[3]; // initiate `max` and `min` 14 | for (i = 2; i >= 0; i--) { 15 | if (nums[i] > max) max = nums[i]; 16 | if (nums[i] < min) min = nums[i]; 17 | } 18 | 19 | printf("Largest: %d\n", max); 20 | printf("Smallest: %d\n", min); 21 | 22 | return 0; 23 | } -------------------------------------------------------------------------------- /ch03/exercises/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | double num; 6 | /* 7 | The first two conversion specifications are for exponential notation, 8 | the last two conversion specifications are for fixed decimal notation 9 | */ 10 | const char formats[4][11] = {"|%-8.1e|\n\0", "|%10.6e|\n\0", "|%-8.3lf|\n\0", "|%6.0lf|\n\0"}; 11 | 12 | printf("Give me a float: "); 13 | scanf("%lf", &num); 14 | 15 | printf("Output the number in specified formats:\n"); 16 | for (int i = 0; i < 4; i++) 17 | { 18 | printf(formats[i], num); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ch06/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Print all square numbers between 1 and a number input by user */ 4 | 5 | int main() 6 | { 7 | long n; 8 | 9 | printf("Input an integer number: "); 10 | scanf("%ld", &n); 11 | 12 | if (n < 4) 13 | { 14 | printf("Your input number is too small!\n"); 15 | } 16 | else 17 | { 18 | unsigned long squared; 19 | for (int i = 2;; i++) 20 | { 21 | squared = i * i; 22 | if (squared <= n) 23 | printf("%ld\n", squared); 24 | else 25 | break; 26 | } 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /ch05/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Display the corresponding description to the wind speed entered by user */ 4 | 5 | int main() { 6 | int n; 7 | 8 | printf("Enter wind speed (in knots): "); 9 | scanf("%d", &n); 10 | 11 | if (n < 1) printf("Calm\n"); 12 | else if (n >= 1 && n <= 3) printf("Light air\n"); 13 | else if (n >= 4 && n <= 27) printf("Breeze\n"); 14 | else if (n >= 28 && n <= 47) printf("Gale\n"); 15 | else if (n >= 48 && n <= 63) printf("Storm\n"); 16 | else printf("Hurricane\n"); 17 | 18 | return 0; 19 | } -------------------------------------------------------------------------------- /ch04/projects/01-02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Reverse any natural number 5 | */ 6 | 7 | int main() 8 | { 9 | int num, reversed_num = 0; 10 | 11 | printf("Enter a natural number: "); 12 | scanf("%d", &num); 13 | 14 | while (num != 0) { 15 | // pad a new ones column to `reversed_num` 16 | reversed_num *= 10; 17 | // add the last digit of `num` to the recently created column 18 | reversed_num += num % 10; 19 | // strip out the last digit of `num` 20 | num /= 10; 21 | } 22 | 23 | printf("The reversed number is: %d\n", reversed_num); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /ch09/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double compute_polynomial(float x) { 4 | double res; 5 | int i; 6 | const int COEFFS[6] = {3, 2, -5, -1, 7, -6}; 7 | 8 | for (i = 0 9 | , res = COEFFS[0] 10 | ; i < 5 11 | ; i++) { 12 | res = res * x + COEFFS[i + 1]; 13 | } 14 | 15 | return res; 16 | } 17 | 18 | int main() { 19 | float inp; 20 | 21 | printf("Calculate the value of 3*x^5 + 2*x^4 - 5*x^3 - x^2 + 7*x - 6.\n"); 22 | printf("Input x: "); 23 | scanf("%f", &inp); 24 | 25 | printf("Result: %.3f\n", compute_polynomial(inp)); 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### reference: https://raw.github.com/github/gitignore/b8da0e3a89f5d75acdb9d5fed06700bfff3695f9/C.gitignore 2 | 3 | # IDEs 4 | .vscode 5 | .idea 6 | 7 | # Object files 8 | *.o 9 | *.ko 10 | *.obj 11 | *.elf 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Libraries 18 | *.lib 19 | *.a 20 | *.la 21 | *.lo 22 | 23 | # Shared objects (inc. Windows DLLs) 24 | *.dll 25 | *.so 26 | *.so.* 27 | *.dylib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | *.i*86 34 | *.x86_64 35 | *.hex 36 | 37 | # Debug files 38 | *.dSYM/ 39 | 40 | # Make file 41 | CMakeLists.txt 42 | cmake-build-debug -------------------------------------------------------------------------------- /ch06/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 6: Loops 2 | 3 | ## Reading Notes 4 | 5 | - Comma operator can be used to initialise more than 1 variable when entering a statement. For example: 6 | 7 | ```C 8 | for (sum = 0, i = 1; i <= N; i++) 9 | sum += i; 10 | ``` 11 | 12 | - `for (;;)` behave the same as `while (1)` 13 | - Null statement example: 14 | 15 | ```C 16 | for (d = 2; d <= n && n % d != 0; d++); 17 | 18 | /* or to make it stand out */ 19 | for (d = 2; d <= n && n % d != 0; d++) {}; 20 | ``` 21 | 22 | ### Exercising Notes 23 | - The most significant projects: [Project 08](./projects/08.c), [Project 10](./projects/10.c) -------------------------------------------------------------------------------- /ch02/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() 5 | { 6 | float x, result = 0.0f; 7 | int coeffs[6] = {-6, 7, -1, -5, 2, 3}; 8 | printf("Input x: "); 9 | scanf("%f", &x); 10 | 11 | /* for (initializationStatement; testExpression; updateStatement) */ 12 | for (int i = 0; i < 6; i++) 13 | { 14 | result += coeffs[i] * pow(x, i); 15 | } 16 | 17 | printf("Result of 3x^5 + 2x^4 - 5x^3 - x^2 + 7x - 6: %.2f\n", result); 18 | 19 | return 0; 20 | } 21 | 22 | /* To compile this file on Ubuntu: 23 | `gcc ./05.c -lm` 24 | `-lm` option helps to link with `libm.a` 25 | */ -------------------------------------------------------------------------------- /ch06/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Reverse any natural number 5 | This is the same code as "../../ch04/projects/01-02.c" 6 | */ 7 | 8 | int main() 9 | { 10 | int num, reversed_num = 0; 11 | 12 | printf("Enter a natural number: "); 13 | scanf("%d", &num); 14 | 15 | while (num != 0) 16 | { 17 | // pad a new ones column to `reversed_num` 18 | reversed_num *= 10; 19 | // add the last digit of `num` to the recently created column 20 | reversed_num += num % 10; 21 | // strip out the last digit of `num` 22 | num /= 10; 23 | } 24 | 25 | printf("The reversed number is: %d\n", reversed_num); 26 | 27 | return 0; 28 | } -------------------------------------------------------------------------------- /ch06/projects/11.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Calculate approximate value of algebraic constant e */ 4 | 5 | int main() 6 | { 7 | unsigned long acc_factorial = 1; // 8 bytes 8 | double res = 1; // 8 bytes 9 | int i, n; 10 | 11 | printf("e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n!\n"); 12 | printf("n = ?: "); 13 | scanf("%d", &n); 14 | 15 | if (n < 0) 16 | { 17 | printf("Invalid input!"); 18 | return 1; 19 | } 20 | else 21 | { 22 | for (i = 1; i <= n; i++) 23 | { 24 | acc_factorial *= i; 25 | res += 1. / acc_factorial; 26 | } 27 | printf("e = %lf\n", res); 28 | 29 | return 0; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ch12/projects/01_03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Read a message, then print the reversal of the message */ 5 | 6 | int main() { 7 | unsigned int i; 8 | char cur; 9 | char *inp = malloc(1000 * sizeof(char)); 10 | 11 | printf("Enter a message: "); 12 | for (i = 0;; i++) { 13 | if ((cur = getchar()) != '\n') { 14 | *(inp + i) = cur; 15 | } 16 | else { 17 | break; 18 | } 19 | } 20 | // at the end of the loop, *(inp + i) is '\n' 21 | 22 | printf("Reversal is: "); 23 | for (char *i_ptr = inp + i - 1; i_ptr >= inp; i_ptr--) { 24 | printf("%c", *i_ptr); 25 | } 26 | printf("\n"); 27 | 28 | free(inp); 29 | return 0; 30 | } -------------------------------------------------------------------------------- /ch03/projects/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(void) 4 | { 5 | int item_number, date, month, year; 6 | float unit_price; 7 | 8 | printf("Enter item number: "); 9 | scanf("%d", &item_number); 10 | printf("Enter unit price: "); 11 | scanf("%f", &unit_price); 12 | printf("Enter purchase date (mm/dd/yyyy): "); 13 | scanf("%2d/%2d/%4d", &month, &date, &year); 14 | 15 | /* 16 | Initially, I use '|' for to have make the output more visualisable; 17 | then, I deleted these '|' characters. 18 | */ 19 | printf("\nItem\t\tUnit\t\tPurchase\t\n"); 20 | printf("\t\tPrice\t\tDate\t\t\n"); 21 | printf("%d\t\t$%7.2f\t%2d/%2d/%2d\t\n", item_number, unit_price, month, date, year); 22 | } -------------------------------------------------------------------------------- /textbook_code_snippets/pun.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* pun.c (Chapter 2, page 10) */ 11 | 12 | #include 13 | 14 | int main(void) 15 | { 16 | printf("To C, or not to C: that is the question.\n"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /ch11/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 11: Pointers 2 | 3 | ## Reading Notes 4 | 5 | - `&` is called *address* operator, `*` is called *indirection* operator. 6 | - Use the keyword `const` to document that a function won't change an object whose address is passed into the function 7 | (but it doesn't prevent the function from doing modifications): 8 | 9 | ```C 10 | void foo(const int *p) { 11 | *p = 0; /** ILLEGAL **/ 12 | } 13 | ``` 14 | 15 | - Pointers as return values: 16 | - **never** return a pointer to an automatic local variable 17 | - A pointer is usually the same as address, but not always. 18 | 19 | ## Exercising Notes 20 | - In [project 02](./projects/02.c), I've changed declaration of `find_closest_flight` to fit my original solution. 21 | 22 | 23 | -------------------------------------------------------------------------------- /ch02/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | /* 6 | Number of $20 bills -> numOfBills[0] 7 | Number of $10 bills -> numOfBills[1] 8 | Number of $5 bills -> numOfBills[2] 9 | Number of $1 bills -> numOfBills[3] 10 | */ 11 | int amount, remainder, numOfBills[4], bills[4] = {20, 10, 5, 1}; 12 | 13 | printf("Enter a dollar amount: "); 14 | scanf("%d", &amount); 15 | printf("\n"); 16 | 17 | for (int i = 0; i < 4; i++) 18 | { 19 | if (bills[i] < 10) 20 | { 21 | printf(" $%d bills: %d\n", bills[i], amount / bills[i]); 22 | } 23 | else 24 | { 25 | printf("$%d bills: %d\n", bills[i], amount / bills[i]); 26 | } 27 | amount = amount % bills[i]; 28 | } 29 | 30 | return 0; 31 | } -------------------------------------------------------------------------------- /ch11/exercises/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void split_time(long total_sec, int *const hr, int *const min, int *const sec) { 5 | /* (*hr * 60^2) + (*min * 60) + *sec == total_sec */ 6 | 7 | if (total_sec < 0) { 8 | printf("INVALID INPUT!\n"); 9 | exit(EXIT_FAILURE); 10 | } 11 | else { 12 | *sec = total_sec % 60; 13 | total_sec /= 60; 14 | *min = total_sec % 60; 15 | *hr = total_sec / 60; 16 | } 17 | } 18 | 19 | int main() { 20 | long sec_num; 21 | int h, m, s; 22 | 23 | printf("Input the number of seconds since midnight: "); 24 | scanf("%ld", &sec_num); 25 | 26 | split_time(sec_num, &h, &m, &s); 27 | printf("Equivalent time: %.2d:%.2d:%.2d\n", h, m, s); 28 | 29 | return 0; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /ch11/exercises/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int *find_largest(int a[], int n) { 5 | int id_max = 0; 6 | 7 | for (int i = 1; i < n; i++) { 8 | if (a[i] > a[id_max]) 9 | id_max = i; 10 | } 11 | 12 | return a + id_max; 13 | } 14 | 15 | int main() { 16 | int len; 17 | printf("Array length? "); 18 | scanf("%d", &len); 19 | 20 | if (len <= 0) { 21 | printf("INVALID ARRAY LENGTH!\n"); 22 | return 1; 23 | } 24 | else { 25 | int *arr = malloc(len * sizeof(int)); 26 | 27 | printf("Input array: "); 28 | for (int i = 0; i < len; i++) { 29 | scanf(" %d", arr + i); 30 | } 31 | 32 | printf("The largest: %d\n", *find_largest(arr, len)); 33 | 34 | free(arr); 35 | return 0; 36 | } 37 | } -------------------------------------------------------------------------------- /ch04/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Read an integer entered by the user and displays it in octal */ 4 | int main() 5 | { 6 | /* Because the output has to be displayed using five digits, 7 | so use `res` array to store octal digits 8 | */ 9 | int num, res[5] = {0, 0, 0, 0, 0}, i = 4; 10 | 11 | printf("Enter a number between 0 and 32767: "); 12 | scanf("%d", &num); 13 | 14 | while (num != 0) 15 | { 16 | // store the remainder in the respective octal digit place, then decrease `i` by 1 17 | res[i--] = num % 8; 18 | // divide the number by 8 now 19 | num /= 8; 20 | } 21 | 22 | printf("In octal, your number is: "); 23 | for (i = 0; i < 5; i++) 24 | { 25 | printf("%d", res[i]); 26 | } 27 | printf("\n"); 28 | 29 | return 0; 30 | } -------------------------------------------------------------------------------- /ch05/projects/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const char *get_am_pm(const int h); 4 | const int convert_hour(const int h); 5 | 6 | int main() 7 | { 8 | int hour, minute; 9 | 10 | printf("Enter a 24-hour time: "); 11 | scanf("%d:%d", &hour, &minute); 12 | 13 | // if the input is invalid, terminate the program 14 | if (hour >= 24 || hour < 0) { 15 | printf("Invalid hour input!!!\n"); 16 | return 1; 17 | } 18 | 19 | printf("Equivalent 12-hour time: %.2d:%.2d %s\n", 20 | convert_hour(hour), 21 | minute, 22 | get_am_pm(hour)); 23 | 24 | return 0; 25 | } 26 | 27 | const char *get_am_pm(const int h) 28 | { 29 | return (h < 12) ? "AM\0" : "PM\0"; 30 | } 31 | 32 | const int convert_hour(const int h) 33 | { 34 | return (h > 12) ? (h % 12) : h; 35 | } -------------------------------------------------------------------------------- /ch09/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* `power` function */ 4 | 5 | double power(float x, int n) { 6 | if (n == 0) { 7 | return 1; 8 | } 9 | else if (n == 1) { 10 | return x; 11 | } 12 | else if (n == -1) { 13 | return 1.0 / x; 14 | } 15 | else { 16 | if (n % 2 == 1) { 17 | return x * power(x, n -1); 18 | } 19 | else { 20 | int half_n = n / 2; 21 | return power(x, half_n) * power(x, half_n); 22 | } 23 | } 24 | } 25 | 26 | int main () { 27 | float base_val; 28 | int power_val; 29 | 30 | printf("Calculate x^n.\n"); 31 | printf("Input x: "); 32 | scanf("%f", &base_val); 33 | printf("Input n: "); 34 | scanf("%d", &power_val); 35 | 36 | printf("Result: %f\n", power(base_val, power_val)); 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /ch07/projects/gcd.h: -------------------------------------------------------------------------------- 1 | /** Euclid's Algorithm to Find the Greatest Common Divisor (GCD) 2 | @return when this procedure ends, *a hold the GCD value 3 | */ 4 | void process_find_gcd(long *const a, long *const b) 5 | { 6 | long temp; 7 | 8 | while (*b != 0) 9 | { 10 | temp = *a % *b; 11 | *a = *b; 12 | *b = temp; 13 | 14 | /* to see visualisation of this process, uncomment the next line */ 15 | // printf("first num = %ld, second num = %ld\n", *a, *b); 16 | } 17 | 18 | // at this point, *a is the GCD 19 | } 20 | 21 | /** Pure Function Implementing Euclid's Algorithm Recursively to 22 | * Find the Greatest Common Divisor (GCD) 23 | */ 24 | const long find_gcd(long a, long b) 25 | { 26 | long temp = a % b; 27 | return (temp == 0) ? b : find_gcd(b, temp); 28 | } 29 | -------------------------------------------------------------------------------- /textbook_code_snippets/pun2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* pun2.c (Chapter 9, page 187) */ 11 | /* Prints a bad pun */ 12 | 13 | #include 14 | 15 | void print_pun(void) 16 | { 17 | printf("To C, or not to C: that is the question.\n"); 18 | } 19 | 20 | int main(void) 21 | { 22 | print_pun(); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /textbook_code_snippets/stack.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stack.h (Chapter 19, page 488) */ 11 | 12 | #ifndef STACK_H 13 | #define STACK_H 14 | 15 | #include /* C99 only */ 16 | 17 | void make_empty(void); 18 | bool is_empty(void); 19 | bool is_full(void); 20 | void push(int i); 21 | int pop(void); 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /ch12/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Finds the largest and smallest elements in an array 4 | * modified version of `maxmin.c` (chapter 11, page 250) 5 | */ 6 | 7 | #define N 10 8 | 9 | void max_min(int *a, int *max, int *min); 10 | 11 | int main(void) 12 | { 13 | int b[N], i, big, small; 14 | 15 | printf("Enter %d numbers: ", N); 16 | for (i = 0; i < N; i++) 17 | scanf("%d", b+i); 18 | 19 | max_min(b, &big, &small); 20 | 21 | printf("Largest: %d\n", big); 22 | printf("Smallest: %d\n", small); 23 | 24 | return 0; 25 | } 26 | 27 | void max_min(int *a, int *max, int *min) 28 | { 29 | int* i_ptr; 30 | 31 | *max = *min = a[0]; 32 | for (i_ptr = a; i_ptr <= a + N; i_ptr++) { 33 | if (*i_ptr > *max) 34 | *max = *i_ptr; 35 | else if (*i_ptr < *min) 36 | *min = *i_ptr; 37 | } 38 | } -------------------------------------------------------------------------------- /ch12/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 12: Pointers and Arrays 2 | 3 | ## Reading Notes 4 | 5 | - **C99** Pointers to compound literals: 6 | 7 | ```C 8 | int *p = (int []) {3, 0, 2, 5, 6}; 9 | ``` 10 | 11 | - Pointer arithmetic: 12 | - Postfix version of `++` has precedence over `*` so that `*p++` is the same as `*(p++)` and `*++p` is the same as `*(++p)`. 13 | 14 | - Two-dimensional array: 15 | - `a[i][j]` is the same as `*(a[i] + j)` 16 | 17 | - Trivia: 18 | - In C, `i[a]` is the same as `a[i]` because C interprets them as `*(a + i)` 19 | 20 | ### Related Chapters 21 | 22 | - [Chapter 13](../ch13): Strings 23 | - [Chapter 17](../ch17): Advanced Uses of Pointers 24 | 25 | ## Exercising Notes 26 | 27 | - The most significant projects: 28 | - [project 6](./projects/06.c): quick-sort implementation using pointers to array as cursors -------------------------------------------------------------------------------- /ch04/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 4: Expressions 2 | 3 | ## Reading Notes 4 | 5 | ### Lvalue 6 | 7 | - A `lvalue` represents an object stored in computer memory, not a constant or result of a computations. Variables are `lvalue`s, expressions are not. 8 | - The assignment operator requires an `lvalue` as its left operand. 9 | 10 | ### Trivias 11 | - Be aware of implementation-defined behaviour. 12 | - Avoid undefined behaviour. 13 | - `rvalue` and "expression" are the terms can be used interchangeably. 14 | - `v += e` isn't equivalent to `v = v + e`. For instance, `a[i++] += 2` behaves differently to `a[i++] = a[i++] + 2`. 15 | 16 | ## Relating Chapters 17 | 18 | - Chapter 7: `printf` to print number in base 8 19 | - Chapter 23: `pow` function, `fmod` function 20 | 21 | ## Exercises Notes 22 | - The most challenging projects: [*Project 04*](./projects/04.c). 23 | 24 | -------------------------------------------------------------------------------- /ch10/projects/03-05.c: -------------------------------------------------------------------------------- 1 | #include "poker_02.h" 2 | 3 | /* Refactored version of `poker.c` */ 4 | 5 | /* Ranks: 2 3 4 5 6 7 8 9 t j q k a 6 | * Suits: c d h s 7 | * 8 | * Royal flush: ace, king, queen, jack, ten of the same suit 9 | * Straight flush: both a straight and a flush 10 | * Four-of-a-kind: four cards of the same rank 11 | * Full house: a three of a kind and a pair 12 | * Flush: five cards of the same suit 13 | * Straight: five cards with consecutive ranks (ace-low straight included) 14 | * Three-of-a-kind: three cards of the sam rank 15 | * Two pairs 16 | * Pair: two cards of the same rank 17 | * High card: any other hand 18 | * */ 19 | int main(void) 20 | { 21 | int hand[5][2] = {}; 22 | 23 | for (;;) { 24 | read_cards(hand); 25 | analyse_hand(hand); 26 | print_result(); 27 | } 28 | } -------------------------------------------------------------------------------- /ch07/projects/10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Count the number of vowels in a sentence */ 5 | 6 | char *const VOWELS = "AEOUIaeoui"; 7 | 8 | int main() 9 | { 10 | char cur, *inp; 11 | // declares an array and fills its values with zeroes 12 | int res = 0, index_array[128] = {}; 13 | 14 | /* count number of occurances for each character in user's input */ 15 | printf("Enter a sentence: "); 16 | for (;;) 17 | { 18 | cur = getchar(); 19 | 20 | if (cur != '\n') 21 | { 22 | index_array[cur]++; 23 | } 24 | else 25 | { 26 | break; 27 | } 28 | } 29 | 30 | /* calculate the sum of occurances of vowel characters */ 31 | for (int i = 0; i < 10; i++) 32 | { 33 | res += index_array[VOWELS[i]]; 34 | } 35 | 36 | printf("Your sentence contains %d vowels.\n", res); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /textbook_code_snippets/countdown.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* countdown.c (Chapter 9, page 186) */ 11 | /* Prints a countdown */ 12 | 13 | #include 14 | 15 | void print_count(int n) 16 | { 17 | printf("T minus %d and counting\n", n); 18 | } 19 | 20 | int main(void) 21 | { 22 | int i; 23 | 24 | for (i = 10; i > 0; --i) 25 | print_count(i); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /textbook_code_snippets/length2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* length2.c (Chapter 7, page 142) */ 11 | /* Determines the length of a message */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int len = 0; 18 | 19 | printf("Enter a message: "); 20 | while (getchar() != '\n') 21 | len++; 22 | printf("Your message was %d character(s) long.\n", len); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /ch08/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* modified version of `repdigit.c` that show which digit(s) from user input are repeated */ 5 | 6 | int main() 7 | { 8 | int i, occurences[10] = {}; 9 | char cur; 10 | 11 | printf("Enter a number: "); 12 | for (;;) 13 | { 14 | cur = getchar(); 15 | if (cur != '\n') 16 | { 17 | if (cur <= '9' && cur >= '0') 18 | // accumulate the number of occurences 19 | occurences[cur - '0']++; 20 | else 21 | { 22 | printf("INVALID INPUT!\n"); 23 | return 1; 24 | } 25 | } 26 | else 27 | { 28 | break; 29 | } 30 | } 31 | 32 | printf("\nRepeated digit(s):"); 33 | for (i = 0; i < 10; i++) 34 | { 35 | if (occurences[i] > 1) 36 | { 37 | printf("%2d", i); 38 | } 39 | } 40 | printf("\n"); 41 | 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /ch05/exercises/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Conclusion: 5 | For comparison operators, side effects are only performed on the left operands. 6 | */ 7 | 8 | int main() 9 | { 10 | int i, j, k; 11 | 12 | /* question (a) */ 13 | i = 3; 14 | j = 4; 15 | k = 5; 16 | printf("%d\n", i < j || ++j < k); 17 | printf("%d %d %d\n", i, j, k); 18 | printf("\n"); 19 | 20 | /* question (b) */ 21 | i = 7; 22 | j = 8; 23 | k = 9; 24 | printf("%d\n", i - 7 && j++ < k); 25 | printf("%d %d %d\n", i, j, k); 26 | printf("\n"); 27 | 28 | /* question (c) */ 29 | i = 7; 30 | j = 8; 31 | k = 9; 32 | printf("%d\n", (i = j) || (j = k)); 33 | printf("%d %d %d\n", i, j, k); 34 | printf("\n"); 35 | 36 | /* question (d) */ 37 | i = 7; 38 | j = 8; 39 | k = 9; 40 | printf("%d\n", ++i || ++j && ++k); 41 | printf("%d %d %d\n", i, j, k); 42 | 43 | return 0; 44 | } -------------------------------------------------------------------------------- /ch10/projects/02.c: -------------------------------------------------------------------------------- 1 | #include "poker_01.h" 2 | 3 | /* Refactored version of `poker.c` */ 4 | 5 | #define NUM_RANKS 13 6 | #define NUM_SUITS 4 7 | 8 | /* Ranks: 2 3 4 5 6 7 8 9 t j q k a 9 | * Suits: c d h s 10 | * 11 | * Straight flush: both a straight and a flush 12 | * Four-of-a-kind: four cards of the same rank 13 | * Full house: a three of a kind and a pair 14 | * Flush: five cards of the same suit 15 | * Straight: five cards with consecutive ranks 16 | * Three-of-a-kind: three cards of the sam rank 17 | * Two pairs 18 | * Pair: two cards of the same rank 19 | * High card: any other hand 20 | * */ 21 | int main(void) 22 | { 23 | int num_in_rank[NUM_RANKS]; 24 | int num_in_suit[NUM_SUITS]; 25 | 26 | for (;;) { 27 | read_cards(num_in_rank, num_in_suit); 28 | analyse_hand(num_in_rank, num_in_suit); 29 | print_result(); 30 | } 31 | } -------------------------------------------------------------------------------- /textbook_code_snippets/tprintf.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tprintf.c (Chapter 3, page 40) */ 11 | /* Prints int and float values in various formats */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int i; 18 | float x; 19 | 20 | i = 40; 21 | x = 839.21f; 22 | 23 | printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i); 24 | printf("|%10.3f|%10.3e|%-10g|\n", x, x, x); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /ch08/projects/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Print out sums of rows and columns of a 5x5 table */ 5 | 6 | int main() 7 | { 8 | int i, j, cur, col_sums[5] = {}, row_sums[5] = {}; 9 | 10 | for (i = 0; i < 5; i++) 11 | // traverse rows 12 | { 13 | printf("Enter row %d: ", i + 1); 14 | for (j = 0; j < 5; j++) 15 | // traverse columns 16 | { 17 | scanf("%d", &cur); 18 | 19 | // accumulated scanned value to respective running totals 20 | row_sums[i] += cur; 21 | col_sums[j] += cur; 22 | } 23 | } 24 | 25 | /* print out results */ 26 | 27 | printf("\nRow totals:\t"); 28 | for (int i = 0; i < 5; i++) 29 | { 30 | printf("%3d", row_sums[i]); 31 | } 32 | printf("\nColumn totals:\t"); 33 | for (int i = 0; i < 5; i++) 34 | { 35 | printf("%3d", col_sums[i]); 36 | } 37 | printf("\n"); 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /ch05/projects/10.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Given a numerical grade, print out a letter grade */ 4 | 5 | char get_grade(int n); 6 | 7 | int main() 8 | { 9 | int grade; 10 | 11 | printf("Enter numerical grade: "); 12 | scanf("%d", &grade); 13 | 14 | if (grade >= 0 && grade <= 100) 15 | { 16 | printf("Letter grade: %c\n", get_grade(grade)); 17 | return 0; 18 | } 19 | else 20 | { 21 | printf("Invalid grade input!!!\n"); 22 | return 1; 23 | } 24 | } 25 | 26 | char get_grade(int n) 27 | { 28 | // get the ten's digit 29 | n = (n / 10); 30 | 31 | if (n >= 0 && n <= 5) 32 | { 33 | return 'F'; 34 | } 35 | else 36 | { 37 | switch (n) 38 | { 39 | case 6: 40 | return 'D'; 41 | case 7: 42 | return 'C'; 43 | case 8: 44 | return 'B'; 45 | case 9: 46 | return 'A'; 47 | case 10: 48 | return 'A'; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /ch07/projects/11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main() 7 | { 8 | int i = 0; 9 | bool is_scanning_last = false; 10 | char cur, *first, *last; 11 | 12 | first = malloc(50 * sizeof(char)); 13 | last = malloc(50 * sizeof(char)); 14 | 15 | printf("Enter a first and last name: "); 16 | for (;;) 17 | { 18 | cur = getchar(); 19 | if (cur != '\n') 20 | { 21 | if (isspace(cur)) 22 | { 23 | i = 0; 24 | is_scanning_last = true; 25 | } 26 | else 27 | { 28 | if (is_scanning_last) 29 | { 30 | last[i++] = cur; 31 | } 32 | else 33 | { 34 | first[i++] = cur; 35 | } 36 | } 37 | } 38 | else 39 | { 40 | break; 41 | } 42 | } 43 | 44 | printf("%s, %c.\n", last, first[0]); 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /textbook_code_snippets/tcasemap.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tcasemap.c (Chapter 23, page 615) */ 11 | /* Tests the case-mapping functions */ 12 | 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | char *p; 19 | 20 | for (p = "aA0!"; *p != '\0'; p++) { 21 | printf("tolower('%c') is '%c'; ", *p, tolower(*p)); 22 | printf("toupper('%c') is '%c'\n", *p, toupper(*p)); 23 | } 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /ch07/projects/09.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Convert 12-hour format to 24-hour format */ 5 | 6 | int Time_input(int *const h_ptr, int *const m_ptr) 7 | { 8 | int i; 9 | char cur; 10 | 11 | // printf("\nPointer address: %zu\n", &t); 12 | scanf("%d:%d", h_ptr, m_ptr); 13 | 14 | // strip space characters out of buffer 15 | for (;;) 16 | { 17 | cur = getchar(); 18 | if (!isspace(cur)) 19 | break; 20 | } 21 | 22 | switch (toupper(cur)) 23 | { 24 | case 'P': 25 | *h_ptr += 12; 26 | return 0; 27 | case 'A': 28 | return 0; 29 | default: 30 | printf("INVALID!\n"); 31 | return 1; 32 | } 33 | } 34 | 35 | int main() 36 | { 37 | int h, m, program_status; 38 | 39 | printf("Enter a 12-hour time: "); 40 | program_status = Time_input(&h, &m); 41 | 42 | printf("Equivalent 24-hour time: %.2d:%.2d\n", h, m); 43 | return program_status; 44 | } 45 | -------------------------------------------------------------------------------- /ch07/projects/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define INTERVAL 24 3 | 4 | /* modified version of `./01.c` */ 5 | 6 | int main() 7 | { 8 | short int i, n; 9 | long int odd, square; 10 | char chr; 11 | 12 | printf("This program prints a table of squares.\n"); 13 | printf("Enter a number of entries in table: "); 14 | scanf("%hd", &n); 15 | // IMPORTANT: remove trailing newline character from the buffer 16 | getchar(); 17 | 18 | for (odd = 3, square = 1, i = 1; 19 | i <= n; 20 | i++, square += odd, odd += 2) 21 | { 22 | // because (n+1)^2 = (n^2) + 2n + 1 23 | printf("%5hd%8ld\n", i, square); 24 | 25 | if (i % INTERVAL == 0) 26 | { 27 | printf("Press Enter to continue..."); 28 | // iteratively read all characters to the buffer 29 | // skip the loop only when getting '\n' 30 | while (getchar() != '\n') 31 | ; 32 | } 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /textbook_code_snippets/length.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* length.c (Chapter 7, page 142) */ 11 | /* Determines the length of a message */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | char ch; 18 | int len = 0; 19 | 20 | printf("Enter a message: "); 21 | ch = getchar(); 22 | while (ch != '\n') { 23 | len++; 24 | ch = getchar(); 25 | } 26 | printf("Your message was %d character(s) long.\n", len); 27 | 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /textbook_code_snippets/readline.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* readline.c (Chapter 16, page 395) */ 11 | 12 | #include 13 | #include 14 | #include "readline.h" 15 | 16 | int read_line(char str[], int n) 17 | { 18 | int ch, i = 0; 19 | 20 | while (isspace(ch = getchar())) 21 | ; 22 | while (ch != '\n' && ch != EOF) { 23 | if (i < n) 24 | str[i++] = ch; 25 | ch = getchar(); 26 | } 27 | str[i] = '\0'; 28 | return i; 29 | } 30 | -------------------------------------------------------------------------------- /ch06/projects/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Calculate the largest approximate value of algebraic constant e 4 | which is smaller than user's input float 5 | */ 6 | 7 | int main() 8 | { 9 | unsigned long acc_factorial = 1; 10 | double res = 1, inp; 11 | int i = 0; 12 | 13 | printf("e = 1 + 1/1! + 1/2! + 1/3! + ... + 1/n!\n"); 14 | printf("Find the largest e which is smaller than your input\n"); 15 | printf("Your threshold input = ?: "); 16 | scanf("%lf", &inp); 17 | 18 | if (inp < 1) 19 | { 20 | printf("Invalid input!"); 21 | return 1; 22 | } 23 | else 24 | { 25 | while (res < inp) 26 | { 27 | i += 1; 28 | acc_factorial *= i; 29 | res += 1.0 / acc_factorial; 30 | } 31 | /* when the above loop terminates, 32 | `res` is larger than the desired result by `1 / acc_factorial` */ 33 | printf("e = %lf\n", res - 1.0 / acc_factorial); 34 | 35 | return 0; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /textbook_code_snippets/square2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* square2.c (Chapter 6, page 110) */ 11 | /* Prints a table of squares using a for statement */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int i, n; 18 | 19 | printf("This program prints a table of squares.\n"); 20 | printf("Enter number of entries in table: "); 21 | scanf("%d", &n); 22 | 23 | for (i = 1; i <= n; i++) 24 | printf("%10d%10d\n", i, i * i); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /textbook_code_snippets/numdigits.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* numdigits.c (Chapter 6, page 105) */ 11 | /* Calculates the number of digits in an integer */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int digits = 0, n; 18 | 19 | printf("Enter a nonnegative integer: "); 20 | scanf("%d", &n); 21 | 22 | do { 23 | n /= 10; 24 | digits++; 25 | } while (n > 0); 26 | 27 | printf("The number has %d digit(s).\n", digits); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/stackADT.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackADT.h (Chapter 19, page 496) */ 11 | 12 | #ifndef STACKADT_H 13 | #define STACKADT_H 14 | 15 | #include /* C99 only */ 16 | 17 | typedef int Item; 18 | 19 | typedef struct stack_type *Stack; 20 | 21 | Stack create(void); 22 | void destroy(Stack s); 23 | void make_empty(Stack s); 24 | bool is_empty(Stack s); 25 | bool is_full(Stack s); 26 | void push(Stack s, Item i); 27 | Item pop(Stack s); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /textbook_code_snippets/stackADT2.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackADT2.h (Chapter 19, page 498) */ 11 | 12 | #ifndef STACKADT_H 13 | #define STACKADT_H 14 | 15 | #include /* C99 only */ 16 | 17 | typedef int Item; 18 | 19 | typedef struct stack_type *Stack; 20 | 21 | Stack create(int size); 22 | void destroy(Stack s); 23 | void make_empty(Stack s); 24 | bool is_empty(Stack s); 25 | bool is_full(Stack s); 26 | void push(Stack s, Item i); 27 | Item pop(Stack s); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /ch08/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* modified version of `interest.c` */ 4 | 5 | int main(void) 6 | { 7 | int i, low_rate, num_years, month, year; 8 | const int INITIAL_BALANCE = 100.00; 9 | double value[5]; 10 | const int NUM_RATES = (int)(sizeof(value) / sizeof(value[0])); 11 | 12 | printf("Enter interest rate: "); 13 | scanf("%d", &low_rate); 14 | printf("Enter number of years: "); 15 | scanf("%d", &num_years); 16 | 17 | printf("\nYears"); 18 | for (i = 0; i < NUM_RATES; i++) 19 | { 20 | printf("%8d%%", low_rate + i); 21 | value[i] = INITIAL_BALANCE; 22 | } 23 | printf("\n"); 24 | 25 | for (year = 1; year <= num_years; year++) 26 | { 27 | printf("%3d ", year); 28 | for (i = 0; i < NUM_RATES; i++) 29 | { 30 | for (month = 1; month <= 12; month++) 31 | value[i] *= (low_rate + i) / 12 / 100.0 + 1; 32 | printf("%9.2f", value[i]); 33 | } 34 | printf("\n"); 35 | } 36 | return 0; 37 | } -------------------------------------------------------------------------------- /textbook_code_snippets/reverse.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* reverse.c (Chapter 8, page 164) */ 11 | /* Reverses a series of numbers */ 12 | 13 | #include 14 | 15 | #define N 10 16 | 17 | int main(void) 18 | { 19 | int a[N], i; 20 | 21 | printf("Enter %d numbers: ", N); 22 | for (i = 0; i < N; i++) 23 | scanf("%d", &a[i]); 24 | 25 | printf("In reverse order:"); 26 | for (i = N - 1; i >= 0; i--) 27 | printf(" %d", a[i]); 28 | printf("\n"); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /textbook_code_snippets/sum.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* sum.c (Chapter 6, page 103) */ 11 | /* Sums a series of numbers */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int n, sum = 0; 18 | 19 | printf("This program sums a series of integers.\n"); 20 | printf("Enter integers (0 to terminate): "); 21 | 22 | scanf("%d", &n); 23 | while (n != 0) { 24 | sum += n; 25 | scanf("%d", &n); 26 | } 27 | printf("The sum is: %d\n", sum); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/square.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* square.c (Chapter 6, page 102) */ 11 | /* Prints a table of squares using a while statement */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int i, n; 18 | 19 | printf("This program prints a table of squares.\n"); 20 | printf("Enter number of entries in table: "); 21 | scanf("%d", &n); 22 | 23 | i = 1; 24 | while (i <= n) { 25 | printf("%10d%10d\n", i, i * i); 26 | i++; 27 | } 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /ch08/projects/13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* this is the same source code as `../../ch07/projects/11.c` */ 7 | 8 | int main() 9 | { 10 | int i = 0; 11 | bool is_scanning_last = false; 12 | char cur, *first, *last; 13 | 14 | first = malloc(50 * sizeof(char)); 15 | last = malloc(50 * sizeof(char)); 16 | 17 | printf("Enter a first and last name: "); 18 | for (;;) 19 | { 20 | cur = getchar(); 21 | if (cur != '\n') 22 | { 23 | if (isspace(cur)) 24 | { 25 | i = 0; 26 | is_scanning_last = true; 27 | } 28 | else 29 | { 30 | if (is_scanning_last) 31 | { 32 | last[i++] = cur; 33 | } 34 | else 35 | { 36 | first[i++] = cur; 37 | } 38 | } 39 | } 40 | else 41 | { 42 | break; 43 | } 44 | } 45 | 46 | printf("%s, %c.\n", last, first[0]); 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /textbook_code_snippets/xor.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* xor.c (Chapter 20, page 515) */ 11 | /* Performs XOR encryption */ 12 | 13 | #include 14 | #include 15 | 16 | #define KEY '&' 17 | 18 | int main(void) 19 | { 20 | int orig_char, new_char; 21 | 22 | while ((orig_char = getchar()) != EOF) { 23 | new_char = orig_char ^ KEY; 24 | if (isprint(orig_char) && isprint(new_char)) 25 | putchar(new_char); 26 | else 27 | putchar(orig_char); 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /textbook_code_snippets/reverse3.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* reverse3.c (Chapter 12, page 264) */ 11 | /* Reverses a series of numbers (pointer version) */ 12 | 13 | #include 14 | 15 | #define N 10 16 | 17 | int main(void) 18 | { 19 | int a[N], *p; 20 | 21 | printf("Enter %d numbers: ", N); 22 | for (p = a; p < a + N; p++) 23 | scanf("%d", p); 24 | 25 | printf("In reverse order:"); 26 | for (p = a + N - 1; p >= a; p--) 27 | printf(" %d", *p); 28 | printf("\n"); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /textbook_code_snippets/sum2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* sum2.c (Chapter 7, page 131) */ 11 | /* Sums a series of numbers (using long variables) */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | long n, sum = 0; 18 | 19 | printf("This program sums a series of integers.\n"); 20 | printf("Enter integers (0 to terminate): "); 21 | 22 | scanf("%ld", &n); 23 | while (n != 0) { 24 | sum += n; 25 | scanf("%ld", &n); 26 | } 27 | printf("The sum is: %ld\n", sum); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /ch08/projects/02-03.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* modified version of `repdigit.c` that show table of occurences */ 6 | 7 | int main() 8 | { 9 | int i, occurences[10] = {}; 10 | char cur; 11 | 12 | printf("Enter a number: "); 13 | for (;;) 14 | { 15 | cur = getchar(); 16 | if (cur != '\n') 17 | { 18 | if (isspace(cur)) 19 | continue; 20 | else if (cur <= '9' && cur >= '0') 21 | // accumulate the number of occurences 22 | occurences[cur - '0']++; 23 | else 24 | { 25 | printf("INVALID INPUT!\n"); 26 | return 1; 27 | } 28 | } 29 | else 30 | { 31 | break; 32 | } 33 | } 34 | 35 | printf("\nDigit:\t\t"); 36 | for (i = 0; i < 10; i++) 37 | { 38 | printf("%3d", i); 39 | } 40 | printf("\nOccurences:\t"); 41 | for (i = 0; i < 10; i++) 42 | { 43 | printf("%3d", occurences[i]); 44 | } 45 | printf("\n"); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /ch10/projects/stack_char.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef C_PROGRAMMING_A_MODERN_APPROACH_STACK_CHAR_H 4 | 5 | /* Empty the stack */ 6 | void stack_make_empty(); 7 | /* Return `true` if stack is empty, `false` is not */ 8 | bool stack_is_empty(); 9 | /* Return `true` if current stack size reaches the stack's limit size */ 10 | bool stack_is_full(); 11 | /* Add an element to the top end of the stack */ 12 | void stack_push(char chr); 13 | /* Remove the element from the top end of the stack then return the popped item */ 14 | char stack_pop(); 15 | /* Return index of the current top element */ 16 | int stack_current_top_index(); 17 | /* Return the value of the current top element */ 18 | char stack_current_top(); 19 | 20 | /* Behaviours for when the stack is overflow */ 21 | void stack_overflow(); 22 | /* Behaviours for when the stack is underflow */ 23 | void stack_underflow(); 24 | 25 | #define C_PROGRAMMING_A_MODERN_APPROACH_STACK_CHAR_H 26 | 27 | #endif //C_PROGRAMMING_A_MODERN_APPROACH_STACK_CHAR_H 28 | -------------------------------------------------------------------------------- /ch02/projects/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | /* Simple Interest */ 6 | float loan, interestRate, monthlyPayment; 7 | char ordinals[3][7] = {"first\0", "second\0", "third\0"}; 8 | 9 | printf("Enter amount of loan: "); 10 | scanf("%f", &loan); 11 | printf("Enter interest rate: "); 12 | scanf("%f", &interestRate); 13 | printf("Enter monthly payment: "); 14 | scanf("%f", &monthlyPayment); 15 | 16 | // convert `interestRate` to its percentage 17 | interestRate = interestRate / 100; 18 | // calculate monthly flat interest rate 19 | float monthlyRate = interestRate / 12; 20 | 21 | for (int i = 0; i < 3; i++) 22 | { 23 | /* every month, the balance is increased by 24 | the balance times the monthly interest rate 25 | and decreased by the amount of payment 26 | */ 27 | loan *= (1 + monthlyRate); 28 | loan -= monthlyPayment; 29 | 30 | printf("Balance remaining after %s payment: %.2f\n", ordinals[i], loan); 31 | } 32 | 33 | return 0; 34 | } -------------------------------------------------------------------------------- /ch10/projects/stack_int.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef C_PROGRAMMING_A_MODERN_APPROACH_STACK_INT_H 4 | 5 | /* Empty the stack */ 6 | void intstack_make_empty(); 7 | /* Return `true` if stack is empty, `false` is not */ 8 | bool intstack_is_empty(); 9 | /* Return `true` if current stack size reaches the stack's limit size */ 10 | bool intstack_is_full(); 11 | /* Add an element to the top end of the stack */ 12 | void intstack_push(int num); 13 | /* Remove the element from the top end of the stack then return the popped item */ 14 | char intstack_pop(); 15 | /* Return index of the current top element */ 16 | int intstack_current_length(); 17 | /* Return the value of the current top element */ 18 | char intstack_current_top(); 19 | 20 | /* Behaviours for when the stack is overflow */ 21 | void stack_overflow(); 22 | /* Behaviours for when the stack is underflow */ 23 | void stack_underflow(); 24 | 25 | #define C_PROGRAMMING_A_MODERN_APPROACH_STACK_INT_H 26 | 27 | #endif //C_PROGRAMMING_A_MODERN_APPROACH_STACK_INT_H 28 | -------------------------------------------------------------------------------- /textbook_code_snippets/celsius.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* celsius.c (Chapter 2, page 24) */ 11 | /* Converts a Fahrenheit temperature to Celsius */ 12 | 13 | #include 14 | 15 | #define FREEZING_PT 32.0f 16 | #define SCALE_FACTOR (5.0f / 9.0f) 17 | 18 | int main(void) 19 | { 20 | float fahrenheit, celsius; 21 | 22 | printf("Enter Fahrenheit temperature: "); 23 | scanf("%f", &fahrenheit); 24 | 25 | celsius = (fahrenheit - FREEZING_PT) * SCALE_FACTOR; 26 | 27 | printf("Celsius equivalent: %.1f\n", celsius); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/square3.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* square3.c (Chapter 6, page 110) */ 11 | /* Prints a table of squares using an odd method */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int i, n, odd, square; 18 | 19 | printf("This program prints a table of squares.\n"); 20 | printf("Enter number of entries in table: "); 21 | scanf("%d", &n); 22 | 23 | i = 1; 24 | odd = 3; 25 | for (square = 1; i <= n; odd += 2) { 26 | printf("%10d%10d\n", i, square); 27 | ++i; 28 | square += odd; 29 | } 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /textbook_code_snippets/word.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* word.c (Chapter 15, page 363) */ 11 | 12 | #include 13 | #include "word.h" 14 | 15 | int read_char(void) 16 | { 17 | int ch = getchar(); 18 | 19 | if (ch == '\n' || ch == '\t') 20 | return ' '; 21 | return ch; 22 | } 23 | 24 | void read_word(char *word, int len) 25 | { 26 | int ch, pos = 0; 27 | 28 | while ((ch = read_char()) == ' ') 29 | ; 30 | while (ch != ' ' && ch != EOF) { 31 | if (pos < len) 32 | word[pos++] = ch; 33 | ch = read_char(); 34 | } 35 | word[pos] = '\0'; 36 | } 37 | -------------------------------------------------------------------------------- /ch09/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 9: Functions 2 | 3 | ## Reading Notes 4 | 5 | - **C99** Variable-Length Array Parameters: 6 | 7 | ```C 8 | int func_arr(int n, int a[n]); 9 | int func_arr(int n, int a[*]); 10 | int func_arr(int, int a[*]); 11 | ``` 12 | 13 | - **C99** `static` in Array Parameter Declarations: 14 | 15 | ```C 16 | int sum_array(int a[static 3], int n); 17 | ``` 18 | 19 | - **C99** Compound Literals: 20 | 21 | ```C 22 | int total = sum_array((int []) {3, 0, 3, 4, 1}, 5); 23 | ``` 24 | 25 | 26 | ### Errata 27 | 28 | - In page 217: 29 | 30 | ```C 31 | void create_magic_square (int n, char magic_square[n][n]); 32 | void print_magic_square (int n, char magic_square[n][n]); 33 | ``` 34 | 35 | is actually: 36 | 37 | ```C 38 | void create_magic_square (int n, int magic_square[n][n]); 39 | void print_magic_square (int n, int magic_square[n][n]); 40 | ``` 41 | 42 | ## Exercising Notes 43 | - The most significant projects: 44 | - [project 01](./projects/01.c): recursive selection sort 45 | - [project 05](./projects/05.c): pointer to multi-dimensional array -------------------------------------------------------------------------------- /ch08/deal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #define NUM_SUITS 4 7 | #define NUM_RANKS 13 8 | 9 | const char RANK_CODES[] = {'2', '3', '4', '5', '6', '7', '8', '9', 't', 'j', 'q', 'k', 'a'}; 10 | const char SUIT_CODES[] = {'c', 'd', 'h', 's'}; 11 | 12 | int main() 13 | { 14 | bool in_hand[NUM_SUITS][NUM_RANKS] = {false}; 15 | int num_cards, rank, suit; 16 | 17 | // prevent the program from dealing the same cards every time it is executed 18 | srand((unsigned) time(NULL)); 19 | 20 | printf("Enter number of cards in hand: "); 21 | scanf("%d", &num_cards); 22 | 23 | printf("Your hand: "); 24 | while (num_cards > 0) 25 | { 26 | // pick a random suit 27 | suit = rand() % NUM_SUITS; 28 | // pick a random rank 29 | rank = rand() % NUM_RANKS; 30 | 31 | if (!in_hand[suit][rank]) 32 | { 33 | in_hand[suit][rank] = true; 34 | num_cards--; 35 | printf(" %c%c", RANK_CODES[rank], SUIT_CODES[suit]); 36 | } 37 | } 38 | printf("\n"); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /textbook_code_snippets/addfrac.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* addfrac.c (Chapter 3, page 46) */ 11 | /* Adds two fractions */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int num1, denom1, num2, denom2, result_num, result_denom; 18 | 19 | printf("Enter first fraction: "); 20 | scanf("%d/%d", &num1, &denom1); 21 | 22 | printf("Enter second fraction: "); 23 | scanf("%d/%d", &num2, &denom2); 24 | 25 | result_num = num1 * denom2 + num2 * denom1; 26 | result_denom = denom1 * denom2; 27 | printf("The sum is %d/%d\n", result_num, result_denom); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /ch06/projects/09.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Simple Interest 4 | modified version of `../../ch02/projects/08.c` 5 | */ 6 | 7 | int main() 8 | { 9 | float loan, interestRate, monthlyRate, payment; 10 | char ordinals[3][7] = {"first\0", "second\0", "third\0"}; 11 | 12 | printf("Enter amount of loan: "); 13 | scanf("%f", &loan); 14 | printf("Enter interest rate: "); 15 | scanf("%f", &interestRate); 16 | 17 | // convert `interestRate` to its percentage 18 | interestRate = interestRate / 100; 19 | // calculate monthly flat interest rate 20 | monthlyRate = interestRate / 12; 21 | 22 | for (int i = 0; i < 3; i++) 23 | { 24 | printf("Enter %s month payment: ", ordinals[i]); 25 | scanf("%f", &payment); 26 | 27 | /* every month, the balance is increased by 28 | the balance times the monthly interest rate 29 | and decreased by the amount of payment 30 | */ 31 | loan *= (1 + monthlyRate); 32 | loan -= payment; 33 | 34 | printf("Balance remaining after %s payment: %.2f\n", ordinals[i], loan); 35 | } 36 | 37 | return 0; 38 | } -------------------------------------------------------------------------------- /textbook_code_snippets/canopen.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* canopen.c (Chapter 22, page 547) */ 11 | /* Checks whether a file can be opened for reading */ 12 | 13 | #include 14 | #include 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | FILE *fp; 19 | 20 | if (argc != 2) { 21 | printf("usage: canopen filename\n"); 22 | exit(EXIT_FAILURE); 23 | } 24 | 25 | if ((fp = fopen(argv[1], "r")) == NULL) { 26 | printf("%s can't be opened\n", argv[1]); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | printf("%s can be opened\n", argv[1]); 31 | fclose(fp); 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /textbook_code_snippets/dweight.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* dweight.c (Chapter 2, page 20) */ 11 | /* Computes the dimensional weight of a 12" x 10" x 8" box */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int height, length, width, volume, weight; 18 | 19 | height = 8; 20 | length = 12; 21 | width = 10; 22 | volume = height * length * width; 23 | weight = (volume + 165) / 166; 24 | 25 | printf("Dimensions: %dx%dx%d\n", length, width, height); 26 | printf("Volume (cubic inches): %d\n", volume); 27 | printf("Dimensional weight (pounds): %d\n", weight); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/average.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* average.c (Chapter 9, page 185) */ 11 | /* Computes pairwise averages of three numbers */ 12 | 13 | #include 14 | 15 | double average(double a, double b) 16 | { 17 | return (a + b) / 2; 18 | } 19 | 20 | int main(void) 21 | { 22 | double x, y, z; 23 | 24 | printf("Enter three numbers: "); 25 | scanf("%lf%lf%lf", &x, &y, &z); 26 | printf("Average of %g and %g: %g\n", x, y, average(x, y)); 27 | printf("Average of %g and %g: %g\n", y, z, average(y, z)); 28 | printf("Average of %g and %g: %g\n", x, z, average(x, z)); 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /textbook_code_snippets/quadratic.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* quadratic.c (Chapter 27, page 723) */ 11 | /* Finds the roots of the equation 5x**2 + 2x + 1 = 0 */ 12 | 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | double a = 5, b = 2, c = 1; 19 | double complex discriminant_sqrt = csqrt(b * b - 4 * a * c); 20 | double complex root1 = (-b + discriminant_sqrt) / (2 * a); 21 | double complex root2 = (-b - discriminant_sqrt) / (2 * a); 22 | 23 | printf("root1 = %g + %gi\n", creal(root1), cimag(root1)); 24 | printf("root2 = %g + %gi\n", creal(root2), cimag(root2)); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /textbook_code_snippets/word.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* word.h (Chapter 15, page 361) */ 11 | 12 | #ifndef WORD_H 13 | #define WORD_H 14 | 15 | /********************************************************** 16 | * read_word: Reads the next word from the input and * 17 | * stores it in word. Makes word empty if no * 18 | * word could be read because of end-of-file. * 19 | * Truncates the word if its length exceeds * 20 | * len. * 21 | **********************************************************/ 22 | void read_word(char *word, int len); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /textbook_code_snippets/readline.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* readline.h (Chapter 16, page 395) */ 11 | 12 | #ifndef READLINE_H 13 | #define READLINE_H 14 | 15 | /********************************************************** 16 | * read_line: Skips leading white-space characters, then * 17 | * reads the remainder of the input line and * 18 | * stores it in str. Truncates the line if its * 19 | * length exceeds n. Returns the number of * 20 | * characters stored. * 21 | **********************************************************/ 22 | int read_line(char str[], int n); 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /textbook_code_snippets/trand.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* trand.c (Chapter 26, page 687) */ 11 | /* Tests the pseudo-random sequence generation functions */ 12 | 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | int i, seed; 19 | 20 | printf("This program displays the first five values of " 21 | "rand.\n"); 22 | 23 | for (;;) { 24 | for (i = 0; i < 5; i++) 25 | printf("%d ", rand()); 26 | printf("\n\n"); 27 | printf("Enter new seed value (0 to terminate): "); 28 | scanf("%d", &seed); 29 | if (seed == 0) 30 | break; 31 | srand(seed); 32 | } 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /ch08/projects/15.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Caesar Cipher */ 4 | 5 | void encode(char *const chr_ptr, short int shift_amount); 6 | 7 | int main() { 8 | char cur = '\0', message[100] = {}; 9 | char *const message_pointer = (char *const) &message; 10 | short int i, n; 11 | 12 | printf("Enter message to be encrypted: "); 13 | for (i = 0; cur != '\n'; i++) { 14 | cur = getchar(); 15 | message[i] = cur; 16 | } 17 | printf("Enter shift amount (1-25): "); 18 | scanf("%hd", &n); 19 | 20 | /* implement the encrypting */ 21 | for (; i >= 0; i--) { 22 | // at the end of last loop, `i` holds the number of `char`s in message minus 1 23 | encode(message_pointer + i, n); 24 | } 25 | 26 | printf("Encrypted message: %s\n", message); 27 | 28 | return 0; 29 | } 30 | 31 | /* implementation */ 32 | 33 | void encode(char *const chr_ptr, short int shift_amount) { 34 | if (*chr_ptr >= 'a' && *chr_ptr <= 'z') { 35 | *chr_ptr = ((*chr_ptr - 'a') + shift_amount) % 26 + 'a'; 36 | } 37 | else if (*chr_ptr >= 'A' && *chr_ptr <= 'Z') { 38 | *chr_ptr = ((*chr_ptr - 'A') + shift_amount) % 26 + 'A'; 39 | } 40 | } -------------------------------------------------------------------------------- /ch04/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int get_check_digit(int digits[12]); 4 | 5 | int main() 6 | { 7 | int ean_digits[12], i; 8 | 9 | printf("Enter the first 12 digits of an EAN: "); 10 | for (i = 0; i < 12; i++) 11 | { 12 | scanf("%1d", &ean_digits[i]); 13 | } 14 | 15 | printf("Check digit: %d\n", get_check_digit(ean_digits)); 16 | 17 | return 0; 18 | } 19 | 20 | /* Implementations */ 21 | int get_check_digit(int digits[12]) 22 | { 23 | int res = 0, i; 24 | 25 | // add the second, fourth, sixth, eighth, tenth, and twelfth digits 26 | for (i = 1; i <= 11; i += 2) 27 | { 28 | res += digits[i]; 29 | } 30 | // multiply it by 3 31 | res *= 3; 32 | // add it to the sum of the first, third, fifth, seventh, ninth, and eleven digits 33 | for (i = 0; i <= 10; i += 2) 34 | { 35 | res += digits[i]; 36 | } 37 | // subtract it from the total 38 | res -= 1; 39 | // the remainder when the adjusted total is divided by 10 40 | res %= 10; 41 | // substract the remainder from 9 42 | res = 9 - res; 43 | 44 | return res; 45 | } 46 | 47 | /* 48 | 12 first digits of an EAN sample: 869148426000 49 | */ -------------------------------------------------------------------------------- /ch08/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 8: Arrays 2 | 3 | ## Reading Notes 4 | 5 | - If the array initialiser is shorter than the array, the remaining elements of array are given the value 0: 6 | 7 | ```C 8 | int index_array[128] = {}; 9 | ``` 10 | 11 | - **C99**: Designated initialisers: 12 | 13 | ```C 14 | int arr[15] = { [2] = 29, [9] = 7, [14] = 35 }; 15 | ``` 16 | 17 | - **C99**: Variable-length array 18 | 19 | - An initialiser mixes the element-by-element technique and the designated technique: 20 | 21 | ```C 22 | int c[10] = { 1, 5, 8, 78, [4] = 3, 7, 2, [8] = 6 }; 23 | ``` 24 | 25 | - A trick to calculate length of an array: `(int) sizeof(arr) / sizeof(arr[0])` 26 | - To declare a constant array, start its declaration with `const`. 27 | ### Related Chapters 28 | 29 | - Chapter 12: relationship between arrays and pointers 30 | - Chapter 26: `time`, `srand`, `rand` functions 31 | 32 | ## Exercising Notes 33 | - The most significant projects: 34 | - [project 06](./projects/06.c) & [project 15](./projects/15.c): relationship between string and pointer 35 | - [project 17](./projects/17.c): implement De la Loubère's method to solve `NxN` magic square -------------------------------------------------------------------------------- /textbook_code_snippets/reverse2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* reverse2.c (Chapter 8, page 174) */ 11 | /* Reverses a series of numbers using a variable-length 12 | array - C99 only */ 13 | 14 | #include 15 | 16 | int main(void) 17 | { 18 | int i, n; 19 | 20 | printf("How many numbers do you want to reverse? "); 21 | scanf("%d", &n); 22 | 23 | int a[n]; /* C99 only - length of array depends on n */ 24 | 25 | printf("Enter %d numbers: ", n); 26 | for (i = 0; i < n; i++) 27 | scanf("%d", &a[i]); 28 | 29 | printf("In reverse order:"); 30 | for (i = n - 1; i >= 0; i--) 31 | printf(" %d", a[i]); 32 | printf("\n"); 33 | 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /textbook_code_snippets/prime.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* prime.c (Chapter 9, page 190) */ 11 | /* Tests whether a number is prime */ 12 | 13 | #include /* C99 only */ 14 | #include 15 | 16 | bool is_prime(int n) 17 | { 18 | int divisor; 19 | 20 | if (n <= 1) 21 | return false; 22 | for (divisor = 2; divisor * divisor <= n; divisor++) 23 | if (n % divisor == 0) 24 | return false; 25 | return true; 26 | } 27 | 28 | int main(void) 29 | { 30 | int n; 31 | 32 | printf("Enter a number: "); 33 | scanf("%d", &n); 34 | if (is_prime(n)) 35 | printf("Prime\n"); 36 | else 37 | printf("Not prime\n"); 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /textbook_code_snippets/repdigit.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* repdigit.c (Chapter 8, page 166) */ 11 | /* Checks numbers for repeated digits */ 12 | 13 | #include /* C99 only */ 14 | #include 15 | 16 | int main(void) 17 | { 18 | bool digit_seen[10] = {false}; 19 | int digit; 20 | long n; 21 | 22 | printf("Enter a number: "); 23 | scanf("%ld", &n); 24 | 25 | while (n > 0) { 26 | digit = n % 10; 27 | if (digit_seen[digit]) 28 | break; 29 | digit_seen[digit] = true; 30 | n /= 10; 31 | } 32 | 33 | if (n > 0) 34 | printf("Repeated digit\n"); 35 | else 36 | printf("No repeated digit\n"); 37 | 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /ch08/exercises/10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DIMENSION 8 5 | 6 | int main() 7 | { 8 | int i, j; 9 | 10 | /* intialise back line of upper side */ 11 | char chess_board[DIMENSION][DIMENSION] = { 12 | [0][0] = 'r', 13 | [0][1] = 'n', 14 | [0][2] = 'b', 15 | [0][3] = 'q', 16 | [0][4] = 'k', 17 | }; 18 | for (i = 0; i < 3; i++) 19 | { 20 | chess_board[0][DIMENSION - i - 1] = chess_board[0][i]; 21 | } 22 | 23 | for (i = 0; i < DIMENSION; i++) 24 | { 25 | /* initialise both sides */ 26 | chess_board[1][i] = 'p'; 27 | chess_board[DIMENSION - 2][i] = 'P'; 28 | chess_board[DIMENSION - 1][i] = toupper(chess_board[0][i]); 29 | 30 | /* intialise spaces in between */ 31 | for (j = 2; j < DIMENSION - 2; j++) 32 | { 33 | chess_board[j][i] = ((i + j) % 2 == 0) ? ' ' : (!(i % 2)) ? '.' : '*'; 34 | } 35 | } 36 | 37 | /* print the chessboard out */ 38 | for (i = 0; i < DIMENSION; i++) 39 | { 40 | for (j = 0; j < DIMENSION; j++) 41 | { 42 | printf("%c ", chess_board[i][j]); 43 | } 44 | printf("\n"); 45 | } 46 | 47 | return 0; 48 | } -------------------------------------------------------------------------------- /ch11/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* modified version of `../../ch02/projects/07.c` */ 5 | 6 | void pay_amount(int dollars, int *twenties, int *tens, int *fives, int *ones) { 7 | if (dollars < 0) { 8 | printf("INVALID INPUT!\n"); 9 | exit(EXIT_FAILURE); 10 | } 11 | else { 12 | *twenties = dollars / 20; 13 | dollars %= 20; 14 | *tens = dollars / 10; 15 | dollars %= 10; 16 | *fives = dollars / 5; 17 | dollars %= 5; 18 | *ones = dollars; 19 | } 20 | } 21 | 22 | int main() 23 | { 24 | /* 25 | Number of $20 bills -> num_of_bills[0] 26 | Number of $10 bills -> num_of_bills[1] 27 | Number of $5 bills -> num_of_bills[2] 28 | Number of $1 bills -> num_of_bills[3] 29 | */ 30 | int amount, num_of_bills[4]; 31 | const int BILLS[4] = {20, 10, 5, 1}; 32 | 33 | printf("Enter a dollar amount: "); 34 | scanf("%d", &amount); 35 | printf("\n"); 36 | 37 | pay_amount(amount, num_of_bills + 0, num_of_bills + 1, num_of_bills + 2, num_of_bills + 3); 38 | 39 | for (int i = 0; i < 4; i++) 40 | { 41 | printf("$%-2d bills: %d\n", BILLS[i], num_of_bills[i]); 42 | } 43 | 44 | return 0; 45 | } -------------------------------------------------------------------------------- /textbook_code_snippets/dweight2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* dweight2.c (Chapter 2, page 23) */ 11 | /* Computes the dimensional weight of a 12 | box from input provided by the user */ 13 | 14 | #include 15 | 16 | int main(void) 17 | { 18 | int height, length, width, volume, weight; 19 | 20 | printf("Enter height of box: "); 21 | scanf("%d", &height); 22 | printf("Enter length of box: "); 23 | scanf("%d", &length); 24 | printf("Enter width of box: "); 25 | scanf("%d", &width); 26 | volume = height * length * width; 27 | weight = (volume + 165) / 166; 28 | 29 | printf("Volume (cubic inches): %d\n", volume); 30 | printf("Dimensional weight (pounds): %d\n", weight); 31 | 32 | return 0; 33 | } 34 | -------------------------------------------------------------------------------- /ch11/projects/04.c: -------------------------------------------------------------------------------- 1 | #include "poker.h" 2 | 3 | /* modified version of `../../ch10/projects/03-05.c` */ 4 | 5 | /* Ranks: 2 3 4 5 6 7 8 9 t j q k a 6 | * Suits: c d h s 7 | * 8 | * Royal flush: ace, king, queen, jack, ten of the same suit 9 | * Straight flush: both a straight and a flush 10 | * Four-of-a-kind: four cards of the same rank 11 | * Full house: a three of a kind and a pair 12 | * Flush: five cards of the same suit 13 | * Straight: five cards with consecutive ranks (ace-low straight included) 14 | * Three-of-a-kind: three cards of the sam rank 15 | * Two pairs 16 | * Pair: two cards of the same rank 17 | * High card: any other hand 18 | * */ 19 | int main() 20 | { 21 | int pairs, hand[5][2] = {}; 22 | bool royal, straight, flush, four, three; 23 | 24 | for (;;) { 25 | read_cards(hand); 26 | analyse_hand(hand, &royal, &straight, &flush, &four, &three, &pairs); 27 | print_result(&royal, &straight, &flush, &four, &three, &pairs); 28 | } 29 | } 30 | 31 | //struct HandClassification 32 | //{ 33 | // bool royal_flush; 34 | // bool straight; 35 | // bool flush; 36 | // bool four; 37 | // bool three; 38 | // int pairs; 39 | //}; 40 | 41 | 42 | -------------------------------------------------------------------------------- /textbook_code_snippets/justify.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* justify.c (Chapter 15, page 363) */ 11 | /* Formats a file of text */ 12 | 13 | #include 14 | #include "line.h" 15 | #include "word.h" 16 | 17 | #define MAX_WORD_LEN 20 18 | 19 | int main(void) 20 | { 21 | char word[MAX_WORD_LEN+2]; 22 | int word_len; 23 | 24 | clear_line(); 25 | for (;;) { 26 | read_word(word, MAX_WORD_LEN+1); 27 | word_len = strlen(word); 28 | if (word_len == 0) { 29 | flush_line(); 30 | return 0; 31 | } 32 | if (word_len > MAX_WORD_LEN) 33 | word[MAX_WORD_LEN] = '*'; 34 | if (word_len + 1 > space_remaining()) { 35 | write_line(); 36 | clear_line(); 37 | } 38 | add_word(word); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /textbook_code_snippets/tsetjmp.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tsetjmp.c (Chapter 24, page 636) */ 11 | /* Tests setjmp/longjmp */ 12 | 13 | #include 14 | #include 15 | 16 | jmp_buf env; 17 | 18 | void f1(void); 19 | void f2(void); 20 | 21 | int main(void) 22 | { 23 | if (setjmp(env) == 0) 24 | printf("setjmp returned 0\n"); 25 | else { 26 | printf("Program terminates: longjmp called\n"); 27 | return 0; 28 | } 29 | 30 | f1(); 31 | printf("Program terminates normally\n"); 32 | return 0; 33 | } 34 | 35 | void f1(void) 36 | { 37 | printf("f1 begins\n"); 38 | f2(); 39 | printf("f1 returns\n"); 40 | } 41 | 42 | void f2(void) 43 | { 44 | printf("f2 begins\n"); 45 | longjmp(env, 1); 46 | printf("f2 returns\n"); 47 | } 48 | -------------------------------------------------------------------------------- /textbook_code_snippets/planet.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* planet.c (Chapter 13, page 304) */ 11 | /* Checks planet names */ 12 | 13 | #include 14 | #include 15 | 16 | #define NUM_PLANETS 9 17 | 18 | int main(int argc, char *argv[]) 19 | { 20 | char *planets[] = {"Mercury", "Venus", "Earth", 21 | "Mars", "Jupiter", "Saturn", 22 | "Uranus", "Neptune", "Pluto"}; 23 | int i, j; 24 | 25 | for (i = 1; i < argc; i++) { 26 | for (j = 0; j < NUM_PLANETS; j++) 27 | if (strcmp(argv[i], planets[j]) == 0) { 28 | printf("%s is planet %d\n", argv[i], j + 1); 29 | break; 30 | } 31 | if (j == NUM_PLANETS) 32 | printf("%s is not a planet\n", argv[i]); 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /textbook_code_snippets/stackclient.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackclient.c (Chapter 19, page 494) */ 11 | 12 | #include 13 | #include "stackADT.h" 14 | 15 | int main(void) 16 | { 17 | Stack s1, s2; 18 | int n; 19 | 20 | s1 = create(); 21 | s2 = create(); 22 | 23 | push(s1, 1); 24 | push(s1, 2); 25 | 26 | n = pop(s1); 27 | printf("Popped %d from s1\n", n); 28 | push(s2, n); 29 | n = pop(s1); 30 | printf("Popped %d from s1\n", n); 31 | push(s2, n); 32 | 33 | destroy(s1); 34 | 35 | while (!is_empty(s2)) 36 | printf("Popped %d from s2\n", pop(s2)); 37 | 38 | push(s2, 3); 39 | make_empty(s2); 40 | if (is_empty(s2)) 41 | printf("s2 is empty\n"); 42 | else 43 | printf("s2 is not empty\n"); 44 | 45 | destroy(s2); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /ch08/projects/14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Reverse the words in a sentence */ 5 | 6 | int main() { 7 | char cur = '\0', sentence[100][100] = {}; 8 | short int i, j; 9 | 10 | printf("Enter a sentence: "); 11 | /* Iteratively scan input and store it as array of words. 12 | * At the end of this loop, number of words in the sentence equals `j` minus 1 13 | * */ 14 | for (i = 0, j = 0; cur != '\n';) { 15 | cur = getchar(); 16 | if (isspace(cur)) { 17 | // signify the end of the word being reading 18 | sentence[j][i] = '\0'; 19 | // reset counter for character index in the word being scanning 20 | i = 0; 21 | // increase counter for number of words 22 | j++; 23 | } 24 | else { 25 | sentence[j][i++] = cur; 26 | } 27 | } 28 | 29 | /* Print the sentence out in reverse */ 30 | for (i = j; i >= 0; i--) { 31 | if (sentence[i][0] != '\0') { 32 | for (j = 0; sentence[i][j] != '\0'; j++) { 33 | printf("%c", sentence[i][j]); 34 | } 35 | printf(" "); 36 | } 37 | else { 38 | continue; 39 | } 40 | } 41 | printf("\n"); 42 | 43 | return 0; 44 | } 45 | 46 | // Test case: "you can cage a swallow can't you" -> "you can't swallow a cage can you" -------------------------------------------------------------------------------- /ch11/exercises/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void find_two_largest(int n, int a[n], int *const largest, int *const second_largest) { 5 | *largest = *second_largest = a[0]; 6 | for (int i = 1; i < n; i++) { 7 | // if the current element is larger than the current largest 8 | if (*largest < a[i]) { 9 | *second_largest = *largest; 10 | *largest = a[i]; 11 | } 12 | // if the current element is in between the current second largest and the current largest 13 | else { 14 | if (*second_largest < a[i]) { 15 | *second_largest = a[i]; 16 | } 17 | } 18 | } 19 | } 20 | 21 | int main() { 22 | int len, max, max1; 23 | 24 | printf("The length of the array? "); 25 | scanf("%d", &len); 26 | 27 | if (len <= 0) { 28 | printf("INVALID INPUT!"); 29 | return 1; 30 | } 31 | else { 32 | int *arr = (int *) malloc(len * sizeof(int)); 33 | 34 | printf("Enter array (each element separated by a blank space): "); 35 | for (int i = 0; i < len; i++) { 36 | scanf(" %d", arr+i); 37 | } 38 | 39 | find_two_largest(len, arr, &max, &max1); 40 | 41 | printf("The largest element: %d; The second largest element: %d\n", max, max1); 42 | 43 | free(arr); 44 | return 0; 45 | } 46 | } -------------------------------------------------------------------------------- /ch07/projects/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /** 5 | * Naively simplified arithmetic expression parser 6 | * Expresion evaluation is left-associative 7 | * & no operator takes precedence over any other operator 8 | * */ 9 | 10 | int main() 11 | { 12 | float cur = 0.0f, res = 0.0f; 13 | char chr; 14 | 15 | printf("Enter an expression: "); 16 | // initialise `res` with the first operand of the input expression 17 | scanf("%f", &res); 18 | 19 | // consume chars being the in buffer using `getchar` calls 20 | while ((chr = getchar()) != '\n') 21 | { 22 | // at this point, operator character at the head of buffer was already 23 | // removed out of the buffer & stored in `chr` 24 | switch (chr) 25 | { 26 | case '+': 27 | scanf("%f", &cur); 28 | res += cur; 29 | break; 30 | case '-': 31 | scanf("%f", &cur); 32 | res -= cur; 33 | break; 34 | case '*': 35 | scanf("%f", &cur); 36 | res *= cur; 37 | break; 38 | case '/': 39 | scanf("%f", &cur); 40 | res /= cur; 41 | break; 42 | default: 43 | // if is not an operator, skip! 44 | continue; 45 | } 46 | } 47 | 48 | printf("Value of expression: %.2f", res); 49 | 50 | return 0; 51 | } -------------------------------------------------------------------------------- /ch11/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Ask the user to input a fraction, return the fraction to lowest terms 4 | * modified version of `../../ch06/projects/03.c`*/ 5 | 6 | /* After this function is called, `*reduced_numerator` is the GCD */ 7 | void reduce(int numerator 8 | ,int denominator 9 | ,int *const reduced_numerator 10 | ,int *const reduced_denominator) { 11 | int temp; 12 | 13 | for (*reduced_denominator = denominator 14 | ,*reduced_numerator = numerator 15 | ;*reduced_denominator != 0 16 | ;) { 17 | temp = *reduced_numerator % *reduced_denominator; 18 | *reduced_numerator = *reduced_denominator; 19 | *reduced_denominator = temp; 20 | 21 | /* to see visualisation of this process, uncomment the next line */ 22 | // printf("first num = %d, second num = %d\n", *reduced_numerator, *b); 23 | } 24 | } 25 | 26 | int main() { 27 | int m, n; 28 | printf("Enter the fraction: "); 29 | scanf("%d/%d", &m, &n); 30 | 31 | if (n == 0) { 32 | printf("DENOMINATOR HAS TO BE NON-ZERO!\n"); 33 | return 1; 34 | } 35 | else { 36 | int tmp_m, tmp_n; 37 | reduce(m, n, &tmp_m, &tmp_n); 38 | 39 | printf("In lowest terms: %d/%d\n", m / tmp_m, n / tmp_m); 40 | return 0; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /textbook_code_snippets/upc.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* upc.c (Chapter 4, page 57) */ 11 | /* Computes a Universal Product Code check digit */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int d, i1, i2, i3, i4, i5, j1, j2, j3, j4, j5, 18 | first_sum, second_sum, total; 19 | 20 | printf("Enter the first (single) digit: "); 21 | scanf("%1d", &d); 22 | printf("Enter first group of five digits: "); 23 | scanf("%1d%1d%1d%1d%1d", &i1, &i2, &i3, &i4, &i5); 24 | printf("Enter second group of five digits: "); 25 | scanf("%1d%1d%1d%1d%1d", &j1, &j2, &j3, &j4, &j5); 26 | 27 | first_sum = d + i2 + i4 + j1 + j3 + j5; 28 | second_sum = i1 + i3 + i5 + j2 + j4; 29 | total = 3 * first_sum + second_sum; 30 | 31 | printf("Check digit: %d\n", 9 - ((total - 1) % 10)); 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /ch06/projects/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define DAYS_PER_WEEK 7 3 | 4 | int main() 5 | { 6 | int days, starting_week_day, i; 7 | 8 | /* 9 | A line need to display only `DAYS_PER_WEEK` piece of info, 10 | which can be padding space (2 spaces) or a number. 11 | 12 | `cursor` helps to keep track of how many piece of info has been displayed in a line: 13 | When a piece of info is display, 14 | update `cursor` respectively by substracting 1 from it. 15 | `cursor` equalling 0 signifies printing of new line 16 | & resetting of `cursor` to its intial value (`DAYS_PER_WEEK`). 17 | */ 18 | int cursor = DAYS_PER_WEEK; 19 | 20 | printf("Enter number of days in month: "); 21 | scanf("%d", &days); 22 | printf("Enter starting days of the week: "); 23 | scanf("%d", &starting_week_day); 24 | printf("\n"); 25 | 26 | /* print 3 padding spaces for `starting_week_day - 1` times */ 27 | for (i = starting_week_day - 2; i >= 0; i--) 28 | { 29 | cursor -= 1; 30 | printf(" "); 31 | } 32 | 33 | for (i = 1; i <= days; i++) 34 | { 35 | cursor -= 1; 36 | printf("%2d %c", i, cursor == 0 ? '\n' : '\0'); 37 | if (cursor == 0) 38 | // reset the cursor 39 | cursor = DAYS_PER_WEEK; 40 | } 41 | printf("\n"); 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /ch08/projects/16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Check If Two Strings Are Anagrams */ 6 | 7 | int main() { 8 | bool res; 9 | int i, cur = '\0', char_indexes[(int) 'z' + 1] = {}; 10 | 11 | /* Counting the number of occurrences of each alphabet character in the first input */ 12 | printf("Enter first word: "); 13 | for (; cur != '\n';) { 14 | cur = getchar(); 15 | if (isalpha(cur)) { 16 | char_indexes[(int) tolower(cur)]++; 17 | } 18 | } 19 | 20 | /* Using the same counter array, but decrement count value for alphabet characters encountered */ 21 | printf("Enter second word: "); 22 | for (cur = '\0'; cur != '\n';) { 23 | cur = getchar(); 24 | if (isalpha(cur)) { 25 | char_indexes[(int) tolower(cur)]--; 26 | } 27 | } 28 | 29 | /* If a letter's number of occurrences in first input 30 | * is different to that of its counterpart in second input, 31 | * then both string are not anagrams */ 32 | for (i = (int) 'a', res = true; i <= 'z'; i++) { 33 | if (char_indexes[i] != 0) { 34 | // printf("anomaly: %c \n", i, char_indexes[i]); 35 | res = false; 36 | break; 37 | } 38 | } 39 | printf("The words are %s.\n", res ? "anagrams" : "not anagrams"); 40 | 41 | return 0; 42 | } -------------------------------------------------------------------------------- /textbook_code_snippets/maxmin.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* maxmin.c (Chapter 11, page 250) */ 11 | /* Finds the largest and smallest elements in an array */ 12 | 13 | #include 14 | 15 | #define N 10 16 | 17 | void max_min(int a[], int n, int *max, int *min); 18 | 19 | int main(void) 20 | { 21 | int b[N], i, big, small; 22 | 23 | printf("Enter %d numbers: ", N); 24 | for (i = 0; i < N; i++) 25 | scanf("%d", &b[i]); 26 | 27 | max_min(b, N, &big, &small); 28 | 29 | printf("Largest: %d\n", big); 30 | printf("Smallest: %d\n", small); 31 | 32 | return 0; 33 | } 34 | 35 | void max_min(int a[], int n, int *max, int *min) 36 | { 37 | int i; 38 | 39 | *max = *min = a[0]; 40 | for (i = 1; i < n; i++) { 41 | if (a[i] > *max) 42 | *max = a[i]; 43 | else if (a[i] < *min) 44 | *min = a[i]; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ch07/projects/13.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Calculate average word length of a sentence */ 4 | 5 | int main() 6 | { 7 | char chr; 8 | int i, num_words, num_chars; 9 | float res; 10 | 11 | printf("Enter a sentence: "); 12 | 13 | for (i = 0, num_words = 0, num_chars = 0; 14 | (chr = getchar()) != '\n';) 15 | { 16 | // printf("This char: %c; ", chr); 17 | 18 | /* ' ' and '.' signify end of a word */ 19 | if ((chr == ' ') || (chr == '.')) 20 | { 21 | // printf("i = %d; ", i); 22 | 23 | /* `i` holds the length of the traversed word */ 24 | num_chars += i; 25 | // printf("res = %d; ", num_chars); 26 | 27 | /* `num_words` holds the number of words counted */ 28 | num_words += 1; 29 | // printf("count = %d; ", num_words); 30 | 31 | /* reset `i` */ 32 | i = 0; 33 | 34 | // printf("Encountered a word end.\n"); 35 | } 36 | else 37 | { 38 | /* counting number of chars of a word */ 39 | i += 1; 40 | 41 | // printf("Still counting.\n"); 42 | } 43 | } 44 | printf("\n"); 45 | 46 | printf("Total num of chars: %d; Total num of words: %d\n", num_chars, num_words); 47 | res = (float)num_chars; 48 | res /= (float)num_words; 49 | 50 | printf("Average word length: %.2f\n", res); 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /ch10/projects/poker_02.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | #ifndef C_PROGRAMMING_A_MODERN_APPROACH_POKER_02_H 11 | 12 | /* Reads the cards into the external variables `num_in_rank` and `num_in_suit`; 13 | * checks for bad cards and duplicate cards. 14 | */ 15 | void read_cards(int hand[5][2]); 16 | 17 | /* Determines whether the hand contains a straight, a flush, four-of-a-kind, 18 | * and/or three-of-a-kind; determines the number of pairs; stores the results into 19 | * the external variables straight, flush, four, three, and pairs. 20 | */ 21 | void analyse_hand(int hand[5][2]); 22 | 23 | /* Prints the classification of the hand, based on the values of the external 24 | * variables straight, flush, four, three, and pairs. 25 | */ 26 | void print_result(); 27 | 28 | #define C_PROGRAMMING_A_MODERN_APPROACH_POKER_02_H 29 | 30 | #endif //C_PROGRAMMING_A_MODERN_APPROACH_POKER_02_H 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/fcopy.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* fcopy.c (Chapter 22, page 568) */ 11 | /* Copies a file */ 12 | 13 | #include 14 | #include 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | FILE *source_fp, *dest_fp; 19 | int ch; 20 | 21 | if (argc != 3) { 22 | fprintf(stderr, "usage: fcopy source dest\n"); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | if ((source_fp = fopen(argv[1], "rb")) == NULL) { 27 | fprintf(stderr, "Can't open %s\n", argv[1]); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | if ((dest_fp = fopen(argv[2], "wb")) == NULL) { 32 | fprintf(stderr, "Can't open %s\n", argv[2]); 33 | fclose(source_fp); 34 | exit(EXIT_FAILURE); 35 | } 36 | 37 | while ((ch = getc(source_fp)) != EOF) 38 | putc(ch, dest_fp); 39 | 40 | fclose(source_fp); 41 | fclose(dest_fp); 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /ch03/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Magic Square */ 4 | 5 | int main() 6 | { 7 | int nums[16], sums[4]; 8 | 9 | printf("Enter the numbers from 1 to 16 in any order: "); 10 | for (int i = 15; i >= 0; i--) 11 | { 12 | /* sample input: 13 | 16 3 2 13 5 10 11 8 9 6 7 12 4 15 14 1 14 | */ 15 | scanf("%d", &nums[i]); 16 | } 17 | printf("\n"); 18 | 19 | for (int i = 15; i >= 3; i -= 4) 20 | { 21 | printf("%3d%3d%3d%3d\n", nums[i], nums[i - 1], nums[i - 2], nums[i - 3]); 22 | 23 | // calculate row sums and store in `sums` 24 | sums[(15 - i) / 4] = nums[i] + nums[i - 1] + nums[i - 2] + nums[i - 3]; 25 | } 26 | printf("\n"); 27 | 28 | printf("Row sums: "); 29 | for (int i = 0; i <= 3; i++) 30 | { 31 | printf(" %d", sums[i]); 32 | 33 | // calculate sum of column 1 and store in sums[i] 34 | sums[i] = nums[i] + nums[i + 4] + nums[i + 8] + nums[i + 12]; 35 | } 36 | printf("\n"); 37 | 38 | printf("Colums sums: "); 39 | for (int i = 0; i <= 3; i++) { 40 | printf(" %d", sums[i]); 41 | } 42 | printf("\n"); 43 | 44 | // use sums[0] and sums[1] to store the two diagonal sums 45 | sums[0] = nums[0] + nums[5] + nums[10] + nums[15]; 46 | sums[1] = nums[3] + nums[6] + nums[9] + nums[12]; 47 | printf("Diagonal sums: %d %d\n", sums[0], sums[1]); 48 | 49 | return 0; 50 | } -------------------------------------------------------------------------------- /ch12/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Reverse the words in a sentence 5 | * modified version of `../../ch08/projects/14.c` 6 | */ 7 | 8 | int main() { 9 | char cur = '\0', sentence[100][100] = {}; 10 | short int i, j; 11 | 12 | printf("Enter a sentence: "); 13 | /* Iteratively scan input and store it as array of words. 14 | * At the end of this loop, number of words in the sentence equals `j` minus 1 15 | */ 16 | for (i = 0, j = 0; cur != '\n';) { 17 | cur = getchar(); 18 | if (isspace(cur)) { 19 | // signify the end of the word being reading 20 | sentence[j][i] = '\0'; 21 | // reset counter for character index in the word being scanning 22 | i = 0; 23 | // increase counter for number of words 24 | j++; 25 | } 26 | else { 27 | sentence[j][i++] = cur; 28 | } 29 | } 30 | 31 | /* Print the sentence out in reverse */ 32 | for (i = j; i >= 0; i--) { 33 | if (*(sentence[i]) != '\0') { 34 | for (char *j_ptr = sentence[i]; *j_ptr != '\0' ;j_ptr++) { 35 | printf("%c", *j_ptr); 36 | } 37 | printf(" "); 38 | } 39 | else { 40 | continue; 41 | } 42 | } 43 | printf("\n"); 44 | 45 | return 0; 46 | } 47 | 48 | // Test case: "you can cage a swallow can't you" -> "you can't swallow a cage can you" 49 | 50 | -------------------------------------------------------------------------------- /textbook_code_snippets/stack1.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stack1.c (Chapter 19, page 488) */ 11 | 12 | #include 13 | #include 14 | #include "stack.h" 15 | 16 | #define STACK_SIZE 100 17 | 18 | static int contents[STACK_SIZE]; 19 | static int top = 0; 20 | 21 | static void terminate(const char *message) 22 | { 23 | printf("%s\n", message); 24 | exit(EXIT_FAILURE); 25 | } 26 | 27 | void make_empty(void) 28 | { 29 | top = 0; 30 | } 31 | 32 | bool is_empty(void) 33 | { 34 | return top == 0; 35 | } 36 | 37 | bool is_full(void) 38 | { 39 | return top == STACK_SIZE; 40 | } 41 | 42 | void push(int i) 43 | { 44 | if (is_full()) 45 | terminate("Error in push: stack is full."); 46 | contents[top++] = i; 47 | } 48 | 49 | int pop(void) 50 | { 51 | if (is_empty()) 52 | terminate("Error in pop: stack is empty."); 53 | return contents[--top]; 54 | } 55 | -------------------------------------------------------------------------------- /textbook_code_snippets/tsignal.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tsignal.c (Chapter 24, page 634) */ 11 | /* Tests signals */ 12 | 13 | #include 14 | #include 15 | 16 | void handler(int sig); 17 | void raise_sig(void); 18 | 19 | int main(void) 20 | { 21 | void (*orig_handler)(int); 22 | 23 | printf("Installing handler for signal %d\n", SIGINT); 24 | orig_handler = signal(SIGINT, handler); 25 | raise_sig(); 26 | 27 | printf("Changing handler to SIG_IGN\n"); 28 | signal(SIGINT, SIG_IGN); 29 | raise_sig(); 30 | 31 | printf("Restoring original handler\n"); 32 | signal(SIGINT, orig_handler); 33 | raise_sig(); 34 | 35 | printf("Program terminates normally\n"); 36 | return 0; 37 | } 38 | 39 | void handler(int sig) 40 | { 41 | printf("Handler called for signal %d\n", sig); 42 | } 43 | 44 | void raise_sig(void) 45 | { 46 | raise(SIGINT); 47 | } 48 | -------------------------------------------------------------------------------- /ch10/projects/poker_01.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | #ifndef C_PROGRAMMING_A_MODERN_APPROACH_POKER_H 11 | 12 | /* Reads the cards into `num_in_rank` and `num_in_suit`; 13 | * checks for bad cards and duplicate cards. 14 | */ 15 | void read_cards(int *const num_in_rank, int *const num_in_suit); 16 | 17 | /* Determines whether the hand contains a straight, a flush, four-of-a-kind, 18 | * and/or three-of-a-kind; determines the number of pairs; stores the results into 19 | * the external variables straight, flush, four, three, and pairs. 20 | */ 21 | void analyse_hand(int *const num_in_rank, int *const num_in_suit); 22 | 23 | /* Prints the classification of the hand, based on the values of the external 24 | * variables straight, flush, four, three, and pairs. 25 | */ 26 | void print_result(); 27 | 28 | #define C_PROGRAMMING_A_MODERN_APPROACH_POKER_H 29 | 30 | #endif //C_PROGRAMMING_A_MODERN_APPROACH_POKER_H 31 | -------------------------------------------------------------------------------- /textbook_code_snippets/broker.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* broker.c (Chapter 5, page 81) */ 11 | /* Calculates a broker's commission */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | float commission, value; 18 | 19 | printf("Enter value of trade: "); 20 | scanf("%f", &value); 21 | 22 | if (value < 2500.00f) 23 | commission = 30.00f + .017f * value; 24 | else if (value < 6250.00f) 25 | commission = 56.00f + .0066f * value; 26 | else if (value < 20000.00f) 27 | commission = 76.00f + .0034f * value; 28 | else if (value < 50000.00f) 29 | commission = 100.00f + .0022f * value; 30 | else if (value < 500000.00f) 31 | commission = 155.00f + .0011f * value; 32 | else 33 | commission = 255.00f + .0009f * value; 34 | 35 | if (commission < 39.00f) 36 | commission = 39.00f; 37 | 38 | printf("Commission: $%.2f\n", commission); 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /ch09/projects/02.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* the same source code as `../../ch05/projects/05.c` */ 4 | 5 | float get_tax(float income); 6 | 7 | int main() 8 | { 9 | float income; 10 | 11 | printf("Enter your taxable income: "); 12 | scanf("%f", &income); 13 | 14 | printf("Tax due: %.2f\n", get_tax(income)); 15 | 16 | return 0; 17 | } 18 | 19 | /* implementation */ 20 | 21 | float get_tax(float income) 22 | { 23 | const int RANGES[5] = {750, 2250, 3750, 5250, 7000}; 24 | float base, ratio, surplus; 25 | 26 | if (income < RANGES[0]) 27 | { 28 | base = 0; 29 | ratio = .01; 30 | surplus = 0; 31 | } 32 | else if (income >= RANGES[0] && income < RANGES[1]) 33 | { 34 | base = 7.50; 35 | ratio = .02; 36 | surplus = income - RANGES[0]; 37 | } 38 | else if (income >= RANGES[1] && income < RANGES[2]) 39 | { 40 | base = 37.50; 41 | ratio = .03; 42 | surplus = income - RANGES[1]; 43 | } 44 | else if (income >= RANGES[2] && income < RANGES[3]) 45 | { 46 | base = 82.50; 47 | ratio = .04; 48 | surplus = income - RANGES[2]; 49 | } 50 | else if (income >= RANGES[3] && income < RANGES[4]) 51 | { 52 | base = 142.50; 53 | ratio = .05; 54 | surplus = income - RANGES[3]; 55 | } 56 | else 57 | { 58 | base = 230.00; 59 | ratio = .06; 60 | surplus = income - RANGES[4]; 61 | } 62 | 63 | return base + ratio * surplus; 64 | } 65 | -------------------------------------------------------------------------------- /ch10/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stack_int.h" 3 | 4 | /* Reverse Polish Notation calculator 5 | * to run this program, compile both this file, `stack_int.h` and `stack_int.c` 6 | * */ 7 | 8 | int main () { 9 | char cur; 10 | int tmp; 11 | 12 | for (;;) { 13 | printf("Enter an RPN expression: "); 14 | intstack_make_empty(); 15 | for (tmp = 0, cur = '\0'; cur != '\n'; ) { 16 | scanf(" %c", &cur); 17 | 18 | if (cur >= '0' && cur <= '9') { 19 | intstack_push(cur - '0'); 20 | } 21 | else if (cur == '+' || cur == '-' || cur == '*' || cur == '/') { 22 | tmp = intstack_pop(); 23 | 24 | switch (cur) { 25 | case '+': 26 | tmp += intstack_pop(); 27 | break; 28 | case '-': 29 | tmp = intstack_pop() - tmp; 30 | break; 31 | case '*': 32 | tmp *= intstack_pop(); 33 | break; 34 | case '/': 35 | tmp = intstack_pop() / tmp; 36 | break; 37 | } 38 | 39 | intstack_push(tmp); 40 | } 41 | else if (cur == '=') { 42 | // if no '=' is read yet, persist current stack for the next expression input 43 | printf("Value of expression: %d\n", intstack_is_empty() ? 0 : intstack_current_top()); 44 | break; 45 | } 46 | else { 47 | return 0; 48 | } 49 | } 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /ch05/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Ask user to enter the amount of taxable income, then displays the tax due */ 4 | 5 | float get_tax(float income); 6 | 7 | int main() 8 | { 9 | float income; 10 | 11 | printf("Enter your taxable income: "); 12 | scanf("%f", &income); 13 | 14 | printf("Tax due: %.2f\n", get_tax(income)); 15 | 16 | return 0; 17 | } 18 | 19 | /* implementation */ 20 | 21 | float get_tax(float income) 22 | { 23 | const int RANGES[5] = {750, 2250, 3750, 5250, 7000}; 24 | float base, ratio, surplus; 25 | 26 | if (income < RANGES[0]) 27 | { 28 | base = 0; 29 | ratio = .01; 30 | surplus = 0; 31 | } 32 | else if (income >= RANGES[0] && income < RANGES[1]) 33 | { 34 | base = 7.50; 35 | ratio = .02; 36 | surplus = income - RANGES[0]; 37 | } 38 | else if (income >= RANGES[1] && income < RANGES[2]) 39 | { 40 | base = 37.50; 41 | ratio = .03; 42 | surplus = income - RANGES[1]; 43 | } 44 | else if (income >= RANGES[2] && income < RANGES[3]) 45 | { 46 | base = 82.50; 47 | ratio = .04; 48 | surplus = income - RANGES[2]; 49 | } 50 | else if (income >= RANGES[3] && income < RANGES[4]) 51 | { 52 | base = 142.50; 53 | ratio = .05; 54 | surplus = income - RANGES[3]; 55 | } 56 | else 57 | { 58 | base = 230.00; 59 | ratio = .06; 60 | surplus = income - RANGES[4]; 61 | } 62 | 63 | return base + ratio * surplus; 64 | } -------------------------------------------------------------------------------- /ch11/projects/poker.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | #include 11 | 12 | #ifndef C_PROGRAMMING_A_MODERN_APPROACH_POKER_CH11_H 13 | 14 | /* Reads the cards into the external variables `num_in_rank` and `num_in_suit`; 15 | * checks for bad cards and duplicate cards. 16 | */ 17 | void read_cards(int hand[5][2]); 18 | 19 | /* Determines whether the hand contains a straight, a flush, four-of-a-kind, 20 | * and/or three-of-a-kind; determines the number of pairs; stores the results into 21 | * the variables whose pointers passed into the function. 22 | */ 23 | void analyse_hand(int hand[5][2], bool *royal, bool *straight, bool *flush, bool *four, bool *three, int *pairs); 24 | 25 | /* Prints the classification of the hand 26 | */ 27 | void print_result(bool *royal, bool *straight, bool *flush, bool *four, bool *three, int *pairs); 28 | 29 | 30 | #define C_PROGRAMMING_A_MODERN_APPROACH_POKER_CH11_H 31 | 32 | #endif //C_PROGRAMMING_A_MODERN_APPROACH_POKER_CH11_H 33 | -------------------------------------------------------------------------------- /ch12/projects/02_04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Check if a string is palindrome */ 6 | 7 | int main() { 8 | char *mes = malloc(1000 * sizeof(char)); 9 | 10 | printf("Enter a message: "); 11 | 12 | char cur; 13 | unsigned short i; 14 | for (i = 0;; i++) { 15 | cur = getchar(); 16 | if (cur == '\n') { 17 | break; 18 | } 19 | else { 20 | *(mes + i) = cur; 21 | } 22 | } 23 | 24 | char *i_ptr, *j_ptr, i_chr, j_chr; 25 | for (i_ptr = mes + 0, j_ptr = mes + i - 1; j_ptr >= i_ptr + 1; ) { 26 | if (!isalpha(*i_ptr)) { 27 | i_ptr++; 28 | } 29 | else if (!isalpha(*j_ptr)) { 30 | j_ptr--; 31 | } 32 | else { 33 | i_chr = tolower(*i_ptr); 34 | j_chr = tolower(*j_ptr); 35 | 36 | if (i_chr != j_chr) { 37 | /* prematurely terminate */ 38 | // printf(" compared %c with %c \n", i_chr, j_chr); 39 | printf("Not a palindrome!\n"); 40 | 41 | free(mes); 42 | return 0; 43 | } 44 | else { 45 | // printf(" compared %c with %c \n", i_chr, j_chr); 46 | i_ptr++; 47 | j_ptr--; 48 | } 49 | } 50 | } 51 | // if the program reaches here without being prematurely terminated, then 52 | printf("Palindrome!\n"); 53 | 54 | free(mes); 55 | return 0; 56 | } 57 | 58 | // Test case: "He lived as a devil, eh?" -> True -------------------------------------------------------------------------------- /ch10/projects/stack_char.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack_char.h" 4 | 5 | #define STACK_SIZE 100 6 | 7 | char contents[STACK_SIZE]; 8 | /* position of the stack top */ 9 | int top = 0; 10 | 11 | void stack_overflow() { 12 | // printf("Stack overflow!!!\n"); 13 | printf("Your input is too long!\n"); 14 | exit(EXIT_FAILURE); 15 | } 16 | 17 | void stack_underflow() { 18 | // printf("Stack underflow!!!\n"); 19 | printf("Parentheses/braces are not nested properly!\n"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | void stack_make_empty() { 24 | top = 0; 25 | } 26 | 27 | bool stack_is_empty() { 28 | return top == 0; 29 | } 30 | 31 | bool stack_is_full() { 32 | return top == STACK_SIZE; 33 | } 34 | 35 | int stack_current_top_index() { 36 | return top; 37 | } 38 | 39 | char stack_current_top() { 40 | return contents[top]; 41 | } 42 | 43 | void stack_push(char chr) { 44 | if (stack_is_full()) { 45 | stack_overflow(); 46 | } 47 | else { 48 | /* store the added item in `contents` at the position indicated by `top` 49 | * and then increment `top` */ 50 | contents[top++] = chr; 51 | } 52 | } 53 | 54 | char stack_pop() { 55 | if (stack_is_empty()) { 56 | stack_underflow(); 57 | } 58 | else { 59 | /* popping an item requires decrementing `top`, then using it as an index 60 | * into contents to fetch the item being popped */ 61 | return contents[--top]; 62 | } 63 | } -------------------------------------------------------------------------------- /textbook_code_snippets/tclassify.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tclassify.c (Chapter 23, page 613) */ 11 | /* Tests the character-classification functions */ 12 | 13 | #include 14 | #include 15 | 16 | #define TEST(f) printf(" %c ", f(*p) ? 'x' : ' ') 17 | 18 | int main(void) 19 | { 20 | char *p; 21 | 22 | printf(" alnum cntrl graph print" 23 | " space xdigit\n" 24 | " alpha digit lower punct" 25 | " upper\n"); 26 | 27 | for (p = "azAZ0 !\t"; *p != '\0'; p++) { 28 | if (iscntrl(*p)) 29 | printf("\\x%02x:", *p); 30 | else 31 | printf(" %c:", *p); 32 | TEST(isalnum); 33 | TEST(isalpha); 34 | TEST(iscntrl); 35 | TEST(isdigit); 36 | TEST(isgraph); 37 | TEST(islower); 38 | TEST(isprint); 39 | TEST(ispunct); 40 | TEST(isspace); 41 | TEST(isupper); 42 | TEST(isxdigit); 43 | printf("\n"); 44 | } 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /textbook_code_snippets/invclear.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* invclear.c (Chapter 22, page 574) */ 11 | /* Modifies a file of part records by setting the quantity 12 | on hand to zero for all records */ 13 | 14 | #include 15 | #include 16 | 17 | #define NAME_LEN 25 18 | #define MAX_PARTS 100 19 | 20 | struct part { 21 | int number; 22 | char name[NAME_LEN+1]; 23 | int on_hand; 24 | } inventory[MAX_PARTS]; 25 | 26 | int num_parts; 27 | 28 | int main(void) 29 | { 30 | FILE *fp; 31 | int i; 32 | 33 | if ((fp = fopen("inventory.dat", "rb+")) == NULL) { 34 | fprintf(stderr, "Can't open inventory file\n"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | num_parts = fread(inventory, sizeof(struct part), 39 | MAX_PARTS, fp); 40 | 41 | for (i = 0; i < num_parts; i++) 42 | inventory[i].on_hand = 0; 43 | 44 | rewind(fp); 45 | fwrite(inventory, sizeof(struct part), num_parts, fp); 46 | fclose(fp); 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /textbook_code_snippets/interest.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* interest.c (Chapter 8, page 169) */ 11 | /* Prints a table of compound interest */ 12 | 13 | #include 14 | 15 | #define NUM_RATES ((int) (sizeof(value) / sizeof(value[0]))) 16 | #define INITIAL_BALANCE 100.00 17 | 18 | int main(void) 19 | { 20 | int i, low_rate, num_years, year; 21 | double value[5]; 22 | 23 | printf("Enter interest rate: "); 24 | scanf("%d", &low_rate); 25 | printf("Enter number of years: "); 26 | scanf("%d", &num_years); 27 | 28 | printf("\nYears"); 29 | for (i = 0; i < NUM_RATES; i++) { 30 | printf("%6d%%", low_rate + i); 31 | value[i] = INITIAL_BALANCE; 32 | } 33 | printf("\n"); 34 | 35 | for (year = 1; year <= num_years; year++) { 36 | printf("%3d ", year); 37 | for (i = 0; i < NUM_RATES; i++) { 38 | value[i] += (low_rate + i) / 100.0 * value[i]; 39 | printf("%7.2f", value[i]); 40 | } 41 | printf("\n"); 42 | } 43 | 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /ch07/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /** 6 | * Calculate Scrabble value of a character 7 | */ 8 | int point_of_char(char *const arr_ptr, size_t id); 9 | 10 | int main() 11 | { 12 | 13 | char *input; 14 | size_t str_len; 15 | unsigned int res = 0; 16 | 17 | printf("Enter a word: "); 18 | scanf("%s", input); 19 | 20 | str_len = strlen(input); 21 | for (int i = 0; i < str_len; i++) 22 | { 23 | // accumulate the result 24 | res += point_of_char(input, i); 25 | } 26 | 27 | printf("Scrabble value: %u\n", res); 28 | 29 | return 0; 30 | } 31 | 32 | /* implementation */ 33 | 34 | const int POINTS[7] = {1, 2, 3, 4, 5, 8, 10}; 35 | const char CHARS[7][12] = {"AEILNORSTU\0", 36 | "DG\0", 37 | "BCMP\0", 38 | "FHVWY\0", 39 | "K\0", 40 | "JX\0", 41 | "QZ\0"}; 42 | 43 | int point_of_char(char *const arr_ptr, size_t id) 44 | { 45 | short int i, j; 46 | 47 | // traverse through list of strings in CHARS 48 | for (i = j = 0; i < 7; i++) 49 | { 50 | // traverse through each character of the string of CHARS[i] 51 | for (j = 0; CHARS[i][j] != '\0'; j++) 52 | { 53 | if (toupper(arr_ptr[id]) == CHARS[i][j]) 54 | { 55 | return POINTS[i]; 56 | } 57 | } 58 | } 59 | 60 | /* will never get here */ 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /ch07/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Convert alphabetic phone number into numeric form */ 5 | 6 | /* Convert character to its respective digit */ 7 | void convert_char_to_digit(char *const chr_ptr, int id); 8 | 9 | int main() 10 | { 11 | int len; 12 | char *const phone_number; 13 | 14 | printf("Enter phone number: "); 15 | scanf("%s", phone_number); 16 | len = strlen(phone_number); 17 | 18 | for (int i = 0; i < len; i++) 19 | { 20 | convert_char_to_digit(phone_number, i); 21 | } 22 | 23 | printf("%s\n", phone_number); 24 | 25 | return 0; 26 | } 27 | 28 | /* implementation */ 29 | 30 | void convert_char_to_digit(char *const chr_ptr, int id) 31 | { 32 | if (chr_ptr[id] >= 'A' && chr_ptr[id] <= 'C') 33 | { 34 | chr_ptr[id] = '2'; 35 | } 36 | else if (chr_ptr[id] >= 'D' && chr_ptr[id] <= 'F') 37 | { 38 | chr_ptr[id] = '3'; 39 | } 40 | else if (chr_ptr[id] >= 'G' && chr_ptr[id] <= 'I') 41 | { 42 | chr_ptr[id] = '4'; 43 | } 44 | else if (chr_ptr[id] >= 'J' && chr_ptr[id] <= 'L') 45 | { 46 | chr_ptr[id] = '5'; 47 | } 48 | else if (chr_ptr[id] >= 'M' && chr_ptr[id] <= 'O') 49 | { 50 | chr_ptr[id] = '6'; 51 | } 52 | else if (chr_ptr[id] >= 'P' && chr_ptr[id] <= 'S') 53 | { 54 | chr_ptr[id] = '7'; 55 | } 56 | else if (chr_ptr[id] >= 'T' && chr_ptr[id] <= 'V') 57 | { 58 | chr_ptr[id] = '8'; 59 | } 60 | else if (chr_ptr[id] >= 'W' && chr_ptr[id] <= 'Y') 61 | { 62 | chr_ptr[id] = '9'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ch08/projects/11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* this is the same source code as `../../ch07/projects/04.c` */ 5 | 6 | /* Convert character to its respective digit */ 7 | void convert_char_to_digit(char *const chr_ptr, int id); 8 | 9 | int main() 10 | { 11 | int len; 12 | char *const phone_number; 13 | 14 | printf("Enter phone number: "); 15 | scanf("%s", phone_number); 16 | len = strlen(phone_number); 17 | 18 | for (int i = 0; i < len; i++) 19 | { 20 | convert_char_to_digit(phone_number, i); 21 | } 22 | 23 | printf("%s\n", phone_number); 24 | 25 | return 0; 26 | } 27 | 28 | /* implementation */ 29 | 30 | void convert_char_to_digit(char *const chr_ptr, int id) 31 | { 32 | if (chr_ptr[id] >= 'A' && chr_ptr[id] <= 'C') 33 | { 34 | chr_ptr[id] = '2'; 35 | } 36 | else if (chr_ptr[id] >= 'D' && chr_ptr[id] <= 'F') 37 | { 38 | chr_ptr[id] = '3'; 39 | } 40 | else if (chr_ptr[id] >= 'G' && chr_ptr[id] <= 'I') 41 | { 42 | chr_ptr[id] = '4'; 43 | } 44 | else if (chr_ptr[id] >= 'J' && chr_ptr[id] <= 'L') 45 | { 46 | chr_ptr[id] = '5'; 47 | } 48 | else if (chr_ptr[id] >= 'M' && chr_ptr[id] <= 'O') 49 | { 50 | chr_ptr[id] = '6'; 51 | } 52 | else if (chr_ptr[id] >= 'P' && chr_ptr[id] <= 'S') 53 | { 54 | chr_ptr[id] = '7'; 55 | } 56 | else if (chr_ptr[id] >= 'T' && chr_ptr[id] <= 'V') 57 | { 58 | chr_ptr[id] = '8'; 59 | } 60 | else if (chr_ptr[id] >= 'W' && chr_ptr[id] <= 'Y') 61 | { 62 | chr_ptr[id] = '9'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /ch09/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Check If Two Strings Are Anagrams 6 | * modified version of `../../ch08/projects/16.c` */ 7 | 8 | /* Read user's input word, count number of occurrences of each alphabet character in the word 9 | * and store them in `counts` array */ 10 | void read_word (int counts[26]); 11 | /* Check if two arrays are identical */ 12 | bool equal_array(int counts1[26], int counts2[26]); 13 | 14 | int main() { 15 | int char_counts_1 [26] = {}, char_counts_2 [26] = {}; 16 | 17 | /* Counting the number of occurrences of each alphabet character in the first input */ 18 | printf("Enter first word: "); 19 | read_word(char_counts_1); 20 | 21 | /* Counting the number of occurrences of each alphabet character in the second input */ 22 | printf("Enter second word: "); 23 | read_word(char_counts_2); 24 | 25 | printf("The words are %s.\n", equal_array(char_counts_1, char_counts_2) ? "anagrams" : "not anagrams"); 26 | 27 | return 0; 28 | } 29 | 30 | /* implementation */ 31 | 32 | void read_word (int counts[26]) { 33 | char cur = '\0'; 34 | 35 | for (; cur != '\n';) { 36 | cur = getchar(); 37 | if (isalpha(cur)) { 38 | counts[(int) tolower(cur) - 'a']++; 39 | } 40 | } 41 | } 42 | 43 | bool equal_array(int counts1[26], int counts2[26]) { 44 | bool res = true; 45 | 46 | for (unsigned short int i = 0; i <= 25; i++) { 47 | if (counts1[i] != counts2[i]) { 48 | res = false; 49 | break; 50 | } 51 | } 52 | 53 | return res; 54 | } -------------------------------------------------------------------------------- /ch08/projects/12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* this is the same source code as `../../ch07/projects/05.c` */ 6 | 7 | /** 8 | * Calculate Scrabble value of a character 9 | */ 10 | int point_of_char(char *const arr_ptr, size_t id); 11 | 12 | int main() 13 | { 14 | 15 | char *input; 16 | size_t str_len; 17 | unsigned int res = 0; 18 | 19 | printf("Enter a word: "); 20 | scanf("%s", input); 21 | 22 | str_len = strlen(input); 23 | for (int i = 0; i < str_len; i++) 24 | { 25 | // accumulate the result 26 | res += point_of_char(input, i); 27 | } 28 | 29 | printf("Scrabble value: %u\n", res); 30 | 31 | return 0; 32 | } 33 | 34 | /* implementation */ 35 | 36 | const int POINTS[7] = {1, 2, 3, 4, 5, 8, 10}; 37 | const char CHARS[7][12] = {"AEILNORSTU\0", 38 | "DG\0", 39 | "BCMP\0", 40 | "FHVWY\0", 41 | "K\0", 42 | "JX\0", 43 | "QZ\0"}; 44 | 45 | int point_of_char(char *const arr_ptr, size_t id) 46 | { 47 | short int i, j; 48 | 49 | // traverse through list of strings in CHARS 50 | for (i = j = 0; i < 7; i++) 51 | { 52 | // traverse through each character of the string of CHARS[i] 53 | for (j = 0; CHARS[i][j] != '\0'; j++) 54 | { 55 | if (toupper(arr_ptr[id]) == CHARS[i][j]) 56 | { 57 | return POINTS[i]; 58 | } 59 | } 60 | } 61 | 62 | /* will never get here */ 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /textbook_code_snippets/datetime.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* datetime.c (Chapter 26, page 700) */ 11 | /* Displays the current date and time in three formats */ 12 | 13 | #include 14 | #include 15 | 16 | int main(void) 17 | { 18 | time_t current = time(NULL); 19 | struct tm *ptr; 20 | char date_time[21]; 21 | int hour; 22 | char am_or_pm; 23 | 24 | /* Print date and time in default format */ 25 | puts(ctime(¤t)); 26 | 27 | /* Print date and time, using strftime to format */ 28 | strftime(date_time, sizeof(date_time), 29 | "%m-%d-%Y %I:%M%p\n", localtime(¤t)); 30 | puts(date_time); 31 | 32 | /* Print date and time, using printf to format */ 33 | ptr = localtime(¤t); 34 | hour = ptr->tm_hour; 35 | if (hour <= 11) 36 | am_or_pm = 'a'; 37 | else { 38 | hour -= 12; 39 | am_or_pm = 'p'; 40 | } 41 | if (hour == 0) 42 | hour = 12; 43 | printf("%.2d-%.2d-%d %2d:%.2d%c\n", ptr->tm_mon + 1, 44 | ptr->tm_mday, ptr->tm_year + 1900, hour, 45 | ptr->tm_min, am_or_pm); 46 | 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /ch07/projects/14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Newton's Method to Compute Square Root of a Positive Number */ 5 | 6 | double res; 7 | /** 8 | * After each guess, `lf_ptr2` points to x/y of last guess 9 | * and `lf_ptr1` point to the average of y and x/y from last turn. 10 | * 11 | * Return: original value of `lf_ptr1` 12 | */ 13 | double exec_guess(double *lf_ptr1, double *lf_ptr2); 14 | 15 | int main() 16 | { 17 | double temp1 = 1., temp2; 18 | 19 | printf("Enter a positive number: "); 20 | /* no re-assignment of `res` is implemented after this initialisation */ 21 | scanf("%lf", &res); 22 | 23 | if (res < 0) 24 | { 25 | printf("INVALID INPUT!"); 26 | 27 | return 1; 28 | } 29 | else 30 | { 31 | /* iteratively carries out guesses until `temp` reaches the desired closeness */ 32 | for (;;) 33 | { 34 | /* 35 | This is possible because function call has the highest precedence among C operators. 36 | `exec_guess` call below not only evaluates to the old value of `temp1` but also update 37 | new value for `temp1` which is used throughout the expression. 38 | */ 39 | if (fabs(exec_guess(&temp1, &temp2) - temp1) < (temp1 * .00001)) 40 | break; 41 | } 42 | 43 | printf("Square root: %lf\n", temp1); 44 | return 0; 45 | } 46 | } 47 | 48 | /* implementation */ 49 | 50 | double exec_guess(double *lf_ptr1, double *lf_ptr2) 51 | { 52 | double old_lf1 = *lf_ptr1; 53 | 54 | *lf_ptr2 = res / *lf_ptr1; 55 | *lf_ptr1 = (*lf_ptr1 + *lf_ptr2) / 2; 56 | 57 | return old_lf1; 58 | } 59 | -------------------------------------------------------------------------------- /textbook_code_snippets/deal.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* deal.c (Chapter 8, page 173) */ 11 | /* Deals a random hand of cards */ 12 | 13 | #include /* C99 only */ 14 | #include 15 | #include 16 | #include 17 | 18 | #define NUM_SUITS 4 19 | #define NUM_RANKS 13 20 | 21 | int main(void) 22 | { 23 | bool in_hand[NUM_SUITS][NUM_RANKS] = {false}; 24 | int num_cards, rank, suit; 25 | const char rank_code[] = {'2','3','4','5','6','7','8', 26 | '9','t','j','q','k','a'}; 27 | const char suit_code[] = {'c','d','h','s'}; 28 | 29 | srand((unsigned) time(NULL)); 30 | 31 | printf("Enter number of cards in hand: "); 32 | scanf("%d", &num_cards); 33 | 34 | printf("Your hand:"); 35 | while (num_cards > 0) { 36 | suit = rand() % NUM_SUITS; /* picks a random suit */ 37 | rank = rand() % NUM_RANKS; /* picks a random rank */ 38 | if (!in_hand[suit][rank]) { 39 | in_hand[suit][rank] = true; 40 | num_cards--; 41 | printf(" %c%c", rank_code[rank], suit_code[suit]); 42 | } 43 | } 44 | printf("\n"); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C Programming: A Modern Approach 2nd Edition 2 | 3 | This repo contains: 4 | - My solutions to the exercises in [*K. N. King*'s "C Programming: A Modern Approach", second edition](http://knking.com/books/c2/). 5 | - My reading notes 6 | - [Source code](/textbook_code_snippets) of programs illustrated in the book. 7 | 8 | ## Table of Contents 9 | 10 | - Chapter 1. Introducing C 11 | - [Chapter 2](./ch02). C Fundamentals 12 | - [Chapter 3](./ch03). Formatted Input/Output 13 | - [Chapter 4](./ch04). Expressions 14 | - [Chapter 5](./ch05). Selection Statements 15 | - [Chapter 6](./ch06). Loops 16 | - [Chapter 7](./ch07). Basic Types 17 | - [Chapter 8](./ch08). Arrays 18 | - [Chapter 9](./ch09). Functions 19 | - [Chapter 10](./ch10). Program Organisation 20 | - [Chapter 11](./ch11). Pointers 21 | - [Chapter 12](./ch12). Pointers and Arrays 22 | - [Chapter 13](./ch13). Strings 23 | - [Chapter 14](./ch14). The Preprocessor 24 | - [Chapter 15](./ch15). Writing Large Programs 25 | - [Chapter 16](./ch16). Structures, Unions, and Enumerations 26 | - [Chapter 17](./ch17). Advanced Uses of Pointers 27 | - [Chapter 18](./ch18). Declarations 28 | - [Chapter 19](./ch19). Program Design 29 | - [Chapter 20](./ch20). Low-Level Programming 30 | - [Chapter 21](./ch21). The Standard Library 31 | - [Chapter 22](./ch22). Input/Output 32 | - [Chapter 23](./ch23). Library Support for Numbers and Character Data 33 | - [Chapter 24](./ch24). Error Handling 34 | - [Chapter 25](./ch25). International Features 35 | - [Chapter 26](./ch26). Miscellaneous Library Functions 36 | - [Chapter 27](./ch27). Additional C99 Support for Mathematics -------------------------------------------------------------------------------- /textbook_code_snippets/stack2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stack2.c (Chapter 19, page 489) */ 11 | 12 | #include 13 | #include 14 | #include "stack.h" 15 | 16 | struct node { 17 | int data; 18 | struct node *next; 19 | }; 20 | 21 | static struct node *top = NULL; 22 | 23 | static void terminate(const char *message) 24 | { 25 | printf("%s\n", message); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | void make_empty(void) 30 | { 31 | while (!is_empty()) 32 | pop(); 33 | } 34 | 35 | bool is_empty(void) 36 | { 37 | return top == NULL; 38 | } 39 | 40 | bool is_full(void) 41 | { 42 | return false; 43 | } 44 | 45 | void push(int i) 46 | { 47 | struct node *new_node = malloc(sizeof(struct node)); 48 | if (new_node == NULL) 49 | terminate("Error in push: stack is full."); 50 | 51 | new_node->data = i; 52 | new_node->next = top; 53 | top = new_node; 54 | } 55 | 56 | int pop(void) 57 | { 58 | struct node *old_top; 59 | int i; 60 | 61 | if (is_empty()) 62 | terminate("Error in pop: stack is empty."); 63 | 64 | old_top = top; 65 | i = top->data; 66 | top = top->next; 67 | free(old_top); 68 | return i; 69 | } 70 | -------------------------------------------------------------------------------- /textbook_code_snippets/checking.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* checking.c (Chapter 6, page 115) */ 11 | /* Balances a checkbook */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int cmd; 18 | float balance = 0.0f, credit, debit; 19 | 20 | printf("*** ACME checkbook-balancing program ***\n"); 21 | printf("Commands: 0=clear, 1=credit, 2=debit, "); 22 | printf("3=balance, 4=exit\n\n"); 23 | 24 | for (;;) { 25 | printf("Enter command: "); 26 | scanf("%d", &cmd); 27 | switch (cmd) { 28 | case 0: 29 | balance = 0.0f; 30 | break; 31 | case 1: 32 | printf("Enter amount of credit: "); 33 | scanf("%f", &credit); 34 | balance += credit; 35 | break; 36 | case 2: 37 | printf("Enter amount of debit: "); 38 | scanf("%f", &debit); 39 | balance -= debit; 40 | break; 41 | case 3: 42 | printf("Current balance: $%.2f\n", balance); 43 | break; 44 | case 4: 45 | return 0; 46 | default: 47 | printf("Commands: 0=clear, 1=credit, 2=debit, "); 48 | printf("3=balance, 4=exit\n\n"); 49 | break; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ch08/projects/17.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* De la Loubère's method for solving magic square 4 | * @reference https://www.magic-squares.info/methods/odd.html 5 | * */ 6 | 7 | int board[99][99] = {}; 8 | 9 | int main() { 10 | short int cur_x, cur_y, next_x, next_y; 11 | unsigned short i, j, size; 12 | 13 | printf("This program creates a magic square of a specific size.\n"); 14 | printf("The size must be an odd number between 1 and 99.\n"); 15 | printf("Enter size of magic number: "); 16 | scanf("%hu", &size); 17 | 18 | /* validate number of size */ 19 | if (size < 0 || size > 99) { 20 | printf("INVALID INPUT!\n"); 21 | return 1; 22 | } 23 | 24 | if (size % 2 == 0) 25 | size++; 26 | 27 | /* implement De la Loubère's method */ 28 | for (i = 1, cur_x = size / 2, cur_y = 0; 29 | i <= size * size; 30 | i++) 31 | { 32 | board[cur_y][cur_x] = i; 33 | 34 | next_y = (size + cur_y - 1) % size; 35 | next_x = (cur_x + 1) % size; 36 | 37 | if (board[next_y][next_x] == 0) { 38 | // move the cursor 1 row upward and 1 column to the rightward 39 | cur_y = next_y; 40 | cur_x = next_x; 41 | } 42 | else { 43 | // if the cell to move to is already populated, move the cursor 1 row downward 44 | next_y = (cur_y + 1) % size; 45 | cur_y = next_y; 46 | } 47 | 48 | // printf("Num: %d \n", i, cur_y, cur_x); 49 | } 50 | 51 | /* print the board out */ 52 | for (i = 0; i < size; i++) { 53 | for (j = 0; j < size; j++) { 54 | printf("%6d ", board[i][j]); 55 | } 56 | printf("\n"); 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /textbook_code_snippets/stackADT.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackADT.c (Chapter 19, page 495) */ 11 | 12 | #include 13 | #include 14 | #include "stackADT.h" 15 | 16 | #define STACK_SIZE 100 17 | 18 | struct stack_type { 19 | int contents[STACK_SIZE]; 20 | int top; 21 | }; 22 | 23 | static void terminate(const char *message) 24 | { 25 | printf("%s\n", message); 26 | exit(EXIT_FAILURE); 27 | } 28 | 29 | Stack create(void) 30 | { 31 | Stack s = malloc(sizeof(struct stack_type)); 32 | if (s == NULL) 33 | terminate("Error in create: stack could not be created."); 34 | s->top = 0; 35 | return s; 36 | } 37 | 38 | void destroy(Stack s) 39 | { 40 | free(s); 41 | } 42 | 43 | void make_empty(Stack s) 44 | { 45 | s->top = 0; 46 | } 47 | 48 | bool is_empty(Stack s) 49 | { 50 | return s->top == 0; 51 | } 52 | 53 | bool is_full(Stack s) 54 | { 55 | return s->top == STACK_SIZE; 56 | } 57 | 58 | void push(Stack s, int i) 59 | { 60 | if (is_full(s)) 61 | terminate("Error in push: stack is full."); 62 | s->contents[s->top++] = i; 63 | } 64 | 65 | int pop(Stack s) 66 | { 67 | if (is_empty(s)) 68 | terminate("Error in pop: stack is empty."); 69 | return s->contents[--s->top]; 70 | } 71 | -------------------------------------------------------------------------------- /ch10/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "stack_char.h" 3 | 4 | /* Using stack to check if brackets/braces are nested properly 5 | * to run this program, compile both this file, `stack.h` and `stack.c` */ 6 | 7 | int main() { 8 | char cur; 9 | 10 | printf("Enter parentheses and/or braces: "); 11 | while ((cur = getchar()) != '\n') { 12 | if ((cur == '(') || (cur == '{')) { 13 | /* after this point, the latest opening bracket/brace will be put on top of the stack */ 14 | stack_push(cur); 15 | } 16 | else if ((cur == ')') && (stack_pop() != '(')) { 17 | /* if the currently reading character doesn't matches the latest opening bracket */ 18 | 19 | // printf("current top element: %c, its index: %d\n" 20 | // , stack_current_top(), stack_current_top_index()); 21 | printf("Round brackets are not nested properly!\n"); 22 | return 1; 23 | } 24 | else if ((cur == '}') && (stack_pop() != '{')) { 25 | /* if the currently reading character doesn't matches the latest opening brace */ 26 | 27 | // printf("current top element: %c, its index: %d\n" 28 | // , stack_current_top(), stack_current_top_index()); 29 | printf("Braces are not nested properly!\n"); 30 | return 1; 31 | } 32 | } 33 | 34 | if (stack_is_empty()) { 35 | printf("Parentheses/braces are nested properly!\n"); 36 | } 37 | else { 38 | /* the program reaches here if user input contains invalid characters 39 | * or if the number of opening brackets/braces is bigger than the number of closing ones */ 40 | printf("Parentheses/braces are not nested properly!\n"); 41 | } 42 | 43 | return 0; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /ch07/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 7: Basic Types 2 | 3 | ## Reading Notes 4 | 5 | - Range of values for integer types are different among 16-bit, 32-bit and 64-bit CPUs. 6 | - **C99** standard allows implementation-defined extended integer types. 7 | - C treats characters as small integers 8 | - For escape characters, numeric escapes can be written using either _octal_ escape sequence (i.e. `\033`, `\33`) or _hexadecimal_ escape sequence (i.e. `\x1b`, `\x1B`) 9 | - To read character, use `ch = getchar()` instead of `scanf("%c", &ch)` 10 | 11 | ```C 12 | while ((chr = getchar()) != '\n') 13 | ; 14 | ``` 15 | 16 | - In **C99**, arithmetic types include: 17 | - Integer types: 18 | - `char` 19 | - Signed integer types, both standard (`signed char`, `short int`, `int`, `long int`, `long long int`) and extended 20 | - Unsigned integer types, both standard (`unsigned char`, `unsigned short int`, `unsigned int`, `unsigned long int`, `unsigned long long int`, `_Bool`) and extended 21 | - Enumerated types 22 | - Floating types: 23 | - Real floating types (`float.double`, `long.double`) 24 | - Complex types (`float _Complex`, `double _Complex`, `long double _Complex`) 25 | - `sizeof` operator: 26 | 27 | ```C 28 | printf("Size of int: %zu\n", sizeof(int)); 29 | ``` 30 | 31 | ### Related Chapters 32 | 33 | - Chapter 9: Implicit type conversions 34 | - Chapter 20: Octal & hex notations 35 | 36 | ## Exercising Notes 37 | 38 | - Significant projects: 39 | - [`project 4`](./projects/04.c) (about string as array notation versus as pointer of `char`) 40 | - [`project 12`](./projects/12.c) (illustrate on how to take advantage of buffer in C) 41 | - [`project 14`](./projects/14.c) (discuss on operator precedence in C) 42 | -------------------------------------------------------------------------------- /textbook_code_snippets/date.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* date.c (Chapter 5, page 89) */ 11 | /* Prints a date in legal form */ 12 | 13 | #include 14 | 15 | int main(void) 16 | { 17 | int month, day, year; 18 | 19 | printf("Enter date (mm/dd/yy): "); 20 | scanf("%d /%d /%d", &month, &day, &year); 21 | 22 | printf("Dated this %d", day); 23 | switch (day) { 24 | case 1: case 21: case 31: 25 | printf("st"); break; 26 | case 2: case 22: 27 | printf("nd"); break; 28 | case 3: case 23: 29 | printf("rd"); break; 30 | default: printf("th"); break; 31 | } 32 | printf(" day of "); 33 | 34 | switch (month) { 35 | case 1: printf("January"); break; 36 | case 2: printf("February"); break; 37 | case 3: printf("March"); break; 38 | case 4: printf("April"); break; 39 | case 5: printf("May"); break; 40 | case 6: printf("June"); break; 41 | case 7: printf("July"); break; 42 | case 8: printf("August"); break; 43 | case 9: printf("September"); break; 44 | case 10: printf("October"); break; 45 | case 11: printf("November"); break; 46 | case 12: printf("December"); break; 47 | } 48 | 49 | printf(", 20%.2d.\n", year); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /ch04/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Compute UPC Check Digit */ 4 | 5 | int main() 6 | { 7 | int item, manufacturer_digits[5], product_digits[5], i, res; 8 | /* 9 | UPC 1st digit = item ; UPC 2nd digit = manufacturer_digits[0]; 10 | UPC 3rd digit = manufacturer_digits[1]; UPC 4th digit = manufacturer_digits[2]; 11 | UPC 5th digit = manufacturer_digits[3]; UPC 6th digit = manufacturer_digits[4]; 12 | UPC 7th digit = product_digits[0] ; UPC 8th digit = product_digits[1] ; 13 | UPC 9th digit = product_digits[2] ; UPC 10th digit = product_digits[3] ; 14 | UPC 11th digit = product_digits[4] ; 15 | */ 16 | 17 | printf("Enter the first 11 digits of a UPC: "); 18 | scanf("%1d", &item); 19 | for (i = 0; i < 5; i++) 20 | { 21 | scanf("%1d", &manufacturer_digits[i]); 22 | } 23 | for (i = 0; i < 5; i++) 24 | { 25 | scanf("%1d", &product_digits[i]); 26 | } 27 | 28 | /* Procedure to compute check number */ 29 | // get sum of digits in odd places 30 | res = item + manufacturer_digits[1] + manufacturer_digits[3]; 31 | for (i = 0; i <= 4; i += 2) 32 | { 33 | res += product_digits[i]; 34 | } 35 | // multiply this sum by 3 36 | res *= 3; 37 | // add it to the sum of digits in even places 38 | for (i = 0; i <= 4; i += 2) 39 | { 40 | res += manufacturer_digits[i]; 41 | } 42 | res += product_digits[1] + product_digits[3]; 43 | // subtract 1 from the total 44 | res -= 1; 45 | // get the remainder when the adjusted total is divided by 10 46 | res /= 10; 47 | // subtract the remainder from 9 48 | res = 9 - res; 49 | /* END Procedure to compute check number */ 50 | 51 | printf("Check digit: %d\n", res); 52 | 53 | return 0; 54 | } -------------------------------------------------------------------------------- /ch09/projects/01.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Selection Sort */ 5 | 6 | void selection_sort(int *const arr, int cur_id) { 7 | if (!cur_id) { 8 | /* base case */ 9 | // printf("base case\n"); 10 | return; 11 | } 12 | else { 13 | /* recursive cases */ 14 | int max_i, tmp, i; 15 | 16 | // find the maximum value in the current sub-array 17 | for (max_i = 0, i = 1; i < cur_id; i++) { 18 | if (arr[i] > arr[max_i]) { 19 | max_i = i; 20 | } 21 | } 22 | 23 | // printf(" current_id: %d, index of max value: %d, max value: %d \n", cur_id, max_i, arr[max_i]); 24 | // swap the largest element with the last element in the current sub-array 25 | tmp = arr[max_i]; 26 | arr[max_i] = arr[cur_id - 1]; 27 | arr[cur_id - 1] = tmp; 28 | 29 | selection_sort(arr, cur_id - 1); 30 | } 31 | } 32 | 33 | int main() { 34 | int i, len; 35 | int *arr = (int *) calloc(100, sizeof(int)); 36 | 37 | printf("Input array of integers\n"); 38 | printf("(please start your input with a blank space, and then each number separated by a black space): \n"); 39 | for (i = 0 40 | // consume blank space between input numbers 41 | ; i < 100 && (getchar() != '\n'); i++) { 42 | scanf(" %d", arr + i); 43 | } 44 | len = i; 45 | 46 | // printf(" Array address: %p \n", arr); 47 | // printf(" Input array: "); 48 | // for (i = 0; i < len; i++) { 49 | // printf("%d ", arr[i]); 50 | // } 51 | // printf("\n"); 52 | 53 | selection_sort(arr, len); 54 | 55 | printf("Sorted array: "); 56 | for (i = 0; i < len; i++) { 57 | printf("%d ", arr[i]); 58 | } 59 | printf("\n"); 60 | 61 | free(arr); 62 | 63 | return 0; 64 | } -------------------------------------------------------------------------------- /ch10/projects/stack_int.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "stack_int.h" 4 | 5 | #define STACK_SIZE 100 6 | 7 | int contents[STACK_SIZE]; 8 | /* position of the stack top */ 9 | int top = 0; 10 | 11 | void stack_overflow() { 12 | // printf("Stack overflow!!!\n"); 13 | printf("Your input expression is too complex!\n"); 14 | printf("Stack contents: \n"); 15 | for (int i; i < top; i++) { 16 | printf("%d ", contents[i]); 17 | } 18 | printf("\n\n"); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | void stack_underflow() { 23 | // printf("Stack underflow!!!\n"); 24 | printf("Not enough operands in your input expression!\n"); 25 | printf("Stack contents: \n"); 26 | for (int i; i < top; i++) { 27 | printf("%d ", contents[i]); 28 | } 29 | printf("\n\n"); 30 | exit(EXIT_FAILURE); 31 | } 32 | 33 | void intstack_make_empty() { 34 | top = 0; 35 | } 36 | 37 | bool intstack_is_empty() { 38 | return top == 0; 39 | } 40 | 41 | bool intstack_is_full() { 42 | return top == STACK_SIZE; 43 | } 44 | 45 | int intstack_current_length() { 46 | return top; 47 | } 48 | 49 | char intstack_current_top() { 50 | return contents[top - 1]; 51 | } 52 | 53 | void intstack_push(int num) { 54 | if (intstack_is_full()) { 55 | stack_overflow(); 56 | } 57 | else { 58 | /* store the added item in `contents` at the position indicated by `top` 59 | * and then increment `top` */ 60 | contents[top++] = num; 61 | } 62 | } 63 | 64 | char intstack_pop() { 65 | if (intstack_is_empty()) { 66 | stack_underflow(); 67 | } 68 | else { 69 | /* popping an item requires decrementing `top`, then using it as an index 70 | * into contents to fetch the item being popped */ 71 | return contents[--top]; 72 | } 73 | } -------------------------------------------------------------------------------- /textbook_code_snippets/viewmemory.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* viewmemory.c (Chapter 20, page 521) */ 11 | /* Allows the user to view regions of computer memory */ 12 | 13 | #include 14 | #include 15 | 16 | typedef unsigned char BYTE; 17 | 18 | int main(void) 19 | { 20 | unsigned int addr; 21 | int i, n; 22 | BYTE *ptr; 23 | 24 | printf("Address of main function: %x\n", (unsigned int) main); 25 | printf("Address of addr variable: %x\n", (unsigned int) &addr); 26 | 27 | printf("\nEnter a (hex) address: "); 28 | scanf("%x", &addr); 29 | printf("Enter number of bytes to view: "); 30 | scanf("%d", &n); 31 | 32 | printf("\n"); 33 | printf(" Address Bytes Characters\n"); 34 | printf(" ------- ----------------------------- ----------\n"); 35 | 36 | ptr = (BYTE *) addr; 37 | for (; n > 0; n -= 10) { 38 | printf("%8X ", (unsigned int) ptr); 39 | for (i = 0; i < 10 && i < n; i++) 40 | printf("%.2X ", *(ptr + i)); 41 | for (; i < 10; i++) 42 | printf(" "); 43 | printf(" "); 44 | for (i = 0; i < 10 && i < n; i++) { 45 | BYTE ch = *(ptr + i); 46 | if (!isprint(ch)) 47 | ch = '.'; 48 | printf("%c", ch); 49 | } 50 | printf("\n"); 51 | ptr += 10; 52 | } 53 | 54 | return 0; 55 | } 56 | -------------------------------------------------------------------------------- /textbook_code_snippets/line.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* line.c (Chapter 15, page 364) */ 11 | 12 | #include 13 | #include 14 | #include "line.h" 15 | 16 | #define MAX_LINE_LEN 60 17 | 18 | char line[MAX_LINE_LEN+1]; 19 | int line_len = 0; 20 | int num_words = 0; 21 | 22 | void clear_line(void) 23 | { 24 | line[0] = '\0'; 25 | line_len = 0; 26 | num_words = 0; 27 | } 28 | 29 | void add_word(const char *word) 30 | { 31 | if (num_words > 0) { 32 | line[line_len] = ' '; 33 | line[line_len+1] = '\0'; 34 | line_len++; 35 | } 36 | strcat(line, word); 37 | line_len += strlen(word); 38 | num_words++; 39 | } 40 | 41 | int space_remaining(void) 42 | { 43 | return MAX_LINE_LEN - line_len; 44 | } 45 | 46 | void write_line(void) 47 | { 48 | int extra_spaces, spaces_to_insert, i, j; 49 | 50 | extra_spaces = MAX_LINE_LEN - line_len; 51 | for (i = 0; i < line_len; i++) { 52 | if (line[i] != ' ') 53 | putchar(line[i]); 54 | else { 55 | spaces_to_insert = extra_spaces / (num_words - 1); 56 | for (j = 1; j <= spaces_to_insert + 1; j++) 57 | putchar(' '); 58 | extra_spaces -= spaces_to_insert; 59 | num_words--; 60 | } 61 | } 62 | putchar('\n'); 63 | } 64 | 65 | void flush_line(void) 66 | { 67 | if (line_len > 0) 68 | puts(line); 69 | } 70 | -------------------------------------------------------------------------------- /textbook_code_snippets/qsort.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* qsort.c (Chapter 9, page 207) */ 11 | /* Sorts an array of integers using Quicksort algorithm */ 12 | 13 | #include 14 | 15 | #define N 10 16 | 17 | void quicksort(int a[], int low, int high); 18 | int split(int a[], int low, int high); 19 | 20 | int main(void) 21 | { 22 | int a[N], i; 23 | 24 | printf("Enter %d numbers to be sorted: ", N); 25 | for (i = 0; i < N; i++) 26 | scanf("%d", &a[i]); 27 | 28 | quicksort(a, 0, N - 1); 29 | 30 | printf("In sorted order: "); 31 | for (i = 0; i < N; i++) 32 | printf("%d ", a[i]); 33 | printf("\n"); 34 | 35 | return 0; 36 | } 37 | 38 | void quicksort(int a[], int low, int high) 39 | { 40 | int middle; 41 | 42 | if (low >= high) return; 43 | middle = split(a, low, high); 44 | quicksort(a, low, middle - 1); 45 | quicksort(a, middle + 1, high); 46 | } 47 | 48 | int split(int a[], int low, int high) 49 | { 50 | int part_element = a[low]; 51 | 52 | for (;;) { 53 | while (low < high && part_element <= a[high]) 54 | high--; 55 | if (low >= high) break; 56 | a[low++] = a[high]; 57 | 58 | while (low < high && a[low] <= part_element) 59 | low++; 60 | if (low >= high) break; 61 | a[high--] = a[low]; 62 | } 63 | 64 | a[high] = part_element; 65 | return high; 66 | } 67 | -------------------------------------------------------------------------------- /textbook_code_snippets/tnumconv.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tnumconv.c (Chapter 26, page 684) */ 11 | /* Tests C89 numeric conversion functions */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #define CHK_VALID printf(" %s %s\n", \ 18 | errno != ERANGE ? "Yes" : "No ", \ 19 | *ptr == '\0' ? "Yes" : "No") 20 | 21 | int main(int argc, char *argv[]) 22 | { 23 | char *ptr; 24 | 25 | if (argc != 2) { 26 | printf("usage: tnumconv string\n"); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | printf("Function Return Value\n"); 31 | printf("-------- ------------\n"); 32 | printf("atof %g\n", atof(argv[1])); 33 | printf("atoi %d\n", atoi(argv[1])); 34 | printf("atol %ld\n\n", atol(argv[1])); 35 | 36 | printf("Function Return Value Valid? " 37 | "String Consumed?\n" 38 | "-------- ------------ ------ " 39 | "----------------\n"); 40 | 41 | errno = 0; 42 | printf("strtod %-12g", strtod(argv[1], &ptr)); 43 | CHK_VALID; 44 | 45 | errno = 0; 46 | printf("strtol %-12ld", strtol(argv[1], &ptr, 10)); 47 | CHK_VALID; 48 | 49 | errno = 0; 50 | printf("strtoul %-12lu", strtoul(argv[1], &ptr, 10)); 51 | CHK_VALID; 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /textbook_code_snippets/tabulate.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* tabulate.c (Chapter 17, page 444) */ 11 | /* Tabulates values of trigonometric functions */ 12 | 13 | #include 14 | #include 15 | 16 | void tabulate(double (*f)(double), double first, 17 | double last, double incr); 18 | 19 | int main(void) 20 | { 21 | double final, increment, initial; 22 | 23 | printf("Enter initial value: "); 24 | scanf("%lf", &initial); 25 | 26 | printf("Enter final value: "); 27 | scanf("%lf", &final); 28 | 29 | printf("Enter increment: "); 30 | scanf("%lf", &increment); 31 | 32 | printf("\n x cos(x)" 33 | "\n ------- -------\n"); 34 | tabulate(cos, initial, final, increment); 35 | 36 | printf("\n x sin(x)" 37 | "\n ------- -------\n"); 38 | tabulate(sin, initial, final, increment); 39 | 40 | printf("\n x tan(x)" 41 | "\n ------- -------\n"); 42 | tabulate(tan, initial, final, increment); 43 | 44 | return 0; 45 | } 46 | 47 | void tabulate(double (*f)(double), double first, 48 | double last, double incr) 49 | { 50 | double x; 51 | int i, num_intervals; 52 | 53 | num_intervals = ceil((last - first) / incr); 54 | for (i = 0; i <= num_intervals; i++) { 55 | x = first + i * incr; 56 | printf("%10.5f %10.5f\n", x, (*f)(x)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ch05/projects/09.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Given 2 dates, find out which date is earlier */ 5 | 6 | int compare(int a, int b) 7 | { 8 | return (a > b) ? 1 : ((a == b) ? 0 : -1); 9 | } 10 | 11 | void print_date(int m, int d, int y) 12 | { 13 | printf("%d/%d/%2d", m, d, y % 100); 14 | } 15 | 16 | void scan_date(int *m_ptr, int *d_ptr, int *y_ptr) 17 | { 18 | scanf("%d/%d/%d", m_ptr, d_ptr, y_ptr); 19 | } 20 | 21 | int main() 22 | { 23 | int dates[2], months[2], years[2]; 24 | bool is_1st_earlier; 25 | 26 | printf("Enter first date (mm/dd/yyyy): "); 27 | scan_date(&months[0], &dates[0], &years[0]); 28 | printf("Enter first date (mm/dd/yyyy): "); 29 | scan_date(&months[1], &dates[1], &years[1]); 30 | 31 | switch (compare(years[0], years[1])) 32 | { 33 | case -1: 34 | is_1st_earlier = true; 35 | break; 36 | case 1: 37 | is_1st_earlier = false; 38 | break; 39 | case 0: 40 | switch (compare(months[0], months[1])) 41 | { 42 | case -1: 43 | is_1st_earlier = true; 44 | break; 45 | case 1: 46 | is_1st_earlier = false; 47 | break; 48 | case 0: 49 | switch (compare(dates[0], dates[1])) 50 | { 51 | case -1: 52 | is_1st_earlier = true; 53 | break; 54 | case 1: 55 | is_1st_earlier = false; 56 | break; 57 | case 0: 58 | printf("These are the same dates.\n"); 59 | return 0; 60 | } 61 | } 62 | } 63 | 64 | if (is_1st_earlier) 65 | { 66 | print_date(months[0], dates[0], years[0]); 67 | printf(" is earlier than "); 68 | print_date(months[1], dates[1], years[1]); 69 | printf(".\n"); 70 | } 71 | else 72 | { 73 | print_date(months[1], dates[1], years[1]); 74 | printf(" is earlier than "); 75 | print_date(months[0], dates[0], years[0]); 76 | printf(".\n"); 77 | } 78 | 79 | return 0; 80 | } -------------------------------------------------------------------------------- /textbook_code_snippets/stackADT2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackADT2.c (Chapter 19, page 498) */ 11 | 12 | #include 13 | #include 14 | #include "stackADT2.h" 15 | 16 | struct stack_type { 17 | Item *contents; 18 | int top; 19 | int size; 20 | }; 21 | 22 | static void terminate(const char *message) 23 | { 24 | printf("%s\n", message); 25 | exit(EXIT_FAILURE); 26 | } 27 | 28 | Stack create(int size) 29 | { 30 | Stack s = malloc(sizeof(struct stack_type)); 31 | if (s == NULL) 32 | terminate("Error in create: stack could not be created."); 33 | s->contents = malloc(size * sizeof(Item)); 34 | if (s->contents == NULL) { 35 | free(s); 36 | terminate("Error in create: stack could not be created."); 37 | } 38 | s->top = 0; 39 | s->size = size; 40 | return s; 41 | } 42 | 43 | void destroy(Stack s) 44 | { 45 | free(s->contents); 46 | free(s); 47 | } 48 | 49 | void make_empty(Stack s) 50 | { 51 | s->top = 0; 52 | } 53 | 54 | bool is_empty(Stack s) 55 | { 56 | return s->top == 0; 57 | } 58 | 59 | bool is_full(Stack s) 60 | { 61 | return s->top == s->size; 62 | } 63 | 64 | void push(Stack s, Item i) 65 | { 66 | if (is_full(s)) 67 | terminate("Error in push: stack is full."); 68 | s->contents[s->top++] = i; 69 | } 70 | 71 | Item pop(Stack s) 72 | { 73 | if (is_empty(s)) 74 | terminate("Error in pop: stack is empty."); 75 | return s->contents[--s->top]; 76 | } 77 | -------------------------------------------------------------------------------- /ch09/projects/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* The Game of Craps */ 7 | 8 | unsigned short int dices[2] = {}; 9 | 10 | int roll_dice() { 11 | dices[0] = rand() % 6 + 1; 12 | dices[1] = rand() % 6 + 1; 13 | 14 | return dices[0] + dices[1]; 15 | } 16 | 17 | bool play_game() { 18 | int res, point; 19 | 20 | printf("\nYou rolled: %d\n", res = roll_dice()); 21 | if (res == 7 || res == 11) { 22 | printf("You win!\n"); 23 | return true; 24 | } 25 | else if (res == 2 || res == 3 || res == 12) { 26 | printf("You lose!\n"); 27 | return false; 28 | } 29 | else { 30 | printf("The point is %d\n", point = rand() % 11 + 1); 31 | 32 | for (res = roll_dice();; res = roll_dice()) { 33 | printf("You rolled: %d\n", res); 34 | if (res == 7) { 35 | if (point == 7) { 36 | printf("You win!\n"); 37 | return true; 38 | } 39 | else { 40 | printf("You lose!\n"); 41 | return false; 42 | } 43 | } 44 | else if (res == point) { 45 | printf("You win!\n"); 46 | return true; 47 | } 48 | else { 49 | continue; 50 | } 51 | } 52 | } 53 | } 54 | 55 | int main() { 56 | unsigned int win_num = 0, lose_num = 0; 57 | 58 | /* prevent the generator from generating the same result 59 | every time the program is executed */ 60 | srand((unsigned) time(NULL)); 61 | 62 | for (;;) { 63 | if (play_game() == true) 64 | win_num++; 65 | else 66 | lose_num++; 67 | 68 | printf("Play again? "); 69 | 70 | if (getchar() == 'y') { 71 | // consume trailing '\n' character; 72 | getchar(); 73 | 74 | continue; 75 | } 76 | else { 77 | break; 78 | } 79 | } 80 | 81 | printf("\nWins: %4d Loses: %4d\n", win_num, lose_num); 82 | return 0; 83 | } -------------------------------------------------------------------------------- /ch08/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | /* B1FF ENCODING */ 7 | 8 | /* convert letter at index `i` to its B1FF counterpart */ 9 | void b1ff_filter(char *const chr, const int i); 10 | /* `scanf` for sentence, and convert the whole string to uppercase */ 11 | void scanf_string(char *const chr); 12 | 13 | int main() 14 | { 15 | int final_len; 16 | char cur, mes[1000]; 17 | 18 | printf("Enter message: "); 19 | /* read the sentence into `mes` and uppercase it */ 20 | scanf_string(mes); 21 | 22 | /* implement the conversion */ 23 | for (int i = 0; *(mes + i) != '\0'; i++) 24 | { 25 | b1ff_filter(mes, i); 26 | } 27 | 28 | /* print the string out & append 10 exclamation mark */ 29 | printf("In B1FF-speak: "); 30 | for (int i = 0; *(mes + i) != '\0'; i++) 31 | { 32 | printf("%c", *(mes + i)); 33 | } 34 | for (int i = 0; i < 10; i++) 35 | { 36 | printf("!"); 37 | } 38 | printf("\n"); 39 | 40 | return 0; 41 | } 42 | 43 | /* implementations */ 44 | 45 | void scanf_string(char *const chr) 46 | { 47 | int i = 0; 48 | char cur; 49 | 50 | for (;;) 51 | { 52 | cur = getchar(); 53 | if (cur != '\n') 54 | { 55 | // append the uppercased `cur` to given string 56 | *(chr + (i++)) = toupper(cur); 57 | } 58 | else 59 | { 60 | // signify the end of the string 61 | *(chr + i) = '\0'; 62 | break; 63 | } 64 | } 65 | } 66 | 67 | void b1ff_filter(char *const chr, const int i) 68 | { 69 | switch (*(chr + i)) 70 | { 71 | case 'A': 72 | *(chr + i) = '4'; 73 | break; 74 | case 'B': 75 | *(chr + i) = '8'; 76 | break; 77 | case 'E': 78 | *(chr + i) = '3'; 79 | break; 80 | case 'I': 81 | *(chr + i) = '1'; 82 | break; 83 | case 'O': 84 | *(chr + i) = '0'; 85 | break; 86 | case 'S': 87 | *(chr + i) = '5'; 88 | break; 89 | } 90 | } -------------------------------------------------------------------------------- /ch05/projects/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Calculate rival's commission and store its value to pointer `rival_ptr` */ 4 | void get_rival_commission(float (*const rival_ptr), const int num_of_shares); 5 | 6 | /* Calculate broker's commission and store its value to pointer `broker_ptr` */ 7 | void get_broker_commission(float (*const broker_ptr), const int value); 8 | 9 | int main() 10 | { 11 | int shares, price_per_share, value; 12 | float broker_commission, rival_commission; 13 | 14 | printf("Enter number of shares: "); 15 | scanf("%d", &shares); 16 | 17 | printf("Enter price per share: "); 18 | scanf("%d", &price_per_share); 19 | 20 | value = shares * price_per_share; 21 | 22 | get_rival_commission(&rival_commission, shares); 23 | get_broker_commission(&broker_commission, value); 24 | 25 | printf("Rival\'s commission: $%.2f\n", rival_commission); 26 | printf("Broker\'s commission: $%.2f\n", broker_commission); 27 | return 0; 28 | } 29 | 30 | /* Implementation */ 31 | 32 | void get_rival_commission(float (*const rival_ptr), const int num_of_shares) 33 | { 34 | if (num_of_shares < 2000) 35 | *rival_ptr = 33 + (num_of_shares * 0.03); 36 | else 37 | *rival_ptr = 33 + (num_of_shares * 0.02); 38 | } 39 | 40 | void get_broker_commission(float (*const broker_ptr), const int value) 41 | { 42 | int base; 43 | float ratio; 44 | 45 | if (value < 2500) 46 | { 47 | base = 30; 48 | ratio = 0.017; 49 | } 50 | else if (value < 6250) 51 | { 52 | base = 56; 53 | ratio = 0.0066; 54 | } 55 | else if (value < 20000) 56 | { 57 | base = 76; 58 | ratio = 0.034; 59 | } 60 | else if (value < 50000) 61 | { 62 | base = 100; 63 | ratio = 0.0022; 64 | } 65 | else if (value < 500000) 66 | { 67 | base = 155; 68 | ratio = 0.0011; 69 | } 70 | else 71 | { 72 | base = 255; 73 | ratio = 0.0009; 74 | } 75 | 76 | *broker_ptr = base + ratio * value; 77 | 78 | if (*broker_ptr < 39) 79 | *broker_ptr = 39; 80 | } -------------------------------------------------------------------------------- /ch06/projects/04.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | const float RANGES[5] = {2500.00, 6250.00, 20000.00, 50000.00, 500000.00}; 4 | struct TradeConstant 5 | { 6 | int base; 7 | float ratio; 8 | }; 9 | 10 | const struct TradeConstant CONSTS[6] = { 11 | { 12 | .base = 30, 13 | .ratio = .017, 14 | }, 15 | { 16 | .base = 56, 17 | .ratio = .0066, 18 | }, 19 | { 20 | .base = 76, 21 | .ratio = .0034, 22 | }, 23 | { 24 | .base = 100, 25 | .ratio = .0022, 26 | }, 27 | { 28 | .base = 155, 29 | .ratio = .0011, 30 | }, 31 | { 32 | .base = 255, 33 | .ratio = .0009, 34 | }, 35 | }; 36 | 37 | int main() 38 | { 39 | int base; 40 | float ratio, commission, value = 1; 41 | 42 | while (value != 0) 43 | { 44 | printf("Enter the value of trade (0 to terminate): "); 45 | scanf("%f", &value); 46 | 47 | for (int i = 0; i < 5; i++) 48 | { 49 | // exclusively for the lower bound check case 50 | if (i == 0) 51 | { 52 | if (value < RANGES[0]) 53 | { 54 | ratio = CONSTS[0].ratio; 55 | base = CONSTS[0].base; 56 | } 57 | } 58 | // for other check cases 59 | else 60 | { 61 | if (value >= RANGES[i - 1] && value < RANGES[i]) 62 | { 63 | ratio = CONSTS[i].ratio; 64 | base = CONSTS[i].base; 65 | } 66 | } 67 | 68 | // for the upper bound, implement this extra check case 69 | if (i == 4) 70 | { 71 | if (value > RANGES[4]) 72 | { 73 | ratio = CONSTS[5].ratio; 74 | base = CONSTS[5].base; 75 | } 76 | } 77 | } 78 | 79 | //printf("base = %d; ratio = %.4f\n", base, ratio); 80 | 81 | commission = base + ratio * value; 82 | if (commission < 39.00) 83 | commission = 39.00; 84 | 85 | printf("Commission: $%.2f\n", commission); 86 | } 87 | 88 | return 0; 89 | } 90 | -------------------------------------------------------------------------------- /ch13/README.md: -------------------------------------------------------------------------------- 1 | # Chapter 13: String 2 | 3 | ## Reading Notes 4 | 5 | - Split a string over 2 or more lines 6 | 7 | ```C 8 | printf("Let me tell you this: if you meet a loner, no matter what they tell you, it's not because they enjoy solitude. " 9 | "It's because they have tried to blend into the world before, and people continue to disappoint them.\n" 10 | "-- Jodi Picoult"); 11 | ``` 12 | 13 | - Attempt to modify a string literal causes undefined behaviours, hence the program may behave erratically. 14 | - Using an uninitialised pointer variable as a string is a serious error which causes undefined behaviour. 15 | - `gets` function reads a full line of string input. 16 | - Functions in `string.h` header: 17 | - `strcpy` copies the second string argument into the first string argument. If the second string is longer than 18 | the first one, undefined behaviour occurs. 19 | 20 | ```C 21 | char *strcpy(char *s1, const char *s2); 22 | ``` 23 | - `strncpy` is safer but slower alternative to `strcpy`. An example of using `strncpy`: 24 | 25 | ```C 26 | strncpy(str1, str2, sizeof(str1)); 27 | ``` 28 | 29 | - `strlen` return the length of a string: 30 | 31 | ```C 32 | size_t strlen(const char *s); 33 | ``` 34 | 35 | - `strcat` appends the content of the second string argument to the first one: 36 | 37 | ```C 38 | char *strcat(char *s1, const char *s2); 39 | ``` 40 | 41 | - `strcmp` compares two string arguments. 42 | 43 | - String idiom: 44 | - The below loop terminates when the value of the assignment is null. 45 | 46 | ```C 47 | while (*p++ = *s2++) { /* do something; */} 48 | 49 | /* safer way: */ 50 | while ((*p++ = *s2++) != 0); 51 | ``` 52 | 53 | - Command-line arguments: 54 | 55 | ```C 56 | int main(int argc, char *argv[]); 57 | ``` 58 | ### Related chapters 59 | 60 | - [Chapter 23](../ch23): `string.h` header 61 | 62 | ## Exercising Notes 63 | -------------------------------------------------------------------------------- /textbook_code_snippets/remind.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* remind.c (Chapter 13, page 294) */ 11 | /* Prints a one-month reminder list */ 12 | 13 | #include 14 | #include 15 | 16 | #define MAX_REMIND 50 /* maximum number of reminders */ 17 | #define MSG_LEN 60 /* max length of reminder message */ 18 | 19 | int read_line(char str[], int n); 20 | 21 | int main(void) 22 | { 23 | char reminders[MAX_REMIND][MSG_LEN+3]; 24 | char day_str[3], msg_str[MSG_LEN+1]; 25 | int day, i, j, num_remind = 0; 26 | 27 | for (;;) { 28 | if (num_remind == MAX_REMIND) { 29 | printf("-- No space left --\n"); 30 | break; 31 | } 32 | 33 | printf("Enter day and reminder: "); 34 | scanf("%2d", &day); 35 | if (day == 0) 36 | break; 37 | sprintf(day_str, "%2d", day); 38 | read_line(msg_str, MSG_LEN); 39 | 40 | for (i = 0; i < num_remind; i++) 41 | if (strcmp(day_str, reminders[i]) < 0) 42 | break; 43 | for (j = num_remind; j > i; j--) 44 | strcpy(reminders[j], reminders[j-1]); 45 | 46 | strcpy(reminders[i], day_str); 47 | strcat(reminders[i], msg_str); 48 | 49 | num_remind++; 50 | } 51 | 52 | printf("\nDay Reminder\n"); 53 | for (i = 0; i < num_remind; i++) 54 | printf(" %s\n", reminders[i]); 55 | 56 | return 0; 57 | } 58 | 59 | int read_line(char str[], int n) 60 | { 61 | int ch, i = 0; 62 | 63 | while ((ch = getchar()) != '\n') 64 | if (i < n) 65 | str[i++] = ch; 66 | str[i] = '\0'; 67 | return i; 68 | } 69 | -------------------------------------------------------------------------------- /ch08/projects/08.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Modified version of `07.c` */ 5 | 6 | int max_score(int arr[5]); 7 | int min_score(int arr[5]); 8 | 9 | int main() 10 | { 11 | int i, j, cur, quiz_score_sums[5] = {}, student_score_sums[5] = {}, 12 | // scores categorised by quizes 13 | quiz_scores[5][5] = {}; 14 | 15 | printf("Enter five quiz grades for each of five students "); 16 | printf("(scores separated by a black space)\n"); 17 | for (i = 0; i < 5; i++) 18 | // traverse rows 19 | { 20 | printf("Enter student #%d\'s grades: ", i + 1); 21 | for (j = 0; j < 5; j++) 22 | // traverse columns 23 | { 24 | scanf("%d", &cur); 25 | 26 | quiz_scores[j][i] = cur; 27 | // accumulate scanned value to respective running totals 28 | student_score_sums[i] += cur; 29 | quiz_score_sums[j] += cur; 30 | } 31 | } 32 | 33 | /* print out results */ 34 | 35 | printf("\n--STUDENT STATISTICS--\n"); 36 | printf("Total score of each student: \n"); 37 | for (int i = 0; i < 5; i++) 38 | { 39 | printf(" Student #%d:", i + 1); 40 | printf("%3d (avg: %4.2f)", student_score_sums[i], student_score_sums[i] / 5.0); 41 | printf("\n"); 42 | } 43 | printf("\n--QUIZ STATISTICS--:\n"); 44 | for (int i = 0; i < 5; i++) 45 | { 46 | printf(" Quiz #%d:", i + 1); 47 | printf(" %4.2f; %d; %d", quiz_score_sums[i] / 5.0, min_score(quiz_scores[i]), max_score(quiz_scores[i])); 48 | printf("\n"); 49 | } 50 | printf("\n"); 51 | 52 | return 0; 53 | } 54 | 55 | /* implementations */ 56 | 57 | int max_score(int arr[5]) 58 | { 59 | int res = 0; 60 | 61 | for (int i = 0; i < 5; i++) 62 | { 63 | if (arr[i] > res) 64 | res = arr[i]; 65 | } 66 | 67 | return res; 68 | } 69 | 70 | int min_score(int arr[5]) 71 | { 72 | int res = arr[0]; 73 | 74 | for (int i = 1; i < 5; i++) 75 | { 76 | if (arr[i] < res) 77 | res = arr[i]; 78 | } 79 | 80 | return res; 81 | } -------------------------------------------------------------------------------- /ch11/exercises/07.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int is_leap_year(int *const year) { 5 | if (*year < 0) { 6 | printf("INVALID YEAR INPUT!\n"); 7 | exit(EXIT_FAILURE); 8 | } 9 | else { 10 | return !(*year % 4); 11 | } 12 | } 13 | 14 | int num_days_in_month(int month, int leap_indicator) { 15 | if (month < 1 || month > 12) { 16 | printf("INVALID MONTH NUMBER!\n"); 17 | exit(EXIT_FAILURE); 18 | } 19 | else { 20 | if (month == 2) { 21 | return 28 + leap_indicator; 22 | } 23 | else { 24 | // return 30 + ((month < 8) ? (month % 2) : !(month % 2)); 25 | return 30 + (!(month < 8) || (month % 2)); 26 | } 27 | } 28 | } 29 | 30 | void split_date(int day_of_year, int year, int *const month, int *const day) { 31 | const int leap_indicator = is_leap_year(&year); 32 | 33 | if (day_of_year < 1 || day_of_year > 365 + leap_indicator) { 34 | printf("INVALID INPUT!\n"); 35 | exit(EXIT_FAILURE); 36 | } 37 | else { 38 | int NUM_DAYS[13]; 39 | 40 | NUM_DAYS[0] = 0; 41 | for (int _month = 1; _month <= 12; _month++) { 42 | // calculate the number of days since the 01/01 to this month 43 | NUM_DAYS[_month] = NUM_DAYS[_month - 1] + num_days_in_month(_month, leap_indicator); 44 | } 45 | 46 | for (int _month = 1; _month <= 12; _month++) { 47 | if (day_of_year > NUM_DAYS[_month - 1] && day_of_year <= NUM_DAYS[_month]) { 48 | *month = _month; 49 | *day = day_of_year - NUM_DAYS[_month - 1]; 50 | break; 51 | } 52 | } 53 | } 54 | 55 | } 56 | 57 | int main () { 58 | int days, y, m, d; 59 | printf("What year? "); 60 | scanf("%d", &y); 61 | int leap_indicator = is_leap_year(&y); 62 | 63 | printf("Input an integer between 1 and %d, specifying a particular day within the year of %d: " 64 | , (365 + leap_indicator), y); 65 | scanf("%d", &days); 66 | 67 | split_date(days, y, &m, &d); 68 | printf("Result: %.2d/%.2d\n", d, m); 69 | 70 | return 0; 71 | } -------------------------------------------------------------------------------- /textbook_code_snippets/stackADT3.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* stackADT3.c (Chapter 19, page 500) */ 11 | 12 | #include 13 | #include 14 | #include "stackADT.h" 15 | 16 | struct node { 17 | Item data; 18 | struct node *next; 19 | }; 20 | 21 | struct stack_type { 22 | struct node *top; 23 | }; 24 | 25 | static void terminate(const char *message) 26 | { 27 | printf("%s\n", message); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | Stack create(void) 32 | { 33 | Stack s = malloc(sizeof(struct stack_type)); 34 | if (s == NULL) 35 | terminate("Error in create: stack could not be created."); 36 | s->top = NULL; 37 | return s; 38 | } 39 | 40 | void destroy(Stack s) 41 | { 42 | make_empty(s); 43 | free(s); 44 | } 45 | 46 | void make_empty(Stack s) 47 | { 48 | while (!is_empty(s)) 49 | pop(s); 50 | } 51 | 52 | bool is_empty(Stack s) 53 | { 54 | return s->top == NULL; 55 | } 56 | 57 | bool is_full(Stack s) 58 | { 59 | return false; 60 | } 61 | 62 | void push(Stack s, Item i) 63 | { 64 | struct node *new_node = malloc(sizeof(struct node)); 65 | if (new_node == NULL) 66 | terminate("Error in push: stack is full."); 67 | 68 | new_node->data = i; 69 | new_node->next = s->top; 70 | s->top = new_node; 71 | } 72 | 73 | Item pop(Stack s) 74 | { 75 | struct node *old_top; 76 | Item i; 77 | 78 | if (is_empty(s)) 79 | terminate("Error in pop: stack is empty."); 80 | 81 | old_top = s->top; 82 | i = old_top->data; 83 | s->top = old_top->next; 84 | free(old_top); 85 | return i; 86 | } 87 | -------------------------------------------------------------------------------- /ch03/exercises/03.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | int a, b, c; 6 | float d, e; 7 | 8 | char formats[4][2][12] = { 9 | {"%d", " %d"}, 10 | {"%d-%d-%d", "%d -%d -%d"}, 11 | {"%f", "%f "}, 12 | {"%f,%f", "%f, %f"} 13 | }; 14 | 15 | /* Test case (a) */ 16 | printf("\nInput x for scanning with the format `%%d`: "); 17 | scanf(formats[0][0], &a); 18 | printf("x = %d\n", a); 19 | 20 | printf("\nInput x for scanning with the format ` %%d`: "); 21 | scanf(formats[0][1], &a); 22 | printf("x = %d\n", a); 23 | 24 | /* Test case (b) */ 25 | printf("\nInput x,y,z for scanning with the format `%%d-%%d-%%d`: "); 26 | scanf(formats[1][0], &a, &b, &c); 27 | printf("x = %d; y = %d; z = %d\n", a, b, c); 28 | 29 | printf("\nInput x,y,z for scanning with the format `%%d -%%d -%%d`: "); 30 | scanf(formats[1][1], &a, &b, &c); 31 | printf("x = %d; y = %d; z = %d\n", a, b, c); 32 | 33 | /* Test case (c) */ 34 | printf("\nInput x for scanning with the format `%%f`: "); 35 | scanf(formats[2][0], &d); 36 | printf("x = %f\n", d); 37 | 38 | printf("\nInput x for scanning with the format `%%f `: "); 39 | // to escape backspace in this case, you should input float followed by an invalid character, i.e. '-' 40 | scanf(formats[2][1], &d); 41 | printf("x = %f\n", d); 42 | 43 | /* Test case (d) */ 44 | printf("\nInput x,y,z for scanning with the format `%%f,%%f`: "); 45 | scanf(formats[3][0], &d, &e); 46 | printf("x = %f; y = %f\n", d, e); 47 | 48 | printf("\nInput x,y,z for scanning with the format `%%f, %%f`: "); 49 | scanf(formats[3][1], &d, &e); 50 | printf("x = %f; y = %f\n", d, e); 51 | 52 | /* CONCLUSION: For case: 53 | (a) these two format strings help `scanf` to behave the same 54 | (b) the second format string can be used as alternative for the first one but not vice versa 55 | (c) these two format strings don't help `scanf` to behave the same 56 | (d) the second format string can be used as alternative for the first one but not vice versa 57 | */ 58 | 59 | return 0; 60 | } -------------------------------------------------------------------------------- /ch12/projects/06.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* Sorts an array of integers using Quicksort algorithm 4 | * modified version of `qsort.c` (chapter 9, page 207) 5 | */ 6 | 7 | #define N 10 8 | 9 | void quicksort(int* a_low, int* a_high); 10 | int *split(int* a_low, int* a_high); 11 | 12 | int main(void) 13 | { 14 | int a[N], i; 15 | 16 | printf("Enter %d numbers to be sorted: ", N); 17 | for (i = 0; i < N; i++) 18 | scanf("%d", a+i); 19 | 20 | quicksort(a, a + N - 1); 21 | 22 | printf("In sorted order: "); 23 | for (i = 0; i < N; i++) 24 | printf("%d ", a[i]); 25 | printf("\n"); 26 | 27 | return 0; 28 | } 29 | 30 | void quicksort(int *a_low, int *a_high) 31 | { 32 | int *middle; 33 | 34 | if (a_low >= a_high) return; 35 | middle = split(a_low, a_high); 36 | quicksort(a_low, middle - 1); 37 | quicksort(middle + 1, a_high); 38 | } 39 | 40 | int *split(int *a_low, int *a_high) { 41 | int pivot = *a_low; 42 | 43 | /* At the end of this loop, `a_high` is the correct position to place `pivot` value in. 44 | All elements from the head of the array to the pivot position are smaller than or equal to `pivot`. 45 | All elements from the pivot position to the end of the array are larger than or equal to `pivot` 46 | */ 47 | for (;;) { 48 | while (a_low < a_high && *a_high >= pivot) { 49 | // shift `a_high` pointer 1 cell leftward 50 | a_high--; 51 | } 52 | if (a_low >= a_high) { 53 | break; 54 | } 55 | /* `a_high` currently points to an element smaller than `pivot`; 56 | hence, this value is assigned to the first position in the sorted array */ 57 | *(a_low++) = *a_high; 58 | 59 | while (a_low < a_high && *a_low <= pivot) { 60 | // shift `a_low` pointer 1 cell rightward 61 | a_low++; 62 | } 63 | if (a_low >= a_high) { 64 | break; 65 | } 66 | /* `a_low` currently points to an element larger than `pivot`; 67 | hence, this value is assigned to the last position in the sorted array */ 68 | *(a_high--) = *a_low; 69 | } 70 | 71 | *a_high = pivot; 72 | return a_high; 73 | } 74 | 75 | -------------------------------------------------------------------------------- /ch09/projects/05.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* De la Loubère's method for solving magic square 4 | * modified version of `../../ch08/projects/17.c` */ 5 | 6 | int i, j; 7 | int board[99][99] = {}; 8 | 9 | /* Implement De la Loubère's method to create magic square of size n*n */ 10 | void create_magic_square(int n, int magic_square[n][n]); 11 | 12 | /* Print the matrix out */ 13 | void print_magic_square(int n, int magic_square[n][n]); 14 | 15 | int main() { 16 | unsigned short int size; 17 | printf("This program creates a magic square of a specific size.\n"); 18 | printf("The size must be an odd number between 1 and 99.\n"); 19 | printf("Enter size of magic number: "); 20 | scanf("%hu", &size); 21 | 22 | /* validate number of size */ 23 | if (size < 0 || size > 99) { 24 | printf("INVALID INPUT!\n"); 25 | return 1; 26 | } 27 | 28 | if (size % 2 == 0) 29 | size++; 30 | 31 | create_magic_square((int) size, (int (*)[size][size]) board); 32 | print_magic_square((int) size, (int (*)[size][size]) board); 33 | 34 | return 0; 35 | } 36 | 37 | /* implementation */ 38 | 39 | void create_magic_square(int n, int magic_square[n][n]) { 40 | int cur_x, cur_y, next_x, next_y; 41 | 42 | for (i = 1, cur_x = n / 2, cur_y = 0; 43 | i <= n * n; 44 | i++) { 45 | magic_square[cur_y][cur_x] = i; 46 | 47 | next_y = (n + cur_y - 1) % n; 48 | next_x = (cur_x + 1) % n; 49 | 50 | if (magic_square[next_y][next_x] == 0) { 51 | // move the cursor 1 row upward and 1 column to the rightward 52 | cur_y = next_y; 53 | cur_x = next_x; 54 | } 55 | else { 56 | // if the cell to move to is already populated, move the cursor 1 row downward 57 | next_y = (cur_y + 1) % n; 58 | cur_y = next_y; 59 | } 60 | 61 | // printf("Num: %d \n", i, cur_y, cur_x); 62 | } 63 | } 64 | 65 | void print_magic_square(int n, int magic_square[n][n]) { 66 | for (i = 0; i < n; i++) { 67 | for (j = 0; j < n; j++) { 68 | printf("%6d ", magic_square[i][j]); 69 | } 70 | printf("\n"); 71 | } 72 | } 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /textbook_code_snippets/line.h: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* line.h (Chapter 15, page 362) */ 11 | 12 | #ifndef LINE_H 13 | #define LINE_H 14 | 15 | /********************************************************** 16 | * clear_line: Clears the current line. * 17 | **********************************************************/ 18 | void clear_line(void); 19 | 20 | /********************************************************** 21 | * add_word: Adds word to the end of the current line. * 22 | * If this is not the first word on the line, * 23 | * puts one space before word. * 24 | **********************************************************/ 25 | void add_word(const char *word); 26 | 27 | /********************************************************** 28 | * space_remaining: Returns the number of characters left * 29 | * in the current line. * 30 | **********************************************************/ 31 | int space_remaining(void); 32 | 33 | /********************************************************** 34 | * write_line: Writes the current line with * 35 | * justification. * 36 | **********************************************************/ 37 | void write_line(void); 38 | 39 | /********************************************************** 40 | * flush_line: Writes the current line without * 41 | * justification. If the line is empty, does * 42 | * nothing. * 43 | **********************************************************/ 44 | void flush_line(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /textbook_code_snippets/remind2.c: -------------------------------------------------------------------------------- 1 | /********************************************************* 2 | * From C PROGRAMMING: A MODERN APPROACH, Second Edition * 3 | * By K. N. King * 4 | * Copyright (c) 2008, 1996 W. W. Norton & Company, Inc. * 5 | * All rights reserved. * 6 | * This program may be freely distributed for class use, * 7 | * provided that this copyright notice is retained. * 8 | *********************************************************/ 9 | 10 | /* remind2.c (Chapter 17, page 418) */ 11 | /* Prints a one-month reminder list (dynamic string version) */ 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #define MAX_REMIND 50 /* maximum number of reminders */ 18 | #define MSG_LEN 60 /* max length of reminder message */ 19 | 20 | int read_line(char str[], int n); 21 | 22 | int main(void) 23 | { 24 | char *reminders[MAX_REMIND]; 25 | char day_str[3], msg_str[MSG_LEN+1]; 26 | int day, i, j, num_remind = 0; 27 | 28 | for (;;) { 29 | if (num_remind == MAX_REMIND) { 30 | printf("-- No space left --\n"); 31 | break; 32 | } 33 | 34 | printf("Enter day and reminder: "); 35 | scanf("%2d", &day); 36 | if (day == 0) 37 | break; 38 | sprintf(day_str, "%2d", day); 39 | read_line(msg_str, MSG_LEN); 40 | 41 | for (i = 0; i < num_remind; i++) 42 | if (strcmp(day_str, reminders[i]) < 0) 43 | break; 44 | for (j = num_remind; j > i; j--) 45 | reminders[j] = reminders[j-1]; 46 | 47 | reminders[i] = malloc(2 + strlen(msg_str) + 1); 48 | if (reminders[i] == NULL) { 49 | printf("-- No space left --\n"); 50 | break; 51 | } 52 | 53 | strcpy(reminders[i], day_str); 54 | strcat(reminders[i], msg_str); 55 | 56 | num_remind++; 57 | } 58 | 59 | printf("\nDay Reminder\n"); 60 | for (i = 0; i < num_remind; i++) 61 | printf(" %s\n", reminders[i]); 62 | 63 | return 0; 64 | } 65 | 66 | int read_line(char str[], int n) 67 | { 68 | int ch, i = 0; 69 | 70 | while ((ch = getchar()) != '\n') 71 | if (i < n) 72 | str[i++] = ch; 73 | str[i] = '\0'; 74 | return i; 75 | } 76 | --------------------------------------------------------------------------------