你好我是汇编中的新手,我在练习中遇到一些问题,要求我在原始字符串中找到子字符串然后,如果找到,则将其替换为另一个给定的字符串,但仅用于奇数事件发现(1,3,5 ......)。即。
此外,这些应适用于所有类型的输入。即使像这种情况一样," world"比{" cat"'更长,我需要更换" world"完全(" catld"会错)。 谁能帮我?!我不知道如何处理。 这是我目前的代码,我还没有考虑奇怪的事情,我只是想让它发挥作用:
#include <stdio.h>
void main() {
//Input
char stringa[1024] ="This string is a string\n";
char str1[] ="string";
char str2[] ="cat";
//Output
char result[1024];
__asm {
XOR EAX, EAX
CLD
LEA ESI, str1
LEA EDI, stringa
Ciclo: MOV AL, [ESI]
REPNZ SCASB
DEC EDI
PUSH EDI
PUSH ESI
MOV ECX, 7
REPE CMPSB
CMP ECX, 0
POP ESI
JZ Sost
JMP Ciclo
Sost: LEA ESI, str2
POP EDI
MOV ECX, 7
REP MOVSB
}
printf("New string: %s\n",result);
}
答案 0 :(得分:3)
检查点:a)增量发生计数器 b)检查计数器。 c)如果奇怪去替换。 d)转到第4点
替换:a)将ECX设置为替换字符串长度 b)在输出字符串中复制替换字符串 c)转到第4点
它看起来如何?
答案 1 :(得分:3)
下一个代码完成工作:它找到并替换另一个字符串的所有(非奇数)出现,并将结果字符串保留在另一个变量中,在编译器EMU8086中测试它(我的VS不工作),代码后面的解释:
.model small
.stack 100h
.data
original db 'abc world def world xyz',0
find db 'world',0
subst db 'cat',0
result db 100 dup(0)
i dw ? ;INDEX FOR "ORIGINAL".
j dw ? ;INDEX FOR "RESULT".
.code
mov ax, @data
mov ds, ax
mov i, offset original ;"I" POINTS TO "ORIGINAL".
mov j, offset result ;"J" POINTS TO "RESULT".
;SEARCH VARIABLE "FIND" AT CURRENT POSITION ("I").
mov si, i
lea di, find
search:
mov al, [di] ;CURRENT CHAR OF VARIABLE "FIND".
;CHECK IF END OF "FIND".
cmp al, 0 ;IF CURRENT CHAR OF "FIND" IS LAST ONE...
je match ;... VARIABLE "FIND" WAS FOUND.
;CHECK IF END OF "ORIGINAL".
cmp [si], 0
je finale
;CONTINUE.
cmp [si], al ;CMP ORIGINAL[SI],FIND[DI].
jne mismatch ;CHARS ARE DIFFERENT.
inc si ;NEXT CHAR OF "ORIGINAL".
inc di ;NEXT CHAR OF "FIND".
jmp search ;REPEAT (COMPARE NEXT CHAR).
match:
;WHEN "FIND" IS FOUND, "SUBST" REPLACE IT IN "RESULT".
mov i, si ;SKIP "FIND" IN "ORIGINAL", BUT...
dec i ;...SKIPPED ON CHAR FORWARD (SO DECREASE).
lea di, subst ;STRING TO REPLACE "FIND".
replace:
mov al, [di] ;CURRENT CHAR OF VARIABLE "SUBST".
;CHECK IF END OF "SUBST".
cmp al, 0 ;IF CURRENT CHAR OF "FIND" IS LAST ONE...
je next
;CONTINUE.
mov si, j ;CURRENT POSITION IN "RESULT".
mov [si], al ;COPY CHAR INTO "RESULT[ J ]".
inc j ;NEXT POSITION IN "RESULT".
inc di ;NEXT POSITION IN "SUBST".
jmp replace
mismatch:
;APPEND CURRENT CHAR (AL) INTO "RESULT".
mov si, i ;CURRENT POSITION IN "ORIGINAL".
mov di, j ;CURRENT POSITION IN "RESULT".
mov al, [si]
mov [di], al
inc j ;"I" IS ALSO INCREMENTED 4 LINES BELOW.
;NEXT CHAR IN "ORIGINAL".
next:
lea di, find ;SEARCH AGAIN VARIABLE "FIND".
inc i ;NEXT CHAR IN "ORIGINAL".
;CHECK IF END OF "ORIGINAL".
mov si, i
cmp [si], 0
jne search ;REPEAT (SEARCH "FIND" AGAIN).
;END OF WHOLE PROCESS.
finale:
mov ax, 4c00h
int 21h
结果是:
original = `abc world def world xyz`
find = `world`
subst = `cat`
result = `abc cat def cat xyz`
请注意,代码中的所有字符串(数据段中的变量)都使用0
作为结束分隔符。这非常重要,因为这是处理任何大小的字符串的关键,而不是硬编码的大小。
现在算法:
要使其适用于奇数事件,请添加另一个数字变量作为在标签match:
下增加的计数器,如果变量在标签search:
之后不是奇数,则使其跳转到标签{{1 }}
编辑:现在是Visual Studio 2013版本(在&#34; C ++ Win32控制台应用程序和#34上测试;):
next:
编辑#2:以前的代码,变量#include "stdafx.h"
#include "conio.h"
int _tmain(int argc, _TCHAR* argv[])
{ //Input
char original[1024] = "abc world def world xyz\n";
char find[] = "world";
char subst[] = "cat";
//Output
char result[1024] = { 0 };
int i;
int j;
_asm { lea esi, original
mov i, esi // "I" POINTS TO "ORIGINAL".
lea esi, result
mov j, esi // "J" POINTS TO "RESULT".
// SEARCH VARIABLE "FIND" AT CURRENT POSITION ("I").
mov esi, i
lea edi, find
search:
mov al, [edi] // CURRENT CHAR OF VARIABLE "FIND".
// CHECK IF END OF "FIND".
cmp al, 0 // IF CURRENT CHAR OF "FIND" IS LAST ONE...
je match // ... VARIABLE "FIND" WAS FOUND.
// CHECK IF END OF "ORIGINAL".
cmp [esi], 0
je finale
// CONTINUE.
cmp [esi], al // CMP ORIGINAL[SI],FIND[DI].
jne mismatch // CHARS ARE DIFFERENT.
inc esi // NEXT CHAR OF "ORIGINAL".
inc edi // NEXT CHAR OF "FIND".
jmp search // REPEAT (COMPARE NEXT CHAR).
match:
// WHEN "FIND" IS FOUND, "SUBST" REPLACE IT IN "RESULT".
mov i, esi // SKIP "FIND" IN "ORIGINAL", BUT...
dec i // ...SKIPPED ON CHAR FORWARD (SO DECREASE).
lea edi, subst // STRING TO REPLACE "FIND".
replace:
mov al, [edi] // CURRENT CHAR OF VARIABLE "SUBST".
// CHECK IF END OF "SUBST".
cmp al, 0 // IF CURRENT CHAR OF "FIND" IS LAST ONE...
je next
// CONTINUE.
mov esi, j // CURRENT POSITION IN "RESULT".
mov [esi], al // COPY CHAR INTO "RESULT[ J ]".
inc j // NEXT POSITION IN "RESULT".
inc edi // NEXT POSITION IN "SUBST".
jmp replace
mismatch:
// APPEND CURRENT CHAR (AL) INTO "RESULT".
mov esi, i // CURRENT POSITION IN "ORIGINAL".
mov edi, j // CURRENT POSITION IN "RESULT".
mov al, [esi]
mov [edi], al
inc j // "I" IS ALSO INCREMENTED 4 LINES BELOW.
// NEXT CHAR IN "ORIGINAL".
next:
lea edi, find // SEARCH AGAIN VARIABLE "FIND".
inc i // NEXT CHAR IN "ORIGINAL".
// CHECK IF END OF "ORIGINAL".
mov esi, i
cmp [esi], 0
jne search // REPEAT (SEARCH "FIND" AGAIN).
// END OF WHOLE PROCESS.
finale:
}
printf("New string: %s", result );
_getch();
return 0;
}
和i
分别替换为j
和ebx
(我留下了评论所说的部分&#34;我& #34;和&#34; J&#34;所以你可以看到我做了替换的地方):
ecx
答案 2 :(得分:0)
此代码有效,我尝试了很多输入。有很多重复的代码行,但它的工作原理。我会看看我能否在下一天减少它。正如我对Josè所说,我不能在输入中给出的4个字符串中添加变量:stringa(原始),str1(找到),str2(新子串),risultato(最终输出):
__asm {
XOR EAX, EAX
XOR EBX, EBX
XOR EDX, EDX
CLD
LEA EDI, str1
LEA ESI, stringa
Cicle :
MOV AL, [ESI]
//CHECK IF STRING ENDED
CMP AL, 0
JZ End
//CHECK THE CHAR
SCASB
//IF THEY DON'T MATCH GO TO COPY CHAR
JNZ Append
//OTHERWISE CHECK IF FROM HERE STRINGS ARE EQUAL
MOV ECX, LENGTH str1
DEC EDI
REPE CMPSB
CMP ECX, 0
//IF YES GO TO CHECK IF IT'S AN ODD OCCURRENCE
JZ Checkpoint
//IF NOT GET BACK ESI AND EDI...
NEG ECX
ADD ECX, LENGTH str1
SUB EDI, ECX
SUB ESI, ECX
//..AND COPY THE SINGLE CHAR
MOV risultato[EBX], AL
INC EBX
INC ESI
JMP Cicle
//COPY CHAR WHEN STRINGS DONT'MATCH
Append :
INC ESI
DEC EDI
MOV risultato[EBX], AL
INC EBX
JMP Cicle
//CHEK IF ODD/EVEN OCCURRENCE
Checkpoint :
INC EDX
TEST EDX, 00000001h
//IF ODD GO TO REPLACE ALL SUBSTRING
JNZ Replacement
//OTHERWISE GET BACK ESI/EDI AND COPY THE SAME SUBSTRING TO RESULT
SUB EDI, LENGTH str1
SUB ESI, LENGTH str1
PUSH EDI
LEA EDI, risultato[EBX]
MOV ECX, LENGTH str1
REP MOVSB
//UPDATE RESULT INDEX COUNTER
ADD EBX, LENGTH str1 - 1
//GET BACK EDI POINTER
POP EDI
DEC ESI
JMP Cicle
//REPLACEMENT OF THE SUBSTRING
Replacement :
//GET BACK EDI AT FIRST CHAR AND STORE ESI/EDI FOR NEXT LOOP
SUB EDI, LENGTH str1
PUSH ESI
PUSH EDI
//SET A POINTER TO THE NEW STRING AND COPY IT TO RESULT
LEA ESI, str2
LEA EDI, risultato[EBX]
MOV ECX, LENGTH str2
REP MOVSB
//UPDATE RESULT COUNTER AND GET BACK EDI/ESI TO PREVIOUS POSITIONS TO CONTINUE
ADD EBX, LENGTH str2 - 1
POP EDI
POP ESI
DEC ESI
JMP Cicle
End :
MOV risultato[EBX], 0
}
我已经忘记了一个细节:当我发现char'è'时,这段代码(在AL中)用ascii 232代替138,为什么呢?我能做什么? 感谢
答案 3 :(得分:0)
最后没关系。我使用Jose Manuel的代码(谢谢),我使用pop / push而不是变量“i”和“j”修改它。然后输入错误的在线测试:“ccccc”,“cc”,“f”。结果应为“fccc”,但为“fcf”。所以我修复了一些其他细节,现在没关系。
XOR ECX, ECX
XOR EAX, EAX
XOR EBX, EBX
XOR EDX, EDX
LEA ESI, result
PUSH ESI //store result into stack
LEA ESI, original //esi points to original
LEA EDI, find //edi points to find
Search :
MOV AL, [EDI]
CMP AL, 0 //chek if the end of find
JE Match //if yes, we have an occurrence
CMP[ESI], 0 //check if end of original
JE Mismatch //if yes, coopy last char going to Mismatch
CMP[ESI], al //check if char match
JNE Mismatch //if yes go to Mismatch
INC ESI //else repeat Search to check if next char match
INC EDI
INC ECX //chars counter
JMP Search
Match :
INC EBX //occurrences counter
TEST EBX, 00000001h
JZ Mismatch //if even go to Mismatch else continue...
LEA EDI, str2 //else point to new string to replace
MOV EDX, ESI //copy the current original pointer
POP ESI //store it also into the stack
Replacement :
MOV AL, [EDI] //copy new string char by char
CMP AL, 0
JE SetRegister //if end of new string, get back the pointers
MOV[ESI], AL //else continue...
INC ESI
INC EDI
JMP Replacement
Mismatch :
POP EDI //edi points to result
SUB ESI, ECX //set esi to the char it was pointing before Search or Match
INC ECX //shows how many chars we need to replace
REP MOVSB //ready to copy chars from original to result
PUSH EDI
CMP[ESI], 0 //check if original has ended
JZ Fine
DEC ESI
XOR ECX, ECX //set to zero the chars counter
JMP Next //go to Next char
SetRegister :
PUSH ESI //after replacement set registers right positions
MOV ESI, EDX
DEC ESI
XOR ECX, ECX
Next :
LEA EDI, find //ready to find next char
INC ESI
CMP[ESI], 0
JNE Search
Fine :
POP EDI
MOV[EDI], 0 //close the result string
谢谢大家。