Clean ways to do multiple undos in C - c

Someone will probably say something about exceptions... but in C, what are other ways to do the following cleanly/clearly and without repeating so much code?
if (Do1()) { printf("Failed 1"); return 1; }
if (Do2()) { Undo1(); printf("Failed 2"); return 2; }
if (Do3()) { Undo2(); Undo1(); printf("Failed 3"); return 3; }
if (Do4()) { Undo3(); Undo2(); Undo1(); printf("Failed 4"); return 4; }
if (Do5()) { Undo4(); Undo3(); Undo2(); Undo1(); printf("Failed 5"); return 5; }
Etc...
This might be one case for using gotos. Or maybe multiple inner functions...

Yes, it's quite common to use goto in such cases to avoid repeating yourself.
An example:
int hello() {
int result;
if (Do1()) { result = 1; goto err_one; }
if (Do2()) { result = 2; goto err_two; }
if (Do3()) { result = 3; goto err_three; }
if (Do4()) { result = 4; goto err_four; }
if (Do5()) { result = 5; goto err_five; }
// Assuming you'd like to return 0 on success.
return 0;
err_five:
Undo4();
err_four:
Undo3();
err_three:
Undo2();
err_two:
Undo1();
err_one:
printf("Failed %i", result);
return result;
}
As always you probably also want to keep your functions small and batch together the operations in a meaningful manner to avoid a large "undo-code".

This might be one case for using gotos.
Sure, let's try that. Here's a possible implementation:
#include "stdio.h"
int main(int argc, char **argv) {
int errorCode = 0;
if (Do1()) { errorCode = 1; goto undo_0; }
if (Do2()) { errorCode = 2; goto undo_1; }
if (Do3()) { errorCode = 3; goto undo_2; }
if (Do4()) { errorCode = 4; goto undo_3; }
if (Do5()) { errorCode = 5; goto undo_4; }
undo_5: Undo5(); /* deliberate fallthrough */
undo_4: Undo4();
undo_3: Undo3();
undo_2: Undo2();
undo_1: Undo1();
undo_0: /* nothing to undo in this case */
if (errorCode != 0) {
printf("Failed %d\n", errorCode);
}
return errorCode;
}

If you have the same signature for your function you can do something like this:
bool Do1(void) { printf("function %s\n", __func__); return true;}
bool Do2(void) { printf("function %s\n", __func__); return true;}
bool Do3(void) { printf("function %s\n", __func__); return false;}
bool Do4(void) { printf("function %s\n", __func__); return true;}
bool Do5(void) { printf("function %s\n", __func__); return true;}
void Undo1(void) { printf("function %s\n", __func__);}
void Undo2(void) { printf("function %s\n", __func__);}
void Undo3(void) { printf("function %s\n", __func__);}
void Undo4(void) { printf("function %s\n", __func__);}
void Undo5(void) { printf("function %s\n", __func__);}
typedef struct action {
bool (*Do)(void);
void (*Undo)(void);
} action_s;
int main(void)
{
action_s actions[] = {{Do1, Undo1},
{Do2, Undo2},
{Do3, Undo3},
{Do4, Undo4},
{Do5, Undo5},
{NULL, NULL}};
for (size_t i = 0; actions[i].Do; ++i) {
if (!actions[i].Do()) {
printf("Failed %zu.\n", i + 1);
for (int j = i - 1; j >= 0; --j) {
actions[j].Undo();
}
return (i);
}
}
return (0);
}
You can change the return of one of Do functions to see how it react :)

For completeness a bit of obfuscation:
int foo(void)
{
int rc;
if (0
|| (rc = 1, do1())
|| (rc = 2, do2())
|| (rc = 3, do3())
|| (rc = 4, do4())
|| (rc = 5, do5())
|| (rc = 0)
)
{
/* More or less stolen from Chris' answer:
https://stackoverflow.com/a/53444967/694576) */
switch(rc - 1)
{
case 5: /* Not needed for this example, but left in in case we'd add do6() ... */
undo5();
case 4:
undo4();
case 3:
undo3();
case 2:
undo2();
case 1:
undo1();
default:
break;
}
}
return rc;
}

Use goto to manage cleanup in C.
For instance, check the Linux kernel coding style:
The rationale for using gotos is:
unconditional statements are easier to understand and follow nesting is reduced
errors by not updating individual exit points when making modifications are prevented
saves the compiler work to optimize redundant code away ;)
Example:
int fun(int a)
{
int result = 0;
char *buffer;
buffer = kmalloc(SIZE, GFP_KERNEL);
if (!buffer)
return -ENOMEM;
if (condition1) {
while (loop1) {
...
}
result = 1;
goto out_free_buffer;
}
...
out_free_buffer:
kfree(buffer);
return result;
}
In your particular case, it could look like:
int f(...)
{
int ret;
if (Do1()) {
printf("Failed 1");
ret = 1;
goto undo1;
}
...
if (Do5()) {
printf("Failed 5");
ret = 5;
goto undo5;
}
// all good, return here if you need to keep the resources
// (or not, if you want them deallocated; in that case initialize `ret`)
return 0;
undo5:
Undo4();
...
undo1:
return ret;
}

