What is the behavior of nested If's in C++? - c++

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

Related

Are there ways to do if statements inside a cout line?

I'm starting to learn C++, and something useful from my main language Lua, is the ability to say:
print(true/false and 1 or 0)
1 or 0 being anything but it seems in c++ it doesnt work the same way?
What I tried for C++ was
cout << (score == 0) and "Valid";
But only a true if check seems to work
if (score == 0) {
cout << "Valid";
} else {
cout << "A";
}
std::cout << ((score == 0) ? "Valid" : "A");
The << in your code isn't simply a syntax, it's an operator:
std::basic_ostream<CharT,Traits>::operator<<
Your attempt will not produce any compilation errors (assuming you have using namespace std;):
cout << (score == 0) and "Valid";
// ^^ T/F ^^ ^^ T ^^
Apply some boolean algebra and that's equivalent to:
cout << true; // if score is 0
cout << false; // if score is not 0
That's certainly not what you are trying to acheive.
Are there ways to do if statements inside a cout line?
if (score == 0)
cout << "Valid";
else
cout << "A";
You can do that using the conditional operator ?:
cout << (score == 0 ? "Valid" : "A");
But this approach is not guaranteed to work always. For example:
cout << (condition ? "String" : 1234);
Reason: Why in conditional operator (?:), second and third operands must have the same type?
Rearranging it like this will work:
condition ? cout << "String" : cout << 1234;
Now, talking about your Lua style:
print(true/false and 1 or 0)
I don't know Lua but that looks like a function. If you are looking for some template like that, try this:
template <typename T, typename U>
void conditionalPrint(const bool& condition, const T& arg1, const U& arg2)
{
condition ? cout << arg1 : cout << arg2;
}
You can use it like this:
conditionalPrint(score == 0, "Valid", "A");
conditionalPrint(someCondition, "String", 1234);
Of course, I'm not going to explain how that works because you're new to C++. I would still recommend the if-else way of doing it. Readability of your code is very important:
if (condition)
{
cout << "true block";
}
else
{
cout << "false block";
}
"Lot can be learned by comparing two lanugages and try to see if what can be done in one can also be done in the other, but usually what is idiomatic in one can be crap in the other. Anyhow, I had my fun with exploring the issue, but imho the conclusion is as important as the rest of the answer" - idclev

Reading into an Array Multiple Times

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

How are these continue statements affecting my code?

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

The best way to execute a sequence once in C++

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.

How can I stop my integers from displaying as HEX?

I am practicing some code implementing different data structures. For this example I am trying to implement a simple stack data structure. So far it works as intended, but I keep getting Hex characters when trying to display my stack. Could anyone help me with figuring out why this is the case?
Also I am trying to get better at structuring my code properly, can anyone that is already involved in the industry please give me some constructive criticism as to what I have coded so far. Thanks.
#include <iostream>
using namespace std;
// stack_MAX == maximum height of stack
const int stack_MAX = 10;
class stack{
public:
stack(){
//Constructor initializes top of stack
top = -1;
}
bool isFull(int top){
//isFull() will check to make sure stack is not full
//Will return TRUE if stack is FULL, and FALSE if
//stack is NOT FULL
if(top == stack_MAX - 1)
return true;
else
return false;
}
bool isEmpty(int top){
//isEmpty() will check to make sure stack is not empty
//Will return TRUE if stack is EMPTY, and FALSE if
//stack is NOT EMPTY
if(top == -1)
return true;
else
return false;
}
void push(int x){
//push() will push new element on top of stack
if(isFull(top)){
cout << "Sorry, but the stack is full!" << endl;
exit(1);
}
else{
top++;
x = stk[top];
}
}
void pop(){
//pop() will pop the top element from the stack
if(isEmpty(top)){
cout << "Sorry, but the stack is empty!" << endl;
exit(1);
}
else{
cout << stk[top] << " is being popped from stack!" << endl;
top--;
}
}
void display_stack(){
//diplay_stack() will show all elements currently in the stack
int temp; //will temporarily hold position of stack
temp = top;
while(!isEmpty(temp)){
cout << stk[temp] << endl;
temp--;
}
}
private:
int top;
int stk[stack_MAX];
};
int menu(){
int choice;
cout << "Welcome to my stack!" << endl;
cout << "What would you like to do? (select corresponding #)" << endl << endl;
cout << "1. Push" << endl;
cout << "2. Pop" << endl;
cout << "3. Display" << endl;
cout << "4. Quit" << endl;
cin >> choice;
return choice;
}
int main()
{
int selection, x;
stack myStack;
selection = menu();
while(selection != 4)
{
switch(selection){
case 1:
cout << "please enter number to be pushed: ";
cin >> x;
myStack.push(x);
selection = menu();
break;
case 2:
myStack.pop();
selection = menu();
break;
case 3:
myStack.display_stack();
selection = menu();
break;
default:
cout << "Oops that's not a selection, try again" << endl;
selection = menu();
break;
}
}
cout << "Thank you for stopping by and using my stack!" << endl;
system("pause");
return 0;
}
A statement in your push functin is wrong, modified as below:
void push(int x)
{
//push() will push new element on top of stack
if(isFull(top))
{
cout << "Sorry, but the stack is full!" << endl;
exit(1);
}
else
{
top++;
/***************************
x = stk[top];
****************************/
stk[top] = x;
}
}
Advice:
Learn to debug, here is the tutorial
Include the head file cstdlib when you want to use exit in your
code
Do not name your class with the same name for any classes in STL
As pointed out by prehistoric penguin, your push() function is incorrect:
x = stk[top];
Should be changed to:
stk[top] = x;
I wanted to comment anyway to offer some general comments as you requested:
If statements like this can be replaced by a single line of code:
if(top == stack_MAX - 1)
return true;
else
return false;
becomes:
return (stack_MAX - 1 == top);
Put constant expressions on the left-hand side of your comparison expression. For example:
(top == stack_MAX - 1)
becomes:
(stack_MAX - 1 == top)
The reason is that one day you will accidentally type something like:
(top = stack_MAX - 1)
and you or somebody else will waste a lot of time debugging it :)
Your isFull() and isEmpty() functions shouldn't take a parameter. They should just use the private member variable top. How would somebody call these functions without access to top, which you've correctly made a private member?
In general, avoid using. In my opinion it defeats the whole purpose of namespaces. using namespace std is a commonly used exception, but even then, is it so hard to type std::cout?
Always put curly braces around the clauses of your if statement, even if they are just one line. It's easy to forget to add braces if you need to add more statements to a clause later on, which can be quite confusing.
Your code formatting is pretty good, but pick a bracket style and be consistent. Either always put the opening curly brace on the same line as the function header / control statements etc, or always put it on the line afterwards.
Hope that helps.