2014年10月31日0件のコメントこんにちはSayahamittです。今回はC言語で逆ポーランド記法(スペース区切り)電卓を作ってみました。文字列の動的確保とか、リストでスタックを実装したりとかしたので備忘録として残しておこうと思います。(...Twitterクライアント?...(やってますよ...OOPとC++難しい...))仕様っぽいもの今回作った電卓では、四則演算が逆ポーランド記法(スペース区切り)によって書かれた数式を文字列入力として受け取り、スタックを利用して計算することにしました。和差積商以外の演算や関数はエラーを返すこととします。入力桁数に制限があるとつまらないので、mallocを使って文字配列を動的確保し、それに伴いスタックも双方向リストを用いて動的に伸縮できるように実装することとしました。動的確保のアルゴリズムは、文字列を伸ばす場合には容量が増えた後の全体を格納するのに必要なメモリを丸々全部確保し直すものとしました。input;}キーボードで入力された文字列を受け取る関数です。この関数では入力文字列の長さに応じて必要な分だけメモリを確保して文字列を作成し、返しています。手順のイメージ詳しい手順を文章で書くとソースコードをそのまま日本語にすることになるのでここではイメージだけ書きます。標準入力から一定長ずつ文字列を読み取って、それまでに読み取った文字列に付け加えていき、その度に累積した文字列の長さ分のメモリ領域を丸々新しく確保し直しています。上のコードでは10文字毎なので、大まかな手順は以下のようなループになります。1.10文字分のメモリ領域を確保しておく。確保したメモリ領域に書き込む。メモリ領域を新たに確保する。文字列(10文字)を付け加える。読み込むまで続けます。実際には、コピー処理そのものに必要なメモリ領域の確保や、一回前のループで確保したメモリ領域の開放などが必要になりますが、イメージとしては大体こんなもんです。value;}スタックをリストを使って実装しました。今回は入力文字列の長さの最大値が予測できないので、スタックも計算式の項数に応じて伸び縮み出来るようにリストを用いて実装することとしました。含める方法が一般的だと思うので、今回もそうしました。́・ω・`))計算をする上で一応小数点も扱えるようにするため、項の値はdouble型で保持しています。スタックについての説明は割愛しますが、実装に当って注意した部分だけ書きます。1.最低部のノードは次(下)のノードへのポインタをNULLとすることで規定しました。2.スタックのハンドラはスタックの最上部のノードへのポインタとしました。最低部のノードのポインタをハンドラにするとポップしたりプッシュしたりするたびにリストを全て辿らねばならず無駄が多いからです。3.プッシュ関数とポップ関数はハンドラへのポインタを介してリストにアクセスするようにしました。プッシュ操作やポップ操作を行うとスタックの最上部を指し示すポインタの値は変化することになります。この時に最上部を指し示すポインタそのものを利用してスタックにアクセスしていた場合には関数内でプッシュやポップの操作をする前に一つ下のノードのアドレスを記録し、呼び出し元へフィードバックする必要があります。ポップ関数では変更後の最上部ノードへのポインタを返せません。引数に取ることで直接スタック最上部へのポインタの値を書き換えることにしています。result;}えっと...まず煩雑で汚いコードでごめんなさい。́・ω・`)汚くて読みにくいので、何をやっているのかざっくりと説明します。この関数は入力された計算式の文字列を引数で受け取って四則演算をするものです。どれかだったらそれぞれ対応する演算処理を行う。スペースだったら読み飛ばす。それ以外の文字列だったら次のスペースまで読み込んでバッファに記録し、double型の数値に変換してスタックに積む。演算を行うまで繰り返す。四則演算の部分ですが、この関数は入力文字列が逆ポーランド記法で記述されていることを前提として期待して書かれているので、演算子を見つけたらスタックの上2つをポップしてその二項を演算することにしています。入力された時にはスタックの最上部にある値をresult変数に記録して、フラグを立ててループを抜けるようにしてあります。演算子を処理したかどうかを認識して読み込みを止めないときっと...確実にバグります。数値を読み込みの部分は、スペース区切りで計算式が入力されることを期待して実装しています(一応数値に続けて演算子が書かれていても何とかなるようには書いていますが)。外側のforで数値を読んだ場合には、次のスペースまでの文字数を数えて、strncpy関数を使ってバッファにその項の文字列をコピーしています。あとはバッファの文字列をatof関数でdoubel型の数値に変換してスタックにプッシュして処理を終えます。この関数では指定された演算子と数値以外の文字が入力された場合のエラー処理を書いていないので必要に応じて書き換えるべきです。項の文字数を数える時に「次の数値でない文字」までの長さを数えれば良いような気がします。今回書いた逆ポーランド記法電卓を実現するための関数の説明はざっくりこんなもんです。沢山のミスデザインと沢山の潜在的実行時エラーを含んでいるので、もし参考にするようなことがあればご注意下さい。́・ω・`)完動コードへのリンクも一応貼っておきます。コメントをキャンセルメールアドレスが公開されることはありません。*サイト次回のコメントで使用するためブラウザーに自分の名前、メールアドレス、サイトを保存する。コメントデータの処理方法の詳細はこちらをご覧ください。