首页 > 解决方案 > 如何将字符串从 delphi 代码源转换为标准字符串以保存在数据库中?

问题描述

我编写了一个解析器来从我的 Delphi 代码中提取资源字符串,以将它们保存到我应该发送给翻译器的数据库中。

我的要求是:有没有一种简单的方法可以将 Delphi 字符串从源代码转换为准备保存到数据库中的“标准”字符串?

这是一个例子:从我的源代码中我有这个:

MyResourceString1 = 'Error : I can''t load the file from disk !';

或者

MyResourceString2 = 'Error : I can'#39't load the file from disk !';

然后在我的解析器过程之后,我提取了这些字符串值。但在将它们保存到数据库之前,我想将所有字符串转换为“标准”句子,如:

"Error : I can't load the file from disk !"

或者

"Error : I can't load the file from disk !"

我想使用与解析 Delphi 字符串不同的解释器函数将所有 #code 字符更改为正确的字符。

谢谢您的帮助。

标签: delphi

解决方案


使用简单的状态机很容易实现:

function TryParseStringLiteral(const ALiteral: string; out AString: string): Boolean;
var
  LLiteral: string;
  i, c: Integer;
  InQuotes: Boolean;
  InCharCode: Boolean;
  NumCodeStr: string;
  NumVal: Integer;
begin

  LLiteral := ALiteral.Trim;

  SetLength(AString, LLiteral.Length);

  InQuotes := False;
  InCharCode := False;
  NumCodeStr := '';
  NumVal := 0;
  c := 0;
  for i := 1 to LLiteral.Length do
  begin

    if InCharCode then
    begin
      if (LLiteral[i] = '#') or (LLiteral[i] = '''') then
      begin
        if TryStrToInt(NumCodeStr, NumVal) and InRange(NumVal, Word.MinValue, Word.MaxValue) then
        begin
          Inc(c);
          AString[c] := Chr(NumVal);
        end
        else
          Exit(False);
        InCharCode := LLiteral[i] = '#';
        InQuotes := LLiteral[i] = '''';
        NumCodeStr := '';
        NumVal := 0;
      end
      else
        NumCodeStr := NumCodeStr + LLiteral[i];
    end
    else if InQuotes then
    begin
      if (LLiteral[i] = '''') and (i < LLiteral.Length) and (LLiteral[Succ(i)] = '''') then
      begin
        InQuotes := False; // a bit of a hack
        Inc(c);
        AString[c] := '''';
      end
      else if LLiteral[i] = '''' then
        InQuotes := False
      else
      begin
        Inc(c);
        AString[c] := LLiteral[i];
      end;
    end
    else if LLiteral[i] = '''' then
      InQuotes := True
    else if LLiteral[i] = '#' then
      InCharCode := True
    else
      Exit(False);

  end;

  if InCharCode then
    if TryStrToInt(NumCodeStr, NumVal) and InRange(NumVal, Word.MinValue, Word.MaxValue) then
    begin
      Inc(c);
      AString[c] := Chr(NumVal);
    end
    else
      Exit(False);

  if InQuotes then
    Exit(False);

  SetLength(AString, c);
  Result := True;

end;

尝试一下:

procedure TForm1.Edit1Change(Sender: TObject);
var
  S: string;
begin
  if TryParseStringLiteral(Edit1.Text, S) then
    Edit2.Text := S
  else
    Edit2.Text := ' -- Invalid string literal -- ';
end;

一些例子:

'This is a test!'                    This is a test!
'What''s up?'                        What's up?
'alpha'#64'beta'#63                  alpha@beta?
'alpha'#$40'beta'#$3F                alpha@beta?
#94#94#94                            ^^^
#94#94#94'ABC'                       ^^^ABC
'ABC'#94#94#94                       ABC^^^
'ABC'#94#94#94'abc'                  ABC^^^abc
'ABC'#94#94#94'abc'#63'!'            ABC^^^abc?!
'test'#32'again'                     test again
'test'#32#32#$20'again'              test   again
''                                   
''''                                 '
''''''''                             '''
'a'                                  a
#65                                  A
#65#$21                              A!
'''test'''#65                        'test'A

推荐阅读