• 締切済み

gotoを使わずに2

やっぱり全体がないとわかりませんよね・・・ とりあえず、コピーします。見にくいとおもいますが・・ 中置法を逆ポーランドに変換するプログラムです。 void CPorandoView::OnButton1() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください CString ss; char st[30],z[30],tai,ap; CEdit* myED1=(CEdit*)GetDlgItem(IDC_EDIT1); //EDIT1のアドレスをmyED1の代入 CEdit* myED2=(CEdit*)GetDlgItem(IDC_EDIT2); //EDIT2のアドレスをmyED2の代入 CEdit* myED3=(CEdit*)GetDlgItem(IDC_EDIT3); //EDIT3のアドレスをmyED3の代入 myED1->GetWindowText(ss); //入力された中置法式を作業領域ssに代入 int np=0,stp=0,zp=0,a=999,i=0,sw=0; char ka[30],s=0,kp=0; float st2[30]; float x=0; char p[100]="" ; char *N = new char[ss.GetLength()+1]; //ダイアログ(中置法入力枠)に入力された式をNに入れ込む strcpy( N, ss ); myED1->SetWindowText(""); myED2->SetWindowText(""); myED3->SetWindowText(""); if(N[0]==NULL){ int ret; ret=AfxMessageBox("入力がありません。",MB_OK|MB_ICONEXCLAMATION); goto end; } if(30<strlen(N)){ int ret; ret=AfxMessageBox("入力文字数オーバーです。",MB_OK|MB_ICONEXCLAMATION); goto end; } for(;a!='\0';np++){ a=N[np]; tai=0; if( a>0x003a){ if(a<0x007e ){ if(a!='*' && a!='/' && a!='+' && a!='-' && a!='(' && a!=')'){ int ret; ret=AfxMessageBox("指定外文字が入力されています。",MB_OK|MB_ICONEXCLAMATION); goto end; } } } if(a==0x0030){ int ret;      ret=AfxMessageBox("0は入力不可です。",MB_OK|MB_ICONEXCLAMATION);//入力が0の場合エラーを表示 goto end; } if(a>'0' && a<='9'){      if(z[zp-1]>='0' && z[zp-1]<='10'){      z[zp]=','; zp++; } z[zp]=a;      zp++; z[zp]='\0';      sw--; }else if(a!='(' && a!=')'){ if(stp==0){ st[stp]=a; stp++; st[stp]='\0'; sw++; }else if(st[stp-1]!='('){ if(st[stp-1]=='*' || st[stp-1]=='/'){ tai=2; }else{ tai=1; } }else{ st[stp]=a; stp++; } if(a=='*' || a=='/'){ ap=2;      sw++; }else{ ap=1; sw++; } if(sw>1){ int ret; ret=AfxMessageBox("演算子が連続しているか、\n先頭、または最後尾に演算子が入力されています。",MB_OK|MB_ICONEXCLAMATION); goto end; } if(tai!=0){ if(ap<=tai){ z[zp]=st[stp-1];                st[stp-1]=a; zp++; z[zp]='\0'; st[stp]='\0'; if(a==st[stp-2]){          z[zp]=st[stp-2]; zp++;          st[stp-2]=st[stp-1]; z[zp]='\0'; st[stp-1]='\0'; stp--; } }else{ st[stp]=a; stp++; st[stp]='\0'; } } }else if(a=='('){ st[stp]='('; stp++; st[stp]='\0'; }else { while(st[stp]!='('){、 stp--; if(st[stp]!='('){ z[zp]=st[stp]; zp++; } } } } if(stp>=0){ stp--; while(stp>=1){ z[zp]=st[stp-1]; zp++; z[zp]='\0'; stp--; } } if(sw<=0){ int ret; ret=AfxMessageBox("数値は1~9までです。",MB_OK|MB_ICONEXCLAMATION);//演算子がないとエラー処理 goto end; } z[zp+1]='\0'; myED2->SetWindowText(z); end: ; }

みんなの回答

  • BLK314
  • ベストアンサー率55% (84/152)
回答No.5

