Читаем Thinking In C++. Volume 2: Practical Programming полностью

This is notably tedious and doesn’t seem like much of an improvement over printf( ), despite improved type checking. Fortunately, the overloaded inserters and extractors are designed to be chained together into a more complicated expression that is much easier to write (and read):.

  cout << "i = " << i << endl;

  cout << "f = " << f << endl;

  cout << "c = " << c << endl;

  cout << "buf = " << buf << endl;

Defining inserters and extractors for your own classes is just a matter of overloading the associated operators to do the right things, namely:

·         Make the first parameter a non-const reference to the stream (istream for input, ostream for output)

·         Perform the operation by insert/extracting data to/from the stream (by processing the components of the object, of course)

·         Return a reference to the stream

The stream should be non-const because processing stream data changes the state of the stream. By returning the stream, you allow for chaining stream operations in a single statement, as shown earlier.

As an example, consider how to output the representation of a Date object in MM-DD-YYYY format. The following inserter does the job:

ostream& operator<<(ostream& os, const Date& d) {

  char fillc = os.fill('0');

  os << setw(2) << d.getMonth() << '-'

     << setw(2) << d.getDay() << '-'

     << setw(4) << setfill(fillc) << d.getYear();

  return os;

}

This function cannot be a member of the Date class, of course, because the left operand of the << operator must be the output stream. The fill( ) member function of ostream changes the padding character used when the width of an output field, determined by the manipulator setw( ), is greater than needed for the data. We use a ‘0’ character so that months before October will display with a leading zero, such as "09" for September. The fill( ) function also returns the previous fill character (which defaults to a single space) so that we can restore it later with the manipulator setfill( ). We discuss manipulators in depth later in this chapter.

Extractors require a little more care because things sometimes go wrong with input data. The way to signal a stream error is to set the stream’s fail bit, as follows:

istream& operator>>(istream& is, Date& d) {

  is >> d.month;

  char dash;

  is >> dash;

  if (dash != '-')

    is.setstate(ios::failbit);

  is >> d.day;

  is >> dash;

  if (dash != '-')

    is.setstate(ios::failbit);

  is >> d.year;

  return is;

}

When an error bit is set in a stream, all further streams operations are ignored until the stream is restored to a good state (explained shortly). That’s why the code above continues extracting even if ios::failbit gets set. This implementation is somewhat forgiving in that it allows white space between the numbers and dashes in a date string (because the >> operator skips white space by default when reading built-in types). The following are valid date strings for this extractor:.

"08-10-2003"

"8-10-2003"

"08 - 10 - 2003"

but these are not:

"A-10-2003"    // No alpha characters allowed

"08%10/2003"   // Only dashes allowed as a delimiter

We’ll discuss stream state in more depth in the section "Handling stream errors" later in this chapter.

<p>Common usage</p>

As the Date extractor illustrated, you must be on guard for erroneous input. If the input produces an unexpected value, the process is skewed, and it’s difficult to recover. In addition, formatted input defaults to white space delimiters. Consider what happens when we collect the code fragments from earlier in this chapter into a single program:.

//: C04:Iosexamp.cpp

// Iostream examples

#include

using namespace std;

int main() {

  int i;

  cin >> i;

  float f;

  cin >> f;

  char c;

  cin >> c;

  char buf[100];

  cin >> buf;

  cout << "i = " << i << endl;

  cout << "f = " << f << endl;

  cout << "c = " << c << endl;

  cout << "buf = " << buf << endl;

  cout << flush;

  cout << hex << "0x" << i << endl;

} ///:~

and give it the following input:.

12 1.4 c this is a test

We expect the same output as if we gave it:

12

1.4

c

this is a test

but the output is, somewhat unexpectedly

i = 12

f = 1.4

c = c

buf = this

0xc

Notice that buf got only the first word because the input routine looked for a space to delimit the input, which it saw after "this." In addition, if the continuous input string is longer than the storage allocated for buf, we overrun the buffer.

In practice, you’ll usually want to get input from interactive programs a line at a time as a sequence of characters, scan them, and then perform conversions once they’re safely in a buffer. This way you don’t have to worry about the input routine choking on unexpected data.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных