Двойное условие в while

Тема в разделе "WASM.ZEN", создана пользователем cresta, 24 окт 2005.

  1. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87


    мой стиль... Копирайтов не держу и честно признаю что он в немалом навеян стилем Торвальдса:



    static char *next_line (char *line, char ch, char *text)

    {

    while (text[0] == '\x0a' || text[0] == '\x0d')

    text ++;



    /* проверка на '\0' тут не нужна случайно? */

    if (text[0] != ch)

    return NULL;



    while (text[0] != '\x0a' && text[0] != '\x0d')

    (line++)[0] = (text++)[0];



    line[0] = '\0';



    return text;

    }



    static char *first_line (char *line, char ch, char *text)

    {

    while (1) {

    /* условия можно было бы и не переставлять,

    * но мне не нравиться конструкция text[-1] */

    if (text[0] == '\x0a' || text[0] == '\x0d')

    if (ch == text[1])

    return next_line (line, from);

    text ++;

    }

    }



    void Fill_List(int buttonID)

    {

    char buffer[256];

    char* lpText;

    char ch;



    GetDlgItemText (hWnd, buttonID, buffer, 256);

    cr_strlcase (buffer); // перевод caption в нижний регистр



    ch = buffer[0];



    lpText = ch < 0 ? lpRus : lpEng; /* так просто короче */



    SendMessage (hList, LB_RESETCONTENT, 0, 0);



    for (lpText = first_line (buffer, ch, &lpText[2]);

    lpText != NULL;

    lpText = next_line (buffet, ch, lpText)) {



    SendMessage (hList, LB_ADDSTRING, 0, (LPARAM)buffer);

    }



    }



    [add] блин извиняйте, забыл табуляции заменить пробелами :dntknw:.
     
  2. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    cresta

    > "Строки разделены последовательностью 0D0A"

    В таком случае не обязательно в while использовать двойное условие ;) Обычно при сканировании проверяется только 0Dh, а проверка 0Ah делается (на всякий случай ;) после того как встретился 0D.

    > "первую строку не читаем (по тех. причинам)"

    Видать у тебя там 0D0A сидит (иначе бы твой код пропускал первую строку). А говоришь без оптимизации ;)



    Что касается стиля, то при сканировании char* обычно не имеет смысла использовать индексы, проще инкрементировать сами указатели lpText и char* p = &buffer. Что собс-но и видим в стиле rgo, навеянном стилем Торвальдса etc ;) ИМХО - классика ;))
     
  3. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    rgo

    Спасибо. Хотя на мой взгляд дробление на мелкие процедуры только усложняет чтение кода. А цикл
    Код (Text):
    1. for (lpText = first_line (buffer, ch, &lpText[2]);
    2.      lpText != NULL;
    3.      lpText = next_line (buffer, ch, lpText))


    Уж больно запутано выглядит. Или это правило такое: чем больше непонятности и абстракции, тем лучше :)

    Переделал процедуру так:
    Код (Text):
    1.  
    2. void Fill_List(int buttonID)
    3. {
    4.     char    buffer[256];
    5.     char*   lpText;
    6.     int     i=2;
    7.  
    8.     GetDlgItemText(hWnd, buttonID, buffer, 256);
    9.     cr_strlcase(buffer);
    10.     if ( buffer[0] < 0 )
    11.         lpText = (char*) lpRus;
    12.     else
    13.         lpText = (char*) lpEng;
    14.  
    15.     SendMessage (hList, LB_RESETCONTENT, 0, 0);
    16.        
    17.     while (i++)
    18.         if ( buffer[0] == lpText[i] && *((short*) (lpText+i-2))==0x0A0D ) break;
    19.     lpText += i;
    20.  
    21.     do
    22.         {
    23.         i = 0;
    24.         while ( *((short*)(lpText+i))!=0x0A0D )
    25.             buffer[i++] = lpText[i];
    26.         buffer[i] = 0;
    27.         lpText += i+2;
    28.         SendMessage (hList, LB_ADDSTRING, 0, (LPARAM) buffer);
    29.         }
    30.     while ( *(lpText) == buffer[0] );
    31.    
    32. }
    33.  




    Это тоже неправильный стиль?
     
  4. rgo

    rgo New Member

    Публикаций:
    0
    Регистрация:
    21 мар 2005
    Сообщения:
    87


    Это упрощает Fill_List. Проще дорубить, что основная работа -- это цикл перебирающий строчки. Понятно что делается с каждой строчкой. А если добавить комменты к функциям, то станет понятно какие строчки перебираются. При этом потенциальный изучатель кода, будет иметь возможность даже не вникать в структуру buffer.





    нет неправильного стиля :) Стили бывают удобными, бывают неудобными, но это очень субъективно.

    Вот когда нету стиля, тогда сливай воду.
     
  5. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    cresta

    Ну так придирайся ...

    ok. О программе в твоем сообщении Дата: Окт 26, 2005 00:07:34



    Ошибки в логике:

    1) "первую строку не читаем (по тех. причинам)" - надо искать первый конец строки, а не пропускать два байта

    2) где проверка выхода за пределы lpText, т.е. как поведет себя программа, если в исходном файле нет слов на требуемую букву или буква соответствует последним строкам, т.е. что в буфере за данными.



    По поводу стиля:

    Наличие глобальных переменных, например, hWnd, lpRus, lpEng, hList - неудачное решение.



    По поводу алгоритма:

    Для нахождения слов на последнюю, или несуществующую, букву просматривается весь буфер/файл - это требует времени.
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    q_q



    Интересно, глобальная hInstance — тоже "неудачное решение"?
     
  7. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    IceStudent







    Это не глобальная переменная. Это свойство объекта "Процесс" :derisive:
     
  8. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    _DEN_

    То с точки зрения системы. А с точки зрения организации кода — именно глобальная переменная. В случае наличия только 1 окна с hWnd выходит тоже самое. Или оборачивать hWnd в синглтон? :lol:
     
  9. _DEN_

    _DEN_ DEN

    Публикаций:
    0
    Регистрация:
    8 окт 2003
    Сообщения:
    5.383
    Адрес:
    Йобастан
    IceStudent



    А не надо судить об организации по конкретному коду. Смотри на идею в целом ;) В винде только один синглтон - винда :derisive: Остальное - объекты.
     
  10. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Винда сама по себе из объектов состоит.
     
  11. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    IceStudent

    глобальная hInstance — тоже "неудачное решение"

    Да.

    Или вопрос с подвохом? Ты знаешь, случаи, когда значение hInstance нельзя получить оперативно?



    На мой взгляд, любая глобальная переменная - неудачное решение, так как лишает код свободы. В данном случае код жестко привязан к конкретным буферам, окну с кнопками и listbox'у. Если посмотреть на задачу под другим углом, то необходимо из некоторого текстового файла найти строки, которые начинаются на определенный символ, т.е. входные параметры - имя файла и символ, выходные каким-либо образом организованный список строк. Над решением этой задачи и надо работать. Причем тут окна, кнопки и др. элементы управления?
     
  12. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    q_q

    По-твоёму, всё, что можно получить оперативно, нужно получать оперативно?





    С этим согласен.
     
  13. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    IceStudent

    Не надо обобщать. Речь не обо всем, а о глобальных переменных.
     
  14. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    q_q

    Ну я их и имел ввиду.
     
  15. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    q_q





    Поясняю: первая строка как минимум состоит из двух байт (0D0A), поэтому пропуская их, я всё равно не перескачу через начало второй строки. В самом удачном случае как раз на начале второй строки.







    Вот эта проверка (в самом конце процедуры):

    if ( *(lpText) != buffer[0] ) break;

    Я оговаривал, что память выделена VirtualAlloc, поэтому при достижениии конца текста в *(lpText) окажется ноль. Длина файла не кратна размеру страницы памяти, поэтому некоторое количество нулей будет обязательно. Первый же из них приведет к окончанию заполнения листа, т.к. буквы с кодом 0 нет.







    Вот два примера: поиск по последней букве (Z):

    а) время с занесением в лист при помощи SendMessage....LB_ADDSTRING - 16 мс

    а) время без занесения в лист (без SendMessage....LB_ADDSTRING) - 0 мс



    Вот ещё два примера: поиск по самой большой (в смысле кол-ва строк) букве (S):

    а) время с занесением в лист при помощи SendMessage....LB_ADDSTRING - 460 мс

    а) время без занесения в лист (без SendMessage....LB_ADDSTRING) - 0 мс



    Это показывает, что время, необходимое на занесение в список практически целиком определяется временем работы SendMessage. Поэтому оптимизировать эту процедуру, начиная поиск с предвычисленных (для каждой буквы) адресов смысла нет, хотя сначала именно так и было сделано: при чтении файла с диска в массив заносились адреса, с которых начиналась новая буква. Но оказалось, что овчинка не стоит выделки, поэтому эта квазиоптимизация была удалена.

    Если мы взвалили большой и тяжелый камень SendMessage на спину, нет никакого смысла сдувать с него пыль. Легче не станет :)



    О глобальных переменных и переносимости кода: при повторном использовании этой процедуры в другом приложении неплохо было бы хотя бы бегло просмотреть её, и заменить hList на что-то другое. Это правильней, чем наворачивать универсальность за счёт передачи нараметров через стек. ИМХО.
     
  16. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta



    Очень ошибочное имхо: copy/paste ни к чему хорошему не приводит. Разве что к появлению статей про индусских программистов :)
     
  17. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent

    Ну так а я о чём говорю: прежде чем делать copy/paste, надо хотя бы бегло просмотреть код, понять его работу. При этом и заметишь hList, и заменишь его на что-то другое.

    А универсализация на все случаи жизни - вот это и есть индусизация, чтобы индус просто взял и подключил универсальный кусок кода, не заглянув в него.
     
  18. q_q

    q_q New Member

    Публикаций:
    0
    Регистрация:
    5 окт 2003
    Сообщения:
    1.706
    IceStudent

    Про оперативность vs глобальные переменные. Зависит от ситуации.



    cresta

    первая строка как минимум состоит из двух байт

    А если больше? Как поведет себе программа?



    Длина файла не кратна размеру страницы памяти ...

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



    Вот два примера ...

    Программа будет работать только на том компьютере, на котором производились измерения и одновременно с теме же запущенными приложениями?



    неплохо было бы хотя бы бегло просмотреть её, и заменить ... чем наворачивать универсальность

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

    В данном случае, можно реализовать следующие подпрограммы:<ul type=disc><li>LPDICTIONARY DictionaryOpen(LPTSTR pszFileName, DWORD dwFlags) - приготовиться к работе со словарем;<li>BOOL DictionaryClose(LPDICTIONARY pDictionary) - завершить работу со словарем;<li>LPDICTIONARIFIND DictionaryFindFirstWord(LPDICTIONARY pDictionary, char ch, char *pszBuffer, DWORD dwBufSize) - начать поиск слов;<li>BOOL DictionaryFindNextWord(LPDICTIONARIFIND pDictionaryFind, char *pszBuffer, DWORD dwBufSize) - продолжить поиск;<li>BOOL DictionaryFindClose(LPDICTIONARIFIND pDictionaryFind) - завершить поиск.</ul>
     
  19. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    cresta

    Счастья в просмотре кода STL :)



    Если библиотека надёжна и документирована, то в код её заглядывать редко когда нужно. Это ведь время, которое лучше потратить на свой код.
     
  20. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    IceStudent







    Это не ко мне :))) Пусть stl'ом индусы пользуются.

    Я не поклонник стандартных либ и stl в частности.

    Надо мной не висит менеджер с угрозами увольнения, если работа не сделана в срок, поэтому я могу позволить себе каждую функцию реализовать с нуля, и мне пофиг, сколько времени я на неё потрачу. Это моё хобби, мне интересен сам процесс.



    q_q

    Программа написана под два файла с известными и фиксированными размерами. Обычный словарик.

    И если первая строка более 2 байт, то она всё равно пропустится.



    И на любом другом компе соотношения времени на процедуру с SendMessage и без неё будет примерно таким же. У тебя есть сомнения на этот счёт? Если не лень качать 700 кб зип, могу кинуть тебе готовую к проверке программу с файлами, проверишь :)





    Вот это принимается