C#.net實驗二-計算器實驗

一. 實驗要求

1、參照Windows提供的計算器工具,設計一個與之類似的程序;另外可參考老師給出的計算器Demo程序。

2、基本要求:實現“普通運算”功能,支持連續運算,如連續輸入“2+3×5”後點擊“等號”按鈕進行運算其結果爲25。

3、附加要求:

A. 支持“科學運算”功能,即輸入表達式時遵循運算符號的優先原則,連續輸入“2+3×5”後點擊“等號”按鈕進行運算其結果爲17。

B. 支持數字鍵盤(小鍵盤)輸入功能(焦點不在文本框內時也支持鍵盤輸入)。

 

二. 設計思路

1、首先,設計出計算器的主要界面和主要按鈕。爲了達到美觀的效果,本次實驗重寫了Button類,將按鈕的輪廓由方形改爲圓形,並加進了陰影效果。

核心代碼:

publicclass myButtonObject : UserControl
{
protectedoverride void OnPaint(PaintEventArgs e)
    {
           Graphicsgraphics = e.Graphics;
        Pen myPen = new Pen(Color.Transparent);//將輪廓的顏色設爲透明
        graphics.DrawEllipse(myPen, 0,0,this.Width,this.Height);
                                                  //輪廓的高度和寬度設爲對象的高度和寬度
myPen.Dispose();
    }
}

2、接着,在解決方案中,按照要求增加“ClassLibrary”文件夾,並在內新增類CalculateClass,裏面包含了兩個方法:計算普通運算的SimpleCalc和科學計算ComplexCalc。實際上,這個方法運算過程都是類似的。接受來自主程序的計算式後,科學計算拆分數字和字符,將數字和符號加入到棧中,而簡單計算拆分後,就直接放入到隊列中。科學計算計算前要判斷符號的優先級,而簡單計算只需根據隊列的出隊順序進行計算即可。

核心代碼:

publicdouble ComplexCalc(string stringBuilder)//科學計算的方法
{
inti = 0, j = 0;
Stack<double>numberStack = new Stack<double>();//存儲數字的棧
Stack<char>oprStack = new Stack<char>();//存儲運算符號的棧
 
for(; i < stringBuilder.Length; i++)//遍歷計算式
{
charc = stringBuilder[i];
    if (c >= '0' && c <= '9')
    {
     j = 10 * j + Convert.ToInt32(c) - 48;
    }
    else//碰到符號,先將前一個數字壓入計算數字棧中
{
               numberStack.Push(j);
               j= 0;
                if(oprStack.Count > 0)
            {
                   charc0 = oprStack.Pop();
//判斷棧的符號是否爲乘、除號,如果是的話,則先計算
if(c0 == '*')
                {
                       double jj = numberStack.Pop() * numberStack.Pop();
                    numberStack.Push(jj);
                }
                else if (c0 == '/')
                {
                       double jj = numberStack.Pop();
                    jj = numberStack.Pop() /jj;
                    numberStack.Push(jj);
}
else
{
oprStack.Push(c0);
}
}
oprStack.Push(c);//將當前符號壓入棧中
}
}
numberStack.Push(j);//將最後一個數字壓入棧中。
 
if(oprStack.Count > 0)//判斷最後一個運算符是否爲乘除號,如果是則先計算
{
charc3 = oprStack.Peek();
if(c3 == '*' || c3 == '/')
{
doublei0 = numberStack.Pop();
doublei2 = numberStack.Pop();
c3= oprStack.Pop();
if(c3 == '*')
{
numberStack.Push(i0* i2);
}
else
{
                   numberStack.Push(i2/ i0);
}
}
}
//將棧化成列表,方便正向計算剩下的加減法
List<double>numberList = numberStack.ToList<double>();
List<char>oprList = oprStack.ToList<char>();
doubleresult = numberList[oprStack.Count];
 
for(int i0 = oprStack.Count - 1; i0 >= 0; i0--)
    {//與壓棧方向相反,正向計算剩下的加減法
           switch(oprList[i0])
           {
               case'+':
                     result+= numberList[i0];
                   break;
            case '-':
                   result-= numberList[i0];
                    break;
             default:
                return -1;//如果符號列表中還存在乘除號則返回錯誤。
         }
    }
 
returnresult;
}
 
