1

Let's say I want to build a printf-like formatter for various values. However, to catch edge cases at the top of my itoa function, I would like to do something like this:

char* itoa(int number) {

    if (num == INT_MIN)
        return INT_MIN_TEXT; // "-2147483648" or whatever it is on that system

    // actual code to do itoa...

}

Or, is even doing something getting a string literal of the limits.h a non-trivial task?

Does a macro have access to the system limits, such as:

// Also should make it 'const' or return a copy.
#define INT_MIN_TEXT ((INT_MIN == -2147483648)? "-2147483648" : "UNKNOWN")
carl.hiass
  • 1,526
  • 1
  • 6
  • 26
  • 2
    1) This sounds like an [XY Problem](https://en.wikipedia.org/wiki/XY_problem). I'm not sure the question you asked is necessarily the best solution for what you're *really* trying to accomplish. 2) [itoa](http://www.cplusplus.com/reference/cstdlib/itoa/) and [sprintf](https://linux.die.net/man/3/printf) and probably the most straightforward ways to "convert an int to a string". 3) The "challenge" is how best to allocate the char[] array for your string, to ensure the memory is a) sufficient, and b) valid upon return from your function. – paulsm4 Mar 21 '21 at 20:58
  • @paulsm4 it's quite helpful, as it makes it so I can handle `INT_MIN` without having to negate the value: https://codereview.stackexchange.com/questions/257428/improving-an-itoa-function. – carl.hiass Mar 21 '21 at 20:59

2 Answers2

2

You can use the preprocessor to evaluate the value of the macros provided by limits.h and convert it to strings as explained here Concatenate int to string using C Preprocessor or here Convert a preprocessor token to a string

Here is the macro declaration:

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

And there how to use it:

#define INT_MIN_TEXT STR(INT_MIN)   // in the code INT_MIN_TEXT
                                    // will be replaced by "-2147483648"

You still need to copy the string to a new memory address before returning it to prevent the caller trying to modifying it.

Orace
  • 7,822
  • 30
  • 45
  • good point about returning a copy about the string! Would you want to post just a very basic example of what you mean with the macro? – carl.hiass Mar 21 '21 at 21:38
1

For whatever it's worth, here is a Linux implementation of itoa. A few significant differences from your version:

  1. It relies on the caller to allocate space for the string (and tell itoa() how much space is available)

  2. It supports multiple radixes (base 10, base 16, etc.)

  3. The return value is a flag (0== succeeded, -1== failed)

  4. Uses strrev() to reverse the string after all digits have been assembled

    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    int
    itoa(int num, unsigned char* str, int len, int base)
    {
        int sum = num;
        int i = 0;
        int digit;
        if (len == 0)
            return -1;
        do
        {
            digit = sum % base;
            if (digit < 0xA)
                str[i++] = '0' + digit;
            else
                str[i++] = 'A' + digit - 0xA;
            sum /= base;
        }while (sum && (i < (len - 1)));
        if (i == (len - 1) && sum)
            return -1;
        str[i] = '\0';
        strrev(str);
        return 0;
    }
    
paulsm4
  • 114,292
  • 17
  • 138
  • 190