数値でなければ〜はどうすれば?

解決


初心者  2009-01-13 03:59:16  No: 69420

今計算機で勉強中です。
数値以外のものを入れると変なことになってしまうので、数値以外のものを入れると注意が入るようにしたいのですが、どうすればいいでしょうか。

今こんな感じです

//
// testing...
//

#include  <iostream>
using namespace std;

int main(void)
{
  /*
    trying to show
      testing
      hello world!
  */

  cout << "testing\n";
  cout << "hello world!\n";

  /*
    trying to declarate x and y
  */

  int x, y;

  /*
    asking what numbers are x and y
  */

  cout << "enter the number for x (only integer, though!!): ";
    cin >> x;
  /*
    if x was not a number, 
    show
        please enter the number
  */
  
  if (x == )
  cout << "enter the number for y (only integer, though!!): ";
    cin >> y;

  /*
    x + y = ???,,,
  */

  cout << "x + y = " << x + y << ",,,\n";

  /*
    this time, I should better challenge to calculate decimal number.
  */

  /*
    trying to declarate a and b
  */

  double a, b;

  /*
    asking what numbers are a and b
  */

  cout << "enter the number for a : ";
    cin >> a;

  cout << "enter the number for b : ";
    cin >> b;

  /*
    a + b = ???
    a - b = ???
    a * b = ???
    a / b = ???
  */

  cout << "a + b = "<< a + b << "\n";
  cout << "a - b = "<< a - b << "\n";
  cout << "a * b = "<< a * b << "\n";
  cout << "a / b = "<< a / b << "\n";
  

  return (0) ;
}


そだ  2009-01-13 05:35:30  No: 69421

これと少し似てるかな
http://madia.world.coocan.jp/cgi-bin/Vcbbs/wwwlng.cgi?print+200901/09010001.txt

他の言語だったら正規表現でやっちゃう。

C言語は、特に昔ながらのCLIで実装する場合は
perlやphpと違って正規表現使うまでが大変なので、
文字コードを直接見るか、文字列→数変換系(atoiとか)で
無理やり変換してエラーコードを監視するかとかじゃないかな。


そだ  2009-01-13 05:50:21  No: 69422

追記
数字じゃない場合 >> が何かしてくれるようだ
http://msdn.microsoft.com/ja-jp/library/whtx1k1x(VS.80).aspx


初心者  2009-01-13 06:51:12  No: 69423

お返事ありがとうございます。
ここのサイトで答えを見つけることができました。

http://www.geocities.jp/tt_ii_rr/c09.html


初心者  2009-01-13 10:20:44  No: 69424

改善しました
ただ、↓に書いてあるようにループから抜け出した後終了してしまいます
どうすればいいのでしょうか

  /*
    if x was not a number, 
    show
        please enter the number
  */
  cout << "enter the number for x (only integer, though!!): ";
    while(1){    
      cin >> x;
      bool cin_err = cin.fail ();
      if( cin_err ==0 ) break;
      cin.clear ();
      cin.ignore (100, '\n');
      cout << "enter the number again, not an alphabet.";
      }
      return x;

  /*
    serious problem going on...
      pushing ENTER key after
        cout << "enter the number again, not an alphbet.";
      is making this program stop.
      I can't find why.
  */
  cout << "enter the number for y (only integer, though!!): ";
    cin >> y;


επιστημη  URL  2009-01-13 19:00:57  No: 69425

while (1) { ... } の直後に return x; してるから抜けるのはアタリマエちゃいます?


tetrapod  2009-01-13 20:04:25  No: 69426

cin>> も scanf+%d も、その仕様として
・バッファに何もなければ、入力を待つ
・バッファに何かあれば、入力を待つ前にそのバッファ中の文字を使う
・数値として解釈できる文字列は数値に変換する(変換できた文字は処理済として取り除く)
・数値として解釈できない文字列は変換せず、そのままバッファに残す
となっているわけだ。だから最初のコードと同等のもので例示すると
cin >> x; // ここで数値と解釈されない文字を入力すると、それがバッファ中に残り
cin >> y; // さてここでどう動くのか解説する
// バッファ中の文字が残っているので入力待ちにならない
// 数値に解釈できない文字をがバッファにあるので、それをまたバッファに残す
cin >> z; // 同上
と動くのは当然の動作となる。

「ユーザの期待している動作」と「scanf/cin>> の動作」は異なる、と言い切っていいだろう。
ユーザの期待している動作は
・改行まで(改行を含む)の入力を受け取る
・数値に解釈できた文字列は処理済として捨てる
・数値に解釈できない文字列は不正入力として捨てる
・どっちであってもまた、改行までの入力を受け取る、に戻る

で、この動作を実現するのにはいくつも手法があるわけだけれど
初心者にとって容易なのは
・改行までの文字列を、文字列として受け取る
・その文字列を数値として解釈する
・解釈結果の成功失敗に関係なく、その文字列を捨てる
だと思う。
となると scanf %d や cin >> int の変数と書かないほうがいい。
stringstream を調べてみるといい。


そだ  2009-01-14 05:16:46  No: 69427

バッファに直前の入力が残るのは忘れていたけど
ignoreが効いているのでは?
それとも標準入力にignore使っちゃいけないって話?

プログラムが終わっちゃうのはεπιστημηさんの言うとおりだろうなぁ。
余談ですが
 !cin_err  ではなく cin_err == false  でもなく cin_err ==0 となっているのが
とても気になります。
いや動くでしょうけどね。参考先がこうなってるみたいですね。


初心者  2009-01-14 06:14:08  No: 69428

解決しました。
επιστημηさんの言った通りでした。
returnを消したら普通に動きました。
皆さんありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加