• ベストアンサー

特定の数字でなければエラーを出したい

こんにちは。 Visual Studio 2005を用いてVisual C++を使ったフォームアプリケーションを作成しています。 3つのテキストボックスA、B、Cとボタンがあります。 テキストボックスに数字(半角)を入力させてボタンを押させるのですが、ボタンを押した時に、 Aは0,1,2 Bは0,1,2,3 Cは0,1,2,3,4 のどれかを入力している時のみOKにして、それ以外の文字や数字を入力していた場合はエラーメッセージを出すようにしたいのです。 できるだけ簡単なコードで記述したいのですが、良い方法があればどうぞよろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8524/19373)
回答No.2

ANo.1の回答のような「KeyPressでどうのこうの」と言う処理は、やってはいけません。 ANo.1の回答では、TABや方向キー、バックスペース、リターンキーを許すように書いていますが、この他に「ペースト」や「カット」も許すべきで、色々な「許さなければならないケース」は予想外に多いのです。 それ以前に「ボタンを押した時に、OKでない入力をされているならエラーを表示する」と言う要求仕様を満たしていません。 プログラムで金を貰ってる人がこんな書き方をしたら「要求仕様を満たしていない。ボツ。作り直せ。作り直しても納期は遅らせるな」と言われます。 プロの場合「別の方法」に、どんなに便利な方法があろうとも「クライアントの要求は絶対」ですから「他の方法」を使うのは許されません。 「ボタンを押したら判定」なのですから、簡単です。 ボタンを押した時に、テキストボックス内の文字列を取得し、その文字列を「文字列変換関数群」の中の「文字列をintに変換する関数」を用いてintに変換しましょう。 「文字列をintに変換する関数」には「変換したintの他に、文字列をどこまで変換したか」も返す関数があります。 「文字列の末尾、つまり、終端文字まで変換した」のなら「文字列すべてを正しく変換した」と判ります。 つまり、第1段階で「intに変換」し、第2段階で「変換出来ない文字列が残ったらエラー」にします。 そして、第3段階で「変換したintの値が、範囲内かどうか?」をif文などで検査します。 例えば、strtoul関数を用いれば "1AA"⇒変換値は1、残った文字列は"AA" "1.1"⇒変換値は1、残った文字列は".1" "CDE"⇒変換値は0、残った文字列は"CDE" "12"⇒変換値は12、残った文字列は無し "1"⇒変換値は1、残った文字列は無し と言う結果が得られます。 "1AA"⇒変換値は1、残った文字列は"AA" "1.1"⇒変換値は1、残った文字列は".1" "CDE"⇒変換値は0、残った文字列は"CDE" は、残った文字列があるので全部エラー。 "12"⇒変換値は12、残った文字列は無し は、残った文字列は無いけど、数値が0,1,2の範囲に無いのでエラー。 "1"⇒変換値は1、残った文字列は無し だけがエラー無しで許可されます。 結論は「strtoul関数を使う」です。

その他の回答 (2)

回答No.3

 こんにちは。  ああ、ボタンを押したと同時に検出でしたか。うっかりしていました。  流石に文章枠外の事に関しては、透視出来ないので、勘弁です。  後、strtoulに関しては、普通では呼べないので要注意です。  どうしても、と言うのならば、#2氏がマーシャリングから一貫したサンプルコードを見せて頂けるそうなので、其方を参考にして下さい。  私はコレで筆を収めさせて頂きます。参考程度に(AとBしかしてませんので念の為)。 //メンバ変数 private:Generic::Dictionary<TextBox^, String^> m_dictionary; //コンストラクタ public: Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // m_dictionary.Add(textBoxA, gcnew String("012")); m_dictionary.Add(textBoxB, gcnew String("0123")); } //受け入れ確認 private: System::Boolean IsAccept(String^% sAccept, const wchar_t wcRhs) { for each(const wchar_t wcLhs in sAccept) if(wcLhs == wcRhs)return true; return false; } //ボタンが押された private: System::Void Button1Click(System::Object^ sender, System::EventArgs^ e) { Generic::Dictionary<TextBox^, String^>::Enumerator it = m_dictionary.GetEnumerator(); while(it.MoveNext()) { TextBox^% textBox = it.Current.Key; String^% sAccept = it.Current.Value; for each(const wchar_t wcPick in textBox->Text) { if(IsAccept(sAccept, wcPick)) continue; //ココで不正扱い MessageBox::Show(this, textBox->Name, "不正を発見"); //テキストボックス1箇所の不正で引き換えしたければbreakを止めてreturnにして下さい break; } } }

