

Parsing a string as a 64-bit integer, somehow - ingve
http://blogs.msdn.com/b/oldnewthing/archive/2015/06/29/10624284.aspx

======
TazeTSchnitzel
Why no negative hex?

I'd write something like this:

    
    
      long long parseLongSomehow(char *s) {
          if (isspace(s[0])) {
              return parseLongSomehow(s + 1);
          } else if (s[0] == '-') {
              return -parseLongSomehow(s + 1);
          } else if (s[0] == '0' && s[1] == 'x') {
              return strtoull(s + 2, 16);
          } else {
              return strtoull(s, 10);
          }
      }
    

That doesn't handle negative values smaller than LONG_LONG_MIN gracefully,
though. Also doesn't do error handling.

~~~
userbinator
Recursion is rarely a good idea, especially when doing something that is
intrinsically non-recursive:

    
    
        char *v = malloc(100000000);
        memset(v, '-', 99999999);
        v[99999999] = 0;
        parseLongSomehow(v);
    

What happens?

~~~
duaneb
> Recursion is rarely a good idea

Umm, I really disagree. Recursion and tail-call semantics are enough to make
it equivalent to iteration, except the state is stored in the calls instead of
explicitly outside the loop. What sucks is buggy code that does not handle
cases. Depending on how you view functional languages, for instance, you could
argue that iteration is necessarily implemented with recursion, and not vice-
versa, and that explicit looping is only necessary to serialize it into steps
(instructions).

Nonetheless, with both approaches you need to guard against multiple negative
signs. Not much to do with recursion. His approach would have been fine if he
had a signed? flag.

~~~
userbinator
Observe that in this case, the difference between a non-tail call and a tail-
call is a single '-'! If the compiler does tail-call optimisation, then the
function can consume an unbounded amount of leading spaces, yet a large amount
of leading '-' would overflow the stack. If it doesn't, then lots of leading
spaces will also overflow. This is not what I'd consider obvious and intuitive
behaviour if you were black-box testing this function.

There is a reason why high-reliability coding standards forbid or severely
restrict recursion. It's difficult to reason about the resource usage of
recursive code, and it also leads to non-obvious failure modes like this.

~~~
duaneb
Well, obviously the - is a base case and should be removed from successive
recursions.

And I don't think it is difficult to reason about resource usage. Tail-calls
are very intuitive. Some languages (e.g. scala) allow you to force a call to
be a tail call (or fail with an error).

I suspect that preferring explicit over implicit is why coding standards
forbid recursion. However, many algorithms become straight-up awkward when
having to manipulate the "call stack" manually: see traversal of graphs.

Finally, what you were really complaining about was the fact that he didn't
handle multiple dashes. It has very little to do with recursion, which is just
a different way to fold the same semantics you'd still have wrong with an
iterative version. It would never overflow the stack because why would you
accept unlimited minuses? You're not evaluating an expression, you're parsing
a known format and can fail fast.

------
yaur
> return (long)ulong.Parse(s);

Why on earth would you do this instead of just letting the underlying library
call throw? Note that it will still throw for strings that parse to a value
that cant fit into a long/unsigned long.

