アプリ版:「スタンプのみでお礼する」機能のリリースについて

卒業研究に取り組んでおり、
コンソールプログラムで得た出力結果(.exe)を、BuilderのMemoで表示させたいのですが、どの部分を書き直したらいいのかわかりません。私が思うに

1.Wimmain
2.出力部分

を書き直せばいいのかなと思うのですが、参考になるサイトなど知っていたら、またアドバイス等ございましたら教えて下さるとありがたいです。
今、namespaceの次にmainを書いているのですが、

 E2268 未定義の関数を呼び出した

というエラーが表示され、main文は読み込めていないようです。どなたかわかる方いましたらアドバイス宜しくお願いします。

追伸 .exeの内容をShellExcuteで呼び出すということも可能なのでしょうか。宜しくお願いいたします。

A 回答 (9件)

基本的なアイデア、namespaceを利用し、coutへの出力をstrstreamのcoutに振り替える、そうした文字列をメモコンポーネントにセットする。


手順1:プログラムファイルをコピーし、拡張子をcppからhに変えてStateをプログラムからincludeできるようにする
手順2:coutをostrstream(文字列への出力ストリーム)に置き換える為にnamespaceを定義し、ostrstream coutを定義する
手順3:main関数部分を削除する
以上の処理をしたState.h
#include <deque>
#include <iostream>
#include <strstream>

using namespace std;
namespace my{
ostrstream cout;

struct State{
bool wolf;
bool goat;
bool cabbage;
bool man;
deque<State> path;

State()
: wolf( false ), goat( false ), cabbage( false ), man( false ), path(){ }

bool succeeded() const{
return( this -> wolf && this -> goat && this -> cabbage && this -> man );
}
bool failed() const {
return( (wolf == goat && man != wolf)||(goat == cabbage && man != goat));
}

State move_wolf() const {
State s = *this;
s.path.push_back( *this );
if ( s.wolf == s.man ){
s.wolf = !s.wolf;
s.man = !s.man;
}
return( s );
}
State move_goat() const {
State s = *this;
s.path.push_back( *this );
if ( s.goat == s.man ){
s.goat = !s.goat;
s.man = !s.man;
}
return( s );
}
State move_cabbage() const {
State s = *this;
s.path.push_back( *this );
if ( s.cabbage == s.man ) {
s.cabbage = !s.cabbage;
s.man = !s.man;
}
return( s );
}
State move_man() const {
State s = *this;
s.path.push_back( *this );
s.man = !s.man;
return( s );
}

bool operator == ( const State& s ) const{
return( this->wolf == s.wolf && this->goat == s.goat && this->cabbage == s.cabbage && this->man == s.man );
}
bool operator != ( const State& s ) const{
return(!(*this == s));
}
};

ostream& operator << ( ostream & ostr , const State & s ){
ostr << (s.wolf ? "" : "w") << (s.goat ? "" : "g")
<< (s.cabbage ? "" : "c") << (s.man ? "" : "m")
<< "-"
<< (s.wolf ? "w" : "") << (s.goat ? "g" : "")
<< (s.cabbage ? "c" : "") << (s.man ? "m" : "");
return( ostr );
}

void print_progress( const State& s, const deque<State>& open_list, const deque<State>& closed_list){
cout << "Testing " << s << endl;
cout << "Open List =";
for ( size_t i = 0 ; i < open_list.size() ; i ++ ){
cout << " " << open_list[i];
}
cout << endl;
cout << "Closed List =";
for ( size_t i = 0 ; i < closed_list.size() ; i ++ ){
cout << " " << closed_list[i];
}
cout << endl;
}

void print_result( const State & s ){
cout << "Result = ";
for ( size_t i = 0 ; i < s.path.size() ; i ++ ){
cout << s.path[i] << " ";
}
cout << s << endl;
}
} //namespace my;
手順4:C++ビルダーを立ち上げて、メモコンポーネントとボタンコンポーネントを配置する
手順5:メモは初期文字列を消して、スクロールできるようにしておく、ボタンは名前を変える。
手順6:プロジェクト及びユニットを名前を付けて保存する
手順7:作成しておいたState.hを、作成したプロジェクトフォルダにコピーする
手順8:フォーム上のボタンをクリックしてボタンクリックイベントを作成する
手順9:元のプログラムのmain関数の中身をココにコピー&ペーストする
手順10:
return 文は消す。
coutの部分はmy::coutに変更しMemo1->Textに代入する
Memo1では、\nを\r\nに変更しないといけないのでAnsiReplaceStrする
State.hとvcl\StrUtils.hppをincludeするように書く
namespace my を使えるようにしておく
以上を処理したUnit1.cpp(このまま使わないでIDE上で書くこと)
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include <vcl\StrUtils.hpp>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
#include "State.h"
using namespace my;
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{

State start_state;
deque<State> open_list;
deque<State> closed_list;

open_list.push_back( start_state );
while( ! open_list.empty() ){
State s = open_list.front();
open_list.erase( open_list.begin() );
print_progress( s , open_list , closed_list );
my::cout << endl;

if ( s.succeeded() ){
print_result( s );
break;
}

if ( s.failed() ){
continue;
}

if ( find( closed_list.begin() , closed_list.end() , s )== closed_list.end() ){
open_list.push_back( s.move_wolf() );
open_list.push_back( s.move_goat() );
open_list.push_back( s.move_cabbage() );
open_list.push_back( s.move_man() );

closed_list.push_back( s );
}
}
Memo1->Text=my::cout.str();
Memo1->Text=AnsiReplaceStr(Memo1->Text, "\n", "\r\n");
}
手順11:いったん全て保存してビルド&実行
    • good
    • 0
