In C++, how do i use like strncmp function in C? - 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.

Related

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

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").

shuffle letters in a string c++

I'm meant to write a function that keeps the first and last letter of a string the same and ignores any non-letters after the last letter. I'm supposed to use the std::random_shuffle(). I read the documentation however I don't seem to grasp the concept of this function. This is my code:
#include <iostream>
#include <algorithm>
#include <string>
std::string mix(std::string s){
int last_char;
if(std::isalpha(s[s.size()-1]) == true){
last_char = s.size()-1;
} else {
for(int i=s.size()-1 ; i>0; --i){
if((std::isalpha(s[i]) == false) && (std::isalpha(s[i-1])==true)){
last_char = i -1;
break;
}
}
}
std::random_shuffle(&s[1],&s[last_char]);
return s;
}
int main(){
std::string test = "Hello";
std::cout << mix(test) << std::endl;
}
edit: Now however I keep getting the error: segmentation fault(core dumped). ANyone got an idea why? Can't seem to find the problem.
std::random_shuffle takes iterators or pointers, as arguments, not values in the array/container to be sorted. Your call to std::random_shuffle should probably be:
std::random_shuffle(&s[1],&s[last_char]);
Note that the second parameter is the ending iterator value. The ending iterator doesn't point to the last value to sort, but the one after that.
This is not the only problem with the shown code. You'll need to fix several bugs in your code that precedes the call to std::random_shuffle. For example:
for(int i=s.size() ; i>0; --i){
if((std::isalpha(s[i]) == false) && (std::isalpha(s[i-1])==true)){
s.size() gives you the size of the string. On the first iteration, i will be equal to its size(), but accessing s[i] will now result in undefined behavior, and a bug, since s[i] obviously does not exist. In a string that contains n characters, the characters are s[0] through s[n-1], of course.
You will need to fix your algorithm so that last_char ends up being the index of the next character after the one you want to shuffle, and then use the fixed std::random_shuffle call, above.
Or, alternatively, compute last_char to be the index of the last character to sort, and call
std::random_shuffle(&s[1],&s[last_char+1]);
Either approach will be fine.
You'll need to find the leftmost "non-letter" in the right side of your string.
One place to the left of this is the position of the last letter.
One place to the right is your first letter.
Simply invoke random_shuffle with your "first" and "last".
Here are some useful links:
http://www.cplusplus.com/reference/algorithm/random_shuffle/
Remember that "begin" is inclusive, "end" is exclusive"
Something to get you started. It has at least one corner case that you'll have to fix. Visit cppreference.com to understand how the algorithms work.
#include <iostream>
#include <cctype>
#include <algorithm>
#include <string>
std::string
special_shuffle(std::string s)
{
if (s.size() < 3) return s;
auto begin = std::find_if(s.begin(), s.end(), ::isalpha);
auto end = std::find_if(s.rbegin(), s.rend(), ::isalpha).base();
std::random_shuffle(++begin, --end);
return s;
}
int
main()
{
std::string s1 = "Hello World!";
std::string s2 = "AB";
std::string s3 = "A";
std::string s4 = "";
std::string s5 = "a string going from a to z";
std::cout << s1 << " --> " << special_shuffle(s1) << "\n"
<< s2 << " --> " << special_shuffle(s2) << "\n"
<< s3 << " --> " << special_shuffle(s3) << "\n"
<< s4 << " --> " << special_shuffle(s4) << "\n"
<< s5 << " --> " << special_shuffle(s5) << "\n";
}
Compile and run:
$ g++ example.cpp -std=c++14 -Wall -Wextra
$ ./a.out
Hello World! --> Hooll eWlrd!
AB --> AB
A --> A
-->
a string going from a to z --> aarfritomgi nnso t g goz

Evaluating null terminated string [duplicate]

This very simple code:
#include <iostream>
using namespace std;
void exec(char* option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "opzion bar";
else
cout << "???";
cout << endl;
}
int main()
{
char opt[] = "foo";
exec(opt);
return 0;
}
generate two warning: comparison with string literal results in unspecified behaviour.
Can you explain why exactly this code doesn't work, but if I change
char opt[]
to
char *opt
it works, but generates the warning? Is it related to the \0 termination? What is the difference between the two declaration of opt? What if I use const qualifier? The solution is to use std::string?
char arrays or char pointers aren't really the same thing as string class objects in C++, so this
if (option == "foo")
Doesn't compare the string option to the string literal "foo" it compares the address of option with the address of the string literal "foo". You need to use one of the many string comparison functions if you want to know if the option is the same as "foo". strcmp is the obvious way to do this, or you can use std::string instead of char*
You can use == operator to compare strings only if you use std::string (which is a good practice). If you use C-style char*/char[] strings, you need to use C functions strcmp or strncmp.
You can also use the std::string::operator == to compare std::string with a C string:
std string foo = "foo";
const char *bar = "bar";
if (foo == bar)
...
The reason why it doesn't work is because the comparison does not compare strings, but character pointers.
The reason why it may work when you use char* is because the compiler may decide to store the literal string "opt" once and reuse it for both references (I am sure I have seen a compiler setting somewhere that indicates whether the compiler does this).
In the case of char opt[], the compiler copies the string literal to the storage area reserved for the opt array (probably on the stack), which causes the pointers to be different.
Renze
For C++ I would use the std::string solution:
#include <iostream>
#include <string>
using namespace std;
void exec(string option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "option bar";
else
cout << "???";
cout << endl;
}
int main()
{
string opt = "foo";
exec(opt);
exec("bar");
char array[] = "other";
exec(array);
return 0;
}
std::string knows how to create itself out of char[], char*, etc, so you can still call the function in these ways, too.

Question about strcmp

For example we have two strings:
string s = "cat";
string s1 = "dog";
Is it correct to write the following method?
int a = strcmp(s, s1);
Or what will be correct form?
C++'s std::string can be compared directly, so you could just write e.g.
if (s == s1)
cout << "the strings are equal" << endl;
else if (s < s1)
cout << "the first string is smaller" << endl;
else
...
But if you really need the integer value, you could use the .compare method.
int a = s.compare(s1);
Just for completeness, while you should use the built-in string functions when you can, there are common situations where you often need to compare a C-style null terminated string to a C++ string. For instance you will constantly run into situations where a system call returns a pointer to a C-string.
You can choose to turn the C-string into a C++ string and compare them
string s1 = "cat";
string s2 = "dog";
const char *s3 = "lion";
if (s1 == string(s3))
cout << "equal" << endl;
else
cout << "not equal" << endl;
or compare the C++'s underlying C-string to the other C-string:
a = strcmp(s1.c_str(), s3);

comparison between string literal

This very simple code:
#include <iostream>
using namespace std;
void exec(char* option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "opzion bar";
else
cout << "???";
cout << endl;
}
int main()
{
char opt[] = "foo";
exec(opt);
return 0;
}
generate two warning: comparison with string literal results in unspecified behaviour.
Can you explain why exactly this code doesn't work, but if I change
char opt[]
to
char *opt
it works, but generates the warning? Is it related to the \0 termination? What is the difference between the two declaration of opt? What if I use const qualifier? The solution is to use std::string?
char arrays or char pointers aren't really the same thing as string class objects in C++, so this
if (option == "foo")
Doesn't compare the string option to the string literal "foo" it compares the address of option with the address of the string literal "foo". You need to use one of the many string comparison functions if you want to know if the option is the same as "foo". strcmp is the obvious way to do this, or you can use std::string instead of char*
You can use == operator to compare strings only if you use std::string (which is a good practice). If you use C-style char*/char[] strings, you need to use C functions strcmp or strncmp.
You can also use the std::string::operator == to compare std::string with a C string:
std string foo = "foo";
const char *bar = "bar";
if (foo == bar)
...
The reason why it doesn't work is because the comparison does not compare strings, but character pointers.
The reason why it may work when you use char* is because the compiler may decide to store the literal string "opt" once and reuse it for both references (I am sure I have seen a compiler setting somewhere that indicates whether the compiler does this).
In the case of char opt[], the compiler copies the string literal to the storage area reserved for the opt array (probably on the stack), which causes the pointers to be different.
Renze
For C++ I would use the std::string solution:
#include <iostream>
#include <string>
using namespace std;
void exec(string option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "option bar";
else
cout << "???";
cout << endl;
}
int main()
{
string opt = "foo";
exec(opt);
exec("bar");
char array[] = "other";
exec(array);
return 0;
}
std::string knows how to create itself out of char[], char*, etc, so you can still call the function in these ways, too.