5

I want to convert a string time stamp formatted in HH:MM:SS to seconds only, and then compare it with a number. I have written a prime version of my code in Java, however I separately ask from Scanner as opposed to having a string time. I'm not much familiar with C++ libraries, as I'm a Java guy. Wondering how I can do it in C++?

Make it brief, String s = "1:01:01"; and String s2= "3600"; I need to know if (s>s2)

import java.util.*;

public class Test {
    public static void main(String[] args) {
        Scanner console = new Scanner(System.in);

        int hours;
        int mins;
        int secs;

        System.out.println("Enter Hours: ");
        hours = console.nextInt();

        System.out.println("Enter Minutes: ");
        mins = console.nextInt();

        System.out.println("Enter Seconds: ");
        secs = console.nextInt();

        int showSecs = (hours * 3600) + (mins * 60) + secs;

        System.out.println(hours + ":" + mins + ":" + secs + " in secs are "
                + showSecs);

    }
}
Tina J
  • 4,983
  • 13
  • 59
  • 125

3 Answers3

10

I'll risk the downvotes and remind you that we still have sscanf in our toolbox.

int h, m, s= 0;
std::string time ="10:40:03"

if (sscanf(time.c_str(), "%d:%d:%d", &h, &m, &s) >= 2)
{
  int secs = h *3600 + m*60 + s;
}
Roddy
  • 66,617
  • 42
  • 165
  • 277
4

As @ghostofstandardspast suggested you can use the std::get_time() I/O manipulator to read a specific time format from a std::istream

#include <iostream>
#include <sstream>
#include <locale>
#include <iomanip>
#include <ctime>

int main() {
    std::tm t;
    std::istringstream ss("1:01:01");
    ss >> std::get_time(&t, "%H:%M:%S");
    std::cout << "Total seconds: " 
              << t.tm_hour * 3600 + t.tm_min * 60 + t.tm_sec 
              << std::endl;
}

Here's a fully working sample using clang. Unfortunately I couldn't get this sample running using GCC 4.8.x, I'd guess it's not complete in this implementation. May be GCC 4.9.x supports this correctly.


As looking for an alternative (if you can't use a compiler supporting the complete current standard actually), you may either consider to use std::sscanf() as @Roddy suggested, or split the string using ':' as delimiter character, and simply convert the split out parts to integer values, using the e.g. the atoi() method.
Here's the alternative

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

std::vector<std::string> &split
    ( const std::string &s
    , char delim
    , std::vector<std::string> &elems) 
{
    std::istringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}

int main() {
    std::vector<std::string> parts;
    split("1:01:01",':',parts);
    if(parts.size() == 3) {
        int hour = std::atoi(parts[0].c_str());
        int min = std::atoi(parts[1].c_str());
        int sec = std::atoi(parts[2].c_str());
        std::cout << "Total seconds: " 
                  << hour * 3600 + min * 60 + sec 
                  << std::endl; 
    }
    return 0;
}
Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

Let's do a simple automaton that parse your string:

#include <string>

int string2sec(const std::string& str) {
  int i = 0;
  int res = -1;
  int tmp = 0;
  int state = 0;

  while(str[i] != '\0') {
    // If we got a digit
    if(str[i] >= '0' && str[i] <= '9') {
      tmp = tmp * 10 + (str[i] - '0');
    }
    // Or if we got a colon
    else if(str[i] == ':') {
      // If we were reading the hours
      if(state == 0) {
        res = 3600 * tmp;
      }
      // Or if we were reading the minutes
      else if(state == 1) {
        if(tmp > 60) {
          return -1;
        }
        res += 60 * tmp;
      }
      // Or we got an extra colon
      else {
        return -1;
      }

      state++;
      tmp = 0;
    }
    // Or we got something wrong
    else {
      return -1;
    }
    i++;
  }

  // If we were reading the seconds when we reached the end
  if(state == 2 && tmp < 60) {
    return res + tmp;
  }
  // Or if we were not, something is wrong in the given string
  else {
    return -1;
  }
}

This has not been tested so there is no warranties.

EDIT: I still can not promise anything but I ran quick tests and it seems to work properly as expected.

#include <iostream>
int main(int argc, char** argv) {
  (void) argc;
  (void) argv;

  std::cout << string2sec("0:2:0") << std::endl;
  std::cout << string2sec("1:0:0") << std::endl;
  std::cout << string2sec("1:2:0") << std::endl;
  std::cout << string2sec("10:10:10") << std::endl;
  return 0;
}

Output:

120
3600
3720
36610
Elioty
  • 81
  • 6
  • [At least the result `208140` for `"1:01:01"` is obviously wrong](http://ideone.com/V1VbFa)! (so much for untested code ...) – πάντα ῥεῖ Jun 17 '14 at 18:15
  • 1
    You definitely did not see my latest update... No need to be mean. – Elioty Jun 17 '14 at 18:19
  • Yes I've been checking the code you've posted before your update, but [results are still not correct](http://ideone.com/V1VbFa), now it yields 3660! :P ... May be next time you test 1st and post afterwards! – πάντα ῥεῖ Jun 17 '14 at 18:21
  • I said there was no warranties... And I see where is the problem, going to fix it. – Elioty Jun 17 '14 at 18:32
  • _'No need to be mean.'_ It's got nothing to do with being _'mean'_, wrong answers are wrong and get downvoted. I retracted my downvote after you had corrected your answer (in 2 iterations!) ... – πάντα ῥεῖ Jun 17 '14 at 19:18