Чтение номеров ввода, разделенных пробелами

Это может быть полный вопрос новичка, но я еще не нашел ответ, который работает для меня.

В настоящее время я пишу программу для класса, которая принимает пользовательский ввод (который может быть одним или несколькими числами, разделенными пробелами), а затем определяет, является ли число простым, совершенным или ни того, ни другого. Если число идеально, то он будет отображать делители.

До сих пор я уже написал код для простого, совершенного и перечисления делителей. Я застрял на входной части моей программы. Я не знаю, как получить входные данные, разделенные пробелами, чтобы пройти через мои циклы по одному.

Это моя текущая программа:

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

По умолчанию 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

Ответ 2

Я бы рекомендовал читать строку в строке, а затем разбивать ее на основе пробелов. Для этого вы можете использовать функцию 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-строку вместо строки стиля С++, мы используем 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 сообщений:/

Изменить: Я немного ошибался в отношении поведения atoi; Я перепутал его с преобразованиями Java string- > Integer, которые генерируют исключение Not-A-Number, когда задано строка, которая не является числом, а затем выдает сообщение о сбое программы, если исключение не обрабатывается. atoi(), с другой стороны, возвращает 0, что не так полезно, потому что, если 0 - это номер, который они ввели? Позвольте использовать функцию isdigit (...). Здесь важно обратить внимание на то, что строки стиля С++ можно использовать как массив, так как rawInput [0] - это первый символ в строке вплоть до rawInput [длина - 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 используется для определения того, нужно ли делать ваши вещи или печатать сообщение об ошибке.

Ответ 3

Вы хотите:

  • Прочитайте всю строку с консоли
  • Токенизировать линию, расщепляясь вдоль пробелов.
  • Поместите эти фрагменты в массив или список
  • Пройдите через этот массив/список, выполнив ваши тесты Prime/Perfect/etc.

Каким будет ваш класс по этим линиям?