SyntacticNewbie
SyntacticNewbie

Reputation: 23

String output strangeness

I'm very much a newbie to Ada and I'm trying to teach myself, with the assistance of one of John Barnes' books.

While dabbling with strings, I wrote a very basic program to read user input from the keyboard and then output it again to the console. However, when the output is produced, it appears to contain additional characters that have not been explicitly typed. Looking at it, my gut reaction is that it's unicode/Konsole-related but I definitely cannot discount whether or not it's something that I have done wrong in my code.

I have attached a screenshot of the program and its output. Any ideas would be greatly appreciated.

enter image description here

Thanks!

Image showing code and output

Upvotes: 2

Views: 148

Answers (1)

user1818839
user1818839

Reputation:

The difference is that strings are NOT null terminated; they are exactly as long as they say they are : in this case, 100 characters.

And not all the characters in your example are what you typed.

Quick fix : only output the Len characters you typed...

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

(I have used the standard portable natural'image(Len) rather than the compiler-specific Len'img form)

This leaves some remaining problems :

  • if you type more than 100 characters, the result will be safe but unsatisfactory.
  • you need to specify the slice boundaries (1..Len) everywhere you need the string.

Better fix : create a string of exactly the length you typed. Easiest way is calling the function form of Get_Line, and initialising an unconstrained String from the function's return value. The unconstrained String has no defined length when it is declared, it gets its length from the initialisation. For this to work, we can start a new block...

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

Notice that there is no more need for the Len variable. The string's length is an attribute of the string, not a separate quantity that may be incorrectly managed; one less thing to go wrong.

And the declare block is a safe and powerful technique for allocating runtime sized storage without needing heap allocation routines, pointers, deallocation etc. Several less things to go wrong.

It is usually a good idea (thanks Simon!) to make UserString a Constant. Not essential (otherwise you can edit it in place, but not change its length) but assuming you don't intend to edit it - one less thing to go wrong.

There are other techniques involving Bounded_String or Unbounded_String but they aren't really necessary here.

Upvotes: 3

Related Questions