PDA

View Full Version : یافتن جایگاه یک کاراکتر در یک رشته



csharpprogramer88
سه شنبه 01 آذر 1390, 09:14 صبح
آخرین کدی که با همکاری شما نوشتم یک رشته را میخواند با یک کاراکتر و کاراکتر را در آن رشت جستجو میکند


STSEG SEGMENT STACK 'STACK'
DB 32 DUP(?)
STSEG ENDS
;----------------------------------------
DTSEG SEGMENT 'DATA'

MSG1 DB "PLEASE ENTER A STRING : ",'$'
MSG2 DB "ENTER A CHAR : ",'$'
msgfound db 13,10, "exist your char in string$"
notmsgfound db 13,10, "not exist your char in string$"

LIN DB 13,10,'$'
ST_0 DB 50
ST_SIZE DB ?
ST1 DB 51 DUP(?)

ch1 db ?
num db 0

DTSEG ENDS

;-----------------------------------------
CDSEG SEGMENT 'CODE'

ASSUME DS:DTSEG , SS:STSEG , CS:CDSEG

MAIN PROC
MOV AX,DTSEG
MOV DS,AX
mov es,ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;show of a message
MOV AH,9
MOV DX,OFFSET MSG1
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H
;;;;;;;;;;;;;;khandane yek karakter baraye serch dar yek kalame
MOV DX,OFFSET MSG2
INT 21H
;;;;;;;;;; read a 1 karakter
MOV AH,1
INT 21H
mov ch1,al

;--------------------------------search karakter dar kalame
cld
mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,50 ;toole reshte
mov DI,offset ST_0 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist
MOV AL,1 ;peyda shode
jmp endsearch
notexist:
MOV AL,0 ;peyda nashode
endsearch:

cmp al,1
je showfound
jmp notfound
showfound:
mov ah,9
lea dx,msgfound
int 21h

jmp endshow
notfound:
mov ah,9
lea dx,notmsgfound
int 21h

endshow:
MOV AH,4CH
INT 21H

MAIN ENDP

CDSEG ENDS
END MAIN


سوال 1:
چطور میتونم در صورت پیدا شدن آن کاراکتر جایگاه آنرا پیدا کنم مثلا بگم عنصر پیدا شده کاراکتر سوم هست
سوال 2 : آیا این کد کل رشته را از ابتدا تا انتها حتی پس از برخورد با اولین کاراکتر جستجو میکنه؟

csharpprogramer88
سه شنبه 01 آذر 1390, 12:26 عصر
چیزی که به نظر خودم رسیده اینه :



mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,50 ;toole reshte
mov DI,offset ST_0 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist


mov bx,[di]



به این معنی که اگر کاراکتر را پیدا کرد اندیس آنرا در bx قرار بده ولی نمیدونم کارم درسته یا نه

برای چاپ اندیس هم این را مینویسم



mov dl,bl
mov ah,02
int 21h


ولی خروجی درست نمیده که در تصویر خرجی را میزارم

آخرین کدی که نوشتم :


STSEG SEGMENT STACK 'STACK'
DB 32 DUP(?)
STSEG ENDS
;----------------------------------------
DTSEG SEGMENT 'DATA'

MSG1 DB "PLEASE ENTER A STRING : ",'$'
MSG2 DB "ENTER A CHAR : ",'$'
msgfound db 13,10, "exist your char in string$"
notmsgfound db 13,10, "not exist your char in string$"

LIN DB 13,10,'$'
ST_0 DB 50
ST_SIZE DB ?
ST1 DB 51 DUP(?)

ch1 db ?
num db 0

DTSEG ENDS

;-----------------------------------------
CDSEG SEGMENT 'CODE'

ASSUME DS:DTSEG , SS:STSEG , CS:CDSEG

MAIN PROC
MOV AX,DTSEG
MOV DS,AX
mov es,ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;show of a message
MOV AH,9
MOV DX,OFFSET MSG1
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H
;;;;;;;;;;;;;;khandane yek karakter baraye serch dar yek kalame
MOV DX,OFFSET MSG2
INT 21H
;;;;;;;;;; read a 1 karakter
MOV AH,1
INT 21H
mov ch1,al

;--------------------------------search karakter dar kalame
cld
mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,50 ;toole reshte
mov DI,offset ST_0 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist



xor bx,bx
mov bx,[di]





