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

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

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

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

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

Спасибо!

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


person SyntacticNewbie    schedule 28.06.2014    source источник
comment
При работе со строками в Аде полезно понимать массивы Ады — уделите особое внимание изучению атрибутов массива (таких как 'Length и 'Range), и вы быстро поймете, что такое строки.   -  person Shark8    schedule 02.07.2014


Ответы (1)


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

И не все символы в вашем примере - это то, что вы набрали.

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

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

(Я использовал стандартную переносимую форму 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: '" & UserString & "' (Chars: " &    
              natural'image(UserString'Length) & ")");
   -- other processing on UserString here
end;
-- UserString is now out of scope, automatically freed

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

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

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

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

person user_1818839    schedule 28.06.2014
comment
Спасибо, Брайан, кажется, теперь я понял. У меня еще есть чему поучиться! - person SyntacticNewbie; 28.06.2014