在C++; 我正在编写一个函数,它在C++中为一个分数类重载运算符>。标题如下:friend-istream&operator>>(istream&,france&)我一直很难满足检测非法输入的所有要求
以下是我想要实现的目标:在C++; 我正在编写一个函数,它在C++中为一个分数类重载运算符>。标题如下:friend-istream&operator>>(istream&,france&)我一直很难满足检测非法输入的所有要求,c++,c,operator-overloading,istream,C++,C,Operator Overloading,Istream,以下是我想要实现的目标: 如果用户输入(int)(输入_键),函数应将分子设置为int,分母设置为1并返回 如果用户输入(int1)(“/”)(int2)(输入_键),则将分子设置为int1,分母设置为int2,然后返回 任何形式的输入如果不符合前两种格式,都会引发异常 函数的调用方式如下: Fraction fin; do { cout << "Enter a fraction here: "; try { cin >> fin;
Fraction fin;
do {
cout << "Enter a fraction here: ";
try {
cin >> fin;
sum += fin;
} catch (FractionException &err) {
cout << err.what() << endl;
}
} while (fin != 0);
int inputSize, slashIndex;
int num, den;
char* line;
char* numStr;
char* denStr;
bool foundSlash(false);
input.getline(line, 1000);
inputSize = strlen(line);
for(int i = 0; i < inputSize; i++) {
if(!isdigit(line[i])) {
if(line[i] == '/'){
slashIndex = i;
foundSlash = true;
goto checkDen;
} else throw FractionException("Non-slash character is entered");
}
}
checkDen:
if(foundSlash){
for(int i = slashIndex + 1; i < inputSize; i++)
if(!isdigit(line[i]))
throw FractionException("Denominator contains non-numbers");
strncpy(numStr, line, slashIndex - 1);
frac.numer = atoi(numStr);
denStr = /*substring from slashIndex + 1 to inputSize*/;
//The strncpy function only copies from index 0
frac.denom = atoi(denStr);
} else {
frac.numer = atoi(line);
frac.denom = 1;
}
我尝试将input.sync()
替换为input.clear()
和input.ignore(streamsize,delim)
,但没有成功
我考虑的是input.peek(),但和整数的长度可以超过一位数
我试图将C字符串与input.getline(char*,streamsize)
一起使用,并在字符串中循环查找“/”,但程序崩溃了。代码如下所示:
Fraction fin;
do {
cout << "Enter a fraction here: ";
try {
cin >> fin;
sum += fin;
} catch (FractionException &err) {
cout << err.what() << endl;
}
} while (fin != 0);
int inputSize, slashIndex;
int num, den;
char* line;
char* numStr;
char* denStr;
bool foundSlash(false);
input.getline(line, 1000);
inputSize = strlen(line);
for(int i = 0; i < inputSize; i++) {
if(!isdigit(line[i])) {
if(line[i] == '/'){
slashIndex = i;
foundSlash = true;
goto checkDen;
} else throw FractionException("Non-slash character is entered");
}
}
checkDen:
if(foundSlash){
for(int i = slashIndex + 1; i < inputSize; i++)
if(!isdigit(line[i]))
throw FractionException("Denominator contains non-numbers");
strncpy(numStr, line, slashIndex - 1);
frac.numer = atoi(numStr);
denStr = /*substring from slashIndex + 1 to inputSize*/;
//The strncpy function only copies from index 0
frac.denom = atoi(denStr);
} else {
frac.numer = atoi(line);
frac.denom = 1;
}
int inputSize,slashIndex;
int num,den;
字符*行;
char*numStr;
char*denStr;
bool-foundSlash(假);
input.getline(第1000行);
inputSize=strlen(行);
for(int i=0;i
另外,在我现在的程序中,输入流有时会在缓冲区中留下字符,这会导致无限循环
我只是对我正在做的事情感到困惑,因为似乎什么都不管用,我的代码也很粗略。任何帮助或提示都会被理解。 < P>你的职责分工对于C++来说是不正常的。你通常希望<代码>操作符> <代码>来设置一个失败状态(或者在调用设置这种状态的流操作时,或者隐式地使用<代码> > StStest),然后,调用方应该控制是否希望流引发异常。下面是一个例子:
#include <iostream>
#include <sstream>
#include <limits>
#include <cassert>
struct X { int a_, b_; };
std::istream& operator>>(std::istream& is, X& x)
{
char c;
if (is >> x.a_ && is.get(c))
if (c == '\n')
x.b_ = 1;
else if (!(c == '/' && is >> x.b_))
is.setstate(std::istream::failbit);
return is;
}
int main()
{
std::istringstream iss("5\n10/2\n3xyz\n8/17\n9\nNOWAY\n42/4\n");
X x;
while (iss >> x)
std::cout << "parsed " << x.a_ << '/' << x.b_ << '\n';
iss.clear();
std::string remnants;
assert(getline(iss, remnants));
std::cout << "parsing failed, line remnants for '" << remnants << "'\n";
// normally would prefer following to getline above...
// iss.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
iss.exceptions(std::istream::failbit);
while (iss)
try
{
while (iss >> x)
std::cout << "also parsed " << x.a_ << '/' << x.b_ << '\n';
}
catch (const std::exception& e)
{
std::cout << "caught exception " << e.what() << '\n';
if (!iss.eof())
{
iss.clear();
iss.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
std::cout << "eof " << iss.eof() << ", bad " << iss.bad()
<< ", fail " << iss.fail() << '\n';
}
请参阅在ideone.com上运行
在is>>x.a&&is.get(c)
中,第一个使用>
流式传输,它将跳过前导空格,但是get()
被用来潜在地读取换行符:这意味着例如“10/2”
,“39”
不被认为是有效的输入:如果您想支持这样的内部和/或尾随空格,考虑:
std::istream& operator>>(std::istream& is, X& x)
{
std::string line;
if (getline(is, line))
{
std::istringstream iss(line);
char c;
x.b_ = 1; // default
if (!(iss >> x.a_) ||
(iss >> c) && (!(c == '/' && iss >> x.b_)))
is.setstate(std::istream::failbit);
}
return is;
}
您可以将
getline
直接与std::string
一起使用。不必担心大小的废话。也转到,真的吗?此外,考虑将读行放进<代码> STD::StrugSuth,然后将StrueFipe解析为一种<代码> ISTRAM< <代码>,但仅限于一行。谢谢!这很有帮助@USSRe36631:不客气——可以看到你投入了大量的工作,而且它不是特别容易,也不是像在C++中那样有基础的,因为我很乐意写这个代码…