C++ 在整数输入中跳过单个减号或加号

C++ 在整数输入中跳过单个减号或加号,c++,validation,C++,Validation,最近,我需要一个简单的程序来对标准输入中出现的所有整数求和,每行一个整数。输入碰巧包含一些未设置的行,其中包含一个减号('-'),以及一些带有垃圾字符的行(将被忽略) 我相信这将是一个微不足道的计划。但事实证明,单减号并没有表现出其他不好的输入。在正常的非整数输入上,设置失败标志,错误输入保留在输入缓冲区中。但是使用一个减号(或加号)设置失败标志,但删除+/-号,导致程序跳过下一个(有效)整数(导致错误和) 我写了一个小测试程序(如下)来分析行为。 上述带有+/-符号的行为是错误还是特性 #in

最近,我需要一个简单的程序来对标准输入中出现的所有整数求和,每行一个整数。输入碰巧包含一些未设置的行,其中包含一个减号('-'),以及一些带有垃圾字符的行(将被忽略)

我相信这将是一个微不足道的计划。但事实证明,单减号并没有表现出其他不好的输入。在正常的非整数输入上,设置失败标志,错误输入保留在输入缓冲区中。但是使用一个减号(或加号)设置失败标志,但删除+/-号,导致程序跳过下一个(有效)整数(导致错误和)

我写了一个小测试程序(如下)来分析行为。 上述带有+/-符号的行为是错误还是特性

#include <iostream>

using namespace std;

int main()
{
  string s;
  int n;

  while (true)
  {
    n = -4711;
    cin >> n;

    cerr << (cin.bad()  ? "ERROR: badbit is set\n" : "");
    cerr << (cin.fail() ? "ERROR: failbit is set\n" : "");
    cerr << (cin.eof()  ? "ERROR: eofbit is set\n" : "");

    if ( cin.bad() || cin.eof() )
      break;

    if ( cin.fail() )
    {
      cin.clear();
      cin >> s;
      cerr << "ERROR: ignored string '" << s
           << "' (integer is '" << n << "')" << endl;
    }
    else
    {
      cout << "OK: read integer '" << n << "'" << endl;
    }
  }
  return 0;
}
(我已经解决了我原来的问题,改为读取字符串,并使用C++11 stoi和异常来识别错误的输入。)

编辑:如果有人对我的原始问题的解决方案感兴趣:

#include <iostream>
#include <string>

using namespace std;

int main()
{
  int sum = 0;
  string n;

  while ( cin >> n )
  {
    try {
      sum += stoi(n);
      cout << n << endl;
    }
    catch (exception& e)
    {
      cerr << e.what() << " ERROR: '" << n << "' is not a number." << endl;
    }
  }
  cout << sum << endl;

  return 0;
}
#包括
#包括
使用名称空间std;
int main()
{
整数和=0;
字符串n;
while(cin>>n)
{
试一试{
sum+=stoi(n);

cout这是一项功能。
cin
在读取“-”后的空格后才知道输入有误。没有可移植的方法使用iostreams放回多个字符,也没有可移植的方法在cin中查找。因此它被卡住了,必须将“-”保持为读取状态


在读取数据时,最好是自己解析。将所有数据读入字符串,然后自己解析这些字符串,以确定哪些是真实的,哪些是垃圾。这样,你就可以完全控制,而不是与iostreams所做的任何事情作斗争。

我会这样做:

#include <locale>
#include <sstream>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

struct number_only: std::ctype<char> { 
    number_only() : std::ctype<char>(get_table()) {} 

    static mask const *get_table() { 
        static std::vector<mask> rc(table_size, space);

        std::fill_n(&rc['0'], 10, digit);
        return &rc[0]; 
    } 
};

int main() { 
    std::string input("1 asdf 2 - 3 + 4 qwer 5 ");
    std::istringstream x(input);

    // use our ctype facet:
    x.imbue(std::locale(std::locale(), new number_only));

    // initialize vector from the numbers in the file:
    std::vector<int> numbers((std::istream_iterator<int>(x)), 
                                std::istream_iterator<int>());

    // display what we read:
    std::copy(numbers.begin(), numbers.end(), 
        std::ostream_iterator<int>(std::cout, "\n"));

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
仅结构编号:std::ctype{
number_only():std::ctype(get_table()){
静态掩码常量*get_table(){
静态标准::向量rc(表大小、空间);
标准::填写(&rc['0',10,数字);
返回&rc[0];
} 
};
int main(){
标准::字符串输入(“1 asdf 2-3+4 qwer 5”);
std::istringstream x(输入);
//使用我们的ctype方面:
x、 imbue(std::locale(std::locale(),仅限新编号_));
//根据文件中的数字初始化矢量:
std::向量数((std::istream_迭代器(x)),
std::istreamu迭代器();
//显示我们阅读的内容:
std::copy(numbers.begin(),numbers.end(),
std::ostream_迭代器(std::cout,“\n”);
返回0;
}

不是最简单的解决方案,但我必须说的很有趣!(我以前没有玩过LoalAs)。KM:我不知道,你编写的代码的逻辑几乎近乎荒谬地简单。请考虑这个代码是有效的,没有(显式)条件(如果是,等等),并且仍然比(非功能性)短。问题中的示例。你的是一个很好的解决方案,它在早期阶段排除了不必要的输入。可能非常有效。这就是为什么我认为它很有趣。如果它是直接的或不直接的,当然是非常主观的-取决于你已经知道的,我猜。顺便说一句,我将我的解决方案添加到了我的原始问题中。它没有缓冲区所有可能重要的向量输入。(杰瑞的解决方案可以很容易地重写,以避免向量和求和。)
#include <locale>
#include <sstream>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>

struct number_only: std::ctype<char> { 
    number_only() : std::ctype<char>(get_table()) {} 

    static mask const *get_table() { 
        static std::vector<mask> rc(table_size, space);

        std::fill_n(&rc['0'], 10, digit);
        return &rc[0]; 
    } 
};

int main() { 
    std::string input("1 asdf 2 - 3 + 4 qwer 5 ");
    std::istringstream x(input);

    // use our ctype facet:
    x.imbue(std::locale(std::locale(), new number_only));

    // initialize vector from the numbers in the file:
    std::vector<int> numbers((std::istream_iterator<int>(x)), 
                                std::istream_iterator<int>());

    // display what we read:
    std::copy(numbers.begin(), numbers.end(), 
        std::ostream_iterator<int>(std::cout, "\n"));

    return 0;
}