关于去除段首全角空格的问题(20分)

  • 主题发起人 主题发起人 *HelloWorld*
  • 开始时间 开始时间
H

*HelloWorld*

Unregistered / Unconfirmed
GUEST, unregistred user!
哪位朋友能给出一个函数,可以去除段落前面的全角空格?(一个全角空格的ASCII字符是
161,161)。Delphi中的Trim等函数只能处理半角字符。
谢谢!
 
while pos(youstring, '此处输入中文空格') > 0 then
delete(youstring,pos(pos(youstring, '此处输入中文空格'), 1);
 
刚才的答案错误。
 
不过您给的delete函数倒让我眼前一亮!非常有用!!!
 
还是没写出来这个函数,谁能帮一下忙?
 
function resultstrings(S:string):string;
begin
while Pos(' ', S)>0 do
delete(s,Pos(' ', S),2);
result:=trim(s);
end;
 
你是 哈达 阿?我是海波阿!
 
是我,没想到在论坛里我们又遇到了。
在给同事写一个排版的小东西,还有这个去除空格的功能没写出来(英文的好说,就是这中文
全角难弄),用了很长时间却不得要领。你能帮我想一想吗?
 
因为*HelloWorld*要求的只是去除字串的前导空格,
所以前两位的代码明显不能完成要求,把字串中所有的全角空格都删了。

以下函数删除一个串的前导空格,不论半角还是全角。这里没有用Pos函数,
而是直接用循环来解决,代码效率应该比在循环中调用POS来得高。

function MyTrimLeft(const S: string): string;
var
ci,sl: integer;
c: char;
begin
ci:=1
sl:=length(S);
while (ci<sl) do
begin
c:=S[ci];
case c of
' ': inc(ci);
#161: if S[ci+1]=c then inc(ci,2);
else break;
end;
end;
Result:=Copy(S,ci,MAXINT);
end;
 
更正一个小错误,当一个串全是空格且最后一个空格为半角空格时
上面的函数会返回一个空格。

更正后的代码:
function MyTrimLeft(const S: string): string;
var
ci,sl: integer;
c: char;
begin
ci:=1
sl:=length(S);
while (ci<=sl) do
begin
c:=S[ci];
case c of
'1': inc(ci);
#161: if (ci<sl) and (S[ci+1]=c) then inc(ci,2);
else break;
end;
end;
Result:=Copy(S,ci,MAXINT);
end;

另外,要写一个MyTrimRight可以采取类似的逻辑
 
谢谢skyweb!用了你给的函数后可以了。但是还有一个问题,也许是我写的代码效率太低了,
程序只能对少量的文本管用,如果文本一多(大概中文1000出头)就会死掉,(这时CPU利用率
马上达到100%)。下面是我引用您给的函数后整体代码,您能帮我看一看怎样优化它吗?谢谢!!!

procedure TForm1.Button4Click(Sender: TObject);
var
s1,s2,s3:string
//s1接收richedit1中的文本等待排列,我把s1中的每一段赋值给s2,然后
//传递给MyTrimLeft函数,得出s3。然后s2归零,重新被赋值为下一段,
//再传递给MyTrimLeft,再得出s3。依次类推,s3最后加起来就是结果。
i:integer;
begin
s1:=richedit1.text
//s1就是需要排列的那段文字
s2:='';

for i:=1 to length(s1) do
begin
s2:=s2+s1
//如果不到段末(#10),则s2一直加下去
if s1=#10 then //如果到了段末
begin
s3:=s3+MyTrimLeft(s2)
//把s2传给MyTrimLeft,得到s3
s2:=''
//s2归零,进入下一轮循环
end;
end;
s3:=s3+MyTrimLeft(s2)
//最后还剩下一点s2,同样传出去,得到s3

richedit2.Lines.Clear;
richedit2.Text:=s3;//把最后结果s3显示出来


end;
 
想要你的程序在不会象死了一样没有反应, 可以在循环体内加上一句
Application.ProcessMessages;以处理Windows消息.

另外,临时中转用的s2可以省略,我们只要记住上一个段落的结尾索引
号即可.

procedure TForm1.Button4Click(Sender: TObject);
var
s1,s3:string;
i,j:integer;
begin
s1:=richedit1.text
//s1就是需要排列的那段文字
j:=1;
for i:=1 to length(s1) do
begin
if s1=#10 then //如果到了段末
begin
s3:=s3+MyTrimLeft(Copy(s1,j,i-j+1));
j:=i+1;
end;
// 为了在长时间循环过程中不让程序看上去像死了一样,
// 可以在循环体中调用Application.ProcessMessages,
// 来处理Windows消息.
// 但是在本例中每次循环的时间很短,如果每次都调用
// Application.ProcessMessage,明显浪费时间,所以我
// 们指定一个循环次数,达到该次数后再处理Windows消
// 息. 或者把Application.ProcessMessages放到上面
// 的 if s1=#10 then 条件判断体内.
if i mod 100 = 0 then
Application.ProcessMessages;
end;
if j<i then
s3:=s3+MyTrimLeft(Copy(s1,j,i-j+1));
richedit2.Text:=s3;//把最后结果s3显示出来
end;

另一个用Pos函数的版本,比上一个看起来简单,执行效率上差一些

procedure TForm1.Button4Click(Sender: TObject);
var
s1,s3:string;
i,j:integer;
begin
s1:=richedit1.text
//s1就是需要排列的那段文字
i:=Pos(#10,s1);
while i>0 do
begin
s3:=s3+MyTrimLeft(Copy(s1,1,i));
Delete(s1,1,i);
i:=Pos(#10,s1);
Application.ProcessMessages;
end;
if s1<>'' then
s3:=s3+MyTrimLeft(s1);
richedit2.Text:=s3;//把最后结果s3显示出来
end;
 
谢谢skyweb!!!我马上就去试!
你说的对,用三个s太浪费了,应该可以省出一个的。
 
多人接受答案了。
 
后退
顶部