例外を使うのも手だと思います。 MFCなので、CException 派生を投げるようにすれば、 ReportErrorでダイアログが表示できますので あちこちでメッセージボックスを開く手間が省けます。 正常系とエラー系が分離できるだけでも プログラムがすっきりできると思います。 もちろん、他の人が指摘されているように 関数化も重要です。 関数化して例外を投げてcatchでReportErrorさせれば、 ぐんとメンテナンス性が向上すると思います。 いかがでしょうか?

  • php504
  • ベストアンサー率42% (926/2160)
回答No.4

end: の後に何もないので全部 return; でいいんじゃないですか

  • Alice022
  • ベストアンサー率37% (3/8)
回答No.3

今後使用していくプログラムであるなら、他の方々がアドバイスして下さっているように、関数化させたほうが良いと思います。 これがただ勉強問題としての利用だけなら、このソースコードを活かすようにするのであれば、 BOOL型で変数何か用意し、TRUEで初期化もしておき、TRUEかFALSEでエラー判断させたループ処理させるのはどうでしょうか。 最初の処理のSetWindowTextは処理が被ってしまうので、そこは直す必要がありますが。 if(N[0]==NULL) 以降から if(sw<=0) までの処理を直すとして ----- BOOL Flags = TRUE; //変数宣言 do{ z[zp+1]='\0'; myED2->SetWindowText(z);  ↑すみません、C++良く知らないので、ウインドウ表示は最初とgoto endで表示させてるのと共通化させて纏めてください。  if(N[0]==NULL){   int ret;   ret=AfxMessageBox("入力がありません。",MB_OK|MB_ICONEXCLAMATION);   //エラーであればフラグセット   Flags = FALSE;  }  ・・・省略します。goto end;の部分は全てフラグ設定する。 }while( Flags == FALSE ); ----- こういった感じにすれば、もとのソースを崩さずにいけるとは思いますが、ざっと見た感じでなので、できなかったら、すみません。

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

ざっと見た感じは、 (1)gotoじゃなくてreturn;で事足りる。 (2)機能ごとに関数化が必要。 (3)再帰呼び出しを使えばスッキリする。 (4)"("の数の対応とか入力が間違っていたらバグにハマる可能性が大きい。 (5)半年後、このプログラムは読むの大変かも。 (6)スタックの処理は他のコードと混ざらないように関数化かマクロで分りやすくしたい。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.1

これは関数にするときれいになるパターンですね。 func() {  処理A  処理B  if(..){   処理C   goto end;  }  処理D  end:  処理E } というところを func() {  処理A  sub();  処理E } sub() {  処理B  if(..){   処理C   return;  }  処理D } } とする。

