了解 cin.fail() 和 cin.clear - 向量追加程序
Understanding cin.fail() and cin.clear - Vector Appending Program
这是我第一次post到Stack Overflow,如有疏漏请见谅post
我目前正在 Code::Blocks 17.12 上使用 GNU GCC 编译器编写 C++ 程序。该程序适用于 Big C++ 第二版的练习 P6.4,我必须编写一个函数来 append/combine 两个用户输入的向量,然后 return 向量
我可以很好地输入第一个向量,但由于某种原因它不允许我输入第二个向量。
我有一种感觉,在 while 循环中使用 cin.fail() 也会触发我的第二个 bool 值立即变为 false。为此,我添加了 cin.clear(),希望它会重置流以允许第二个矢量输入,但无济于事。
是真的 cin.fail() 导致了这个错误,还是我忽略了其他东西?
编辑:通过使用 crtl-z,我现在能够获得第二个向量,并且 运行 程序完成,尽管第一个向量的最后一个元素 a/a_vct 是复制两次。你能给我一些关于 crtl-z 使用的资源来更好地理解它的使用吗? (书上还没讲到)
前任。如果我为 a_vct 输入 1 2 3 并为 b_vct 输入 1 2 3,c_vct 将输出 1 2 3 3 1 2 3 0
#include <iostream>
#include <vector>
using namespace std;
vector<double>append(vector<double>a,vector<double>b)
{
vector<double>c; //combined vct
for (int i=0; i<a.size(); i++)
{
c.push_back(a[i]);
}
for (int i=0; i<b.size(); i++)
{
c.push_back(b[i]);
}
return c;
};
int main()
{
vector<double>a_vct; //inputs
vector<double>b_vct; //inputs
vector<double>c_vct; //appended vct
cout<<"Welcome to the vector append-er!"<<endl;
cout<<"Please enter 1st Vector (enter v to set vector after inputs):"<<endl;
bool v1_add=true;
while(v1_add)
{
double a;
cin>>a;
a_vct.push_back(a);
if(cin.fail()) //double usage is setting both bools to false???
{
v1_add=false;
}
}
cin.clear();
cout<<"Please enter 2nd Vector. Please enter the same number of elements (enter v to set vector after inputs):"<<endl;
bool v2_add=true;
while(v2_add)
{
double b;
cin>>b;
b_vct.push_back(b);
if(cin.fail())
{
v2_add=false;
}
}
c_vct=append(a_vct,b_vct);
cout<<"The appended vector is:"<<endl;
for (int i=0; i<c_vct.size(); i++)
{
cout<<c_vct[i]<<" ";
}
return 0;
}
编辑 2:根据响应进行的新更改,现在按预期工作
if(cin.good())
{
a_vct.push_back(a);
}
if(cin.good())
{
b_vct.push_back(b);
}
输入第一个矢量输入后,为 windows 写 Ctrl+Z
(通过键盘而不是数字)或 Ctrl+D
为 linux 使 cin.fail()
是 true
以停止循环获取输入并在输入第二个矢量输入之后。
请注意,向量将重复最后的条目,因为您在检测到 cin.fail()
后生成 push_back(a)
。因此,您可以通过更改
来避免这种情况
a_vct.push_back(a);
至
if(cin.good()) a_vct.push_back(a);
所选答案解决了眼前的问题,但是...
当你有一个失败的输入时,你不仅要清除失败标志,你可能还必须删除错误的输入。如果您不这样做,下一次读取将尝试解析相同的错误输入,并且会再次失败。删除错误输入通常使用 std::istream::ignore
来完成。典型用法
cin.ignore(numeric_limits<streamsize>::max(), '\n')
删除流中直到行尾的所有内容。您可以将 '\n'
替换为 space、制表符、逗号或任何其他更符合您要求的字符。绝对确定您的输入有误,而不是其他一些失败案例,否则您会发现自己删除了确实想要的数据。
旁注:
cin>>b;
b_vct.push_back(b);
if(cin.fail())
{
v2_add=false;
}
是个坏主意。如果 cin>>b;
失败,您不想将 b
添加到 vector
。在添加它之前,您要确保 b
是好的。
cin>>b;
if(cin.fail())
{
v2_add=false;
}
else
{
b_vct.push_back(b);
}
但我们可以利用 cin >>b;
的 return 值并稍微重新安排逻辑以使其更容易:
if(cin>>b) // if read succeeded
{
b_vct.push_back(b); // store
}
else
{
v2_add=false; // read failed
}
然后,如果我们考虑 while
while(v2_add) // loop until failed
{
if(cin>>b)
{
b_vct.push_back(b);
}
else
{
v2_add=false;
}
}
我们发现我们根本不需要 if
。它正在做的工作可以在 while
的条件下完成。
while(cin>>b) // loop until read fails
{
b_vct.push_back(b); // store
}
因为跳出循环的唯一方法就是失败,所以这里就是放置 clear
和 ignore
的地方
while(cin>>b) // loop until read fails
{
b_vct.push_back(b); // store
}
// Check for EOF here if appropriate
cin.clear(); // clear error flag
// discard invalid input if appropriate
// cin.ignore(numeric_limits<streamsize>::max(), '\n'); // discard up to end of line
如果您有多种可能的字符分隔输入,通常更容易(但更慢)将有问题的标记读入 std::string
并忽略结果。
cin.clear(); // clear error flag
std::string discard;
cin >> discard; // discard whatever follows
这是我第一次post到Stack Overflow,如有疏漏请见谅post
我目前正在 Code::Blocks 17.12 上使用 GNU GCC 编译器编写 C++ 程序。该程序适用于 Big C++ 第二版的练习 P6.4,我必须编写一个函数来 append/combine 两个用户输入的向量,然后 return 向量
我可以很好地输入第一个向量,但由于某种原因它不允许我输入第二个向量。
我有一种感觉,在 while 循环中使用 cin.fail() 也会触发我的第二个 bool 值立即变为 false。为此,我添加了 cin.clear(),希望它会重置流以允许第二个矢量输入,但无济于事。
是真的 cin.fail() 导致了这个错误,还是我忽略了其他东西?
编辑:通过使用 crtl-z,我现在能够获得第二个向量,并且 运行 程序完成,尽管第一个向量的最后一个元素 a/a_vct 是复制两次。你能给我一些关于 crtl-z 使用的资源来更好地理解它的使用吗? (书上还没讲到) 前任。如果我为 a_vct 输入 1 2 3 并为 b_vct 输入 1 2 3,c_vct 将输出 1 2 3 3 1 2 3 0
#include <iostream>
#include <vector>
using namespace std;
vector<double>append(vector<double>a,vector<double>b)
{
vector<double>c; //combined vct
for (int i=0; i<a.size(); i++)
{
c.push_back(a[i]);
}
for (int i=0; i<b.size(); i++)
{
c.push_back(b[i]);
}
return c;
};
int main()
{
vector<double>a_vct; //inputs
vector<double>b_vct; //inputs
vector<double>c_vct; //appended vct
cout<<"Welcome to the vector append-er!"<<endl;
cout<<"Please enter 1st Vector (enter v to set vector after inputs):"<<endl;
bool v1_add=true;
while(v1_add)
{
double a;
cin>>a;
a_vct.push_back(a);
if(cin.fail()) //double usage is setting both bools to false???
{
v1_add=false;
}
}
cin.clear();
cout<<"Please enter 2nd Vector. Please enter the same number of elements (enter v to set vector after inputs):"<<endl;
bool v2_add=true;
while(v2_add)
{
double b;
cin>>b;
b_vct.push_back(b);
if(cin.fail())
{
v2_add=false;
}
}
c_vct=append(a_vct,b_vct);
cout<<"The appended vector is:"<<endl;
for (int i=0; i<c_vct.size(); i++)
{
cout<<c_vct[i]<<" ";
}
return 0;
}
编辑 2:根据响应进行的新更改,现在按预期工作
if(cin.good())
{
a_vct.push_back(a);
}
if(cin.good())
{
b_vct.push_back(b);
}
输入第一个矢量输入后,为 windows 写 Ctrl+Z
(通过键盘而不是数字)或 Ctrl+D
为 linux 使 cin.fail()
是 true
以停止循环获取输入并在输入第二个矢量输入之后。
请注意,向量将重复最后的条目,因为您在检测到 cin.fail()
后生成 push_back(a)
。因此,您可以通过更改
a_vct.push_back(a);
至
if(cin.good()) a_vct.push_back(a);
所选答案解决了眼前的问题,但是...
当你有一个失败的输入时,你不仅要清除失败标志,你可能还必须删除错误的输入。如果您不这样做,下一次读取将尝试解析相同的错误输入,并且会再次失败。删除错误输入通常使用 std::istream::ignore
来完成。典型用法
cin.ignore(numeric_limits<streamsize>::max(), '\n')
删除流中直到行尾的所有内容。您可以将 '\n'
替换为 space、制表符、逗号或任何其他更符合您要求的字符。绝对确定您的输入有误,而不是其他一些失败案例,否则您会发现自己删除了确实想要的数据。
旁注:
cin>>b;
b_vct.push_back(b);
if(cin.fail())
{
v2_add=false;
}
是个坏主意。如果 cin>>b;
失败,您不想将 b
添加到 vector
。在添加它之前,您要确保 b
是好的。
cin>>b;
if(cin.fail())
{
v2_add=false;
}
else
{
b_vct.push_back(b);
}
但我们可以利用 cin >>b;
的 return 值并稍微重新安排逻辑以使其更容易:
if(cin>>b) // if read succeeded
{
b_vct.push_back(b); // store
}
else
{
v2_add=false; // read failed
}
然后,如果我们考虑 while
while(v2_add) // loop until failed
{
if(cin>>b)
{
b_vct.push_back(b);
}
else
{
v2_add=false;
}
}
我们发现我们根本不需要 if
。它正在做的工作可以在 while
的条件下完成。
while(cin>>b) // loop until read fails
{
b_vct.push_back(b); // store
}
因为跳出循环的唯一方法就是失败,所以这里就是放置 clear
和 ignore
while(cin>>b) // loop until read fails
{
b_vct.push_back(b); // store
}
// Check for EOF here if appropriate
cin.clear(); // clear error flag
// discard invalid input if appropriate
// cin.ignore(numeric_limits<streamsize>::max(), '\n'); // discard up to end of line
如果您有多种可能的字符分隔输入,通常更容易(但更慢)将有问题的标记读入 std::string
并忽略结果。
cin.clear(); // clear error flag
std::string discard;
cin >> discard; // discard whatever follows