I currently use three different functions to return a numeric value (one returns a double
, the other two return a long
):
int main(void)
{
// lots of code
dRate = funcGetInterestRate();
lMonths = funcGetTerm();
lPrincipal = funcGetPrincipal();
// lots of code
return 0;
}
The three functions code is about 90% the same so I would like to consolidate into 1 function. I want to pass a value flag to a single function something like this:
double
long
long
I only want to return 1 value ever from the function when it is called, but the value I want to return can be either a double
or a long
. I want to do something like this:
void funcFunction(value passed to determine either long or double)
{
// lots of code
if (foo)
return double value;
else
return long value;
}
Is there an easy way to do this?
A function's return type is fixed at compile time. You can't change the return type based on the parameters you pass in.
However, since your main goal is to remove repeated code in the functions and consolidate them, this can be addressed in a different way. In other words, this is an XY problem .
What you can do in your case is extract the common code in each of your three functions into a separate function, then the three original functions can call the common function to do most of the work, then extract the part they need and return that.
For example:
struct loan {
double rate;
long term;
long principal;
};
void calcLoan(struct loan *loan)
{
// do stuff
loan->rate = // some value
loan->term = // some value
loan->principal = // some value
}
double funcGetInterestRate()
{
struct loan loan;
calcLoan(&loan);
return loan.rate;
}
long funcGetTerm()
{
struct loan loan;
calcLoan(&loan);
return loan.term;
}
long funcGetPrincipal()
{
struct loan loan;
calcLoan(&loan);
return loan.principal;
}
No, C does not allow this. The return type is in the function declaration (which you have as void).
Slightly easier is to provide two pointers to variables and indicate which one to use in the return value:
int funcFunction(yourArgument, long *longResult, double *dblResult)
{
// lots of code
if (foo)
{
*dblResult = value;
return 1;
} else
{
*longResult = otherValue;
return 0;
}
}
(And possibly you can even use a union
.) However ... I had to use value
and otherValue
as inside the function you cannot use the same variable to hold either a long
or a double
. You can – again, with a union
– but this is stressing the eaze of having only one single function to the breaking point.
You might consider returning some tagged union . The Glib GVariant type could be inspirational, and since Glib is free software, you could study its source code. See also this answer .
So you would declare some public struct
with an anonymous union
inside:
struct choice_st {
bool islong;
union {
long i; // valid when islong is true
double d; // valid when islong is false
}
}
and you could return a value of that struct choice_st
.
struct choice_st res;
if (foo) {
res.islong = true;
res.i = somelong;
return res;
}
else {
res.islong = false;
res.d = somedouble;
return res;
}
You might also decide to use C dynamic memory allocation , return a freshly malloc
-ed pointer to struct choice_st
, and adopt a convention about who is responsible of free
-ing that pointer. (BTW, GVariant
is doing something similar to this).
You sort of can do this. It's easier to show than explain, but I'll add an explanation if this isn't clear:
void add_or_divide_by_xor(unsigned int a, unsigned int b, unsigned short c,
unsigned long *add, unsigned double *divide) {
unsigned int xor = a ^ b;
if (add != NULL) {
*add = xor + c;
}
if (divide != NULL) {
*divide = (double)xor / (double)c;
}
}
Called:
unsigned long add;
unsigned double divide;
add_or_divide_by_xor(5, 17, 4, &add, NULL);
add_or_divide_by_xor(17, 6, 4, NULL, ÷);
Depending on your platform, double
might be a superset of long
. You should already know whether this is true (because you know what your algorithms do, and what their possible output values are); if you don't, consider the following:
double
can represent integers up to 2 53 exactly long
is either a 32-bit or a 64-bit type So if your long
values are 32-bit, you can just always return double
from your functions, and cast it to long
outside your functions, where needed.
You could try something like this.
#include <stdio.h>
void* func1(int key){
static double interest;
static long term;
static long principle;
//your common code to modify values of interest, term and principle
//
//Let us give them some dummy values for demonstration
interest = 34.29347;
term = 5843535;
principle = 7397930;
//conditions
if(key == 1){
return &interest;
}
else if(key == 2){
return &term;
}else if(key == 3){
return &principle;
}else printf("%s\n","error!!");
}
int main()
{
printf("%f\n",*(double*)func1(1));
printf("%ld\n",*(long*)func1(2));
printf("%ld\n",*(long*)func1(3));
func1(4);
return 0;
}
Output
34.293470
5843535
7397930
error!!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.