C++ if statements using strings not working as intended - c++

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.

Related

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.

Issue Comparing strings for an Answer Key (C++)

I'm working on a midterm project for my coding class, and while I've gotten the majority of kinks worked out I'm struggling with comparing two string values and determining if they are equal or not. The strings in question are ANSWERKEYand studentAnswers. The former is a constant that the latter is compared to.
The code in question is as follows.
if (studentAnswers == ANSWERKEY)
{
percentScore = 100.0;
cout << "Score: " << percentScore << " % " << 'A' << endl;
}
else if (studentAnswers != ANSWERKEY)
{
int count = 0;
double answerCount = 0.0;
while (count < ANSWERKEY.length())
{
if (studentAnswers.substr(count, count+1) == ANSWERKEY.substr(count, count+1)
{
answerCount++;
count++;
}
else
{
cout << "Incorrect answer." << endl;
count++;
}
}
percentScore = ((answerCount) / (double)ANSWERKEY.length()) * 100.0;
cout << "Percent score is " << percentScore << "%" << endl;
}
The exact issue I'm facing is that I can't work out a better way to compare the strings. With the current method, the output is the following:
The intro to the code runs fine. Only when I get to checking the answers against the key, in this case "abcdefabcdefabcdefab", do I run into issues. Regardless of what characters are changed, the program marks roughly half of all characters as mismatching and drops the score down because of it.
I've thought of using a pair of arrays, but then I can't find a solution to setting up the array when some values of it are empty. If the student's answers are too short, e.g. only 15 characters long, I don't know how to compare the blank space, or even store it in the array.
Thank you for any help you can give.
First:
if (studentAnswers == ANSWERKEY)
{...}
else if (studentAnswers != ANSWERKEY)
{ ...}
looks like an overkill when comparing strings. And where is the else part ?
Second, this is risky. Read the IEE754 and articles about cancellation, or even SO:
double answerCount = 0.0;
...
answerCount++
Third:
You are checking character by character using substr. To me it feels like using a hammer to kill a bacteria.
studentAnswers.substr(count, count+1) == ANSWERKEY.substr(count, count+1)
Fourth:
What if studentAnswers is shorter than ANSWERKEY ?
Conclusion:
You need to clarify inputs/expected outputs and use the debugger to better understand what is happening during execution. Carefully check all your variables at each step fo your program.

Is this the right way to loop through Arrays?

#include <iostream>
#include <Windows.h>
#include <string>
using namespace std;
int main(){
string Whitelist[4] = {"Stian", "Mathias", "Modaser"};
for (int x = 0; x < 3; x++){
cout << x + 1<< ". " << Whitelist[x] << endl;
if (Whitelist[x] == "Stian" && "Mathias" && "Modaser"){
cout << "" << Whitelist[x] << " is here" << endl;
}
else{ cout << "no one is here" << endl; }
}
cin.get();
return 0;
}
//so yeah basically im just trying to loop through my array and see if any of these names are there. so i guess u can pretty much read what the code does since most of u are pros :P. but when i asked my friend, whos been coding for 1-2 years, he said that i couldnt loop through arrays like this and told me to use a vector. what does he mean by that? and my code works?
This set of code is wrong
if (Whitelist[x] == "Stian" && "Mathias" && "Modaser"){
cout << "" << Whitelist[x] << " is here" << endl;
}
Why? because suppose the first condition of the if statement evaluates to true like this:
if (true && "Mathias" && "Modaser")
{
//...
}
Then the code wouldn't make sense. In an if statement, you have to check for every condition separately, like this:
if (Whitelist[x] == "Stian" && Whitelist[x] =="Mathias" && Whitelist[x] =="Modaser"){
cout << "" << Whitelist[x] << " is here" << endl;
}
But since any 1 string cannot be three names at the same time, this condition will fail, (you used &&). Fix your code using the || operator, like this, for your final code (Also, remove << "", that is just redundant, and unnecessary):
if (Whitelist[x] == "Stian" || Whitelist[x] =="Mathias" || Whitelist[x] =="Modaser"){
cout << Whitelist[x] << " is here" << endl;
}
BTW: As a recommendation, use a std::vector<std::string>, not a raw array, so you get easier and more capabilities than an array.
Lastly, you also have 4 elements in your array, of which one is unused. It might be a typo, so make your array size 3.
There is nothing fundamentally wrong with looping over an array like this.
We can only guess what your friend meant, but I can perform my own review of your code.
However, you have four array elements and only loop over three of them, which may be a mistake; if it is, it's evidence that you'd be better off using iterators, rather than hard-coding numbers that you can get wrong.
Furthermore, your if conditional is wrong: did you mean || ("or"), instead of && ("and")? And you have to write out the adjoined conditions in full, so:
if (Whitelist[x] == "Stian" || Whitelist[x] =="Mathias" || Whitelist[x] =="Modaser")
I'm not sure why you're comparing against all these values, when they're the only ones in the array. Well, except for that empty fourth element; perhaps you're trying to catch that. We don't know, because you didn't tell us. Did you mean to search Whitelist while iterating over some other array? We have no way of knowing. Maybe that's what your friend really meant? Again, I couldn't say.
Streaming "" to std::cout just waits resources and does literally nothing else. Remove it.
Finally, and somewhat tangentially, it would be better not to block waiting for input as a means to keep your console window open. That is not your program's job.

How do I add elements to two different arrays inside of a loop based on parameters without using the STL?

I'm very new to C++, so please let me know if there is an easier way to accomplish what I'm trying to do.
Basically I am checking for two different types of input commands on the command line. If the user enters a C followed by an integer(1 in this case) (I don't need error checking) its supposed to add "C 1" to my first array. If they type A 1 2 400 then it supposed to add that to a second array.
In java I would simply type
if (input.contains("c")){
cityArray.add(input)
else if (input.contains ("a"){
routeArray.add(input)
}
or something along those lines.
Here is what I have in C++
while(loopCheck == false )
{
cout << "Please Enter A Command:> " << endl;
cin >> Input;
if((cin >> c) ){
cout << "Citys: " << city[] << endl;
}
if (cin == " "){
loopCheck = true;
}
}
It is really not much different than in Java. Here is an example of input handling with a switch statement. You can try it as an if clause as exercise.
#include <iostream>
int main()
{
std::string line;
bool stop = false;
while (!stop && getline(std::cin, line)) {
switch (line[0]) {
case 'C':
// add to first array
std::cout << "Case 'C': '" << line << "'\n";
break;
case 'A':
// add to second array
std::cout << "Case 'A': '" << line << "'\n";
break;
default:
stop = true;
break;
}
}
}
I skipped the part with inserting in an array and you should think about what you are allowed or supposed to use. Since you are not allowed to use the STL you should look into your class notes and problem statement what you have learned about arrays (dynamic and static ones).
Keep in mind, that you would not not use the STL in todays C++ applications.
For the moment I'm going to assume that the C++ code you have in the question doesn't matter much, and you're primarily looking for a reasonable analog of the Java code you included. In that case, C++ code intended to look similar to your Java code might look something like this:
std::string input;
std::vector<std::string> cityArray;
std::vector<std::string> routeArray;
// ...
if (input.find('c') != std::string::npos) {
cityArray.push_back(input);
}
else if (input.find('a') != std::string::npos) {
routeArray.push_back(input);
}
If I were personally writing it in C++, I'd probably do something more like this though:
std::map<char, std::vector<std::string>> arrays;
// ...
arrays[input[0]].push_back(input);
Another possibility (that eliminates using vector) would be to use an std::multimap instead:
std::multimap<char, std::string> arrays;
arrays.insert(std::make_pair(input[0], input));
As to not being allowed to use the standard library: knock your teacher over the head with a clue stick. Without using the standard library you can't read any input or produce any output (just for a couple of examples) so for any practical purpose, your code can't do anything at all. You might as well just write every program as int main() {} and be done with it, because that's equivalent to essentially anything you can do without the standard library.

string program for ice cream shop (Edited again) [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
With the assistance of others, I have redone the code from scratch due to them pointing out numerous errors and things that wouldn't work. Thus I have changed the code massively.
I have the program working other than two formatting settings that I can't figure out how to get to work.
I need to only print "DAILY SCOOP REPORT" once at the top of the output, but I've moved it around but due to the way the arrays are set up I don't know where to put it.
Here is my code:
#include <iostream>
include
include
include
include
include
using namespace std;
int main()
{
string flavor_input, Capitalize;
string flavors[] = { "Chocolate", "Vanilla", "Strawberry", "Mint", "Rocky Road", "Mocha" };
int scoop_count [6] = { 0, 0, 0, 0, 0, 0 }, scoops = 0, j, k;
bool valid_option;
cout << "Welcome to Frozen Tongue Ice Cream Shop\n"<<endl;
cout << "Flavors avaliable: "<<endl;
cout << "Chocolate "<<endl;
cout << "Valnilla "<<endl;
cout << "Strawberry "<<endl;
cout << "Mint "<<endl;
cout << "Rocky Road "<<endl;
cout << "Mocha \n"<<endl;
while(true) {
cout << "Please enter the flavor of icecream sold or 'STOP' to exit.\n"<<endl;
getline (cin, flavor_input); // getline causes rocky road to be accepted with a space between the words.
string::iterator it( flavor_input.begin()); //converting the first letter of input to uppercase if not already.
if (it != flavor_input.end())
flavor_input[0] = toupper((unsigned char)flavor_input[0]);
while(++it != flavor_input.end())
{
*it = tolower((unsigned char)*it);
}
if (flavor_input == "STOP" || flavor_input == "Stop")
break;
valid_option = false;
for(int i=0;i<6;i++) //Checks to see if input matches those of possible inputs.
if(!flavor_input.compare(flavors[i]))
{
valid_option = true;
break;
}
if(!valid_option)
{
cout << "Invalid Flavor. Try again.\n\n";
flavor_input.clear();
continue;
}
for(int i=0;i<6;i++)
{
if(!flavor_input.compare(flavors[i]))
{
cout << "Enter how many scoops were sold: ";
cin >> scoops;
cin.ignore();
scoop_count[i] += scoops;
scoops = 0;
cout << '\n';
break;
}
}
}
for(int i=0;i<6;i++)
{
if(!scoop_count[i])
continue;
else
{
cout << "\nDAILY SCOOP REPORT: "<<endl;
cout << setiosflags( ios::left )
<< setw( 11 ) << flavors[i]
<< resetiosflags( ios::left )
<< setw( 4 ) << scoop_count[i] << endl;
}
}
cin.get();
return 0;
}
Thanks again for all of the assistance. It is greatly appreciated.
Thanks to all the assistance and pointing me in the direction of what to study, I have the program completed other than one last part.
I figured out that why it wasn't working when I moved the "DAILY SCOOP REPORT" line around. I had renamed the file and when I compiled it, it was outputing the "last working configuration" kinda deal if that makes sense. So I created a new project (the .cpp file has to have a certain name for submission) and put the code in it. Now the line is printed only once.
In the code block below, I have it where it lowers casing for all other letters other than the first or so it seems to be doing. The reason I have the case coding the way I do is that the instructions want the flavor report to print out with first letter of each word cap and lower after that. I am going to look into how to cap the 2nd "R" in Rocky Road, but other than the ignore white-space I don't really know how. Do I need to parse the line?
Anyone to point me in the right direction would be appreciated.
I tried but it gives error that in the first if statement "syntax error : identifier 'flavor_input'".
//converting the first letter of input to uppercase if not already.
string::iterator it( flavor_input.begin());
if flavor_input = "rocky road"
(it != flavor_input.end())
flavor_input[6] = toupper((unsigned char)flavor_input[6]);
if (it != flavor_input.end())
flavor_input[0] = toupper((unsigned char)flavor_input[0]);
while(++it != flavor_input.end())
{
*it = tolower((unsigned char)*it);
}
switch doesn't work with strings.
You need to use the operator == to select the right choice like so:
string count = // ... something
if (count == "choc") {
}
else if (count == "van") {
}
else if (count == "str") {
} // .. etc
A few other things: make sure you spell string with a consistent case, all lower case and no upper case. String is something different than string.
Make sure you surround strings with double quotes "" and not single quotes ''. single quotes are for single characters like 'a' or 'b'. double quotes are for multiple characters strings like "abc" and "hello"
Having the word count as both the function name and an argument name is probably a bad idea and will not compile because the same name means two different things.
You can't return multiple values from a function. writing something like return a,b,c; doesn't mean what you probably want it to mean. the comma (,) operator allows several expressions to be evaluated in the same statement and the result is the value of the last expression so writing return 1,2,3; is exactly the same as writing return 3;
C++ cannot switch on a string. Replace your switch(count) {...} with if/else if statements. Additionally the proper format for a string is "string", not 'string' (single quotes designate a single character, like: 'a'). Also, ensure that you always use the correct casing for string objects (string as opposed to String, like you have as your return values)
Other than that, it would be helpful to see the compiler errors you are getting.
Another thing I noticed in your source: you will have to omit the semicolons (-cola?) at the end of the following lines:
cout << "Please enter the flavor of icecream sold or 'STOP' to exit.\n"<<endl
<< "Flavors avaliable:\n"<<endl
<< "chocolate\n"<<endl
<< "valnilla\n"<<endl
<< "strawberry\n"<<endl
<< "mint\n"<<endl
<< "rocky road\n"<<endl
<< "mocha\n"<<endl
<< "Enter flavor : ";
This is just a single huge expression. The same applies to
cout << "\nDAILY SCOOP REPORT: \n"<<endl
<< "chocolate :"<<chocolate<<"\n"<<endl
<< "vanilla :"<<vanilla<<"\n"<<endl
<< "strawberry :"<<strawberry<<"\n"<<endl
<< "mint :"<<mint<<"\n"<<endl
<< "rocky road :"<<rocky_road<<"\n"<<endl
<< "mocha :"<<mocha<<"\n"<<endl;
Also: the endl and the "\n" are redundant. You will see the choices being separated by empty lines.
I haven't looked at the whole thing, but this isn't going to do what you want:
if (flavor = 'STOP' || 'stop')
I think you need:
if (flavor.compare("STOP") == 0 || flavor.compare("stop") == 0)
Let's go down the problems I see.
String count (string& flavor, string& count, string& chocolate, string& vanilla, string& strawberry, string& mint, string& rocky_road, string& mocha);
You're using String here, I'm sure you meant std::string or just string.
Inside the count function (SO is truncating the code when pasted), you're ending the line with a semicolon after endl yet trying to continue the stream output. I think you meant
Next:
if (flavor = 'STOP' || 'stop')
I think you meant to use the operator== instead of operator=, which is assignment not comparison. Also, there are no junctions in c++, so you will have to write that out as:
if (flavor == 'STOP' || flavor == 'stop')
Next:
switch (count) { case 'choc' :
Two problems here. First, you can only use plain-old-data (pod) in switch statements. Using std::string in a switch will not automatically call operator==; you will have to use if/else statements. Also, string literals are double quoted whereas character literals are single quoted.
Next:
chocCount + count;
This isn't really a statement. I'm sure you meant chocCount += count;
Next:
if (flavor = chocolate) chocCount + count;
Again, you want to use == and chocCount += count;.
Most of these problems are repeated. You should fix each of these problems everywhere they exist. There may be other problems, but I was basically compiling that in my head.
I didn't read through all of it to find semantic problems, but your count function is clearly not returning a count (at least what I currently see posted). You are returning a String, which I assume you meant string.
That's all this human compiler is going to solve for 1 homework assignment. I could recommend you go read a good C++ tutorial.