寫C#程序就是在設計一個類!
先看一個C#程序(表達式求值):
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplicationCal
{
class Program
{
private static char[,] Precede_Matrix = new char[7, 7]
{
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'<', '<', '<', '<', '<', '=', '0',},
{'>', '>', '>', '>', '0', '>', '>',},
{'<', '<', '<', '<', '<', '0', '=',}
};
public static char Precede(char a, char b)
{
int i = 0;
int j = 0;
switch (a)
{
case '+': i = 0; break;
case '-': i = 1; break;
case '*': i = 2; break;
case '/': i = 3; break;
case '(': i = 4; break;
case ')': i = 5; break;
case '#': i = 6; break;
default: break;
}
switch (b)
{
case '+': j = 0; break;
case '-': j = 1; break;
case '*': j = 2; break;
case '/': j = 3; break;
case '(': j = 4; break;
case ')': j = 5; break;
case '#': j = 6; break;
default: break;
}
return (Precede_Matrix[i, j]);
}
public static double Operate(double a, char oper, double b)
{
switch (oper)
{
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: return -1;
}
}
public static bool IsOperand(char c)
{
if (('0' <= c && c <= '9') || c == '.') // c是數字或小數點
return true;
else
return false;
}
static void Main(string[] args)
{
string str;
while ((str = Console.ReadLine()) != null)
{
str += "#"; // 最後是#(結束標志)
double a;
double b;
char x;
char theta;
Stack<char> OPTR = new Stack<char>();
OPTR.Push('#');
Stack<double> OPND = new Stack<double>();
int i = 0;
char c = str[i++];
double operand = 0;
while (!(c == '#' && OPTR.Peek() == '#'))
{
if (IsOperand(c)) // c是數字或小數點(這裡一定是數字),小數點已在下面轉換掉了
{
int startIndex = i - 1;
int length = 1; // c是數字,故初始一定是1
while (IsOperand(str[i]))
{
i++;
length++;
}
string doubleString = str.Substring(startIndex, length);
// operand = atof(&str[i - 1]); // 把從c開頭的數轉化成double
OPND.Push(double.Parse(doubleString));
c = str[i++];
}
else // c is operator or delimiter
{
switch (Precede(OPTR.Peek(), c))
{
case '<':
OPTR.Push(c);
c = str[i++];
break;
case '=':
x = OPTR.Pop();
c = str[i++];
break;
case '>':
theta = OPTR.Pop();
b = OPND.Pop();
a = OPND.Pop();
OPND.Push(Operate(a, theta, b));
break;
default:
break;
}
}
}
// OPTR棧的棧頂元素和當前讀入的字符均為“#”
// 即“#”=“#”時整個表達式求值完畢
Console.WriteLine(OPND.Peek());
}
}
}
}
2、下面是用C++改寫的:
[cpp]
#include <iostream>
#include <stack>
#include <string>
using namespace std;
// 因為只有靜態常量整型數據成員才可以直接(也必須)在類中初始化,
// 故下面這個全局數組定義在類(命名空間)的外面,待解決
char Precede_Matrix[7][7] =
{
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '<', '<', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'>', '>', '>', '>', '<', '>', '>',},
{'<', '<', '<', '<', '<', '=', '0',},
{'>', '>', '>', '>', '0', '>', '>',},
{'<', '<', '<', '<', '<', '0', '=',}
};
namespace ConsoleApplicationCal
{
class Program
{
// 寫這個構造函數是因為想在main函數中創建Program對象時
// 就自動調用Main()了,符合C#的運行規則
public: Program::Program(void)
{
Main();
}
public: static char Precede(char a, char b)
{
int i = 0;
int j = 0;
switch (a)
{
case '+': i = 0; break;
case '-': i = 1; break;
case '*': i = 2; break;
case '/': i = 3; break;
case '(': i = 4; break;
case ')': i = 5; break;
case '#': i = 6; break;
default: break;
}
switch (b)
{
case '+': j = 0; break;
case '-': j = 1; break;
case '*': j = 2; break;
case '/': j = 3; break;
case '(': j = 4; break;
case ')': j = 5; break;
case '#': j = 6; break;
default: break;
}
return (Precede_Matrix[i][j]);
}
public: static double Operate(double a, char oper, double b)
{
switch (oper)
{
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
default: return -1;
}
}
public: static bool IsOperand(char c)
{
if (('0' <= c && c <= '9') || c == '.') // c是數字或小數點
return true;
else
return false;
}
public: static void Main(void)
{
string str;
while (cin >> str)
{
str += "#"; // 最後是#(結束標志)
double a;
double b;
char x;
char theta;
stack<char> OPTR;
OPTR.push('#');
stack<double> OPND;
int i = 0;
char c = str[i++];
double operand = 0;
while (!(c == '#' && OPTR.top() == '#'))
{
if (IsOperand(c)) // c是數字或小數點(這裡一定是數字),小數點已在下面轉換掉了
{
int startIndex = i - 1;
int length = 1; // c是數字,故初始一定是1
while (IsOperand(str[i]))
{
i++;
length++;
}
string doubleString = str.substr(startIndex, length);
// operand = atof(&str[i - 1]); // 把從c開頭的數轉化成double
char **endPtr = NULL; // 沒什麼用,只是為了strtod的傳參
OPND.push(strtod(doubleString.c_str(), endPtr));
c = str[i++];
}
else // c is operator or delimiter
{
switch (Precede(OPTR.top(), c))
{
case '<':
OPTR.push(c);
c = str[i++];
break;
case '=':
x = OPTR.top();
OPTR.pop();
c = str[i++];
break;
case '>':
theta = OPTR.top();
OPTR.pop();
b = OPND.top();
OPND.pop();
a = OPND.top();
OPND.pop();
OPND.push(Operate(a, theta, b));
break;
default:
break;
}
}
}
// OPTR棧的棧頂元素和當前讀入的字符均為“#”
// 即“#”=“#”時整個表達式求值完畢
cout << OPND.top() << endl;
}
}
};
}
int main(int argc, char **argv)
{
// 仿照Winform中的Main函數new一個窗體對象:Application.Run(new Form1());
// 都在堆上分配空間
delete(new ConsoleApplicationCal::Program); // 為了對比,這裡就省略了檢查分配空間失敗的情況
return 0;
}
可以看到,上面的C++程序主體就是在設計一個類,而C#將這種特點發揮到了極致,C#程序是從Main()開始執行的,完全在類中進行一切。
另外,上面的C++程序開頭的全局變量初始化之所以不能定義在類裡面,是因為這是在設計一個類!往往不能在類中直接對數據成員初始化,只有靜態常量整型數據成員才可以直接(也必須)在類中初始化。
最後,發現C#中的構造函數挺妙的,東西多。