Thread: Homework Problem About Pointers

  1. #31
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    Thanks guys, I think what the teacher wants us is just to check if the pointer sent to the overloaded function is NULL or not, if it is, show an error(either on screen or using exception handeling)
    So, what I did was to modify my << overloaded function...
    Code:
    std::ostream& operator <<( std::ostream& outs, const SodaCan *can ){
    
         if(!can){
             outs<<"NULL POINTER, NOT ENOUGH MEMORY";
         }
         else{
         outs<< can->getContents() <<" ounces of " <<can->getBrand() <<" in a "<<can->getSize()<< " can.";
         }
         return outs ; 
    }
    What do you think?! The program works now, it checks to see if the pointer is NULL, and then sends a message on screen....Is this a right way of coding?! or should I go with ==NULL in if statement?
    Last edited by Ashl7; 06-04-2014 at 03:59 PM.

  2. #32
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    Well, I prefer to write code with the "affirmative" condition first.

    Code:
    if(can)
    {
        // have a can
    }
    else
    {
        // have no can
    }
    That said, the message is garbage. You've been given a null pointer, but you don't have enough information to speculate on the available memory. The message is also unrelated to a `SodaCan'. How is "null pointer" a thing your client seeking soda is going to care about?

    Beyond that, you also seem to be confused about exceptions. You could `throw' an exception from the implementation. I'd even prefer you use the exception mechanism. (Using exceptions for error reporting in overloaded operators is idiomatic in C++ programming.) However, the exception mechanism is about "client code". (That is, the exception mechanism reports errors to the code calling the function.) Reporting a message with `cout', and similar, is about reporting an error to the "user". (That is, the individual using the application.) The two methods of reporting errors are not naturally related. If you are expected to report an error to the "user", the exception mechanism will require you to add a `catch' block as part of the "client code" so that you could then report a specific error to the "user".

    With the exception mechanism, the driver code becomes problematic. I would assume you can't change the driver. I also assume the application is expected to run to a successful completion. If you can't change the driver code, using exceptions is not a path you want to take. The uncaught exception will call `terminate', unless changed, which will likely call `abort' prematurely terminating the program.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  3. #33
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    They are logically equivalent in this case.

    false is the same thing as 0 and NULL is the same thing as 0.

    Now, C++11 introduced to concept of nullptr (which should have the same value of 0) because of things like this :
    Code:
    void foo(int x);
    void foo(int *x);
    
    int main(void) {
    
        foo(0); // which function is called? NULL is 0, afterall
        foo(nullptr); // call foo(int *x)
    
        return 0;
    }

  4. #34
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    Ok, I've changed the message, and I'm going to be content with cout message to inform the user about the NULL pointer.
    So, next is overloading >> operator. here's my definition for it:

    Code:
     
       std::istream& operator >>( std::istream& ins, SodaCan *&can ){
    
           std::cout<<"Enter the brand of the soda, the size and then the amount of soda in it, respectivly: ";
           
           ins >> can->my_Brand;
           ins >>can->my_Size;
           ins >>can->my_Contents;
    
           return ins;
    
       }
    It works fine and by now, I'm done with this program...however, I wanted to add another thing for checking if the content in the can entered by the user is less than the size of the can or not, and I changed my function to this:

    Code:
       std::istream& operator >>( std::istream& ins, SodaCan *&can ){
    
           std::cout<<"Enter the brand of the soda, the size and then the amount of soda in it, respectivly: ";
           
           ins >> can->my_Brand;
           ins >>can->my_Size;
           ins >>can->my_Contents;
    
            while(can->my_Contents > can->my_Size){
               std::cout<<"\nThe content should not be bigger than the size";
               ins>>"Enter the amount of soda in the can again: ";
               ins>>can->my_Contents;
    
           return ins;
    
       }
    And this one does not work...why is that?

  5. #35
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Looks ike you're missing a closing brace for your while statement.

    Jim

  6. #36
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    Yeah I missed in when I was copy/pasting....but the brace was already in my code!

  7. #37
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Ashl7
    And this one does not work...why is that?
    How does it not work?

    Incidentally, this:
    Code:
    std::istream& operator >>( std::istream& ins, SodaCan *&can )
    should be:
    Code:
    std::istream& operator >>( std::istream& ins, SodaCan *can )
    You are not going to change the pointer in the function, so there's no point declaring it to be a reference parameter.
    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

  8. #38
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    You are not going to change the pointer in the function, so there's no point declaring it to be a reference parameter.
    O_o

    He isn't changing the pointer as of that post; he should be changing the pointer.

    @Ashl7: If you are going to handle null the way you are in the "output stream" overload, you should have parity in the "input stream" overload.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  9. #39
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    Quote Originally Posted by laserlight View Post
    How does it not work?.
    I get this error, it is very long!!

    e:\users\ashl7\desktop\sodacan2012\sodacan2012\sod acan.cpp(86): error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'const char [44]' (or there is no acceptable conversion)
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(1053): could be 'std::basic_istream<_Elem,_Traits> &std:perator >><std::char_traits<char>>(std::basic_istream<_Ele m,_Traits> &,signed char *)' [found using argument-dependent lookup]
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(1060): or 'std::basic_istream<_Elem,_Traits> &std:perator >><std::char_traits<char>>(std::basic_istream<_Ele m,_Traits> &,signed char &)' [found using argument-dependent lookup]
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(1067): or 'std::basic_istream<_Elem,_Traits> &std:perator >><std::char_traits<char>>(std::basic_istream<_Ele m,_Traits> &,unsigned char *)' [found using argument-dependent lookup]
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(1074): or 'std::basic_istream<_Elem,_Traits> &std:perator >><std::char_traits<char>>(std::basic_istream<_Ele m,_Traits> &,unsigned char &)' [found using argument-dependent lookup]
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(1084): or 'std::basic_istream<_Elem,_Traits> &std:perator >><char,std::char_traits<char>,const char[44]>(std::basic_istream<_Elem,_Traits> &&,_Ty (&))' [found using argument-dependent lookup]
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>,
    1> _Ty=const char [44]
    1> ]
    1> e:\users\ashl7\desktop\sodacan2012\sodacan2012\sod acan.h(32): or 'std::istream &operator >>(std::istream &,SodaCan *&)'
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(193): or 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>:perator >>(std::basic_istream<_Elem,_Traits> &(__cdecl *)(std::basic_istream<_Elem,_Traits> &))'
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(199): or 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>:perator >>(std::basic_ios<_Elem,_Traits> &(__cdecl *)(std::basic_ios<_Elem,_Traits> &))'
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(206): or 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>:perator >>(std::ios_base &(__cdecl *)(std::ios_base &))'
    1> with
    1> [
    1> _Elem=char,
    1> _Traits=std::char_traits<char>
    1> ]
    1> e:\program files (x86)\microsoft visual studio 11.0\vc\include\istream(213): or 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>:perator >>(std::_Bool &)'

    and it goes on and on...


    that is the way my teacher wanted us to declare the function...so it might be wrong, but I can't do anything about it.

  10. #40
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    @phantomotap: you mean I should define it in a way that it gets a null pointer?! (explain pls)

  11. #41
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    A post by Elysia shows you how to approach handling the errors the compiler shows you.

    You are blaming the wrong code for parts of those errors.

    Post again after you've tried to correct the code.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  12. #42
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    can't figure it out for the life of me.

  13. #43
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I skimmed the thread. I have some stuff to show off and some advice to give, but at this point I need to write some code to explain myself. We'll see if it helps any.

    Quote Originally Posted by Ashl7 View Post
    can't figure it out for the life of me.
    Sounds like someone needs to re-evaluate their choices and/or priorities.

    This was the offending line:
    Code:
    ins>>"Enter the amount of soda in the can again: ";
    std::cin, for example, is not something that could insert new data into a string literal. Since literals are a kind of constant, I think Soma is expecting that you figured this one out. I think that you were just guilty of typing on the keyboard a little too quickly.

    To be honest with you, I don't like that you want to display messages inside of the function that takes input for SodaCans. You could also set the stream state to bad so that you can handle bad input outside of the extraction operator, too.

    Consider this:
    Code:
    std::cout << "Enter the brand of soda, the size, and then the amount of soda in the container, respectively: ";
    while ( ! (std::cin >> can)) {
      std::cout << "The amount in the container should not be more than the container size." << std::endl;
      std::cin.clear();
      std::cin.ignore(100000, '\n');
    }
    That is a lot cleaner is it not? Well the operator that works this way would look a lot like:
    Code:
    std::istream& operator >>( std::istream& ins, SodaCan *&can )
    {
       SodaCan * temp = new SodaCan;
    
       ins >> temp->my_Brand >> temp->my_Size >> temp->my_Contents;
    
       if (ins.eof()) {
          ins.clear(std::ios::eofbit);
          delete temp;
       }
       else if (ins.fail() || temp->my_Size > temp->my_Contents) {
          ins.clear(std::ios::failbit);
          delete temp;
       }
       else {
          delete can;
          can = temp;
       }
       return ins;
    }
    That's as simple as I can make it, at least. I can't be bothered to test it, as bad as that is. But you can assume that the code which you did not write, like ins.clear() will work. The error message is also kinda dumb if you actually sent EOF. I included it in the code because I thought it would bad to write an extraction operator and not deal with that situation. It would be brittle.

    If you want to handle EOF silently, a simple condition like while( ! (std::cin >> can)) is very inclusive. You will have to write something like if(cin.fail()) to handle bad input inside of the loop.

    Don't ignore the other guys advice just because I typed so much.

    Finally, a tip on reading long dumps/big error messages. 99% of the time, the problem you need to deal with is explained in the first few words. Concentrate on that and comprehend those first few words the best you can; look at the related lines; see if it points out any obvious errors.
    Last edited by whiteflags; 06-05-2014 at 04:32 AM.

  14. #44
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Ashl7 View Post
    I get this error, it is very long!!
    Looks like to me that the error is very clear in the beginning.

    e:\users\ashl7\desktop\sodacan2012\sodacan2012\sod acan.cpp(86): error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'const char [44]' (or there is no acceptable conversion)
    Red: The source file and line where the error occured.
    Orange: Describes the error. There is no overloaded operator >> that takes a const char literal as its argument (that the compiler can find). But really, it doesn't exist because it doesn't make sense. a >> b says read from "a" into "b". But if b is const (i.e. cannot be modified), how do you expect it to be able to do that? And how does it make sense to read into a string literal? That is not a variable! A string literal cannot hold information.
    Green: The compiler also complains that it cannot find a conversion from const char[44] to some type that operator >> expects. This is just for completeness. Since there is no sense in doing what you are doing, of course it makes no sense to provide some conversion that makes it work.

    Also, you must understand what these operators are for. Operator << inserts some data into a stream and operator >> extracts some data from a stream. So what is a stream? Well, it is a concept, but suffice to say that both writing to the console screen, writing to files and reading from the keyboard and from files are part of this concept. Therefore, it makes sense that

    a << some_data;
    a >> some_other_data;
    Then, some_data == some_other_data.

    Because I expect to be able to read back exactly what I wrote to a stream (e.g. file). How then, does it make sense for the operators to prompt for input from the user inside the operator? It does not! It makes absolutely no sense at all, so don't do it. The operators job is to write or read data from a stream. That's it. If you want to ask data from the user, then go ahead and do it in your client code. But don't do it in the operators!
    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
    Registered User Ashl7's Avatar
    Join Date
    Oct 2012
    Posts
    57
    I'm so sorry guys, I hate myself right now...sometimes I miss the smallest inconsequential details and I go look for an error somewhere else, and I do have problem reading and interpreting the errors compiler gives. Thanks everyone. The project is DONE!
    Last edited by Ashl7; 06-05-2014 at 03:59 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Homework Problem help!! Please.
    By arti in forum C Programming
    Replies: 10
    Last Post: 03-22-2013, 06:50 AM
  2. help!!!!!! pointers homework
    By ver_gon89 in forum C++ Programming
    Replies: 17
    Last Post: 11-24-2008, 12:23 AM
  3. homework problem Please Help!
    By alexwink in forum C Programming
    Replies: 24
    Last Post: 10-27-2006, 08:20 AM
  4. Replies: 27
    Last Post: 10-11-2006, 04:27 AM