1

I study Data Structure in C and I study part of Polynomial by using structs in C.

I am implementing a function Coef(polynomial, exponent). This is a function that returns the coefficient corresponding to the parameter exponent.

This is my code:

typedef struct polynomial{
    int degree;
    float coef[MAX_DEGREE];
}Polynomial;

typedef int coefficient;
typedef int Exponent;

coefficient Coef(Polynomial* poly,int expon){
    if(poly->coef[MAX_DEGREE - expon]){ // because array stored coefficient in descending order of exponent
        return poly->coef[expon];
    }
    else{
        return Error
    }
}

In the else statement, if polynomial doesn't have a term that exponent matches parameter exponent, I want to return an error.

But the return type of the function is coefficient (i.e. int) and this can have any number.

How can I return an error?

wovano
  • 4,543
  • 5
  • 22
  • 49
정민욱
  • 37
  • 3
  • 2
    `I want to return Error sign` What is an "error sign"? You want to "notify the caller of your function that an error occured"? `the long question` No worries, it's quite short. – KamilCuk Jul 05 '20 at 10:16
  • 2
    Does this answer your question? [Error handling in C code](https://stackoverflow.com/questions/385975/error-handling-in-c-code) – Ardent Coder Jul 05 '20 at 10:23
  • I understand what you want to ask but this could have been way better explained at a more simple and focused example. Your costum function with your explanatory "Error" return value was not necessary to illustrate and is source of confusion here. – RobertS supports Monica Cellio Jul 05 '20 at 11:10

3 Answers3

0

you can use enums or Enumeration and write a functiont that return this enum. Enumeration is a user defined datatype in C language. It is used to assign names to the integral constants which makes a program easy to read and maintain. The keyword “enum” is used to declare an enumeration.

and the value that need to be returned in standard situation (no errors) return it by pointer dereference p_ret which caller need to pass to foo function.

typedef enum{
  E_ERROR = 0,
  E_INVALID_ENTRY,
  E_SUCCESS
  /*
  ADD error codes as neccessary
 */

}E_RET;


E_RET foo(Polynomial* poly,int expon, float* p_ret)
{
    if(poly->coef[MAX_DEGREE - expon] )
    { 
     /********************************
     because array stored coefficient
     in descending order of exponent
     *********************************/
        *p_ret = poly->coef[expon];
        return E_SUCCESS;
    }
    else
    {
        return E_ERROR;
    }
}

caller

here illustration of how you should call the function:

Polynomial poly;
float ret;

E_RET return_stat = foo(&poly, 1, &ret)
/* check for return status */
if(return_stat != E_SUCCESS)
{
    /*something wrong! envoke error handling*/
    abort();
}
Adam
  • 2,820
  • 1
  • 13
  • 33
  • @KamilCuk - my answer is suggesting to use the `enum` c feature. i am not fixing his function logic. this is not what he asked for. – Adam Jul 05 '20 at 10:23
  • 1
    @wovano Sure, but before the edit it did ;) I guess then I just remove my comments as they are no longer relevant – KamilCuk Jul 05 '20 at 14:45
-1
  1. You could store the result in a separate value, passed by pointer
  2. You could return a pointer to a result in case of a success and a NULL pointer in case of failure, because the value used to store the result is declared outside of a function scope
  3. Use a global variable to store an error code, that is checked after the function call. It is also recommended to highlight that the variable in question is global by something like "g_" prefix. WARNING: Only viable in an environment, where no two threads could access the global variable in question after the function that uses the global variable already been called, but the check on global variable has not yet been executed.
SunGrow
  • 87
  • 1
  • 8
  • 2
    Or just make the returning `coefficient` a pointer and return either `NULL` or `return &poly->coef[expon];` – Daniel Schütte Jul 05 '20 at 10:25
  • 1
    using global variables in c is dangerous and try to prevent them. globals are used as last choice. this case can be handled easily without using global variables. – Adam Jul 05 '20 at 10:27
  • 1
    @Adam using global variables in general is dangerous and could result in some unwanted behavior, as all the possible error check could only be done at link time, BUT, if you are using one global value to store the last executed function error code, and are highlighting that this is, indeed, a global value with something like "g_" prefix, then I see little to no harm in that – SunGrow Jul 05 '20 at 12:46
-1

Welcome to the world of error handling. So basically you want to return an optional value - either the value if valid and you want to return the value or the value is invalid and want to return an error condition.

You can wrap it in a structure, but don't:

struct coef_or_err {
  int err;
  coefficient coef;
};
struct coef_or_err function() {
    if (poly->coef[MAX_DEGREE - expon]){
       return (struct coef_or_err){ .err = 0, .coef = poly->coef[expon] };
    } else {
       return (struct coef_or_err){ .err = 1 };
    }
}

But that is a lot of typing and different structures for all possible cases, it's not bearable to maintain such code easily. So it's typical in C to pass additional parameters by pointers. Either passing a pointer to an int that will be an non-zero error code in case of error or most prefer returning an int with value 0 on success and take all other parameters by pointers:

int Coef(Polynomial* poly, int expon, coefficient *coef) {
    if (!poly->coef[MAX_DEGREE - expon]) {
       return -1; // or some error code, maybe ENOENT from errno.h
    }
    *coef = poly->coef[expon];
    return 0;
}
// example user call
int main() {
   coefficient coef;
   if (!Coef(some_poly, 15, &coef)) {
      // handle error
      abort();
   }
   // use coef
}

Eamples of such error handling can be found in many places. Another type of error handling is using a global variable, either stored in the object or... globally, but please don't (errno and why global variables are bad):

coefficient Coef(Polynomial* poly, int expon) {
    if (!poly->coef[MAX_DEGREE - expon]) {
       poly->err = 1;
       return 0;
    }
    return poly->coef[expon];
}
int Coef_is_err(Polynomial* poly){
   return poly->err;
}
void Coef_clear_err(Polynomial* poly){
   poly->err = 0;
}
int main() {
   coefficient coef = Coef(some_poly, 15);
   if (Coef_is_err(some_poly)) abort();
   // use coef
}

The most prominent example is ferror(FILE*) from standard library. Such code is more usefull in case of I/O operations, for example aio_error() from posix.

And yet another way is using out-of-bounds values to transfer errors, typically used when the type can represent more values then are valid for the meaning. For example function returning count of somethings has to return a positive number or zero - a negative would be an error.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
  • why you dont use just `enum`? why we need to declare astructure for error code? – Adam Jul 05 '20 at 10:29
  • It literally says there `You can wrap it in a structure, but don't:` and then I follow to explain why such code is not feasible in real codebase. Still such implementations of optional values are used sometimes. `why we need to declare astructure for error code?` To return the value with an additional information together in a return statement. – KamilCuk Jul 05 '20 at 10:34