1

I am following along the great book C++17 by Example, which introduces C++17 by showcasing a series of mini projects -- very cool.

However, in chapter 2, where a Set is implemented on top of a LinkedList, there is this code:

void Set::read(std::istream& inStream) {
  int size;
  inStream >> size;

  int count = 0;
  while (count < size) {
    double value;
    inStream >> value;
    insert(value);
    ++count;
  }
}
void Set::write(std::ostream& outStream) {
  outStream << "{";

  bool firstValue = true;
  Iterator iterator = first();

  while (iterator.hasNext()) {
    outStream << (firstValue ? "" : ", ") << iterator.getValue();
    firstValue = false;
    iterator.next();
  }

  outStream << "}";
}
int main() {
  Set s, t;

  s.read(std::cin);
  t.read(std::cin);

  std::cout << std::endl << "s = ";
  s.write(std::cout);
  std::cout << std::endl;

  std::cout << std::endl << "t = ";
  t.write(std::cout);
  std::cout << std::endl << std::endl;

  // snip
}

I am fairly new to C++, and I do not know how to run this. Of course, I did some research before asking, but the way I came up with does not produce the expected results:

lambdarookies-MacBook:02-the-set-class lambdarookie$ ./02-the-set-class
1 2 3
3 4 5

s = {2}         // Expected: s = {1, 2, 3}
t = {3, 4, 5}

Now I am wondering:

  • Is this simply not the right way to supply arguments, or
  • it is the right way, and the bug must be elsewhere in the code?
Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
typeduke
  • 6,494
  • 6
  • 25
  • 34
  • 1
    Sorry to have to say it, but the book looks crappy. I hate seeing code like "inStream >> size;" with no error checking... at the very least it should be saying "assert(inStream >> size);" (you'd need to #include ` atop your file too), so it stops when it can't read what's expected. There're also standard function names for reading into a class (namely `operator>>`), and writing out - perhaps the book is leaving introducing them until later, but that's a bit sad. When streaming single characters, it's more efficient to use single quotes, e.g. `outStream << '}';` – Tony Delroy May 26 '19 at 17:54
  • 1
    And `int count = 0; while (count < size) { ... ++count; }` is better written as `for (int count = 0; count < size; ++count) { ... }` so all the control logic is in one place to see/understand/maintain. – Tony Delroy May 26 '19 at 17:57
  • @TonyDelroy Obviously, I am not in the position to be judging the book. I will, however, keep an eye out regarding whether the code will be refined in the way you recommend. To be fair, there is a chapter that introduces an "advanced" set implementation, to which I haven't gotten yet. That said, I am always thankful for book recommendations. However, I do kind of insist on the "by example" part -- I really think that dry language introductions that do not take the reader by the hand and guide them through sample projects are not worthwhile. – typeduke May 26 '19 at 18:04
  • all fair - I couldn't recommend such an introductory book myself (I used "The C++ Programming Language" decades years ago, but was already a C programmer), but SO users seem to maintain a [list of recommendations here](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list/388282#388282). Best of luck. – Tony Delroy May 26 '19 at 18:07
  • @TonyDelroy -- it absolutely should **not** be `assert(inStream >> size);`. That suggests that the extraction is used only for testing, and that the code would work correctly without it. – Pete Becker May 26 '19 at 20:53
  • @PeteBecker: very true for `assert` from ``. I tend to use a custom `ASSERT()` macro a lot that always runs - overlooked that crucial difference here :-(. Thanks! – Tony Delroy Feb 23 '20 at 14:26

1 Answers1

4

The first number Set::read reads is the size of the set. Then it reads that many numbers, and adds them to the set. The rest of the line is ignored by the current invocation of read, and is picked up by the next one, which is, by coincidence, the size of the next set you are testing with. Therefore, inputting 1 2 3 results in a set of size 1, with the only elem 2.

Please note: hasNext is a java-ism, unlike how the usual C++ iterators work. Perhaps you could consider also taking a look at a different manual.

erenon
  • 18,838
  • 2
  • 61
  • 93
  • 1
    @TonyDelroy Yes, I just noticed that. This confused me even more. I asked myself: "Why does it work for `t` but not for `s`?" But thank you for clarifiying! – typeduke May 26 '19 at 17:53