如何通过字段读取和验证istringstream

How to read-and-validate from istringstream by fields

本文关键字:验证 istringstream 读取 何通过 字段      更新时间:2023-10-16

我正在尝试检查输入有效性。我有一个文件,里面有两列,第一列是字符串,第二列是整型。分隔符是任意数量的空格。问题是,我不知道如何正确地检查第二项是否真的是int。考虑以下代码:

string line; // parameter with a string to be parsed
string name;
int num;
istringstream lineStream(line);
lineStream >> name;
lineStream >> num;

通过调用lineStream.good(),我可以检测诸如"abcd g"之类的输入,但是当我放入诸如"abcd 12a"之类的东西时,它被解析为"abcd"和12。与"abcd 12.2"等相同

在Java中,我可以使用String.split()到一个数组,然后解析每个整个元素,不忽略任何字符,但我不知道这里的正确方法是什么。

谢谢你的提示

您可以简单地检查在提取int之后是否到达了行std::stringstream的末尾。如果int提取失败,则根本没有整数。如果它成功了,但是流中仍然有内容,那么行中有太多内容了。我将这样处理这个问题:

std::string line, name;
int num;
while (std::getline(file, line)) {
  std::stringstream line_stream(line);
  if (line_stream >> name >> num &&
      line_stream.eof()) {
    // Line was of the correct format
  }
}

基本上,有两个检查:

  1. line_stream >> name >> num将失败,如果不能提取stringint
  2. 在这些提取之后,如果它们到达流的末尾,eof位将被设置。所以如果流中还有内容,line_stream.eof()将失败。

显然,这是一个非常脆弱的方法,只适用于特定情况,并且需要适应几乎任何行格式的变化。

您可以读取两个字符串,然后检查第二个字符串是否真的是数字。像这样:

std::string line; // parameter with a string to be parsed
std::string name;
std::string strNum;
int num;
std::istringstream lineStream(line);
lineStream >> name;
lineStream >> strNum;
if (isNumber(strNum))
{
   num = atoi(strNum.c_str());
}
//
bool isNumber(const std::string& strNum)
{
   bool lIsNumber = true;
   std::string::const_iterator it = strNum.begin();
   while (it != strNum.end())
   {
      if (!std::isdigit(*it))
      {
         lIsNumber = false;
         break;
      }
      ++it;
  }
   return lIsNumber;
}