MOV AL,1 ;peyda shode
jmp endsearch
notexist:
MOV AL,0 ;peyda nashode
endsearch:

cmp al,1
je showfound
jmp notfound
showfound:


;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H


mov dl,bl
mov ah,02
int 21h





mov ah,9
lea dx,msgfound
int 21h

jmp endshow
notfound:
mov ah,9
lea dx,notmsgfound
int 21h

endshow:
MOV AH,4CH
INT 21H

MAIN ENDP

CDSEG ENDS
END MAIN

xman_1365_x
سه شنبه 01 آذر 1390, 12:55 عصر
سوال 1:
چطور میتونم در صورت پیدا شدن آن کاراکتر جایگاه آنرا پیدا کنم مثلا بگم عنصر پیدا شده کاراکتر سوم هست

در قسمت دیتا:
charinstr dw 50
قست کد :
در بدنه جستجو هنگامی که کاراکتر رو پیدا کرد
sub charinstr,cx

حالا charinstr مکان کلمه ای که پیدا شده رو نمایش میده
مثال:
اگر رشته زیر را وارد کنید
1234567890
و کاراکتر 0 را در رشته بالا جستجو کنید، charinstr برابر با 10 میشود.

دلیل اینکه من در بدنه جستجو نمایش ندادم و نوشتم پیدا شده و مقدار 1 رو به این عنوان قرار دادم همین بود که بعدا برای کار های دیگه ای که میشه انجام داد دچار مشکل نشین

سعی کنید کارکرد دستورات رو بهتر متوجه بشین مثلا همین دستور repne SCASB دقیقا داره چی کار میکنه در هر مرحله روی چه ثباتهایی تاثیر میزاره و شما میتونید با شناسایی این تغییرات
برنامه بنویسید،برای مثال چون میدونیم که cx طول رشته هست و در هر بار جستجو اگر نباشد یکی کم میشه از طول و به کاراکتر بعدی میره اگر پیدا شد برای بدست آوردن کافیه طول رو از مکان جاری حذف کنیم


سوال 2 : آیا این کد کل رشته را از ابتدا تا انتها حتی پس از برخورد با اولین کاراکتر جستجو میکنه؟

نه این کد به محض پیدا شدن کاراکتر از بدنه خارج میشه،بازم میگم روی کارکرد دستورات دقیقتر شید و ببینید هر دستور دقیقا چه کاری انجام میده بعد میبینید چقدر ساده همین برنامه روی توی حلقه بزارین
میشه بعد ار پیدا کردن کارکتر باز به جستجو اگر به پایان رشته نرسیدیم ادامه بدیم



به این معنی که اگر کاراکتر را پیدا کرد اندیس آنرا در bx قرار بده ولی نمیدونم کارم درسته یا نه

شما با این کار آدرس رو در bx قرار میدین نه اندیس و وقتی bx رو نمایش بدین مقدار عنصر مورد نظر به خروجی میره برای اینکه درست نمایش بدینش به این شکل تغییرش بدین


xor bx,bx
mov bl,byte ptr [di-1]

دلیل اینکه عنصر بعد رو بهتون نمایش داده اینه که در دستور repne SCASB بر اساس طول در حال جستجو هست اما در نمایش رشتهای از کاراکتر یک بایتی ما میدونیم عنصر اول با صفر و آدرس جمع میشه و عنصر دوم با یک + آدرس
پس یعنی مکان مورد نظر همیشه n-1 هست برای همین با نوشتن di-1 خروجی درست میشه
موفق باشی

csharpprogramer88
سه شنبه 01 آذر 1390, 13:36 عصر
STSEG SEGMENT STACK 'STACK'
DB 32 DUP(?)
STSEG ENDS
;----------------------------------------
DTSEG SEGMENT 'DATA'

MSG1 DB "PLEASE ENTER A STRING : ",'$'
MSG2 DB "ENTER A CHAR : ",'$'
msgfound db 13,10, "exist your char in string$"
notmsgfound db 13,10, "not exist your char in string$"

LIN DB 13,10,'$'
ST_0 DB 50
ST_SIZE DB ?
ST1 DB 51 DUP(?)

charinstr dw 50

ch1 db ?
num db 0

DTSEG ENDS

;-----------------------------------------
CDSEG SEGMENT 'CODE'

ASSUME DS:DTSEG , SS:STSEG , CS:CDSEG