There are probably many ways to do this, but one idea is since you won't call one function unless the preceeding one succeeded, you could chain your function calls using else if like this. And using a variable to track where it fails you can use a switch statement to roll back easily too.
int ret=0;
if(Do1()) {
ret=1;
} else if(Do2()) {
ret=2;
} else if(Do3()) {
ret=3;
} else if(Do4()) {
ret=4;
} else if(Do5()) {
ret=5;
}
switch(ret) {
case 5:
Undo4();
case 4:
Undo3();
case 3:
Undo2();
case 2:
Undo1();
case 1:
printf("Failed %d\n",ret);
break;
}
return ret;

Yes, as explained by other answers, using goto for error-handling is often appropriate in C.
That said, if possible, you probably should make your cleanup code safe to call even if the corresponding action was never performed. For example, instead of:
void foo()
{
int result;
int* p = malloc(...);
if (p == NULL) { result = 1; goto err1; }
int* p2 = malloc(...);
if (p2 == NULL) { result = 2; goto err2; }
int* p3 = malloc(...);
if (p3 == NULL) { result = 3; goto err3; }
// Do something with p, p2, and p3.
bar(p, p2, p3);
// Maybe bar() saved references to p and p2, but we don't need
// p3 anymore.
free(p3);
return 0;
err3:
free(p2);
err2:
free(p);
err1:
return result;
}
I'd advocate:
void foo()
{
int result = -1; // Or some generic error code for unknown errors.
int* p = NULL;
int* p2 = NULL;
int* p3 = NULL;
p = malloc(...);
if (p == NULL) { result = 1; goto exit; }
p2 = malloc(...);
if (p2 == NULL) { result = 2; goto exit; }
p3 = malloc(...);
if (p3 == NULL) { result = 3; goto exit; }
// Do something with p, p2, and p3.
bar(p, p2, p3);
// Set success *only* on the successful path.
result = 0;
exit:
// free(NULL) is a no-op, so this is safe even if p3 was never allocated.
free(p3);
if (result != 0)
{
free(p2);
free(p);
}
return result;
}
It's slightly less efficient since it requires initializing variables to NULL, but it's more maintainable since you don't need extra labels. There's less stuff to get wrong when making changes to the code. Also, if there's cleanup code that you need on both success and failure paths, you can avoid code duplication.

I typically approach this kind of problem by nesting the conditionals:
int rval = 1;
if (!Do1()) {
if (!Do2()) {
if (!Do3()) {
if (!Do4()) {
if (!Do5()) {
return 0;
// or "goto succeeded", or ...;
} else {
printf("Failed 5");
rval = 5;
}
Undo4();
} else {
printf("Failed 4");
rval = 4;
}
Undo3();
} else {
printf("Failed 3");
rval = 3;
}
Undo2();
} else {
printf("Failed 2");
rval = 2;
}
Undo1();
} else {
printf("Failed 1");
rval = 1;
}
return rval;
Usually, for me, the DoX() are some kind of resource acquisition, such as malloc(), and the UndoX() are corresponding resource releases that should be performed only in the event of failure. The nesting clearly shows the association between corresponding acquisitions and releases, and avoids the need for repetition of the code for undo operations. It's also very easy to write -- you don't need to create or maintain labels, and it's easy to put the resource release in the right place as soon as you write the acquisition.
This approach does sometimes produce deeply nested code. That doesn't bother me much, but you might consider it an issue.

This question is already overburdened with answers, but I would ike to point out that some codebases actually have wrapper code to deal with -what basically are- exceptions, in clean ways. For example, MuPdf implemented some trickery using longjmp's that emulate exception handling. In my opinion, if it comes to that, they should just be using C++ already, but that's just me.
You could try to do such wrappers yourself. As an exercise, let's think about your requirements and try to come up with a (very) crude design that tries to satisfy them:
We have a set of operations that need to be undone if subsequent operations fail;
Multiple operations must be undone in the reverse order that they were done;
The operation that failed must not be undone. It failed, after all;
Operations that were never reached must also not be undone, since they were never done in the first place.
Ideally, allow the programmer to be explicit: He knows what operations need to be undone, and when they do.
I've come up with some macros to solve this problem:
#include <stdio.h>
// Define some variables to keep track of when an error happened, and how many operations should be undone.
// Names are "mangled" by prefixing them with try_. You probably should come up with a better mangling scheme than this.
#define BEGIN_TRY int try_done = 0, try_error = 0, try_count = 0
// Here's how this works:
// - First, count the expression as an operation that may need to be undone;
// - If no error occured yet, do the operation;
// - If it succeeds, count it as a "done" operation;
// - If it fails, signal the error
#define TRY(expression) try_count++; if(!try_error && !(expression)) try_done++; else try_error = 1
// Here we take advantage of the fact that the operations behave like a queue.
// This means that, no matter what, operations need to be undone in the same
// order everytime, and if an operation needs to be undone when there
// are N operations, it also needs to be undone when there are N+1 operations.
// So, we don't really need to maintain the queue, if the programmer puts the operations in the correct order already. We just
// need to know how many operations to undo, and how much total operations are there (because we need to start at the end)
#define ON_ERROR(expression) do { if(try_error && try_done >= try_count--) {try_done--; (expression);} } while(0)
// To simplify the test, the "jobs" that we will try to do just pass or fail depending on the argument passed.
int job(int result) {return result;}
void undo(int i) {printf("Undone %d.\n", i);}
#define PASS 0
#define FAIL 1
// Let's test this
int main() {
BEGIN_TRY;
// try toying with the order (and quantity) of these.
// just remember that for each "TRY" there must be one "ON_ERROR"!
TRY(job(PASS));
TRY(job(PASS));
TRY(job(FAIL));
TRY(job(PASS));
// Because only the first two operations succeeded, we should only see the effects of undo(2) and undo(1).
ON_ERROR(undo(4));
ON_ERROR(undo(3));
ON_ERROR(undo(2));
ON_ERROR(undo(1));
}
See it live!
I'm no C expert, so there's probably some bugs in this (writing safe macros is hard), but my point is: If you think about your requirements in detail, all you will have to do is to come up with a solution which satisfies all of them. Another point that can be made is: Much like goto, many people see macros as evil. Don't be one of them: If a macro will make your code clearer, easier to read, then, by all means, use it.

