How to filter alphabets and whitespace only in WinAsm?

Started by cecil1887, March 22, 2012, 06:23:55 PM

Previous topic - Next topic

cecil1887

Hi, I want to write a program that allows the user to enter a sentence of up to 99 characters.
The program shall then remove characters other than alphabet and white space from the input
string and display the total number of alphabets entered by the user.

Example:
Input string:
Hello ???+-09258World

Output:
Hello World

Count:
11

Can anyone please help??

jj2007

Pure assembler :green

include \masm32\MasmBasic\MasmBasic.inc   ; download
  Init
  Let esi=""
  .Repeat
   Inkey
   mov ebx, eax   ; save to a "safe" register
   .if Instr_(Chr$("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz ", 9), Chr$(ebx))
      Let esi=esi+Chr$(ebx)
      Print Chr$(ebx)
   .endif
  .Until ebx==13 || Len(esi)>=99
  Inkey CrLf$, "Your string: [", esi, Str$("] with %i bytes", Len(esi))
  Exit
end start

dedndave

lol
that's not "pure"   :P

try this one...

jj2007

268 vs 14 lines - and yours does not even block the illegal input ::)

But it's 16-bit code, in contrast to mine. so I will be generous:  :U

dedndave

block what illegal input ?

ohhh - you mean it accepts everything into the buffer, then strips it out
well - that's just the easiest way to do it, seeing as i already have the routine in place   :P

cecil1887

dave your output is correct, it should not block any characters. accept everything to input then remove any character other than alphabets & spaces. is it possible to do it in a fewer lines of code?
all of your immediate help  very much appreciated!
thanks.

dedndave

yah - i could move all the code into the loop
but, you wouldn't be able to use the code for other programs   :P
i try to write routines that may be used over and over
and - i am sure there is an easier way to filter the string - but the way i did it is simple - easy to understand
for example, i could use a look-up-table
but that is overkill, i think   :bg

let me add that Jochen's code is a lot bigger, if you take his MasmBasic library into account
it just looks smaller because he uses a lot of macros
my program is 754 bytes of EXE - how small you want it - lol
if i made a tiny model version, it would be 242 bytes or less

cecil1887

it would be great if u can minimize the codes as much... as long as it do work,
1. read input
2. filter input
3. output result with count

i think i would prefer a tiny model if u can deliver?
thanx :D

cecil1887

title loop
.dosseg
.model small
.stack 100h

.data
msg db "Enter string:"
input db 99 dup(0);duplicate 99 bytes, and values are undefined '?', can fill a value instead
blank   db 0Ah, 0Dh,'$'

.code
main proc

mov ax, @data
mov ds, ax

mov dx, offset msg
mov ah, 9
;int 21h
mov si, offset input
again : mov ah, 1
int 21h
cmp al, 0Dh     ;ASCII code for 'enter'
je stop
mov [si], al
inc si
    jmp again

stop : mov dx, offset blank ;need to print a blank space or '\n' so the out put goes to the next line
mov ah, 9
int 21h

mov bl,'$'
mov [si], bl
mov ah, 9
mov dx, offset input
int 21h

mov ah, 1
int 21h

mov ax, 4c00h
int 21h

main EndP
end main


This code is without a filter. So when you enter a string, it will output the same string. I need to insert a filter whereby compare characters and truncate all characters except alphabets & spaces.

Please give your feedbacks  :bg

dedndave

well - many of the lines in my program are simply documentation and to make it more legible
for example...
;********************************************************************

PrStr   PROC    NEAR
;
;Get User Input String With Prompt
;
;Call With: DX = address of prompt string to display
;
;  Returns: CX = number of characters entered
;           DX = address of '$' terminated user entered string
;
;Also Uses: all other registers are preserved
;           the "InpBuf" buffer is used to hold the string
;
;------------------------------------------

        push    ax
        push    bx
        mov     ah,9
        int     21h
        mov     dx,offset InpBuf
        mov     ah,0Ah
        int     21h
        call    NewLine
        mov     cl,InpBuf.UsedBytes
        mov     ch,0
        mov     dx,offset InpBuf.Buffer
        mov     bx,cx
        add     bx,dx
        mov byte ptr [bx],'$'
        pop     bx
        pop     ax
        ret

