Как разобрать разные части строки на отдельные переменные?

#ada

#ada

Вопрос:

Как мне получить «IL», затем сохранить его в TempCode, который является строкой, и так далее, чтобы дать каждому слову, целому числу и переменной с плавающей точкой временную переменную. Затем получите следующий временный код и так далее. Весь смысл в том, чтобы получить определенный код в столбце Code, затем выполнить эту операцию и получить отдел, имя / поставщика, название, идентификатор и размер оплаты для использования.

     with Ada.Text_IO;       use Ada.Text_IO;
    with GNAT.String_Split; use GNAT.String_Split;
    
    procedure TextFile is
       File   : File_Type;
   Tokens : Slice_Set;
   --Index : Slice_Number;
   TempCode: String := "";
begin
   Open (File, In_File, "DynList.txt");
   -- Skip the file header
   Skip_Line (File);
   -- Read the data
   while not End_Of_File (File) loop
      -- Split the line from the file on array which contains separated
      -- words. Treat multiple spaces as a single separator (don't
      -- create empty elements).
      Create (Tokens, Get_Line (File), " ", Multiple);
      -- Print each of the array's values
      for I in 1 .. Slice_Count (Tokens) loop
--I have try using function Separators 
         Put_Line (Slice (Tokens, I));
      end loop;

   end loop;

   Close (File);
    end TextFile;
  

Store.txt

 Code    Department  Name/Vendor  Title          ID      Payrate
IL      Sales       John         Sales_person   1378    25.46
IR      Crew        Jesse        Sales_person   1379    25.46 
  

Ответ №1:

Сначала вы хотите определить тип для вашего payrate. Float будет работать, но я бы рекомендовал вместо этого использовать тип с фиксированной точкой, поскольку он печатает более чистый для того, что вы хотите.

 type Payrate_Type is delta 0.01 range 0.00 .. 1000.00;
  

Чтобы прочитать значения для вашего типа, вам нужно создать экземпляр универсального файла Ada.Text_IO.Fixed_IO:

 package Payrate_IO is new Ada.Text_IO.Fixed_IO(Payrate_Type);
  

Затем я бы сгруппировал все ваши переменные для каждого поля в одну запись. Используйте Unbounded_String для хранения строк, естественных для идентификатора, и типа вашей ставки оплаты для вашей ставки оплаты.

 type Line_Info is record
    Code       : Unbounded_String;
    Department : Unbounded_String;
    Name       : Unbounded_String;
    Title      : Unbounded_String;
    ID         : Natural;
    Payrate    : Payrate_Type;
end record;

A_Line : Line_Info;
  

Затем для каждой итерации вашего цикла while вместо цикла for вы просто выполняете отдельные назначения для каждого из различных фрагментов фрагмента:

 A_Line.Code       := To_Unbounded_String(Slice(Tokens, 1));
A_Line.Department := To_Unbounded_String(Slice(Tokens, 2));
A_Line.Name       := To_Unbounded_String(Slice(Tokens, 3));
A_Line.Title      := To_Unbounded_String(Slice(Tokens, 4));
A_Line.ID         := Natural'Value(Slice(Tokens, 5));
Payrate_IO.Get(Slice(Tokens,6),A_Line.Payrate,Last);
  

Вам нужно будет выполнить некоторую логику обработки исключений, чтобы учесть, когда ваш ввод неверен. Я оставлю это на ваше усмотрение.

Вот тестовая программа для вашего набора входных данных:

 with Ada.Text_IO;       use Ada.Text_IO;
with GNAT.String_Split; use GNAT.String_Split;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
    
procedure Hello is
    Tokens : Slice_Set;
    --Index : Slice_Number;
    TempCode: String := "";
    
    type Payrate_Type is delta 0.01 range 0.00 .. 1000.00;
    
    type Line_Info is record
        Code       : Unbounded_String;
        Department : Unbounded_String;
        Name       : Unbounded_String;
        Title      : Unbounded_String;
        ID         : Natural;
        Payrate    : Payrate_Type;
    end record;
    
    A_Line : Line_Info;
    
    package Payrate_IO is new Ada.Text_IO.Fixed_IO(Payrate_Type);
    
    Last : Positive;
    
begin
    Put_Line("Hello, world!");
    Skip_Line;
    -- Read the data
    while not End_Of_File loop
        -- Split the line from the file on array which contains separated
        -- words. Treat multiple spaces as a single separator (don't
        -- create empty elements).
        Create (Tokens, Get_Line, " ", Multiple);
        -- Print each of the array's values
        
        A_Line.Code       := To_Unbounded_String(Slice(Tokens, 1));
        A_Line.Department := To_Unbounded_String(Slice(Tokens, 2));
        A_Line.Name       := To_Unbounded_String(Slice(Tokens, 3));
        A_Line.Title      := To_Unbounded_String(Slice(Tokens, 4));
        A_Line.ID         := Natural'Value(Slice(Tokens, 5));
        Payrate_IO.Get(Slice(Tokens,6),A_Line.Payrate,Last);
        
        Put_Line(To_String(A_Line.Code));
        Put_Line(To_String(A_Line.Department));
        Put_Line(To_String(A_Line.Name));
        Put_Line(To_String(A_Line.Title));
        Put_Line(A_Line.ID'Image);
        Put_Line(A_Line.Payrate'Image);

    end loop;
end Hello;
  

И вывод:

 $gnatmake -o hello *.adb
gcc -c hello.adb
gnatbind -x hello.ali
gnatlink hello.ali -o hello
$hello
Hello, world!
IL
Sales
John
Sales_person
 1378
 25.46
IR
Crew
Jesse
Sales_person
 1379
 25.46
  

Обратите внимание, что я удалил ваш тип файла и вызовы, чтобы я мог очень быстро протестировать, используя standard in в качестве источника ввода.

Комментарии:

1. Возможно, вы захотите использовать здесь десятичный тип с фиксированной запятой вместо обычного типа с фиксированной запятой. Обычные типы с фиксированной запятой (без явно определенного значения для Small атрибута) приведут к проблемам при выполнении умножения и деления позже (попробуйте вычислить, например 10 * 25.46 , с помощью type Payrate_Type и проверьте результат). Десятичные типы с фиксированной запятой были добавлены в Ada 95 для решения этих проблем при обработке финансовых данных.