MAIN PROC
MOV AX,DTSEG
MOV DS,AX
mov es,ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;show of a message
MOV AH,9
MOV DX,OFFSET MSG1
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H
;;;;;;;;;;;;;;khandane yek karakter baraye serch dar yek kalame
MOV DX,OFFSET MSG2
INT 21H
;;;;;;;;;; read a 1 karakter
MOV AH,1
INT 21H
mov ch1,al

;--------------------------------search karakter dar kalame
cld
mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,50 ;toole reshte
mov DI,offset ST_0 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist

sub charinstr,cx

xor bx,bx
mov bx,[di-1]





MOV AL,1 ;peyda shode
jmp endsearch
notexist:
MOV AL,0 ;peyda nashode
endsearch:

cmp al,1
je showfound
jmp notfound
showfound:


;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H


mov dl,bl
mov ah,02
int 21h



mov ah,9
lea dx,msgfound
int 21h

jmp endshow
notfound:
mov ah,9
lea dx,notmsgfound
int 21h

endshow:
MOV AH,4CH
INT 21H

MAIN ENDP

CDSEG ENDS
END MAIN

چیزایی که گفتید تو کد تغییر دادم و خروجی دقیق همان عنصر را نمایش میدهد ولی من اندیس را میخوام نه مقدار اندیس
مثلا وقتی زشته را میدم : computer و کاراکتر ار میدم p در خروجی مقدار 4 که برابر با اندیس p هست نمایش داده بشه ولی تو این خود p به نمایش در میاد

csharpprogramer88
سه شنبه 01 آذر 1390, 13:47 عصر
چیزی که به فکرم رسید :



mov charinstr,cx


چون انجایی که آن مقدار پیدا میشه مقدار فعلی cx هست پس میشه گفت اندیس آن با cx برابره که من جای دستور sub که شما کفتید mov قرار دادم سپس برای خروجی هم اینگارو کردم


mov dl,offset charinstr;
mov ah,02
int 21h


ولی در خروجی اینجوری نشان میده که غلطه

اینم کدی که کمی تغییرش دادم


STSEG SEGMENT STACK 'STACK'
DB 32 DUP(?)
STSEG ENDS
;----------------------------------------
DTSEG SEGMENT 'DATA'

MSG1 DB "PLEASE ENTER A STRING : ",'$'
MSG2 DB "ENTER A CHAR : ",'$'
msgfound db 13,10, "exist your char in string$"
notmsgfound db 13,10, "not exist your char in string$"

LIN DB 13,10,'$'
ST_0 DB 50
ST_SIZE DB ?
ST1 DB 51 DUP(?)

charinstr dw 50

ch1 db ?
num db 0

DTSEG ENDS

;-----------------------------------------
CDSEG SEGMENT 'CODE'

ASSUME DS:DTSEG , SS:STSEG , CS:CDSEG

MAIN PROC
MOV AX,DTSEG
MOV DS,AX
mov es,ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;show of a message
MOV AH,9
MOV DX,OFFSET MSG1
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H
;;;;;;;;;;;;;;khandane yek karakter baraye serch dar yek kalame
MOV DX,OFFSET MSG2
INT 21H
;;;;;;;;;; read a 1 karakter
MOV AH,1
INT 21H
mov ch1,al

;--------------------------------search karakter dar kalame
cld
mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,50 ;toole reshte
mov DI,offset ST_0 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist

mov charinstr,cx

xor bx,bx
mov bx,[di-1]





MOV AL,1 ;peyda shode
jmp endsearch
notexist:
MOV AL,0 ;peyda nashode
endsearch:

cmp al,1
je showfound
jmp notfound
showfound:


;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H


mov dl,offset charinstr;
mov ah,02
int 21h



mov ah,9
lea dx,msgfound
int 21h

jmp endshow
notfound:
mov ah,9
lea dx,notmsgfound
int 21h

endshow:
MOV AH,4CH
INT 21H

MAIN ENDP

CDSEG ENDS
END MAIN

