Создайте класс, содержащий информацию синтаксического анализа

Скажем, у меня есть ресторан, который делает пирог. Я хочу вырезать этот пирог в соответствии с вводом анализируется из файла. Это ключ к информации о том, как разрезать пирог. я использую CircleDividerParser class, чтобы разобрать file.txt.

формат файла:

  • pie_cuttin_style_name = - ключ для поиска.
  • радиус = радиус или пирог
  • x = x-координата центра пирога
  • y = y-координата центра пирога
  • angle_type = угол может быть как градусом, так и радиан
  • angle_value = значение угла, которое может быть радиан или градус
  • направление = часовой или против часовой стрелки
  • from_x = x точка в круге, откуда угол измеряется
  • from_y = y точка в круге, где угол равен измеренная

, например: file.txt

  

cut_pattern_1,5,1,2, degree, 40, anti-clock, 6,2

     

....

     

..

Тогда у меня есть класс для выполнения логики синтаксического анализа:

Class CircleDividerParser{

  // does the parsing logic to capture the values
  void Dowork(filename){
    std::ifstream file_stream.open(filename);
    std::string line;
    while(std::getline(file_stream, line){
       std::string str;
       std::stringstream ss(line);
       int i = 0;
       while(std::getline(ss, str, ',')){
         holder[i] = str; 
         i++;
       }
       pcc.add_pie_cutting_info(holder);
    }

  }

  private:
   std::array<std::string, 9> holder;
   PieCutterCreator pcc;

};

//Этот класс создает PieCuttingInfo на основе массива строки, предоставленной CicleDividerParser

class PieCutterCreator{

public:
  void add_pie_cutting_info(std::array<std::string, 9> arr){
     PieCuttingInfo obj;    

     obj.AddPieCuttingStyleName(arr[0]);
     obj.AddRadius(arr[1]);
     ...
     ..

  }
  PieCuttingInfo GetPieCuttingInfo(const std::string& name_to_find);

  std::vector<PieCuttingInfo> GetAllPieCuttingInfo() { return collect;}

private:
  std::vector<PieCuttingInfo> collect;

};

class PieCuttingInfo{

  class enum angle_type {Degree, Radian};

public:
  PieCuttingInfo()=default;

  void AddPieCuttingStyleName(const std::string& name){ pie_cutting_style_name = name;}

  void AddRaius(const std::string& r) {radius = r;}

  void AddAngleType(const std::string& at) {
    if(at == "degree"){
      angle_value = angle_type::Degree;
    }else if(at == "radian"){
      angle_value = angle_type::Radian;
    }else {// error}
  }
   ...


private:

 std::string pie_cutting_style_name;
 std::string radius;// radius or pie 
 std::string x;//  x-coordinate of pie center
 std::string y;//  y-coordinate of pie center
 std::string angle_type;  angle can be either degree or radian
 std::string angle_value; value of angle that could be radian or degree
 std::string direction;  clock wise or anti-clockwise angle
 std::string from_x;   x point in circle from where the angle is measured
 std::string from_y;   y point in circle from where the angle is measured

};


class PieCuttingMaching(){

  void DoAllThePieCutting(){
    save = obj.GetAllPieCuttingInfo();
    for(auto& it: save){
        // use the info from PieCuttingInfo to do the job
    }
  }  

private:
  std::vector<PieCuttingInfo> save;
  PieCutterCreator obj;
}

Вопросы:

  • Является ли дизайн правильным, или я делаю вещи compilcated
  • Можно создать класс PieCuttingInfo, даже если вся информация не предусмотрено.
  • Если переменные, которые будут инициализированы классом PieCuttingInfo во время его создания,  передавая всю переменную сразу.
3 голоса | спросил vanta mula 24 +03002017-10-24T05:13:40+03:00312017bEurope/MoscowTue, 24 Oct 2017 05:13:40 +0300 2017, 05:13:40

1 ответ


3

Хорошо, что вы видите перед собой, действительно завтрак плита . Шутка в сторону, похоже, ваше решение позволяет помещать ошибки в ваш файл для чтения, и ваша программа будет иметь проблемы с определением возможных ошибок такого рода. Я не могу сказать, потому что, возможно, машина, разрезающая пироги, нуждается во всей этой информации, и вы хотите дать максимальный контроль лицу, записывающему файл.

В этом нет ничего плохого, но это очень низкий уровень. То есть, человек, записывающий параметры, должен получить все правильно, а не вы. Если это было введено в машину, существует серьезная возможность заставить машину делать то, что она не может сделать или пытается сделать, и в конечном итоге уничтожить себя в процессе.

Упрощение - это ключ

Это могут быть фактические параметры машины, но мой совет для вас состоял в том, чтобы упростить операции резки пирога в случаях использования и перевести «простые» параметры в более сложные, которые может выполнить ваш компьютер. Начните с абстрактного класса CuttingInfo с помощью метода GetMachineParams. Любой класс, полученный из CuttingInfo принимает в качестве входных упрощенных параметров и его вывод в GetMachineParams - это сведения о низком уровне, которые необходимо передать компьютеру.

Вы также можете создать абстрактный класс Parser с методами CanRead и Read. CanRead можно вызывать с текущей строкой файла, чтобы определить, можно ли десериализовать этот класс этим классом, а Read вызывается, когда CanRead возвращает значение true, которое возвращает экземпляр ---- +: = 10 =:. + ----

Use Case - 8 срезов

Я хочу, чтобы машина разделила мой пирог на 8 четных фрагментов. Это будет популярный запрос без сомнения. Если не 8 ломтиков, то 10 или 6, но, тем не менее, пользователь вашей программы, или ваш клиент, не собирается говорить о количестве радианов на кусочек или перемещаться против часовой стрелки.

Класс CuttingInfo принимает в качестве параметра только число, представляющее N. Фактическая работа по переводу этого в ряд инструкций переходит в NEvenSlicesCuttingInfo

Вам тогда нужен только класс GetMachineParams, который возвращает true в NEvenSlicesParser тогда и только тогда, когда линия начинается с «NEvenSlices». Второй параметр в той же строке должен быть N. Таким образом, строка в файле должна быть:

CanRead

Задача NEvenSlices 8 в NEvenSlicesParser должен быть не более сложным, чем чтение параметра после Read и возврата NEvenSlices.

Конечно, файл может по-прежнему содержать неправильные параметры таким образом, но вы можете проверить упрощенные параметры. Предполагая, что ваш класс делает все, что нужно, вам не нужно беспокоиться о том, чтобы разбить машину на эти параметры.

Объединение вместе

Чтобы использовать его, в вашей программе у вас будет вектор классов new NEvenSlicesCuttingInfo(numberRead), созданных один раз при запуске программы со всеми реализациями Parser. Когда вы читаете файл, строка за строкой, вы переходите к Parser. Если он возвращает true, вызовите его метод CanRead и получите Read, который вы можете вызвать в любое время для получения параметров машины. Все это без знания деталей реализации в каждом классе реализации.

Вы можете ясно видеть, что вы можете расширить его, чтобы добавить другие варианты использования. Вы даже можете покрыть свой первоначальный сценарий, создав парсер 1 к 1, который загружает каждый возможный параметр и просто возвращает его в CuttingInfo, если вам требуется абсолютное контроль, который не нарушает этоесли вы этого потребуете (хотя я бы категорически отказался от использования такого класса).

Этот подход имеет тот недостаток, что вам придется переписать файл инструкции, чтобы содержать всю информацию в той же строке, но ничто не мешает вам создавать более сложный Parser, который имеет своеобразное соглашение для написания инструкций на нескольких строках (т. е. если вы видите начало строки с помощью GetMachineParams, прочитайте, пока не найдете строку, заканчивающуюся на <<< и верните содержимое в середине на >>>).

Самое главное, что ваша программная логика больше не заботится о деталях реализации, позволяя вам максимально гибко и легко поддерживать будущее.

ответил Neil 24 +03002017-10-24T10:16:54+03:00312017bEurope/MoscowTue, 24 Oct 2017 10:16:54 +0300 2017, 10:16:54

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132