Программирование на C++

10 способов прострелить себе ногу

Создание веб приложений

В инете столько порнухи, что создается впечатление, что каждая женщина на Земле хотя бы раз в ней снималась...

Подпись для третьего не придумал

Американец изнасиловал лошадь, потому что думал, что у них родится кентавр

Помощь обездоленным якутам на дальнем севере

Благотворительность (на правах рекламы)

Показаны сообщения с ярлыком Technology. Показать все сообщения
Показаны сообщения с ярлыком Technology. Показать все сообщения

воскресенье, 22 декабря 2013 г.

Решение задач с Regex.One (с объяснениями)


С первого взгляда Регулярные выражения (Regex) могут показаться очень непонятными и сложными, поэтому после теоретического материала, лучше обязательно попрактиковаться на реальных примерах и упражнениях.
Лично для меня источником таких упражнений является сайт:
Прежде чем читать мои попытки пройти там задания, вам лучше самостоятельно пройти их, задания там очень легкие, если честно :)
Решение будет скоро, примерно через неделю )

Решение:

Первое задание: Letters

  • abcdefg
  • abcde
  • abc
Видно, что 3 буквы повторяются во всех трех строках abc, поэтому можно применить тупо выражение : 
abc
но вдруг нам надо 3 буквы, которые будут стоять рядом по алфавиту, то мы используем:
[a-c]{3}
То есть в этот паттерн будут входить abc, bac, cab итд. [a-c] означает группу, а {3} - то что букв всего 3.
\w{3} - любая буква, цифра или подчеркивание 3 раза

Второе задание: Digits


  • abc123xyz
  • define “123”
  • var g = 123;
