Path: csiph.com!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: scanf used for to get a line Date: Thu, 03 Nov 2016 16:34:54 -0700 Organization: None to speak of Lines: 92 Message-ID: References: <15ea8d6d-0173-491c-b6b5-b1c57dd61769@googlegroups.com> <236c25a6-8c18-4082-ab3a-86eb55fb2408@googlegroups.com> <5e06af91-eec8-42cd-87c4-99d2b448de84@googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: mx02.eternal-september.org; posting-host="6f57f3023f7434c61f7dba030433622e"; logging-data="21859"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+L3u4Ipem4e3uV1w1gFxV1" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) Cancel-Lock: sha1:TeCimyrUThABINk6y2an9U/wAd8= sha1:guIC/OJqGZhKbuGCVXBYEp6CVNE= Xref: csiph.com comp.lang.c:95706 supercat@casperkitty.com writes: >> supercat writes: >> > On Thursday, November 3, 2016 at 11:38:40 AM UTC-5, Keith Thompson wrote: >> >> But be careful. sscanf() has undefined behavior on numeric overflow. >> > >> > If one wanted to write the simplest strictly-conforming program that would >> > e.g. read a line of input from stdin and: >> > >> > 1. If the input contains two signed numbers separated by a space, both >> > within the range of "long long", and their product is also within the >> > range of that type, output their product. >> > >> > 2. In all other cases, output any sequence of 0 to 1,000 characters and >> > exit. >> > >> > How should one make that program most simply? >> >> I'd use strtoll() to parse the numbers. I find its interface a bit >> clunky, but it does let you unambiguously determine whether the numbers >> are in range (you need to set and test errno). > > Before using strtoll, one would need to get the input into a string and > then find where each part starts. No, you just need to get the input into a string (fgets() will do that, or something more sophisticated if you can't place an upper bound on the input line length). strtoll will tell you where in the string the number ends if you ask it to. >> Determining whether their product is representable is a bit tricker, but >> I have no doubt that it's been solved. A Google search for existing >> solutions would probably be faster than writing a solution from scratch. >> I'm not sure why you introduced this irrelevant requirement. > > The main point of the exercise was to process the input safely and without > UB for all cases. The multiply was included to necessitate actually > converting the input to a number (if the code simply had to output the > values that were typed, it could simply echo the input). The language > about the product being representable was to exempt the code from having > to worry about the overflow case beyond preventing UB. You could have just specified storing the input into objects of type long long. Multiplying while avoiding overflow just adds a layer of complexity that wasn't in the original problem. >> I don't know why your requirement #2 is so loose. It's easy enough to >> print, say, "ERROR" on stderr. > > Efficiently detecting the overflow condition requires a bit of code, so I > didn't want to require it. Methods that don't detect the overflow tend to have undefined behavior. strtoll() can reliably detect overflow. >> (Incidentally, I intensely dislike the fact that numeric overflow in >> scanf() has undefined behavior. It's clearly not accidental, but I'd >> love to see it changed in the next edition of the standard. Libraries >> already have to be able to parse numbers while reliably detecting >> numeric overflow; see the strto*() functions.) > > I suspect that dates back to the time when many implementations tried to > implement useful behaviors in many places where the Standard imposed no > requirements. > > It's easy to imagine a version of "scanf" where the variables may be set > to Unspecified (and unpredictable) values if the input is invalid. It's also easy to imagine an implementation that would have an signed integer overflow given an out of range input. Given the age of scanf, I suspect early implementations did that, because they simply ignored the issue of overflow. > It's also not hard to imagine a version of "scanf" which, if input was > coming from a console, might inform the user if an attempt was made to > enter invalid data. Such notification might be done in ways outside the > jurisdiction of the C Standard (triggering a buzzer, for example). That doesn't seem plausible. The idea of treating standard input consistently regardless of where it's coming from is quite old. I don't think even a very old implementation of scanf would have triggered a buzzer on an error. > There only simply way the Standard could allow both of the above was to > make the behavior UB. The first would not qualify as Implementation- > Defined, and the second would not qualify as yielding an Unspecified or > Indeterminate value (because of the side-effect of triggering the buzzer). -- Keith Thompson (The_Other_Keith) kst-u@mib.org Working, but not speaking, for JetHead Development, Inc. "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"