Мне нужно вычеркнуть все нестандартные символы символов из строки. Мне нужно удалить все не ascii и управляющие символы (кроме строк/возврат каретки).
Delphi - вырезать все нестандартные символы текста из строки
Ответ 1
Что-то вроде этого должно делать:
// For those who need a disclaimer:
// This code is meant as a sample to show you how the basic check for non-ASCII characters goes
// It will give low performance with long strings that are called often.
// Use a TStringBuilder, or SetLength & Integer loop index to optimize.
// If you need really optimized code, pass this on to the FastCode people.
function StripNonAsciiExceptCRLF(const Value: AnsiString): AnsiString;
var
AnsiCh: AnsiChar;
begin
for AnsiCh in Value do
if (AnsiCh >= #32) and (AnsiCh <= #127) and (AnsiCh <> #13) and (AnsiCh <> #10) then
Result := Result + AnsiCh;
end;
Для UnicodeString
вы можете сделать что-то подобное.
Ответ 2
И вот вариант Cosmin, который только один раз перемещает строку, но использует эффективный шаблон распределения:
function StrippedOfNonAscii(const s: string): string;
var
i, Count: Integer;
begin
SetLength(Result, Length(s));
Count := 0;
for i := 1 to Length(s) do begin
if ((s[i] >= #32) and (s[i] <= #127)) or (s[i] in [#10, #13]) then begin
inc(Count);
Result[Count] := s[i];
end;
end;
SetLength(Result, Count);
end;
Ответ 3
если вам не нужно делать это на месте, но генерируя копию строки, попробуйте этот код
type CharSet=Set of Char;
function StripCharsInSet(s:string; c:CharSet):string;
var i:Integer;
begin
result:='';
for i:=1 to Length(s) do
if not (s[i] in c) then
result:=result+s[i];
end;
и используйте его так:
s := StripCharsInSet(s,[#0..#9,#11,#12,#14..#31,#127]);
EDIT: добавлено # 127 для DEL ctrl char.
EDIT2: это более быстрая версия, благодаря ldsandon
function StripCharsInSet(s:string; c:CharSet):string;
var i,j:Integer;
begin
SetLength(result,Length(s));
j:=0;
for i:=1 to Length(s) do
if not (s[i] in c) then
begin
inc(j);
result[j]:=s[i];
end;
SetLength(result,j);
end;
Ответ 4
Здесь версия, которая не создает строку, добавляя char -by- char, но выделяет целую строку за один раз. Он требует перебора строки дважды, один раз, чтобы подсчитать "хороший" char, один раз, чтобы эффективно скопировать эти символы, но он того стоит, потому что он не выполняет множественные перераспределения:
function StripNonAscii(s:string):string;
var Count, i:Integer;
begin
Count := 0;
for i:=1 to Length(s) do
if ((s[i] >= #32) and (s[i] <= #127)) or (s[i] in [#10, #13]) then
Inc(Count);
if Count = Length(s) then
Result := s // No characters need to be removed, return the original string (no mem allocation!)
else
begin
SetLength(Result, Count);
Count := 1;
for i:=1 to Length(s) do
if ((s[i] >= #32) and (s[i] <= #127)) or (s[i] in [#10, #13]) then
begin
Result[Count] := s[i];
Inc(Count);
end;
end;
end;
Ответ 5
мое решение по производительности;
function StripNonAnsiChars(const AStr: String; const AIgnoreChars: TSysCharSet): string;
var
lBuilder: TStringBuilder;
I: Integer;
begin
lBuilder := TStringBuilder.Create;
try
for I := 1 to AStr.Length do
if CharInSet(AStr[I], [#32..#127] + AIgnoreChars) then
lBuilder.Append(AStr[I]);
Result := lBuilder.ToString;
finally
FreeAndNil(lBuilder);
end;
end;
Я написал delphi xe7
Ответ 6
моя версия с массивом результата массива:
интерфейс
type
TSBox = array of byte;
и функция:
function StripNonAscii(buf: array of byte): TSBox;
var temp: TSBox;
countr, countr2: integer;
const validchars : TSysCharSet = [#32..#127];
begin
if Length(buf) = 0 then exit;
countr2:= 0;
SetLength(temp, Length(buf)); //setze temp auf länge buff
for countr := 0 to Length(buf) do if CharInSet(chr(buf[countr]), validchars) then
begin
temp[countr2] := buf[countr];
inc(countr2); //count valid chars
end;
SetLength(temp, countr2);
Result := temp;
end;