Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/3: Рейтинг темы: голосов - 3, средняя оценка - 5.00
1 / 1 / 1
Регистрация: 28.04.2013
Сообщений: 35
1

Проверьте пожалуйста реализацию кода [Мини-скрипт язык]

22.10.2014, 05:21. Показов 517. Ответов 6
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Встала задача создать структурный язык на подобие xml, для передачи и приёма данных в моём протоколе..
Собственно что должно получится:
1. Язык должен иметь теги <>.
2. Между двумя тегами должны хранится данные.
3. По выбору тега, должны возвращаться данные.

В итоге получилось это:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <iostream.h>
#include "oriLang.h"
 
int main() {
 
    char login[32], pass[32];
    memset(login, '\x00', 32);
    memset(pass,  '\x00', 32);
 
    OriLng Lng;
 
    Lng < "<Логин>Orion<Логин>"
             "<Пароль>1234<Пароль>";
 
    Lng.ReturnData(login, "<Логин>");
    Lng.ReturnData(pass,  "<Пароль>");
 
    std::cout << "\nlogin teg: " << login << "\npass  teg: " << pass;
    std::cout << "\n";
    std::system("PAUSE");
    return 0;
}
Результат выполнения:
C++
1
2
login teg: Orion
pass  teg: 1234
Реализация:
Хейдер:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/*
   Orion Game 22.10.2014
   Скриптовый язык Ori Lng
*/
#ifndef oriLangH
#define oriLangH
 
#define MAX_BUFFER_LNG 40000
#define MAX_TEG_LEN    1000
#define OPEN_TEG_SYMBOL  '<'
#define CLOSE_TEG_SYMBOL '>'
#define MAX_SYMBOL_NAME 33
 
#define ERROR_LEN_TEG "Error 1! Name teg in symbol: [%d] have > 32 symbol"
 
// Хранит в себе теги и их адреса в буфере
struct Сache_Teg
{
  char Teg[32];          // Имя тега
  int  StartSymbol;      // Стартовый символ
  int  EndSymbol;        // Конечный символ
};
 
/* Класс для работы с скриптовым языком */
class OriLng
{
  public:
    int  ReturnData(char *_buffer, char *NameTeg);
    void Clear();
    OriLng& operator < (char *LngCode);
    char ErrorTeg[512];
    int CountTeg;
 
 
  private:
    char Buffer          [MAX_BUFFER_LNG];
    int  lenBuffer;
 
    Сache_Teg  Teg       [MAX_TEG_LEN * 5];
 
    int  StartScan(int StartPosition, char* NameTeg, int &StartPositionTeg, int &EndPositionTeg);
};
 
#endif

Private:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
   Orion Game 22.10.2014
   Скриптовый язык Ori Lng
*/
 
#include  <stdio.h>
#include  <string.h>
 
#include  "oriLang.h"
 
/***********************************************************
 Функция принимает код и начинает сортировку в массив тегов.
 LngCode - скрипт код
 ********************************************************** */
 
OriLng& OriLng:: operator < (char *LngCode) {
 
    lenBuffer = strlen(LngCode);
    strcat(Buffer, LngCode);
 
    CountTeg = 0;
    int endRead = 0;
    int a = 0, b = 0;
    char buffer[MAX_SYMBOL_NAME];
    while (endRead >= 0) {
        endRead = StartScan(b, buffer, a, b);
        if (endRead == 1) {
            Teg[CountTeg].StartSymbol = a;
            Teg[CountTeg].EndSymbol = b;
            strcpy(Teg[CountTeg].Teg, buffer);
            CountTeg++;
        }  //EndIf
    }  //EndWhile
}
 
/***********************************************************
 Функция ищет имя тега вместе с указаными скобками.
 StartPosition    - Адрес с которого начинается поиск
 NameTeg          - Буффер для найденого тега
 StartPositionTeg - Адрес, где был открыт тег
 EndPositionTeg   - Адрес, где был закрыт тег
 ********************************************************** */
