Thread: Vector of Structure

  1. #31
    Registered User
    Join Date
    Feb 2010
    Posts
    67
    I just looked up a tutorial and saw

    "These [operator] functions return a reference to the stream object so that these operators can be chained together ( e.g. cout << "the answer is" << i << endl; )"

    Should I put references on the intstr object?
    Code:
    ostream &operator<<(ostream &output, IntStr &intstr)
    and
    Code:
    istream &operator>>(istream &input, IntStr &intstr)
    ?

    Thanks
    Last edited by CPlus; 08-15-2010 at 04:32 AM.

  2. #32
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Since it's outside the class, obviously you must specify the instance of whose member you are referring to. Yes, they should be outside the class and friends.

    Yes, it is incorrect because it lacks a reference. Also add references to << and use const correctness. Otherwise you cause unnecessary overhead.

    typeid would only see your struct, not what it contains. And typeid is bad anyway. Plus what the name() returns is not standard either, so it's unportable, as well.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #33
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by CPlus View Post
    Oh I was hoping to relate to the mTypeInfo within the class. Overloading operators must be done outside of the class and referred to with friend, right?

    If I ignored inputs for now, how could I make it so that it outputs a string or int within the union depending on the type?
    Would I use
    typeid().name()
    or would that simply return a union type?

    Thanks.
    If I could have used run time type identification on a union, I would have, but you won't get what you want. The union interprets the same area of memory as a value of some type, depending on the member you access. This means that if the expression of typeid is the union variable, it will be of union type, if you access mInt, for example, it will be interpreted as an int even if it doesn't make sense. Hence, we make the internal representation private and keep track of the type ourselves.

    If you must have stream operators, then I would define a public access method that returns the type information someway. I don't use idioms when they don't work for me, though.
    Last edited by whiteflags; 08-15-2010 at 10:19 AM.

  4. #34
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Now why return a string with its type, though? Why wouldn't an integer value be better?
    Is there also not a typo in your code? You're lacking one "?". I'd also make it a switch seeing as it nests two ifs. But that's a style issue.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #35
    Registered User
    Join Date
    Feb 2010
    Posts
    67

    Post

    Thanks guys. Okay this is what I have so far:

    Code:
    class IntStr
    {
        private:
            typedef enum { INTEGER, STRING, UNION } MyType; //INTEGER, STRING, UNION are defined into MyType
            MyType mTypeInfo; //mTypeInfo is declared as a MyType
        
            union IntStrTag {  //a union is declared
                const char *mStr; //consisting of a pointer to a string
                int mInt; //and an integer
            } mIntStr; //the union is then named mIntStr
    
        public:
            //First constructor
            IntStr ()
            {
                mTypeInfo = UNION;
            }
            
            //Second constructor
            void SetInt (int init)
            {
                mTypeInfo = INTEGER;
                mIntStr.mInt = init;
                return ;
            }
            IntStr (int init)
            {
                SetInt (init);
            }
        
            //Third constructor
            void SetString (const char *init)
            {
                mTypeInfo = STRING;
                mIntStr.mStr = init;
                return ;
            }
            IntStr (const char* init)
            {
                SetString (init);
            }
    
            //GetInt and GetString are defined
    
            bool GetInt (int &retval)
            {
                if (mTypeInfo == INTEGER)
                {
                    retval = mIntStr.mInt;
                    return false;
                }
                else if (mTypeInfo == STRING)
                {
                    std::istringstream conv;
                    conv.str(mIntStr.mStr);
                    int temp;
                    conv >> temp;
                    if (conv)
                    {
                        SetInt (temp);
                        retval = mIntStr.mInt;
                        return false;
                    }
                    else { return true; }
                }
                else{ return true; }
            }
    
            bool GetString (const char *&retval)
            {
                if (mTypeInfo == STRING)
                {
                    retval = mIntStr.mStr;
                    return false;
                }
                else if (mTypeInfo == INTEGER)
                {
                    std::ostringstream conv;
                    conv << mIntStr.mInt;
                    if (conv)
                    {
                        SetString (conv.str().c_str());
                        retval = mIntStr.mStr;
                        return false;
                    }
                    else { return true; }
                }
                else { return true; }
            }
    
        // I/O friends are declared
        friend istream& operator >> (istream &input , IntStr &intstr);
        friend ostream& operator << (ostream &output , const IntStr &intstr);
    };
    
    istream& operator >> (istream &input , IntStr &intstr)
    {
        input >> intstr;
        return input;
    }
    ostream& operator << (ostream &output , const IntStr &intstr)
    {
        output << intstr;
        return output;
    }
    
    int main()
    {
        IntStr sample1_; //no error
        IntStr sample2_; //no error
        sample1_ = 123; //no error
        sample2_ = "abc"; //no error
        cout << sample1_ << endl; //run-time error here
        cout << sample2_ << endl; //run-time error here
        cin.get(); //pause to see console results
    }
    This compiles correctly.
    I get a run-time error starting at 'cout'. I think I messed up the I/O again, but I made sure to add const on the ostream as Elysia pointed out.
    To see if I understand: a union type contains enough memory for each type it unifies and can be treated as any type at any time?
    If not, do I have to specify which part of the memory I want inside the union to be represented at runtime? Or is this handled inside of the class?
    Sorry just trying to understand. If I have to specify it with .mInt or .mStr , then maybe I would have to include that information within the stream operator overloads right?


    At least it compiles when the union type is defined as an int or a string, so that's good.
    I just have to find a way to do I/O on the union class type.
    I'm still learning but I'll study up on WhiteFlag's mention of public access methods.

    Thanks guys

  6. #36
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I get a run-time error starting at 'cout'. I think I messed up the I/O again
    Your code for this is:
    Code:
    istream& operator >> (istream &input , IntStr &intstr)
    {
        input >> intstr;
        return input;
    }
    ostream& operator << (ostream &output , const IntStr &intstr)
    {
        output << intstr;
        return output;
    }
    The way you did it before is closer to what you needed. When you write this kind of code you shouldn't send things to a stream that it doesn't know how to handle. That said, remember that I said I don't use idioms when they don't work for me?

    You can already do this:
    Code:
    if (!sample.GetInt(foo)) cout << foo;
    
    string bar;
    cin >> bar;
    /* copy bar to some new C string qux here */
    if (!sample.SetString(qux)) /* do something */
    A method that does this is not hard.

    To see if I understand: a union type contains enough memory for each type it unifies and can be treated as any type at any time?
    If not, do I have to specify which part of the memory I want inside the union to be represented at runtime? Or is this handled inside of the class?
    As I said, we keep track of the type inside the class. The fact that you can treat a union as any one type it contains at a time is the idea. In an assignment, it will put the value in its memory, which is as big in size as the largest type it contains. If you don't manage it things will become mystified quickly.

    Again, for the moment, IntStr does not clean up qux when it changes types or dies. This is also problem. Unions are basically something C++ shouldn't have, because they don't work with other objects, only plain data types. I even spoke against doing exactly this, but whatever I guess. Make sure IntStr deletes strings whenever it changes types or dies.
    Last edited by whiteflags; 08-15-2010 at 01:01 PM.

  7. #37
    Registered User
    Join Date
    Feb 2010
    Posts
    67
    Where does the 'foo' come from? I see the 'bar' declared for the string.

    Thanks

  8. #38
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    It should be self-explanatory that it is an int.
    But this is getting awfully complicated. I really suggest you ditch this idea or use boost. You already have a solution for your needs. Use it.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 05-18-2010, 04:14 AM
  2. Problem Passing Structure Reference To Function
    By soj0mq3 in forum C Programming
    Replies: 9
    Last Post: 04-24-2010, 10:27 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Serial Communications in C
    By ExDigit in forum Windows Programming
    Replies: 7
    Last Post: 01-09-2002, 10:52 AM
  5. C structure within structure problem, need help
    By Unregistered in forum C Programming
    Replies: 5
    Last Post: 11-30-2001, 05:48 PM

Tags for this Thread