2013-02-24 31 views
3

我正在编写一个程序,它将日期字符串转换为三个单独的int变量:年,月,日。sscanf C++将字符串拆分为整数有时不起作用

int m,d,y; 
sscanf("2011-03-08","%i %*[-] %i %*[-] %i",&y,&m,&d); 
cout << y<<" "<<m<<" "<<" "<<d<<std::endl; 
sscanf("2011-03-07","%i %*[-] %i %*[-] %i",&y,&m,&d); 
cout << y<<" "<<m<<" "<<" "<<d; 

如果我转换2011-03-08 2011-03-09或者,这一天将是0,但对于2011-03-07,06 ......这一天是7,6,...正如我所期望的那样。有人可以解释它,为什么它不适用于08或09年,只为他们?

预先感谢您!

+0

我认为这可能是由于八进制,请尝试使用%d – QuentinUK 2013-02-24 12:47:17

+0

你真的应该不能混合使用C和C++这样。这些是不同的语言,所以避免在编写C++ – LihO 2013-02-24 12:56:59

回答

4

参见man sscanf


匹配任选符号整数;下一个指针必须是一个指向int的指针。如果以0x或0X开始,则以16为基数读取整数;如果以0开始,则以8为基数读取整数;否则以基数10读取。只使用对应于基地的字符。

08将被扫描为八进制整数,因为它以0开头。但08不是有效的八进制整数,而07是。如果您使用%d而不是%i,它将按照您的预期工作。

sscanf("2011-03-08","%d %*[-] %d %*[-] %d", &y, &m, &d); 

或者也可以简单

sscanf("2011-03-08","%d-%d-%d", &y, &m, &d); 
+0

+1时编写C风格的代码。然而,问这个问题的人可能应该更喜欢使用std :: istringstream而不是sscanf。 – Aleph 2013-02-24 12:50:15

+0

@AnotherTest同意,这将是下一步。但是如果他必须保留一些现有的代码,这可能不是一个选项。 – 2013-02-24 12:52:18

+0

@AnotherTest:流并不总是一个选项。如果编译时的格式未知,该怎么办?周围有如此多的日期格式......此外,对于更复杂的解析任务,流不支持'sscanf',实际上它实现了一种小型解析器。然而,正则表达式可能更像它;特别是现在它们已经标准化了。 – 2013-02-24 14:43:57

1

你的格式字符串是错误的...它应该仅仅是"%4d-%02d-%02d"

它不会伤害到检查的sscanf与if (3 != sscanf(...)) { /* failed */ }

工作太
2

问题是%i08视为一个八进制整数,所以可能的解决方案可能是使用%d替代,,因为这是C++,你应该使用std::istringstream#include <sstream>)代替:

int y,m,d; 
char delimiter; 

std::istringstream dateStream("2011-03-08"); 
dateStream >> y >> delimiter >> m >> delimiter >> d; 

std::cout << y << " " << m << " " << d; 
+0

你忘了验证''''定界符''''''每次','sscanf'暗示为你做的,所以它不完全等价。 – 2013-02-24 14:44:48

+0

@MatthieuM .:好点,虽然我不是说它完全等同于'sscanf'。我只想指出还有其他可能的解决方案。 – LihO 2013-02-24 14:50:32