understanding break statement and handling it for existing code - c++

In the below example, i have problem in handling the break statement. For country = US, somearray will be of length one only. but in case of "DE", length is more than one. but given program, since break statement is used to get out after processing 1st row, it will not suite for DE country since DE country has more than one rows Since re-
using is a better way, checking if there is someway i can re use the same logic for country =DE as well
if(country == "US" || country == "DE")
{
for(int i = 0; i < somearray.length(); i++)
{
if( (payment == "USD") )
{
if(amount > 0)
{
//do something
}
if( balance.is_positive())
{
// do something
}
break;
}
}
}
Note : this is not actual code.. just wrote like an example to understand..

if(country = "US" || country = "DE")
{
for(int i = 0; i < somearray.length(); i++)
{
if( (payment == "USD") )
{
if(amount > 0)
{
//do something
}
if( balance.is_positive())
{
// do something
}
if(somearray.length()==1) // as per Your requirement country **us** has **length 1** ,in this can break the loop
{break;}
}
}
}

From what I have understood, You want to process each element in somearray, Therefore removing break statement will suffice. if (payment = "USD") is useless here, a simple statement payment="USD" would suffice. Moreover since that is an assignment which is same for all the loop iterations, pull it outside and assign before the loop.

Related

How to use continue for a while loop in a nested for loop

I'm trying to continue a while loop after a condition of an if statement is met, however, that if statement is in a for loop, and the continue statement is just continuing the for loop instead of the while loop. My code looks like this:
while (valid_input == false) {
printf("Enter a date (yyyy/mm/dd): ");
fflush(stdout);
fgets(date, 20, stdin);
for (int i = 0; i <= 3; i++) {
if (!isdigit(date[i])) {
printf("Error: You didn't enter a date in the format (yyyy/mm/dd)\n");
continue;
}
}
How could I code this so I continue at the beginning of the while loop after the condition (!isdigit(date[i])) is met?
You can simply use another boolean variable to indicate that you want to continue the outer loop and break executing the inner one:
while (valid_input == false) {
printf("Enter a date (yyyy/mm/dd): ");
fflush(stdout);
fgets(date, 20, stdin);
bool continue_while = false; // <<<
for (int i = 0; i <= 3; i++) {
if (!isdigit(date[i])) {
printf("Error: You didn't enter a date in the format (yyyy/mm/dd)\n");
continue_while = true; // <<<
break; // <<< Stop the for loop
}
}
if(continue_while) {
continue; // continue the while loop and skip the following code
}
// Some more code in the while loop that should be skipped ...
}
Maybe just break; in the for() loop is already enough if there's no more code which needs to be skipped after.
It's impossible using continue, you would need to use goto or conditionals. Tough, in your particular case break would achieve the same result.
Btw. I am not jugdeing the design decision to handle date validation here. Just answering how to proceed to next while iteration.

Clang Format chained else ifs on single lines

I'm trying to write a .clang-format file that will allow the following:
if (value.Is<bool>()) { index = 1; }
else if (value.Is<int>()) { index = 2; }
else if (value.Is<unsigned int>()) { index = 3; }
else if (value.Is<long long>()) { index = 4; }
else if (value.Is<unsigned long long>()) { index = 5; }
else if (value.Is<float>()) { index = 6; }
else if (value.Is<double>()) { index = 7; }
else if (value.Is<long double>()) { index = 8; }
else if (value.Is<std::string>()) { index = 9; }
else if (value.IsArray()) { index = 10; }
else { index = 0; }
I've tried every option I can find related to breaks and allowShort*, and no matter what I do it seems to split them into multi-lines after the first like so:
if (value.Is<bool>()) { index = 1; }
else if (value.Is<int>()) {
index = 2;
}
...
Is there some option I'm missing that could support this?
Unfortunately, this is currently not supported for if-else statements, only for simple if's (as of revision 329373, dating 6/4/18). The AllowShortBlocksOnASingleLine and AllowShortIfStatementsOnASingleLine options are not applicable for if-else statements.
Hopefully this will change in the future.
The doc is not explicit about this, saying that AllowShortIfStatementsOnASingleLine will allow simple if statements on a single line:
AllowShortIfStatementsOnASingleLine (bool)
If true, if (a) return; can be put on a single line.
However, clang-format code suggests that if-else blocks are not allowed on single lines:
1) UnwrappedLineFormatter.cpp, tryMergeSimpleControlStatement:
// Only inline simple if's (no nested if or else).
if (I + 2 != E && Line.startsWith(tok::kw_if) &&
I[2]->First->is(tok::kw_else))
return 0;
2) FormatTest.cpp, FormatShortBracedStatements test.
Notice the test parameters, and that in the expected formatting in the unittests, else always resides in its own line, while plain if statements with no else are on a single line with their blocks, for example:
verifyFormat("if (true) {\n"
" f();\n"
"} else {\n"
" f();\n"
"}",
AllowSimpleBracedStatements);
https://clang.llvm.org/docs/ClangFormatStyleOptions.html says:
SIS_AllIfsAndElse (in configuration: AllIfsAndElse) Always put short ifs, else >ifs and else statements on the same line.
if (a) return;
if (b) return;
else return;
if (c) return;
else {
return;
}

