码迷,mamicode.com
首页 > 其他好文 > 详细

C 栈实例

时间:2015-09-15 21:50:56      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:

就近匹配:
应用1:就近匹配 
几乎所有的编译器都具有检测括号是否匹配的能力
如何实现编译器中的符号成对检测?
#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; 

算法思路
从第一个字符开始扫描
当遇见普通字符时忽略,
当遇见左符号时压入栈中
当遇见右符号时从栈中弹出栈顶符号,并进行匹配
匹配成功:继续读入下一个字符
匹配失败:立即停止,并报错
结束:
成功: 所有字符扫描完毕,且栈为空
失败:匹配失败或所有字符扫描完毕但栈非空
当需要检测成对出现但又互不相邻的事物时
可以使用栈“后进先出”的特性
栈非常适合于需要“就近匹配”的场合

计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
#include "stdio.h"
#include "stdlib.h"
#include "linkstack.h"

int isLeft(char c)
{
    int ret = 0;

    switch(c)
    {
    case <:
    case (:
    case [:
    case {:
    case \‘:
    case \":
        ret = 1;
        break;
    default:
        ret = 0;
        break;
    }

    return ret;
}

int isRight(char c)
{
    int ret = 0;

    switch(c)
    {
    case >:
    case ):
    case ]:
    case }:
    case \‘:
    case \":
        ret = 1;
        break;
    default:
        ret = 0;
        break;
    }

    return ret;
}

