用C#风格写C++程序(探索C#对象模型)


写C#程序就是在设计一个类

先看一个C#程序(计算一个表达式):

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5.   
  6. namespace ConsoleApplicationCal  
  7. {  
  8.     class Program  
  9.     {  
  10.         private static char[,] Precede_Matrix = new char[7, 7]  
  11.         {  
  12.             {'>''>''<''<''<''>''>',},  
  13.             {'>''>''<''<''<''>''>',},  
  14.             {'>''>''>''>''<''>''>',},  
  15.             {'>''>''>''>''<''>''>',},  
  16.             {'<''<''<''<''<''=''0',},  
  17.             {'>''>''>''>''0''>''>',},  
  18.             {'<''<''<''<''<''0''=',}  
  19.         };  
  20.   
  21.         public static char Precede(char a, char b)  
  22.         {  
  23.             int i = 0;  
  24.             int j = 0;  
  25.             switch (a)  
  26.             {  
  27.                 case '+': i = 0; break;  
  28.                 case '-': i = 1; break;  
  29.                 case '*': i = 2; break;  
  30.                 case '/': i = 3; break;  
  31.                 case '(': i = 4; break;  
  32.                 case ')': i = 5; break;  
  33.                 case '#': i = 6; break;  
  34.                 defaultbreak;  
  35.             }  
  36.             switch (b)  
  37.             {  
  38.                 case '+': j = 0; break;  
  39.                 case '-': j = 1; break;  
  40.                 case '*': j = 2; break;  
  41.                 case '/': j = 3; break;  
  42.                 case '(': j = 4; break;  
  43.                 case ')': j = 5; break;  
  44.                 case '#': j = 6; break;  
  45.                 defaultbreak;  
  46.             }  
  47.   
  48.             return (Precede_Matrix[i, j]);  
  49.         }  
  50.   
  51.         public static double Operate(double a, char oper, double b)  
  52.         {  
  53.             switch (oper)  
  54.             {  
  55.                 case '+'return a + b;  
  56.                 case '-'return a - b;  
  57.                 case '*'return a * b;  
  58.                 case '/'return a / b;  
  59.                 defaultreturn -1;  
  60.             }  
  61.         }  
  62.   
  63.         public static bool IsOperand(char c)  
  64.         {  
  65.             if (('0' <= c && c <= '9') || c == '.')   //  c是数字或小数点   
  66.                 return true;  
  67.             else  
  68.                 return false;  
  69.         }  
  70.   
  71.         static void Main(string[] args)  
  72.         {  
  73.             string str;  
  74.             while ((str = Console.ReadLine()) != null)  
  75.             {  
  76.                 str += "#";                     //  最后是#(结束标志)   
  77.   
  78.                 double a;  
  79.                 double b;  
  80.                 char x;  
  81.                 char theta;  
  82.   
  83.                 Stack<char> OPTR = new Stack<char>();  
  84.                 OPTR.Push('#');  
  85.                 Stack<double> OPND = new Stack<double>();  
  86.   
  87.                 int i = 0;  
  88.                 char c = str[i++];  
  89.                 double operand = 0;  
  90.                 while (!(c == '#' && OPTR.Peek() == '#'))  
  91.                 {  
  92.                     if (IsOperand(c))   // c是数字或小数点(这里一定是数字),小数点已在下面转换掉了   
  93.                     {  
  94.                         int startIndex = i - 1;  
  95.                         int length = 1; // c是数字,故初始一定是1   
  96.                         while (IsOperand(str[i]))  
  97.                         {  
  98.                             i++;  
  99.                             length++;  
  100.                         }  
  101.   
  102.                         string doubleString = str.Substring(startIndex, length);  
  103.                         //     operand = atof(&str[i - 1]); //  把从c开头的数转化成double   
  104.                         OPND.Push(double.Parse(doubleString));  
  105.   
  106.   
  107.                         c = str[i++];  
  108.                     }  
  109.                     else                            // c is operator or delimiter   
  110.                     {  
  111.                         switch (Precede(OPTR.Peek(), c))  
  112.                         {  
  113.   
  114.                             case '<':  
  115.                                 OPTR.Push(c);  
  116.                                 c = str[i++];  
  117.                                 break;  
  118.   
  119.                             case '=':  
  120.                                 x = OPTR.Pop();  
  121.   
  122.                                 c = str[i++];  
  123.                                 break;  
  124.   
  125.                             case '>':  
  126.                                 theta = OPTR.Pop();  
  127.                                 b = OPND.Pop();  
  128.                                 a = OPND.Pop();  
  129.                                 OPND.Push(Operate(a, theta, b));  
  130.                                 break;  
  131.   
  132.                             default:  
  133.                                 break;  
  134.                         }  
  135.                     }  
  136.                 }  
  137.                 //  OPTR栈的栈顶元素和当前读入的字符均为“#”   
  138.                 //  即“#”=“#”时整个表达式求值完毕   
  139.                 Console.WriteLine(OPND.Peek());  
  140.             }       
  141.         }  
  142.     }  
  143. }  

