假设你有一个字符串:
std::string s = "ABCD\t1234";
我可以使用std::string::find
来获取'\ t'字符的偏移量,但据我所知,没有具有以下签名的函数:
int atoi_n(char *, int len);
我错过了什么? strtok
将\t
替换为\0
,我不想触及原始缓冲区。我发现很难相信没有atoi
,atof
等实例采用长度参数,但我找不到任何内容。
任何人都知道我有什么东西不见了?我知道boost有一些标记符,但我想避免添加boost的依赖。
到目前为止看的评论我想澄清一下。让我们改变一下场景: char buffer [1024]; char * pStartPos; char * pEndPost; pStartPos = buffer + 5; pEndPos = buffer + 10;
我们还要说你不能对pStartPos和pEndPos之外的内存做任何假设。如何将pStartPos和pEndPos之间的字符转换为int而不将'\ 0'添加到缓冲区或使用substr进行复制?
答案 0 :(得分:4)
如果你只想解析字符串的结尾(从\t
之后的字符到结尾)你只需要传递指向第一个字符的指针来解析atoi
...
int n = atoi(s.c_str()+s.find('\t')+1);
(为简洁起见,省略了错误检查 - 特别是,我们总是假设实际存在\t
)
相反,如果你想从字符串的开头解析到\t
,你可以这样做
int n = atoi(s.c_str());
因为atoi
无论如何都会停在第一个非数字字符处。
顺便说一下,您应该考虑使用更强大的解决方案来解析数字,例如strtol
,sscanf
或C ++流 - 它们都可以以某种方式报告解析错误,而{{ 1}}只返回atoi
(与解析字符串时的0无法区分)。
顺便说一句,0
无论如何都不在“STL”中 - 它只是C标准库的一部分。
我知道atoi不在STL中。我想知道在STL中是否有任何东西可以指定你想要包含在转换中的最后一个字符。基本上我有一个可能部分装满垃圾的缓冲区。我知道可能的有效数据的开始和可能的有效数据的结束。我不想依赖空格来结束转换,我想明确“字段”的长度,因为它也可能不会被/ 0终止。
如果您确定垃圾不是以数字开头,您可以按原样使用atoi
/ atoi
/ strtol
- 它们会在看到垃圾时自动停止。否则,使用istringstream
方法提取所需的确切子字符串:
substr
答案 1 :(得分:1)
据我所知,没有开箱即用的功能,但实施起来应该不难。
例如:
template <typename ForwardIterator>
int range_to_int(ForwardIterator begin, ForwardIterator past_end) {
if (begin != past_end) {
bool negative = false;
auto ch = *begin;
if (ch == '-') {
negative = true;
++begin;
}
else if (ch == '+')
++begin;
if (begin != past_end) {
int result = 0;
do {
auto ch = *begin;
if (ch < '0' || ch > '9')
throw std::invalid_argument("Invalid digit.");
result = result * 10 + (ch - '0');
++begin;
} while (begin != past_end);
if (negative)
result = -result;
return result;
}
throw std::invalid_argument("+ or - must be followed by at least one digit.");
}
throw std::invalid_argument("Empty range.");
}
你可以像这样使用它:
int main() {
const char* buffer = "abc-123def";
int i = range_to_int(buffer + 4, buffer + 7);
assert(i == 123);
i = range_to_int(buffer + 3, buffer + 7);
assert(i == -123);
try {
i = range_to_int(buffer + 3, buffer + 8);
assert(false);
}
catch (const std::exception& ex) {
std::cout << ex.what() << std::endl;
}
try {
i = range_to_int(buffer + 3, buffer + 4);
assert(false);
}
catch (const std::exception& ex) {
std::cout << ex.what() << std::endl;
}
try {
i = range_to_int(buffer + 4, buffer + 4);
assert(false);
}
catch (const std::exception& ex) {
std::cout << ex.what() << std::endl;
}
// You can use it on std::string as well....
const std::string str = buffer;
i = range_to_int(str.begin() + 4, str.begin() + 7);
assert(i == 123);
// Etc...
return EXIT_SUCCESS;
}