Асемблер
От: zeny  
Дата: 23.06.04 18:09
Оценка:
Подскажите пожелуйста как решить эту задачу:
Необходимо сделать функцию, которая делает следующее:
Дана строка слов разделённых пробелами, найти слово максимальной длинны.
Зараннее благодарен!
Re: Асемблер
От: Dr_Sh0ck Беларусь  
Дата: 24.06.04 06:51
Оценка:
Здравствуйте, zeny, Вы писали:

Z>Подскажите пожелуйста как решить эту задачу:

Z>Необходимо сделать функцию, которая делает следующее:
Z>Дана строка слов разделённых пробелами, найти слово максимальной длинны.
Z>Зараннее благодарен!

"В лоб", что называется, и решай.
1. Поставь указатель на начало строки.
2. Найди первый символ, не являющийся пробелом. Добаляй к адресу размер 1 символа в байтах, пока не наткнешся на пробел.
3. Как только наткнулся на пробел, количество добавленных на шаге (2) символов и есть длина очередной строки
4. Сравниваешь полученную на шаге (3) длину с длиной предыдущей строки. И если она больше, то сохрани значение указателя.
5. Если не достигнут конец строки, переходи на шаг (2)
6. Как только достигнут конец всей строки, сохраненный указатель будет содержать начало самой длинной подстроки.

Давненько я на ассемблере ничего не писал, но это может выглядеть примерно так:
   mov di, offset _string ;в di загоняем адрес начала строки
   xor bx,bx              ;обнуляем bx - им будем индексировать
skip_spaces:
   mov al, [di+bx]        ;загружает первый символ строки
   inc bx
   cmp al, 020h           ;пропускаем все
   je skip_spaces         ;ведущие пробелы
   lea di, [di+bx-001h]   ;загоняем в di адрес первой подстроки (di = di + bx - 1)
   xor bx,bx
   xor cx,cxcx будем накапливать текущую наибольшую длину строки
next_char:
   mov al, [di+bx]
   inc bx
   or al, al              ;достигли конца строки?
   jz exit
   cmp al, 020h           ;если не достигли пробела,
   jne next_char          ;то продолжаем считать длину текущей подстроки
exit:
   cmp bx,cx              ;длина текущей построки больше, чем предыдущей?
   jna next_substring
   mov cx,bx              ;Если ДА, то сохраняем значение длины
   mov si,di              ;и указатель на эту подстроку
next_substring:
   lea di, [di+bx-001h]   ;переходим к следующему симаолу строки
   or al,al               ;достигли конца строки?
   jnz skip_spaces        ;если ДА, то выводим на печать самую длинную найденную подстроку
   ;на этом этапе в si находится начало самой длинной подстроки, а в cx - ее длина
   ;на экран ее можно вывести примерно так (хотя я тоже е уверен ибо многое забыл уже  :) )
   cld
   mov ah,00Eh
print_char:
   lodsb
   int 010h
   loop print_char


Этот код для ДОС-программы типа СОМ (те изначально CS=DS=ES=SS)

P.S. Это примерный код. Не гарантирую что он даже скомпилируется, ибо на асме не писал уже года 4
Do not fake yourself ;)
ICQ#: 198114726
Re[2]: Асемблер
От: glyph  
Дата: 24.06.04 12:21
Оценка:
Здравствуйте, Dr_Sh0ck, Вы писали:

D_S>Здравствуйте, zeny, Вы писали:

Z>>Подскажите пожелуйста как решить эту задачу:
Z>>Необходимо сделать функцию, которая делает следующее:
Z>>Дана строка слов разделённых пробелами, найти слово максимальной длинны.
Z>>Зараннее благодарен!

D_S>"В лоб", что называется, и решай.

Нееее...
D_S>1. Поставь указатель на начало строки.
Поскипал...
D_S>6. Как только достигнут конец всей строки, сохраненный указатель будет содержать начало самой длинной подстроки.
Зачем так?
Прощелкиваем всю строку. Запоминаем в массив номера позиций, в которой стоят пробелы. В конце цикла пишем в массив последним элементом длину строки. Затем находим попарные разности между элементами полученного массива и записываем рядом (все можно сделать в одном цикле). К примеру, получим что-то такое:
    Позиция    Разность
    3            12        (15-3)
    15            3        (18-15)
    18            5        (23-18)    
    23            5        (27-23)
    27            2        (29-27)
    29

