Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Дайте совет, Написал парсер получилось не ООП 
:(
    Опции темы
Pro100MoNEy
Дата 6.7.2013, 15:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 7.11.2010

Репутация: нет
Всего: нет



Написал небольшой парсер для BSDL файлов, но получилось как-то функционально что ли, я не смог выделить абстракции, к тому же приходится создавать объект парсера, затем вызвать функцию и передавать ему имя файла и объект для того что он разобрал(jtagDevice), мне кажется можно проще или более гибко но не могу придумать как, плюс зачемто унаследовал его от QObject что было лишним это я уберу, с помощью него разбираю отдельно файлы или папки вызывая для каждого файла parse(), еще вопрос как обрабатывать ситуации когда он не нашел чегото, можно ли использовать исключения или они не подходят и это будет избыточным, пока что просто вывожу в консоль если чтото не так, еще не встречал файла с ошибкой.
Вот класс:
Скрытый текст

Код

#include <QFile>
#include <QDir>
#include <QDebug>
#include <QStringList>
#include <QRegExp>
#include "jtagdevice.h"

class parser : public QObject
{
    Q_OBJECT
public:
    explicit parser(QObject *parent = 0);
    bool parse(QString filename,jtagDevice* device);
private:
    QFile* File;
    QString* fileStr;
    jtagDevice* dev;
    bool openFile(QString file);
    void removeGarbage();
    QString extractName();
    QString extractID();
    int extractDRLength();
    int extractIRLength();
signals:
    
public slots:
    
};

#endif
Код

#include "parser.h"
parser::parser(QObject *parent) :
    QObject(parent){
}

bool parser::parse(QString filename, jtagDevice *device){
    File=new QFile(filename);
    File->open(QIODevice::ReadOnly);
    if(!File->exists()){
        qDebug()<<"File not exist"<<filename;
        return false;}

    QString name,ID;
    int IRL,DRL;
    QMap < QString,QString > commands;
    fileStr =  new QString(File->readAll());
    removeGarbage();
    name=extractName();
    ID=extractID();
    IRL=extractIRLength();
    DRL=extractDRLength();
    commands=extractInstructions();
    if(name.isEmpty()||ID.isEmpty()){
        qDebug()<<"name or ID is empty";
        return false;}
    device->setName(name);
    device->setIDBIN(ID);
    device->setDRLength(DRL);
    device->setIRLength(IRL);
    device->setInstructions(commands);

    delete File;
    delete fileStr;

    return true;
}

void parser::removeGarbage(){
    qDebug()<<"garbage";
    QRegExp rx;
    int pos = 0;

    rx.setPattern("(\\-\\-.+\\n)");
    rx.setMinimal(true);
    while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // Убираем комментарии
        fileStr->remove(rx);
        pos += rx.matchedLength();
    }

    pos=0;
    rx.setMinimal(false);
    rx.setPattern("\\s+");
    while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // Убираем повторяющиеся пробелы
        fileStr->replace(pos,rx.matchedLength()," ");
        pos += (rx.matchedLength()-(rx.matchedLength()-1));
    }

    pos=0;
    rx.setPattern("\\r|\\n");
    rx.setMinimal(true);
    while ((pos = rx.indexIn(*fileStr, pos)) != -1) { // приводим все к одной строке
        fileStr->remove(rx);
        pos += rx.matchedLength();
    }
    pos=0;
    rx.setMinimal(false);
    rx.setPattern("\\s*([,:;\"\\)\\]\\(\\[])\\s*");
    while ((pos = rx.indexIn(*fileStr, pos)) != -1) {   // убираем пробелы у разделительных(,.:) знаков
        fileStr->replace(pos,rx.matchedLength(),rx.cap(1));
        pos += (rx.matchedLength()-(rx.matchedLength()-1));
    }

}