PrStr   ENDP

;********************************************************************


that's 19 lines of code and 18 lines for comments and "airing it out"   :bg
4 of those lines are to preserve registers - not really necessary in this case
and the proc/endp/call/return - i chose a routine that is only used once - so it could be "inlined"
believe me, your instructor won't mind the extra lines - lol
but, we can go that route, if you like
give me some time to play with it...

dedndave

ok - here is a striped down version, 718 byte EXE
you can remove the extra comment lines, if you like

next, i will make a tiny model (.COM) version.......

dedndave


dedndave

and, when i knock the zero's off the end of the file, 178 byte COM...
:bg

dedndave

if i strip a bunch of extra stuff out, the tiny model code looks like this   :P
        .MODEL  Tiny
        OPTION  CaseMap:None        ;case sensitive

BUFSIZE EQU 99                      ;user input buffer size, 255 max

INBUFFER  STRUCT
  MaxBytes  db BUFSIZE+1
  UsedBytes db ?
  Buffer    db BUFSIZE+1 dup(?)
INBUFFER  ENDS

;####################################################################

        .CODE
        ORG     100h

_main   PROC    NEAR

        call    NewLine
        mov     dx,offset s$Prompt1 ;'Enter a String:'
        mov     ah,9
        int     21h
        mov     dx,offset InpBuf
        mov     ah,0Ah
        int     21h
        call    NewLine
        mov     dx,offset InpBuf.Buffer
        xor     bx,bx
        mov     cl,InpBuf.UsedBytes
        mov     ch,bl
        mov     si,dx
        mov     di,dx
        jcxz    Loop03

Loop00: lodsb
        mov     ah,al
        and     ah,0DFh             ;clear bit 5 - forces upper case
        jz      Loop01              ;if it's 0 or 20h - white space

        cmp     ah,'A'
        jb      Loop02

        cmp     ah,'Z'
        ja      Loop02

Loop01: stosb
        inc     bx                  ;count it in BX

Loop02: loop    Loop00

Loop03: mov     al,'$'
        stosb
        call    StrOut
        mov     ax,bx
        call    UnsDec
        call    StrOut
        mov     dx,offset s$AnyKey  ;'Press Any Key To Exit'
        call    StrOut
        mov     ah,1                ;wait for key
        int     16h                 ;BIOS keyboard call
        mov     ah,0                ;get keyboard character
        int     16h                 ;BIOS keyboard call
        mov     ax,4C00h            ;terminate, return = 0
        int     21h                 ;DOS function call

_main   ENDP

;********************************************************************

StrOut  PROC    NEAR

        mov     ah,9
        int     21h

NewLine::
        mov     dx,offset s$CrLf
        mov     ah,9
        int     21h
        ret

StrOut  ENDP

;********************************************************************

UnsDec  PROC    NEAR

        mov     di,offset OutBuf+sizeof OutBuf-1
        mov     cx,10               ;BX = divisor

UnDec0: xor     dx,dx               ;zero the high word
        dec     di                  ;point to next string byte
        div     cx                  ;divide DX:AX by 10
        or      dl,30h              ;set ASCII bits in remainder
        mov     [di],dl             ;store the numeric character
        or      ax,ax               ;any quotient left ?
        jnz     UnDec0              ;loop until done

        mov     dx,di
        ret

UnsDec  ENDP

;####################################################################

s$Prompt1 db 'Enter a String: ',24h
s$AnyKey  db 0Dh,0Ah,'Press Any Key To Exit',24h
s$CrLf    db 0Dh,0Ah,24h
OutBuf    db 5 dup(?),24h
InpBuf    INBUFFER <>

;####################################################################

        END     _main

jj2007

Quote from: dedndave on March 22, 2012, 07:39:25 PM
let me add that Jochen's code is a lot bigger, if you take his MasmBasic library into account
it just looks smaller because he uses a lot of macros

Dave,

Your example uses DOS - how big is that library?  :wink
But jokes apart: My example was meant as "real pseudo code" - just a demo what are the necessary steps (and I assumed you wanted blocking while the user types).