31

これはまったくの初心者の質問かもしれませんが、私にとって有効な答えはまだ見つかっていません。

現在、ユーザーの入力 (スペースで区切られた 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;

機能しますが、単一の数値に対してのみです。誰かがスペースで区切られた複数の入力を読み取れるようにするのを手伝ってくれたら、大歓迎です。また、余談ですが、入力される数字の数がわからないので、数字ごとに変数を作成することはできません。ランダムな数字になります。

ありがとう!

4

4 に答える 4

24

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

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
于 2012-10-27T02:34:52.447 に答える
23

行を文字列に読み込んでから、スペースに基づいて分割することをお勧めします。これには、 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 を必要とするため、文字列クラスの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 未満であるため、2 つ以上投稿することはできません :/

編集: atoi の動作について少し間違っていました。数値ではない文字列を指定すると Not-A-Number 例外をスローし、例外が処理されない場合はプログラムをクラッシュさせる Java の string->Integer 変換と混同しました。一方、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 ループのフラグとして使用されます。for ループは、文字列内の各文字をステップ実行し、それが 0 から 9 の数字かどうかを確認します。文字列内のいずれかの文字が数字ではない場合、次の実行中に「&& isNum」という条件に達したときにループが中断されます (既にループをカバーしていると仮定します)。次に、ループの後、 isNum を使用して、処理を実行するか、エラー メッセージを出力するかを決定します。

于 2012-10-27T03:54:21.083 に答える
6

あなたはしたいでしょう:

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

あなたのクラスは、これまでにこれらの線に沿って何をカバーしましたか?

于 2012-10-27T02:34:15.040 に答える