Search code examples
c++stringloops

Using a subscript for random access c++ primer 2013


Recently, I've been trying to learn C++, and I've been following this book my friends recomended, which is "C++ Primer, 5th Edition". In it, there is the following code:

const string hexdigits = "0123456789ABCDEF"; // possible hex digits
cout << "Enter a series of numbers between 0 and 15"
    << " separated by spaces. Hit ENTER when finished: "
    << endl;
string result; // will hold the resulting hexify’d string
string::size_type n; // hold numbers from the input
while (cin >> n)
    if (n < hexdigits.size()) // ignore invalid input
        result += hexdigits[n]; // fetch the indicated hex digit
cout << "Your hex number is: " << result << endl;

I've been breaking my brain and trying to figure out how to make it work.

I have two problems with this code, both are related to the "\\n" or end of line with cin.

  1. How do I make the "hit ENTER when finished" work, so that when I do 2 12 3 4 ENTER it breaks from the while loop?

  2. How do I check if the very first thing I do is click Enter and not enter the loop (basically, how do I check that the first thing entered isn't a new line, and if it is to skip the whole process)?

Maybe what I'm asking is so simple, but I swear I can't get my head around it.

I've tried things like cin.peek() and cin.get(), but then it's more complicated to still read after them.

With the first option, I've tried this:

cin >> n;
while (n < hexdigits.size()) {
    result += hexdigits[n];
    if (cin.peek() == '\n') {
        break;
    }
    else {
        cin >> n; // Read the actual input if not ENTER
    }
}

Which works, but I think it's quite ugly, and I want to know if there is another way of doing things.

EDIT: So ive been trying a few things and reading a bit more about how cin does things, and ive come up with this solution that fixes both,Solution also gave by PookyFan in comment. My solution:

const string hexdigits = "0123456789ABCDEF"; 
cout << "Enter a series of numbers between 0 and 15"
<< " separated by spaces. Hit ENTER when finished: "
<< endl;
string::size_type n; 
string result;
  while (cin.peek() != '\n'){
    cin >> n;
    if (n < hexdigits.size()) {
        result += hexdigits[n];
    }
}
cout << result;

Solution

  • Your solution is correct and not that ugly at all, though this else at the end is not necessary (if we break from the loop, we will not reach the else part anyway). You may further prettify your code by, for example, using do...while loop instead (so that you don't have to have cin >> n; twice, but only once at the start of the loop), but this is a minor detail.

    The reason you can't retrieve Enter as new line character up straight is because the stream performs some internal parsing which results in (among other actions) dropping the newline character at the end of the input in the process of eliminating leading whitespaces. This is apparently just how operator >> is implemented for standard input stream. You can read more about it here.