1

Need to convert string into unsigned int in C. I've tried using sscanf() and strtoul(), but both of them on inputting negative digits like -123 inverts them and do not signals about error.

I mean, that strtoul(-1) will return UNSIGNED_INT_MAX - 1 and not an error.

I need something that will do so:

"123" - fine

"-123" - wrong

"wewe" - wrong

"123wew" - wrong

PinkiNice
  • 1,455
  • 2
  • 13
  • 19
  • The `endptr` parameter of `strtoul` will point to the first character in the string that isn't part of a valid unsigned integer constant; if it's not whitespace or `0`, then the input is invalid. – John Bode Dec 10 '15 at 16:07
  • 4
    This is not a good duplicate. The OP wants a conversion to *unsigned*. This is not as simple as it looks. I think you can use `strtoul` and check if the result (an `unsigned long`) can fit into an `unsigned`. – Bathsheba Dec 10 '15 at 16:07
  • Just to add, if you want something _very specific to your needs_, you better roll out your own function. Most of the library functions are targeted to be generic, you know. :) – Sourav Ghosh Dec 10 '15 at 16:22
  • 2
    I don't understand why this question was downvoted. Converting into an unsigned int *and throwing an error if a '-' is present* is not trivial and I don't see an obvious duplicate. The OP has clearly stated his question and clarified with examples and what he's tried to do. This is a valid question that can help future users. – Samidamaru Dec 10 '15 at 16:25
  • What result did you want should the string have leading spaces? – chux - Reinstate Monica Dec 10 '15 at 17:07
  • 1
    @chux Spaces before first digits should be OK, because in this case the number still can be allocated definitely. – PinkiNice Dec 11 '15 at 17:39
  • Note that selected answer will not accept leading spaces. (Nor a `'+'`) – chux - Reinstate Monica Dec 11 '15 at 17:52
  • @chux My problem is specific at this point. If someone will look here searching for solving negative digit transformation, he just need to understand, that there is no such function. And the solve is to check string on unacceptable symbols. And do not waste time looking for a premade function :) – PinkiNice Dec 11 '15 at 22:49

4 Answers4

7

You could try checking all the individual characters of the string to assure that they are digits (isdigit() is your friend) - and then if this passes, calling strtoul. Some may argue that you could do a regexp call or something instead - but at the end of the day something is going to have to do this check.

unsigned int convert(char *st) {
  char *x;
  for (x = st ; *x ; x++) {
    if (!isdigit(*x))
      return 0L;
  }
  return (strtoul(st, 0L, 10));
}

(I "return zero" if the string is invalid - you'll have to change the behavior to your liking")

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Brad
  • 11,262
  • 8
  • 55
  • 74
2

In order to get an error return value from a function aswell as an unsigned int, you can do something like the following. The code is self explanatory.

#include <stdio.h>  
#include <stdlib.h> 

int atoui(char *in,unsigned int *out);

int main() 
{
    char str[4][7] = {{"123"},
                  {"-123"},
                  {"wewe"},
                  {"123wew"}};
    unsigned int ui,
             uc;

    for(uc = 0; uc < 4; uc++)
        if(atoui(str[uc],&ui))  printf("ERROR: %s\n",str[uc]);
        else printf("OK: %u\n",ui);

return 0; 
}

int atoui(char *in,unsigned int *out) 
{
    char *p;

    for(p = in; *p; p++) 
        if (*p > '9' || *p < '0') 
            return 1;

    *out = strtoul(in, NULL, 10);
return 0;
}
1

strtoul will set endptr to point to the first non-digit character in the input string; however, it doesn't catch the sign (because, after all, you are allowed to write unsigned int x = -1;).

So you'll have to do this in two stages; first, you'll have to look for the leading -; if you don't find it, use strtoul to do the conversion and check endptr:

char input[N];
char *p;

while ( fgets( input, sizeof input, input_stream ) )
{
  p = input;
  while ( isspace( *p ) ) // skip over any leading whitespace
    p++;

  if ( !isdigit( *p ) )
  {
    printf( "\"%s\" is not a valid unsigned integer string\n" );
  }
  else
  {
    char *endptr;
    unsigned int val = (unsigned int ) strtoul( p, &endptr, 0 );
    if ( isspace( *endptr) || *endptr == 0 )
      printf( "\"%s\" is a valid unsigned integer string: %u\n", val );
    else
      printf( "\"%s\" is *not* a valid integer string\n" );
  }
}      
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

Simply look for a '-', then call strtoul().

unsigned long PN_strtoul(const char *s, int *fail) {
  *fail = strchr(s, '-') != NULL;
  char *endptr;
  errno = 0;
  unsigned long ul = strtoul(s, &endptr, 10);
  // overflow? no conversion? trailing junk?
  if (errno || endptr == s || *endptr) *fail = 1;
  return ul;
}

This way, leading spaces and '+' are still allowed.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256