slugo
slugo

Reputation: 1039

Comparing strings lexicographically

I thought that if I used operators such as ">" and "<" in c++ to compare strings, these would compare them lexicographically, the problem is that this only works sometimes in my computer. For example

if("aa" > "bz") cout<<"Yes";

This will print nothing, and thats what I need, but If I type

if("aa" > "bzaa") cout<<"Yes";

This will print "Yes", why is this happening? Or is there some other way I should use to compare strings lexicographically?

Upvotes: 30

Views: 57827

Answers (4)

C++20 operator<=> (spaceship operator) allows you to get <, == or > in one go

This is another related feature that is of interest for Googlers:

main.cpp

#include <cassert>
#include <string>

int main() {
    std::string aa = "aa", ab = "ab";
    assert(((aa <=> aa) == 0));
    assert(((aa <=> ab)  < 0));
    assert(((ab <=> aa)  > 0));
}

Compile and run:

g++ -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o main.out main.cpp
./main.out

Note that in this case, you can only compare the output of <=>, which is a std::strong_ordering object, with 0 and nothing else. E.g. if you attempt:

((aa <=> aa) == 1)

if fails with a 119 line long error message that we so much love from C++ starting with:

main.cpp: In function ‘int main()’:                                                                                                                                                           main.cpp:6:25: error: no match for ‘operator==’ (operand types are ‘std::strong_ordering’ and ‘int’)
    6 |     assert(((aa <=> aa) == 1));                                                                                                                                                       
      |             ~~~~~~~~~~~ ^~ ~                                                                                                                                                          
      |                 |          |                                                                                                                                                          
      |                 |          int                                                                                                                                                        
      |                 std::strong_ordering                                                   
In file included from /usr/include/c++/13/string:43,                             
                 from main.cpp:2:

This is mentioned e.g. at: https://en.cppreference.com/w/cpp/utility/compare/strong_ordering

The behavior of a program that attempts to compare a strong_ordering with anything other than the integer literal ​0​ is undefined.

Related broader question: What is the <=> ("spaceship", three-way comparison) operator in C++?

Tested on Ubuntu 24.04, GCC 13.2.0.

Upvotes: 0

Ivaylo Strandjev
Ivaylo Strandjev

Reputation: 71009

Comparing std::string -s like that will work. However you are comparing string literals. To do the comparison you want either initialize a std::string with them or use strcmp:

if(std::string("aa") > std::string("bz")) cout<<"Yes";

This is the c++ style solution to that.

Or alternatively:

if(strcmp("aa", "bz") > 0) cout<<"Yes";

EDIT(thanks to Konrad Rudolph's comment): in fact in the first version only one of the operands should be converted explicitly so:

if(std::string("aa") > "bz") cout<<"Yes";

Will again work as expected.

EDIT(thanks to churill's comment): since c++14 you can use string literals:

if("aa"s > "bz") cout<<"Yes";

Upvotes: 40

AngryParticle
AngryParticle

Reputation: 1549

You can use strcmp() function which is included in the #include <cstring> header file. strcmp() compares the two strings character by character. The process will continue until it reaches NULL or one of the strings become unequal (characters become unequal). For example:

#include <iostream>
#include <cstring>


void display(char *lhs, char *rhs, int result)
{
    if(result > 0)
        std::cout << rhs << " precedes " << lhs << std::endl;
    else if (result < 0)
        std::cout << lhs << " precedes " << rhs << std::endl;
    else
        std::cout << lhs << " and " << rhs << " are same" << std::endl;
}

int main()
{
    char lhs[] = "aa";
    char rhs[] = "bz";
    int result;

    result = strcmp(lhs,rhs);
    display(lhs,rhs,result);

    result = strcmp(lhs,lhs);
    display(lhs,lhs,result);

    return 0;
}

Output:

aa precedes bz
aa and aa are same

Upvotes: 0

Brent Bradburn
Brent Bradburn

Reputation: 55019

You are comparing "primitive" strings, which are of type char const *.

The following is essentially equivalent to your example:

char const * s1 = "aa";
char const * s2 = "bz";
if ( s1 > s2 ) cout<<"Yes";

This is comparing the pointers (the memory addresses of the strings), not the contents.

@izomorphius has suggested some good solutions.

Upvotes: 7

Related Questions