The C Programming Language,C程序设计语言 (K&R),为C语言的设计者Dennis M. Ritchie和著名的计算机科学家Brian W.Kernighan合著的 一本介绍C语言的权威经典著作,学习c语言至今,第一次读这本书,这本书适合有一定的c语言基础的深入学习。
为什么说不适合初学者,觉得这本书更像一本字典,比如在函数章节,举例代码中用到了下面章节的数组,用到了数据结构的栈知识,为了学习大师的代码,在读这本书的时候,书中引用的代码,一一记录如下
第一章 导言
1、华氏温度与摄氏温度对照表
#include/* 当 fahr=0,20,… ,300 时,分别 打印华氏温度与摄氏温度对照表 */ int main() { int fahr, celsius; int lower, upper, step; lower = 0; /* 温度表的下限 */ upper = 300; /* 温度表的上限 */ step = 20; /* 步长 */ fahr = lower; while (fahr <= upper) { celsius = 5 * (fahr-32) / 9; printf("%d\t%d\n", fahr, celsius); fahr = fahr + step; } return 0; }
#include/* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300; floating-point version */ int main() { float fahr, celsius; float lower, upper, step; lower = 0; /* lower limit of temperatuire scale */ upper = 300; /* upper limit */ step = 20; /* step size */ fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf("%3.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } return 0; }
#include/* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300; floating-point version */ int main() { int fahr; for (fahr = 0; fahr <= 300; fahr = fahr + 20) printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); return 0; }
#include#define LOWER 0 /* lower limit of table */ #define UPPER 300 /* upper limit */ #define STEP 20 /* step size */ /* print Fahrenheit-Celsius table */ int main() { int fahr; for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP) printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); return 0; }
2、文件复制,getchar 与 putchar 函数
#include/* copy input to output; 1st version */ int main() { int c; c = getchar(); while (c != EOF) { putchar(c); c = getchar(); } return 0; }
#include/* copy input to output; 1st version */ int main() { int c; while ((c = getchar()) != EOF) putchar(c); return 0; }
3、字符计数,double也可以自增
#include/* count characters in input; 1st version */ int main() { long nc; nc = 0; while (getchar() != EOF) ++nc; printf("%ld\n", nc); return 0; }
#include/* count characters in input; 2nd version */ int main() { double nc; for (nc = 0; getchar() != EOF; ++nc) ; printf("%.0f\n", nc); return 0; }
4、行计数
#include/* count lines in input */ int main() { int c, nl; nl = 0; while ((c = getchar()) != EOF) if (c == '\n') ++nl; printf("%d\n", nl); return 0; }
5、单词计数,符号常量
#include#define IN 1 /* inside a word */ #define OUT 0 /* outside a word */ /* count lines, words, and characters in input */ int main() { int c, nl, nw, nc, state; state = OUT; nl = nw = nc = 0; while ((c = getchar()) != EOF) { ++nc; if (c == '\n') ++nl; if (c == ' ' || c == '\n' || c == '\t') state = OUT; else if (state == OUT) { state = IN; ++nw; } } printf("%d %d %d\n", nl, nw, nc); return 0; }
6、统计数字、空白符、其他字符,利用数组统计数字
#include/* count digits, white space, others */ int main() { int c, i, nwhite, nother; int ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; ++i) ndigit[i] = 0; while ((c = getchar()) != EOF) if (c >= '0' && c <= '9') ++ndigit[c-'0']; /*count digits*/ else if (c == ' ' || c == '\n' || c == '\t') ++nwhite; else ++nother; printf("digits ="); for (i = 0; i < 10; ++i) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); return 0; }
7、求幂的函数 power(m, n) ,传值调用
#includeint power(int m, int n); /* test power function */ int main() { int i; for (i = 0; i < 10; ++i) printf("%d %d %d\n", i, power(2,i), power(-3,i)); return 0; } /* power: raise base to n-th power; n >= 0 */ int power(int base, int n) { int i, p; p = 1; for (i = 1; i <= n; ++i) p = p * base; return p; }
#includeint power(int m, int n); /* test power function */ int main() { int i; for (i = 0; i < 10; ++i) printf("%d %d %d\n", i, power(2,i), power(-3,i)); return 0; } /* power: raise base to n-th power; n >= 0; version 2 */ int power(int base, int n) /*传值*/ { int p; for (p = 1; n > 0; --n) p = p * base; return p; }
8、输出最长字符串,字符数组,getline,copy,外部变量
#include#define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int maxline); void copy(char to[], char from[]); /* print the longest input line */ int main() { int len; /* current line length */ int max; /* maximum length seen so far */ char line[MAXLINE]; /* current input line */ char longest[MAXLINE]; /* longest line saved here */ max = 0; while ((len = getline(line, MAXLINE)) > 0) if (len > max) { max = len; copy(longest, line); } if (max > 0) /* there was a line */ printf("%s", longest); return 0; } /* getline: read a line into s, return length */ int getline(char s[],int lim) { int c, i; for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) s[i] = c; if (c == '\n') { /*长度包含回车符*/ s[i] = c; ++i; } s[i] = '\0'; return i; } /* copy: copy 'from' into 'to'; assume to is big enough */ void copy(char to[], char from[]) { int i; i = 0; while ((to[i] = from[i]) != '\0') ++i; }
#include/*外部变量*/ #define MAXLINE 1000 /* maximum input line length */ int max; /* maximum length seen so far */ char line[MAXLINE]; /* current input line */ char longest[MAXLINE]; /* longest line saved here */ int getline(void); void copy(void); /* print longest input line; specialized version */ int main() { int len; extern int max; /*外部变量*/ extern char longest[]; /*外部变量*/ max = 0; while ((len = getline()) > 0) if (len > max) { max = len; copy(); } if (max > 0) /* there was a line */ printf("%s", longest); return 0; } /* getline: specialized version */ int getline(void) { int c, i; extern char line[]; /*外部变量*/ for (i = 0; i < MAXLINE - 1 && (c=getchar()) != EOF && c != '\n'; ++i) line[i] = c; if (c == '\n') { line[i] = c; ++i; } line[i] = '\0'; return i; } /* copy: specialized version */ void copy(void) { int i; extern char line[], longest[]; /*外部变量*/ i = 0; while ((longest[i] = line[i]) != '\0') ++i; }
第二章 类型、运算符与表达式
9、字符串长度
/* strlen: return length of s */ int strlen(char s[]) { int i = 0; while (s[i] != '\0') ++i; return i; }
10、枚举,不同枚举中的名字必须互不相同,同一枚举中不同的名字可以具有相同的值
enum escapes { BELL = '\a', BACKSPACE = '\b', TAB = '\t', NEWLINE = '\n', VTAB = '\v', RETURN = '\r' }; enum months { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
11、闰年
int year; scanf("%d", &year); if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) printf("%d is a leap year\n", year); else printf("%d is not a leap year\n", year);
12、atoi
/* atoi: convert s to integer */ int atoi(char s[]) { int i, n; n = 0; for (i = 0; s[i] >= '0' && s[i] <= '9'; ++i) n = 10 * n + (s[i] - '0'); return n; }
13、lower
/* lower: convert c to lower case; ASCII only */ int lower(int c) { if (c >= 'A' && c <= 'Z') return c + 'a' - 'A'; else return c; }
14、sqrt,强制类型转换只是生成一个指定类型的 n 的值,n 本身的值并没有改变
int n; n = 19; sqrt((double) n);
15、rand,srand,
unsigned long int next = 1; /* rand: return pseudo-random integer on 0..32767 */ int rand(void) { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } /* srand: set seed for rand() */ void srand(unsigned int seed) { next = seed; }
16、删除字符串中的出现的所有字符c,自增、自减运算符
/* squeeze: delete all c from s */ void squeeze(char s[], int c) { int i, j; for (i = j = 0; s[i] != '\0'; i++) if (s[i] != c) s[j++] = s[i]; s[j] = '\0'; }
17、strcat,
/* strcat: concatenate t to end of s; s must be big enough */ void strcat(char s[], char t[]) { int i, j; i = j = 0; while (s[i] != '\0') /* find end of s */ i++; while ((s[i++] = t[j++]) != '\0') /* copy t */ ; }
18、getbits,返回 x 中从右边数第 p 位开始向右数 n 位的字段
/* getbits: get n bits from position p */ unsigned getbits(unsigned x, int p, int n) { return (x >> (p+1-n)) & ~(~0 << n); }
19、bitcount,
/* bitcount: count 1 bits in x */ int bitcount(unsigned x) { int b; for (b = 0; x != 0; x >>= 1) if (x & 01) b++; return b; }
20、每行打印 10 个元素,每列之间用一个空格隔开,每行用一个换行符结束;自动判断加复数s,条件表达式
for (i = 0; i < n; i++) printf("%6d%c", a[i], (i%10==9 || i==n-1) ? '\n' : ' ');
printf("You have %d item%s.\n", n, n==1 ? "" : "s");
第3章 控制流
21、binsearch,
/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ int binsearch(int x, int v[], int n) { int low, high, mid; low = 0; high = n - 1; while (low <= high) { mid = (low+high)/2; if (x < v[mid]) high = mid + 1; else if (x > v[mid]) low = mid + 1; else /* found match */ return mid; } return -1; /* no match */ }
22、switch,统计数字、空白符、其他字符
#include/* count digits, white space, others */ int main() { int c, i, nwhite, nother, ndigit[10]; nwhite = nother = 0; for (i = 0; i < 10; i++) ndigit[i] = 0; while ((c = getchar()) != EOF) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': ndigit[c-'0']++; break; case ' ': case '\n': case '\t': nwhite++; break; default: nother++; break; } } printf("digits ="); for (i = 0; i < 10; i++) printf(" %d", ndigit[i]); printf(", white space = %d, other = %d\n", nwhite, nother); return 0; }
23、atoi
#include#include /* atoi: convert s to integer; version 2 */ int atoi(char s[]) { int i, n, sign; for (i = 0; isspace(s[i]); i++) /* skip white space */ ; sign = (s[i] == '-') ? -1 : 1; if (s[i] == '+' || s[i] == '-') /* skip sign */ i++; for (n = 0; isdigit(s[i]); i++) n = 10 * n + (s[i] - '0'); return sign * n; } int main() { char s[256]; scanf("%s",s); printf("%d\n", atoi(s)); return 0; }
24、shell排序算法
/* shellsort: sort v[0]...v[n-1] into increasing order */ void shellsort(int v[], int n) { int gap, i, j, temp; for (gap = n/2; gap > 0; gap /= 2) for (i = gap; i < n; i++) for (j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) { temp = v[j]; v[j] = v[j+gap]; v[j+gap] = temp; } }
25、reverse
#include <string.h> /* reverse: reverse string s in place */ void reverse(char s[]) { int c, i, j; for (i = 0, j = strlen(s)-1; i < j; i++, j--) { c = s[i]; s[i] = s[j]; s[j] = c; /*c = s[i], s[i] = s[j], s[j] = c;*/ /*逗号表达式*/ } }
26、itoa
/* itoa: convert n to characters in s */ void itoa(int n, char s[]) { int i, sign; if ((sign = n) < 0) /* record sign */ n = -n; /* make n positive */ i = 0; do { /* generate digits in reverse order */ s[i++] = n % 10 + '0'; /* get next digit */ } while ((n /= 10) > 0); /* delete it */ if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); }
27、trim
/* trim: remove trailing blanks, tabs, newlines */ int trim(char s[]) { int n; for (n = strlen(s)-1; n >= 0; n--) if (s[n] != ' ' && s[n] != '\t' && s[n] != '\n') break; s[n+1] = '\0'; return n; }
28、goto
for ( ... ) for ( ... ) { ... if (disaster) goto error; } ... error: /* clean up the mess */
for (i = 0; i < n; i++) for (j = 0; j < m; j++) if (a[i] == b[j]) goto found; /* didn't find any common element */ ... found: /* got one: a[i] == b[j] */ ...
found = 0; for (i = 0; i < n && !found; i++) for (j = 0; j < m && !found; j++) if (a[i] == b[j]) found = 1; if (found) /* got one: a[i-1] == b[j-1] */ ... else /* didn't find any common element */ ...
第4章 函数与程序结构
29、getline,strindex,printf,分别处理 3 个小的部分比处理一个大的整体更容易
#include#define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int max); int strindex(char source[], char searchfor[]); char pattern[] = "ould"; /* pattern to search for */ /* find all lines matching pattern */ int main() { char line[MAXLINE]; int found = 0; while (getline(line, MAXLINE) > 0) if (strindex(line, pattern) >= 0) { printf("%s", line); found++; } return found; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } /* strindex: return index of t in s, -1 if none */ int strindex(char s[], char t[]) { int i, j, k; for (i = 0; s[i] != '\0'; i++) { for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++) ; if (k > 0 && t[k] == '\0') return i; } return -1; }
30、atof,
#include/* atof: convert string s to double */ double atof(char s[]) { double val, power; int i, sign; for (i = 0; isspace(s[i]); i++) /* skip white space */ ; sign = (s[i] == '-') ? -1 : 1; if (s[i] == '+' || s[i] == '-') i++; for (val = 0.0; isdigit(s[i]); i++) val = 10.0 * val + (s[i] - '0'); if (s[i] == '.') /*处理小数,除以power*/ i++; for (power = 1.0; isdigit(s[i]); i++) { val = 10.0 * val + (s[i] - '0'); power *= 10; } return sign * val / power; }
31、rudimentary calculator
#include#define MAXLINE 100 #include double atof(char s[]); int getline(char s[], int lim); /* rudimentary calculator */ main() { double sum, atof(char []); char line[MAXLINE]; int getline(char line[], int max); sum = 0; while (getline(line, MAXLINE) > 0) printf("\t%g\n", sum += atof(line)); return 0; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } double atof(char s[]) { double val, power; int i, sign; for (i = 0; isspace(s[i]); i++) /* skip white space */ ; sign = (s[i] == '-') ? -1 : 1; if (s[i] == '+' || s[i] == '-') i++; for (val = 0.0; isdigit(s[i]); i++) val = 10.0 * val + (s[i] - '0'); if (s[i] == '.') i++; for (power = 1.0; isdigit(s[i]); i++) { val = 10.0 * val + (s[i] - '0'); power *= 10; } return sign * val / power; }
32、逆波兰表达式,计算器,1 2 - 4 5 + *,外部变量或函数的作用域从声明它的地方开始,到其所在的(待编译的)文件的末尾结束
#include#include /* for atof() */ #define MAXOP 100 /* max size of operand or operator */ #define NUMBER '0' /* signal that a number was found */ int getop(char []); void push(double); double pop(void); /* reverse Polish calculator */ int main() { int type; double op2; char s[MAXOP]; while ((type = getop(s)) != EOF) { switch (type) { case NUMBER: push(atof(s)); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop() / op2); else printf("error: zero divisor\n"); break; case '\n': /*回车, 输入结束, 打印结果*/ printf("\t%.8g\n", pop()); break; default: printf("error: unknown command %s\n", s); break; } } return 0; } #define MAXVAL 100 /* maximum depth of val stack */ int sp = 0; /* next free stack position */ double val[MAXVAL]; /* value stack */ /* push: push f onto value stack */ void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("error: stack full, can't push %g\n", f); } /* pop: pop and return top value from stack */ double pop(void) { if (sp > 0) return val[--sp]; else { printf("error: stack empty\n"); return 0.0; } } #include int getch(void); void ungetch(int); /* getop: get next character or numeric operand */ int getop(char s[]) { int i, c; while ((s[0] = c = getch()) == ' ' || c == '\t') ; s[1] = '\0'; if (!isdigit(c) && c != '.') return c; /* not a number */ i = 0; if (isdigit(c)) /* collect integer part */ while (isdigit(s[++i] = c = getch())) ; if (c == '.') /* collect fraction part */ while (isdigit(s[++i] = c = getch())) ; s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; } #define BUFSIZE 100 char buf[BUFSIZE]; /* buffer for ungetch */ int bufp = 0; /* next free position in buf */ int getch(void) /* get a (possibly pushed-back) character */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* push character back on input */ { if (bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
33、reverse Polish calculator,多文件,定义和声明考虑共享问题,尽可能把共享的部分集中在一起 ,外部的 static 声明通常多用于变量,当然,它也可用于声明函数 ,可以屏蔽变量或函数
#include#include /* for atof() */ #include "calc.h" #define MAXOP 100 /* max size of operand or operator */ /* reverse Polish calculator */ int main() { int type; double op2; char s[MAXOP]; while ((type = getop(s)) != EOF) { switch (type) { case NUMBER: push(atof(s)); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop() / op2); else printf("error: zero divisor\n"); break; case '\n': /*回车输入结束,打印结果*/ printf("\t%.8g\n", pop()); break; default: printf("error: unknown command %s\n", s); break; } } return 0; }
#define NUMBER '0' void push(double); double pop(void); int getop(char[]); int getch(void); void ungetch(int c);
#include#include "calc.h" #define MAXVAL 100 /* maximum depth of val stack */ int sp = 0; /* next free stack position */ double val[MAXVAL]; /* value stack */ /* push: push f onto value stack */ void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("error: stack full, can't push %g\n", f); } /* pop: pop and return top value from stack */ double pop(void) { if (sp > 0) return val[--sp]; else { printf("error: stack empty\n"); return 0.0; } }
#include#include #include "calc.h" /* getop: get next character or numeric operand */ int getop(char s[]) { int i, c; while ((s[0] = c = getch()) == ' ' || c == '\t') ; s[1] = '\0'; if (!isdigit(c) && c != '.') return c; /* not a number */ i = 0; if (isdigit(c)) /* collect integer part */ while (isdigit(s[++i] = c = getch())) ; if (c == '.') /* collect fraction part */ while (isdigit(s[++i] = c = getch())) ; s[i] = '\0'; if (c != EOF) ungetch(c); return NUMBER; }
#include#define BUFSIZE 100 char buf[BUFSIZE]; /* buffer for ungetch */ int bufp = 0; /* next free position in buf */ int getch(void) /* get a (possibly pushed-back) character */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* push character back on input */ { if (bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
34、修改 getop 函数,使其不必使用 ungetch 函数 ,通过静态内部变量实现,另,文件 stack.c 中定义的变量 sp 与 val 以及文件 getch.c 中定义的变量 buf 与 bufp前加static限定,隐藏外部变量
#include#include #include "calc.h" /* getop: get next character or numeric operand */ int getop(char s[]) { int i; static int c = ' '; /*静态内部变量,初始化' '*/ while ((s[0] = c = getch()) == ' ' || c == '\t') ; s[1] = '\0'; if (!isdigit(c) && c != '.') return c; /* not a number */ i = 0; if (isdigit(c)) /* collect integer part */ while (isdigit(s[++i] = c = getch())) ; if (c == '.') /* collect fraction part */ while (isdigit(s[++i] = c = getch())) ; s[i] = '\0'; return NUMBER; }
35、递归打印整数,在C语言中,枚举类型、字符型和各种整数的表示形式统一叫做标量类型
#include/* printd: print n in decimal */ void printd(int n) { if (n < 0) { /*n为负数*/ putchar('-'); /*第一次调用打印'-'*/ n = -n; /*正数*/ } if (n / 10) /*递归调用*/ printd(n / 10); putchar(n % 10 + '0');/*递归返回打印*/ } int main() { printd(-12345); return 0; }
36、递归快排
#include/* swap: interchange v[i] and v[j] */ void swap(int v[], int i, int j) { int temp; temp = v[i]; v[i] = v[j]; v[j] = temp; } /* qsort: sort v[left]...v[right] into increasing order */ void qsort(int v[], int left, int right) { int i, last; //void swap(int v[], int i, int j); if (left >= right) /* do nothing if array contains */ return; /* fewer than two elements */ swap(v, left, (left + right)/2); /* move partition elem */ last = left; /* to v[0] */ for (i = left + 1; i <= right; i++) /* partition */ if (v[i] < v[left]) swap(v, ++last, i); swap(v, left, last); /* restore partition elem */ qsort(v, left, last-1); qsort(v, last+1, right); } int main() { int i, v[] = {9,1,5,2,3,7,4,8,0,6}; qsort(v,0,9); for(i=0; i<10; ++i) printf("\t%d\n", v[i]); return 0; }
37、带参的宏
#include#define dprint(expr) printf(#expr " = %g\n", expr) int main() { double x = 9, y = 3; dprint(x/y); //printf("x/y = %g\n", x/y); return 0; }
第5章 指针与数组
38、getint,
#include#define SIZE 256 int main() { int i, n, array[SIZE], getint(int *); for (n = 0; n < SIZE && getint(&array[n]) != EOF; n++) ; for(i = 0; i < n; ++i) printf("%d\n", array[i]); return 0; } #include int getch(void); void ungetch(int); /* getint: get next integer from input into *pn */ int getint(int *pn) { int c, sign; while (isspace(c = getch())) /* skip white space */ ; if (!isdigit(c) && c != EOF && c != '+' && c != '-') { ungetch(c); /* it is not a number */ return 0; } sign = (c == '-') ? -1 : 1; if (c == '+' || c == '-') c = getch(); for (*pn = 0; isdigit(c); c = getch()) *pn = 10 * *pn + (c - '0'); *pn *= sign; if (c != EOF) ungetch(c); return c; } #define BUFSIZE 100 char buf[BUFSIZE]; /* buffer for ungetch */ int bufp = 0; /* next free position in buf */ int getch(void) /* get a (possibly pushed-back) character */ { return (bufp > 0) ? buf[--bufp] : getchar(); } void ungetch(int c) /* push character back on input */ { if (bufp >= BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++] = c; }
39、strlen,
/* strlen: return length of string s */ int strlen(const char *s)/*int strlen(const char s[])*/ { int n; for (n = 0; *s != '\0'; s++) n++; return n; }
/* strlen: return length of string s */ int strlen(const char *s) { const char *p = s; while (*p != '\0') p++; return p - s; }
40、alloc,afree
#define ALLOCSIZE 10000 /* size of available space */ static char allocbuf[ALLOCSIZE]; /* storage for alloc */ static char *allocp = allocbuf; /* next free position */ char *alloc(int n) /* return pointer to n characters */ { if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ allocp += n; return allocp - n; /* old p */ } else /* not enough room */ return 0; }
41、strcpy
/* strcpy: copy t to s; array subscript version */ void strcpy(char *s, char *t) { int i; i = 0; while ((s[i] = t[i]) != '\0') i++; }
/* strcpy: copy t to s; pointer version */ void strcpy(char *s, char *t) { int i; i = 0; while ((*s = *t) != '\0') { s++; t++; } }
/* strcpy: copy t to s; pointer version 2 */ void strcpy(char *s, char *t) { while ((*s++ = *t++) != '\0') ; }
/* strcpy: copy t to s; pointer version 3 */ void strcpy(char *s, char *t) { while (*s++ = *t++) ; }
42、strcmp
/* strcmp: return <0 if s0 if s>t */ int strcmp(char *s, char *t) { int i; for (i = 0; s[i] == t[i]; i++) if (s[i] == '\0') return 0; return s[i] - t[i]; }
/* strcmp: return <0 if s0 if s>t */ int strcmp(char *s, char *t) { for ( ; *s == *t; s++, t++) if (*s == '\0') return 0; return *s - *t; }
43、sort
#include#include <string.h> /* strcpy strcmp */ #define MAXLINES 5000 /* max #lines to be sorted */ char *lineptr[MAXLINES]; /* pointers to text lines */ int readlines(char *lineptr[], int nlines); void writelines(char *lineptr[], int nlines); void qsort(char *lineptr[], int left, int right); /* sort input lines */ main() { int nlines; /* number of input lines read */ if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { qsort(lineptr, 0, nlines-1); writelines(lineptr, nlines); return 0; } else { printf("error: input too big to sort\n"); return 1; } } #define MAXLEN 1000 /* max length of any input line */ int getline(char *, int); char *alloc(int); /* readlines: read input lines */ int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN]; nlines = 0; while ((len = getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; /* delete newline */ strcpy(p, line); lineptr[nlines++] = p; } return nlines; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } #define ALLOCSIZE 10000 /* size of available space */ static char allocbuf[ALLOCSIZE]; /* storage for alloc */ static char *allocp = allocbuf; /* next free position */ char *alloc(int n) /* return pointer to n characters */ { if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ allocp += n; return allocp - n; /* old p */ } else /* not enough room */ return 0; } /* writelines: write output lines */ void writelines(char *lineptr[], int nlines) { int i; for (i = 0; i < nlines; i++) printf("%s\n", lineptr[i]); } /* writelines: write output lines */ /* void writelines(char *lineptr[], int nlines) { while (nlines-- > 0) printf("%s\n", *lineptr++); } */ /* qsort: sort v[left]...v[right] into increasing order */ void qsort(char *v[], int left, int right) { int i, last; void swap(char *v[], int i, int j); if (left >= right) /* do nothing if array contains */ return; /* fewer than two elements */ swap(v, left, (left + right)/2); last = left; for (i = left+1; i <= right; i++) if (strcmp(v[i], v[left]) < 0) swap(v, ++last, i); swap(v, left, last); qsort(v, left, last-1); qsort(v, last+1, right); } /* swap: interchange v[i] and v[j] */ void swap(char *v[], int i, int j) { char *temp;temp = v[i]; v[i] = v[j]; v[j] = temp; }
44、day_of_year 、month_day
#includestatic char daytab[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; /* day_of_year: set day of year from month & day */ int day_of_year(int year, int month, int day) { int i, leap; leap = year%4 == 0 && year%100 != 0 || year%400 == 0; for (i = 1; i < month; i++) day += daytab[leap][i]; return day; } /* month_day: set month, day from day of year */ void month_day(int year, int yearday, int *pmonth, int *pday) { int i, leap; leap = year%4 == 0 && year%100 != 0 || year%400 == 0; for (i = 1; yearday > daytab[leap][i]; i++) yearday -= daytab[leap][i]; *pmonth = i; *pday = yearday; } int main() { int year = 2020, month, day; printf("day = %d\n",day_of_year(year,8,6)); month_day(year,219,&month,&day); printf("month = %d, day = %d\n", month, day); return 0; }
45、month_name
/* month_name: return name of n-th month */ char *month_name(int n) { static char *name[] = { "Illegal month", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" };
46、命令行参数
#include/* echo command-line arguments; 1st version */ int main(int argc, char *argv[]) { int i; for (i = 1; i < argc; i++) printf("%s%s", argv[i], (i < argc-1) ? " " : ""); printf("\n"); return 0; }
#include/* echo command-line arguments; 2nd version */ int main(int argc, char *argv[]) { while (--argc > 0) printf("%s%s", *++argv, (argc > 1) ? " " : ""); printf("\n"); return 0; }
#include#include <string.h> #define MAXLINE 1000 int getline(char *line, int max); /* find: print lines that match pattern from 1st arg */ int main(int argc, char *argv[]) { char line[MAXLINE]; int found = 0; if (argc != 2) printf("Usage: find pattern\n"); else while (getline(line, MAXLINE) > 0) if (strstr(line, argv[1]) != NULL) { printf("%s", line); found++; } return found; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; }
#include#include <string.h> #define MAXLINE 1000 int getline(char *line, int max); /* find: print lines that match pattern from 1st arg */ int main(int argc, char *argv[]) { char line[MAXLINE]; long lineno = 0; int c, except = 0, number = 0, found = 0; while (--argc > 0 && (*++argv)[0] == '-') while (c = *++argv[0]) switch (c) { case 'x': except = 1; break; case 'n': number = 1; break; default: printf("find: illegal option %c\n", c); argc = 0; found = -1; break; } if (argc != 1) printf("Usage: find -x -n pattern\n"); else while (getline(line, MAXLINE) > 0) { lineno++; if ((strstr(line, *argv) != NULL) != except) { if (number) printf("%ld:", lineno); printf("%s", line); found++; } } return found; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; }
47、qsort,函数指针
#include#include <string.h> #define MAXLINES 5000 /* max #lines to be sorted */ char *lineptr[MAXLINES]; /* pointers to text lines */ int readlines(char *lineptr[], int nlines); void writelines(char *lineptr[], int nlines); void Qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *)); int numcmp(char *, char *); /* sort input lines */ main(int argc, char *argv[]) { int nlines; /* number of input lines read */ int numeric = 0; /* 1 if numeric sort */ if (argc > 1 && strcmp(argv[1], "-n") == 0) numeric = 1; if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { Qsort((void**) lineptr, 0, nlines-1, (int (*)(void*,void*))(numeric ? numcmp : strcmp)); writelines(lineptr, nlines); return 0; } else { printf("input too big to sort\n"); return 1; } } /* Qsort: sort v[left]...v[right] into increasing order */ void Qsort(void *v[], int left, int right, int (*comp)(void *, void *)) { int i, last; void swap(void *v[], int, int); if (left >= right) /* do nothing if array contains */ return; /* fewer than two elements */ swap(v, left, (left + right)/2); last = left; for (i = left+1; i <= right; i++) if ((*comp)(v[i], v[left]) < 0) swap(v, ++last, i); swap(v, left, last); Qsort(v, left, last-1, comp); Qsort(v, last+1, right, comp); } /* writelines: write output lines */ void writelines(char *lineptr[], int nlines) { while (nlines-- > 0) printf("%s\n", *lineptr++); } #define MAXLEN 1000 /* max length of any input line */ int getline(char *, int); char *alloc(int); /* readlines: read input lines */ int readlines(char *lineptr[], int maxlines) { int len, nlines; char *p, line[MAXLEN]; nlines = 0; while ((len = getline(line, MAXLEN)) > 0) if (nlines >= maxlines || (p = alloc(len)) == NULL) return -1; else { line[len-1] = '\0'; /* delete newline */ strcpy(p, line); lineptr[nlines++] = p; } return nlines; } /* getline: get line into s, return length */ int getline(char s[], int lim) { int c, i; i = 0; while (--lim > 0 && (c=getchar()) != EOF && c != '\n') s[i++] = c; if (c == '\n') s[i++] = c; s[i] = '\0'; return i; } #define ALLOCSIZE 10000 /* size of available space */ static char allocbuf[ALLOCSIZE]; /* storage for alloc */ static char *allocp = allocbuf; /* next free position */ char *alloc(int n) /* return pointer to n characters */ { if (allocbuf + ALLOCSIZE - allocp >= n) { /* it fits */ allocp += n; return allocp - n; /* old p */ } else /* not enough room */ return 0; } #include /* numcmp: compare s1 and s2 numerically */ int numcmp(char *s1, char *s2) { double v1, v2; v1 = atof(s1); v2 = atof(s2); if (v1 < v2) return -1; else if (v1 > v2) return 1; else return 0; } void swap(void *v[], int i, int j) { void *temp; temp = v[i]; v[i] = v[j]; v[j] = temp; }
48、复杂声明
#include#include <string.h> #include #define MAXTOKEN 100 enum { NAME, PARENS, BRACKETS }; void dcl(void); void dirdcl(void); int gettoken(void); int tokentype; /* type of last token */ char token[MAXTOKEN]; /* last token string */ char name[MAXTOKEN]; /* identifier name */ char datatype[MAXTOKEN]; /* data type = char, int, etc. */ char out[1000]; main() /* convert declaration to words */ { while (gettoken() != EOF) { /* 1st token on line */ strcpy(datatype, token); /* is the datatype */ out[0] = '\0'; dcl(); /* parse rest of line */ if (tokentype != '\n') printf("syntax error\n"); printf("%s: %s %s\n", name, out, datatype); } return 0; } /* dcl: parse a declarator */ void dcl(void) { int ns; for (ns = 0; gettoken() == '*'; ) /* count *'s */ ns++; dirdcl(); while (ns-- > 0) strcat(out, " pointer to"); } /* dirdcl: parse a direct declarator */ void dirdcl(void) { int type; if (tokentype == '(') { /* ( dcl ) */ dcl(); if (tokentype != ')') printf("error: missing )\n"); } else if (tokentype == NAME) /* variable name */ strcpy(name, token); else printf("error: expected name or (dcl)\n"); while ((type=gettoken()) == PARENS || type == BRACKETS) if (type == PARENS) strcat(out, " function returning"); else { strcat(out, " array"); strcat(out, token); strcat(out, " of"); } } int gettoken(void) /* return next token */ { int c, getch(void); void ungetch(int); char *p = token; while ((c = getch()) == ' ' || c == '\t') ; if (c == '(') { if ((c = getch()) == ')') { strcpy(token, "()"); return tokentype = PARENS; } else { ungetch(c); return tokentype = '('; } } else if (c == '[') { for (*p++ = c; (*p++ = getch()) != ']'; ) ; *p = '\0'; return tokentype = BRACKETS; } else if (isalpha(c)) { for (*p++ = c; isalnum(c = getch()); ) *p++ = c; *p = '\0'; ungetch(c); return tokentype = NAME; } else return tokentype = c; }
第6章 结构