模块笔记{程序源代码分析模块}

        这个模块是预测程序执行时间的基础。要预测程序执行时间,需要了解两个方面的信息

         (1)程序信息:程序的复杂程度

        (2)运行环境信息:运行程序的系统当前的状况

 

        其中,程序信息在本设计中,用时间权值来估计。 参考文献资料,设计出一套不同操作占用的时钟数权重指标,并且在特定的网格计算环境中进行了测试和验证。下表中WT列表示权重系数,此值是各个操作占用的时钟数与“+”操作占用的时钟数的比值。

 

         关于程序代码分析,目前只是一个粗略的分析过程,得到的分析结果不是十分精确,主要的设计思想是:


        采用程序遍历的方法,统计程序代码中的各种指令数目,参照上表中的WT值,得到程序代码的总WT值,作为衡量该程序代码运算量的参数。程序中的分支部分参照参考文献的做法,其具体实现方案为:
      识别出表表中列出的操作代码以后,则将相应的累加器递加。这种情况适用于严格的顺序结构的代码。但是对于分支结构代码,如if{}else{}或switch{case 1,case 2,...,case n},如果前提条件为假,一些分支代码则不会执行,在这种情况下,这些分支代码不应统计在内。不幸的是,只有在运行时才能确定分支条件到底是真还是假,而且条件的真假也可能随着程序的执行而发生变化。我们用概率来处理这种情况,对于if{}else{}语句,每个分支被执行的概率为1/2,switch{case l , case 2,..., case n}语句中每个分支的执行概率为1/n。现在考虑循环语句,情况变得较为复杂一些。如果编译时能够决定迭代的总次数m,则循环体中的每条语句均被计数m次,但是对于while{}来说,我们无法得知其何时才会终结,也就无从知晓其迭代次数,此时就要借助于经验了,我们取其迭代次数为1或100。从算法的执行效果来看,确实达到了判定程序密集类型的目标。


        这样,由于充分考虑了循环结构中的所有运算量,因此得到的参数里已经包含了该程序时间复杂度的信息,所以不需要再单独计算代码的时间复杂度。

 

 

      用C++编写一个分析C程序的算法,以下源代码在VISUAL STUDIO 2008中调试通过:


 

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <string.h>
  4. #include <conio.h>
  5. #include <stdlib.h>
  6. #define PRO_MAX_LEN 20480    //源程序最大长度
  7. #define STR_MAX_LEN 300        //标识符最大长度
  8. #define STB_MAX_LEN 10000    //单词表最大容量
  9. #define BLOCK_MAX_NUM 1000   //最多块数
  10. #define KEYWORD_LEN 32        //保留字个数
  11. #define OP_LEN 51  //指令代码的个数
  12. int 循环体默认计数 = 50;  //循环体 无法判断循环次数时,默认循环 “循环体默认计数” 次
  13. int if块分支数(int if位置,int *if终点);
  14. char proBuffer[PRO_MAX_LEN] = "";    //存储程序代码的全局缓冲区
  15. char wordget[STR_MAX_LEN];            //标识符 或 常量
  16. char wordTab[STB_MAX_LEN][STR_MAX_LEN];    //符号表
  17. float  单词表长度=0;
  18. char 块名表[BLOCK_MAX_NUM][STR_MAX_LEN],顺序块名表[BLOCK_MAX_NUM][STR_MAX_LEN];
  19. int 块开始位置[BLOCK_MAX_NUM],块结束位置[BLOCK_MAX_NUM],块表长度=0,顺序块开始位置[BLOCK_MAX_NUM],顺序块结束位置[BLOCK_MAX_NUM];
  20. float 块权值[BLOCK_MAX_NUM];
  21. bool 是否发现语法错误 = false;
  22. char 关键字表[KEYWORD_LEN][10]={        //保留字表 C语言一共有32个保留字[关键字]
  23.         "auto"/*0*/,        "break"/*1*/,    "case"/*2*/,        "char"/*3*/,        "const"/*4*/,
  24.         "continue"/*5*/,    "default"/*6*/,    "do"/*7*/,        "float"/*8*/,    "else"/*9*/,
  25.         "enum"/*10*/,        "extern"/*11*/,    "float"/*12*/,    "for"/*13*/,        "goto"/*14*/,
  26.         "if"/*15*/,        "int"/*16*/,        "long"/*17*/,        "register"/*18*/,    "return"/*19*/,
  27.         "short"/*20*/,    "signed"/*21*/,    "sizeof"/*22*/,    "static"/*23*/,    "struct"/*24*/,
  28.         "switch"/*25*/,    "typedef"/*26*/,    "union"/*27*/,    "unsigned"/*28*/,    "void"/*29*/,
  29.         "volatile"/*30*/,    "while"/*31*/};
  30. char 操作指令表[OP_LEN][10]={        //指令代码的个数
  31.         "+",        "-",    "*",        "/",        "|",
  32.         "!",    "^",    "<<",        ">",    ">=",
  33.         "==",        "!=",    "++",    "--",        "&",
  34.         ">>",        "<",        "<=",        "&&",    "||",
  35.         "=",    "[",    ".",    "fopen",    "fclose",
  36.         "fgets",    "fptf",    "scanf",    "fputs",    "fread",
  37.         "fwrite",    "fscanf",    "printf""+=" };
  38. double 指令相对权值[OP_LEN]={0.01,0.01,0.08,0.26,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.07,0.08,8.67,2.98,1.59,4.02,28.91,1.73,2.33,2.86,3.48,36.88,0.01};
  39. bool 是否输出详情 = false;
  40. FILE *fin, *fout;
  41. char ch;
  42. float 指针;
  43. int 单词表指针 = 0;
  44. float 权值总数 = 0;
  45. bool 是否为数字(char *str)
  46. {
  47.     int i=0;
  48.     while(str[i]!='/0')
  49.     {
  50.         if(!isdigit(str[i]))
  51.             return false;
  52.         i++;
  53.     }
  54.     return true;
  55. }
  56. int 返回字串长度(char *str)
  57.   int i=0;
  58.   while(str[i] != '/0') i++;
  59.   return i;
  60. }
  61. int 字串变数字(char *str)
  62. {
  63.    int i=0,sum=0,temp,j=0,len;
  64.    len = 返回字串长度(str);
  65.    while( i < len )
  66.    {
  67.        temp=(int)str[i];
  68.        temp-=48;
  69.        for(j=i;j<len-1;j++)
  70.        {
  71.            temp *= 10;
  72.        }
  73.        
  74.        sum += temp;
  75.        i++;
  76.    }
  77.    
  78.    return sum;
  79. }
  80. void 发现语法错误()
  81. {
  82.     是否发现语法错误 = true;
  83.     if(是否输出详情)
  84.     {
  85.        printf("/n发现语法错误/n");
  86.     }
  87.     //exit(0);
  88. }
  89.  bool 读入程序()
  90. {
  91.     char c;
  92.      if ((fin=fopen("Test.c","r")) == NULL)
  93.     {
  94.         if(是否输出详情)
  95.         {
  96.            printf("Cannot open infile/n");
  97.         }
  98.         return false;
  99.     }
  100.     int i = 0;
  101.     while((c = fgetc(fin)) != EOF)
  102.     {
  103.         if(i >= PRO_MAX_LEN-1)
  104.         {
  105.             if(是否输出详情)
  106.             {
  107.                 printf("/n程序代码太长,无法处理/a");
  108.             }
  109.             return 0;
  110.         }
  111.         proBuffer[i++] = c;
  112.     }
  113.     fclose(fin);    //关闭文件
  114.     proBuffer[i++] = '/0';
  115.     return true;
  116. }
  117.  bool 读入程序1(char *source)
  118. {
  119.     char c;
  120.     
  121.     int i = 0;
  122.     while((c = source[i]) != '/0')
  123.     {
  124.         
  125.         proBuffer[i++] = c;
  126.     }
  127.     
  128.     proBuffer[i++] = '/0';
  129.     return true;
  130. }
  131.  char 获得字符(int point)
  132. {
  133.     char ch;
  134.     if(point < PRO_MAX_LEN && proBuffer[point] != '/0')
  135.     {//如果当前下标合法且当前字符为结束标记则取字符增游标
  136.         ch = proBuffer[point];
  137.         //if (ch == '/n')
  138.         //    errorLine ++;
  139.         return ch;
  140.     }
  141.     ch = '/0';
  142.     return ch;
  143. }
  144.  char 获得非空字符(int *point)//读到文件末尾 返回'/0' 否则返回当前指针所指最近的一个非空字符
  145. {
  146.     char c;
  147.     do
  148.     {
  149.         c=获得字符(*point);
  150.         if(isspace(c))
  151.         {
  152.            *point+=1;
  153.         }
  154.         if(c=='/0')    //读到文件末尾
  155.         {
  156.             c = '/0';
  157.             return c;
  158.         }
  159.     }while(isspace(c));    //直到获得一个非空白字符
  160.     return c;
  161. }
  162. void 预处理()
  163. {
  164.     int lines=0;
  165.     char tmp[PRO_MAX_LEN];    //先将处理结果保存到临时空间,这样虽然浪费空间但是节约
  166.                             //时间
  167.     int tmpp = 0;    //这个临时空间的末尾指针
  168.     char flg;
  169.     char flg1;
  170.     char tmpc;
  171.     int point = 0;
  172.     //去掉注释
  173.     //注释有两种 一种是C++风格的// 另一种是C风格的/**/
  174.     
  175.     do
  176.     {
  177.         flg = 获得字符(point);
  178.         point++;
  179.         if(flg == '/')
  180.         {
  181.             flg = 获得字符(point);
  182.             point++;
  183.             switch(flg)
  184.             {
  185.             case '/'://如果‘/’后面接一个‘/’ 就是注释
  186.                 do
  187.                 {
  188.                     flg = 获得字符(point); 
  189.                     point++;
  190.                 }while(!(flg == '/n' || flg == '/0'));// || ch == '/0'));//注释一直到行尾或文件结束
  191.                 if(flg == '/n')
  192.                     point--;    //归还换行
  193.                 break;
  194.             case '*':
  195.                 do
  196.                 {
  197.                     flg = 获得字符(point); //flg=前一个字符
  198.                     point++;
  199.                     tmpc = flg;
  200.                     //为了保证出错处理程序能正确定位出错位置 保留注释中的换行
  201.                     if(tmpc == '/n')
  202.                         tmp[tmpp++] = tmpc;
  203.                     flg1 = 获得字符(point);//flg1=后一个字符
  204.                     
  205.                 }while(flg != '/0' && !( tmpc == '*' && flg1 == '/'));
  206.                 flg = 获得字符(point);
  207.                 point++;
  208.                 if (flg == '/0')
  209.                 {
  210.                     //ProcError(5);===========================================================================------------------
  211.                     //"注释丢失'*/'"
  212.                 }
  213.                 break;
  214.             default:
  215.                 //不是任何一种注释
  216.                 point--;
  217.                 point--;
  218.                 flg = 获得字符(point);
  219.                 point++;
  220.                 tmp[tmpp++] = flg;
  221.                 flg = 获得字符(point);
  222.                 point++;
  223.                 tmp[tmpp++] = flg;
  224.             }
  225.         }
  226.         else
  227.         {
  228.             tmp[tmpp++] = flg;
  229.         }
  230.     }while(flg != '/0');
  231.     tmp[tmpp] = '/0';
  232.     strcpy(proBuffer,tmp);
  233. }
  234. bool 获得单词(int *point)
  235. {
  236.     int  code, value;
  237.     char judge;    //这里有个技巧 
  238.     
  239.     int  i = 0;    //辅助
  240.     ch = 获得非空字符(point);//获取一个非空字符 赋值给ch
  241.     if(ch == '/0'return false;//读到了文件尾,则退出
  242.     if (isalpha(ch) || ch == '_')    
  243.     {
  244.         judge='L'//如果ch是“字母”或者“下划线” judge 赋值为L (letter)
  245.     }
  246.     else if (isdigit(ch))
  247.     {
  248.         judge='D';              //如果ch是“数字”  judge 赋值为D (digit)
  249.     }else
  250.     {
  251.         judge=ch;
  252.     }
  253.     switch(judge)
  254.     {
  255.     case 'L':    //ch 是字母时
  256.         {
  257.             *point+=1; 
  258.             while(isalnum(ch) || ch == '_'//只要ch是字母、数字、下划线 则循环()
  259.              {    //标识符
  260.                
  261.               wordget[i++] = ch; //将ch放到wordget中去形成单词
  262.              
  263.               ch=获得字符(*point);
  264.                  *point+=1;  
  265.              }
  266.             wordget[i] = '/0';//成字符串
  267.             *point-=1;    //回退一个字符
  268.             /*
  269.             code = Reserve(wordget);//对wordget字符串查找保留字表 若是一个保留字-返回其编码 否则返回0
  270.             if(code == 0)//wordget这个单词不是一个保留字
  271.             {
  272.                value = InsertId(wordget);//将str串以标识符插入符号表,并返回符号表指针(如果str在符号表中存在 则返回存在的指针)
  273.                pDu->kind  = ID;         //这个单词的类型为“标识符” ID 33
  274.                pDu->value = value;      //其值为 在符号表中的指针位置
  275.             }
  276.             else//wordget这个单词是一个保留字
  277.             {
  278.                pDu->kind = code;       //类型为保留字在保留字表中的位置
  279.                pDu->value = -1;         //其值为-1
  280.                if(0 == strcmp("for", wordget))
  281.                {
  282.                    //printf("dddddff:%d--%d",forstart(point),point);
  283.                    printf("发现一个for循环,/"(/"开始位置%d,/"{/"位置:%d,/"}/"位置:%d:/n",point,forstart(point),forblock(forstart(point)));
  284.                    getBlocksoWT(forstart(point),forblock(forstart(point)),pDu,fin, fout);
  285.                }
  286.             
  287.             }
  288.         
  289.             updatesoWT(wordget);
  290.         */
  291.             return true;
  292.         }
  293.     case 'D':  //ch是数字时
  294.         *point+=1; 
  295.         while(isdigit(ch))//只要下一个字符是数字 则和这个数字连成一个单词
  296.         {
  297.             wordget[i++] = ch;
  298.             ch=获得字符(*point);
  299.              *point+=1;
  300.         }
  301.         wordget[i] = '/0';//成字串
  302.         *point-=1;
  303.         /*
  304.         value = InsertConst(wordget);//将str串以常数插入常量表,并返回常数表指针(如果str在常量表中存在 则返回存在的指针)
  305.         pDu->kind = CONST; //类型为“常量” 34
  306.         pDu->value= value; //其值为wordget在常量表中的指针位置
  307.         */
  308.         return true;
  309. //以下为ch为一下符号的情况( ) [ ] . , !  != ~ sizeof < << <= > >> >= = ==  & && &= | || |= ?: + ++ +=
  310. // - -> -- -= * *= / /= % %= >>= <<= ^ ^=
  311.     case '"'//ch是"时 接下来的应该是个字符串
  312.         //字符串常量
  313.         do
  314.         {
  315.             wordget[i++] = ch;
  316.             *point+=1;
  317.             ch=获得字符(*point);
  318.             
  319.         }while(ch != '"' && ch != '/0');// 将“”中的字符串 放入到wordget中去
  320.         wordget[i++] = ch;    
  321.         wordget[i] = '/0';//变成字串
  322.         *point+=1;
  323.         /*
  324.         if(ch == '/0')
  325.         {
  326.             printf("%s",wordget);
  327.             ProcError(3);         //不正确的字符串表达
  328.             pDu->kind = ERROR;    //类型0 
  329.             pDu->value = 0;       //值 0
  330.         }
  331.         else
  332.         {
  333.             value = InsertConst(wordget);  //将wordget串以常数插入常量表,并返回常数表指针
  334.             pDu->kind = CONST;             //类型 常数
  335.             pDu->value = value;            //值  在常数表中的位置
  336.         }
  337.         */
  338.         return true;
  339.         //字符常量
  340.     case '/''://ch是'时 接下来的应该是个字符常量
  341.         wordget[i++] = ch;    // '
  342.         ch=获得字符(++*point);
  343.         
  344.         wordget[i++] = ch;
  345.         if(ch == '//')    // '/n'
  346.         {//如果是转义字符则要多接收一个字符
  347.             ch=获得字符(++*point);         // ch = '
  348.             wordget[i++] = ch;
  349.         }
  350.         ch=获得字符(++*point); 
  351.         wordget[i++] = ch;
  352.         wordget[i] = '/0';//编程字串 '/n'/0
  353.         *point+=1;
  354.         /*
  355.         if(ch != '/'')//'号不配对 则不对
  356.         {//'/b'
  357.             printf("%s",wordget);
  358.             ProcError(2);      //非法的字符
  359.             pDu->kind = ERROR; 
  360.             pDu->value = 0;
  361.         }
  362.         else
  363.         {
  364.             value = InsertConst(wordget); //将wordget串以常数插入常量表,并返回常数表指针
  365.             pDu->kind = CONST;
  366.             pDu->value = value;
  367.         }*/
  368.         return true;
  369.     case '(':
  370.     case ')':
  371.     case '[':
  372.     case ']':
  373.     case '.':
  374.     case ',':
  375.     case '~':
  376.     case '?':
  377.     case ':':
  378.     case ';':
  379.     case '{':
  380.     case '}':
  381.     case '#':
  382.         wordget[i++] = ch;    
  383.         wordget[i] = '/0';
  384.         *point+=1;
  385.         /*
  386.         pDu->kind = DIVIDE; //界符
  387.         pDu->value = -1;    //界符的时候 -1
  388.         */
  389.         return true;
  390.     case '!':
  391.         //!=
  392.         wordget[i++] = ch;
  393.         ch=获得字符(++*point); 
  394.         if (ch=='=') wordget[i++] = ch;
  395.         else *point-=1;
  396.         wordget[i]='/0';
  397.         
  398.         break;
  399.     case '<':
  400.         // << <=
  401.         wordget[i++] = ch;
  402.         ch=获得字符(++*point); 
  403.         if (ch == '<' || ch == '=') wordget[i++] = ch;
  404.         else *point-=1;
  405.         wordget[i]='/0';
  406.         
  407.         break;
  408.     case '>':
  409.         // >> >=
  410.         wordget[i++] = ch;
  411.          ch=获得字符(++*point); 
  412.         if (ch == '>' || ch == '=') wordget[i++] = ch;
  413.         else *point-=1;
  414.         wordget[i]='/0';
  415.         
  416.         break;
  417.     case '=':
  418.         // ==
  419.         wordget[i++] = ch;
  420.         ch=获得字符(++*point); 
  421.         if (ch == '=') wordget[i++] = ch;
  422.         else *point-=1;
  423.         wordget[i]='/0';
  424.         
  425.         break;
  426.     case '&':
  427.         // && &=
  428.         wordget[i++] = ch;
  429.        ch=获得字符(++*point); 
  430.         //if (ch == '&' || ch == '=') wordget[i++] = ch;
  431.         if (ch !=' ') wordget[i++] = ch;
  432.         else *point-=1;
  433.         wordget[i]='/0';
  434.         
  435.         break;
  436.     case '|':
  437.         // || |=
  438.         wordget[i++] = ch;
  439.         ch=获得字符(++*point); 
  440.         if (ch == '|' || ch == '=') wordget[i++] = ch;
  441.         else *point-=1;
  442.         wordget[i]='/0';
  443.         
  444.         break;
  445.     case '+':
  446.         // ++ +=
  447.         wordget[i++] = ch;
  448.         
  449.         ch=获得字符(++(*point)); 
  450.         if (ch == '+' || ch == '=') wordget[i++] = ch;
  451.         else *point-=1;
  452.         wordget[i]='/0';
  453.         
  454.         break;
  455.     case '-':
  456.         // -- -= ->
  457.         wordget[i++] = ch;
  458.         ch=获得字符(++*point); 
  459.         if (ch == '-' || ch == '=' || ch == '>') wordget[i++] = ch;
  460.         else *point-=1;
  461.         wordget[i]='/0';
  462.         
  463.         break;
  464.     case '*':
  465.         // ** *=
  466.         wordget[i++] = ch;
  467.         ch=获得字符(++*point); 
  468.         if (ch == '*' || ch == '=') wordget[i++] = ch;
  469.         else *point-=1;
  470.         wordget[i]='/0';
  471.         
  472.         break;
  473.     case '/':
  474.         // /=
  475.         wordget[i++] = ch;
  476.         ch=获得字符(++*point); 
  477.         if (ch == '=') wordget[i++] = ch;
  478.         else *point-=1;
  479.         wordget[i]='/0';
  480.         
  481.         break;
  482.     case '%':
  483.         // %=
  484.         wordget[i++] = ch;
  485.         ch=获得字符(++*point); 
  486.         if (ch == '=') wordget[i++] = ch;
  487.         else *point-=1;
  488.         wordget[i]='/0';
  489.         
  490.         break;
  491.     case '^':
  492.         // ^=
  493.         wordget[i++] = ch;
  494.         ch=获得字符(++*point); 
  495.         if (ch == '=') wordget[i++] = ch;
  496.         else *point-=1;
  497.         wordget[i]='/0';
  498.         
  499.         break;
  500.     case '/0':
  501.         return false;
  502.     default:
  503.         //ProcError(1);
  504.         return false;
  505.     }
  506.     //updatesoWT(wordget);
  507.     //pDu->kind = OPERAT;
  508.     *point+=1;
  509.     return true;
  510. }
  511. void 寻找程序块名(int 开始左括号位置)
  512. {
  513. }
  514. int 返回右括号配对(int 右括号位置)
  515. {
  516.      int flag = 0;//表示开始默认搜索(
  517.      int i = 右括号位置-1;
  518.      while(i > 0)
  519.      {
  520.      
  521.          if(0 == strcmp(")", wordTab[i])&&flag>=0)
  522.                {
  523.                    
  524.                    flag++;//表示开始搜索这个{匹配的}
  525.                }
  526.          
  527.          else if(0 == strcmp("(", wordTab[i])&&flag>=1)
  528.          {
  529.              flag--;
  530.          }
  531.          else if(0 == strcmp("(", wordTab[i])&&flag==0)
  532.          {
  533.              
  534.              return i;
  535.          }
  536.          i--;
  537.      }
  538.     return -1;
  539. }
  540. int 返回左括号配对(int 左括号位置)
  541. {
  542.      int flag = 0;//表示开始默认搜索)
  543.      int i = 左括号位置+1;
  544.      while(i < 单词表长度)
  545.      {
  546.      
  547.          if(0 == strcmp("(", wordTab[i])&&flag>=0)
  548.                {
  549.                    
  550.                    flag++;//表示开始搜索这个{匹配的}
  551.                }
  552.          
  553.          else if(0 == strcmp(")", wordTab[i])&&flag>=1)
  554.          {
  555.              flag--;
  556.          }
  557.          else if(0 == strcmp(")", wordTab[i])&&flag==0)
  558.          {
  559.              
  560.              return i;
  561.          }
  562.          i++;
  563.      }
  564.     return -1;
  565. }
  566. int 返回左大括号配对(int 左大括号位置)
  567. {
  568.       int flag = 0;//表示开始默认搜索}
  569.      int i = 左大括号位置+1;
  570.      while(i < 单词表长度)
  571.      {
  572.      
  573.          if(0 == strcmp("{", wordTab[i])&&flag>=0)
  574.                {
  575.                    
  576.                    flag++;//表示开始搜索这个{匹配的}
  577.                }
  578.          
  579.          else if(0 == strcmp("}", wordTab[i])&&flag>=1)
  580.          {
  581.              flag--;
  582.          }
  583.          else if(0 == strcmp("}", wordTab[i])&&flag==0)
  584.          {
  585.              
  586.              return i;
  587.              
  588.          }
  589.          i++;
  590.      }
  591.      return -1;
  592. }
  593. void 分割程序()
  594. {
  595.     int flag = 0;//表示开始默认搜索{
  596.     int i = 0;
  597.      while(i<单词表长度)
  598.      {
  599.      
  600.          if(0 == strcmp("{", wordTab[i])&&flag==0)//发现一级{
  601.                {
  602.                    if(0 == strcmp(")", wordTab[i-1]))//只有{前紧跟着()的才是一个块,块一般是指函数
  603.                    {
  604.                         int ff = 返回右括号配对(i-1)-1;
  605.                   
  606.                          strcpy(块名表[块表长度], wordTab[ff]);
  607.                          块开始位置[块表长度]=i;
  608.                          块结束位置[块表长度]=返回左大括号配对(i);
  609.                         //printf("发现一个块,块名字:%s,块开始位置:%d,结束位置:%d",wordTab[ff],i,返回左大括号配对(i));
  610.                         if(是否输出详情)
  611.                         {
  612.                             printf("/n发现一个块,块名字:%s,块开始位置:%d,结束位置:%d",块名表[块表长度],块开始位置[块表长度],块结束位置[块表长度]);
  613.                         }
  614.                         块表长度++;
  615.                         flag++;//表示开始搜索这个{匹配的}
  616.                    }
  617.                }
  618.          if(0 == strcmp("{", wordTab[i])&&flag>0)//发现非一级{
  619.          {
  620.              flag++;
  621.          }
  622.          if(0 == strcmp("}", wordTab[i])&&flag>1)
  623.          {
  624.              flag--;
  625.          }
  626.          if(0 == strcmp("}", wordTab[i])&&flag==1)
  627.          {
  628.              
  629.              flag--;
  630.          }
  631.          i++;
  632.      }
  633.     
  634. }
  635. void 插入单词表(char *str)
  636. {
  637.     
  638.    
  639.     strcpy(wordTab[单词表指针++], str);
  640.     //return (pointCTB-1);
  641. }
  642. void 建立单词表()
  643. {
  644.     int 指针 = 0;
  645.      while(获得单词(&指针))
  646.      {
  647.         插入单词表(wordget);
  648.         单词表长度++;
  649.      }
  650. }
  651. int 查关键字表(char *str)
  652. {
  653.     int i;
  654.     for(i=0; i<KEYWORD_LEN; ++i)    //从保留字表中查找str串
  655.     {
  656.         if(0 == strcmp(关键字表[i], str))
  657.             return i;    
  658.     }
  659.     return -1;
  660. }
  661. int 查函数名表(char *str)
  662. {
  663.     int i;
  664.     for(i = 0; i < 块表长度; ++i)    //从函数名表中查找str串
  665.     {
  666.         if(0 == strcmp(顺序块名表[i], str))
  667.             return i;    
  668.     }
  669.     return -1;
  670. }
  671. float 查指令表返回权值(char *str)
  672. {
  673.     int i;
  674.     int 位置 = -1;
  675.     for(i=0; i<OP_LEN; ++i)    //从保留字表中查找str串
  676.     {
  677.         if(0 == strcmp(操作指令表[i], str))
  678.             位置 = i;    
  679.     }
  680.     if(位置 == -1)
  681.     {
  682.          return -1;
  683.     }else
  684.     {
  685.         return 指令相对权值[位置];
  686.     }
  687. }
  688. int 分析for起点(int for位置)
  689. {
  690.     int 分析点 = for位置+1;
  691.     if(0 == strcmp("(", wordTab[分析点]))
  692.     {
  693.         分析点=返回左括号配对(分析点)+1;
  694.     }else
  695.     {
  696.         发现语法错误();
  697.         return -1;
  698.     }
  699.     return 分析点;
  700. }
  701. int 分析for终点(int for位置)
  702. {
  703.     int 分析点 = 分析for起点(for位置);
  704.     
  705.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  706.     {
  707.          return 返回左大括号配对(分析点);
  708.     }
  709.     else if(0 == strcmp("if", wordTab[分析点]))
  710.     {
  711.         int if的终点;
  712.         if块分支数(分析点,if的终点);
  713.         return if的终点;
  714.     }
  715.     else if(0 == strcmp("for", wordTab[分析点]))
  716.     {
  717.         return 分析for终点(分析点);
  718.     }
  719.     else
  720.     {//for后面没有{}块 只跟一条语句
  721.         while(0 != strcmp(";", wordTab[分析点]))
  722.         {
  723.            分析点++;
  724.         }
  725.         return 分析点;
  726.     }
  727. }
  728. int 分析for条件点(int for位置)
  729. {
  730.     int 分析点 = for位置 + 1;
  731.     
  732.     while(0 != strcmp(";", wordTab[分析点]))
  733.     {//找到第一个";"
  734.         
  735.       分析点++;
  736.     }
  737.     分析点++;
  738.     while(0 != strcmp(";", wordTab[分析点]))
  739.     {//找到第二个";"
  740.         
  741.       分析点++;
  742.     }
  743.     return 分析点;
  744. }
  745. int 分析for循环次数(int for位置)
  746. {
  747.      int 分析点 = for位置+1;
  748.      int 开始条件,结束条件,次数;
  749.     if(0 == strcmp("(", wordTab[分析点]))
  750.     {
  751.         /**
  752.         for(i=0;i<n;i++) 只能分析一下这个情况下的循环次数,并且只有n是一个常数的时候才分析
  753.         */
  754.         if(  (0 == strcmp(wordTab[分析点+1], wordTab[分析点+5]))  &&  (0 == strcmp(wordTab[分析点+5], wordTab[分析点+9]))  &&  是否为数字(wordTab[分析点+3])  &&  是否为数字(wordTab[分析点+7])  &&  ((0 == strcmp("++", wordTab[分析点+10]))||(0 == strcmp("--", wordTab[分析点+10]))))
  755.         {   
  756.              结束条件 = 字串变数字(wordTab[分析点+7]);
  757.              开始条件 = 字串变数字(wordTab[分析点+3]);
  758.              if(0 == strcmp("++", wordTab[分析点+10]))
  759.              {
  760.                   次数 = 结束条件-开始条件;
  761.              }else
  762.              {
  763.                   次数 = 开始条件-结束条件;
  764.              }
  765.              if(次数>0)
  766.              return 次数;
  767.              else
  768.              return 0;//起始条件都不满足 则这个循环不开始
  769.         }else//其他的情况不好分析,默认循环“循环体默认计数”次,这个参数应该是个可以调整的多次调整以得到最好的预测结果
  770.         {
  771.              return 循环体默认计数;
  772.         }
  773.         
  774.         
  775.     }else
  776.     {
  777.         发现语法错误();
  778.         return -1;
  779.     }
  780.     
  781. }
  782. int 分析if起点(int if位置)
  783. {
  784.     int 分析点 = if位置+1;
  785.     if(0 == strcmp("(", wordTab[分析点]))
  786.     {
  787.         分析点=返回左括号配对(分析点) + 1;
  788.     }else
  789.     {
  790.         发现语法错误();
  791.         return -1;
  792.     }
  793.     return 分析点;
  794. }
  795. int 块后面一个单词(int 块起点)
  796. {
  797.     int 分析点;
  798.     分析点 = 块起点;//此时分析点在if条件括号后面一个单词
  799.     if(0==strcmp("{",wordTab[分析点]))
  800.     {//if语句后面有{}
  801.         分析点=返回左大括号配对(分析点);
  802.     }else
  803.     {//if语句后面直接接一个语句的
  804.         while(0 != strcmp(";", wordTab[分析点]))
  805.         {
  806.            分析点++;
  807.         }//循环完后 分析点 指向;
  808.         
  809.     }
  810.     return ++分析点;
  811. }
  812. int if块分支数(int if位置,int *if终点)
  813. {
  814.     int 分支 = 1;
  815.     int 块结束下一位置 = 块后面一个单词(分析if起点(if位置));
  816.     while(0==strcmp("else",wordTab[块结束下一位置]))
  817.     {
  818.         分支++;
  819.         if(0 == strcmp("if",wordTab[块结束下一位置+1]))
  820.         {
  821.             块结束下一位置 = 块后面一个单词(分析if起点(块结束下一位置+1));
  822.         }else
  823.         {
  824.             块结束下一位置 = 块后面一个单词(块结束下一位置+1);
  825.             break;
  826.         }
  827.     }
  828.     *if终点 = 块结束下一位置-1;
  829.     if(分支 == 1) 分支 = 2;
  830.     return 分支;
  831. }
  832. int 分析while起点(int while位置)
  833. {
  834.     int 分析点 = while位置 + 1;
  835.     if(0 == strcmp("(", wordTab[分析点]))
  836.     {
  837.         分析点 = 返回左括号配对(分析点)+1;
  838.     }else
  839.     {
  840.         发现语法错误();
  841.         return -1;
  842.     }
  843.     return 分析点;
  844. }
  845. int 分析while终点(int while位置)
  846. {
  847.     int 分析点 = 分析while起点(while位置);
  848.     
  849.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  850.     {
  851.          return 返回左大括号配对(分析点);
  852.     }
  853.     else
  854.     {//for后面没有{}块 只跟一条语句
  855.         while(0 != strcmp(";", wordTab[分析点]))
  856.         {
  857.            分析点++;
  858.         }
  859.         return 分析点;
  860.     }
  861. }
  862. int 分析switch起点(int switch位置)
  863. {
  864.     int 分析点 = switch位置 + 1;
  865.     if(0 == strcmp("(", wordTab[分析点]))
  866.     {
  867.         分析点 = 返回左括号配对(分析点)+1;
  868.     }else
  869.     {
  870.         发现语法错误();
  871.         return -1;
  872.     }
  873.     return 分析点;
  874. }
  875. int 分析switch终点(int switch位置)
  876. {
  877.     int 分析点 = 分析switch起点(switch位置);
  878.     
  879.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  880.     {
  881.          return 返回左大括号配对(分析点);
  882.     }
  883.     else
  884.     {
  885.         发现语法错误();
  886.         return -1;
  887.     }
  888. }
  889. int switch分支数(int switch起点,int switch终点)
  890. {
  891.     int 分析点 = switch起点;
  892.     int sum=0;
  893.     while(分析点 <= switch终点)
  894.     {
  895.        if(0 == strcmp("case", wordTab[分析点]))
  896.        {
  897.           sum++;
  898.        }
  899.        分析点++;
  900.     }
  901.     return sum;
  902. }
  903. float 顺序分析(int 起点,int 终点)
  904. {
  905.     float 该块权值 = 0.0;
  906.     int 当前分析点=起点;
  907.     while(当前分析点 < 终点)
  908.     {
  909.         switch(查关键字表(wordTab[当前分析点]))
  910.         {
  911.             case 13://for
  912.                 {
  913.                     int forend = 分析for终点(当前分析点);
  914.                     int forbegin = 分析for起点(当前分析点);
  915.                     if(forbegin != -1)
  916.                     {
  917.                     int div= 分析for条件点(当前分析点);
  918.                     int times = 分析for循环次数(当前分析点);
  919.                     int forblockWT = 顺序分析(div,forend);
  920.                     int forst = 顺序分析(当前分析点+1,div);
  921.                     该块权值 += forst;
  922.                     该块权值 += times * forblockWT;
  923.                     当前分析点 = forend;
  924.                     if(是否输出详情)
  925.                     {
  926.                         printf("/nfor语句的起点:%d 终点:%d 这个FOR语句的循环次数:%d,该for语句块的权值:%d,总权值 = 条件权值 + for语句块的权值 * 循环次数(%d = %d + %d * %d)",forbegin,forend,times,forblockWT,该块权值,forst,forblockWT,times);
  927.             
  928.                     }
  929.                         //该块权值 += 顺序分析(当前分析点,div)  + 分析for循环次数(当前分析点) * (顺序分析(div,forend));
  930.                     }
  931.                     else
  932.                     {
  933.                         当前分析点 = 单词表长度;
  934.                     }
  935.                     break;
  936.                 }
  937.             case 15://if
  938.                 {
  939.                     if(0 != strcmp("else",wordTab[当前分析点-1])){
  940.                         //如果当前IF是一个if块的第一个if,而不是分支中的 else if
  941.                     int if结束点 = 0 ;
  942.                     int if起点 = 分析if起点(当前分析点);
  943.                     int if分支数 = if块分支数(当前分析点,if结束点);
  944.                     
  945.                     if(if起点 != -1)
  946.                     {
  947.                     
  948.                         if(是否输出详情)
  949.                          {
  950.                              printf("/n发现一个if,该if开始位置:%d 分支数为%d,-----",if起点,if分支数);
  951.                              printf("/n该if块结束位置为:%d,",if结束点);
  952.                         }
  953.                          该块权值 += 顺序分析(if起点,if结束点)/if分支数;
  954.                     }
  955.                     else
  956.                     {
  957.                          当前分析点 = 单词表长度;
  958.                     }
  959.                     当前分析点 = if结束点;
  960.                     }
  961.                     break;
  962.                 }
  963.             case 31://while
  964.                 {
  965.                     
  966.                     int whilebegin = 分析while起点(当前分析点);
  967.                     if(whilebegin != -1)
  968.                     {
  969.                        int whileend = 分析while终点(当前分析点);
  970.                        if(是否输出详情)
  971.                        {
  972.                            printf("/nwhile语句的起点:%d 终点:%d ",whilebegin,whileend);
  973.                        }
  974.                     
  975.                        该块权值 += 循环体默认计数 * 顺序分析(whilebegin,whileend);
  976.             
  977.             
  978.                        当前分析点 = whileend;
  979.                     }
  980.                     else
  981.                     {
  982.                         当前分析点 = 单词表长度;
  983.                     }
  984.                     break;
  985.                 }
  986.             case 25://switch
  987.                 {   int switchbegin = 分析switch起点(当前分析点);
  988.                     int switchend = 分析switch终点(当前分析点);
  989.                     int fenzhi = switch分支数(switchbegin,switchend);
  990.                      
  991.                     if((switchbegin != -1) && (switchend != -1))
  992.                     {
  993.                         if(是否输出详情)
  994.                         {
  995.                             printf("/n发现一个switch,该switch开始位置:%d 分支数为%d,-----",switchbegin,fenzhi);
  996.                             printf("/n该if块结束位置为:%d,",switchend);
  997.                         }
  998.                         该块权值 += (顺序分析(switchbegin,switchend) / fenzhi);
  999.                         当前分析点 = switchend;
  1000.                     }
  1001.                     else
  1002.                     {
  1003.                         当前分析点 = 单词表长度;
  1004.                     }
  1005.                 }
  1006.             case -1://不是一个关键字
  1007.                 {
  1008.                     int temp = 查函数名表(wordTab[当前分析点]);
  1009.                     if(temp != -1)
  1010.                     {//如果是一个函数,则用前面分析到的这个函数的权值 作为这个关键字的权值
  1011.                         if(是否输出详情)
  1012.                         {
  1013.                             printf("/n发现一个函数,当前分析点:%d, 函数名:%s:权值: %f/n",当前分析点,wordTab[当前分析点],块权值[temp]);
  1014.                         }
  1015.                         该块权值 += 块权值[temp];
  1016.                     }
  1017.                     
  1018.                     else if(查指令表返回权值(wordTab[当前分析点]) != -1)
  1019.                     {
  1020.                         if(是否输出详情)
  1021.                         {
  1022.                             printf("/n当前分析点:%d, 单词:%s:权值: %f=====%f/n",当前分析点,wordTab[当前分析点],查指令表返回权值(wordTab[当前分析点]),该块权值);
  1023.                         }
  1024.                         该块权值 += 查指令表返回权值(wordTab[当前分析点]);
  1025.                     }
  1026.                 
  1027.                 
  1028.                 }
  1029.             default:break;
  1030.         }
  1031.         当前分析点++;
  1032.     }
  1033.     
  1034.     return 该块权值;
  1035. }
  1036. int 按函数名查找函数表(char *str)//如果在函数表里 就返回在“块名表”里的位置
  1037. {
  1038.     int i;
  1039.     for(i=0;i<块表长度;i++)
  1040.     {
  1041.         if(0 == strcmp(str,块名表[i]))
  1042.         {
  1043.             return i;
  1044.         }
  1045.     }
  1046.     return -1;
  1047. }
  1048. void 块名表调序(int 新顺序,int 老位置)
  1049. {
  1050.     //顺序块名表[新顺序] = 块名表[老位置];
  1051.     strcpy(顺序块名表[新顺序],块名表[老位置]);
  1052.     
  1053.     strcpy(块名表[老位置],"");
  1054.     顺序块开始位置[新顺序] = 块开始位置[老位置];
  1055.     顺序块结束位置[新顺序] = 块结束位置[老位置];
  1056.     
  1057. }
  1058. void 按函数出现顺序排序()
  1059. {
  1060.     int 当前分析点 = 0;
  1061.     int i=0,j=0;
  1062.     while(当前分析点 < 单词表长度)
  1063.     {
  1064.         i = 按函数名查找函数表(wordTab[当前分析点]);
  1065.             if(i != -1)
  1066.             {
  1067.                 块名表调序(j,i);
  1068.                 j++;
  1069.             }
  1070.         当前分析点++;
  1071.     }
  1072.     
  1073.     
  1074. }
  1075. float getSourceWT(int times,bool isprint)
  1076. {
  1077.     循环体默认计数 = times;
  1078.     是否输出详情 = isprint;
  1079.      int i=0;
  1080.     char c;
  1081.    
  1082.     读入程序();
  1083.     
  1084.     //读入程序1(source);
  1085.     //char* csStr = env->GetStringUTFChars(str,NULL);
  1086.     //char* csStr = GetStringUTFChars(
  1087.     预处理();
  1088.    
  1089.     建立单词表();
  1090.     分割程序();
  1091.     按函数出现顺序排序();
  1092.     
  1093.     for(int i=0;i<块表长度;i++)
  1094.     {
  1095.         块权值[i] = 顺序分析(顺序块开始位置[i],顺序块结束位置[i]);
  1096.         
  1097.         
  1098.         
  1099.     }
  1100.     if(是否输出详情)
  1101.     {
  1102.         for(int i=0;i<块表长度;i++)
  1103.         {
  1104.             printf("/n块信息:/n%s:%d---%d/n",顺序块名表[i],顺序块开始位置[i],顺序块结束位置[i]);
  1105.             printf("权值:%f",块权值[i]);
  1106.         }
  1107.     }
  1108.     if(是否发现语法错误)
  1109.     {
  1110.         return -1;
  1111.     }
  1112.     else
  1113.     {
  1114.         for(int i=0;i<块表长度;i++)
  1115.         { 
  1116.             if(0==strcmp("main",顺序块名表[i]))
  1117.             {
  1118.                return 块权值[i];
  1119.             }
  1120.         }
  1121.         //没有main块 ,也算是语法错误
  1122.         return -1;
  1123.         
  1124.     }
  1125.     
  1126. }
  1127. int main()
  1128. {
  1129.     
  1130.     
  1131.      
  1132.     printf("权值---->:%f",getSourceWT(90,false));
  1133.     
  1134.     
  1135.     printf("/n写入完毕/n按任意键继续/n");    getch();
  1136.     return 0;
  1137. }

        getSourceWT(int times,bool isprint)函数中的两个参数:

        第一个提供外部修改“默认循环次数”的接口,在以后的预测过程中调整这个数值,以与期望的预测时间更接近

        第二个参数方便调试用,如果要查看具体的分析过程,可以设置这个值为真,则在命令管理器中会输出分析过程。

        下面是JNI改造:

 

        步骤一:在“C:/c/com/swjtu/sourcemanage”里建立文件SourceScan.java,文件代码如下:

 

  1. package com.swjtu.sourcemanage;
  2. public class SourceScan {
  3.     public static native double getSourceWT(int times,boolean isprint,String source);   
  4.     static  
  5.     {   
  6.     System.loadLibrary("SourceScan");   
  7.     }   
  8. }

步骤二:点击“开始”——>“运行”——>cmd 敲命令 Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.
C:/Documents and Settings/Administrator>cd c:/c
C:/c>cd com/swjtu/sourcemanage
C:/c/com/swjtu/sourcemanage>javac SourceScan .java
C:/c/com/swjtu/sourcemanage>cd c:/c
C:/c>javah com.swjtu.sourcemanage.SourceScan 
C:/c>
注:javah命令在c:/c文件夹下生成了com_swjtu_sourcemanage_SourceScan.h头文件,文件代码如下:

  1. /* DO NOT EDIT THIS FILE - it is machine generated */
  2. #include <jni.h>
  3. /* Header for class com_swjtu_sourcemanage_SourceScan */
  4. #ifndef _Included_com_swjtu_sourcemanage_SourceScan
  5. #define _Included_com_swjtu_sourcemanage_SourceScan
  6. #ifdef __cplusplus
  7. extern "C" {
  8. #endif
  9. /*
  10.  * Class:     com_swjtu_sourcemanage_SourceScan
  11.  * Method:    getSourceWT
  12.  * Signature: (IZLjava/lang/String;)D
  13.  */
  14. JNIEXPORT jdouble JNICALL Java_com_swjtu_sourcemanage_SourceScan_getSourceWT
  15.   (JNIEnv *, jclass, jint, jboolean, jstring);
  16. #ifdef __cplusplus
  17. }
  18. #endif
  19. #endif

 

步骤三:在文件夹“C:/c”建立com_swjtu_sourcemanage_SourceScan.cpp文件,这个文件是上面的经过一些小修改而成的,为可以被JAVA调用的DLL源代码,文件内容如下:

 

  1. #include "com_swjtu_sourcemanage_SourceScan.h"
  2. #include <stdio.h>
  3. #include <ctype.h>
  4. #include <string.h>
  5. #include <conio.h>
  6. #include <stdlib.h>
  7. #define PRO_MAX_LEN 20480    //源程序最大长度
  8. #define STR_MAX_LEN 300        //标识符最大长度
  9. #define STB_MAX_LEN 10000    //单词表最大容量
  10. #define BLOCK_MAX_NUM 1000   //最多块数
  11. #define KEYWORD_LEN 32        //保留字个数
  12. #define OP_LEN 51  //指令代码的个数
  13. int 循环体默认计数 = 50;  //循环体 无法判断循环次数时,默认循环 “循环体默认计数” 次
  14. int if块分支数(int if位置,int *if终点);
  15. char proBuffer[PRO_MAX_LEN] = "";    //存储程序代码的全局缓冲区
  16. char wordget[STR_MAX_LEN];            //标识符 或 常量
  17. char wordTab[STB_MAX_LEN][STR_MAX_LEN];    //符号表
  18. float  单词表长度=0;
  19. char 块名表[BLOCK_MAX_NUM][STR_MAX_LEN],顺序块名表[BLOCK_MAX_NUM][STR_MAX_LEN];
  20. int 块开始位置[BLOCK_MAX_NUM],块结束位置[BLOCK_MAX_NUM],块表长度=0,顺序块开始位置[BLOCK_MAX_NUM],顺序块结束位置[BLOCK_MAX_NUM];
  21. float 块权值[BLOCK_MAX_NUM];
  22. bool 是否发现语法错误 = false;
  23. char 关键字表[KEYWORD_LEN][10]={        //保留字表 C语言一共有32个保留字[关键字]
  24.         "auto"/*0*/,        "break"/*1*/,    "case"/*2*/,        "char"/*3*/,        "const"/*4*/,
  25.         "continue"/*5*/,    "default"/*6*/,    "do"/*7*/,        "float"/*8*/,    "else"/*9*/,
  26.         "enum"/*10*/,        "extern"/*11*/,    "float"/*12*/,    "for"/*13*/,        "goto"/*14*/,
  27.         "if"/*15*/,        "int"/*16*/,        "long"/*17*/,        "register"/*18*/,    "return"/*19*/,
  28.         "short"/*20*/,    "signed"/*21*/,    "sizeof"/*22*/,    "static"/*23*/,    "struct"/*24*/,
  29.         "switch"/*25*/,    "typedef"/*26*/,    "union"/*27*/,    "unsigned"/*28*/,    "void"/*29*/,
  30.         "volatile"/*30*/,    "while"/*31*/};
  31. char 操作指令表[OP_LEN][10]={        //指令代码的个数
  32.         "+",        "-",    "*",        "/",        "|",
  33.         "!",    "^",    "<<",        ">",    ">=",
  34.         "==",        "!=",    "++",    "--",        "&",
  35.         ">>",        "<",        "<=",        "&&",    "||",
  36.         "=",    "[",    ".",    "fopen",    "fclose",
  37.         "fgets",    "fptf",    "scanf",    "fputs",    "fread",
  38.         "fwrite",    "fscanf",    "printf""+=" };
  39. double 指令相对权值[OP_LEN]={0.01,0.01,0.08,0.26,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.01,0.07,0.08,8.67,2.98,1.59,4.02,28.91,1.73,2.33,2.86,3.48,36.88,0.01};
  40. bool 是否输出详情 = false;
  41. FILE *fin, *fout;
  42. char ch;
  43. float 指针;
  44. int 单词表指针 = 0;
  45. float 权值总数 = 0;
  46. bool 是否为数字(char *str)
  47. {
  48.     int i=0;
  49.     while(str[i]!='/0')
  50.     {
  51.         if(!isdigit(str[i]))
  52.             return false;
  53.         i++;
  54.     }
  55.     return true;
  56. }
  57. int 返回字串长度(char *str)
  58.   int i=0;
  59.   while(str[i] != '/0') i++;
  60.   return i;
  61. }
  62. int 字串变数字(char *str)
  63. {
  64.    int i=0,sum=0,temp,j=0,len;
  65.    len = 返回字串长度(str);
  66.    while( i < len )
  67.    {
  68.        temp=(int)str[i];
  69.        temp-=48;
  70.        for(j=i;j<len-1;j++)
  71.        {
  72.            temp *= 10;
  73.        }
  74.        
  75.        sum += temp;
  76.        i++;
  77.    }
  78.    
  79.    return sum;
  80. }
  81. void 发现语法错误()
  82. {
  83.     是否发现语法错误 = true;
  84.     if(是否输出详情)
  85.     {
  86.        printf("/n发现语法错误/n");
  87.     }
  88.     //exit(0);
  89. }
  90.  bool 读入程序()
  91. {
  92.     char c;
  93.      if ((fin=fopen("Test.c","r")) == NULL)
  94.     {
  95.         if(是否输出详情)
  96.         {
  97.            printf("Cannot open infile/n");
  98.         }
  99.         return false;
  100.     }
  101.     int i = 0;
  102.     while((c = fgetc(fin)) != EOF)
  103.     {
  104.         if(i >= PRO_MAX_LEN-1)
  105.         {
  106.             if(是否输出详情)
  107.             {
  108.                 printf("/n程序代码太长,无法处理/a");
  109.             }
  110.             return 0;
  111.         }
  112.         proBuffer[i++] = c;
  113.     }
  114.     fclose(fin);    //关闭文件
  115.     proBuffer[i++] = '/0';
  116.     return true;
  117. }
  118.  bool 读入程序1(const char *source)
  119. {
  120.     char c;
  121.     
  122.     int i = 0;
  123.     while((c = source[i]) != '/0')
  124.     {
  125.         
  126.         proBuffer[i++] = c;
  127.     }
  128.     
  129.     proBuffer[i++] = '/0';
  130.     return true;
  131. }
  132.  char 获得字符(int point)
  133. {
  134.     char ch;
  135.     if(point < PRO_MAX_LEN && proBuffer[point] != '/0')
  136.     {//如果当前下标合法且当前字符为结束标记则取字符增游标
  137.         ch = proBuffer[point];
  138.         //if (ch == '/n')
  139.         //    errorLine ++;
  140.         return ch;
  141.     }
  142.     ch = '/0';
  143.     return ch;
  144. }
  145.  char 获得非空字符(int *point)//读到文件末尾 返回'/0' 否则返回当前指针所指最近的一个非空字符
  146. {
  147.     char c;
  148.     do
  149.     {
  150.         c=获得字符(*point);
  151.         if(isspace(c))
  152.         {
  153.            *point+=1;
  154.         }
  155.         if(c=='/0')    //读到文件末尾
  156.         {
  157.             c = '/0';
  158.             return c;
  159.         }
  160.     }while(isspace(c));    //直到获得一个非空白字符
  161.     return c;
  162. }
  163. void 预处理()
  164. {
  165.     int lines=0;
  166.     char tmp[PRO_MAX_LEN];    //先将处理结果保存到临时空间,这样虽然浪费空间但是节约
  167.                             //时间
  168.     int tmpp = 0;    //这个临时空间的末尾指针
  169.     char flg;
  170.     char flg1;
  171.     char tmpc;
  172.     int point = 0;
  173.     //去掉注释
  174.     //注释有两种 一种是C++风格的// 另一种是C风格的/**/
  175.     
  176.     do
  177.     {
  178.         flg = 获得字符(point);
  179.         point++;
  180.         if(flg == '/')
  181.         {
  182.             flg = 获得字符(point);
  183.             point++;
  184.             switch(flg)
  185.             {
  186.             case '/'://如果‘/’后面接一个‘/’ 就是注释
  187.                 do
  188.                 {
  189.                     flg = 获得字符(point); 
  190.                     point++;
  191.                 }while(!(flg == '/n' || flg == '/0'));// || ch == '/0'));//注释一直到行尾或文件结束
  192.                 if(flg == '/n')
  193.                     point--;    //归还换行
  194.                 break;
  195.             case '*':
  196.                 do
  197.                 {
  198.                     flg = 获得字符(point); //flg=前一个字符
  199.                     point++;
  200.                     tmpc = flg;
  201.                     //为了保证出错处理程序能正确定位出错位置 保留注释中的换行
  202.                     if(tmpc == '/n')
  203.                         tmp[tmpp++] = tmpc;
  204.                     flg1 = 获得字符(point);//flg1=后一个字符
  205.                     
  206.                 }while(flg != '/0' && !( tmpc == '*' && flg1 == '/'));
  207.                 flg = 获得字符(point);
  208.                 point++;
  209.                 if (flg == '/0')
  210.                 {
  211.                     //ProcError(5);===========================================================================------------------
  212.                     //"注释丢失'*/'"
  213.                 }
  214.                 break;
  215.             default:
  216.                 //不是任何一种注释
  217.                 point--;
  218.                 point--;
  219.                 flg = 获得字符(point);
  220.                 point++;
  221.                 tmp[tmpp++] = flg;
  222.                 flg = 获得字符(point);
  223.                 point++;
  224.                 tmp[tmpp++] = flg;
  225.             }
  226.         }
  227.         else
  228.         {
  229.             tmp[tmpp++] = flg;
  230.         }
  231.     }while(flg != '/0');
  232.     tmp[tmpp] = '/0';
  233.     strcpy(proBuffer,tmp);
  234. }
  235. bool 获得单词(int *point)
  236. {
  237.     int  code, value;
  238.     char judge;    //这里有个技巧 
  239.     
  240.     int  i = 0;    //辅助
  241.     ch = 获得非空字符(point);//获取一个非空字符 赋值给ch
  242.     if(ch == '/0'return false;//读到了文件尾,则退出
  243.     if (isalpha(ch) || ch == '_')    
  244.     {
  245.         judge='L'//如果ch是“字母”或者“下划线” judge 赋值为L (letter)
  246.     }
  247.     else if (isdigit(ch))
  248.     {
  249.         judge='D';              //如果ch是“数字”  judge 赋值为D (digit)
  250.     }else
  251.     {
  252.         judge=ch;
  253.     }
  254.     switch(judge)
  255.     {
  256.     case 'L':    //ch 是字母时
  257.         {
  258.             *point+=1; 
  259.             while(isalnum(ch) || ch == '_'//只要ch是字母、数字、下划线 则循环()
  260.              {    //标识符
  261.                
  262.               wordget[i++] = ch; //将ch放到wordget中去形成单词
  263.              
  264.               ch=获得字符(*point);
  265.                  *point+=1;  
  266.              }
  267.             wordget[i] = '/0';//成字符串
  268.             *point-=1;    //回退一个字符
  269.             /*
  270.             code = Reserve(wordget);//对wordget字符串查找保留字表 若是一个保留字-返回其编码 否则返回0
  271.             if(code == 0)//wordget这个单词不是一个保留字
  272.             {
  273.                value = InsertId(wordget);//将str串以标识符插入符号表,并返回符号表指针(如果str在符号表中存在 则返回存在的指针)
  274.                pDu->kind  = ID;         //这个单词的类型为“标识符” ID 33
  275.                pDu->value = value;      //其值为 在符号表中的指针位置
  276.             }
  277.             else//wordget这个单词是一个保留字
  278.             {
  279.                pDu->kind = code;       //类型为保留字在保留字表中的位置
  280.                pDu->value = -1;         //其值为-1
  281.                if(0 == strcmp("for", wordget))
  282.                {
  283.                    //printf("dddddff:%d--%d",forstart(point),point);
  284.                    printf("发现一个for循环,/"(/"开始位置%d,/"{/"位置:%d,/"}/"位置:%d:/n",point,forstart(point),forblock(forstart(point)));
  285.                    getBlocksoWT(forstart(point),forblock(forstart(point)),pDu,fin, fout);
  286.                }
  287.             
  288.             }
  289.         
  290.             updatesoWT(wordget);
  291.         */
  292.             return true;
  293.         }
  294.     case 'D':  //ch是数字时
  295.         *point+=1; 
  296.         while(isdigit(ch))//只要下一个字符是数字 则和这个数字连成一个单词
  297.         {
  298.             wordget[i++] = ch;
  299.             ch=获得字符(*point);
  300.              *point+=1;
  301.         }
  302.         wordget[i] = '/0';//成字串
  303.         *point-=1;
  304.         /*
  305.         value = InsertConst(wordget);//将str串以常数插入常量表,并返回常数表指针(如果str在常量表中存在 则返回存在的指针)
  306.         pDu->kind = CONST; //类型为“常量” 34
  307.         pDu->value= value; //其值为wordget在常量表中的指针位置
  308.         */
  309.         return true;
  310. //以下为ch为一下符号的情况( ) [ ] . , !  != ~ sizeof < << <= > >> >= = ==  & && &= | || |= ?: + ++ +=
  311. // - -> -- -= * *= / /= % %= >>= <<= ^ ^=
  312.     case '"'//ch是"时 接下来的应该是个字符串
  313.         //字符串常量
  314.         do
  315.         {
  316.             wordget[i++] = ch;
  317.             *point+=1;
  318.             ch=获得字符(*point);
  319.             
  320.         }while(ch != '"' && ch != '/0');// 将“”中的字符串 放入到wordget中去
  321.         wordget[i++] = ch;    
  322.         wordget[i] = '/0';//变成字串
  323.         *point+=1;
  324.         /*
  325.         if(ch == '/0')
  326.         {
  327.             printf("%s",wordget);
  328.             ProcError(3);         //不正确的字符串表达
  329.             pDu->kind = ERROR;    //类型0 
  330.             pDu->value = 0;       //值 0
  331.         }
  332.         else
  333.         {
  334.             value = InsertConst(wordget);  //将wordget串以常数插入常量表,并返回常数表指针
  335.             pDu->kind = CONST;             //类型 常数
  336.             pDu->value = value;            //值  在常数表中的位置
  337.         }
  338.         */
  339.         return true;
  340.         //字符常量
  341.     case '/''://ch是'时 接下来的应该是个字符常量
  342.         wordget[i++] = ch;    // '
  343.         ch=获得字符(++*point);
  344.         
  345.         wordget[i++] = ch;
  346.         if(ch == '//')    // '/n'
  347.         {//如果是转义字符则要多接收一个字符
  348.             ch=获得字符(++*point);         // ch = '
  349.             wordget[i++] = ch;
  350.         }
  351.         ch=获得字符(++*point); 
  352.         wordget[i++] = ch;
  353.         wordget[i] = '/0';//编程字串 '/n'/0
  354.         *point+=1;
  355.         /*
  356.         if(ch != '/'')//'号不配对 则不对
  357.         {//'/b'
  358.             printf("%s",wordget);
  359.             ProcError(2);      //非法的字符
  360.             pDu->kind = ERROR; 
  361.             pDu->value = 0;
  362.         }
  363.         else
  364.         {
  365.             value = InsertConst(wordget); //将wordget串以常数插入常量表,并返回常数表指针
  366.             pDu->kind = CONST;
  367.             pDu->value = value;
  368.         }*/
  369.         return true;
  370.     case '(':
  371.     case ')':
  372.     case '[':
  373.     case ']':
  374.     case '.':
  375.     case ',':
  376.     case '~':
  377.     case '?':
  378.     case ':':
  379.     case ';':
  380.     case '{':
  381.     case '}':
  382.     case '#':
  383.         wordget[i++] = ch;    
  384.         wordget[i] = '/0';
  385.         *point+=1;
  386.         /*
  387.         pDu->kind = DIVIDE; //界符
  388.         pDu->value = -1;    //界符的时候 -1
  389.         */
  390.         return true;
  391.     case '!':
  392.         //!=
  393.         wordget[i++] = ch;
  394.         ch=获得字符(++*point); 
  395.         if (ch=='=') wordget[i++] = ch;
  396.         else *point-=1;
  397.         wordget[i]='/0';
  398.         
  399.         break;
  400.     case '<':
  401.         // << <=
  402.         wordget[i++] = ch;
  403.         ch=获得字符(++*point); 
  404.         if (ch == '<' || ch == '=') wordget[i++] = ch;
  405.         else *point-=1;
  406.         wordget[i]='/0';
  407.         
  408.         break;
  409.     case '>':
  410.         // >> >=
  411.         wordget[i++] = ch;
  412.          ch=获得字符(++*point); 
  413.         if (ch == '>' || ch == '=') wordget[i++] = ch;
  414.         else *point-=1;
  415.         wordget[i]='/0';
  416.         
  417.         break;
  418.     case '=':
  419.         // ==
  420.         wordget[i++] = ch;
  421.         ch=获得字符(++*point); 
  422.         if (ch == '=') wordget[i++] = ch;
  423.         else *point-=1;
  424.         wordget[i]='/0';
  425.         
  426.         break;
  427.     case '&':
  428.         // && &=
  429.         wordget[i++] = ch;
  430.        ch=获得字符(++*point); 
  431.         //if (ch == '&' || ch == '=') wordget[i++] = ch;
  432.         if (ch !=' ') wordget[i++] = ch;
  433.         else *point-=1;
  434.         wordget[i]='/0';
  435.         
  436.         break;
  437.     case '|':
  438.         // || |=
  439.         wordget[i++] = ch;
  440.         ch=获得字符(++*point); 
  441.         if (ch == '|' || ch == '=') wordget[i++] = ch;
  442.         else *point-=1;
  443.         wordget[i]='/0';
  444.         
  445.         break;
  446.     case '+':
  447.         // ++ +=
  448.         wordget[i++] = ch;
  449.         
  450.         ch=获得字符(++(*point)); 
  451.         if (ch == '+' || ch == '=') wordget[i++] = ch;
  452.         else *point-=1;
  453.         wordget[i]='/0';
  454.         
  455.         break;
  456.     case '-':
  457.         // -- -= ->
  458.         wordget[i++] = ch;
  459.         ch=获得字符(++*point); 
  460.         if (ch == '-' || ch == '=' || ch == '>') wordget[i++] = ch;
  461.         else *point-=1;
  462.         wordget[i]='/0';
  463.         
  464.         break;
  465.     case '*':
  466.         // ** *=
  467.         wordget[i++] = ch;
  468.         ch=获得字符(++*point); 
  469.         if (ch == '*' || ch == '=') wordget[i++] = ch;
  470.         else *point-=1;
  471.         wordget[i]='/0';
  472.         
  473.         break;
  474.     case '/':
  475.         // /=
  476.         wordget[i++] = ch;
  477.         ch=获得字符(++*point); 
  478.         if (ch == '=') wordget[i++] = ch;
  479.         else *point-=1;
  480.         wordget[i]='/0';
  481.         
  482.         break;
  483.     case '%':
  484.         // %=
  485.         wordget[i++] = ch;
  486.         ch=获得字符(++*point); 
  487.         if (ch == '=') wordget[i++] = ch;
  488.         else *point-=1;
  489.         wordget[i]='/0';
  490.         
  491.         break;
  492.     case '^':
  493.         // ^=
  494.         wordget[i++] = ch;
  495.         ch=获得字符(++*point); 
  496.         if (ch == '=') wordget[i++] = ch;
  497.         else *point-=1;
  498.         wordget[i]='/0';
  499.         
  500.         break;
  501.     case '/0':
  502.         return false;
  503.     default:
  504.         //ProcError(1);
  505.         return false;
  506.     }
  507.     //updatesoWT(wordget);
  508.     //pDu->kind = OPERAT;
  509.     *point+=1;
  510.     return true;
  511. }
  512. void 寻找程序块名(int 开始左括号位置)
  513. {
  514. }
  515. int 返回右括号配对(int 右括号位置)
  516. {
  517.      int flag = 0;//表示开始默认搜索(
  518.      int i = 右括号位置-1;
  519.      while(i > 0)
  520.      {
  521.      
  522.          if(0 == strcmp(")", wordTab[i])&&flag>=0)
  523.                {
  524.                    
  525.                    flag++;//表示开始搜索这个{匹配的}
  526.                }
  527.          
  528.          else if(0 == strcmp("(", wordTab[i])&&flag>=1)
  529.          {
  530.              flag--;
  531.          }
  532.          else if(0 == strcmp("(", wordTab[i])&&flag==0)
  533.          {
  534.              
  535.              return i;
  536.          }
  537.          i--;
  538.      }
  539.     return -1;
  540. }
  541. int 返回左括号配对(int 左括号位置)
  542. {
  543.      int flag = 0;//表示开始默认搜索)
  544.      int i = 左括号位置+1;
  545.      while(i < 单词表长度)
  546.      {
  547.      
  548.          if(0 == strcmp("(", wordTab[i])&&flag>=0)
  549.                {
  550.                    
  551.                    flag++;//表示开始搜索这个{匹配的}
  552.                }
  553.          
  554.          else if(0 == strcmp(")", wordTab[i])&&flag>=1)
  555.          {
  556.              flag--;
  557.          }
  558.          else if(0 == strcmp(")", wordTab[i])&&flag==0)
  559.          {
  560.              
  561.              return i;
  562.          }
  563.          i++;
  564.      }
  565.     return -1;
  566. }
  567. int 返回左大括号配对(int 左大括号位置)
  568. {
  569.       int flag = 0;//表示开始默认搜索}
  570.      int i = 左大括号位置+1;
  571.      while(i < 单词表长度)
  572.      {
  573.      
  574.          if(0 == strcmp("{", wordTab[i])&&flag>=0)
  575.                {
  576.                    
  577.                    flag++;//表示开始搜索这个{匹配的}
  578.                }
  579.          
  580.          else if(0 == strcmp("}", wordTab[i])&&flag>=1)
  581.          {
  582.              flag--;
  583.          }
  584.          else if(0 == strcmp("}", wordTab[i])&&flag==0)
  585.          {
  586.              
  587.              return i;
  588.              
  589.          }
  590.          i++;
  591.      }
  592.      return -1;
  593. }
  594. void 分割程序()
  595. {
  596.     int flag = 0;//表示开始默认搜索{
  597.     int i = 0;
  598.      while(i<单词表长度)
  599.      {
  600.      
  601.          if(0 == strcmp("{", wordTab[i])&&flag==0)//发现一级{
  602.                {
  603.                    if(0 == strcmp(")", wordTab[i-1]))//只有{前紧跟着()的才是一个块,块一般是指函数
  604.                    {
  605.                         int ff = 返回右括号配对(i-1)-1;
  606.                   
  607.                          strcpy(块名表[块表长度], wordTab[ff]);
  608.                          块开始位置[块表长度]=i;
  609.                          块结束位置[块表长度]=返回左大括号配对(i);
  610.                         //printf("发现一个块,块名字:%s,块开始位置:%d,结束位置:%d",wordTab[ff],i,返回左大括号配对(i));
  611.                         if(是否输出详情)
  612.                         {
  613.                             printf("/n发现一个块,块名字:%s,块开始位置:%d,结束位置:%d",块名表[块表长度],块开始位置[块表长度],块结束位置[块表长度]);
  614.                         }
  615.                         块表长度++;
  616.                         flag++;//表示开始搜索这个{匹配的}
  617.                    }
  618.                }
  619.          if(0 == strcmp("{", wordTab[i])&&flag>0)//发现非一级{
  620.          {
  621.              flag++;
  622.          }
  623.          if(0 == strcmp("}", wordTab[i])&&flag>1)
  624.          {
  625.              flag--;
  626.          }
  627.          if(0 == strcmp("}", wordTab[i])&&flag==1)
  628.          {
  629.              
  630.              flag--;
  631.          }
  632.          i++;
  633.      }
  634.     
  635. }
  636. void 插入单词表(char *str)
  637. {
  638.     
  639.    
  640.     strcpy(wordTab[单词表指针++], str);
  641.     //return (pointCTB-1);
  642. }
  643. void 建立单词表()
  644. {
  645.     int 指针 = 0;
  646.      while(获得单词(&指针))
  647.      {
  648.         插入单词表(wordget);
  649.         单词表长度++;
  650.      }
  651. }
  652. int 查关键字表(char *str)
  653. {
  654.     int i;
  655.     for(i=0; i<KEYWORD_LEN; ++i)    //从保留字表中查找str串
  656.     {
  657.         if(0 == strcmp(关键字表[i], str))
  658.             return i;    
  659.     }
  660.     return -1;
  661. }
  662. int 查函数名表(char *str)
  663. {
  664.     int i;
  665.     for(i = 0; i < 块表长度; ++i)    //从函数名表中查找str串
  666.     {
  667.         if(0 == strcmp(顺序块名表[i], str))
  668.             return i;    
  669.     }
  670.     return -1;
  671. }
  672. float 查指令表返回权值(char *str)
  673. {
  674.     int i;
  675.     int 位置 = -1;
  676.     for(i=0; i<OP_LEN; ++i)    //从保留字表中查找str串
  677.     {
  678.         if(0 == strcmp(操作指令表[i], str))
  679.             位置 = i;    
  680.     }
  681.     if(位置 == -1)
  682.     {
  683.          return -1;
  684.     }else
  685.     {
  686.         return 指令相对权值[位置];
  687.     }
  688. }
  689. int 分析for起点(int for位置)
  690. {
  691.     int 分析点 = for位置+1;
  692.     if(0 == strcmp("(", wordTab[分析点]))
  693.     {
  694.         分析点=返回左括号配对(分析点)+1;
  695.     }else
  696.     {
  697.         发现语法错误();
  698.         return -1;
  699.     }
  700.     return 分析点;
  701. }
  702. int 分析for终点(int for位置)
  703. {
  704.     int 分析点 = 分析for起点(for位置);
  705.     
  706.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  707.     {
  708.          return 返回左大括号配对(分析点);
  709.     }
  710.     else if(0 == strcmp("if", wordTab[分析点]))
  711.     {
  712.         int if的终点;
  713.         if块分支数(分析点,if的终点);
  714.         return if的终点;
  715.     }
  716.     else if(0 == strcmp("for", wordTab[分析点]))
  717.     {
  718.         return 分析for终点(分析点);
  719.     }
  720.     else
  721.     {//for后面没有{}块 只跟一条语句
  722.         while(0 != strcmp(";", wordTab[分析点]))
  723.         {
  724.            分析点++;
  725.         }
  726.         return 分析点;
  727.     }
  728. }
  729. int 分析for条件点(int for位置)
  730. {
  731.     int 分析点 = for位置 + 1;
  732.     
  733.     while(0 != strcmp(";", wordTab[分析点]))
  734.     {//找到第一个";"
  735.         
  736.       分析点++;
  737.     }
  738.     分析点++;
  739.     while(0 != strcmp(";", wordTab[分析点]))
  740.     {//找到第二个";"
  741.         
  742.       分析点++;
  743.     }
  744.     return 分析点;
  745. }
  746. int 分析for循环次数(int for位置)
  747. {
  748.      int 分析点 = for位置+1;
  749.      int 开始条件,结束条件,次数;
  750.     if(0 == strcmp("(", wordTab[分析点]))
  751.     {
  752.         /**
  753.         for(i=0;i<n;i++) 只能分析一下这个情况下的循环次数,并且只有n是一个常数的时候才分析
  754.         */
  755.         if(  (0 == strcmp(wordTab[分析点+1], wordTab[分析点+5]))  &&  (0 == strcmp(wordTab[分析点+5], wordTab[分析点+9]))  &&  是否为数字(wordTab[分析点+3])  &&  是否为数字(wordTab[分析点+7])  &&  ((0 == strcmp("++", wordTab[分析点+10]))||(0 == strcmp("--", wordTab[分析点+10]))))
  756.         {   
  757.              结束条件 = 字串变数字(wordTab[分析点+7]);
  758.              开始条件 = 字串变数字(wordTab[分析点+3]);
  759.              if(0 == strcmp("++", wordTab[分析点+10]))
  760.              {
  761.                   次数 = 结束条件-开始条件;
  762.              }else
  763.              {
  764.                   次数 = 开始条件-结束条件;
  765.              }
  766.              if(次数>0)
  767.              return 次数;
  768.              else
  769.              return 0;//起始条件都不满足 则这个循环不开始
  770.         }else//其他的情况不好分析,默认循环“循环体默认计数”次,这个参数应该是个可以调整的多次调整以得到最好的预测结果
  771.         {
  772.              return 循环体默认计数;
  773.         }
  774.         
  775.         
  776.     }else
  777.     {
  778.         发现语法错误();
  779.         return -1;
  780.     }
  781.     
  782. }
  783. int 分析if起点(int if位置)
  784. {
  785.     int 分析点 = if位置+1;
  786.     if(0 == strcmp("(", wordTab[分析点]))
  787.     {
  788.         分析点=返回左括号配对(分析点) + 1;
  789.     }else
  790.     {
  791.         发现语法错误();
  792.         return -1;
  793.     }
  794.     return 分析点;
  795. }
  796. int 块后面一个单词(int 块起点)
  797. {
  798.     int 分析点;
  799.     分析点 = 块起点;//此时分析点在if条件括号后面一个单词
  800.     if(0==strcmp("{",wordTab[分析点]))
  801.     {//if语句后面有{}
  802.         分析点=返回左大括号配对(分析点);
  803.     }else
  804.     {//if语句后面直接接一个语句的
  805.         while(0 != strcmp(";", wordTab[分析点]))
  806.         {
  807.            分析点++;
  808.         }//循环完后 分析点 指向;
  809.         
  810.     }
  811.     return ++分析点;
  812. }
  813. int if块分支数(int if位置,int *if终点)
  814. {
  815.     int 分支 = 1;
  816.     int 块结束下一位置 = 块后面一个单词(分析if起点(if位置));
  817.     while(0==strcmp("else",wordTab[块结束下一位置]))
  818.     {
  819.         分支++;
  820.         if(0 == strcmp("if",wordTab[块结束下一位置+1]))
  821.         {
  822.             块结束下一位置 = 块后面一个单词(分析if起点(块结束下一位置+1));
  823.         }else
  824.         {
  825.             块结束下一位置 = 块后面一个单词(块结束下一位置+1);
  826.             break;
  827.         }
  828.     }
  829.     *if终点 = 块结束下一位置-1;
  830.     if(分支 == 1) 分支 = 2;
  831.     return 分支;
  832. }
  833. int 分析while起点(int while位置)
  834. {
  835.     int 分析点 = while位置 + 1;
  836.     if(0 == strcmp("(", wordTab[分析点]))
  837.     {
  838.         分析点 = 返回左括号配对(分析点)+1;
  839.     }else
  840.     {
  841.         发现语法错误();
  842.         return -1;
  843.     }
  844.     return 分析点;
  845. }
  846. int 分析while终点(int while位置)
  847. {
  848.     int 分析点 = 分析while起点(while位置);
  849.     
  850.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  851.     {
  852.          return 返回左大括号配对(分析点);
  853.     }
  854.     else
  855.     {//for后面没有{}块 只跟一条语句
  856.         while(0 != strcmp(";", wordTab[分析点]))
  857.         {
  858.            分析点++;
  859.         }
  860.         return 分析点;
  861.     }
  862. }
  863. int 分析switch起点(int switch位置)
  864. {
  865.     int 分析点 = switch位置 + 1;
  866.     if(0 == strcmp("(", wordTab[分析点]))
  867.     {
  868.         分析点 = 返回左括号配对(分析点)+1;
  869.     }else
  870.     {
  871.         发现语法错误();
  872.         return -1;
  873.     }
  874.     return 分析点;
  875. }
  876. int 分析switch终点(int switch位置)
  877. {
  878.     int 分析点 = 分析switch起点(switch位置);
  879.     
  880.     if(0 == strcmp("{", wordTab[分析点]))//for块 以{}出现
  881.     {
  882.          return 返回左大括号配对(分析点);
  883.     }
  884.     else
  885.     {
  886.         发现语法错误();
  887.         return -1;
  888.     }
  889. }
  890. int switch分支数(int switch起点,int switch终点)
  891. {
  892.     int 分析点 = switch起点;
  893.     int sum=0;
  894.     while(分析点 <= switch终点)
  895.     {
  896.        if(0 == strcmp("case", wordTab[分析点]))
  897.        {
  898.           sum++;
  899.        }
  900.        分析点++;
  901.     }
  902.     return sum;
  903. }
  904. float 顺序分析(int 起点,int 终点)
  905. {
  906.     float 该块权值 = 0.0;
  907.     int 当前分析点=起点;
  908.     while(当前分析点 < 终点)
  909.     {
  910.         switch(查关键字表(wordTab[当前分析点]))
  911.         {
  912.             case 13://for
  913.                 {
  914.                     int forend = 分析for终点(当前分析点);
  915.                     int forbegin = 分析for起点(当前分析点);
  916.                     if(forbegin != -1)
  917.                     {
  918.                     int div= 分析for条件点(当前分析点);
  919.                     int times = 分析for循环次数(当前分析点);
  920.                     int forblockWT = 顺序分析(div,forend);
  921.                     int forst = 顺序分析(当前分析点+1,div);
  922.                     该块权值 += forst;
  923.                     该块权值 += times * forblockWT;
  924.                     当前分析点 = forend;
  925.                     if(是否输出详情)
  926.                     {
  927.                         printf("/nfor语句的起点:%d 终点:%d 这个FOR语句的循环次数:%d,该for语句块的权值:%d,总权值 = 条件权值 + for语句块的权值 * 循环次数(%d = %d + %d * %d)",forbegin,forend,times,forblockWT,该块权值,forst,forblockWT,times);
  928.             
  929.                     }
  930.                         //该块权值 += 顺序分析(当前分析点,div)  + 分析for循环次数(当前分析点) * (顺序分析(div,forend));
  931.                     }
  932.                     else
  933.                     {
  934.                         当前分析点 = 单词表长度;
  935.                     }
  936.                     break;
  937.                 }
  938.             case 15://if
  939.                 {
  940.                     if(0 != strcmp("else",wordTab[当前分析点-1])){
  941.                         //如果当前IF是一个if块的第一个if,而不是分支中的 else if
  942.                     int if结束点 = 0 ;
  943.                     int if起点 = 分析if起点(当前分析点);
  944.                     int if分支数 = if块分支数(当前分析点,if结束点);
  945.                     
  946.                     if(if起点 != -1)
  947.                     {
  948.                     
  949.                         if(是否输出详情)
  950.                          {
  951.                              printf("/n发现一个if,该if开始位置:%d 分支数为%d,-----",if起点,if分支数);
  952.                              printf("/n该if块结束位置为:%d,",if结束点);
  953.                         }
  954.                          该块权值 += 顺序分析(if起点,if结束点)/if分支数;
  955.                     }
  956.                     else
  957.                     {
  958.                          当前分析点 = 单词表长度;
  959.                     }
  960.                     当前分析点 = if结束点;
  961.                     }
  962.                     break;
  963.                 }
  964.             case 31://while
  965.                 {
  966.                     
  967.                     int whilebegin = 分析while起点(当前分析点);
  968.                     if(whilebegin != -1)
  969.                     {
  970.                        int whileend = 分析while终点(当前分析点);
  971.                        if(是否输出详情)
  972.                        {
  973.                            printf("/nwhile语句的起点:%d 终点:%d ",whilebegin,whileend);
  974.                        }
  975.                     
  976.                        该块权值 += 循环体默认计数 * 顺序分析(whilebegin,whileend);
  977.             
  978.             
  979.                        当前分析点 = whileend;
  980.                     }
  981.                     else
  982.                     {
  983.                         当前分析点 = 单词表长度;
  984.                     }
  985.                     break;
  986.                 }
  987.             case 25://switch
  988.                 {   int switchbegin = 分析switch起点(当前分析点);
  989.                     int switchend = 分析switch终点(当前分析点);
  990.                     int fenzhi = switch分支数(switchbegin,switchend);
  991.                      
  992.                     if((switchbegin != -1) && (switchend != -1))
  993.                     {
  994.                         if(是否输出详情)
  995.                         {
  996.                             printf("/n发现一个switch,该switch开始位置:%d 分支数为%d,-----",switchbegin,fenzhi);
  997.                             printf("/n该if块结束位置为:%d,",switchend);
  998.                         }
  999.                         该块权值 += (顺序分析(switchbegin,switchend) / fenzhi);
  1000.                         当前分析点 = switchend;
  1001.                     }
  1002.                     else
  1003.                     {
  1004.                         当前分析点 = 单词表长度;
  1005.                     }
  1006.                 }
  1007.             case -1://不是一个关键字
  1008.                 {
  1009.                     int temp = 查函数名表(wordTab[当前分析点]);
  1010.                     if(temp != -1)
  1011.                     {//如果是一个函数,则用前面分析到的这个函数的权值 作为这个关键字的权值
  1012.                         if(是否输出详情)
  1013.                         {
  1014.                             printf("/n发现一个函数,当前分析点:%d, 函数名:%s:权值: %f/n",当前分析点,wordTab[当前分析点],块权值[temp]);
  1015.                         }
  1016.                         该块权值 += 块权值[temp];
  1017.                     }
  1018.                     
  1019.                     else if(查指令表返回权值(wordTab[当前分析点]) != -1)
  1020.                     {
  1021.                         if(是否输出详情)
  1022.                         {
  1023.                             printf("/n当前分析点:%d, 单词:%s:权值: %f=====%f/n",当前分析点,wordTab[当前分析点],查指令表返回权值(wordTab[当前分析点]),该块权值);
  1024.                         }
  1025.                         该块权值 += 查指令表返回权值(wordTab[当前分析点]);
  1026.                     }
  1027.                 
  1028.                 
  1029.                 }
  1030.             default:break;
  1031.         }
  1032.         当前分析点++;
  1033.     }
  1034.     
  1035.     return 该块权值;
  1036. }
  1037. int 按函数名查找函数表(char *str)//如果在函数表里 就返回在“块名表”里的位置
  1038. {
  1039.     int i;
  1040.     for(i=0;i<块表长度;i++)
  1041.     {
  1042.         if(0 == strcmp(str,块名表[i]))
  1043.         {
  1044.             return i;
  1045.         }
  1046.     }
  1047.     return -1;
  1048. }
  1049. void 块名表调序(int 新顺序,int 老位置)
  1050. {
  1051.     //顺序块名表[新顺序] = 块名表[老位置];
  1052.     strcpy(顺序块名表[新顺序],块名表[老位置]);
  1053.     
  1054.     strcpy(块名表[老位置],"");
  1055.     顺序块开始位置[新顺序] = 块开始位置[老位置];
  1056.     顺序块结束位置[新顺序] = 块结束位置[老位置];
  1057.     
  1058. }
  1059. void 按函数出现顺序排序()
  1060. {
  1061.     int 当前分析点 = 0;
  1062.     int i=0,j=0;
  1063.     while(当前分析点 < 单词表长度)
  1064.     {
  1065.         i = 按函数名查找函数表(wordTab[当前分析点]);
  1066.             if(i != -1)
  1067.             {
  1068.                 块名表调序(j,i);
  1069.                 j++;
  1070.             }
  1071.         当前分析点++;
  1072.     }
  1073.     
  1074.     
  1075. }
  1076. //float getSourceWT(int times,bool isprint,String str)
  1077. JNIEXPORT jdouble JNICALL Java_com_swjtu_sourcemanage_SourceScan_getSourceWT(JNIEnv * env, jclass c1, jint times, jboolean isprint, jstring str)
  1078. {
  1079.     循环体默认计数 = times;
  1080.     是否输出详情 = isprint;
  1081.      int i=0;
  1082.     char c;
  1083.    
  1084.         //读入程序();
  1085.     
  1086.     //读入程序1(source);
  1087.     //char* csStr = env->GetStringUTFChars(str,NULL);
  1088.     //char* csStr = GetStringUTFChars(
  1089.        
  1090.         const char* csStr = env->GetStringUTFChars(str,NULL);
  1091.         读入程序1(csStr);
  1092.     预处理();
  1093.    
  1094.     建立单词表();
  1095.     分割程序();
  1096.     按函数出现顺序排序();
  1097.     
  1098.     for(int i=0;i<块表长度;i++)
  1099.     {
  1100.         块权值[i] = 顺序分析(顺序块开始位置[i],顺序块结束位置[i]);
  1101.         
  1102.         
  1103.         
  1104.     }
  1105.     if(是否输出详情)
  1106.     {
  1107.         for(int i=0;i<块表长度;i++)
  1108.         {
  1109.             printf("/n块信息:/n%s:%d---%d/n",顺序块名表[i],顺序块开始位置[i],顺序块结束位置[i]);
  1110.             printf("权值:%f",块权值[i]);
  1111.         }
  1112.     }
  1113.     if(是否发现语法错误)
  1114.     {
  1115.         return -1;
  1116.     }
  1117.     else
  1118.     {
  1119.         for(int i=0;i<块表长度;i++)
  1120.         { 
  1121.             if(0==strcmp("main",顺序块名表[i]))
  1122.             {
  1123.                return 块权值[i];
  1124.             }
  1125.         }
  1126.         //没有main块 ,也算是语法错误
  1127.         return -1;
  1128.         
  1129.     }
  1130.     
  1131. }
  1132. /*
  1133. int main()
  1134. {
  1135.     
  1136.     
  1137.      
  1138.     printf("权值---->:%f",getSourceWT(90,false));
  1139.     
  1140.     
  1141.     printf("/n写入完毕/n按任意键继续/n");    getch();
  1142.     return 0;
  1143. }
  1144. */

        步骤四:生成DLL文件 使用命令:cl -IC:/include -LD com_swjtu_sourcemanage_SourceScan.cpp -FeSourceScan.dll如果执行过程中出现找不到头文件错误,则将该头文件所在目录加入到命令中(如-IC:/include,目录名不要有空格),如果执行过程出现打不开lib文件错误,则将相应的文件拷贝到C:/c文件夹下。成功后生成SourceScan.dll,将这个文件拷贝到com文件同目录。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值