How do I make a function execute a task when it ends? - c++

I have a function that I wish to be called infinitely as long as conditions are met. However, I cannot simply call the function inside of itself, as that will cause a stack overflow. How do I end the function and start another one at the same time?
Example:
int myFunc() {
//do stuff
char again;
std::cout << "Do it again?\n";
std::cin >> again;
//I want to do this, but in a way that ends the function first.
if (again = y) {
myFunc();
}
}

Well you haven't given any code example, so I'm probably out on a limb here, but I'm guessing you have something like this:
void my_func()
{
// do stuff
// ...
while (cond)
{
my_func();
}
}
There's two ways you can fix this:
1)
// this is wherever you call my_func
void some_other_func()
{
while (cond)
{
my_func();
}
}
void my_func()
{
// do stuff
// ...
}
(better, you only have to edit my_func to call a private implementation of the actual method part)
void my_func_impl()
{
// do stuff
// ...
}
void my_func()
{
while (cond)
{
my_func_impl();
}
}
EDIT
Now that you posted an example, this is how I'd refactor your code to accomplish this:
void doIt() {
// do stuff
}
void myFunc() {
//do stuff
char again;
while (1) {
std::cout << "Do it again?\n";
std::cin >> again;
if (again = y) {
doIt();
}
// if the answer wasn't yes, the if case won't enter
// break the loop in that case
break;
}
}

int myFunc() {
char again;
do {
std::cout << "Do it again?\n";
std::cin >> again;
} while (again == 'y');
}

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

Scope of an object created in an if-condition in C++

In the following example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else {
// ...
}
}
What is the scope of i? Can we use it inside the if-block? Can we use it inside the else-block?
Edit:
As a follow-up, in this modified example
void fun() {
if(int i=SOME_VALUE) {
// ...
} else if(int j=SOME_OTHER_VALUE){
// ...
} else {
// ...
}
}
Can we access both i and j in the else clause?
Yes, and yes.
A typical use for this is dynamic casting:
if (auto p = dynamic_cast<Derived*>(base_pointer))
{
// p is a Derived*
}
else
{
// not the right dynamic type
}
Another construction I've been finding useful:
if (auto fp = std::unique_ptr<FILE, int(*)(FILE*)>(std::fopen("file.txt", "rb"), std::fclose))
{
// file exists, use fp.get()
}
else
{
// file does not exist
}
And one more:
if (pid_t pid = fork())
{
waitpid(pid, nullptr, 0);
}
else
{
execl("/bin/rm", "/bin/rm", "-rf", "/", static_cast<char*>(nullptr));
}
Yes, you can use the variable declared in the if condition in the else substatement like your example.
However, if you declare i inside the if substatement like this:
if (some_condition) {
int i = 42;
// ...
} else {
std::cout << i; //error
// ...
}
in the else part, the variable i is no longer in scope.
Yes, because the variable is "created" in the outermost scope and only then, evaluated in the if condition. Your code could be rewritten like:
int i = SOME_VALUE;
if(i) {
// ...
} else {
// ...
}
and not like:
if(SOME_VALUE) {
int i = SOME_VALUE;
// ...
} else {
// ...
}
as you may have though.
The second question can be answered the same way.

Should I use returning functions when the return value isn't needed?

I have a function that looks like this:
int Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return 0;
}
else {
// do other stuff
}
}
}
I'm wondering if it is common or proper to have a returning function, rather than a void function, for the sole purpose of leaving the function (the value being returned wouldn't do anything in the program except for ending the function). Is this good practice, or is there a better way to end a function?
There is no problem with void functions. If it does not return anything useful, it should be void.
Just make your function void, and simply return?
// vv void return type
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return; // <<<< No return value
}
else {
// do other stuff
}
}
}
You can easily just use return; with no parameter to exit a void function. Your above code would become:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
else {
// do other stuff
}
}
}
If there is no useful value for the function to return, it is better not to return a value - because the calling code should check the returned value.
Your code can be doubly simplified:
void Game::GetInput() {
while (true) {
// do stuff
if (something) {
// do this
return;
}
// do other stuff
}
}
The else is unnecessary; the only way to execute the 'do other stuff' is if something is false.

Two questions of c++ which just change a little,however very different answers

Recently I do a exercise about algorithm with c++. Exercise in here:poj
I find two very confused questions.
I write a class MAZE and there are three primary functions in MAZE,they are
int left_path();int right_path();int mini_path();
and a function to print the answers:
void display(){
cout<<left_path()<<" "<<right_path()<<" ";
cout<<mini_path()<<endl;
}
the program can work correctly.As we see the function display() can be easy;
I write like this
void display(){
cout<<left_path()<<" "<<right_path()<<" "<<mini_path()<<endl;
}
just one change ;however the program can't work,it like loop infinitely.
following is the other question:
the function mini_path's frame like this
int maze::mini_path(){
ini();
queue<pair<int,int> > q;
q.push(make_pair(x,y));
while(!q.empty()){
pair<int,int> tmp=q.front();
q.pop();
int t=...;
if(E){
return t;
}
if(E){
S
}
if(E){
S
}
if(E){
S
}
if(E){
S
}
}
return -1;
}
if there is "return -1" in the end ,the function works right,else the function return random big number.
The program is in only one file and i use the gun compiler.
I don't show the total codes,because i think nobody wants to see them.I just want to ask what problems may lead above strange behaviors.
source code(simplified for question2):
typedef enum {LEFT=-1,RIGHT=1,UP,DOWN} direction;
ifstream fin("file_test3.txt");
class maze{
public:
maze(){input();}
int mini_path();
void input();
void display(){
cout<<mini_path()<<endl;
}
private:
bool is_not_dest(){
return !(x==d_x && y==d_y);
}
void ini_dir()
{
if(e_x==0) dir=DOWN;
else if(e_x==height-1) dir=UP;
else if(e_y==0) dir=RIGHT;
else dir=LEFT;
}
void ini(){
x=e_x;
y=e_y;
path_lenth=1;
ini_dir();
}
direction dir,d;
int width,height,maze_map[40][40],path_lenth;
int x,y,e_x,e_y,d_x,d_y;
};
void maze::input()
{
fin>>width>>height;
char sym;
for(int i=0;i<height;++i)
for(int j=0;j<width;++j){
fin>>sym;
if(sym=='#')
maze_map[i][j]=1;
else if(sym=='.')
maze_map[i][j]=0;
else if(sym=='S'){
maze_map[i][j]=-1;
e_x=i;
e_y=j;
}
else {
maze_map[i][j]=-2;
d_x=i;
d_y=j;
}
}
}
int maze::mini_path()
{
ini();
queue<pair<int,int> > q;
if(dir==LEFT) {maze_map[x][--y]=2;}
else if(dir==RIGHT) {maze_map[x][++y]=2;}
else if(dir==UP) {maze_map[--x][y]=2;}
else {maze_map[++x][y]=2;}
q.push(make_pair(x,y));
while(!q.empty()){
pair<int,int> tmp=q.front();
q.pop();
x=tmp.first;
y=tmp.second;
int t=maze_map[x][y]+1;
if((x==d_x && (y-d_y==1 || y-d_y==-1)) ||(y==d_y && (x-d_x==1||x-d_x==-1))){
return t;
}
if(maze_map[x-1][y]==0){
maze_map[x-1][y]=t;
q.push(make_pair(x-1,y));
}
if(maze_map[x+1][y]==0){
maze_map[x+1][y]=t;
q.push(make_pair(x+1,y));
}
if(maze_map[x][y-1]==0){
maze_map[x][y-1]=t;
q.push(make_pair(x,y-1));
}
if(maze_map[x][y+1]==0){
maze_map[x][y+1]=t;
q.push(make_pair(x,y+1));
}
}
return -1;
}
main()
{
int n;
fin>>n;
while(n-- >0){
class maze m;
m.display();
}
}
I see it! Can you see it? :)
#include <iostream>
using namespace std;
int foo(int bar)
{
cout << bar << endl;
return bar;
}
int _tmain(int argc, _TCHAR* argv[])
{
cout << foo(1) << foo(2) << foo(3) << endl;
return 0;
}
The output:
3
2
1
123
regarding question1:
The order in which the functions are called will be different.
the first solution will call them in following order:
right_path
left_path
mini_path
the second solution results in following order:
mini_path
right_path
left_path
so the solution you probaly want is:
void display(){
cout<<left_path()<<" ";
cout<<right_path()<<" ";
cout<<mini_path()<<endl;
}
There is not enough info to answer the first question; both codes are equivalent.
[Edit:Check other answers. Anyway, both codes should be equivalent: you have bugs in your code.]
About the second question, I guess that that "return -1" marks "no possible path" in your maze, that's why, when you remove it, your program stops working.
In the maze problem, a backtracking algorithm moves square by square. When from a square there is no possible path, this square must be marked as no path.

How to implement final conditions properly?

This is what I'm trying to do (this is a simplification of a real project):
int param;
int result;
void isolated(int p) {
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
} catch (...) {
throw "problems..";
}
}
I can't change the way process() works, since this function is not created in the project and is a third-party function. It works with global variables param and result and we can't change this.
The problem appears when isolated() is called back from process() with another parameter. I want to catch this situation, but don't know how to do it, since finally is absent in C++. I feel that I should use RAII technique, but can't figure out how to do it in this case properly.
This is how I can make it with code duplication:
int param;
int result;
void isolated(int p) {
static bool running;
if (running) {
throw "you can't call isolated() from itself!";
}
running = true;
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
running = false;
} catch (...) {
running = false; // duplication!
throw "problems..";
}
}
"finally" like situations are handled in C++ using guard objects, that do their finally thing in the destructor. This is IMHO much more powerful approach, because you have to analyze the situation to finalize in order to create a reuseable object. In this case, we need to make process rentrant, because parameters and returns are passed in globals. The solution is to save their values on entry and restore them on exit:
template<class T>
class restorer
{
T &var; // this is the variable we want to save/restore
T old_value; // the old value
restorer(const restorer&);
void operator=(const restorer&);
public:
restorer(T &v) : var(v), old_value(v) {}
~restorer() { var=old_value; }
};
int param;
int result;
int isolated(int p) {
restorer<int> rest_param(param);
restorer<int> rest_result(result);
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
return result;
} catch (...) {
return 0;
}
}
Maybe I didn't get it right, but why don't you use a flag? You want to know when the isolated() is called from the process(), right?
int isolated(int p) {
static int execDeep = 0;
execDeep++;
// your code here
execDeep--;
}
Now you can check 'execDeep' value, > 1 means it is called from the process() while still being executed.
I still don't quite sure how finally is related here, but you could try Boost.ScopeExit if you want to avoid creating a scope guard structure yourself.
Example:
#include <boost/scope_exit.hpp>
#include <cstdio>
int isolated(int p) {
static bool running = false;
if (running) {
printf("Throwing %d\n", p);
throw p;
}
printf("Starting %d\n", p);
running = true;
BOOST_SCOPE_EXIT( (p)(&running) ) { // <--
printf("Stopping %d\n", p); // <--
running = false; // <--
} BOOST_SCOPE_EXIT_END // <--
// ...
if (p)
isolated(p*10);
// ...
printf("Returing %d\n", p);
return 4;
}
int main() {
printf(">> first\n");
isolated(0);
printf(">> second\n");
try {
isolated(1);
printf(">> third (should not be printed.)\n");
} catch(int p) {
printf("Caught %d\n", p);
}
isolated(0);
printf(">> fourth\n");
return 0;
}
Result:
>> first
Starting 0
Returing 0
Stopping 0
>> second
Starting 1
Throwing 10
Stopping 1
Caught 10
Starting 0
Returing 0
Stopping 0
>> fourth
Could this work?
int save = -10000000000;
int param;
int result;
int isolated(int p) {
if (save != -10000000000)
{
// run the other condition
}
else
{
save = p;
param = p;
try {
// make calculations with "param" and place the
// result into "result"
process();
return result;
} catch (...) {
return 0;
}
}
}
If I understand correctly, you want to automatically set the running flag to false at the end of function. If that is the requirement then you can use the ScopeGuard approarch mentioned in the link.