int OriLng::StartScan(int StartPosition, char* NameTeg, int &StartPositionTeg,
    int &EndPositionTeg) {
 
    NameTeg[0] = '\x00';
    if (StartPosition > MAX_BUFFER_LNG)
        return false;
 
    int _count_symbol = 0;
    int CountTegSymbol = 0;
 
    for (int i = StartPosition; i <= lenBuffer; i++) {
        if (Buffer[i] == OPEN_TEG_SYMBOL) {
            StartPositionTeg = i;
            int WFor = i + MAX_SYMBOL_NAME;
 
            for (int w = i; w <= WFor; w++) {
                if (CountTegSymbol > MAX_SYMBOL_NAME - 1) {
                    sprintf(ErrorTeg, ERROR_LEN_TEG,    StartPositionTeg);
                    return 0;
                }
                CountTegSymbol++;
 
                if (Buffer[w] == CLOSE_TEG_SYMBOL) {
                    EndPositionTeg = w;
 
                    for (int k = StartPositionTeg; k <= EndPositionTeg; k++) {
                        NameTeg[_count_symbol] = Buffer[k];
                        _count_symbol++;
                    }
 
                    NameTeg[_count_symbol] = '\x00';
                    return 1;
                } //end if close symbol
            } // endfori
        } //end if symbol
    } //endfori
 
    return -1;
}
 
/***********************************************************
 Функция кладёт в буффер данные, указаные в скрипт языке.
 _buffer - буффер
 NameTeg - имя тега
 ********************************************************** */
 
int OriLng::ReturnData(char *_buffer, char *NameTeg) {
    _buffer[0] = '\x00';
    int StartDataRead = 0;
    int EndDataRead = 0;
    int NTeg = 0;
    // Найдем первый тег
    for (int i = 0; i < CountTeg; i++)
        if (strcmp(NameTeg, Teg[i].Teg) == 0) {
            StartDataRead = Teg[i].EndSymbol;
            NTeg = i + 1;
            break;
        }
 
    // Найдем его пару
    for (int i = NTeg; i < CountTeg; i++)
        if (strcmp(NameTeg, Teg[i].Teg) == 0) {
            EndDataRead = Teg[i].StartSymbol;
            break;
        }
 
    if (EndDataRead == 0)
        return 0;
 
    int count = 0;
    for (int i = StartDataRead + 1; i < EndDataRead; i++) {
        _buffer[count] = this->Buffer[i];
        count++;
    }
 
    return 1;
}
 
/***********************************************************
  Функция чистит буфер и теги
 ********************************************************** */
void OriLng::Clear() {
    Buffer[0] = '\0';
    CountTeg  = 0;
}


Первый минус который я нашел, это фиксированный размер буффера, но если его делать динамическим, возникает ряд проблем, но всё же сделаю позже его фиксированным.
Хорошо ли с производительностью? Не где не ошибся? Вроде более 1000 тегов грузились мгновенно.. Заранее спасибо..
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.10.2014, 05:21
Ответы с готовыми решениями:

Проверьте скрипт пожалуйста.
Дано: vlad@vlad-desktop:~/Загрузки$ ls -1 27 5.jpg 29 5.jpg 5 Ethernet.chm 94 58.jpg...

Пожалуйста, проверьте, есть ли ошибки в приведённом куске кода.
... unsigned short many = 10, people = 5; unsigned long int peep = 5, zood = 3; ...

Вычисление значения по формуле (пожалуйста, проверьте правильность кода)
Добрый день! Пишу программу, которая вычисляет значение по формуле (a + b^2) / (a – b + c) числа...

Проверьте реализацию бинарного поиска
Проверьте , пожалуйста , реализацию бинарного поиска . Пока только учусь , может какие-то...

6
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
22.10.2014, 07:42 2
Цитата Сообщение от Орион Посмотреть сообщение
Встала задача создать структурный язык на подобие xml, для передачи и приёма данных в моём протоколе
Прежде всего: почему потребовалось разрабатывать свой формат и вместе с этим писать свой парсер? Уже существует множество форматов и готовых библиотек для разбора json, xml, yaml, ini и т. д. Возможны варианты в духе "я это осознаю, но все равно хочу все написать самостоятельно", "это учебное задание и такие требования" или что-нибудь еще. Если же существующие форматы не подходят или есть сомнения в производительности/качестве библиотек - это уже повод остановиться и задуматься.

