Предлагаю на суд класс работы с ini

Разговоры на любые темы: вы можете обсудить здесь какой-либо сайт, найти единомышленников или просто пообщаться...
SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 17.06.2008 (Вт) 15:53

Тема стала популярной. Классно! А я всего лишь хотел показать то что сделал. А тут еще и узнал много. Добавлю в свой архив топиков.
Пишите жизнь на чистовик.....переписать не удастся.....

Ramzes
Скромный человек
Скромный человек
Аватара пользователя
 
Сообщения: 5004
Зарегистрирован: 12.04.2003 (Сб) 11:59
Откуда: Из гробницы :)

Сообщение Ramzes » 18.06.2008 (Ср) 19:44

Хакер писал(а):Да, кстати, сколько же стоит твоё время? :D

столько, сколько готова мне платить моя компания, а это (моя зп) не та вещь, которую я бы хотел обсуждать на форумах

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 0:07

Значитца так. Выкладываю опять. Если мона то хотел бы услышать повторные комментарии. Исправлял сегодня весь день, мож и упустил что.
Что сделано:
1.Счетчики теперь i и j, и они глобальны на уровне класса
2.Добавил поля количества секций и количества ключей
3.При получении какого-нибудь значения из массива (а значит и из файла) сначала проверяю есть ли там секциии(тогда пробегаю по ним в цикле) потом если надо в цикле , и есть ли ключи в этих секциях
4. поставил Explic (Знаю что ни так написал, просто вспоминать не захотел)
5.Появились константы [, ], ;, = на уровне класса
6.Исправил(вроде везде) тупое сравнение True с True
7.Проверяем существование файла ini, причем с деррикторией, и если нет ее, то создаем (Открыл для себя InStrRev)
8.Все аргументы теперь ByVal. Хакер. Первый урок на эту тему я уяснил. Но мне не надо нигде устанавливать параметр. Тогда зачем еще? Короче я опять сделал то что посоветовали не зная зачем это


Теперь о главном
Плюся для меня
1.Теперь не будет ошибок если в массиве ничего нет
2.Поле кол-во ключей и секцтй значительно упростило жизнь, но добавило if then ....геморрой, но безопаснее для конечного пользователя.

И...Что не сделано (Как я считаю)
Обратите внимание на DeleteSection и LoadIni
1.LoadIni
Я так и не смог сначало просчитать по циклу секции и ключи из массива строк файла, только потом переопределить массивы и потом записать все в массив секций и ключей. Все равно приходится переопределять на каддом шаге. При многократных пробах я максимум ушел от переопределения массива секций, но не массива ключей. Мысли след-е. Как только я находил секцию, я прибавлял к некому счетчику +1. Вышел из циклы, переопределил массив секций и записал значение в поле "кол. секций" Надо опять циклить для поиска ключей. После поиска соотв-но пишем для кадой секции поле "кол-во ключей" закончили цикл. Переопределяем массив ключей для каждой секции. Опять циклим для записи. Записываем. Сделать сделал, но скорость оказалась намного ниже чем при считывании навалом и переопределении в цикле каждый шаг. Оставил так. Что сделать не знаю.
2.DeleteSection
Процедура разбухла. И знаете из-за чего. Прочита статью ADLL-а. Все вроде понятно (Кроме того как это все происходит), но вот не работает для эл-та, который й-1 по счету. В этом случае он просто удаляет все данные из массива. Если можно, то подскажите смысл этих API-шек и (если сам не догадаюсь), как сделать как надо.

В целом по классу. Если есть еще какие-то замечания, я как и прежде жду критики и приму ее. Главное чтобы она была. Только тогда я чему-то научусь. Зарание спасибо
Вложения
C.rar
(4.42 Кб) Скачиваний: 105

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 1:13

Буду писать замечания по ходу обнаружения:

0) Почему столько ошибок в постинге? :)

1) Комментарии написаны отстойным образом.
2)
1.Счетчики теперь i и j, и они глобальны на уровне класса

Это совершенно зря. С какой целью-то? Работа с такими переменными происходит гораздо медленнее (адресация через Me идёт, во-первых, а во-вторых, БК заканчивается на любом вызове).
Так что надо юзать локальные переменные.

3) Почему везде используется Integer? Integer -- 16 битное число, и 32-разрядному процессору с ним работать тяжело (т.е. такая работа занимает больше времени).
Заменить все Integer на Long, кроме тех случаев, где требуется именно его 16-битность (я ещё не знаю, есть ли у тебя там такое, но читывая что я видел CopyMemory -- вполне может быть).

4)
Все аргументы теперь ByVal. Хакер. Первый урок на эту тему я уяснил.

