switch case avoid loop - c++

I have the following code:
int send_cmd( int sock, char * buffer, int lbuffer )
{
int err = 0;
//do_something part 1
while(1)
switch(check_status(buffer)){
case 1:
return 0;
break;
case 0:
if (err > 0)
break;
//do_something part 2
err = 1;
}
return -1;
}
I don't think this is well coded but I didn't know how to optimize it.
I wanna run the "part 2 code" only once and only if "part 1 code" gives an error.
Can you tell me how to make it run correctly? Cause right now doesn't return anything after part 2 is executed once.

I wanna run the "part 2 code" only once and only if "part 1 code" gives an error.
There's no need for a while loop or a switch statement.
// Do something part 1
if (check_status(buffer) == 1) {
return 0;
}
// Do something part 2
if (check_status(buffer) == 1) {
return 0;
}
else {
return -1;
}

If you don't need the loop, you can just use an if and return. Since you don't use err, you can omit it as well.
// first command
int status = check_status(buffer);
if (status == 1)
return 0;
// second command
status = check_status(buffer);
if (status == 1)
return 0;
return -1;
At least in this simple case, switch is not better or faster than if. There might be cases, where this is true, but I won't bet on it. Usually, the optimizer is good enough to emit optimal machine code, whether you use switch or if. So go for the simple, readable and maintainable code.

Looking at your, i think this is what you are trying to achieve using the err variable :
//Part 1
if ( check_status(buffer) ) return 0; //No error
//Part 2
if ( check_status(buffer) ) return 1; //One error
else return -1; //Two errors
You dont need any while loops to do this.

Related

How IF statement works with AND and OR?

Suppose that I have the following code in a generic language:
a = 1
b = 2
IF a == 3 AND b == 2:
do something
ELSE:
do something
If a == 3 is false the program wouldn't need to check the second part because always results false for any value of n.
In the same way with or:
a = 1
b = 2
IF a == 1 OR b == 3:
do something
ELSE:
do something
if a == 1 is true the program wouldn't need to check if b == 3 because is always true.
I want to know if the program stops in the first part in these cases.
It could very well depend on the language. I know that in C/C++ it would indeed only check b==2 if a==3 in the case of an and statement. I wasn't positive about the or statement, but I just checked by running this and the output I got indicates only the first part of the or statement executes. I'd recommend going through the effort of just writing your own sample to test such questions in the future.
#include <stdio.h>
int call_false()
{
printf("CALL FALSE \n\r");
return 0;
}
int call_true()
{
printf("CALL TRUE \n\r");
return 1;
}
int main()
{
printf("Hello World");
int a = 1;
int b = 2;
if( a == call_true() || b == call_false())
{
printf("TRUE \n\r");
}else
{
printf("FALSE");
}
return 0;
}
Gives the following output:
Hello WorldCALL TRUE
TRUE
...Program finished with exit code 0
Press ENTER to exit console.

Future task just vanishes

