现在的位置: 首页 > 设计导读 > 正文

【K&R C语言】第4章 函数与程序结构

2011年04月13日 设计导读 ⁄ 共 3759字 ⁄ 字号 暂无评论

函数可以把大的计算任务分解成若干个较小的任务,从而使整个程序结构更加清晰,并降低编写和修改程序的难度。

4.1 函数的基本知识	【A * 查找模式串】
4.2 返回非整型值的函数	 
   【B * 函数: atof 字符串 ->双精度浮点数】
   【简单的计算器程序】
4.3 外部变量 【逆波兰计算器】
4.10 递归	 
   【C 打印十进制数】
   【D * 快速排序】

4.1 函数的基本知识 【查找模式串】

任务的划分

while (还有未处理的行)
    if (该行包含指定的模式)
        打印该行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#define MAXLINE 1000
#define MAXWORD 20
 
int getline(char line[], int max);
 
int main()
{
    char line[MAXLINE];
    char pattern[MAXWORD];
    int found = 0;
 
    scanf("%s", pattern); 
    while (getline(line, MAXLINE) > 0)
        if (strstr(line, pattern)) {
            printf("%s", line);
            found++;
        }
    printf("total found: %d\n", found);
}
 
/* getline: get line into s, return length */
int getline(char line[],int max)
{
    if (fgets(line, max, stdin) == NULL)
        return 0;
    else
        return strlen(line);
}

函数 strindex 在库函数中已经有实现,也就是 strstr 。

另一种实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#define MAXLINE 1000 
#define MAXWORD 20
 
int main()
{
    char line[MAXLINE];
    char pattern[MAXWORD];
    int  found = 0;
 
    /* freopen("in.txt","r",stdin); */
    scanf("%s", pattern);
 
    while (gets(line))
        if (strstr(line, pattern)) {
            puts(line);
            found++;
        }
    printf("total found: %d\n", found);
    return 0;
}

上面这个程序只能用作学校练习来使用,并不足以胜任工业级应用,因为 gets 函数存在缓冲区溢出漏洞。
这也是教材为何要定义了函数 getline 来替换 gets 。

#include <string.h>
char *strstr( const char *str1, const char *str2 );
char *gets( char *str );

为了避免输入,可以使用重定向,从文件 in.txt 而不是标准输入 stdin 中读取数据。
文件 in.txt 的第1行是待搜索的字符串,下面是搜索的文本。下面是 in.txt 的示例。

1
2
3
4
5
6
7
8
9
Richie
100107001	Apple	F	20	 72
100107002 	Darwin	M	19	 68
100107003	Eric    	M	19	 79
100107004	Peter	M	21	 46
100107006	Richie	M	70	100
100107007	Kern    	M	69	100
100107008	Jane    	F	20	 74
100107009	Ann   	F	19	 69

4.2 返回非整型值的函数
【函数: atof 字符串 ->双精度浮点数】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
double atof(char s[])
{
    double val, power;
    int i, sign;
 
    for (i = 0; isspace(s[i]); i++)
        ;
    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;
}

【简单的计算器程序】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
 
#define MAXLINE 100
 
int main()
{
    double sum;
    char line[MAXLINE];
 
    sum = 0;
    while (getline(line, MAXLINE) > 0)
        printf("\t%g\n", sum += atof(line));
    return 0;
}

4.3 外部变量 【逆波兰计算器】

程序结构

1
2
3
4
5
6
7
8
9
10
11
12
13
while (下一个运算符或操作数不是文件结束指示符) {
    if (是数)
        将该数压入到栈中 ;
    else if (是运算符) {
        弹出所需数目的操作数 ;
        执行运算 ;
        将结果压入到栈中 ;
    }
    else if (是换行符)
        弹出并打印栈顶的值;
    else
        出错;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <ctype.h>
 
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
 
#define MAXVAL 100 /* maximum depth of val stack */
int sp = 0;
double val[MAXVAL]; /* value stack */
 
void push(double f)
{
    if (sp < MAXVAL)
        val[sp++] = f;
    else
        printf("error: stack full, can't push %g\n", f);
}
 
double pop(void)
{
    if (sp > 0)
        return val[--sp];
    else {
        printf("error: stack empty\n");
        return 0.0;
    }
}
 
#define BUFSIZE 100
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0;
 
int getch(void) /* get a (possibly pushed-back) character */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}
 
void ungetch(int c)
{
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}
 
/* 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;
    i = 0;
 
    /* not a number */
    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;
}
 
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;
}

4.10 递归
【打印十进制数】

1
2
3
4
5
6
7
8
9
10
void printd(int n)
{
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    if (n / 10)
        printd(n / 10);
    putchar(n % 10 + '0');
}

调用 printd(123)时,第一次调用 printd 的参数 n=123。它把 12 传递给printd 的第二次调用,后者又把 1 传递结 printd 的第三次调用。第三次调用 printd 时,首先将打印 1,然后再返回到第二次调用。从第三次调用返回后的第二次调用同样也将先打印2,然后再返回到第一次调用。返回到第一次调用时将打 3,随之结束函数的执行。

【快速排序】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void swap(int v[], int i, int j)
{
    int t;
 
    t = v[i];  v[i] = v[j]; v[j] = t;
}
 
 
void qsort(int v[], int left, int right)
{
    int i, last;
 
    if (left >= right) /* fewer than two elements */
        return;
 
    /* move partition elem to v[0]*/
    swap(v, left, (left + right)/2); 
    last = left;
 
    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);
}

抱歉!评论已关闭.