Неправда. Optional ReMake As Boolean не ByVal.
А ещё Path As String у FileExists

5) Вывод ошибок сделан неправильно. Для вывода ошибок никогда (кроме некоторых случаев) не используют MsgBox. Если в программе возникает ошибка, то нужно использовать специальные средства языка, чтобы разобраться с этой ситуацией. Т.е. использовать Err.Raise. Можно использовать не Err.Raise, а возвращаемое значение (определить специальный набор констант для всех функций, каждая из которых будет обозначать определённую ошибку. Так делают большинство WinAPI-функций (почти так), и практически все COM-функции.

6) Очень много нареканий по культуре давать функциям/переменным/свойствам/константам имена:
  • По поводу констант.
    Константы принято давать имя в верхнем регистре и смысловые части разделять символом подчёркивания, причём слева обычно ставится общая для нескольких констант часть.

    Т.е. не Const MySuperConst а Const MY_SUPER_CONST. В vb, однако же, все константы названы не так, но тем не менее, везде принято давать константам названия именно так, как я показал.

    А что касается смысловой части, то надо делать не
    BAD_SYNTAX_ERROR,
    UNKNOWN_ERROR

    а
    ERROR_BAD_SYNTAX
    ERROR_UNKNOWN.

    Во-первых, как только начинаешь читать такую константу, сразу понимаешь к чему она относится (особенно это актуально для длинных констант), а во-вторых, если напишешь ERROR_ и нажмёшь Ctrl+J, получишь список всех близких "по теме" констант.

    Те у тебя должно быть
    не Koler (что такое Koler вообще? В английском такого нет. Из какого этого языка?), а MARKER_EQUAL,
    не LeftD, а MARKER_BRACKET_LEFT,
    не RightD, а MARKER_BRACKET_RIGHT,
    не Comment, а MARKER_SEMICOLON или MARKER_COMMENT
    (semicolon -- точка с запятой)

    Называть строковую константу, содержащую символ точки с запятой, словом Comment вообще недопустимо.
  • По поводу типов
    Код: Выделить всё
    Private Type KeyI
        NameK As String     ' стало быть имя ключа
        ValueK As String    ' и значение
    End Type

    ' походу секция?
    Private Type Sect
        CountKey As Integer
        CountS As Integer       '\\Добавил поле количество секций
        NameS As String     ' таки имя
        ValuesS() As KeyI   ' массив ключей... ага
    End Type


    Ну вообще, я обычно применяю к User-Defined типам то же правило наименования, что и к константам, только ещё добавляю префикс T_ (например T_EXPORT_TABLE). Но это я так делаю -- вобщем то это не общепринятое правило.

    Но как бы там ни было, назвать "Sect" -- никуда не годится. Нет никаких поводов экономить на буквах, и делать "Sect" вместо "Section". "Section" будет намного понятнее, намного милее смотреться, нежели "Sect". К тому же, Sect может быть Sector-ом, Section-ом, Sectant-ом и возможно ещё чем-нибудь. Зачем писать в коде загадки? Код должен быть максимально прозрачен и понятен.

    В названиях членов типов абсолютной глупостью является приписывать буквы K и S в конце.

    Во-первых, и так понятно, что раз Name находится внутри Sect, то это имя секции, а не чего-либо ещё.

    Во-вторых, так ничего кроме NameK и ValueK нет, незачем приписывать K -- ступать всё равно не с чем.

    В-третьих, если всё-таки хочется сделать так, чтобы было видно, что Name ключа, а не чего-нибудь ещё, то делать это надо по правилам английского языка. Английский язык очень чувствителен к порядку слов. Скажем "key press" - это "нажатие клавишы" (или "ключевая пресса" :) ), а "press key" - "нажать клавишу".

    Поэтому, надо писать KeyName и KeyValue (или допустимо писать kName, kValue).

  • Код: Выделить всё
    Public Sub MakeINIFile(ByVal Path As String, Optional ReMake As Boolean)


    Ini - это не аббревиатура, так что лучше написать MakeIniFile. Аббревиатуры в программировании -- вообще беда (при выдумывании имён). Потому что граница слова теряется. Может быть INI+Fi... А может быть IN + IF + i...

    Кроме того, у аргументов функций необязательно, но желательно префиксально указывать её тип (венгерская нотация). Причём, это может быть как смысловой тип (венгерская для приложений), так и фактический (венгерская системная). Или комбинация.

    Например lValue, sName, bRemake.
  • По поводу переменных.
    Та же беда. FNumb. Так переменные не называют. Во-первых, я не вижу никаких причин сокращать. Во-вторых, очень плохо сокращать так, что сокращение совпадает с каким-то словом. В данном случае сократив Number до Numb мы получили "Оцепенение" (Numb).

    Кроме того, обычно делают в точности наоброт, не FNumb (file number), INumber (item number), а nFile, nItem, nSection. Это как раз таки пример "венгерской для приложений", когда префикс обозначает не фактический тип (Long или Integer), а смысл (number).



