/*コメント*/を取り除く
Posted feedbacks - Nested
Flatten Hidden1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | using System;
using System.Text;
class Program
{
static void Main(string[] args)
{
Console.WriteLine(RemoveBlockComment("AAA"));
Console.WriteLine(RemoveBlockComment("AAA/*/BBB"));
Console.WriteLine(RemoveBlockComment("AAA/*BBB"));
Console.WriteLine(RemoveBlockComment("AAA/*BBB*/CCC"));
Console.WriteLine(RemoveBlockComment("AAA/*BBB/*CCC*/DDD*/EEE"));
Console.WriteLine(RemoveBlockComment("AAA/a//*BB*B**/CCC"));
}
static string RemoveBlockComment(string s)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.Length; ++i)
{
if (i < s.Length - 1 && s[i] == '/' && s[i + 1] == '*')
{
i += 3;
while (i < s.Length && (s[i - 1] != '*' || s[i] != '/')) ++i;
}
else sb.Append(s[i]);
}
return sb.ToString();
}
}
|
一番乗りかな?
正規表現は自信が無いので、あってるか不安。
1 2 3 4 5 6 7 8 9 10 11 12 | -*- coding: utf-8 -*-
import re
def remove_comment(comment):
print re.sub(r'/\*.*?((\*/)|($))','',comment, re.M)
remove_comment('AAA')
remove_comment('AAA/*BBB*/')
remove_comment('AAA/*BBB')
remove_comment('AAA/*BBB*/CCC')
remove_comment('AAA/*BBB/*CCC*/DDD*/EEE')
remove_comment('AAA/a//*BB*B**/CCC')
|
一撃必殺!
1 2 3 4 5 6 7 8 9 10 | (require :cl-ppcre)
(defun remove-comment (str)
(ppcre:regex-replace-all "/\\*(.+?)(\\*/|$)" str ""))
(remove-comment "AAA") ; => "AAA"
(remove-comment "AAA/*BBB*/") ; => "AAA"
(remove-comment "AAA/*BBB") ; => "AAA"
(remove-comment "AAA/*BBB*/CCC") ; => "AAACCC"
(remove-comment "AAA/*BBB/*CCC*/DDD*/EEE") ; => "AAADDD*/EEE"
(remove-comment "AAA/a//*BB*B**/CCC") ; => "AAA/a/CCC"
|
上のと同じかも
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System;
using System.Text;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
string[] ss = {"AAA", "AAA/*/BBB", "AAA/*BBB",
"AAA/*BBB*/CCC", "AAA/*BBB/*CCC*/DDD*/EEE", "AAA/a//*BB*B**/CCC"};
foreach (string s in ss)
Console.WriteLine(Regex.Replace(Regex.Replace(s, "\\/\\*.*?\\*\\/", ""), "\\/\\*.*$", ""));
}
}
|
1 2 3 4 5 6 7 8 9 10 | def remove_comment(str)
str.gsub(%r!/\*(.+?)(\*/|$)!, "")
end
remove_comment('AAA') # => "AAA"
remove_comment('AAA/*BBB*/') # => "AAA"
remove_comment('AAA/*BBB') # => "AAA"
remove_comment('AAA/*BBB*/CCC') # => "AAACCC"
remove_comment('AAA/*BBB/*CCC*/DDD*/EEE') # => "AAADDD*/EEE"
remove_comment('AAA/a//*BB*B**/CCC') # => "AAA/a/CCC"
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <string.h>
void remove_comment(const char* s) {
const char* cs;
while ((cs = strstr(s, "/*")) != NULL) {
fwrite(s, 1, cs - s, stdout);
if ((s = strstr(cs, "*/")) == NULL)
return;
s += 2;
}
printf("%s\n", s);
}
main() {
remove_comment("AAA");
remove_comment("AAA/*BBB*/");
remove_comment("AAA/*BBB");
remove_comment("AAA/*BBB*/CCC");
remove_comment("AAA/*BBB/*CCC*/DDD*/EEE");
remove_comment("AAA/a//*BB*B**/CCC");
}
|
N年ぶりにperlでw
1 2 3 4 5 6 7 8 9 10 11 | sub remove_comment($) {
my $s = @_[0];
$s =~ s/\/\*(.+?)(\*\/|$)//g;
$s;
}
print remove_comment('AAA'), "\n";
print remove_comment('AAA/*BBB*/'), "\n";
print remove_comment('AAA/*BBB'), "\n";
print remove_comment('AAA/*BBB*/CCC'), "\n";
print remove_comment('AAA/*BBB/*CCC*/DDD*/EEE'), "\n";
print remove_comment('AAA/a//*BB*B**/CCC'), "\n";
|
しばらく書いてないと書き方忘れたorz
D言語も選択肢に入れてちょ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | module doukaku;
private import std.regexp;
private import std.stdio;
char[] remove_comment(char[] str) {
return sub(str, r"/\*(.+?)(\*/|$)", "", "g");
}
int main () {
writefln(remove_comment("AAA"));
writefln(remove_comment("AAA/*BBB*/"));
writefln(remove_comment("AAA/*BBB"));
writefln(remove_comment("AAA/*BBB*/CCC"));
writefln(remove_comment("AAA/*BBB/*CCC*/DDD*/EEE"));
writefln(remove_comment("AAA/a//*BB*B**/CCC"));
return 0;
}
|
1 2 3 | function remove_comment(s) {
return s.replace(/\/\*.*?(\*\/|$)/, '');
}
|
サクっとやってみました。
1 2 3 4 5 6 7 8 9 10 11 12 | <?php
function remove_comment($str)
{
return preg_replace('/\/\*.*?(\*\/|$)/', '', $str);
}
echo remove_comment('AAA')."\n";
echo remove_comment('AAA/*BBB*/')."\n";
echo remove_comment('AAA/*BBB')."\n";
echo remove_comment('AAA/*BBB/*CCC*/')."\n";
echo remove_comment('AAA/*BBB/*CCC*/DDD*/EEE')."\n";
|
Gaucheです
1 2 3 4 5 6 7 8 9 | (define (remove-comment str)
(regexp-replace-all #/\/\*(.+?)(\*\/|$)/ str ""))
(print (remove-comment "AAA")) ; => "AAA"
(print (remove-comment "AAA/*BBB*/")) ; => "AAA"
(print (remove-comment "AAA/*BBB")) ; => "AAA"
(print (remove-comment "AAA/*BBB*/CCC")) ; => "AAACCC"
(print (remove-comment "AAA/*BBB/*CCC*/DDD*/EEE")) ; => "AAADDD*/EEE"
(print (remove-comment "AAA/a//*BB*B**/CCC")) ; => "AAA/a/CCC"
|
1 2 3 4 5 6 7 8 9 | (defun remove-comment (str)
(replace-regexp-in-string "/\\*\\(.+?\\)\\(\\*/\\|$\\)" "" str))
(remove-comment "AAA") ; => "AAA"
(remove-comment "AAA/*BBB*/") ; => "AAA"
(remove-comment "AAA/*BBB") ; => "AAA"
(remove-comment "AAA/*BBB*/CCC") ; => "AAACCC"
(remove-comment "AAA/*BBB/*CCC*/DDD*/EEE") ; => "AAADDD*/EEE"
(remove-comment "AAA/a//*BB*B**/CCC") ; => "AAA/a/CCC"
|
std::stringで。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #include <iostream>
#include <string>
std::string remove_comment(const std::string& s)
{
std::string ret;
std::string::size_type i1 = 0;
while (1)
{
std::string::size_type i2;
if ((i2 = s.find("/*", i1)) == std::string::npos)
{
ret.append(s.substr(i1));
break;
}
else
{
ret.append(s.substr(i1, i2 - i1));
i1 = i2 + 2;
}
if ((i2 = s.find("*/", i1)) == std::string::npos)
{
break;
}
else
{
i1 = i2 + 2;
}
}
return ret;
}
void run(const std::string& s)
{
std::cout << remove_comment(s) << std::endl;
}
int main()
{
run("AAA");
run("AAA/*BBB*/");
run("AAA/*BBB");
run("AAA/*BBB*/CCC");
run("AAA/*BBB/*CCC*/DDD*/EEE");
run("AAA/a//*BB*B**/CCC");
}
|
1 2 3 4 5 6 7 8 9 | import java.util.regex.Pattern;
public class StringUtils {
private static Pattern p = Pattern.compile("/\\*.*?(\\*/|$)");
public static String removeComment(String s) {
return p.matcher(s).replaceAll("");
}
}
|
$だと複数行には対応できないので\zを使って"/\\*.*?(\\*/|\\z)"とすべきかと。
よく考えたらそれはPattern.MULTILINEを立ててる場合だけでした。
しかし、よく考えたらデフォルトでは"."は行末記号と一致しないのでPattern.compile("/\\*.*?(\\*/|$)", Pattern.DOTALL);とすべきですね。
確かに、サンプル入力に「改行が含まれるケース」も入れておくべきでしたね(^^;
$ より \z の方がそれっぽい出力ではないですかね。私は\z ばかりで $ は滅多に使わないのですが。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | class String
def remove_comment
self.gsub(/\/\*.*?(\*\/|\z)/m, '')
#self.gsub(/\/\*.*?(\*\/|$)/m, '')
end
end
str = DATA.readlines.join
print str.remove_comment
__END__
code
/*
comment
*/
code
|
<algorithm>のstd::searchを使ってみた。size_typeよりイテレータのほうが扱いやすいかと思ったけど、そうでもなかった。(bcc32で確認)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #include <iostream>
#include <string>
#include <algorithm>
std::string remove_comment(const std::string& s)
{
std::string ret;
const std::string beg = "/*";
const std::string end = "*/";
std::string::const_iterator it1 = s.begin();
while (1)
{
std::string::const_iterator it2;
it2 = std::search(it1, s.end(), beg.begin(), beg.end());
ret.append(std::string(it1, it2));
if (it2 == s.end())
{
break;
}
else
{
it1 = it2 + beg.size();
}
it2 = std::search(it1, s.end(), end.begin(), end.end());
if (it2 == s.end())
{
break;
}
else
{
it1 = it2 + end.size();
}
}
return ret;
}
void run(const std::string& s)
{
std::cout << remove_comment(s) << std::endl;
}
int main()
{
run("AAA");
run("AAA/*BBB*/");
run("AAA/*BBB");
run("AAA/*BBB*/CCC");
run("AAA/*BBB/*CCC*/DDD*/EEE");
run("AAA/a//*BB*B**/CCC");
}
|
今回もoneliner。
見落としがなければ、欲張らないmatchができる正規表現が書ける言語ならすぐできる?
1 | perl -pe 's#/\*.*?(?:\*/|$)##g'
|
正規表現使ったら、負けかなと思ったりします。 愚直に、一文字ずつ
1 2 3 4 5 6 7 8 9 10 | (define (comment a)
(with-output-to-string (lambda ()
(with-input-from-string a (lambda ()
(let loop ((sw #t) (c (read-char)))
(let ((loopx (cut loop <> (read-char)))
(test-char-peek (lambda (x y) (and (char=? c x) (char=? (peek-char) y)))))
(cond ((eof-object? c) #t)
((and sw (test-char-peek #\/ #\*)) (loopx #f))
((and (not sw) (test-char-peek #\* #\/)) (read-char) (loopx #t))
(else (when sw (write-char c)) (loopx sw))))))))))
|
いちお~、文字列を返す仕様で。
というか、元を破壊する方向で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | #include <stdio.h>
#include <string.h>
char* remove_comment(char* str){
char* comment_start;
char* comment_end;
comment_end=str;
while(comment_start=strstr(comment_end,"/*")){
comment_end=strstr(comment_start,"*/");
if(comment_end){
strcpy(comment_start,comment_end+2);
comment_end=comment_start+1;
}else{
*comment_start='\0';
break;
}
}
return str;
}
int main(){
puts(remove_comment("AAA"));
puts(remove_comment("AAA/*BBB*/"));
puts(remove_comment("AAA/*BBB"));
puts(remove_comment("AAA/*BBB*/CCC"));
puts(remove_comment("AAA/*BBB/*CCC*/DDD*/EEE"));
puts(remove_comment("AAA/a//*BB*B**/CCC"));
}
|
正規表現使わない
1 2 3 4 5 6 7 8 | removeComment [] = []
removeComment ('/':'*':xs) = skip xs
where skip [] = []
skip ('*':'/':xs) = removeComment xs
skip (x:xs) = skip xs
removeComment (x:xs) = x : removeComment xs
main = getContents >>= (putStr . removeComment)
|
これでいいんじゃないかな?
1 2 3 | def remove_comment(str)
str.gsub(/\/\*.*?(\*\/|\z)/,"")
end
|
後で読んでも分かるようにVERBOSEにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 | def remove_comment(xs):
import re
p = re.compile(r"""
/ # comment starts with slash
\* # next comes asterisk
.*? # comment contents
(?: # start of grouping without getting value
\*/ # end of comment (asterisk followed by slash)
| # or
$ # end of input value
) # end of grouping
""",re.VERBOSE)
return p.sub('',xs)
|
Squeak Smalltalk で手続き的に。
1 2 3 4 5 6 7 8 9 10 11 12 | | stream delimiter out string upToAll |
string := 'AAA/a//*BB*B**/CCC'.
stream := string readStream.
delimiter := '*/'.
upToAll := [stream upToAll: (delimiter := delimiter reversed)].
out := String new writeStream.
[stream atEnd] whileFalse: [
out nextPutAll: upToAll value.
upToAll value].
^out contents
"=> 'AAA/a/CCC' "
|
Luaはまだいないかな?
1 2 3 | function remove_comment( str )
return (string.gsub( str, "/%*.-%*/", "" ) )
end
|
それだとコメントが閉じずに終わる入力で削除できないので美しくないけどこうかなあと。1つのパターンで書ける方法はないかなあ。
1 2 3 | function remove_comment(str)
return string.gsub(string.gsub(str, "/%*.-%*/", ""), "/%*.*$", "")
end
|
相互再帰版も書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | function proc(input, output, i)
local s, e = string.find(input, "/%*", i)
if s then
table.insert(output, string.sub(input, i, s - 1))
return skip(input, output, e + 1)
else
table.insert(output, string.sub(input, i))
return table.concat(output)
end
end
function skip(input, output, i)
local s, e = string.find(input, "%*/", i)
if s then
return proc(input, output, e + 1)
else
return table.concat(output)
end
end
function remove_comment(input)
return proc(input, {}, 1)
end
|
shiroさんの"なんでも再帰"(http://practical-scheme.net/docs/tailcall-j.html)にでていた方法で。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | (define (remove-comment str)
(define (cmnt-open-/ l r)
(cond ((null? l) r)
((char=? #\/ (car l)) (cmnt-open-* (cdr l) r))
(else (cmnt-open-/ (cdr l) (cons (car l) r)))))
(define (cmnt-open-* l r)
(cond ((null? l) (cons #\/ r))
((char=? #\* (car l)) (cmnt-close-* (cdr l) r))
(else (cmnt-open-/ l (cons #\/ r)))))
(define (cmnt-close-* l r)
(cond ((null? l) r)
((char=? #\* (car l)) (cmnt-close-/ (cdr l) r))
(else (cmnt-close-* (cdr l) r))))
(define (cmnt-close-/ l r)
(cond ((null? l) (cons #\* r))
((char=? #\/ (car l)) (cmnt-open-/ (cdr l) r))
(else (cmnt-close-* l r))))
(list->string (reverse (cmnt-open-/ (string->list str) '()))))
|
1 2 3 4 5 6 7 8 | (define (remove-comment str)
(receive (ss cs) (string-scan str "/*" 'both)
(if ss
(string-append ss (receive (se ce) (string-scan cs "*/" 'both)
(if se
(remove-comment ce)
"")))
str)))
|
正規表現1つで
1 2 3 4 | import re
PAT = re.compile(r'/\* (.(?!\*/)) *.? (?:\*/)? ', re.X)
def remove_comment(s):
return PAT.sub('', s)
|
Haskell の練習
1 2 3 4 5 6 7 8 9 | removeComment :: String -> String
removeComment = outOfComment
where
outOfComment ('/':'*':cs) = inComment cs
outOfComment (c:cs) = c : outOfComment cs
outOfComment [] = []
inComment ('*':'/':cs) = outOfComment cs
inComment (c:cs) = inComment cs
inComment [] = []
|
既出のHaskellコードのアルゴリズムを拝借してRubyで書いてみた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | def remove_comment(str)
def off_comment(cs, rs)
return rs.join unless(cs);
if ((cs[0] == "/") && (cs[1] == "*"))
|




にしお
#3373()
Rating0/0=0.00
なお、「/*」と入力末尾で挟まれた部分も取り除いてください。 つまり、入力が「AAA/*BBB」なら出力は「AAA」です。 また、コメントは入れ子になりません。入力が「AAA/*BBB/*CCC*/DDD*/EEE」のとき、ひとつめの「*/」でコメントが終わるので出力は「AAADDD*/EEE」になります。 「//」や「**」が混ざる場合の挙動は失敗しやすいので要注意です。
Pythonでの実行例は下のようになります:
>>> remove_comment('AAA') 'AAA' >>> remove_comment('AAA/*BBB*/') 'AAA' >>> remove_comment('AAA/*BBB') 'AAA' >>> remove_comment('AAA/*BBB*/CCC') 'AAACCC' >>> remove_comment('AAA/*BBB/*CCC*/DDD*/EEE') 'AAADDD*/EEE' >>> remove_comment('AAA/a//*BB*B**/CCC') 'AAA/a/CCC'このお題は匿名での投稿を参考にして作成しました。 ありがとうございます。
[ reply ]