2

I'm expecting a single digit integer input, and have error handling in place already if this is not the case. Are the any potential unforeseen consequences by simply subtracting the input character by '0' to "convert" it into an integer?

I'm not looking for opinions on readability or what's more commonly used (although they wouldn't hurt as an extension to the answer), but simply whether or not it's a reliable form of conversion. If I ask the user to input an integer between 0 and 9, is there any scenario in which there can be input that input = input-'0' should handle, but doesn't?

Sellyme
  • 179
  • 1
  • 14
  • I can't think of any, not with the characer encodings in comon use, anyway. – Martin James Jan 07 '18 at 21:51
  • 3
    C guarantees that the chararacters `'0'` to `'9'` are coded consecutively, so yes, subtracting `'0'` will convert a digit character to an integer. – Weather Vane Jan 07 '18 at 21:56
  • Do you care about the scenario where `input` is not a decimal digit? – chux - Reinstate Monica Jan 07 '18 at 22:33
  • @chux That was bad wording on my part, I meant that I'm not preferring one option over another just because it's more common or "the official" version, I'm more concerned with the actual result of what the code does. As for when input is not a decimal digit, are you referring to representation in another base (e.g., hex)? Because that would be invalid input in my use case. – Sellyme Jan 07 '18 at 22:36
  • Sellyme "are you referring to representation in another base". No,I mean that if you ask a user to input an integer between 0 and 9, the user types in a _character_ and code has no control over user's fingers. A user may type `'0'`, `'4'`, `'x'`, `'\0'` either by design or mistake, so `input` may have a wide range of values - expected and unexpected prior to conversion. As [@Stephan Lechner](https://stackoverflow.com/a/48141940/2410359) wisely answered, "as long as you guarantee that `input` contains a digit", else other issues may apply. – chux - Reinstate Monica Jan 07 '18 at 22:43
  • I have error handling in place that checks the character is between '0' and '9', so that's a non-issue. Of course, that does rely on that range actually being what I think it is, but that is the question being asked, after all. – Sellyme Jan 07 '18 at 22:52
  • I hope your "I have error handling in place that checks the character" is correct. Being un-posted - one can only surmise. The reliability you seek with `input = input-'0'` exists - provided prior code handled user input right, error handling/filtering, right types, and how code later uses `input`. It is why good questions usually contain compilable code samples. – chux - Reinstate Monica Jan 07 '18 at 23:02
  • @chux I didn't provide a code sample because I know from fairly extensive testing that my implementation works for everything I need it to work for. My question is about whether or not that is going to hold true for other implementations, since if there's a better way to do it I want to get used to doing that. – Sellyme Jan 07 '18 at 23:16
  • `- '0'` will even work with EBCDIC-based encodings – ikegami Jan 08 '18 at 01:25

2 Answers2

8

This is safe and guaranteed by the C language. In the current version, C11, the relevant text is 5.2.1 Character sets, ¶3:

In both the source and execution basic character sets, the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous.

As for whether it's "bad practice", that's a matter of opinion, but I would say no. It's both idiomatic (commonly used and understood by C programmers) and lacks any alternative that's not confusing and inefficient. For example nobody reading C would want to see this written as a switch statement with 10 cases or by setting up a dummy one-character string to pass to atoi.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
5

The order of characters are encoding/system-dependent, so one must not rely on a particular order in general. For the sequence of digits 0..9 in any system, however, it is guaranteed that it starts with 0 and continues to 9 without any intermediate characters. So input = input - '0' is perfect as long as you guarantee that input contains a digit (e.g. by using isdigit).

Stephan Lechner
  • 34,891
  • 4
  • 35
  • 58