If the functions return some kind of state pointer or handle (like most allocation & initialization functions would), you can quite cleanly do this without goto by giving initial values to variables. Then you can have a single deallocation function that can handle the case where only part of the resources has been allocated.
For example:
void *mymemoryblock = NULL;
FILE *myfile = NULL;
int mysocket = -1;
bool allocate_everything()
{
mymemoryblock = malloc(1000);
if (!mymemoryblock)
{
return false;
}
myfile = fopen("/file", "r");
if (!myfile)
{
return false;
}
mysocket = socket(AF_INET, SOCK_STREAM, 0);
if (mysocket < 0)
{
return false;
}
return true;
}
void deallocate_everything()
{
if (mysocket >= 0)
{
close(mysocket);
mysocket = -1;
}
if (myfile)
{
fclose(myfile);
myfile = NULL;
}
if (mymemoryblock)
{
free(mymemoryblock);
mymemoryblock = NULL;
}
}
And then just do:
if (allocate_everything())
{
do_the_deed();
}
deallocate_everything();

TL;DR:
I believe it should be written as:
int main (void)
{
int result = do_func();
printf("Failed %d\n", result);
}
Detailed explanation:
If nothing can be assumed what-so-ever about the function types, we can't easily use an array of function pointers, which would otherwise be the correct answer.
Assuming all function types are incompatible, then we would have to wrap in the original obscure design containing all those non-compatible functions, inside something else.
We should make something that is readable, maintainable, fast. We should avoid tight coupling, so that the undo behavior of "Do_x" doesn't depend on the undo behavior of "Do_y".
int main (void)
{
int result = do_func();
printf("Failed %d\n", result);
}
Where do_func is the function doing all the calls required by the algorithm, and the printf is the UI output, separated from the algorithm logic.
do_func would be implemented like a wrapper function around the actual function calls, handling the outcome depending on the result:
(With gcc -O3, do_func is inlined in the caller, so there is no overhead for having 2 separate functions)
int do_it (void)
{
if(Do1()) { return 1; };
if(Do2()) { return 2; };
if(Do3()) { return 3; };
if(Do4()) { return 4; };
if(Do5()) { return 5; };
return 0;
}
int do_func (void)
{
int result = do_it();
if(result != 0)
{
undo[result-1]();
}
return result;
}
Here the specific behavior is controlled by the array undo, which is a wrapper around the various non-compatible functions. Which functions to to call, in which order, is all part of the specific behavior tied to each result code.
We need to tidy it all up, so that we can couple a certain behavior to a certain result code. Then when needed, we only change the code in one single place if the behavior should be changed during maintenance:
void Undo_stuff1 (void) { }
void Undo_stuff2 (void) { Undo1(); }
void Undo_stuff3 (void) { Undo2(); Undo1(); }
void Undo_stuff4 (void) { Undo3(); Undo2(); Undo1(); }
void Undo_stuff5 (void) { Undo4(); Undo3(); Undo2(); Undo1(); }
typedef void Undo_stuff_t (void);
static Undo_stuff_t* undo[5] =
{
Undo_stuff1,
Undo_stuff2,
Undo_stuff3,
Undo_stuff4,
Undo_stuff5,
};
MCVE:
#include <stdbool.h>
#include <stdio.h>
// some nonsense functions:
bool Do1 (void) { puts(__func__); return false; }
bool Do2 (void) { puts(__func__); return false; }
bool Do3 (void) { puts(__func__); return false; }
bool Do4 (void) { puts(__func__); return false; }
bool Do5 (void) { puts(__func__); return true; }
void Undo1 (void) { puts(__func__); }
void Undo2 (void) { puts(__func__); }
void Undo3 (void) { puts(__func__); }
void Undo4 (void) { puts(__func__); }
void Undo5 (void) { puts(__func__); }
// wrappers specifying undo behavior:
void Undo_stuff1 (void) { }
void Undo_stuff2 (void) { Undo1(); }
void Undo_stuff3 (void) { Undo2(); Undo1(); }
void Undo_stuff4 (void) { Undo3(); Undo2(); Undo1(); }
void Undo_stuff5 (void) { Undo4(); Undo3(); Undo2(); Undo1(); }
typedef void Undo_stuff_t (void);
static Undo_stuff_t* undo[5] =
{
Undo_stuff1,
Undo_stuff2,
Undo_stuff3,
Undo_stuff4,
Undo_stuff5,
};
int do_it (void)
{
if(Do1()) { return 1; };
if(Do2()) { return 2; };
if(Do3()) { return 3; };
if(Do4()) { return 4; };
if(Do5()) { return 5; };
return 0;
}
int do_func (void)
{
int result = do_it();
if(result != 0)
{
undo[result-1]();
}
return result;
}
int main (void)
{
int result = do_func();
printf("Failed %d\n", result);
}
Output:
Do1
Do2
Do3
Do4
Do5
Undo4
Undo3
Undo2
Undo1
Failed 5

