extracting the first line out of a text paragraph in delphi
I have text being passed to a function. That text can contain anything, from a single chara开发者_如何学JAVActer all the way to a full book.
I need to extract the first like and use it as a "title" so I can name a file where I am saving that text as a backup. I am using the following:
function GetTitle(var Text:string):string;
var
title: string;
position: integer;
begin
title := '';
position := AnsiPos(#10, Text);
if position = 0 then
begin
position := AnsiPos('.', Text);
if (position = 0) then
title := Text
else
title := copy(Text, 1, position);
end
else
begin
title := copy(Text, 1, position);
end;
result := title;
end;
I'm checking #10 and not #13 because the text can be either passed from a Windows app or a Mac OS X app. In cases where there is no #10 I'm checking for the 1st . (dot) and if there is none then I am passing the whole thing as a title.
This approach is causing some problems with filenames containing #13 in the name or names being too long. I can add a check for > 256 on title but that's just another thing.Anyway, is there any way to properly read the first line (including #13#10 or #10 or #13 or . or whatever)?
I know this is simple, but I can't seem to find a way to deal with this without having nested ifs...
code is appreciated. thank you
What you're doing sounds like the most you can do given the arbitrary nature of your input, but it's not going to be enough because there is no guarantee that the first sentence in your arbitrary text will be short enough to be a title. You need to add a step to truncate the text if it is longer than some arbitrary length limit, and add ellipsis (three dots ...) to indicate that there is more text.
hmmm, this one works:
function TForm1.SimpleNoteGetTitle(Text:string):string;
var
position: integer;
begin
position := AnsiPos(#13#10, Text);
if (position = 0) or (position > 50) then position := AnsiPos(#10, Text);
if (position = 0) or (position > 50) then position := AnsiPos(#13, Text);
if (position = 0) or (position > 50) then position := AnsiPos('.', Text);
if (position = 0) or (position > 50) then position := AnsiPos(',', Text);
if (position = 0) or (position > 50) then position := AnsiPos(';', Text);
if (position = 0) or (position > 50) then position := AnsiPos('?', Text);
if (position = 0) or (position > 50) then position := AnsiPos('!', Text);
if (position = 0) or (position > 50) then position := AnsiPos(' ', Text);
if position = 0 then
result := Text
else
result := copy(Text, 1, position - 1);
end;
UPDATED version of the function
This may not be the best way, but it does eliminate the nested if's...
function GetTitle(var Text:string):string;
var
position1: integer;
position2: integer;
position3: integer;
position: integer;
begin
Text := copy(Text,0,255);
position1 := AnsiPos(#10, Text);
position2 := AnsiPos(#13, Text);
position3 := AnsiPos('.', Text);
if position1 = 0 then position1 := 255;
if position2 = 0 then position2 := 255;
if position3 = 0 then position3 := 255;
position := Min(Min(position1,position2),position3);
result := copy(Text, 1, position);
end;
I'd tackle the problem with a loop, probably a bit faster than multiple calls to Pos.
function GetTitle(const Text:string):string;
var
I: integer;
begin
I := 0;
while I < Length(Text) do
begin
if (Text[I+1] in [#10,#13,'.']) then
Break;
Inc(I);
end;
Result := Copy(Text,1,I);
end;
Why not extract up to (say) 10 words from the beginning of the string while ignoring illegal file characters such as CR, LF, : . etc if they exist.
and make that the title?
more complex but certain to produce a legal filename
just a thought :)
精彩评论