stl中是否有任何函数可以进行字符串转换,但带有长度参数

Are there any functions in the stl which do string conversion, but with a length parameter?

本文关键字:转换 参数 字符串 任何 是否 函数 stl      更新时间:2023-10-16

假设您有一个字符串:

std::string s = "ABCDt1234";

我可以使用std::string::find来获得'\t'字符的偏移量,但据我所知,没有具有以下签名的函数:

int atoi_n(char *, int len);

我会错过什么吗?strtok替换了t,我不想触摸原始缓冲区。我发现很难相信atoiatof等的实例都不需要长度参数,但我什么都找不到。

有人知道我是否遗漏了什么吗?我知道boost有一些标记器,但我希望避免添加对boost的依赖。

看看目前的评论,我想澄清一下。让我们改变这个场景:字符缓冲区[1024];char*pStartPos;char*pEndPost;pStartPos=缓冲液+5;pEndPos=缓冲区+10;

假设您不能对pStartPos和pEndPos之外的内存进行任何假设。如何将pStartPos和pEndPos之间的字符转换为int,而不向缓冲区添加"\0"或使用substr进行复制?

如果只想解析字符串的末尾(从t之后的字符到末尾),只需要传递一个指向要解析到atoi的第一个字符的指针。。。

int n = atoi(s.c_str()+s.find('t')+1);

(为简洁起见,省略了错误检查-特别是,我们总是假设t实际存在)

相反,如果你想从字符串的开头一直解析到t,你可以只做

int n = atoi(s.c_str());

因为CCD_ 11无论如何都停止在第一个非数字字符处。

顺便说一句,您应该考虑使用更强大的解决方案来解析数字,如strtolsscanf或C++流——它们都可以以某种方式报告解析错误,而atoi只返回0(这与解析字符串时的0无法区分)。


顺便说一句,atoi无论如何都不在"STL"中——它只是C标准库的一部分。


我知道atoi不在STL。我想知道STL中是否有类似的东西可以指定转换中要包含的最后一个字符。基本上,我有一个缓冲区,其中可能部分填充了垃圾。我知道可能有效数据的开始和可能有效数据结束。我不想依赖空白来结束转换,我想明确"字段"的长度,因为它也可能不会以/0结尾。

如果你确定垃圾不是以数字开头的,你可以按原样使用atoi/strtol/istringstream——它们在看到垃圾时会自动停止。否则,请使用substr方法提取所需的确切子字符串:

std::string mayContainGarbage="alcak123456amaclmò";
std::string onlyTheDigits=mayContainGarbage.substr(5, 6);
// now parse onlyTheDigits as you prefer

据我所知,没有现成的函数,但实现起来应该不难。

例如:

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;
}