I run into a rather strange situation when using std::future and ThreadPool, though I do not think it's ThreadPool (I'm using https://github.com/bandi13/ThreadPool/blob/master/example.cpp) since (I've tried multiple forks of it and after some debugging I do not see how it would be related to the issue).
The issue is that under certain situation my doProcess method just goes nirvana - it does not return. It just disappears midst of a long running loop.
Therefore I think I must be doing something wrong, but can't figure out what.
Here's the code:
ThreadPool pool(numThreads);
std::vector< std::future<bool> > futures;
int count = 0;
string orgOut = outFile;
for (auto fileToProcess : filesToProcess) {
count++;
outFile = orgOut + std::to_string(count);
// enque processing in the thread pool
futures.emplace_back(
pool.enqueue([count, fileToProcess, outFile, filteredKeys, sql] {
return doProcess(fileToProcess, outFile, filteredKeys, sql);
})
);
}
Then I wait for all processings to be done (I think this could be done in a more elegant way also):
bool done = false;
while (!done) {
done = true;
for (auto && futr : futures) {
auto status = futr.wait_for(std::chrono::milliseconds(1));
if (status != std::future_status::ready) {
done = false;
break;
}
}
}
Edit: At first I also tried the obvius wait(), with the same result however:
bool done = false;
while (!done) {
done = true;
for (auto && futr : futures) {
futr.wait();
}
}
Edit: The doProcess() method. The behavior is this: The loopcnt variable is just a counter to debug how often the method was entered and the loop started. As you can see, there is no return from this loop, but the thread just vanishes when inside this loop with no error whatsoever and wasHereCnt is reached only occasionally (like 1 of 100 times the method is run). I'm really puzzled.
bool doProcess([...]) {
// ....
vector<vector<KVO*>*>& features = filter.result();
vector<vector<KVO*>*> filteredFeatures;
static int loopcnt = 0;
std::cout << "loops " << loopcnt << endl;
loopcnt++;
for (vector<KVO*>* feature : features) {
for (KVO *kv : *feature) {
switch (kv->value.type()) {
case Variant::JNULL:
sqlFilter.setNullValue(kv->key);
break;
case Variant::INT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
case Variant::UINT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
case Variant::DOUBLE:
sqlFilter.setValue(static_cast<double>(kv->value), kv->key);
break;
case Variant::STRING:
sqlFilter.setValue(static_cast<string>(kv->value), kv->key);
break;
default:
assert(false);
break;
}
}
int filterResult = sqlFilter.exec();
if (filterResult > 0) {
filteredFeatures.push_back(feature);
}
sqlFilter.reset();
}
static int wasHereCnt = 0;
std::cout << "was here: " << wasHereCnt << endl;
wasHereCnt++;
JsonWriter<Writer<FileWriteStream>> geojsonWriter(writer, filteredFeatures);
bool res = geojsonWriter.write();
os.Flush();
fclose(fp);
return res;
}
The doProcess method does work when it's taking less time. It breaks and disappears when it takes somewhat more time. The difference being just the complexity of an SQL query I run in the method. So I don't post the code for doProcess().
What causes the thread of the thread pool to be interrupted, and how to fix it?
UPDATE
Well, I found it out. After several hours I decided to remove the future tasks and just ran the task on the main thread. The issue was that an exception was thrown via:
throw std::runtime_error("bad cast");
... some time down the code flow after this:
case Variant::UINT:
sqlFilter.setValue(static_cast<int64_t>(kv->value), kv->key);
break;
This error was thrown as expected when running on the main thread. But it's never raised when run as future task. This is really odd and seems like a compiler or debugger issue.

C++ wrap multiple returns

I have the following code which returns ERROR in many lines:
bool func()
{
if (acondition)
{
return 0;
}
return 1;
}
int cmdfun()
{
other_funcs;
if (func()) return ERROR#NUMBER;
other_funcs;
if (func()) return ERROR#NUMBER;
}
But I found its becoming longer and longer. How can I encapsulate return ERROR#NUMBER into func() also? Or any way to encapsulate if (func()) return ERROR; into another independent function?
You can't really achieve this using return on its own.
But you could throw an exception in func which will bubble up the call stack, in the way you seem to want program control to:
struct myexception{}; /*ToDo - inherit from std::exception?*/
bool func()
{
if (acondition){
return 0; /*normal behaviour, perhaps make `func` void if not needed?*/
}
throw myexception();
}
cmdfun then takes the form:
int cmdfun()
{
other_funcs;
func();
other_funcs;
func();
/* don't forget to return something*/
}
Finally, make sure you catch the exception in the caller to cmdfun.
As I said it is not an exception and cannot be handled by std::exception, it is just an error message and ERROR#NUMBER is just another macro. And I cannot access to the caller to cmdfun(). So unable to adopt the first answer. But after asked someone else, it is possible to encapsulate returns and save time when typing them, though it's not recommended, but in this particular case, I can use macro. A complete example is given below:
#include <iostream>
using namespace std;
#define CHECK_VEC(acondition)\
if(checkcondition(acondition)) return -1;
bool checkcondition(bool acondition)
{
if (acondition) return 1;
return 0;
}
int fun_called_by_main()
{
int a = 5 + 4;
bool acondition = a;
CHECK_VEC(acondition);
return 1;
}
int main()
{
int a = fun_called_by_main();
cout << a << endl;
cin.get();
return 0;
}
If I understood corectly your question, you are asking for an 'error reporter' for your own errors. There are 2 solutions for 2 separate cases:
Case 1 - you still want to use a return statement to make an 'error reporter':
To do this, you'll have to make another function or just learn how to use goto. However, you don't need to - your function returns a boolean(bool) - which means you only have 2 possible results: 0 (False) and 1 (True)
bool func()
{
if (acondition)
{
return (bool)0; // False (no error)
}
return (bool)1; // True (error)
// Note: I used (bool)0 and (bool)1 because it is
// more correct because your returning type is bool.
}
void errorcase(bool trueorfalse)
{
switch(trueorfalse)
{
case False:
... // your code (func() returned 0)
break;
default:
... // your code (func() returned 1)
break;
// Note that you will not need to check if an error occurred every time.
}
return;
}
int cmdfun()
{
... // your code
errorcase(func());
... // again - your code
return 0; // I suppouse that you will return 0...
}
But I think that the second case is more interesting (unfortunetly it is also preety hard to understand as a beginner and the first solution might be a lot easier for you):
Case 2 - you decided to do it somehow else - that's by learning throw and catch - I won't repeat the answer because it is already given: #Bathsheba answered preety good...

