C言語関係掲示板

過去ログ

No797 プログラム実行結果をテキストに保存するには

[戻る] [ホームページ]
No.9997

プログラム実行結果をテキストに保存するには
投稿者---翔太(2003/10/25 10:03:14)


http://wwwdoi.elec.nara-k.ac.jp/html/jisyu/dxm/cap2/index.html
のcap26.cppのプログラム実行結果をテキストに保存するプログラムをください。このプログラムを実行すると
amt.lSampleSize = 1036800
BitmapInfo.bmiHeader.biBitCount = 24
キャプチャを開始します、どれかキーを押して下さい
グラブ hr = 80040227, n = 0.000000
グラブ hr = 0, n = 58.767339
グラブ hr = 0, n = 4.656205
グラブ hr = 0, n = 4.146371

と、このような結果があられます。そこで、nの結果だけをテキストまたは、エクセルに保存するプログラムを教えてください。
また、何回も実行しても前のデータが消えないように、名前をつけて保存できるようにしたいです。
(実行結果の例)
*****************************************************
amt.lSampleSize = 1036800
BitmapInfo.bmiHeader.biBitCount = 24
キャプチャを開始します、どれかキーを押して下さい
グラブ hr = 80040227, n = 0.000000
グラブ hr = 0, n = 58.767339
グラブ hr = 0, n = 4.656205
グラブ hr = 0, n = 4.146371

nの値を名前をつけて保存します。
保存名:xxxx.txt
グラブ停止:終了 -- q 、再開 -- その他のキー
******************************************

また、どこに実行結果の数値をテキストに書き込む処理を入れれば、
いいのでしょうか?

教えてください。




No.9998

Re:プログラム実行結果をテキストに保存するには
投稿者---YuO(2003/10/25 11:45:26)


>と、このような結果があられます。そこで、nの結果だけをテキストまたは、エクセルに保存するプログラムを教えてください。

標準出力をリダイレクトして,あとはsedで整形してしまうのが一番手っ取り早そうです。


>また、どこに実行結果の数値をテキストに書き込む処理を入れれば、
>いいのでしょうか?

最初にファイル名をきめて置くならば,nの値を出力している場所に,
最後であるなら,ファイル名を入力した直後に,入れることになります。

最後だと,それまでのnの値を保存しておく必要があります。
まぁ,C++だしstd::vector<double>か何かに突っ込んでおけばすむ話ですが。
#今回のプログラムだと例外対策が一切無いから,vectorは使いにくいかも。


No.10085

割り込みですみません。
投稿者---かな(2003/10/27 10:57:38)


>まぁ,C++だしstd::vector<double>か何かに突っ込んでおけばすむ話ですが。
>#今回のプログラムだと例外対策が一切無いから,vectorは使いにくいかも。

vectorを使用するためには、どういった例外対策が必要なのでしょうか?
このままだと、どんな点が「vectorは使いにくい」のでしょうか?
できれば、初心者向けに教えて頂けると嬉しいです。



No.10086

Re:割り込みですみません。
投稿者---YuO(2003/10/27 12:39:59)


>>まぁ,C++だしstd::vector<double>か何かに突っ込んでおけばすむ話ですが。
>>#今回のプログラムだと例外対策が一切無いから,vectorは使いにくいかも。
>vectorを使用するためには、どういった例外対策が必要なのでしょうか?
>このままだと、どんな点が「vectorは使いにくい」のでしょうか?

まず,vectorの宣言は
template <class T, class Allocator = std::allocator<T> > class std::vector;
であることを思い出して下さい。
#知らない人も結構いるかも……。
そして,vectorはメモリをAllocatorで指定されたクラスのインスタンスから取得します。

std::allocator(標準のアロケータ)は,メモリが割り当てられない時にstd::bad_alloc例外を発生させます。
それを捕捉していないですから,例外が起きたときにstd::abortが最終的に呼び出されます。

結果,一切の終了処理が行われないままプログラムが終了してしまいます。
COM後処理が行われないですから,リソースリークが起きる可能性を持っています。

