Flowchart nodes permitted in any order? - flowchart

I'm writing the instructions for a process. Steps C, D, and E must be done between Step B and Step F, but they can be done in any order. What's the best way to show that in a flowchart?
In what I hope is a related question: If Step X can be performed at any point between Step F and Step K, how would I signify that on a flowchart?

I'm writing the instructions for a process. Steps C, D, and E must be done between Step B and Step F, but they can be done in any order. What's the best way to show that in a flowchart?
The best way is up to you. There are different ways, some are easier to program--others are easier to explain. And, while you only ask about process; there is, at least, some similarity between programming a computer and instructing others.
The first diagram shows the various routes that may be taken. These routes are presented using something like a state diagram, without noting the context of the transitions. The context required is next; that is, I did this--what's next.. There are six combinations each with four paths, to cover all possibilities.
Although I used simple process symbols in the following; any could need a predefined process symbol, if they are (or could be) diagrammed with a separate flowchart.
The second diagram has two implementation choices. (Using C psuedocode to explain.)
Using a for statement,
int next[3]; // next is prepared elsewhere,
// because each next[] value is unique there can be no repetition
{
b();
for (int i = 0; i < 3; i++)
{
case 1: c();
case 2: d();
case 3: e();
}
f();
}
Or, for old time state machine people, using goto statements (Note that goto is often used in instructions for US income tax forms and may be useful for instructing others, in other contexts.)
int next[4]; // next is prepared elsewhere, next[3] defaults to 4 or F
int i = 0;
{
b();
switch (next[i++])
{
case 1: goto C;
case 2: goto D;
case 3: goto E;
default: goto F;
}
C: c(); // do the C thing
switch (next[i++])
{
case 1: goto C;
case 2: goto D;
case 3: goto E;
default: goto F;
}
D: d(); // do the D thing
switch (next[i++])
{
case 1: goto C;
case 2: goto D;
case 3: goto E;
default: goto F;
}
E: e(); // do the E thing
switch (next[i++])
{
case 1: goto C;
case 2: goto D;
case 3: goto E;
default: goto F;
}
F: f();
}
The third diagram uses nested if statements,
int next[3]; // next is prepared elsewhere, next[3] is not used
{
b();
if (next[0] == 1)
{
c();
if (next[1] == 2)
{
d();
e();
}
else
{
e();
d();
}
}
else if (next[0]) == 2)
{
d();
if (next[1] == 1)
{
c();
e();
}
else
{
e();
c();
}
}
else if (next[0] == 3)
{
e();
if (next[1] == 1)
{
c();
d();
}
else
{
d();
c();
}
}
f();
}
The fourth diagram uses a switch statement for the required pattern,
int pattern; // prepared elsewhere, values 1 through 6
{
b();
switch (pattern)
{
case 1:
{
c();
d();
e();
}
case 2:
{
c();
e();
d();
}
case 3:
{
d();
c();
e();
}
case 4:
{
d();
e();
c();
}
case 5:
{
e();
c();
d();
}
case 6:
{
e();
d();
c();
}
}
f();
}
In what I hope is a related question: If Step X can be performed at any point between Step F and Step K, how would I signify that on a flowchart?
{
f();
if (condition) x();
g();
if (condition) x();
h();
if (condition) x();
i();
if (condition) x();
j();
if (condition) x();
k();
}

Related

how to replace a value of a variable inside code from user input?

