Re: iostream >> string, but fixed length string - how?

Discussion in 'C++' started by cpp4ever, Apr 30, 2010.

  1. cpp4ever

    cpp4ever Guest

    On 04/30/2010 01:38 PM, Adam Nielsen wrote:
    > Hi all,
    >
    > I'd like to read a fixed number of bytes from a binary file into a
    > std::string. I have been doing this sort of thing:
    >
    > char foo[123];
    > stream.read(foo, 123);
    > std::string bar(foo);
    >
    > However I would like to use iostream operators to make the code a bit easier
    > to read, but I'm not sure how to read in a fixed length string...
    >
    > std::string foo;
    > stream >> std::setw(123) >> foo;
    >
    > Of course that doesn't work (it just reads to the first whitespace character),
    > so any suggestions would be much appreciated!
    >
    > Many thanks,
    > Adam.


    Seems a combination of what Mr V and I suggested should do the trick?

    JB
     
    cpp4ever, Apr 30, 2010
    #1
    1. Advertising

  2. cpp4ever

    cpp4ever Guest

    On 05/01/2010 05:07 AM, Adam Nielsen wrote:
    >> Seems a combination of what Mr V and I suggested should do the trick?

    >
    > Indeed. This is what I have gone with, using a const cast for simplicity but
    > which could break if compiled with an implementation of std::string that does
    > things differently: (which, if it ever happens, will at least be picked up by
    > the unit tests)
    >
    > struct fixedLength {
    > std::string& data;
    > int len;
    > fixedLength(std::string& data, int len) :
    > data(data),
    > len(len)
    > {
    > }
    > };
    >
    > std::istream& operator >> (std::istream& s, const fixedLength& n)
    > {
    > n.data.resize(n.len);
    > s.read(const_cast<char *>(n.data.c_str()), n.len);
    > return s;
    > }
    >
    > Then it can be used as:
    >
    > std::string foo;
    > stream >> fixedLength(foo, 123);
    >
    > I'll probably have to create another class for the times when I want to read
    > in the same amount of data but have the string stop at the first null.
    >
    > Thanks again both for your suggestions.
    >
    > Cheers,
    > Adam.

    Ever thought of creating a template?

    Regards

    JB
     
    cpp4ever, May 1, 2010
    #2
    1. Advertising

  3. cpp4ever

    cpp4ever Guest

    On 05/04/2010 09:55 PM, Paavo Helde wrote:
    > Stuart Golodetz <> wrote in
    > news::
    >
    >> Adam Nielsen wrote:
    >>>>> struct fixedLength {
    >>>>> std::string& data;
    >>>>> int len;
    >>>>> fixedLength(std::string& data, int len) :
    >>>>> data(data),
    >>>>> len(len)
    >>>>> {
    >>>>> }
    >>>>> };
    >>>>>
    >>>>> std::istream& operator >> (std::istream& s, const fixedLength& n)
    >>>>> {
    >>>>> n.data.resize(n.len);
    >>>>> s.read(const_cast<char *>(n.data.c_str()), n.len);
    >>>>> return s;
    >>>>> }
    >>>
    >>>> Why "const fixedLength& n"? If you're reading into it, isn't the
    >>>> implication that it's going to change? So "fixedLength& n" would
    >>>> seem more intuitive.
    >>>
    >>> That's what I thought too, but the way C++ operators seem to work it
    >>> has to be const for it to be called implicitly. I think. Actually
    >>> I'm not sure, but it didn't work without the const and it did with it
    >>> :) Maybe because you're passing in a reference to a temporary.
    >>>
    >>> But logically you're not changing the fixedLength object itself
    >>> (because the length is the same) so I think it can be const. You'll
    >>> note the std::string reference is non-const, because this sits
    >>> "outside" the fixedLength class and can be changed. I agree it may
    >>> be a little unintuitive, but like I say, it didn't work without the
    >>> const ;-)

    >>
    >> My bad, I just looked at the operator>> when I made that comment
    >> instead of looking at the usage. The issue is the old 'you can't bind
    >> a non-const reference to a temporary', yes. Ignore me!
    >>
    >>>> Also, could you write "&n.data[0]" instead of
    >>>> "const_cast<char*>(n.data.c_str())" to avoid the const_cast?
    >>>
    >>> Hmm, good idea, I'd never noticed that. I understand why operator[]
    >>> would return a non-const value, but then why would both c_str() and
    >>> data() return const values?

    >>
    >> Good question -- judging by a bit of Googling, I suspect it might be
    >> something to do with designing the interface in a way that's more
    >> convenient for copy-on-write implementations (if you return const char
    >> * from c_str() and data() then you don't need to make a copy at that
    >> point as you can assume the string won't be changed). But the honest
    >> answer is I don't know :) So if anyone else can clarify...?

    >
    > The current standard (2003) explicitly says "The program shall not alter
    > any of the values stored in the array" returned by c_str() and data().
    > The wording also seems to allow returning a pointer to a *copy* of the
    > string content. I guess this is for better support of COW and maybe also
    > for non-contiguous std::string storage (though this seems to be
    > implicitly forbidden by defining operator[] via data()[pos] (which would
    > not really work for non-const version however)).
    >
    > Thus, to avoid problems with a potential implementation using COW, one
    > should use &str[0] instead of c_str() or data(). Because of multi-
    > threading complications COW has fallen out of fashion, but better be safe
    > than sorry.
    >
    > OTOH, to my knowledge all current std::string implementations are using
    > contiguous storage and this will be explicitly mandated by the next
    > standard, so one should not worry about that point.
    >
    > hth
    > Paavo
    >
    >
    >
    >
    >
    >
    >
    >


    IMHO, unless the design of the class provides for some form of direct
    access to it's private data, rather than via it's member functions, I
    would strongly disapprove of ever trying to do so, as any change to the
    class implementation could be catastrophic!

    JB
     
    cpp4ever, May 4, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Tiger
    Replies:
    10
    Views:
    5,668
  2. ai@work
    Replies:
    9
    Views:
    569
    Ron Natalie
    Dec 16, 2004
  3. S. Nurbe

    iostream + iostream.h

    S. Nurbe, Jan 14, 2005, in forum: C++
    Replies:
    7
    Views:
    805
    red floyd
    Jan 15, 2005
  4. red floyd
    Replies:
    3
    Views:
    558
    Dietmar Kuehl
    Mar 8, 2005
  5. Victor Bazarov
    Replies:
    2
    Views:
    734
    Alf P. Steinbach
    May 3, 2010
Loading...

Share This Page