You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::string_view无终止符无法用sscanf,求POSIX替代方案

POSIX标准下处理std::string_view格式化输入的替代方案

由于std::string_view不保证以空字符结尾,直接使用sscanf会触发未定义行为。微软CRT的_snscanf_s支持传入缓冲区长度规避该问题,POSIX标准里有两种可靠的替代方案:

1. 转换为临时空终止字符串(简单直观)

把std::string_view转换成std::string,利用std::string自动添加空终止符的特性,再传给sscanf:

TIMESTAMP_STRUCT StringToTimestamp(std::string_view dTime, bool dayfirst) noexcept
{
    TIMESTAMP_STRUCT t{};
    const std::string temp_str(dTime);
    int res;
    if (dayfirst)
        res = sscanf(temp_str.c_str(), "%2hu.%2hu.%4hd %2hu:%2hu:%2hu", &t.day, &t.month, &t.year, &t.hour, &t.minute, &t.second);
    else
        res = sscanf(temp_str.c_str(), "%4hd-%2hu-%2hu %2hu:%2hu:%2hu", &t.year, &t.month, &t.day, &t.hour, &t.minute, &t.second);

    if (res == 6)
        return t;

    if (!dTime.empty() && dTime != "0")
        Common::Log::Instance()->TraceFatal("StringToTimestamp failed");
    return {};
}

该方案实现简单,无额外依赖;缺点是会产生一次内存拷贝,对于短时间戳字符串而言,性能影响可忽略。

2. 用fmemopen包装内存为文件流(无内存拷贝)

POSIX.1-2008标准定义的fmemopen可直接将string_view指向的内存区域包装成只读文件流,再用fscanf读取内容,完全避免内存拷贝:

#include <cstdio>

TIMESTAMP_STRUCT StringToTimestamp(std::string_view dTime, bool dayfirst) noexcept
{
    TIMESTAMP_STRUCT t{};
    // fmemopen要求非const指针,但我们仅做只读操作,const_cast是安全的
    FILE* stream = fmemopen(const_cast<char*>(dTime.data()), dTime.size(), "r");
    if (!stream) {
        if (!dTime.empty() && dTime != "0")
            Common::Log::Instance()->TraceFatal("StringToTimestamp failed: fmemopen failed");
        return {};
    }

    int res;
    if (dayfirst)
        res = fscanf(stream, "%2hu.%2hu.%4hd %2hu:%2hu:%2hu", &t.day, &t.month, &t.year, &t.hour, &t.minute, &t.second);
    else
        res = fscanf(stream, "%4hd-%2hu-%2hu %2hu:%2hu:%2hu", &t.year, &t.month, &t.day, &t.hour, &t.minute, &t.second);

    fclose(stream);

    if (res == 6)
        return t;

    if (!dTime.empty() && dTime != "0")
        Common::Log::Instance()->TraceFatal("StringToTimestamp failed");
    return {};
}

此方案适合性能敏感场景,但需确保目标系统支持POSIX.1-2008及以上标准。

不推荐的方案:直接用sscanf+strnlen

部分场景下有人会先通过strnlen检查string_view是否包含空字符,若没有则直接用sscanf。但该方式存在风险:若string_view中间意外包含空字符,会导致sscanf提前终止读取,引发逻辑错误,因此不建议使用。

内容的提问来源于stack exchange,提问作者OwnageIsMagic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 17:22:39