Switch statement instead of multiple nested if - else?

I've come across a situation where I have a bunch of "systems" that need to be initialized in sequence, with the next system only being initialized if all of the proceeding systems initialized successfully.
This has led me to a whole slew of nested if - else statements. Here's some pseudo-code for visualization.
bool mainInit () {
if (!system1Init ()) {
reportError (); // some error reporting function
}
else {
if (!system2Init ()) {
reportError ();
}
else {
if (!system3Init ()) {
// ... and so on
I find that this starts to look like a mess when you get even a handful of levels to it.
Now I thought of using a switch statement instead, starting at the first case and falling through to the other cases on success, only breaking if there's an error.
bool mainInit () {
switch (1) {
case 1:
if (!system1Init ()) {
reportError ();
break;
}
case 2:
if (!system2Init ())
reportError ();
break;
}
// ....
}
Now, I like this a lot better. I find it much easier to read, especially with some decent comments, but I'm fairly new to programming.
So, my question is: Seeing how this is not how switch statements are traditionally used(at least from what I've seen), is something like this acceptable, or would this be considered bad form?
Being new to programming, I'm trying not to develop too many bad habits that might frustrate and make things more difficult for other programmers down the road.
I did a search, but most of what I found had to do with replacing chains of if - else if statements, not replacing nested ones.
Reference all of the systems in an array, for example an std::vector<mySystem*>, and loop over them sequentially, breaking off on the first fail. This way your entire code is reduced to less than 5 lines of code, even for 500+ systems.
The suggested switch hack is an evil example of XY problem solving: your real problem is that you don't have the array of systems, and are using named variables, thus eliminating all options to more flexibly use all systems, like in a loop.
Assuming that all your system#Init() calls are known at compile time, you can very easily put them in a table and then iterate over that table.
typedef (*system_init)(void);
system_init initialization_functions[] =
{
system1Init,
system2Init,
system3Init,
...
systemNInit
};
bool mainInit()
{
for(size_t idx(0); idx < sizeof(initialization_functions) / sizeof(initialization_functions[0]); ++idx)
{
if(!initialization_functions[idx]())
{
ReportError();
return false;
}
}
return true;
}
However, your existing code looks incorrect since the first mainInit() only calls system1Init() and then exits. Probably not what you wanted in the first place.
if(!system1Init())
{
ReportError();
return false;
}
// if you add an else, the system2Init() does not get called
// even if system1Init() succeeds
if(!system2Init())
{
ReportError();
return false;
}
[...]
return true;
Would the switch answer your problem? Not as it was written. That is, if you wanted to call the mainInit() function with a counter, it could be useful. Drupal uses that mechanism:
bool mainInit(int idx)
{
bool r(true);
switch(idx)
{
case 1:
r = system1Init();
break;
case 2:
r = system2Init();
break;
[...]
}
if(!r)
{
ReportError();
}
return r
}
Note that the table mechanism works the same way as the switch. As long as all the code is found in the systemNInit() functions (and it should be), the switch does not add anything, so you could do something like this too:
bool mainInit(int idx)
{
if(idx < 0 || idx >= sizeof(initialization_functions) / sizeof(initialization_functions[0]))
{
throw std::range_error("index out of bounds");
}
if(!initialization_functions[idx]())
{
ReportError();
return false;
}
return true;
}
Calling the mainInit() with an index can be helpful in case you want to "de-initialize" properly:
int main()
{
for(size_t idx(0); idx < ...; ++idx)
{
if(!mainInit(idx))
{
while(idx > 0)
{
--idx;
mainDeinit(idx);
}
exit(1);
}
}
...app do something here...
}
Use custom exceptions with clear error messages and add a try-catch-report-die around the code in main(). Exceptions are there to specifically make your case look good by making "bad path" implicit.
void initX() { ...; throw std::invalid_argument_exception("..."); }
int main() {
try {
init1(); init2(); ... run();
return 0;
} catch (std::exception const& e) {
log(e.what()); exit 42;
}
}
I'd do it this way:
bool mainInit () {
if (!system1Init ()) {
return(false);
}
if (!system2Init ()) {
return(false);
}
if (!system3Init ()) {
return(false);
}
//...
return(true);
}
//...
if(!mainInit()) {
reportError();
}

How are error-handling statements formatted?

I have a few functions that return a 1 if an error is encountered. Each function calls on a lower-level function, such that if the lower-level function returns a 1, the original function returns a 1 as well. Thus errors get passed up the chain in this way.
Here's an highly abridged version of one of these functions:
if (low_level_function()) {
[do stuff]
return 1;
}
[do other stuff]
return 0;
Should I instead declare an error variable, assign the result of low_level_function() to it, and then use the error variable in the if() statement? In other words:
int error = low_level_function();
if (error) {
[do stuff]
return 1;
}
[do other stuff]
return 0;
Or is there yet another, better way of doing this? I've never coded to account for errors before, so my experience here is rather limited.
Edit: I've reformatted the functions to better convey the nature of my code.
One reason to prefer the second form is when you don't have anything to do in the error case and you want to avoid the stair-step effect of nested if statements.
int error_flag = low_level_function();
if (!error_flag)
error_flag = second_function();
if (!error_flag)
error_flag = third_function();
return error_flag;
Of course for that specific example you can really simplify by using the short-circuiting property of ||:
return low_level_function() || second_function() || third_function();
I dont see the difference between the two approaches above.
I would recomment using exception, much more cleaner approach. why the reinvent the wheel? You can either use standard exception or implement custome exception like
You can use this also,
return low_level_function();
If low_level_function() returns nonzero on error and zero on success. Or
return low_level_function()>0? 1 : 0;
Although it it's s side comment I´ll be first stateing that I prefer one exit for any method.
One major pro tof his construction is the possiblity to only have the need for a error-logging statement at one place.
Also it's very easy to add tracing logs for debugging porpose.
So following this idea I'd propose the following
#define OK (0)
int mid_level_func(....)
{
log_entry(...);
int rc = OK
{
...
if ((rc = low_level_func1(...)))
goto lblExit;
...
if ((rc = low_level_func2(...)))
goto lblExit;
...
lblExit:
;
}
if (OK != rc)
log_error(rc, ...);
log_exit(...);
return rc;
}
For the ones that insist on goto being 'evil' the following variation on the scheme above might help:
#define OK (0)
int mid_level_func(....)
{
log_entry(...);
int rc = OK
do
{
...
if ((rc = low_level_func1(...)))
break;
...
if ((rc = low_level_func2(...)))
break;
...
} while (0);
if (OK != rc)
log_error(rc, ...);
log_exit(...);
return rc;
}