Сравнение String Elements vs Strings

Следующий код печатает

1
0

И мне было интересно, почему значения разные, если сравнения используют одну и ту же строку... Я некоторое время боролся с этим и не могу понять, почему они возвращают разные логические значения.

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

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

    return 0;
}

Ответ 1

stringArray[n] является std::string, но "Banana" является строковым литералом (массив из char s).

Когда вы выполняете "Banana" < "banana", оба строковых литерала неявно преобразуются в указатели char, указывающие на массив char. < затем сравнивает эти адреса памяти.

Ответ 2

"Banana" < "banana" не сравнивает содержимое строк. Это сравнение указателей, для которых "Banana" и "Banana" разрешено.

Чтобы сравнить строки cstyle без их преобразования в std::string, вы можете использовать strcmp().

Ответ 3

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

Это означает, что вы получаете кучу объектов std::string, созданных из char const*, полученных из отдельных строковых литералов.

Рассмотрим одиночную инициализацию std::string:

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

Литерал справа имеет тип char const[4]. Он "распадается" на char const*, используемый конструктором std::string.

То же самое происходит, когда вы инициализируете массив объектов std::string из строковых литералов.

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

Для std::string использование оператора < означает лексикографическое сравнение. Поэтому это использует лексикографическое сравнение и имеет ожидаемый результат.

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

В этом случае не участвует std::string. Вы сравниваете два char const[7] друг с другом.

Что это значит? Как оказалось, совершенно другая вещь. Оба массива "распадаются" на char const* до их первого элемента. Результатом сравнения двух несвязанных указателей с < является неуказанный. Вам посчастливилось получить 0 в результате, потому что вы также можете получить 1 и не заметить ошибку. Компиляторы также могут генерировать предупреждение для этого, например:

warning: comparison with string literal results in unspecified behaviour

Итак, как вы можете видеть, эта операция не имеет абсолютно никакого отношения к лексикографическому сравнению.

Один из способов решения этой проблемы - повернуть хотя бы один из операндов в std::string:

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

A < сравнение между std::string и a char const* (или наоборот) определяется как лексикографическое.