Thread: Alright, how does one compare an element of argv with a literal string?

  1. #1
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827

    Alright, how does one compare an element of argv with a literal string?

    How does one compare an element of argv (an array of char pointers) with a literal string, or to put it more accurately, how does one compare the char array being pointed at by an element of argv with a literal string?

    When I use the syntax:

    if (argv[1] == "ALiteralString")

    my compiler warns "comparison with string literal results in unspecified behavior", and its right. Its unspecified behavior alright. Because it ignores the if statement designed to be entered if the second argument (counting the program name) is a certain string ("--help", to be more exact).

  2. #2
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    And if I try dereferencing the char pointer argv[1] in the if statement by doing

    if (*argv[1] == "ALiteralString")

    it wont compile at all. It says "ISO C++ forbids comparison between pointer and integer".

  3. #3
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Ok, another problem dealing with argv:

    When I get the argv[1] argument and store it in a string, I then get the size of the string by calling the size() function of that string.
    Later on in the code, I was noticing it was outputting the wrong message at was supposed to be the last character of the string (i.e. inputFilePathSize - 1). And so I went and outputted the size of the inputFilePath string (which is the string which was given the contents of argv[1]), and it turns out that size is 2 less than what it should be.

    It claims the length/size of the string is 32, when in reality, its 34. It also gets the size of argv[2] (an output filename string) wrong. It claims it has 7 characters, when in reality, it has 9.

    With both strings, I depending on the size() function of the string type, and store what that function returns inside an int. Is that the problem? I know that string::size() returns a size_t type which is an unsigned type as opposed to "int" which is a signed type. I don't know if that would change the inner value though. I was under the impression it wouldn't, which is why I'm using an int variable instead of a size_t for storing the size.

  4. #4
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    Use strcmp() to compare strings.
    Mainframe assembler programmer by trade. C coder when I can.

  5. #5
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by Dino View Post
    Use strcmp() to compare strings.
    Is that a member function of the string type?
    I couldn't find it anywhere in the string C++ reference, though I see a "compare()" function which might do the same thing as the function you mentioned.

  6. #6
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    You're running into the fact that C++ supports two distinct but unrelated types which might be described as a string.

    1) The std::string class which is specified in the header <string>.

    2) An array of char that is delimited with a zero. This form of string is inherited by C++ from C.

    String literals are stored in the second form. For example "Hello" is represented by 6 characters 'H', 'e', 'l', 'l', 'o', and '\0' (a zero character).

    The argv argument of main() is an array of strings in the second form.

    strcmp() is a function declared in the C header <string.h> or in the C++ header <cstring> (where the function is in namespace std). It is used to compare two strings that are each in the second form above.

    The C++ std::string class has a constructor that accepts a const char * (so a C-style string can be converted to a std::string) and a method named c_str() which returns an equivalent C-style string.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  7. #7
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by grumpy View Post
    You're running into the fact that C++ supports two distinct but unrelated types which might be described as a string.

    1) The std::string class which is specified in the header <string>.

    2) An array of char that is delimited with a zero. This form of string is inherited by C++ from C.

    String literals are stored in the second form. For example "Hello" is represented by 6 characters 'H', 'e', 'l', 'l', 'o', and '\0' (a zero character).

    The argv argument of main() is an array of strings in the second form.
    That's right. So why then is:

    if (argv[3] == "--help")

    not working, since they're both c-style strings?

    strcmp() is a function declared in the C header <string.h> or in the C++ header <cstring> (where the function is in namespace std). It is used to compare two strings that are each in the second form above.

    The C++ std::string class has a constructor that accepts a const char * (so a C-style string can be converted to a std::string) and a method named c_str() which returns an equivalent C-style string.
    Right. A little Googling provided me that same info just a little before your reply.
    Thanks to both of you for replying, btw.

    I just tried to compare two c-style strings with strcmp(), passing in argv[3] as the first argument, and the c-style string "--help" as the second, and storing the int result in a variable which I then check inside an if statement to see if its 0 (meaning the two strings are the same). If they are, I print out a help message. Else if they're not, I output an error saying you can't pass in just 1 argument into the program, if that argument is not "--help". Only problem is, that else if statement is entered even though I DO pass in "--help" as the only argument (not counting the program name, of course), and so I end up getting that error which lets me know its f****** up for some reason.
    Last edited by Programmer_P; 05-29-2010 at 08:41 PM.

  8. #8
    Jack of many languages Dino's Avatar
    Join Date
    Nov 2007
    Location
    Chappell Hill, Texas
    Posts
    2,332
    argv[] elements will always point to c-style strings.

    Show your current code that is not working.
    Mainframe assembler programmer by trade. C coder when I can.

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    If you are only passing 1 argument it is argv[1] not argv[3]. Also you can check the number of arguments passed by using argc (The number of parameters passed).

  10. #10
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by jimblumberg View Post
    If you are only passing 1 argument it is argv[1] not argv[3]. Also you can check the number of arguments passed by using argc (The number of parameters passed).
    Yes, I know that. I neglected to mention that I'm allowing the user to pass in the "--help" argument as either argv[1] when there is only one argument other than the program name OR argv[3] when the number of arguments other than the program name is 3. So both are valid. However, the statement that's acting up when I pass in only one argument which is "--help" looks like this:
    Code:
    if (argc == 2) {
                if (argv[1] == "--help") {
                    cout<< "You passed the '--help' argument." <<endl;
                    cout<< helpObject.help(); //print help message
                    cout<< "\n\nPress Enter to end this program." <<endl;
                    cin.get(); //make the user press Enter
                    return 0; //to indicate successful program completion because user passed in the --help argument
                }
    
                else {
                    cout<< "Error! If you only pass 1 argument, that cannot be\n"
                           "anything other than '--help' to print a help message." <<endl;
                    cout<< helpObject.help(); //print help message
                    cout<< "\n\nPress Enter to end this program." <<endl;
                    cin.get(); //make the user press Enter
                    return 1; //because the user tried to do something funny and unallowed with this program
                }
     }
    The problem is, the "else" instead of the "if" statement is entered, even though I pass in "--help", and so consequently, the program outputs the wrong thing.
    Also note that the code above is both what I tried first, and also is my current code, though I also tried using strcmp() as suggested instead of the '==' operator to compare the strings, but the result was the same, so I switched it back, since I prefer the compare statement to be in only 1 line.
    Last edited by Programmer_P; 05-29-2010 at 08:58 PM.

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    You must use strcmp() to compare cstrings

    Jim

  12. #12
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Programmer_P View Post
    That's right. So why then is:

    if (argv[3] == "--help")

    not working, since they're both c-style strings?
    Because what you've done here is a pointer comparison. It compares the address of the first character in argv[3] with the address of the first character in the string literal "--help". Since those addresses in memory will generally be different, the comparison yields a false (zero) result.

    Quote Originally Posted by Programmer_P View Post
    I just tried to compare two c-style strings with strcmp(), passing in argv[3] as the first argument, and the c-style string "--help" as the second, and storing the int result in a variable which I then check inside an if statement to see if its 0 (meaning the two strings are the same). If they are, I print out a help message. Else if they're not, I output an error saying you can't pass in just 1 argument into the program, if that argument is not "--help". Only problem is, that else if statement is entered even though I DO pass in "--help" as the only argument (not counting the program name, of course), and so I end up getting that error which lets me know its f****** up for some reason.
    Without seeing your code or the command line you're using to run your program, only guesses are possible. However, the problem is either in your code or in the command line you are providing to your program.

    The obvious possibilities are

    1) "--help" is not the third argument you are supplying after the program name, so the comparison is doomed to failure.

    2) You're doing the comparison incorrectly. From your description, you could be doing;
    Code:
       int result = strcmp(argv[3], "--help");
       if (result = 0)
            do_something();
       else
            do_something_else();
    A single '=' character does an assignment. A comparison requires two of them. if (result = 0) will always test false (as zero is false).

    3) You are using a command line interpreter that filters "--help", and changes what is being passed to your program. For example, conversion to upper case, stripping one of the '-' characters.

    4) You have not ensured argv[3] is valid. You also need to check argc. For example, if argc is less than 4, using strcmp(argv[3], anything) always gives undefined behaviour.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  13. #13
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by jimblumberg View Post
    You must use strcmp() to compare cstrings

    Jim
    Hmm...though I thought I had tried that already, I just changed the code to use strcmp(), and this time, it works as expected. I think probably what happened before was I was accidentally editing the code which deals with the argv[3] and accepts the same argument as argv[1] and thinking I was editing the code which execution was entering when I passed "--help" as the only argument, but now I realize what was actually happening.

    Oh well...problem solved.

  14. #14
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quote Originally Posted by grumpy View Post
    Because what you've done here is a pointer comparison. It compares the address of the first character in argv[3] with the address of the first character in the string literal "--help". Since those addresses in memory will generally be different, the comparison yields a false (zero) result.
    Well, that is what I originally guessed was happening if I compare argv[3] with a literal string. However, when I attempted to dereference the pointer at element 3 of argv, it wouldn't compile, as I think I stated in an earlier post.
    Without seeing your code or the command line you're using to run your program, only guesses are possible. However, the problem is either in your code or in the command line you are providing to your program.

    The obvious possibilities are

    1) "--help" is not the third argument you are supplying after the program name, so the comparison is doomed to failure.

    2) You're doing the comparison incorrectly. From your description, you could be doing;
    Code:
       int result = strcmp(argv[3], "--help");
       if (result = 0)
            do_something();
       else
            do_something_else();
    A single '=' character does an assignment. A comparison requires two of them. if (result = 0) will always test false (as zero is false).
    No, I wasn't doing that. The problem stemmed from changing the wrong code to use strcmp() and thinking I was changing the right code. Once I realized my error, and corrected the right code, POOF! went my problem. Or something like that...
    3) You are using a command line interpreter that filters "--help", and changes what is being passed to your program. For example, conversion to upper case, stripping one of the '-' characters.
    Well, I sure hope nothing like that will ever occur when someone uses my program...
    4) You have not ensured argv[3] is valid. You also need to check argc. For example, if argc is less than 4, using strcmp(argv[3], anything) always gives undefined behaviour.
    Oh, I ensured it, alright. I just didn't post all the code that I have.
    Obviously I took care of all the obvious things such as that. Its the subtle errors that are harder to find.

  15. #15
    Programming Ninja In-T...
    Join Date
    May 2009
    Posts
    827
    Quick question though:

    Does the string::c_str() function work with comparison operators such as '!=' and '==', if I use those operators with the other operand being a literal c-style string?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Inheritance Hierarchy for a Package class
    By twickre in forum C++ Programming
    Replies: 7
    Last Post: 12-08-2007, 04:13 PM
  2. Pointer dangling or not
    By vaibhav in forum C++ Programming
    Replies: 16
    Last Post: 08-05-2006, 06:39 PM
  3. Something is wrong with this menu...
    By DarkViper in forum Windows Programming
    Replies: 2
    Last Post: 12-14-2002, 11:06 PM
  4. String literal
    By subdene in forum C++ Programming
    Replies: 5
    Last Post: 11-05-2002, 02:10 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM