Working around the Standard Library

We can't use the >> operator because the implementation of that operator in the C++ standard library stops reading data into a string variable whenever it sees a blank or other “white space” character, rather than only at the end of a line. Therefore, if we tried to use >> to read a line of data such as “3-ounce cups” into m_Name, we would only get the part of it before the first blank. The rest of the data would be left on the input stream for the next read operation to retrieve.

Personally, I think it would be much better for >> to read the whole line into a string and as we'll see, that's how I did it when I implemented my own string class. But, as Bjarne has said, “Victories over the type system of a language are always Pyrrhic victories”. Even though the string class and the rest of the standard library aren't quite an intrinsic part of the C++ language in the sense that the native types are, they are woven tightly enough into the fabric of the language that we should use them unless we have a compelling reason not to do so. In this case, the cure (throwing out the standard library string class) is worse than the disease, so we'll just have to put up with the peculiarities of the standard library even when they make our programs somewhat more complicated.

The next two lines, which read the data from the input stream into m_Instock and m_Price, respectively, aren't anything special; we've seen how we can use >> to read data into numeric variables before. But what does that next line, s.ignore();, do?

This is yet another of the peculiarities of the standard library. You see, when we read data into a numeric variable via the >> operator, that operator stops taking characters from the input stream as soon as it sees a character that doesn't belong in a number, like a space, newline (' '), or alphabetic character. In this case, that character is the newline at the end of the line containing the price. That seems reasonable enough in itself.

However, once it sees that character it doesn't remove it from the input stream, but leaves it there for the next input operator. Therefore, if we didn't take account of this odd behavior, our next input statement, getline(s,m_Distributor);, would see the ' ' as the first character in the input stream and would stop reading at that point. That would leave our m_Distributor variable empty.

In order to get around this problem, we have to use the ignore function to ignore the next character in the input stream after we finish reading the price. This allows the value of the m_Distributor variable to be read correctly from the input stream.

The Second Version of the StockItem Interface

Now that we're finished with that unfortunate complication in our function, there's just one more construct here we haven't seen before: the & in istream&. As soon as we take a look at the new interface to the StockItem class (Figure 6.13), we'll see exactly what that means. I strongly recommend that you print out the files that contain this interface and its implementation, as well as the test program, for reference as you are going through this part of the chapter; those files are item2.h, item2.cpp, and itemtst2.cpp, respectively.

Figure 6.13. The second version of the interface for the StockItem class (codeitem2.h)
class StockItem
{
public:
  StockItem();

  StockItem(std::string Name, short InStock, short Price,
  std::string Distributor, std::string UPC);

  void Display();
  void Read(std::istream& is);

private:
   short m_InStock;
   short m_Price;
   std::string m_Name;
   std::string m_Distributor;
   std::string m_UPC;
};

The &, as used here in the context of declaring an argument to a function, means that the argument to which it refers is a reference argument, rather than a "normal" (value) argument. It's important to understand this concept thoroughly, so let's go into it in detail.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset