1

This question is in regards to a program I'm working on for an intro to programming class in Ada. The only packages I can use are the basic text, integer, and float packages. I'm writing a procedure right now to remove the spaces from the string and I keep getting a constraint error on the same line. This is the line:

if inputString(count) /= Character'Val(32) then

I have count set to start at 1 and then increment through a loop until the end of the string, which would in turn check each character of the string to see if it was different than the character value of a blank space (32). I was then going to include this line:

noSpace(count..count) := inputString(count..count) 

where noSpace is to be the string with no spaces. My line of thinking may be completely off and I may need to approach this from a completely different angle.

Update: I've now managed to get past the error message and successfully remove the spaces from my string. But now when I print the new string there is a random variety of characters and shaded spaces after it. I believe the problem is caused because the new string is shorter than the previous one and the last characters are different.

Lareaper
  • 31
  • 1
  • 6
  • 1
    Why are you using `Character'Val(32)` rather than just `' '`? – Keith Thompson Mar 30 '15 at 19:33
  • I was actually trying to use both to see if I got an error with only one or the other. I got the same error with both unfortunately haha. – Lareaper Mar 30 '15 at 19:41
  • `' '` and `'Character'Val(32)'` are identical. `' '` is much clearer. – Keith Thompson Mar 30 '15 at 19:42
  • Thanks, I'll be sure to remember that in the future! – Lareaper Mar 30 '15 at 19:47
  • What are you doing with the places that did contain spaces? Does the string shrink? and does package Ada.Strings.Fixed count as a basic package? – NWS Mar 30 '15 at 19:55
  • @NWS For the lines that aren't spaces I have: Else null; I am trying to shrink the string. And I can't use that package. I finally got past the error I was getting and now when it prints the new string to me it successfully removes the spaces but there's a variety of strange characters and shaded spaces after this. I believe this has to do with setting a new last character for the string? – Lareaper Mar 30 '15 at 20:00
  • You ought to post more of your code; a minimal example, cut down to show just the problem but capable of being compiled, is ideal. And even as a newcomer you have enough privilege to be able to edit your own question - posting code in comments doesn’t work. – Simon Wright Mar 30 '15 at 21:33

4 Answers4

3

Probably the bug is hid somewhere else.

Try this:

with Ada.Text_IO;

procedure String_Remove_Space is

    function Count_Space( S : String ) return Natural is
        Sum_Of_Space : Natural := 0;
    begin
        for I in S'range loop
            if S(I) = ' ' then
                Sum_Of_Space := Sum_Of_Space + 1;
            end if;
        end loop;
        return Sum_Of_Space;
    end Count_Space;

    Input_String : String := "Apple is on the tree";
    Input_No : String := "AppleIsOnTheTree";

    No_Space : String(1..Input_String'Length - Count_Space(Input_String));

    Index : Positive := 1;
begin

    for I in Input_String'range loop
        if Input_String(I) /= ' ' then
            No_Space(Index) := Input_String(I);
            Index := Index + 1;
        end if;
    end loop;

    Ada.Text_IO.Put_Line(Input_String);
    Ada.Text_IO.Put_Line(No_Space);

end String_Remove_Space;
Mark
  • 5,994
  • 5
  • 42
  • 55
  • Definitely a good answer, although I tend to like Simon's approach better because it only makes one pass through the string. Yup, still worried about squeezing out every last nanosecond... – ajb Mar 31 '15 at 04:01
  • @ajb, only one pass through the string *but* a lot more moves! In [my version](http://stackoverflow.com/a/29356929/40851), each non-space character will be moved as many times as there are spaces before it in the input string. – Simon Wright Mar 31 '15 at 06:11
  • @SimonWright Oops, didn't look at your answer carefully. I've added to my answer. – ajb Mar 31 '15 at 06:19
2

If there are spaces in your input string, the valid part of the output string must be shorter. I imagine you wrote something like

noSpace : String := inputString;

to start things off with noSpace as long as it would need to be if there were no spaces in inputString? then, as you squeeze the spaces out, you seem to be writing garbage (undefined characters) to the end of noSpace. This doesn’t matter so long as you only deal with the valid part.

I tried this:

with Ada.Text_IO; use Ada.Text_IO;
procedure Lareaper is
   function Strip_Space (S : String) return String is
      Result : String := S;
      Current : Positive := Result'First;
      Last : Natural := Result'Last;
   begin
      loop
         exit when Current > Last; --  processed the whole string
         if Result (Current) = ' ' then
            --  slide the rest of the string back one
            Result (Current .. Last - 1) := Result (Current + 1 .. Last);
            --  which reduces the length by 1 too
            Last := Last - 1;
         else
            --  non-space character, skip
            Current := Current + 1;
         end if;
      end loop;
      --  return only the part of the result that doesn't contain spaces
      return Result (Result'First .. Last);
   end Strip_Space;
begin
   Put_Line ('|' & Strip_Space ("") & '|');
   Put_Line ('|' & Strip_Space (" ") & '|');
   Put_Line ('|' & Strip_Space ("a") & '|');
   Put_Line ('|' & Strip_Space ("ab") & '|');
   Put_Line ('|' & Strip_Space (" a") & '|');
   Put_Line ('|' & Strip_Space ("a ") & '|');
   Put_Line ('|' & Strip_Space ("a b") & '|');
   Put_Line ('|' & Strip_Space (" a b ") & '|');
end Lareaper;

which outputs

$ ./lareaper 
||
||
|a|
|ab|
|a|
|a|
|ab|
|ab|
Simon Wright
  • 25,108
  • 2
  • 35
  • 62
1

Count should start at InputString'First, not at 1. In particular, when InputString is created as a slice/substring of another string, it is very likely that its first character is not at index 1.

manuBriot
  • 2,755
  • 13
  • 21
1

Just to show you another possible solution, although one I would never use in real life:

function Strip_Space (S : String) return String is
begin
    if S'Length = 0 then
        return "";
    elsif S (S'First) = ' ' then
        return Strip_Space (S (S'First + 1 .. S'Last));
    else
        return S (S'First) & Strip_Space (S (S'First + 1 .. S'Last));
    end if;
end Strip_Space;

And then there's the way I would really do it. I didn't read Simon's answer carefully enough to realize that he was sliding substrings around. The most efficient answer, I think, is similar to Mark's, but you don't actually need to count the spaces in the string first.

function Strip_Space (Input_String : String) return String is
    No_Space : String(1..Input_String'Length);

    Index : Positive := 1;
begin

    for I in Input_String'range loop
        if Input_String(I) /= ' ' then
            No_Space(Index) := Input_String(I);
            Index := Index + 1;
        end if;
    end loop;

    return No_Space(1 .. Index - 1);
end Strip_Space;
ajb
  • 31,309
  • 3
  • 58
  • 84