This question already has answers here:
Should we use exit() in C?
(7 answers)
Closed 7 years ago.
I've been making some school project and I've used this function for error outputs:
void errorMsg(char* msg)
{
fprintf(stderr, msg);
exit(EXIT_FAILURE);
}
So I can do something like this:
if (condition)
errorMsg("Error, Wrong parameters.");
Message will be shown to user and program will exit with error code.
But I've recieved minus points for using exit function.
So I was just wondering how should I do it? Is there some another way than writing this for several times in main function?
if (condition)
{
fprintf(stderr, "Error, Wrong parameters.");
return(EXIT_FAILURE);
}
Thanks for you time.
It really depends on how you program, or in this case, how your teacher wants you to program.
The best answer at this case, is to go to your teacher and ask for an explanation why this is wrong.
When I program in C, all my functions always return int (or a typedef of int) and then I can return errors from functions. Then my main function returns an error as it returns. Something like this template:
int func(void)
{
int return_value = 0;
if (/* Some condition */) {
return_value = 1
}
/* Some code */
return return_value;
}
int main(void)
{
int return_value = 0;
return_value = func();
return return_value
}
Using this template, if there is an error, 1 would be returned from the main function, and in case of success, 0 would be returned. As well, you can add an if condition in the main function, to check the return value of func. This gives you the option to handle errors in your code.
One important reaons:
If you have some code which has opened files, but not yet finished to write in them, and this piece of code delegates some work to a function that will end the program, what happens?
Right, you´ll get a broken file.
Same reasoning is valid for allocated memory, open handles of any kind, etc.etc.
Instead of thinking everytime if the function could end the program, don´t write such functions in the first place. It doesn´t matter if everything is ok or not, but return the "control" after a function to the caller everytime. The only place where exit could be ok is main, because it will basically do the same thing as return there. And in main, there´s no reason to not write return in the first place.
My opinion is that exit functions are harder to test. I struggled a lot while testing a function that has exit call.
Related
I'm in my first semester at university studying C programming. We've gained an introduction to modularising our code, and the basic gist of my problem is that I've created a function which prompts the user to continue or exit the program. Obviously I have a few other functions before this and I call these in main(). Bear in mind the functions are in separate C files. I wish to loop back to main() if the user inputs 'Y' (i.e. to start the program from the beginning), but given my beginner knowledge I've had a hard time figuring out how to go about this. Any help/guidance would be appreciated!
int continueOrExit() {
char response;
char upperResponse;
printf("Do you wish to continue the program? Y/N");
scanf("%c", &response);
upperResponse = toupper(response);
while(upperResponse == 'Y')
main(); // this is the bit which I struggle with
.....
}
You should not run your main() again from inside a function already called from main(). Well, you could; recursive calls are possible, but you definitely don't want to do it in this case.
What you want to do is for your continueOrExit() to return true when user chooses to continue, and put a selected large part of your main() body in a loop:
do
{
/* your code here */
} while (continueOrExit());
Going from one function directly to another is against the rules of structured programming. It may be used for handling of errors (longjmp), but such a mechanism should be used sparingly - only when you really have an error which you cannot handle in any other way.
To implement the "start over" functionality, you have to structure your code with that in mind. For example:
int exitByUserRequest()
{
char upperResponse;
...
return (upperResponse != 'Y');
}
int main()
{
do
{
...
} while (!exitByUserRequest());
}
Here, the main function calls exitByUserRequest and interprets its exit code.
If you have several layers of functions between main and "ask user whether to continue", all of them should pass the information "exit or continue" to the caller, using return codes. Therefore, you should avoid this situation - your "exit or continue" should be called directly from main.
fairly new to C and have a slight issue,
I have a function which is filled with 'fprintf' statements and some calculations relevant to the output.
When I call it from main() it works correctly and prints to the document, I then want to call it a second time and have the same text but only outputted to the terminal (as in printf).
I have a flag in the function parameters which would specify this choice but no way of accomplishing it aside from an if statement for every fprintf saying:
if (flag == 1)
{
fprintf(pt, "Random text...
} else {
printf("The same random text...
}
Which seems dreadfully inefficient. My other idea was to (with my little understanding of it) use #define within the function in the context:
if (flag== 1)
{
#define fprintf(pt, printf(
}
Which not only seemed very cheap but did not work.
Any ideas would be appreciated,
Thanks
How about something like this:
FILE *out=stdout;
fprintf(out,"Hello World\n");
Since this is a function, you can pass in the out pointer as an argument. When printing to the terminal, just assign stdout to it.
you could do a ternary expression using the fact that printf( is equivalent to fprintf(stdout,:
fprintf(flag == 1 ? pt : stdout, "Random text...");
Generally say I have some functions step1 step2 ... and they are called successively:
int main()
{
...
step1(); // something wrong detected and need to break out of the whole program
step2();
step3();
...
}
How can I break out from step1 and skip all the rest of code to terminate main() function?
Currently I can only think of setting a global variable like bool isErr as a flag so that
step1(); // error detected and isErr is set to 1 inside step1()
if (isErr)
return;
step2();
...
Are there better or more 'canonical' approaches?
BTW I've heard that goto is bad so I discard it :)
Use
exit(1);
The number indicates the exit status. 0 is no failure, everything larger then 0 indicates an error.
One option is to check return value of your step1() function and if it is error, just use for example return 1 in main. Using return (with appropriate status code) from main to finish the program is the preferred way in C++.
Other option is exit. The point is you can call it anywhere in the code. However, in C++ exit is not recommended that much. Regarding C, there is a question here which discusses whether using exit in C is a good idea or not.
You can use the exit() function to terminate the process at any point during step1(), step2()... anywhere actually.
exit will terminate the program from wherever you are, but in most cases this is a bad idea, checking the return value of a function and handling (e.g. exit in your case) is a cleaner way to do it (no need for globals)
Basically, I am writing a program in SDL.
This is part of the code:
// create game window
game.window = SDL_CreateWindow(
"Game",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
160,
144,
0
);
if (game.window == NULL)
{
fprintf(stderr, "Window error: %s\n", SDL_GetError());
return 1;
}
atexit(SDL_DestroyWindow());
atexit(SDL_Quit());
return 0;
}
My question is the following. Considering the procedural nature of C, what happens if (game.window == NULL) is the case and return 1 executes. Does the program terminate with return 1 without calling the atexit() functions that come after this if-statement?
Does the program still call SDL_DestroyWindow() and SDL_Quit(), which are both in atexit() functions despite the atexit() functions coming after the return 1 in the if (game.window == NULL)-statement?
As far as I understand, C executes code from top to bottom, so how would it know to call the functions in atexit() at the end if return 1 happens before?
You're right, it wont call those functions registered with atexit().
To show this behaviour I wrote a small code snippet.
#include <stdlib.h>
#include <stdio.h>
void bye()
{
printf("Bye!\n");
}
int main(int argc, char *argv[])
{
int i = 1;
if (i) {
printf("Ending\n");
return 0;
}
atexit(bye);
return 0;
}
And this won't print the "Bye!", as the atexit() is registered after the check for i.
First of all, you cannot destroy the window before you know for true you have it created So the call to atexit(3) to register the function to destroy the window must be done after you know the window exists. (this is after the } closing bracket of the if)
The call to atexit(SDL_Quit); might be done once you have the SDL environment intialized (this is after it has been correctly inited, so it will be called only for a truly intialized environment) but it must be called before the call to register the destroy of the SDL window, as atexit(3) makes the functions you register, to be called in reverse order so it must first desroy the window and then close the SDL environment (and there will be no sense to call a function that destroys a window when the SDL has already been closed).
By the way, atexit() requires the function pointers, not the result of the function call. Better to write
atexit(SDL_Quit);
atexit(SDL_DestroyWindow);
Than what you have written.
NOTE
If the functions need parameters, better to write function wrappers to call them with the appropiate parameters.
For my assignment I have to create a program similar to the -wc unix command which counts words, lines, etc.
I have to read in flags and read in a text file.
I've set up all the flags and now I'm trying to read in a text file. I don't think I'm doing this right.
void readInFile(char** argv, int arg)
{
FILE *myFile;
char c;
myFile = fopen(argv[arg], "r");
if(!myfile)
{
printf("%s not found!", argv[arg]);
exit(EXIT_FAILURE);
}
}
in my main I call the function readInFile() and pass 2 arguments. Argv and the element where the file should be. So assume this to be correct.
I need help with actually opening up the file. I feel like my fopen() is wrong. I'm new to reading/writing files in C. Thanks alot!
I'm going to give you some general advice here.
Usually functions should do a single job. In this case, you are writing a function to read in a single file. So, don't pass a pointer to all the command-line arguments; pass in a single read-only pointer to the name of the file to open. Then in main() select the correct argument and pass that as the argument.
void readInFile(char const *filename)
Now, if this function will be reading in the file and doing nothing else, it needs to return the data somehow. But if this function will be doing the equivalent of wc, maybe it will read the file and print stuff, not return any data to the main() function. Then maybe the name should be improved:
void wordcount(char const *filename)
The actual call to fopen() looks fine to me.
You check for error, and then call exit() immediately. That's one way to do it. Another way to do it is to return an error code from your function, and have the caller (the main() function) check for failure, and handle the error there.
int wordcount(char const *filename)
{
// ... do stuff
if (failed)
return 1; // return nonzero error code on failure
// ... do more stuff
return 0; // success code
}
int main(int argc, char const **argv)
{
char const *filename;
int result;
filename = argv[1];
result = wordcount(filename);
if (result)
{
fprintf(stderr, "unable to open file '%s'\n", filename, result);
exit(result);
}
return 0;
}
For a program this simple, it doesn't matter much. But once you start building larger systems in software, you will be happier if your functions work well together, and part of that is making functions that return error codes rather than terminating your whole program on any error.
Why am I using 0 for the success code, and non-zero for failure? It's a common way to do it. It's easy to test for non-zero, like if (result) and there are many non-zero codes but only one zero, so you can return many different kinds of errors, but there is only one value needed for "success".
Note that instead of calling exit() from main(), you can just use the return statement. When you return 0 from main(), that signals success, and a non-zero value indicates an error. So you could just use return result; from main() if you like.
In my dummy code, I'm just returning 1 as the error code. But actually, when you call fopen() it returns an error code to you, in a global variable called errno. Probably a better option is to make your function return the actual error code as specified in errno. You could even modify the print statement in the main() function print the errno code, or use the strerror() function to turn that error code into a human-readable message.
Your call to fopen is correct, assuming that argv[arg] is a valid string which refers to a file that exists on the filesystem.
There is a small typo in the program snippet. if(!myfile) should prpbably be if(!myFile). With this change, I presume the code should work. Can you please elaborate the error faced by you?
P.S: I tried your program and it seems to work!