我使用boost :: date_time为VS2012构建了一系列日期输入格式的简单解析器。我写的有问题的部分在下面
#include <iostream>
#include <sstream>
#include <string>
#include "boost/date_time.hpp"
namespace bt = boost::posix_time;
const std::locale formats[] = {
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")), //25042014 23:59
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%y %H:%M")), //250414 23:59
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m %H:%M")) //2504 23:59
//additional formats removed for brevity
};
const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
int main(void) {
std::string input = "25052014 12:45";
bt::ptime dateTime;
std::stringstream ss(input);
for(size_t i = 0; i < formats_n; ++i) {
ss.imbue(formats[i]);
ss >> dateTime;
if(dateTime != bt::not_a_date_time) {
break;
}
}
std::cout << dateTime << std::endl;
return 0;
}
问题在于ss.imbue()似乎并没有以这种方式为我工作,尽管已经在其他地方搜索并找到了类似的代码。我总是得到一个not_a_date_time。如果我用
替换它,它工作正常ss.imbue(std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")));
但是因为我需要循环使用不同的格式,这不是一个真正的选择。
答案 0 :(得分:0)
您忘记重置输入流。因此,如果第一个失败,它将继续失败。
以下是修复:
ss.clear();
ss.seekg(0);
现在,您仍需要修复已接受的输入格式的顺序。见 Live On Coliru 。
考虑为这种场景编写适当的解析器,因为仅通过对格式进行排序来强制执行正确的解释是很困难的。
流式传输操作可能最适合固定格式(反)序列化。
#include <iostream>
#include <sstream>
#include <string>
#include "boost/date_time.hpp"
namespace bt = boost::posix_time;
const std::locale formats[] = {
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%Y %H:%M")), //25042014 23:59
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m%y %H:%M")), //250414 23:59
std::locale(std::locale::classic(), new bt::time_input_facet("%d%m %H:%M")) //2504 23:59
//additional formats removed for brevity
};
const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
int main(void) {
for (std::string input : {
"25052014 12:45",
"250514 12:45",
"2505 12:45",
})
{
bt::ptime dateTime;
std::stringstream ss(input);
for(size_t i = 0; i < formats_n; ++i) {
ss.imbue(formats[i]);
ss >> dateTime;
if(dateTime != bt::not_a_date_time) {
break;
}
ss.clear();
ss.seekg(0);
}
std::cout << dateTime << std::endl;
}
}