QString parser::extractName(){

    QString name;
    int index=fileStr->indexOf(";end ");
    if(index==-1){
        qDebug()<<"Can't find ID. 1";
        return name;}
    index+=5;
    if(fileStr->endsWith(";")){
        while(index!=fileStr->length()-1){
            name.push_back(fileStr->at(index));
            index++;
        }
        return name;}
    else{
        qDebug()<<"Can't find ID. 2";
        return name;
    }


}

QString parser::extractID(){
    QString ID,temp;
    int end;
    int index = fileStr->indexOf("IDCODE_REGISTER",0,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"IDCODE_REGISTER not found. 1";
        return ID;}
    index+=15;
    index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"IDCODE_REGISTER start not found. 2";
        return ID;}
    end=fileStr->indexOf(";",index,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"IDCODE_REGISTER end not found. 3";
        return ID;}
    while(index!=end){
        temp=fileStr->at(index);
        if(temp=="0"||temp=="1"||temp=="X")
            ID.push_back(temp);
        temp.clear();
        index++;
    }
    return ID;
}

int parser::extractIRLength(){
    QString result;
    int index=fileStr->indexOf("instruction_length",0,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"Can't extract IRLength";
        return -1;
    }
    index+=18;
    index=fileStr->indexOf(";",index,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"Can't extract IRLength";
        return -1;
    }
    index--;
    while(fileStr->at(index).isDigit()){
        result.push_front(fileStr->at(index));
        index--;
    }
    return result.toInt();
}

QMap<QString,QString> parser::extractInstructions(){
    QMap<QString,QString> result;
    QString command,code1;
    int end;
    int index=fileStr->indexOf("instruction_opcode",0,Qt::CaseInsensitive);
    index+=18;
    index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
    end=fileStr->indexOf(";",index,Qt::CaseInsensitive);
    while(index<end){
        index++;
        while(fileStr->at(index)!='('){
            command.push_back(fileStr->at(index));
            index++;
        }

        index++;
        while(fileStr->at(index)!=')'){
            code1.push_back(fileStr->at(index));
            index++;
        }
        result[code1]=command;
        command.clear();
        code1.clear();
        index=fileStr->indexOf("&",index,Qt::CaseInsensitive);
        index=fileStr->indexOf("\"",index,Qt::CaseInsensitive);
    }
    return result;

}

int parser::extractDRLength(){
    QString result;
    int index=fileStr->indexOf("boundary_length",0,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"Can't extract DRLength";
        return -1;
    }
    index+=15;
    index=fileStr->indexOf(";",index,Qt::CaseInsensitive);
    if(index==-1){
        qDebug()<<"Can't extract DRLength";
        return -1;
    }
    index--;
    while(fileStr->at(index).isDigit()){
        result.push_front(fileStr->at(index));
        index--;
    }
    return result.toInt();
}

И еще вопрос 
Допустим есть два класса
Код


class Obj1{
public:
    Obj2(string str, int num);
    int getNumBase();
    string getStrBase();
    virtual int getNumChild();
    virtual string getStrChild();
private:
    string strBase;
    int numBase
};

class Obj2 : public Obj1
{
public:
    Obj2(string str, int num, string str_cild, int num_chuld);
    int getNumChild();
    string getStrChild();
private:
    int numChild;
    string strChild;
};


Мне нужно хранить много экземпляров этих класов, я создал класс хранилище который хранит указатели на базовый класс в векторе, дает доступ к желементам и еще какойто функционал.
Я передаю в вектор указатели на объект так push(new Obj1()) push(new Obj2()).
Соответственно обратно тоже указатель на базовый класс.
Удаляю обьекты в деструкторе хранилища 
Код

for(;;)
delete vector[i];

