Inconsistency between C++ std::string::compare() and the operator on string - c++

Given the below piece of C++ code
cout<<("100">"035")<<"\n";
cout<<("100"<"035")<<"\n";
string str = "100";
cout<<str.compare("035");
The output of this code is
0
1
1
Which means "100" < "035" by the operator but "100" > "035" by the compare function. Is there any known implementation differences of these two?
P.S. "100" > "035" definitely makes more sense.

C-String literals (such as "100") compare themselves as pointer.
std::string comparison compare content lexicography.
If you want consistent results:
using namespace std::string_literals;
std::cout << ("100"s > "035"s)<<"\n";
std::cout << ("100"s < "035"s)<<"\n";
std::string str = "100"s;
std::cout << str.compare("035");
"100"s is "equivalent" to std::string("100").

Related

string relational operator comparison vs string::compare() in cpp

In short I am getting different output for string comparison using string::compare() vs relational operator '<' on std::string class objects.
string str = "100";
cout << str.compare("10")<<endl; //prints 1
cout << ("100" < "10") <<endl; //prints 1
Here's the demo url
lexicographically "100" is greater than "10" and hence ("100" <"10") must print 0 since it's false but the output 1 i.e true is not expected.
The str.compare() function returns > 0 which is expected validating "100" > "10".
Why is this happening?
In this statement
cout << ("100" < "10") <<endl;
you are comparing two pointers of the type const char * to which the used string literals are implicitly converted. The result of such a comparison is undefined (At least in the C Standard there is explicitly stated that such operation is undefined).
In fact the above statement is equivalent to
cout << ( &"100"[0] < &"10"[0] ) <<endl;
If you want to compare strings the you need to write at least like
cout << (std::string( "100" ) < "10") <<endl;
In this case the output will be
0
Pay attention to that according to the C++ 20 (7.6.9 Relational operators)
...The comparison is deprecated if both operands were of array type prior to these conversions
And the both string literals prior to comparison have array types.

Concatenate a char into a string [duplicate]

im getting totally confused by this seemingly simple problem.
I have a pain old char, and I want to concatenate it in the middle of a string.
Like so.
string missingOptionArg(char missingArg) {
return "Option -" + missingArg + " requires an operand";
}
I was guessing the + operand was smart enough to deal with this sort of trivial thing, if not, what would be the simplest way of doing this?
To concatenate string literal and char:
std::string miString = std::string("something") + c;
A similar thing happens when you need to concat two strings literals.
Note that "something" is not a std::string, it is a pointer to an array of chars. Then you can't concatenate two string literals using +, that would be adding two pointers and is not what you want.
The correction of your code is in Igor's comment.
Accepted answer is the simplest but other ways to achieve the concatenation.
#include <iostream>
#include <string>
using namespace std;
string missingOptionArgRet(char missingArg) {
string s("Option -");
s += missingArg;
s += " requires an operand";
return s;
}
void missingOptionArgOut(char missingArg, std::string* out) {
*out = "Option -";
*out += missingArg;
*out += " requires an operand";
}
main(int, char**)
{
string s1 = missingOptionArgRet('x');
string s2;
missingOptionArgOut('x', &s2);
cout << "s1 = " << s1 << '\n';
cout << "s2 = " << s2 << '\n';
}
Using += rather than + will prevent temporary string objects. Also there are 2 options. Return by value missingOptionArgRet. This has disadvantage that as a result of return by value the string must be copied to the caller.
The second option missingOptionArgOut can prevent this at the cost of slightly more verbose code. I pass in an already constructed string (by pointer to make it clear its a variable to be modified, but could be passed by reference).

In C++, how do i use like strncmp function in C?

In C++, Isn`t there string function like strncmp() in C ???
for example
string str1 = "abc";
string str2 = "ab";
str2.compare(0,1,str1) == 0
is it possible??
You can compare std::string directly:
if (str1 == str2)
To compare up to length 2, use compare:
if (str2.compare(0, 2, str1) == 0)
You can also use C functions in C++ if you include the corresponding C header, for example to use string.h, include <cstring>.
std::string has overloaded its '==' operator. Just if (a == b) works.
Interestingly even (a < b) works and applies a lexical ordering.
EDIT: Since the TE seems to ask about the equality of the length of strings after all, not their actual letters:
if (str1.length() == str2.length())
{
}
Yes the class std::string has the member function compare declared for you use case like
int compare(size_type pos1, size_type n1, basic_string_view<charT, traits> sv) const;
Here is a demonstrative program that shows using this overloaded member function.
#include <iostream>
#include <string>
int main()
{
std::string str1 = "abc";
std::string str2 = "ab";
std::cout << str2.compare( 0, 1 ,str1) << '\n';
std::cout << str1.compare( 0, 2 , str2) << '\n';
std::cout << str2.compare( str1 ) << '\n';
std::cout << str2.compare( 1, 1, str1 ) << '\n';
return 0;
}
The program output is
-2
0
-1
1
So if two strings are equal then the function returns 0. If the first string is less than the second string then the function returns a negative value. Otherwise the function returns a positive value.

Unable to compare strings in c++ without using variables

I do not get the right answer when I compare the strings in c++ without assigning them to variables.
string a = "286";
string b = "256";
if("286" > "256") cout << "yay";
else cout << "nope";
cout <<endl;
if(a > b) cout << "yay";
else cout << "nope";
Output :
nope
yay
Is it not possible to compare strings without using variables? Why?
Is it not possible to compare strings without using variables?
It is obviously possible, but you need to understand what you are comparing.
When you write this:
"abc" < "cbe"
you compare two const char * so basically you check which address is lower. To compare them as strings you need to convert at least one of them:
std::string( "abc" ) < "cbe"
or more verbose:
static_cast<std::string>( "abc" ) < "cbe"
or use string literals:
using namespace std::string_literals;
"abc"s < "cbe"s
then you will compare 2 std::string objects (like you do when you use named variables).
Slava's answer covers the most proper way to do so in C++, and it's certainly the most readable one - you should prefer it in normal situations.
The other solution (without involving std::string and in style typical to C programming) would be to use std::strcmp:
#include <cstring>
if(std::strcmp("286", "256") == 0)
cout << "yay";
else
cout << "nope";
Note that this is much more unsafe code (behaviou is unspecified if any of the arguments to std::strcmp is not a pointer to null-terminated char array) and arguably less readable.

Concatenate plain char and string?

im getting totally confused by this seemingly simple problem.
I have a pain old char, and I want to concatenate it in the middle of a string.
Like so.
string missingOptionArg(char missingArg) {
return "Option -" + missingArg + " requires an operand";
}
I was guessing the + operand was smart enough to deal with this sort of trivial thing, if not, what would be the simplest way of doing this?
To concatenate string literal and char:
std::string miString = std::string("something") + c;
A similar thing happens when you need to concat two strings literals.
Note that "something" is not a std::string, it is a pointer to an array of chars. Then you can't concatenate two string literals using +, that would be adding two pointers and is not what you want.
The correction of your code is in Igor's comment.
Accepted answer is the simplest but other ways to achieve the concatenation.
#include <iostream>
#include <string>
using namespace std;
string missingOptionArgRet(char missingArg) {
string s("Option -");
s += missingArg;
s += " requires an operand";
return s;
}
void missingOptionArgOut(char missingArg, std::string* out) {
*out = "Option -";
*out += missingArg;
*out += " requires an operand";
}
main(int, char**)
{
string s1 = missingOptionArgRet('x');
string s2;
missingOptionArgOut('x', &s2);
cout << "s1 = " << s1 << '\n';
cout << "s2 = " << s2 << '\n';
}
Using += rather than + will prevent temporary string objects. Also there are 2 options. Return by value missingOptionArgRet. This has disadvantage that as a result of return by value the string must be copied to the caller.
The second option missingOptionArgOut can prevent this at the cost of slightly more verbose code. I pass in an already constructed string (by pointer to make it clear its a variable to be modified, but could be passed by reference).