Chinaunix首页 | 论坛 | 博客
  • 博客访问: 85008
  • 博文数量: 34
  • 博客积分: 1640
  • 博客等级: 上尉
  • 技术积分: 395
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-17 14:37
文章分类
文章存档

2008年(34)

我的朋友
最近访客

分类: C/C++

2008-04-25 21:49:48

1. 第一节的程序,讲解了Functions的基本结构:
思路:
while (there's another line)
    if (the line contains the pattern)
        print it

代码:
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int max);
int strindex(char source[], char searchfor[]);

char patterns[] = "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进行比较。区别主要在于控制结构的使用。在第一章用的是for语句。这里使用

// 的是while语句

/* 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 (s == '\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;
}

第二节:functions returning non-integers。为了证明对于函数来说,不仅仅可以返回int或是void,还可以返回其他类型的值。

#include <ctype.h>

/* atof: convert string to double */
double atof(char s[])
{
    double val, power;
    int i, sign;

    /* skip white space */
    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;
}

#include <stdio.h>
#define MAXLINE 100
/* rudimentary calculator */
int main()
{
    double sum, atof(char []); //注意这里对函数的声明方式

    char line[MAXLINE];
    int getline(char line[], int max); // 声明getline函数

    sum = 0;
    while (getline(line, MAXLINE) > 0)
        printf("\t%g\n", sum += atof(line));
    return 0;
}


第三节 外部变量:其通常用于在不同函数之间传递参数。
本节的程序是一个计算器,其基本思路为:
while (next operator or operand is not end-of-file indicator)
    if (number)
        put it
    else if (operator)
        pop operands
        do operation
        push result
    else if (newline)
        pop and print top of stack
    else
        error
在这个程序中,最重要的应该是决定如何来设计stack.很显然,stack应该在pop和push操作之间共享,但是main函数不能直接存取stack。设计决策为:将pop,push操作与main放在不同的文件中,同时stack与push和pop操作放在一起。这样的话,stack为push和pop共有,但不被main存取
#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];

    // 看来getop的实现很关键

    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()
{
    if (sp > 0)
        return val[--sp];
    else {
        printf("error: stack empty\n");
        return 0.0;
    }
}

#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[i] = '\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

// 另外两个external变量的实例。

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;
}

第四节和第五节讲解的是Scope rules和header files。也就是如何将上面的几个文件进行分配,以存放到不同的文件中。一种比较常见的方法是将所有外部可用的函数都声明在一个hearder files中,然后再在其他的.c文件中进行实现。

第六节 将static variables。当将static用于external variables时,可以限制该external variables只能在定义该变量的文件中使用。在上面的代码中,其实我们就可以将buf和bufp声明为static变量,如
static char buf[BUFSIZE];
static int bufp = 0;
另外static同样可以运用于函数以及internal variables。但是含义有所变化。

第十一节 预处理。分为三个部分:文件的包含,宏替换和条件编译。对于文件包含也就是#include命令。对于宏替换,是用#define命令。对于宏替换的几个例子:
#define forever for(;;) /* infinite loop */
#define max(A, B) ((A) > (B) ? (A) : (B))
#define dprint(expr) printf(#expr " = %g\n", expr) //#的作用
#define paste(front, back) front ## back
//##的作用, paste(name, 1) == name1
条件编译包括#if, #endif, #elif和#else等。例子为:

#if !defined(HDR)
#define HDR
/* contents of hdr.h go here */
#endif

另外的一个例子为:
// 这段代码根据系统的类型来包括不同的头文件
#if SYSTEM == SYSV
    #define HDR "sysv.h"
#elif SYSTEM == BSD
    #define HDR "bsd.h"
#elif SYSTEM == MSDOS
    #define HDR "msdos.h"
#else
    #define HDR "default.h"
#endif
#include HDR

第三个例子:#ifndef的应用, 常常用于头文件中

#ifndef HDR
#define HDR
/* contents of hdr.h go here */
#endif






阅读(598) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~