i am trying to add a developer mode in my program. since duty of car defers every month,i want give my user permission to change every single variables in my program alike duty lccost yen2taka freight
#include <iostream>
using namespace std;
class A
{
public:
int carbid,duty;
void Input()
{
cout<<"please insert the car price you want to bid for(in yen): ";
cin>>carbid;
cout<<"duty of the car: ";
cin>>duty;
}
int Exportcost()
{
int exportcost;
int servicechrg=10;
int freight=20;
exportcost=servicechrg+freight+carbid;
return exportcost;
}
int Yen2taka()
{
int yen2taka;
int taka2dollarrate=10;
int dollar2yen=1;
yen2taka=((Exportcost())/dollar2yen)*taka2dollarrate;
return yen2taka;
}
int Importcost()
{
int importcost;
int lccost=10;
int cnfcost=20;
importcost=lccost+cnfcost;
return importcost;
}
int Totalcosting()
{
int total;
int myprofit=10; //80000
total=myprofit+Importcost()+Yen2taka();
cout<<total;
return total;
}
void summary()
{
cout<<
}
};
int main()
{
x:
A ob;
ob.Input();
ob.Exportcost();
ob.Yen2taka();
ob.Importcost();
ob.Totalcosting();
int ch;
cout<<"press 1 to see the summery of the costing or 2 to restart costing again"<<endl;
cin>>ch;
switch(ch)
{
case 1:
ob.summary();
break;
case 2:
goto x;
}
}
At first, you should collect these parameters in a separate class:
class Configuration // maybe you find a better name...
{
int m_servicechrg = 10; // default
int m_freight = 20;
// ...
public:
int servicechrg() { return m_servicechrg; }
void servicechrg(int value); { /* check some limits? */ m_servicechrg = value; }
int freight() { return m_freight; }
void freight(int value); { /* check some limits? */ m_freight = value; }
// ...
};
// will allow you to do:
// C c; std::cout << c;
ostream& operator<<(ostream& s, Configuration const& c)
{
// which ever formatting is appropriate...
s << c.servicechrg() << ' ' << c.freight();
return s;
}
The setters could alternatively return bool to indicate invalid values.
Now you can use this class within main:
Configuration c;
A a;
int cost = a.exportCost(c); // you'd have to adjust signatures...
int value;
switch(ch)
{
case 4:
if(stc::cin >> freight) // catches invalid user input!
// one ALWAYS should do, otherwise you might end up in
// your program not working any more
{
c.freight(value);
// or, if you have:
if(!c.freight(value))
{
// some appropriate error message
// (it's better not to output in the setter, you are more flexible this
// way – maybe you want different messages at different occasions?)
}
}
else
{
// appropriate error handling
}
break;
default:
// handling invalid user input
// again, you always should; but stream state is not in error state,
// so you just can print appropriate error message
break;
}
See this answer for how to correctly handle stream errors.
If you wonder about the differences in error handling: First case is met if user enters non-numerical input, such as ss, second case, if input is numerical, but out of valid range (77).
Now if you don't want to pass the configuration as parameter all the time, you could make a global variable from (but careful, there are some dangers with global variables, use them as sparely as possible) or implement the singleton pattern.
Side notes: goto can be a fine tool sometimes, but it is a dangerous one (and the label's name x isn't a good one, prefer a name that clearly shows intention, such as REENTRY_POINT, LOOP_START, ...). If you can get along without unreasonable effort, prefer such variants:
bool isRunning = true;
do
{
// ...
case 2:
isRunning = false;
break;
}
while(isRunning);
Sure, an additional variable, an additional check; unfortunately, you cannot use break to exit a (pseudo-) endless loop (for(;;)) (but don't apply this pattern for nested loops, then it gets more and more unreadabla – and ineffcient: bool isExit = false; for(int i = 0; !isExit && i < n; ++i) { for(j = 0; j < n; ++j) { isExit = true; break; } } – see what I mean?). A variant might be:
for(;;)
{
switch(ch)
case 1:
// ...
//break; <- replace
continue;
case 2:
//
break;
} // end of switch
break; // break the surrounding for(;;) loop
}
But that's not really nice either.
A pretty nice variant allowing to exit the loop in the given case, as there isn't anyhting to do afterwards:
for(;;)
{
switch(ch)
{
case 2:
// maybe yet some cleaning up here
return 0;
default:
// ...
break;
}
}
Drawback: The function's exit point possibly is deeply nested inside the code.
There are yet other tricks to allow this pattern, like packing sub-sections of code in a lambda having a return inside and call that one directly. But that now really starts going beyond the scope...
Finally, if you insist on goto, my variant would rather be:
for(;;)
{
switch(ch)
{
case 2:
// ...
goto LOOP_EXIT;
default:
// ...
break;
}
}
LOOP_EXIT:
return 0; // e. g. main
(void)0; // if there isn't anything to do in the function any more
// (labels require an instruction afterwards!)
There won't be a hidden loop now and it is more obvious what you actually are doing. Currently, not really an issue, but if your code grows, the hidden loop gets more and more difficult to spot.
In such cases, I clearly mark the gotos so that another coder can immediately spot the critical code points:
///////////////////////////////////////////////////
// possibly some comment why applying this pattern
goto SOME_LABEL;
///////////////////////////////////////////////////
One could do the same with deeply nested function exit points (return).

Why can you define a variable in a switch statement under 'default' but not under 'case'

I understand why I can't define a variable under 'case', but why can I define one under 'default' then? I thought it was another label, just like 'case'.
switch(myVar)
{
case 0:
int a = 12; //error
break;
default:
int b = 42; //OK
}
Try reordering your cases:
switch(myVar)
{
default:
int b = 42; // error
break;
case 0:
int a = 12; // ok
}
Now you will see the compiler complain about b, and not a. There is nothing magical about default, it's just that if you define the variable in the last case statement, then there is no way to skip over the initialization of that variable, and so it is perfectly fine to do so.
You can always scope your cases, so that the variables can't be accessed outside of a case, if that was your intention:
switch(myVar)
{
case 0: {
int a = 12;
}
break;
default:
int b = 42;
}
You can't define it under case 0 because a jump to the default label (which is what a switch statement does) will skip the initialization of a.
C++ forbids such skipping. If there's variable being initialized in a block, then control cannot go to a point inside the block that is past the initialization, without preforming it.
However, since int is a type without a constructor, then you can define the variable if you omit the initializer:
switch(myvar)
{
case 0:
int a; //OK too
break;
default:
int b = 42; //OK
}
Initialize all your variable before the switch statement.
int a = 0;
switch(myVar)
{
case 0:
a = 12; //now ok
break;
default:
int b = 42; //OK
}
It has got something to do with C++ standard.
More info here Cross initialization
You can also do that:
switch(myVar)
{
case 0:
{
int a = 0;
}
break;
default:
int b = 42; //OK
}

