使用stringstream而不是`sscanf`来解析固定格式的字符串

Joh*_*ing 13 c++

我想使用提供的工具stringstream从固定格式中提取值string作为类型安全的替代sscanf.我怎样才能做到这一点?

请考虑以下特定用例.我有std::string以下固定格式:

YYYYMMDDHHMMSSmmm

哪里:

YYYY = 4 digits representing the year
MM = 2 digits representing the month ('0' padded to 2 characters)
DD = 2 digits representing the day ('0' padded to 2 characters)
HH = 2 digits representing the hour ('0' padded to 2 characters)
MM = 2 digits representing the minute ('0' padded to 2 characters)
SS = 2 digits representing the second ('0' padded to 2 characters)
mmm = 3 digits representing the milliseconds ('0' padded to 3 characters)
Run Code Online (Sandbox Code Playgroud)

以前我在这方面做了一些事情:

string s = "20101220110651184";
unsigned year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, milli = 0;    
sscanf(s.c_str(), "%4u%2u%2u%2u%2u%2u%3u", &year, &month, &day, &hour, &minute, &second, &milli );
Run Code Online (Sandbox Code Playgroud)

宽度值是幻数,这没关系.我想使用流来提取这些值并将它们转换为unsigneds以保证类型安全.但是,当我尝试这个:

stringstream ss;
ss << "20101220110651184";
ss >> setw(4) >> year;
Run Code Online (Sandbox Code Playgroud)

year保留价值0.它应该是2010.

我该怎么做我想做的事情?我不能使用Boost或任何其他第三方库,也不能使用C++ 0x.

Jam*_*lis 7

一个不是特别有效的选择是构造一些临时字符串并使用词法强制转换:

std::string s("20101220110651184");
int year = lexical_cast<int>(s.substr(0, 4));
// etc.
Run Code Online (Sandbox Code Playgroud)

lexical_cast可以用几行代码实现; Herb Sutter在他的文章"庄园农场的字符串格式化程序"中提出了最低限度的要求.

它并不是您正在寻找的,但它是一种从字符串中提取固定宽度字段的类型安全方法.


Nim*_*Nim 5

嗯,如果是固定格式,为什么不这样做?

  std::string sd("20101220110651184");
  // insert spaces from the back
  sd.insert(14, 1, ' ');
  sd.insert(12, 1, ' ');
  sd.insert(10, 1, ' ');
  sd.insert(8, 1, ' ');
  sd.insert(6, 1, ' ');
  sd.insert(4, 1, ' ');
  int year, month, day, hour, min, sec, ms;
  std::istringstream str(sd);
  str >> year >> month >> day >> hour >> min >> sec >> ms;
Run Code Online (Sandbox Code Playgroud)