C++ - Continuing a while loop upon exception - c++

When an exception is encountered in C++, does the program automatically terminate upon catching it. Is there a way that ,if the exception was caught within a loop, I could just skip the rest of the loop and go straight to the next iteration?

There are a number of different ways to solve this problem.
Create a member function that checks whether a move is valid before making it. The calling code will need to call this function before calling advance, and only call advance if the move is valid.
Make the advance member function return a value indicating whether the player's position was advanced. The calling code will need to test the return value to decide whether to print the board or print a "try again" type of message.
Make the advance member function throw an exception if the move is invalid. The calling code will need to catch the exception.
There are lots of other ways to solve this problems.

Well first of all, if that snipped of code is EXACTLY how you copy-pasted it, it has some syntax errors. This is how it should be written:
int main() {
...
Person *p = new Person("Neo");
...
string in;
while(cin >> in) {
if (in == "q") {
break;
}
else if (in == /*One of the eight directions North ... Northwest*/) {
p->advance(in);
} //this bracket here ends the if. after the parentheses, nothing else will execute
else {
cerr << "Input one of the eight directions" < endl;
}
}
}
So yeah, if I understood correctly your problem, adding that closing bracket there should solve it. I hope this is what you needed and that it was helpful

Related

word.exe has stopped working using recursion

when I remove return in else section the code throw word.exe has stopped working
I tried to debug and when the base condition is true and 'i' start to decrement when 'i' is equal to 1 it throws the error
string o = "555";
string play(int i){
if(i == 3) return o;
else
return play(i+1);
}
You cannot remove the return statement.
Indeed, play() returns a string. So if the condition is true, you return the string o. But if you enter the else block, you also have to return a string, because the play(i+1) will return a string if its condition succeed, but nothing otherwise (except running another call). And you don't want to get nothing, you want to get back the resulting string.
In other words, when the child function returns a string, the current function needs to pass it to its parent and so on. If the child function condition succeeds and you missed the return statement, you will never pass this result to the parent and finally, you will return nothing at the top (Unexpected behaviour or error, honestly I didn't try).
And by the way, the code you are running is very dangerous. If the int passed in parameter is greater than 3, the recursion will run endlessly, adding play() calls until running out of memory.
I hope it answers your question :)

How to use a variable in the same struct it's defined in?

I am making a rogue-like ASCII game and made a struct called "Armor" and I want to use the name variable in the struct to have the path to whatever the name is.
struct Armor {
bool equipped;
std::string name;
int getBuff(int buff) {
std::fstream item;
std::string line;
std::string response;
std::string value;
item.open("../Data/Items/" + name + ".item", std::fstream::in);
if (item.fail())
errorQuit("ERROR: There was a problem loading armor type .ITEM file."); // Error and quit function
while (!item.eof()) {
getline(item, line);
response = split(line, '=', 0); // Splits string
if (response == "buff" + std::to_string(buff)) {
value = split(line, '=', 1);
break;
}
}
item.close();
return std::stoi(value);
}
};
Then I called it like this:
Armor sword;
sword.name = "Wooden Sword";
int buff = sword.getBuff(1);
But this throws an Unhandled exception error.
I changed it so that getBuff takes 2 parameters, int buff and std::string itemName. and replaced name in the path with itemName;
Then I tried calling it like this:
Armor sword;
sword.name = "Wooden Sword";
int buff = sword.getBuff(1, sword.name);
But this throws the same error.
I'm confused as to why I can't use the name variable as it has already be defined. Is there any other way I can use the name variable like that?
I see you've just edited your comment to say you've figured your problem out, but I just want to add something else that may be helpful:
Without seeing how errorQuit() is defined, there's a potential problem in your getBuff() function. If the expression if (item.fail()) evaluates to true, the function may continue on trying to process the data (unless errorQuit() somehow breaks out of the program or something, which probably isn't the best approach).
Basically, testing for fail() may or may not provide the behavior you require in all scenarios, depending on what bits are set in the stream state. Implementations vary, but... if the file fails to open, failbit and/or badbit will be set, but not eofbit. getline() will see the error state and so it will not try to read from the stream when you call it. But that also means the eofbit will never be set!
There's lots of different "techniques" to file reading. Some people prefer an RAII approach. Others like looping on getline(). Or you could even just use good() to check the error state if you don't care what happened and simply want to know if everything is fine or not.
In any case, you might be interested in the info on this page: std::ios_base::iostate.
Thanks for all your help but I figured it out on my own.
I just made a stupid error that I overlooked like an idiot.
It is searching for buff + int (e.x. buff1) in the file but there are multiple lines that contain that word so I guessed that messed it up. I just made an adjustment to the if statement and it is working as expected.
Sorry to bother you!
your getBuf() function fails on some io-operation and throws an exception.You dont handle exceptions and thus the application quits with the appropriate message. Try surrounding the call to getBuf with try/catch (add the includes to iostream and stdexcept)
try {
int buff = sword.getBuff(1);
}
catch (const std::exception &e) {
std::cout << e.what() << std::endl;
}

Throwing an error to main from a function called by another function

