0

I have a problem with passing an argument into my program, seems to not be equal to what I put in as argument, except they're identical. Turning them into a string makes them identical, but I would like to know why the initial duo isn't.

Here's my code:

int main(int argc, char *argv[]) {
  if (argc>1) {
    cout << "#" << argv[1] << "#" << endl;
    cout << "#" << "nomast" << "#" << endl;
    cout << (argv[1] == "nomast" ? "equal" : "not equal") << endl;

    string s1 = argv[1];
    string s2 = "nomast";
    cout << (s1 == s2 ? "equal after all" : "nope") << endl;
    system("pause");
  }
  return 0;
}

When I launch the compiled code with "call thingy.exe nomast" I get the output

#nomast#
#nomast#
not equal
equal after all
Press any key to continue . . .

My best idea is that I'm not handling the "char *argv[]" properly. Don't know how to handle it differently though.

nDARQ
  • 9
  • 1
  • 3
  • 3
    `argv[1] == "nomast"` - that isn't how you compare char-array strings and/or char string literals, in either C or C++. [`strcmp`](https://en.cppreference.com/w/c/string/byte/strcmp), sir. – WhozCraig Aug 09 '18 at 09:53
  • 1
    you want [`strcmp`](https://en.cppreference.com/w/cpp/string/byte/strcmp) to compare `char*`, `string` has a `==` operator that is able to compare the character arrays which is why that works. When you use `==` with `char*` this compares the pointer address not what it's pointing at – EdChum Aug 09 '18 at 09:54
  • Different language (C), identical problem and solution. Duplicate here: [How do I properly compare strings?](https://stackoverflow.com/questions/8004237/how-do-i-properly-compare-strings) – WhozCraig Aug 09 '18 at 09:58
  • Does this answer your question? [Why are my two tuples containing strings, created the same way, not equal?](https://stackoverflow.com/questions/63724412/why-are-my-two-tuples-containing-strings-created-the-same-way-not-equal) – JaMiT Feb 04 '23 at 08:38

4 Answers4

8

You are comparing pointers, in other word addresses, not their content. Since you are using C++ I suggest you use std::string and compare such objects instead (as you did in your second comparison).

Otherwise, if you have to deal with C, just use the strcmp function from the C standard library.

Rerito
  • 5,886
  • 21
  • 47
  • Creating `std::string`s from `main`'s arguments is just overhead (creating copies) - if you receive C-Strings for whatever reason (in given case: main is just defined by standard that way...) and *don't need* a std::string afterwards anyway, just use `strcmp` even in C++! – Aconcagua Aug 09 '18 at 09:57
  • @MaxLanghof Valid alternative, still you'd iterate twice over the C-string: once for determining length on construction, then for comparison. strcmp is superior in this case... – Aconcagua Aug 09 '18 at 10:10
  • Ah, so == in C++ defaults to comparing only pointers' addresses, not checking pointed memory. Good to know, thanks! And I went with strcmp, because it's faster. – nDARQ Aug 09 '18 at 10:15
  • @nDARQ Be aware that this is the case for *any* pointer, no matter of which type! – Aconcagua Aug 09 '18 at 10:16
  • 1
    @nDARQ Keep in mind that you can always use == and != for any pointers of same type. You can additionally use <, >, <=, >=, but ***only*** if both pointers point to the same array (or one past last element), otherwise it is undefined behaviour! – Aconcagua Aug 09 '18 at 10:18
1

The problem is simple, this line

 cout << (argv[1] == "nomast" ? "equal" : "not equal") << endl;

gives you not equal as you are comparing char* (pointers) and there are not equal to each other. This comparison is acutaly doing something like 0x00134 == 0x00345 both of these are under different memory adresses.

On the second case with std::strings there is special operator== which will compare you strings by characters which they contain.

To get the same result with first example you would need to do

if (strcmp(argv[1], "nomast") == 0) //need to add #include <string.h>
wdudzik
  • 1,264
  • 15
  • 24
1

You should use strcmp() function to compare two C strings. For C++ strings you can use string::compare.

AndrejH
  • 2,028
  • 1
  • 11
  • 23
0

char *argv[] is a char array that makes a null terminated string, which indeed don't have overloaded == to test equality of the string. When you say == in statement argv[1] == "nomast" its actually comparing pointers.

Where in

string s1 = argv[1];
string s2 = "nomast";

s1 and s2 are string objects. Which have overloaded == to test equality.

To test equality of char string in first case use if (strcmp(argv[1], "nomast") == 0) function or you can write your own function to check equality. However today it is recommended to use standard library std::string for stings.

Rizwan
  • 3,324
  • 3
  • 17
  • 38
  • That's just pure overhead if you don't need the strings afterwards anyway. `std::string` creates copies of, so `strcmp` should be preferred... – Aconcagua Aug 09 '18 at 10:00
  • if C++ is being used its recommended to use std::string. However I support your statement of overhead. – Rizwan Aug 09 '18 at 10:04
  • "*always*" is a bit too strong. Although in general C is preferred for, you could code in C++ as well on microcontrollers. Typically, though, you don't want dynamic memory allocation, so you wouldn't use `std::string` there either (as well as any STL containers with exception of `std::array`)... – Aconcagua Aug 09 '18 at 10:07
  • 1
    My point is: prefer `std::string` wherever you define your own interfaces, classes, etc. Convert a C-string to a `std::string` if you *want or need* to maintain a copy. But if your recive C-strings from unmodifiable API (such as with `main`) and just need read access (comparing, finding first occurence of specific character, ...), use C-API for efficiency. – Aconcagua Aug 09 '18 at 10:14