Question about strcmp - c++

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);

Related

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

Problems with transforming a c++ string to a const char *

I am trying to make a pointer to a constant character array from a c++ string.
In the last four lines, I am adding the three strings to one string. This should be used to create a pointer to a constant array. This pointer should then be returned to be used in another function. When I am debugging step by step, the "cout" at the end of the function shows the correct behaviour. When I am looking at the returned value in the main function, it points to garbage data. What am I doing wrong while returning the pointer?
const char *checkMultiID(void){
string startID = "USB0::0x2A8D::0x0101::";
string usbID = "MY54500604";
string endID = "::0::INSTR";
char answerID;
int correctFunctionInput = 0;
cout << "ID = " << usbID << "? [Y/N]" << endl;
scanf("%c", &answerID);
while(correctFunctionInput == 0){
if ((answerID == 'Y') || (answerID == 'N')){
correctFunctionInput = 1;
}
else{
cout << "Incorrect Input. Please repeat." << endl;
scanf("%c", &answerID);
}
}
if (answerID == 'N'){
cout << "Please Type in the ID like MY..." << endl;
getline (cin, usbID);
}
string fullID = startID + usbID + endID;
const char *idChar = &fullID[0];
cout << idChar << endl;
return idChar;
}
You are returning a pointer to data which is handled by a container, the c++ string, which is going out of scope, therefore is being deconstructed at the end of the function. What you want to do to get the exact behavior you describe is use a heap allocation, like so:
char* result = new char[fullID.length()+1];
std::copy(string.c_str(),string.c_str()+fullID.length()+1,result);
What you should to is return the c++ string directly, because I guarantee you that you will forget to deallocate this string eventually.
const string checkMultiID(){
return fullID;
}
You can add static keyword to fullID like :
static string fullID = startID + usbID + endID;
Better option would be to just return string.
Edit:
1201programalarm is right.
To avoid this you can do :
static string fullID;
fullID = startID + usbID + endID;
In this case after second call of checkMultiID() value from the first call will be deleted.
If you change function return type to std::string then you can just return fullID and in another function call c_str() method of returned string.
const char * result = checkMultiID().c_str();
This will solve your problem and it's the simplest solution.

Trying to check entered text versus my own custom answers

here is what I attempted to throw together, unfortunately it's not doing what I want it to. What I want it to be doing is checking the entered text vs a few words that I consider correct. So, for example, if I want the only correct answers to be "thanks" or "please", how would I make the program check if the word the user entered is either "thanks" or "please"?
I have a feeling I can't just write B == 'funs etc.
help me out please:
#include <iostream>
using namespace std;
int main ()
{
string B;
for (;;)
{cout << "enter text here" << '\n' ;
cin >> B ;
if (B == 'fUNS'|| B == 'funs' || B == 'funzies')
{
cout << "correct!!!!!!" << endl;
break;
}
else
{
cout << "sorry, please try again" << endl;
continue;
}
}
return 0;
}
Unlike some languages using ' or " to enclose a sequence of characters produces very different results.
A single quote defines a single character literal e.g:
char a = 'A';
You can use multiple characters to define the value of an integer (although this is non-standard):
int a = 'ABCD';
A double quote defines a string literal which is a sequence of characters in an array:
const char str[5] = "ABCD";
Note the literal has a hidden null character at the end which is why it has 5 elements rather than 4. String literals are comparable and assignable with std::string:
std::string test( "ABCD" );
std::cout << test == "ABCD";
test = "EFGH";
std::cout << test == "ABCD";
I have a feeling I can't just write B == 'funs etc.
Yes, you can, since B is a std::string, which has an operator== defined. You just need to use " (which is used to define string literals) instead of ' (which is used to define character literals), eg:
if (B == "fUNS" || B == "funs" || B == "funzies")

Difference between string.empty and string[0] == '\0'

Suppose we have a string
std::string str; // some value is assigned
What is the difference between str.empty() and str[0] == '\0'?
C++11 and beyond
string_variable[0] is required to return the null character if the string is empty. That way there is no undefined behavior and the comparison still works if the string is truly empty. However you could have a string that starts with a null character ("\0Hi there") which returns true even though it is not empty. If you really want to know if it's empty, use empty().
Pre-C++11
The difference is that if the string is empty then string_variable[0] has undefined behavior; There is no index 0 unless the string is const-qualified. If the string is const qualified then it will return a null character.
string_variable.empty() on the other hand returns true if the string is empty, and false if it is not; the behavior won't be undefined.
Summary
empty() is meant to check whether the string/container is empty or not. It works on all containers that provide it and using empty clearly states your intent - which means a lot to people reading your code (including you).
Since C++11 it is guaranteed that str[str.size()] == '\0'. This means that if a string is empty, then str[0] == '\0'. But a C++ string has an explicit length field, meaning it can contain embedded null characters.
E.g. for std::string str("\0ab", 3), str[0] == '\0' but str.empty() is false.
Besides, str.empty() is more readable than str[0] == '\0'.
Other answers here are 100% correct. I just want to add three more notes:
empty is generic (every STL container implements this function) while operator [] with size_t only works with string objects and array-like containers. when dealing with generic STL code, empty is preferred.
also, empty is pretty much self explanatory while =='\0' is not very much.
when it's 2AM and you debug your code, would you prefer see if(str.empty()) or if(str[0] == '\0')?
if only functionality matters, we would all write in vanilla assembly.
there is also a performance penalty involved. empty is usually implemented by comparing the size member of the string to zero, which is very cheap, easy to inline etc. comparing against the first character might be more heavy. first of all, since all strings implement short string optimization, the program first has to ask if the string is in "short mode" or "long mode". branching - worse performance. if the string is long, dereferencing it may be costly if the string was "ignored" for some time and the dereference itself may cause a cache-fault which is costly.
empty() is not implemented as looking for the existence of a null character at position 0, its simply
bool empty() const
{
return size() == 0 ;
}
Which could be different
Also, beware of the functions you'll use if you use C++ 11 or later version:
#include <iostream>
#include <cstring>
int main() {
std::string str("\0ab", 3);
std::cout << "The size of str is " << str.size() << " bytes.\n";
std::cout << "The size of str is " << str.length() << " long.\n";
std::cout << "The size of str is " << std::strlen(str.c_str()) << " long.\n";
return 0;
}
will return
The size of str is 3 bytes.
The size of str is 3 long.
The size of str is 0 long.
You want to know the difference between str.empty() and str[0] == '\0'. Lets follow the example:
#include<iostream>
#include<string>
using namespace std;
int main(){
string str, str2; //both string is empty
str2 = "values"; //assigning a value to 'str2' string
str2[0] = '\0'; //assigning '\0' to str2[0], to make sure i have '\0' at 0 index
if(str.empty()) cout << "str is empty" << endl;
else cout << "str contains: " << str << endl;
if(str2.empty()) cout << "str2 is empty" << endl;
else cout << "str2 contains: " << str2 << endl;
return 0;
}
Output:
str is empty
str2 contains: alues
str.empty() will let you know the string is empty or not and str[0] == '\0' will let you know your strings 0 index contains '\0' or not. Your string variables 0 index contains '\0' doesn't mean that your string is empty. Yes, only once it can be possible when your string length is 1 and your string variables 0 index contains '\0'. That time you can say that, its an empty string.
C++ string has the concept of whether it is empty or not. If the string is empty then str[0] is undefined. Only if C++ string has size >1, str[0] is defined.
str[i] == '\0' is a concept of the C-string style. In the implementation of C-string, the last character of the string is '\0' to mark the end of a C-string.
For C-string you usually have to 'remember' the length of your string with a separate variable. In C++ String you can assign any position with '\0'.
Just a code segment to play with:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
char str[5] = "abc";
cout << str << " length: " << strlen(str) << endl;
cout << "char at 4th position: " << str[3] << "|" << endl;
cout << "char at 5th position: " << str[4] << "|" << endl;
str[4]='X'; // this is OK, since Cstring is just an array of char!
cout << "char at 5th position after assignment: " << str[4] << "|" << endl;
string cppstr("abc");
cppstr.resize(3);
cout << "cppstr: " << cppstr << " length: " << cppstr.length() << endl;
cout << "char at 4th position:" << cppstr[3] << endl;
cout << "char at 401th positon:" << cppstr[400] << endl;
// you should be getting segmentation fault in the
// above two lines! But this may not happen every time.
cppstr[0] = '\0';
str[0] = '\0';
cout << "After zero the first char. Cstring: " << str << " length: " << strlen(str) << " | C++String: " << cppstr << " length: " << cppstr.length() << endl;
return 0;
}
On my machine the output:
abc length: 3
char at 4th position: |
char at 5th position: |
char at 5th position after assignment: X|
cppstr: abc length: 3
char at 4th position:
char at 401th positon:?
After zero the first char. Cstring: length: 0 | C++String: bc length: 3

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