Silviu-Marius Ardelean's blog

a software engineer's web log

Numeric type conversion to std::string and vice versa

In our real applications we have to convert from strings to integer or to real variables and vice versa (double/float/int variable to std::string).
We can realize these conversions using C style CRT function or we can try C++ approach via STL.
Unfortunately, current C standard libraries do not offer a complete support for any type of conversion. For instance, if we try to put an integer into a C++ string object (std::(w)string) using a well known function itoa() then we get next error:
[cpp]
int x1 = 230;
std::string s1;
itoa(x1, s1, 10);
[/cpp]
// error C2664: ‘itoa’ : cannot convert parameter 2 from ‘std::string’ to ‘char *’

A C style approach in order to avoid this error means using an intermediary buffer:
[cpp]
int x1 = 230;
std::string s1;
char szBuff[64]={0};
itoa(x1, szBuff, 10);
s1 = szBuff;
[/cpp]

Same story if we try to convert a std::string to an int:
[cpp]
std::string s3 = “442”;
int x3 = atoi(s3);
[/cpp]
// error C2664: ‘atoi’ : cannot convert parameter 1 from ‘std::string’ to ‘const char *’

In this case we can use c_str() in order to return a constant pointer to char.
[cpp]int x3 = atoi(s3.c_str());[/cpp]

An elegant way to get rid of such problems is to build two conversion function that use templates and C++ streams.
Base on this idea, I created a Sting2Numeric class that contains two static methods: Type2String() and String2Type().
[cpp]
class String2Numeric
{
public:

template
static xstring Type2String(TypeT x)
{
xostringstream o;
if (!(o << x)) throw BadConversion("Type2String(TypeT)"); return o.str(); } template
static TypeT String2Type(const xstring& s)
{
xistringstream i(s);
TypeT x;
if (!(i >> x))
throw BadConversion(“String2Type(TypeT)”);

return x;
}
};
[/cpp]

where BadConvertion is a std::runtime_error‘s derived class.
[cpp]
class BadConversion : public std::runtime_error {
public:
BadConversion(const std::string& s)
: std::runtime_error(s)
{ }
};[/cpp]

Because of ANSI and UNICODE project’s compatibility I defined few macros:
[cpp]
#ifdef _UNICODE
#define xstring std::wstring
#define xostringstream std::wostringstream
#define xistringstream std::wistringstream
#else
#define xstring std::string
#define xostringstream std::ostringstream
#define xistringstream std::istringstream
#endif
[/cpp]
Because of this compatibility I strongly recommend using a xstring alias instead of std::wstring or std::string.
When you want to convert an int, float, double, or other numerical type to a xstring in a C++ style you can use the Type2String() function. Vice versa, if you want to convert a xstring to these types you can use String2Type().

In order to avoid possible thrown exception I recommend to you using a try catch block whenever you’re using these functions. I prefer using xstring for string/wstring variables definition, too.
Here is a sample of using this class:
[cpp]
double y1 = 0.2312, y2 = 1.0123;
xstring s1 , s2;

try
{
s1 = String2Numeric::Type2String(y1);
s2 = String2Numeric::Type2String(x2);

#ifdef _UNICODE
xstring s3(L”43.52″);
#else
xstring s3(“43.52”);
#endif

x2 = String2Numeric::String2Type(s3);
y2 = String2Numeric::String2Type(s3);
}
catch (BadConversion &eBC)
{
std::cout << "An exception has been thrown: " << eBC.what() << std::endl; } [/cpp] The String2Numeric class can be extended. For instance, if the conversion throw an error then you can add detailed information in the exception message.

Download String2Numeric (1148 downloads) class.

, , , , ,
15/01/2011 at 6:25 PM Comments (0)

Flexible changes for product version properties – Visual C++ binaries

Manually editing of binary files version in the resource editor of Visual Studio IDE is not a viable solution. If we have dozens of projects in our solution, then for each kit building we should need manual resources file edit. Otherwise, we can use a special tool that does this thing for us.
Unfortunately this approach is not the most flexible and could fail.

For our flexible binaries properties changes and in order to avoid manual edit for each rebuild we can create and include a header file (version.h) that contains some constants of product version and file version of our project (.rc files).

We have to include only these constants into this file (version.h):
[cpp]
#define PRODUCT_VERSION 4.3.2.198
#define PRODUCT_VERSION_STR “4.3.2.198”[/cpp]
Then, for each .rc file wherever we have FileVersion and ProductVersion we have to use this constants.
When we will build a new kit, we have to change only these constants and then to start the kit building process. Everything is fine until we add new controls in our projects resource files. Then, because of Visual Studio IDE automation we can get an unlikely surprise: the FileVersion and the ProductVersion properties could be reset to 1.0.0.0.

