用C#风格写C++程序(探索C#对象模型)
用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;
- else
- return 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是数字,故初始一定是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());
- ConsoleApplicationCal::Program objForm;
- return 0;
- }
可以看到,上面的C++程序主体就是在设计一个类,而C#将这种特点发挥到了极致,C#程序是从Main()开始执行的,完全在类中进行一切。
另外,上面的C++程序开头的全局变量初始化之所以不能定义在类里面,是因为这是在设计一个类!不能在类中直接对数据成员初始化,只有静态常量整型数据成员才可以在类中初始化。
评论暂时关闭