Потом находим пару с самой большой разностью. Сразу получаем номер символа в строке и длину слова.
d TOXICITY — Chop Suey! d
Re[3]: Асемблер
От: Аноним  
Дата: 24.06.04 12:34
Оценка: +1
Здравствуйте, glyph, Вы писали:

G> Зачем так?


"Так" быстрее

G> Прощелкиваем всю строку. Запоминаем в массив номера позиций, в которой стоят пробелы. В конце цикла пишем в массив последним элементом длину строки. Затем находим попарные разности между элементами полученного массива и записываем рядом (все можно сделать в одном цикле). К примеру, получим что-то такое:


Гмм. А зачем это? В предыдущем решении все находится за один проход, а тут массивы какие то.
И потом где эти массивы находятся? Если в стэке или секции данных то вопрос а хватит ли их размера,
если в куче то надо еще ее выделять/освобождать.
Может ну его?
Re[3]: Асемблер
От: Dr_Sh0ck Беларусь  
Дата: 24.06.04 13:28
Оценка:
Здравствуйте, glyph, Вы писали:

D_S>>"В лоб", что называется, и решай.

G> Нееее...

Не надо мудрить, там где все просто

G>Прощелкиваем всю строку. Запоминаем в массив номера позиций, в которой стоят пробелы. В конце цикла пишем в массив последним элементом длину строки. Затем находим попарные разности между элементами полученного массива и записываем рядом (все можно сделать в одном цикле). К примеру, получим что-то такое:


Так было бы красивей, если бы ты заранее знал сколько элементов тебе понадобиться в таком массиве. Кроме того его еще хранить нужно где-то... Кроме того между подстроками может стоять не ожин пробел, а несколько... и т.д. и т.п.
Do not fake yourself ;)
ICQ#: 198114726
Re[4]: Асемблер
От: glyph  
Дата: 24.06.04 13:32
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Здравствуйте, glyph, Вы писали:


G>> Зачем так?


А>"Так" быстрее

Уверен?

G>> Прощелкиваем всю строку. Запоминаем в массив номера позиций, в которой стоят пробелы. В конце цикла пишем в массив последним элементом длину строки. Затем находим попарные разности между элементами полученного массива и записываем рядом (все можно сделать в одном цикле). К примеру, получим что-то такое:


А>Гмм. А зачем это? В предыдущем решении все находится за один проход, а тут массивы какие то.

А тут что, 10? Тут тоже все в одном цикле. В моем случае ты получишь длины всех слов и их положения внутри подстроки. В варианте Dr_Sh0k — самой длинной.
А>И потом где эти массивы находятся? Если в стэке или секции данных то вопрос а хватит ли их размера,
А>если в куче то надо еще ее выделять/освобождать.
А>Может ну его?
Однозначно этот массив потребует места меньше чем, твоя строка.

А если внимательно прочитать оба поста, то станет ясным, что алгоритм одинаковый, просто я предлагаю подсчитывать длину слова не итерациями, а как разность между старым значением указателя на пробел и текущим. Ну, и итерирование по строке можно делать по stos. Или тебя вообще интересует мой вариант кода?
d Unknown Artist — Mano8703 d
Re[5]: Асемблер
От: Аноним  
Дата: 24.06.04 14:38
Оценка:
Здравствуйте, glyph, Вы писали:

А>>"Так" быстрее

G> Уверен?

Вопрос риторический. Да — уверен...

А>>Гмм. А зачем это? В предыдущем решении все находится за один проход, а тут массивы какие то.

G> А тут что, 10? Тут тоже все в одном цикле. В моем случае ты получишь длины всех слов и
G> их положения внутри подстроки. В варианте Dr_Sh0k — самой длинной.

Если бы по условиям задачи надо было найти длины всех слов — базару нет был бы нужен и массив и пробег по нему.

