function delstrblank(astr: String): String;
var
i: Integer;
s: String;
begin
Result:='';
for i:=0 to length(astr) do
begin
s:=copy(astr,i,1);
if s<>' 'then
Result := Result + s;
end;
end;
消除str字符串中的空格!
var
str:string;
index,j:integer;
begin
j:=length(str);
while j>0 do
begin
index:=pos(' ',str);
delete(str,index,1);
j:=j-1;
end;
此时得到的str就没有空格了
这样是不是好些?
procedure ss(var s:string);
var
i,j:integer;
begin
j := 1;
for i := 1 to length(s) do
begin
if s<>' ' then
begin
if j <> i then s[j] := s;
inc(j);
end;
end;
setlength(s,j-1);
end;
你的代码改成
var
str:string;
index,j:integer;
begin
index:=pos(' ',str);
while index>0 do
begin
delete(str,index,1);
index:=pos(' ',str);
end;
end;
才是比较正确的写法。
不过我觉得效率低了点,每次使用pos,还要从字符串的起始位置去搜索空格,有点浪费。
直接逐字搜索,可能效果更好,一次搜索就完成。没有浪费的对比。
又看到此帖,既然说到效率,就小小测试了一下
function ss(var s:string):integer;//改了下代码顺便统计下空格数
var
i,j:integer;
begin
j := 1;
Result := length(s);
for i := 1 to Result do
begin
if s<>' ' then
begin
if j <> i then s[j] := s;
inc(j);
end;
end;
setlength(s,j-1);
Result := Result - j + 1;
end;
找了个文件测试,721550字节,空格:67912,结果:
我 :20ms左右
无泪:等了10分钟,放弃,终止运行时j=634820
monkeyking1983:等了2分钟,也放弃
测试中感觉length函数比较慢,就又修改了下程序:
function ss2(var s:string):integer;
var
i,j:integer;
begin
j := 1;
Result := pinteger(integer(s)-4)^;//不用length了
for i := 1 to Result do
begin
if s<>' ' then
begin
if j <> i then s[j] := s;
inc(j);
end;
end;
setlength(s,j-1);
Result := Result - j + 1;
end;
测试20次,最快992ms,最慢1022ms,平均1004.7ms。
因为delphi对string的处理方式是copy on write,所以,在处理大字符串或循环次数多时,尽量不要用会写字符串的操作、函数,否则效率极低,而单纯检索一遍字符串的速度还是相当快的,38M的字符串,大约1″左右也就够了,我的机器PⅢ800+192M。
如果不用汇编的话,这种可能简单一些(从后往前来):
procedure DeleteBlank(var s: string);
var
i: LongWord;
begin
i := Length(s);
while i > 0 do
begin
if s = #32 then Delete(s, i, 1);
Dec(i);
end;
end;
1983,pos是效率的一个原因,无泪的程序效率低的另外一大原因是delete,delphi对字符串处理是copy on write,也就是,每当修改字符串时,都会重新申请内存,700k的字符串,每次调用delete删除一个空格,都会导致重新申请700k内存、复制、释放这么一个过程,可以想像,处理721550|67912这样的字符串,会重复申请67912次700k内存,这是很大的一个开销。
function Kill32(StrPointointer):Integer;
asm
PUSH EDI //保留这些寄存器进栈
PUSH ESI
PUSH EBX
MOV EDI,EAX //设置目标和源指针,指向字串的第一个字节
MOV ESI,EAX
MOV ECX,StrLong //设置循环长度,即字串长度
XOR EBX,EBX //初始化目标长度计数器,记录字串处理后的长度
@@J2: //循环体开始
MOV AL,[ESI] //取一个字节
OR AL,AL //字串是否结束
JZ @@J3
CMP AL, 32 //32是空格的编码
JZ @@J1 //是空格则跳过,不处理
MOV [EDI],AL //非空格,则保存到目标指针的位置
INC EDI //目标指针加一
INC EBX //目标长度计数器加一
@@J1:
INC ESI //源指针加一
JMP @@J2 //执行循环体
@@J3:
MOV RESULT,EBX //返回处理后字串的长度
POP EBX //从栈中恢复寄存器
POP ESI
POP EDI
end;
调用例子
var
s:string;
begin
s := '1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l ';
L := Kill32(@S[1]);
SetLength(S, L); //在汇编程序里面完全可以给处理结果填写结束符
//但考虑到是在使用Delphi写程序而不是汇编
//要照顾它的内存分配,所以保留这行
......
end;