Если комуто не лень скажите пожалуйста
1)Это хорошее решение хранить указатели а не объекты, и удалять их в деструкторе вышеописанным образом
2)Можно ли так использовать наследование как в Obj1 Obj2 или стоит определить виртуальный класс и два наследника(или вобще хранить все в одном и определять тип как пустая строка Str_Child или нет, что в принципе я и собираюсь делать с классами Obj1 Obj2 тк нужно определять тип)
3) Как выбрать хранить указатель на данные (str_Base,str_child) или переменные.
Спасибо всем ответившим и прочитавшим до конца.
PM MAIL   Вверх
SenkraD
Дата 6.7.2013, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: нет
Всего: 23



Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
1)Это хорошее решение хранить указатели а не объекты, и удалять их в деструкторе вышеописанным образом
вполне. еще можете использовать смарт поинтеры для большей безопасности, но тут дело вкуса и ситуации
Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
Как выбрать хранить указатель на данные (str_Base,str_child) или переменные.
поясните
Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
Можно ли так использовать наследование как в Obj1 Obj2 или стоит определить виртуальный класс и два наследника(или вобще хранить все в одном и определять тип как пустая строка Str_Child или нет, что в принципе я и собираюсь делать с классами Obj1 Obj2 тк нужно определять тип)
если класс Obj2 розширяет класс Obj1, то да. а вот если нужна просто имплементация класса Obj1 в классе Obj2, то тут дело вкуса. определить интерфейс, чтобы через него работать можно и зачастую это правильное решение


а по самому парсеру: можно просто розбить код на более мелкие функции и этого будет достаточно, чтобы код читался легче и легче модифицировался, а вот если вы вкладуете в понятие ООП что-то типа "нужно больше класов", то смотрите в сторону паттерна State и/или в сторону конечных автоматов, но не думаю, что вам тут нужет такой классовый оверхед, хотя если вы в целях самообразования, то пожалуйста

Это сообщение отредактировал(а) SenkraD - 6.7.2013, 18:55


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
xvr
Дата 6.7.2013, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 35
Всего: 223



Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
Написал небольшой парсер для BSDL файлов,

Парсером это можно назвать с натяжкой. Почитайте, как делают парсеры (хотя бы у Ахо и Ульман в их Dragon book'е). Или возьмите готовый генератор парсеров (начиная от классического yacc/bison и кончая spirit'ом из boost'а)

PM MAIL   Вверх
Pro100MoNEy
Дата 6.7.2013, 23:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 7.11.2010

Репутация: нет
Всего: нет



Цитата(SenkraD @ 6.7.2013,  18:50)
Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
1)Это хорошее решение хранить указатели а не объекты, и удалять их в деструкторе вышеописанным образом
вполне. еще можете использовать смарт поинтеры для большей безопасности, но тут дело вкуса и ситуации
Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
Как выбрать хранить указатель на данные (str_Base,str_child) или переменные.
поясните
Цитата(Pro100MoNEy @  6.7.2013,  15:34 Найти цитируемый пост)
Можно ли так использовать наследование как в Obj1 Obj2 или стоит определить виртуальный класс и два наследника(или вобще хранить все в одном и определять тип как пустая строка Str_Child или нет, что в принципе я и собираюсь делать с классами Obj1 Obj2 тк нужно определять тип)
если класс Obj2 розширяет класс Obj1, то да. а вот если нужна просто имплементация класса Obj1 в классе Obj2, то тут дело вкуса. определить интерфейс, чтобы через него работать можно и зачастую это правильное решение


а по самому парсеру: можно просто розбить код на более мелкие функции и этого будет достаточно, чтобы код читался легче и легче модифицировался, а вот если вы вкладуете в понятие ООП что-то типа "нужно больше класов", то смотрите в сторону паттерна State и/или в сторону конечных автоматов, но не думаю, что вам тут нужет такой классовый оверхед, хотя если вы в целях самообразования, то пожалуйста

Под хранить указатель или переменную  имел ввиду например в классе Obj1 есть строка и число, как лучше задать их указателями и выделять память например в конструкторе, или просто создать в классе переменные,
Код

class obj1{
private:
int num;
string str;
}