Recursion to iteration preserving variables and order of calls

I have a very complex code to transform from recursion to iteration. I don't know how to do that with this kind of code :
read(std::queue<int>& rules, std::queue<double>& data)
{
int r = rules.top();
rules.pop();
switch(r)
{
case 1:
{
double a = data.front(); data.pop();
read(rules, data);
double b = data.front(); data.pop();
read(rules, data);
double c = a + b;
data.push(c);
}
break;
case 2:
{
read(rules, data);
data.pop();
}
break;
case 3:
{
data.push(0.0);
}
}
}
I have no idea how to start in this kind of situation...
The standard way is to simulate your recursion stack with an explicit stack as a local variable.
struct Task {
int caseValue; /* 1, 2, 3 */
std::queue<int>& rules;
std::queue<double>& data;
void execute(std::stack<Task>& agenda)
{ // do one thing and put next tasks in the agenda
// by using agenda.push_back
}
};
typedef std::stack<Task> Agenda;
void read(...) {
Agenda agenda;
int r = rules.top();
rules.pop();
agenda.push_back(Task(r, rules, data));
while (!agenda.empty()) {
Task task = agenda.top();
agenda.pop_back();
task.execute(agenda);
};
}
Here the agenda simulates your recursion stack. The iterative version may be less efficient, but it may ease the debugging since you can set a breakpoint within the while loop.

Control may reach end of non-void function switch statement

I tried to do a simple calculator. Don't understand why i'm getting the warning that "Control may reach end of non-void function." for the f() function. Any suggestions?
Here is my code:
#include <iostream>
using namespace std;
int f(int a, int b, int i){
switch(i){
case 1: return a+b;
case 2: return a-b;
case 3: return a*b;
case 4: return a/b;
case 5: return a%b;
}
}
int main(){
char Continue='y';
int a,b,i;
cout<<"1.Add"<<endl<<"2.Subtract"<<endl<<"3.Multiply"<<endl<<"4.Divide"<<endl<<"5.modulus"<<endl;
do{
cout<<"Enter two numbers:"<<endl;
cin>>a;
cin>>b;
cout<<"Enter the number of what kind of caculation you want to do";
cin>>i;
cout<<f(a,b,i);
cout<<"Press y to continue/n";
cin>>Continue;
}while(Continue=='y');
}
Because if i is neither 1, 2, 3, 4, 5, then the execution passes over the entire switch statement completely, and there is no explicit return from a function that should return an int.
you need to add some type of default label into your switch statement, general syntax is as follows
switch(value)
{
case 0 :
//do something
break;
case 1:
break;
//// add any case as needed
default : // this would be the line you're missing
break;
}
non void means it doesn't return anything, it's the same thing as witting a function that returns a something, but instead you skip that part entirely
tldr you're esentially doing this
int non_void()
{
//do stuff but not return anything
}

Nested IF statements vs IF-ELSE

I'm learning C language usnig Turbo C++ compiler and just in time I encountered the two statements:
IF (nested with many IFs)
IF-else(not nested but continuing else,else and so on)
I was wondering if my idea is correct or not that IF (nested with many IFs) and IF-else(not nested) are the same? Suggestions are well appreciated.
That's only basic logic behind that:
Nested if conditions:
IF first condition's value is true, go into the second condition.
if(a > 0)
{
printf("A is greater than 0\n");
if(a > 2) printf("A is greater than 0 and 2\n");
}
if-else condition:
IF first condition's value is false, go to the next:
if(a > 0) printf("A is greater than zero\n");
else if(a < 0) printf("A is lesser than zero\n");
else printf("A is zero\n");
There is one more instruction that you should know, switch:
switch(a)
{
case 0: printf("A is zero\n"); break;
case 1: printf("A is one\n"); break;
case 5: printf("A is five\n"); break;
default: printf("A is not 0, 1 or 5\n"); break;
}
Nested if is not equivalent to if-else. It can be equivalent to single if with a combined condition, for instance:
if (a == 1) {
if (b == 2) {
...
}
}
is equivalent to:
if (a == 1 && b == 2) {
...
}
I guess you rather mean if this:
if(expression){
//code
}
else{
if(expression){
//code
}
}
is equivalent to this:
if(expression){
//code
}
else if(expression){
//code
}
and yes it's absolutely the same. Second one is just better looking way of doing this.
The else if blocks are in fact nested else’s since C and C++ don’t have any special support for “elseif” or “elif” concept (not speaking about the preprocessor directives now). It gets obvious with strict use of blocks and indentation:
if(something) { doSomething(); }
else {
if(anotherThing) { doAnotherThing(); }
else {
if(yetAnotherThing) { doYetAnotherThing(); }
else
{ doSomethingElse(); }
}
}
The same code written with the usual else if notation:
if(something) { doSomething(); }
else if(anotherThing) { doAnotherThing(); }
else if(yetAnotherThing) { doYetAnotherThing(); }
else { doSomethingElse(); }
And as Mateusz Kwaśniak has mentioned, you should prefer switch over else if when possible. However, it’s not available for string comparison, for example.