1

So, I have to make the following program:

I input two "clocks", in format HH:MM, and I have to check the difference between them in minutes and output it. Then I have to check which time has bigger size, in minutes, and output which time is bigger or if they are equal.

So, I've done this:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
    string a, b, c, d;
    int a_min, b_min;

    getline(cin, a, ':');
    cin >> b;

    getline(cin, c, ':');
    cin >> d;

    a_min = atoi(a.c_str()) * 60 + atoi(b.c_str());

    b_min = atoi(c.c_str()) * 60 + atoi(d.c_str());

    if (a_min > b_min){
        cout << "Razlikata iznesuva " << a_min - b_min << " minuti" << endl;
        cout << "Pogolemo e prvoto vreme" << endl;
    }
    else if (b_min > a_min){
        cout << "Razlikata iznesuva " << b_min - a_min << " minuti" << endl;
        cout << "Pogolemo e vtoroto vreme" << endl;
    }
    else if (a_min == b_min){
        cout << "Vreminjata se isti" << endl;
    }
    return 0;
}

But when you input HH:MM, I have a ":" between the HH and MM, therefore I can't get the numbers simply, so I need help how to get hours and minutes and convert them (conversion should be easy I guess) or if there's alternative and better method for this?

user2699298
  • 1,446
  • 3
  • 17
  • 33

3 Answers3

2
  1. You should be reading NUMBERS, not strings. Numbers are read until non-digit, so will stop at ::

    char dummy;
    int hour, minute;
    cin >> hour >> dummy >> minute;
    // check dummy == ':'
    
  2. Strings are read until whitespace. And the whitespace is not skipped unless you've set skipws. However there is a function that allows reading string until specific separator:

    string hour, minute;
    getline(cin, hour, ':'); // this will eat the `:`
    cin >> minute; // assuming whitespace or eof after this
    // check the values, that you didn't cross eof and such.
    
Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • ok, so here's what I tried: `string a, b, a_min, b_min; char c; getline(cin, a, ':'); cin >> c >> b; cout << a << " " << b;` And for input 12:33, I get only a=12, b=3, one number in b is skipped for some reason. – user2699298 Oct 21 '13 at 14:33
  • @user2699298: ... of course; sorry, getline will eat the `:`. – Jan Hudec Oct 21 '13 at 14:37
  • @user: Get rid of `dummy`, the `getline` specification says "the delimiter character is extracted from input, but is not appended to str" – Ben Voigt Oct 21 '13 at 14:37
  • @BenVoigt: Yes, I noticed. – Jan Hudec Oct 21 '13 at 14:38
  • I managed to get it working now, I'll try to finish the program with this for now. Let's see how it goes! :) – user2699298 Oct 21 '13 at 14:44
  • It's not enough to check only `dummy`. You also have to check that `hour` is in interval [0, 24) and `minute` is in interval [0, 60). – Marius Bancila Oct 22 '13 at 11:28
1

Use a std::istringstream to do the parsing for you; this expects time stamps in 24-hours format:

static unsigned int minutesSinceMidnight( const std::string &timeStamp )
{
    unsigned int hours, minutes;
    char colon;
    std::istringstream( timeStamp ) >> hours >> colon >> minutes;
    return hours * 60 + minutes;
}

You can then compare two time stamps easily and also tell how many minutes they are apart.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207
  • Why don't you do the parsing on `cin` directly? All streams have the same capabilities! – Jan Hudec Oct 21 '13 at 14:25
  • 2
    @JanHudec: Not using `std::cin` greatly simplifies testing the code (if I wanted to support *all* kinds of streams, I'd probably have used `std::istream` directly). Maybe this is just the Haskell mindset in me, but I try to separate the code doing IO from the code which purely transforms arguments into a return value. – Frerich Raabe Oct 21 '13 at 14:31
  • Yes, getting an istream as argument would be the most sensible way. Easy to test and easy to apply directly to input. But this is just unnecessarily longer. – Jan Hudec Oct 21 '13 at 14:36
  • So, I want to implement this code without usage of functions and here is my code and I get an error. `string a, b, a_min, b_min; cin >> a >> b; unsigned int casovi, minuti; char c; istringstream ( a ) >> casovi >> c >> minuti; a_min = casovi * 60 + minuti; cout << a_min;` and the error I get is: invalid use of incomplete type 'struct std::istringstream for istringstream function. – user2699298 Oct 21 '13 at 14:37
  • @user2699298: Make sure to `#include ` – Frerich Raabe Oct 21 '13 at 14:38
  • I did it, and here's the code: `string a, a_min; cin >> a; unsigned int hours, minutes; char c; istringstream ( a ) >> hours >> minutes; a_min = hours * 60 + minutes; cout << a_min; return 0;` but I get some weird characters as results. – user2699298 Oct 21 '13 at 14:42
0

Something like this:

int h,m;
char separator;
cin >> h >> separator >> m;
if(separator == ':' && h>=0 && h < 24 && m >=0 && m < 60)
{
  // you have a correct hour
}
Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
  • Well, I guess there has to be space in this case? And is it possible to use operator >, < etc with string? – user2699298 Oct 21 '13 at 14:15
  • You're right, regex does the job here, but unfortunately I haven't learned it yet, so I need alternative option like strings / chars if possible. – user2699298 Oct 21 '13 at 14:18
  • 3
    This won't fly. If you read the hours and minutes directly as numbers, they'd stop on any character. But strings won't. The first string will eat it all, IIRC the separator will get the newline and the last string will get nothing. – Jan Hudec Oct 21 '13 at 14:18
  • that was just a slip from copying from the original post. things like `h>=0 && h < 24` would not work if h was a `string` – Marius Bancila Oct 21 '13 at 14:37