Changing while loop to accommodate two situations

Suppose I have a while loop that depends on two separate inputs. In situation one, the while loop will take the value 1, and in situation two, it should take !cin.eof(). Is there a way I can do this efficiently? To be more concise:
string hello;
cin >> hello;
if(hello == "one")
{
//make the while loop depend on value 1
}
else if(hello == "two")
{
//make the while loop depend on value !cin.eof()
}
while(/*depends on above conditional*/)
{}
I don't want to do something like:
if(hello == "one)
{
while(1){}
}
else if(hello == "two")
{
while(!cin.eof){}
}
because the while loop essentially does the same thing in each situation.
For readability and in the interest of cohesion, I think you should move the contents of your loop into a separate function:
void DoSomething() { /* ... */ }
// ...
if(hello == "one)
{
while(1){ DoSomething(); }
}
else if(hello == "two")
{
while(!cin.eof){ DoSomething(); }
}
It's easier to see that the different while loops are doing the same thing but their conditions are different.
I believe you're looking for something like this:
while((hello == "one") || (hello == "two" && !cin.eof)) {
}
This code will do what you want, because it checks 'is the variable "one"? If so, keep executing. If it's not, it'll check: Is the variable "two"? If so, it'll check for cin.eof.
If it's neither, the loop won't execute. (the && 1 in the first condition was omitted, because it's always 'true', equalling and infinite loop)
Edit:
To simplify things, you may want to consider this code (as suggested in the comments):
bool HelloIsOne = (strcmp(hello, "one") == 0);
bool HelloIsTwo = (strcmp(hello, "two") == 0);
while(HelloIsOne || HelloIsTwo && !cin.eof) {
}
The brackets, which I placed in the previous example are actually unnecessary, because && binds stronger than ||, but they help the general clarity of the code.
Simply use or (||) as a condition in the while loop. Set the first condition if(hello == "one"). Now you have a while loop that will loop if one of the conditions is true.
bool value = hello == "one";
while (value || !cin.eof) {}
If you're using C++11:
#include <functional>
auto check = (hello == "one") ? []() bool -> { return 1; } :
[]() bool -> { return !cin.eof(); };
while(check) {
};
How about this:
switch(hello)
{
case 'one':
{
for(; 1; );
{
// your loop here
}
break;
}
case 'two':
{
for(;!cin.eof; )
{
// your other loop here
}
break;
}
default:
{
cout << " shouldnt get here unless bad user input" << endl;
break;
}
}
You can do something like this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string hello;
cin >> hello;
while(hello=="one"?1:(!cin.eof()))
{
//do stuff
}
return 0;
}
It checks if the string hello is "one" and if it's true, the condition of the while is 1, else it is !cin.eof() as you wanted.

C++ console game input && refresh function

I am writing a small console adventure game and I faced a few problems.
1. The input is kinda laggy, I'm using while loop ( while(getch() == 'w') ). After a key is pressed the first time, nothing happens (you have to press it 2 times) and if you switch directions (press key A/D/S) it also doesn't react the 1st time. If you hold a key, it works fine. How can this be fixed?
2. Here's the function I use to refresh game (render the game scene when a key is pressed):
void refresh(char map[Y][X])
{
system("cls");
for (int i = 0; i<UP; i++)
{
cout<<endl;
}
for (int i = 0; i<Y; i++)
{
for (int k = 0; k<LEFT; k++)
{
cout<<" ";
}
for (int j = 0; j<X; j++)
{
cout<<map[i][j];
}
cout<<endl;
}
}
When I use this function once, it's ok, but when they key is pressed or held multiple times - the game field starts to flash. I figured that I need to redraw only a part of the field (where changes are made/movements are done), not the whole field. Can you offer any ideas how to do that?
The sample code for input:
while(getch() == 'w')
{
if (map[y-1][x]!= WALL)
{
map[y-1][x] = CHARACTER;
map [y][x] = ' ';
y--;
refresh(map);
Sleep(SPEED); // this is unnecessary, SPEED is 0, I just kept it for tests
}
}
Basically, the main function looks like this:
int main()
{
(...) Variables (...)
generateMap(FROM FILE);
refresh(); // First initialization of the field
while (getch() != 'q') // While not quitting
{
while(getch() == 'w')
{
if (THE FIELD ABOVE IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 's')
{
if (THE FIELD BELOW IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'a')
{
if (THE FIELD ON THE LEFT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
while(getch() == 'd')
{
if (THE FIELD ON THE RIGHT IS NOT OCCUPIED)
{
setSomeVariables();
refresh(THE GAMEFIELD);
}
}
}
return 0;
}
Don't use system("cls"), it is really slow, instead set the cursor on the beginning of the screen with the following code:
COORD cur = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cur);
You should call getch() only one time in the loop, like this:
char key;
do
{
key = getch();
if(key == 'w')
{
//do something
}
//the other if statements
}while(key != 'q');
The code should have only one getch() in the whole code (if possible) and inside a switch you do the action for each input. So, it is switch inside the loop, and not loops inside the switch. Something like this:
while ((ch = getch()) != 'q')
{
switch (ch)
{
case 'a':
GoLeft();
break;
...
}
}
There is a library called ncurses that you can use to move the cursor around the screen, and write anything anywhere.
It looks like your problem is calling getch() multiple times. Have only one loop, and call getch() once per loop, and store the result. Test that result for each value (q, w, s, ...) for each iteration of the loop.
I would recommend you to use function input() as it stands:
void input()
{ if (GetKeyState('W') & 0x8000) // That means when button "W" is pressed
... your code ...
// (changes global variables, or you can pass variables by reference)
}
without any getch() command that stops your game every single time.
You can use it with the draw() and calculate()/refresh() functions in the main(), like:
int main()
{
... other part of code ...
while (!gameover)
{
input();
calculate();
draw();
}
}
so that you will always have some sort of input value before the calculations, and then you would draw (+ it's much easier to debug ;) )

arrays and functions

my assignment requires me to write a function that reads in a title and return the corresponding fee to the calling function. if the title is not in the list, return -1.0.
this is what i have got at the moment:
struct eventType
{
string title;
double fees;
};
eventType eventTable[10];
int findFees (string newTitle, string newFees)
{
int Index = 0;
int flag;
while (Index < 9) && (eventTable[Index].title != newTitle))
Index = Index + 1;
if (eventTable[Index].title == newTitle)
{
eventTable[Index].fees = newFees;
flag = 0;
}
else
flag = -1;
return flag;
}
is anything missing?
update
after looking at the advice u guys have given, i have adopted and changed the codes to:
double findFees (string title)
{
for (int Index = 0 ; Index < 10 ; Index++)
{
if (eventTable[Index].title == title)
{
return eventTable[Index].fees;
}
}
return -1.0;
}
I'm not sure if this is correct either but I do not need a new title or new fees since these values are to be found within eventTable, and return it.
corrections?
I don't want to give away the answer for you, but here are two things you should keep in mind:
When you have a conditional or a loop, you need to surround statements in { and } so that the compiler knows which statements go inside the loop.
Second, C++ is a type-safe language, meaning that if you are assigning variables to a value of a different type, your program won't compile, look through your code and see if you can find anything wrong on that front
It should be:
while (Index < 10)
And you said it should return the fee, but it returns 0 when found. (This is ok, since you are passing in the fee, why return it too?)
I would also change the signature of the function to be:
int findFees (const string &newTitle, const string &newFees)
and while you are at it, have it return a "bool" instead of a flag to denote success since:
if(findFees(blahTitle, blahFees))
sounds a lot better than:
if(findFees(blahTitle, blahFees) == 0)
when checking for whether the title is found.
It seems to me your function does not return the fees, as you described.
It looks like it updates the eventTable, changing the fee stored there, and returns a flag if the update was done successfully.
Please clarify. Do you want to find the fee stored in the eventTable and return it? Or do you want to update the eventTable with new data? Or a hybrid of both.
Still, for a noob, your code is well structured and reasonably well written.
You could simplfy it as so.
int flag = -1;
int Index = 0;
while(Index <= 9)
{
if(eventTable[Index].title == newTitle)
{
eventTable[Index].fees = newFees;
flag = 0
break;
}
}
return flag;
eventTable[Index].fees = newFees;
This won't work because fees is a double and newFees is a string. Also you didn't say anything about changing the fees, so I'm confused by that line.
If you want to return the fees of the item you found, you should just put return eventTable[Index].fees; at that point and change the return value of the function to float.
Your description (return the fee, or -1.0 if not found) does not match your code:
struct eventType
{
string title;
double fees;
};
eventType eventTable[10];
double findFees (string newTitle)
{
for (int Index = 0 ; Index < 10 ; Index++)
{
if (eventTable[Index].title == newTitle)
{
return eventTable[Index].fees;
}
}
return -1.0;
}
The only error I see is
while (Index < 9) && (eventTable[Index].title != newTitle))
should probably be:
while ((Index < 10) && (eventTable[Index].title != newTitle))
Note the missing '('. Otherwise you miss matching the last entry in the array.
I would probably write the function something like:
double findFees (const string& title, double newFee)
{
for (int i = 0; i < 10; i++)
{
if (eventTable[i].title == title)
{
eventTable[i].fees = newFee;
return newFee;
}
}
return -1.0;
}
This way you will not iterate through the entire array if you already found the item you where searching for.