从文件中读取日期



我将输入一个输入,如2021/10/7(年/月/日)。我不会要求用户输入,我需要的代码能够正确读取输入。我不明白如何从Linux获得输入(日期),以及我的程序如何将该输入横向到我的代码中的适当位置。

我们已经简要地介绍了<fstream>ifstream inData; ofstream outData;.open.close,但在我发布的样品溶液中的最后一次作业中,我使用了我完全不熟悉的freopen。我特别向我的教授寻求帮助,但鼓励使用外部手段,如计算机科学和辅导,这些都没有多大帮助。

我正在寻找的是一种学习如何能够输入数据的方法,以便它可以从数据流中读取,以及我应该如何构建这样的东西,以便从Linux而不是用户获取输入。

编写程序从标准输入流中读取日期。

如果日期有效,程序应在工作日的英文名称(例如,"Monday", "Tuesday", "Wednesday",…,"Sunday"。函数main返回0

如果从标准输入流中读取的日期无效,程序应该写&;Error: invalid date&;。函数main返回1.

<<p>样本交互/strong>
$ echo "2021/03/01" | ./pa04
0 Monday
$ echo $?
0
$ echo "  2022/3/1" | ./pa04
1 Tuesday
$ echo $?
0
$ echo "3/1/2022" | ./pa04
Error: invalid date
$ echo $?
1
$ echo "abracadabra" | ./pa04
Error: invalid date
$ echo $?
1  
#include iostream
#include string
#include iomanip
#include cmath
using namespace std;
int main() {
int day, month, year, w;
// When I get here I feel there needs to be a cin.ignore() for the '/' in 2021/10/07. 
// But I'm also concerned that if someone puts in 7 instead of 07 like in the sample interactions that it will jack up the results.
cin >> year >> month >> day;
w = (day + (13 * (month + 1) / 5) + (year) + (year / 4) - (year / 100) + (year / 400)) % 7;
switch (w) {
case 1:
cout << "Sunday n";
break;
case 2:
cout << "Monday n";
break;
case 3:
cout << "Tuesday n";
break;
case 4:
cout << "Wednesday n";
break;
case 5:
cout << "Thursday n";
break;
case 6:
cout << "Friday n";
break;
case 7:
cout << "Saturday n";
break;
}

return 0;
}

您根本没有处理/字符。

你可以使用额外的>>调用和变量:

int day, month, year;
char slash1, slash2;
if ((cin >> year >> slash1 >> month >> slash2 >> day) &&
(slash1 == '/') &&
(slash2 == '/'))
{
// use values as needed...
}
else
{
// invalid format...
}

或者,您可以使用istream::ignore()跳过/字符:

int day, month, year;
if (cin >> year &&
cin.ignore(numeric_limits<streamsize>::max(), '/') &&
cin >> month &&
cin.ignore(numeric_limits<streamsize>::max(), '/') &&
cin >> day)
{
// use values as needed...
}
else
{
// invalid format...
}

或者,在c++ 11及更高版本中,您可以使用std::get_time()让标准库为您读入和解析日期组件:

#include <iomanip>
tm date;
if (cin >> get_time(&date, "%Y/%m/%d"))
{
int day = date.tm_mday;
int month = date.tm_mon + 1;
int year = date.tm_year + 1900;
int w = date.tm_wday + 1;
// use values as needed...
}
else
{
// invalid format...
}

使用std::get_time()还有一个额外的好处,std::tm有一个tm_wday成员,用于一周中的一天,正如你上面看到的,所以你不必手动计算它。

您也可以使用c++ 20的std::chrono。它允许你:

  • 根据格式规范将输入字符串解析为时间对象(例如系统时钟中的天数)。
  • 获取该时间对象的星期。

我发现std::chronoparse方法:

  1. 不是很灵活。AFAIK,它不允许您使用正则表达式(例如,用于匹配输入字符串开头的空白,如在您的输入示例之一,
    2022/4/2;特别是,这可以很容易地修复在解析字符串之前修剪字符串)。
  2. 可能导致一些解析意外。例如,对于另一个输入示例5/3/2023,它将把日期解释为第5年的3月20日。也就是说,它会将日期匹配到输入字符串2023中应该是日期的前两位数字20

所以我会选择混合溶液:

  • 将输入字符串手工解析为时间对象。
  • 然后使用std::chrono获取该时间对象对应的星期。

下面的代码在两个不同的函数using_just_chronousing_regex_and_chrono中实现了这两个解决方案,只是为了显示我上面提到的问题,如果我们只使用std::chrono。我使用正则表达式进行手动解析,但是您可以在做一些调整后使用字符串流捕获每个日期的年、月和日。

#include <chrono>  // parse, sys_days, weekday
#include <iostream>  // cout
#include <regex>  // regex_match, smatch
#include <sstream>  // istringstream
namespace ch = std::chrono;
void using_just_chrono(const std::string& date)
{
ch::year_month_day ymd{};
std::istringstream iss{ date };
if (iss >> ch::parse(std::string{ "%Y/%m/%d" }, ymd) and ymd.ok())
{
std::cout << "ttusing just chrono: " << ch::weekday{ ch::sys_days{ ymd } } << "n";
}
}
void using_regex_and_chrono(const std::string& date)
{
// Probably more portable using [[:space:]] and [[:digit:]] here
std::regex pattern{ R"(^s*(d{1,4})/(d{1,2})/(d{1,2})s*$)" };
std::smatch matches{};
if (std::regex_match(date, matches, pattern))
{
ch::year_month_day ymd(
ch::year{ std::stoi(matches[1]) },
ch::month{ std::stoul(matches[2]) },
ch::day{ std::stoul(matches[3]) });
if (ymd.ok())
{
std::cout << "ttusing rgx and chr: " << ch::weekday{ ch::sys_days{ ymd } } << "n";
}
}
}
int main()
{
std::cout << "Parsing dates:n";
for (const std::string& date : {
"2021/03/01",  // OK
"  2022/4/2",  // OK: needs trimming white spaces at the front
"5/3/2023",  // wrong: day is 2023
"abracadabra",  // wrong format
"2020/12/32",  // wrong: day is 32
"2019/13/20",  // wrong: month is 13
"2021/2/29" })  // wrong: non existing date
{
std::cout << "t"" << date << "":n";
using_just_chrono(date);
using_regex_and_chrono(date);
}
std::cout << "n";
}
// Outputs:
//
// Parsing dates:
//     "2021/03/01":
//         using just chrono: Mon
//         using rgx and chr: Mon
//     "  2022/4/2":
//         using rgx and chr: Sat
//     "5/3/2023":
//         using just chrono: Sun
//     "abracadabra":
//     "2020/12/32":
//     "2019/13/20":
//     "2021/2/29":

最新更新