Here is an answer that I have found resilient to bugs.
Yes. It uses goto. I firmly believe you should use what gives you most clarity, rather than just blindly following the advice of those before you (goto as a construct can make spaghetti code, but in this instance every other error handling method ususally ends up more spaghetti-like than using this method of goto, so IMO it's superior).
Some people may not like the form of this code, but I contest that when used to the style it is cleaner, easier to read (when everything's lined up, of course), and much more resilient to errors. If you have the properly linter/static analysis setup, and you're working with POSIX, it pretty much requires you to code in this fashion to allow for good error handling.
static char *readbuf(char *path)
{
struct stat st;
char *s = NULL;
size_t size = 0;
int fd = -1;
if (!path) { return NULL; }
if ((stat(path, &st)) < 0) { perror(path); goto _throw; }
size = st.st_size;
if (size == 0) { printf("%s is empty!\n", path); goto _throw; }
if (!(s = calloc(size, 1))) { perror("calloc"); goto _throw; }
fd = open(path, O_RDONLY);
if (fd < -1) { perror(path); goto _throw; }
if ((read(fd, s, size)) < 0) { perror("read"); goto _throw; }
close(fd); /* There's really no point checking close for errors */
return s;
_throw:
if (fd > 0) close(fd);
if (s) free(s);
return NULL;
}

typedef void(*undoer)();
int undo( undoer*const* list ) {
while(*list) {
(*list)();
++list;
}
}
void undo_push( undoer** list, undoer* undo ) {
if (!undo) return;
// swap
undoer* tmp = *list;
*list = undo;
undo = tmp;
undo_push( list+1, undo );
}
int func() {
undoer undoers[6]={0};
if (Do1()) { printf("Failed 1"); return 1; }
undo_push( undoers, Undo1 );
if (Do2()) { undo(undoers); printf("Failed 2"); return 2; }
undo_push( undoers, Undo2 );
if (Do3()) { undo(undoers); printf("Failed 3"); return 3; }
undo_push( undoers, Undo3 );
if (Do4()) { undo(undoers); printf("Failed 4"); return 4; }
undo_push( undoers, Undo4 );
if (Do5()) { undo(undoers); printf("Failed 5"); return 5; }
return 6;
}
I made undo_push do the O(n) work. This is less efficient than having undo do the O(n) work, as we expect more push's than undos. But this version was a touch simpler.
A more industrial strength version would have head and tail pointers and even capacity.
The basic idea is to keep a queue of undo actions in a stack, then execute them if you need to clean up.
Everything is local here, so we don't pollute global state.
struct undoer {
void(*action)(void*);
void(*cleanup)(void*);
void* state;
};
struct undoers {
undoer* top;
undoer buff[5];
};
void undo( undoers u ) {
while (u.top != buff)
{
(u.top->action)(u.top->state);
if (u.top->cleanup)
(u.top->cleanup)(u.top->state);
--u.top;
}
}
void pundo(void* pu) {
undo( *(undoers*)pu );
free(pu);
}
void cleanup_undoers(undoers u) {
while (u.top != buff)
{
if (u.top->cleanup)
(u.top->cleanup)(u.top->state);
--u.top;
}
}
void pcleanup_undoers(void* pu) {
cleanup_undoers(*(undoers*)pu);
free(pu);
}
void push_undoer( undoers* to_here, undoer u ) {
if (to_here->top != (to_here->buff+5))
{
to_here->top = u;
++(to_here->top)
return;
}
undoers* chain = (undoers*)malloc( sizeof(undoers) );
memcpy(chain, to_here, sizeof(undoers));
memset(to_here, 0, sizeof(undoers));
undoer chainer;
chainer.action = pundo;
chainer.cleanup = pcleanup_undoers;
chainer.data = chain;
push_undoer( to_here, chainer );
push_undoer( to_here, u );
}
void paction( void* p ) {
(void)(*a)() = ((void)(*)());
a();
}
void push_undo( undoers* to_here, void(*action)() ) {
undor u;
u.action = paction;
u.cleanup = 0;
u.data = (void*)action;
push_undoer(to_here, u);
}
then you get:
int func() {
undoers u={0};
if (Do1()) { printf("Failed 1"); return 1; }
push_undo( &u, Undo1 );
if (Do2()) { undo(u); printf("Failed 2"); return 2; }
push_undo( &u, Undo2 );
if (Do3()) { undo(u); printf("Failed 3"); return 3; }
push_undo( &u, Undo3 );
if (Do4()) { undo(u); printf("Failed 4"); return 4; }
push_undo( &u, Undo4 );
if (Do5()) { undo(u); printf("Failed 5"); return 5; }
cleanup_undoers(u);
return 6;
}
but that is getting ridiculous.

Let's try for something with zero curly braces:
int result;
result = Do1() ? 1 : 0;
result = result ? result : Do2() ? 2 : 0;
result = result ? result : Do3() ? 3 : 0;
result = result ? result : Do4() ? 4 : 0;
result = result ? result : Do5() ? 5 : 0;
result > 4 ? (Undo5(),0) : 0;
result > 3 ? Undo4() : 0;
result > 2 ? Undo3() : 0;
result > 1 ? Undo2() : 0;
result > 0 ? Undo1() : 0;
result ? printf("Failed %d\r\n", result) : 0;
Yes. 0; is a valid statement in C (and C++). In the case that some of the functions return something that is incompatible with this syntax (e.g. void perhaps) then the Undo5() style can be used.

A sane (no gotos, no nested or chained ifs) approach would be
int bar(void)
{
int rc = 0;
do
{
if (do1())
{
rc = 1;
break;
}
if (do2())
{
rc = 2;
break;
}
...
if (do5())
{
rc = 5;
break;
}
} while (0);
if (rc)
{
/* More or less stolen from Chris' answer:
https://stackoverflow.com/a/53444967/694576) */
switch(rc - 1)
{
case 5: /* Not needed for this example, but left in in case we'd add do6() ... */
undo5();
case 4:
undo4();
case 3:
undo3();
case 2:
undo2();
case 1:
undo1();
default:
break;
}
}
return rc;
}

Related

Checking balanced parentheses in a string with stacks in c

I am trying to write a program where i implement stacks with arrays and use them to check if a given string has balanced parentheses.
For ex. if inputted '(()){}[()]' ,program would output 'Balanced', otherwise if inputted '({})[' the program would output 'Not balanced'.
This part is the array implementation of the stack.
#include <stdio.h>
#include <stdlib.h>
#define MAX 50
int stack[MAX];
int top=-1;
void push(char val){
if(top==MAX-1){
printf("stack is already full,error\n");
}else{
top++;
stack[top]=val;
}
}
char pop(){
if(top==-1){
printf("not enough elements,error\n");
exit(1);
}else{
top--;
return stack[top];
}
}
This part is the implementation of a common method to solve the problem.
int isMatching(char c1, char c2){
if(c1=='{' && c2=='}')
return 1;
else if(c1 =='(' && c2==')')
return 1;
else if(c1=='[' && c2==']')
return 1;
return 0;
}
int isBalanced(char str[]){
int i=0;
while(str[i]!='\0'){
if(str[i]=='{' || str[i]=='[' || str[i]=='('){
push(str[i]);
}
if(str[i]==')' || str[i] == ']' || str[i]=='}'){
if(stack==NULL){
return 0;
}
if(!isMatching(pop(), str[i])){
return 0;
}
}
i++;
}
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
}
And this is the main function where the user inputs a string and it's tested if it's 'Balanced' or not.
int main(){
char str[MAX];
int flag;
printf("Enter the string with the brackets and etc.\n");
fgets(str, sizeof(str),stdin);
flag=isBalanced(str);
if(flag==1){
printf("Balanced\n");
}
else{
printf("Not balanced\n");
}
return 0;
}
When i input a very simple example, i get a wrong answer, for instance
Enter the string with the brackets and etc.
()
Not balanced
This is supposed to output 'Balanced' instead.I don't understand how this could have occured.
in pop(), you are decrementing before returning the top element. Change:
top--;
return stack[top];
to
return stack[top--];
Also, in isBalanced(), stack is NEVER null, so delete:
if(stack==NULL){
return 0;
}
and change the balanced check to look for the empty stack from:
if(stack==NULL){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
To:
if(top==-1){
return 1; // balanced parenthesis
}else{
return 0; // not balanced parenthesis
}
After making these changes, your code appeared to work on my box. This isn't quite how I'd have coded it, but this is the minimal set of changes to make it work.
if (stack==NULL) is the problem here, stack will never be NULL.
You need to check if there are still elements in your stack, by verifying that top > 0
You implemented the push/pop combo wrong. If you push one character top becomes 0. If you popping it immediately it finally executes top--; return stack[top], which evaluates to stack[-1].
Try this push/pop:
int top=-1; //idx to be popped next; <0 -> invalid
void push(char val)
{
if(top==MAX-2)
printf("stack is already full,error\n");
else
stack[++top]=val;
}
char pop()
{
if(top<0) return '\0'; //no abort, just return invalid char
return stack[top--];
}
The answer to your question has already been satisfactorily answered, but as a suggestion for a different approach, consider the following.
Since there are only a very small number of common enclosures used within C source code you can easily track pairs of them using an increment-decrement counter. The following uses a struct, typedefed to balanced_s which is encapsulated into a function to simplify the evaluation. Following is a sample implementation:
typedef struct {
int paren;
int curly;
int square;
bool bBal
}balanced_s;
balanced_s * balanced_enclosures(const char *source);
int main(void)
{
char in[5000] = {0};//you could improve this by reading file size
//first then creating array sized accordingly
FILE *fp = fopen("C:\\play\\source.c", "r");//using copy of this source to test
if(fp)
{
size_t bytes = fread(in, 1, sizeof(in), fp);
}
balanced_s * b = balanced_enclosures(in);
bool balanced = b->bBal;//If not true, inspect the rest of the
//members to see where the imbalance has occurred.
free(b);
return 0;
}
balanced_s * balanced_enclosures(const char *source)
{
balanced_s *pBal = malloc(sizeof(*pBal));
memset(pBal, 0, sizeof(*pBal));
while(*source)
{
switch(*source) {
case '(':
pBal->paren++;
break;
case ')':
pBal->paren--;
break;
case '{':
pBal->curly++;
break;
case '}':
pBal->curly--;
break;
case '[':
pBal->square++;
break;
case ']':
pBal->square--;
break;
}
source++;
pBal->bBal = (!pBal->paren && !pBal->curly && !pBal->square);
}
return pBal;
}

Return error code after first detected error

I have a function which does some initialization and calls other functions, each of which returns an error code. I want to be able to return from this function after the first detected error like this:
int error_code = FirstFunction();
if (error_code != 0) {
return error_code;
}
error_code = SecondFunction();
if (error_code != 0) {
return error_code;
}
// etc...
However, not only does this look rather cumbersome, it also has multiple return statements, and for compliance reasons at my company this is not allowed.
How can I rearrange this so that there is only one return statement, but still stop after the first error code? The only way I can think of is to do nested if statements:
int error_code = FirstFunction();
if (error_code == 0) {
error_code = SecondFunction();
if (error_code == 0) {
error_code = ThirdFunction();
// etc...
}
}
return error_code;
But this could get unreasonable pretty fast. Is there another way to do this?
EDIT: In my program, return code of 0 means success (OK) and non-zero means failure/error (NOT OK)
You don't have to nest all the function calls, the code below do the job as well and should comply with your code writing rules:
error_code = FirstFunction();
if (error_code == 0) {
error_code = SecondFunction();
}
if (error_code == 0) {
error_code = ThirdFunction();
}
// etc...
return error_code;
Here is another lean method that can return different error codes depending on which function fails:
int func(void)
{
int code;
int error_code = (code = FirstFunction()) ? code :
(code = SecondFunction()) ? code :
(code = ThirdFunction()) ? code : 0;
/* ... */
return error_code;
}
Lean and clean (like this one, but avoiding the disliked gotos):
int foo(void)
{
int error_code;
do {
if (0 != (error_code = FirstFunction()))
{
break;
}
if (0 != (error_code = SecondFunction()))
{
break;
}
...
} while (0);
return error_code;
}
This, BTW, follows the more common pattern: 0 is OK, everything else isn't. Adjust as needed)
You could even obfuscate this using a macro:
#define RUN_AND_BREAK_ON_ERROR(rc, f, ...) \
if (0 != (rc = f(__VA_ARGS__))) \
{ \
break; \
}
int foo(void)
{
int error_code;
do {
RUN_AND_BREAK_ON_ERROR(error_code, FirstFunction, <args go here>);
RUN_AND_BREAK_ON_ERROR(error_code, SecondFunction, <args go here>);
...
} while (0);
return error_code;
}
if( (error_code = FirstFunction()) || (error_code = SecondFunction()) || ... ){
return error_code ;
}
return error_code; //denoting no error.
This would return only the first function which returns nonzero. The idea is that for if statement the first function that returns nonzero would short-circuit the whole evaluation and returns the error_code from the function which returned non-zero error_code. Also another thing is value of an assignment statement is the value assigned. That's why this works.
A more easier way would be to sequential if-else
if( error_code = FirstFunction() ) {}
else if( error_code = SecondFunction() ) {}
...
return error_code;
If all these functions take the same type of parameters and have the same return type, you could put them in a function array and iterate over it. When an error is found, it simply breaks out of the loop and returns.
int (*function_array[max_array])();
/*Fill the array with the functions you need*/
for(i=0;i<max_array;i++){
if((error_code=function_array[i]())!=OK){
break;
}
}
return error_code;
(OK is whatever the success return value is for these functions)
Well, there's the one used e.g. in the Linux kernel:
int somefunc(whatever)
{
if (do_something()) {
ret = -EINVAL;
goto err;
}
if (do_something_else()) {
ret = -EPERM;
goto err;
}
/* ... */
ret = 0;
err:
some_mandatory_cleanup();
return ret;
}
But I suspect that's going to be even less well received. (Before you scream, the whole point of that is the mandatory cleanup in the end. The goto arranges it to be executed always, but still puts it out of way.)
Really, I think the code in your first snippet is fine, and the issue is with your guidelines. Even if we only write return error_code; in one place, it's not enough to guarantee that the error code saved in variable is always correct, or that the function completes all cleanup that might be required. (Consider something that allocates memory, and has to release it in any case.)

Is it normal that void pointers give warnings?

I'm doing a school project and i'm going out of my away to get a better grade
With that being said i'm trying to use void pointers and type casting to make my program as general as possible for any type of scenario i throw at it.
I did some code and it does everything it should do but it gives me some warnings whenever i rebuild all but no warning when i compile it.
Side note: I know i am returning an integer to a pointer, but i can't return an local pointer otherwise it will not give me the result i need.
#define VERDADEIRO 1
#define FALSO 0
void * removido(info* tab,int pos)
{
if(strcmp(tab[pos].nome,REMOVIDO) != 0)
{
return FALSO;
}
else
{
return VERDADEIRO;
}
}
void * vazio(info* tab,int pos)
{
if(strcmp(tab[pos].nome,CHAVENULA)!= 0)
{
return FALSO;
}
else
{
return VERDADEIRO;
}
}
int listar(info * tab)
{
int i,c=0,j;
for(i=0;i<HASHTAM;i++)
{
if((int *)removido(tab,i) ==FALSO && (int *)vazio(tab,i)==FALSO)
{
printf("Nome: %s",tab[i].nome);
printf("NIF: %d\n",tab[i].NIF);
printf("Morada: %s",tab[i].morada);
printf("Telefone: %d\n",tab[i].telefone);
printf("Codigo Postal: %d - %d\n",tab[i].codigopostal/1000,tab[i].codigopostal%1000);
printf("Data de nasicmento: %d - %d - %d\n",tab[i].datanascimento%100,(tab[i].datanascimento%10000)/100,tab[i].datanascimento/10000);
printf("Associado: %s\n",tab[i].infoassociado.associado);
if(associado(tab,i)==VERDADEIRO)
{
for(j=0;j<10;j++)
{
printf("Cota de %d anos atras - Estado: %c\n",j+1,tab[i].infoassociado.cotas[j]);
}
}
c++;
}
}
The warnings are comparison between pointer and integer and return makes pointer from integer without a cast.
No, they're not normal. They're telling you that you're using pointers incorrectly. FALSO and VERDADEIRO are not pointers.
Functions which return true and false are not a good use of void pointers, or pointers in general. Nor do you have to define your own true and false values. Instead use the booleans true and false from stdbool.h. (Note: this was added in C99 and some professors cling to the C90 standard.)
#include <stdbool.h>
bool removido(info* tab,int pos)
{
if(strcmp(tab[pos].nome,REMOVIDO) != 0) {
return false;
}
else {
return true;
}
}
bool vazio(info* tab,int pos)
{
if(strcmp(tab[pos].nome,CHAVENULA)!= 0) {
return false;
}
else {
return true;
}
}
And then later you can simply check whether the return value is true or false using normal boolean checks.
if( !removido(tab,i) && !vazio(tab,i) ) {
...
}
Note that double negatives make code difficult to understand. If you check for equality and return true, that is simpler.
bool vazio(info* tab,int pos)
{
if(strcmp(tab[pos].nome,CHAVENULA)== 0) {
return true;
}
else {
return false;
}
}
To really simplify the code, you can take advantage that strcmp(...) == 0 returns a boolean (technically it returns 0 or 1 which can be used as a boolean) and reduce those functions to one line.
bool removido(info* tab,int pos)
{
return strcmp(tab[pos].nome,REMOVIDO) == 0;
}

Refactoring: Very similar switch cases

I have several struct declared which contain different data. I also have an enum that corresponds to those structures. There are several places in my code where I need to access information about the structures and I'm doing it via the enum. This results in few switch statements that return this information.
I've enclosed those switch statements in their own functions in order to re-use wherever possible. This resulted in three functions that look very similar.
Example psuedo-code:
#include <stdio.h>
typedef struct
{
int varA;
char varB;
} A;
typedef struct
{
int varA;
int varB;
int varC;
} B;
typedef struct
{
int varA;
short varB;
} C;
typedef enum { structA, structB, structC } STRUCT_ENUM;
int returnSize(STRUCT_ENUM structType)
{
int retVal = 0;
switch(structType)
{
case structA:
retVal = sizeof(A);
break;
case structB:
retVal = sizeof(B);
break;
case structC:
retVal = sizeof(C);
break;
default:
break;
}
return retVal;
}
void printStructName(STRUCT_ENUM structType)
{
switch(structType)
{
case structA:
printf("Struct: A\r\n");
break;
case structB:
printf("Struct: B\r\n");
break;
case structC:
printf("Struct: C\r\n");
break;
default:
break;
}
}
void createDataString(STRUCT_ENUM structType, char* output, unsigned char* input)
{
switch(structType)
{
case structA:
{
A a = *(A*)input;
sprintf(output, "data: %d, %d", a.varA, a.varB);
break;
}
case structB:
{
B b = *(B*)input;
sprintf(output, "data: %d, %d, %d", b.varA, b.varB, b.varC);
break;
}
case structC:
{
C c = *(C*)input;
sprintf(output, "data: %d, %d", c.varA, c.varB);
break;
}
default:
break;
}
}
int main(void) {
char foobar[50];
printf("Return size: %d\r\n", returnSize(structA));
printStructName(structB);
C c = { 10, 20 };
createDataString(structC, foobar, (unsigned char*) &c);
printf("Data string: %s\r\n", foobar);
return 0;
}
Those free functions basically contain the same switch with different code placed in the cases. With this setup, adding new struct and enum value results in three places in the code that needs changing.
The question is: is there a way to refactor this into something more maintainable? Additional constraint is that the code is written in C.
EDIT: online example: http://ideone.com/xhXmXu
You can always use static arrays and use STRUCT_ENUM as the index. Given the nature of your functions, I don't really know if you would consider it more maintainable, but it's an alternative I usually prefer, examples for names and sizes:
typedef enum { structA, structB, structC, STRUCT_ENUM_MAX } STRUCT_ENUM;
char *struct_name[STRUCT_ENUM_MAX] = {[structA] = "Struct A", [structB] = "Struct B", [structC] = "Struct C"};
size_t struct_size[STRUCT_ENUM_MAX] = {[structA] = sizeof(A), [structB] = sizeof(B), [structC] = sizeof(C)};
for printing content you can keep a similar array of functions receiving a void * that will print the value of this argument.
Edit:
Added designated initializers as per Jen Gustedt's comment.
You can make it into a single function and a single switch, with an additional parameter. Like so
int enumInfo(STRUCT_ENUM structType, int type) // 1 = returnSize 2 = printStructName
{
int retVal = 0;
switch(structType)
{
case structA:
If ( type == 1 ) { retVal = sizeof(A); }
else { printf("Struct: A"); }
break;
case structB:
If ( type == 1 ) { retVal = sizeof(B); }
else { printf("Struct: B"); }
break;
case structC:
If ( type == 1 ) { retVal = sizeof(C); }
else { printf("Struct: C"); }
break;
default:
break;
}
return retVal;
}

write a C construct

Is there a way (in C) to write a construct like the switch statement, but for strings? Is there a way to write a C construct at all in C?
By C construct I mean a statement with braces ... like an if statement has braces, and it's a C construct... right?
The simplest approach is an if-else chain using strcmp to do the comparisons:
if (strcmp(str, "String 1") == 0)
// do something
else if (strcmp(str, "String 2") == 0)
// do something else
else if (strcmp(str, "String 3") == 0)
// do something else
...
else
printf("%s not found\n", str);
A more complicated approach is to use a lookup table, keyed by the string:
struct lookup {const char *key; int value};
struct lookup LookupTable[] = {
{"String 1", 1},
{"String 2", 2},
{"String 3", 3},
...
{NULL, -1}
};
int lookup(const char *key)
{
size_t i = 0;
while (LookupTable[i].key != NULL)
if (strcmp(str, LookupTable[i].key) == 0)
return LookupTable[i].value;
else
i++;
return -1;
}
...
switch(lookup(str))
{
case 1: ...
case 2: ...
case 3: ...
...
default: printf("%s not found\n", str); break;
}
If you want to get really fancy, you could modify the lookup table so that the value is a pointer to a function:
void String1Cmd(void) { ... }
void String2Cmd(void) { ... }
void String3Cmd(void) { ... }
...
void BadCmd(void) { printf("Key not found!\n"); }
struct lookup {char *key, void (*cmd)(void); };
struct lookup LookupTable[] = {
{"String 1", String1Cmd},
{"String 2", String2Cmd},
{"String 3", String3Cmd},
...
{NULL, BadCmd}
};
void (*lookup(const char *str))(void)
{
size_t i = 0;
while(LookupTable[i].key != NULL)
if (strcmp(str, LookupTable[i].key) == 0)
return LookupTable[i].cmd;
else
i++;
return BadCmd;
}
...
void (*f)(void) = lookup(str); // retrieve the function for the given string
f(); // execute the function
In the last example, if str == "String 1", then String1Cmd will be executed. If str is a string not found in the lookup table, then BadCmd will be executed. This method is very flexible, and depending on your design, allows you to add behavior at runtime (sort of a plug-in architecture).
However, note that we've just deferred the main problem - branching on a string value - to the lookup function, and that the lookup function is back to just doing strcmp against each value in the table. We could speed that part of the process up by using a hash table or a tree to minimize the number of comparisons. Depending on how many strings you're branching on, that may or may not be worth the additional effort.
No, you have to do it yourself. There are many variants:
if (strcmp(str, "toto") == 0)
{
// ...
}
else if (strcmp(str, "tata") == 0)
{
// ...
}
else
{
// ...
}
If the number of strings is expected to grow, then a dispatch table with function pointers
struct dispatch_entry
{
const char *key;
void (*action)(void);
};
// Make sure it is sorted !
dispatch_entry dispatch_table[] =
{
{ "tata", &action_tata },
{ "toto", &action_toto },
};
coupled with binary search:
int dispatch_compare(const void *x, const void *y)
{
const dispatch_entry *xx = x, *yy = y;
return strcmp(xx->key, yy->key);
}
// Return -1 on failure
int dispatch(const char *str)
{
static const size = sizeof(struct dispatch_entry);
static const n = sizeof(dispatch_table) / size ;
dispatch_entry tmp = { str, NULL };
dispatch_entry *what = bsearch(tmp, dispatch_table, n, size, &dispatch_compare);
if (what == NULL) return -1;
(*what->action)();
return 0;
}
will do. Hash table based approaches are OK as well.
if you have the function lfind in your lib (POSIX or gcc) you can use it like:
enum { NOTFOUND, HELLO, WORLD, FOO, BAR };
char list[][100]={"hello","world","foo","bar"};
size_t r, siz = sizeof*list, num = sizeof list/siz;
char *tosearch = "foo";
switch ( (r=lfind(tosearch,list,&num,siz,strcmp))?
(r+siz-(size_t)list)/siz:0 ) {
case HELLO: puts("hello");break;
case WORLD: puts("world");break;
case FOO: puts("foo"); break;
case BAR: puts("bar"); break;
case NOTFOUND:puts("not found");
}
each string in the array must have the same size and should not be a pointer
a hashtable if you have a large number of strings and speed is an issue
No, since the switch may only be used with integral types, or a type convertible to an integral type
No, switch works on an integer value (I think floats/doubles are not even allowed). You can emulate that with if/else if/else doing strcmp.
if (strcmp(mystr, "this") == 0) {
//mystr == "this"
}
else if (strcmp(mystr, "that") == 0) {
//mystr == "that"
}
else {
//mystr is not "this" or "that"
}
Yes, and the way is - long if-else-if statement. (for reference: Why switch statement cannot be applied on strings? )
And what do you mean by "a C construct at all in C" o.O ? I'll edit my post, when you answer :)
Sure, depending on how much work you are willing to do.
You can use a preprocessor and some macros to map strings to integral identifiers, giving you a syntax like:
switch (SOSID_LOOKUP (sample_string)) {
case SOSID (hello): printf ("Hello "); break;
case SOSID (world): printf ("World! "); break;
case 0: default: printf ("unknown "); break;
}
If you can use C++ instead of C, you can use litb's template-based string switcher, giving you syntax like:
sswitch(s) {
scase("foo"): {
std::cout << "s is foo" << std::endl;
break; // could fall-through if we wanted
}
// supports brace-less style too
scase("bar"):
std::cout << "s is bar" << std::endl;
break;
// default must be at the end
sdefault():
std::cout << "neither of those!" << std::endl;
break;
}

Resources