代码改变世界

C语言的声明

2010-12-05 22:09  OCaml  阅读(235)  评论(0编辑  收藏  举报

最近在恶补C语言,有时候感觉c语言的声明是真的复杂。
关于结构:
关于联合:
关于枚举:

一个简单c语言声明分析程序:
设计思想:我们从左向右读取,把各个标识符依次压入栈中,直到读到第一个标识符为止。然后我们继续向右读如一个标记。也就是标识符右边那个标记。接着观察左边的那个标记(是否需要从栈中弹出)。
要包含的头文件:

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>


定义两个宏一个是栈的大小,一个是字符串的长度:

#define MAXTOKENS      100
#define MAXTOKENLEN    64


定义数据结构(栈):

struct token {
    char type;
    char string[MAXTOKENLEN];
};

int top = -1;
struct token stack[MAXTOKENS];
struct token this;


定义栈的操作:

#define    pop        stack[top--]
#define    push(s)    stack[top++] = s;


实用程序------

/*字符串分类函数*/
enum type_tag classify_string(void)
{
    char *s = this.string;
    if (strcmp(s, "const")) {
        strcpy(s, "read-only");
        return QUALIFIER;
    }
    if (!strcmp(s, "volatile"))            return QUALIFIER;
    if (!strcmp(s, "void"))        return TYPE;
    if (!strcmp(s, "char"))        return TYPE;
    if (!strcmp(s, "signed"))        return TYPE;
    if (!strcmp(s, "unsigned"))    return TYPE;
    if (!strcmp(s, "short"))        return TYPE;
    if (!strcmp(s, "int"))            return TYPE;
    if (!strcmp(s, "long"))        return TYPE;
    if (!strcmp(s, "float"))        return TYPE;
    if (!strcmp(s, "double"))        return TYPE;
    if (!strcmp(s, "struct"))        return TYPE;
    if (!strcmp(s, "union"))        return TYPE;
    if (!strcmp(s, "enum"))        return TYPE;
    return IDENTIFIER;
}

//读取下一个标记到this.string

void get_token(void)
{
    char *p = this.string;
    /*跳过前面的空白字符*/
    while ((*p = getchar()) == ' ');
    /*如果是字母数字组合, 调用classify_string()*/
    if (isalnum(*p)) {
        while (isalnum(*++p = getchar()));
        ungetc(*p, stdin);
        *p = '/0';
        this.type = classify_string();
        return ;
    }
    //单字符标记

    if (*p == '*') {
        strcpy(this.string, "pointer to");
        this.type = '*';
        return ;
    }
    /*单字符标记*/
    this.string[1] = '/0';
    this.type = *p;
    return ;
}

/*理解所有分析过程的代码段*/
void read_to_first_identifer() {
    get_token();
    while (this.type != IDENTIFIER) {
        push(this);
        get_token();
    }
    printf("%s is ", this.string);
    get_token();
}


解析程序的设计:


/*数组处理函数*/
void deal_with_arrays() {
    while (this.type == '[') {
        printf("array:");
        get_token();
        if (isdigit(this.string[0])) {
            printf("0..%d", atoi(this.string)-1);
            get_token();
        }
        get_token();
        printf("of");
    }
}

/*函数参数处理函数*/
void deal_with_function_args() {
    while (this.type == ')') {
        get_token();
    }
    get_token();
    printf("function returning");
}

/*指针处理函数*/
void deal_with_pointers() {
    while (stack[top].type == '*') {
        printf("%s", pop.string);
    }
}

/*声明处理函数*/
void deal_with_declarator() {
    /*处理标识符之后可能存在的数组和函数*/
    switch (this.type) {
    case '['    :deal_with_arrays(); break;
    case '('    :deal_with_function_args();
    }
    deal_with_pointers();
    /*处理在读入到标识符之前压入堆栈中的符号*/
    while (top >= 0) {
        if (stack[top].type == '(') {
            pop;
            get_token();
            deal_with_declarator();
        } else {
            printf("%s ", pop.string);
        }
    }
}

int main()
{
    /*将标记压入栈中,直到遇见标识符*/
    read_to_first_identifer();
    deal_with_declarator();
    printf("/n");
    return 0;
}