user126865
user126865

Reputation: 319

Comparing String Elements vs Strings

The following code prints

1
0

And I've been wondering why the values are different if the comparisons are using the same string… I've been struggling with this for a while and cannot figure out why they return different boolean values.

int main()
{
    string stringArray[] = { "banana","Banana","zebra","apple","Apple","Zebra","cayote" };

    cout << (stringArray[1] < stringArray[0]) << endl;
    cout << ("Banana" < "banana") << endl;

    return 0;
}

Upvotes: 12

Views: 1260

Answers (3)

NathanOliver
NathanOliver

Reputation: 180500

"Banana" < "banana" is not comparing the contents of the strings. It is comparing the pointers that "Banana" and "banana" resolve to.

To compare cstyle strings without converting them to a std::string you can use strcmp().

Upvotes: 8

Christian Hackl
Christian Hackl

Reputation: 27528

string stringArray[] = { "banana","Banana","zebra","apple","Apple","Zebra","cayote" };

This means that you get a bunch of std::string objects, created from char const*s resulting from the individual string literals.

Consider a single std::string initialisation:

std::string s = "...";

The literal on the right is of type char const[4]. It "decays" to a char const* used by std::string's constructor.

The same happens when you initialize an array of std::string objects from string literals.

cout << (stringArray[1] < stringArray[0]) << endl;

For std::string, using the < operator means lexicographical comparison. Therefore, this uses lexicographical comparison and has the expected result.

cout << ("Banana" < "banana") << endl;

In this case, there is no std::string involved. You compare two char const[7] with each other.

What does this mean? A completely different thing, as it turns out. Both arrays "decay" to a char const* to their first element. The result of comparing two unrelated pointers with < is unspecified. You are lucky to receive 0 as a result, because you may as well receive 1 and not notice the error. Compilers can also generate a warning for this, for example:

warning: comparison with string literal results in unspecified behaviour

So, as you can see, this operation has absolutely nothing to do with lexicographical comparison.

One way to solve this problem is to turn at least one of the operands into an std::string:

cout << (string("Banana") < "banana") << endl;

A < comparison between an std::string and a char const* (or vice versa) is defined to be lexicographical.

Upvotes: 7

Emil Laine
Emil Laine

Reputation: 42828

stringArray[n] is an std::string, but "Banana" is a string literal (an array of chars).

When you do "Banana" < "banana", both string literals are implicitly converted to char pointers pointing to the char array. < then compares those memory addresses.

Upvotes: 17

Related Questions