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

//: C07:StringVector.cpp

// A vector of strings

#include

#include

#include

#include

#include

#include

#include "../require.h"

using namespace std;

int main(int argc, char* argv[]) {

  char* fname = "StringVector.cpp";

  if(argc > 1) fname = argv[1];

  ifstream in(fname);

  assure(in, fname);

  vector strings;

  string line;

  while(getline(in, line))

    strings.push_back(line);

  // Do something to the strings...

  int i = 1;

  vector::iterator w;

  for(w = strings.begin();

      w != strings.end(); w++) {

    ostringstream ss;

    ss << i++;

    *w = ss.str() + ": " + *w;

  }

  // Now send them out:

  copy(strings.begin(), strings.end(),

    ostream_iterator(cout, "\n"));

  // Since they aren't pointers, string

  // objects clean themselves up!

} ///:~

Once the vector called strings is created, each line in the file is read into a string and put in the vector:.

  while(getline(in, line))

    strings.push_back(line);

The operation that’s being performed on this file is to add line numbers. A stringstream provides easy conversion from an int to a string of characters representing that int.

Assembling string objects is quite easy, since operator+ is overloaded. Sensibly enough, the iterator w can be dereferenced to produce a string that can be used as both an rvalue and an lvalue:.

*w = ss.str() + ": " + *w;

You may be surprised that you can assign back into the container via the iterator , but it’s a tribute to the careful design of the STL.

Because the vector contains the objects themselves, a number of interesting things take place. First, no explicit cleanup of the string objects on your part is necessary. Even if you were to put addresses of the string objects as pointers into other containers, it’s clear that strings is the "master list" and maintains ownership of the objects.

Second, you are effectively using dynamic object creation, and yet you never use new or delete! That’s because, somehow, it’s all taken care of for you by the vector because it stores copies of the objects you give it. Thus your coding is significantly cleaned up.

<p>Inheriting from STL containers</p>

The power of instantly creating a sequence of elements is amazing, and it makes you realize how much time you may have spent (or rather wasted) in the past solving this particular problem. For example, many utility programs involve reading a file into memory, modifying the file, and writing it back out to disk. You might as well take the functionality in StringVector.cpp and package it into a class for later reuse.

Now the question is: do you create a member object of type vector, or do you inherit? A general object-oriented design guideline is to prefer composition (member objects) over inheritance, but the standard algorithms expect sequences that implement a specified interface, so inheritance is often called for.

//: C07:FileEditor.h

// File editor tool

#ifndef FILEEDITOR_H

#define FILEEDITOR_H

#include

#include

#include

class FileEditor :

  public std::vector {

public:

  void open(const char* filename);

  FileEditor(const char* filename) {

    open(filename);

  }

  FileEditor() {};

  void write(std::ostream& out = std::cout);

};

#endif // FILEEDITOR_H ///:~

Note the careful avoidance of a global using namespace std statement here, to prevent the opening of the std namespace in every file that includes this header.

The constructor opens the file and reads it into the FileEditor, and write( ) puts the vector of string onto any ostream. Notice in write( ) that you can have a default argument for the reference.

The implementation is quite simple:.

//: C07:FileEditor.cpp {O}

#include "FileEditor.h"

#include

#include "../require.h"

using namespace std;

void FileEditor::open(const char* filename) {

  ifstream in(filename);

  assure(in, filename);

  string line;

  while(getline(in, line))

    push_back(line);

}

// Could also use copy() here:

void FileEditor::write(ostream& out) {

  for(iterator w = begin();  w != end(); w++)

    out << *w << endl;

} ///:~

The functions from StringVector.cpp are simply repackaged. Often this is the way classes evolve—you start by creating a program to solve a particular application and then discover some commonly used functionality within the program that can be turned into a class.

The line-numbering program can now be rewritten using FileEditor:.

//: C07:FEditTest.cpp

//{L} FileEditor

// Test the FileEditor tool

#include

#include "FileEditor.h"

#include "../require.h"

using namespace std;

int main(int argc, char* argv[]) {

  FileEditor file;

  if(argc > 1) {

    file.open(argv[1]);

  } else {

    file.open("FEditTest.cpp");

  }

  // Do something to the lines...

  int i = 1;

  FileEditor::iterator w = file.begin();

  while(w != file.end()) {

    ostringstream ss;

    ss << i++;

    *w = ss.str() + ": " + *w;

    w++;

  }

  // Now send them to cout:

  file.write();

} ///:~

Now the operation of reading the file is in the constructor:.

FileEditor file(argv[1]);

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

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

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

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

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

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

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

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

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