Thread: Function returns string

  1. #1
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154

    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.

    Thanks in advance,
    Ren&#233;
    Last edited by rkooij; 08-29-2006 at 08:00 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  2. #2
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    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. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > 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.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    Thanks for your answer Maragato.
    Quote 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 '*'.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  5. #5
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    >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é
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > 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)
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    >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.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  8. #8
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    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;
    Last edited by rkooij; 08-29-2006 at 08:00 AM.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    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 . . . .)
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    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).

    Thanks for your answers!

    Still though
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    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 . . . .)

    Can you post the latest version?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    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.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  13. #13
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    >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... :/

    >Can you post the latest version?
    I will.
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  14. #14
    1ST » R. vd Kooij
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    154
    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.....(?)
    http://www.f1rstracing.nl/
    OS: Windows XP
    Compiler: Dev-C++

  15. #15
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    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. [edit] Like this: http://cboard.cprogramming.com/showp...79&postcount=7 [/edit]
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 11
    Last Post: 05-19-2009, 08:17 AM
  2. Question..
    By pode in forum Windows Programming
    Replies: 12
    Last Post: 12-19-2004, 07:05 PM
  3. Contest Results - May 27, 2002
    By ygfperson in forum A Brief History of Cprogramming.com
    Replies: 18
    Last Post: 06-18-2002, 01:27 PM
  4. Custom String Parsing Function
    By Unregistered in forum C++ Programming
    Replies: 2
    Last Post: 05-01-2002, 11:07 PM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM