Better way to use istream to read an ascii value into a char.

Discussion in 'C++' started by Jim Langston, May 4, 2006.

  1. Jim Langston

    Jim Langston Guest

    In one of my files I am outputting the value of a char into a human readable
    file. That is,
    char a = 123;
    std::eek:fstream CharFile( ("Players\\" + Name + ".char").c_str());
    if ( CharFile.is_open() )
    CharFile << (int) a;

    So the file has the character a stored as "123".

    That was the easy part, now comes the fun of reading it back into the char.

    I tried a number of things and finally wound up doing this:

    std::istream& operator >>( std::istream& is, char& Byte )
    {
    int temp;
    is >> temp;
    Byte = temp;
    return is;
    }

    char a;
    std::ifstream CharFile( ( "Players\\" + CharName + ".char" ).c_str());
    if ( CharFile.is_open() )
    CharFile >> a;

    You may wonder why I did that instead of just directly reading it into a
    temp int directly and assigning, the reason being I'm writing many of these
    to the file.

    is >> CChar.GM >> CChar.GMLevel >> CChar.Banned >> CChar.Jailed >>
    CChar.Muted >>
    CChar.MessageRange >> CChar.Avatar >> CChar.Map >> CChar.Pos.x >>
    CChar.Pos.y >>
    CChar.Pos.z >> CChar.X_Degrees >> CChar.Race >> CChar.Vigor >>
    CChar.Fortitude >>
    CChar.Coordination >> CChar.Agility >> CChar.Reason >> CChar.Perception >>
    CChar.Willpower >> CChar.Psychic >> CChar.Charisma >> CChar.Affinity >>
    CChar.AffinityAir >> CChar.AffinityWater >> CChar.AffinityFire >>
    CChar.AffinityEarth >> CChar.Sin;

    If I had to break this up into different calls it would be, in my opionion,
    harder to maintain.

    The thing I don't like about overriding the operator >> for a char, though,
    is if I ever want to actually write a char as a byte itself (which I don't
    think I will).

    I'm just wondering if there is a better way.

    I attempted something along the lines of:

    std::istream& ReadByteVal( std::istream& is, char& Byte ) {/**/}

    and then attempted to use it like

    is >> ReadByteVal( is, CChar.Agility ) >> ReadByteVal( is, CChar.Reason ) >>
    /**/

    but that wouldn't compile, the compiler complaining something about not
    finding a call taking an rvalue.

    Someone else came up with a horrible looking template that seems to be prone
    to errors itself. Anyone have any ideas?
     
    Jim Langston, May 4, 2006
    #1
    1. Advertising

  2. Jim Langston wrote:
    > In one of my files I am outputting the value of a char into a human readable
    > file. That is,
    > char a = 123;
    > std::eek:fstream CharFile( ("Players\\" + Name + ".char").c_str());
    > if ( CharFile.is_open() )
    > CharFile << (int) a;
    >
    > So the file has the character a stored as "123".
    >
    > That was the easy part, now comes the fun of reading it back into the char.
    >
    > I tried a number of things and finally wound up doing this:
    >
    > std::istream& operator >>( std::istream& is, char& Byte )
    > {
    > int temp;
    > is >> temp;
    > Byte = temp;
    > return is;
    > }
    >
    > char a;
    > std::ifstream CharFile( ( "Players\\" + CharName + ".char" ).c_str());
    > if ( CharFile.is_open() )
    > CharFile >> a;
    >
    > You may wonder why I did that instead of just directly reading it into a
    > temp int directly and assigning, the reason being I'm writing many of these
    > to the file.
    >
    > is >> CChar.GM >> CChar.GMLevel >> CChar.Banned >> CChar.Jailed >>
    > CChar.Muted >>
    > CChar.MessageRange >> CChar.Avatar >> CChar.Map >> CChar.Pos.x >>
    > CChar.Pos.y >>
    > CChar.Pos.z >> CChar.X_Degrees >> CChar.Race >> CChar.Vigor >>
    > CChar.Fortitude >>
    > CChar.Coordination >> CChar.Agility >> CChar.Reason >> CChar.Perception >>
    > CChar.Willpower >> CChar.Psychic >> CChar.Charisma >> CChar.Affinity >>
    > CChar.AffinityAir >> CChar.AffinityWater >> CChar.AffinityFire >>
    > CChar.AffinityEarth >> CChar.Sin;
    >
    > If I had to break this up into different calls it would be, in my opionion,
    > harder to maintain.
    >
    > The thing I don't like about overriding the operator >> for a char, though,
    > is if I ever want to actually write a char as a byte itself (which I don't
    > think I will).
    >
    > I'm just wondering if there is a better way.
    >
    > I attempted something along the lines of:
    >
    > std::istream& ReadByteVal( std::istream& is, char& Byte ) {/**/}
    >
    > and then attempted to use it like
    >
    > is >> ReadByteVal( is, CChar.Agility ) >> ReadByteVal( is, CChar.Reason ) >>
    > /**/
    >
    > but that wouldn't compile, the compiler complaining something about not
    > finding a call taking an rvalue.
    >
    > Someone else came up with a horrible looking template that seems to be prone
    > to errors itself. Anyone have any ideas?


    Any easy way would be to make your own stream:

    class my_stream
    {
    public:
    my_stream(const std::string& fn)
    : ifs_(fn.c_str())
    {
    }

    char read_byte()
    {
    int i = 0;
    ifs_ >> i;
    char c = i;
    return c;
    }

    private:
    std::ifstream ifs_;
    };

    my_stream& operator>>(my_stream& s, char& c)
    {
    c = s.read_byte();
    return s;
    }

    int main()
    {
    my_stream s("test");
    char c;
    s >> c;
    }

    Deriving from std::*istream or aggregating one depends on your design.


    Jonathan
     
    Jonathan Mcdougall, May 4, 2006
    #2
    1. Advertising

  3. Jim Langston wrote:
    > In one of my files I am outputting the value of a char into a human readable
    > file. That is,
    > char a = 123;
    > std::eek:fstream CharFile( ("Players\\" + Name + ".char").c_str());
    > if ( CharFile.is_open() )
    > CharFile << (int) a;
    >
    > So the file has the character a stored as "123".
    >
    > That was the easy part, now comes the fun of reading it back into the char.
    >
    > I tried a number of things and finally wound up doing this:
    >
    > std::istream& operator >>( std::istream& is, char& Byte )
    > {
    > int temp;
    > is >> temp;
    > Byte = temp;
    > return is;
    > }
    >
    > char a;
    > std::ifstream CharFile( ( "Players\\" + CharName + ".char" ).c_str());
    > if ( CharFile.is_open() )
    > CharFile >> a;


    [snip]

    > The thing I don't like about overriding the operator >> for a char, though,
    > is if I ever want to actually write a char as a byte itself (which I don't
    > think I will).
    >
    > I'm just wondering if there is a better way.
    >
    > I attempted something along the lines of:
    >
    > std::istream& ReadByteVal( std::istream& is, char& Byte ) {/**/}
    >
    > and then attempted to use it like
    >
    > is >> ReadByteVal( is, CChar.Agility ) >> ReadByteVal( is, CChar.Reason ) >>
    > /**/
    >
    > but that wouldn't compile, the compiler complaining something about not
    > finding a call taking an rvalue.
    >
    > Someone else came up with a horrible looking template that seems to be prone
    > to errors itself. Anyone have any ideas?


    Wrap a char reference in a user defined type and define operator>> for
    this type:

    #include <iostream>

    struct achar
    {
    achar(char &c) : c_(c) {}
    char &c_;
    };

    std::istream &
    operator>>(std::istream &is, achar a)
    {
    int tmp;
    is >> tmp;
    a.c_ = tmp;
    return is;
    }

    int
    main()
    {
    char c;
    std::cin >> achar(c);
    std::cout << c << std::endl;
    }
     
    Markus Schoder, May 4, 2006
    #3
  4. Jim Langston

    Jim Langston Guest

    "Markus Schoder" <> wrote in message
    news:...
    > Jim Langston wrote:
    >> In one of my files I am outputting the value of a char into a human
    >> readable
    >> file. That is,
    >> char a = 123;
    >> std::eek:fstream CharFile( ("Players\\" + Name + ".char").c_str());
    >> if ( CharFile.is_open() )
    >> CharFile << (int) a;
    >>
    >> So the file has the character a stored as "123".
    >>
    >> That was the easy part, now comes the fun of reading it back into the
    >> char.
    >>
    >> I tried a number of things and finally wound up doing this:
    >>
    >> std::istream& operator >>( std::istream& is, char& Byte )
    >> {
    >> int temp;
    >> is >> temp;
    >> Byte = temp;
    >> return is;
    >> }
    >>
    >> char a;
    >> std::ifstream CharFile( ( "Players\\" + CharName + ".char" ).c_str());
    >> if ( CharFile.is_open() )
    >> CharFile >> a;

    >
    > [snip]
    >
    >> The thing I don't like about overriding the operator >> for a char,
    >> though,
    >> is if I ever want to actually write a char as a byte itself (which I
    >> don't
    >> think I will).
    >>
    >> I'm just wondering if there is a better way.


    <snip>

    > Wrap a char reference in a user defined type and define operator>> for
    > this type:
    >
    > #include <iostream>
    >
    > struct achar
    > {
    > achar(char &c) : c_(c) {}
    > char &c_;
    > };
    >
    > std::istream &
    > operator>>(std::istream &is, achar a)
    > {
    > int tmp;
    > is >> tmp;
    > a.c_ = tmp;
    > return is;
    > }
    >
    > int
    > main()
    > {
    > char c;
    > std::cin >> achar(c);
    > std::cout << c << std::endl;
    > }


    Ahh, perfect, thanks! I'm sure you meant
    std::istream &
    operator>>(std::istream &is, achar& a)
     
    Jim Langston, May 6, 2006
    #4
  5. Jim Langston

    Jim Langston Guest

    "Jim Langston" <> wrote in message
    news:p0_6g.623$...
    > "Markus Schoder" <> wrote in message
    > news:...

    [big snip]
    >> Wrap a char reference in a user defined type and define operator>> for
    >> this type:
    >>
    >> #include <iostream>
    >>
    >> struct achar
    >> {
    >> achar(char &c) : c_(c) {}
    >> char &c_;
    >> };
    >>
    >> std::istream &
    >> operator>>(std::istream &is, achar a)
    >> {
    >> int tmp;
    >> is >> tmp;
    >> a.c_ = tmp;
    >> return is;
    >> }
    >>
    >> int
    >> main()
    >> {
    >> char c;
    >> std::cin >> achar(c);
    >> std::cout << c << std::endl;
    >> }

    >
    > Ahh, perfect, thanks! I'm sure you meant
    > std::istream &
    > operator>>(std::istream &is, achar& a)


    I guess I was wrong on this. I tried it with the achar& a and the compiler
    warned about converting an achar a to an achar& a on a non constant
    variable. So I put it the way you had it and it seems to work (compiled,
    only one warning about achar not being able to have an assigment oporator
    generated) but not tested. Thanks again.
     
    Jim Langston, May 6, 2006
    #5
  6. Jim Langston wrote:
    > "Jim Langston" <> wrote in message
    > news:p0_6g.623$...
    > > "Markus Schoder" <> wrote in message
    > > news:...

    > [big snip]
    > >> Wrap a char reference in a user defined type and define operator>> for
    > >> this type:
    > >>
    > >> #include <iostream>
    > >>
    > >> struct achar
    > >> {
    > >> achar(char &c) : c_(c) {}
    > >> char &c_;
    > >> };
    > >>
    > >> std::istream &
    > >> operator>>(std::istream &is, achar a)
    > >> {
    > >> int tmp;
    > >> is >> tmp;
    > >> a.c_ = tmp;
    > >> return is;
    > >> }
    > >>
    > >> int
    > >> main()
    > >> {
    > >> char c;
    > >> std::cin >> achar(c);
    > >> std::cout << c << std::endl;
    > >> }

    > >
    > > Ahh, perfect, thanks! I'm sure you meant
    > > std::istream &
    > > operator>>(std::istream &is, achar& a)

    >
    > I guess I was wrong on this.


    Note that achar takes the char by reference, not by value. So whether
    achar itself is passed by value or reference does not matter.

    > I tried it with the achar& a and the compiler
    > warned about converting an achar a to an achar& a on a non constant
    > variable.


    In the statement

    std::cin >> achar(c);

    "achar(c)" constructs an rvalue which cannot be bound to a non-const
    reference. You must either pass it by value or by const reference.


    Jonathan
     
    Jonathan Mcdougall, May 6, 2006
    #6
    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. Earl Teigrob
    Replies:
    3
    Views:
    8,993
    Earl Teigrob
    Jan 6, 2004
  2. Steve
    Replies:
    6
    Views:
    3,694
    Steve
    May 13, 2004
  3. lovecreatesbeauty
    Replies:
    1
    Views:
    1,098
    Ian Collins
    May 9, 2006
  4. Replies:
    1
    Views:
    462
    Daniel Kay
    Sep 4, 2006
  5. xmllmx
    Replies:
    5
    Views:
    597
    Jorgen Grahn
    Jun 15, 2010
Loading...

Share This Page