この回答へのお礼

おっしゃるとおりにしてみましたら、memoに表示されました!大変ありがとうございました。
私は全文ボタンのイベント内に書き込んでいたのですが、それでは、main文きちんとを読み込んで表示することはできないのでしょうか。State.hとmain部分と二つに分割しないとできないのでしょうか。

お礼日時:2005/01/14 13:50

>参考にできるサイトなどご存じであれば教えてほしいのですが…


参考になるサイトなんかないと思います。
というのも、ステップ実行のアルゴリズムというのは、アルゴリズムとして独立したようなものではないためです。
ステップ実行したいプログラムの構造に強く依存していて、その"ステップ"の切り出しはプログラムに依るからです。
強いて言うなら、ステップで実行できるような構造であらかじめ作っておくということでしょうか
例えば、このプログラムで言えば、その時の状態をゴールの状態に1コ変移させるというのが1つのステップ(ゴールを目指してということ、トラックバックは当然起こる)とするというとわかりがいいかもしれません。
ステップ実行というのを、どういうレベルで捉えるかでまた違うのかも知れませんが、
簡単には、今あるプログラムでは、whileの一回のループを1つのステップとして考えるなら、ボタンを押す毎にループ一回分の実行をすると考えれば、(今のループを開くことに相当する)いいのじゃないですか?
まあ、好きにやればいいですよ。

もともとこのプログラムってどっかに載っていたものなんですよね。
一体あなたが考えたことってどれ程有るのでしょうか?
すぐに、何かに求めるのではなく少しは試行錯誤しないと何も身に付きません。
    • good
    • 0
この回答へのお礼

依存してしまい、大変すみませんでした。
それでもお返事を下さり申し訳なく思います。
がんばります。

お礼日時:2005/01/19 17:13

>…の方が取り組みやすいですかね?


いろいろちゃちゃを入れてごめんなさい
好きにやってもらえばいいんですよ。
    • good
    • 0
この回答へのお礼

こんなお返事させてすみません。
まったく見当の付かないもので思わずどちらが難しくないのかという意味で聞いてしまいました。

しかしながらステップ実行ですが、考え方がわからず…
参考にできるサイトなどご存じであれば教えてほしいのですが…

お礼日時:2005/01/19 11:22

>例えば、出力先としてMemoコンポーネントを引数で渡すようなプログラムにするとしても、State側とのインターフェース部分でやるようにするということです


確かに、変な文章ですね。すみません。
言いたかったことは、
利用するプログラムから
#include "State.h"すれば使えるようにするということで、Stateの実現部分でMemo1とかMemo2とかを直接触るようなプログラムにはしないということです。
つまり、決められたインターフェースにしたがって、Stateは出力し、利用する側は出力を受けるようにするということです。
まあ、その受け渡し窓口は、Stringでも、strstreamでも、MemoでもMemo->Linesでもいいかと思いますけど。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。

>#include "State.h"すれば使えるようにするということで、Stateの実現部分でMemo1とかMemo2とかを直接触るようなプログラムにはしないということです。

の文章が理解に苦しみました。。

#5より
>print_progress( s , open_list , closed_list );
>my::cout << endl;
>の部分で、継続できるように作り直さないとしょうがないのじゃないでしょうか

>簡単には、
>単に、メッセージボックスを表示して、継続するようにすればいいだけの様にも思えます。

継続するとはどういう意味でしょうか。
例えば今考えている例としては
 
 1.Buttonを押すことにより1ステップずつ、1つのMemo実行結果が表示される
 2.Buttonを押し、1ステップ結果が表示され、同時にMessageBoxを出し、Box内のButtonをクリックすると2ステップ目の結果が表示される

だとすれば1.の方が取り組みやすいですかね?
別のmemoに表示するのは難しそうなので、まずは実行部分をいじろうかと思っているのですが…

お礼日時:2005/01/18 15:06

>Memo出力のところで止まってしまい


