среда, 30 июня 2010 г.

case-insensitive substring search

Что делать, если нужно найти подстроку в строке без учета регистра? Можно, конечно, написать целый case-insensitive класс строк, как предлагает Саттер. Ну а если уже есть строки std::string и хочется в них искать? В это случае можно использовать стандартный алгоритм std::search с собственным предикатом:
// templated version of my_equal so it could 
// work with both char and wchar_t
template<typename charT>
struct my_equal {
  my_equal( const std::locale& loc ) : loc_(loc) {}
  bool operator()(charT ch1, charT ch2) {
    return std::toupper(ch1, loc_) == std::toupper(ch2, loc_);
  }
private:
  const std::locale& loc_;
};

Можно написать ещё вспомогательную фукнцию, чтобы не писать каждый раз строку с длинными итераторами:
// find substring (case insensitive)
template<typename T>
int ci_find_substr( const T& str1, const T& str2, const std::locale& loc = std::locale() )
{
  T::const_iterator it = std::search( str1.begin(), str1.end(), 
    str2.begin(), str2.end(), my_equal<T::value_type>(loc) );
  if ( it != str1.end() )
    return it - str1.begin();
  else
    return -1; // not found
}

Использовать совсем просто:
// не забываем включить необходимые части
#include <locale>
#include <iostream>
#include <algorithm>
using namespace std;

int main(int arc, char *argv[]) 
{
  // string test
  std::string str1 = "FIRST HELLO";
  std::string str2 = "hello";
  int f1 = ci_find_substr( str1, str2 );

  // wstring test
  std::wstring wstr1 = L"ОПЯТЬ ПРИВЕТ";
  std::wstring wstr2 = L"привет";
  int f2 = ci_find_substr( wstr1, wstr2 );

  return 0;
}

воскресенье, 27 июня 2010 г.

Лето

В Москве очень жарко. Из крана для холодной воды течет теплая. Плавится асфальт и мозг. Комп можно включать только утром, в остальное время перегревается. Работать невозможно...

Выбрал погоду на яндексе, получается в Дублин надо ехать работать. Говорят, там свою Кремниевую долину уже построили без лишнего шума.

Доставка погодыЯ сказал, что хочу +20°С, и мою погоду доставили в 167 городов.
Среди них:
— Севилья (Испания)
— Кордова (Испания)
— Кастория (Греция)
А вашу?
Доставка и прогноз погоды

пятница, 4 июня 2010 г.

Function overload

Как известно, если в наследнике определить функцию с таким же именем, как в базовом классе, то она скроет все функции этого базового класса с этим именем не смотря на аргументы. Например,
struct B {
void f( char );
void f( std::string );
};

struct D : B {
void f(int) { f('c'); } // получаем рекурсивный вызов D::f(int)
};

Однако, если мы хотим оставить функцию(или несколько функций) базового класса, а не скрывать её, то можно написать using B::f;
struct D : B {
using B::f;
void f( int ) { f('c'); } // вызывается B::f(char)
};

четверг, 3 июня 2010 г.

typedef forward declare

При реализации PIMPL идиомы скрывается реализация и необходимо писать предварительные определения(forward declaration) классов, структур и прочего. Возникает вопрос — как написать предварительное объявление для typedef. Делается это следующим образом: сначала определяем класс, который учавствует в typedef, а потом пишем само определение. Например,
class A;
typedef std::shared_ptr<A> A_ptr;

Интересно, что стандарт запрещает писать предварительные объявления для классов стандартной библиотеки (17.4.2.1/3). Единственно правильный вариант — включать стандартные файлы. Для группы iosteam классов в стандарте сделан отдельный файл <iosfwd> (27.2) с преварительным определениями. Его можно включать и программа будет считаться корректной.