├── figure ├── 1.1.pdf ├── 1.1.png ├── 5.1.pdf ├── 5.1.png ├── 5.2.pdf ├── 5.2.png ├── 5.3.pdf ├── 5.3.png ├── 5.4.pdf ├── 5.4.png ├── 5.5.pdf ├── 5.5.png ├── 5.6.pdf ├── 5.6.png ├── 5.7.pdf ├── 5.7.png ├── 6.1.pdf ├── 6.1.png ├── 6.2.pdf ├── 6.2.png ├── 6.3.pdf ├── 6.3.png ├── 7.1.pdf ├── 7.1.png ├── 8.1.pdf ├── 8.1.png ├── 10.1.pdf ├── 10.1.png ├── 10.2.pdf └── 10.2.png ├── example ├── example4-1.c ├── example5-9.c ├── example4-11.c ├── example5-17.c ├── example9-5.c ├── example6-16.c ├── example6-17.c ├── example7-2.c ├── example9-2.c ├── example6-10.c ├── example6-18.c ├── example10-1.c ├── example7-3.c ├── example3-9.c ├── example2-6.c ├── example2-1.c ├── example4-6.c ├── example6-3.c ├── example5-15.c ├── example2-10.c ├── example2-5.c ├── example2-3.c ├── example2-11.c ├── example3-3.c ├── example7-1.c ├── example1-3.c ├── example3-2.c ├── example2-7.c ├── example6-15.c ├── example4-5.c ├── example5-16.c ├── example5-5.c ├── example6-11.c ├── example3-1.c ├── example3-7.c ├── example5-14.c ├── example8-6.c ├── example5-3.c ├── example6-5.c ├── example3-4.c ├── example5-4.c ├── example3-5.c ├── example5-8.c ├── example4-7.c ├── example4-9.c ├── example9-8.c ├── example4-12.c ├── example5-7.c ├── example3-6.c ├── example4-10.c ├── example9-1.c ├── example6-13.c ├── example2-9.c ├── example5-1.c ├── example6-4.c ├── example2-4.c ├── example2-2.c ├── example3-10.c ├── example5-2.c ├── example4-3.c ├── example6-6.c ├── example4-2.c ├── example8-1.c ├── example6-14.c ├── example1-2.c ├── example5-6.c ├── example1-1.c ├── example4-4.c ├── example9-6.c ├── example2-8.c ├── example8-3.c ├── example9-3.c ├── example9-4.c ├── example9-7.c ├── example6-12.c ├── example6-7.c ├── example8-5.c ├── example8-4.c ├── example1-4.c ├── example6-8.c ├── example6-2.c ├── example6-1.c ├── example10-4.c ├── example5-12.c ├── example5-11.c ├── example8-2.c ├── example6-9.c ├── example5-10.c ├── example4-8.c ├── example10-6.c ├── example5-13.c ├── example10-2.c ├── example10-8.c ├── example10-7.c ├── example10-5.c └── example10-3.c ├── .gitignore ├── bib.bib ├── fancyvrb.ins ├── README.md ├── LICENSE └── thecbook.tex /figure/1.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/1.1.pdf -------------------------------------------------------------------------------- /figure/1.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/1.1.png -------------------------------------------------------------------------------- /figure/5.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.1.pdf -------------------------------------------------------------------------------- /figure/5.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.1.png -------------------------------------------------------------------------------- /figure/5.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.2.pdf -------------------------------------------------------------------------------- /figure/5.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.2.png -------------------------------------------------------------------------------- /figure/5.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.3.pdf -------------------------------------------------------------------------------- /figure/5.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.3.png -------------------------------------------------------------------------------- /figure/5.4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.4.pdf -------------------------------------------------------------------------------- /figure/5.4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.4.png -------------------------------------------------------------------------------- /figure/5.5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.5.pdf -------------------------------------------------------------------------------- /figure/5.5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.5.png -------------------------------------------------------------------------------- /figure/5.6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.6.pdf -------------------------------------------------------------------------------- /figure/5.6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.6.png -------------------------------------------------------------------------------- /figure/5.7.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.7.pdf -------------------------------------------------------------------------------- /figure/5.7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/5.7.png -------------------------------------------------------------------------------- /figure/6.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.1.pdf -------------------------------------------------------------------------------- /figure/6.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.1.png -------------------------------------------------------------------------------- /figure/6.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.2.pdf -------------------------------------------------------------------------------- /figure/6.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.2.png -------------------------------------------------------------------------------- /figure/6.3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.3.pdf -------------------------------------------------------------------------------- /figure/6.3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/6.3.png -------------------------------------------------------------------------------- /figure/7.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/7.1.pdf -------------------------------------------------------------------------------- /figure/7.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/7.1.png -------------------------------------------------------------------------------- /figure/8.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/8.1.pdf -------------------------------------------------------------------------------- /figure/8.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/8.1.png -------------------------------------------------------------------------------- /figure/10.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/10.1.pdf -------------------------------------------------------------------------------- /figure/10.1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/10.1.png -------------------------------------------------------------------------------- /figure/10.2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/10.2.pdf -------------------------------------------------------------------------------- /figure/10.2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wardvanwanrooij/thecbook/HEAD/figure/10.2.png -------------------------------------------------------------------------------- /example/example4-1.c: -------------------------------------------------------------------------------- 1 | main() { 2 | double return_v, aax1(void); 3 | return_v = aax1(); 4 | exit(EXIT_SUCCESS); 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /*.aux 2 | /*.log 3 | /*.out 4 | /*.toc 5 | /*.bbl 6 | /*.blg 7 | /*.synctex.gz 8 | /*.lot 9 | /*.lof 10 | /*.pdf 11 | -------------------------------------------------------------------------------- /example/example5-9.c: -------------------------------------------------------------------------------- 1 | #define ARLEN 10 2 | 3 | int ar[ARLEN], *ip; 4 | 5 | ip = ar; 6 | while (ip < &ar[ARLEN]) 7 | *(ip++) = 0; 8 | -------------------------------------------------------------------------------- /example/example4-11.c: -------------------------------------------------------------------------------- 1 | int 2 | small_val (void) { 3 | static unsigned count; 4 | count++; 5 | return (count % 16); 6 | } 7 | -------------------------------------------------------------------------------- /example/example5-17.c: -------------------------------------------------------------------------------- 1 | void (*fparr[])(int, float) = { 2 | /* initializers */ 3 | }; 4 | /* then call one */ 5 | 6 | fparr[5](1, 3.4); 7 | -------------------------------------------------------------------------------- /example/example9-5.c: -------------------------------------------------------------------------------- 1 | int f(int, ... ); 2 | 3 | int f(int a, ... ) { 4 | /* ... */ 5 | } 6 | 7 | int g() { 8 | f(1,2,3); 9 | } 10 | -------------------------------------------------------------------------------- /example/example6-16.c: -------------------------------------------------------------------------------- 1 | struct s { 2 | int a; 3 | struct ss { 4 | int c; 5 | char d; 6 | } e; 7 | } x[] = { 8 | 1, 2, 'a', 9 | 3, 4, 'b' 10 | }; 11 | -------------------------------------------------------------------------------- /example/example6-17.c: -------------------------------------------------------------------------------- 1 | struct s { 2 | int a; 3 | struct ss { 4 | int c; 5 | char d; 6 | } e; 7 | } x[] = { 8 | {1, {2, 'a'}}, 9 | {3, {4, 'b'}} 10 | }; 11 | -------------------------------------------------------------------------------- /example/example7-2.c: -------------------------------------------------------------------------------- 1 | #define TEST(x) if(!(x))\ 2 | printf("test failed, line %d file %s\n",\ 3 | __LINE__, __FILE__) 4 | 5 | /**/ 6 | 7 | TEST(a != 23); 8 | 9 | /**/ -------------------------------------------------------------------------------- /example/example9-2.c: -------------------------------------------------------------------------------- 1 | #define NDEBUG 2 | #include 3 | 4 | void 5 | func(void) 6 | { 7 | int c; 8 | assert((c = getchar()) != EOF); 9 | putchar(c); 10 | } -------------------------------------------------------------------------------- /example/example6-10.c: -------------------------------------------------------------------------------- 1 | void 2 | t_walk(struct tree_node *root_p) { 3 | if(root_p == 0) 4 | return; 5 | t_walk(root_p->left_p); 6 | printf("%d\n", root_p->data); 7 | t_walk(root_p->right_p); 8 | } 9 | -------------------------------------------------------------------------------- /example/example6-18.c: -------------------------------------------------------------------------------- 1 | float y[4][3] = { 2 | {1, 3, 5}, /* y[0][0], y[0][1], y[0][2] */ 3 | {2, 4, 6}, /* y[1][0], y[1][1], y[1][2] */ 4 | {3, 5, 7} /* y[2][0], y[2][1], y[2][2] */ 5 | }; 6 | -------------------------------------------------------------------------------- /example/example10-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv) 5 | { 6 | while(argc--) 7 | printf("%s\n", *argv++); 8 | exit(EXIT_SUCCESS); 9 | } -------------------------------------------------------------------------------- /example/example7-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #if ULONG_MAX+1 != 0 4 | printf("Preprocessor: ULONG_MAX+1 != 0\n"); 5 | #endif 6 | 7 | if(ULONG_MAX+1 != 0) 8 | printf("Runtime: ULONG_MAX+1 != 0\n"); -------------------------------------------------------------------------------- /example/example3-9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | 7 | for (i=0; i <= 10; i++) { 8 | printf((i&1) ? "odd\n" : "even\n"); 9 | } 10 | exit(EXIT_SUCCESS); 11 | } 12 | -------------------------------------------------------------------------------- /bib.bib: -------------------------------------------------------------------------------- 1 | @Book{Stro, 2 | author = {B. Stroustrup}, 3 | title = {The C++ Programming Language}, 4 | publisher = {Addison-Wesley}, 5 | year = {1991}, 6 | address = {Reading, MA}, 7 | edition = {2.} 8 | } 9 | 10 | -------------------------------------------------------------------------------- /example/example2-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | unsigned int x; 6 | x = 0; 7 | while (x >= 0) { 8 | printf("%d\n", x); 9 | x = x+1; 10 | } 11 | 12 | exit(EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /example/example2-1.c: -------------------------------------------------------------------------------- 1 | int f(void) { 2 | float f_var; 3 | double d_var; 4 | long double l_d_var; 5 | 6 | f_var = 1; d_var = 1; l_d_var = 1; 7 | d_var = d_var + f_var; 8 | l_d_var = d_var + f_var; 9 | return(l_d_var); 10 | } 11 | -------------------------------------------------------------------------------- /example/example4-6.c: -------------------------------------------------------------------------------- 1 | void called_func(int, float); 2 | 3 | main() { 4 | called_func(1, 2*3.5); 5 | exit(EXIT_SUCCESS); 6 | } 7 | 8 | void 9 | called_func(int iarg, float farg) { 10 | float tmp; 11 | 12 | tmp = iarg * farg; 13 | } 14 | -------------------------------------------------------------------------------- /example/example6-3.c: -------------------------------------------------------------------------------- 1 | struct s_1; /* incomplete type */ 2 | 3 | struct s_2 { 4 | int something; 5 | struct s_1 *sp; 6 | }; 7 | 8 | struct s_1 { /* now the full declaration */ 9 | float something; 10 | struct s_2 *sp; 11 | }; 12 | -------------------------------------------------------------------------------- /example/example5-15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | main() { 6 | size_t sz; 7 | sz = sizeof(sz); 8 | printf("size of sizeof is %lu\n", 9 | (unsigned long)sz); 10 | exit(EXIT_SUCCESS); 11 | } 12 | -------------------------------------------------------------------------------- /example/example2-10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | int a,b; 5 | a = b = 5; 6 | printf("%d\n", ++a+5); 7 | printf("%d\n", a); 8 | printf("%d\n", b++ +5); 9 | printf("%d\n", b); 10 | exit(EXIT_SUCCESS); 11 | } 12 | -------------------------------------------------------------------------------- /example/example2-5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | char c; 6 | 7 | c = 'a'; 8 | while (c <= 'z') { 9 | printf("value %d char %c\n", c, c); 10 | c = c+1; 11 | } 12 | 13 | exit(EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /example/example2-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | main() { 6 | char c; 7 | 8 | c = CHAR_MIN; 9 | do { 10 | printf("%d\n", c); 11 | c = c+1; 12 | } while (c < CHAR_MAX); 13 | 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example2-11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main(){ 5 | int i,j; 6 | float f; 7 | 8 | i = 5; j = 2; 9 | f = 3.0; 10 | 11 | f = f + j / i; 12 | printf("value of f is %f\n", f); 13 | exit(EXIT_SUCCESS); 14 | } -------------------------------------------------------------------------------- /example/example3-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | /* initialise */ 7 | i = 0; 8 | /* check */ 9 | while (i <= 10) { 10 | printf("%d\n", i); 11 | /* update */ 12 | i++; 13 | } 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example7-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define DOUBLE(x) ((x)+(x)) 4 | 5 | main(){ 6 | int a[20], *ip; 7 | 8 | ip = a; 9 | a[0] = 1; 10 | a[1] = 2; 11 | printf("%d\n", DOUBLE(*ip++)); 12 | exit(EXIT_SUCCESS); 13 | } -------------------------------------------------------------------------------- /example/example1-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | int ch; 5 | 6 | ch = getchar(); 7 | while(ch != 'a'){ 8 | if(ch != '\n') 9 | printf("ch was %c, value %d\n", ch, ch); 10 | ch = getchar(); 11 | } 12 | exit(EXIT_SUCCESS); 13 | } 14 | -------------------------------------------------------------------------------- /example/example3-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int input_c; 6 | 7 | /* The Classic Bit */ 8 | while ((input_c = getchar()) != EOF) { 9 | printf("%c was read\n", input_c); 10 | } 11 | exit(EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /example/example2-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | int i; 5 | unsigned int stop_val; 6 | 7 | stop_val = 0; 8 | i = -10; 9 | 10 | while (i <= stop_val) { 11 | printf("%d\n", i); 12 | i = i + 1; 13 | } 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example6-15.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct s { 5 | int a; 6 | char b; 7 | char *cp; 8 | } ex_s = {1, 'a', "hello"}; 9 | 10 | main() { 11 | struct s first = ex_s; 12 | struct s second = {2, 'b', "byebye" }; 13 | 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example4-5.c: -------------------------------------------------------------------------------- 1 | int a; /* visible from here onwards */ 2 | 3 | void func(void) { 4 | float a; /* a different 'a' */ 5 | { 6 | char a; /* yet another 'a' */ 7 | } 8 | /* the float 'a' reappears */ 9 | } 10 | /* the int 'a' reappears */ 11 | -------------------------------------------------------------------------------- /example/example5-16.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void func(int); 5 | 6 | main() { 7 | void (*fp)(int); 8 | 9 | fp = func; 10 | 11 | (*fp)(1); 12 | fp(2); 13 | 14 | exit(EXIT_SUCCESS); 15 | } 16 | 17 | void 18 | func(int arg) { 19 | printf("%d\n", arg); 20 | } 21 | -------------------------------------------------------------------------------- /example/example5-5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #define ARSZ 10 3 | 4 | main() { 5 | float fa[ARSZ], *fp1, *fp2; 6 | 7 | fp1 = fp2 = fa; /* address of first element */ 8 | while (fp2 != &fa[ARSZ]) { 9 | printf("Difference: %ld\n", (long)(fp2-fp1)); 10 | fp2++; 11 | } 12 | return(0); 13 | } 14 | -------------------------------------------------------------------------------- /example/example6-11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | union { 6 | float u_f; 7 | int u_i; 8 | } var; 9 | 10 | var.u_f = 23.5; 11 | printf("value is %f\n", var.u_f); 12 | var.u_i = 5; 13 | printf("value is %d\n", var.u_i); 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example3-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | 7 | i = -10; 8 | while (i <= 5) { 9 | printf("value of i is %d, ", i); 10 | printf("i == 0 = %d, ", i==0 ); 11 | printf("i > -5 = %d\n", i > -5); 12 | i++; 13 | } 14 | exit(EXIT_SUCCESS); 15 | } 16 | -------------------------------------------------------------------------------- /example/example3-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | 7 | for (i = -10; i < 10; i++) { 8 | if (i == 0) 9 | continue; 10 | printf("%f\n", 15.0/i); 11 | /* 12 | * Lots of other statements ..... 13 | */ 14 | } 15 | exit(EXIT_SUCCESS); 16 | } 17 | -------------------------------------------------------------------------------- /example/example5-14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | const char arr[] = "hello"; 5 | const char *cp = arr; 6 | main() { 7 | printf("Size of arr %lu\n", (unsigned long) 8 | sizeof(arr)); 9 | printf("Size of *cp %lu\n", (unsigned long) 10 | sizeof(*cp)); 11 | exit(EXIT_SUCCESS); 12 | } 13 | -------------------------------------------------------------------------------- /example/example8-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int i_var; 5 | void func(void); 6 | 7 | main() { 8 | while (i_var != 10000) { 9 | func(); 10 | i_var++; 11 | } 12 | exit(EXIT_SUCCESS); 13 | } 14 | 15 | void 16 | func(void) { 17 | printf("in func, i_var is %d\n", i_var); 18 | } 19 | -------------------------------------------------------------------------------- /example/example5-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define ARSZ 20 4 | main() { 5 | int ar[ARSZ], i; 6 | for (i = 0; i < ARSZ; i++) { 7 | ar[i] = i; 8 | i[ar]++; 9 | printf("ar[%d] now = %d\n", i, ar[i]); 10 | } 11 | 12 | printf("15[ar] = %d\n", 15[ar]); 13 | exit(EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /example/example6-5.c: -------------------------------------------------------------------------------- 1 | struct list_ele { 2 | int data; 3 | struct list_ele *pointer; 4 | } ar[3]; 5 | 6 | main() { 7 | ar[0].data = 5; 8 | ar[0].pointer = &ar[1]; 9 | ar[1].data = 99; 10 | ar[1].pointer = &ar[2]; 11 | ar[2].data = -7; 12 | ar[2].pointer = 0; /* mark end of list */ 13 | return(0); 14 | } 15 | -------------------------------------------------------------------------------- /example/example3-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | int i; 5 | 6 | i = 0; 7 | while (i <= 10) { 8 | printf("%d\n", i); 9 | i++; 10 | } 11 | 12 | /* the same done using ``for'' */ 13 | for (i = 0; i <= 10; i++) { 14 | printf("%d\n", i); 15 | } 16 | exit(EXIT_SUCCESS); 17 | } 18 | -------------------------------------------------------------------------------- /example/example5-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define ARSZ 10 4 | 5 | main() { 6 | float fa[ARSZ], *fp1, *fp2; 7 | 8 | fp1 = fp2 = fa; /* address of first element */ 9 | while (fp2 != &fa[ARSZ]) { 10 | printf("Difference: %d\n", (int)(fp2-fp1)); 11 | fp2++; 12 | } 13 | exit(EXIT_SUCCESS); 14 | } 15 | -------------------------------------------------------------------------------- /example/example3-5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | for (i = 0; i <= 10; i++) { 7 | switch (i) { 8 | case 1: 9 | case 2: 10 | printf("1 or 2\n"); 11 | case 7: 12 | printf("7\n"); 13 | default: 14 | printf("default\n"); 15 | } 16 | } 17 | exit(EXIT_SUCCESS); 18 | } 19 | -------------------------------------------------------------------------------- /example/example5-8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | char *cp; 7 | 8 | cp = "a string"; 9 | while (*cp != 0) { 10 | putchar(*cp); 11 | cp++; 12 | } 13 | putchar('\n'); 14 | 15 | for(i = 0; i < 8; i++) 16 | putchar("a string"[i]); 17 | putchar('\n'); 18 | exit(EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /example/example4-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | void changer(int); 5 | int i; 6 | 7 | i = 5; 8 | printf("before i=%d\n", i); 9 | changer(i); 10 | printf("after i=%d\n", i); 11 | exit(EXIT_SUCCESS); 12 | } 13 | 14 | void 15 | changer(int x) { 16 | while(x){ 17 | printf("changer: x=%d\n", x); 18 | x--; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/example4-9.c: -------------------------------------------------------------------------------- 1 | /* first file */ 2 | 3 | int i; /* definition */ 4 | main () { 5 | void f_in_other_place (void); /* declaration */ 6 | i = 0; 7 | } 8 | /* end of first file */ 9 | 10 | 11 | /* start of second file */ 12 | 13 | extern int i; /* declaration */ 14 | void f_in_other_place (void) { /* definition */ 15 | i++; 16 | } 17 | /* end of second file */ 18 | -------------------------------------------------------------------------------- /example/example9-8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main(){ 5 | 6 | fclose(stdout); 7 | if(fgetc(stdout) >= 0){ 8 | fprintf(stderr, "What - no error!\n"); 9 | exit(EXIT_FAILURE); 10 | } 11 | perror("fgetc"); 12 | exit(EXIT_SUCCESS); 13 | } 14 | 15 | /* Result */ 16 | fgetc: Bad file number -------------------------------------------------------------------------------- /example/example4-12.c: -------------------------------------------------------------------------------- 1 | void 2 | r_func(void) { 3 | static int depth; 4 | depth++; 5 | if (depth > 200) { 6 | printf ("excessive recursion\n"); 7 | exit (1); 8 | } else { 9 | /* do usual thing, not shown here. 10 | * This last action 11 | * occasionally results in another call on r_func() 12 | */ 13 | x_func(); 14 | } 15 | depth--; 16 | } 17 | -------------------------------------------------------------------------------- /example/example5-7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Compare two strings for equality. 3 | * Return 'false' if they are. 4 | */ 5 | int 6 | str_eq(const char *s1, const char *s2) { 7 | while(*s1 == *s2) { 8 | /* 9 | * At end of string return 0. 10 | */ 11 | if (*s1 == 0) 12 | return(0); 13 | s1++; s2++; 14 | } 15 | /* Difference detected! */ 16 | return(1); 17 | } 18 | -------------------------------------------------------------------------------- /example/example3-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | for (i = 0; i <= 10; i++) { 7 | switch (i) { 8 | case 1: 9 | case 2: 10 | printf("1 or 2\n"); 11 | break; 12 | case 7: 13 | printf("7\n"); 14 | break; 15 | default: 16 | printf("default\n"); 17 | } 18 | } 19 | exit(EXIT_SUCCESS); 20 | } 21 | -------------------------------------------------------------------------------- /example/example4-10.c: -------------------------------------------------------------------------------- 1 | /* example library module */ 2 | /* only 'callable' is visible outside */ 3 | static buf [100]; 4 | static length; 5 | static void fillup(void); 6 | 7 | int 8 | callable() { 9 | if (length == 0) { 10 | fillup(); 11 | } 12 | return(buf[length--]); 13 | } 14 | 15 | static void 16 | fillup(void) { 17 | while (length <100) { 18 | buf[length++] = 0; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /example/example9-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | main(){ 6 | size_t distance; 7 | struct x{ 8 | int a, b, c; 9 | }s_tr; 10 | 11 | distance = offsetof(struct x, c); 12 | printf("Offset of x.c is %lu bytes\n", 13 | (unsigned long)distance); 14 | 15 | exit(EXIT_SUCCESS); 16 | } 17 | -------------------------------------------------------------------------------- /example/example6-13.c: -------------------------------------------------------------------------------- 1 | struct { 2 | /* field 4 bits wide */ 3 | unsigned field1 :4; 4 | /* 5 | * unnamed 3 bit field 6 | * unnamed fields allow for padding 7 | */ 8 | unsigned :3; 9 | /* 10 | * one-bit field 11 | * can only be 0 or -1 in two's complement! 12 | */ 13 | signed field2 :1; 14 | /* align next field on a storage unit */ 15 | unsigned :0; 16 | unsigned field3 :6; 17 | } full_of_fields; 18 | -------------------------------------------------------------------------------- /example/example2-9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int x,y; 6 | x = 0; y = ~0; 7 | 8 | while (x != y) { 9 | printf("%x & %x = %x\n", x, 0xff, x&0xff); 10 | printf("%x | %x = %x\n", x, 0x10f, x|0x10f); 11 | printf("%x ^ %x = %x\n", x, 0xf00f, x^0xf00f); 12 | printf("%x >> 2 = %x\n", x, x >> 2); 13 | printf("%x << 2 = %x\n", x, x << 2); 14 | x = (x << 1) | 1; 15 | } 16 | exit(EXIT_SUCCESS); 17 | } 18 | -------------------------------------------------------------------------------- /example/example5-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | int x, *p; 5 | 6 | p = &x; /* initialise pointer */ 7 | *p = 0; /* set x to zero */ 8 | printf("x is %d\n", x); 9 | printf("*p is %d\n", *p); 10 | 11 | *p += 1; /* increment what p points to */ 12 | printf("x is %d\n", x); 13 | 14 | (*p)++; /* increment what p points to */ 15 | printf("x is %d\n", x); 16 | 17 | exit(EXIT_SUCCESS); 18 | } 19 | -------------------------------------------------------------------------------- /example/example6-4.c: -------------------------------------------------------------------------------- 1 | struct x; /* incomplete type */ 2 | 3 | /* valid uses of the tag */ 4 | struct x *p, func(void); 5 | 6 | void f1(void) { 7 | struct x{int i;}; /* redeclaration! */ 8 | } 9 | 10 | /* full declaration now */ 11 | struct x { 12 | float f; 13 | } s_x; 14 | 15 | void f2(void) { 16 | /* valid statements */ 17 | p = &s_x; 18 | *p = func(); 19 | s_x = func(); 20 | } 21 | 22 | struct x 23 | func(void) { 24 | struct x tmp; 25 | tmp.f = 0; 26 | return (tmp); 27 | } 28 | -------------------------------------------------------------------------------- /example/example2-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int this_char, comma_count, stop_count; 6 | 7 | comma_count = stop_count = 0; 8 | this_char = getchar(); 9 | while(this_char != EOF) { 10 | if (this_char == '.') 11 | stop_count = stop_count+1; 12 | if (this_char == ',') 13 | comma_count = comma_count+1; 14 | this_char = getchar(); 15 | } 16 | printf("%d commas, %d stops\n", 17 | comma_count, stop_count); 18 | exit(EXIT_SUCCESS); 19 | } 20 | -------------------------------------------------------------------------------- /example/example2-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define BOILING 212 /* degrees Fahrenheit */ 5 | 6 | main() { 7 | float f_var; double d_var; long double l_d_var; 8 | int i; 9 | 10 | i = 0; 11 | printf("Fahrenheit to Centigrade\n"); 12 | while(i <= BOILING){ 13 | l_d_var = 5*(i-32); 14 | l_d_var = l_d_var/9; 15 | d_var = l_d_var; 16 | f_var = l_d_var; 17 | printf("%d %f %f %lf\n", 18 | i, f_var, d_var, l_d_var); 19 | i = i+1; 20 | } 21 | exit(EXIT_SUCCESS); 22 | } 23 | -------------------------------------------------------------------------------- /example/example3-10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i, j; 6 | 7 | /* comma used - this loop has two counters */ 8 | for(i=0, j=0; i <= 10; i++, j = i*i){ 9 | printf("i %d j %d\n", i, j); 10 | } 11 | 12 | /* 13 | * In this futile example, all but the last 14 | * constant value is discarded. 15 | * Note use of parentheses to force a comma 16 | * expression in a function call. 17 | */ 18 | printf("Overall: %d\n", ("abc", 1.2e6, 4*3+2)); 19 | exit(EXIT_SUCCESS); 20 | } 21 | -------------------------------------------------------------------------------- /example/example5-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | void 4 | date(int *, int *); /* declare the function */ 5 | 6 | main() { 7 | int month, day; 8 | date(&day, &month); 9 | printf("day is %d, month is %d\n", day, month); 10 | exit(EXIT_SUCCESS); 11 | } 12 | 13 | void 14 | date(int *day_p, int *month_p) { 15 | int day_ret, month_ret; 16 | /* 17 | * At this point, calculate the day and month 18 | * values in day_ret and month_ret respectively. 19 | */ 20 | *day_p = day_ret; 21 | *month_p = month_ret; 22 | } 23 | -------------------------------------------------------------------------------- /example/example4-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | void pmax(int first, int second); /*declaration*/ 6 | int i,j; 7 | for (i = -10; i <= 10; i++) { 8 | for (j = -10; j <= 10; j++) { 9 | pmax(i,j); 10 | } 11 | } 12 | exit(EXIT_SUCCESS); 13 | } 14 | 15 | void 16 | pmax(int a1, int a2) { /*definition*/ 17 | int biggest = (a1 > a2) ? a1: a2; 18 | printf("largest of %d and %d is %d\n", 19 | a1, a2, biggest); 20 | } 21 | -------------------------------------------------------------------------------- /example/example6-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct list_ele { 5 | int data; 6 | struct list_ele *pointer; 7 | } ar[3]; 8 | 9 | main() { 10 | struct list_ele *lp; 11 | 12 | ar[0].data = 5; 13 | ar[0].pointer = &ar[1]; 14 | ar[1].data = 99; 15 | ar[1].pointer = &ar[2]; 16 | ar[2].data = -7; 17 | ar[2].pointer = 0; /* mark end of list */ 18 | 19 | /* follow pointers */ 20 | lp = ar; 21 | while(lp) { 22 | printf("contents %d\n", lp->data); 23 | lp = lp->pointer; 24 | } 25 | exit(EXIT_SUCCESS); 26 | } 27 | -------------------------------------------------------------------------------- /example/example4-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | main() { 4 | void pmax(); /* declaration */ 5 | int i,j; 6 | for (i = -10; i <= 10; i++) { 7 | for (j = -10; j <= 10; j++) { 8 | pmax(i,j); 9 | } 10 | } 11 | exit(EXIT_SUCCESS); 12 | } 13 | /* 14 | * Function pmax. 15 | * Returns: void 16 | * Prints larger of its two arguments. 17 | */ 18 | void 19 | pmax(int a1, int a2) { /* definition */ 20 | int biggest = (a1 > a2) ? a1 : a2; 21 | printf("larger of %d and %d is %d\n", 22 | a1, a2, biggest); 23 | } 24 | -------------------------------------------------------------------------------- /example/example8-1.c: -------------------------------------------------------------------------------- 1 | \#include 2 | #include 3 | 4 | void func(register int arg1, double arg2); 5 | 6 | main() { 7 | func(5, 2); 8 | exit(EXIT_SUCCESS); 9 | } 10 | 11 | /* 12 | * Function illustrating that formal parameters 13 | * may be declared to have register storage class. 14 | */ 15 | void func(register int arg1, double arg2) { 16 | 17 | /* 18 | * Illustrative only - nobody would do this 19 | * in this context. 20 | * Cannot take address of arg1, even if you want to 21 | */ 22 | double *fp = &arg2; 23 | 24 | while (arg1) { 25 | printf("res = %f\n", arg1 * (*fp)); 26 | arg1--; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /example/example6-14.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NMONTHS 12 5 | 6 | int month = 0; 7 | 8 | short month_days[] = 9 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 10 | 11 | char *mnames[] = { 12 | "January", "February", 13 | "March", "April", 14 | "May", "June", 15 | "July", "August", 16 | "September", "October", 17 | "November", "December" 18 | }; 19 | 20 | main() { 21 | int day_count = month; 22 | 23 | for (day_count = month; day_count < NMONTHS; 24 | day_count++) { 25 | printf("%d days in %s\n", 26 | month_days[day_count], 27 | mnames[day_count]); 28 | } 29 | exit(EXIT_SUCCESS); 30 | } 31 | -------------------------------------------------------------------------------- /example/example1-2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Dumb program that generates prime numbers. 3 | */ 4 | #include 5 | #include 6 | 7 | main() { 8 | int this_number, divisor, not_prime; 9 | this_number = 3; 10 | 11 | while(this_number < 10000 ){ 12 | divisor = this_number / 2; 13 | not_prime = 0; 14 | while(divisor > 1) { 15 | if(this_number % divisor == 0){ 16 | not_prime = 1; 17 | divisor = 0; 18 | } 19 | else 20 | divisor = divisor-1; 21 | } 22 | 23 | if(not_prime == 0) 24 | printf("%d is a prime number\n", this_number); 25 | this_number = this_number + 1; 26 | } 27 | exit(EXIT_SUCCESS); 28 | } 29 | -------------------------------------------------------------------------------- /example/example5-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define LINELNG 100 /* max. length of input line */ 6 | 7 | main() { 8 | char in_line[LINELNG]; 9 | char *cp; 10 | int c; 11 | 12 | cp = in_line; 13 | while ((c = getc(stdin)) != EOF) { 14 | if (cp == &in_line[LINELNG-1] || c == '\n'){ 15 | /* Insert end-of-line marker */ 16 | *cp = 0; 17 | if (strcmp(in_line, "stop") == 0 ) 18 | exit(EXIT_SUCCESS); 19 | else 20 | printf("line was %d characters long\n", 21 | (int)(cp-in_line)); 22 | cp = in_line; 23 | } 24 | else 25 | *cp++ = c; 26 | } 27 | exit(EXIT_SUCCESS); 28 | } 29 | -------------------------------------------------------------------------------- /example/example1-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * Tell the compiler that we intend to use a function called show_message. 6 | * It has no arguments and returns no value This is the "declaration". 7 | */ 8 | void show_message(void); 9 | 10 | /* 11 | * Another function, but this includes the body of 12 | * the function. This is a "definition". 13 | */ 14 | main() { 15 | int count; 16 | count = 0; 17 | while(count < 10){ 18 | show_message(); 19 | count = count + 1; 20 | } 21 | exit(0); 22 | } 23 | 24 | /* 25 | * The body of the simple function. This is now a "definition". 26 | */ 27 | void show_message(void) { 28 | printf("hello\n"); 29 | } 30 | -------------------------------------------------------------------------------- /example/example4-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define DELTA 0.0001 4 | main() { 5 | double sq_root(double); /* prototype */ 6 | int i; 7 | 8 | for (i = 1; i < 100; i++) { 9 | printf("root of %d is %f\n", i, sq_root(i)); 10 | } 11 | exit(EXIT_SUCCESS); 12 | } 13 | 14 | double 15 | sq_root(double x) { /* definition */ 16 | double curr_appx, last_appx, diff; 17 | 18 | last_appx = x; 19 | diff = DELTA+1; 20 | 21 | while (diff > DELTA ) { 22 | curr_appx = 0.5*(last_appx 23 | + x/last_appx); 24 | diff = curr_appx - last_appx; 25 | if (diff < 0) 26 | diff = -diff; 27 | last_appx = curr_appx; 28 | } 29 | return(curr_appx); 30 | } 31 | -------------------------------------------------------------------------------- /example/example9-6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int maxof(int, ...) ; 6 | void f(void); 7 | 8 | main() { 9 | f(); 10 | exit(EXIT_SUCCESS); 11 | } 12 | 13 | int maxof(int n_args, ...) { 14 | register int i; 15 | int max, a; 16 | va_list ap; 17 | 18 | va_start(ap, n_args); 19 | max = va_arg(ap, int); 20 | for(i = 2; i <= n_args; i++) { 21 | if((a = va_arg(ap, int)) > max) 22 | max = a; 23 | } 24 | 25 | va_end(ap); 26 | return max; 27 | } 28 | 29 | void f(void) { 30 | int i = 5; 31 | int j[256]; 32 | j[42] = 24; 33 | printf("%d\n",maxof(3, i, j[42], 0)); 34 | } 35 | -------------------------------------------------------------------------------- /example/example2-8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* 5 | * Illustrates casts. 6 | * For each of the numbers between 2 and 20, 7 | * print the percentage difference between it and the one before. 8 | */ 9 | main() { 10 | int curr_val; 11 | float temp, pcnt_diff; 12 | 13 | curr_val = 2; 14 | while (curr_val <= 20 ){ 15 | /* 16 | * % difference is 1/(curr_val)*100 17 | */ 18 | temp = curr_val; 19 | pcnt_diff = 100/temp; 20 | printf("Percent difference at %d is %f\n", 21 | curr_val, pcnt_diff); 22 | /* 23 | * Or, using a cast: 24 | */ 25 | pcnt_diff = 100/(float)curr_val; 26 | printf("Percent difference at %d is %f\n", 27 | curr_val, pcnt_diff); 28 | curr_val = curr_val + 1; 29 | } 30 | exit(EXIT_SUCCESS); 31 | } 32 | -------------------------------------------------------------------------------- /example/example8-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | main() { 5 | int i; 6 | const int ci = 123; 7 | 8 | /* declare a pointer to a const.. */ 9 | const int *cpi; 10 | 11 | /* ordinary pointer to a non-const */ 12 | int *ncpi; 13 | 14 | cpi = &ci; 15 | ncpi = &i; 16 | 17 | printf("ci has value %i at address %p, cpi has value %i " 18 | "and points at address %p.\n", ci, &ci, *cpi, cpi); 19 | 20 | /* this needs a cast 21 | * because it is usually a big mistake, 22 | * see what it permits below. 23 | */ 24 | ncpi = (int *)cpi; 25 | 26 | /*now to get undefined behaviour... 27 | * modify a const through a pointer 28 | */ 29 | *ncpi = 42; 30 | 31 | printf("ci has value %i at address %p, cpi has value %i " 32 | "and points at address %p.\n", ci, &ci, *cpi, cpi); 33 | 34 | exit(EXIT_SUCCESS); 35 | } 36 | -------------------------------------------------------------------------------- /example/example9-3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void func(void); 6 | jmp_buf place; 7 | 8 | main(){ 9 | int retval; 10 | 11 | /* 12 | * First call returns 0, 13 | * a later longjmp will return non-zero. 14 | */ 15 | if(setjmp(place) != 0){ 16 | printf("Returned using longjmp\n"); 17 | exit(EXIT_SUCCESS); 18 | } 19 | 20 | /* 21 | * This call will never return - it 22 | * 'jumps' back above. 23 | */ 24 | func(); 25 | printf("What! func returned!\n"); 26 | } 27 | 28 | void 29 | func(void){ 30 | /* 31 | * Return to main. 32 | * Looks like a second return from setjmp, 33 | * returning 4! 34 | */ 35 | longjmp(place, 4); 36 | printf("What! longjmp returned!\n"); 37 | } -------------------------------------------------------------------------------- /example/example9-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | FILE *temp_file; 7 | void leave(int sig); 8 | 9 | main() { 10 | (void) signal(SIGINT,leave); 11 | temp_file = fopen("tmp","w"); 12 | for(;;) { 13 | /* 14 | * Do things.... 15 | */ 16 | printf("Ready...\n"); 17 | (void)getchar(); 18 | } 19 | /* can't get here ... */ 20 | exit(EXIT_SUCCESS); 21 | } 22 | 23 | /* 24 | * on receipt of SIGINT, close tmp file 25 | * but beware - calling library functions from a 26 | * signal handler is not guaranteed to work in all 27 | * implementations..... 28 | * this is not a strictly conforming program 29 | */ 30 | 31 | void 32 | leave(int sig) { 33 | fprintf(temp_file,"\nInterrupted..\n"); 34 | fclose(temp_file); 35 | exit(sig); 36 | } -------------------------------------------------------------------------------- /example/example9-7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct xx{ 5 | int xx_int; 6 | float xx_float; 7 | }ar[20]; 8 | 9 | main(){ 10 | 11 | FILE *fp = fopen("testfile", "w"); 12 | 13 | if(fwrite((const void *)ar, 14 | sizeof(ar[0]), 5, fp) != 5){ 15 | 16 | fprintf(stderr,"Error writing\n"); 17 | exit(EXIT_FAILURE); 18 | } 19 | 20 | rewind(fp); 21 | 22 | if(fread((void *)&ar[10], 23 | sizeof(ar[0]), 5, fp) != 5){ 24 | 25 | if(ferror(fp)){ 26 | fprintf(stderr,"Error reading\n"); 27 | exit(EXIT_FAILURE); 28 | } 29 | if(feof(fp)){ 30 | fprintf(stderr,"End of File\n"); 31 | exit(EXIT_FAILURE); 32 | } 33 | } 34 | exit(EXIT_SUCCESS); 35 | } -------------------------------------------------------------------------------- /example/example6-12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* code for types in union */ 5 | #define FLOAT_TYPE 1 6 | #define CHAR_TYPE 2 7 | #define INT_TYPE 3 8 | 9 | struct var_type { 10 | int type_in_union; 11 | union { 12 | float un_float; 13 | char un_char; 14 | int un_int; 15 | } vt_un; 16 | } var_type; 17 | 18 | void 19 | print_vt(void) { 20 | switch (var_type.type_in_union) { 21 | default: 22 | printf("Unknown type in union\n"); 23 | break; 24 | case FLOAT_TYPE: 25 | printf("%f\n", var_type.vt_un.un_float); 26 | break; 27 | case CHAR_TYPE: 28 | printf("%c\n", var_type.vt_un.un_char); 29 | break; 30 | case INT_TYPE: 31 | printf("%d\n", var_type.vt_un.un_int); 32 | break; 33 | } 34 | } 35 | 36 | main() { 37 | var_type.type_in_union = FLOAT_TYPE; 38 | var_type.vt_un.un_float = 3.5; 39 | 40 | print_vt(); 41 | 42 | var_type.type_in_union = CHAR_TYPE; 43 | var_type.vt_un.un_char = 'a'; 44 | 45 | print_vt(); 46 | exit(EXIT_SUCCESS); 47 | } 48 | -------------------------------------------------------------------------------- /example/example6-7.c: -------------------------------------------------------------------------------- 1 | struct list_ele * 2 | sortfun(struct list_ele *list) { 3 | 4 | int exchange; 5 | struct list_ele *nextp, *thisp, dummy; 6 | 7 | /* 8 | * Algorithm is this: 9 | * Repeatedly scan list. 10 | * If two list items are out of order, 11 | * link them in the other way round. 12 | * Stop if a full pass is made and no 13 | * exchanges are required. 14 | * The whole business is confused by 15 | * working one element behind the 16 | * first one of interest. 17 | * This is because of the simple mechanics of 18 | * linking and unlinking elements. 19 | */ 20 | 21 | dummy.pointer = list; 22 | do { 23 | exchange = 0; 24 | thisp = &dummy; 25 | while ((nextp = thisp->pointer) 26 | && nextp->pointer) { 27 | if (nextp->data < nextp->pointer->data) { 28 | /* exchange */ 29 | exchange = 1; 30 | thisp->pointer = nextp->pointer; 31 | nextp->pointer = 32 | thisp->pointer->pointer; 33 | thisp->pointer->pointer = nextp; 34 | } 35 | thisp = thisp->pointer; 36 | } 37 | } while(exchange); 38 | 39 | return(dummy.pointer); 40 | } 41 | -------------------------------------------------------------------------------- /fancyvrb.ins: -------------------------------------------------------------------------------- 1 | %% `fancyvrb.ins' 2 | %% 3 | %% Docstrip installation instruction file for docstyle `fancyvrb' 4 | %% 5 | %% Timothy Van Zandt (Princeton University - USA) 6 | %% June 24, 1998 7 | 8 | \def\batchfile{fancyvrb.ins} 9 | \input docstrip.tex 10 | \keepsilent 11 | \Msg{*** Generating the `fancyvrb' package ***} 12 | \askforoverwritefalse 13 | \generate{\file{fancyvrb.sty}{\from{fancyvrb.dtx}{fancyvrb}}} 14 | 15 | \ifToplevel{% 16 | \Msg{***********************************************************} 17 | \Msg{*} 18 | \Msg{* To finish the installation you have to move the file} 19 | \Msg{* fancyvrb.sty searched by TeX.} 20 | \Msg{*} 21 | \Msg{* To produce the documentation, run the file `fvrb-ex.dtx'} 22 | \Msg{* through LaTeX.} 23 | \Msg{*} 24 | \Msg{* If you require the commented code, desactivating the} 25 | \Msg{* OnlyDescription macro, you must recompile, execute:} 26 | \Msg{* `makeindex -s PATH/gind.ist fancyvrb'} 27 | \Msg{* `makeindex -s PATH/gglo.ist -o fancyvrb.gls fancyvrb.glo'} 28 | \Msg{* and recompile.} 29 | \Msg{*} 30 | \Msg{***********************************************************} 31 | } 32 | 33 | \endinput 34 | %% 35 | %% End of file `fancyvrb.ins' 36 | -------------------------------------------------------------------------------- /example/example8-5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Declare the device registers 3 | * Whether to use int or short 4 | * is implementation dependent 5 | */ 6 | struct devregs { 7 | unsigned short volatile csr; /* control & status */ 8 | unsigned short const volatile data; /* data port */ 9 | }; 10 | 11 | /* bit patterns in the csr */ 12 | #define ERROR 0x1 13 | #define READY 0x2 14 | #define RESET 0x4 15 | 16 | /* absolute address of the device */ 17 | #define DEVADDR ((struct devregs *)0xffff0004) 18 | 19 | /* number of such devices in system */ 20 | #define NDEVS 4 21 | 22 | /* 23 | * Busy-wait function to read a byte from device n. 24 | * check range of device number. 25 | * Wait until READY or ERROR 26 | * if no error, read byte, return it 27 | * otherwise reset error, return 0xffff 28 | */ 29 | unsigned int read_dev(unsigned devno) { 30 | 31 | struct devregs * const dvp = DEVADDR + devno; 32 | 33 | if (devno >= NDEVS) 34 | return(0xffff); 35 | 36 | while((dvp->csr & (READY | ERROR)) == 0) 37 | ; /* NULL - wait till done */ 38 | 39 | if(dvp->csr & ERROR){ 40 | dvp->csr = RESET; 41 | return(0xffff); 42 | } 43 | 44 | return((dvp->data) & 0xff); 45 | } 46 | -------------------------------------------------------------------------------- /example/example8-4.c: -------------------------------------------------------------------------------- 1 | /* Standard C example but without const or volatile */ 2 | /* 3 | * Declare the device registers 4 | * Whether to use int or short 5 | * is implementation dependent 6 | */ 7 | struct devregs { 8 | unsigned short csr; /* control & status */ 9 | unsigned short data; /* data port */ 10 | }; 11 | 12 | /* bit patterns in the csr */ 13 | #define ERROR 0x1 14 | #define READY 0x2 15 | #define RESET 0x4 16 | 17 | /* absolute address of the device */ 18 | #define DEVADDR ((struct devregs *)0xffff0004) 19 | 20 | /* number of such devices in system */ 21 | #define NDEVS 4 22 | 23 | /* 24 | * Busy-wait function to read a byte from device n. 25 | * check range of device number. 26 | * Wait until READY or ERROR 27 | * if no error, read byte, return it 28 | * otherwise reset error, return 0xffff 29 | */ 30 | unsigned int read_dev(unsigned devno) { 31 | 32 | struct devregs *dvp = DEVADDR + devno; 33 | 34 | if (devno >= NDEVS) 35 | return(0xffff); 36 | 37 | while ((dvp->csr & (READY | ERROR)) == 0) 38 | ; /* NULL - wait till done */ 39 | 40 | if (dvp->csr & ERROR) { 41 | dvp->csr = RESET; 42 | return(0xffff); 43 | } 44 | 45 | return((dvp->data) & 0xff); 46 | } 47 | -------------------------------------------------------------------------------- /example/example1-4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #define ARSIZE 10 4 | main() { 5 | int ch_arr[ARSIZE],count1; 6 | int count2, stop, lastchar; 7 | 8 | lastchar = 0; 9 | stop = 0; 10 | /* 11 | * Read characters into array. 12 | * Stop if end of line, or array full. 13 | */ 14 | while (stop != 1) { 15 | ch_arr[lastchar] = getchar(); 16 | if(ch_arr[lastchar] == '\n') 17 | stop = 1; 18 | else 19 | lastchar = lastchar + 1; 20 | if(lastchar == ARSIZE) 21 | stop = 1; 22 | } 23 | lastchar = lastchar-1; 24 | 25 | /* 26 | * Now the traditional bubble sort. 27 | */ 28 | count1 = 0; 29 | while (count1 < lastchar ) { 30 | count2 = count1 + 1; 31 | while (count2 <= lastchar) { 32 | if (ch_arr[count1] > ch_arr[count2]) { 33 | /* swap */ 34 | int temp; 35 | temp = ch_arr[count1]; 36 | ch_arr[count1] = ch_arr[count2]; 37 | ch_arr[count2] = temp; 38 | } 39 | count2 = count2 + 1; 40 | } 41 | count1 = count1 + 1; 42 | } 43 | 44 | count1 = 0; 45 | while (count1 <= lastchar) { 46 | printf("%c\n", ch_arr[count1]); 47 | count1 = count1 + 1; 48 | } 49 | exit(EXIT_SUCCESS); 50 | } 51 | -------------------------------------------------------------------------------- /example/example6-8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | struct tree_node { 4 | int data; 5 | struct tree_node *left_p, *right_p; 6 | } tree[7]; 7 | /* 8 | * Tree search algorithm. 9 | * Searches for value 'v' in tree, 10 | * returns pointer to first node found containing 11 | * the value otherwise 0. 12 | */ 13 | struct tree_node * 14 | t_search(struct tree_node *root, int v) { 15 | while (root) { 16 | if (root->data == v) 17 | return(root); 18 | if (root->data > v) 19 | root = root->left_p; 20 | else 21 | root = root->right_p; 22 | } 23 | /* value not found, no tree left */ 24 | return(0); 25 | } 26 | 27 | main() { 28 | /* construct tree by hand */ 29 | struct tree_node *tp, *root_p; 30 | int i; 31 | for (i = 0; i < 7; i++) { 32 | int j; 33 | j = i+1; 34 | 35 | tree[i].data = j; 36 | if (j == 2 || j == 6) { 37 | tree[i].left_p = &tree[i-1]; 38 | tree[i].right_p = &tree[i+1]; 39 | } 40 | } 41 | /* root */ 42 | root_p = &tree[3]; 43 | root_p->left_p = &tree[1]; 44 | root_p->right_p = &tree[5]; 45 | 46 | /* try the search */ 47 | tp = t_search(root_p, 9); 48 | if (tp) 49 | printf("found at position %d\n", tp-tree); 50 | else 51 | printf("value not found\n"); 52 | exit(EXIT_SUCCESS); 53 | } 54 | -------------------------------------------------------------------------------- /example/example6-2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ARSIZE 10 5 | 6 | struct wp_char { 7 | char wp_cval; 8 | short wp_font; 9 | short wp_psize; 10 | } ar[ARSIZE]; 11 | 12 | void infun(struct wp_char *); 13 | 14 | main() { 15 | struct wp_char wp_tmp, *lo_indx, *hi_indx, *in_p; 16 | 17 | for (in_p = ar; in_p < &ar[ARSIZE]; in_p++) { 18 | infun(in_p); 19 | if (in_p->wp_cval == '\n') { 20 | /* Leave the loop. 21 | * not incrementing in_p means that the 22 | * '\n' is ignored in the sort */ 23 | break; 24 | } 25 | } 26 | 27 | /* Now a simple exchange sort. 28 | * We must be careful to avoid the danger of pointer underflow, 29 | * so check that there are at least two entries to sort. */ 30 | if (in_p-ar > 1) for (lo_indx = ar; lo_indx <= in_p-2; lo_indx++) { 31 | for (hi_indx = lo_indx+1; hi_indx <= in_p-1; hi_indx++) { 32 | if (lo_indx->wp_cval > hi_indx->wp_cval) { 33 | /* Swap the structures. */ 34 | struct wp_char wp_tmp = *lo_indx; 35 | *lo_indx = *hi_indx; 36 | *hi_indx = wp_tmp; 37 | } 38 | } 39 | } 40 | 41 | /* now print */ 42 | for (lo_indx = ar; lo_indx < in_p; lo_indx++) { 43 | printf("%c %d %d\n", lo_indx->wp_cval, 44 | lo_indx->wp_font, 45 | lo_indx->wp_psize); 46 | } 47 | exit(EXIT_SUCCESS); 48 | } 49 | 50 | void 51 | infun(struct wp_char *inp) { 52 | inp->wp_cval = getchar(); 53 | inp->wp_font = 2; 54 | inp->wp_psize = 10; 55 | } 56 | -------------------------------------------------------------------------------- /example/example6-1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define ARSIZE 10 5 | 6 | struct wp_char { 7 | char wp_cval; 8 | short wp_font; 9 | short wp_psize; 10 | } ar[ARSIZE]; 11 | 12 | /* type of the input function - 13 | * could equally have been declared above; 14 | * it returns a structure and takes no arguments. */ 15 | struct wp_char infun(void); 16 | 17 | main() { 18 | int icount, lo_indx, hi_indx; 19 | 20 | for (icount = 0; icount < ARSIZE; icount++){ 21 | ar[icount] = infun(); 22 | if (ar[icount].wp_cval == '\n') { 23 | /* Leave the loop. 24 | * not incrementing icount means that the 25 | * '\n' is ignored in the sort */ 26 | break; 27 | } 28 | } 29 | 30 | /* now a simple exchange sort */ 31 | 32 | for (lo_indx = 0; lo_indx <= icount-2; lo_indx++) 33 | for (hi_indx = lo_indx+1; hi_indx <= icount-1; hi_indx++) { 34 | if (ar[lo_indx].wp_cval > ar[hi_indx].wp_cval) { 35 | /* Swap the two structures. */ 36 | struct wp_char wp_tmp = ar[lo_indx]; 37 | ar[lo_indx] = ar[hi_indx]; 38 | ar[hi_indx] = wp_tmp; 39 | } 40 | } 41 | 42 | /* now print */ 43 | for (lo_indx = 0; lo_indx < icount; lo_indx++) { 44 | printf("%c %d %d\n", ar[lo_indx].wp_cval, 45 | ar[lo_indx].wp_font, 46 | ar[lo_indx].wp_psize); 47 | } 48 | exit(EXIT_SUCCESS); 49 | } 50 | 51 | struct wp_char 52 | infun(void) { 53 | struct wp_char wp_char; 54 | 55 | wp_char.wp_cval = getchar(); 56 | wp_char.wp_font = 2; 57 | wp_char.wp_psize = 10; 58 | 59 | return(wp_char); 60 | } 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The C Book 2 | 3 | ## Overview 4 | This is the TeX/PDF version of The C Book by Mike Banahan, Declan Brady and Mark Doran. This version is based on the second edition and contains minor edits and corrections of the past 10 years. These edits mainly pertain to formatting and fixing small errors. The PDF can be freely redistributed. 5 | 6 | ## PDF download 7 | The latest version of the PDF of The C Book can be downloaded at [https://github.com/wardvanwanrooij/thecbook/releases/latest](https://github.com/wardvanwanrooij/thecbook/releases/latest). 8 | 9 | ## History 10 | The second edition was made printed in 1991 by Addison Wesley. The original nroff sources were converted to HTML and made available in 2003 by [Mike Banahan](https://publications.gbdirect.co.uk/c_book/copyright.html). In 2010 these HTML files were converted by a purpose-built Perl script to TeX/PdF by [Ward van Wanrooij](https://github.com/wardvanwanrooij). The TeX sources have been put on Github and since then have also incorporated changes by [Andrea D'Amore](https://github.com/anddam) and [Ernst Reissner](https://github.com/Reissner) and others. 11 | 12 | ## Comments 13 | If you spot any errors, please open an issue or send a pull request. 14 | 15 | ## License 16 | Permission is hereby granted for anyone to do anything that they want with this material—you may freely reprint it, redistribute it, amend it or do whatever you like with it provided that you include an acknowledgement of the original authorship and copyright in the form of a link to https://publications.gbdirect.co.uk/c_book/copyright.html. 17 | For more information please review the [original license](./LICENSE). 18 | 19 | -------------------------------------------------------------------------------- /example/example10-4.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * Declarations and definitions for functions which manipulate player 4 | * records which form the basis of the ladder 5 | * 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define NAMELEN 12 /* max. for player name length */ 14 | 15 | #define LENBUF 256 /* max. for input buffer length */ 16 | 17 | #define CHALLENGE_RANGE 3 /* number of higher ranked players who may 18 | * be challenged to move up in rank 19 | */ 20 | 21 | extern char *OptArg; 22 | 23 | typedef struct { 24 | char name[NAMELEN+1]; 25 | int rank; 26 | int wins; 27 | int losses; 28 | time_t last_game; 29 | } player; 30 | 31 | #define NULLPLAYER (player *)0 32 | 33 | extern const char *LadderFile; 34 | 35 | extern const char *WrFmt; /* used when writing records */ 36 | extern const char *RdFmt; /* used when reading records */ 37 | 38 | /* 39 | * Declarations for routines used to manipulate the player records 40 | * and the ladder file which are defined in player.c 41 | * 42 | */ 43 | 44 | int valid_records(FILE *); 45 | int read_records(FILE *, int, player *); 46 | int write_records(FILE *, player *, int); 47 | player *find_by_name(char *, player *, int); 48 | player *find_by_rank(int, player *, int); 49 | void push_down(player *, int, int, int); 50 | int print_records(player *, int); 51 | void copy_player(player *, player *); 52 | int compare_name(player *, player *); 53 | int compare_rank(player *, player *); 54 | void sort_players(player *, int); -------------------------------------------------------------------------------- /example/example5-12.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXSTRING 50 /* max no. of strings */ 6 | #define MAXLEN 80 /* max length. of strings */ 7 | 8 | void print_arr(const char **p_array); 9 | void sort_arr(const char **p_array); 10 | char *next_string(void); 11 | 12 | main() { 13 | const char **p_array; 14 | int nstrings; /* count of strings read */ 15 | 16 | p_array = (const char **)malloc(sizeof(char *[MAXSTRING+1])); 17 | if (p_array == 0) { 18 | printf("No memory\n"); 19 | exit(EXIT_FAILURE); 20 | } 21 | 22 | nstrings = 0; 23 | while (nstrings < MAXSTRING && 24 | (p_array[nstrings] = next_string()) != 0 ){ 25 | 26 | nstrings++; 27 | } 28 | /* terminate p_array */ 29 | p_array[nstrings] = 0; 30 | 31 | sort_arr(p_array); 32 | print_arr(p_array); 33 | exit(EXIT_SUCCESS); 34 | } 35 | 36 | void print_arr(const char **p_array) { 37 | while (*p_array) 38 | printf("%s\n", *p_array++); 39 | } 40 | 41 | 42 | void sort_arr(const char **p_array) { 43 | const char **lo_p, **hi_p, *tmp; 44 | 45 | for (lo_p = p_array; 46 | *lo_p != 0 && *(lo_p+1) != 0; 47 | lo_p++) { 48 | for (hi_p = lo_p+1; *hi_p != 0; hi_p++) { 49 | 50 | if(strcmp(*hi_p, *lo_p) >= 0) 51 | continue; 52 | /* swap strings */ 53 | tmp = *hi_p; 54 | *hi_p = *lo_p; 55 | *lo_p = tmp; 56 | } 57 | } 58 | } 59 | 60 | 61 | 62 | char *next_string(void) { 63 | char *cp, *destination; 64 | int c; 65 | 66 | destination = (char *)malloc(MAXLEN); 67 | if (destination != 0) { 68 | cp = destination; 69 | while ((c = getchar()) != '\n' && c != EOF) { 70 | if(cp-destination < MAXLEN-1) 71 | *cp++ = c; 72 | } 73 | *cp = 0; 74 | if (c == EOF && cp == destination) 75 | return(0); 76 | } 77 | return(destination); 78 | } 79 | -------------------------------------------------------------------------------- /example/example5-11.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXSTRING 50 /* max no. of strings */ 6 | #define MAXLEN 80 /* max length. of strings */ 7 | 8 | void print_arr(const char *p_array[]); 9 | void sort_arr(const char *p_array[]); 10 | char *next_string(void); 11 | 12 | main() { 13 | const char *p_array[MAXSTRING+1]; 14 | int nstrings; 15 | 16 | nstrings = 0; 17 | while (nstrings < MAXSTRING && 18 | (p_array[nstrings] = next_string()) != 0) { 19 | 20 | nstrings++; 21 | } 22 | /* terminate p_array */ 23 | p_array[nstrings] = 0; 24 | 25 | sort_arr(p_array); 26 | print_arr(p_array); 27 | exit(EXIT_SUCCESS); 28 | } 29 | 30 | void print_arr(const char *p_array[]) { 31 | int index; 32 | for (index = 0; p_array[index] != 0; index++) 33 | printf("%s\n", p_array[index]); 34 | } 35 | 36 | 37 | void sort_arr(const char *p_array[]) { 38 | int comp_val, low_index, hi_index; 39 | const char *tmp; 40 | 41 | for (low_index = 0; 42 | p_array[low_index] != 0 && 43 | p_array[low_index+1] != 0; 44 | low_index++) { 45 | 46 | for (hi_index = low_index+1; 47 | p_array[hi_index] != 0; 48 | hi_index++) { 49 | 50 | comp_val=strcmp(p_array[hi_index], 51 | p_array[low_index]); 52 | if(comp_val >= 0) 53 | continue; 54 | /* swap strings */ 55 | tmp = p_array[hi_index]; 56 | p_array[hi_index] = p_array[low_index]; 57 | p_array[low_index] = tmp; 58 | } 59 | } 60 | } 61 | 62 | char *next_string(void) { 63 | char *cp, *destination; 64 | int c; 65 | 66 | destination = (char *)malloc(MAXLEN); 67 | if (destination != 0) { 68 | cp = destination; 69 | while ((c = getchar()) != '\n' && c != EOF) { 70 | if(cp-destination < MAXLEN-1) 71 | *cp++ = c; 72 | } 73 | *cp = 0; 74 | if (c == EOF && cp == destination) 75 | return(0); 76 | } 77 | return(destination); 78 | } 79 | -------------------------------------------------------------------------------- /example/example8-2.c: -------------------------------------------------------------------------------- 1 | /* example of a single source file layout */ 2 | #include 3 | 4 | /* Things with external linkage: 5 | * accessible throughout program. 6 | * These are declarations, not definitions, so 7 | * we assume their definition is somewhere else. 8 | */ 9 | 10 | extern int important_variable; 11 | extern int library_func(double, int); 12 | 13 | /* 14 | * Definitions with external linkage. 15 | */ 16 | extern int ext_int_def = 0; /* explicit definition */ 17 | int tent_ext_int_def; /* tentative definition */ 18 | 19 | /* 20 | * Things with internal linkage: 21 | * only accessible inside this file. 22 | * The use of static means that they are also 23 | * tentative definitions. 24 | */ 25 | 26 | static int less_important_variable; 27 | static struct { 28 | int member_1; 29 | int member_2; 30 | } local_struct; 31 | 32 | /* 33 | * Also with internal linkage, but not a tentative 34 | * definition because this is a function. 35 | */ 36 | static void lf(void); 37 | 38 | /* 39 | * Definition with internal linkage. 40 | */ 41 | static float int_link_f_def = 5.3; 42 | 43 | /* Finally definitions of functions within this file */ 44 | 45 | /* 46 | * This function has external linkage and can be called 47 | * from anywhere in the program. 48 | */ 49 | void f1(int a) {} 50 | 51 | /* 52 | * These two functions can only be invoked by name from 53 | * within this file. 54 | */ 55 | static int local_function(int a1, int a2) { 56 | return(a1 * a2); 57 | } 58 | 59 | static void lf(void) { 60 | /* A static variable with no linkage, 61 | * so usable only within this function. 62 | * Also a definition (because of no linkage) */ 63 | static int count; 64 | /* Automatic variable with no linkage but an initializer */ 65 | int i = 1; 66 | 67 | printf("lf called for time no %d\n", ++count); 68 | } 69 | 70 | /* Actual definitions are implicitly provided for 71 | * all remaining tentative definitions at the end of the file */ 72 | -------------------------------------------------------------------------------- /example/example6-9.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | struct tree_node { 5 | int data; 6 | struct tree_node *left_p, *right_p; 7 | }; 8 | 9 | /* 10 | * Tree search algorithm. 11 | * Searches for value 'v' in tree, 12 | * returns pointer to first node found containing 13 | * the value otherwise 0. 14 | */ 15 | struct tree_node * 16 | t_search(struct tree_node *root, int v) { 17 | while(root) { 18 | printf("looking for %d, looking at %d\n", 19 | v, root->data); 20 | if (root->data == v) 21 | return(root); 22 | if (root->data > v) 23 | root = root->left_p; 24 | else 25 | root = root->right_p; 26 | } 27 | /* value not found, no tree left */ 28 | return(0); 29 | } 30 | 31 | /* 32 | * Insert node into tree. 33 | * Return 0 for success, 34 | * 1 for value already in tree, 35 | * 2 for malloc error 36 | */ 37 | int 38 | t_insert(struct tree_node **root, int v) { 39 | while (*root) { 40 | if ((*root)->data == v) 41 | return(1); 42 | if ((*root)->data > v) 43 | root = &((*root)->left_p); 44 | else 45 | root = &((*root)->right_p); 46 | } 47 | /* value not found, no tree left */ 48 | if ((*root = (struct tree_node *) 49 | malloc(sizeof (struct tree_node))) 50 | == 0) 51 | return(2); 52 | (*root)->data = v; 53 | (*root)->left_p = 0; 54 | (*root)->right_p = 0; 55 | return(0); 56 | } 57 | 58 | main() { 59 | /* construct tree by hand */ 60 | struct tree_node *tp, *root_p = 0; 61 | int i; 62 | 63 | /* we ingore the return value of t_insert */ 64 | t_insert(&root_p, 4); 65 | t_insert(&root_p, 2); 66 | t_insert(&root_p, 6); 67 | t_insert(&root_p, 1); 68 | t_insert(&root_p, 3); 69 | t_insert(&root_p, 5); 70 | t_insert(&root_p, 7); 71 | 72 | /* try the search */ 73 | for (i = 1; i < 9; i++) { 74 | tp = t_search(root_p, i); 75 | if (tp) 76 | printf("%d found\n", i); 77 | else 78 | printf("%d not found\n", i); 79 | } 80 | exit(EXIT_SUCCESS); 81 | } 82 | -------------------------------------------------------------------------------- /example/example5-10.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAXSTRING 50 /* max no. of strings */ 6 | #define MAXLEN 80 /* max length. of strings */ 7 | 8 | void print_arr(const char *p_array[]); 9 | void sort_arr(const char *p_array[]); 10 | char *next_string(char *destination); 11 | 12 | main() { 13 | /* leave room for null at end */ 14 | const char *p_array[MAXSTRING+1]; 15 | 16 | /* storage for strings */ 17 | char strings[MAXSTRING][MAXLEN]; 18 | 19 | /* count of strings read */ 20 | int nstrings; 21 | 22 | nstrings = 0; 23 | while (nstrings < MAXSTRING && 24 | next_string(strings[nstrings]) != 0) { 25 | 26 | p_array[nstrings] = strings[nstrings]; 27 | nstrings++; 28 | } 29 | /* terminate p_array */ 30 | p_array[nstrings] = 0; 31 | 32 | sort_arr(p_array); 33 | print_arr(p_array); 34 | exit(EXIT_SUCCESS); 35 | } 36 | 37 | void print_arr(const char *p_array[]) { 38 | int index; 39 | for (index = 0; p_array[index] != 0; index++) 40 | printf("%s\n", p_array[index]); 41 | } 42 | 43 | void sort_arr(const char *p_array[]) { 44 | int comp_val, low_index, hi_index; 45 | const char *tmp; 46 | 47 | for (low_index = 0; 48 | p_array[low_index] != 0 && 49 | p_array[low_index+1] != 0; 50 | low_index++) { 51 | 52 | for (hi_index = low_index+1; 53 | p_array[hi_index] != 0; 54 | hi_index++){ 55 | 56 | comp_val=strcmp(p_array[hi_index], 57 | p_array[low_index]); 58 | if (comp_val >= 0) 59 | continue; 60 | /* swap strings */ 61 | tmp = p_array[hi_index]; 62 | p_array[hi_index] = p_array[low_index]; 63 | p_array[low_index] = tmp; 64 | } 65 | } 66 | } 67 | 68 | char *next_string(char *destination) { 69 | char *cp; 70 | int c; 71 | 72 | cp = destination; 73 | while ((c = getchar()) != '\n' && c != EOF) { 74 | if (cp-destination < MAXLEN-1) 75 | *cp++ = c; 76 | } 77 | *cp = 0; 78 | if (c == EOF && cp == destination) 79 | return(0); 80 | return(destination); 81 | } 82 | -------------------------------------------------------------------------------- /example/example4-8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Recursive descent parser for simple C expressions. 3 | * Very little error checking. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | int expr(void); 10 | int mul_exp(void); 11 | int unary_exp(void); 12 | int primary(void); 13 | 14 | main() { 15 | int val; 16 | 17 | for(;;){ 18 | printf("expression: "); 19 | val = expr(); 20 | if(getchar() != '\n') { 21 | printf("error\n"); 22 | while(getchar() != '\n') 23 | ; /* NULL */ 24 | } else { 25 | printf("result is %d\n", val); 26 | } 27 | } 28 | exit(EXIT_SUCCESS); 29 | } 30 | 31 | int 32 | expr(void) { 33 | int val, ch_in; 34 | 35 | val = mul_exp(); 36 | for(;;){ 37 | switch(ch_in = getchar()) { 38 | default: 39 | ungetc(ch_in,stdin); 40 | return(val); 41 | case '+': 42 | val = val + mul_exp(); 43 | break; 44 | case '-': 45 | val = val - mul_exp(); 46 | break; 47 | } 48 | } 49 | } 50 | 51 | int 52 | mul_exp(void) { 53 | int val, ch_in; 54 | 55 | val = unary_exp(); 56 | for(;;){ 57 | switch(ch_in = getchar()) { 58 | default: 59 | ungetc(ch_in, stdin); 60 | return(val); 61 | case '*': 62 | val = val * unary_exp(); 63 | break; 64 | case '/': 65 | val = val / unary_exp(); 66 | break; 67 | case '%': 68 | val = val % unary_exp(); 69 | break; 70 | } 71 | } 72 | } 73 | 74 | int 75 | unary_exp(void) { 76 | int val, ch_in; 77 | 78 | switch (ch_in = getchar()) { 79 | default: 80 | ungetc(ch_in, stdin); 81 | val = primary(); 82 | break; 83 | case '+': 84 | val = unary_exp(); 85 | break; 86 | case '-': 87 | val = -unary_exp(); 88 | break; 89 | } 90 | return(val); 91 | } 92 | 93 | int 94 | primary(void) { 95 | int val, ch_in; 96 | 97 | ch_in = getchar(); 98 | if (ch_in >= '0' && ch_in <= '9') { 99 | val = ch_in - '0'; 100 | goto out; 101 | } 102 | if (ch_in == '(') { 103 | val = expr(); 104 | getchar(); /* skip closing ')' */ 105 | goto out; 106 | } 107 | printf("error: primary read %d\n", ch_in); 108 | exit(EXIT_FAILURE); 109 | out: 110 | return(val); 111 | } 112 | -------------------------------------------------------------------------------- /example/example10-6.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Program to print the current ladder status. 3 | * 4 | */ 5 | 6 | #include "player.h" 7 | 8 | const char *ValidOpts = "f:"; 9 | 10 | const char *Usage = "usage: showlddr [-f ladder_file]\n"; 11 | 12 | char *OtherFile; 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | int number; 17 | char ch; 18 | player *them; 19 | const char *fname; 20 | FILE *fp; 21 | 22 | if(argc == 3){ 23 | while((ch = options(argc, argv, ValidOpts)) != -1){ 24 | switch(ch){ 25 | case 'f': 26 | OtherFile = OptArg; 27 | break; 28 | case '?': 29 | fprintf(stderr, Usage); 30 | break; 31 | } 32 | } 33 | } else if(argc > 1){ 34 | fprintf(stderr, Usage); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | fname = (OtherFile == 0)? LadderFile : OtherFile; 39 | fp = fopen(fname, "r+"); 40 | 41 | if(fp == NULL){ 42 | perror("showlddr"); 43 | exit(EXIT_FAILURE); 44 | } 45 | 46 | number = valid_records (fp); 47 | 48 | them = (player *)malloc((sizeof(player) * number)); 49 | 50 | if(them == NULL){ 51 | fprintf(stderr,"showlddr: out of memory\n"); 52 | exit(EXIT_FAILURE); 53 | } 54 | 55 | if(read_records(fp, number, them) != number){ 56 | fprintf(stderr, "showlddr: error while reading" 57 | " player records\n"); 58 | free(them); 59 | fclose(fp); 60 | exit(EXIT_FAILURE); 61 | } 62 | 63 | fclose(fp); 64 | 65 | sort_players(them, number); 66 | 67 | if(print_records(them, number) != number){ 68 | fprintf(stderr, "showlddr: error while printing" 69 | " player records\n"); 70 | free(them); 71 | exit(EXIT_FAILURE); 72 | } 73 | 74 | free(them); 75 | exit(EXIT_SUCCESS); 76 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The C Book - Disclaimer and Copyright Notice 2 | 3 | The first edition of this book was based on a late draft of the ANSI standard for C and is copyright Mike Banahan. This online version is a reproduction of the second edition based on the published ANSI standard. The second edition was published in 1991, copyright Mike Banahan, Declan Brady and Mark Doran. By agreement with Declan Brady and Mark Doran, copyright in this online version and derived works is copyright Mike Banahan, 2003. The print versions were published by Addison Wesley. 4 | 5 | This online version is derived from files in Unix nroff format discovered on a floppy disk just prior to a move of offices by GBdirect Ltd. It is believed that the files were were used by the publishers Addison Wesley in the preparation of the second print edition and that some amendments or corrections may have been made in the print version that are not reflected in this online version. The online version was prepared with the assistance of some Perl scripts written by Mike Banahan, by Steve King, who cleaned up the output of the Perl scripts and also by sterling work by Geoff Richards and Aaron Crane who performed magic with XSLT to produce the HTML documents. 6 | 7 | The publication of the online version is for historical interest and readers are warned that it should be treated as an historical document. There is now a later standard for the C programming language and this publication cannot be considered current: whilst for the most part the current and the first standard are very close, some substantive changes and extensions have occurred since 1991. NO WARRANTY IS OFFERED AS TO THE COMPLETENESS OR ACCURACY OF THE MATERIAL. 8 | 9 | Permission is hereby granted for anyone to do anything that they want with this material: you may freely reprint it, redistribute it, amend it or do whatever you like with it provided that you include an acknowledgement of the original authorship and copyright in the form of a link to this page. In doing so you must accept that you do so strictly on your own liability and that you accept any consequences with no liability whatsoever remaining with the original authors. If you find the material useful and happen to encounter one of the authors, it is unlikely that they will refuse offers to buy them a drink. You may therefore like to consider this material 'drinkware'. (Offer void where prohibited by law, in which case fawning and flattery may be substituted.) 10 | -------------------------------------------------------------------------------- /example/example5-13.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define GROW_BY 10 /* string grows by 10 chars */ 6 | 7 | main() { 8 | char *str_p, *next_p, *tmp_p; 9 | int ch, need, chars_read; 10 | 11 | if (GROW_BY < 2) { 12 | fprintf(stderr, 13 | "Growth constant too small\n"); 14 | exit(EXIT_FAILURE); 15 | } 16 | 17 | str_p = (char *)malloc(GROW_BY); 18 | if (str_p == NULL) { 19 | fprintf(stderr,"No initial store\n"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | next_p = str_p; 24 | chars_read = 0; 25 | while ((ch = getchar()) != EOF) { 26 | /* 27 | * Completely restart at each new line. 28 | * There will always be room for the 29 | * terminating zero in the string, 30 | * because of the check further down, 31 | * unless GROW_BY is less than 2, 32 | * and that has already been checked. 33 | */ 34 | if (ch == '\n') { 35 | /* indicate end of line */ 36 | *next_p = 0; 37 | printf("%s\n", str_p); 38 | free(str_p); 39 | chars_read = 0; 40 | str_p = (char *)malloc(GROW_BY); 41 | if (str_p == NULL) { 42 | fprintf(stderr,"No initial store\n"); 43 | exit(EXIT_FAILURE); 44 | } 45 | next_p = str_p; 46 | continue; 47 | } 48 | /* 49 | * Have we reached the end of the current 50 | * allocation ? 51 | */ 52 | if (chars_read == GROW_BY-1) { 53 | *next_p = 0; /* mark end of string */ 54 | /* 55 | * use pointer subtraction 56 | * to find length of 57 | * current string. 58 | */ 59 | need = next_p - str_p +1; 60 | tmp_p = (char *)malloc(need+GROW_BY); 61 | if (tmp_p == NULL) { 62 | fprintf(stderr,"No more store\n"); 63 | exit(EXIT_FAILURE); 64 | } 65 | /* 66 | * Copy the string using library. 67 | */ 68 | strcpy(tmp_p, str_p); 69 | free(str_p); 70 | str_p = tmp_p; 71 | /* 72 | * and reset next_p, character count 73 | */ 74 | next_p = str_p + need-1; 75 | chars_read = 0; 76 | } 77 | /* 78 | * Put character at end of current string. 79 | */ 80 | *next_p++ = ch; 81 | chars_read++; 82 | } 83 | /* 84 | * EOF - but do unprinted characters exist? 85 | */ 86 | if (str_p - next_p) { 87 | *next_p = 0; 88 | fprintf(stderr,"Incomplete last line\n"); 89 | printf("%s\n", str_p); 90 | } 91 | exit(EXIT_SUCCESS); 92 | } 93 | -------------------------------------------------------------------------------- /example/example10-2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * options() parses option letters and option arguments from the argv list. 3 | * Succesive calls return succesive option letters which match one of 4 | * those in the legal list. Option letters may require option arguments 5 | * as indicated by a ':' following the letter in the legal list. 6 | * for example, a legal list of "ab:c" implies that a, b and c are 7 | * all valid options and that b takes an option argument. The option 8 | * argument is passed back to the calling function in the value 9 | * of the global OptArg pointer. The OptIndex gives the next string 10 | * in the argv[] array that has not already been processed by options(). 11 | * 12 | * options() returns -1 if there are no more option letters or if 13 | * double SwitchChar is found. Double SwitchChar forces options() 14 | * to finish processing options. 15 | * 16 | * options() returns '?' if an option not in the legal set is 17 | * encountered or an option needing an argument is found without an 18 | * argument following it. 19 | * 20 | */ 21 | 22 | #include 23 | #include 24 | 25 | static const char SwitchChar = '-'; 26 | static const char Unknown = '?'; 27 | 28 | int OptIndex = 1; /* first option should be argv[1] */ 29 | char *OptArg = NULL; /* global option argument pointer */ 30 | 31 | int options(int argc, char *argv[], const char *legal) 32 | { 33 | static char *posn = ""; /* position in argv[OptIndex] */ 34 | char *legal_index = NULL; 35 | int letter = 0; 36 | 37 | if(!*posn){ 38 | /* no more args, no SwitchChar or no option letter ? */ 39 | if((OptIndex >= argc) || 40 | (*(posn = argv[OptIndex]) != SwitchChar) || 41 | !*++posn) 42 | return -1; 43 | /* find double SwitchChar ? */ 44 | if(*posn == SwitchChar){ 45 | OptIndex++; 46 | return -1; 47 | } 48 | } 49 | letter = *posn++; 50 | if(!(legal_index = strchr(legal, letter))){ 51 | if(!*posn) 52 | OptIndex++; 53 | return Unknown; 54 | } 55 | if(*++legal_index != ':'){ 56 | /* no option argument */ 57 | OptArg = NULL; 58 | if(!*posn) 59 | OptIndex++; 60 | } else { 61 | if(*posn) 62 | /* no space between opt and opt arg */ 63 | OptArg = posn; 64 | else 65 | if(argc <= ++OptIndex){ 66 | posn = ""; 67 | return Unknown; 68 | } else 69 | OptArg = argv[OptIndex]; 70 | posn = ""; 71 | OptIndex++; 72 | } 73 | return letter; 74 | } -------------------------------------------------------------------------------- /thecbook.tex: -------------------------------------------------------------------------------- 1 | \documentclass[12pt,twoside,a4paper]{book} 2 | \usepackage[T1]{fontenc} 3 | \usepackage[latin1]{inputenc} 4 | \usepackage{fancyhdr} 5 | \usepackage{fancyvrb} 6 | %\usepackage[normal,footnotesize,bf]{caption3} 7 | \usepackage{caption3} 8 | \usepackage{float} 9 | \usepackage[pdftex]{graphicx} 10 | \usepackage[shortcuts]{extdash} 11 | \usepackage{geometry} 12 | \usepackage{booktabs} 13 | \usepackage{longtable} 14 | %\usepackage{pdfsync} % does not provide forward search 15 | \usepackage{srcltx} % does provide forward search 16 | \usepackage{adjustbox} 17 | \usepackage{verbatimbox} 18 | \usepackage{caption} 19 | \usepackage[numbib, numindex]{tocbibind}%[nottoc, 20 | \usepackage{longtable} 21 | \usepackage{booktabs} 22 | \usepackage[pdftex,bookmarks=true,bookmarksnumbered=true,hypertexnames=false,breaklinks=true,linkbordercolor={0 0 1}]{hyperref} 23 | \hypersetup{pdfauthor={Ward van Wanrooij}, 24 | pdftitle={The C Book}, 25 | pdfsubject={The C Book}} 26 | 27 | \pdfadjustspacing=1 28 | \raggedbottom 29 | \setcounter{secnumdepth}{3} 30 | \setcounter{tocdepth}{3} 31 | \fvset{fontsize=\footnotesize} 32 | \pagestyle{fancy} 33 | \fancyhf{} 34 | \fancyhead[EL,OR]{\bfseries\thepage} 35 | \fancyhead[LO]{\bfseries\rightmark} 36 | \fancyhead[RE]{\bfseries\leftmark} 37 | \fancypagestyle{plain}{} 38 | \setlength{\headheight}{28pt} 39 | \setlength{\parindent}{0in} 40 | 41 | 42 | \newfloat{program}{tbhp}{prg}[chapter] 43 | \floatname{program}{Program} 44 | 45 | % keywords 46 | \newcommand{\auto} {\texttt{auto}} 47 | \newcommand{\kbreak}{\texttt{break}} % command 48 | \newcommand{\case} {\texttt{case}} % command 49 | \newcommand{\kchar} {\texttt{char}} % type 50 | \newcommand{\const}{\texttt{const}} 51 | \newcommand{\continue}{\texttt{continue}} % command 52 | \newcommand{\default}{\texttt{default}} 53 | \newcommand{\kdo} {\texttt{do}} % command **** mysterious:\do does not 54 | 55 | \newcommand{\double}{\texttt{double}} % type 56 | \newcommand{\kelse}{\texttt{else}} % command 57 | \newcommand{\enum}{\texttt{enum}} % type 58 | \newcommand{\extern}{\texttt{extern}} 59 | \newcommand{\float}{\texttt{float}} % type 60 | \newcommand{\for}{\texttt{for}} % command 61 | \newcommand{\goto}{\texttt{goto}} % command 62 | \newcommand{\kif}{\texttt{if}} % command 63 | 64 | \newcommand{\kint}{\texttt{int}} % type 65 | \newcommand{\klong}{\texttt{long}} % type 66 | \newcommand{\register}{\texttt{register}} 67 | \newcommand{\return}{\texttt{return}} % command 68 | \newcommand{\short}{\texttt{short}} % type 69 | \newcommand{\signed}{\texttt{signed}} % type 70 | \newcommand{\sizeof}{\texttt{sizeof}} % function 71 | \newcommand{\static}{\texttt{static}} 72 | 73 | \newcommand{\struct}{\texttt{struct}} % type 74 | \newcommand{\switch}{\texttt{switch}} % command 75 | \newcommand{\typedef}{\texttt{typedef}} 76 | \newcommand{\union}{\texttt{union}} 77 | \newcommand{\unsigned}{\texttt{unsigned}} % type 78 | \newcommand{\void}{\texttt{void}} % type 79 | \newcommand{\volatile}{\texttt{volatile}} 80 | \newcommand{\while}{\texttt{while}} % command 81 | 82 | \newcommand{\pp}{\texttt{++}} 83 | \newcommand{\mm}{\texttt{-{}-}} 84 | 85 | 86 | 87 | 88 | 89 | \begin{document} 90 | \frontmatter 91 | \title{The C Book\thanks{Conversion to TeX and editing by Ward van Wanrooij.\newline This version contains changes up to 2023-06-22.\newline The latest version is available at https://github.com/wardvanwanrooij/thecbook}} 92 | \author{Mike Banahan \and Declan Brady \and Mark Doran} 93 | \date{January 1991} 94 | \maketitle 95 | \pdfbookmark[1]{Preamble}{prea} 96 | \newpage 97 | \pdfbookmark[1]{Contents}{toc} 98 | \setcounter{page}{1} 99 | \tableofcontents 100 | \mainmatter 101 | \include{book} 102 | 103 | 104 | \bibliographystyle{apalike} 105 | \bibliography{bib}{} 106 | \end{document} 107 | 108 | %%% Local Variables: 109 | %%% mode: latex 110 | %%% TeX-master: t 111 | %%% End: 112 | -------------------------------------------------------------------------------- /example/example10-8.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Program to record a result in the ladder 3 | * 4 | */ 5 | 6 | #include "player.h" 7 | 8 | /* Forward declarations for functions defined in this file */ 9 | 10 | char *read_name(char *, char *); 11 | void move_winner(player *, player *, player *, int); 12 | 13 | const char *ValidOpts = "f:"; 14 | 15 | const char *Usage = "usage: result [-f file]\n"; 16 | 17 | char *OtherFile; 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | player *winner, *loser, *them; 22 | int number; 23 | FILE *fp; 24 | const char *fname; 25 | char buf[LENBUF], ch; 26 | 27 | if(argc == 3){ 28 | while((ch = options(argc, argv, ValidOpts)) != -1){ 29 | switch(ch){ 30 | case 'f': 31 | OtherFile = OptArg; 32 | break; 33 | case '?': 34 | fprintf(stderr, Usage); 35 | break; 36 | } 37 | } 38 | } else if(argc > 1){ 39 | fprintf(stderr, Usage); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | fname = (OtherFile == 0)? LadderFile : OtherFile; 44 | fp = fopen(fname, "r+"); 45 | 46 | if(fp == NULL){ 47 | perror("result"); 48 | exit(EXIT_FAILURE); 49 | } 50 | 51 | number = valid_records (fp); 52 | 53 | them = (player *)malloc((sizeof(player) * number)); 54 | 55 | if(them == NULL){ 56 | fprintf(stderr,"result: out of memory\n"); 57 | exit(EXIT_FAILURE); 58 | } 59 | 60 | if(read_records(fp, number, them) != number){ 61 | fprintf(stderr, 62 | "result: error while reading player records\n"); 63 | fclose(fp); 64 | free(them); 65 | exit(EXIT_FAILURE); 66 | } 67 | 68 | fclose(fp); 69 | 70 | if((winner = find_by_name(read_name(buf, "winner"), them, number)) 71 | == NULLPLAYER){ 72 | fprintf(stderr,"result: no such player %s\n",buf); 73 | free(them); 74 | exit(EXIT_FAILURE); 75 | } 76 | 77 | if((loser = find_by_name(read_name(buf, "loser"), them, number)) 78 | == NULLPLAYER){ 79 | fprintf(stderr,"result: no such player %s\n",buf); 80 | free(them); 81 | exit(EXIT_FAILURE); 82 | } 83 | 84 | winner->wins++; 85 | loser->losses++; 86 | 87 | winner->last_game = loser->last_game = time(0); 88 | 89 | if(loser->rank < winner->rank) 90 | if((winner->rank - loser->rank) <= CHALLENGE_RANGE) 91 | move_winner(winner, loser, them, number); 92 | 93 | if((fp = freopen(fname, "w+", fp)) == NULL){ 94 | perror("result"); 95 | free(them); 96 | exit(EXIT_FAILURE); 97 | } 98 | 99 | if(write_records(fp, them, number) != number){ 100 | fprintf(stderr,"result: error while writing player records\n"); 101 | free(them); 102 | exit(EXIT_FAILURE); 103 | } 104 | fclose(fp); 105 | free(them); 106 | exit(EXIT_SUCCESS); 107 | } 108 | 109 | void move_winner(player *ww, player *ll, player *them, int number) 110 | { 111 | int loser_rank = ll->rank; 112 | 113 | if((ll->rank - ww->rank) > 3) 114 | return; 115 | 116 | push_down(them, number, ll->rank, (ww->rank - 1)); 117 | ww->rank = loser_rank; 118 | sort_players(them, number); 119 | return; 120 | } 121 | 122 | char *read_name(char *buf, char *whom) 123 | { 124 | for(;;){ 125 | char *cp; 126 | printf("Enter name of %s : ",whom); 127 | if(fgets(buf, LENBUF, stdin) == NULL) 128 | continue; 129 | /* delete newline */ 130 | cp = &buf[strlen(buf)-1]; 131 | if(*cp == '\n') 132 | *cp = 0; 133 | /* at least one char? */ 134 | if(cp != buf) 135 | return buf; 136 | } 137 | } -------------------------------------------------------------------------------- /example/example10-7.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Program to add a new player to the ladder. 3 | * You are expected to assign a realistic 4 | * ranking value to the player. 5 | * 6 | */ 7 | 8 | #include "player.h" 9 | 10 | const char *ValidOpts = "n:r:f:"; 11 | 12 | char *OtherFile; 13 | 14 | static const char *Usage = "usage: newplyr -r rank -n name [-f file]\n"; 15 | 16 | /* Forward declaration of function defined in this file */ 17 | 18 | void record(player *extra); 19 | 20 | int main(int argc, char *argv[]) 21 | { 22 | char ch; 23 | player dummy, *new = &dummy; 24 | 25 | if(argc < 5){ 26 | fprintf(stderr, Usage); 27 | exit(EXIT_FAILURE); 28 | } 29 | 30 | while((ch = options(argc, argv, ValidOpts)) != -1){ 31 | switch(ch){ 32 | case 'f': 33 | OtherFile=OptArg; 34 | break; 35 | case 'n': 36 | strncpy(new->name, OptArg, NAMELEN); 37 | new->name[NAMELEN] = 0; 38 | if(strcmp(new->name, OptArg) != 0) 39 | fprintf(stderr, 40 | "Warning: name truncated to %s\n", new->name); 41 | break; 42 | case 'r': 43 | if((new->rank = atoi(OptArg)) == 0){ 44 | fprintf(stderr, Usage); 45 | exit(EXIT_FAILURE); 46 | } 47 | break; 48 | case '?': 49 | fprintf(stderr, Usage); 50 | break; 51 | } 52 | } 53 | 54 | if((new->rank == 0)){ 55 | fprintf(stderr, "newplyr: bad value for rank\n"); 56 | exit(EXIT_FAILURE); 57 | } 58 | 59 | if(strlen(new->name) == 0){ 60 | fprintf(stderr, 61 | "newplyr: needs a valid name for new player\n"); 62 | exit(EXIT_FAILURE); 63 | } 64 | 65 | new->wins = new->losses = 0; 66 | time(& new->last_game); /* make now the time of the "last game" */ 67 | 68 | record(new); 69 | 70 | exit(EXIT_SUCCESS); 71 | } 72 | 73 | void record(player *extra) 74 | { 75 | int number, new_number, i; 76 | player *them; 77 | const char *fname =(OtherFile==0)?LadderFile:OtherFile; 78 | FILE *fp; 79 | 80 | fp = fopen(fname, "r+"); 81 | 82 | if(fp == NULL){ 83 | if((fp = fopen(fname, "w")) == NULL){ 84 | perror("newplyr"); 85 | exit(EXIT_FAILURE); 86 | } 87 | } 88 | 89 | number = valid_records (fp); 90 | new_number = number + 1; 91 | 92 | if((extra->rank <= 0) || (extra->rank > new_number)){ 93 | fprintf(stderr, 94 | "newplyr: rank must be between 1 and %d\n", 95 | new_number); 96 | exit(EXIT_FAILURE); 97 | } 98 | 99 | them = (player *)malloc((sizeof(player) * new_number)); 100 | 101 | if(them == NULL){ 102 | fprintf(stderr,"newplyr: out of memory\n"); 103 | exit(EXIT_FAILURE); 104 | } 105 | 106 | if(read_records(fp, number, them) != number){ 107 | fprintf(stderr, 108 | "newplyr: error while reading player records\n"); 109 | free(them); 110 | exit(EXIT_FAILURE); 111 | } 112 | 113 | if(find_by_name(extra->name, them, number) != NULLPLAYER){ 114 | fprintf(stderr, 115 | "newplyr: %s is already on the ladder\n", 116 | extra->name); 117 | free(them); 118 | exit(EXIT_FAILURE); 119 | } 120 | 121 | copy_player(&them[number], extra); 122 | 123 | if(extra->rank != new_number) 124 | push_down(them, number, extra->rank, number); 125 | 126 | sort_players(them, new_number); 127 | 128 | if((fp = freopen(fname, "w+", fp)) == NULL){ 129 | perror("newplyr"); 130 | free(them); 131 | exit(EXIT_FAILURE); 132 | } 133 | 134 | if(write_records(fp, them, new_number) != new_number){ 135 | fprintf(stderr, 136 | "newplyr: error while writing player records\n"); 137 | fclose(fp); 138 | free(them); 139 | exit(EXIT_FAILURE); 140 | } 141 | fclose(fp); 142 | free(them); 143 | } -------------------------------------------------------------------------------- /example/example10-5.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Generic functions to manipulate the ladder data file and 3 | * player records. 4 | * 5 | */ 6 | 7 | #include "player.h" 8 | 9 | const char *LadderFile = "ladder"; 10 | 11 | const char *WrFmt = "%s %d %d %d %ld\n"; 12 | const char *RdFmt = "%s %d %d %d %ld"; 13 | 14 | 15 | /* note use of string-joining */ 16 | const char *HeaderLine = 17 | "Player Rank Won Lost Last Game\n" 18 | "===============================================\n"; 19 | 20 | const char *PrtFmt = "%-12s%4d %4d %4d %s\n"; 21 | 22 | /* return the number of records in the data file */ 23 | 24 | int valid_records(FILE *fp) 25 | { 26 | int i = 0; 27 | long plrs = 0L; 28 | long tmp = ftell(fp); 29 | char buf[LENBUF]; 30 | 31 | fseek(fp, 0L, SEEK_SET); 32 | 33 | for(i = 0; fgets(buf, LENBUF, fp) != NULL ; i++) 34 | ; 35 | 36 | /* Restore the file pointer to original state */ 37 | 38 | fseek(fp, tmp, SEEK_SET); 39 | 40 | return i; 41 | } 42 | 43 | /* read num player records from fp into the array them */ 44 | 45 | int read_records(FILE *fp, int num, player *them) 46 | { 47 | int i = 0; 48 | long tmp = ftell(fp); 49 | 50 | if(num == 0) 51 | return 0; 52 | 53 | fseek(fp, 0L, SEEK_SET); 54 | 55 | for(i = 0 ; i < num ; i++){ 56 | if(fscanf(fp, RdFmt, (them[i]).name, 57 | &((them[i]).rank), 58 | &((them[i]).wins), 59 | &((them[i]).losses), 60 | &((them[i]).last_game)) != 5) 61 | break; /* error on fscanf! */ 62 | } 63 | 64 | fseek(fp, tmp, SEEK_SET); 65 | return i; 66 | } 67 | 68 | /* write num player records to the file fp from the array them */ 69 | 70 | int write_records(FILE *fp, player *them, int num) 71 | { 72 | int i = 0; 73 | 74 | fseek(fp, 0L, SEEK_SET); 75 | 76 | for(i = 0 ; i < num ; i++){ 77 | if(fprintf(fp, WrFmt, (them[i]).name, 78 | (them[i]).rank, 79 | (them[i]).wins, 80 | (them[i]).losses, 81 | (them[i]).last_game) < 0) 82 | break; /* error on fprintf! */ 83 | } 84 | 85 | return i; 86 | } 87 | 88 | /* 89 | * return a pointer to the player in array them 90 | * whose name matches name 91 | */ 92 | 93 | player *find_by_name(char * name, player *them, int num) 94 | { 95 | player *pp = them; 96 | int i = 0; 97 | 98 | for(i = 0; i < num; i++, pp++) 99 | if(strcmp(name, pp->name) == 0) 100 | return pp; 101 | 102 | return NULLPLAYER; 103 | } 104 | 105 | /* 106 | * return a pointer to the player in array them 107 | * whose rank matches rank 108 | */ 109 | 110 | player *find_by_rank(int rank, player *them, int num) 111 | { 112 | player *pp = them; 113 | int i = 0; 114 | 115 | for(i = 0; i < num; i++, pp++) 116 | if(rank == pp->rank) 117 | return pp; 118 | 119 | return NULLPLAYER; 120 | } 121 | 122 | /* 123 | * reduce by one the ranking of all players in array them 124 | * whose ranks are now between start and end 125 | */ 126 | 127 | void push_down(player *them, int number, int start, int end) 128 | { 129 | int i; 130 | player *pp; 131 | 132 | for(i = end; i >= start; i--){ 133 | if((pp = find_by_rank(i, them, number)) == NULLPLAYER){ 134 | fprintf(stderr, 135 | "error: could not find player ranked %d\n", i); 136 | free(them); 137 | exit(EXIT_FAILURE); 138 | } else 139 | (pp->rank)++; 140 | } 141 | } 142 | 143 | /* pretty print num player records from the array them */ 144 | 145 | int print_records(player *them, int num) 146 | { 147 | int i = 0; 148 | 149 | printf(HeaderLine); 150 | 151 | for(i = 0 ; i < num ; i++){ 152 | if(printf(PrtFmt, 153 | (them[i]).name, (them[i]).rank, 154 | (them[i]).wins, (them[i]).losses, 155 | asctime(localtime(&(them[i]).last_game))) < 0) 156 | break; /* error on printf! */ 157 | } 158 | 159 | return i; 160 | } 161 | 162 | /* copy the values from player from to player to */ 163 | 164 | void copy_player(player *to, player *from) 165 | { 166 | if((to == NULLPLAYER) || (from == NULLPLAYER)) 167 | return; 168 | 169 | *to = *from; 170 | return; 171 | } 172 | 173 | /* compare the names of player first and player second */ 174 | 175 | int compare_name(player *first, player *second) 176 | { 177 | return strcmp(first->name, second->name); 178 | } 179 | 180 | /* compare the ranks of player first and player second */ 181 | 182 | int compare_rank(player *first, player *second) 183 | { 184 | return (first->rank - second->rank); 185 | } 186 | 187 | /* sort num player records in the array them */ 188 | 189 | void sort_players(player *them, int num) 190 | { 191 | qsort(them, num, sizeof(player), compare_rank); 192 | } -------------------------------------------------------------------------------- /example/example10-3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Simple program to print lines from a text file which contain 3 | * the "word" supplied on the command line. 4 | * 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * Declarations for the pattern program 14 | * 15 | */ 16 | 17 | #define CFLAG 0x001 /* only count the number of matching lines */ 18 | #define IFLAG 0x002 /* ignore case of letters */ 19 | #define LFLAG 0x004 /* show line numbers */ 20 | #define NFLAG 0x008 /* show input file names */ 21 | #define VFLAG 0x010 /* show lines which do NOT match */ 22 | 23 | extern int OptIndex; /* current index into argv[] */ 24 | extern char *OptArg; /* global option argument pointer */ 25 | 26 | /* 27 | * Fetch command line switches from arguments to main() 28 | */ 29 | 30 | int options(int, char **, const char *); 31 | 32 | /* 33 | * Record the required options ready to control program beaviour 34 | */ 35 | 36 | unsigned set_flags(int, char **, const char *); 37 | 38 | /* 39 | * Check each line of the input file for a match 40 | */ 41 | 42 | int look_in(const char *, const char *, unsigned); 43 | 44 | /* 45 | * Print a line from the input file on the standard output 46 | * in the format specified by the command line switches 47 | */ 48 | 49 | void print_line(unsigned mask, const char *fname, 50 | int lnno, const char *text); 51 | 52 | 53 | static const char 54 | /* Legal options for pattern */ 55 | *OptString = "cilnv", 56 | /* message when options or arguments incorrect */ 57 | *errmssg = "usage: pattern [-cilnv] word [filename]\n"; 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | unsigned flags = 0; 62 | int success = 0; 63 | char *search_string; 64 | 65 | if(argc < 2){ 66 | fprintf(stderr, errmssg); 67 | exit(EXIT_FAILURE); 68 | } 69 | 70 | flags = set_flags(argc, argv, OptString); 71 | 72 | if(argv[OptIndex]) 73 | search_string = argv[OptIndex++]; 74 | else { 75 | fprintf(stderr, errmssg); 76 | exit(EXIT_FAILURE); 77 | } 78 | 79 | if(flags & IFLAG){ 80 | /* ignore case by dealing only with lowercase */ 81 | char *p; 82 | for(p = search_string ; *p ; p++) 83 | if(isupper(*p)) 84 | *p = tolower(*p); 85 | } 86 | 87 | if(argv[OptIndex] == NULL){ 88 | /* no file name given, so use stdin */ 89 | success = look_in(NULL, search_string, flags); 90 | } else while(argv[OptIndex] != NULL) 91 | success += look_in(argv[OptIndex++], 92 | search_string, flags); 93 | 94 | if(flags & CFLAG) 95 | printf("%d\n", success); 96 | 97 | exit(success ? EXIT_SUCCESS : EXIT_FAILURE); 98 | } 99 | 100 | unsigned set_flags(int argc, char **argv, const char *opts) 101 | { 102 | unsigned flags = 0; 103 | int ch = 0; 104 | 105 | while((ch = options(argc, argv, opts)) != -1){ 106 | switch(ch){ 107 | case 'c': 108 | flags |= CFLAG; 109 | break; 110 | case 'i': 111 | flags |= IFLAG; 112 | break; 113 | case 'l': 114 | flags |= LFLAG; 115 | break; 116 | case 'n': 117 | flags |= NFLAG; 118 | break; 119 | case 'v': 120 | flags |= VFLAG; 121 | break; 122 | case '?': 123 | fprintf(stderr, errmssg); 124 | exit(EXIT_FAILURE); 125 | } 126 | } 127 | return flags; 128 | } 129 | 130 | 131 | int look_in(const char *infile, const char *pat, unsigned flgs) 132 | { 133 | FILE *in; 134 | /* 135 | * line[0] stores the input line as read, 136 | * line[1] is converted to lower-case if necessary 137 | */ 138 | char line[2][BUFSIZ]; 139 | int lineno = 0; 140 | int matches = 0; 141 | 142 | if(infile){ 143 | if((in = fopen(infile, "r")) == NULL){ 144 | perror("pattern"); 145 | return 0; 146 | } 147 | } else 148 | in = stdin; 149 | 150 | while(fgets(line[0], BUFSIZ, in)){ 151 | char *line_to_use = line[0]; 152 | lineno++; 153 | if(flgs & IFLAG){ 154 | /* ignore case */ 155 | char *p; 156 | strcpy(line[1], line[0]); 157 | for(p = line[1] ; *p ; *p++) 158 | if(isupper(*p)) 159 | *p = tolower(*p); 160 | line_to_use = line[1]; 161 | } 162 | 163 | if(strstr(line_to_use, pat)){ 164 | matches++; 165 | if(!(flgs & VFLAG)) 166 | print_line(flgs, infile, lineno, line[0]); 167 | } else if(flgs & VFLAG) 168 | print_line(flgs, infile, lineno, line[0]); 169 | } 170 | fclose(in); 171 | return matches; 172 | } 173 | 174 | void print_line(unsigned mask, const char *fname, 175 | int lnno, const char *text) 176 | { 177 | if(mask & CFLAG) 178 | return; 179 | if(mask & NFLAG) 180 | printf("%s:", *fname ? fname : "stdin"); 181 | if(mask & LFLAG) 182 | printf(" %d :", lnno); 183 | printf("%s", text); 184 | } --------------------------------------------------------------------------------