【问题标题】:How do I use getline and stringstream to parse formatted date and time input?如何使用 getline 和 stringstream 解析格式化的日期和时间输入?
【发布时间】:2012-04-06 05:09:45
【问题描述】:

我只在 C++ 上工作了大约一个月。我不太了解它是如何工作的,但是我需要为学校编写一个程序。我使用了一个 void 函数,到目前为止它似乎正在工作,但我不知道下一步该做什么我在第 44 行迷路了,我不知道如何让它工作,有没有办法从某个字符串?如果值在两个字符串中,我将如何确定哪个值?这是我的任务:

停车库收取 2.00 美元的最低停车费,最多可停车三个小时。超过三个小时,车库每小时或部分每小时额外收费 0.50 美元。任何给定 24 小时期间的最高费用为 10.00 美元。停车超过 24 小时的人每天将支付 8.00 美元。

编写一个计算并打印停车费的程序。程序的输入是汽车进入停车场的日期和时间,以及同一辆车离开停车场的日期和时间。两个输入的格式都是 YY/MM/DD hh:mm

这是我目前编写的代码:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cmath>
#include <algorithm>
#include <sstream>
using namespace std;

stringstream ss;
string enter_date;
string enter_time;
string exit_date;
string exit_time;
int calculatecharge;
int num;
int i;
int year;
int month;
int ddmmyyChar;
int dayStr;
string line;
int x;

void atk() 
{
    getline (cin,line);             // This is the line entered by the user
    stringstream  ss1(line);        // Use stringstream  to interpret that line
    ss >> enter_date >> enter_time;
    stringstream  ss2(enter_date);  // Use stringstream  to interpret date
    string year, month, day;
    getline (ss2, year, '/');
}

int main()
{
    cout << "Please enter the date and time the car is entering "<< endl
         << "the parking garage in the following format: YY/MM/DD hh:mm"<< endl;
    atk();
    cout << "Please enter the date and time the car is exiting "<< endl
         << "the parking garage in the following format: YY/MM/DD hh:mm"<< endl;
    atk();
    if (hr - hr < 3)
        cout<<"Parking fee due: $2.00" << endl;

【问题讨论】:

  • 您包含的某些头文件不是必需的。例如,如果您不执行文件 I/O,则不需要#include &lt;fstream&gt;

标签: c++ parsing stringstream getline


【解决方案1】:

编写一个计算并打印停车费的程序。

这是我们计划的目标。基本上,这就是输出。

程序的输入是汽车进入的日期和时间 停车场,以及同一辆车离开停车场的日期和时间 停车库。两个输入的格式都是 YY/MM/DD hh:mm

因此,我们需要某种方法将作为字符串输入的日期格式转换为时间差异。您可以将时间存储在int 中,它表示停车期间经过的分钟数(我选择分钟,因为这是输入的最小时间段)。这里的挑战是将字符串解析成这个整数。

你可以这样写一个函数:

int parseDate( std::string dateStr )
{
    // Format: YY/MM/DD hh:mm
    int year  = atoi( dateStr.substr( 0, 2 ).c_str() );
    int month = atoi( dateStr.substr( 3, 2 ).c_str() );
    int day   = atoi( dateStr.substr( 6, 2 ).c_str() );
    int hour  = atoi( dateStr.substr( 9, 2 ).c_str() );
    int min   = atoi( dateStr.substr( 12, 2 ).c_str() );

    // Now calculate no. of mins and return this
    int totalMins = 0;
    totalMins += ( year * 365 * 24 * 60 ); // Warning: may not be accurate enough
    totalMins += ( month * 30 * 24 * 60 ); // in terms of leap years and the fact
    totalMins += ( day * 24 * 60 );        // that some months have 31 days
    totalMins += ( hour * 60 );
    totalMins += ( min );

    return totalMins;
}

小心!我在这里的功能只是一个说明,并没有考虑到闰年和不同月份长度等细微之处。你可能需要改进它。重要的是要认识到它会尝试获取一个字符串并返回自 '00 年以来经过的分钟数。这意味着我们只需从两个日期字符串中减去两个整数即可找到经过的时间:

int startTime = parseDate( startDateString );
int endTime   = parseDate( endDateString );
int elapsedTime = endTime - startTime; // elapsedTime is no. of minutes parked

这可能是问题中最难的部分,一旦你解决了这个问题,剩下的就应该更简单了。我再给你一些提示:

停车场最多收取 2.00 美元的停车费,最多可停三个 小时。

基本上只是一个统一费率:无论如何,描述成本的输出变量至少应该等于2.00

车库每小时收取 0.50 美元的额外费用 或部分时间超过三个小时。

计算过去三个小时过去的小时数 - 从 elapsedTime 中减去 180。如果这大于0,则将其除以60,并将结果存储在float(因为它不一定是整数结果)中,称为excessHours。使用excessHours = floor( excessHours ) + 1; 将这个数字向上取整。现在乘以0.5;这是额外的费用。 (尝试理解为什么这在数学上有效)。

任何人的最高收费 给定的 24 小时周期为 10.00 美元。停车时间更长的人 超过 24 小时将支付 8.00 美元/天。

我将把这留给你来解决,因为这毕竟是家庭作业。希望我在这里提供了足够的信息,让您了解需要做的事情的要点。这个问题也有很多可能的方法,这只是一种,可能是也可能不是“最好的”。

【讨论】:

  • 非常感谢您对我的帮助!我不确定数学,但你如何解释它很有意义。我真的很感激。
  • 您好,我非常感谢您给我的所有帮助,但我仍然完全迷失了。我不知道该怎么做,甚至不知道你到底做了什么。将字符串放入正确格式后,我该如何使用它以及如何使用计算?
  • 日期字符串转换为整数后,这些整数现在表示自'00 年以来的分钟数。通过从“结束”时间中减去“开始”时间,您可以得到进入和离开停车场之间的时间差,以分钟为单位。这使您可以计算费用。你说的是这个吗?
  • 是的,但是我无法让那部分工作我不确定如何修复错误 C2371: 'std::cin' : redefinition;不同的基本类型。
  • 没有代码很难帮忙,但是网上有很多资源都提到了这个错误。我会说做一个彻底的谷歌搜索,如果这没有产生任何结果,你可能想开始另一个问题。评论不是诊断/修复代码错误的最佳场所。
【解决方案2】:

首先,由于日期字符串和时间字符串都是连续的(不包​​含空格),因此您不需要使用 stringstream 来解析行。您可以像这样读取日期和时间:

cin >> enter_date >> enter_time;
cin >> exit_date >> exit_time;

现在您需要将这些字符串转换为实际的日期和时间。由于两者的格式都是固定的,你可以这样写:

void parse_date(const string& date_string, int& y, int& m, int& d) {
  y = (date_string[0] - '0')*10 + date_string[1] - '0'; // YY/../..
  m = (date_string[3] - '0')*10 + date_string[4] - '0'; // ../mm/..
  d = (date_string[6] - '0')*10 + date_string[7] - '0'; // ../../dd
}

当然,这段代码有些难看,可以用更好的方式编写,但我相信这样更容易理解。有了这个函数,如何写这个应该是显而易见的:

void parse_time(const string& time_string, int& h, int &m);

现在您已经解析了日期和时间,您需要实现一个减去两个日期的方法。实际上,您关心的是从进入日期时间到退出日期时间四舍五入的小时数。我在这里建议的是,您将日期从某个初始时刻(例如 00/01/01)转换为天数,然后减去这两个值。然后将两个时间转换为自 00:00 以来的分钟数,然后再次减去它们。这不是特定于语言的,所以我相信这些提示应该足够了。再次使用一些内置库可以更轻松地完成,但我认为这不是您分配的想法。

将小时数四舍五入后,您实际上需要做的就是执行语句中的规则。这只需要几个 ifs,实际上很容易。

希望这会有所帮助。我故意不给出更详细的解释,以便您可以考虑一些事情。毕竟这是家庭作业,旨在让您思考如何去做。

【讨论】:

  • 非常感谢!我已经为此工作了好几天,你是第一个解释得足以让我理解的人。我真的很感激。
  • 这更有意义,我的导师告诉我使用 cin 不起作用,我不得不使用 getline 让我失望,谢谢你澄清它。
【解决方案3】:

您不需要执行单独的输入读取和解析操作。您可以通过引用传递必要的变量,并使用stringstream 将输入直接读入变量中。我会使用一个结构来存储日期和时间,并使用用于减去两个日期/时间值的算法重载operator-。以下是我的做法:

#include <iostream>
#include <sstream>

using namespace std;

struct DateTime {
    // Variables for each part of the date and time
    int year, month, day, hour, minute;

    // Naive date and time subtraction algorithm
    int operator-(const DateTime& rval) const {
        // Total minutes for left side of operator
        int lvalMinutes = 525600 * year
                        + 43200 * month
                        + 1440 * day
                        + 60 * hour
                        + minute;

        // Total minutes for right side of operator
        int rvalMinutes = 525600 * rval.year
                        + 43200 * rval.month
                        + 1440 * rval.day
                        + 60 * rval.hour
                        + rval.minute;

        // Subtract the total minutes to determine the difference between
        // the two DateTime's and return the result.
        return lvalMinutes - rvalMinutes;
    }
};

bool inputDateTime(DateTime& dt) {
    // A string used to store user input.
    string line;
    // A dummy variable for handling separator characters like "/" and ":".
    char dummy;

    // Read the user's input.
    getline(cin, line);
    stringstream lineStream(line);

    // Parse the input and store each value into the correct variables.
    lineStream >> dt.year >> dummy >> dt.month >> dummy >> dt.day >> dummy 
               >> dt.hour >> dummy >> dt.minute;

    // If input was invalid, print an error and return false to signal failure
    // to the caller.  Otherwise, return true to indicate success.
    if(!lineStream) {
        cerr << "You entered an invalid date/time value." << endl;
        return false;
    } else
        return true;
}

从这里开始,在main() 函数中,声明两个DateTime 结构,一个用于进入时间,一个用于退出时间。然后读入DateTime的两个,从退出时间中减去进入时间,并使用结果生成正确的输出。

【讨论】:

    猜你喜欢
    • 2014-05-08
    • 1970-01-01
    • 2015-01-01
    • 2011-05-09
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 2017-12-02
    相关资源
    最近更新 更多