• 締切済み

外部変数と関数内処理、スマートなのはどっち?

今書いているプログラムで、少し気になったので、皆さんのご意見をお聞きしたいです。 void Sample(){   A式; } 上記のようなひとつの関数があるとします。 Sample()は、プラグラムの中では基本的には一度しか使用しません。 ただ、コマンドにより、プログラムが最初の状態に戻ることがあります。 その際にはまた、Sample()を一度だけ実行する仕様としたいです。 この動作を実現する方法として、私が考え付いたのは以下の2つ、 1. 外部変数(bool型辺り)を使い、最初の状態に戻った時にフラグを立つようにする。 そして、フラグが立っているときのみSample()を実行、終了時にそのフラグを消す。  (例)  bool flag;    void Sample(){      if( flag ){      A式;    }  } 2. Sample()内で最初の状態に戻ったことを検知するB文を置き、   最初の状態と判断した(B文が真)ときだけA式を実行する。  (例)    void Sample(){   if( !B文 ) return;     A式;  } 前者は、記述的には簡単ですが、外部変数が増えてしまいます。 後者は、関数内で閉じて判断できますが、毎回B文のチェックが必要。 (B文はそれなりに煩雑な処理をしていると仮定します) どちらも一長一短ありますが、一般的にはどちらが好まれるのでしょうか?

みんなの回答

  • racene
  • ベストアンサー率70% (21/30)
回答No.3

static変数を使うのが良いのではないかと思います。 void Sample() {  static bool flag = true;  if (flag) {   A;   flag = false;  } } 1とやっている事自体は同じですが、flagはSampleの外部には公開されません。

全文を見る
すると、全ての回答が全文表示されます。
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

そもそも、 void Sample(){   A式; } は、定期的に呼び出されるものなのですか? 基本的に、一度しか使用しないなら、そこで(たぶん初期処理かとおもいますが) Sampleを呼びだせば、よいのではないでしょうか? また、コマンドにより、プログラムが最初の状態に戻ることがあります。 とのことですが、「プログラムが最初の状態に戻ること」を検知した箇所で、 Sampleを呼びだせば、よいのではないでしょうか? そうすれば、フラグとか条件式等は不要になります。 その場合は、当然ですが、void Sample()は、どこからでも呼び出せるように、 extern void Sample(); の定義をしておく必要があります。

全文を見る
すると、全ての回答が全文表示されます。
  • chie65535
  • ベストアンサー率43% (8546/19426)
回答No.1

