Пропуск ожидаемых символов, таких как scanf () с помощью cin

Как добиться scanf("%d # %d",&a,&b);своего рода эффект с cin в С ++?

5

Решение

Вы можете создать свой собственный потоковый манипулятор. Это довольно легко.

#include <ios>
#include <iostream>
using namespace std;

// skips the number of characters equal to the length of given text
// does not check whether the skipped characters are the same as it
struct skip
{
const char * text;
skip(const char * text) : text(text) {}
};

std::istream & operator >> (std::istream & stream, const skip & x)
{
ios_base::fmtflags f = stream.flags();
stream >> noskipws;

char c;
const char * text = x.text;
while (stream && *text++)
stream >> c;

stream.flags(f);
return stream;
}

int main()
{
int a, b;
cin >> a >> skip(" # ") >> b;
cout << a << ", " << b << endl;
return 0;
}
3

Другие решения

Вы можете пропустить # извлекая его в персонажа:

std::istringstream iss("10 # 20");

int main()
{
int a, b; char hash;
iss >> a >> hash >> b;

assert(a == 10 && b == 20);
}
3

Там нет прямой функции внутри istream класс, который имитирует это, к сожалению. Существуют функции, которые вы можете использовать для управления потоком и получения правильных входных данных, но я не знаком с тем, как они работают, поэтому я не могу рассказать вам, как.

Мое лучшее предложение о том, как я лично это сделаю, это использовать getline() чтобы поместить ввод в строку, а затем оттуда я бы сделал несколько проверок, чтобы увидеть, соответствует ли он формату. Так что в вашем случае я бы взял первую подстроку до первого пробела, удостоверился, что это действительный десятичный знак, проверил, чтобы знак фунта (‘#’) находился в правильном месте, а затем схватил конечное число, чтобы убедиться, что это действительный. Если какой-либо из этих трех объектов неверен, я бы установил для некоторой логической переменной значение false выкинуть или вернуть или что-то, чтобы указать, что ввод был неверным и не в правильном формате.

Псевдокод:

...

getline(cin,myStr);

while(!formatCheck(myStr))
{
cout<<"Not valid format for input";
getline(cin,myStr);
}

...

bool formatCheck(string str)
{
string firstPart=str.subString(0,firstSpaceLocation);
string middle=str[firstSpaceLocation+1];
string lastPart=str.subString(firstSpaceLocation+3,end);

if(first part not a valid number || middle!="#" || last part not a valid number)
{
return false;
}

return true;
}
1

Вот другой способ. Вы можете классифицировать # как символ пробела через std::ctype<char> фасет проникнут в локаль:

#include <iostream>
#include <sstream>
#include <vector>

namespace detail
{
enum options { add, remove };

class ctype : public std::ctype<char>
{
private:
static mask* get_table(const std::string& ws, options opt)
{
static std::vector<mask> table(classic_table(),
classic_table() + table_size);
for (char c : ws)
{
if (opt == add)
table[c] |= space;
else if (opt == remove)
table[c] &= ~space;
}
return &table[0];
}
public:
ctype(const std::string& ws, options opt)
: std::ctype<char>(get_table(ws, opt)) { }
};
}

class adjustws_impl
{
public:
adjustws_impl(const std::string& ws, detail::options opt) :
m_ws(ws),
m_opt(opt)
{ }

friend std::istream& operator>>(std::istream& is,
const adjustws_impl& manip)
{
is.imbue(std::locale(is.getloc(),
new detail::ctype(manip.m_ws, manip.m_opt)));
return is;
}
private:
std::string m_ws;
detail::options m_opt;
};

adjustws_impl setws(const std::string& ws)
{
return adjustws_impl(ws, detail::add);
}

adjustws_impl unsetws(const std::string& ws)
{
return adjustws_impl(ws, detail::remove);
}

int main()
{
std::istringstream iss("10 # 20");
int a, b;

iss >> setws("#");
iss >> a >> b;

iss >> unsetws("#");
std::cout << a << ' ' << b; // 10 20
}
1