Parsing string

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • tech

    Parsing string

    Hi, I need to parse a string used to represent a time and then
    populate
    a simple time struct. The time string will always be this format

    23:45.45 ie hours separated from mins by ':' and minutes separated
    from seconds by '.'
    The string will be 8 chars in len. I've come up with some simple code
    below
    but am wondering do i really need a wstringstream and a string to do
    this. Can
    the parsing just be done with a wstringstream.

    struct TIMESTRUCT
    {
    unsigned short Hour;
    unsigned short Minute;
    unsigned short Second;
    }

    bool TimeParser(cons t std::wstring& time, TIMESTRUCT& st)
    {
    std::wistringst ream tmp;
    // a time string must be 8 chars in len
    assert(time.siz e() == 8);

    tmp.str(time.su bstr(0, 2));
    tmp >st.Hour;
    if (time[2] != ':') return false;
    tmp.clear();
    tmp.str(time.su bstr(3, 2));
    tmp >st.Minute;
    if (time[5] != '.') return false;
    tmp.clear();
    tmp.str(time.su bstr(6, 2));
    tmp >st.Second;
    return true;
    }

    int main()
    {
    TIMESTRUCT st;
    std::wstring t(L"23:34.45") ;
    TimeParser(t, st);
    return 0;
    }
  • Mirco Wahab

    #2
    Re: Parsing string

    tech wrote:
    Hi, I need to parse a string used to represent a time and then
    populate a simple time struct. The time string will always be
    this format 23:45.45 ie hours separated from mins by ':' and
    minutes separated from seconds by '.'
    The string will be 8 chars in len. I've come up with some simple code
    below but am wondering do i really need a wstringstream and a
    string to do this. Can
    the parsing just be done with a wstringstream.
    This would work with istringstream if you change
    its formal argument from
    bool TimeParser(cons t std::wstring& time, TIMESTRUCT& st)
    to bool TimeParser(cons t std::string& time, TIMESTRUCT& st)

    and the actual data from
    int main()
    {
    TIMESTRUCT st;
    std::wstring t(L"23:34.45") ;
    to std::string t("23:34.45") ;


    BTW, some people tend to do almost everythin
    in regular expressions (which will be there
    soon and are long available via boost).

    Your TimeParser would be much simpler, like:

    ...
    #include <boost/regex.hpp>
    using namespace boost;
    ...

    bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
    {
    cmatch m;
    if(regex_match( time.c_str(), m, regex("^(\\d{2} ):(\\d{2})\\.(\ \d{2})$"))) {
    st.Hour = atoi(m[1].first);
    st.Minute = atoi(m[2].first);
    st.Second = atoi(m[3].first);
    return true;
    }
    return false;
    }

    The required format "dd:dd.dd" would be checked by
    the regular expression and all would be fine.

    Regards

    M.

    Comment

    • James Kanze

      #3
      Re: Parsing string

      On Jun 25, 2:30 pm, Mirco Wahab <wa...@chemie.u ni-halle.dewrote:
      tech wrote:
      BTW, some people tend to do almost everythin
      in regular expressions (which will be there
      soon and are long available via boost).
      Your TimeParser would be much simpler, like:
      ...
      #include <boost/regex.hpp>
      using namespace boost;
      ...
      bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
      {
      cmatch m;
      if(regex_match( time.c_str(), m, regex("^(\\d{2} ):(\\d{2})\\.(\ \d{2})$"))) {
      st.Hour = atoi(m[1].first);
      st.Minute = atoi(m[2].first);
      st.Second = atoi(m[3].first);
      return true;
      }
      return false;
      }
      The required format "dd:dd.dd" would be checked by
      the regular expression and all would be fine.
      Two small nits: first, regex_match can take iterators, so you
      can just write:
      if ( regex_match( time.begin(), time.end(), m, expr ) ) ...
      And since the expression is a constant, that's how I'd write it:
      static regex const expr( "^(\\d{2}):(\\d {2})\\.(\\d{2}) $" ) ;
      (at the start of the function, before the if).

      --
      James Kanze (GABI Software) email:james.kan ze@gmail.com
      Conseils en informatique orientée objet/
      Beratung in objektorientier ter Datenverarbeitu ng
      9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

      Comment

      • tech

        #4
        Re: Parsing string

        On Jun 25, 4:37 pm, James Kanze <james.ka...@gm ail.comwrote:
        On Jun 25, 2:30 pm, Mirco Wahab <wa...@chemie.u ni-halle.dewrote:
        >
        >
        >
        >
        >
        tech wrote:
        BTW, some people tend to do almost everythin
        in regular expressions (which will be there
        soon and are long available via boost).
        Your TimeParser would be much simpler, like:
           ...
           #include <boost/regex.hpp>
           using namespace boost;
           ...
           bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
          {
           cmatch m;
           if(regex_match( time.c_str(), m, regex("^(\\d{2} ):(\\d{2})\\.(\ \d{2})$"))) {
              st.Hour   = atoi(m[1].first);
              st.Minute = atoi(m[2].first);
              st.Second = atoi(m[3].first);
              return true;
           }
           return false;
          }
        The required format "dd:dd.dd" would be checked by
        the regular expression and all would be fine.
        >
        Two small nits: first, regex_match can take iterators, so you
        can just write:
            if ( regex_match( time.begin(), time.end(), m, expr ) ) ...
        And since the expression is a constant, that's how I'd write it:
            static regex const expr( "^(\\d{2}):(\\d {2})\\.(\\d{2}) $" ) ;
        (at the start of the function, before the if).
        >
        --
        James Kanze (GABI Software)             email:james.ka. ..@gmail.com
        Conseils en informatique orientée objet/
                           Beratung in objektorientier ter Datenverarbeitu ng
        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -
        >
        - Show quoted text -
        Thanks guys but i was wondering whether i could do my simple function
        with just
        a stringstream rather with a string aswell.

        Comment

        • Mirco Wahab

          #5
          Re: Parsing string

          tech wrote:
          Thanks guys but i was wondering whether i could do my simple function
          with just a stringstream rather with a string aswell.
          I don't completely understand what you
          want and what you are trying to
          accomplish. What means:
          /with just a stringstream rather with a string aswell/

          If you only want to get rid of the w_ functions, just
          don't use them:

          bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
          {
          assert(time.siz e() == 8); // a time string must be 8 chars
          char a ,b;
          std::istringstr eam tmp(time);
          tmp > st.Hour >a > st.Minute >b >st.Second;
          return a == ':' && b == '.' ? true : false;
          }

          int main()
          {
          TIMESTRUCT st;
          std::string t("03:34.45") ;
          TimeParser(t, st);
          return 0;
          }

          But maybe there's something else?

          Regards

          M.

          Comment

          • Mirco Wahab

            #6
            Re: Parsing string

            James Kanze wrote:
            On Jun 25, 2:30 pm, Mirco Wahab <wa...@chemie.u ni-halle.dewrote:
            > bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
            > {
            > cmatch m;
            > if(regex_match( time.c_str(), m, regex("^(\\d{2} ):(\\d{2})\\.(\ \d{2})$"))) {
            > st.Hour = atoi(m[1].first);
            > st.Minute = atoi(m[2].first);
            > st.Second = atoi(m[3].first);
            > return true;
            > }
            > return false;
            > }
            >
            Two small nits: first, regex_match can take iterators, so you
            can just write:
            if ( regex_match( time.begin(), time.end(), m, expr ) ) ...
            This would require the smatch overloaded 'regex_match',
            which returns std::string objects in matches and does,
            in this case, also provide a version that uses the
            plain std::string:

            bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
            {
            using namespace boost;
            smatch m;
            static regex r("^(\\d{2}):(\ \d{2})\\.(\\d{2 })$");
            if(regex_match( time, m, r)) {
            st.Hour = atoi(m[1].str().c_str()) ;
            st.Minute = atoi(m[2].str().c_str()) ;
            st.Second = atoi(m[3].str().c_str()) ;
            return true;
            }
            return false;
            }

            The use of the smatch-overloaded regex_... requires
            an additional step to extract the resulting values,
            compare it to the original version:

            bool TimeParser(cons t std::string& time, TIMESTRUCT& st)
            {
            using namespace boost;
            cmatch m;
            if(regex_match( time.c_str(), m, regex("^(\\d{2} ):(\\d{2})\\.(\ \d{2})$"))) {
            st.Hour = atoi(m[1].first);
            st.Minute = atoi(m[2].first);
            st.Second = atoi(m[3].first);
            return true;
            }
            return false;
            }

            Which looks (imho) less cluttered.
            And since the expression is a constant, that's how I'd write it:
            static regex const expr( "^(\\d{2}):(\\d {2})\\.(\\d{2}) $" ) ;
            (at the start of the function, before the if).
            This would, of course, be better from a technical point of view
            but it costs one additional line ;-) But if you are paid for
            LOCaday ...

            Regards & thanks

            M.

            Comment

            Working...