Thread: passing argv[1] to a method

  1. #1
    Registered User
    Join Date
    Sep 2007
    Posts
    100

    passing argv[1] to a method

    Hey,

    I have a method that takes in the command line argument argv[1] and runs some checks on it - making sure it is not null, then making sure that it is an integer. However, we do not know at first what argv[1] is. It might be a string, null, or a character. This is where I am running into a problem - how do I appropriately declare my method to take in argv[1] when I don't know what type it is? Should I have my method take in a string, since that could cover everything, and then after the tests are done cast argv[1] as an int? That is what I have done so far (declare it as a string), but after I run the checks I am having trouble casting the string, which is no determined to be a number, as an int. Here is some code:

    Code:
    int main(int argc, char *argv[]) {
        myStack stack1;
    
        stack1.setStackSize(argv[1]);
    Code:
    class myStack {
        
        public:
            int stackSize;
            void setStackSize(string);
            int displayStackSize();
    };
    Code:
    void myStack::setStackSize(string carg) {
        
        int arg_length;
        char current_digit;
    
        if(carg == "") {
            cerr << "Bad command line argument.\n";
            exit(1);
        }
    
        arg_length = carg.length();
    
        for(int ii = 0; ii < arg_length; ii++) {
            current_digit = carg[ii];
            if(!(isdigit(current_digit))) {
                cerr << "Bad command line argument.\n";
                exit(1);
            }
        }
    
        stackSize = atoi(carg);
       
    }
    I am getting this error:

    40 N:\USERS\bakewens\CS240\myStack.cpp cannot convert `std::string' to `const char*' for argument `1' to `int atoi(const char*)'
    on my line stacksize = atoi(carg)

  2. #2
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    The compiler trys to tell you that std::string is not a const char *
    try
    Code:
    stackSize = atoi(carg.c_str());
    Kurt

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    However, we do not know at first what argv[1] is. It might be a string, null, or a character. This is where I am running into a problem - how do I appropriately declare my method to take in argv[1] when I don't know what type it is?
    If it exists, argv[1] is a null terminated string, a char*, or more precisely, a char[n], where n is the length of the string including the null terminator.

    Your function parameter is not problematic, though perhaps passing by const reference is better. The problem is that atoi() expects a null terminated string as its argument, but you are passing it a std::string. The solution is to use stringstreams to perform the conversion.
    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

  4. #4
    Registered User
    Join Date
    Sep 2007
    Posts
    100
    Is using stackSize = atoi(carg.c_str()); incorrect? Or is using streamstreams just better practice?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Is using stackSize = atoi(carg.c_str()); incorrect?
    It is correct.

    Or is using streamstreams just better practice?
    Generally, yes.
    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

  6. #6
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    It is possible that argv[1] is a null pointer if no command line arguments are passed to the program. You need to verify that argc is greater than 1 before you use argv[1] to initialize a string. It's not legal to pass a null pointer to the string constructor that expects a const char*.
    Last edited by Daved; 09-23-2007 at 02:18 PM.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Am I the only one that wonders why this is not done something like this:
    Code:
    int main(int argc, char *argv[]) {
        myStack stack1;
    
        if (argc > 1) {
           // insert error checking code here.
           stack1.setStackSize(atoi(argv[1]));
        }
    ...
    
    void myStack::setStackSize(int size) {
    ...
    }
    The natural value for a stackSize is an (unsigned) integer number of some sort - the size of this integer, and whether it is declared as unsigned is a case of "what does it have to do and how is it supposed to work in a bigger picture". But passing a string to a member function called setStackSize is just unnatural. If stacksize happens to be a character array containing a number, it should be converted before it's passed in - that's the "natural" way to do these things.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    I agree that setStackSize should take an int. I would probably use a stringstream (or lexical_cast) in main or some other command line argument checking function to convert the string to an int and provide a proper error message on failure, though. It's easy for users to provide incorrect command line parameters.

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Daved View Post
    I agree that setStackSize should take an int. I would probably use a stringstream (or lexical_cast) in main or some other command line argument checking function to convert the string to an int and provide a proper error message on failure, though. It's easy for users to provide incorrect command line parameters.
    Yes, for sure - using safer methods is always better. I didn't want to "modify" the original too much, because that would sort of make my INTENDED changes more difficult to spot, but yes, using stringstream or lexical_cast, or in standard C, strtol, would be a good way to do it.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Sep 2007
    Posts
    100
    I added the check to make sure argc > 1 before I call setStackSize.

    I wanted it how all my error checking was in setStackSize and not in main.

    Can someone point me in the right direction for using stringstream? I've been reading through all the google results and they just confuse me more. Is this how it is done?

    Code:
    #include <sstream>
    
    ...
    
    stringstream out;
    out << argv[1];
    stackSize = out.int();

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    When extracting from the stream into a variable, use it like cin.
    Code:
    out >> stackSize;
    To add error checking, put it in an if block:
    Code:
    if (!(out >> stacksize))
    {
        cerr << "Bad command line argument.\n";
    }
    >> I wanted it how all my error checking was in setStackSize and not in main.
    As matsp indicated that is bad design. You don't want to make your class have to know where it is getting that value from.
    Last edited by Daved; 09-23-2007 at 04:14 PM.

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, you obviously don't have to do the processing/error-checkin in main itself if you don't want to. But doing it in a class that is essentially an implementation of a stack is a bit like saying "well, I didn't want to have the toilet in the kitchen, so I put it in the front room instead"...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Sep 2007
    Posts
    100
    Would using lexical_cast be better?

    Code:
    #include <boost/lexical_cast.hpp>
    
    stackSize = Boost::lexical_cast<int>(argv[1])

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you're already using boost I'd say use lexical_cast. It does basically the same thing internally anyway. Otherwise the stringstream should be fine.

    Don't forget to catch the exception for a bad cast if you use lexical_cast.

  15. #15
    Registered User
    Join Date
    Sep 2007
    Posts
    100
    So the code would look like this?

    Code:
    #include <sstream>
    
    ...
    
    stringstream out;
    out << argv[1];
    
    
    if (!(out >> int))
    {
        cerr << "Bad command line argument.\n";
    } else {
        out >> stackSize;
    }
    Last edited by Beowolf; 09-23-2007 at 04:03 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. on method pointers and inheritance
    By BrownB in forum C++ Programming
    Replies: 2
    Last Post: 03-02-2009, 07:50 PM
  2. stuck on display method
    By shintaro in forum C++ Programming
    Replies: 2
    Last Post: 02-01-2009, 05:17 PM
  3. C# method
    By siten0308 in forum C# Programming
    Replies: 6
    Last Post: 07-15-2008, 07:01 AM
  4. Replies: 2
    Last Post: 01-22-2008, 04:22 PM
  5. Newb Question on Passing Objects as Parameters
    By Mariano L Gappa in forum C++ Programming
    Replies: 12
    Last Post: 11-29-2006, 01:08 PM