Muveletek karakterlancokkal problema(Assembly - NASM)

Muveletek karakterlancokkal problema(Assembly - NASM)
2016-11-27T15:46:07+01:00
2016-11-28T07:43:51+01:00
2022-12-04T05:00:37+01:00
bokica25
Az a feladatom, hogy olvassak be ket karakterlancot (c stilusu, 0 terminalt), es a harmadikat epitsem fel a kovetkezo modon: az elsobol a kisbetuket nagybeture alakitom, az igy kapott karakterlancot belemasolom az eredmenybe, a harmadikba. Utana a masodik karakterlancban a legalabb 2 egymast koveto karakter ha van akkor azokat bemasolom az eredmenybe, ahanyszor elofordultak(pl 222344, akkor 22244 belekerul a karakterlancba), s utana az elso + a masodik karakterlanc hosszat is beleteszem a karakterlancba.

Elakadtam ott, hogy a karaktereket a masodikbol, amelyek legalabb 2szer elofordulnak egymas utan belerakjam az utolsoba. A hosszuk az mar fog menni.
Bemasolom a kodomat:



%include 'mio.inc' global main section .text ;kiir egy memoriaban levo karakterlancot kiir_string: call mio_writestr .loop: lodsb cmp al, 0 je .vege call mio_writechar jmp .loop .vege: call mio_writeln ret ;karakterlanc beolvasasa beolvas_string: push edx call mio_writestr mov edx, edi .loop: call mio_readchar cmp al, 13 je .vege cmp al, 8 jne .tarol cmp edi, edx je .loop call mio_writechar mov al, ' ' call mio_writechar mov al, 8 call mio_writechar dec edi jmp .loop .tarol: call mio_writechar stosb jmp .loop .vege: xor eax, eax stosb call mio_writeln pop edx ret ;egy karakterlancban a kisbetuket nagybetukke alakitja nagybetukkeAlakit: ;kisbetuk 97 - 122 push eax xor eax, eax .loop: mov edi, esi lodsb cmp al, 0 je .vege ;ha elertunk idaig, akkor kisbetu cmp al, 'a' jl .mindenkeppen cmp al, 'z' jg .mindenkeppen sub eax, 32 .mindenkeppen: stosb jmp .loop .vege: xor eax, eax stosb pop eax ret ;az esiben levo karakterlanc hosszat visszateriti az ecx regiszterben karlancHossza: push esi xor ecx, ecx ;ebben fogjuk visszateriteni a karlanc hosszat .loop: lodsb inc ecx cmp al, 0 je .vege jmp .loop .vege: pop esi ret ;atmasolja az esi-bol a karakterlancot az edi-be atMasol: push ecx .masol: call karlancHossza rep movsb .vege: pop ecx ret ;az esiben tarolt karakterlancot hozzafuzi edi-ben tarolt karakterlanchoz osszefuz: push eax mov eax, esi mov esi, edi .loop: lodsb cmp al, 0 je .hozzafuz jmp .loop .hozzafuz: dec esi mov edi, esi mov esi, eax call karlancHossza rep movsb .vege: pop eax ret ;az edi-ben tarolt karakterlanchoz hozzafuz egy karaktert osszefuzKarakter: push eax mov eax, esi mov esi, edi .loop: lodsb cmp al, 0 je .hozzafuz jmp .loop .hozzafuz: dec esi mov edi, esi mov esi, ebx movsb .vege: pop eax ret ;a B-bol azokat a karaktereket amelyek legalabb 2-szer szerepelnek egymas utan hozzafuzi a karlanc3-hoz feldolgozKarakterek: push eax push ebx push edx mov esi, karlanc2 call karlancHossza dec ecx .loop: mov ebx, esi xor edx, edx inc esi mov edi, esi dec esi .loop2: lodsb cmp al, 0 je .folytat cmp al, [edi] jne .folytat inc edx inc edi jmp .loop2 .folytat: cmp edx, 0 je .novelunk inc edx push edi .muvelet: mov edi, karlanc3 call osszefuzKarakter dec edx cmp edx, 0 jle .novelunk jmp .muvelet .novelunk: pop edi mov esi, edi loop .loop .vege: pop edx pop ebx pop eax ret main: mov eax, str_szabaly call mio_writestr call mio_writeln mov eax, str_karlanc1 mov edi, karlanc1 call beolvas_string mov eax, str_karlanc2 mov edi, karlanc2 call beolvas_string call mio_writeln mov eax, str_karlanc1 mov esi, karlanc1 call kiir_string mov eax, str_karlanc2 mov esi, karlanc2 call kiir_string call mio_writeln mov esi, karlanc1 call nagybetukkeAlakit call mio_writeln mov esi, karlanc1 mov edi, karlanc3 call atMasol mov eax, str_karlanc3 mov esi, karlanc3 call kiir_string call feldolgozKarakterek call mio_writeln mov eax, str_karlanc3 mov esi, karlanc3 call kiir_string ret section .data str_szabaly db "[A-ban a kisbetuket nagybetukke alakitjuk] + [B-bol azok a karakterek, amelyek egymas utan legalabb ketszer szerepelnek (annyiszor ahanyszor szerepeltek)] + [A hossza + B hossza] ",0 str_karlanc1 db "1.karakterlanc = ", 0 str_karlanc2 db "2.karakterlanc = ", 0 str_karlanc3 db "3.karakterlanc = ", 0 section .bss karlanc1 resb 256 karlanc2 resb 256 karlanc3 resb 256
Mutasd a teljes hozzászólást!
Igen, odáig egész jó, amikor a két (vagy több) egymás utáni karaktert kell átmásolni, azt jól elbonyolítottad Ilyenkor kell megállni, és végiggondolni.
Mi a legegyszerűbb, legvilágosabb megközelítés? Tegyük fel, hogy bl-be mindig elrakod a legutóbbi karaktert, és ugye al-be olvasod be az újat. Ekkor könnyen összehasonlíthatod a két karaktert (al=bl?) és ha igen, akkor a ciklust kiírásokkal folytatod. Vigyázat, az első találatnál két karaktert kell kiírni, a továbbiaknál már csak egyet.