Видно, что повторяются 3 цифры 123:
123 - если явно 3 цифры
\d{3} - цифры 3 раза
\w{3} - более нестрогое, если еще и буквы и _
[1-3]{3} - {123, 321, 213 итд (аналог \d{3} }

Третье задание: the Dot

Здесь уже сложнее, так как есть паттерн который НЕ НАДО выбирать

  • match text cat.
  • match text 896.
  • match text ?=+. 
  • skip text abc1
Видно, что здесь в каждом примере повторяется символ точка и перед точкой какие-то другие символы, но нельзя забывать, что в регексах есть оператор точка!, а если мы хотим найти символ точку, то нужно использовать слэш. Слэш экранирует символ.
.{3}\.
"." - любой символ {3} раза
"\." - поиск точки
По идее можно использовать точку вот так:
\.

Четвертое задание: Matching specific characters


  • match text can
  • match text man
  • match text fan
  • skip text dan
  • skip text ran
  • skip text pan
Видно, что регекс должен содержать c,m,f первым символом и не содержать d,r,p, используем группировку:
[cmf]an

Пятое задание: Excluding specific characters

  • match text hog 
  • match text dog
  • skip text bog
Здесь мы должны исключить символ b, это используется с помощью спецсимвола ^. Отрицание работает ТОЛЬКО в КВАДРАТНЫХ СКОБКАХ.
[^b]og
Также по заданию можно было использовать предыдущую технику:
[hd]og

Шестое задание: Character ranges

  • match text Ana
  • match text Bob
  • match text Cpc
  • skip text aax
  • skip text bby
  • skip text ccz
Ну решение состоит в группировке, здесь я думаю все понятно:
[A-C][nop][a-c]

Седьмое задание: Catching some zzz's


  • match text wazzzzup 
  • match text wazzzup
  • skip text wazup
Оч хороший пример, видно, что wazzz повторяется в двух примерах, но в некоторых жизненных ситуациях z может повторяться и больше 3ех раз, поэтому лучше использовать квантификаторы, они обозначаются обычно в фигурных скобках:
waz{3}z?up
z{3} //значит, что z может повторяться только 3 раза
z? //значит, что z может повторяться от 0 до 1 раза. (можно заменить на {0,1}
waz{3}z{0,1}up
Более лаконично:
waz{2,4}up

Восьмое задание: Mr Kleene


  • match text aaaabcc
  • match text aabbbbc
  • match text aacc
Как обычно группировка:
a{2,4}b{0,}c{1,2}
Но это не лаконично:
[abc]+ //Плюс значит один или более {1,} - эквивалент
Совсем не лаконично:
a*b*c*

Девятое задание: Characters Optional


  • match text 1 file found?
  • match text 2 files found?
  • match text x files found?
Хм, мы можем использовать логический оператор или ("|") и применить к нему квантификатор от 0, потому что число может быть и двухзначным и трехзначным итд.
К тому же на конце file может быть s или не может.
И нельзя забывать, что "?" - метасимвол, его нужно экранировать.
(\d|x){0,} files? found\?

Десятое задание: All this whitespace



  • match text 1.      abc
  • match text 2.           abc
  • match text 3.                    abc
  • skip text 4.abc

Увы, здесь пробелы при копировании не отобразились но суть в том, что нужно использовать метасимвол \s который обозначает пробел
\d\.\s{1,}abc

Одиннадцатое задание: Starting and ending



  • match text Mission: successful
  • skip text Last Mission: unsuccessful
  • skip text Next Mission: successful upon capture of target


Здесь в этом задании надо использовать символы окончания и начала строки (^ - начало и $ - конец).
^M - первая строка начинается с M
^[^LN] - первая строка не начинается с L или N
\ssuccessful$ - так как перед successful пробел, successful - идет в конце
\bsuccessful$ - \b - разделитель между словами

Двенадцатое задание: Match Groups


your task text capture
capture text file_a_record_file.pdf       (file_a_record_file)
capture text file_yesterday.pdf            (file_yesterday)
skip text testfile_fake.pdf.tmp
Суть в том, что нужно чтобы результатом выборки были строки в скобке. Делать это надо через механизм запоминающих скобок: "( )"

(file.*)\.pdf$
Видно, что на конце должно быть расширение .pdf, поэтому ставим знак окончания строки. Потом в запоминающих скобках выражение, которое содержится во всех строках. Запоминающие скобки помогают возвратить результат работы регекса.

Тринадцатое задание: Nested Groups


capture text Jan 1987 (Jan 1987, 1987)
 capture text May 1969 (May 1969, 1969)
 capture text Aug 2011 (Aug 2011, 2011)

Суть в том, что мы должны использовать ВЛОЖЕННЫЕ запоминающие скобки.
Например мы хотим захватить все содержимое, мы делаем в скобках (.*) - это захватит к примеру всю строку Jan 1987, плюс мы хотим еще вывести год, тогда мы добавляем в скобках еще скобки
(.*(\d{4}))
Еще более точно:
(\w+\s(\d{4}))

Четырнадцатое задание: More Work Group

(\d+)x(\d+)

15
I love (cats|dogs)
16

воскресенье, 10 марта 2013 г.

Шаблон проектирования Команда (Command) + Реализация на C#

Существуют ситуации, когда у нас есть просто данные, над которыми нужно провести одну лишь единственную операцию, например, у нас есть кино на DVD диске и нам нужно всего лишь либо, запустить фильм, либо остановить, либо нажать на паузу и так далее. Также нам может понадобится такое действие, которое может отменить предыдущее (например операция undo в блокноте). Я могу написать функции (или методы), которые будут исполнять нашу команду и обрабатывать ее, но у нас будет очень много похожего кода, так как у нас не будет базового класса, который будет иметь поля схожие для всех команд. К тому же код будет очень не гибким. Фактически это КЛАСС, который инкапсулирует один единственный метод execute(). Это позволяет нам хранить команды в каких то контейнерах, обрабатывать их с помощью наших обработчиков.
(Пример стыбзен с википедии). Мы проектируем калькулятор со стандартными операциями сложения, деления, умножения, вычитания
Все строится сначала на классе Command:

abstract class Command
  {
    public abstract void Execute(); //метод выполнения команды
    public abstract void UnExecute(); //метод отмены
  }
Теперь делаем производные классы от команды. Причем этот класс должен хранить получателя(Calculator), класс, который принимает команды и обрабатывает их.

class CalculatorCommand : Command
  {
 char @operator; //оператор
 int operand;
 Calculator calculator; //ОБЪЕКТ ПОЛУЧАЮЩИЙ КОМАНДЫ (Receiver)
 
    // Constructor
 public CalculatorCommand(Calculator calculator,
    char @operator, int operand)
    {
      this.calculator = calculator;
      this.@operator = @operator;
      this.operand = operand;
    }
 
    public char Operator
    {
      set{ @operator = value; }
    }
 
    public int Operand
    {
      set{ operand = value; }
    }
 //здесь мы просто вызываем метод нашего получателя, на вход которого мы отправляем оператор и операнд
    public override void Execute() 
    {
      calculator.Operation(@operator, operand);
    }
 
    public override void UnExecute()
    {
      calculator.Operation(Undo(@operator), operand);
    }
 
    // Private helper function : приватные вспомогательные функции
    private char Undo(char @operator)
    {
      char undo;
      switch(@operator)
      {
        case '+': undo = '-'; break;
        case '-': undo = '+'; break;
        case '*': undo = '/'; break;
        case '/': undo = '*'; break;
        default : undo = ' '; break;
      }
      return undo;
    }
  }
Теперь нужен класс который будет получать команды и их обрабатывать.

// "Receiver" : получатель
 
  class Calculator
  {
    private int curr = 0;
 
    public void Operation(char @operator, int operand)
    {
      switch(@operator)
      {
        case '+': curr += operand; break;
        case '-': curr -= operand; break;
        case '*': curr *= operand; break;
        case '/': curr /= operand; break;
      }
      Console.WriteLine(
        "Current value = {0,3} (following {1} {2})",
        curr, @operator, operand);
    }
  }
Теперь нужен класс, который будет отдавать команды на обработку калькулятору..

class User
  {
    // Initializers
    private Calculator _calculator = new Calculator();
    private List _commands = new List();
 
    private int _current = 0;
 
    public void Redo(int levels)
    {
      Console.WriteLine("\n---- Redo {0} levels ", levels);
 
      // Делаем возврат операций
      for (int i = 0; i < levels; i++)
        if (_current < _commands.Count - 1)
          _commands[_current++].Execute();
    }
 
    public void Undo(int levels)
    {
      Console.WriteLine("\n---- Undo {0} levels ", levels);
 
      // Делаем отмену операций
      for (int i = 0; i < levels; i++)
        if (_current > 0)
          _commands[--_current].UnExecute();
    }
 
    public void Compute(char @operator, int operand)
    {
 
      // Создаем команду операции и выполняем её
      Command command = new CalculatorCommand(
        _calculator, @operator, operand);
      command.Execute();
 
      // Добавляем операцию к списку отмены
      _commands.Add(command);
      _current++;
    }
  }
Ну и пример работы с нашим калькулятором

class MainApp
  {
    static void Main()
    {
      // Создаем пользователя.
      User user = new User();
 
      // Пусть он что-нибудь сделает.
      user.Compute('+', 100);
      user.Compute('-', 50);
      user.Compute('*', 10);
      user.Compute('/', 2);
 
      // Отменяем 4 команды
      user.Undo(4);
 
      // Вернём 3 отменённые команды.
      user.Redo(3);
 
      // Ждем ввода пользователя и завершаемся.
      Console.Read();
    }
  }
Итак, теперь обобщим все, что мы здесь написали, вот схемка шаблона:
Ну, кто не силен в английском, могу объяснить, сначала наш вызывающий (по английски Invoker) (в нашем случае User), вызывает команду (причем команда передается в виде объекта) и посылает ее получателю (Calculator), где команда успешно обрабатывается калькулятором.
Благодаря такому шаблону, мы можем без труда можем добавить свои команды, которые с помощью метода execute() будут также выполнятся. Всего лишь надо унаследовать все от Command.

вторник, 26 февраля 2013 г.

Шаблон проектирования Абстрактная фабрика (Abstract factory) Реализация C#

Абстрактная фабрика - порождающий шаблон проектирования, используемый для создания ГРУППЫ объектов, реализующих одно поведение, то есть объекты одного типа, причем не специфируя их конкретные классы.

Абстрактная фабрика используется, когда:
  1. Система должна работать с группами объектов и объекты в этом семействе должны использоваться совместно.
  2. Система не должна зависеть от того, как создаются компоненты и взаимодействуют.
  3. Когда надо, чтобы при изменении класса конкретного продукта, не приходилось изменять класс клиента (класс, взаимодействующий  с созданными продуктами)
Действующие лица:
  • AbstractProduct — абстрактный продукт
    • определяет интерфейс для создания объектов, создаваемых методом CreateProduct, то есть он содержит виртуальные функции CreateProduct, где уже в ConcreteFactory переопределяются (override).
  • ConcreteProduct — конкретный продукт
    • реализует интерфейс Product (то есть у нас есть класс AbstractProduct, от которого у нас несколько производных классов, типа ConcreteProductA, либо ConcreteProductB и так далее)
  • AbstractProduct — абстрактный создатель
    • предназначен, для реализации интерфейса от производных классов типа ConcreteProduct
  • ConcreteFactory — конкретная фабрика
    • переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.
  • Client - клиент
    • дает команды на получение продукта определенного семейства, к тому же в параметры передается фабрика, к-ая создает все объекты, фактически это наш интерфейс взаимодействия, с помощью которого, мы решаем какие объекты создать.

Диаграмма:
Шаблон:


//сам интерфейс абстрактной фабрики
//два абстрактных методов, к-ые переопределяются в наследниках
    abstract class AbstractFactory
    {
        public abstract AbstractProductA CreateProductA();
        public abstract AbstractProductB CreateProductB();
    }

    // "ConcreteFactory1" 
    class ConcreteFactory1 : AbstractFactory
    {
//переопредление методов интерфейсных для 1ой фабрики
        public override AbstractProductA CreateProductA()
        {
            return new ProductA1();
        }
        public override AbstractProductB CreateProductB()
        {
            return new ProductB1();
        }
    }

    // "ConcreteFactory2" 
    class ConcreteFactory2 : AbstractFactory
    {
//переопредление методов интерфейсных для 2ой фабрики
        public override AbstractProductA CreateProductA()
        {
            return new ProductA2();
        }
        public override AbstractProductB CreateProductB()
        {
            return new ProductB2();
        }
    }
//пошли уже наши интерфейсы продуктов
    // "AbstractProductA" 
    abstract class AbstractProductA
    {
    }

    // "AbstractProductB" 
    abstract class AbstractProductB
    {
//метод, который показывает, как продукт B взаимодействует с объектом А
        public abstract void Interact(AbstractProductA a);
    }
//реализация продуктов
    // "ProductA1" 
    class ProductA1 : AbstractProductA
    {
    }

    // "ProductB1" 
    class ProductB1 : AbstractProductB
    {
//определение
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }
    }

    // "ProductA2" 
    class ProductA2 : AbstractProductA
    {
    }

    // "ProductB2" 
    class ProductB2 : AbstractProductB
    {
        public override void Interact(AbstractProductA a)
        {
            Console.WriteLine(this.GetType().Name + " interacts with " + a.GetType().Name);
        }
    }
//интерфейс взаимодействия, с помощью которого мы решаем какого типа создать объекты
    // "Client" - the interaction environment of the products 
    class Client
    {
        private AbstractProductA abstractProductA;
        private AbstractProductB abstractProductB;

        // Constructor, создается группа объектов, причем все в зависимости от типа фабрики
        public Client(AbstractFactory factory)
        {
            abstractProductB = factory.CreateProductB();
            abstractProductA = factory.CreateProductA();
        }
//запуск клиента
        public void Run()
        {
            abstractProductB.Interact(abstractProductA);
        }
    }

Main():

        static void Main(string[] args)
        {
            // Abstract factory #1 
            AbstractFactory factory1 = new ConcreteFactory1();
            Client c1 = new Client(factory1);
            c1.Run();

            // Abstract factory #2 
            AbstractFactory factory2 = new ConcreteFactory2();
            Client c2 = new Client(factory2);
            c2.Run();

            // Wait for user input 
            Console.Read();

        }
Вывод: Итак, все как в фабричном методе, только мы создаем ГРУППЫ объектов, и также у нас клиент занимается созданием объектов и анализ взаимодействия созданных объектов.

Шаблон проектирования Фабричный метод (Factory Method) Реализация C#

Фабричный метод используется для создания одного! объекта с определенным интерфейсом (типом).

Фабричный метод относится к порождающим шаблонам проектирования. Порождающие шаблоны проектирования используются для создания объектов, причем они позволяют быть независимыми от типа создаваемого объекта и от процесса создания.

Фабричный метод используется, когда:
  1. Заранее известно, когда создавать объект, но не известен его тип.
  2. Созданные фабричным методом объекты должны определятся уже в подклассе.
  3. Класс делегирует свои методы производному классу, после чего происходит определение, какой класс принимает какие методы.
Диаграмма:

Действующие лица:
  • Product — продукт
    • определяет интерфейс объектов, создаваемых абстрактным методом;
  • ConcreteProduct — конкретный продукт
    • реализует интерфейс Product (то есть у нас есть интерфейс IProduct, от которого у нас несколько производных классов, типа ConcreteProductA, либо ConcreteProductB и так далее)
  • Creator — создатель
    • предназначен, для реализации интерфейса от производных классов типа ConcreteCreator
    • содержит фабричный метод для создания объекта типа Product, который переопределяется в классах ConcreteCreatorA, ConcreteCreatorB;
  • ConcreteCreator — конкретный создатель
    • переопределяет фабричный метод таким образом, чтобы он создавал и возвращал объект класса ConcreteProduct.
На основе класса Factory создается один или несколько классов фабрик (причем эти фабрики имеют тип), и эти фабрики создают конкретные модели.

Шаблон:
//абстрактный класс создателя, который имеет абстрактный метод FactoryMethod, принимающий тип продукта
public abstract class Creator
{
    public abstract Product FactoryMethod(int type);
}
 
 
public class ConcreteCreator : Creator
{
    public override Product FactoryMethod(int type)
    {
        switch (type)
        {
            //возвращает объект A, если type==1
            case 1: return new ConcreteProductA();
            //возвращает объект B, если type==2 
            case 2: return new ConcreteProductB(); 
            default: throw new ArgumentException("Invalid type.", "type");
        }
    }
}

public abstract class Product { } //абстрактный класс продукт
 //конкретные продукты с разной реализацией
public class ConcreteProductA : Product { } 
 
public class ConcreteProductB : Product { }
 //
Потом в Main()

static void Main()
{       //создаем создателя
        Creator creator = new ConcreteCreator();
 for (int i = 1; i <= 2; i++)
 {
            //создаем сначала продукт с типом 1, потом с типом 2
     var product = creator.FactoryMethod(i);
     Console.WriteLine("Where id = {0}, Created {1} ", i, product.GetType());
 }
}
Здесь сначала создается сам конкретный создатель, который потом будет использоваться в создании продуктов, сначала ConcreteProductA, вывод на экран типа, потом ConcreteProductB, и также вывод его типа.

Итак, подводим итоги:

Самый главный недостаток, это необходимость создания объекта Creator для того, чтобы создать любой продукт с помощью метода FactoryMethod().