2014年11月02日

C#で コメントの削除

   このエントリーをはてなブックマークに追加 Clip to Evernote
どう書く?orgに感謝を込めて」シリーズ その45

■問題 (出題者:nobsun さん)
ソースコードからコメント部分を削除するプログラム decomment を書いてください. すくなくとも,decomment を記述したのと同じ言語で書かれているソースコードが 扱えるようにしてください.

DeComentクラスをStateマシン風に書いてみました。
ただし、Stateクラスを定義するのではなく、delegateで Stateを表現しています。
ラムダ式使えるので、なんかいい感じです。
ちゃんと、C#の文字列リテラルの中の // や、 /* はコメントと認識しなようになってます。
でも、//で始まるコメント行が、削除されずに空白行となるのが、いまいちかな。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Doukaku.Org {
    public class DeComment {
        delegate void Scan(char c);
        private static string result = "";       
        private static Scan eat;

        private static Scan outComment = (c) => {
            if (c == '/')
                eat = preInComment;
            else {
                if (c == '"')
                    eat = InLiteralString;
                result += c;
            }
        };

        private static Scan preInComment = (c) => {
            if (c == '*')
                eat = inMultiLineComment;
            else if (c == '/')
                eat = inOneLineComment;
            else {
                eat = outComment;
                result += "/" + c;
            }
        };

        private static Scan inOneLineComment = (c) => {
            if (c == '\r' || c == '\n') {
                eat = outComment;
                result += c;
            }
        };

        private static Scan inMultiLineComment = (c) => {
            if (c == '*')
                eat = preOutMultiLineComment;
        };

        private static Scan preOutMultiLineComment = (c) => {
            if (c == '/')
                eat = outComment;
            else
                eat = inMultiLineComment;
        };

        private static Scan InLiteralString = (c) => {
            if (c == '"')
                eat = outComment;
            else if (c == '\\')
                eat = InLiteralStringEscape;
            result += c;
        };

        private static Scan InLiteralStringEscape = (c) => {
            eat = InLiteralString;
            result += c;
        };

        public string Execute(string line) {
            result = "";
            eat = outComment;
            foreach (var c in line) {
                eat(c);
            }
            return result;
        }

    }

}

使い方は、こんな感じ。
ファイルから読み込んだテキストを改行コード込みで、そのまま Decommentクラスの Executeメソッドに渡します。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Doukaku.Org {
    class Program {
        static void Main(string[] args) {
            var cc = new DeComment();
            var text = File.ReadAllText("Sample.cs");
            var s = cc.Execute(text);
            Console.WriteLine(s);
            Console.ReadLine();
        }
    }

}


 

この記事へのトラックバックURL

http://trackback.blogsys.jp/livedoor/gushwell/52383412