I have been working on this little program in Visual Basic 2013 in an attempt to create a sort of tiered structure for user-input commands. Basically, I want the first of a two word input to direct the program to an area of code with a set of responses for the second word. In this program, the first word can either be "human" or "animal." These words direct the program to functions that select the kind of animal or human.
#include "stdafx.h"
#include <iostream>
#include <sstream>
void ifAnimal(std::string b) //This is the set of responses for a first word of "Animal"
{
if (b == "pig")
{
std::cout << "It is a pig." << std::endl;
}
if (b == "cow")
{
std::cout << "It is a cow." << std::endl;
}
}
void ifHuman(std::string b) //This is the set of responses for a first word of "Human"
{
if (b == "boy")
{
std::cout << "You are a boy." << std::endl;
}
if (b == "girl")
{
std::cout << "You are a girl." << std::endl;
}
}
int main()
{
while (1)
{
std::string t;
std::string word;
std::cin >> t;
std::istringstream iss(t); // Set up the stream for processing
int order = 0;
//use while loop to move through individual words
while (iss >> word)
{
if (word == "animal")
{
order = 1;
continue; //something wrong with these continues
}
if (word == "human")
{
order = 2;
continue;
}
if (order == 1)
{
std::cout << "The if statement works" << std::endl;
ifAnimal(word);
}
if (order == 2)
{
std::cout << "This one too" << std::endl;
ifHuman(word);
}
}
}
return 0;
}
The problem is that whenever the program reaches the continue statements, the if statements calling my functions are not triggered. No text is displayed at all. If the continue statements are removed, the if statements trigger, but then the corresponding function has the wrong word. Am I unaware of something that those continues are doing? Is there a better way to accomplish what I want to do?
what continue means is skip the rest of the loop and go back to the top. whatever is after the continue statement won't be executed if continue gets hit.
It looks like you expect your word to be two words at the same time, so once you execute ifAnimal() none of the cases in ifAnimal will be met. word will never be "pig" or "cow" when you call that method because you only ever call that method when word is equal to "animal", and you don't change it after that.
Continue means "Go immediately to the top of the loop, and start over again". You do not want that at all.
//use while loop to move through individual words
while (iss >> word)
{
if (word == "animal")
{
order = 1;
}
else if (word == "human")
{
order = 2;
}
if (order == 1)
{
std::cout << "The if statement works" << std::endl;
ifAnimal(word);
}
if (order == 2)
{
std::cout << "This one too" << std::endl;
ifHuman(word);
}
}
Related
#include <iostream>
using namespace std;
int main()
{
int a = 1;
int b = 2;
if(a > 0)
{
cout << "we are in the first" << endl;
if(b > 3)
{
cout << "we are in the second" << endl;
}
}
else
{
cout << "we are in else" << endl;
}
}
According to the C++ISO:
In the second form of if statement (the one including else), if the
first substatement is also an if statement then that inner if
statement shall contain an else part. In other words, the else
is associated with the nearest un-elsed if.
I thought that my code above would print out "we are in else", since the condition of the nearest un-elsed if, the inner one, resulted in false. What did I miss?
The standard talks here about no block statements. In situation like this:
if (a > 0)
if (b > 3) std::cout << "nested-if\n";
else std::cout << "nested-else\n";
else is a part of the nested if. Such things must be unambiguous in standard, but I strongly recommend using block statements (wrapped in {}) in every situation to prevent confusion.
When they say "nearest" then they refer to the distance to the whole if statement, not only the if keyword. The whole if statement is:
if (a>0){
cout<<"we are in the first"<<endl;
if (b>3){cout<<"we are in the second"<<endl;}
}
It ends at the }. The } closes the block of the outer if and that is the if which is closes to the else.
See also here for a little more formal explanation of the if-statement consisting of more than just the if: https://en.cppreference.com/w/cpp/language/if.
Context. The part you're missing is context.
Every time you open a {} pair you introduce a new context, so the exterior else only "knows" about the first if.
The if inside the new context could have an else of it's own. If you wanted the behavior of the else being pertaining to the last if, you should not have created a new context.
E.g:
if (someVar == true)
if (someOtherVar == true)
cout << "Some text" << endl;
else
cout << "Some other text" << endl;
else
cout << "Another entirely different text" << endl;
Your code -
int a =1;
int b =2;
if (a>0)
{
cout<<"we are in the first"<<endl;
if (b>3){cout<<"we are in the second"<<endl;}
}
else
{
cout<<"we are in else"<<endl;
}
Logic path -
int a =1;
int b =2;
if (1>0)
{
cout<<"we are in the first"<<endl;
if (b>3){cout<<"we are in the second"<<endl;}
}
else
{
cout<<"we are in else"<<endl;
}
int a =1;
int b =2;
cout<<"we are in the first"<<endl;
if (b>3){cout<<"we are in the second"<<endl;}
we are in else is not executed.
This is gonna be laughed at because I'm probably very stupid, but can I use more than one string as a condition in an if statement?
#pragma once
#include <iostream>
#include <string>
#include "Baxter.h"
#include "Inventory.h"
#include "Room1Items.h"
int woman = 6;
int children = 5;
int inputNumberOfAnimalsToSave;
int numberOfAnimals;
int numberOfAnimalsToKill;
int numberOfAnimalToTakeHome;
std::string Yes;
std::string firstAction;
bool killRemainingAnimals;
int playerSaidYes;
int AddNumber()
{
numberOfAnimals = woman + children;
return numberOfAnimals;
}
int RemoveNumber()
{
numberOfAnimalsToKill = numberOfAnimalToTakeHome - numberOfAnimals;
return numberOfAnimalsToKill;
}
int InputNumber()
{
std::cout << " Comrade Kurchenko: Well, they are irridiated and will most likely end up poisioning \n";
std::cout << " your family, but sure, why not! How many animals Shall we Save ?\n ";
std::cin >> inputNumberOfAnimalsToSave;
numberOfAnimalToTakeHome = numberOfAnimals - inputNumberOfAnimalsToSave;
return numberOfAnimalToTakeHome;
}
int DoYouWantToKillTheRest()
{
std::cout << " Comrade Kurchenko: Fair Enough Comrade! Do you want to move on? \n\n";
std::cout << " Private Lenin: "; std::cin >> Yes;
while (Yes == "No")
{
//std::cout << " Comrade Kurchenko: So, you want the remaining " << numberOfAnimalToTakeHome << " Put The sleep do you?\n\n";
//std::cout << " Private Lenin: Im afraid so sir!\n\n";
//std::cout << " Comrade Kurchenko: Then so be it. They will be better off dead by our hands, than starving to death.\n\n\n\n";
//std::cout << " *** Loud Bangs and Then Silence....\n\n\n ***";
std::cout << " Comrade Kurchenko: What do you want to do?\n";
std::cout << " Private Lenin: "; std::cin >> firstAction; std::cout << "\n";
while (firstAction != "MoveOn")
{
if (firstAction == "Take food" || "Recover Meal" )
{
if (canTakeFood)
{
TakeFood();
std::cout << " You have taken a peice of food \n";
DoYouWantToKillTheRest();
}
if (canTakeFood == false)
{
std::cout << " There is no more food to take \n";
DoYouWantToKillTheRest();
}
}
if (firstAction == "Eatfood")
{
EatFood();
DoYouWantToKillTheRest();
}
if (firstAction == "Inventory")
{
ShowInventory();
DoYouWantToKillTheRest();
}
if (firstAction == "Ouch")
{
JabAFingerInYourEye();
std::cout << " Comrade Kurchenko : Why the hell did you stab yourself in the eye?\n\n";
std::cout << " Private Lenin : I dont know sir, its like someone was controlling my arm!\n";
DoYouWantToKillTheRest();
}
if (firstAction == "Look")
{
Look();
DoYouWantToKillTheRest();
}
if( firstAction == "Help")
{
WhatCanIDo();
DoYouWantToKillTheRest();
}
if (firstAction == "Baxter")
{
ShowBaxter();
std::cout << "Here is baxter";
DoYouWantToKillTheRest();
}
}
return 0;
}
return 0;
}
I've tried it and get no bugs when I run it. It just doesn't work.
I have tried to google it but I can't seem to find the right way to word it to get results. Messing around with a console based text adventure.
I've googled as many different ways of asking this question and can't get any results that help me.
I get no error messages. It runs fine, it just doesn't work.
"Can I compare with more than one string in an if statement?" - Sure you can (I'm assuming we are talking about std::strings here).
You are doing
if (firstAction == "Take food")
If you wanted to test against two strings you could do:
if (firstAction == "Take food" or firstAction == "Drop food")
You could change that or to || which is more conventional, but both are valid and do the same thing.
In C++ (and most other programming languages) you usually can't compare one thing (a string variable) to multiple others in one operation because of the way operator precedence is defined:
// Does not work!!
if (firstAction == "Take food" || "Recover Meal" )
// Because it will evaluate to (firstAction == "Take food") || "Recover Meal"
Rather you use logical operators to combine the result of one comparison with another comparison:
if (firstAction == "Take food" || firstAction == "Recover Meal")
{
You should read up on logical operators in C++ to learn more, for instance here: https://www.learncpp.com/cpp-tutorial/36-logical-operators/
If you want to dynamically compare to a whole list of strings, then you can do so of course as well:
std::set<std::string> validActions = {"Take food", "Recover meal"};
if (validActions.find(firstAction) != validActions.end())
{
// ... found a valid action ...
This is not how you compare c-strings in C++. That type of string is just an array of characters and operator == tells if it is the same array, not if it has the same content.
To compare strings properly use function strcmp from <cstring>.
firstAction == "Take food"; // bad
strcmp(firstAction, "Take food") == 0; // good
Better yet solution would be using class std::string which allows to use normal operators.
std::string(firstAction) == "Take food"; // good
std::string(firstAction) == std::string("Take food"); // also good
firstAction == std::string("Take food"); // also good
Or, like #JVApen has hinted, maybe even better solution would be to use std::string_view.
firstAction == std::string_view("Take food"); // good
firstAction == "Take food"sv; // the same meaning as above but written shorter
You just need to remember to insert line using std::operator""sv; before that. (using namespace std; would also do.)
If you comparing string properly (let's say using the std::string_view) then of course you can use || (or) or && (and) or any other operator to make multiple comparisons in a single if.
if (firstAction == "Take food"sv || firstAction == "Take water"sv)
{
// do stuff
}
if (firstAction == "Take food"sv && !canTakeFood)
std::cout << " There is no more food to take \n";
LoopAndDoAction();
}
(This code probably doesn't make sense but it's just an example.)
Depending on what are you trying to do, consider using enum instead of string constants. Enums are faster, more readable, take less memory and there is harder to make mistake like a type when using it. Actually, only situation I can think of when you would not want to use enum would be parsing user input.
The second if is with who you can compare strings a lot of strings if you find some condition true on these if, the entire condition will be true.
I exaplained all on code //comments
Documentation: http://www.cplusplus.com/reference/string/string/compare/
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1ok = "Im a string";
string str2ok = "Im a string";
string str3ok = "Im a string different";
//First condition with and operator (&&) you can compare with a lot && operators
if(str1ok.compare(str2ok) == 0 && str3ok.compare(str2ok) == 0){ //First condition is true, second false, this condition is false because have true and false, need have true and true for be true
cout << "1st condition" << endl;
}
//Another condition with or operator (||) one condition need be true, if not is false
if(str1ok.compare(str2ok) == 0 || str3ok.compare(str2ok) == 0){ //First condition is true, only for this this condition is true, second condition is false.
cout << "2nd condition" << endl;
}
//You can make a mixed the operators like this some condition && (anothercondition || condition)
return 0;
}
Ouptput: https://onlinegdb.com/By39WpOGS
I'm having a little trouble with my code. It's pretty much supposed to open two files, and compare the first twenty line of the file "StudentAnswers.txt" [inputted as a char into a char array] against a char value in (each line of another file) "CorrectAnswers.txt" in another array at the same position (index). It's like a linear search, but the same position in the arrays. Then a report should be displayed, detailing which question the student missed, the given answer, the correct answer, and if the student passed (got >= 70%) or not, like the following:
Report for Student X:
2 (A/D), 3 (C/D), 5(D/A)
This student passed the exam!
Then it should clear the SAArray, and feed the next twenty lines from StudentAnswers.txt, and start the process all over again. I guess the program has to determine the number of students from (lines of 'StudentAnswers.txt' file / 20).
I'm having trouble displaying the report, and having the array clear itself after the program. I'm guessing this can be done with a while loop and an accumulator for the number of students (to be determined by above equation).
Also, Visual Studio seems to go to "Missed __ questions for a total of ___ %", and then keep looping -858993460.
Any help would be appreciated.
#include <iostream>
#include <fstream>
#include <string>
#include <array>
#include <algorithm>
using namespace std;
void GradeReturn(char[], char[], int, int, int);
string PassFail(float);
int main()
{
ifstream SA("StudentAnswers.txt");
ifstream CA("CorrectAnswers.txt");char CAArray[20];
char SAArray[20];
// char SA2Array[20];
bool isCorrect;
int correct;
int incorrect;
int counter;
correct = 0;incorrect = 0;
counter = 0;
cout << endl;
if (!SA.fail())
{
cout << "'StudentAnswers.txt' file opened successfully." << endl;
cout << "'CorrectAnswers.txt' file opened successfully." << endl << endl;
int a = 0;
int b = 0;
while (a < 20)
{
CA >> CAArray[a];
a++;
} // while loop to feed char into the array
while (b < 20)
{
SA >> SAArray[b];
b++;
}
} // while loop to feed char into array
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
return 0;
}
void GradeReturn(char CAArray[], char SAArray[], int correct, int incorrect, int counter)
{
float percent;
float hundred;
int student;
int catcher[20];
int writeCatcher; int starter;
int catcher_size;
student = 0;
writeCatcher = 0;
catcher_size = ((sizeof catcher) / 4);
while (counter < 20)
{
if ((CAArray[counter]) == (SAArray[counter]))
{
correct++;
cout << "Good job!" << endl;
} // correct handling
else
{
incorrect++;
cout << "You got question " << counter << " wrong." << endl;
counter >> catcher[writeCatcher];
writeCatcher++;
} // incorrect handling
counter++;
} // while loop to determine if a student got a question right or wrong
static_cast <float> (incorrect); // float conversion
cout << endl; // for cleanliness
percent = ((static_cast <float> (correct)) / 20); // percentage
hundred = percent * 100;
PassFail(percent);
if (PassFail(percent) == "pass")
{
student++;
cout << "Report for Student " << student << ":" << endl;
cout << "-----------------------------" << endl;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
starter = 0;
while (starter < (sizeof catcher)
{
if(1=1)
{
catcher_size
}
else
{
cout << "";
starter++;
}
}
}
else if (PassFail(percent) == "fail")
{
student++;
cout << "Missed " << incorrect << " questions out of 20 for ";
cout << hundred << " % correct." << endl << endl;
while (starter < catcher_size)
{
if ((catcher[starter]) == -858993460)
{
starter++;
}
else
{
cout << "";
starter++;
}
}
}
return;
}
string PassFail(float percent)
{
if (percent >= 0.70) // if <pass>
{
return "pass";
}
else // if <fail>
{
return "fail";
}
cout << endl;
}
To get a loop you should keep streams open instead of closing them after reading 20 lines.
As pseudo code that would be:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter);
a = 0; // Reset a
}
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
You would also need to pass correct, incorrect, counter by reference so that the GradeReturn can change their value and their by do the accumulation.
Like:
void GradeReturn(char CAArray[], char SAArray[], int& correct, int& incorrect, int& counter)
Further you shouldn't rely on being able to read exactly Nx20 lines from the files every time. A file could have, e.g. 108 (5x20 + 8) lines, so you code should be able to handle the with only 8 lines. In other words, don't hard code 20 in your function like while (counter < 20). Instead pass the number of lines to be handled and do while (counter < number_to_handle).
Something like this as pseudo code:
a = 0;
while(streams_not_empty)
{
CA >> CAArray[a];
SA >> SAArray[a];
++a;
if (a == 20)
{
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
// ^
a = 0; // Reset a
}
}
if (a != 0)
{
// Process the rest
GradeReturn(&CAArray[counter], &SAArray[counter], correct, incorrect, counter, a);
}
CA.close(); // closing "CorrectAnswers.txt"
SA.close(); // closing "StudentAnswers.txt"
One problem you have is you're trying to compare C-style strings with the == operator. This will compare them essentially as if they were pointers to char, i.e. compare whether they point at the same location in memory, not compare the contents of the string. I urge you to look up array-decay and c-string variables to understand more.
Specifically, if (PassFail(percent) == "pass") isn't going to do what you want it to. strcomp doc, strncmp doc using std::string variables instead of c-style strings would all work, but it would be better simply to compare percent to a value, i.e. if(percent >= 0.70 directly instead of calling PassFail and comparing a string.
There are many other issues here also, you at one point call PassFail but do nothing with the return value. The only side affect of PassFail is cout << endl, if that's what you intend, it's a poor decision and hard to read way to put a newline on the console.
Try asking your compiler for more warnings, that's often helpful in finding these types of issues. -Wall -Wextra work for gcc, you may have to read your compiler manual...
Using C++ What could possibly the best way for a sequence to run only once? To make it clearer for example that I have a program in where you need to guess a string, if the user entered hint I would display the hint of the word but I would only allow it once... I am currently doing this:
bool hintLock = false;
...
if (guess == "hint"){
if (!hintLock){
cout << hint << endl;
hintLock = true;
}
else
cout << "I've given you the hint" << endl;
}
Here's my code:
#include <iostream>
#include <string>
using namespace std;
void main(){
string guess;
bool hintLock = false;
cout << "Guess one of StackExchange's best site: Type \"hint\" for hint" << endl << endl;
do{
cout << "Guess > ";
cin >> guess;
if (guess == "hint"){ // Here it is
if (!hintLock){
cout << hint << endl;
hintLock = true;
}
else
cout << "I've given you the hint" << endl;
}
}
while (guess != "stackoverflow");
cout << "You've got it right!" << endl;
}
Is there any much better statement to do this? or is it already the best?
I suspect that either you are overanalyzing things or you haven't adequately described the real problem. From the code you've posted, I see no reason why you shouldn't wrap the code you want to execute in to a function and then simply call that function one time.
void blahBlah()
{
// blah blah
}
int main()
{
if (userInput == "hint")
blahBlah();
}
Perhaps what you meant is that in your program you have a main loop which executes until program termination, and in that loop you accept input from the user. The user is allowed to ask for a hint, but only once during the program's run. The first time the ask for a hint they are given one, but subsequent times they are not.
I still believe simple is better than fancy (read: complex). To that end, I start with having a bool scoped outside of the main loop which you check each time they ask for help:
int main()
{
bool displayedHint = false;
// program's main loop
for (bool endProgram = false; !endProgram; )
{
std::string command = getUserInput();
if (command == "hint")
{
if (displayedHint)
{
cout << "I already gave you a hint!\n";
}
else
{
displayHint();
displayedHint = true;
}
}
}
}
If you want to make sure it only shows once for any particular run of the program (anything more global than that is pretty complicated and platfrom-specific), all you need is a global boolean to protect the function. For example:
bool shownHint = false;
void showHint() {
if (!shownHint) {
cout << "The hint is: ........" << endl;
shownHint = true;
} else {
cout << "Hint has already been shown, no cheating!" << endl;
}
Whenever you think you might want to show the hint, call showHint() and it will show (or not) as appropriate.
The trick is making sure the variable is global (or a static, in a class, which looks almost the same), so that it doesn't get reset during your loop or otherwise while the program is running.
If you need to persist between runs, you could write to a file, check a server, set a registry key, or any number of other options.
I think that the most appropriate iteration statement is do-while. It allows at least one iteration
for example
do
{
std::cout << "Enter your word: ";
std::string answer;
std::cin >> answer;
// some other stuff
} while ( false );
Or
bool allow = true;
do
{
std::cout << "Enter your word: ";
std::string answer;
std::cin >> answer;
// some other stuff
} while ( allow = !allow );
You can use flags that are boolean, that represent a state in your system. Once the state is "defined", you can then query the state and find if it is "set" or "cleared"..
to be more precise
bool hasHinted = false; // unset or cleared( also definition of a state variable)
if(hasHinted == false){
//do something
hasHinted = true; // set
}else{
// do nothing
}
I think the OP is looking for a piece of code similar to singleton init. i.e.: only create the singleton once, and after that always return the pointer.
void Init() {
static bool isInitialized = false;
if (!isInitialized) {
isInitialized = true;
doRealInit();
}
}
the same thing done with std::call_once as a comment suggests:
std::once_flag flag;
void do_once() {
std::call_once(flag, [](){ std::cout << "Called once" << std::endl; });
}
in my opinion it's not really more readable or shorter.
I'm trying to make a program that looks for syntax and everytime it goes from state to state
It needs to indicate that state. I'm getting different output that I shouldn't have got.
using namespace cppfsm;
#include <vector>
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::vector;
int cppfsm::updateState(int& state, char c) {
const int state1 = 1;
const int state2 = 2;
switch (state) {
case state1:
if (c == '/')
cout << "1" << endl;
// do stuff; update state
else if (c == '"')
cout << "1" << endl;
// do something else; update state
case state2:
if (c == '/')
cout << "1" << endl;
// do stuff; update state
else if (c == '"')
cout << "1" << endl;
// do something else; update state
}
return 0;
}
void testFSM(string s) {
vector<int> stlist; // list of states.
int cstate = start;
for (unsigned long i = 0; i < s.length(); i++) {
stlist.push_back(updateState(cstate,s[i]));
}
// push the last state:
stlist.push_back(cstate);
cout << s << endl;
for (unsigned long i = 0; i < stlist.size(); i++) {
cout << stlist[i];
}
cout << endl;
}
int main() {
// the finite state machine:
string input;
while(getline(cin,input)) {
cout << " ";
testFSM(input);
}
return 0;
}
the output should be looking like this.
the numbers are the states when going from 1 to another
$ echo "int x; // holds stuff" | ./fsm
int x; // holds stuff
0111010042222222222222
$ echo 'cout << "some string";' | ./fsm
cout << "some string";
01111000033333333333300
$ echo 'cout << "\"escape\" chars are fun";' | ./fsm
cout << "\"escape\" chars are fun";
011110000353333333533333333333333300
But my output comes out to be all 0000......s. How do I fix this problem?
If you're wondering why stlist is all 0's, take a look at the return statement for updateState:
return 0;
}
Compare this with your code for populating stlist:
stlist.push_back(updateState(cstate,s[i]));
As far as I can tell, all 0's is the correct behavior of this code. Obviously, this is not the expected or logical behavior, so I suggest changing updateState:
int cppfsm::updateState(int& state, char c) {
// ...
return state;
}
Now when you run the code stlist should contain each state change as intended.
It looks like you aleays call updateState with the same value, start. That value ist not handled in the switch, so the function returns zero. This means tha you just keep appending zeros to the stlist vector.
Try handling the start state in the switch, and the return value of the updateState function should be assigned to the cstate variable.
Your code never checks you start state:
switch (state) {
case state1: /* ... */
case state2: /* ... */
case start : /* ... */
}