Domanda

The main problem I am facing here is that strtoll() is flagged as an error in VC 2010 (error C3861: 'strtoll': identifier not found). Will it do the same thing if I replace it with strtol()?

unsigned int get_uintval_from_arg(int argc, int index, char **argv,
                                  unsigned int lower_bound, unsigned int upper_bound) 
{  
    unsigned int return_val=0;

    if (index + 1 <= argc - 1)
    {
        return_val=(unsigned int)strtoll(argv[index+1],NULL,10);
        if (errno == EINVAL || errno== ERANGE) 
        {
            fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                    argv[index], argv[index+1]);
            return 0;
        }
    }
    // ....... I will post the remaining part of the code if necessary 
    .......
}
È stato utile?

Soluzione

Since your return_val is an unsigned int, you should probably be using strtoul() which has been standard since C89 and is therefore supported by MSVC (whereas strtoll() has only been standard since C99 and is not supported by MSVC).

Your testing of the error conditions is not adequate. You need to set errno to zero before calling the conversion function; you also need to detect whether an error was reported, which is trickier than it seems.

Section §7.20.1.4 'The strtol, strtoll, strtoul, and strtoull functions' of the C99 standard says:

Returns

The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.

You also have to read the look at the value stored in the endptr parameter to the conversion functions to tell that no conversion was performed (as opposed to a valid zero was converted).

If the subject sequence is empty or does not have the expected form, no conversion is performed; the value of nptr is stored in the object pointed to by endptr, provided that endptr is not a null pointer.

So, you must write code more like this (omitting the test against EINVAL because the standard does not mention these functions setting errno to EINVAL):

unsigned int return_val=0;

if (index + 1 <= argc - 1)
{
    char *end;
    unsigned long ul;
    errno = 0;
    ul = strtoul(argv[index+1], &end, 10);
    if ((ul == 0 && end == argv[index+1]) ||
        (ul == ULONG_MAX && errno == ERANGE) ||
        (ul > UINT_MAX))
    {
        fprintf(stderr, "Could not parse argument %s for switch %s!\n",
                argv[index], argv[index+1]);
        return 0;
    }
    retval = (unsigned int)ul;
}

Note that this is simpler than the test for a signed integer conversion which must take into account the negative <type>_MIN limit as well as the <type>_MAX limit.

Also note that you really should record the result in an unsigned long and then check whether it fits within your designated range, which may be limited to UINT_MAX (which can be less than ULONG_MAX in a Unix-like 64-bit environment).

Altri suggerimenti

In Visual studio use _strtoi64() method instead. It has the same parameters as strtoll.

For compatibility you can simply use a define to wrap it as strtoll (if you need portability) such as

#if defined(_MSC_VER)
#define strtoll _strtoi64
#endif

strtol() is the proper library function for a long. For portability, declare return_val as a long or unsigned long. If the latter, see if MSVC offers strtoul().

For your purposes, you should use strtoul, as you are converting to an unsigned long type, not a signed long long type (which is what strtoll would do). If you need to read in long longs, use the Microsoft-specific _strtoi64; you can use #defines to rename it to strtoll on Microsoft platforms, or write a wrapper function in a Windows-specific portability shims file (with your own prototype for it in a private header).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top