ちなみに,VC++ 6.0までのstd::allocatorはstd::bad_allocを送出しないので,なかなか悲惨なことになります。
#空ポインタアクセスが起きる。


C++の鉄則に近いですが,リソースは自動解放用のオブジェクトに管理させることによって,リークの可能性を排除することができます。
#スマートポインタと呼びます。

今回の場合だと,
template <typename T> class COMObject {
    T * object_;

public:
    COMObject (T * object = 0) : object_(object)
    {
        if (object_ != 0) object_->AddRef();
    }
    COMObject (const COMObject & object) : object_(object.object_)
    {
        if (object_ != 0) object_->AddRef();
    }
    ~COMObject (void)
    {
        if (object_) object_->Release();
    }
    COMObject & operator= (const COMObject & rhs)
    {
        if (rhs.object_) rhs.object_->AddRef();
        if (object_) object_->Release();
        object_ = rhs.object_;
        return *this;
    }

    T * operator-> (void) const { return object_; }
    T * get (void) const { return object_; }

    void ** toPPVoid (void) { return (void **)&object_; }

    void release (void)
    {
        if (object_) object_->Release();
        object_ = 0;
    }

    bool isValid (void) const { return object_ != 0; }
    bool operator! (void) const { return !object_; }
};

なんてテンプレートを用意してやると,例外が起きても必ずCOMインターフェースのリソースを解放してくれます。
#VC++利用なら,COMの為のスマートポインタは_com_ptr_tを使った方がよいかも。


No.10092

Re:割り込みですみません。
投稿者---たか(2003/10/27 16:24:43)


>C++の鉄則に近いですが,リソースは自動解放用のオブジェクトに管理させることによって,リークの可能性を排除することができます。
>#スマートポインタと呼びます。

なるほど、参照カウント型のスマートポインタですか。boost::shared_ptr
に似ていますな。そうでないとSTLのコンテナに入れて操作した途端破綻
してしまいますから。COAP(Containers of auto_ptr)は標準C++では禁止
されていますね。


No.10116

Re:割り込みですみません。
投稿者---かな(2003/10/28 09:37:35)


Yuoさん、たかさん、ありがとうございます。
丁寧な説明なのだと思うのですが、初心者すぎて理解できませんでした。
すみません。。。
でも、このままにしたくないので、もう少し時間をかけて勉強して
理解したいと思います。
今は、どこを質問して良いのかも分からないので、
勉強した後、別スレをたてて、質問したいと思います。
そのときは、よろしくお願いします。

現在、引き継いだシステムの改造中なのですが、
vectorを使用している箇所もあり、「初心者で、分かりません。」では、すまないから。。。
今のところ、例外にどこまで対応して良いのか、わからない状態です。
引き継いだソースには、CArray::Add()など、MSDNを見るとthrow();と書いてあるのに、
例外をcatchしていない個所が多々あります。
というか、ファイルI/O以外は、全く例外を考慮していません。
ひとつ、ひとつ調べて、どういう例外には対策するか基準を決めて、
修正しなくっちゃかなぁ。。。と思っているのですが。。。

普通、Windowsのアプリケーションって、どこまで例外対策するものなのでしょうか?
やっぱ、いちがいには言えないって感じですか?
それとも、MSDNにthrow();と載っているもの全てでしょうか?
Yuoさんや、たかさんがアプリケーションを作る時の
例外対策の基準を聞かせて頂けたら嬉しいです。

No.10121

Re:割り込みですみません。
投稿者---たか(2003/10/28 12:38:47)


>>普通、Windowsのアプリケーションって、どこまで例外対策するものなのでしょうか?
>やっぱ、いちがいには言えないって感じですか?
>それとも、MSDNにthrow();と載っているもの全てでしょうか?

