NilsK
NilsK

Reputation: 125

C – How to use an exit/return statement in ternary operator?

I wanted to formulate these two if statements in a shorter way:

//FUNCTION PROTOTYPES
int checkCommandLineArguments(int argc, char *argv[]);
int checkFile(char *argv[]);

//MAIN FUNCTIONxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
int main(int argc, char *argv[])
{
    checkCommandLineArguments(argc, &argv[1]);
    checkFile(&argv[1]);
    return 0;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx



//F1–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
int checkCommandLineArguments(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("Usage: ./recover image\n");
        exit(1);
    }
    return 0;
}
//–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

//F2–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
int checkFile(char *argv[])
{
    FILE *file = fopen(argv[1], "r");
    if (NULL == file)
    {
        printf("Cannot open file!\n");
        exit(1);
    }
    return 0;
}
//–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––

I thought about using a ternary operator:

(argc != 2) ? printf("Error X\n"), exit(1) : (NULL == file) ? printf("Cannot open file!\n"),
        exit(1): return 0 ;

However, it doesn't seem to work (probably because of the return/exit statements). How can I fix that, or are there any other (more appropriate) ways to do this?

Thank you!

EDIT 1 It has been commented that ternary operators don't work with statements, so that option is off the table. However, I'm still searching for better ways to do this.

EDIT 2 I added a more extended code example, since it has been asked for in the comments.

Upvotes: 0

Views: 664

Answers (2)

John Bollinger
John Bollinger

Reputation: 181169

How to use an exit/return statement in ternary operator?

You cannot. The second and third operands of a ternary operator must be expressions, and a return statement is not an expression (see Ternary operators and Return in C). It is, however, allowed for the two to both be void expressions, such as exit(1), in which case the result of the operation is also a void expression.

Additionally, with respect to your specific code, the comma operator (,) has the lowest precedence of all C operators. Therefore, if you intend to use a comma expression as an operand in any other operation, then you need to parenthesize it.

I wanted to formulate these two if statements in a shorter way:

Why? Mere conciseness or brevity is not a useful objective. If it makes your code hard for a human to read and understand, then making your code shorter is a liability.

But if you mean that you want to express the same thing more simply, more clearly, and / or less redundantly, then that can lead you toward forms that also happen to be shorter. For example, you can encapsulate the logic in a function or macro. Personally I often supply a macro that looks something like this:

#define ERROR_IF_NZ(cond, message) do { \
    if (cond) { \
        fputs(message, stderr); \
        exit(1); \
    } \
} while (0)

Using that, your code could look like this:

ERROR_IF_NZ(argc != 2, "Error X\n");
ERROR_IF_NZ(NULL == file, "Cannot open file!\n");

Adjust the macro name so that it makes the most sense to you, and look! It is not only clearer than the original code, but shorter, too, even if you count the length of the macro definition.

Update

Edits to the question have pretty much mooted this answer. If you already have functions that serve the the same role that a macro such as described here would do, then just call them. There is no redeeming value in replacing the functions and the calls to them with a ternary expression, nor is it worth any effort to convert the functions you have into macros. Certainly, reducing source code size is not an reasonable motivation for such changes.

Upvotes: 2

Jabberwocky
Jabberwocky

Reputation: 50883

The code you added with the edit is readable and more or less fine, you don't need to obfuscate it with ternary operator tricks.

Only checkFile is pretty pointless, you open the file and then you quit the function without doing anything with file and eventually leaking the file handle.

You probably want this pattern:

int main(int argc, char *argv[])
{
    checkCommandLineArguments(argc, &argv[1]);
    FILE *file = checkFile(&argv[1]);

    // do stuff with file

    fclose(file);
    return 0;
}

FILE *checkFile(char *argv[])
{
    FILE *file = fopen(argv[1], "r");
    if (NULL == file)
    {
        printf("Cannot open file!\n");
        exit(1);
    }
    return file;
}

Upvotes: 2

Related Questions