Click here to Skip to main content
15,896,153 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

In my application, I want read the two integer values from ini file.That value should be in the range -1 to 1023. I have used GetPrivateProfileString() to read the values and converted the string to integer using _wtoi().
But if I enter some invalid values like string values or empty values, the _wtoi returns the value as zero. That is a valid number in my case, but it should not happen.

So please tell me whether I can specify any range while reading the value from ini file or any other alternative for _wtoi().

Thanks in advance...
Posted
Updated 19-Aug-11 19:44pm
v2

Finally I have decided to write my own function which will read the integer value from INI and does the validation according to the input as shown below.

C++
long ReadIntegerValueFromIni( const CString& csAppName_i,
                              const CString& csKeyName_i,
                              const CString& csDefaultVal_i,
                              const CString& csFileName_i,
                              const int nMinVal_i,
                              const int nMaxVal_i )
{
    long lKeyValue = 0;
    int nDefaultVal = _ttoi( csDefaultVal_i );
    try
    {
        const int SUCCESS_RET = 1;
        TCHAR tcszBuf[ MAX_PATH ];
        TCHAR tcszBufTemp[ MAX_PATH ];
        lKeyValue = nDefaultVal;

        // Read the value from INI file.
        GetPrivateProfileString( csAppName_i, csKeyName_i, csDefaultVal_i, tcszBuf, sizeof( tcszBuf ),
                                 csFileName_i );
        // Check whether the value read from ini is a valid numeric number or not.
        if( SUCCESS_RET != swscanf( tcszBuf, _T( "%d%s" ), &lKeyValue, &tcszBufTemp ))
        {
            lKeyValue = nDefaultVal;
            // Invalid value found so adjusted to Default Value.
        }
        // Check whether the value read from ini is within the allowed range or not.
        else if( nMinVal_i > lKeyValue || nMaxVal_i < lKeyValue )
        {
            lKeyValue = nDefaultVal;
            // Input value is not within the allowed range, so adjusted to Default Value
        }
        else
        {
            // Do nothing.
        }
    }
    catch( ... )
    {
        // Unhandled exception occured in ReadIntegerValueFromIni()
        lKeyValue = nDefaultVal;
    }
    return lKeyValue;
}


Valid comments are welcome.
 
Share this answer
 
v3
You can't specify any limits on GetPrivbateProfileString - it returns what it finds, and can only be given a default value (which could be a number outside your valid range). But it only applied the default if it does not find the key defined in the INI file.

There is no equivalent of _wtoi that does what you ask - it returns 0 if the function fails.

I would suggest that you pre-process the returned string, and check it for validity yourself.
 
Share this answer
 
You may use instead the GetPrivateProfileInt[^] function, providing a default value 'out of the allowed range' (e.g. 16384) and then check the return value.
 
Share this answer
 
Comments
sanoopdas 19-Aug-11 3:38am    
We can't use GetPrivateProfileInt(), since it does not support negative values.

UINT WINAPI GetPrivateProfileInt()
CPallini 19-Aug-11 3:44am    
Despite its signature, that function works with (signed) integers (just made a test).
An alternative route would be using GetPrivateProfileString and then strtol to perform the conversion (the latter function gives you the means to check if the conversion was good).
Philippe Mori 19-Aug-11 16:38pm    
strtol won't help to detect all errors.
CPallini 21-Aug-11 3:58am    
Yes, it would help.
Philippe Mori 21-Aug-11 7:36am    
It helps for out of range values but not for invalid text which will still returns 0.... which seems to be the main concern of the OP.
There are no standard library functions to do what you want, so you should write your own conversion routine which checks for illegal characters and values.

[edit]Alternatively you could use wcsspn()[^] to check for valid characters and then use _wtoi() to convert if valid.[/edit]
 
Share this answer
 
v2
If the returns value is 0 then check if the string contains a 0.

It is a bit simpler to do it that way as the extra check is simpler to code.
 
Share this answer
 
v2
Comments
sanoopdas 20-Aug-11 2:02am    
That is a nice solution.
But if the user has given like this "00" or "000", then also that is a zero. So the checking will be little difficult.
Philippe Mori 20-Aug-11 8:27am    
Well, often if user should not modify those strings, then a bit of "undefined" behavior could be acceptable. Thus it might not be that bad if such string are handled either as 0 or as other invalid strings.

Similary, does the application has to handle binary, hexadecimal or octal numbers? Do it have to handle number in scientific notation (1e3 for 1000)? Does it have to handle very large numbers? Does it have to handle the case where there is some text after the number?

If you want it to be fully defined and implement it according to the specification, then it is fine but most of the time simpler code is more than enough (particulary when normally the settings are written only by the application itself).
You can use GetPrivateProfileInt() for this requirement.

UINT WINAPI GetPrivateProfileInt()

Since the size of UINT and INT are same, there will not any data lose.
The only difference is that, UINT take the sign bit as value.
but when you type cast the same UINT to a INT, the sign bit is valid again.
C++
UINT uRet = GetPrivateProfileInt( csAppName, csKeyName, nDefaultVal, lpctszFile );
// Now the nRet is invalid due to the sign error
// convert the UINT to INT
INT nValue = static_cast<int>( uRet );
</int>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900