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

template

  class traits = char_traits,

  class allocator = allocator >

  class basic_string;

In Chapter 5, we examine templates in great detail (much more than in Chapter 16 of Volume 1). For now, the main thing to notice about the two previous declarations is that the string type is created when the basic_string template is instantiated with char. Inside the basic_string< > template declaration, the line.

class traits = char_traits,

tells us that the behavior of the class made from the basic_string< > template is specified by a class based on the template char_traits< >. Thus, the basic_string< > template provides for cases in which you need string-oriented classes that manipulate types other than char (wide characters, for example). To do this, the char_traits< > template controls the content and collating behaviors of a variety of character sets using the character comparison functions eq( ) (equal), ne( ) (not equal), and lt( ) (less than) upon which the basic_string< > string comparison functions rely.

This is why the string class doesn’t include case-insensitive member functions: that’s not in its job description. To change the way the string class treats character comparison, you must supply a different char_traits< > template, because that defines the behavior of the individual character comparison member functions.

You can use this information to make a new type of string class that ignores case. First, we’ll define a new case-insensitive char_traits< > template that inherits from the existing template. Next, we’ll override only the members we need to change to make character-by-character comparison case insensitive. (In addition to the three lexical character comparison members mentioned earlier, we’ll also have to supply a new implementation for the char_traits functions find( ) and compare( ).) Finally, we’ll typedef a new class based on basic_string, but using the case-insensitive ichar_traits template for its second argument.

//: C03:ichar_traits.h

// Creating your own character traits

#ifndef ICHAR_TRAITS_H

#define ICHAR_TRAITS_H

#include

#include

#include

#include

#include

using std::toupper;

using std::tolower;

using std::ostream;

using std::string;

using std::char_traits;

using std::allocator;

using std::basic_string;

struct ichar_traits : char_traits {

  // We'll only change character-by-

  // character comparison functions

  static bool eq(char c1st, char c2nd) {

    return toupper(c1st) == toupper(c2nd);

  }

  static bool ne(char c1st, char c2nd) {

    return !eq(c1st, c2nd);

  }

  static bool lt(char c1st, char c2nd) {

    return toupper(c1st) < toupper(c2nd);

  }

  static int compare(const char* str1,

    const char* str2, size_t n) {

    for(size_t i = 0; i < n; i++) {

      if(str1 == 0)

        return -1;

      else if(str2 == 0)

        return 1;

      else if(tolower(*str1) < tolower(*str2))

        return -1;

      else if(tolower(*str1) > tolower(*str2))

        return 1;

      assert(tolower(*str1) == tolower(*str2));

      str1++; str2++; // Compare the other chars

    }

    return 0;

  }

  static const char* find(const char* s1,

    size_t n, char c) {

    while(n-- > 0)

      if(toupper(*s1) == toupper(c))

        return s1;

      else

        ++s1;

    return 0;

  }

};

typedef basic_string istring;

inline ostream& operator<<(ostream& os, const istring& s) {

  return os << string(s.c_str(), s.length());

}

#endif // ICHAR_TRAITS_H  ///:~

We provide a typedef named istring so that our class will act like an ordinary string in every way, except that it will make all comparisons without respect to case. For convenience, we’ve also provided an overloaded operator<<( ) so that you can print istrings. Here’s an example:.

//: C03:ICompare.cpp

#include

#include

#include "ichar_traits.h"

using namespace std;

int main() {

  // The same letters except for case:

  istring first = "tHis";

  istring second = "ThIS";

  cout << first << endl;

  cout << second << endl;

  assert(first.compare(second) == 0);

  assert(first.find('h') == 1);

  assert(first.find('I') == 2);

  assert(first.find('x') == string::npos);

} ///:~

This is just a toy example, of course. To make istring fully equivalent to string, we’d have to create the other functions necessary to support the new istring type.

The header provides a wide string class via the following typedef:

typedef basic_string wstring;

Wide string support also reveals itself in wide streams (wostream in place of ostream, also defined in ) and in the header , a wide-character version of . This along with the wchar_t specialization of char_traits in the standard library allows us to do a wide-character version of ichar_traits:

//: C03:iwchar_traits.h

//{-bor}

//{-g++}

// Creating your own wide-character traits

#ifndef IWCHAR_TRAITS_H

#define IWCHAR_TRAITS_H

#include

#include

#include

#include

#include

using std::towupper;

using std::towlower;

using std::wostream;

using std::wstring;

using std::char_traits;

using std::allocator;

using std::basic_string;

struct iwchar_traits : char_traits {

  // We'll only change character-by-

  // character comparison functions

  static bool eq(wchar_t c1st, wchar_t c2nd) {

    return towupper(c1st) == towupper(c2nd);

  }

  static bool ne(wchar_t c1st, wchar_t c2nd) {

    return towupper(c1st) != towupper(c2nd);

  }

  static bool lt(wchar_t c1st, wchar_t c2nd) {

    return towupper(c1st) < towupper(c2nd);

  }

  static int compare(const wchar_t* str1,

    const wchar_t* str2, size_t n) {

    for(size_t i = 0; i < n; i++) {

      if(str1 == 0)

        return -1;

      else if(str2 == 0)

        return 1;

      else if(towlower(*str1) < towlower(*str2))

        return -1;

      else if(towlower(*str1) > towlower(*str2))

        return 1;

      assert(towlower(*str1) == towlower(*str2));

      str1++; str2++; // Compare the other wchar_ts

    }

    return 0;

  }

  static const wchar_t* find(const wchar_t* s1,

    size_t n, wchar_t c) {

    while(n-- > 0)

      if(towupper(*s1) == towupper(c))

        return s1;

      else

        ++s1;

    return 0;

  }

};

typedef basic_string iwstring;

inline wostream& operator<<(wostream& os,

  const iwstring& s) {

  return os << wstring(s.c_str(), s.length());

}

#endif // IWCHAR_TRAITS_H  ///:~

As you can see, this is mostly an exercise in placing a ‘w’ in the appropriate place in the source code. The test program looks like this:

//: C03:IWCompare.cpp

//{-g++}

#include

#include

#include "iwchar_traits.h"

using namespace std;

int main() {

  // The same letters except for case:

  iwstring wfirst = L"tHis";

  iwstring wsecond = L"ThIS";

  wcout << wfirst << endl;

  wcout << wsecond << endl;

  assert(wfirst.compare(wsecond) == 0);

  assert(wfirst.find('h') == 1);

  assert(wfirst.find('I') == 2);

  assert(wfirst.find('x') == wstring::npos);

} ///:~

Unfortunately, some compilers still do not provide robust support for wide characters.

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

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

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

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

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

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

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

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

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