>どちらも一長一短ありますが、一般的にはどちらが好まれるのでしょうか? どちらも好ましくない。 >ただ、コマンドにより、プログラムが最初の状態に戻ることがあります。 >その際にはまた、Sample()を一度だけ実行する仕様としたいです。 そういう場合は「exec関数で自分自身を起動させてから、自分自身を終了する」とか「setjump、longjumpを使って、main関数の頭に戻る」とかって方法を取る。 main.c -------- pubpic jmp_buf jmp_env; int main(int argc,char *argv[]) {  setjump(jmp_env);  Sample();  //何らかの処理。たぶん、subfunc()を呼ぶような処理  return 0; } sub.c -------- extern jmp_buf jmp_env; void subfunc(void) {  //main関数の中から呼ばれたどこか  //main関数と同一スレッドでなければいけない  //再起動コマンドを受けた  if (再起動条件) {   longjump(jmp_env,1);  } }

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • 3ビットのフラグを持つ2個の変数の組み合わせによる分岐の上手な書き方

    お世話になります。 C言語において、3つの状態を持っている変数で状態の組み合わせによって分岐するプログラムを作りたいと思っています。 3ビットのフラグによって2進数で001,010,100の3個のどれかの状態であるとして、以下の条件で分岐させるさせたいです。 ・2個とも同じ状態のとき ・片方が001,010で、もう一方が100 ・片方が001で、もう一方が010 自分では以下のように書いたのですが、条件式もっと簡潔に書くことはできないでしょうか?よろしくお願いいたします。 #include<stdio.h> typedef struct{ int name;//識別番号 unsigned int flag:3;//状態を表すフラグ }Status; int main(void) { Status a,b;//例として2変数のみ定義 a.name=10; a.flag=1; b.name=20; b.flag=2; if(!(a.flag^b.flag)){ printf("2個とも同じ状態のとき\n"); } else if( ( (a.flag&1 || a.flag&2) && b.flag&4 ) || ( a.flag&4 && (b.flag&1 || b.flag&2 ) ) ){ printf("片方が001か010で、もう一方が100\n"); } else if( (a.flag&1 && b.flag&2) || (a.flag&2 && b.flag&1) ){ printf("片方が001で、もう一方が010\n"); } }

  • C# こういう場合ってどうなるの?

    public void A(bool b) {   if(b ? B() : C())//分かると思いますが、三項演算子   {     //略   } } public bool B() {   return true; } public bool C() {   return false } 上記のAにtrueを渡し実行した場合、 if文の中はどうなるのでしょうか? 引数がtrueならBを実行し、Bの戻り値trueが if文で処理され、if内に入る・・・でよろしいのでしょうか? それとも引数bの評価がそのままifで使われるのでしょうか? 例えばのコードなので、bだろうがBだろうが変わらない・・・みたいな 回答はご遠慮ください。

  • 処理中に動的に変化する変数をウィンドウプロージャで表示させるには?

    Win32APIを使っています。 タイトルの通りウィンドウプロージャ以外(実際はダイアログプロージャ)である処理をしているとします。そこで変化する変数(時間など)をウィンドウに表示させ、かつ無効リージョンが発生しても大丈夫なようにしたいのですが、 現在は 処理を実行中に(ダイアログプロージャ内で)変数aが変わった瞬間、グローバル変数flag=TRUEにし、次に SendMessage(hwnd,WM_PAINT,0,0); を実行し、 ウィンドウプロージャでは case :WM_PAINT if(flag) "aを表示する命令"; という感じにしています。しかしこれでは表示してくれません。 どこか変なことしてますか? また別の方法はありますか? 必要であればソース見せます。 よろしくお願いします。

  • 1回だけ変数の宣言や初期化をする方法は?

    VisualStudio2010を使いC#で以下のコードを書いてます。 bool flag = true; //※ private void dataGridView1_CellPainting(object sender, DataGridViewCellPaintingEventArgs e) {   Rectangle rect = new Rectangle(); //※   if (e.RowIndex < 0 || e.ColumnIndex < 0)    return;    if (e.ColumnIndex == 0)      {       DataGridViewCell Cell = dataGridView1[e.ColumnIndex, e.RowIndex];          if (flag)             {             rect = e.CellBounds;             flag = false;             }           else            {             rect.Height += Cell.Size.Height;             }     } } CellPaintingのような繰り返される処理でflagやrect(※印)のような変数をCellPaintingのブロック内でかつ、一回だけ変数の宣言や初期化を行う方法はありますか? ちなみに、このコードは最初のセルの位置とその他のセル高さの合計をrectに設定しようとしてますが、これ自体にはあまり意味はありません。 何卒、よろしくお願いします。

  • グローバル変数について

    ◎1--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; glb=30; printf("main a=%d glb=%d\n",a,glb); func(); return 0; } void func(void) { int b=88; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎1の実行結果----------------------- main a=20 glb=30 func b=88 glb=30 ------------------------------------- ◎2--------------------------------- #include<stdio.h> void func(void); int glb; int main(void) { int a=20; func(); printf("main a=%d glb=%d\n",a,glb); return 0; } void func(void) { int b=88; int glb=30; printf("func b=%d glb=%d\n",b,glb); } ------------------------------------- ◎2の実行結果----------------------- func b=88 glb=30 main a=20 glb=0 ------------------------------------- 以上2つのプログラムで、◎1は参考書を参考に作成したものです。 ◎1のプログラムで、グローバル変数glbの値をmain( )関数内で設定していたので、次に◎2のようにfunc( )という関数プロトタイプ内で、グローバル変数glbの値を設定し、main( )関数内のprintf文でも表示させようと思ったら、「glb=0」となってしまいました。 なぜこのようになってしまうか、教えてもらえたら嬉しいです。

  • EXCELマクロの外部から、マクロの中の変数の値を設定する方法について

    EXCELマクロの外部から、マクロの中の変数の値を設定する方法について教えて下さい。 どなたか詳しい方教えて頂けないでしょうか?。 マクロの先頭で、 ・普通にマクロを実行する時には、Flag = 0 ・デバッグをしたい時には、Flag = 1 に設定して、マクロの中でFlagの値によって条件分けをして実行したいのです。 でも、いちいちマクロを開いてFlagの値を変えたくありません。 また、内容は同じでFlag=0のマクロとFlag=1のマクロは用意したくありません。 なぜなら、片方のマクロで修正した内容をもう片方のマクロに反映させなければならず、 間違いの元になる可能性があるからです。 あと、対話式でFlagの値も設定したくありません。 キーの割り当ても検索していたのですが、マクロそのものの登録しか出来ないようですし、 困っています。 詳しい方がおられましたらご回答宜しくお願いします。

  • 【エクセル/excel】if関数とフラグ

    if関数でフラグを立てたものからさらにif関数で 条件を絞ってフラグを立てようとするのですが エラーが表示されてうまくいきません。   A  B  C 1 1  0  * 2 1  1  * 3 2  1  * 上記の図で (1)A1:B3の範囲でif関数を用いてフラグを立てます。 (2)C1:C3の範囲でif関数を用いてフラグを立てます。 (たとえばA行とB行がともに1ならば1というフラグ を立てるといった感じです。) 式の立て方がいけないんでしょうか?どなたか教えて下さい。 なんだか至極簡単なことのような気もして申し訳ありません。

  • VC2005においてif文が正しく評価されない

    環境: WindowsXP SP2 VC2005 下記ソースをデバッグしています(F10によるステップ実行)。 if文の直前で変数aの値を-1など、0未満へ変更し、 そのままステップ実行しても、なぜかif文の中に入りません。 本来であれば、-1は0未満であるため、if文の判定は真と判定 されるべきであると思います。 個人的に「a = b - c」の式が悪さをしているのではないかなと 考えています。 なぜこのような現象が起こるのでしょうか? int main(void) { long a = 0; long b = 2; long c = 1; a = b - c; if( a < 0 ){ return 0; } }

  • static変数の配列の初期値を空文字列にする一般的な方法

    いつもお世話になっております。 static変数の配列の初期値を空文字列(各要素が'\0')にしたいです。 static変数なので放って置いても各要素に'\0'が入りますが、 初期値として空文字列にしている事を明記したいです。 そこで以下の様な方法を考えてみました。 (1)初期値に何もせず、コメントを書いておく (2)初回起動フラグを持ち、フラグが立っていれば空文字列にする (3)初期値にnull文字をSTR_LENの数だけ書く (4)初期値の先頭のみnull文字にし、残りは省略する どの様な方法が一般的でしょうか? 上記以外にもあれば、教えていただければ幸いです。 また、以下は私が考えたそれぞれの方法のソースです。 -------------------------------------------------------------------------------- #include <stdio.h> #include <string.h> #define STR_LEN 16 #define FLAG_ON (1) #define FLAG_OFF (0) -------------------------------------------------------------------------------- /* 初期値に何もせず、コメントを書いておく */ -------------------------------------------------------------------------------- void clear_1(void) { static char hoge[STR_LEN]; /* 空文字列 */ } -------------------------------------------------------------------------------- /* 初回起動フラグを持ち、フラグが立っていれば空文字列にする */ -------------------------------------------------------------------------------- void clear_2(void) { static char hoge[STR_LEN]; static int first = FLAG_ON; if(first == FLAG_ON){ strncpy(hoge, "\0", STR_LEN); first = FLAG_OFF; } } -------------------------------------------------------------------------------- /* 初期値にnull文字をSTR_LENの数だけ書く */ -------------------------------------------------------------------------------- void clear_3(void) { static char hoge[] = {'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'}; } -------------------------------------------------------------------------------- /* 初期値の先頭のみnull文字にし、残りは省略する */ -------------------------------------------------------------------------------- void clear_4(void) { static char str[STR_LEN] = {'\0', }; } --------------------------------------------------------------------------------

  • 一つの配列変数をいじると連動して他が代わってしまう理由が知りたいです

    以下の二つの命令 flagSave() と flagLoad() は、ローカル上に _root.flag の値をセーブ、ロードするプログラムです。 _root.flag は配列変数で、 _root.flag.A = "1" _root.flag.B ="全角文字" 等、様々な変数が入ります。 _root.flag の値は、色々変化した後、セーブをしないでロード(昔セーブしたデータに戻す)をする場合があります。 私はこれで動くと思ってプログラムしたのですが・・・ 一度でも flagSave() か flagLoad() を実行すると、 以後 _root.flag の値を変化させると(_root.flag.A="1" 等の命令実行)、それに連動して _root.savedata.data.flag の値も同じように変化するようになってしまいます。 私のやりたい事は、 セーブ&ロードをする時以外は、_root.flag の値だけを変化させ、_root.savedata.data.flag の値は変動させないようにしたいのです。 何方か、以下のプログラムの悪い点等がわかりましたら、是非とも御教授させてはいただけないでしょうか。 よろしくお願い致します。 ------------------------------------------ //================ // フラグのセーブ //================ function flagSave() { _root.savedata = SharedObject.getLocal("TEST"); _root.savedata.clear(); _root.savedata.data.flag = new Array; _root.savedata.data.flag = _root.flag; _root.savedata.flush(); } //================ // フラグのロード //================ function flagLoad() { _root.savedata = SharedObject.getLocal("TEST"); _root.flag = new Array; _root.flag = _root.savedata.data.flag; }

    • ベストアンサー
    • Flash