home *** CD-ROM | disk | FTP | other *** search
/ Solo Programadores 22 / SOLO_22.iso / docs / lovelace / lesson8.les < prev    next >
Encoding:
Text File  |  1995-11-21  |  20.3 KB  |  556 lines

  1. <COMMENT This is a lesson file for the Lovelace Ada tutorial>
  2. <COMMENT A program called genlesson is used to transform this file into a set>
  3. <COMMENT of useful HTML files for use by Mosaic & other WWW browsers.>
  4.  
  5. <COMMENT  Edit the following lines. >
  6. <TUTOR NAME="Lovelace">
  7. <LESSON NUMBER=8>
  8. <AUTHOR NAME="David A. Wheeler" EMAIL="wheeler@ida.org">
  9. <AUTHOR ADDRESS="<A HREF="dwheeler.htm">David A. Wheeler (wheeler@ida.org)</A>">
  10. <COMMENT $Id: lesson8.les,v 1.4 1995/05/17 21:25:18 wheeler Exp $ >
  11.  
  12. <COMMENT  You'll probably want to uncomment and edit these lines: >
  13. <COMMENT  <PREVIOUS_LESSON LOCATION="URL_of_directory/" >
  14. <COMMENT  <NEXT_LESSON LOCATION="URL_of_directory/" >
  15.  
  16. <COMMENT A lesson is divided into 1 or more "sections".>
  17. <COMMENT Each section has a title; SECTION starts a new section.>
  18.  
  19. <SECTION NAME="Type Character and Wide_Character">
  20. Many programs must manipulate text; these next few sections will
  21. present the basic Ada types used to manipulate text.
  22. <P>
  23. The basic element of text is represented as type <EM>Character</EM>.
  24. A variable of type character can hold, well, a character.
  25. More precisely, something of type Character can
  26. represent any one of the 256 possible characters in the ``Latin-1'' set.
  27. Type Character is sufficient for handling most languages written
  28. using Latin-based characters, such as English, French, and Spanish.
  29. Latin-1 is a superset of the ASCII character set (also called ISO 646),
  30. so Character is the right type for processing ASCII text files.
  31. <P>
  32. Ada 95 also defines a type called <EM>Wide_Character</EM>.
  33. If you need to handle non-Latin alphabets (such as
  34. Chinese or Arabic) you would use Wide_Character instead of Character.
  35. A Wide_Character can represent any character from the
  36. entire ISO 10646 character set.
  37. We won't discuss Wide_Character right now, but it's important to
  38. know that it's available if you need it.
  39. <P>
  40. Constants of type Character are written between single quotes
  41. (this is the same way it's done in C and C++).
  42. Thus, <EM>'a'</EM> is the constant ``lower-case A'', and <EM>'''</EM>
  43. is the constant ``single quote mark.''
  44. <P>
  45. Ada 95 defines a large set of predefined operations to help
  46. manipulate characters.
  47. Many of them are defined in the package Characters.Handling;
  48. if you're curious you can look at the
  49. <A HREF="http://lglwww.epfl.ch/Ada/LRM/9X/rm9x/rm9x-A-03-02.html">complete
  50. declaration of package Characters.Handling in the LRM.</A>
  51. For example, Characters.Handling defines a function
  52. named <EM>To_Lower</EM> that accepts a single
  53. character and returns a lower case version of that character
  54. (if there is one - otherwise it just returns the character it was given).
  55. <P>
  56. Package Text_IO has a `Get' operation that can read a single
  57. character, and a `Put' operation that can write a single character.
  58. <P>
  59. Let's put these ideas together into a simple program that asks a yes-or-no
  60. question, gets a character as a response, and does something based on
  61. the user response:
  62. <P>
  63. <PRE>
  64. <TEXT FONT=PRE FILE="yes_no.adb">
  65. </PRE>
  66. <P>
  67. Ada's type Character is similar to C's ``char'' type, and
  68. package Characters.Handling is the Ada 95 equivalent of C's ctypes.h file.
  69. <P>
  70. Ada permits compilers to support additional ``local'' character sets as
  71. a compile-time option, but Ada compilers must support at least Latin-1
  72. and ISO 10646.
  73.  
  74. <QUESTION Type=Multiple-Choice>
  75. Which of the following is a Character constant?
  76. <CHOICES>
  77. <CHOICE ANS=1>"Hello"
  78. <CHOICE ANS=2>'n'
  79. <CHOICE ANS=3>Response
  80. </CHOICES>
  81. <ANSWER ANS=2>
  82. <RESPONSES>
  83. <WHEN ANS=1>
  84. No, sorry.  Something in double quotes is a <EM>string</EM> constant.
  85. Character constants are in <EM>single</EM> quotes.
  86. Here's a simple rule of thumb we'll describe later:
  87. single characters get single quotes.
  88. <WHEN ANS=2>
  89. You are correct.
  90. <WHEN ANS=3>
  91. No, sorry.  That looks like the name of a variable. Try again!
  92. </RESPONSES>
  93. <SECTION NAME="Types of Strings">
  94. Actually, single characters aren't all that useful.
  95. Characters are usually found in sequences, and these sequences
  96. are called ``strings''.
  97. <P>
  98. Ada 83 provided a built-in type for strings, called String.
  99. String is still a useful type, but many clamored for types which provided
  100. string-like capability but had different trade-offs between ease-of-use
  101. and performance for different tasks.
  102. Thus, Ada 95 provides a number of different ``string'' types, each
  103. best for a certain purpose.  All can be converted to and from the
  104. original type String, so you can easily use the different ``string''
  105. types together in a single program.
  106. Here's the list of ``string'' types provided by Ada:
  107. <P>
  108. <DL>
  109. <DT>String
  110. <DD>
  111. This is the basic Ada String type, and is also
  112. called a ``fixed length string''.
  113. This type (String) is simply an array of Characters.
  114. A String value must be given its length when it's created
  115. and its length will stay fixed.
  116. This isn't as bad as it sounds, since there are simple techniques to
  117. handle changing the length of values stored using Strings.
  118. For example, you can use an approach similar to the C programming language -
  119. use access values (pointers) to Strings, which would allow you to
  120. "free" a String and then create a new String with a potentially different
  121. length.
  122. However, if you change a string's length often, other ``string'' types
  123. (Bounded_String or Unbounded_String) are probably a better choice.
  124. <DT>
  125. Bounded_String
  126. <DD>
  127. Values of this type can vary in length up to a maximum length
  128. (which you supply).
  129. This is useful if you know at compile time what the maximum length
  130. of a string will be.
  131. <DT>
  132. Unbounded_String
  133. <DD>
  134. Values of this type can vary in length up to the largest value of
  135. type `Natural' (usually that's over 2 billion characters).
  136. If you have string variables whose length you want to vary, this is
  137. probably the best type to use.
  138. <DT>
  139. Other Language Strings: C.Strings.chars_ptr, COBOL.Alphanumeric,
  140. and Fortran_Character.
  141. <DD>
  142. Ada 95 includes some types that represent strings from other languages,
  143. namely C, COBOL, and Fortran.
  144. If you're interfacing to components written in these other languages,
  145. these types may be very useful to you.
  146. </DL>
  147. <P>
  148. Whenever you enclose characters inside double quotes, "like this", you
  149. are creating a constant of type String.
  150. Remember that a constant of type Character is inside single quotes,
  151. for example, 'L'.
  152. There's a simple rule of thumb to help remember the difference between
  153. constants of types Character and String:
  154. if you want a constant for a single character, use single quotes.
  155. The same symbols are used the same way in C and C++.
  156.  
  157. <QUESTION Type=Multiple-Choice>
  158. Let's say you want to declare a ``string'' variable whose length will vary,
  159. and you don't really know exactly what its maximum length will be.
  160. What type would you probably use?
  161. <CHOICES>
  162. <CHOICE ANS=1>String
  163. <CHOICE ANS=2>Bounded_String
  164. <CHOICE ANS=3>Unbounded_String
  165. <CHOICE ANS=4>C.Strings.chars_ptr
  166. </CHOICES>
  167. <ANSWER ANS=3>
  168. <RESPONSES>
  169. <WHEN ANS=1>
  170. No, sorry; string isn't as good a choice when lengths vary.
  171. <WHEN ANS=2>
  172. No, Bounded_String is only a good choice if you know
  173. a string's maximum length.
  174. <WHEN ANS=3>
  175. Right!
  176. Because varying lengths is common in many applications, and
  177. because Unbounded_String is relatively easy to use, we'll
  178. use Unbounded_String quite a bit in this tutorial.
  179. However, since String is the ``basic'' string type in Ada, we will
  180. start by looking at how to use type String.
  181. <WHEN ANS=4>
  182. No,
  183. C.Strings.chars_ptr is intended for interfacing with C components,
  184. and the question didn't state that this type was an interface
  185. to C components.
  186. </RESPONSES>
  187. <SECTION NAME="Basics of Type String">
  188. Ada's type <EM>String</EM> can be considered
  189. a "primitive" type for handling sequences of text.
  190. It's simple and efficient, but some operations require a little work.
  191. <P>
  192. A String is simply an array of characters.
  193. The major "catch" with variables of type String is that,
  194. when you create a String variable, you must give Ada a way of determining
  195. its length - and the variable will stay fixed at that length from then on.
  196. There are two major ways for determining a string's length -
  197. you can explicitly state how long the string will be, or you can
  198. assign the variable a string value (Ada will determine how long the
  199. string value is and make the new variable that length).
  200. <P>
  201. Ada requires that at least the bounds or the initial string value be given;
  202. if both are given, they must match. The "low_bound" is usually 1, though
  203. Ada permits the low_bound to be a larger Integer.
  204. Here are some examples:
  205. <P>
  206. <PRE>
  207. A        : String(1..50);   -- Variable A holds 50 characters.
  208. Question : String := "What is your name?"  -- Ada will make String(1..18).
  209. </PRE>
  210. <P>
  211. <P>
  212. Here's a simplified <A HREF="bnf.htm">BNF</A>
  213. for declaring String variables:
  214. <P>
  215. <PRE>
  216. declare_string_variable ::= list_of_variable_names ":" [ "constant" ]
  217.                            "String" [ bounds ] 
  218.                                     [ ":=" initial_string_value ]
  219. bounds ::= "(" low_bound ".." high_bound ")"
  220. </PRE>
  221. Once you have a string, you can use predefined Ada operations on arrays
  222. (since a string is simply an array of characters).
  223. These include the following:
  224. <OL>
  225. <LI>You can read or overwrite a Character (an element of a String) at
  226. a given index position. For example, A(2) refers to the character
  227. in string A at index position 2.
  228. Any attempt to read or write a nonexistent index position will cause
  229. the exception Constraint_Error to be raised.
  230. To change the character at a given position,
  231. simply assign to it, for example:
  232. <PRE>
  233.     A(2) := 'f';
  234. </PRE>
  235. <LI>You can read or overwrite a <EM>slice</EM> (i.e., a substring).
  236. A slice refers to a portion of a string, from one index position
  237. to another, and is also considered a String.
  238. A slice from index position "low" to position "high" of some
  239. String variable B is written as "B(low..high)".
  240. You can write to a slice, too, but the source and destinations
  241. must have the same length.
  242. <LI>You can assign a whole string from one String to another the same
  243. way as any other variable, as long as their lengths are equal, like this:
  244. <PRE>
  245.     B := A;
  246. </PRE>
  247. <LI>You can concatenate (combine) strings together using the "&"
  248. operator.
  249. </OL>
  250. <P>
  251. There are also predefined operations in Text_IO for printing
  252. Strings, namely Put and Put_Line.
  253. Let's look at an example:
  254. <P>
  255. <PRE>
  256.   with Text_IO; use Text_IO;
  257.   procedure String1 is
  258.     A : String := "Hello";
  259.     B : String(1..5);
  260.   begin
  261.     B := A;                      -- B becomes "Hello"
  262.     A(1) := 'h';                 -- A becomes "hello"
  263.     A(2..3) := A(4..5);          -- A becomes "hlolo"
  264.     A := B(1) & A(2..3) & "ol";  -- A becomes "Hlool"
  265.     Put_Line(A);
  266.     A(2..3) := B(2..3);
  267.     Put_Line(A);
  268.   end String1;
  269. </PRE>
  270. <P>
  271.  
  272. <QUESTION Type=Multiple-Choice>
  273. What is the last line that program String1 will print?
  274.  
  275. <CHOICES>
  276. <CHOICE ANS=1>Hello
  277. <CHOICE ANS=2>Hlolo
  278. <CHOICE ANS=3>hello
  279. <CHOICE ANS=4>Helol
  280. </CHOICES>
  281. <ANSWER ANS=4>
  282. <RESPONSES>
  283. <WHEN ANS=4>
  284. That's right.
  285. Granted, that was a pretty boring program, but hopefully it was
  286. a clear example.
  287. </RESPONSES>
  288. <SECTION NAME="Passing String Between Subprograms">
  289. Strings can be passed between subprograms just like any other
  290. variable type.
  291. Procedures and functions can have a type String as an in (or in out)
  292. variable, and those parameters will be set when the subprogram
  293. is called.
  294. In addition, functions can return variables of type String, just like
  295. any other type.
  296. <P>
  297. Beginning Ada developers often make an unwarranted assumption
  298. when writing subprograms that accept Strings - they assume that String
  299. indexes always begin with one.
  300. Not true.
  301. String indexes do not <EM>have</EM> to start at one - that's just
  302. the smallest possible starting index.
  303. In particular, if you pass in a string slice as an input parameter
  304. to a subprogram, the receiving subprogram will receive the slice's
  305. index values. This helps to keep String efficient, but it can be surprising.
  306. <P>
  307. The smallest index value of a String named A is written as
  308. A'First. Similarly, the largest index value is A'Last, and the
  309. string's length is A'Length.
  310. <P>
  311. Here's a simple rule of thumb: whenever you write a subprogram
  312. that accepts a String variable as an in parameter, 
  313. <EM>always</EM> use 'First, 'Last, and
  314. 'Length - never assume that the String index begins with one.
  315. If you try to reference an out-of-range index, Ada will raise an
  316. exception - but it's better to not make the mistake in the first place.
  317. <P>
  318. Here is an example, which will hopefully make this clearer:
  319. <P>
  320. <PRE>
  321.   with Text_IO; use Text_IO;
  322.   procedure String2 is
  323.  
  324.     procedure Print_Reverse( S : String ) is
  325.     begin
  326.       for I in reverse S'First .. S'Last loop
  327.         Put(S(I));
  328.       end loop;
  329.     end Print_Reverse;
  330.   
  331.     Demo : String := "A test";
  332.     
  333.   begin
  334.     Print_Reverse(Demo(3..Demo'Last));
  335.   end String2;
  336. </PRE>
  337. <P>
  338.  
  339. <QUESTION Type=Multiple-Choice>
  340. When Print_Reverse is called, which is true?
  341.  
  342. <CHOICES>
  343. <CHOICE ANS=1>S="test", S'First=3, S'Length=4
  344. <CHOICE ANS=2>S="test", S'First=1, S'Length=4
  345. </CHOICES>
  346. <ANSWER ANS=1>
  347. <RESPONSES>
  348. <WHEN ANS=1>
  349. Right.
  350. <P>
  351. A number of times it's been emphasized that a String has
  352. a fixed length.
  353. What happens if you really want to vary a string's length?
  354. <P>
  355. One solution is to create a long string, long enough to
  356. hold the maximum number of characters in a String, and then
  357. use another variable to store the number of characters currently
  358. used in the String.
  359. This may be appropriate when actual string sizes are (on the average)
  360. close to the maximum string size and when maximum string sizes can
  361. be predetermined.
  362. That idea is the basis for the Bounded_String type we mentioned earlier.
  363. <P>
  364. Another solution is to create an "access (pointer) to string" variable
  365. (we haven't discussed "access" types yet, but Ada provides them).
  366. Such a variable would be very similar to C and C++'s
  367. <EM>char *</EM> type.
  368. Unlike C and C++, Ada provides a number of built-in protections for
  369. "access to String" types.
  370. Still, varying-length Strings occur often 
  371. enough that Ada 95 provides a predefined
  372. type, Unbounded_String, that does some additional housekeeping for us.
  373. Unbounded_String is usually implemented using String in some way,
  374. but it does a number of things automatically for us.
  375. Thus, we will talk about Unbounded_String next, and discuss
  376. "access to String" later.
  377. </RESPONSES>
  378. <SECTION NAME="Unbounded String Basics">
  379. The Unbounded_String type is defined in the package
  380. Ada.Strings.Unbounded, so you'll need to ``with'' package
  381. Ada.Strings.Unbounded to use the Unbounded_String type.
  382. Package Ada.Strings.Unbounded also provides a number
  383. of useful basic operations on Unbounded_String.
  384. <A HREF="http://lglwww.epfl.ch/Ada/LRM/9X/rm9x/rm9x-A-04-05.html">The
  385. Ada LRM provides a complete definition of package Ada.Strings.Unbounded.</A>
  386. <P>
  387. Here are a few important operations:
  388. <UL>
  389. <LI>
  390. Function To_Unbounded_String takes something of type String and converts
  391. it into type Unbounded_String.
  392. This is useful for a variety of purposes, for example, for
  393. setting Unbounded_String values to some constant value,
  394. as we'll show later.
  395. <LI>
  396. Function To_String is the reverse; it
  397. takes something of type Unbounded_String and converts it to type String.
  398. <LI>
  399. Function Length takes an Unbounded_String and returns
  400. the number of characters currently stored in the Unbounded_String.
  401. <LI>
  402. Procedure Append takes two arguments; it appends to the end of
  403. its first argument the contents of the second argument.
  404. The first argument has to be an Unbounded_String;
  405. the second argument can be a String or an Unbounded_String.
  406. <LI>
  407. Function Element extracts from a given Unbounded_String (its <EM>Source</EM>)
  408. the character at a given position (its <EM>index</EM>).
  409. The leftmost character has an index of 1, just like Pascal;
  410. C and C++ start their indexes at zero.
  411. Here's the official definition of Element:
  412. <PRE>
  413.   function Element (Source : in Unbounded_String; Index  : in Positive)
  414.                     return Character;
  415. </PRE>
  416. <LI>
  417. Procedure Replace_Element is the opposite of Element; it lets you
  418. modify a character at a given position.
  419. Here's the official definition of Replace_Element:
  420. <PRE>
  421.   procedure Replace_Element (Source : in out Unbounded_String;
  422.                              Index  : in Positive;
  423.                              By     : in Character);
  424. </PRE>
  425. <LI>
  426. Function Slice takes a given Unbounded_String and returns a ``slice''
  427. of it, i.e., all the characters between a given low and high index.
  428. Slice returns a String, so if you want to use its result as an
  429. Unbounded_String, use To_Unbounded_String on the result.
  430. <PRE>
  431.   function Slice (Source : in Unbounded_String;
  432.                   Low    : in Positive;
  433.                   High   : in Natural) return String;
  434.  
  435. </PRE>
  436. <LI>
  437. Procedure Insert takes a New Item (of type String) and inserts it
  438. into an Unbounded_String before a given index.
  439. If the string isn't empty, this will change the Unbounded_String's length.
  440. This procedure's definition is:
  441. <PRE>
  442.   procedure Insert (Source   : in out Unbounded_String;
  443.                     Before   : in Positive;
  444.                     New_Item : in String);
  445. </PRE>
  446. <LI>
  447. Procedure Delete takes an Unbounded_String and two indexes, and deletes
  448. the characters between those two index positions (including the end points).
  449. Its definition is:
  450. <PRE>
  451. Procedure Delete
  452.   procedure Delete (Source  : in out Unbounded_String;
  453.                     From    : in Positive;
  454.                     Through : in Natural);
  455. </PRE>
  456. </UL>
  457. <P>
  458. Comparison operations (such as "=" and "<") are defined in this package.
  459. There are other routines to modify or search Unbounded_Strings, including
  460. "&" (concatenate two Unbounded_Strings together),
  461. Translate, Trim, Head, Tail, Index, and Find_Token.
  462. We'll discuss those operations later.
  463. <P>
  464. Because of the way Unbounded_String is defined, you can use
  465. assignment (:=) as well.
  466.  
  467.  
  468. <QUESTION Type=Multiple-Choice>
  469. Given a variable ``Input'' of type Unbounded_String,
  470. what expression would return the value of the fourth character in Input?
  471. <CHOICES>
  472. <CHOICE ANS=1>Element(Input, 4)
  473. <CHOICE ANS=2>Replace_Element(Input, 4, 'L')
  474. <CHOICE ANS=3>Element(4, Input)
  475. </CHOICES>
  476. <ANSWER ANS=1>
  477. <RESPONSES>
  478. <WHEN ANS=1>
  479. Right.
  480. What happens if there aren't four characters in the input?
  481. The answer, like most other such problems, is that an exception is raised;
  482. we'll find out later how to deal with exceptions.
  483. <WHEN ANS=2>
  484. No, that would change the value of the fourth character, not show
  485. you what its value is.
  486. <WHEN ANS=3>
  487. Very close, but not right. Try again.
  488. </RESPONSES>
  489. <SECTION NAME="Unbounded_String Input and Output">
  490. Ada 95 does not define input and output packages for
  491. Unbounded_String; instead, it defines operations on type String and
  492. operations to convert a String into an Unbounded_String.
  493. <P>
  494. Personally, I find that it's easier to use a package that defines Input-Output
  495. operations directly for an Unbounded_String.
  496. It's easy to define such a package, so I've provided one for you.
  497. <P>
  498. I call my package ``Ustrings'', which is a nice short name - I'll explain
  499. later why it has that name.
  500. It has a procedure Get_Line, which reads in a whole text line into
  501. an Unbounded_String. Procedure Put prints the Unbounded_String.
  502. Procedure Put_Line first Puts the Unbounded_String, and then
  503. starts a new line.
  504. Here's a shortened version of this package's declaration:
  505. <P>
  506. <PRE>
  507. package Ustrings is
  508.   procedure Get_Line(Item : out Unbounded_String);
  509.   procedure Put(Item : in Unbounded_String);
  510.   procedure Put_Line(Item : in Unbounded_String);
  511. end Ustrings;
  512. </PRE>
  513. <P>
  514. If you're curious you can see the complete
  515. <A HREF="ustrings.ads">declaration (specification)</A> and
  516. <A HREF="ustrings.adb">body</A>
  517. of my package Ustrings.
  518. <P>
  519. Also, I also believe that
  520. ``Unbounded_String'' is too long a name for
  521. such a widely-used type, so I define in package ``Ustrings'' a new
  522. name for Unbounded_String called ``Ustring''.
  523. You can declare variables of type ``Ustring'' and they'll simply be
  524. Unbounded_Strings.
  525. You do <EM>not</EM> need to use "Ustring" instead of "Unbounded_String";
  526. I simply find it convenient.
  527. <P>
  528. Let's look at a short Unbounded_String demonstration program
  529. named `Unbound'.
  530. It reads in text, one line at a time, and then does various things with
  531. the line of text.
  532. Study the following program and see if you can figure out what it does.
  533. <P>
  534. <TEXT FONT=PRE FILE="unbound.adb">
  535. <P>
  536.  
  537. <QUESTION Type=Multiple-Choice>
  538. What does subprogram Unbound do
  539. after it prints the line showing the number of characters
  540. in the input string?
  541.  
  542. <CHOICES>
  543. <CHOICE ANS=1>It prints the input string in reverse.
  544. <CHOICE ANS=2>It prints the input string as it was entered.
  545. <CHOICE ANS=3>Nothing.
  546. </CHOICES>
  547. <ANSWER ANS=1>
  548. <RESPONSES>
  549. <WHEN ANS=1>
  550. Right.
  551. The big giveaway here is the ``reverse'' keyword.
  552. <WHEN ANS=2>
  553. No, it does that <EM>before</EM> it prints the length of the input string.
  554. Try again.
  555. </RESPONSES>
  556.