用C#风格写C++程序(探索C#对象模型)
写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()); } } }}下面是用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;elsereturn false;}public: 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是数字,故初始一定是1while (IsOperand(str[i])){i++;length++;}string doubleString = str.substr(startIndex, length);// operand = atof(&str[i - 1]);//把从c开头的数转化成doublechar **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());ConsoleApplicationCal::Program objForm;return 0;}可以看到,上面的C++程序主体就是在设计一个类,而C#将这种特点发挥到了极致,C#程序是从Main()开始执行的,完全在类中进行一切。
另外,上面的C++程序开头的全局变量初始化之所以不能定义在类里面,是因为这是在设计一个类!不能在类中直接对数据成员初始化,只有静态常量整型数据成员才可以在类中初始化。