Цитата Сообщение от Орион Посмотреть сообщение
Между двумя тегами должны хранится данные.
Структура плоская, вложенных тегов быть не может?

Цитата Сообщение от Орион Посмотреть сообщение
Первый минус который я нашел, это фиксированный размер буффера
Используй std::string - сразу станет меньше головной боли.

Теперь к коду.
Прежде всего, пройтись с заменой s/teg/tag/.

Цитата Сообщение от Орион Посмотреть сообщение
C++
1
class OriLng
Не сокр.
Уже тут неконсистентность в именовании:
Цитата Сообщение от Орион Посмотреть сообщение
C++
1
#include "oriLang.h"
Цитата Сообщение от Орион Посмотреть сообщение
C++
1
Lng < "<Логин>Orion<Логин>"
Неочевидное использование оператора <, который практически всегда используется для сравнения. Лучше написать метод с человекочитаемым названием. А если уж хочется оператором, то лучше в стиле стандартных потоков: <<.

Цитата Сообщение от Орион Посмотреть сообщение
C++
1
2
3
4
5
#define MAX_BUFFER_LNG 40000
#define MAX_TEG_LEN * *1000
#define OPEN_TEG_SYMBOL *'<'
#define CLOSE_TEG_SYMBOL '>'
#define MAX_SYMBOL_NAME 33
Заменить все константами.

Цитата Сообщение от Орион Посмотреть сообщение
C++
1
#include <iostream.h>
iostream

Цитата Сообщение от Орион Посмотреть сообщение
C++
1
_buffer[count] = this->Buffer[i];
Идентификаторы, начинающиеся с подчеркивания, зарезервированы.

Цитата Сообщение от Орион Посмотреть сообщение
Хорошо ли с производительностью?
Преждевременная оптимизация - корень всех зол.

Цитата Сообщение от Орион Посмотреть сообщение
Не где не ошибся?
s/Не где/Нигде/
Чтобы ответить на этот вопрос, достаточно покрыть код тестами.
Что произойдет, если не подавать на вход конфиг, но попытаться получить значение? Если подать пустой конфиг? Если подать невалидный конфиг?
Вроде бы ни в одном случае ничего не падает, но проявляется одна проблема: в случае невалидного конфига нет механизма сообщений об ошибке.

И еще замечание. Функции возвращают 1, 0, -1 для сообщения о результате выполнения. лучше использовать именованые константы. Или бросать исключения.
1
1 / 1 / 1
Регистрация: 28.04.2013
Сообщений: 35
22.10.2014, 09:15  [ТС] 3
Спасибо за ваш пост!
Цитата Сообщение от 0x10 Посмотреть сообщение
это учебное задание
Небольшая часть от дипломной)
Цитата Сообщение от 0x10 Посмотреть сообщение
Структура плоская, вложенных тегов быть не может?
По началу, по плану хотел создать с вложенными тегами, но потом планируя алгоритм по обращению к тегу, понял что удобнее обращаться к плоским тегам. Напишу пару сетевых программ, там будет видно, что лучше, плоские структуры или нет.
Цитата Сообщение от 0x10 Посмотреть сообщение
то лучше в стиле стандартных потоков: <<
Вы правы.
Цитата Сообщение от 0x10 Посмотреть сообщение
Заменить все константами.
Поясните почему?
Цитата Сообщение от 0x10 Посмотреть сообщение
Что произойдет, если не подавать на вход конфиг, но попытаться получить значение?
Ничего не произойдет. Если нужна проверка, то метод ReturnData возвращает 0, если не был найдет тег или у тега нет пары(т.е он не закрыт)..
Цитата Сообщение от 0x10 Посмотреть сообщение
в случае невалидного конфига нет механизма сообщений об ошибке.
Есть небольшой механизм - это обращение к ErrorTeg, после вашего поста увеличил число ошибок, который в него подгружается, в случае их возникновения..
Цитата Сообщение от 0x10 Посмотреть сообщение
И еще замечание. Функции возвращают 1, 0, -1 для сообщения о результате выполнения. лучше использовать именованые константы. Или бросать исключения.
Но ведь она приватная функция и пользователю нет дела, что она возвращает
Еще раз спасибо!
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
22.10.2014, 09:29 4
Цитата Сообщение от Орион Посмотреть сообщение
Поясните почему?
Правило хорошего тона - использовать препроцессор только в случае необходимости, во всех остальных - обходиться языковыми средствами.

