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.
Related
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").
This is my first question here, so I've done my best to make this a good question.
I am creating a program that essentially takes user input and converts all characters to uppercase. I am using a for-loop to scan for lowercase characters using corresponding ASCII codes.
I am able to do this just fine using a character array that is assigned a string in-code: char text[] = "Text".
I want to be able to take user input and use it in the character array. I tried using getline(cin,myString) and assigning the character array with that, but it says array must be initialized with a brace enclosed initializer.
I kept the character array uninitialized because sizeof(text) isn't giving the correct size when the array is initialized. I was reading about using pointers but I'm still a bit fresh on that topic. Below is the code I wrote:
int main() {
// User input as a string
char textConvert[] = "This text will be converted to uppercase.";
cout << textConvert << endl;
int endChar = sizeof(textConvert); //Only gives correct size when array is uninitialized
for (int i = 0; i < endChar; i++) {
if (textConvert[i] >= 97 && textConvert[i] <= 122) {
textConvert[i] = textConvert[i] - 32;
}
}
cout << textConvert;
return 0;
}
Question:
I tried using getline(cin,myString) and assigning the character array with that, but it says array must be initialized with a brace enclosed initializer
Here the compiler works out the size of the array needed.
char textConvert[] = "This text will be converted to uppercase.";
If you want user input you need to allocate an array and specify size.
char textConvert[50];
Now you can read a line and copy it into the array:
std::string myString;
std::getline(std::cin , myString);
// Should check that the string is not more than 50 characters.
std::copy(std::begin(myString), std::end(myString), textConvert);
But really there is no need to do this at all. Just use the std::string and loop over the string. Best to avoid C constructs like arrays and use the C++ constructs that stop you making errors.
Size of String
This is not a good idea.
int endChar = sizeof(textConvert);
This measures the size of the array (not the size of the string). There is also an issue that arrays will very easily decay into pointers. When this happens sizeof() will give you the size of the pointer (probably 4 or 8) not the size of the array.
To get the size of a string use std::strlen() (include <cstring>).
But really you should be using std::string the C++ version of string that does its own memory management and re-sizes as required.
Magic Numbers
Prefer not to use magic numbers:
if (textConvert[i] >= 97 && textConvert[i] <= 122) {
textConvert[i] = textConvert[i] - 32;
}
These magic numbers make the code hard to read. You can use character constants instead.
if (textConvert[i] >= 'a' && textConvert[i] <= 'z') {
textConvert[i] = textConvert[i] - ('a' - 'A');
}
Prefer the standard Library
But doing this manually is not recommended. You should use the standard library routines.
std::islower() . // Check if a character is lower case.
std::toupper() . // Convert a lowercase character to upper.
// include <cctype>
C++ Example
Try this:
#include <iostream>
#include <string>
#include <cctype>
int main()
{
std::string myString;
while(std::getline(std::cin, myString)) {
std::cout << "User Input: " << myString << "\n";
for(auto& c: myString) {
c = std::toupper(c);
}
std::cout << "Upper Case: " << myString << "\n";
}
}
Since you are dealing with ASCII, you can just use std::toupper.
No need to write custom code to do it, the standard library has you covered.
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).
I have a question:
Let's say there are two std::strings and I want to compare them, there is the option of using the compare() function of the string class but I also noticed that it is possible using simple < > != operators (both of the cases are possible even if I don't include the <string> library).
Can someone explain why the compare() function exists if a comparison can be made using simple operators?
btw I use Code::Blocks 13.12
here is an example of my code:
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::getline;
int main()
{
string temp1, temp2;
cout << "Enter first word: ";
getline (cin,temp1);
cout << "Enter second word: ";
getline (cin,temp2);
cout << "First word: " << temp1 << endl << "Second word: " << temp2 << endl;
if (temp1 > temp2)
{
cout << "One" << endl;
}
if (temp1.compare(temp2) < 0)
{
cout << "Two" << endl;
}
return 0;
}
.compare() returns an integer, which is a measure of the difference between the two strings.
A return value of 0 indicates that the two strings compare as equal.
A positive value means that the compared string is longer, or the first non-matching character is greater.
A negative value means that the compared string is shorter, or the first non-matching character is lower.
operator== simply returns a boolean, indicating whether the strings are equal or not.
If you don't need the extra detail, you may as well just use ==.
string cat = "cat";
string human = "human";
cout << cat.compare(human) << endl;
This code will give -1 as a result. This is due to the first non-matching character of the compared string 'h' is lower or appears after 'c' in alphabetical order, even though the compared string, 'human' is longer than 'cat'.
I find the return value described in cplusplus.com is more accurate which are-:
0 : They compare equal
<0 : Either the value of the first character that does not match is lower in the compared string, or all compared characters match but the compared string is shorter.
more than 0 : Either the value of the first character that does not match is greater in the compared string, or all compared characters match but the compared string is longer.
Moreover, IMO cppreference.com's description is simpler and so far best describe to my own experience.
negative value if *this appears before the character sequence specified by the arguments, in lexicographical order
zero if both character sequences compare equivalent
positive value if *this appears after the character sequence specified by the arguments, in lexicographical order
Regarding the question,
” can someone explain why the compare() function exists if a comparison can be made using simple operands?
Relative to < and ==, the compare function is conceptually simpler and in practice it can be more efficient since it avoids two comparisons per item for ordinary ordering of items.
As an example of simplicity, for small integer values you can write a compare function like this:
auto compare( int a, int b ) -> int { return a - b; }
which is highly efficient.
Now for a structure
struct Foo
{
int a;
int b;
int c;
};
auto compare( Foo const& x, Foo const& y )
-> int
{
if( int const r = compare( x.a, y.a ) ) { return r; }
if( int const r = compare( x.b, y.b ) ) { return r; }
return compare( x.c, y.c );
}
Trying to express this lexicographic compare directly in terms of < you wind up with horrendous complexity and inefficiency, relatively speaking.
With C++11, for the simplicity alone ordinary less-than comparison based lexicographic compare can be very simply implemented in terms of tuple comparison.
I have searched for this error but noone seems to be having the same problem as me. I am trying to make a basic text based RPG game in C++ to learn, and I want the user to be able to type what they want to do, for example if they type ATTACK they will attack the monster, but my if statement:
if((current_move == "ATTACK") || (current_move == "attack"))
returns false!
Here is the full function below:
while(monster_health > 0)
{
std::cin >> current_move;
std::cout << current_move;
if((current_move == "ATTACK") || (current_move == "attack"))
{
std::cout << "You attacked the monster!\n";
double damage = return_level(xp) * 1.2;
std::cout << "You did " << damage << " damage!\n";
monster_health -= damage;
if(monster_health < 0)
{
monster_health = 0;
break_out = true;
}
}
else if(current_move == "FLEE")
{
std::cout << "You ran away...\n";
break_out = true;
}
else
{
std::cout << "Sorry, I didn't understand, what will you do? ATTACK or FLEE?\n";
}
}
I just keep getting "Sorry, I didn't understand" message;
Please let me know of any other errors or bad practises as I've only just started learning :)
What's the type of current_move? If it's char* (or char[]), you are comparing pointers, not strings. Better use std::string for current_move, then the comparison with == will work intuitively.
You need to add #include <string>. (In MSVC certain parts of strings also work without that, but it's nonstandard and leads to errors e.g. when passing strings to cout).
If you're using a C string (char[]), you need to use strcmp() to compare it. If the two strings are equivalent, it will return 0.
if (strcmp(current_move, "ATTACK") == 0) will return true if they match.
You need to do current_move==string("attack") otherwise you will be comparing pointers. String operator == or strncmp, either one or the other...
Your problem is that you are comparing C strings. When you do == on them, you are comparing the pointer of the two, which in this code is useless to do.
My suggestion would be to just change the type of current_move to std::string and it will just work. Then you will be comparing the contents, not the pointers.