كيف أقوم ببناء سلسلة من سلاسل أخرى في ADA؟
سؤال
أرغب في إخراج سطر رأس في ملف السجل ثم سطر "-" قبل البيانات. للقيام بذلك ، أقوم بإنشاء سلسلة من الرأس ثم تفوق على نفس العدد من "-".
لكن الرمز أدناه يفشل دائمًا باستخدام Crodent_error لأن السلسلة التي تم إنشاؤها ليست 1024 حرفًا. في واجبات سلسلة ADA تتطلب نفس الطول بالضبط وليس السعة الكافية فقط.
الخيار 1) هو حساب الطول الدقيق ولكن هذا هش إلى التغييرات المستقبلية. الخيار 2) هو استخدام شيء آخر غير السلسلة.
procedure F() is
Msg : String(1..1024);
begin
Open_Log();
Msg := FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16);
Log_To_File("# " & Msg);
Log_To_File("# " & Fill_String(Msg'Last, '-'));
end;
المحلول
الكثير من الناس الذين اعتادوا على طريقة C لبناء السلاسل في الخطوات يواجهون مشكلة من المفترض أن تهيئة واستخدامها كما هي. عندما تتجه إلى هذه الحقيقة حول سلاسل ADA ، يصبح الحل أبسط بكثير. يمكنني حتى رمي روتين "ملء" الخاص بك.
procedure F() is
Msg : constant String
:= FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16);
Separator : constant String := (1..Msg'length => '-'); --'
begin
Open_Log();
Log_To_File("# " & Msg);
Log_To_File("# " & Separator);
end;
(ملاحظة: التعليق هو اختراق لاستعادة ملونة SO على المسار الصحيح)
إذا لم يكن لديك فاصل بنفس الطول ، فلن تحتاج حتى إلى إعلان المتغير.
لو كان الأمر أنا ، سأفعل شيئًا مثل Log_To_File
تتبع الأطوال وإنشاء فاصل خاص به بشكل صحيح عند الطلب. ثم يمكنك الكتابة فقط:
Open_Log();
Log_To_File ("# " & FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16));
Log_Separator_To_File;
نصائح أخرى
ما عليك سوى إعلان MSG كسلسلة بدلاً من سلسلة (1 .. 1024)
procedure F() is
Msg: String
:= FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16);
--// this 'magically' declares Msg as a String(1 .. Something)
--// with the right Something
begin
Open_Log();
Log_To_File("# " & Msg);
Log_To_File("# " & Fill_String(Msg'Last, '-')); --'
end;
قد يكون أحد الأساليب هو كتابة وظيفة تملأ سلسلة طول ثابتة بسلسلة إدخال بحجم ديناميكي ، حشو مع المسافات:
procedure Pad_String(Str: in String; Dest: out String; Len: out Integer) is
begin
Len := Str'Last - Str'First + 1;
Dest(Dest'First .. Dest'First + Len - 1) := Str(Str'First .. Str'First + Len - 1);
Dest(Dest'First + Len .. Dest'Last) := Fill_String(Dest'Last - Len, ' ');
end Pad_String;
يتيح لك معالجة سلسلة ADA تمرير أي مخزن مؤقت للطول إلى Dest
و ال 'First
و 'Last
ستكون السمات صحيحة في نص الإجراء.
ثم ، يمكن أن يصبح الرمز الخاص بك:
procedure F() is
Msg : String(1..1024);
Len : Integer;
begin
Open_Log();
Pad_String( FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16),
Msg,
Len);
Log_To_File("# " & Msg(1 .. Len));
Log_To_File("# " & Fill_String(Len, '-'));
end;
كراحة ، يمكنك استخدام وظائف مُنشئ السلسلة في Ada.Strings.Fixed
, Ada.Strings.Bounded
أو Ada.Strings.Unbounded
. هذه الحمل الزائد للمشغل إلى "تكرار حرف أو سلسلة من المرات المحددة." فمثلا،
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
...
Log_To_File("# " & Length(Msg) * '-');
لقد عملت على كيفية استخدام undounded_string. هذا النوع سوف يقبل السلاسل الحجم الأخرى.
لا يمكنك إنشاء سلسلة غير محدودة مع المشغل إلا إذا كنت تستخدم سلاسل غير محدودة ، لذا استخدم وظيفة to_unbounded_string.
with Ada.Strings.Unbounded;
procedure F() is
use Ada.Strings.Unbounded;
Msg : Unbounded_String;
begin
Open_Log();
Msg := Ada.Strings.Unbounded.To_Unbounded_String(
FLS(" Field1", 12) &
"|" & FLS(" Field2", 12) &
"|" & FLS(" Field3", 16));
Log_To_File("# " & Ada.Strings.Unbounded.To_String(Msg));
Log_To_File("# " &
Fill_String(Ada.Strings.Unbounded.Length(Msg), '-'));
end;