どのように実現しようとしているかは知らないので、見当違いのコメントかもしれませんが、
struct Stateの問題点の1つは、
coutを使っていることです。
coutは、言わば大域変数で、struct Stateは、出力をこれに依存しています。
これでは、カプセル化されてるとは言えず、使い難いものになります。今回のような出力を他に切り替えようと言う場合に、苦労することになります。
なので、Stateを大幅に変更しようと考えておられるのなら、そのような、カプセル化ということを考えてみられると良いと思います。
例えば、今回は、coutを別のストリームで置き換えることで、ラップをかぶせて、元の部分がそのままでいけるようにしたわけですが、ストリームを、クラス変数のような形で、クラスに持たせることにし、コンストラクタにストリームの参照を渡すことで、簡単に切り替えることができたと思います。
現在は、外部の関数である、print_*の関数の引数で渡してもいいし。
最悪なのは、それぞれの部分でMemoコンポーネントに直接アクセスすることですが、
例えば、出力先としてMemoコンポーネントを引数で渡すようなプログラムにするとしても、State側とのインターフェース部分でやるようにするということです。
そうすれば、オーバーロードで、出力先が、ストリームの場合、Memoコンポーネントの場合というように入口を作ることができます。
なんだか、わけわからんコメントだとしたらすみません。
#5でのコメントが、coutを単にMemo->Lines->Addに置き換えるようなこと意味していると思われたらイヤなので余談を書いてみました。
    • good
    • 0
この回答へのお礼

お返事ありがとうございます。大幅に変更しなければ出力先を変えるのは難しいんですね、やはり。
いまの出力方法ではS,Open_listなど区別できないですもんね…
難しいお話でしたが理解はできました。(書くのは別問題ですが…

ひとつ
>例えば、出力先としてMemoコンポーネントを引数で渡すようなプログラムにするとしても、State側とのインターフェース部分でやるようにするということです。

の意味合いがよく取れなかったのですがもう少し説明して頂けませんでしょうか。

お礼日時:2005/01/18 11:14

>別のメモに表示するにはどのようにしたらいいのでしょうか


#1の参考URLは、見ましたか?
そもそも、coutしている部分を
参考URL#2
「Memo1->Lines->Add("書きたい文字列");
のようにして、メモに行を追加することができます。」
のようにして、メモに文字列を追加していくことができます。(同じことを言ってるにすぎませんが、やってみてから聞いてるんでしょうねと言いたいだけです)

>結果をステップ実行で一探索ごと表示していくにはどのようにすればよいのでしょうか。
print_progress( s , open_list , closed_list );
my::cout << endl;
の部分で、継続できるように作り直さないとしょうがないのじゃないでしょうか

簡単には、
単に、メッセージボックスを表示して、継続するようにすればいいだけの様にも思えます。
勘違いしてたらすみません。
    • good
    • 0

>main関数について


main関数は、特別な関数で、コンソールプログラムの場合、初期起動プロセス(?)から呼び出されます。
Winmain関数は、ウインドウズプログラムで同等のもの(最初に呼び出される)と考えてもいいのですが、
デルファイやC++ビルダー(あるいはVB)のようなイベント駆動型のプログラムを書いている時には、あまり気にしないでよいものです。
結論から言うと、イベント処理関数の中にmain関数を書いてもしょうがないです。(特別な呼び出しをされる関数とかでもなんでもないので)

イベント駆動型では、
例えば、ボタンをクリックしたら何々を実行するのようにプログラムを作成します。
なので、この場合、コンソールプログラムで実行したかったmainの中の処理部分を(ボタンを押すことで駆動されるように)書けばいいのです。
C++ビルダーに限らず、一般的にC系列の言語(GCCは除く)では、関数の中で関数を定義するということができません。
なので、ボタンイベントに今回のような全てのプログラムを書くのは正しくないです。
Stateは、プログラムというよりは、構造体なので、書けるかもしれませんが、こういう、クラスやC++でのクラスに準じた構造体は(再利用するだろうと思われるものは)別にするのが普通です。(ちなみに関数部分(structの外の部分)は、関数の中の関数になるのでできないと思います)
    • good
    • 0
この回答へのお礼

お返事遅くなり申し訳ありません。
細部にわたる説明、大変ありがとうございました。
ちなみにtesting、open_list、close_list、Resultをそれぞれ別のメモに表示するにはどのようにしたらいいのでしょうか。
私の案として、
print_progress1,2,3に分け、それぞれにs、open_list,closed_listの表示部分を書き、呼び出せばと思ったのですが、その後のMemo出力のところで止まってしまい…
またこの結果をステップ実行で一探索ごと表示していくにはどのようにすればよいのでしょうか。

意見ばかり求めてしまい、大変申し訳ないです。すみません。

お礼日時:2005/01/17 12:27

直接質問文の内容とは関係ないのですけど、


#1の補足で挙げて貰ったプログラムには、
move_goat()
move_cabbage()
move_man()
の定義がないです。
コンパイルしてみたいので、さらに補足していただけませんか?

この回答への補足

大変遅くなりました。
似たものであり、補足に入りきれなかったので、割愛してしまいました。念のため、上記の定義の前後も付けましたので宜しくお願いします。


public:
State()
: wolf( false ), goat( false ), cabbage( false ), man( false ),
path()
{
}

bool succeeded() const
{
return( this -> wolf
&& this -> goat
&& this -> cabbage
&& this -> man );
}

bool failed() const
{
return( (wolf == goat && man != wolf)
|| (goat == cabbage && man != goat) );
}

State move_wolf() const
{
State s = *this;

s.path.push_back( *this );

if ( s.wolf == s.man )
{
s.wolf = !s.wolf;
s.man = !s.man;
}

return( s );
}

State move_goat() const
{
State s = *this;

s.path.push_back( *this );

if ( s.goat == s.man )
{
s.goat = !s.goat;
s.man = !s.man;
}

return( s );
}

State move_cabbage() const
{
State s = *this;
s.path.push_back( *this );

if ( s.cabbage == s.man )
{
s.cabbage = !s.cabbage;
s.man = !s.man;
}

return( s );
}

State move_man() const
{
State s = *this;

s.path.push_back( *this );

s.man = !s.man;

return( s );
}
bool operator== ( const State & s ) const
{
return( this -> wolf == s.wolf
&& this -> goat == s.goat
&& this -> cabbage == s.cabbage
&& this -> man == s.man );
}
};