G> А если внимательно прочитать оба поста, то станет ясным, что алгоритм одинаковый,

G> просто я предлагаю подсчитывать длину слова не итерациями, а как разность между старым
G> значением указателя на пробел и текущим.
G> Ну, и итерирование по строке можно делать по stos. Или тебя вообще интересует мой вариант кода?

Ради б.га, но массивы-то зачем?
Re[4]: Асемблер
От: glyph  
Дата: 25.06.04 08:40
Оценка:
Здравствуйте, Dr_Sh0ck, Вы писали:

D_S>Так было бы красивей, если бы ты заранее знал сколько элементов тебе понадобиться в таком массиве. Кроме того его еще хранить нужно где-то... Кроме того между подстроками может стоять не ожин пробел, а несколько... и т.д. и т.п.

Ну, нам надо переехать в "Философию". Количество пробелов можно запросто оценить. Их будет не больше, чем длина строки. Определения термина "слово" не было, поэтому два пробела запросто можно считать как слово нулевой длины.
Короче, смысл не в этом.
d Бесы d
Re[4]: Асемблер
От: glyph  
Дата: 25.06.04 08:40
Оценка:
Здравствуйте, Dr_Sh0ck, Вы писали:

D_S>>>"В лоб", что называется, и решай.

G>> Нееее...
D_S>Не надо мудрить, там где все просто
Я сегодня вечером посидел и решил, что да. С разностями ненужный напряг.
G>>Прощелкиваем всю строку. Запоминаем в массив номера позиций, в которой стоят пробелы. В конце цикла пишем в массив последним элементом длину строки. Затем находим попарные разности между элементами полученного массива и записываем рядом (все можно сделать в одном цикле). К примеру, получим что-то такое:

D_S>Так было бы красивей, если бы ты заранее знал сколько элементов тебе понадобиться в таком массиве. Кроме того его еще хранить нужно где-то... Кроме того между подстроками может стоять не ожин пробел, а несколько... и т.д. и т.п.

Вот пример рабочего кода: (стековый фрейм можно было бы и не делать, +ограничение на длину строки)
    format binary
        org 100h
;a test values
        mov     cx, StrLen
        mov     si, strText
        sub     cx, si
;proc
;in:
;cx - stringLen
;si - stringPtr
;
;out:
;ax - last space position
;bx - max word length
;
;size - 44
enp:
        push    bp
        mov     bp,sp
        sub     sp,cx
        push    si              ;save initial position to stack
        xor     bx,bx
L:
        lodsb
        cmp     al,  32
        je      found            ;a space found
        or      al,al
        jnz     endl
found:
        pop     ax              ;get an old position from stack
        push    ax              ;saving previous space position
        push    si              ;save current space position in stack
        sub     ax,si
        neg     ax
        dec     ax              ;ax = prev. word length
        cmp     ax,bx           ;bx  = maxLength
        jna     endl
        xchg    ax, bx          ;ax > bx
        xchg    bp, sp
        mov     di, [bp+2]      ;di = Last Space Position
        xchg    bp, sp
endl:
        loop L
        xchg    ax,di
        mov     sp,bp
        pop     bp
        ret
        strText db 'This is  a  sente111111111111111111nce  for testing   purposes.',0
        StrLen  db 0

и кому лень тащить fasm:
0000000000:  B9 74 01 BE 34 01 29 F1 55 89 E5 29 CC 56 31 DB
0000000010:  AC 3C 20 74 04 08 C0 75 14 58 50 56 29 F0 F7 D8
0000000020:  48 39 D8 76 08 93 87 EC 8B 7E 02 87 EC E2 E1 97
0000000030:  89 EC 5D C3 54 68 69 73 20 69 73 20 20 61 20 20
0000000040:  73 65 6E 74 65 31 31 31 31 31 31 31 31 31 31 31
0000000050:  31 31 31 31 31 31 31 6E 63 65 20 20 66 6F 72 20
0000000060:  74 65 73 74 69 6E 67 20 20 20 70 75 72 70 6F 73
0000000070:  65 73 2E 00 00

Запускать в отладчике.
d Бесы d
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.