幻想森林

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2372|回复: 7

[通用编程] 栈的一个例子

[复制链接]

313

主题

1574

帖子

1万

积分

⑧专业

*永恒国度*

积分
14145
QQ
发表于 2007-9-8 22:26:22 | 显示全部楼层 |阅读模式
求一表达式的值: 先将算术表达式转换成后缀表达式,然后对后缀表达式求值
     以字符形式输入,存放在字符型数组str中,后缀表达式存放在字符型数组exp中,将算术表达式转换成后缀表达式过程中用字符型数组stack作为栈.操作如下:
1.若ch 为数字,后后续所有数字依次存入数组exp,并以字符 #  标志数字结束
2.若ch为左括号 (   将特号插入栈 stack
3.若ch 为右括号 )  将栈stack中左括号 以前的字符依次删除并存入数组exp中,后将左括号 (  删除
4.若ch 为+,- ,将当前栈stack 中左括号以前的所有字符(运算符)依次删除并存入数组exp中,然后将ch
    插入栈stack中
5.若ch 为 *,  /  将当前栈stack中的栈顶端连续的 * , /   删除并依次存入数组exp中,然后ch插入栈stack   
   中,
6.若ch为 #  将栈stack的所有运算符依次删除并存入数组exp中,再将ch 存入数组exp中,最后在exp
    得出表达式后缀表示.
  1. #include<stdio.h>
  2. #define MAX 100
  3. char exp[MAX];
  4. void trans()            // 将算术表达式转换成后缀表达式
  5. {
  6.     char str[MAX];      // 存储原算术表达式
  7.     char stack[MAX];    // 作栈使用
  8.     char ch;                                                 [color=#FF0000]问题一:为什么下标以一为开始呢?[/color]    int sum,i,j,t,top=0;  // t 为 exp的下标,top 作stack的下标,i作str的下标
  9.     printf("**********************8**************************************\n");
  10.     printf("*输入一个求值的表达式,以#结束。只能包含+-*/运算符和正整数*\n");
  11.     printf("**************************************************************\n");
  12.     printf("算术表达式:");
  13.     i=0;
  14.     do                          // 获取用户输入的表达式
  15.     {
  16.         i++;
  17.         scanf("%c",&str[i]);
  18.     }while(str[i]!='#' && i!=MAX);
  19.     sum=i;              // 记录输入表达式总的字符数
  20.     t=1;i=1;
  21.     ch=str[i];i++;
  22.     while(ch!='#')
  23.     {
  24.         switch(ch)
  25.         {
  26.         case '(':             // 判定为左括号
  27.             top++;stack[top]=ch;break;
  28.         case ')':              // 判定为右括号
  29.             while(stack[top]!='(')
  30.             {
  31.                 exp[t]=stack[top];top--;t++;
  32.             }
  33.             top--;
  34.             break;          [color=#FF0000]问题二:这里开始,下面的top都是top++,为什么呢?[/color]
  35.         case '+':                 // 判定为加减号
  36.         case '-':
  37.             while(top!=0 && stack[top]!='(')
  38.             {
  39.                 exp[t]=stack[top];top--;t++;
  40.             }
  41.             top++;stack[top]=ch;
  42.             break;
  43.         case '*':                // 判定为乘除号
  44.         case '/':
  45.             while(stack[top]=='*' || stack[top]=='/')
  46.             {
  47.                 exp[t]=stack[top];top--;t++;
  48.             }
  49.             top++;stack[top]=ch;
  50.             break;
  51.         case ' ':break;
  52.         default:while(ch>='0' && ch<='9')    // 判定为数字
  53.                 {
  54.                     exp[t]=ch;t++;
  55.                     ch=str[i];i++;
  56.                 }
  57.             i--;
  58.             exp[t]='#';t++;
  59.         }
  60.         ch=str[i];i++;
  61.     }
  62.     while(top!=0)
  63.     {
  64.         exp[t]=stack[top];t++;top--;
  65.     }
  66.     exp[t]='#';
  67.     printf("\n\t原来表达式:");
  68.     for(j=1;j<sum;j++) printf("%c",str[j]);
  69.     printf("\n\t后缀表达式:",exp);
  70.     for(j=1;j<t;j++) printf("%c",exp[j]);
  71. }
  72. void compvalue()        // 计算后缀表达式的值
  73. {
  74.     float stack[MAX],d;   // 作为栈使用
  75.     char ch;
  76.     int t=1,top=0;       // t作为exp的下标,top作为stack的下标
  77.   ch=exp[t];t++;
  78.     while(ch!='#')          [color=#FF0000]问题三:这里是以数组exp所以经过数字就会有#为什么可以历遍整个表达式呢?[/color]    {
  79.         switch(ch)
  80.         {
  81.         case '+':stack[top-1]=stack[top-1]+stack[top];
  82.             top--;break;
  83.         case '-':stack[top-1]=stack[top-1]-stack[top];
  84.             top--;break;
  85.         case '*':stack[top-1]=stack[top-1]*stack[top];
  86.             top--;break;
  87.         case '/':
  88.             if(stack[top]!=0)
  89.                 stack[top-1]=stack[top-1]/stack[top];
  90.             else
  91.             {
  92.                 printf("\n\t除零错误!\n");
  93.                 exit(0);
  94.             }
  95.             top--;break;
  96.         default:d=0;
  97.             while(ch>='0' && ch<='9')    // 判定为数字字符
  98.             {
  99. [color=#FF0000]  问题四:这里的d置0这样的表达式好像没啥意义吧?[/color]        
  100.                                                                     d=10*d+ch-'0';           // 将数字字符转换成对应数值
  101.                 ch=exp[t];t++;
  102.             }
  103.             top++;
  104.             stack[top]=d;
  105.         }
  106.         ch=exp[t];t++;
  107.     }
  108.     printf("\n\t计算结果:%g\n",stack[top]);
  109. }
  110. void main()
  111. {
  112.     trans();
  113.     compvalue();
  114. }
  115. 输入表达式(56-20)/(4+2)#
  116. 原表达式:(56-20)/(4+2)
  117. 后缀表达式:56#20#-4#2#+/
  118. 结果:6
复制代码
总的来说对这例子整个运行过程都不太理解,请指点一下吧[s:6][s:6]
[img][/img] http://shop33698673.taobao.com被别人嫉妒,证明你优秀,嫉妒别人说明你无能
回复

使用道具 举报

19

主题

842

帖子

1万

积分

⑧专业

絕望青年,一起增高吧

积分
13676
发表于 2007-9-8 22:58:17 | 显示全部楼层
某沒仔細看,多見諒[s:78]
問題一:t不明。。。
問題二:top表示著stack 最後加入的index,每次++當然表代著最後
問題三: #是用作標記用,有點兒類似split中的標記,程式的協定問題
問題四:ch-'0' -> 因為ch是用ASCII格式記下,'0' 實際上不是int 的0,而是'0'這個字符的ASCII Code

為著彼岸,便要與之妥協 但為著彼岸,更不能與之妥協

回复 支持 反对

使用道具 举报

313

主题

1574

帖子

1万

积分

⑧专业

*永恒国度*

积分
14145
QQ
 楼主| 发表于 2007-9-8 23:21:55 | 显示全部楼层
问题一:它以 t 和top 作为下标,但开始时却以i=1 这样来赋值,就是将下标以一开始不是以0开始为什么 要   这样做?
问题三:while(ch!='#')  但表达式:56#20#-4#2#+/   56后就已经是#了,那不是到56就结束了吗?
问题四:ACII偶知道,但 d=10*d+ch-'0';有什么意义呢?d初始为0,这样的话还不与这样写 ,d=ch-'0'
PS:输入数字过程中比如56 在数组中是不是以5和6分开了存储呢?
[img][/img] http://shop33698673.taobao.com被别人嫉妒,证明你优秀,嫉妒别人说明你无能
回复 支持 反对

使用道具 举报

20

主题

197

帖子

2641

积分

⑥精研

积分
2641
QQ
发表于 2007-9-9 05:16:03 | 显示全部楼层
Q1:个人选择问题....你也可以选择从0开始...只是思考起来总要想着下标-1不太舒服
Q3:default:while(ch>='0' && ch<='9')    // 判定为数字
                {
                    d=10*d+ch-'0';                    
                    exp[t]=ch;t++;
                    ch=str;i++;
                }
            i--;
            exp[t]='#';t++;
        }
这部份处理了数字分隔问题
Q4:有些编译器在没有给变量值的情况下会使用随机数...只是给个既定的值...一般不会有什么影响
QPS:看Q3的答就应当了解了公式d=d*10+ch-'0'是用于组合数字的...所以可以看出是按字符存储的...这种说法只是逆推导...一般来说字符串是由字符组成的...字符串就类似一个字符型数组...嗯..以上
签名要少于60,SO,i haven't upload my pic
回复 支持 反对

使用道具 举报

136

主题

1751

帖子

548

积分

版主

Rank: 7Rank: 7Rank: 7

积分
548
发表于 2007-9-9 10:08:23 | 显示全部楼层
好像在c中,char*和char[]是可以隐式转换的.
え~え~お!!!
回复 支持 反对

使用道具 举报

313

主题

1574

帖子

1万

积分

⑧专业

*永恒国度*

积分
14145
QQ
 楼主| 发表于 2007-9-9 10:47:06 | 显示全部楼层
问题三:while(ch!='#')  但表达式:56#20#-4#2#+/  56后就已经是#了,那不是到56就结束了吗?
                    [s:5] 这问题好像还没答到点上吧?
还有这里:d=10*d+ch-'0';  跟 d=ch-'0'    没看出有什么不同.... [s:6]
[img][/img] http://shop33698673.taobao.com被别人嫉妒,证明你优秀,嫉妒别人说明你无能
回复 支持 反对

使用道具 举报

19

主题

842

帖子

1万

积分

⑧专业

絕望青年,一起增高吧

积分
13676
发表于 2007-9-9 11:13:58 | 显示全部楼层
d=10*d+ch-'0'
如果只運行一次,d=10*d+ch-'0' 和d=ch-'0'是沒分別
但如果ch 是字串的一部份
比如說str="123"; ch -> for loop中的運行變數
那d=10*d+ch-'0'會被運行3次
第一次,d的內容為 10*0+'1'-'0' = 1
第2次,d的內容為 10*1+'2'-'0' = 10+2=12
第3次,d的內容為 10*12+'3'-'0' = 120+3=123

LZ打入56也不會希望變成int時只餘下5或6吧

為著彼岸,便要與之妥協 但為著彼岸,更不能與之妥協

回复 支持 反对

使用道具 举报

19

主题

842

帖子

1万

积分

⑧专业

絕望青年,一起增高吧

积分
13676
发表于 2007-9-9 11:26:28 | 显示全部楼层
Q3
再看為何
  1. while(ch!='#')
  2. switch...{
  3. .....
  4.         default:d=0;
  5.             while(ch>='0' && ch<='9')    // 判定为数字字符
  6.             {
  7.   问题四:这里的d置0这样的表达式好像没啥意义吧?      
  8.                                                                     d=10*d+ch-'0';          // 将数字字符转换成对应数值
  9.                 ch=exp[t];t++;
  10.             }
  11.             top++;
  12.             stack[top]=d;
  13.         }
  14.         ch=exp[t];t++;
  15. ....
  16. }
复制代码
能走遍整個 后缀表达式:56#20#-4#2#+/

先指明
  1.             stack[top]=d;
  2.         }
  3.         ch=exp[t];t++;
复制代码
是錯的。。正確代碼為
  1.             stack[top]=d;
  2.         ch=exp[t];t++;
复制代码
理所當然地,如果ch是'0'->'9'的話,程序會選行 default: 的路段
在while(ch>='0' && ch<='9'),就是指當ch依然是數字是,會不停運行這個loop
那何時會結束?就是ch不是'0'->'9',那只可以是'#'
而這是的t剛好加了1(while loop 中最後一次運行ch=exp[t];t++;)
那嘛ch='#', exp[t]='0'->'9' or '+-*/'
再運行一次ch=exp[t];t++;
ch變成上面的exp[t] 也就是'0'->'9' or '+-*/',所以程序能一直行下去

為著彼岸,便要與之妥協 但為著彼岸,更不能與之妥協

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|幻想森林

GMT+8, 2024-5-2 21:18 , Processed in 0.028214 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表