01/19
_ [プログラミング] ファイルパスをソースコードの中に書く時に
プログラミング中に、ファイルパスをソースコードの中にべたっと書きたくなる事があります。その手のデータ文字列はプログラムとは分けて外部ファイルにしましょう、と言われてしまうとそれまでですが、このエントリは手抜き優先で。
たとえば、次のような文字列を出力したい場合。
start "\\gotta\ni\miracle moon.txt"
「\」が制御文字なこと、「"」がよく文字列の開始と終了を表す事から、この文字列を表示させようとするとエスケープが必要で少し面倒です。そうしないと「"」の区切り位置で文法エラーになったり、「\\」が1つの「\」になってしまったり、「\n」で改行されてしまったり。
そこで、最近気になる言語についてまとめてみました。
言語 | 表示文 |
---|---|
C | printf("start \"\\\\gotta\\ni\\miracle moon.txt\""); |
VBA | ? "start ""\\gotta\ni\miracle moon.txt""" |
F# | printfn @"start ""\\gotta\ni\miracle moon.txt""";; |
Ruby | puts 'start "\\\\gotta\ni\miracle moon.txt"' |
Python | print(r'start "\\gotta\ni\miracle moon.txt"') |
C++0x | printf(R"[start "\\gotta\ni\miracle moon.txt"]"); |
C
printf("start \"\\\\gotta\\ni\\miracle moon.txt\"");
ファイルパスを貼り付けた後に何かするところを太字にしています。
「\」を追加するのが面倒です。1つのパスを追加するたびにエディタで「[\\"]」を「\\\0」に置換しないと、だとか。
パスの中に「%」が入っていると危ないから printf("%s", "start \"\\\\gotta\\ni\\miracle moon.txt\""); しましょうという出力関数の話は、このエントリでは気にしないことにします。(他の不慣れな言語でやってしまっていそうですし…)
VB, VBA
Excel VBAを起動して、イミディエイトウィンドウで次のように。
? "start ""\\gotta\ni\miracle moon.txt"""
「\」はVB, VBAでは制御文字でなくて安心です。文字列の前後を「"」で挟むために、「"」文字列を表示するためには「""」と1つ重ねる必要があり、それだけは面倒です。といってもWindowsのファイルパスに「"」は許されないですから、多分困る事は少ないと思います。
C#, F#
標準リテラル文字列だとCと同じです。逐語的文字列リテラルを使うと、VB同様にエスケープする数を減らせます。最近 実践 F# 関数型プログラミング入門 (amazon) を読んでいるからと、F#で書いてみた例。
printfn @"start ""\\gotta\ni\miracle moon.txt""";;
Ruby
puts 'start "\\\\gotta\ni\miracle moon.txt"'
「'」がエスケープしない文字列として扱えて、「"」を特別扱いしなくて良くなります。しかし「'」の表示に「\'」が使われるために、「\\」が「\」になってしまいます。ネットワークパスで困ってしまいます。
これを避けようとヒアドキュメントしてみると、
puts <<'EOS'
\\gotta\ni\miracle moon.txt
EOS
こんなに面倒なら「\」をエスケープする方がまだまし。
Python
print(r'start "\\gotta\ni\miracle moon.txt"')
raw文字列を表す「r」を、文字列「""」や「''」の頭に付けると、全ての文字列がエスケープされなくなります。これまでの中で一番簡単。
D言語にも同じような書き方の出来るWYSIWYG文字列というのがあるそうです。たぶん「writeln(r`start "\\gotta\ni\miracle moon.txt"`;」。手元にDのコンパイラは無くて試せていません。
C++0x
printf(R"[start "\\gotta\ni\miracle moon.txt"]");
C++にも今後raw文字列が追加されるそうです。
区切り文字を文字列中に使うための方法が特徴的です。.NET系では「""」と2つ重ねる事で特別扱い、Rubyでは「\'」とシングルクォート文字列でもエスケープ、PythonやDでは「""」「''」「``」という同じ意味の複数の区切り方を使えるためにどれかが現れても大丈夫としていました。C++0xは確かにこのままでは「]」を文字列中に使おうとすると困りますが、それなら「R"foobar[start "\\gotta\ni\miracle moon.txt"]foobar"」のように終了文字列を長くできて、これなら中の文字列が既知ならどうにでも避けられます。
というのを試してみようとして… VC++2010 Expressではまだ使えませんでした。いち早く試したい方はGCCだそうです。こちらもDと同じように動作確認していないのに載せています。
最後に
C以外はそんなに頑張らなくて良いということが分かりました。
このエントリのきっかけは、キーボードランチャー [CraftLaunch]。Tweenなどのアプリケーションを登録するのに、Pythonを使います。それで気になったというわけでした。Paint Shop ProのスクリプトもPythonですし、もう少し使えるようになりたいかも。