强制字符串到int消耗整个字符串的函数 [英] Forcing String to int Function to Consume Entire String
问题描述
给定一个应该代表一个数字的字符串,我想把它放到一个转换函数中,如果整个字符串没有转换,它会提供通知。
输入: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 $中的错误c $ c>阻止。
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 12atoi
outputs 12stoi
outputs 12
For input "1X"
I'd like a failure response but I get:
istringstream::operator>>
outputs 1atoi
outputs 1stoi
outputs 1
For input "X2"
:
istringstream::operator>>
outputs 0 and sets an error flagatoi
outputs 0stoi
throws an error
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()
anddata()
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 thestring
to any standard library function- Calling non-
const
member functions on thestring
, excludingoperator[]
,at()
,front()
,back()
,begin()
,rbegin()
,end()
andrend()
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";
}
这篇关于强制字符串到int消耗整个字符串的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!