我正在研究一個項目,我必須閱讀一個日期以確保它是一個有效的日期。例如,2月29日只是閏年的有效日期,或者6月31日不是有效日期,因此計算機會根據輸入信息輸出該信息。我的問題是,我無法弄清楚如何解析字符串,以便用戶可以輸入「05/11/1996」作爲日期(例如),然後將其放入單獨的整數中。我正在考慮嘗試使用while循環和字符串流做些事情,但我有點卡住了。如果有人能幫助我,我會很感激。如何在C++中解析和驗證std :: string中的日期?
回答
如果格式就像你的榜樣,你可以取出整數這樣的:
int day, month, year;
sscanf(buffer, "%2d/%2d/%4d",
&month,
&day,
&year);
其中當然在緩衝區你有日期(「1996年5月11日」)
一個可能的解決方案也是基於strptime
,但是請注意,此功能僅驗證日是否爲從區間<1;31>
和一個月<1;12>
,即"30/02/2013"
是有效的還是:
#include <iostream>
#include <ctime>
int main() {
struct tm tm;
std::string s("32/02/2013");
if (strptime(s.c_str(), "%d/%m/%Y", &tm))
std::cout << "date is valid" << std::endl;
else
std::cout << "date is invalid" << std::endl;
}
但由於
strptime
並不總是可用的和額外的驗證將是很好,這裏是你能做什麼:
- 提取日,月,年
- 填寫
struct tm
- 正常化它
- 檢查是否歸日期仍然與檢索日期,月份,年份相同
ie:
#include <iostream>
#include <sstream>
#include <ctime>
// function expects the string in format dd/mm/yyyy:
bool extractDate(const std::string& s, int& d, int& m, int& y){
std::istringstream is(s);
char delimiter;
if (is >> d >> delimiter >> m >> delimiter >> y) {
struct tm t = {0};
t.tm_mday = d;
t.tm_mon = m - 1;
t.tm_year = y - 1900;
t.tm_isdst = -1;
// normalize:
time_t when = mktime(&t);
const struct tm *norm = localtime(&when);
// the actual date would be:
// m = norm->tm_mon + 1;
// d = norm->tm_mday;
// y = norm->tm_year;
// e.g. 29/02/2013 would become 01/03/2013
// validate (is the normalized date still the same?):
return (norm->tm_mday == d &&
norm->tm_mon == m - 1 &&
norm->tm_year == y - 1900);
}
return false;
}
用作:
int main() {
std::string s("29/02/2013");
int d,m,y;
if (extractDate(s, d, m, y))
std::cout << "date "
<< d << "/" << m << "/" << y
<< " is valid" << std::endl;
else
std::cout << "date is invalid" << std::endl;
}
在這種情況下將輸出date is invalid
因爲正常化將檢測29/02/2013
已被標準化爲01/03/2013
。
很好的答案。當Google試圖找到驗證輸入日期的方法時,Google搜索將我帶到了這裏。您的方法還處理閏年和其他邊緣情況,這非常棒。 – DaV
有一個問題:如果你輸入的年份低於1970年(epoch年),它將被歸一化到1970年,並且該函數將失敗 –
我寧願使用升壓日期時間:
#include <iostream>
#include <boost/date_time/local_time/local_time.hpp>
struct dateparser
{
dateparser(std::string fmt)
{
// set format
using namespace boost::local_time;
local_time_input_facet* input_facet = new local_time_input_facet();
input_facet->format(fmt.c_str());
ss.imbue(std::locale(ss.getloc(), input_facet));
}
bool operator()(std::string const& text)
{
ss.clear();
ss.str(text);
bool ok = ss >> pt;
if (ok)
{
auto tm = to_tm(pt);
year = tm.tm_year;
month = tm.tm_mon + 1; // for 1-based (1:jan, .. 12:dec)
day = tm.tm_mday;
}
return ok;
}
boost::posix_time::ptime pt;
unsigned year, month, day;
private:
std::stringstream ss;
};
int main(){
dateparser parser("%d/%m/%Y"); // not thread safe
// parse
for (auto&& txt : { "05/11/1996", "30/02/1983", "29/02/2000", "29/02/2001" })
{
if (parser(txt))
std::cout << txt << " -> " << parser.pt << " is the "
<< parser.day << "th of "
<< std::setw(2) << std::setfill('0') << parser.month
<< " in the year " << parser.year << "\n";
else
std::cout << txt << " is not a valid date\n";
}
}
輸出:
05/11/1996 -> 1996-Nov-05 00:00:00 is the 5th of 11 in the year 96
30/02/1983 is not a valid date
29/02/2000 -> 2000-Feb-29 00:00:00 is the 29th of 02 in the year 100
29/02/2001 is not a valid date
我剛剛重構了我的答案以顯示(a)如何有效地重新使用imbued流解析(b)它驗證輸入 – sehe
另一種選擇是使用std::get_time
從<iomanip>
頭(可自C++ 11以來)。它的一個很好的例子可以找到here。
- 1. JavaScript中的日期解析和驗證
- 2. 在C#中解析和驗證解析#
- 3. 如何解析std :: string中的rapidjson?
- 4. 解析日期與驗證
- 5. 如何解析DWORD和LPBYTE爲std :: string
- 6. C++中的日期驗證和轉換
- 7. 未在Eclipse/CDT 8.0中解析std :: string
- 8. 解析的std :: string與升壓ptree中
- 9. 如何在JQuery中驗證日期和日期?
- 10. C++ std :: string和string
- 11. 如何驗證日曆中的日期
- 12. 日期在C#中的XML解析
- 13. C++ - 從std :: string解析數字
- 14. 如何在iphone中驗證日期選擇器中的日期?
- 15. 在C++中驗證日期格式
- 16. 在C#中的std :: string?
- 17. 如何在php中驗證日期?
- 18. 如何在導軌中驗證日期?
- 19. 如何在javascript中驗證日期
- 20. 如何在Flash AS3中解析日期
- 21. 如何在C++中終止std :: string?
- 22. 解析和驗證ruby中的任意日期格式(在rails上)
- 23. 解析和驗證數字和日期時間輸入
- 24. 如何在文本框中驗證日期實施的日期?
- 25. 驗證C#中的日期時間#
- 26. 目標c中的日期驗證
- 27. 用於C中日期驗證的庫?
- 28. 如何驗證jQuery中的datepicker日期
- 29. 如何在java中解析無法解析的日期
- 30. 在symfony2中驗證日期
有沒有一種方法可以使用字符串?我把它放到一些代碼中,並將一個變量緩衝區設置爲「05/20/13」,不幸的是它說在string和const char之間沒有合適的轉換。 – emufossum13
是的,如果你使用std :: string,那麼buffer.c_str()就是你需要的。 – DrM
這是我如何設置變量decleration std :: string buffer = buffer。c_str(); buffer =「05/10/1996」; 是你在說什麼? – emufossum13