関連するQ&A

  • goto を使わずに

    VC++でプログラムを作ったんですが、上司からgotoは使うなとの指示があり困ってます。 なにせ、まだまだVC++になれてないし、かなりの初心者です。 C言語は学生のころ習いました。 if(a==0x0030){ //0による除算を回避するために0は入力不可とする(0ディバイト) int ret; //エラー画面出力 ret=AfxMessageBox("0は入力不可です。",MB_OK|MB_ICONEXCLAMATION);//入力が0の場合エラーを表示 goto end; } ・ ・ ・ end: //エラーがあった場合ここにとんで最初からやり直される ; } こんなかんじなのですが、なにか解決法ありませんか?

  • エディットボックスのテキストが表示されないのはなぜですか

    VC++初心者です。 以下のソースでエディットボックスのテキストが表示されません。というか、最後のループの時のみ表示されますが、一回一回表示するにはどうしたらいいでしょうか? void CCRPTC_accessDlg::OnBnClickedOk() {  int i;  CEdit* myEdit1 = (CEdit*)GetDlgItem(IDC_EDIT1);    ・    ・    ・  for (i=1;i<10;i++){   if (Ret != SUCCESS)   {    myEdit1->SetWindowText("NG!");   }   else   {    myEdit1->SetWindowText("OK!");   }  } }

  • VC++ MFC エラーコード C2248 private メンバ (クラス 'CObject'で…

    VC++ MFC エラーコード C2248 現在、ダイアログAにあるコンボボックス(IDC_COMBO1)に単語を登録、削除する処理をしています。 ダイアログAには他に[登録]ボタン(IDC_BUTTON1)と[削除]ボタン(IDC_BUTTON2)があります。 IDC_COMBO1 を CComboBox m_combo; として // [登録]ボタン押下時 void CADlg::OnBnClickedButton1() { CString Txt, old; int ret = 0, count = 0, i; m_combo.GetWindowText(Txt); if ( strcmp(Txt, "") == 0 ) { AfxMessageBox( _T("語句を入力してください")); return; } // コンボボックスのリスト数取得 count = m_combo.GetCount(); for(i = 0; i < count; i++){ // IDC_COMBO1に登録済みの語句を順番に調べていく m_combo.GetLBText(i, old); // 既に登録済みの名前があった場合 if (oldFile == Txt){ ret = MessageBox( _T("上書きしますか?"), _T("語句登録"), MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2 ); } } if ( ret == IDYES ) { return; } else if ( ret == IDNO ) { // 後ほど説明します CBDlg dlg; dlg.DoModal(); m_combo1.AddString(NewName); // extern CString NewName;←グローバル変数(Bダイアログから) return; } // 登録されていない語句の場合 m_combo.AddString(Txt); } 上記の登録の方、エラーなくコンパイルがとおり、コンボボックスにもちゃんと格納されています。 削除の方もエラーなくちゃんとコンボボックスから削除されます。 次に >else if ( ret == IDNO ) の部分なのですが [いいえ]ボタン(IDNO)が押された場合にはダイアログBが表示されます。 ダイアログBには語句を入力するエディットボックスIDC_EDIT1、[登録]ボタン(IDC_TOUROKU)、[取り消し]ボタン(IDC_TORIKESI)があります。 IDC_EDIT1 を CEdit m_ed1; として ここのBダイアログでもAダイアログ中のコンボボックスに格納されている語句が入力された場合はメッセージボックスを表示したいのです。 そこで void CBDlg::OnBnClickedTouroku() { // TODO: ここにコントロール通知ハンドラ コードを追加します。 int rup, cnt, ret; CString oldf; CADlg cad; CComboBox cfdn = cad.m_combo; m_ed1.GetWindowText(NewName); // CString NewName;←グローバル変数 // Aダイアログ中のコンボボックスリスト数の取得 cnt = cfdn.GetCount(); for(rup = 0; rup < cnt; rup++){ // Aダイアログのコンボボックス中に登録されている語句取得 cfdn.GetLBText(rup, oldf); if (oldf == NewName){ ret = MessageBox( _T("本当に上書きしてもいいですか?"), _T("環境設定"), MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2 ); } } if(ret == IDOK){ OnOK(); } else{ return; } } としました。 ここでコンパイルすると 1>c:\program files\microsoft visual studio 8\vc\atlmfc\include\afxwin.h(1820) : error C2248: 'CObject::CObject' : private メンバ (クラス 'CObject' で宣言されている) にアクセスできません。 1> c:\program files\microsoft visual studio 8\vc\atlmfc\include\afx.h(558) : 'CObject::CObject' の宣言を確認してください。 1> c:\program files\microsoft visual studio 8\vc\atlmfc\include\afx.h(529) : 'CObject' の宣言を確認してください。 1> コンパイラでのこの診断により関数 'CCmdTarget::CCmdTarget(const CCmdTarget &)' が生成されました。 のようにエラーがでます。 調べてみると CComboBox cfdn = cad.m_combo; が原因のようです。 ググってみたりしたのですが解消法がわからず質問させていただきました。 よろしくお願いします。

  • メッセージボックスが表示されないのですが?

    WIN98 VC++6.0 MFCにて mmmというプロジェクト名でウィザードに従いダイアログベースのPGを作りました。 下記のようにコードの2箇所にAfxMessageBox("3",MB_OK);を追加しましたが、どちらもメッセージボックスが表示されません。 どうしてなのでしょうか? お分かりも方是非教えてください。 ************************** BOOL CMmmApp::InitInstance() { AfxEnableControlContainer(); #ifdef _AFXDLL Enable3dControls(); #else Enable3dControlsStatic(); #endif CMmmDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); AfxMessageBox("3",MB_OK);//■追加 if (nResponse == IDOK) { AfxMessageBox("3",MB_OK);//■追加 } else if (nResponse == IDCANCEL) { } // ダイアログが閉じられてからアプリケーションのメッセージ ポンプを開始するよりは、 // アプリケーションを終了するために FALSE を返してください。 return FALSE; }

  • ShellExecuteをつかって・・・

    もしかしたら非常に簡単な問題かもしれないんですけど、 SDIベースでShellExecuteをつかって以下のような関数を作ってコンパイルすると、 ”error C2065: 'm_hWnd' : 定義されていない識別子です。” がでます。 前に別プロジェクトでやったときは特に定義せず使えたような気がするのですが、 何か使い方が間違っているのでしょうか? #include "stdafx.h" #include "FCwin.h" #include "MainFrm.h" #include "FCwinDoc.h" #include "FCwinView.h" ・・・中略・・・ int CFCwinApp::DosFcExe() { HINSTANCE ret = ShellExecute(m_hWnd,"open","command.com",NULL,"c:\\",SW_SHOW); if((int)ret <= 32 ){AfxMessageBox("DOS窓開けません",MB_OK);return 1;} return 0; }

  • 拡張子なしファイル検索について

    WindowsXPでVC++.NETを使ってプログラミングをしています。 拡張子なしファイル検索について質問があります。 現在、下記のようなソースを記述してます。 CString testPath = "D:\\*."; BOOL Working = finder.FindFile(testPath,0); if(Working) { AfxMessageBox("見つかりました",MB_OK,0); } else { AfxMessageBox("見つかりません",MB_OK,0); } で、ファイルがないのに、見つかりましたのメッセージボックスがでてきてしまいます。 すみませんが、ヒントか回答をいただけたら幸いです。 宜しくお願い致します。

  • C++BuilderのRadioGroupについて

    今、単純にラジオグループを作成し、RadioGroupのItemsを3つ、それぞれ「a」、「b」、「c」と設定して、そのアルファベットのラジオボタンが押されたらTEditにそのアルファベットを表示させるというものを作成していますが、うまくいきません。どなたかアドバイスお願いします。 現在のプログラムを以下に書きます。 RadioGroup = new RadioGroup(Form1); RadioGroup->Items->Add("a"); RadioGroup->Items->Add("b"); RadioGroup->Items->Add("c"); if(RadioGroup->ItemIndex==0) Edit1->Text="a"; else if(RadioGroup->ItemIndex==1) Edit1->Text="b"; else if(RadioGroup->ItemIndex==2) Edit1->Text="c"; else Edit1->Text="not Selected";

  • visualstudioについて

    visual studio2008 c++ を使用しています. ダイアログ形式でアプリケーションを作成しています. ボタンを押すと画像のようなアプリケーションを起動してenterキーを送るようにしたいのですがうまく出来ません. void CMy6Dlg::OnBnClickedButton1() { // TODO: ここにコントロール通知ハンドラ コードを追加します。 HINSTANCE ret = ShellExecute(m_hWnd, "open", "---Release\\scip_20_gd.exe", NULL, NULL, SW_SHOW); HWND hWnd = ::FindWindowEx(NULL, NULL, NULL, "---Release\scip_20_gd.exe"); ::SendMessage(hWnd,WM_SETFOCUS,0,0); ::SendMessage(hEdit, WM_KEYDOWN, VK_RETURN,0); if (ret <= (HINSTANCE)32) AfxMessageBox("シェル処理ができません.", MB_OK); } よろしくお願いします.

  • 1と表示させたいが12と表示される

    windows XP VC++.net 2003です。 よろしくお願いします。 症状は毎回コピーアンドペーストでプログラムを書くよりも 関数化してソースをきれいにしようと思い BOOL ButtonNumber (int bNumber,HWND hWnd) { long z; char sBuff[100]; char number[100]; wsprintf(number,"%d",bNumber); z = GetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff,99); if(z == 0){ SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),number); return TRUE; } if(z == 10){ //桁数が多すぎる警告メッセージ MessageBox(NULL,"桁数が多すぎます。","警告",MB_OK); return TRUE; } z = atol(sBuff); wsprintf(sBuff,"%d1",z); SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff); return TRUE; } という関数を作りました。 numberに1という数字が入っていてエディットボックスに1と表示されるはずなのですが12と表示されてしまいます。 ためしにnumberに12と入れてみると表示されるのが122 123と入力すると1232と表示されてしまいます。 SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),number); どこも間違っていないように思いますが・・なんででしょう・・ 関数化せずmainに直接書き込んでいけば正常に1と表示されます・ switch (LOWORD(wParam)) { case IDC_BUTTON1: ButtonNumber(1,hWnd); case IDC_BUTTON2: a = GetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff,99); if(a == 0){ SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),"2"); return TRUE; } if(a == 10){ //桁数が多すぎる警告メッセージ MessageBox(NULL,"桁数が多すぎます。","警告",MB_OK); return TRUE; } a = atol(sBuff); wsprintf(sBuff,"%d2",a); SetWindowText(GetDlgItem(hWnd,IDC_EDIT1),sBuff); return TRUE; この場合BUTTON1は12と意図しない表示をしますが BUTTON2はちゃんと2と表示されます。 非常に困っていますよろしくお願いします。

  • ADボードにとるCSVでの無限サンプリング

    ADボードで無限サンプリングをおこないたいのですが。 作成したCSVファイルにデータが1行しか作成されません。 何が問題でしょうか? ちなみにプログラムはこちらです。 int nRet; HANDLE hDeviceHandle; ADSMPLREQ SmplConfig; ADBOARDSPEC BoardSpec; ULONG ulSmplNum; FILE *outp; WORD wSmplData[20000][2]; hDeviceHandle = AdOpen ("FBIAD1"); if (hDeviceHandle == INVALID_HANDLE_VALUE){ AfxMessageBox("デバイスのオープンに失敗しました",MB_OK, 0); return; } else{ nRet = AdGetSamplingConfig(hDeviceHandle,&SmplConfig); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング設定情報の読み出しに失敗しました",MB_OK, 0); } nRet = AdGetDeviceInfo(hDeviceHandle, &BoardSpec ); if(nRet !=AD_ERROR_SUCCESS){ AfxMessageBox("デバイスの情報取得にに失敗しました", MB_OK, 0); } { SmplConfig.SmplChReq[0]. ulChNo = 2; SmplConfig.ulSmplNum = 20000; SmplConfig.ulTrigMode = AD_ETERNITY; SmplConfig.fSmplFreq = 20000; SmplConfig.SmplChReq[0]. ulRange = AD_5V; nRet = AdSetSamplingConfig(hDeviceHandle,&SmplConfig ); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("サンプリング条件設定に失敗しました",MB_OK, 0); } /* nRet = AdStartSampling(hDeviceHandle, FLAG_SYNC); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSVファイル作成に失敗しました", MB_OK, 0); }*/ /* nRet = AdStartFileSampling( hDeviceHandle, "DATA.CSV", FLAG_CSV ); if(nRet != AD_ERROR_SUCCESS){ AfxMessageBox("CSV ファイル作成に失敗しました", MB_OK, 0); }*/ AdGetSamplingData(hDeviceHandle,&wSmplData[0][0], &ulSmplNum ); AdOutputDO(hDeviceHandle,1); outp = fopen("E:\\Edata\\record.csv","a"); fprintf(outp,"%f\n",wSmplData[0][0]); fclose(outp); // 終了処理. nRet = AdClose( hDeviceHandle ); if (nRet != AD_ERROR_SUCCESS) { AfxMessageBox("デバイスのクローズに失敗しました"); } } } }

専門家に質問してみよう