Live data from Hacker News

No way to parse integers in C (2022)

blog.habets.se

11–20 of 117 posts

Re: No way to parse integers in C (2022)

#11

As a C programmer, I find this kind of bad faith article very irritating. Yes, the standard library is bad. This is by far the worst part of the C legacy. But it is not that hard to write your own. String functions like this are not difficult at all, and you can use better naming and semantics, write faster code etc. C is not the C standard library, ffs.

Exactly. A wrapper that handles all of the edge cases properly and gives proper reporting just gets added to your own library of functions and the devs get used to using it. Much like the code for abstract data types like lists/hashmaps/etc which neither C nor the standard libraries provide.

Bonus points for having bespoke linting rules to point out the use of known “bad” functions.

In one old project we went through and replaced all instances of sprintf() with snprintf() or equivalent. Once we were happy that we’d got every occurrence we could then add lint rules to flag up any new use of sprintf() so that devs didn’t introduce new possible problems into the code.

(Obviously you can still introduce plenty of problems with snprintf() but we learned to give that more scrutiny.)

Re: No way to parse integers in C (2022)

#12
Why not look at how other languages attack this? e.g. how does "42".parse() work in rust?

Edit: https://doc.rust-lang.org/src/core/num/mod.rs.html#1537

interesting! It boils down to this

pub const fn from_ascii_radix(src: &[u8], radix: u32) -> Result {

    use self::IntErrorKind::*;

    use self::ParseIntError as PIE;

    // guard: radix must be 2..=36

    if 2 > radix || radix > 36 {

        from_ascii_radix_panic(radix);

    }

    if src.is_empty() {

        return Err(PIE { kind: Empty });

    }

    // Strip leading '+' or '-', detect sign

    // (a bare '+' or '-' with nothing after it is an error)

    // accumulate digits, checking for overflow

    Ok(result)

}

Re: No way to parse integers in C (2022)

#13
Can't you regex that given string contains just numbers and then use any of the provided methods? Then check if the returning value is a number to cater for edge cases

Ok, having a method to do that for you would be nice, but the post reads like it's an issue that std library doesn't provide you with a method behaving as you exactly want

Re: No way to parse integers in C (2022)

#14
post #10

Cant you just: for(int i = 0; i = 0) { ret = ret * 10 + characters[i] - 48; } else { return ERROR; } } return ret; Adjust until it actually works, but you get the picture.

And how does this avoid returning nonsense if the number is too large? (Wrapping if the accumulator is unsigned, straight to UB land if signed.) Not reporting overflows as errors is one of the major problems demonstrated by TFA.

you could check if ret > ret * 10 + characters[i]-48, if so it has wrapped around and you return an error

Re: No way to parse integers in C (2022)

#15

Cant you just: for(int i = 0; i = 0) { ret = ret * 10 + characters[i] - 48; } else { return ERROR; } } return ret; Adjust until it actually works, but you get the picture.

this wouldn't catch overflow or underflow errors, nor does it allow non-base-10 numbers, nor does it handle negative numbers. and writing your own parser is a failure case by op's logic. they are complaining about the builtin parsing functions.

the author admits you can parse signed integers in their second example, but for unsigned, they don't like seem to like that unsigned parsing will accept negative numbers and then automatically wrap them to their unsigned equivalents, nor do they like that C number parsing often bails with best effort on non-numeric trailing data rather than flagging it an error, nor do they like that ULONG_MAX is used as a sentinel value by sscanf.

I'm not sure what they mean by "output raw" vs "output"

    $ cat t.c
    
    #include 
    #include 
    #include 
    
    int main(int argc, char \* argv){
    
      char * enda = NULL;
      unsigned long long a = strtoull("-18446744073709551614", &enda, 10);
      printf("in = -18446744073709551614, out = %llu\n", a);
      
      char * endb = NULL;
      unsigned long long b = strtoull("-18446744073709551615", &endb, 10);
      printf("in = -18446744073709551615, out = %llu\n", b);
      
      return 0;
    }
    $ gcc t.c
    $ ./a.out 
    in = -18446744073709551614, out = 2
    in = -18446744073709551615, out = 1
    $
I get their "output raw" value. I don't know what their "output" value is coming from.

I don't see anywhere they describe what they are representing in the raw vs not columns.

Re: No way to parse integers in C (2022)

#16

As a C programmer, I find this kind of bad faith article very irritating. Yes, the standard library is bad. This is by far the worst part of the C legacy. But it is not that hard to write your own. String functions like this are not difficult at all, and you can use better naming and semantics, write faster code etc. C is not the C standard library, ffs.

The thing I find irritating is all the folks who say C is broken because it’s not a write once run anywhere language like JavaScript or python. Part of the deal has always been that the programmer needs to understand the target platform and the target compiler’s behavior.

Re: No way to parse integers in C (2022)

#17
post #11

As a C programmer, I find this kind of bad faith article very irritating. Yes, the standard library is bad. This is by far the worst part of the C legacy. But it is not that hard to write your own. String functions like this are not difficult at all, and you can use better naming and semantics, write faster code etc. C is not the C standard library, ffs.

Exactly. A wrapper that handles all of the edge cases properly and gives proper reporting just gets added to your own library of functions and the devs get used to using it. Much like the code for abstract data types like lists/hashmaps/etc which neither C nor the standard libraries provide. Bonus points for having bespoke linting rules to point out the use of known “bad” functions. In one old project we went through…

> like lists/hashmaps/etc which neither C nor the standard libraries provide

There is a hashmap implementation though: https://man7.org/linux/man-pages/man3/hsearch.3.html

Re: No way to parse integers in C (2022)

#20

Cant you just: for(int i = 0; i = 0) { ret = ret * 10 + characters[i] - 48; } else { return ERROR; } } return ret; Adjust until it actually works, but you get the picture.

What if the number you want to return just happens to be the value of ERROR? You need an error flag that can't be represented as an int, but then C wouldn't let you return it from a function that only returns "int". It is why some languages throw exceptions and why databases have the special "null" value.
Post reply on HN