или
Код

class obj1{
private:
int *num;
string *str;
}

наверрно это дело вкуса, но есть же плюсы и минусы?

Это сообщение отредактировал(а) Pro100MoNEy - 6.7.2013, 23:38
PM MAIL   Вверх
SenkraD
Дата 7.7.2013, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 3.2.2006
Где: Украина::Киев

Репутация: нет
Всего: 23



создаются через указатели когда
  • по другому нельзя, класс так написали, тоесть запретеили создавать на стеке
  • когда вы не владеете обьетом или его могут передавать и изменять из вне (допустим, вам передают стратегию поведения)
  • обьект слишком большой чтобы его розмещать на стеке
  • вы работаете с полиморфными типами

минусы указателей:
  • легко получить утечки памяти
  • нереально проверить битость указателя, что при обращении дает креш
  • не всегда приятный синтаксис

P.S. оба списка можно розширять долго, но это так сказать основное


--------------------
 Имеющий язык - да не убоится спросить! 
user posted image
PM MAIL ICQ   Вверх
vvms
Дата 8.7.2013, 04:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 5
Регистрация: 7.10.2008

Репутация: нет
Всего: 1



Немного не по теме вопроса, но по предъявленному коду:
1. Не очень понятно зачем проверять наличие файла после попытки его открытия. Поскольку используется Qt, то тут два варианта: а) убрать строку "if(!File->exists()){" совсем, так как метод open у QFile возвращает true/false - смог открыть или нет, вот результат open проверять и надо б) если хочется все-таки проверить наличие, то делать
это до реального открытия файла, плюс ко всему у QFile есть статический метод exists, что не требует создания объекта. Для случая б) получим такой код:
Код

    if(! QFile::exists(filename)){
        qDebug()<<"File not exist"<<filename;
        return false;}

    File=new QFile(filename);
    File->open(QIODevice::ReadOnly);

    QString name,ID;


2. Утечки памяти тоже надо чинить. "File=new QFile(filename)" - имеется, а вот "delete File" - отсутствует вообще, а должен быть перед каждым "return false" или "return true". Конкретно, в приложенном коде как минмум 2 возможных места утечки: 11 строка и 25. Если воспользоваться моим предожением б) из первого пункта, утечка возможна только в 25 строке. Добавочно, в 25 строке еще будет утечка из-за неудаленного объекта, созданного в строке 16.
PM MAIL   Вверх
Pro100MoNEy
Дата 8.7.2013, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 22
Регистрация: 7.11.2010

Репутация: нет
Всего: нет



Цитата(vvms @ 8.7.2013,  04:45)
Немного не по теме вопроса, но по предъявленному коду:
1. Не очень понятно зачем проверять наличие файла после попытки его открытия. Поскольку используется Qt, то тут два варианта: а) убрать строку "if(!File->exists()){" совсем, так как метод open у QFile возвращает true/false - смог открыть или нет, вот результат open проверять и надо б) если хочется все-таки проверить наличие, то делать
это до реального открытия файла, плюс ко всему у QFile есть статический метод exists, что не требует создания объекта. Для случая б) получим такой код:
Код

    if(! QFile::exists(filename)){
        qDebug()<<"File not exist"<<filename;
        return false;}

    File=new QFile(filename);
    File->open(QIODevice::ReadOnly);

    QString name,ID;


2. Утечки памяти тоже надо чинить. "File=new QFile(filename)" - имеется, а вот "delete File" - отсутствует вообще, а должен быть перед каждым "return false" или "return true". Конкретно, в приложенном коде как минмум 2 возможных места утечки: 11 строка и 25. Если воспользоваться моим предожением б) из первого пункта, утечка возможна только в 25 строке. Добавочно, в 25 строке еще будет утечка из-за неудаленного объекта, созданного в строке 16.

Спасибо! Действительно File я забыл удалить.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1186 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.