回答No.1

 こんばんは。  フォームアプリケーションと書いてありますが、C++/CLIマネージドの事でしょうか。であれば、KeyPressイベントを処理するのが良いと思います。  数字以外にも、TABキーや方向キー、バックスペースキー位は基本で受け付けないと、操作が出来なくなります。  受付可能な数字をarray<int>^にまとめ、textBox^とペアでコレクションクラスの中に突っ込み、KeyPressイベント内で、senderパラメータをキーにしてarray<int>^を取り出して、array<int>^を使用して、総当りで確認して見るなど(こうすれば「0,5,7,8」と言った条件にも耐えられるのでは)。  尚、KeyDownイベント内での処理は、お勧め出来ません。以下参考程度に。 //コレはメンバ変数として追加 private:Generic::Dictionary<TextBox^, array<int>^> m_dictionary; //フォームのコンストラクタ Form1(void) { InitializeComponent(); // //TODO: ここにコンストラクタ コードを追加します // //ココでテキストボックスのインスタンスと、受付可能な数字をまとめた配列を登録する m_dictionary.Add(textBoxA, gcnew array<int>{0, 1, 2}); m_dictionary.Add(textBoxB, gcnew array<int>{0, 1, 2, 3}); } //ココがイベント処理 private:System::Void KeyPress(System::Object^ sender, System::Windows::Forms::KeyPressEventArgs^ e) { //TABや方向キー、バックスペース、リターンキー位は基本で受け入れないとマズい事になる array<wchar_t>^ arDefKeyCode = gcnew array<wchar_t>{37,38,39,40,8,9,13}; //オブジェクトを捕まえる TextBox^ box = dynamic_cast<TextBox^>(sender); //テキストボックスが登録されているかどうか、辞書から探す array<int>^ arFound = m_dictionary.default[box]; //見当たらなかったので引き返す if(arFound == nullptr) return; //基本キーに当てはまったので引き返す for(int i = 0; i < arDefKeyCode->Length; ++i) if(arDefKeyCode[i] == e->KeyChar) return; //10進数である事を確認 if(wchar_t::IsDigit(e->KeyChar)) { //入力文字を数字にする const int iVal = int::Parse(e->KeyChar.ToString()); //条件と合っているかを総当り確認 for(int i = 0; i < arFound->Length; ++i) if(arFound[i] == iVal) return; } //ココまで来れば不正値確定 MessageBox::Show(this, String::Concat(box->Name, " : ", e->KeyChar.ToString()), "不正です"); //テキストボックスへの入力を拒絶する e->Handled = true; }

関連するQ&A

  • VBについて

    Visual Basicで1つのオブジェクトの中にフォームを2つ作った時、片方のフォームに入力した情報を処理し、もう1つのフォームでその結果を見るにはどうすれば良いのでしょうか?  例えば、1つのフォームにテキストボックスAとコマンドボタンを貼り付け、もうひとつにテキストボックスBを貼り付けて、テキストボックスAにXと入力し、コマンドボタンを押すとテキストボックスBにYと入力されるような事です。  分かる方、是非教えてください。

  • 最大公約数を見つけたい

    C++初心者です。Visual studio 2005を用いてvisual C++の計算フォームアプリケーションを作りたいのです。 2ヶ所のテキストボックスに整数を入力させ、「実行」ボタンを押すとその2つの整数の最大公約数を出力させたいのですが、どうも上手くいきません。 できるだけ簡素なコードで最大公約数を見つけるにはどうすればいいでしょうか? どうかよろしくお願いいたします。

  • 子フォームの情報を親フォームに利用する

    Visual C++初心者です。visual studio2005を使用しています。 まず親フォームで名前を入力させ、「次へ」を押すと子フォームが出て来ます。 そこで好きな食べ物を入力させて「決定」ボタンを押すと子フォームが閉じ、親フォームのテキストボックスに 「○○さん、こんにちは!好きな食べ物は●●ですね」というメッセージを表示させる・・・というフォームアプリケーションを作りたいのです。 子フォームの表示は分かるのですが、そこで入力させた情報を親フォームに反映させる方法が分かりません。 できれば初心者でも分かる回答をして頂ければ有難く思います。 よろしくお願いします。

  • テキストボックスが空白の時、セルに入力"しない"

    ユーザーフォームにて、テキストボックスに入力されている文字や数字をユーザーフォーム内の"入力開始ボタン"を押したら、セル(A1)に入力されるように設定しています。 しかし、別のセル(C1)に A1 × B1 = X   という式が入力されており、テキストボックスが空白の状態で入力開始ボタンを押したら、セル(A1)に文字が打ち込まれたとカウントするのか、正しく計算できなくなります(A1を選択してデリートするとXに正しく0と表示されます)。 そこで、テキストボックスに文字か数字が打ち込まれている時のみセル(A1)に入力されるようにしたいのですが、回答宜しくお願いします。

  • CGI,Perlで下記のようなことを、行いたいと考えています。

    CGI,Perlで下記のようなことを、行いたいと考えています。  a.html  b.html  c.html があり、 __________________________________ 1:それぞれ、フォームに、テキストボックスが一つあります。 2:他のフォームに遷移できます。(例:a.htmlからc.hmtlのように) 3:各フォームに「A、B、Cの値を確認」ボタンがあります。 4:3のボタンをクリックすると、各テキストボックスで入力した 値が表示される。 【イメージ】 a.htmlのテキストボックスに、100を入力 b.htmlのテキストボックスに、200を入力 c.htmlのテキストボックスに、300を入力 した場合。 Aで入力された値は100です。 Bで入力された値は200です。 Cで入力された値は300です。 ______________________________________ と表示させる、cgiを作成したいです。 又、その際、hiddenを使用して行う方法(手順)を教えて頂けないでしょうか。 ファイルに書き込むことで、値を保持しておくのではと 考えましたが、a.htmlの値100を書き込み、再度、a.htmlの 値を書き込むと、a.htmlのフォームから送られた値が2つ(1回目、2回目)書き込まれた 状態になるように思います。 今回のように、例えば、ファームの入力値を保持して他の(b.thmlなど)に 遷移し、ボタンをクリックすると、全フォームの値を表示するような場合、 どのような方法が考えられるのでしょうか? どうぞ、宜しくお願いいたします。

    • ベストアンサー
    • CGI
  • perl/cgiについて、教えて下さい。

    perl/cgiについて、教えて下さい。 下記のようなことを、行いたいと考えています。 とりあえず、  a.html  b.html  c.html があり、 __________________________________ 1:それぞれ、フォームに、テキストボックスが一つあります。 2:他のフォームに遷移できます。(例:a.htmlからc.hmtlのように) 3:各フォームに「A、B、Cの値を確認」ボタンがあります。 4:3のボタンをクリックすると、各テキストボックスで入力した 値が表示される。 【イメージ】 a.htmlのテキストボックスに、100を入力 b.htmlのテキストボックスに、200を入力 c.htmlのテキストボックスに、300を入力 した場合。 Aで入力された値は100です。 Bで入力された値は200です。 Cで入力された値は300です。 ______________________________________ と表示させる、cgiを作成したいです。 又、その際、hiddenを使用して行う方法(手順)を教えて頂けないでしょうか。 ファイルに書き込むことで、値を保持しておくのではと 考えましたが、a.htmlの値100を書き込み、再度、a.htmlの 値を書き込むと、a.htmlのフォームから送られた値が2つ(1回目、2回目)書き込まれた 状態になるように思います。 今回のように、例えば、ファームの入力値を保持して他の(b.thmlなど)に 遷移し、ボタンをクリックすると、全フォームの値を表示するような場合、 どのような方法が考えられるのでしょうか? どうぞ、宜しくお願いいたします。

    • ベストアンサー
    • Perl
  • 入力フォームの作成について

    現在、入力フォームを作成しています。 テキストボックス「A」 ラジオボタン(またはチェックボックス)「1」「2」「3」 テキストボックス「B」 Aのテキストボックスに文字を入力し、ラジオボタン(またはチェックボックス)の2を選択した時のみにBにAの内容をコピーさせるにはどのように記述すればよろしいでしょうか。 JavaScript 関係の書籍を読みましたが、具体的に書いてあるものはなく、組み合わせが必要だとは思うのですが、うまくいきません。 webでも調べてみましたが、テキストボックスに入力するとラジオボタンがチェックされるというのは見つけましたが、この質問のことは見つけられませんでした。 逆に言えば、難しいということでしょうか・・・ 以上、よろしくお願いします。

  • VS.NET2003 WEBアプリケーションのテキストボックスのIMEを設定したい

    開発環境 VISUAL STUDIO 2003  言語 VISIAL BASIC アプリケーション WEBアプリケーション やりたいこと フォームがLOADされたときに、テキストボックスのIMEが 半角英数字になっています。 そのテキストボックスは かならず全角文字しか入れないところなので、 フォームがLOADされたときに、すでに全角に強制的に セットしたいのですが・・・・・ インターネットで検索してコードを探すことが出来ず 手持ちの書籍でも、その文献がありませんでした。 どのようにコーディングしたら、最初から全角に 出来るでしょうか。 どうぞよろしくお願いいたします。

  • 入力値をListボックスに表示させたい。

    (仕様1) ユーザーフォーム1でテキストボックス1~5に 入力した値をListボックスに表示させたい。 例えば textbox1=A,textbox2=B,textbox3=C・・・ と入力されたら、 A B C D E のように順に横方向一列に表示させるようにしたいです。 (仕様2) これをコマンドボタン1を押す度にリストボックス1に新しく追加されていく 様にしたいのですが、できますでしょうか。 例えば、 A B C D E A C D B E (テキストボックスに入力後ボタン1を押す) A C B D E (テキストボックスに入力後ボタン1を押す)

  • Windowsアプリケーションのフォームのフォーカスについて

    Windowsアプリケーションのフォームのフォーカスについて Windowsフォームアプリケーションを、C/C++で作成しています。 開発環境:Visual C++ 2008 Express Edition OS:WindowsXP テキストボックスに入力され、 フォーカスアウトした時に入力値の判定し、 偽だった時はボタンを非アクティブにする処理を実装しています。 しかし、タブ移動でのフォーカスアウトは可能なのですが、 フォームにマウスクリックした時にフォーカスが変わりません。 フォームにフォーカスを持たせることはできないのでしょうか? また、何か良い方法があったら教えていただけると幸いです。 宜しくお願いします。

専門家に質問してみよう