xman_1365_x
سه شنبه 01 آذر 1390, 15:36 عصر
خوب حرفای منو خوب نمیخونید چون جوابتون رو توی پست قبلم دادم اما باید روی کد فکر میکردین که بجای درست کردن اومدین کد من رو تغییر دادین ، بجای توضیح بیشتر ترجیح دادم برنامه رو بنویسم حالا بررسی کنید ببینید چه کد هایی اضافه کردم و سعی کنید بفهمید! اگر برنامه شما ادامه داشته باشه اینطوری نمیشه ادامه داد چون همشو من دارم می نویسم پس کاری که انجام میدین این باشه که خط به خط رو درک کنید اگر نمیدونین سوال کنید ،چون به این شکل من دیگه جواب نمیدم
مشکلی که دارین اینه الگوریتم کارو نمیدونین و بعد برای انجام الگوریتم چون دستورات رو خوب نمیشناسید نمیتونین برنامه رو تکمیل کنید برای این مهم هم فقط باید مطالعه و تمرین کنید.


STSEG SEGMENT STACK 'STACK'
DB 32 DUP(?)
STSEG ENDS
;----------------------------------------
DTSEG SEGMENT 'DATA'

MSG1 DB "PLEASE ENTER A STRING : ",'$'
MSG2 DB "ENTER A CHAR : ",'$'
msgfound db 13,10, "exist your char in string$"
notmsgfound db 13,10, "not exist your char in string$"

LIN DB 13,10,'$'
ST_0 DB 50
ST_SIZE DB ?
ST_1 DB 51 DUP(?)

charinstr dw 50

ch1 db ?
num db 0

DTSEG ENDS

;-----------------------------------------
CDSEG SEGMENT 'CODE'

ASSUME DS:DTSEG , SS:STSEG , CS:CDSEG

MAIN PROC
MOV AX,DTSEG
MOV DS,AX
mov es,ax

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;show of a message
MOV AH,9
MOV DX,OFFSET MSG1
INT 21H
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H

xor ax,ax
mov al,ST_SIZE
mov charinstr,ax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H
;;;;;;;;;;;;;;khandane yek karakter baraye serch dar yek kalame
MOV DX,OFFSET MSG2
INT 21H
;;;;;;;;;; read a 1 karakter
MOV AH,1
INT 21H
mov ch1,al

;--------------------------------search karakter dar kalame
xor ax,ax
cld
mov al,ch1 ;karakteri ke mikhaym jostojo konim
mov cx,charinstr ;toole reshte
mov DI,offset ST_1 ;buffer gerefte shode az karbar
repne SCASB ;jostogo
JNE notexist


sub charinstr,cx


MOV AL,1 ;peyda shode
jmp endsearch
notexist:
MOV AL,0 ;peyda nashode
endsearch:

cmp al,1
je showfound
jmp notfound
showfound:


;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H

;namayeshe andis onsore peyda shode

mov ax,charinstr
mov cl,10
div cl

add ax,3030h
mov bl,ah

mov dl, al
mov ah,02
int 21h

mov dl, bl
int 21h

;raftan b khate bad
MOV AH,9
MOV DX,OFFSET LIN
INT 21H


mov ah,9
lea dx,msgfound
int 21h

jmp endshow
notfound:
mov ah,9
lea dx,notmsgfound
int 21h

endshow:
MOV AH,4CH
INT 21H

MAIN ENDP

CDSEG ENDS
END MAIN


موفق باشی

csharpprogramer88
سه شنبه 01 آذر 1390, 16:34 عصر
از لطفت ممنون که جواب دادی ناراحتیتونو:خجالت: بگذارید بحساب تازه کار بودنم من اینطور نبوده که بخوام یک پروژه را بفرستم رو سایت که دیگران و از دیگران بخوام برام بنویسن اینکه کد را تغییر دادم گفتم که میخوام با تغییر کدها یه چیزهایی دستم بیا پس به اندازه خودم تلاش کردم :لبخندساده: که در باره کد شما یک کارهایی گه به ذهنم رسیده انجام دادم
تازه آن توضیحات شما با ان پست آخری شما کمی فرق داره
سوال:


MOV AH,10
MOV DX,OFFSET ST_0
INT 21H

xor ax,ax
mov al,ST_SIZE
mov charinstr,ax

در اینجا که ما یک رشته را میخونیم بعد ax را صفر میکنیم .
کاربر میتونه تا 50 تا کاراکتر ووارد کنه . آیا ST_SIZE تعداد کاراکتری هست که کاربر وارد کرده ؟ مثلا وقتی کاربر کلمه computer را وارد میکند ST_SIZE و al برابر 8 میشود ؟

در کد قبلی ما


