在这个问题的最后,您似乎在寻求 Ada 字符串处理方面的帮助。
是的,Ada 字符串确实最好作为静态字符串处理,而不是可调整大小的缓冲区。有三种典型的方法来处理这个问题。
第一个是创建一个非常大的String
缓冲区,用一个单独的Natural
变量来保存字符串的逻辑长度。这有点痛苦,而且有点容易出错,但至少比 C 中在缓冲区末尾不断扫描空值的方法快。
第二种是直接使用 Ada.Strings.Unbounded.Unbounded_String。这是大多数人所做的,因为如果您习惯于以程序方式思考事物,那将是最简单的。
第三,(如果可能的话,我更喜欢)是在功能上处理你的字符串。您在这里需要的主要见解是 AdaString
确实是静态的,但您可以控制它们的生命周期,并且如果您进行函数式编程,您可以随时动态地制作静态字符串。
例如,我可以Token
通过执行以下操作来创建一个我想要的任何长度的新字符串(理论上无限前瞻):
function Matches_Token (Scanned : String) return boolean; --// Returns true if the given string is a token
function Could_Match_Longer (Scanned : String) return boolean; --// Returns true if the given string could be part of a larger token.
function Get_Next_Char return Character; --// Returns the next character from the stream
procedure Unget; --// Puts the last character back onto the stream
procedure Advance (Amount : Natural); --// Advance the stream pointer the given amount
function Longest_Matching_Token (Scanned : String) return String is
New_Token : constant String := Scanned & Get_Next_Char;
begin
--// Find the longest token a further scan can match
if Could_Match_Longer(New_Token) then
declare
LMT : constant String := Longest_Matching_Token (New_Token);
begin
if LMT /= "" then
unget;
return LMT;
end if;
end;
end if;
--// See if this string at least matches.
if Matches_Token(New_Token) then
unget;
return New_Token;
else
unget;
return "";
end if;
end Build_Token;
function Get_Next_Token return String is
Next_Token : constant String := Build_Token("");
begin
Advance (Next_Token'length);
return Next_Token;
end Get_Next_Token;
这并不总是最有效的字符串处理方法(堆栈使用过多),但它通常是最简单的。
在实践中,扫描和解析实际上是一种特殊情况的应用程序,通常建议避免丑陋的东西,例如缓冲区(方法 1)和 goto。