Let's say I have a function (mnHw) that calculates the mean of a vector (a vector of homework grades). This function throws a domain_error("Student did no homework") exception when the vector is empty. When I call mnHw from main, things are simple when I want to print out the error:
try
{
cout << mnHw(student.homework);
}
catch (domain_error e)
{
cout << e.what();
}
However, things are complicated if I only want to store the mean homework grade, instead of vector of all grades, for the student. In that case I call mnHw within the function that reads in the student information (readStudent), and put up a flag (-1) when no homework is entered:
try
{
student.finalGrade=mnHw(hwGrades);
}
catch (domain_error e)
{
student.finalGrade = -1;
}
Then, within main, I can do the following to recover the error:
if (allStudents[i].finalGrade == -1)
cout << "Student did no homework";
else
cout << allStudents[i].finalGrade;
Intuitively, though, this flag method seems less elegant than having the actual error message pass directly to main, at least for those cases when I want to display it from main (which is the case here). Is there some trick or technique I am missing that would directly give main access to e.what() from mnHw?
What is good practice?
Note I have full functions for each of these cases that I could post, but they seemed too long. Please let me know if I should have included them to make myself more clear. Also, please feel free to correct any other mistakes I’m making. I am just now learning C++ the right way, and want to be corrected as much as possible. <flame-retardant vest>
You can re-throw the exception catched (const domain_error* e){ throw e;}. Or better, you can create based on domain_error create another exception i.e., student_final_grade_exceptionand throw it.
EDIT:
Something like:
try
{
student.finalGrade=mnHw(hwGrades);
}
catch (domain_error& e)
{
student_final_grade_exception mean_excep;
mean_excep.addInfo("Error in calculation means...");
mean_excep.addInfo(e.what());
throw mean_excep;
}
And then, you prepare your main to catch student_final_grade_exception. Of course, there is a litle bit more work to create a new exception type, but it can make possible to get more info and let the functions to only what they suppose to do as were told.

c++:return statement behaving weirdly

Here is an outline of the code containing the relevant part of my code.
Inside the empprint function i call a bfs print function, which calls itself recursively till its done printing everything that needs to be printed, after which its supposed to return me back to empprint function. But the return statement in bfsprint doesn't take me back to empprint.
One possible reason I can think of is that bfsprint calls itself recursively so it will only return to the last bfsprint method that called it instead of empprint function but it doesnt seem to solve my problem. I m stuck up with a code whose execution doesnt terminate.
void node::empprint(node* myroot)
{
//do something
bfsprint(c);
cout<<"pt 5"; //this cout is not reached
return;
}
void node::bfsprint(Linklist<node*> noddy)
{
// lot of code to implement breadth-first search. No issue
if(c.getHead()==NULL) cout<<"1" //this does print 1 to output
if(c.getHead()==NULL) return; //I think this should send me back to empprint
// and print "pt 5" on output but program hangs.
// instead of this happening
bfsprint(c);
}
If anybody thinks this might be influenced by other code in the method , I will add it but I dont think its the case.
If your call stack looks like:
node::empprint
node::bfsprint
node::bfsprint
then returning from the final call will result in
node::empprint
node::bfsprint
So your still N calls deep away from getting back to node::empprint.
You could set a bool in the class to return back out, but thats a bit hacky..
void node::bfsprint(Linklist<node*> noddy)
{
if ( something ) { m_unwindstack = true; }
// setting the bool to force returning early/stop recursion once m_unwindstack is true to get back to empprint
if ( m_unwindstack ) { return; }
}
Edit: By the way if you're doing anything with Linklist you'll never seen the changes since your passing a copy of the data. You should pass a reference Linklist&.
Also Linklist seems like your own class? So if you don't use a reference then be sure its copyable otherwise bad things will happen.

Throw in C++ triggers program message then crash

I debugged my application and the code crashes instantly upon the throw statement inside of this code:
try
{
char newbuff[8];
if(strlen(cstr) > sizeof(newbuff))
{
throw BUFFER_TOO_SMALL;
}
if(strlen(cstr) == 0)
{
throw NO_CONTENT;
}
strcpy(newbuff, cstr); //Yeah yeah yeah, I know, I'm just learning
ptr = newbuff;
}
catch(int errn)
{
cout << "error: ";
if(errn == BUFFER_TOO_SMALL)
{
cout << "storage buffer too small.\n";
return 0;
}
if(errn == NO_CONTENT)
{
cout << "no content inside of buffer.\n";
return 0;
}
}
So, upon debugging it crashes right on the throw statement. Interestingly enough, the CLI (in this case, 'cmd.exe') shows this message (which was not put in there by me, and is either from the compiler or the OS):
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
I'm leaning more towards C++ now, as I used to just program in C. As you can tell, right now I am trying to manage the try-catch exception handling system that C++ uses.
Your if statement looks incorrect: the name newbuff indicates a pointer, and the size of that will be 4 on a 32-bit system or 8 on a 64-bit system. Oh, right, after I posted that you've edited you code to show the definition of newbuff as an array. But anyway.
The throw can crash if there is no handler. In this case the standard does not require that the stack is rewound (local objects destroyed).
It seems that BUFFER_TOO_SMALL is a constant, probably an integer. You should not throw integers (unless you really know what you're doing). Throw std::exception objects, e.g. std::runtime_error.
Edit: Your updated code shows that you're catching int. That means your uppercase constants are not int. But the advice stands anyway.
There is also a style issue, the use of ALL UPPERCASE for a constant. Don't. That's a Java-ism: in C and C++ by convention all uppercase is for macros and macros only.
Cheers & hth.,
It seems that newbuff don't have space for NULL terminator. you should resize newbuff[8] to newbuff[9].