Продолжение следует.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 7:58

Почему столько ошибок в постинге?

Ночью писал, запарился......исправлю
Комментарии написаны отстойным образом.

Покажи как надо, седлал как смог....
Неправда. Optional ReMake As Boolean не ByVal.
А ещё Path As String у FileExists

Увидел, поменяю. Но не ответил на мой вопрос по этому поводу. Урок 2 в пользу ByVal будет?
Вывод ошибок сделан неправильно. Для вывода ошибок никогда (кроме некоторых случаев) не используют MsgBox.

Знаю. А в чем разница то? В том что в моем случае это по определению не ошибка, а окно сообщения с критическим выходом.
что такое Koler вообще? В английском такого нет. Из какого этого языка?
Колерантны..... :oops:
Причём, это может быть как смысловой тип (венгерская для приложений), так и фактический (венгерская системная). Или комбинация.

Ууууу.....даже так. Учту.

А в остальном. Все это только про прально непрально написано, не так красиво и т.д. Для меня на данном этапе очень важен функционал, а он сейчас страдает в как минимум двух процедурах. Вот здесь мне реально нужна помощь. Может я чего-то не знаю...
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 8:26

Покажи как надо, седлал как смог....

Седлал :)

Посмотреть как надо можно в исходниках одного интересного сложного проекта, который нафиг никому оказался не нужен.

(Но тот образ комментирования, который можно наблюдать там, не самый лучший, т.к. комментарии писались просто так, а как сопровождение к статье)

Хорошо комментировать вот так:
Код: Выделить всё
//
// Функция search_index_article($article_id,
//                              $article_name,
//                              $article_description)
// Назначение:
//   Прозводит поисковую индексацию товара, добавляя в таблицу поисковой
//   индексации записи для всех основ слов, встречающихся в описании и
//   названии товара.
// Аргументы:
//   $article_id            Идентификатор товара
//   $article_name          Наименование товара
//   $article_description   Описание товара
// Примечание:
//   Наименование и идентификатор функция очищает от несемантических данных сама.
// Среда работы:
//   Требует загруженности shanrak.php\bbcodes, DBMS-AL, минисистемы
//
function search_index_article($article_id, $article_name, $article_description)
{
    global $search_stopwords;
    global $db;

    if(!defined('STEMMER_PRESENT'))
    {
        inc('engine/search/wordbaser.php');
    }

    if(!isset($search_stopwords))
    {
        inc('engine/search/stopwords.php');
    }

    // Очищаем входные данные от несемантических элементов (bbcode-ов,
    // символов разметки и т.п.)



    $article_name        = bbcode_clear($article_name,        $article_id);
    $article_description = bbcode_clear($article_description, $article_id);

    $article_name        = html_entity_decode($article_name);
    $article_description = html_entity_decode($article_description);

    // Сначала выделим из текста слова ( \w+ )

    preg_match_all('/\b\w+\b/', $article_name, $keywords_name);
    preg_match_all('/\b\w+\b/', $article_description, $keywords_descr);

    $keywords_name  = $keywords_name[0];
    $keywords_descr = $keywords_descr[0];


    // Затем сократим их до основ

    $keywords_name  = array_map('stemmer_process_word', $keywords_name);
    $keywords_descr = array_map('stemmer_process_word', $keywords_descr);

    // Затем убирём повторяющиеся основы

    $keywords_name  = array_unique($keywords_name);
    $keywords_descr = array_unique($keywords_descr);

    // Затем исключим из них стоп-слова
    $keywords_name  = array_values(array_diff($keywords_name,  $search_stopwords));
    $keywords_descr = array_values(array_diff($keywords_descr, $search_stopwords));


    // Соберём INSERT-запрос для обоих типов слов:

    for($i = 0; $i < count($keywords_name); $i++)
    {
        $parts[] = "('{$keywords_name[$i]}', '1', '$article_id')";
    }

    for($i = 0; $i < count($keywords_descr); $i++)
    {
        $parts[] = "('{$keywords_descr[$i]}', '2', '$article_id')";
    }


    $insertion_clause = join(",\r\n", $parts);
    $sql = "INSERT INTO `t_search_index`
            (`si_keyword`,
             `si_context`,
             `si_article_id`)
            VALUES
            " . $insertion_clause;

    $db->query($sql);
    if($db->error_info(EI_NUMBER))
    {
        error_die(CRITICAL_ERROR, "Не удаётся произвести поисковую индексацию товара [ID товара = '$article_id']. Сбой при работе с БД.".dberrordef());
    }
}


