-3

I'm trying to get this input loop to stop if the user enters a space ' ' or enter \n but the space part doesn't seem to work, even when I replace in != ' ' with in != 32 which is the ASCII code for space.

#include<iostream>
using namespace std;

int main()
{
        int temp, cho = 0;
        char in = '0';

        while (in != '\n' && in != ' ')
        {
                in = cin.get();
                temp = in - '0';
                if (temp >= 0 && temp <= 9)
                        cho += temp;
        }
}

Is it even possible to achieve with cin.get() and a console application?

shinzou
  • 5,850
  • 10
  • 60
  • 124
  • Duplicate of http://stackoverflow.com/questions/2765462/how-to-cin-space-in-c – Jay Miller Dec 15 '14 at 22:40
  • Well, you're checking `in` before actually reading it. – Colonel Thirty Two Dec 15 '14 at 22:40
  • 2
    @JayMiller not exactly a dupe. – shinzou Dec 15 '14 at 22:41
  • 1
    @ColonelThirtyTwo what do you mean? – shinzou Dec 15 '14 at 22:42
  • 2
    Yet another duplicate of `if (x != ' ' || y != ' ')`... Related [meta discussion](https://meta.stackoverflow.com/questions/273262/canonical-language-agnostic-question-for-ifvar-x-var-y) –  Dec 15 '14 at 22:46
  • Space is 32, not 38. What does it mean "the space part doesn't seem to work? You probably want a conjunction not a disjunction when testing value but you should describe in you question what you want to happen and what is happening instead: without it is guess work what should happen. – Dietmar Kühl Dec 15 '14 at 22:48
  • @DietmarKühl I want the loop to stop if the user enters an enter or space. – shinzou Dec 15 '14 at 22:54
  • @LightnessRacesinOrbit So it reads `in`, performs the operation, then checks `in`. Presumably, you'd want to check `in` before performing the operation. No need to be rude. – Colonel Thirty Two Dec 15 '14 at 22:57
  • @kuhaku: so remyabel's comment applies (as well as my guess in the comment above). – Dietmar Kühl Dec 15 '14 at 23:01
  • @DietmarKühl: Nice guess! Posted minutes _after_ I wrote the same thing as an actual answer.. hm... Yet, strangely, you did not include me in your list of credits. :( – Lightness Races in Orbit Dec 15 '14 at 23:07
  • @LightnessRacesinOrbit: have an upvote then! (and I didn't see your answer while typing on a mobile phone) kuhaku: ... and, of course, see the answer from Lightness Races in Orbit! – Dietmar Kühl Dec 15 '14 at 23:11
  • Well, your code mostly works by chance (if you apply the fix of using a conjunction instead of a disjunction in the condition checking for [some] spaces). The canonical approach is to first to verify the input was successful. – Dietmar Kühl Dec 15 '14 at 23:20

2 Answers2

8

You actually have three problems here that won't be independently distinguishable from each other to begin with, but which become clear once you apply the reasoning below:


I. Boolean conditional is incorrect

while (in != '\n' || in != ' ')

This is wrong! You probably meant &&.

(A != B || A != C) is always true (assuming B and C are different, as they are in your example) because A cannot possibly equal both of them at the same time.


II. Program logic is in the wrong order

Furthermore, you're checking this in the wrong place. You're doing this:

  • Set input #0 to '0' to get us going
  • Does the input #0 meet my exit criteria? (no)
  • Take input #1
  • Deal with input #1
  • Does the input #1 meet my exit criteria? (no)
  • Take input #2 (say this is a space)
  • Deal with input #2
  • Does the input #2 meet my exit criteria? (YES!)
  • End the loop

You see how you check input #2 too late? It's already been "dealt with". You'll exit the loop just fine after implementing the above fix, but you've already appended the character to cho.

How about this:

int temp, cho = 0;

// Get input for the first iteration
char in = cin.get();

while (in != '\n' && in != ' ')
{
    temp = in - '0';
    if(temp >=0 && temp <=9)//so only the ASCII of digits would be entered
        cho += temp;

    // Now get input for the next iteration
    in = cin.get();
}

The duplication isn't nice, but you can fiddle with it as you please once the logic's correct.


III. Your terminal has line buffering turned on

Finally, even with this code you may experience problems due to line buffering in your terminal: your program will be functioning absolutely correctly, but since your characters are often by default not sent to the program until a whole line is provided, there is no "live"/"instant" reaction to the act of pressing a space. Only once you hit enter are all those characters finally submitted to your program by your terminal, at which point the backlogged spaces trigger the loop exit; this makes it look like your program is only terminating on the newline condition, but it's not. You might have spotted this if you had generated some output from within your program to see how many characters it was actually processing before quitting.

You can resolve this by turning off line buffering in your terminal emulator, or by removing the ability to use spaces to terminate the loop and instead just rely on newlines — the latter is the convention as then you do not have to ask your users to configure their terminal specially to run your program: it'll already function properly in all the usual cases.


Bootnote — general advice

It's important not to assume that, if applying solution A for problem 1 doesn't immediately make your program work perfectly, that solution A must be wrong. You should consider the possibility that you also have as-yet-unknown problems 2 and 3.

It's really important to keep an open mind and gather evidence, such as writing output from your program to track its execution... or use a debugger to step through it and analyse what it is doing. As far as I can tell, you haven't really gathered any evidence at all about how your program executes… beyond cursory empirical observations, that is.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • @kuhaku: It's hard _not_ to think that someone's making stuff up when they post some code and an image of output that literally could not possibly have been generated by that code. That's not my fault. Just sayin'. – Lightness Races in Orbit Dec 15 '14 at 23:35
3

Keeping Lightness's great answer in mind, it should be noted that you're reading a single whitespace-separated token, which the built-in formatted I/O operators already do. For example, operator>>() is designed to pull out a token of input (say a number) until it reaches whitespace which is a space character and newline character.

A cleaner way of doing it would be to use the standard algorithms and classes from the standard library such as std::istream_iterator and std::accumulate():

#include <iterator>
#include <string>
#include <iostream>
#include <numeric>

int main()
{
    typedef std::istream_iterator<std::string> iter_t;
    iter_t it(std::cin);
    int cho(0);

    if (it != iter_t{})
    {
        auto s = *it;
        cho = std::accumulate(std::begin(s), std::end(s), 0,
              [] (int v, unsigned char c) { return v + c - '0'; });
    }
    std::cout << cho;
}

std::istream_iterator uses operator>>() internally and std::accumulate() will go through the characters, convert them to integers, and accumulate their sum.

Community
  • 1
  • 1
David G
  • 94,763
  • 41
  • 167
  • 253
  • Wildly harder to read but, yes, this. When sufficiently commented. – Lightness Races in Orbit Dec 15 '14 at 23:36
  • _"until it reaches whitespace which is a space character and newline character"_ Well, you forgot quite a few characters there! (C++11: 27.7.2.2.3/8, 22.3.3.1/1, 22.4.1.1/2, a sprinkling of luck that the OP's "implementation's native character set" uses the default locale, and then the fact that [`isspace` for the default locale returns `true` for far more than just spaces and newlines](http://en.cppreference.com/w/cpp/string/byte/isspace).) – Lightness Races in Orbit Dec 15 '14 at 23:42
  • @kuhaku You need `` as well. Sorry I thought I added the includes earlier. :) – David G Dec 15 '14 at 23:50
  • After some more googling, looks like `#include ` is needed too. – shinzou Dec 15 '14 at 23:54
  • @0x499602D2: Ah, then you don't need ``. – Lightness Races in Orbit Dec 16 '14 at 00:42