#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. Спасибо, Брайан, думаю, теперь я понимаю. Мне нужно еще кое-что изучить!