3

標準入力として提供されているCプログラムからのコメントの文字数を数える必要があります。これは私の機能ですが、何らかの理由で正しくカウントされていません。手伝ってくれませんか。

int characters(FILE *file)
{
     int i=0;
     char ch[500], *p;
     while (fgets(ch, sizeof(ch),file)!=NULL)
     {
        p=ch;
        while (*p)
        { 
           if (*p=='/')
           { 
              p++;
              if (*p=='*')
              {
                 p++;
                 while (*p!='*' && *(p++)!='/')
                 {
                    i++;
                    p++;
                 }
              }
           }
           else
              p++;

         }


   return i;
}
4

5 に答える 5

5

問題は最も内側のループにあると思います:

while (*p!='*' && *(p++)!='/')

する必要があります

while (*p!='*' && *(p+1)!='/')

しかし、次のようなものが表示されると、これは壊れます。

/* comment * */

条件の最初の部分は*p!='*'最初のアスタリスクで false になるため、代わりに次のようにすることができます。

while (!(*p=='*' && *(p+1)=='/')) {
   p++;
   i++;
}

注: 行が壊れていると、セグメンテーション違反が発生します。

    /* comment * \n
    */

それでも対処する必要がありますが*p、内側のループに追加する必要があります。

while (*p && !(*p=='*' && *(p+1)=='/')) {
   p++;
   i++;
}
于 2012-11-14T15:21:33.853 に答える
1

あなたのコードは私を怖がらせました。

多くのポインターが進行中であり、ネストされたループがありました。

ロジックを間違えやすく、変更が必要な場合にコードを拡張するのは困難です。

別の解決策を提案できますか?

ステートマシン

一度に 1 文字ずつファイルを読み込み、マシンの状態を追跡します。次に、これを使用して、コメントに含まれているかどうかを判断します。

#include <cstdio>
#define S_CODE          1
#define S_ONESLASH      2
#define S_LINECOMMENT   3
#define S_BLOCKCOMMENT  4
#define S_BLOCKSTAR     5

int characters(FILE *file){
    int ccount=0;
    char ch;
    int state=S_CODE;
     while ((ch=fgetc(file))!=EOF){
        switch(state){
            case S_CODE:
                if (ch=='/')
                    state=S_ONESLASH;
                break;

            case S_ONESLASH:
                if (ch=='/')
                    state=S_LINECOMMENT;
                else if (ch=='*')
                    state=S_BLOCKCOMMENT;
                else
                    state=S_CODE;
                break;

            case S_LINECOMMENT:
                if (ch=='\n')
                    state=S_CODE;
                else
                    ccount++;
                break;

            case S_BLOCKCOMMENT:
                if (ch=='*')
                    state=S_BLOCKSTAR;
                ccount++;
                break;

            case S_BLOCKSTAR:
                if (ch=='/')
                    state=S_CODE;
                else if (ch=='*')
                    state=S_BLOCKSTAR;
                else
                    state=S_CODE;
                ccount++;
                break;
        }
    }
    return ccount;
}

int main(int argc, char **argv){
    FILE *fin=fopen(argv[1],"r");
    printf("%d\n",characters(fin));
}

文字/*およびを使用して\n、マシンのさまざまな状態間の遷移をマークする方法と、一部の状態ではコメント文字カウンターをインクリメントする方法に注意してください。ここで何が起こっているのかを追跡する方がはるかに簡単だと思います。

于 2012-11-14T15:51:52.980 に答える
1

これがあなたの問題だと思います:

while (*p!='*' && *(p++)!='/')

インクリメントp++のの値に評価されることを思い出してください。実際には、テストはp

while (*p != '*' && *p != '/')

したがって、 が と*p評価された場合*、テストは失敗します。それをに変更します

while (*p != '*' && *(++p) != '/')
于 2012-11-14T15:24:57.307 に答える
0

すでに述べたように、while (*p!='*' && *(p++)!='/') この場合、問題は一致しています。ステートメント(*(p++)!='/')の2番目の部分は、最初の部分が「起動」した場合にのみ評価されるためp、アスタリスクが見つかった場合は増分されます。

于 2012-11-14T15:33:06.753 に答える
0

それは働いているようです

int characters(FILE *file)
{
    int i = 0;
    char ch[500], *p;
    fread(ch, sizeof(char), 500, file);
    p = ch;
    while (*p)
    {
        if (*p=='/' && *(p+1) == '*')
        { 
            while (*p && (*p != '*' && *(p+1) != '/')) 
                ++p;
            ++i;
        }
        ++p;
    }
    return i;
}
于 2012-11-14T15:42:03.917 に答える