Хорошо писать (имеется в виду отступы, способы наименования констант, переменных и функий) вот так:

Код: Выделить всё
    Select Case lSize
        Case 0 To POOL_MIN_SIZE
            ' Нам нужен пустой кипер.
            InfoProvider.AddFromString POOL_KEEPER_PREFIX + _
                                       POOL_KEEPER_POSTFIX
            AllocateCodePool = POOL_MIN_SIZE
            Exit Function
           
        Case POOL_MIN_SIZE To POOL_1Q_SIZE
            ' Нам нужен кипер с одним квантом
            InfoProvider.AddFromString POOL_KEEPER_PREFIX + _
                                       POOL_KEEPER_QUANT + _
                                       POOL_KEEPER_POSTFIX
            AllocateCodePool = POOL_1Q_SIZE
            Exit Function
           
        Case POOL_1Q_SIZE To POOL_2Q_SIZE
            ' Нам нужен кипер с двумя квантами
            InfoProvider.AddFromString POOL_KEEPER_PREFIX + _
                                       POOL_KEEPER_QUANT + _
                                       POOL_KEEPER_QUANT + _
                                       POOL_KEEPER_POSTFIX
            AllocateCodePool = POOL_2Q_SIZE
            Exit Function
                       
        Case Is > POOL_2Q_SIZE
            ' Нужен кипер с множеством квантов
            Dim lQuants                     As Long
            Dim sBuffer                     As String
            lQuants = Ceil(lSize - POOL_CONST_SIZE, POOL_GROW_QUANT) \ POOL_GROW_QUANT
            AllocateCodePool = POOL_CONST_SIZE + POOL_GROW_QUANT * lQuants
           
           


Но комментарии вида

Код: Выделить всё
Dim str As String ' Ну это наверноме может быть таки буфер???


недопустимы.


Знаю. А в чем разница то? В том что в моем случае это по определению не ошибка, а окно сообщения с критическим выходом.

Такого рода функции не должн выдавать сообщений с критическим выходом. Они должны возвращаться и каким-либо образом (любым: через Err, через возврат, через что-то ещё) сообщать вызывающей стороне о том, что произошла ошибка. А вызывающая сторона сама решит, либо грохнуть программу и сообщить об ошибке, либо передать сведения об ошибке выше -- своей вызывающей стороне. А та, возможно, своей.
Это считается хорошим тоном.

Заметь, ни одна API-функция не кричит об ошибке и не убивает программу. Она просто возвращает соответствующий результат (например 0), и помещает информацию об ошибке в специальное место, из которого её потом можно получить с помощью GetLastError.

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

А в остальном. Все это только про прально непрально написано, не так красиво и т.д. Для меня на данном этапе очень важен функционал, а он сейчас страдает в как минимум двух процедурах. Вот здесь мне реально нужна помощь. Может я чего-то не знаю...

Видишь ли. Узнать чего-то можно всегда.

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

Так что это, кажется, намного важнее.

К тому же, все те замечания, что я расписал, -- для их обнаружения достаточно беглого просмотра. А чтобы сказать что-то конкретное по поводу кода, нужно его как миниум трейсить или долго читать.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 8:57

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

Вот смотри. Уже во второй раз я выложил, и уже что-то исправил. То есть я исправляю по ходу, учусь по ходу событий. Когда выложу след. раз думаю именование констант, функций и т.д. и комментарии придут в порядок. По карйней мере я сижу сейчас и пишу прогу уже с учетом косяков, указанных тобой.
Все же. Хакер, удели секунду и помоги если можешь с функционалом...
Пишите жизнь на чистовик.....переписать не удастся.....

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 9:01

интересного сложного проекта, который нафиг никому оказался не нужен.

Отзывов куча а никому не нужен?
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 9:02

SLIM
Где ты увидел кучу отзывов?

(пишу продолжение оценки)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 9:07

Где ты увидел кучу отзывов?

Ну восхищений то точно было куча

(пишу продолжение оценки)

Это хорошо. Жду
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 9:17

Ну восхищений-то точно было куча

Угу, 10 человек, из них 2-3 не по теме.

Но, дело не в этом. Дело в том, что никто не юзает. Я потратил очень много времени чтобы сделать общедоступный инструмент. Сделать DLL-ку с экспортами я мог бы себе сам с помощью отладчика и Hex-редактора, и это зянало бы минут 10. А здесь ... и в пустую.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 9:26

