- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在为 C++ 中的 Fraction 类编写一个重载运算符 >> 的函数。标题是这样的:friend istream& operator>>(istream&, Fraction&);
我一直难以满足我为检测非法输入设置的所有要求。
这是我想要实现的目标:
函数是这样调用的:
Fraction fin;
do {
cout << "Enter a fraction here: ";
try {
cin >> fin;
sum += fin;
} catch (FractionException &err) {
cout << err.what() << endl;
}
} while (fin != 0);
我已经尝试了很多东西,这里是我的代码的一个版本。 FractionException 已得到处理:
istream& operator>>(istream& input, Fraction& frac){
int num, den;
char slash = '\0';
//_________________________________
if(!(input >> num)){
input.sync();
throw FractionException("Please enter numbers only.");
}
frac.numer = num;
//_________________________________
if(!(input >> slash)){
input.sync();
throw FractionException("Please enter slash.");
} else if(slash == '\0'){ //useless
frac.denom = 1;
return input;
} else if(slash != '/')
throw FractionException("Illegal character.");
//_________________________________
if(!(input >> den)){
input.sync();
throw FractionException("Please enter numbers only.");
} else if(den == 0) {
throw FractionException("The denominator is 0; illegal entry.");
} else
frac.denom = den;
return input;
}
我尝试用 input.clear()
和 input.ignore(streamsize, delim)
替换 input.sync()
, 但没有用。
我正在考虑 input.peek(),但是整数可以超过一位数。
我尝试将 C 字符串与 input.getline(char*, streamsize)
一起使用并循环遍历字符串以查找“/”,但程序崩溃了。代码如下所示:
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;
}
另外,对于我现在的程序,输入流有时会在缓冲区中留下字符,这会导致无限循环。
我只是对我正在做的事情感到困惑,因为似乎没有任何效果,而且我的代码很粗略。任何帮助或提示将不胜感激。
最佳答案
您的责任划分对于 C++ 来说是不正常的——您通常希望 operator>>
设置失败状态(在调用设置此类状态的流操作时隐式地设置,或者显式地使用 。 setstate
),那么调用者应该控制他们是否愿意让流引发异常。这是一个例子:
#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';
}
输出:
parsed 5/1
parsed 10/2
parsing failed, line remnants for 'yz'
also parsed 8/17
also parsed 9/1
caught exception basic_ios::clear
also parsed 42/4
caught exception basic_ios::clear
eof 1, bad 0, fail 1
看它运行here在 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;
}
关于c++ - 在 C++ 中过滤来自 istream 的非法输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28554582/
我正在尝试弄清楚如何让一个成员变量代表传入的 istream 或类自己创建的成员变量。 我认为,如果我动态分配类创建的 istream,那么使用指向 istream 的指针可能会起作用;然而,问题在于
我正在尝试理解这段代码 istream &read(istream &is, Sales_data &item) { double price = 0; is >> item.b
我编写了一个实现 IStream(COM 接口(interface)而不是 C++ 标准库类)的过滤器。这一切都很好,但我的问题是我不确定何时(如果有的话)我可以确定不会发送进一步的 IStream
我正在测试 C++PL 书中的一段代码并找到了下一段代码(我不想感觉我是在将它从书中复制粘贴到我的 IDE,所以我至少改变了变量名): istream& operator>> (istream& is
我正在阅读 C++ Practical Programming by Example by Andrew Koenig (Author)并在 4.1.3 Reading homework grades
我正在尝试使用 istream& getline 而不是使用 istream& operator 从文件中读取行。 结果cpp #include "Result.h" Result::Result()
我试图通过套接字连接发送图像,但我遇到了以下代码的问题: //stream to char array STATSTG myStreamStats; ULONG bytesSaved; myStrea
这里有两段代码,我起初认为它们应该是等价的: { std::ifstream stream("test.bin", std::ios_base::in | std::ios_base::bin
我在网上查了,但没找到合适的。 怎么可能有这样的主线(原始主线): int main() { Image left; std::ifstream ifs("l
假设我有以下代码: std::ifstream file(name, flags); file.seekg(0, std::ios::beg); // Check for error file.rea
在 Windows 上的 C++ 中,是否有任何简单的方法可以为现有 std::stream 对象创建 (COM) IStream 接口(interface)? 一个示例是使用 IWICStream:
考虑以下简单程序,它将输入拆分为空白并每行打印出一个非空白标记: #include int main(int argc, char* argv[]) { while (std::ci
istream& getline (istream& is, string& str); 此处 str 在换行符后终止。但是,如果我想处理 str cotents 2-3 行的情况,那么还有什么选择呢
这个问题已经有答案了: Java multiple file transfer over socket (3 个回答) 已关闭 5 年前。 我正在编写一个程序在两台计算机之间传输文件,但我没有关闭套接
void transferData(ifstream& input_file, ofstream& output_file) { char ch; while (input_file
我正在读取包含以下行的文本文件: deltaT 0.005; 在字符串中找到正确的行后,我想使用如下代码读出该值: double deltaT;
我正在查看 istream 类,但没有看到可以完全清除缓冲区并将输入设置为为下一个“干净”输入做好准备的方法。 我为我的类定义了提取运算符,在我的主程序中我要求用户输入,如下所示: while (tr
我正在编写一个解析器,之前我在尝试解析标识符(任何对 C++ 变量名有效的东西)和未闭合的字符串文字(任何以 " 开头的东西)时遇到了麻烦,但是在我的输入末尾缺少结束符 ")。我认为这是因为词法分析器
我得到了一个具有以下签名的函数。我无法改变它,我必须接受它。 void parse(std::istream & in); 我应该测试这个函数,所以基本上用预定义的内容调用它并检查值是否被正确解析。因
我的运算符(operator)有问题>> istream& operator>> (istream& is, Matrix& M) { char first; is>>first;
我是一名优秀的程序员,十分优秀!