mov DI,offset ST_0 ;buffer gerefte shode az karbar

داشتیم ولی در کد آخری این کد اضافه شده که من دلیل این کار را نمیفهمم چون درسته که من در قسمت DATA تعریف کردم ST_1 ولی از آن در هیچ ج استفاده نکردم


mov DI,offset ST_1 ;buffer gerefte shode az karbar



چون در خواندن رشته ما از ST_0 استفاده کردیم



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;read a string
MOV AH,10
MOV DX,OFFSET ST_0
INT 21H




sub charinstr,cx

نمیفهمم چرا تفریق انجام میشه

xman_1365_x
سه شنبه 01 آذر 1390, 19:30 عصر
تازه آن توضیحات شما با ان پست آخری شما کمی فرق داره

مورد 1 که من نوشتم رو خوب خوندین ؟
و اینکه برنامه ای که نوشتم کجاش با حرفام تضاد داشته ؟
طبق همون گفته برنامه رو نوشتم



کاربر میتونه تا 50 تا کاراکتر ووارد کنه . آیا ST_SIZE تعداد کاراکتری هست که کاربر وارد کرده ؟ مثلا وقتی کاربر کلمه computer را وارد میکند ST_SIZE و al برابر 8 میشود ؟

بله دقیقا چون سایز بافر ما میتونه متغیر باشه ماکزیمم 50 هست اما اگر کاربر حروف کمتر وارد کنه نمیتونیم تشخیص بدیم اندیس پیدا شده مربوط به کجا بوده
بهتر بگم تا متوجه شین
وقتی شما 5 کاراکتر وارد کردین
و مثلا حرف دوم در آرایه وجود داره
حالا برنامه بعد از پیدا کردن میاد
50-3=47
در صورتی که جواب ما باید از طول وارد شده بدست بیاد
یعنی
5-3=2
3 هم مربوط به cx هست



در کد قبلی ما
mov DI,offset ST_0 ;buffer gerefte shode az karbar

داشتیم ولی در کد آخری این کد اضافه شده که من دلیل این کار را نمیفهمم چون درسته که من در قسمت DATA تعریف کردم ST_1 ولی از آن در هیچ ج استفاده نکردم

mov DI,offset ST_1 ;buffer gerefte shode az karbar


دلیلش اینه که گفتم حرفای منو خوب نمیخونید!
ادامه این برنامه را چطور بنویسم (http://barnamenevis.org/showthread.php?314369-%D8%A7%D8%AF%D8%A7%D9%85%D9%87-%D8%A7%DB%8C%D9%86-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D8%B1%D8%A7-%DA%86%D8%B7%D9%88%D8%B1-%D8%A8%D9%86%D9%88%DB%8C%D8%B3%D9%85)
پست آخرش رو مجددا ببینید و خوب بخونید!



در خواندن رشته ما از ST_0 استفاده کردیم

درسته که st_0 شروع بافر هست اما st_0 طول رو مشخص میکنه و ST_SIZE تعداد کاراکتری که کاربر بعد از اینتر زدن وارد کرده
و رشته ای که کارکتر ها در اون ذخیره شدهst_1 هست ، برای همین ما از آدرس شروع مذکور این کارو انجام دادیم روش دیگه اینه st_0+2 با این کار ار اون دو بایت هرز پرش میکنیم


نمیفهمم چرا تفریق انجام میشه
در مورد تفریق بالا نوشتم اما بازم میگم
شما یک طول کارکتر دارین که وارد کردین مشخص هست
بعد هنگام جستجو میاد cx که برابر طول رشته هست یکی یکی کم میشه تا به صفر برسه که اگر برسه یعنی در رشته مذکور کاراکتر پیدا نشده
حالا اگر پیدا شه باید طول اولیه رو از طولی که جستجو کرده کم کنیم تا مکان اندیس رو پیدا کنیم
مثال:
alireza
طول=7
کاراکتر z رو در رشته جستجو میکنیم
اولین مرحله
cx=7 , a
cx=6 , l
cx=5 , i
cx=4 , r
cx=3 , e
cx=2 , z
cx=1 , a
پس
7-1=6
اندیس کارکتر ما هست اگر هم بخواین با اندیس مذکور به داده دسترسی پیدا کنید باید اندیس را یک واحد کاهش بدین

امیدوارم توضیحات کافی بوده باشه
موفق باشی