publicdouble SimpleCalc(string calcString)//普通計算,從左往右計算
{
Queue<char>oprQueue = new Queue<char>();//符號隊列
Queue<double>numberQueue = new Queue<double>();//數字隊列
inti = 0, j = 0;
charc;
 
for(; i < calcString.Length; i++)//遍歷計算式分別將數字和符號加入隊列中
{
    c = calcString[i];
    if (c >= '0' && c <= '9')
    {
         j = 10 * j + Convert.ToInt32(c) - 48;
    }
         else
{
numberQueue.Enqueue(j);
 j = 0;
oprQueue.Enqueue(c);
}
 }
numberQueue.Enqueue(j);
 
doubleresult = numberQueue.Dequeue();
 
while(oprQueue.Count > 0)//計算得數
{
switch(oprQueue.Dequeue())
{
               case'+':
                   result+= numberQueue.Dequeue();
                   break;
                case'-':
                   result-= numberQueue.Dequeue();
                break;
            case '*':
                result *=numberQueue.Dequeue();
                break;
            case '/':
                result /=numberQueue.Dequeue();
                break;
            default:
                return -1;//遇到其他符號則返回錯誤
                break;
         }
     }
 
     returnresult;//返回正確結果
}


3、根據題目要求,實現在鍵盤上按下相關鍵或鼠標點擊按鈕時會出現相關數字或運算符號。

核心代碼:

//判斷鼠標點擊的鍵
privatevoid Keys_Click(object sender, EventArgs e)
       {
            myButtonObject myButton =(myButtonObject)sender;
            string opr;
            switch (myButton.Name.ToString())
            {
                case "KeyAdd":
                    opr = "+";
                    break;
         case "KeyMinus":
                        opr = "-";
                    break;
         case "KeyMutiply":
                    opr = "*";
                    break;
           case "KeyDivision":
             opr = "/";
                    break;
                default:
                    opr =myButton.Name.Substring(3);
                    break;
            }
            AddToList(opr);
        }
//將判斷鍵盤輸入的鍵
privatevoid Calc_KeyPress(object sender, KeyPressEventArgs e)
{
if(e.KeyChar >= '0' && e.KeyChar <= '9')//數字鍵
{
             AddToList(e.KeyChar.ToString());
}
elseif (e.KeyChar == '+' || e.KeyChar == '-' || e.KeyChar == '*' || e.KeyChar =='/')//符號鍵
{
AddToList(e.KeyChar.ToString());
}
elseif (e.KeyChar == (char)Keys.Back)//退格鍵,關聯退格功能
  {
             BackSpaceButton_Click(sender,e);
  }
  else if (e.KeyChar == (char)Keys.Enter)//關聯等於效果
  {
             KeyEqual_Click(sender,e);
  }
  else if(e.KeyChar == (char)Keys.Escape)//關聯清空功能
{
ClearButton_Click(sender,e);
}
}

4、由於本次界面,採用無邊框的界面。爲了讓窗體能夠移動,爲窗體增加了3個事件。

核心代碼:

privatevoid Calc_MouseDown(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
mouseOff= new Point(-e.X, -e.Y);
leftFlag= true;
}
}//如果用鼠標的左鍵點擊了界面,則做好移動標記
privatevoid Calc_MouseMove(object sender, MouseEventArgs e)
{
if(leftFlag)
{
PointmouseSet = Control.MousePosition;
mouseSet.Offset(mouseOff.X,mouseOff.Y);
Location= mouseSet;
}
        }//將整個窗體移動到鼠標移動到的位置
privatevoid Calc_MouseUp(object sender, MouseEventArgs e)
{
if(leftFlag)
{
leftFlag= false;
}
}//將取消移動的標記 

三. 程序運行效果圖


1、主界面,默認是簡單計算模式,見圖1。

示例圖1
2、簡單模式下計算2+2×5,見圖2。

示例圖2
3、科學計算模式下計算2+3×5,見圖3。

示例圖3

四. 實驗總結

這是我第一次設計Windows界面風格的程序。通過實驗,我終於發現,原來界面的設計原來是這麼難的。設計這個程序,中間有太多的折中和不情願,但是最後還是由於技術的原因,不得不放棄。相對於Web的界面設計,Windows風格窗體的設計,的確難很多,還有很多需要學習的地方。接下來學習C#的時間,我會着重於學習這些地方,力求設計出一個“擺得上臺面”的界面。

另外一方面,通過這次的實驗,也讓我重溫了大二時學習的數據結構隊列和棧的知識,還好,數據結構的知識沒有忘掉太多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章