Path: csiph.com!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c++ Subject: Re: rational numbers Date: Thu, 23 Sep 2021 19:35:34 -0700 Organization: None to speak of Lines: 154 Message-ID: <87v92qlmyx.fsf@nosuchdomain.example.com> References: <87zgs2lubf.fsf@nosuchdomain.example.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Injection-Info: reader02.eternal-september.org; posting-host="cb76b4cf9eef9ed26a2d895456785e0e"; logging-data="732"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX185a79wTbbdhKutlgIpNdSx" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.2 (gnu/linux) Cancel-Lock: sha1:lAzBkNnypglOobiZJRvH1nDCuFA= sha1:gW2VuDmRHnfKJAAEdSyLEHBJLfQ= Xref: csiph.com comp.lang.c++:81497 Bart writes: > On 24/09/2021 00:56, Keith Thompson wrote: >> Bart writes: > >>> * It's not line-oriented; the new lines get out of sync with the data >>> being read >> Right, it's not designed to be. For example: >> int a, b, c; >> std::cin >> a >> b >> c; >> std::cout << "a=" << a << " b=" << b << " c=" << c << '\n'; >> The std::cin line reads integer values, skipping white space (which >> includes newlines) before each. If you just want to skip white space >> other than newlines, there's probably a way to do that. >> If you want line-oriented input, read a line at a time using >> std::getline() and then parse each line. It's not that hard. >> std::string line; >> std::getline(std::cin, line); >> std::stringstream ss(line); >> ss >> a >> b >> c; > > Thanks at last somebody posted some actual code instead of just saying > how easy it was. But a couple of things: > > * (It needs #include ) Yes? > * If I put this in my loop, and type 10 20 30 on the first line, it > prints 10 20 30; that's fine. > > * But if I type only 40 on the next line, it prints 40 20 30. So if > there are fewer entries than expected, it will not do '>> b >> c'; > those values are unchanged from before. My quick and dirty code sample didn't check for errors. The user didn't provide inputs for those values. What exactly do you expect to happen? You can query ss.good(), ss.bad(), ss.fail(), and ss.eof() to see whether the input operation succeeded. > * It's better behaved as it doesn't try to exhaust the same line over > again. But if the input is '10.2 11 12', the output is '10 0 > 999'. (The 999 is what I've now initialised a,b,c to at the start of > each loop.) > > >>> * If fewer than 3 items are present on a line, then it apparently >>> hangs, with no explanation, waiting for them on the next line >> Because it's not line-oriented. > >> Because it's not line-oriented. > >> Because it's not line-oriented. > > Isn't that what I said? My point is that you complained that it's not line-oriented (which is a deliberate design decision) and then complained about the inevitable consequences of the fact that it's not line-oriented. >>> * Numeric separators within numbers such as "_" and "'" are not >>> recognised, and cause an error >> Right. Just how permissive do you think it should be? > > For interactive user input - quite permissive. People are quite likely > to type in decimal points or do unexpected things. A full treatment is > hard, but if someone types "100." or 1e2 instead of "100", should that > be a hanging offence? Hanging offence? Give me a freaking break. Numeric input has to define *some* syntax. If you want a different syntax, implement it. That includes deciding what an integer should be set to if the input is "1.5". If you like, read it into a string and try converting that string to whatever you want. The default input for numeric input is reasonably simple and straightforward. >>> * Numbers which are quoted are not recognised, and cause an error >> Right. 123 is a number; "123", “123”, '123', and «123» are not. > > If you are reading CSV files and such, fields are sometimes enclosed > in quotes, including numeric fields. > >>> * When an out-of-range number is entered, it reads i32.max (etc) for >>> that number, but also generates an error >> Yes, and? > > That error is the problem. What? You're not suggesting that it should set the value to INT_MAX *and then not give any indication that there was a problem*, are you? >>> * I mentioned error a few times, when that happens, it goes crazy. I >>> think the internal pointer is not stepped past it, and it just reads >>> zeros, so it never consumes the rest of the line. So in a loop, it >>> just prints zeros over and over again without the user entering >>> anything. >> It's difficult to respond to that without an example. > > I thought I posted it earlier. Here's the code: > > #include > > int main() > { int a,b,c; > int x=0; > do { > std::cout << "Prompt> "; > std::cin >> a >> b >> c; > std::cout << a << " " << b << " " << c << "\n"; > } while (++x<10); > } > > And here it is in action; the only input I type in is the '10.2 11 12' > line, the rest just keeps going, and only stops because I cap the > output at 10 lines: > > C:\c>a > Prompt> 10.2 11 12 > 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 > Prompt> 10 0 0 The first << operation succeeded, set a to 10, and consumed the characters '1' and '0'. The second one failed because it was trying to read an integer value and saw a '.' character. Try reading an integer again, and it fails again. If you instead tried to read a string or a character, it would consume the '.' character and whatever follows it. If you want to consume and discard incorrect input rather than letting it remain in the input stream, you can do that by writing different code. If you do something simple like `std::cin >> a >> b >> c`, it doesn't give you a way to determine which input operation failed -- but you can tell whether they were all successful or not. Sometimes that's good enough. If it isn't, write different code. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com Working, but not speaking, for Philips void Void(void) { Void(); } /* The recursive call of the void */