In order to avoid this issue and edit the version only in a single place I propose the following workaround:

  • Create a version.h header file that have to contain these constants only (as on top). I should recommend to create it into the root solution in order of being easy included in all the projects.
  • Include this file in the project you need to use.
  • Use a text editor (ex. notepad.exe) and include next code section at the end of .rc2 resource file of your project (res\your_project.rc2) – this section contains the include version.h file section, too.
  • [cpp]
    // Neutral resources
    #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
    #ifdef _WIN32
    LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
    #pragma code_page(1252)
    #endif //_WIN32

    /////////////////////////////////////////////////////////////////////////////
    //
    // Version
    //

    #include “..\version.h”

    VS_VERSION_INFO VERSIONINFO
    FILEVERSION PRODUCT_VERSION
    PRODUCTVERSION PRODUCT_VERSION
    FILEFLAGSMASK 0x3fL
    #ifdef _DEBUG
    FILEFLAGS 0x1L
    #else
    FILEFLAGS 0x0L
    #endif
    FILEOS 0x4L
    FILETYPE 0x1L
    FILESUBTYPE 0x0L
    BEGIN
    BLOCK “StringFileInfo”
    BEGIN
    BLOCK “040904e4”
    BEGIN
    VALUE “CompanyName”, “TODO:
    VALUE “FileDescription”, “TODO:
    VALUE “FileVersion”, PRODUCT_VERSION_STR
    VALUE “InternalName”, “testResources.exe”
    VALUE “LegalCopyright”, “TODO: (c) . All rights reserved.”
    VALUE “OriginalFilename”, “your_project.exe”
    VALUE “ProductName”, “TODO:
    VALUE “ProductVersion”, PRODUCT_VERSION_STR
    END
    END
    BLOCK “VarFileInfo”
    BEGIN
    VALUE “Translation”, 0x409, 1252
    END
    END
    #endif // Neutral resources
    /////////////////////////////////////////////////////////////////////////////
    [/cpp]

  • Edit “040904e4” block code with same data as if we should edit in a resources editor and use the version.h‘s file defined constants. As you can see in my example, for the FileVersion and ProductVersion properties I use my version.h constants. These properties will not be edited anymore.
  • Delete “// Version” section from default resource file your_project.rc (including comments – recommended).
  • Insert next lines into your_project.rc file after “3 TEXTINCLUDE BEGIN” and before “#define _AFX_NO_SPLITTER_RESOURCES\r\n“:
  • [cpp] “\r\n”
    “#include “”res\\your_project.rc2″”\r\n”
    “\0″[/cpp]
    That code block looks like this:
    [cpp]
    3 TEXTINCLUDE
    BEGIN
    “\r\n”
    “#include “”res\\your_project.rc2″”\r\n”
    “\0”
    “#define _AFX_NO_SPLITTER_RESOURCES\r\n”
    “#define _AFX_NO_OLE_RESOURCES\r\n”
    “#define _AFX_NO_TRACKER_RESOURCES\r\n”
    “#define _AFX_NO_PROPERTY_RESOURCES\r\n”
    “\r\n”
    “#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)\r\n”
    “LANGUAGE 9, 1\r\n”
    “#pragma code_page(1252)\r\n”
    “#include “”res\\your_project.rc2″” // non-Microsoft Visual C++ edited resources\r\n”
    “#include “”afxres.rc”” // Standard components\r\n”
    “#endif\r\n”
    “\0”
    END
    [/cpp]
    Don’t forget to edit .rc2 file name with the right file name of your project.

  • In your_project.rc file the section “// Generated from the TEXTINCLUDE 3 resource.” have to contain only next declaration:
  • [cpp]#include “res\your_project.rc2″[/cpp]
    The rest of the section’s lines have to be deleted.

  • We save both resources files: your_project.rc and your_project.rc2.
  • Rebuild the project and check the new generated binary properties. In the FileVersion we will have the major version (in my case 4.0.0.0) and in ProductVersion we have the current build version (4.3.2.198).
  • Observations
    Once you apply these steps, the product version properties will not possible from the Visual Studio IDE resource editor, anymore (only as edit text file or an external text editor). If we didn’t define something special in our project’s String Table we will see only IDS_ABOUTBOX.

    Demo application - AutoProductVersion (1339 downloads)
    , , , , ,
    09/01/2011 at 4:40 PM Comment (1)

    Simple Pictures Unifier – first version

    Have you just returned from vacation and you have a lot of pictures? You just downloaded your taken pictures and you got your friends pictures, too? Then, probably, the pictures are scattered, with a random order in your computer.
    Would you like seeing pictures from all sources in order of events happening?
    If so, try to sort your photos using Simple Pictures Unifier tool! 🙂

    Simple Pictures Unifier application

    Please, feel free to add comments, suggestions or bugs reports to this application.
    Any constructive feedback is sincerely appreciated. Thanks you!

    , , , , , , , ,
    04/01/2011 at 10:40 AM Comments (0)