So, I'm kinda new to C and I wanted to know what are the good practices or even how do I handle runtime errors when programming, here is an example:
State s_toState(std::string state){
if (state == "MG")
return State::MG;
else if (state == "PR")
return State::PR;
else if (state == "SP")
return State::SP;
else if (state == "SC")
return State::SC;
else if (state == "RJ")
return State::RJ;
else if (state == "RN")
return State::RN;
else if (state == "RS")
return State::RS;
// ???
}
So I have this function that transforms a string
into a State
. Without using exception, what is the ideal way for me to assert that the given state is an existing one (MG, PR, SP, etc...)?
Gave an example but I'm asking for the general rule. As far as I know i could use exceptions, assertions or just print the error. I do pretend to unit test this too (also new to unit testing and know nothing about it).
CodePudding user response:
This looks like a good opportunity to use exceptions. The cplusplus.com guide is reasonable, but I found that playing around with it is a better way to learn.
The basic idea is this:
- A function
throw
s an exception, terminating the function and passing the exception to whoever called the function. - If the caller calls the function in a
try
block, then the subsequentcatch
will be executed. - If the caller does not have a
try
/catch
system, the caller is terminated as well and the process repeats down the function call stack until it either finds atry
/catch
ormain()
is terminated.
CodePudding user response:
The answer depends on what s_toState
"promises" to do.
If state
being invalid is a fault of a programmer who the function or an error in other internal logic. Add assert
and document state validity as a precondition (same as !=nullptr
for pointers). For release build, add some default behaviour just so the program does not crash if possible. Or let it crash if you are not writing critical SW, it will at least make debugging easier.
If it is a recoverable fault of an user and plausible scenario (not a bug), then consider returning std::optional
or throw
. I prefer the former when the thrown exception would have always been caught by the direct caller, i.e. never propagated up the call stack. I also find it more clear as it forces the caller to explicitly handle it.
For unrecoverable faults, i.e. when the direct caller cannot handle the nullopt
, just throw and let some other code deal with that.
I like the naming convetion of try_parse
returning std::optional
, while parse
throwing.
It might be worth givin Exceptions and Error Handling FAQ a try.