補足日時:2005/01/13 11:57
    • good
    • 0

ウィンドウズアプリケーションを作成している場合には、mainは要らない(自分では書きません)です。



>どの部分を書き直したらいいのかわかりません
そのコンソールプログラムを、(コンパイルできる形のものを)補足でアップできますか?

参考URL:http://okweb.jp/kotaeru.php3?q=1058834

この回答への補足

#include <deque>
#include <algorithm>
#include <iostream>

using namespace std;
struct State
{
bool wolf;
bool goat;
bool cabbage;
bool man;
deque<State> path;

State()
: wolf( false ), goat( false ), cabbage( false ), man( false ),
path()
{
}

bool succeeded() const
{
return( this -> wolf
&& this -> goat
&& this -> cabbage
&& this -> man );
}
  bool failed() const
{
return( (wolf == goat && man != wolf)
|| (goat == cabbage && man != goat) );
}

State move_wolf() const
{
State s = *this;
s.path.push_back( *this );
if ( s.wolf == s.man )
{
s.wolf = !s.wolf;
s.man = !s.man;
}
return( s );
}
           ・
           ・
bool operator== ( const State & s ) const
{
     return( this -> wolf == s.wolf
&& this -> goat == s.goat
&& this -> cabbage == s.cabbage
&& this -> man == s.man );
}
};

static
ostream & operator << ( ostream & ostr , const State & s )
{
ostr << (s.wolf ? "" : "w") << (s.goat ? "" : "g")
<< (s.cabbage ? "" : "c") << (s.man ? "" : "m")
<< "-"
<< (s.wolf ? "w" : "") << (s.goat ? "g" : "")
<< (s.cabbage ? "c" : "") << (s.man ? "m" : "");

return( ostr );
}

static
void print_progress( const State & s ,
const deque<State> & open_list ,
const deque<State> & closed_list )
{
cout << "Testing " << s << endl;
cout << "Open List =";
for ( size_t i = 0 ; i < open_list.size() ; i ++ )
{
cout << " " << open_list[i];
}
cout << endl;
cout << "Closed List =";
for ( size_t i = 0 ; i < closed_list.size() ; i ++ )
{
cout << " " << closed_list[i];
}
cout << endl;
}

static
void print_result( const State & s )
{
cout << "Result = ";
for ( size_t i = 0 ; i < s.path.size() ; i ++ )
{
cout << s.path[i] << " ";
}
cout << s << endl;
}

int main( void )
{
State start_state;
deque<State> open_list;
deque<State> closed_list;

open_list.push_back( start_state );
while( ! open_list.empty() )
{
State s = open_list.front();
open_list.erase( open_list.begin() );
print_progress( s , open_list , closed_list );
cout << endl;

if ( s.succeeded() )
{
print_result( s );
break;
}

if ( s.failed() )
{
continue;
}

if ( find( closed_list.begin() , closed_list.end() , s )
== closed_list.end() )
{
open_list.push_back( s.move_wolf() );
open_list.push_back( s.move_goat() );
open_list.push_back( s.move_cabbage() );
open_list.push_back( s.move_man() );

closed_list.push_back( s );
}
}

return( 0 );
}
アップしましたが見づらくてすみません。

補足日時:2005/01/12 16:30
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!