สร้างฟังก์ชันแทนที่สำหรับสตริงใน Delphi
หมายเหตุบรรณาธิการ: อันที่จริงแล้ว ฟังก์ชัน StringReplace ของ Delphi ได้รับการออกแบบมาโดยเฉพาะเพื่อตอบสนองความต้องการนี้ แต่เรายังเผยแพร่บทความนี้ - อย่างน้อยผู้เขียนก็มีทางเลือกอื่นและควรส่งเสริมจิตวิญญาณแห่งการสำรวจ! นี่เป็นบทความแรกของฉันที่นี่ และเนื่องจากระดับของฉันไม่สูงมาก ฉันจะพูดถึงประเด็นพื้นฐานแต่ใช้งานได้จริง ฉันหวังว่ามันจะช่วยคุณได้บ้าง เพื่อนที่เคยใช้ VB หรือ ASP ทราบดีว่ามีฟังก์ชันการแทนที่ที่เป็นประโยชน์มากใน VB ฟังก์ชันคือการแทนที่สตริงที่ตรงกับสตริงย่อย (หรือที่เรียกว่าสตริงรูปแบบ) ในสตริงด้วยสตริงที่ระบุ ตัวอย่างเช่น มีสตริงดังกล่าว: s:='apple is apple!' หลังจากใช้ฟังก์ชันแทนที่เพื่อแทนที่ (s,'apple','box') s จะกลายเป็น 'box is box!' ความยาวของสตริงก็เปลี่ยนแปลงตามไปด้วย นี่เป็นฟังก์ชันที่มีประโยชน์มาก ทุกคนรู้ดีว่าคำสั่ง sql แบบมีโครงสร้างมักใช้เมื่อพัฒนาระบบฐานข้อมูล และคำสั่งนี้มีความละเอียดอ่อนต่ออักขระบางตัว เช่น เครื่องหมายคำพูดเดี่ยว หากเครื่องหมายคำพูดเดี่ยวปรากฏในเครื่องหมายคำพูดของ sql (เนื่องจากเครื่องหมายคำพูดเดี่ยว) ใช้ในตารางเมตร l) โปรแกรมจะทำให้เกิดข้อผิดพลาดที่ไม่คาดคิด และยังสามารถถูกใช้โดยผู้อื่นเพื่อสร้างช่องโหว่ด้านความปลอดภัยที่ร้ายแรงในระบบ (นี่คือการโจมตีแบบฉีด SQL ที่มีชื่อเสียง ฉันเชื่อว่าทุกคนยังจำสิ่งที่ถูกค้นพบโดยฟอรัม CSDN มาก่อน) นี่เป็นช่องโหว่ ). ในเวลานี้ คุณต้องแทนที่เครื่องหมายคำพูดเดี่ยวด้วยสตริงอื่นหรือสตริงว่างระหว่างการทำงานของฐานข้อมูล จากนั้นแทนที่กลับเมื่ออ่านข้อมูล เพื่อให้สามารถบันทึกเครื่องหมายคำพูดเดี่ยวในบันทึกข้อมูลได้โดยไม่มีข้อผิดพลาด อย่างไรก็ตาม ฉันไม่พบฟังก์ชันที่คล้ายกันใน Delphi (บางทีฉันอาจจะไม่พบมันใช่ไหม) ซึ่งไม่สะดวกจริงๆ ดังนั้นฉันจึงเขียนขึ้นมาเอง ซึ่งจะสะดวกกว่ามากในการพัฒนาระบบฐานข้อมูลในอนาคต หลังจากพูดเรื่องไร้สาระมามากมาย นี่คือโค้ด มันควรจะเข้าใจง่ายกว่าด้วยความคิดเห็น
PROcedure แทนที่(var s:string;const SourceChar:pchar;const RChar:pchar); // พารามิเตอร์ตัวแรกคือสตริงดั้งเดิม ตัวที่สองคือสตริงรูปแบบ และตัวที่สามคือสตริงการแทนที่ var ta,i,j: จำนวนเต็ม ; m,n,pn,sn:จำนวนเต็ม; SLen,SCLen,RCLen:integer;//SLen แสดงถึงความยาวของสตริงดั้งเดิม, SCLen แสดงถึงความยาวที่ส่งผ่านโดยโหมด, RCLen แสดงถึงความยาวของสตริงการแทนที่ IsSame:integer; newp:array of char;// Used to บันทึกอาร์เรย์อักขระที่ถูกแทนที่ เริ่มต้น SLen:=strlen(pchar(s));SCLen:=strlen(SourceChar);RCLen:=strlen(RChar); j:=pos(string(SourceChar),s); s:=s+chr(0);ta:=0;i:=j; ในขณะที่ s[i]<>chr(0) do // วงนี้ใช้ ta นับจำนวนครั้งที่สตริงรูปแบบปรากฏในสตริงดั้งเดิม start n:=0;IsSame:=1; for m:=i ถึง i+SCLen-1 do beginning if m>SLen จากนั้น start IsSame:=0;break ; จบ ; s[m]<>sourceChar[n] จากนั้นให้เริ่มต้น IsSame:=0;break; end; n:=n+1; end ; i:=i+1; end; ถ้า j>0 ให้ เริ่ม pn:=0;sn:=1; setlength(newp,SLen-ta*SCLen+ta*RCLen+1);// จัดสรร ความยาวของ newp, +1 หมายความว่ามี เทอร์มิเนเตอร์ #0 อยู่ด้านหลัง
ขณะที่ s[sn]<>chr(0) do // ส่วนใหญ่จะวนซ้ำ เริ่มแทนที่ start n:=0;IsSame:=1; สำหรับ m:=sn ถึง sn+SCLen-1 do // เปรียบเทียบว่าสตริงย่อยเหมือนกับสตริงรูปแบบ start หรือไม่
ถ้า m>SLen เริ่มต้น IsSame:=0;break; end; if s[m]<
> sourceChar
[ n] จากนั้นให้เริ่ม
IsSame :=0;break; n:=n+ 1 ; m:=0 ถึง RCLen-1 จะ เริ่มต้น newp [ pn]:=RChar[m];pn:=pn+1; end ; sn:=sn+SCLen; // newp[pn]
: =s[sn]; pn :
= pn+1; end ; / รีเซ็ต การเปลี่ยนเสร็จสมบูรณ์! สิ้นสุด ; ที่จริงแล้ว นี่เป็นปัญหาเกี่ยวกับโครงสร้างข้อมูลพื้นฐาน ในปัจจุบัน เมื่อเรามักจะเขียนโปรแกรมด้วยการควบคุมแบบลากแล้ววาง เราควรฝึกโครงสร้างข้อมูลเพียงอย่างเดียว แน่นอนว่าฟังก์ชันนี้ไม่ได้เขียนอย่างเหมาะสมที่สุด ฉันทดสอบการแทนที่สตริง 10,000 คำแล้วและใช้เวลาเพียงครึ่งวินาทีเท่านั้น ความซับซ้อนของเวลายังค่อนข้างสูง หากคุณมีวิธีที่ดีกว่า โปรดหารือเกี่ยวกับเรื่องนี้