# Thread: Function returns string

1. ## Function returns string

I'm very sorry for making the 1100th thread about this subject. I've been searching all afternoon, scrolling through the questions and solutions but I can't get ANY of 'em to fix my problem.

What I'm trying to do is sending the line generated by the floating_point() function, for example:
166 155 68 60
(when 0.012 is entered)
...back to the main, where the function is called. I've read all about having to use malloc() because the local string is removed as soon as floating_point returns and etc. but my code won't compile.
I might be COMPLETELY wrong in the code below, it's just copy-paste-combine-alter-change of all the solutions I've seen.

Code:
```/************************ Floating point converter ****************************/
//* Function:   converts a decimal value to a floating point
//* Parameters: none
//* Returns:    none
//*
char floating_point(float flt)
{
char hex[8], hex_2[8], hex_3[8], temp[3], *p;
char **formula;
int decimal[4], i=0;
short cnt=0, cnt2=0;

formula = malloc(20 * sizeof *formula);
if ( formula != NULL )
{
for ( i = 0; i < 20; ++i )
{
formula[i] = malloc(20 * sizeof *formula[i]);
if ( formula[i] == NULL )
{
for ( i = 0; i < 20; ++i )
{
free(formula[i]);
}
free(formula);

return 0;
}
}
}

union
{
unsigned long i;
float f;
}v;

v.f = flt;
sprintf(hex_2,"%08lx",v.i);
puts(hex_2);

cnt=7;
while(cnt2<=3)
{
sprintf(temp,"%c%c",hex_2[cnt-1],hex_2[cnt]);
//      printf("%s\t",temp);
decimal[cnt2] = strtol(temp,&p,16);
cnt-=2;
cnt2++;
}
sprintf(*formula,"%d\t%d\t%d\t%d",decimal[0],decimal[1],decimal[2],decimal[3]);
puts(*formula);

return **formula;
}
/******************************************************************************/```

Code:
```int main(void)
{

char *string;

/*code*/

case '7':
*string = floating_point(0.012);
puts(string);
free(string);
break;

/*code*/

}```
Edit: http://cboard.cprogramming.com/showp...70&postcount=8 for further explanation.

I'd actually appreciate someone kicking my butt - and telling me what I'm doing wrong.

Ren&#233;

2. All you need is to return an array of values to another function right?

so create something like:
Code:
```//Return a pointer to an array of foos
foo *myfunction(int number){
foo* tmp = malloc(sizeof(foo)*number); //mallocs n elements
filltmp(temp,number); // fills your stuff

return tmp;
}```
now the trick is having something like foo* perm = myfunction();
so you are saving the value returned by myfunction (wich is the adress of the array).

3. > 294 invalid conversion from `void*' to `char*'
I've no idea which is line 294 in your code - can you annotate to indicate which line it is

Did you include all the correct header files?

Are you compiling C code with a C++ compiler (that's the usual cause of void* to type* warnings)

> if(strlen(hex)%2!=0)
If you want a padded string, try
sprintf(hex,"%08lx",v.i);
Also, you need 9 chars to store this string, not 8

> hex_3[6]=hex_2[0];
A separate stringReverse() function would be a good idea, especially if you do this elsewhere.

You could always run the next loop backwards to save reversing it at all

How about just get the bytes out of the unsigned long directly rather than via sprintf and strtol
Say
Code:
```sprintf(formula,"%d\t%d\t%d\t%d",
( v.i >> 24 ) & 0xff,
( v.i >> 16 ) & 0xff,
( v.i >>  8 ) & 0xff,
( v.i >>  0 ) & 0xff );```
Or maybe it's the other way round, but you'll get the idea.

Originally Posted by Maragato
All you need is to return an array of values to another function right?
Either that (return the four values in the decimal array) or the string "166 155 68 60" of which the latter is preferred.

I'm sorry but I don't understand anything of your example code. To give an indication of my programming knowledge: I'm still having a hard time to understand the usage of '*'.

5. >I've no idea which is line 294 in your code - can you annotate to indicate which line it is
sorry, it's *formula = malloc(20);

>Did you include all the correct header files?
afaik, yes

>Are you compiling C code with a C++ compiler (that's the usual cause of void* to type* warnings)
I'm afraid so, yes Normally I dont have any problems whatsoever though. What can I do to prevent this warnings? (please don't make me change compiler )

>If you want a padded string, try sprintf(hex,"%08lx",v.i);
That's great thanks!

>Also, you need 9 chars to store this string, not 8
Oops, thanks again.

>A separate stringReverse() function would be a good idea, especially if you do this elsewhere.
Yeah, 8 lines of plain code like that looks kinda stupid, I was trying to create an algorythm for it, but since I dont need it anywhere else it's fine like this.

>You could always run the next loop backwards to save reversing it at all
Ah there's the algorythm, lol. Damn there's still a lot to learn... thanks again

How about just get the bytes out of the unsigned long directly rather than via sprintf and strtol
Say
Code:
```sprintf(formula,"%d\t%d\t%d\t%d",
( v.i >> 24 ) & 0xff,
( v.i >> 16 ) & 0xff,
( v.i >>  8 ) & 0xff,
( v.i >>  0 ) & 0xff );```
Or maybe it's the other way round, but you'll get the idea.
> OK, I don't have to feel stupid about this one, just never heard of this method. What does this mean/do:
( v.i >> 24 ) & 0xff
(I think I know what >> 24 should do, but "& 0xff"... ?)

Thanks so much for your educational reply, well appreciated!

René

6. > please don't make me change compiler
Change your source file to be prog.c rather than prog.cpp
Or use new/delete if you really want to allocate memory in a C++ program.

> (I think I know what >> 24 should do, but "& 0xff"... ?)
Shift it right 24 bits, then mask off everything except the bottom 8 bits
Thus ensuring that whatever number it is, it will be 0x000000NN (or 0 to 255 decimal)

7. >Change your source file to be prog.c rather than prog.cpp. Or use new/delete if you really want to allocate memory in a C++ program.

Great, thanks for the tips. After including stdbool.h I had not further "C++ to C" related errors. All I got was this warning:
[Warning] assignment makes integer from pointer without a cast on this line:
Code:
`   *formula = malloc(20);`
I've solved it by removing the * in front of formula (according to another malloc example). Will try to look into the how and why soon.

>Shift it right 24 bits, then mask off everything except the bottom 8 bits. Thus ensuring that whatever number it is, it will be 0x000000NN (or 0 to 255 decimal)
Thanks, I will look into that masking method. I'm gonna have to write that down to make it clear I think.

Thanks again for the clear and helpful tips, fantastic.

8. OK, so my floating point function has been improved, which is great. But the main problem is still to send a string from the function floating_point() back to main.

Apparently I can't just send a string back but I have to allocate memory for it and send a pointer to the string back to the main. Since I hardly understand anything about pointers (well, I think I know what they are/do, but I have serious problems putting that knowledge into practise), I have no idea where to put a * and where not. I've updated the code in my first post to the latest version.

I don't get any warnings or errors during compiling. Now when I press 7 in the program I see hex_2 and *formula on my screen, just the way they're supposed to be, but after that the progam crashes. My conclusion is that it crashes when it tries to return the **formula to main.

If someone could please help me understand this pointercrap then I'd be very very grateful.

Thanks, Ren&#233;

1. The first thing to do is to look at your function's signature.
Code:
`char floating_point(float flt)`
It returns a char, ie, a single character, not a string. You probably want it to return char* if you're returning a string (or char** if you're returning an array of strings).
2. Code:
```      for ( i = 0; i < 20; ++i )
{
formula[i] = malloc(20 * sizeof *formula[i]);
if ( formula[i] == NULL )
{
for ( i = 0; i < 20; ++i )
{
free(formula[i]);
}
free(formula);

return 0;
}
}```
Don't use the same variable in two loops, one inside the other. It will mess it up completely.
3. Code:
```char hex_2[8];
sprintf(hex_2,"%08lx",v.i);```
You're stuffing nine characters (eight plus a null) into a string of eight characters. Make the array bigger.

Does your program segfault or enter an infinite loop? (I bet it's an infinite loop . . . .)

9. 1. ok, so char* it is. -thanks
2. hmm I just copied this from a reply on an earlier thread, dunno why I never thought of that... :S changed the variable in the inner loop to ii. -thanks
3. weird, I'm abolutely sure I've already changed that before (after Salem pointed me to that mistake), but I think that was in the stand-alone version of this function (which I created before implementing it in this program)

And you're lucky there wasn't money involved in the bet - my program segfaults (even after the corrections above).

Still though

10. Code:
```   if ( formula != NULL )
{
for ( i = 0; i < 20; ++i )
{
formula[i] = malloc(20 * sizeof *formula[i]);
if ( formula[i] == NULL )
{
for ( ii = 0; ii < 20; ++ii )
{
free(formula[i]);
}
free(formula);

return 0;
}
}
}```
You probably want to change the red 20 to i . . . otherwise you might end up freeing data that was never allocated.

Where does your program segfault? (Time to fire up your debugger . . . .)

11. Omg, after another "randomly adding / removing of asterisks"-session I got it to work!!

the return should be like this:
return *formula;

and then the string back in main should be filled like this:
string = floating_point(0.012);

... and the best thing is, I even think I understand WHY

Thanks for all your help guys, I don't know what I'd do without this forum, really.

12. >You probably want to change the red 20 to i . . . otherwise you might end up freeing data that was never allocated.
Hmm yeah, good point, thanks.

>Where does your program segfault? (Time to fire up your debugger . . . .)
There's a problem. The debugger in Dev-C++ sucks, I just get a message it segfaults but then it doesnt say on which line it crashed... :/

I will.

13. Code:
```char* floating_point(float flt)
{
char hex[9], hex_2[9], hex_3[9], temp[3], *p;
char **formula;
int decimal[4], i=0, ii=0;
short cnt=0, cnt2=0;

formula = malloc(20 * sizeof *formula);
if ( formula != NULL )
{
for ( i = 0; i < 20; ++i )
{
formula[i] = malloc(20 * sizeof *formula[i]);
if ( formula[i] == NULL )
{
for ( ii = 0; ii < i; ++ii )
{
free(formula[ii]);
}
free(formula);

return 0;
}
}
}

union
{
unsigned long i;
float f;
}v;

v.f = flt;
sprintf(hex_2,"%08lx",v.i);
puts(hex_2);

cnt=7;
while(cnt2<=3)
{
sprintf(temp,"%c%c",hex_2[cnt-1],hex_2[cnt]);
//      printf("%s\t",temp);
decimal[cnt2] = strtol(temp,&p,16);
cnt-=2;
cnt2++;
}
sprintf(*formula,"%d\t%d\t%d\t%d",decimal[0],decimal[1],decimal[2],decimal[3]);
puts(*formula);

return *formula;
}```

Code:
```         case '7':

string = floating_point(0.012);
puts(string);
free(string);

break;```
So this should be correct.....(?)

14. Pretty much . . . but what happens if the first call to malloc fails (formula==NULL)? Boom . . . segfault.

Code:
```   union
{
unsigned long i;
float f;
}v;```
You're aware that declarations in the middle of a block is C++/C99 and not C89?

>Where does your program segfault? (Time to fire up your debugger . . . .)
There's a problem. The debugger in Dev-C++ sucks, I just get a message it segfaults but then it doesnt say on which line it crashed... :/
Try running gdb from the command line.  Like this: http://cboard.cprogramming.com/showp...79&postcount=7 [/edit]

Popular pages Recent additions