<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>taichino.com &#187; C/C++</title>
	<atom:link href="http://taichino.com/category/programming/cc/feed" rel="self" type="application/rss+xml" />
	<link>http://taichino.com</link>
	<description>永遠のネバーランド</description>
	<lastBuildDate>Sat, 04 Sep 2010 16:20:47 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hello Yacc &amp; Lex World</title>
		<link>http://taichino.com/memo/1803</link>
		<comments>http://taichino.com/memo/1803#comments</comments>
		<pubDate>Thu, 17 Jun 2010 17:16:20 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[メモ]]></category>
		<category><![CDATA[bison]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[lex]]></category>
		<category><![CDATA[yacc]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1803</guid>
		<description><![CDATA[最近ちまちまとyacc/lex(実際はbison/flex)を触っているのですが、やたらと苦労しています。真面目に学校に行ってなかったのが悔やまれますが、愚痴っていても仕方が無いのでメモ書きです。
ここでは以下の様なTinyCモドキのコードをyaccとlexで扱ってみます。

main&#40;&#41;
&#123;
    var i;
    var s;
    s = 0;
    i = 0; 
    while&#40;i &#60; 10&#41;&#123;
	  s = s + i;
	  i = i + 1;
    &#125;
    println&#40;&#34;s = %d&#34;,s&#41;;
&#125;

TinyCについてはコチラのページを参考にさせて頂きました。何故モドキかと言うと、僕にはTinyCですら複雑だったので、TinyCを更に小さくしたモドキをパースする事にしました。ヘタレですいません。

まずはlexで字句解析をします。ここでは各ルールにマッチした文字をそのまま出力させています。ルールに対応する処理内では、yytextでマッチした文字列、yylinenoで行番号を取得しています。


/*
 * tinyc.l
 */
&#160;
/* [...]]]></description>
			<content:encoded><![CDATA[<p>最近ちまちまとyacc/lex(実際はbison/flex)を触っているのですが、やたらと苦労しています。真面目に学校に行ってなかったのが悔やまれますが、愚痴っていても仕方が無いのでメモ書きです。</p>
<p>ここでは以下の様なTinyCモドキのコードをyaccとlexで扱ってみます。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
    var i<span style="color: #339933;">;</span>
    var s<span style="color: #339933;">;</span>
    s <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
    i <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span> 
    <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>i <span style="color: #339933;">&lt;</span> <span style="color: #0000dd;">10</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
	  s <span style="color: #339933;">=</span> s <span style="color: #339933;">+</span> i<span style="color: #339933;">;</span>
	  i <span style="color: #339933;">=</span> i <span style="color: #339933;">+</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    println<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;s = %d&quot;</span><span style="color: #339933;">,</span>s<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>TinyCについては<a href="http://www.hpcs.cs.tsukuba.ac.jp/~msato/lecture-note/comp-lecture/tiny-c-note1.html">コチラのページ</a>を参考にさせて頂きました。何故モドキかと言うと、僕にはTinyCですら複雑だったので、TinyCを更に小さくしたモドキをパースする事にしました。ヘタレですいません。</p>
<p><span id="more-1803"></span></p>
<p>まずはlexで字句解析をします。ここでは各ルールにマッチした文字をそのまま出力させています。ルールに対応する処理内では、yytextでマッチした文字列、yylinenoで行番号を取得しています。</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*
 * tinyc.l
 */</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 準備 */</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#123;</span>
<span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 規則 */</span>
<span style="color: #000040;">%%</span>
<span style="color: #008000;">&#91;</span> \t<span style="color: #008000;">&#93;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #ff0000; font-style: italic;">/* Skip white space */</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#91;</span>\n<span style="color: #008000;">&#93;</span>                    <span style="color: #008000;">&#123;</span> yylineno<span style="color: #000040;">++</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;while&quot;</span>                 <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d: WHILE<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, yylineno<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;var&quot;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d: VAR<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, yylineno<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;for&quot;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d: FOR<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, yylineno<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #000040;">-</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #000040;">-</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#93;</span><span style="color: #000040;">*</span>             <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d: CONSTANT %d<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>,   yylineno, <span style="color: #0000dd;">atoi</span><span style="color: #008000;">&#40;</span>yytext<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
\<span style="color: #FF0000;">&quot;[^<span style="color: #000099; font-weight: bold;">\&quot;</span>]*<span style="color: #000099; font-weight: bold;">\&quot;</span>              { printf(&quot;</span><span style="color: #000040;">%</span>d<span style="color: #008080;">:</span> LITERAL <span style="color: #000040;">%</span>s\n<span style="color: #FF0000;">&quot;,    yylineno, yytext);       }
[a-zA-Z][0-9a-zA-Z]*    { printf(&quot;</span><span style="color: #000040;">%</span>d<span style="color: #008080;">:</span> IDENTIFIER <span style="color: #000040;">%</span>s\n<span style="color: #FF0000;">&quot;, yylineno, yytext);       }
.                       { /* Skip other characters */ }
%%
&nbsp;
/* ユーザ関数 */
int main() {
	yylex();
}</span></pre></div></div>

<p>特に難しいところは有りませんね。以下のように実行します。ビルド時にlibflをリンクしている事に注意しましょう。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">flex</span> tinyc.l
$ <span style="color: #c20cb9; font-weight: bold;">gcc</span> lex.yy.c <span style="color: #660033;">-o</span> tinyc_scan <span style="color: #660033;">-lfl</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>tinyc_scan <span style="color: #000000; font-weight: bold;">&lt;</span> test.c
<span style="color: #000000;">1</span>: IDENTIFIER main
<span style="color: #000000;">3</span>: VAR
<span style="color: #000000;">3</span>: IDENTIFIER i
<span style="color: #000000;">4</span>: VAR
<span style="color: #000000;">4</span>: IDENTIFIER s
<span style="color: #000000;">5</span>: IDENTIFIER s
<span style="color: #000000;">5</span>: CONSTANT <span style="color: #000000;">0</span>
<span style="color: #000000;">6</span>: IDENTIFIER i
<span style="color: #000000;">6</span>: CONSTANT <span style="color: #000000;">0</span>
<span style="color: #000000;">7</span>: WHILE
<span style="color: #000000;">7</span>: IDENTIFIER i
<span style="color: #000000;">7</span>: CONSTANT <span style="color: #000000;">10</span>
<span style="color: #000000;">8</span>: IDENTIFIER s
<span style="color: #000000;">8</span>: IDENTIFIER s
<span style="color: #000000;">8</span>: IDENTIFIER i
<span style="color: #000000;">9</span>: IDENTIFIER i
<span style="color: #000000;">9</span>: IDENTIFIER i
<span style="color: #000000;">9</span>: CONSTANT <span style="color: #000000;">1</span>
<span style="color: #000000;">11</span>: IDENTIFIER println
<span style="color: #000000;">11</span>: LITERAL <span style="color: #ff0000;">&quot;s = %d&quot;</span>
<span style="color: #000000;">11</span>: IDENTIFIER s</pre></div></div>

<p>無事に字句解析に成功していますね。これで与えられた文字列を分解して特定の塊ごとに処理できるようになりましたが、それだけではあまり役に立ちません。実際は塊の並びに基づいた処理をしたいことが多いです。例えば変数の宣言だけ抜き出したいとか、関数の呼出し部分だけ変更を加えたい等が考えられますが、自前で実装となると結構大変なのでyaccを使って必要なパーサを自動的に生成するというのが話の流れです。</p>
<p>早速先ほどの字句解析に対応するyaccファイルを実装したいところですが、その前に字句解析側をyaccに対応するように修正する必要があります。具体的にはyaccの入力に必要なトークン列を字句解析側で準備します。先ほどはルール部の核処理で、マッチした文字列をそのまま出力していましたが、今回は各ルールに対応したトークンを返却するようにしています。</p>
<p>また、これらのトークンはyacc側で定義されていることが期待されていて、その為にtinyc.tab.hというファイルをincludeしています。またyylvalという変数にトークンの実際の内容を代入しています。これでyaccはlexが返した各トークンを並べたトークン列を元に処理でき、必要に応じてトークンの内容も参照できるようになります。</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*
 * tinyc.l yacc向けに修正
 */</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 準備 */</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#123;</span>
<span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #339900;">#include &quot;tinyc.tab.h&quot;</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 規則 */</span>
<span style="color: #000040;">%%</span>
<span style="color: #008000;">&#91;</span> \t<span style="color: #008000;">&#93;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #ff0000; font-style: italic;">/* Skip white space */</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#91;</span>\n<span style="color: #008000;">&#93;</span>                    <span style="color: #008000;">&#123;</span> yylineno<span style="color: #000040;">++</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;+&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'+'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;-&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'-'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;*&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'*'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;/&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'/'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;{&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'{'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;}&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'}'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;(&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">'('</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;)&quot;</span>                     <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> <span style="color: #FF0000;">')'</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;while&quot;</span>                 <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> WHILE<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;var&quot;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> VAR<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #FF0000;">&quot;for&quot;</span>                   <span style="color: #008000;">&#123;</span> <span style="color: #0000ff;">return</span> FOR<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #000040;">-</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#91;</span><span style="color: #0000dd;">0</span><span style="color: #000040;">-</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#93;</span><span style="color: #000040;">*</span>             <span style="color: #008000;">&#123;</span> yylval <span style="color: #000080;">=</span> <span style="color: #0000dd;">atoi</span><span style="color: #008000;">&#40;</span>yytext<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #0000ff;">return</span> CONSTANT<span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
\<span style="color: #FF0000;">&quot;[^<span style="color: #000099; font-weight: bold;">\&quot;</span>]*<span style="color: #000099; font-weight: bold;">\&quot;</span>              { yylval = (int)strdup(yytext); return LITERAL; }
[a-zA-Z][0-9a-zA-Z]*    { yylval = (int)strdup(yytext); return IDENTIFIER; }
.                       { return yytext[0]; }
%%
&nbsp;
/* ユーザ関数 */
/* mainは.yに移動 */</span></pre></div></div>

<p>いよいよyaccファイルを実装します。ここではトークン列を解析して「変数の宣言」と「関数の呼出し」を判別して出力してみます。頑張って短くしたつもりですが、それでも結構複雑ですね。雰囲気はlexによく似ていて、大きくはトークンの定義と構文の定義に別れています。トークン定義は簡単なのでスキップします。注意点としては下に行くほど優先順位の高いトークンになります。なので+は*よりも上に定義しないと駄目ですね。なお、ここで書いた定義が先ほどのtinyc.tab.hに反映されて、それをlex側からも参照する形になります。</p>
<p>さて問題は構文定義です。最初から自力で書くのは結構難しいと思うので、ノリとしては必要なBNFを探すなり書くなりして準備して、それをyaccに置き換えるという感じでしょうか。注意点はyaccで直接表現できない繰り返しの定義を再帰を使って置き換えないといけない事です。この例で言うとparamtersやstatementsなどです。慣れの問題かもしれませんが、僕は好きになれません。yaccのEBNF対応を願うばかりです。(自分でやる程、力も熱意もないであります。)</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #ff0000; font-style: italic;">/*
 * tinyc.y
 */</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 準備 */</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#123;</span>
<span style="color: #339900;">#include &lt;stdio .h&gt;</span>
<span style="color: #000040;">%</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* トークン定義 */</span>
<span style="color: #000040;">%</span>token CONSTANT LITERAL IDENTIFIER
<span style="color: #000040;">%</span>token VAR TYPE WHILE FOR IF
<span style="color: #000040;">%</span>left <span style="color: #FF0000;">';'</span> <span style="color: #FF0000;">','</span>
<span style="color: #000040;">%</span>left <span style="color: #FF0000;">'&lt; '</span> <span style="color: #FF0000;">'&gt;'</span>
<span style="color: #000040;">%</span>right <span style="color: #FF0000;">'='</span>
<span style="color: #000040;">%</span>left <span style="color: #FF0000;">'+'</span> <span style="color: #FF0000;">'-'</span>
<span style="color: #000040;">%</span>left <span style="color: #FF0000;">'*'</span>
<span style="color: #000040;">%</span>token <span style="color: #FF0000;">'('</span> <span style="color: #FF0000;">')'</span> <span style="color: #FF0000;">'{'</span> <span style="color: #FF0000;">'}'</span>
&nbsp;
<span style="color: #000040;">%</span>start program
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* 構文定義 */</span>
<span style="color: #000040;">%%</span>
&nbsp;
program <span style="color: #008080;">:</span> external_definitions
&nbsp;
external_definitions<span style="color: #008080;">:</span>
                external_definitions external_definition
        <span style="color: #000040;">|</span>       external_definition
&nbsp;
external_definition<span style="color: #008080;">:</span>
                IDENTIFIER <span style="color: #FF0000;">'('</span> parameters <span style="color: #FF0000;">')'</span> block
        <span style="color: #000040;">|</span>       VAR IDENTIFIER <span style="color: #FF0000;">'='</span> expr <span style="color: #FF0000;">';'</span>
&nbsp;
parameters<span style="color: #008080;">:</span>     parameters <span style="color: #FF0000;">','</span> parameter
        <span style="color: #000040;">|</span>       parameter
&nbsp;
parameter<span style="color: #008080;">:</span>      <span style="color: #ff0000; font-style: italic;">/* empty */</span>
        <span style="color: #000040;">|</span>       TYPE IDENTIFIER
&nbsp;
block<span style="color: #008080;">:</span>          <span style="color: #FF0000;">'{'</span> statements <span style="color: #FF0000;">'}'</span>
&nbsp;
statements <span style="color: #008080;">:</span>    statements statement
        <span style="color: #000040;">|</span>       statement
&nbsp;
statement <span style="color: #008080;">:</span>     block
        <span style="color: #000040;">|</span>       expr <span style="color: #FF0000;">';'</span>
        <span style="color: #000040;">|</span>       IF <span style="color: #FF0000;">'('</span> expr <span style="color: #FF0000;">')'</span> statement
        <span style="color: #000040;">|</span>       WHILE <span style="color: #FF0000;">'('</span> expr <span style="color: #FF0000;">')'</span> statement
        <span style="color: #000040;">|</span>       FOR <span style="color: #FF0000;">'('</span> expr <span style="color: #FF0000;">';'</span> expr <span style="color: #FF0000;">';'</span> expr <span style="color: #FF0000;">')'</span> statement
        <span style="color: #000040;">|</span>       VAR IDENTIFIER <span style="color: #FF0000;">';'</span>  <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;@ variable declaration %s @<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, $<span style="color: #0000dd;">2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
exprs<span style="color: #008080;">:</span>          exprs <span style="color: #FF0000;">','</span> expr
        <span style="color: #000040;">|</span>       expr
&nbsp;
expr<span style="color: #008080;">:</span>           primary_expr
        <span style="color: #000040;">|</span>       IDENTIFIER <span style="color: #FF0000;">'='</span> expr
        <span style="color: #000040;">|</span>       expr <span style="color: #FF0000;">'+'</span> expr   <span style="color: #000040;">|</span>   expr <span style="color: #FF0000;">'-'</span> expr   <span style="color: #000040;">|</span>   expr <span style="color: #FF0000;">'*'</span> expr
        <span style="color: #000040;">|</span>       expr <span style="color: #FF0000;">'&lt; '</span> expr   <span style="color: #000040;">|</span>   expr <span style="color: #FF0000;">'&gt;'</span> expr
&nbsp;
primary_expr<span style="color: #008080;">:</span>   IDENTIFIER      <span style="color: #000040;">|</span>       CONSTANT        <span style="color: #000040;">|</span>       LITERAL
        <span style="color: #000040;">|</span>       <span style="color: #FF0000;">'('</span> expr <span style="color: #FF0000;">')'</span>
        <span style="color: #000040;">|</span>       IDENTIFIER <span style="color: #FF0000;">'('</span> exprs <span style="color: #FF0000;">')'</span> <span style="color: #008000;">&#123;</span> <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;@ function call %s @<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, $<span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span> <span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #000040;">%%</span>
&nbsp;
<span style="color: #ff0000; font-style: italic;">/* ユーザ関数 */</span>
<span style="color: #0000ff;">int</span> yydebug<span style="color: #008080;">;</span>
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//  yydebug = 1;</span>
    yyparse<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #000080;">&lt;</span><span style="color: #000040;">/</span>stdio<span style="color: #000080;">&gt;</span></pre></div></div>

<p>早速実行してみます。リンク時にlibflに加えてlibyの指定も必要なので注意しましょう。うまく実行されていますね！</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">bison</span> <span style="color: #660033;">-d</span> tinyc.y <span style="color: #660033;">-v</span>
$ <span style="color: #c20cb9; font-weight: bold;">flex</span> tinyc.l
$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> lex.yy.c <span style="color: #660033;">-DYYDEBUG</span>
$ <span style="color: #c20cb9; font-weight: bold;">cc</span> <span style="color: #660033;">-c</span> tinyc.tab.c <span style="color: #660033;">-DYYDEBUG</span>
$ <span style="color: #c20cb9; font-weight: bold;">gcc</span> lex.yy.o tinyc.tab.o <span style="color: #660033;">-o</span> tinyc_parser <span style="color: #660033;">-lfl</span> <span style="color: #660033;">-ly</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>tinyc_parser <span style="color: #000000; font-weight: bold;">&lt;</span> test.c
<span style="color: #000000; font-weight: bold;">@</span> variable declaration i <span style="color: #000000; font-weight: bold;">@</span>
<span style="color: #000000; font-weight: bold;">@</span> variable declaration s <span style="color: #000000; font-weight: bold;">@</span>
<span style="color: #000000; font-weight: bold;">@</span> <span style="color: #000000; font-weight: bold;">function</span> call println <span style="color: #000000; font-weight: bold;">@</span></pre></div></div>

<p>大抵の情報源だと当然ながらうまく行った場合しか紹介されていませんが、残念ながらyaccファイルは複雑なので一発で正しく動かす事は期待できません。なので地道にデバッグする必要があります。僕が理解している限りだと、基本的には以下のようにデバッグします。</p>
<ul>
<li><strong>コンフリクト</strong><br />
bison(yacc)を実行した時に以下の様な警告が出る事があります。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">bison</span> <span style="color: #660033;">-d</span> tinyc.y <span style="color: #660033;">-v</span>
tinyc.y: conflicts: <span style="color: #000000;">18</span> shift<span style="color: #000000; font-weight: bold;">/</span>reduce</pre></div></div>

<p>その場合は-v(verbose)を付けて再度実行します。そうすると.outputというファイルにパーサー内部の状態マシンの情報が詳しく出力されます。出力されたファイルとにらめっこしてconflictをやっつけます。
</li>
<li><strong>syntax error</strong><br />
生成されたパーサがパース処理に失敗するとこのエラーがでます。このままでは辛いので、上記のmain関数内にコメントアウトしているyydebugを有効にします。そうするとパース処理中の状態遷移が詳しく出力されるので、出力されたメッセージとにらめっこしてパーサのデバッグを行います。
</li>
</ul>
<p>これで漸くyacc &#038; lexが少しは使えるようになりました。コンパイラ・コンパイラは使えると強力な武器になりそうなので、ちょっとずつ肉付けしていこうと思います。最後にこの例の場合の処理の流れを図にしてみました。言うほど複雑じゃないですけど、すぐ忘れるので念のため。<br />
<a href="http://taichino.com/wp-content/uploads/2010/06/yacc_lex_flow.png"><img src="http://taichino.com/wp-content/uploads/2010/06/yacc_lex_flow-300x179.png" alt="yacc lex flow image" title="yacc_lex_flow" width="300" height="179" class="alignnone size-medium wp-image-1819" /></a>
</pre>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/memo/1803/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cでのコマンドラインパラメータの受け方メモ</title>
		<link>http://taichino.com/programming/1753</link>
		<comments>http://taichino.com/programming/1753#comments</comments>
		<pubDate>Mon, 03 May 2010 08:24:19 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[getopt]]></category>
		<category><![CDATA[getopt_long]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1753</guid>
		<description><![CDATA[Cのプログラムでコマンドラインからパラメータを受けたい訳ですが、自力でやろうとしてもargv経由で文字列配列が渡されるだけなので非常に面倒です(LL病な自分としてはハッシュで欲しい)。例えば以下のgrepコマンドの用に複数のパラメータを順不同で受けたいとかになると、かなり大変ですね。

$ grep -nH -I -R search_text *

そこで、なんか無いのかと思って調べてみるとgetoptを使えば良い事がわかりました。

この関数を使うとパラメータを受ける処理を以下のように書けます。第3引数で取り得るオプションの種類を指定します。&#8221;abcd:e:&#8221;の場合は、取り得るオプションはa,b,c,d,eの５種類で、その内コロン付きのdとeは値を取ります。

#include &#34;stdio.h&#34;
#include &#34;stdlib.h&#34;
#include &#34;getopt.h&#34;
&#160;
int main&#40;int argc, char** argv&#41; &#123;
    int result = 0;
&#160;
    while &#40;&#40;result = getopt&#40;argc, argv, &#34;abcd:e:&#34;&#41;&#41; != -1&#41; &#123;
        switch &#40;result&#41; &#123;
        case 'a':
   [...]]]></description>
			<content:encoded><![CDATA[<p>Cのプログラムでコマンドラインからパラメータを受けたい訳ですが、自力でやろうとしてもargv経由で文字列配列が渡されるだけなので非常に面倒です(LL病な自分としてはハッシュで欲しい)。例えば以下のgrepコマンドの用に複数のパラメータを順不同で受けたいとかになると、かなり大変ですね。</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">grep</span> <span style="color: #660033;">-nH</span> <span style="color: #660033;">-I</span> <span style="color: #660033;">-R</span> search_text <span style="color: #000000; font-weight: bold;">*</span></pre></div></div>

<p>そこで、なんか無いのかと思って調べてみると<a href="http://www.linux.or.jp/JM/html/LDP_man-pages/man3/getopt.3.html">getopt</a>を使えば良い事がわかりました。</p>
<p><span id="more-1753"></span></p>
<p>この関数を使うとパラメータを受ける処理を以下のように書けます。第3引数で取り得るオプションの種類を指定します。&#8221;abcd:e:&#8221;の場合は、取り得るオプションはa,b,c,d,eの５種類で、その内コロン付きのdとeは値を取ります。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #339900;">#include &quot;stdlib.h&quot;</span>
<span style="color: #339900;">#include &quot;getopt.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> result <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>result <span style="color: #000080;">=</span> getopt<span style="color: #008000;">&#40;</span>argc, argv, <span style="color: #FF0000;">&quot;abcd:e:&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">switch</span> <span style="color: #008000;">&#40;</span>result<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'a'</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'b'</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'c'</span><span style="color: #008080;">:</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;option: %c applied<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, result<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'d'</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'e'</span><span style="color: #008080;">:</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;option %c applied with %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, result, optarg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">':'</span><span style="color: #008080;">:</span>   <span style="color: #666666;">// no value applied</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'?'</span><span style="color: #008080;">:</span>   <span style="color: #666666;">// invalid option</span>
            <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;@@ param start @@<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> optind<span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> argc<span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;param: %s <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, argv<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>このプログラムは、例えば以下のように実行できます。オプションの指定は順不同に書けますし、-bcの用にまとめて指定する事もできます。素晴しいですね。</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ .<span style="color: #000000; font-weight: bold;">/</span>option_test <span style="color: #660033;">-a</span> <span style="color: #660033;">-bc</span> <span style="color: #660033;">-d</span> val_for_d param1 param2
option: a applied
option: b applied
option: c applied
option d applied with val_for_d
<span style="color: #000000; font-weight: bold;">@@</span> param start <span style="color: #000000; font-weight: bold;">@@</span>
param: param1
param: param2</pre></div></div>

<p>さてgetoptで殆どの要求には対応できますが、所謂longオプションには対応していません。しかし俺々コマンドでもカッコ良く--verboseとか--helpとかやりたい！という熱い思いをかなえる為(かどうかは知りませんが)にgetopt_longという関数が準備されています。</p>
<p>結論のコードが以下になります。殆どgetoptと同じように使えますが、longオプション用の配列(long_opts)を準備する必要があり、少し面倒ですね。覚える必要があるのは、option構造体のvalメンバ(コード中の4つ目の値)がgetopt_long関数の戻り値になる事です。この値を弄ることでshortオプションのエイリアスとして使う事が出来ますね。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #339900;">#include &quot;stdlib.h&quot;</span>
<span style="color: #339900;">#include &quot;getopt.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">struct</span> option long_opts<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #008000;">&#123;</span><span style="color: #FF0000;">&quot;ls&quot;</span>,      <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">NULL</span>,  <span style="color: #0000dd;">0</span><span style="color: #008000;">&#125;</span>,    <span style="color: #666666;">// ls doesn't have option value</span>
        <span style="color: #008000;">&#123;</span><span style="color: #FF0000;">&quot;type&quot;</span>,    <span style="color: #0000dd;">1</span>, <span style="color: #0000ff;">NULL</span>,  <span style="color: #0000dd;">1</span><span style="color: #008000;">&#125;</span>,    <span style="color: #666666;">// type has option value</span>
        <span style="color: #008000;">&#123;</span><span style="color: #FF0000;">&quot;help&quot;</span>,    <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #FF0000;">'h'</span><span style="color: #008000;">&#125;</span>,   <span style="color: #666666;">// alias of h</span>
        <span style="color: #008000;">&#123;</span><span style="color: #FF0000;">&quot;version&quot;</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000ff;">NULL</span>, <span style="color: #FF0000;">'v'</span><span style="color: #008000;">&#125;</span>,   <span style="color: #666666;">// alias of v</span>
        <span style="color: #008000;">&#123;</span><span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#125;</span>  <span style="color: #666666;">// 最後の要素は全部0の必要があります。</span>
    <span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">int</span> result <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">int</span> opt_idx <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>result <span style="color: #000080;">=</span> getopt_long<span style="color: #008000;">&#40;</span>argc, argv, <span style="color: #FF0000;">&quot;hv&quot;</span>, long_opts, <span style="color: #000040;">&amp;</span>opt_idx<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">switch</span> <span style="color: #008000;">&#40;</span>result<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #666666;">// for long options</span>
        <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">:</span>  <span style="color: #666666;">// ls</span>
        <span style="color: #0000ff;">case</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">:</span>  <span style="color: #666666;">// type</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;[%s] applied: %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, long_opts<span style="color: #008000;">&#91;</span>opt_idx<span style="color: #008000;">&#93;</span>.<span style="color: #007788;">name</span>, optarg<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #666666;">// for short options</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'h'</span><span style="color: #008080;">:</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;help! <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'v'</span><span style="color: #008080;">:</span>
            <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;version! <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">':'</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">case</span> <span style="color: #FF0000;">'?'</span><span style="color: #008080;">:</span>
            <span style="color: #0000dd;">exit</span><span style="color: #008000;">&#40;</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;@@ param start @@<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> optind<span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> argc<span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;param: %s <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, argv<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>例えば以下のように実行できます。</p>
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ .<span style="color: #000000; font-weight: bold;">/</span>option_test <span style="color: #660033;">-v</span> <span style="color: #660033;">--type</span>=text <span style="color: #660033;">--ls</span> . hello.txt
version<span style="color: #000000; font-weight: bold;">!</span>
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #7a0874; font-weight: bold;">type</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> applied: text
<span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #c20cb9; font-weight: bold;">ls</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> applied: <span style="color: #7a0874; font-weight: bold;">&#40;</span>null<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">@@</span> param start <span style="color: #000000; font-weight: bold;">@@</span>
param: .
param: hello.txt</pre></div></div>

<p>遅まきながらCでコマンドライン引数を割と自由に扱えるようになりました。個人的には、rmコマンドのソースが分かり易くてオススメかなぁと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1753/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>浮動小数点の情報落ちを追って見た</title>
		<link>http://taichino.com/programming/1546</link>
		<comments>http://taichino.com/programming/1546#comments</comments>
		<pubDate>Thu, 18 Feb 2010 17:55:42 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[algorithm]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1546</guid>
		<description><![CDATA[今日topcoderの問題を解いてて、浮動小数点の誤差ではまりました。問題を単純化したコードが以下になります。

#include ＜iostream＞
using namespace std;
&#160;
int main&#40;int argc, char** argv&#41; &#123;
    double small = 1e-18;
    double big   = 1;
    double added = small + big;
    cout ＜＜ added ＜＜ endl;  // 1が出力される。(small分が切り捨てられてる)
&#125;

加算を行った結果、小数点以下の値が切り捨てられています。一瞬何が起こったのか解らなかったのですが、折角なので追ってみる事にしました。

まずdoubleの内部表現は次のようになります。(詳細はwikipediaを参照)

符号部(sign)が1bit、指数部(exponential)が11bit, 仮数部(significand)が52bitです。
実際に確認してみます。gdbで確認するには以下のようにします。(他に簡単な確認方法があれば教えて下さい。)

$ g++ -g test.cpp
$ gdb ./a.out
&#40;gdb&#41; x/g &#38;small
0xbfffee88:	0x3c32725dd1d243ac
&#40;gdb&#41; x/g &#38;big
0xbfffee90:	0x3ff0000000000000
&#40;gdb&#41; [...]]]></description>
			<content:encoded><![CDATA[<p>今日topcoderの問題を解いてて、浮動小数点の誤差ではまりました。問題を単純化したコードが以下になります。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include ＜iostream＞</span>
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">double</span> small <span style="color: #000080;">=</span> <span style="color:#800080;">1e-18</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">double</span> big   <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">double</span> added <span style="color: #000080;">=</span> small <span style="color: #000040;">+</span> big<span style="color: #008080;">;</span>
    <span style="color: #0000dd;">cout</span> ＜＜ added ＜＜ endl<span style="color: #008080;">;</span>  <span style="color: #666666;">// 1が出力される。(small分が切り捨てられてる)</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>加算を行った結果、小数点以下の値が切り捨てられています。一瞬何が起こったのか解らなかったのですが、折角なので追ってみる事にしました。</p>
<p><span id="more-1546"></span></p>
<p>まずdoubleの内部表現は次のようになります。(詳細は<a href="http://ja.wikipedia.org/wiki/浮動小数点数">wikipediaを参照</a>)<br />
<img src='http://taichino.com/wp-content/plugins/wp-latexrender/pictures/ec2ed113f3e1c88825d107509b199200.gif' title='(-1)^{sign} \times 2^{(exponential-1023)} \times (1+significand)' alt='(-1)^{sign} \times 2^{(exponential-1023)} \times (1+significand)' align=absmiddle><br />
符号部(sign)が1bit、指数部(exponential)が11bit, 仮数部(significand)が52bitです。</p>
<p>実際に確認してみます。gdbで確認するには以下のようにします。(他に簡単な確認方法があれば教えて下さい。)</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">g++</span> <span style="color: #660033;">-g</span> test.cpp
$ <span style="color: #c20cb9; font-weight: bold;">gdb</span> .<span style="color: #000000; font-weight: bold;">/</span>a.out
<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">gdb</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> x<span style="color: #000000; font-weight: bold;">/</span>g <span style="color: #000000; font-weight: bold;">&amp;</span>small
0xbfffee88:	0x3c32725dd1d243ac
<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">gdb</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> x<span style="color: #000000; font-weight: bold;">/</span>g <span style="color: #000000; font-weight: bold;">&amp;</span>big
0xbfffee90:	0x3ff0000000000000
<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #c20cb9; font-weight: bold;">gdb</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> x<span style="color: #000000; font-weight: bold;">/</span>g <span style="color: #000000; font-weight: bold;">&amp;</span>added
0xbfffee98:	0x3ff0000000000000</pre></div></div>

<p>見ての通り、0&#215;3c32725dd1d243acと0&#215;3ff0000000000000の加算結果が0&#215;3ff0000000000000となっています。</p>
<p>まずbigの値を見てみると、符号部は0, 指数部は3ff, 仮数部は0です。これを先ほどの式に当てはめます。<br />
<img src='http://taichino.com/wp-content/plugins/wp-latexrender/pictures/e833edef2f7b2416105d2708f8807cfa.gif' title='(-1)^{0} \times 2^{(1023-1023)} \times (1.0) = 1.0' alt='(-1)^{0} \times 2^{(1023-1023)} \times (1.0) = 1.0' align=absmiddle></p>
<p>上で見た式の通りにデータが構成されていますね！同様にsmallについても見てみましょう。<br />
<img src='http://taichino.com/wp-content/plugins/wp-latexrender/pictures/b207980a01ccc01da64fd8118fe225ba.gif' title='(-1)^{0} \times 2^{(963-1023)} \times (1.2725dd1d243ac) = (-1)^{0} \times 2^{-60} \times (1.2725dd1d243ac)' alt='(-1)^{0} \times 2^{(963-1023)} \times (1.2725dd1d243ac) = (-1)^{0} \times 2^{-60} \times (1.2725dd1d243ac)' align=absmiddle></p>
<p>これで大分と事情が飲み込めますね。加算の際は指数部の桁をあわせる必要がありますが、smallとbigでは指数部に2^60倍の差があるため、smallの仮数部が60bit分右にシフトします。仮数部は全部で52bitしか無いので、結果的にすべて0になってしまい、smallの値は切り捨てられることになります。</p>
<p>このような現象は情報落ちと呼ばれていて、僕も学校で習った気はしますが、きちんと考えたのは今回が初めてでした。倍精度の浮動小数点といっても、絶対値の大きく違う数を同時に扱おうとすると簡単に誤差が発生してしまう事が解りました。まだ感覚は掴みきれていませんが、気をつけて行こうと思います。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1546/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>flockのサンプルコード</title>
		<link>http://taichino.com/programming/1282</link>
		<comments>http://taichino.com/programming/1282#comments</comments>
		<pubDate>Fri, 04 Dec 2009 16:09:55 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[flock]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1282</guid>
		<description><![CDATA[マルチプロセスな処理をするのに必須な排他制御ですが、flockのサンプルが見つからなかったので書いてみました。

まず排他制御しないとまずい例は以下の様なコードでしょうか。(サンプルなのでエラー処理をしていません。)
ファイルを読み、記述されている数字をインクリメントして再度ファイルに書くという処理を２つのプロセスから10回ずつ行っています。合計で20回のインクリメントが走るので最後の値は20を期待してるのですがそうはなりません。

#include &#34;stdio.h&#34;
#include &#34;string.h&#34;
#include &#34;stdlib.h&#34;
#include &#34;unistd.h&#34;
&#160;
int main&#40;int argc, char* argv&#41; &#123;
	char* filename = &#34;test.txt&#34;;
	FILE* fh;
	char rbuf&#91;16&#93;, wbuf&#91;16&#93;;	
&#160;
	// ファイルの初期化
	if &#40;fh = fopen&#40;filename, &#34;w&#34;&#41;&#41; &#123;
		fclose&#40;fh&#41;;
	&#125;
&#160;
	// 親プロセスと子プロセスで同時に以下のコードを走らせる
	pid_t id = fork&#40;&#41;;	
	for &#40;int i = 0; i &#60; 10; i++&#41; &#123;
		pid_t cur = getpid&#40;&#41;;
		if &#40;fh = fopen&#40;filename, &#34;r+&#34;&#41;&#41; &#123;
			fread&#40;rbuf, sizeof&#40;char&#41;, sizeof&#40;rbuf&#41;, fh&#41;;
			fseek&#40;fh, 0L, SEEK_SET&#41;;
			sprintf&#40;wbuf, &#34;%d&#34;, atoi&#40;rbuf&#41;+1&#41;;
			fwrite&#40;wbuf, sizeof&#40;char&#41;, strlen&#40;wbuf&#41;, fh&#41;;
			printf&#40;&#34;%d:%s\n&#34;, cur, wbuf&#41;;
			fclose&#40;fh&#41;;			
		&#125;
	&#125;
&#125;

実行毎に結果は違いますが、例えば以下の様な出力が得られます。


$ [...]]]></description>
			<content:encoded><![CDATA[<p>マルチプロセスな処理をするのに必須な排他制御ですが、flockのサンプルが見つからなかったので書いてみました。</p>
<p><span id="more-1282"></span></p>
<p>まず排他制御しないとまずい例は以下の様なコードでしょうか。(サンプルなのでエラー処理をしていません。)<br />
ファイルを読み、記述されている数字をインクリメントして再度ファイルに書くという処理を２つのプロセスから10回ずつ行っています。合計で20回のインクリメントが走るので最後の値は20を期待してるのですがそうはなりません。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #339900;">#include &quot;string.h&quot;</span>
<span style="color: #339900;">#include &quot;stdlib.h&quot;</span>
<span style="color: #339900;">#include &quot;unistd.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> filename <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;test.txt&quot;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">FILE</span><span style="color: #000040;">*</span> fh<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">char</span> rbuf<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #008000;">&#93;</span>, wbuf<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>	
&nbsp;
	<span style="color: #666666;">// ファイルの初期化</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>fh <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span>filename, <span style="color: #FF0000;">&quot;w&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">fclose</span><span style="color: #008000;">&#40;</span>fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #666666;">// 親プロセスと子プロセスで同時に以下のコードを走らせる</span>
	pid_t id <span style="color: #000080;">=</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>	
	<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">10</span><span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
		pid_t cur <span style="color: #000080;">=</span> getpid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>fh <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span>filename, <span style="color: #FF0000;">&quot;r+&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
			<span style="color: #0000dd;">fread</span><span style="color: #008000;">&#40;</span>rbuf, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>rbuf<span style="color: #008000;">&#41;</span>, fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000dd;">fseek</span><span style="color: #008000;">&#40;</span>fh, <span style="color: #0000dd;">0L</span>, <span style="color: #0000ff;">SEEK_SET</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>wbuf, <span style="color: #FF0000;">&quot;%d&quot;</span>, <span style="color: #0000dd;">atoi</span><span style="color: #008000;">&#40;</span>rbuf<span style="color: #008000;">&#41;</span><span style="color: #000040;">+</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000dd;">fwrite</span><span style="color: #008000;">&#40;</span>wbuf, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>wbuf<span style="color: #008000;">&#41;</span>, fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d:%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, cur, wbuf<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000dd;">fclose</span><span style="color: #008000;">&#40;</span>fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>			
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>実行毎に結果は違いますが、例えば以下の様な出力が得られます。
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">g++</span> flock_test.cpp <span style="color: #660033;">-o</span> flock_test <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> .<span style="color: #000000; font-weight: bold;">/</span>flock_test
<span style="color: #666666; font-style: italic;"># 出力例１ プロセスAが書き込む前に、プロセスBが読み込んでいる</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">1</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">1</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">2</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">3</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">4</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">5</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">6</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">7</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">7</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">8</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">8</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">9</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">9</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">10</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">10</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">11</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">11</span>
<span style="color: #000000;">80293</span>:<span style="color: #000000;">12</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">12</span>
<span style="color: #000000;">80292</span>:<span style="color: #000000;">13</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># 出力例２プロセスAの書込中に、プロセスBも書込んでいる</span>
$ .<span style="color: #000000; font-weight: bold;">/</span>flock_test
<span style="color: #000000;">80322</span>:<span style="color: #000000;">1</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">2</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">2</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">3</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">4</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">3</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">4</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">5</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">6</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">7</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">8</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">9</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">10</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">11</span>
<span style="color: #000000;">80322</span>:<span style="color: #000000;">12</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">8</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">83</span>    <span style="color: #666666; font-style: italic;"># ここで値が壊れている</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">84</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">85</span>
<span style="color: #000000;">80323</span>:<span style="color: #000000;">86</span></pre></div></div>

<p>特に出力例２ではプロセスAが「13」と書こうとして1を書いたタイミングでプロセスBが8書き、その後プロセスAが3を書き込み、見事に値が壊れています。このように複数のプロセスから同一ファイルへアクセスする為には排他制御が必須で、linux系のOSではflockがよく使われます。</p>
<p>先ほどのコードをflockを使って排他制御してみたコードが以下になります。(やはりエラー処理はしていません) 処理自体は簡単で、flockにロックを取得したいファイルのファイルディスクリプタを指定してロックを取得します。ファイルディスクリプタはfilenoでファイルハンドルから取得できます。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;stdio.h&quot;</span>
<span style="color: #339900;">#include &quot;string.h&quot;</span>
<span style="color: #339900;">#include &quot;stdlib.h&quot;</span>
<span style="color: #339900;">#include &quot;unistd.h&quot;</span>
<span style="color: #339900;">#include &quot;sys/file.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
	<span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> filename <span style="color: #000080;">=</span> <span style="color: #FF0000;">&quot;test.txt&quot;</span><span style="color: #008080;">;</span>
	<span style="color: #0000ff;">FILE</span><span style="color: #000040;">*</span> fh<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">char</span> rbuf<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #008000;">&#93;</span>, wbuf<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">16</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>	
&nbsp;
	<span style="color: #666666;">// ファイルの初期化</span>
	<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>fh <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span>filename, <span style="color: #FF0000;">&quot;w&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">fclose</span><span style="color: #008000;">&#40;</span>fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #666666;">// 親プロセスと子プロセスで同時に以下のコードを走らせる</span>
	pid_t id <span style="color: #000080;">=</span> fork<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>	
	<span style="color: #0000ff;">for</span> <span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span> i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">10</span><span style="color: #008080;">;</span> i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
		pid_t cur <span style="color: #000080;">=</span> getpid<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
		<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>fh <span style="color: #000080;">=</span> <span style="color: #0000dd;">fopen</span><span style="color: #008000;">&#40;</span>filename, <span style="color: #FF0000;">&quot;r+&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
			<span style="color: #0000ff;">int</span> fd <span style="color: #000080;">=</span> fileno<span style="color: #008000;">&#40;</span>fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span>flock<span style="color: #008000;">&#40;</span>fd, LOCK_EX<span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>  <span style="color: #666666;">// ロックを取得</span>
				<span style="color: #0000dd;">fread</span><span style="color: #008000;">&#40;</span>rbuf, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span>rbuf<span style="color: #008000;">&#41;</span>, fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
				<span style="color: #0000dd;">fseek</span><span style="color: #008000;">&#40;</span>fh, <span style="color: #0000dd;">0L</span>, <span style="color: #0000ff;">SEEK_SET</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
				<span style="color: #0000dd;">sprintf</span><span style="color: #008000;">&#40;</span>wbuf, <span style="color: #FF0000;">&quot;%d&quot;</span>, <span style="color: #0000dd;">atoi</span><span style="color: #008000;">&#40;</span>rbuf<span style="color: #008000;">&#41;</span><span style="color: #000040;">+</span><span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
				<span style="color: #0000dd;">fwrite</span><span style="color: #008000;">&#40;</span>wbuf, <span style="color: #0000dd;">sizeof</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #008000;">&#41;</span>, <span style="color: #0000dd;">strlen</span><span style="color: #008000;">&#40;</span>wbuf<span style="color: #008000;">&#41;</span>, fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
				<span style="color: #0000dd;">printf</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;%d:%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>, cur, wbuf<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			<span style="color: #008000;">&#125;</span>
			<span style="color: #0000dd;">fclose</span><span style="color: #008000;">&#40;</span>fh<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
			flock<span style="color: #008000;">&#40;</span>fd, LOCK_UN<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>			    <span style="color: #666666;">// ロックを解放</span>
		<span style="color: #008000;">&#125;</span>
	<span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>これだと期待した出力が得られますね。
</pre>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">g++</span> flock_test.cpp <span style="color: #660033;">-o</span> flock_test <span style="color: #000000; font-weight: bold;">&amp;&amp;</span> .<span style="color: #000000; font-weight: bold;">/</span>flock_test
<span style="color: #000000;">80475</span>:<span style="color: #000000;">1</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">2</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">3</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">4</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">5</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">6</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">7</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">8</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">9</span>
<span style="color: #000000;">80475</span>:<span style="color: #000000;">10</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">11</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">12</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">13</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">14</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">15</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">16</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">17</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">18</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">19</span>
<span style="color: #000000;">80476</span>:<span style="color: #000000;">20</span></pre></div></div>

<p>なおflock時に指定するフラグは以下の通り。</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define   LOCK_SH   1    /* shared lock */</span>
<span style="color: #339900;">#define   LOCK_EX   2    /* exclusive lock */</span>
<span style="color: #339900;">#define   LOCK_NB   4    /* don't block when locking */</span>
<span style="color: #339900;">#define   LOCK_UN   8    /* unlock */</span></pre></div></div>

<p>後flockはタイムアウトの機構が無いのが色々と面倒です。これだったらデータベースのトランザクション使った方が幾らか楽な気がしましたが、どうなんでしょうか。</p>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1282/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++で文字列のsplitにstringstreamが使える気がする</title>
		<link>http://taichino.com/programming/1238</link>
		<comments>http://taichino.com/programming/1238#comments</comments>
		<pubDate>Wed, 25 Nov 2009 18:55:48 +0000</pubDate>
		<dc:creator>taichino</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[c++]]></category>
		<category><![CDATA[stringstream]]></category>

		<guid isPermaLink="false">http://taichino.com/?p=1238</guid>
		<description><![CDATA[久々にtopcoderをやってみたんですが、１問しか解けませんでした。終わった時は練習しようと思うんですが、中々実行できないです。。
久々すぎて文字列のsplitすら出来なくて、そんな馬鹿なと思って調べてみると、STLのstringってsplitメソッドが無いんですね。仕方ないのでその辺のコードをコピペしたんですが、終わってから皆さんのコードを見るとstringstreamでsplitするのが、常套手段っぽくて、初めて目にしたのでメモ書きです。


#include &#60;vector&#62;
#include &#60;string&#62;
#include &#60;iostream&#62;
#include &#60;sstream&#62;
&#160;
using namespace std;
&#160;
int main&#40;int argc, char* argv&#41; &#123;
	stringstream ss&#40;&#34;hello std world&#34;&#41;;   // これでスペースで文字列splitできる
	string elem;
	while &#40;ss &#62;&#62; elem&#41; &#123;
		cout &#60; &#60; elem &#60;&#60; endl;
	&#125;
&#160;
	return 0;
&#125;

確かにこれなら結構シンプルで良いですね。デリミタがスペースしか受け付けないので、事前にreplace処理をしておかないと駄目なのが面倒ですけど。あれ、TopCoderってboost使えないんでしたっけ。

]]></description>
			<content:encoded><![CDATA[<p>久々にtopcoderをやってみたんですが、１問しか解けませんでした。終わった時は練習しようと思うんですが、中々実行できないです。。</p>
<p>久々すぎて文字列のsplitすら出来なくて、そんな馬鹿なと思って調べてみると、STLのstringってsplitメソッドが無いんですね。仕方ないのでその辺のコードをコピペしたんですが、終わってから皆さんのコードを見るとstringstreamでsplitするのが、常套手段っぽくて、初めて目にしたのでメモ書きです。</p>
<p><span id="more-1238"></span></p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;vector&gt;</span>
<span style="color: #339900;">#include &lt;string&gt;</span>
<span style="color: #339900;">#include &lt;iostream&gt;</span>
<span style="color: #339900;">#include &lt;sstream&gt;</span>
&nbsp;
<span style="color: #0000ff;">using</span> <span style="color: #0000ff;">namespace</span> std<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
	stringstream ss<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;hello std world&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>   <span style="color: #666666;">// これでスペースで文字列splitできる</span>
	string elem<span style="color: #008080;">;</span>
	<span style="color: #0000ff;">while</span> <span style="color: #008000;">&#40;</span>ss <span style="color: #000080;">&gt;&gt;</span> elem<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
		<span style="color: #0000dd;">cout</span> <span style="color: #000080;">&lt;</span> <span style="color: #000080;">&lt;</span> elem <span style="color: #000080;">&lt;&lt;</span> endl<span style="color: #008080;">;</span>
	<span style="color: #008000;">&#125;</span>
&nbsp;
	<span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>確かにこれなら結構シンプルで良いですね。デリミタがスペースしか受け付けないので、事前にreplace処理をしておかないと駄目なのが面倒ですけど。あれ、TopCoderってboost使えないんでしたっけ。<br />
</sstream></iostream></string></vector></pre>
]]></content:encoded>
			<wfw:commentRss>http://taichino.com/programming/1238/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