Цитата Сообщение от Орион Посмотреть сообщение
Ничего не произойдет
Все-таки нужно, мне кажется, строже валидировать входные данные. Иначе получаем "мусор на входе - мусор на выходе". Причем мусор на выходе отследить сложно.
Пример. Вот такой конфиг совершенно спокойно принимается парсером. <login>0x10<pass>42<pass>. И при запросе pass возвращается именно 42. При запросе login - не получим ничего. Нелогично. Если данные были невалидны, то по хорошему мы не должны ничего делать.

Цитата Сообщение от Орион Посмотреть сообщение
Есть небольшой механизм, это обращение к ErrorTeg
Я сразу как-то проглядел его. Это чисто сишный подход - хранить ошибку последней операции как состояние. Порождает ряд проблем.
1. Состояние имеет смысл только непосредственно после вызова функции. Следовательно, нужно контролировать его использование.
2. Не подходит для случаев, когда объект разделяется несколькими потоками.

Конкретно здесь ни то, ни другое, возможно, и не проявит себя.

Цитата Сообщение от Орион Посмотреть сообщение
Но ведь она приватная функция и пользователю нет дела, что она возвращает
К этому и другим вопросам, где причины моих замечаний были неочевидны. Небольшие программы многое могут стерпеть, поэтому на изменениях не настаиваю.
0
1 / 1 / 1
Регистрация: 28.04.2013
Сообщений: 35
22.10.2014, 09:45  [ТС] 5
Цитата Сообщение от 0x10 Посмотреть сообщение
Правило хорошего тона - использовать препроцессор только в случае необходимости, во всех остальных - обходиться языковыми средствами.
Работая с исходными кодами одной корейской мморпг, вижу использования препроцессора, похоже заразился такой привычкой..
Пруф: http://c2n.me/j8hpbK
В других проектах как-то не обращал внимания..
Цитата Сообщение от 0x10 Посмотреть сообщение
<login>0x10<pass>42<pass>. И при запросе pass возвращается именно 42. При запросе login - не получим ничего. Нелогично.
http://c2n.me/j8hu20 Тип данной ошибки добавил, а так она исключалась в моём коде, просто её не было в ErrorTeg.. упс, за teg простите
Цитата Сообщение от 0x10 Посмотреть сообщение
Конкретно здесь ни то, ни другое, возможно, и не проявит себя.
Верно и из примера выше, вроде удобнее )
0
XI
0 / 0 / 0
Регистрация: 22.10.2014
Сообщений: 3
22.10.2014, 09:51 6
Автор, попробуйте boost::spirit. Ручной парсинг - дело неблагодарное.
0
1 / 1 / 1
Регистрация: 28.04.2013
Сообщений: 35
22.10.2014, 10:00  [ТС] 7
Цитата Сообщение от XI Посмотреть сообщение
Автор, попробуйте boost::spirit. Ручной парсинг - дело неблагодарное.
Спасибо, но.. у меня курсовая по небольшой сетевой библиотеке, будет странным, если она будет с boost asio и прочими средствами из данной библиотеки
0
22.10.2014, 10:00
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
22.10.2014, 10:00
Помогаю со студенческими работами здесь

Silverlight - геометрический мини-язык в коде
Вопрос такой, есть ли возможность создать объект Path из строки, содержащей описание в виде...

Как перевести на немецкий язык мини-диалог?
Мне потребовалось перевести на немецкий язык следующий текст На сельской дискотеке парень...

Не могу понять реализацию кода
Всем доброго времени суток. В PHP не сильно силён, только начал изучать Есть такой код &lt;div...

Вынеси реализацию в файл кода
Есть файл dop.h помогите пожалуйста сделать 2 файла dop.cpp и dop.h #ifndef DOP_H #define DOP_H...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru