3

I am new to Ada and currently trying to write a simple program involving an if-else if statement. The code is as follows:

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure Year_Codes is

  Year : String(1..9) := "         ";
  CharsRead : Natural;

  function YearCode(Name : in String) return Integer is
  begin
    if(Name = "freshman")then
      return 1;
    elsif(Name = "sophomore")then
      return 2;
    elsif(Name = "junior")then
      return 3;
    elsif(Name = "senior")then
      return 4;
    else
      return 0;
    end if;
  end YearCode;


begin
  Put("Enter your academic year: ");           -- Prompt for input
  Get_Line(Year, CharsRead);                   -- Input
  Put( YearCode(Year) );                       -- Convert and output
  New_Line;
end Year_Codes;

I am getting 0 for every answer. Any input on what I am doing wrong?

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
ola
  • 882
  • 2
  • 12
  • 29
  • Your E-lisp program should be in a separate question. I've answered your Ada question; that answer has nothing to do with your E-lisp program. – Keith Thompson Feb 06 '13 at 22:09
  • I thought if I asked two I would be yelled at but I will take it out :| I'm sorry – ola Feb 06 '13 at 22:11
  • I've edited your Ada code to correct the indentation and add `with` and `use` clauses. I've also taken the liberty of updating your title and tags (the real issue is string comparison, not `if` statements). – Keith Thompson Feb 06 '13 at 22:11
  • thank you very much. You've been more than helpful. – ola Feb 06 '13 at 22:16

3 Answers3

7

The "=" operation on strings compares the entire strings. If the user's input is "freshman", the value of Name will be "freshman ", not "freshman". Read the documentation for the Get_Line procedure.

You should probably pass YearCode a slice of the Year string, not the entire string; CharsRead tells you what that slice should be.

Specifically, the call should be:

Put( YearCode(Year(Year'First..CharsRead)) );
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
  • thank you that did work for freshman, but the others after are still registering 0. Is something wrong with my ifels statements? – ola Feb 06 '13 at 22:09
  • @user1998581: I tried it myself, and it works; I enter `senior` and it prints `4`. – Keith Thompson Feb 06 '13 at 22:12
  • 1
    Note that the name `CharsRead` is a bit misleading here. Im RM, it is called `Last`: this variable contains the last character written in the input buffer, not the number of characters written. The difference becomes (especially) apparent when `Year'First` is larger than 1: the correct slice will still be `Year(Year'First..Last)` – Ansgar Esztermann Feb 07 '13 at 08:23
  • Also I'm noticing that his buffer is only 9 characters long. That will work, but could exhibit odd behavior if a user mistakenly enters a 10 or more character string. It would probably be better to make that buffer unreasonably large (eg: 256, 1K, something like that). – T.E.D. Feb 08 '13 at 09:53
3

Here's a case-insensitive version using attributes:

function YearCode(Name : in String) return Integer is
    Type Class is (Freshman, Sophmore, Junior, Senior);
begin
    Return 1 + Class'Pos(Class'Value(Name));  
exception
    When CONSTRAINT_ERROR => Return 0;
end YearCode;
Shark8
  • 4,095
  • 1
  • 17
  • 31
  • 1
    Big +1 here. This is my preferred method for dealing with user input against a fixed set of allowed command words. With a bit more work you can come up with a version that automatically prints the allowed commands upon request (eg in the contraint_error handler). Back in the day I even used to have some nice generic code that would automatically create menus and process menu input for a given enumerated type using DEC SMG$ calls. – T.E.D. Feb 08 '13 at 09:59
2

With that extra character in your buffer, it looks to me like you are thinking of strings in C terms. You need to stop that. Of everything in the language, string handling is the most different between Ada and C.

While C strings are null terminated, Ada strings are not. Instead, an Ada string is assumed to be the size of the string array object. Its a simple difference, but it has enormous consequences in how you handle strings.

I go into this a bit in my answer to How to I build a string from other strings in Ada? The basic gist is that in Ada you always try to build perfectly-sized string objects on the fly.

Sadly, Text_IO input is one place that has traditionally made that really hard, due to its string buffer-based input. In that case, you are forced to use an overly large string object as a buffer, and use the returned value as the end of the defined area of the buffer, as Keith showed.

However, if you have a new version of the compiler, you can use the function version of Get_Line to fix that. Simply change your middle two lines to:

Put( YearCode(Get_Line) );                       
Community
  • 1
  • 1
T.E.D.
  • 44,016
  • 10
  • 73
  • 134