C++の特徴として、例外処理が簡単にできる事があげられますが、そうと
は言え全部が全部のメンバ関数の呼び出し時にユーザプログラム側でtry
{} catch() を付けると相当面倒な事になります。だから、プログラム
にもよって変わりますが、関数が異常なパラメータを与えられて、この
ままプログラムを実行するとシステム全体のダウンを引き起こすような
重大な(クリティカル)な部分か、OOプログラムをして継承先のメンバ関数
でエラーを起こしBaseに戻ってエラー処理をしたい場合とか、そんな場合
でしょう。

それよりも、「いつ例外を送出するか」の方がずっと難しいです。例えば
コンストラクタ内で不幸にも必要なメモリ領域がnewで確保できなかった
としましょう。この場合newをいくつも含んだコンストラクタでは例外を
送出しないとどちらにしろこのコンストラクタで初期化されたオブジェク
トは役に立たず、new出来た分はメモリリークの原因となります。そのた
め例外が送出されたら自動的にデストラクタを呼び出すようにしておけば、
そのような事態は防げます。後そうですね、コンストラクタ内でファイル
のオープン処理を行っていて、それに失敗した場合など。

MSDNを読んでらっしゃるなら、関数の仕様にthrow(何とか)と書いてある
ものを呼び出す時は原則としてtry catch で囲んでおくとよいでしょう。
そうしないといざ例外が送出された時点でエラーハンドリングルーチンが
ないとたちまちプログラムが異常終了します。

もちろん学習用とか売り物にするつもりがないのであれば、例外処理は
一切省くのが普通です。これはまだバグが残っているようなβバージョン
を時間の関係で顧客に出す場合、最低限止まらずに走り続けさせたい場合
に役立ちます。もちろん完成版でも常に例外を送出する可能性のある関数
にはエラーハンドリングルーチンを付けます。

No.10122

Re:割り込みですみません。
投稿者---たか(2003/10/28 12:41:56)


それと関数の後ろ側に throw(); と書いてあるものは「例外を送出でき
ない」という意味ですので誤解なきよう。

No.10181

Re:割り込みですみません。
投稿者---かな(2003/10/30 09:43:12)


出張があって、お返事が遅くなってしまって、すみません。

たかさん、例外処理について丁寧な説明を本当にありがとうございます。
周りがCプログラマばかりで、C++について相談できず、
かなり煮詰まっていたので、とても嬉しかったです。

>それと関数の後ろ側に throw(); と書いてあるものは「例外を送出でき
>ない」という意味ですので誤解なきよう。
  これは、MSDNのことですか?
  関数の形式の次にthrow(****);って書いてあるのは、
  「その例外がthrow()されることがある」って読み取れば良いのですよね?
  上記の件は、どこの記述のことでしょうか?
  「関数の後ろ側」というのが分からず、いろんな関数のMSDNを
  見てみたのですが、結局分かりませんでした。
  たいへん申し訳ありませんが、もう少し詳しく教えて頂けないでしょうか?

翔太さん、割り込みで長くなってしまい、申し訳ありません。


No.10187

Re:割り込みですみません。
投稿者---たか(2003/10/30 10:35:25)


>出張があって、お返事が遅くなってしまって、すみません。
>
>たかさん、例外処理について丁寧な説明を本当にありがとうございます。
>周りがCプログラマばかりで、C++について相談できず、
>かなり煮詰まっていたので、とても嬉しかったです。
>
>>それと関数の後ろ側に throw(); と書いてあるものは「例外を送出でき
>>ない」という意味ですので誤解なきよう。
>  これは、MSDNのことですか?
>  関数の形式の次にthrow(****);って書いてあるのは、
>  「その例外がthrow()されることがある」って読み取れば良いのですよね?
>  上記の件は、どこの記述のことでしょうか?
>  「関数の後ろ側」というのが分からず、いろんな関数のMSDNを
>  見てみたのですが、結局分かりませんでした。
>  たいへん申し訳ありませんが、もう少し詳しく教えて頂けないでしょうか?
>
>翔太さん、割り込みで長くなってしまい、申し訳ありません。

例えばMSDNのCとC++、第6部ではnewとdeleteのオーバーロード版

