istringstream不尊重基地? [英] istringstream not honoring base?

查看:180
本文介绍了istringstream不尊重基地?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于使用 atoi atof ,我试图补救一些关于污染值的Coverity发现。我切换到 istringstream ,但它不产生除10之外的预期结果。



如果我切换到base 16,输入0xa并避免 iss.ignore(2); ,则结果为0:

  $ ./tt.exe 0xa 
X:0

如果我切换到base 16,输入0xa并使用 iss.ignore(2); ,那么结果是一个例外:

  $ ./tt.exe 0xa 
'0xa'不是值

我访问过 CPP Reference on istringstream ,由@πάντα推荐,但它没有讨论此上下文中的限制。



任何想法我做错了什么?






  $ cat tt .cxx 
#include< iostream>
#include< sstream>
#include< iomanip>
#include< stdexcept>
using namespace std;

template< class T>
T StringToValue(const std :: string& str){
std :: istringstream iss(str);
T value;

if(str.length()> = 2){
if(str [0] =='0'&&(str [1] =='X' || str [1] =='x'))
{
iss.setf(std :: ios_base :: hex);
iss.ignore(2)
}
}
iss>>值;

if(iss.fail())
throw runtime_error('+ str +'不是值);

返回值;
}

int main(int argc,char * argv [])
{
try
{
int x = StringToValue< int> ;(argc> = 2?argv [1]:ZZZ ...);
cout<< X:<< x<< endl;
}
catch(const runtime_error& ex)
{
cerr< ex.what()<< endl;
return 1;
}

return 0;
}


解决方案

。以十六进制记数法读取值很容易。

  #include< sstream> 
#include< iomanip>
#include< cassert>

int main()
{
{
int x = 0;
std :: istringstream(0xa);
是>> std :: hex>> X;
assert(x == 10);
}
{
int x = 0;
std :: istringstream(a);
是>> std :: hex>> X;
assert(x == 10);
}
}



现场演示






无论如何,我可以找出您的代码的两个问题。



1。不正确地使用 std :: ios_base :: setf



std :: ios_base :: hex 。标志不仅仅用于数字基。要做到这一点,你需要屏蔽其他一切,以防止取消设置其他,不相关,但必要的标志(我不知道他们是什么):

  iss.setf(std :: ios_base :: hex,std :: ios :: basefield); 

这是为什么 iss>



这也是为什么你应该构造一个最小的测试用例,它由只有一个测试

2。 破坏的逻辑



输入只是a的情况完全跳过该语句,因为它是前两个字符为0x的条件。



将其移动到 iss>>>






您可以看到您的固定代码这里,但是,正如我在开始的答案,整个接通领先 - 0x这是不必要的,所以大多数代码可以删除。


I'm trying to remediate some Coverity findings on tainted values due to the use of atoi and atof. I switched to an istringstream, but its not producing expected results for bases other than 10.

If I switch to base 16, enter 0xa and avoid the iss.ignore(2);, then the result is 0:

$ ./tt.exe 0xa
X: 0

If I switch to base 16, enter 0xa and utilize the iss.ignore(2);, then the result is an exception:

$ ./tt.exe 0xa
'0xa' is not a value

I visited CPP Reference on istringstream as recommended by @πάντα, but it does not discuss a limitation in this context.

Any ideas what I am doing wrong? Or, how can I get this to work as expected?


$ cat tt.cxx
#include <iostream>
#include <sstream>
#include <iomanip>
#include <stdexcept>
using namespace std;

template <class T>
T StringToValue(const std::string& str) {
  std::istringstream iss(str);
  T value;

  if (str.length() >= 2) {
    if (str[0] == '0' && (str[1] =='X' || str[1] =='x'))
      {
        iss.setf(std::ios_base::hex);
        iss.ignore(2);
      }
  }
  iss >> value;

  if (iss.fail())
    throw runtime_error("'" + str +"' is not a value");

  return value;
}

int main(int argc, char* argv[])
{
  try
    {
      int x = StringToValue<int>(argc >= 2 ? argv[1] : "ZZZ...");
      cout << "X: " << x << endl;
    }
  catch(const runtime_error& ex)
    {
      cerr << ex.what() << endl;
      return 1;
    }

  return 0;
}

解决方案

You're completely overthinking this. Reading a value in hexadecimal notation is easy.

#include <sstream>
#include <iomanip>
#include <cassert>

int main()
{
   {
      int x = 0;
      std::istringstream is("0xa");
      is >> std::hex >> x;
      assert(x == 10);
   }
   {
      int x = 0;
      std::istringstream is("a");
      is >> std::hex >> x;
      assert(x == 10);
   }
}

(live demo)


Regardless, I can identify two problems with your code.

1. Incorrect use of std::ios_base::setf

You're replacing the stream's entire flagset with only std::ios_base::hex. The flags are not just for numeric bases. To do that, you need to mask out everything else to prevent unsetting other, unrelated, but necessary flags (I don't know what they are):

iss.setf(std::ios_base::hex, std::ios::basefield);

This is why iss >> std::hex is so much easier.

It's also why you should have constructed a minimal testcase consisting of nothing but a test of iss.setf before posting!

2. Broken logic

The case where input is just "a" skips that statement entirely, as it is conditional on the first two characters being "0x".

Move it to just before the iss >> value, I would.


You can see your fixed code here but, as explored at the start of my answer, the whole switching-on-leading-"0x" thing is unnecessary, so most of your code can just be removed.

这篇关于istringstream不尊重基地?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