C言語関係掲示板

過去ログ

No.336.コメント文の削除

[戻る] [ホームページ]
No.2129

コメント文の削除
投稿者---未熟者(2002/07/19 02:09:59)


ある文字列からコメント文を削除するプログラムを作りたいのですが、うまくいきませんでした。
文字列の入力:abcd/*comment*/efgh/*comment*/ijklm
コメント文削除後:abcdefghijklm

とゆような実行例にしたいのですが。

#include <stdio.h>
#include <string.h>

int main(void)
{
char str1[128], str2[128]="/*comment*/;
char str3[128] = "";
char *p1 = str1, *p2;
size_t len;

printf("対象文字列の入力 ");
scanf("%s",str1);

len = strlen(str2);

while((p2 = strstr(p1,str2)) != NULL) {
strncat(str3,p1,p2 - p1);
p1 = p2 + len;
}
strcat(str3,p1);
printf("%s\n",str3);

return(0);
}

とやったのですが、うまく取り除けませんでした。
なるべくポインタを使わずにやりたいのですが、どなたかヒントを下さい。

No.2130

Re:コメント文の削除
投稿者---snow(2002/07/19 08:50:42)


ども、snowです。
これ実行してみましたが、普通に動きました。
1箇所修正しましたが。

str2[128]="/*comment*/;

これ、終わりの"が足りません。
正しくは

str2[128]="/*comment*/";
です。
こうしないとバグが出ると思うのですがいかがでしょうか?
あと、コメント文の削除って言うタイトルは語弊があると思うのですが。
どちらかといえば、指定文字列の削除だと思います。

No.2131

追加:指定文字列の削除
投稿者---未熟者(2002/07/19 10:15:52)


snowさんアドバイスに訂正ありがとうございます!
感謝します。

このプログラムだと/*comment*/は削除されるんですけど、
例えば,/*ポインタの指定*/などコメント文を変えても
削除するようにしたかったのですけど、これは無理なんですか?

すみませんが、わかる方またお願い致します。

No.2132

Re:追加:指定文字列の削除
投稿者---TDa(2002/07/19 18:05:23)


>このプログラムだと/*comment*/は削除されるんですけど、
>例えば,/*ポインタの指定*/などコメント文を変えても
>削除するようにしたかったのですけど、これは無理なんですか?
>すみませんが、わかる方またお願い致します。

たぶんソースの中のコメントを削除したいという意味ですよね。

それならばfileを読んでいって"/*"が見つかったら"*/"が見つかるまで読み飛ば
すようにしなければなりません。ただし文字列リテラルの中の"/*", "*/"
コメント中の"/*"の処理をお忘れ無く。

ANSI-Cのコメントは入れ子を許さないのでそういう意味では楽です。

No.2133

ソース中のコメント文削除
投稿者---未熟者(2002/07/19 18:23:40)


TDaさんありがとうございます。
ソース中のコメント文を消したかったんです。

ですが、最初の「/*」以降が全部消えてしまうんですけれども。

for(i = 0; str[i] != NULL ;i++){
if( !(str[i] == '/' && str[i+1] == '*'){
   buff[i] = str[i]

コメント文じゃない文字列をbuffに入れておいて、コメント文中はbuffに入れないというようなやり方でコメントを削除しようと思ったのですが、うまくいきませんでした。

何回もすみませんがわかる方アドバイスよろしくお願い致します。

No.2134

Re:ソース中のコメント文削除
投稿者---Aki(2002/07/19 20:39:11)


#include <stdio.h>

#define STR_MAX     1000

int main(void)
{
    char    str[STR_MAX];
    int     incom, i;

    printf("文字列の入力:");
    fgets(str, sizeof str, stdin);

    printf("コメント文削除後:");
    incom = 0;
    for (i = 0; str[i]; i++)
        if (incom == 0) {
            if (str[i] == '/' && str[i+1] == '*') {
                incom = 1;
                i++;
            } else
                putchar(str[i]);
        } else if (str[i] == '*' && str[i+1] == '/') {
                incom = 0;
                i++;
        }
    return 0;
}


No.2135

Re:追加:指定文字列の削除
投稿者---かずま(2002/07/19 20:56:12)


状態遷移を使ってみました。有限オートマトンですね。
    printf("abc /* def */ ghi");