xor al,al .loop: mov bl,al ; elteszem az elozo karaktert lodsb cmp al,0 je .vege cmp al,bl ; azonos karakterek? jne .loop stosb ; az elsot kiirjuk .duplak: stosb ; akt.karakter kiirasa lodsb cmp al,0 je .vege cmp al,bl ; amig egyformak je .duplak jmp .loop
  Vagy ennél jobban.
Mutasd a teljes hozzászólást!

  • Valamiféle algoritmust kellene először kitalálni, mondjuk egy olyat, ami karakterenként olvassa az inputot, és abból, meg az állapotváltozókból találja ki, hogy mi legyen az output, és hogyan kell módosítani az állapotváltozókat.
    Pl (C-szerű nyelven):

    typedef struct State { char lastchar; /* ez ismétlődött eddig */ size_t nrep; /* ennyiszer ismétlődött eddig */ size_t nprint; /* ennyiszer írtuk ki */ } State; State state= { 'X', 0, 0 }; char *EgyCharFeldolgozása (State *pstate, char chr, char *to_ptr) { if (pstate->nrep==0) { /* legeleje: ezt még nem írjuk ki */ pstate->lastchar= chr; pstate->nrep= 1; pstate->nprint= 0; } else if (pstate->lastchar==chr) { /* ugyanaz, mint az előző */ ++pstate->nrep; while (pstate->nprint < pstate->nrep) { *to_ptr++ = chr; ++pstate->nprint; } } else { /* különbözik az előzőtől */ pstate->lastchar= chr; pstate->nrep= 1; pstate->nprint= 0; } return to_ptr; /* output folytatási cím */ }
    Mutasd a teljes hozzászólást!
  • Ennek a továbbfejlesztése az úgynevezett fájltranszformáció, vagyis hogy úgy teszünk, mintha ilyen sorozatunk lenne (karakter,ismétlődések_száma). Na ezt már könnyű lesz feldolgozni. Ilyesmi műveletek lesznek:

    typedef struct CharAndRep { char char; size_t nrep; } CharAndRep; void CAR_Init (const char *from, size_t fromlen); int CAR_Read (CharAndRep *into); / return: 0/1 = van/nincs több */
    Persze itt is kellenek belső állapotváltozók (kb úgy, mint az előbb), de azokat a hívó nem látja, nem kell tudjon róluk. Haladó esetben az állapotváltozók egy dinamikusan foglalt memóriában vannak (bár itt már tényleg elég messze kerültünk az eredeti feladattól;)

    struct CAR_Internal; /* magánügy */ CAR_Internal *CAR_Init (const char *from, size_t fromlen); int CAR_Read (CAR_Internal *handle, CharAndRep *into); / return: 0/1 = van/nincs több */
    void CAR_Release (CAR_Internal *handle);
    Mutasd a teljes hozzászólást!
  • Na jó, de minek kell ezt így elbonyolítani? Nyilván az aktuális feladathoz nem kell, csak éppen ezek a feladatok olyanok szoktak lenni, hogy ha egyet megoldasz, jön egy hasonló, de kétszer bonyolultabb. Például: ilyen stringből nem egy van, hanem kettő (továbbra is rendezettek), válogassuk le azokat a karaktereket, amik az első inputban egyszer, a másodikban legalább háromszor fordulnak elő.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd