Is this the right way to loop through Arrays? - c++

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

Related

What is proper way to use the curly arrow in C++?

Consider:
for(int i = 10; b >= i; i++){
if(i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
}
for(int i = 10; b >= i; i++){
if(i%2 == 0){
cout << "even" << endl;
}else{
cout << "odd" << endl;
}
}
Both of these code work with the only difference being the curly brackets for the if else statement. When should I use curly brackets and when not?
They're called braces or curly brackets, not to be confused with the "curly arrow" in some languages, ~>.
In C, and by inheritance C++, these are optional on single-line if statements, but as many, many bugs have been created by omitting them you'd be advised to use them as a matter of principle even when they're redundant.
That is a mistake like this is easy to overlook:
if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
goto fail;
goto fail;
Where it seems like that goto is conditional, yet it's not, it just drops through. This is the huge OpenSSL bug that caught everyone by surprise, and if veteran developers can mess it up, so can you.
The second form is the most reliable, least ambiguous, especially when formatted according to typical conventions:
for (int i = 10 ; b >= i;i++) {
if (i%2 == 0) {
cout << "even" << endl;
}
else {
cout << "odd" << endl;
}
}
for is a statement, not a function, so the syntax is for (...) with a space. Functions have no space, like f(...). Omitting the space implies for is a function, which it absolutely is not. The same goes for if, while and so on.
It's worth noting that the original code can actually be reduced to:
for (int i = 10 ; b >= i;i++)
if (i%2 == 0)
cout << "even" << endl;
else
cout << "odd" << endl;
Since that if is a single statement, even with the else clause attached.
Again, this is not advised because the rules of what is and isn't a single statement can be confusing.
Google has a detailed C++ style guide that may help you. In particular, it says that
In general, curly braces are not required for single-line statements, but they are allowed if you like them; conditional or loop statements with complex conditions or statements may be more readable with curly braces. Some projects require that an if must always have an accompanying brace.
If the 'if', 'else' or 'for' structures have only one statement inside them, you can decide not to use the curly brackets. However, I would recommend to use them in order to improve the code readability.

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.

While loop in C++ (using break)

I'm currently working through the book C++ Primer (recommended on SO book list). An exercise was given that was essentially read through some strings, check if any strings were repeated twice in succession, if a string was repeated print which word and break out of the loop. If no word was repeated, print that. Here is my solution, I'm wondering a) if it's not a good solution and b) is my test condition for no repeated words ok? Because I had to add 1 to the variable to get it to work as expected. Here is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> words = {"Cow", "Cat", "Dog", "Dog", "Bird"};
string tempWord;
unsigned int i = 0;
while (i != words.size())
{
if (words[i] == tempWord)
{
cout << "Loop exited as the word " << tempWord << " was repeated.";
break;
}
else
{
tempWord = words[i];
}
// add 1 to i to test equality as i starts at 0
if (i + 1 == words.size())
cout << "No word was repeated.";
++i;
}
return 0;
}
The definition of "good solution" will somewhat depend on the requirements - the most important will always be "does it work" - but then there may be speed and memory requirements on top.
Yours seems to work (unless you have the first string being blank, in which case it'll break); so it's certainly not that bad.
The only suggestion I could make is that you could have a go at writing a version that doesn't keep a copy of one of the strings, because what if they're really really big / lots of them and copying them will be an expensive process?
I would move the test condition outside of the loop, as it seems unnecessary to perform it at every step. For readability I would add a bool:
string tempWord;
unsigned int i = 0;
bool exited = false;
while (i != words.size())
{
if (words[i] == tempWord)
{
cout << "Loop exited as the word " << tempWord << " was repeated.";
exited = true;
break;
}
else
{
tempWord = words[i];
}
++i;
}
// Doing the check afterwards instead
if (!exited)
{
cout << "No word was repeated.";
}
a) if it's not a good solution
For the input specified it is a good solution (it works). However, tempWord is not initialized, so the first time the loop runs it will test against an empty string. Because the input does not contain an empty string, it works. But if your input started with an empty string it would falsely find as repeating.
b) is my test condition for no repeated words ok? Because I had to add 1 to the variable to get it to work as expected.
Yes, and it is simply because the indexing of the array starts from zero, and you are testing it against the count of items in the array. So for example an array with count of 1 will have only one element which will be indexed as zero. So you were right to add 1 to i.
As an answer for the training task your code (after some fixes suggested in other answers) look good. However, if this was a real world problem (and therefore it didn't contain strange restrictions like "use a for loop and break"), then its writer should also consider ways of improving readability.
Usage of default STL algorithm is almost always better than reinventing the wheel, so I would write this code as follows:
auto equal = std::find_adjacent(words.begin(), words.end());
if (equal == words.end())
{
cout << "No word was repeated" << endl;
}
else
{
cout << "Word " << *equal << " was repeated" << endl;
}

Do-while loop running twice when it should run only once (C++)

friends. I have a problem.
Problem: the computer must pick randomly one string out of an array of 36 strings. If by any chance it picks strings #34 or #35 (the two last ones), it has to draw two more random strings from the same array. I tried a do-while solution, and it "almost" works (see code below).
The randomization works fine - called srand inside main(). There is a forced "x2" draw (for testing reasons), so the computer draws two more strings. These two new random picks are NOT "x2", but still the loop kicks again - but just one more time! This time the computer picks two more "chits", which aren't "x2" either, so, as expected, it returns the "The chits have been drawn" sentence and the function is terminated. Why is the same code running twice with the same results but different if/else behavior? Thank you very much in advance.
string mortalityCalc ()
{
string mortalityChits[36] = {"1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","-","-","-","-","x2","x2"};
int mortalityResult;
// mortalityResult = rand() %36;
mortalityResult = 35; // for testing only. Delete afterwards.
string drawnChit = mortalityChits[mortalityResult];
string drawnChit1;
string drawnChit2;
if (drawnChit != "-" && drawnChit != "x2")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'.";
return returnText;
}
else if (drawnChit == "-")
{
string returnText = string("The computer has drawn the chit '") + drawnChit + "'. No senators died this year.";
return returnText;
}
do
{
cout << "The computer has drawn the 'x2' chit." << endl;
cout << "Two more chits will be drawn.\n" << endl;
mortalityResult = rand() %36;
drawnChit1 = mortalityChits[mortalityResult];
cout << "The first draw is the chit '" << drawnChit1 << "'. ";
mortalityResult = rand() %36;
drawnChit2 = mortalityChits[mortalityResult];
cout << "The second draw is the chit '" << drawnChit2 << "'." << endl;
} while (drawnChit1 == "x2" || drawnChit2 == "x2");
return "The mortality chits have been drawn. The corresponding senators are dead.";
}
UPDATE: Tried running this code isolated from the rest of the program and it behave as expected. So I guess it's important to post what comes before it:
cout << "If you are a lazy bastard, the computer can pick one senator randomly for you.\nAre you a lazy bastard? [y/n]" << endl;
string lazyBastard;
cin >> lazyBastard;
cout << endl;
if (lazyBastard == "y" || lazyBastard == "Y" || lazyBastard == "yes" || lazyBastard == "YES" || lazyBastard == "Yes")
{
mortalityCalc ();
cout << mortalityCalc () << endl;
cout << "Very well. Now, imminent wars become active (Only one of each match)." << endl;
cout << "Get ready for the next phase." << endl;
My guess, from reading some other questions here, is that somehow the cin is messing with the loop behavior, even though they are not related and there's no user input whatsoever in the loop's statements or conditions. Is that possible? If so, why and how to remedy it?
Thank you again.
In the first loop you are forcing an 'x2' so your are entering the do-while loop. The result of the two calls for 'rand())%36' is always 19 and a number between 30 and 34. The point is that the random number generator generates always the same sequence of numbers, if you don't give him a seed 'srand(...)'.
do {
// ...
cout << rand()%36;
// ...
} while( /*...*/ )
See http://ideone.com/zl8ggH
You have to create random numbers and your code does what you expect.
Finally! I thought it would be a stupid thing! I just realized that I called the mortalityCalc() function twice! That's why it was looping twice!
Thanks to all who tried to help!

C++ if statements using strings not working as intended

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.