int match(char left, char right)
{
    int ret = 0;

    switch(left)
    {
    case <:
        ret = (right == >);
        break;
    case (:
        ret = (right == ));
        break;
    case [:
        ret = (right == ]);
        break;
    case {:
        ret = (right == });
        break;
    case \‘:
        ret = (right == \‘);
        break;
    case \":
        ret = (right == \");
        break;
    default:
        ret = 0;
        break;
    }

    return ret;
}

int scanner(const char* code)
{
    LinkStack* stack = LinkStack_Create();
    int ret = 0;
    int i = 0;

    while( code[i] != \0 )
    {
        if( isLeft(code[i]) )
        {
            LinkStack_Push(stack, (void*)(code + i)); //&code[i]
        }

        if( isRight(code[i]) )
        {
            char* c = (char*)LinkStack_Pop(stack);

            if( (c == NULL) || !match(*c, code[i]) )
            {
                printf("%c does not match!\n", code[i]);
                ret = 0;
                break;
            }
        }

        i++;
    }

    if( (LinkStack_Size(stack) == 0) && (code[i] == \0) )
    {
        printf("Succeed!\n");
        ret = 1;
    }
    else
    {
        printf("Invalid code!\n");
        ret = 0;
    }

    LinkStack_Destroy(stack); 

    return ret;
}

void main()
{
    const char* code = "#include <stdio.h> int main() { int a[4][4]; int (*p)[4]; p = a[0]; return 0; ";

    scanner(code);
    system("pause");
    return ;
}
中缀表达式和后缀表达式
应用2:中缀 后缀
计算机的本质工作就是做数学运算,那计算机可以读入字符串
“9 + (3 - 1) * 5 + 8 / 2”并计算值吗?
后缀表达式  ==?符合计算机运算
波兰科学家在20世纪50年代提出了一种将运算符放在数字后面的后缀表达式对应的,
我们习惯的数学表达式叫做中缀表达式===》符合人类思考习惯

实例:
5 + 4=> 5 4 +  
1 + 2 * 3 => 1 2 3 * +  
8 + ( 31 ) * 5 => 8 3 15 * +  
中缀表达式符合人类的阅读和思维习惯
后缀表达式符合计算机的“运算习惯”
如何将中缀表达式转换成后缀表达式?
中缀转后缀算法:
遍历中缀表达式中的数字和符号
对于数字:直接输出
对于符号:
左括号:进栈  
运算符号:与栈顶符号进行优先级比较
若栈顶符号优先级低:此符合进栈  (默认栈顶若是左括号,左括号优先级最低)
若栈顶符号优先级不低:将栈顶符号弹出并输出,之后进栈
右括号:将栈顶符号弹出并输出,直到匹配左括号
遍历结束:将栈中的所有符号弹出并输出
中缀转后缀
计算机是如何基于后缀表达式计算的?
8 3 15 * + 
遍历后缀表达式中的数字和符号
对于数字:进栈
对于符号:
从栈中弹出右操作数
从栈中弹出左操作数
根据符号进行运算
将运算结果压入栈中
遍历结束:栈中的唯一数字为计算结果
栈的神奇!    
中缀表达式是人习惯的表达方式
后缀表达式是计算机喜欢的表达方式
通过栈可以方便的将中缀形式变换为后缀形式
中缀表达式的计算过程类似程序编译运行的过程  

扩展:给你一个字符串,计算结果
“1 + 2 * (66 / (2 * 3) + 7 )”   
1
字符串解析
词法语法分析
优先级分析     
数据结构选型===》栈还是树?
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "linkstack.h"

int isNumber(char c)
{
    return (0 <= c) && (c <= 9);
}

int isOperator(char c)
{
    return (c == +) || (c == -) || (c == *) || (c == /);
}

int isLeft(char c)
{
    return (c == ();
}

int isRight(char c)
{
    return (c == ));
}

int priority(char c)
{
    int ret = 0;

    if( (c == +) || (c == -) )
    {
        ret = 1;
    }

    if( (c == *) || (c == /) )
    {
        ret = 2;
    }

    return ret;
}

void output(char c)
{
    if( c != \0 )
    {
        printf("%c", c);
    }
}

//  
void transform(const char* exp)
{
    int i = 0;
    LinkStack* stack = LinkStack_Create();

    while( exp[i] != \0 )
    {
        if( isNumber(exp[i]) )
        {
            output(exp[i]);
        }
        else if( isOperator(exp[i]) )
        {
            while( priority(exp[i]) <= priority((char)(int)LinkStack_Top(stack)) )
            {
                output((char)(int)LinkStack_Pop(stack));
            }

            LinkStack_Push(stack, (void*)(int)exp[i]);
        } 
        else if( isLeft(exp[i]) )
        {
            LinkStack_Push(stack, (void*)(int)exp[i]);
        } 
        else if( isRight(exp[i]) )
        {
            //char c = ‘\0‘;
            while( !isLeft( (char)(int)LinkStack_Top(stack) ) )
            {
                output((char)(int)LinkStack_Pop(stack));
            }

            LinkStack_Pop(stack);
        }
        else
        {
            printf("Invalid expression!");
            break;
        }

        i++;
    }

    while( (LinkStack_Size(stack) > 0) && (exp[i] == \0) )
    {
        output((char)(int)LinkStack_Pop(stack));
    }

    LinkStack_Destroy(stack);
}

int main()
{
    transform("8+(3-1)*5");

    printf("\n");
    system("pause");
    return 0;
}




#include <stdio.h>
#include "LinkStack.h"

int isNumber3(char c)
{
    return (0 <= c) && (c <= 9);
}

int isOperator3(char c)
{
    return (c == +) || (c == -) || (c == *) || (c == /);
}

int value(char c)
{
    return (c - 0);
}

int express(int left, int right, char op)
{
    int ret = 0;

    switch(op)
    {
    case +:
        ret = left + right;
        break;
    case -:
        ret = left - right;
        break;
    case *:
        ret = left * right;
        break;
    case /:
        ret = left / right;
        break;
    default:
        break;
    }

    return ret;
}

int compute(const char* exp)
{
    LinkStack* stack = LinkStack_Create();
    int ret = 0;
    int i = 0;

    while( exp[i] != \0 )
    {
        if( isNumber3(exp[i]) )
        {
            LinkStack_Push(stack, (void*)value(exp[i]));
        }
        else if( isOperator3(exp[i]) )
        {
            int right = (int)LinkStack_Pop(stack);
            int left = (int)LinkStack_Pop(stack);
            int result = express(left, right, exp[i]);

            LinkStack_Push(stack, (void*)result);
        }
        else
        {
            printf("Invalid expression!");
            break;
        }

        i++;
    }

    if( (LinkStack_Size(stack) == 1) && (exp[i] == \0) )
    {
        ret = (int)LinkStack_Pop(stack);
    } 
    else 
    {
        printf("Invalid expression!");
    }

    LinkStack_Destroy(stack);

    return ret;
}

int main()
{
    printf("8 + (3 - 1) * 5  = %d\n", compute("831-5*+"));
    system("pause");
    return 0;
}

 

C 栈实例

标签:

原文地址:http://www.cnblogs.com/yaowen/p/4811366.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!