强制字符串到int消耗整个字符串的函数 [英] Forcing String to int Function to Consume Entire String

查看:353
本文介绍了强制字符串到int消耗整个字符串的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个应该代表一个数字的字符串,我想把它放到一个转换函数中,如果整个字符串没有转换,它会提供通知。



输入:12




  • code> istringstream :: operator>> 输出12

  • li>
  • stoi 输出12



1X我想要一个失败响应,但我得到:




  • code> istringstream :: operator>> 输出1

  • li>
  • stoi 输出1



X2




  • istringstream :: operator> > 输出0并设置错误标志

  • atoi b
  • stoi 发生错误



[ Live Example ]



有一种方法可以引起输入的错误行为1X

解决方案



com / w / cpp / string / byte / strtolrel =nofollow> strtol



正如建议的这里 strtol 的out-parameter可以使用以获取读取的字符数。 strtol 实际上会返回 long 而不是 int

  char * size; 
const int num = strtol(i.c_str(),& size,10);

if(distance(i.c_str(),const_cast< const char *>(size))== i.size()){
cout< strtol:< num<< endl;
} else {
cout<< strtol:error\\\
;
}

注意,这使用 i.c_str / code>来引用同一个字符串。 c_str 退款如果你有C ++ 11,指向底层数组的指针不是临时的:



data()执行相同的函数


另请注意, c_str 返回的指针将在 strtol distance之间有效除非:



  • 传递非 - const c>引用任何标准库函数的字符串

  • 调用非 - <$ c $在字符串上除了运算符[] ,<$ c> $ c> at() front() back() begin() rbegin() code> rend()


在这些情况下,您需要创建 i 的基础 const char * 的临时副本,然后执行测试



sscanf



sscanf 可以使用%n 返回读取的字符数,这可能比执行指针比较更直观。如果base很重要, sscanf 可能不是一个好的选择。与 strtol stoi 不同,支持基础2 - 36, sscanf 提供了八进制(%o ),十进制(%d )和十六进制(%x )。

  size_t size; 
int num;

if(sscanf(i.c_str(),%d%n,& num,& size)== 1&&
cout<< sscanf:< num<< endl;
} else {
cout<< sscanf:error\\\
;
}



stoi



此处 stoi 的输出参数像 sscanf 的工作原理%n 读取的字符数。与C ++相比,这需要一个 string ,而不像上面的C实现 stoi throws a invalid_argument 如果未考虑第一个非空格字符这不幸意味着不像C的实现,这必须检查在 try catch 阻止。

  try {
size_t size;
const auto num = stoi(i,& size);

if(size == i.size()){
cout< stoi:< num<< endl;
} else {
throw invalid_argument(invalid stoi argument);
}
} catch(const invalid_argument& / * e * /){
cout< stoi:error\\\
;
}

[ Live Example ]


Given a string that should represent a number, I'd like to put it into a conversion function which would provide notification if the whole string did not convert.

For input: "12":

  • istringstream::operator>> outputs 12
  • atoi outputs 12
  • stoi outputs 12

For input "1X" I'd like a failure response but I get:

  • istringstream::operator>> outputs 1
  • atoi outputs 1
  • stoi outputs 1

For input "X2":

  • istringstream::operator>> outputs 0 and sets an error flag
  • atoi outputs 0
  • stoi throws an error

[Live Example]

Is there a way to provoke the error behavior on input "1X"?

解决方案

For a given string str there are several ways to accomplish this each with advantages and disadvantages.

strtol

As suggested here strtol's out-parameter can be used to get the number of characters read. strtol actually returns a long not an int so a cast is happening on the return.

char* size;
const int num = strtol(i.c_str(), &size, 10);

if(distance(i.c_str(), const_cast<const char*>(size)) == i.size()) {
    cout << "strtol: " << num << endl;
} else {
    cout << "strtol: error\n";
}

Note that this uses i.c_str() to refer to the same string. c_str Returns pointer to the underlying array serving as character storage not a temporary if you have C++11:

c_str() and data() perform the same function

Also note that the pointer returned by c_str will be valid between the strtol and distance calls unless:

  • Passing a non-const reference to the string to any standard library function
  • Calling non-const member functions on the string, excluding operator[], at(), front(), back(), begin(), rbegin(), end() and rend()

If you violate either of these cases you'll need to make a temporary copy of i's underlying const char* and perform the test on that.

sscanf

sscanf can use %n to return the number of characters read which may be more intuitive than doing a pointer comparison. If base is important, sscanf may not be a good choice. Unlike strtol and stoi which support bases 2 - 36, sscanf provides specifiers for only octal (%o), decimal (%d), and hexadecimal (%x).

size_t size;
int num;

if(sscanf(i.c_str(), "%d%n", &num, &size) == 1 && size == i.size()) {
    cout << "sscanf: " << num << endl;
} else {
    cout << "sscanf: error\n";
}

stoi

As suggested here stoi's output parameter works like sscanf's %n returning the number of characters read. In keeping with C++ this takes a string and unlike the C implementations above stoi throws an invalid_argument if the first non-whitespace character is not considered a digit for the current base, and this unfortunately means that unlike the C implementations this must check for an error in both the try and catch blocks.

try {
    size_t size;
    const auto num = stoi(i, &size);

    if(size == i.size()) {
        cout << "stoi: " << num << endl;
    } else {
        throw invalid_argument("invalid stoi argument");
    }
} catch(const invalid_argument& /*e*/) {
    cout << "stoi: error\n";
}

[Live Example]

这篇关于强制字符串到int消耗整个字符串的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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