Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

CSVでダブルクォートで囲まれた場合のパース方法(C言語)

スポンサードリンク


CSVでダブルクォートで囲まれた場合のパースって
なんかうまい書き方あるんだろうかと、
一応自分でも考えながら調べてみると、
あるんですね。なかなかきれいな書き方が。
まぁ、こんなのは普通のプログラミング言語使っている場合は
ライブラリ頼りで自分で書かないのが普通ですが、
勉強を兼ねて調べてみました。
そうするとここに若干トリッキーなコードが……。
C言語関係掲示板 過去ログ1227

ソースコード


実行結果

$ ./csvutil.exe
:123:456:789
:abcd:efg:hij
:klm:nop:qrs
:あいう:えお:かきく
:123:456:789
:12"3:456:789

コード上にも書いていますが、

・一行の中のデータは ,(カンマ)で区切る。行の終りは改行。
・データがカンマやダブルクォートを含む場合は "(ダブルクォート)で囲む。
・データの中のダブルクォートはそれをダブルクォート2個("")で置き換える。

という方針でコードがかかれています。
ところが、このコードを読むと、

while (*(++p) && *p != '\n' && (*p != '"' || *(++p) == '"'))

の部分で何をやってるのか最初、意図がつかめませんでした。
前置インクリメントとショートサーキット(短絡評価)演算子の性質をうまく扱っています。
一応念のため

短絡評価(たんらくひょうか、英: short-circuit evaluation)または最小評価(さいしょうひょうか、英: minimal evaluation)とは、一部のプログラミング言語での論理演算子の意味論を示す用語であり、演算子の第一引数を評価した段階で式全体の値が定まらない場合のみ第二引数を評価する方式を意味する。例えば、ANDの第一引数を評価した結果が false であれば、式全体は必ず false になるし、ORの第一引数が true であれば、式全体は必ず true になるので、第二引数を評価するまでもない。

http://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B5%A1%E8%A9%95%E4%BE%A1

ここでは現在調べようとしている文字(前回のループの直後から見ると次)が
「null文字でなくてそれが改行かダブルクォートでない」場合ループに入るのですが、
ここで現在の文字がダブルクォートだった場合、*(++p) == '"'の評価がされて
ポインタを一個進めています。そして続いて"が連続であるとわかった場合はループを継続します。
この等号が満たされないときは単純にループを抜けます。
ただし、インクリメントはされます(そうでないと次のfor分ループで"から評価されてしまう)。

うーん、この程度はスラスラ読めないとダメなんだろうか……。
これ置換えるとなると複雑になりそう……。うーん、自分の頭の悪さが憎いです。