Live data from Hacker News

No way to parse integers in C (2022)

blog.habets.se

91–100 of 117 posts

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

#91
The problem is that float parsing is highly non-trivial if you want it to be correct for all edge cases.

For integers, you're faster (in both development time and runtime) to write your own parser than to try and assemble the pieces in this pile of shit into a half-working one.

C++17 from_chars excluded. Incidentally, 2022 seems about right for the year that ONE open source implementation finally actually implemented the float part of that. Or was it more like 2024?

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

#92

Earlier quoted context omitted.

Crashing (in the sense of "give up and exit with an error") on invalid inputs is valid (and often the best thing) in many cases. Fix your inputs.

I think you're using "crash" to mean "exit early". I am using "crash" in the sense of "this program did something causing the OS to terminate it externally". I suppose that's a real point of difficulty in communication across different programming languages. We agree that the program should exit early. I think we agree it should do it cleanly and intentionally. I'm adding the constraint that "crash" doesn't necessari…

There's a position in between "exit cleanly" and "general protection fault, core dumped" where the process essentially does the internal equivalent of SIGKILLing itself.

I.e. either intentionally (e.g. tripping an assertion failure), or accidentally due to some logic-failure in exception/error-handling, the process ends up calling the exit(3) syscall without first having run its libc at_exit finalizers that a clean exit(2) would run; or, at a slightly higher runtime abstraction level, the process calls exit(2) or returns from main(), without having run through the appropriate RAII destructors (in C++/Rust), or gracefully signalled will-shutdown to managed threads to allow them to run terminating-state code (in Java/Go/Erlang/Win32/etc), or etc.

This kind of "hard abort" often truncates logging output at the point of abort; leaves TCP connections hanging open; leaves lockfiles around on disk; and has the potential to corrupt any data files that were being written to. Basically, it results in the process not executing "should always execute" code to clean up after itself.

So, although the OS kernel/scheduler thinks everything went fine, and that it didn't have to step in to forcibly terminate the process's lifecycle (though it did very likely observe a nonzero process exit code), I think most people would still generally call this type of abort a "crash." The process's runtime got into an invalid/broken state and stopped cleaning up, even if the process itself didn't violate any protection rules / resource limits / etc.

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

#93

There's no one correct way to parse integers. Do you want to support 0x prefixes? Is a leading zero an indicator or octal, a zero-padded decimal, or a syntax error? Are you willing to accept a leading "+"? Are leading whitespaces OK? Trailing ones? Is 0x0c a whitespace? What about all the weird Unicode ones? Do you allow exponential notation (1e1)? Etc, etc. In every language, the standard library makes some assumpti…

> There's no one correct way to parse integers.

No, but there are a myriad of incorrect ways and the C library's way is one of them.

It's perfectly fine to make reasonable choices for all those options and then implement them correctly.

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

#94

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.

Here's a readability tip for working with ASCII numbers: Treat adding and subtracting the ASCIIness as you would multiplying and dividing by a unit in physics. You can add '0' to convert a numeral to ASCII and subtract '0' to convert it back, and you can do direct comparisons between ASCII numerals. if(characters[i] = '0') { ret = ret * 10 + characters[i] - '0'; }

[deleted]

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

#95

I wasn't in this class myself, but one prof at my alma mater started his "Programming 201" class with the simplest assignment: write a C program that accepts two integers from the user and prints their sum. It actually was the only assignment for the rest of the semester, since he has a test suite that would humiliate the students gently at first, but would ultimately pipe a billion nines into stdin as the first argu…

It's a little awkward, because you'd need to parse the strings in reverse, but if all you need to do is sum, you can do it one digit at a time, while at any given moment only handling only one character from each input string, a carry byte, and one output character.

You don't need to parse the strings in reverse. That's for printing integers, not parsing. Roughly:

    int stdin_atoi() {
      int i = 0;
      while (1) {
        int c = getchar();
        if (c >= '0' && c 

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

#96
post #95

Earlier quoted context omitted.

It's a little awkward, because you'd need to parse the strings in reverse, but if all you need to do is sum, you can do it one digit at a time, while at any given moment only handling only one character from each input string, a carry byte, and one output character.

You don't need to parse the strings in reverse. That's for printing integers, not parsing . Roughly: int stdin_atoi() { int i = 0; while (1) { int c = getchar(); if (c >= '0' && c

That covers the ‘int’ case, but not the ‘integer’ case described. Unless you have unlimited memory, you’ll need to go least- to most-significant digit; but you’ll need to do that on both inputs, which doesn’t really work with the interface described unless at least the first argument first in memory all at once, so… well, I assume “I under specified this problem and it’s impossible” is the point of this sort of exercise.

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

#97
post #27

One of the first homework assignments when I learned C back in '83 was after a long lecture on how the string functions are fundamentally broken, and the class introduction to writing C was fixing all of them.

My memory growing up is that making your own C library was basically an inevitable rite of passage for any aspiring programmer.

And then your own custom allocator that would be fitted for your algorithms and vastly faster than malloc.

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

#98
post #86

Earlier quoted context omitted.

Fair enough. For strtoul and friends, maybe? 7.24.1 is pretty dense, but the key parts are "the expected form of the subject sequence is a sequence of letters and digits representing an integer with the radix specified by base, optionally preceded by a plus or minus sign […] If the correct value is outside the range of representable values […] ULONG_MAX […] is returned". So the "expected form" allows a minus sign, bu…

Passing a negative value to a function that is specifically for converting strings into unsigned numbers is pretty much an error. In the case of functions that return an unsigned number, at least, negative return values can represent errors. It’s more fun when the result can be signed though. Maybe strcmp with the representation of the LONG_MAX, and if it doesn’t match, call strtol and watch for a LONG_MAX indicating…

If that's an error then so is passing in a non number.

So catch 22. You can only check for valid numbers if the number is valid?

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

#99

Earlier quoted context omitted.

Crashing (in the sense of "give up and exit with an error") on invalid inputs is valid (and often the best thing) in many cases. Fix your inputs.

I think you're using "crash" to mean "exit early". I am using "crash" in the sense of "this program did something causing the OS to terminate it externally". I suppose that's a real point of difficulty in communication across different programming languages. We agree that the program should exit early. I think we agree it should do it cleanly and intentionally. I'm adding the constraint that "crash" doesn't necessari…

Interesting difference in nomenclature. For me, "crash" absolutely includes intentional early termination. A Rust panic, for example.

I think that that's by far the dominant usage of crash. It would surprise me if someone used the word crash but intended to exclude panics, etc.

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

#100
post #89

Earlier quoted context omitted.

It's a little awkward, because you'd need to parse the strings in reverse, but if all you need to do is sum, you can do it one digit at a time, while at any given moment only handling only one character from each input string, a carry byte, and one output character.

How do you know where the first string ends and the second starts? Did you miss the "stdin" part? This is not ./program first_number second_number

Of course the method described requires both input and output buffers, because everything is processed last-character-first.

Now that you mention it, if the assignment had called for arguments, instead of files or pipes, argv points to a writable array, so the result could be written directly to it, negating any need to allocate memory, and any out-of-memory conditions from large input data would occur before the program is even called.

If it usually uses a file to store the numbers, the same could be done by writing the result back to the file, but that only works if it is passed as an argument, as piping it would throw a seek error. I wonder if the instructor would accept an interleaved little-endian input syntax, with a little-endian output; then the program could use pipes without a need to seek. An infinite series of '9' characters would output an '8', followed by one '9' per two input characters.

Post reply on HN