Странность вывода строки

#string #ada

#строка #ada

Вопрос:

Я очень новичок в Ada, и я пытаюсь научиться сам, с помощью одной из книг Джона Барнса.

Возясь со строками, я написал очень простую программу для чтения пользовательского ввода с клавиатуры, а затем снова выводил его на консоль. Однако, когда вывод создается, он, по-видимому, содержит дополнительные символы, которые не были введены явно. Глядя на это, моя внутренняя реакция заключается в том, что это связано с unicode / Konsole, но я определенно не могу сбрасывать со счетов, является ли это тем, что я сделал неправильно в своем коде.

Я приложил скриншот программы и ее вывода. Любые идеи будут с благодарностью приняты.

введите описание изображения здесь

Спасибо!

Изображение, показывающее код и вывод

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

1. При работе со строками в Ada это помогает понять массивы Ada — уделите особое внимание изучению атрибутов массива (например 'Length , и 'Range ), и вы быстро поймете строки.

Ответ №1:

Разница в том, что строки НЕ заканчиваются нулем; они ровно такой длины, как они говорят: в данном случае 100 символов.

И не все символы в вашем примере соответствуют тому, что вы ввели.

Быстрое исправление: выводите только введенные вами символы Len…

    Put_Line ("Your String: '" amp; UserString(1 .. Len) amp; "' (Chars: " amp; natural'image(Len) amp; ")");
 

(Я использовал стандартную переносимую natural'image(Len) , а не специфичную для компилятора Len'img форму)

Это оставляет некоторые оставшиеся проблемы :

  • если вы введете более 100 символов, результат будет безопасным, но неудовлетворительным.
  • вам нужно указать границы фрагмента (1 ..Len) везде, где вам нужна строка.

Лучшее исправление: создайте строку точно такой длины, какую вы ввели. Самый простой способ — вызвать функциональную форму Get_Line и инициализировать неограниченную строку из возвращаемого значения функции. Неограниченная строка не имеет определенной длины при объявлении, она получает свою длину из инициализации. Чтобы это сработало, мы можем запустить новый блок…

 Put_Line("Enter a string: ");
declare
   UserString : constant String := Get_Line;
   -- the string is now the correct length, however much you typed.
begin
   Put_Line ("Your String: '" amp; UserString amp; "' (Chars: " amp;    
              natural'image(UserString'Length) amp; ")");
   -- other processing on UserString here
end;
-- UserString is now out of scope, automatically freed
 

Обратите внимание, что в переменной больше нет необходимости Len . Длина строки является атрибутом строки, а не отдельной величиной, которая может быть неправильно обработана; одной ошибкой меньше.

И блок declare — это безопасный и мощный метод выделения хранилища размером с время выполнения без необходимости использования процедур выделения кучи, указателей, освобождения и т. Д. Несколько меньше вещей, которые могут пойти не так.

Обычно хорошей идеей (спасибо, Саймон!) является создание UserString Constant . Не обязательно (в противном случае вы можете отредактировать его на месте, но не изменять его длину), но предполагая, что вы не собираетесь его редактировать — на одну ошибку меньше.

Существуют и другие методы, включающие Bounded_String or Unbounded_String , но здесь они на самом деле не нужны.

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

1. Спасибо, Брайан, думаю, теперь я понимаю. Мне нужно еще кое-что изучить!