如何将日期转换时的段错误提示替换为自定义无效日期提示?
解决日期转换函数的段错误与自定义错误提示问题
首先,咱们得搞清楚为什么你的try-catch没起作用:strptime、mktime这些C标准库函数不会抛出C++异常,你的段错误是因为当输入无效日期时,strptime返回了nullptr,然后你直接把这个空指针传给std::atof,触发了空指针访问的崩溃——这种属于未定义行为,try-catch根本捕获不到。
要解决这个问题,咱们需要主动检查关键函数的返回值,而不是依赖异常捕获。下面是完整的解决方案:
核心检查点说明
- 检查
strptime返回值:解析失败时会返回nullptr,直接判定日期无效;若解析成功,它会指向未处理的毫秒小数部分,需确保该指针合法。 - 检查
mktime返回值:即使字符串被解析,像40-10-2015这种无效日期,mktime转换时会返回-1,这一步必须校验。 - 安全处理小数部分:用
std::strtod替代std::atof,它能通过额外参数检查解析是否成功,避免空指针或非法格式的问题。
修改后的完整代码
#include <iostream> #include <ctime> #include <chrono> #include <cstdlib> #include <stdexcept> long long dateToMs(const char* text) { std::tm tm = {}; // 1. 检查日期主体解析是否成功 const char* snext = ::strptime(text, "%d-%m-%Y %H:%M:%S", &tm); if (snext == nullptr) { throw std::invalid_argument("输入的日期无效"); // 若不想抛异常,也可直接输出提示并返回错误标记: // std::cout << "输入的日期无效" << std::endl; // return -1; } // 2. 检查时间戳转换是否成功 std::time_t time_t_val = std::mktime(&tm); if (time_t_val == -1) { throw std::invalid_argument("输入的日期无效"); } // 3. 安全解析毫秒小数部分 double ms_fraction = 0.0; if (*snext == '.') { char* end_ptr; ms_fraction = std::strtod(snext, &end_ptr); // 校验小数部分是否合法 if (end_ptr == snext) { throw std::invalid_argument("输入的日期无效(毫秒格式错误)"); } } // 计算最终毫秒数 auto time_point = std::chrono::system_clock::from_time_t(time_t_val); auto ms_since_epoch = std::chrono::duration_cast<std::chrono::milliseconds>( time_point.time_since_epoch() ).count(); return ms_since_epoch + static_cast<long long>(ms_fraction * 1000.0); } // 调用示例 int main() { try { long long ms = dateToMs("40-10-2015 12:23:45.2354"); std::cout << "转换后的毫秒数:" << ms << std::endl; } catch (const std::exception& e) { std::cout << e.what() << std::endl; } return 0; }
额外说明
如果你更倾向于不使用异常,也可以把错误提示直接写在函数内,返回-1作为错误标记,但在调用处需要判断返回值是否有效。这种写法适合对异常处理有顾虑的场景。
内容的提问来源于stack exchange,提问作者david.t_92
相关产品推荐
相关产品推荐

