Thread: Assigning the content of one map to another map and doing the same with vector

  1. #31
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Hmm...weird. It did become "not good" after inserting into a string from the stringstream, but it didn't do so with inserting an int into the stringstream. The statement I made earlier about checking to see if it was good() after using the operator >> wasn't exactly true, come to find out. I was checking it in one block of code, I think, but I wasn't checking it everywhere. I changed the code to check to see if stringstream::good() returned false after inserting into a string, and it did (apparently in all cases too). The weird thing is, even though, some error bit (not sure which one) was set to true, the "currentEnumeratorValue_s" string still ended up with the right value, so it outputted the right thing to file.

    EDIT: I'm thinking it was probably the "badbit". I'm going to change the code to use the bad() function instead, and see if I'm right.
    Last edited by Programmer_P; 07-12-2010 at 08:58 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  2. #32
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Nope. Its not the badbit. It must be either failbit or eofbit.

    EDIT: Its eofbit. I guess you can't use >> when the eofbit has been set. clear() resets those flags, which is why it worked.
    Last edited by Programmer_P; 07-12-2010 at 09:17 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  3. #33
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Programmer_P View Post
    Maybe its a compiler specific issue then? I'm using GCC. What compiler are you using?
    I'm about to try to compile your code in my compiler and see if I get the same results.

    At any rate, clearing the stringstream after each operation in the loops fixed the problem (note that I call clear() after using both the << and >> operators). I don't know why, but it did.

    EDIT: Hmm...I got the same results you did.
    It's not that something is wrong with the compiler or the streams you are using. In fact, pianorain's program is doing what it is supposed to do. I believe he is trying to point out your misuse, and your willingness to blame it on external factors, in a passive agressive way.

    The problem is you, not your tools.

    Quote Originally Posted by Programmer_P View Post
    I thought cout outputs whatever argument was passed to its parameter, and then clears itself.

    An output like this:

    Code:
    int num = 10;
    cout<< "You suck this amount of times: "  << num << endl;
    I thought would first output the string, clear itself, output the number, clear itself, and then finally output the endl and clear itself. If it appends it, then why does using later cout statements without explicitly clearing the stream only output the new arguments being passed to cout?
    I will try to make sense of the madness.

    Specifically, there are two kinds of streams: sources, and sinks. Sources are the kind of stream that have all the data you ever need, you just have to extract from it. Sinks can take anything in and put it somewhere else, like how water is the universal solvent and flows to the oceans, or tap water to the sewers. An example of a sink stream is cout.

    cout itself has a default way of operating. It will print your lines at once, because it is line buffered. This means that you can break up a long cout statement however you want, but cout will be as big as it needs to be to hold a single line. To display the line, you flush it with endl;

    cout << "My rage burns with the power of " << 1000000L << " suns!" << endl;

    But the point is, now we know the terms sink and source. A stringstream can be used either way. When you use it as a source, you're usually not happy with the stream's state because you forget what the stream already has: what you put into it when it was acting like a sink.

    Every character is important to the stream. Either you will extract everything and set the stream pointer to indicate a state of emptiness though the interface (operator>>), or you will discard the stream itself and... set the stream pointer to indicate emptiness, through the interface (e.g. clear() ).

    My conclusion is, you need to find a default way of operating, like cout, yourself. Maybe you can parse smarter so that it is impossible to be confused like you are in this thread. After all, enums have a defined syntax. There are a number of quick fixes, like clearing exactly where you need to, but I think you need to give real attention to the algorithm.

    I mean, I sort of get what it takes to parse an enum:

    Find and store an enum keyword.
    Find and store an optional identifier.
    Counted the opening brace.
    Recursively parse the constant=value, expression
    Balance the closing brace.
    Find a sequence point ( ';' ).

    If you put a whole enum into a stringstream, expect to take all of it back out. Or divide it into parts elsewhere, and feed that to a string stream, and take it back out.
    Last edited by whiteflags; 07-12-2010 at 09:28 PM. Reason: Now with color!

  4. #34
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by whiteflags View Post
    It's not that something is wrong with the compiler or the streams you are using. In fact, pianorain's program is doing what it is supposed to do. I believe he is trying to point out your misuse, and your willingness to blame it on external factors, in a passive agressive way.

    The problem is you, not your tools.
    Wow! This post made me crack up and laugh.
    No offense intended.
    I will try to make sense of the madness.

    Specifically, there are two kinds of streams: sources, and sinks. Sources are the kind of stream that have all the data you ever need, you just have to extract from it. Sinks can take anything in and put it somewhere else, like how water is the universal solvent and flows to the oceans, or tap water to the sewers. An example of a sink stream is cout.

    cout itself has a default way of operating. It will print your lines at once, because it is line buffered. This means that you can break up a long cout statement however you want, but cout will be as big as it needs to be to hold a single line. To display the line, you flush it with endl;

    cout << "My rage burns with the power of " << 1000000L << " suns!" << endl;
    I LOLed when I read this comment in particular. Its even funnier because I have actually felt that way before...
    But the point is, now we know the terms sink and source. A stringstream can be used either way. When you use it as a source, you're usually not happy with the stream's state because you forget what the stream already has: what you put into it when it was acting like a sink.

    Every character is important to the stream. Either you will extract everything and set the stream pointer to indicate a state of emptiness though the interface (operator>>), or you will discard the stream itself and... set the stream pointer to indicate emptiness, through the interface (e.g. clear() ).

    My conclusion is, you need to find a default way of operating, like cout, yourself. Maybe you can parse smarter so that it is impossible to be confused like you are in this thread. After all, enums have a defined syntax. There are a number of quick fixes, like clearing exactly where you need to, but I think you need to give real attention to the algorithm.

    I mean, I sort of get what it takes to parse an enum:

    Find and store an enum keyword.
    Find and store an optional identifier.
    Counted the opening brace.
    Recursively parse the constant=value, expression
    Balance the closing brace.
    Find a sequence point ( ';' ).
    My algorithm does it a little differently, but I wont get into exactly how it works here. If you're interested, feel free to check out the code once I post the next version of ConvertEnumToStrings. And I'm not confused. As a matter of fact, the program is working now.
    If you put a whole enum into a stringstream, expect to take all of it back out. Or divide it into parts elsewhere, and feed that to a string stream, and take it back out.
    I don't put the whole enum into a stringstream. Instead, I put each enumerator value of an enum into a stringstream, since I need to convert it to a string so I can add it to the output string. And yes, of course I take it back out of the stringstream. Otherwise, there wouldn't be any point of putting them in the stringstream to begin with.
    Last edited by Programmer_P; 07-12-2010 at 10:12 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  5. #35
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    And I'm not confused.
    I giggle every time I read that.

    Soma

  6. #36
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by phantomotap View Post
    I giggle every time I read that.

    Soma
    Keep giggling like a little girl then.
    Hell, I crack myself up all the time. What do I care if other people laugh at me too?
    Last edited by Programmer_P; 07-12-2010 at 10:08 PM.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  7. #37
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I intend to... as long as it is funny.

    Soma

  8. #38
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Programmer_P View Post
    Wow! This post made me crack up and laugh.
    No offense intended.

    I LOLed when I read this comment in particular. Its even funnier because I have actually felt that way before...
    It's good that you can laugh at yourself, and stuff.

    My algorithm does it a little differently, but I wont get into how exactly it works here. If you're interested, feel free to check out the code once I post the next version of ConvertEnumToStrings. And I'm not confused. As a matter of fact, the program is working now.

    I don't put the whole enum into a stringstream. Instead, I put each enumerator value of an enum into a stringstream, since I need to convert it to a string so I can add it to the output string. And yes, of course I take it back out of the stringstream. Otherwise, there wouldn't be any point of putting them in the stringstream to begin with.
    Not to get abrasive, but knowing how your algorithm works is not my goal. We need to stick to defined teacher-pupil roles.

    Just because your program works, does not mean my point is less lost on you. It would be my fault if it was, for I have not explained clearly. It would probably be your fault to, if you didn't make an effort to understand. Now if you know why your program works, you'll have an easier time finding the root of the next mistake.

    I think, though you wont acknowledge, that you understand how stringstreams work now?

  9. #39
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by whiteflags View Post
    \Now if you know why your program works, you'll have an easier time finding the root of the next mistake.

    I think, though you wont acknowledge, that you understand how stringstreams work now?
    Yes, I know why my program works now.
    Its because I call clear() on the stringstream every time I'm done with it, so next time I use it, I have a fresh start with it. I don't really need to know the fine details of the "why" and "how" it works, so long as I remember that I need to call clear() on any other stringstream that I make in the future, so I wont make the same mistake again.

    And yes, I understand how stringstreams work now, even though I still think its kind of lame that the << operator appends to existing data instead of replaces. For appending, a better operator to use would be the "+=" operator. That way its more clearer that its appending.
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

  10. #40
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Programmer_P
    And yes, I understand how stringstreams work now, even though I still think its kind of lame that the << operator appends to existing data instead of replaces. For appending, a better operator to use would be the "+=" operator. That way its more clearer that its appending.
    Choice of operators to overload can sometimes be rather subjective. In fact, I have read a piece critical of the overloading of operator>> and operator<< for input/output streams for this very reason.

    If you are familiar with code that chains operators like this:
    Code:
    std::string name("Programmer_P");
    std::cout << "Hello " << name;
    then it should be natural to accept that operator<< is overloaded to append, not replace, since you would know that after "Hello " is printed, "Programmer_P" is then appended to the output. If we use your suggestion, it would then be:
    Code:
    std::cout += "Hello " += name;
    This could work too, since it is a matter of interpretation, though care would have to be paid concerning the change in precedence.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #41
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I still think its kind of lame that the << operator appends to existing data instead of replaces.
    The standard streams are designed with "OOP" in mind as a representation of stream devices. (This as opposed to block devices.) They can't "replace" by definition.

    For appending, a better operator to use would be the "+=" operator.
    What would you use for "extraction" if you had used "+=" as "insertion"? I'm here to tell you that "-=" would be incredibly stupid.



    In fact, I have read a piece critical of the overloading of operator>> and operator<< for input/output streams for this very reason.
    It is not as subjective as people would like to believe. The only operators with parity that logically maintain the "read order" in processing are the "stream operators" ("<<" and ">>"). (I'm ignoring the possibility of overloading the comparison operators for this purpose because we still may need to compare the result of such chaining.)

    This could work too, since it is a matter of interpretation, though care would have to be paid concerning the change in precedence.
    WTF!?

    It could not work. You could not "chain" the operators. It is not an issue of precedence. It is an issue of associativity. And wrapping the expression in countless parentheses doesn't count!

    Soma

    Code:
    struct test1_1
    {
    };
    
    struct test1_2
    {
    };
    
    struct test2_1
    {
    };
    
    struct test2_2
    {
    };
    
    #include <iostream>
    
    test1_1 & operator +=
    (
       test1_1 & fLHS
     , const test1_2 & fRHS
    )
    {
       std::cout << "test1_1 & operator += (const test1_1 &, const test1_2 &)" << '\n';
       return(fLHS);
    }
    
    test1_2 & operator +=
    (
       test1_2 & fLHS
     , const test1_2 & fRHS
    )
    {
       std::cout << "test1_2 & operator += (const test1_2 &, const test1_2 &)" << '\n';
       return(fLHS);
    }
    
    test2_1 & operator <<
    (
       test2_1 & fLHS
     , const test2_2 & fRHS
    )
    {
       std::cout << "test2_1 & operator << (const test2_1 &, const test2_2 &)" << '\n';
       return(fLHS);
    }
    
    test2_2 & operator <<
    (
       test2_2 & fLHS
     , const test2_2 & fRHS
    )
    {
       std::cout << "test2_2 & operator << (const test2_2 &, const test2_2 &)" << '\n';
       return(fLHS);
    }
    
    int main
    (
       int argc
     , char ** argv
    )
    {
       test1_1 t1_1;
       test1_2 t1_2;
       test2_1 t2_1;
       test2_2 t2_2;
       t1_1 += t1_2 += t1_2;
       t2_1 << t2_2 << t2_2;
       return(0);
    }
    Last edited by phantomotap; 07-13-2010 at 01:21 AM.

  12. #42
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by phantomotap
    WTF!?
    omgwtfbbq!?

    Quote Originally Posted by phantomotap
    It could not work. You could not "chain" the operators. It is not an issue of precedence. It is an issue of associativity.
    That's true. Precedence is an issue, but I did not notice the more pertinent issue.

    Quote Originally Posted by phantomotap
    And wrapping the expression in countless parentheses doesn't count!
    Of course it does, if you're a masochist.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #43
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    omgwtfbbq!?
    IANRIILUTAFTPOTDBITFYA!?

    Of course it does, if you're a masochist.
    Don't be stupid; if the programmer were a masochist they'd be using Java.

    Soma

  14. #44
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Programmer_P: WTF! (Always wanted to say that.)
    There are some points you just seem to fail to understand.
    First of all: a stringstream is just like your vanilla file streams or console streams or whatever you want to call them. You don't see...
    Code:
    std::cout << "Hello" << "World";
    ...only printing out "World", do you? Then why do you expect stringstreams to do that?

    Second point.
    You need to understand how stringstreams work, not just, "oh I've seen this scenario before; do this and it's fixed." You don't have a clear view of what the actual problem is, and that is by all definitions, bad. You must understand that streams are bastards in many ways. If they fail, they will just silently fail to do anything else. You need to check if a problem occurred, and if so, fix it. If the stream failed for some reason, it usually means that whatever you parsed is wrong. Or you parsed it wrong. If it cannot convert from type X to type Y for some reason, it will fail. Keep this in mind. The clear member function clears the error flags and allows the stream to continue to do work.

    Third point.
    If there is an error, fail or recover. Don't silently ignore it. For simple code, all you can do is just throw an exception or put an assert. But don't ignore it altogether. This will just cause you headaches.

    Fourth point.
    Why couldn't you just put the damn debugger into the parsing routine and do a step-by-step instead of putting out a lot of verbose, useless debug information? Why was it so extremely difficult to do this!?!

    Fifth point.
    There is an edit button Use it.

    Sixth point.
    There is a multi-quote button. 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.

  15. #45
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Elysia View Post
    Programmer_P: WTF! (Always wanted to say that.)
    There are some points you just seem to fail to understand.
    First of all: a stringstream is just like your vanilla file streams or console streams or whatever you want to call them. You don't see...
    Code:
    std::cout << "Hello" << "World";
    ...only printing out "World", do you? Then why do you expect stringstreams to do that?
    Because with stringstream, I'm dealing with a stringstream variable and I'm doing this:

    Code:
    ss<< i;
    not:

    Code:
    ss<< i << i2;
    As for cout, I didn't know it appended. I thought it outputted each argument after << then cleared itself, in which case your line of code would still output both "Hello" and "World".
    Second point.
    You need to understand how stringstreams work, not just, "oh I've seen this scenario before; do this and it's fixed." You don't have a clear view of what the actual problem is, and that is by all definitions, bad. You must understand that streams are bastards in many ways. If they fail, they will just silently fail to do anything else. You need to check if a problem occurred, and if so, fix it. If the stream failed for some reason, it usually means that whatever you parsed is wrong. Or you parsed it wrong. If it cannot convert from type X to type Y for some reason, it will fail. Keep this in mind. The clear member function clears the error flags and allows the stream to continue to do work.
    Third point.
    If there is an error, fail or recover. Don't silently ignore it. For simple code, all you can do is just throw an exception or put an assert. But don't ignore it altogether. This will just cause you headaches.
    Well, in this case, the problem was the "eofbit" was being set. Neither "badbit" or "failbit" were set, so I didn't see a need to output anything, or fail. I just cleared it and moved on. I guess I could do something like this though:

    Code:
    for (unsigned int i = 0; i < valuesOfEnumerators_v_i.size(); i++) {
          currentEnumeratorValue_i = valuesOfEnumerators_v_i.at(i); //get the current enumerator's value
          currentEnumeratorValue_ss<< currentEnumeratorValue_i;
          if (!currentEnumeratorValue_ss.good()) {
              if (currentEnumeratorValue_ss.bad()) {
                  cout<< "Error! Badbit was set on stringstream input operation.\n"
                              "Failing..." <<endl;
                  return 1;
              }
    
              else if (currentEnumeratorValue_ss.fail()) {
                   cout<< "Error! Failbit was set on stringstream input operation.\n"
                               "Failing..." <<endl;
                   return 1;
              }
    
             else if (currentEnumeratorValue_ss.eof()) {
                   cout<< "Error! eofbit was set on stringstream input operation.\n"
                               "Recovering..." <<endl;
                   }
             }
    
             currentEnumeratorValue_ss>> currentEnumeratorValue_s;
             if (!currentEnumeratorValue_ss.good()) {
                 if (currentEnumeratorValue_ss.bad()) {
                     cout<< "Error! Badbit was set on stringstream output operation.\n"
                                 "Failing..." <<endl;
                     return 1;
                 }
    
                 else if (currentEnumeratorValue_ss.fail()) {
                      cout<< "Error! Failbit was set on stringstream output operation.\n"
                                  "Failing..." <<endl;
                      return 1;
                 }
    
                 else if (currentEnumeratorValue_ss.eof()) {
                      cout<< "WTF?! eofbit was set on stringstream output operation.\n"
                                  "Recovering..." <<endl;
                  }
             }
             output_s += "    enumeratorValues.push_back(";
             output_s += currentEnumeratorValue_s; //add it to the output string
             currentEnumeratorValue_ss.clear();
             currentEnumeratorValue_s.clear();
             output_s += ");\n";
    }
    Fourth point.
    Why couldn't you just put the damn debugger into the parsing routine and do a step-by-step instead of putting out a lot of verbose, useless debug information? Why was it so extremely difficult to do this!?!
    The thing is, I didn't want to use my debugger. I wanted to waste my time "putting out a lot of verbose, useless debug information" just so I could annoy you. And it worked...
    Fifth point.
    There is an edit button Use it.
    I use it all the time. That's why you see lots of posts with "Last edited by Programmer_P;"...
    Sixth point.
    There is a multi-quote button. Use it.
    I know there is a multi-quote button. But sometimes I forget about it. Anyway, I don't see what the big deal is. Why are you so into multi-quote buttons?
    Last edited by Programmer_P; 07-13-2010 at 07:46 AM. Reason: fixed formatting. see...I used it again :)
    I'm an alien from another world. Planet Earth is only my vacation home, and I'm not liking it.

Popular pages Recent additions subscribe to a feed