下面是用C++改写的:

  1. #include <iostream>   
  2. #include <stack>   
  3. #include <string>   
  4. using namespace std;  
  5.   
  6. // 因为在定义类时不能对数据成员直接初始化,   
  7. // 故下面这个全局数组定义在类(命名空间)的外面,待解决   
  8. char Precede_Matrix[7][7] =  
  9. {  
  10.     {'>''>''<''<''<''>''>',},  
  11.     {'>''>''<''<''<''>''>',},  
  12.     {'>''>''>''>''<''>''>',},  
  13.     {'>''>''>''>''<''>''>',},  
  14.     {'<''<''<''<''<''=''0',},  
  15.     {'>''>''>''>''0''>''>',},  
  16.     {'<''<''<''<''<''0''=',}  
  17. };  
  18.   
  19. namespace ConsoleApplicationCal  
  20. {  
  21.     class Program  
  22.     {  
  23.         // 写这个构造函数是因为想在main函数中创建Program对象时   
  24.         // 就自动调用Main()了,符合C#的运行规则   
  25.     public: Program::Program(void)  
  26.             {  
  27.                 Main();  
  28.             }  
  29.   
  30.     publicstatic char Precede(char a, char b)  
  31.             {  
  32.                 int i = 0;  
  33.                 int j = 0;  
  34.                 switch (a)  
  35.                 {  
  36.                 case '+': i = 0; break;  
  37.                 case '-': i = 1; break;  
  38.                 case '*': i = 2; break;  
  39.                 case '/': i = 3; break;  
  40.                 case '(': i = 4; break;  
  41.                 case ')': i = 5; break;  
  42.                 case '#': i = 6; break;  
  43.                 defaultbreak;  
  44.                 }  
  45.                 switch (b)  
  46.                 {  
  47.                 case '+': j = 0; break;  
  48.                 case '-': j = 1; break;  
  49.                 case '*': j = 2; break;  
  50.                 case '/': j = 3; break;  
  51.                 case '(': j = 4; break;  
  52.                 case ')': j = 5; break;  
  53.                 case '#': j = 6; break;  
  54.                 defaultbreak;  
  55.                 }  
  56.   
  57.                 return (Precede_Matrix[i][j]);  
  58.             }  
  59.   
  60.     publicstatic double Operate(double a, char oper, double b)  
  61.             {  
  62.                 switch (oper)  
  63.                 {  
  64.                 case '+'return a + b;  
  65.                 case '-'return a - b;  
  66.                 case '*'return a * b;  
  67.                 case '/'return a / b;  
  68.                 defaultreturn -1;  
  69.                 }  
  70.             }  
  71.   
  72.     publicstatic bool IsOperand(char c)  
  73.             {  
  74.                 if (('0' <= c && c <= '9') || c == '.')   //  c是数字或小数点   
  75.                     return true;  
  76.                 else  
  77.                     return false;  
  78.             }  
  79.   
  80.     publicvoid Main(void)  
  81.             {  
  82.                 string str;  
  83.                 while (cin >> str)  
  84.                 {  
  85.                     str += "#";                     //  最后是#(结束标志)   
  86.   
  87.                     double a;  
  88.                     double b;  
  89.                     char x;  
  90.                     char theta;  
  91.   
  92.                     stack<char> OPTR;  
  93.                     OPTR.push('#');  
  94.                     stack<double> OPND;  
  95.   
  96.                     int i = 0;  
  97.                     char c = str[i++];  
  98.                     double operand = 0;  
  99.                     while (!(c == '#' && OPTR.top() == '#'))  
  100.                     {  
  101.                         if (IsOperand(c))   // c是数字或小数点(这里一定是数字),小数点已在下面转换掉了   
  102.                         {  
  103.                             int startIndex = i - 1;  
  104.                             int length = 1; // c是数字,故初始一定是1   
  105.                             while (IsOperand(str[i]))  
  106.                             {  
  107.                                 i++;  
  108.                                 length++;  
  109.                             }  
  110.   
  111.                             string doubleString = str.substr(startIndex, length);  
  112.                             //     operand = atof(&str[i - 1]); //  把从c开头的数转化成double   
  113.                             char **endPtr = NULL;   // 没什么用,只是为了strtod的传参   
  114.                             OPND.push(strtod(doubleString.c_str(), endPtr));  
  115.   
  116.   
  117.                             c = str[i++];  
  118.                         }  
  119.                         else                            // c is operator or delimiter   
  120.                         {  
  121.                             switch (Precede(OPTR.top(), c))  
  122.                             {  
  123.   
  124.                             case '<':  
  125.                                 OPTR.push(c);  
  126.                                 c = str[i++];  
  127.                                 break;  
  128.   
  129.                             case '=':  
  130.                                 x = OPTR.top();  
  131.                                 OPTR.pop();  
  132.   
  133.                                 c = str[i++];  
  134.                                 break;  
  135.   
  136.                             case '>':  
  137.                                 theta = OPTR.top();  
  138.                                 OPTR.pop();  
  139.   
  140.                                 b = OPND.top();  
  141.                                 OPND.pop();  
  142.   
  143.                                 a = OPND.top();  
  144.                                 OPND.pop();  
  145.   
  146.                                 OPND.push(Operate(a, theta, b));  
  147.                                 break;  
  148.   
  149.                             default:  
  150.                                 break;  
  151.                             }  
  152.                         }  
  153.                     }  
  154.                     //  OPTR栈的栈顶元素和当前读入的字符均为“#”   
  155.                     //  即“#”=“#”时整个表达式求值完毕   
  156.                     cout << OPND.top() << endl;  
  157.                 }  
  158.   
  159.             }  
  160.     };  
  161. }  
  162.   
  163. int main(int argc, char **argv)  
  164. {  
  165.     // 仿照Winform中的Main函数new一个窗体对象   
  166.     // Application.Run(new Form1());   
  167.     ConsoleApplicationCal::Program objForm;  
  168.   
  169.     return 0;  
  170. }  

可以看到,上面的C++程序主体就是在设计一个类,而C#将这种特点发挥到了极致,C#程序是从Main()开始执行的,完全在类中进行一切。

另外,上面的C++程序开头的全局变量初始化之所以不能定义在类里面,是因为这是在设计一个类!不能在类中直接对数据成员初始化,只有静态常量整型数据成员才可以在类中初始化。

相关内容