web-dev-qa-db-ja.com

スペースで区切られた入力番号を読み取る

これは完全に初心者の質問かもしれませんが、私に役立つ答えをまだ見つけていません。

現在、ユーザーの入力(スペースで区切られた1つ以上の数値)を受け取り、その数値が素数、完全、またはどちらでもないかを判別するクラスのプログラムを作成しています。数値が完全な場合、除数が表示されます。

これまで、素数、完全、除数のリストのコードをすでに作成しました。プログラムの入力部分にこだわっています。ループを1つずつ通過するために、スペースで区切られた入力を取得する方法がわかりません。

これは私の現在のプログラムです:

cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
cin>>num;

while (divisor<=num)
    if(num%divisor==0)
    {
        cout<<divisor<<endl;
        total=total+divisor;
        divisor++;
    }
    else divisor++;
if(total==num*2)
    cout<<"The number you entered is perfect!"<<endl;
else cout<<"The number you entered is not perfect!"<<endl;


if(num==2||num==3||num==5||num==7)
    cout<<"The number you entered is prime!"<<endl;

else if(num%2==0||num%3==0||num%5==0||num%7==0)
    cout<<"The number you entered is not prime!"<<endl;
else cout<<"The number you entered is prime!"<<endl;

return 0;

動作しますが、1つの番号に対してのみです。スペースで区切られた複数の入力を読み取ることができるように誰かが私を助けることができれば、それは大歓迎です。また、単なる補足として、入力する数値の数がわからないので、それぞれに変数を作成することはできません。ランダムな数の数字になります。

ありがとう!

17
Raymond Aaron

デフォルトでは、cinはスペースを破棄して入力から読み取ります。したがって、do whileループを使用して、入力を複数回読み取るだけです。

do {
   cout<<"Enter a number, or numbers separated by a space, between 1 and 1000."<<endl;
   cin >> num;

   // reset your variables

   // your function stuff (calculations)
}
while (true); // or some condition
19

行を文字列に読み込んでから、スペースに基づいて分割することをお勧めします。これには、 getline(...) 関数を使用できます。トリックは、分割された文字列を保持するために動的なサイズのデータ​​構造を持つことです。おそらく最も使いやすいのは vector です。

#include <string>
#include <vector>
...
  string rawInput;
  vector<String> numbers;
  while( getline( cin, rawInput, ' ' ) )
  {
    numbers.Push_back(rawInput);
  }

したがって、入力は次のようになります。

Enter a number, or numbers separated by a space, between 1 and 1000.
10 5 20 1 200 7

これで、要素{{10 "、" 5 "、" 20 "、" 1 "、" 200 "、" 7 "}を含む数字のベクターが作成されます。

これらはまだ文字列であるため、算術には役立ちません。それらを整数に変換するには、STL関数atoi(...)の組み合わせを使用します。atoiはc ++スタイルの文字列ではなくc-stringを必要とするため、 string class 'を使用します。 c_str() メンバー関数。

while(!numbers.empty())
{
  string temp = numbers.pop_back();//removes the last element from the string
  num = atoi( temp.c_str() ); //re-used your 'num' variable from your code

  ...//do stuff
}

このコードにはいくつかの問題があります。はい、実行されますが、それはちょっと不格好で、数字を逆の順序で出力します。もう少しコンパクトになるように書き直してみましょう。

#include <string>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
  num = atoi( rawInput.c_str() );
  ...//do your stuff
}

エラー処理にはまだ改善の余地が多くあり(現在、非数値を入力するとプログラムがクラッシュします)、入力を実際に処理して使用可能な数値形式にするための無限の方法があります(プログラミングの楽しさ! )、しかしそれはあなたに包括的なスタートを与えるはずです。 :)

注:リンクとして参照ページがありましたが、投稿数が15未満なので、3つ以上投稿することはできません:/

編集:私はatoiの動作について少し間違っていました。 Javaのstring-> Integer変換と混同しました。この変換では、数字ではない文字列を指定するとNot-A-Number例外がスローされ、例外が処理されないとプログラムがクラッシュします。一方、atoi()は0を返しますが、0が入力された場合はどうなるでしょうか? isdigit(...) 関数を使用してみましょう。ここで注意すべき重要なことは、c ++スタイルの文字列は配列のようにアクセスできることです。つまり、rawInput [0]は文字列の最初の文字で、rawInput [length-1]までのことです。

#include <string>
#include <ctype.h>
...
string rawInput;
cout << "Enter a number, or numbers separated by a space, between 1 and 1000." << endl;
while( getline( cin, rawInput, ' ') )
{
  bool isNum = true;
  for(int i = 0; i < rawInput.length() && isNum; ++i)
  {
    isNum = isdigit( rawInput[i]);
  }

  if(isNum)
  {
    num = atoi( rawInput.c_str() );
    ...//do your stuff
  }
  else
    cout << rawInput << " is not a number!" << endl;
}

ブール値(それぞれtrue/falseまたは1/0)はforループのフラグとして使用されます。これは、文字列内の各文字をステップ実行し、0〜9桁かどうかを確認します。文字列内の文字が数字でない場合、ループは次の実行中に条件「&& isNum」に到達すると中断します(すでにループをカバーしていると仮定)。次に、ループの後、isNumを使用して作業を行うか、エラーメッセージを出力するかを決定します。

14
Logan Nichols

あなたがしたいと思うでしょう:

  • コンソールから行全体を読む
  • 行をトークン化し、スペースに沿って分割します。
  • 分割したピースを配列またはリストに配置します
  • その配列/リストをステップ実行して、prime/perfect/etcテストを実行します。

あなたのクラスはこれまでこれらの方針に沿って何を扱ってきましたか?

5
ravuya