0

I tried using all these flags ld li and lu with sscanf but none worked. The following gets 4294967295 no matter what number i put in buf:

long unsigned data;
char buf[40] = "data 2349872764943587";

if (sscanf (buf, "data %lu", &data) == 1)
{
    printf ("%s\n", buf);
    printf ("data:\t%lu\n", data);
}

Output:

data 2349872764943587
data:   4294967295

Am I using the wrong conversion flag or is there something I missed?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
razz
  • 9,770
  • 7
  • 50
  • 68
  • use `long long unsigned` – BLUEPIXY Jan 20 '16 at 13:35
  • Mind that a long unsigned int is a 32 bit data type, with the maximum of 4294967295? – Magisch Jan 20 '16 at 13:35
  • check `sizeof(unsigned long)`. maybe you need `unsigned long long.` – Sourav Ghosh Jan 20 '16 at 13:35
  • 1
    My guess is that `long`s are only 32 bits on your platform. Use `uint64_t` instead to eliminate this possibility. – Paul R Jan 20 '16 at 13:35
  • 2
    The size of `long` depends on compiler and platform. On e.g. Windows 64-bit using the Visual Studio compiler `long` is *still* 32 bits. You should use `unsigned long long` (or `uint64_t`) and corresponding formats (for which you could see e.g. [this `printf` reference](http://en.cppreference.com/w/c/io/fprintf) or [this `scanf` reference](http://en.cppreference.com/w/c/io/fscanf)). – Some programmer dude Jan 20 '16 at 13:35
  • 1
    @Magisch: That is not necessarily true. E.g. POSIX64 is LP64. – too honest for this site Jan 20 '16 at 14:46

4 Answers4

2

OP's unsigned long appears to be a 32-bit and so cannot represent the 51-bit 2349872764943587.

If stuck using a compiler that lacks 64-bit integers, code could use double, which typically handles 53-bit whole number values without loss of precision.

double data;
char buf[40] = "data 2349872764943587";

if (sscanf (buf, "data %lf", &data) == 1)
{
    printf ("%s\n", buf);
    printf ("data:\t%.0f\n", data);
}

Output

data:   2349872764943587
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • printf complains about `ISO C90 does not support the '%lf' gnu_printf format [-Wformat=]`, however it works when i replace the `%0.lf` with `%0.f`. thanks :) – razz Jan 20 '16 at 16:10
  • 1
    @razzak Yes - older compiler do not accept the `l` in printf formats. Newer compilers (C99) simply allow it and ignore it. Answer amended. – chux - Reinstate Monica Jan 20 '16 at 16:48
1

Your data type long unsigned is only guaranteed to be 32 bits in size, so the max value it can hold is 4294967295, which you are getting.

Use a unsigned long long instead.

Magisch
  • 7,312
  • 9
  • 36
  • 52
  • It's saying `error: ISO C90 does not support long long` – razz Jan 20 '16 at 13:39
  • 1
    @razzak why are you compiling under ISO C90 standard? try the compiler option, `-std=c99` to compile under a standard that supports this. – Magisch Jan 20 '16 at 13:41
1

It appears, in your case, unsigned long occupies 4 bytes hence is not able to hold 2349872764943587 which takes more that 32 bits to be stored.

You can use unsigned long long (check the size using sizeof, need to be 8) or uint64_t instead.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

For portability, avoid using int, long, etc. In your platform, for example, long unsigned int is 32 bits, which is why you have your problem.

Instead, #include <stdint.h> then use standard types, such as int32_t, int64_t, uint32_t, uint64_t. In your particular case, uint64_t does the trick.

To use uint64_t data; in printf and scanf, you need to #include <inttypes.h> and then printf("%" PRIu64 "\n", data);

More info here.

Community
  • 1
  • 1
BlueMoon93
  • 2,910
  • 22
  • 39