地址:http://blog.csdn.net/justme0/article/details/7994133
写C#程序就是在设计一个类!
先看一个C#程序(表达式求值):
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++改写的:
#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#中的构造函数挺妙的,东西多。