私自身が表題の問題を解いた時のプログラムについて解説します。
問題の詳細は「// TODO: 田中くんMarkdown直しといて」(CodeIQ)を参照してください。
Markdown形式のリストを整形せよという問題です。
ルールは次の通りです。
具体的には次のようにパラメータが入力されます。
それを次のように修正します。
Javascript(Node.js)で解答しています。
process.stdin.resume(); process.stdin.setEncoding('utf8'); var MarkListFormat = MarkListFormat || { inputed : Array(), } MarkListFormat.output = function(line){ console.log(line); } MarkListFormat.formatList = function(input){ var out = input.replace(/^(\d+?)\./, "1. "); console.log(out); } process.stdin.on('data', function (chunk) { var inputed = Array(); var lines = chunk.toString().split('\n'); var N = lines.length; for(var i=0; i<lines.length; i++) { var input = lines[i].trim(); if (input.match(/^(\d+?)\./)) { MarkListFormat.inputed.push(input); } } }); process.stdin.on('end', function () { for(var i=0; i<MarkListFormat.inputed.length; i++){ //console.log(MarkListFormat.inputed[i]); MarkListFormat.formatList(MarkListFormat.inputed[i]); } });
この問題は難しくありません。
素直に処理すれば正しい結果にできます。
Javascriptで以外と困るのがJavascriptにはJavaのような名前空間の仕組みがないことです。これはNode.jsですが上ブラウザで実行される場合、名前が衝突しておかしくなることが割と良くあります。私の経験で覚えているのはnameという変数を使ったらあるブラウザでは正しく動くのに別のブラウザではダメということがありました。どうも、タグのname属性と衝突していたような記憶があります。
それを防ぐためのテクニックが4行目です。
var Hoge = Hoge || {};
のようにある名前のオブジェクトがなかったら生成し、自作するfunctionや変数は全てそのメンバにしてしまうとGlobalな名前空間に属する名前はHogeだけになります。これで名前の衝突を気にしなくて良くなります。
ちなみに、このプログラムではやっていませんが、名前空間オブジェクトのメンバにアクセスする場合、Webを検索するとthisを使ってthis.ValNameとかthis.FuncName()とかするのが一般的なようですが、私はHoge.ValNameとかHoge.FuncName()のようにしています。これはthisを使うとクロージャなどでthisが参照しているオブジェクトが変わってしまうためですが、thisを使う方が良い理由はあるのでしょうか?
process.stdin.on('data', function)で入力値を配列MarkListFormat.inputedにバッファし、process.stdin.on('end', function)で処理して出力しています。
処理の本体です。と言っても正規表現で置換しているだけです。
私は念のため最短マッチしていますがしなくても問題ないかもしれません。
この問題をJavascriptでやった理由は確か、このころElectronでアプリケーションを作っていてJavascriptの正規表現が頭にあったからだと思います。問題を一目見て正規表現で置換すればOKと思いましたから。
C言語の場合CodeIQでregex.hを使えるかどうかわからないので自力でやることになりますが、1行の先頭から「.」を探してsprintf("1. %s", line+x)のようにすれば良いのでそんなんに難しくはありません。
※lineは1行分の文字列のバッファ。xは「.」の次のポインタ位置。