も大丈夫。
#include <stdio.h>

enum State { INITIAL, SLASH, COMMENT, ASTERISK, STRING, ESCAPE };
enum State state = INITIAL;
int quote;

void delete_comment(const char *s1, char *s2)
{
    int c;

    while (c = *s1++) {
        switch (state) {
        case INITIAL:
            if (c == '/') { state = SLASH; break; }
            if (c == '"' || c == '\'') { quote = c; state = STRING; }
            *s2++ = c; break;
        case SLASH:
            if (c == '*') { state = COMMENT; break; }
            *s2++ = '/';
            if (c == '/') break;
            *s2++ = c; state = INITIAL; break;
        case COMMENT:
            if (c == '*') state = ASTERISK;
            break;
        case ASTERISK:
            if (c == '/') { state = 0; break; }
            if (c == '*') break;
            state = COMMENT; break;
        case STRING:
            *s2++ = c;
            if (c == quote) { state = INITIAL; break; }
            if (c == '\\') { state = ESCAPE; break; }
            break;
        case ESCAPE:
            *s2++ = c;  state = STRING; break;
        }
    }
    *s2 = '\0';
}

int main()
{
    char buf[1024];

    while (fgets(buf, sizeof buf, stdin)) {
        delete_comment(buf, buf);
        fputs(buf, stdout);
    }
    return 0;
}

実は、このプログラムは、現在の C の規格に合わないところがあります。
abc/*def*/ghi が abcghi になってしまいますが、abc ghi のようにくっつかないのが本当です。

なお、C では、コメントは「文」でありません。

No.2145

Re:追加:指定文字列の削除
投稿者---未熟者(2002/07/22 12:02:00)



Akiさん、かずまさん色々な解答方法と考え方を示してくださってありがとうございました!

Akiさんのソースだと、aaa /*bbb*/ cccのようにコメントの前に空白を入れた場合うまく削除されなかったんですけれども、どこが原因なのか私のはわかりませんでした。またよろしければ教えてください。

かずまさんのソースは私の使用しているコンパイラでは警告が出てうまくコンパイルされませんでした。せっかく作って頂いたソースなのに申し訳ないです。



No.2146

Re:追加:指定文字列の削除
投稿者---かずま(2002/07/22 13:57:22)


> Akiさんのソースだと、aaa /*bbb*/ cccのようにコメントの前に空白を入れた場合うまく
> 削除されなかったんですけれども、どこが原因なのか私のはわかりませんでした。

うまく削除されないだけでは分かりません。どうなったかを書いてください。
本当に Aki さんのソースそのままで、そんなことになるんでしょうか。
文字列の入力 fgets(str, sizeof str, stdin); を勝手に scanf("%s", str); に変えた
とかじゃないんでしょうか。


> かずまさんのソースは私の使用しているコンパイラでは警告が出てうまくコンパイル
> されませんでした。

私は超能力者じゃありませんから、質問者の使用しているコンパイラやそれが出す警告を
察知することが出来ません。そういう基本情報を書いて質問をするのが正しいマナーです。
エラーメッセージやソースプログラムは、改変せず copy & paste するのがよいでしょう。

私のプログラムで警告が出るのは、まず while (c = *s1++) { だと思いますが、
これは、while ((c = *s1++) != '\0') { と書き換えれば警告は出なくなります。
他では、state = INITIAL; とかくべきところを一か所 state = 0; と書いていることろ。

でも、警告だけでエラーがないと、コンパイルは完了するはずですが、そうではないので
しょうか。