使用C语言计算程序中的标签数

使用C语言计算程序中的标签数,c,labels,C,Labels,我曾尝试使用C本身计算C程序中存在的标签数量。它工作得很好。我将其扩展为,我有一个数组ca[],其中包含行号作为元素。读取相应的行时,不应在该行中搜索标签。这背后的概念是,我将从另一个程序接收一个数组,其中包含注释行的行号。因此,我将获取数组作为输入,并跳过单独处理这些行 我试过的是 int nl=0,flag=0,i=1,j=0; int ca[100]={3,5}; char c; fp=fopen("chumma.c","r"); while((c=getc(fp))!=EOF) {

我曾尝试使用C本身计算C程序中存在的标签数量。它工作得很好。我将其扩展为,我有一个数组
ca[]
,其中包含行号作为元素。读取相应的行时,不应在该行中搜索标签。这背后的概念是,我将从另一个程序接收一个数组,其中包含注释行的行号。因此,我将获取数组作为输入,并跳过单独处理这些行

我试过的是

int nl=0,flag=0,i=1,j=0;
int ca[100]={3,5};
char c;

fp=fopen("chumma.c","r");

while((c=getc(fp))!=EOF)
{
if(c=='\n')
    i=i+1;
if((ca[j])!=i)
{

    if(c==':')
        flag=1;

    else if((flag==1) && (c=='\n'))
    {      
      flag=0;nl++;
    }

}
else
   j++;
}

nl
是标签的数量。这不会检查线路本身。请告诉我哪里出了问题。

这听起来像是家庭作业/学习练习,因此我将解释规划/设计这样一个程序的过程。然后我将给您一个实现它的方法的示例

编写此类程序的一种方法是构建一对状态机:

  • 初始状态/空白状态
  • 从状态1开始:已看到
    /*
    序列;保持此状态直到
    */
    ;返回到1
  • 从状态1开始:已看到
    字符;保持此状态直到
    \
    ;返回到1
  • 从状态1开始:已看到
    /
    序列;保持这种状态直到换行;返回到1
  • 来自状态1:看到一封信;保持这种状态直到非字母和非数字
  • 从状态1开始:如果你还看到了什么,就呆在这个状态直到换行
  • 从状态3:看到
    \
    提取下一个字符,然后返回状态3
  • 一旦离开第5国:

    • 如果单词是
      switch
      ,我们将进入另一个状态机(如下)
    • 如果我们没有看到
      ,则返回状态1
    • 否则我们的话就是一个标签;你想用它做什么就做什么,然后回到状态1
    但是,当我们看到
    开关时,我们需要另一个状态表,因为后面紧跟着一个表达式:

  • 初始状态/空白
  • 从状态1开始:
    开关之后启动
  • 从状态1开始:所有其他字符生成一个错误
  • 从状态2:
    /*
    被视为状态机1(如上所述)
  • 从状态2:
    查看
  • 从状态5:
    {
    -增加嵌套级别并立即转到状态7
  • 空白/状态
  • 从状态7开始:
    }
    -在进入该状态时降低嵌套级别;如果嵌套级别为零,则在第一个状态机中返回状态1,否则保持状态7
  • 从状态7:已看到一个字母;保持此状态直到非字母或
  • 从状态7开始:如果看到任何其他情况,请保持此状态,直到分别移动到状态7和状态8为止
  • 一旦离开第9国:

    • 如果我们没有看到
      ,则转到状态10
    • 否则,如果单词为默认值,则转到状态10
    • 否则,这是一个标签;使用它做任何你想做的事情,然后转到状态10
    下一步是为每个状态编写一个函数。对状态进行编号并给出函数编号可能会有所帮助。它们对“字符”或“字符序列”的操作方式通常与我之前编写的一些低级内容有关:

    int c;
    int next() { c=getchar(); return c; }
    typedef int (*state)();
    
    例如,上面的状态2和状态3可以写成:

    state state2() { if(c == '*' && next() == '/') return state1; return state2; }
    state state3() { if(c == '"') return state1; if (c == '\\') return state7; }
    
    计算出其余的状态应该很容易。状态5将有一个缓冲区,您将填充该缓冲区以“读取”单词:

    char word[600];
    int ptr;
    state state5() { 
      ptr = 0;
      while(isdigit(c) || isalpha(c)) {
        word[ptr] = c;
        ptr++;
        if(ptr==600)abort();
        next();
      }
      /* now leaving state 5 */
    }
    
    完成此操作后,可以编写驱动程序:

    void statemachine1() {
      state x = state1;
      while(c != -1) x = x();
    }
    
    如果您犯了错误,使用一些调试工具会很有帮助。一个好的方法是标记数组中的每个状态:

    state statelist1[] = { state1, state2, state3, state4, state5, state6, state7 };
    int statenumber(state x) {
      int i, n = sizeof(statelist1) / sizeof(state);
      while(n-->0) if(x == statelist1[n]) return n;
      abort();
    }
    
    这在调试时会很有帮助;我可以插入:

    printf("state = %d, char = %02x (%c)\n", statenumber(x), c,c);
    
    进入驱动程序循环,类似这样:

    printf("char = %02x (%c)\n", c,c);
    
    在我跟踪机器的各个部分。这将在我的脑海中建立一个更牢固的状态机地图,当我沿着我的测试程序跟踪它时,它将使验证所有状态变得更容易

    如果事情开始变得困难,我将修改
    next()
    ,以跟踪当前行:

    int line = 1;
    int next() { c=getchar(); if(c == '\n') line++; return c; }
    
    这样,我也可以在我的
    printf()
    语句中使用它

    一旦我对工作感到满意,我将删除调试代码


    祝你好运!

    这听起来像是家庭作业/学习练习,所以我将解释规划/设计这样一个程序的过程。然后我将给你一个实现它的方法示例

    编写此类程序的一种方法是构建一对状态机:

  • 初始状态/空白状态
  • 从状态1开始:已看到
    /*
    序列;保持此状态直到
    */
    ;返回到1
  • 从状态1开始:已看到
    字符;保持此状态,直到
    \
    ;返回到1
  • 从状态1:已看到
    /
    序列;保持此状态直到换行;返回到1
  • 从状态1:看到一个字母;一直保持这种状态,直到非字母和非数字
  • 从状态1开始:如果你还看到了什么,就呆在这个状态直到换行
  • 从状态3:看到
    \
    提取下一个字符,然后返回状态3
  • 一旦离开第5国:

    • 如果单词是
      switch
      ,我们将进入另一个状态机(如下)
    • 如果我们没有看到
      ,则返回状态1
    • 否则,我们的词就是一个标签;你想用它做什么就做什么,然后回到状态1
    但是,当我们看到
    开关时,我们需要另一个状态表,因为后面紧跟着一个表达式:

  • 初始状态/空白
  • 从状态1开始:
    开关之后启动
  • 从状态1开始:所有其他字符生成一个错误
  • Fro
    int nl=0,flag=0,i=1,j=0;
    int ca[100]={3,5};
    char c;
    
    fp=fopen("Kiss.c","r");
    
    while ((c=getc(fp))!=EOF) {
    
    if (c == '\n') {
        if (ca[j] == i) j ++;
    
        if (flag == 1) {      
            flag = 0; nl ++;
        }
    
        i = i ++;
        continue;
    }
    
    if (ca[j] == i)
        continue;
    
    if (c==':')
        flag=1;