解決後にあれっぽいですが「mktime って使えねー」と思った人も居ると思うので
弁護しておきます。
mktime で 2003/02/29 等がエラーにならないのはわざとです。
mktime は日付の妥当性を調べる関数ではないからです。
例えばある日の翌日の日付を求めるときには次のコードでよいのです。
++tm.tm_mday; // 31 日であってもこれだけでよい
t=mktime(&tm);
p=localtime(&t);
今日が 2/28 であったとしたら、結果は 2/29 または 3/1 になります。
どうしても日付の妥当性を mktime で取りたいのなら
mktime->localtime した結果が元の日付と同じかどうかで判断できます。
ざくざくっと書いてみた。
#include <iostream>
#include <string>
int str2int(const std::string& str) {
int result = 0;
for ( std::string::const_iterator iter = str.begin();
iter != str.end(); ++iter ) {
result = result*10 + *iter - '0';
}
return result;
}
bool is_leap(int y) {
bool result = false;
if ( y % 4 == 0 ) result = true;
if ( y % 100 == 0 ) result = false;
if ( y % 400 == 0 ) result = true;
return result;
}
bool validate(int y, int m, int d) {
const int days[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
if ( m < 1 || m > 12 ) return false;
int daysinmonth = days[m-1];
if ( is_leap(y) && m == 2 ) ++daysinmonth;
return ( d < 1 || d > daysinmonth ) ? false : true;
}
void split(const std::string& str, int& y, int& m, int& d) {
if ( str.size() != 8 ) return;
y = str2int(str.substr(0,4));
m = str2int(str.substr(4,2));
d = str2int(str.substr(6,2));
}
int main(int argc, char* argv[]) {
for ( int i = 1; i < argc; ++i ) {
int y, m, d;
split(argv[i], y, m, d);
std::cout << y << '/' << m << '/' << d << :
<< std::boolalpha << validate(y,m,d) << std::endl;
}
return 0;
}