15177
备注:
|
22058
|
删除的内容标记成这样。 | 加入的内容标记成这样。 |
行号 580: | 行号 580: |
== 字符串转数值第2版 == | == 字符串转整数第2版 == |
行号 668: | 行号 668: |
= 函数 = == 模式查找 == 设计并编写一个程序,它将输入中包含特定“模式”或字符串的各行打印出来(这是UNIX程序grep的特例) {{{#!cplusplus #include <stdio.h> #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 */ 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; } }}} == 字符串转浮点数 == 函数atof把字符串s转换为相应的双精度浮点数,是atoi函数的扩展 {{{#!cplusplus #include <ctype.h> /* 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] == '.') i++; for (power = 1.0; isdigit(s[i]); i++) { val = 10.0 * val + (s[i] - '0'); power *= 10; } return sign * val / power; } }}} == 调用atof == {{{#!cplusplus #include <stdio.h> #define MAXLINE 100 /* 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; } }}} == 字符串转整数第3版 == 在函数atof的基础上,我们可以利用它编写出函数atoi(将字符串转换为int类型) {{{#!cplusplus /* atoi: convert string s to integer using atof */ int atoi(char s[]) { double atof(char s[]); return (int) atof(s); } }}} == 计算器 == 编写一个具有加(+)、减(-)、乘(*)、除(/)四则运算功能的计算器程序。为了更容易实现,我们在计算器中使用逆波兰表示法代替普通的中缀表示法,比如: {{{(1 - 2) * (4 + 5)}}} 采用逆波兰表示法表示为: {{{1 2 - 4 5 + *}}} {{{#!cplusplus #include <stdio.h> #include <stdlib.h> /* 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 */ 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; } }}} {{{#!cplusplus #include <ctype.h> 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; } }}} {{{#!cplusplus #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; } }}} == 打印整数 == {{{#!cplusplus #include <stdio.h> /* printd: print n in decimal */ void printd(int n) { if (n < 0) { putchar('-'); n = -n; } if (n / 10) printd(n / 10); putchar(n % 10 + '0'); } }}} == 快速排序 == {{{#!cplusplus /* 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); } }}} {{{#!cplusplus /* 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; } }}} |
1. 入门
1.1. 第一个C语言程序
写一个程序,在屏幕上输出hello, world
1.2. 摄氏华氏温度对照表
使用公式℃=(5/9)(℉-32) 打印华氏温度与摄氏温度对照表
1 #include <stdio.h>
2
3 /* print Fahrenheit-Celsius table
4 for fahr = 0, 20, ..., 300 */
5 main()
6 {
7 int fahr, celsius;
8 int lower, upper, step;
9
10 lower = 0; /* lower limit of temperature scale */
11 upper = 300; /* upper limit */
12 step = 20; /* step size */
13
14 fahr = lower;
15 while (fahr <= upper) {
16 celsius = 5 * (fahr-32) / 9;
17 printf("%d\t%d\n", fahr, celsius);
18 fahr = fahr + step;
19 }
20 }
1.3. 温度对照表第2版
上述的温度转换程序存在两个问题。比较简单的问题是,由于输出的数不是右对齐的,所以输出的结果不是很美观。另一个较为严重的问题是,由于我们使用的是整型算术运算,因此经计算得到的摄氏温度值不太精确,例如,与0℉对应的精确的摄氏温度应该为-17.8℃,而不是-17℃。
1 #include <stdio.h>
2
3 /* print Fahrenheit-Celsius table
4 for fahr = 0, 20, ..., 300; floating-point version */
5 main()
6 {
7 float fahr, celsius;
8 float lower, upper, step;
9
10 lower = 0; /* lower limit of temperatuire scale */
11 upper = 300; /* upper limit */
12 step = 20; /* step size */
13
14 fahr = lower;
15 while (fahr <= upper) {
16 celsius = (5.0/9.0) * (fahr-32.0);
17 printf("%3.0f %6.1f\n", fahr, celsius);
18 fahr = fahr + step;
19 }
20 }
1.4. 温度对照表第3版
对于某个特定任务我们可以采用多种方法来编写程序。
1.5. 温度对照表第4版
1 #include <stdio.h>
2
3 #define LOWER 0 /* lower limit of table */
4 #define UPPER 300 /* upper limit */
5 #define STEP 20 /* step size */
6
7 /* print Fahrenheit-Celsius table */
8 main()
9 {
10 int fahr;
11
12 for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP)
13 printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
14 }
1.6. 文件复制
把输入一次一个字符地复制到输出
1.7. 文件复制第2版
对于经验比较丰富的C语言程序员,可以把这个字符复制程序编写得更精炼一些。
1.8. 字符计数
下列程序用于对字符进行计数,它与上面的复制程序类似。
1.9. 字符计数第2版
1.10. 行计数
接下来的这个程序用于统计输入中的行数。
1.11. 单词计数
写一个程序用于统计行数、单词数与字符数
1 #include <stdio.h>
2
3 #define IN 1 /* inside a word */
4 #define OUT 0 /* outside a word */
5
6 /* count lines, words, and characters in input */
7 main()
8 {
9 int c, nl, nw, nc, state;
10
11 state = OUT;
12 nl = nw = nc = 0;
13 while ((c = getchar()) != EOF) {
14 ++nc;
15 if (c == '\n')
16 ++nl;
17 if (c == ' ' || c == '\n' || c = '\t')
18 state = OUT;
19 else if (state == OUT) {
20 state = IN;
21 ++nw;
22 }
23 }
24 printf("%d %d %d\n", nl, nw, nc);
25 }
1.12. 数字字符计数
编写一个程序,以统计各个数字、空白符(包括空格符、制表符及换行符)以及所有其他字符出现的次数
1 #include <stdio.h>
2
3 /* count digits, white space, others */
4 main()
5 {
6 int c, i, nwhite, nother;
7 int ndigit[10];
8
9 nwhite = nother = 0;
10 for (i = 0; i < 10; ++i)
11 ndigit[i] = 0;
12
13 while ((c = getchar()) != EOF)
14 if (c >= '0' && c <= '9')
15 ++ndigit[c-'0'];
16 else if (c == ' ' || c == '\n' || c == '\t')
17 ++nwhite;
18 else
19 ++nother;
20
21 printf("digits =");
22 for (i = 0; i < 10; ++i)
23 printf(" %d", ndigit[i]);
24 printf(", white space = %d, other = %d\n",
25 nwhite, nother);
26 }
1.13. 函数
写一个求幂的函数power(m,n)
1 #include <stdio.h>
2
3 int power(int m, int n);
4
5 /* test power function */
6 main()
7 {
8 int i;
9
10 for (i = 0; i < 10; ++i)
11 printf("%d %d %d\n", i, power(2,i), power(-3,i));
12 return 0;
13 }
14
15 /* power: raise base to n-th power; n >= 0 */
16 int power(int base, int n)
17 {
18 int i, p;
19
20 p = 1;
21 for (i = 1; i <= n; ++i)
22 p = p * base;
23 return p;
24 }
1.14. power函数第2版
1.15. 最长的行
写一个程序读入一组文本行,并把最长的文本行打印出来。
1 #include <stdio.h>
2 #define MAXLINE 1000 /* maximum input line length */
3
4 int getline(char line[], int maxline);
5 void copy(char to[], char from[]);
6
7 /* print the longest input line */
8 main()
9 {
10 int len; /* current line length */
11 int max; /* maximum length seen so far */
12 char line[MAXLINE]; /* current input line */
13 char longest[MAXLINE]; /* longest line saved here */
14
15 max = 0;
16 while ((len = getline(line, MAXLINE)) > 0)
17 if (len > max) {
18 max = len;
19 copy(longest, line);
20 }
21 if (max > 0) /* there was a line */
22 printf("%s", longest);
23 return 0;
24 }
25
26 /* getline: read a line into s, return length */
27 int getline(char s[],int lim)
28 {
29 int c, i;
30
31 for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
32 s[i] = c;
33 if (c == '\n') {
34 s[i] = c;
35 ++i;
36 }
37 s[i] = '\0';
38 return i;
39 }
40
41 /* copy: copy 'from' into 'to'; assume to is big enough */
42 void copy(char to[], char from[])
43 {
44 int i;
45
46 i = 0;
47 while ((to[i] = from[i]) != '\0')
48 ++i;
49 }
1.16. 最长的行第2版
使用全局变量来实现
1 #include <stdio.h>
2
3 #define MAXLINE 1000 /* maximum input line size */
4
5 int max; /* maximum length seen so far */
6 char line[MAXLINE]; /* current input line */
7 char longest[MAXLINE]; /* longest line saved here */
8
9 int getline(void);
10 void copy(void);
11
12 /* print longest input line; specialized version */
13 main()
14 {
15 int len;
16 extern int max;
17 extern char longest[];
18
19 max = 0;
20 while ((len = getline()) > 0)
21 if (len > max) {
22 max = len;
23 copy();
24 }
25 if (max > 0) /* there was a line */
26 printf("%s", longest);
27 return 0;
28 }
29
30 /* getline: specialized version */
31 int getline(void)
32 {
33 int c, i;
34 extern char line[];
35
36 for (i = 0; i < MAXLINE - 1
37 && (c=getchar)) != EOF && c != '\n'; ++i)
38 line[i] = c;
39 if (c == '\n') {
40 line[i] = c;
41 ++i;
42 }
43 line[i] = '\0';
44 return i;
45 }
46
47 /* copy: specialized version */
48 void copy(void)
49 {
50 int i;
51 extern char line[], longest[];
52
53 i = 0;
54 while ((longest[i] = line[i]) != '\0')
55 ++i;
56 }
2. 类型、运算符和表达式
2.1. 字符串长度
写一个函数求字符串的长度
2.2. 字符串转整数
写一个函数将包含一串数字的字符串转换成整数
2.3. 大写变小写
写一个函数,将大写字母变成小写字母,其他字符不变。
2.4. 随机函数
写一个函数,用来产生随机的整数
2.5. 字符串删除
写一个函数squeeze(s, c),删除字符串s中所有的字符c。
2.6. 字符串连接
写一个函数strcat(s,t),它将字符串t连接到字符串s的尾部
2.7. 位运算
写一个函数getbits(x,p,n),它返回x中从右边数第p位开始向右数n位的字段
2.8. 位计数
函数bitcount统计其整型参数的值为1的二进制位的个数
3. 控制流
3.1. 折半查找
1 /* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */
2 int binsearch(int x, int v[], int n)
3 {
4 int low, high, mid;
5
6 low = 0;
7 high = n - 1;
8 while (low <= high) {
9 mid = (low+high)/2;
10 if (x < v[mid])
11 high = mid + 1;
12 else if (x > v[mid])
13 low = mid + 1;
14 else /* found match */
15 return mid;
16 }
17 return -1; /* no match */
18 }
3.2. 数字字符计数第2版
1 #include <stdio.h>
2
3 main() /* count digits, white space, others */
4 {
5 int c, i, nwhite, nother, ndigit[10];
6
7 nwhite = nother = 0;
8 for (i = 0; i < 10; i++)
9 ndigit[i] = 0;
10 while ((c = getchar()) != EOF) {
11 switch (c) {
12 case '0': case '1': case '2': case '3': case '4':
13 case '5': case '6': case '7': case '8': case '9':
14 ndigit[c-'0']++;
15 break;
16 case ' ':
17 case '\n':
18 case '\t':
19 nwhite++;
20 break;
21 default:
22 nother++;
23 break;
24 }
25 }
26 printf("digits =");
27 for (i = 0; i < 10; i++)
28 printf(" %d", ndigit[i]);
29 printf(", white space = %d, other = %d\n",
30 nwhite, nother);
31 return 0;
32 }
3.3. 字符串转整数第2版
1 #include <ctype.h>
2
3 /* atoi: convert s to integer; version 2 */
4 int atoi(char s[])
5 {
6 int i, n, sign;
7
8 for (i = 0; isspace(s[i]); i++) /* skip white space */
9 ;
10 sign = (s[i] == '-') ? -1 : 1;
11 if (s[i] == '+' || s[i] == '-') /* skip sign */
12 i++;
13 for (n = 0; isdigit(s[i]); i++)
14 n = 10 * n + (s[i] - '0');
15 return sign * n;
16 }
3.4. 希尔排序
1 /* shellsort: sort v[0]...v[n-1] into increasing order */
2 void shellsort(int v[], int n)
3 {
4 int gap, i, j, temp;
5
6 for (gap = n/2; gap > 0; gap /= 2)
7 for (i = gap; i < n; i++)
8 for (j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) {
9 temp = v[j];
10 v[j] = v[j+gap];
11 v[j+gap] = temp;
12 }
13 }
3.5. 字符串翻转
3.6. 整数转字符串
1 /* itoa: convert n to characters in s */
2 void itoa(int n, char s[])
3 {
4 int i, sign;
5
6 if ((sign = n) < 0) /* record sign */
7 n = -n; /* make n positive */
8 i = 0;
9 do { /* generate digits in reverse order */
10 s[i++] = n % 10 + '0'; /* get next digit */
11 } while ((n /= 10) > 0); /* delete it */
12 if (sign < 0)
13 s[i++] = '-';
14 s[i] = '\0';
15 reverse(s);
16 }
3.7. 字符串裁剪
4. 函数
4.1. 模式查找
设计并编写一个程序,它将输入中包含特定“模式”或字符串的各行打印出来(这是UNIX程序grep的特例)
1 #include <stdio.h>
2 #define MAXLINE 1000 /* maximum input line length */
3
4 int getline(char line[], int max)
5 int strindex(char source[], char searchfor[]);
6
7 char pattern[] = "ould"; /* pattern to search for */
8
9 /* find all lines matching pattern */
10 main()
11 {
12 char line[MAXLINE];
13 int found = 0;
14
15 while (getline(line, MAXLINE) > 0)
16 if (strindex(line, pattern) >= 0) {
17 printf("%s", line);
18 found++;
19 }
20 return found;
21 }
22
23 /* getline: get line into s, return length */
24 int getline(char s[], int lim)
25 {
26 int c, i;
27
28 i = 0;
29 while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
30 s[i++] = c;
31 if (c == '\n')
32 s[i++] = c;
33 s[i] = '\0';
34 return i;
35 }
36
37 /* strindex: return index of t in s, -1 if none */
38 int strindex(char s[], char t[])
39 {
40 int i, j, k;
41
42 for (i = 0; s[i] != '\0'; i++) {
43 for (j=i, k=0; t[k]!='\0' && s[j]==t[k]; j++, k++)
44 ;
45 if (k > 0 && t[k] == '\0')
46 return i;
47 }
48 return -1;
49 }
4.2. 字符串转浮点数
函数atof把字符串s转换为相应的双精度浮点数,是atoi函数的扩展
1 #include <ctype.h>
2
3 /* atof: convert string s to double */
4 double atof(char s[])
5 {
6 double val, power;
7 int i, sign;
8
9 for (i = 0; isspace(s[i]); i++) /* skip white space */
10 ;
11 sign = (s[i] == '-') ? -1 : 1;
12 if (s[i] == '+' || s[i] == '-')
13 i++;
14 for (val = 0.0; isdigit(s[i]); i++)
15 val = 10.0 * val + (s[i] - '0');
16 if (s[i] == '.')
17 i++;
18 for (power = 1.0; isdigit(s[i]); i++) {
19 val = 10.0 * val + (s[i] - '0');
20 power *= 10;
21 }
22 return sign * val / power;
23 }
4.3. 调用atof
4.4. 字符串转整数第3版
在函数atof的基础上,我们可以利用它编写出函数atoi(将字符串转换为int类型)
4.5. 计算器
编写一个具有加(+)、减(-)、乘(*)、除(/)四则运算功能的计算器程序。为了更容易实现,我们在计算器中使用逆波兰表示法代替普通的中缀表示法,比如: (1 - 2) * (4 + 5) 采用逆波兰表示法表示为: 1 2 - 4 5 + *
1 #include <stdio.h>
2 #include <stdlib.h> /* for atof() */
3
4 #define MAXOP 100 /* max size of operand or operator */
5 #define NUMBER '0' /* signal that a number was found */
6
7 int getop(char []);
8 void push(double);
9 double pop(void);
10
11 /* reverse Polish calculator */
12 main()
13 {
14 int type;
15 double op2;
16 char s[MAXOP];
17
18 while ((type = getop(s)) != EOF) {
19 switch (type) {
20 case NUMBER:
21 push(atof(s));
22 break;
23 case '+':
24 push(pop() + pop());
25 break;
26 case '*':
27 push(pop() * pop());
28 break;
29 case '-':
30 op2 = pop();
31 push(pop() - op2);
32 break;
33 case '/':
34 op2 = pop();
35 if (op2 != 0.0)
36 push(pop() / op2);
37 else
38 printf("error: zero divisor\n");
39 break;
40 case '\n':
41 printf("\t%.8g\n", pop());
42 break;
43 default:
44 printf("error: unknown command %s\n", s);
45 break;
46 }
47 }
48 return 0;
49 }
1 #include <ctype.h>
2
3 int getch(void);
4 void ungetch(int);
5
6 /* getop: get next character or numeric operand */
7 int getop(char s[])
8 {
9 int i, c;
10
11 while ((s[0] = c = getch()) == ' ' || c == '\t')
12 ;
13 s[1] = '\0';
14 if (!isdigit(c) && c != '.')
15 return c; /* not a number */
16 i = 0;
17 if (isdigit(c)) /* collect integer part */
18 while (isdigit(s[++i] = c = getch()))
19 ;
20 if (c == '.') /* collect fraction part */
21 while (isdigit(s[++i] = c = getch()))
22 ;
23 s[i] = '\0';
24 if (c != EOF)
25 ungetch(c);
26 return NUMBER;
27 }
1 #define BUFSIZE 100
2
3 char buf[BUFSIZE]; /* buffer for ungetch */
4 int bufp = 0; /* next free position in buf */
5
6 int getch(void) /* get a (possibly pushed-back) character */
7 {
8 return (bufp > 0) ? buf[--bufp] : getchar();
9 }
10
11 void ungetch(int c) /* push character back on input */
12 {
13 if (bufp >= BUFSIZE)
14 printf("ungetch: too many characters\n");
15 else
16 buf[bufp++] = c;
17 }
4.6. 打印整数
4.7. 快速排序
1 /* qsort: sort v[left]...v[right] into increasing order */
2 void qsort(int v[], int left, int right)
3 {
4 int i, last;
5 void swap(int v[], int i, int j);
6
7 if (left >= right) /* do nothing if array contains */
8 return; /* fewer than two elements */
9 swap(v, left, (left + right)/2); /* move partition elem */
10 last = left; /* to v[0] */
11 for (i = left + 1; i <= right; i++) /* partition */
12 if (v[i] < v[left])
13 swap(v, ++last, i);
14 swap(v, left, last); /* restore partition elem */
15 qsort(v, left, last-1);
16 qsort(v, last+1, right);
17 }