void *operator new(size_t) throw(std::bad_alloc);
void operator delete(void *) throw();

の宣言が書いてありますが、これによるとnewはstd::bad_allocを投げる
可能性があり、deleteは例外を投げないことがわかります。もしdelete
の実現ルーチン内から例外を投げると、abort()が呼び出されるでしょう。

またdynamic_castの検索をすると、リファレンス型をキャストして失敗
すると、std::bad_cast例外を投げる事が書いてあります。MSDNで例外処理
について勉強するのは私個人的にはちょっと酷な気がします。(とにかく
読みにくいし、大半が英語のままです。)

C++は言語仕様が膨大ですので、Cと違い参考書も多めに購入する必要があ
ると思います。言語仕様、標準ライブラリ、STL、OOデザインパターンな
どの各種本から必要なものを選んでご購入される事をお勧めします。

No.10189

Re:割り込みですみません。
投稿者---たか(2003/10/30 10:54:26)


そうだ、忘れてました。MSDNで "std::exception" で検索してみてくださ
い。それなりに詳しい説明があります(英語ですが・・・・)

ちなみに関数の後ろ側に throw(hoge, hage) が書かれていないものは
(初めはこればかりですね)、あらゆる例外を投げる可能性があるという
ことで、とてもcatch()では受けきれない事が分かります。
(もっともcatch(...)というのがありますが、意味がないですね。)

No.10193

Re:割り込みですみません。
投稿者---やすお(2003/10/30 11:48:44)


たかさん、ありがとうございます。
使っている関数を片っ端から見てみたのですが、
最も頻繁に使っているnewとdeleteを見ていませんでした。。。

>そうだ、忘れてました。MSDNで "std::exception" で検索してみてくださ
>い。それなりに詳しい説明があります(英語ですが・・・・)
  英語ですか。。。
  でも、頑張ってみます。

>ちなみに関数の後ろ側に throw(hoge, hage) が書かれていないものは
>(初めはこればかりですね)、あらゆる例外を投げる可能性があるという
>ことで、とてもcatch()では受けきれない事が分かります。
  え〜っ!!!
  書いてないものは、例外をthrowしないものだと思ってました!
  大変だぁぁぁ!
  貴重な情報を本当に本当にありがとうございました。
  現状のソースをどう直そうか、ちょっと呆然としてます。。。

この3ヶ月、MSDNのみを頼りに作ってきたのですが、参考書を購入してもらいます。
(まわりには言語関連はCの本だけで。。。)

ほんとうに、ありがとうございました。


No.10195

Re:割り込みですみません。
投稿者---かな(2003/10/30 12:34:19)


友達が使ったままの状態で返事を書いたのでHNが変わってしまいました。
上記のは「かな」です。

No.10196

Re:割り込みですみません。
投稿者---たか(2003/10/30 12:54:04)


ええと、ちょっと私自身うろ覚えなところがありました(^_^;)。
例外を送出する関数のプロトタイプで宣言されていない例外を送出した
場合はunexpected()、catch()で受けきれなかった場合はterminate()関数
が呼び出され、これらの関数はデフォルトでabort()関数を呼び出すでし
た。

unexpected()、terminate()関数はそれぞれset_unexpected()、set_terminate()
でabort()の代わりに呼び出す関数をユーザー指定できます。

それと、深くネストした関数から一気にトップレベルの関数に返値を返す
場合に例外を使うのはやめましょう。学習しだした最初の頃はどうしても
例外が便利でこのような使い方をしたくなりますが、setjmp()、longjmp()
と同じでスタックの巻き戻しが発生し、著しくコストがかかります。例外
はあくまでもエラーが発生した時のみに使用を限るべきです。

No.10202

Re:割り込みですみません。
投稿者---かな(2003/10/30 15:14:56)


たかさん、ありがとうございました。
わたしにとって、どれも貴重な情報でした。
参考にしてコーディングを進めようと思います。

ほんとうにありがとうございました。