Но, дело не в этом. Дело в том, что никто не юзает. Я потратил очень много времени чтобы сделать общедоступный инструмент. Сделать DLL-ку с экспортами я мог бы себе сам с помощью отладчика и Hex-редактора, и это зянало бы минут 10. А здесь ... и в пустую.

Как дорасту думаю поюзаю.... ты еще отвечать будешь?
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 9:48

7) Код неплохо бы разрывать пустыми строчками, чтобы отделять связанные смыслом блоки друг от друга.

8) Я думал, это описка, но выяснилось, что и в коде также. ANDLL, а не ADLL :)

9)
Код: Выделить всё
Err.Raise 10, , "Откуда такая сеция?" 'нут тут понятно, проверяем правильность индекса

Нет, нет и нет.

Во-первых, номер 10 использовать нелья - это номер стандартнй ошибки 10 :: This array fixed or temporary locked. Во-вторых, в качестве описание ошибки строку "Откуда такая секция?" использовать недопустимо.

10) Посмотрел на твою возню с удалением добавлением. Так вот, если предполагается частое удаление/добавление, то лучше использовать коллекции или связанные списки.

11) ReedStrg -- это хранилище камыша, не иначе. Потому что Reed -- это камыш, а Strg -- более-менее устоявшееся сокращение для Storage. По крайне мерее, более устоявшиеся, чем для String.

Но даже если бы там было ReadString, всё равно это какое-то косой название для переменной. Buffer куда лучше.

12)
Код: Выделить всё
    Open Path For Input As FNumber ' Считываем по строкам в массив
    Do While Not EOF(FNumber) 'До конца файла
        Line Input #FNumber, ReedStrg 'Читаем очередную строку в пер-ю ReedStrg
        i = i + 1 'прибавляем к счетчику 1
        ReDim Preserve ArrayString(i) 'Переопределяем массив на значение счетчика
        ArrayString(i) = ReedStrg 'Записываем в последний эл-т строку
    Loop 'Следующая строка
    Close FNumber 'Закарываем файл


Постоянный ReDim Preserve не лучшим образом сказывается на производительности.

Я бы сделал иначе. Сделал бы гранулярность изменения побольше. Т.е бы делал в массиве изначально 256 элементов. И читал строки в низ. Если бы при выделении этих 256 не хватало бы - выделял бы ещё 256 и продолжал бы читать.
По достижении EOF, удалял бы лишнюю часть.

С другой стороны, на фоне чтения это мало что даст.

Так что я бы, как я тебе уже говорил, прочитал весь файл разом в буфер, а потом бы его обрабатывал.

13)
Код: Выделить всё
        If i > 0 Then 'Если строки есть то
        For i = LBound(ArrayString) To UBound(ArrayString) 'С верха до низу массива строк
            'Если левый символ строки без пробелов по бокам равен [ то...
            If Left$(LTrim$(RTrim$(ArrayString(i))), 1) = LeftD Then
                IndexSec = IndexSec + 1 'прибавляем счетчик секций
                ReDim Preserve SectionArr(IndexSec) 'Переопределяем массив секций на значение счетчика секций
                'заодно записываем имя секции без пробелов с двух сторон
                SectionArr(IndexSec).NameS = LTrim$(RTrim$(ArrayString(i)))
                'В поле CountS записываем кол-во секций
                SectionArr(1).CountS = IndexSec
                'Ключей в этой секции 0
                SectionArr(IndexSec).CountKey = 0
                Index = 0 'обнуляем счетчик ключей, т.к. след-й видимо будет ключ
            Else 'Иначе если слева не [, то...
                If Left$(LTrim$(RTrim$(ArrayString(i))), 1) <> Comment Then 'Если это не комментарий, то
                    If InStr(1, ArrayString(i), Koler) > 0 Then 'Если в строке есть знак =, то..
                        Index = Index + 1 'Мы нашли ключ, прибаляем счетчик ключей на 1
                        'Записываем в поле CountKey значение кол-ва ключей секции IndexSec
                        SectionArr(IndexSec).CountKey = Index
                        'Переопределяем маасив ключей в секции IndexSec на значение счетчика Index
                        ReDim Preserve SectionArr(IndexSec).ValuesS(Index)
                        'Записываем туда имя ключа и его значение без пробелов и знака =
                        SectionArr(IndexSec).ValuesS(Index).NameK = LTrim$(RTrim$(Mid$(LTrim$(RTrim$(ArrayString(i))), 1, InStr(1, (LTrim$(RTrim$(ArrayString(i)))), "=") - 1)))
                        SectionArr(IndexSec).ValuesS(Index).ValueK = LTrim(RTrim$(Mid$(LTrim$(RTrim$(ArrayString(i))), InStr(1, LTrim$(RTrim$(ArrayString(i))), "=") + 1)))


Первое, и самое главное -- Назачем 10 раз вычислять RTrim от RTrim-а от строоки. Надо обрезать строку один раз, а потом работать с обрезанной. Обрезание строки - очень медленная операция. Чем меньше операций со строками - тем лучше для производительности (тебе ведь её, кажется, не хватало?)

И второе: Вместо LTrim(RTrim(..)) надо использовать Trim(...).

Третье: ты так и не избавился от дурацкого парсинга, основанного на Mid$, InStr, Trim$ и прочей гадости (в рамках парсинга).

Четвёртое:
Код: Выделить всё
[Section] ; Комментарий
foo=123 ; Тоже комментарий

; Такой "код" твой модуль не переварит...


14)
Код: Выделить всё
Public Sub AddKeyInSection(ByVal Section As String, ByVal Key As String, ByVal ValKey As String)End Sub


Вообще, у тебя какая-то помесь ООП-а с ПОП-ом.
Если ты применяешь ООП, так будь добр, применяй его в полной мере.
Т.е. если ты используешь класс, и даёшь мне возможность написать

Код: Выделить всё
Dim myIni As C

' ...

myIni.MakeINIFile(...)


то вместо
Код: Выделить всё
myIni.AddKeyInSection "MySect", "Вес", "900кг"

дай мне возможность писать
Код: Выделить всё
myIni.Sections("MySect").AddKey "Вес", "900кг"

Это будет во-первых правильнее, а во-вторых, если не криво сделать, то будет выигрыш по производительности. У тебя AddKeyInSection каждый перебирает все секции и ищет нужную, что очень неэффективно. Если ты сделаешь так, как я сказал, то во-первых, это будет быстрее, потому что коллекция более интеллектуально и найдёт нужный элемент по строке быстее, чем ты со своим циклом+сравнением.
А во-вторых, если надо добавить несколько ключей в одну секцию, можно будет сделать так:
Код: Выделить всё
Dim MySect As CSection

Set MySect = myIni.Sections("MySect")

MySect.AddKey "Weight", "900kg"
MySect.AddKey "Voltage", "380V"
MySect.AddKey "Protection", "IP20"

Set MySect = Nothing

(при таком подходе секция MySect ищется один раз. У тебя же если три раза добавлять ключи с помощью AddKeyInSection, нужная секция будет искаться каждый раз, что очень неэффективно).

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

(прожолжение следует)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 23.06.2008 (Пн) 10:11

Хакер писал(а):Дело в том, что никто не юзает. Я потратил очень много времени чтобы сделать общедоступный инструмент. Сделать DLL-ку с экспортами я мог бы себе сам с помощью отладчика и Hex-редактора, и это зянало бы минут 10. А здесь ... и в пустую.

А ты чего ожидал?
То что на форуме любят возмущаться "ай-ай-ай, VB не позволяет делать native dll, а мне без них никак не обойтись" не имеет никакого отношения к действительности, большинству людей native dll действительно не нужны. Поэтому и твой проект практического значения почти не имеет.
Что не мешает ему быть очень интересным академическим решением.
Lasciate ogni speranza, voi ch'entrate.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 10:18

Ожидал, что большинству людей native dll действительно будут нужны.

Вот, мне например, нужны. Я потому и не перестал копать, когда первый раз не получилось.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 10:19

Во-первых, номер 10 использовать нелья - это номер стандартнй ошибки 10 :: This array fixed or temporary locked. Во-вторых, в качестве описание ошибки строку "Откуда такая секция?" использовать недопустимо.
описание исправлю, а какой номер допустим?
Я бы сделал иначе. Сделал бы гранулярность изменения побольше. Т.е бы делал в массиве изначально 256 элементов. И читал строки в низ. Если бы при выделении этих 256 не хватало бы - выделял бы ещё 256 и продолжал бы читать.
По достижении EOF, удалял бы лишнюю часть.

Ну вот. Вот те некоторые мысли, которых мне не хватало

Так что я бы, как я тебе уже говорил, прочитал весь файл разом в буфер, а потом бы его обрабатывал.

Я тогда не понял, и сейчас не понимаю. В буфер - это куда.
Чем меньше операций со строками - тем лучше для производительности (тебе ведь её, кажется, не хватало?)

Про строки понял(странно правда - понял, а почему сразу не сделал). Производительности мне не хватало по сравнению с моей же первой кривой компазицией, ну и в сравнении с великим API

И второе: Вместо LTrim(RTrim(..)) надо использовать Trim(...).
Ага....и удаляем все пробелы вообще. А если в имени ключа два слова?

Третье: ты так и не избавился от дурацкого парсинга, основанного на Mid$, InStr, Trim$ и прочей гадости (в рамках парсинга).

??? Каким еще образом можно определить что в строке символ "=" или что левый символ равен "[" и т.д. Если есть, то я видимо пол жизни потерял...

Такой "код" твой модуль не переварит...

Блин, да, не переварит. И это плохо, надо переделывать

(при таком подходе секция MySect ищется один раз. У тебя же если три раза добавлять ключи с помощью AddKeyInSection, нужная секция будет искаться каждый раз, что очень неэффективно).

Да. Долго я искал и читал про коллекции и ООП. Но столкнулся только сейчас. И уже реально стал задумываться. Балван....

Посмотри, сколько мест для оптимизации нашлось

Да....простор для прямых руче.

(прожолжение следует)

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

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 10:32

описание исправлю, а какой номер допустим?

Допустимыми (рекомендуемыми к использованию) являются номера начиная с vbObjectError.

Т.е. у тебя должны быть константы, объявленный через vbObjectError + N.

Я тогда не понял, и сейчас не понимаю. В буфер - это куда.

Да хоть куда. Хоть в строковую переменную, хоть в байтовый массив, хоть в блок памяти выделенный с помощью HeapAlloc/VirtualAlloc/LocalAlloc/GlobalAlloc.

Ага....и удаляем все пробелы вообще. А если в имени ключа два слова?

Trim ничем не отличается от композиции двух функций LTrim(RTrim(...)) или RTrim(LTrim(...)).

Trim удаляет все пробелы слева и все пробелы справа, LTrim удаляет все пробелы слева, RTrim - справа.

Код: Выделить всё
Trim("   Hello            ") будет "Hello".
LTrim("   Hello            ") будет "Hello            "
RTrim("   Hello            ") будет "   Hello"
LTrim(RTrim("   Hello            ")) будет LTrim("   Hello") будет "Hello".


И в чём разница? И что ты хотел сказать своим "Ага"?


??? Каким еще образом можно определить что в строке символ "=" или что левый символ равен "[" и т.д. Если есть, то я видимо пол жизни потерял...

А ты посмотри на ДКА-лексер (или ДКА-парсер, -- не помню как он пиисал в комментариях, но я думаю, найдёшь) в Тёмычевском эвалюаторе.

Собственно, смысл в том, что все Trim-ы, Mid-ы и InStr-инги проходят по строке несколько раз. В то время как всё нужное можно сделать за один проход по строке.

Пробелы, например, вообще убирать не надо (т.е. не надо никаких Trim-ов).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Денис
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2734
Зарегистрирован: 07.11.2006 (Вт) 13:55
Откуда: Ейск, Краснодарский край

Сообщение Денис » 23.06.2008 (Пн) 10:48

Буфер, это хитрая фишка VB! :lol:
Инициализируется примерно так:
Код: Выделить всё
Dim Buffer as String
Программирование — богоизбранная дисциплина! Если бог и есть, то вселенную он скомпилировал, не иначе.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 12:14

И в чём разница? И что ты хотел сказать своим "Ага"?

Да, действительно не в чем :roll:
Да хоть куда. Хоть в строковую переменную, хоть в байтовый массив, хоть в блок памяти выделенный с помощью HeapAlloc/VirtualAlloc/LocalAlloc/GlobalAlloc.

А я куда считываю. В массив строковых переменных. Это не буфер? :?

Буфер, это хитрая фишка VB! Laughing
Инициализируется примерно так:

Гы :P :P :P :P :P
А ты посмотри на ДКА-лексер (или ДКА-парсер, -- не помню как он пиисал в комментариях, но я думаю, найдёшь) в Тёмычевском эвалюаторе.

Поищу.
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 12:26

А я куда считываю. В массив строковых переменных. Это не буфер?


Ты, скажем так, считываешь каждую строку в своей отдельный буфер. А надо весь файл целиком в цельный буфер. Чтобы потом одним единственным циклом обработать весь буфер.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 12:41

Т.е. потом разделить по строкам и работать с ним?
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 12:41

Нет, не надо вообще делить по строкам.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 12:52

:shock: Из одной строки вытащить все секции и ключи?
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 12:57

Давай сначала так.

Тестовое задание:
Есть строка вида:
Код: Выделить всё
    [   Ascschebka ]       [sdOipo ]   [ s]                    [kiam] [    olkun]

Задача: обработать её и вывести в debugout (Debug.Print "Ы!" если не знаешь, что это) строчки, которые содержатся внутри квадратных скобок:

Т.е. для приведённого выше примера надо вывести следующее:
Код: Выделить всё
Ascschebka
sdOipo
s
kiam


Примечание: кол-во пробелов между словами и скобками, и между скобками и скобками может быть любым.

Реализуй это в виде функции, принимающей входную строку.
Потом я покажу, как бы это сделал я, и это будет тебе почвой для размышлений на тему как всё это применить к обработке ini-файла.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 16:44

Debug.Print "Ы!" если не знаешь, что это

Ну не до такой же степени я новичок. Не обижай

Реализовал


Код: Выделить всё
Private Sub SectionFind(ByVal StringFind As String)
Dim OneSymbol As String
Dim OneSymbolInSection As String
Const LEFT_BRACKET = "["
Const RIGHT_BRACKET = "]"
Dim Section As String
Dim i As Long
Dim j As Long

For i = 1 To Len(StringFind)                            'С начала до конца строки
    OneSymbol = Mid$(StringFind, i, 1)                  'Один символ, вырезанный со строки с позиции i
    If OneSymbol = LEFT_BRACKET Then                    'Если он равен [ то....
        Section = vbNullString                          'Обнуляем название секции
        j = i + 1                                       'Находим позицию где начинается [, со следующей начинается имя секции
        OneSymbolInSection = vbNullString               'Символ для прочтения имени секции обнуляем
        Do While OneSymbolInSection <> RIGHT_BRACKET    'Делаем уикл, пока не найдем ]
            OneSymbolInSection = Mid$(StringFind, j, 1) 'Выризаем один исмвол из строки позиции j
            Section = Section + OneSymbolInSection      'В переменную Section прибавляем каждый символ
            j = j + 1                                   'Приращиваем j для выризания след-го символа
        Loop                                            'Убираем все пробелы и правую ]
        Section = Trim$(Mid$(Section, 1, Len(Section) - 1))
        Debug.Print Section                             'печатаем что получилось
        i = j - 1                                       'Чтобы опять не пробегать то что уже пробежали(При считывании имени секции)
                                                        'делаем так чтобы сдледуюий шаг начинался с того места где нашли последний ]
    End If
   
Next i
End Sub
Пишите жизнь на чистовик.....переписать не удастся.....

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16489
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 23.06.2008 (Пн) 16:49

Ок. Напишу свой вариант.

OneSymbolInSection = vbNullString 'Символ для прочтения имени секции обнуляем

1) И зачем обнулять?
2) И почему бы не использовать уже имеющуюся OneSymbol?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 23.06.2008 (Пн) 16:55

1) И зачем обнулять?
2) И почему бы не использовать уже имеющуюся OneSymbol?

Боюсь всего уже. :) Навсякий случай сделал :lol:
Пишите жизнь на чистовик.....переписать не удастся.....

pronto
Постоялец
Постоялец
 
Сообщения: 598
Зарегистрирован: 04.12.2005 (Вс) 6:20
Откуда: Владивосток

Сообщение pronto » 24.06.2008 (Вт) 15:01

Код: Выделить всё
       If Mid$(Buffer, i, 1) = LEFT_BRACKET Then

           j = i '+ 1

           Do
               j = j + 1
               OneSymbol = Mid$(Buffer, j, 1)

           Loop Until OneSymbol = RIGHT_BRACKET

           Section = Mid$(Buffer, i + 1, j - i - 1)
           Section = Trim$(Section)
           'Debug.Print Section
           i = j '- 1

       End If


Быстрее примерно на 30%
O, sancta simplicitas!

SLIM
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1840
Зарегистрирован: 04.04.2008 (Пт) 18:21
Откуда: Краснодар

Сообщение SLIM » 24.06.2008 (Вт) 21:54

pronto
Ну да. эт так....
Пишите жизнь на чистовик.....переписать не удастся.....

Zenitchik
Постоялец
Постоялец
 
Сообщения: 369
Зарегистрирован: 21.12.2006 (Чт) 14:48

Сообщение Zenitchik » 24.06.2008 (Вт) 22:04

Кстати, чем в txt разделены строки? vbNewLine или Chr(13)? В смысле, мне "лишние" символы ловить придется?

(решил поупражняться в написании КА на технологии из темы http://bbs.vbstreets.ru/viewtopic.php?t=36100 )
Знание английского языка - затрудняет понимание кода

Пред.След.

Вернуться в Народный треп

Кто сейчас на конференции

Сейчас этот форум просматривают: AhrefsBot и гости: 3

    TopList