CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Oct 2010
    Location
    Australia
    Posts
    98

    Need to return a *char not address of...

    Hi,
    The following function is supposed to return a const char from a float. But instead the warning I get says it is returning the address of the local variable ans
    Code:
    #include <cstdio>
    
    char *ftostr(float dVar)
    {
        char ans[20];
    
        snprintf(ans, 20, "%f", dVar);
    
        return ans;
    }
    How to achieve the return of a const char and not the address of ans?

  2. #2
    Join Date
    Oct 2010
    Location
    Australia
    Posts
    98

    Re: Need to return a *char not address of...

    CORRECTION:
    Hi,
    The following function is supposed to return a const CHAR* from a float. But instead the warning I get says it is returning the address of the local variable ans
    Code:
    #include <cstdio>
    
    char *ftostr(float dVar)
    {
        char ans[20];
    
        snprintf(ans, 20, "%f", dVar);
    
        return ans;
    }
    How to achieve the return of a const CHAR* and not the address of ans?

  3. #3
    Join Date
    Aug 2006
    Posts
    157

    Re: Need to return a *char not address of...

    First of all your function is not set up to return a const char. You need to declare it thusly:
    Code:
    const char *ftostr(float dVar) {...}
    Secondly, you are returning a pointer to a local variable "ans". Notice how you have declared ans in the scope of that function. This means that once the function has returned, the pointer will no longer be valid. That's why the compiler warns you.

    BJW

  4. #4
    Join Date
    Oct 2010
    Location
    Australia
    Posts
    98

    Re: Need to return a *char not address of...

    Thanks sockman, I actually figured that out just a few minutes ago. But the return still comes up garbled symbol.

    This is the fragment I am using in my Win32 project:
    Code:
         float fNum = GetDlgItemFlt(hwndDlgM, IDC_NUMBER);
    
         fNum = (fNum / 2.54);
    
         const CHAR*sNum = ftostr(fNum);
    
         SetDlgItemText(hwndDlgM, IDC_CONVERTION, sNum);
    Nevermind the GetDlgItemFlt(...) I am sure its not the problem (hopefully)
    I think this test code below hold a partial answer but the cout is totally ignoring anything right of the decimal - which does not go out.
    Code:
    #include <cstdio>
    #include <iostream>
    
    const char *ftostr(float dVar)
    {
        char ans[20];
    
        snprintf(ans, 20, "&#37;f", dVar);
    
        return ans;
    }
    
    int main()
    {
        double fNum;// = 3.145;
        std::cout << "Enter a decimal value: ";
        std::cin >> fNum;
        
        const char *cNum = ftostr(fNum);
        
        std::cout << *cNum << std::endl;
        
        system("pause");
        
        return 0;    
    }
    Ultimately, this line:
    Code:
    SetDlgItemText(hwndDlgM, IDC_CONVERTION, sNum);
    Will output the fully converted sNum.

    Any suggestions or examples are humbly welcome.

  5. #5
    Join Date
    May 2008
    Posts
    38

    Re: Need to return a *char not address of...

    First of all I'd just do std::cout << cNum << std::endl; rather than passing a pointer to it...... but then there's also one or two things that could also do with changing before it works properly. Like sockman mentioned, you shouldn't be returning a pointer to something declared locally in the function. I'd change what you have to something more like this....
    Code:
    #include <cstdio>
    #include <iostream>
    
    const char *ftostr(float dVar, char* buffer)
    {
       // char ans[20];
    
        snprintf(buffer, 20, "%f", dVar);
    
        return buffer;
    }
    
    int main()
    {
        double fNum;// = 3.145;
        std::cout << "Enter a decimal value: ";
        std::cin >> fNum;
        char buffer[20];
        //const char *cNum = ftostr(fNum);
        ftostr(fNum, buffer);
        
        std::cout << buffer << std::endl;
        
        system("pause");
        
        return 0;    
    }

  6. #6
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Need to return a *char not address of...

    Quote Originally Posted by Morbane View Post
    I am sure its not the problem (hopefully)
    I think this test code below hold a partial answer but the cout is totally ignoring anything right of the decimal - which does not go out.
    Do not return pointers or references to local variables. Doing so is undefined behaviour.
    Code:
    #include <cstdio>
    #include <iostream>
    
    const char *ftostr(float dVar)
    {
        char ans[20];
    
        snprintf(ans, 20, "%f", dVar);
    
        return ans;  // this is absolutely no good
    }
    So you must scrap this idea of returning a pointer to local variable and come up with another way of doing what you want. One way has been mentioned, and that is to pass the buffer to fill in, and you fill the buffer with the information.

    The other way is to use container classes such as std::string or std::vector<char> instead of character arrays. If this is a C++ program, you shouldn't be writing functions in the way you wrote yours -- there is no need to.
    Code:
    #include <string>
    //...
    std::string ftostr(float dVar)
    {
        char ans[20];
        snprintf(ans, 20, "%f", dVar);
        return ans;
    }
    The trick is that on return, the char array is converted to a std::string, so you are not returning a pointer or reference to a local variable. A much safer approach:
    Code:
    #include <string>
    #include <sstream>
    //...
    std::string ftostr(float dVar)
    {
        std::ostringstream strm;
        strm << dVar;
        return strm.str();
    }
    Now there is no chance of buffer overflow.

    Regards,

    Paul McKenzie

  7. #7
    Join Date
    Oct 2010
    Location
    Australia
    Posts
    98

    Re: Need to return a *char not address of...

    I found the solution - it is similar to Paul's suggestion. If there are any potential problems such as buffer overflow or something like, please let me know.

    Here is the function I am using:
    Code:
    char* ftochar(double val)
    {
        stringstream ss (stringstream::in | stringstream::out);
    
        ss << val;
    
        string test = ss.str();
    
        char * cstr;
    
        cstr = new char [test.size()+1];
        strcpy (cstr, test.c_str());
    
        return cstr;
    }
    It works to pass the value into the Win32 function below nicely - so far:
    Code:
    SetDlgItemText(hwndDlgM, IDC_CONVERTION, (CHAR*)sNum);
    THANKS for the replies everyone!

  8. #8
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: Need to return a *char not address of...

    Quote Originally Posted by Morbane View Post
    I found the solution - it is similar to Paul's suggestion. If there are any potential problems such as buffer overflow or something like, please let me know.
    The solutions were already given to you. Your 'solution' has a memory leak--new without delete.

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Need to return a *char not address of...

    Quote Originally Posted by Morbane View Post
    I found the solution - it is similar to Paul's suggestion. If there are any potential problems such as buffer overflow or something like, please let me know.
    So who is responsible for cleaning up the call to "new"? Your program has a memory leak.

    The solution is what I gave you. If a C++ program is resorting to strcpy() and char* to handle strings, then there better be a good reason to do that, with the person giving the reason a good C++ programmer before it can be accepted.

    If the function returns a std::string such as my version, and then if you need to pass that to a function that takes a const char*, then use the c_str() member function.
    Code:
    std::string sNum;
    sNum = // my version of the function in question, not yours.
    SetDlgItemText(hwndDlgM, IDC_CONVERTION, sNum.c_str());
    Regards,

    Paul McKenzie

  10. #10
    Join Date
    Oct 2010
    Location
    Australia
    Posts
    98

    Re: Need to return a *char not address of...

    Well - Thanks again!

    I was a bit overexcited that I found something that worked - even if it was not a 'solution'.

    I put Paul's code to use and I feel much better about things now.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured