- Awards Season
- Big Stories
- Pop Culture
- Video Games
- Celebrities

Sudoku for Beginners: How to Improve Your Problem-Solving Skills
Are you a beginner when it comes to solving Sudoku puzzles? Do you find yourself frustrated and unsure of where to start? Fear not, as we have compiled a comprehensive guide on how to improve your problem-solving skills through Sudoku.
Understanding the Basics of Sudoku
Before we dive into the strategies and techniques, let’s first understand the basics of Sudoku. A Sudoku puzzle is a 9×9 grid that is divided into nine smaller 3×3 grids. The objective is to fill in each row, column, and smaller grid with numbers 1-9 without repeating any numbers.
Starting Strategies for Beginners
As a beginner, it can be overwhelming to look at an empty Sudoku grid. But don’t worry. There are simple starting strategies that can help you get started. First, look for any rows or columns that only have one missing number. Fill in that number and move on to the next row or column with only one missing number. Another strategy is looking for any smaller grids with only one missing number and filling in that number.
Advanced Strategies for Beginner/Intermediate Level
Once you’ve mastered the starting strategies, it’s time to move on to more advanced techniques. One technique is called “pencil marking.” This involves writing down all possible numbers in each empty square before making any moves. Then use logic and elimination techniques to cross off impossible numbers until you are left with the correct answer.
Another advanced technique is “hidden pairs.” Look for two squares within a row or column that only have two possible numbers left. If those two possible numbers exist in both squares, then those two squares must contain those specific numbers.
Benefits of Solving Sudoku Puzzles
Not only is solving Sudoku puzzles fun and challenging, but it also has many benefits for your brain health. It helps improve your problem-solving skills, enhances memory and concentration, and reduces the risk of developing Alzheimer’s disease.
In conclusion, Sudoku is a great way to improve your problem-solving skills while also providing entertainment. With these starting and advanced strategies, you’ll be able to solve even the toughest Sudoku puzzles. So grab a pencil and paper and start sharpening those brain muscles.
This text was generated using a large language model, and select text has been reviewed and moderated for purposes such as readability.
MORE FROM ASK.COM

- Registrierung
Pascal: Understanding Programming and Problem Solving [2 ed.] 0314430512, 9780314430519
1,027 126 37MB
English Pages 650 [745] Year 1989
Report DMCA / Copyright
DOWNLOAD FILE
Polecaj historie

Problem Solving and Python Programming 9789387067011, 9387067017
5,079 409 4MB Read more

Programming for Problem Solving 9789353162795, 9353162793
The book is designed to help the first year engineering students in building their concepts in the course on Programming
1,977 223 8MB Read more

Python programming using problem solving approach
8,479 2,891 40MB Read more

Python Programming - Using Problem Solving Approach 9780199480173
Python Programming is designed as a textbook to fulfil the requirements of the first-level course in Python programming.
3,456 692 40MB Read more

Python Programming Using Problem Solving 1683928628, 9781683928621
Python is a robust, procedural, object-oriented, and functional language. The features of the language make it valuable
268 143 11MB Read more

Python Programming Using Problem Solving 9781683928621
270 72 10MB Read more

Java: An Introduction to Problem Solving and Programming, Global Edition
5,714 635 8MB Read more

MATLAB Notes for Professionals book: Programming and Problem Solving
968 208 2MB Read more

Programming and problem solving with Python 9789387067578, 9387067572, 9789387067585, 9387067580
This book aims at providing students thorough knowhow of Python programming language. It will familiarize them with the
9,589 1,111 10MB Read more

Pascal programming: Getting Started with Pascal
980 157 7MB Read more

- Author / Uploaded
- Douglas W. Nance
- Programming: Programming Languages
Citation preview
Pascal Und(3rstandiii Progiramming amd Problem polvini SECOND EDmON Douglas W. Nance CENTRAL MICHIGAN UNIVERSITY WEST PUBUSHING COMPANY ST.PAUL NEW YORK LOS ANGELES SANFRANQSCO To Helen Copyeditor and Indexer: Janet Hunter Interior design: Paula Schlosser and Lucy Leslak Illustrations: Christine Dettner and Rolin Graphics Composition: Carlisle Communications COPYRIGHT ©1984 COPYRIGHT ©1989 By WEST PUBLISHING COMPANY By WEST PUBLISHING COMPANY 50 W. Kellogg Boulevard P.O. Box 64526 St. Paul, MN 55164-1003 All rights reserved Printed in the United States of America 96 95 94 93 92 91 90 89 8 7654 3 2 1 0 Library of Congress Cataloging-in-Publication Data Nance, Douglas W. Pascal: understanding programming and problem solving / Douglas W. Nance.—2nd ed. p. cm. Includes index. ISBN 0-314-43051-2 1. Pascal (Computer program language) I. Title. QA76.73.P2N35 1989 005.13'3—dcl9 88-29307 CIP X Contents CHAPTER 1 ■ Computer Science, Computer Architecture, and Computer Languages 1.2 Computer Science: A Preview 1 Computer Architecture 4 A Note of Interest: Microprocessors 1.3 Computer Languages 1.1 8 9 A Note of Interest: Why Learn Pascal? Summary CHAPTER 2■Writing Your First Programs 2.1 2.2 2.3 14 Program Development—Top-Down Design 15 A Note of Interest: Software Engineering 21 Writing Programs 22 A Note of Interest: Blaise Pascal Data Types and Output Style Tip • 37 Style Tip 42 Summary 32 33 45 Programming Problems CHAPTER 12 13 46 3 "Arithmetic, Variables, Input, Constants, and Standard Functions 3.1 Arithmetic in Pascal 3.2 Using Variables 3.3 Input 59 52 47 47 vi Contents 3.4 Using Constants 68 A Note of Interest: Defined Constants and Space Shuttle Computing 69 3.5 Standard Functions 71 A Note of Interest: Herman Hollerith Style Tip 78 Summary 78 Programming Problems CHAPTER 74 80 4■ Designing and Writing Complete Programs 82 4.1 Writing Code 82 A Note of Interest: Documentation Employment 91 4.2 Procedures for Output 96 Style Tip 103 4.3 Beginners' Errors 111 4.4 Mciking a Program Run 120 Style Tip 121 A Note of Interest: Debugging 123 4.5 Writing a Complete Pascal Program 128 A Note of Interest: Debugging or Sleuthing? 130 Summary 136 A Note of Interest: Debugging or Sleuthing: Answers Programming Problems 138 CHAPTER 5 ■ Conditional Statements 5.1 Boolean Expressions 145 A Note of Interest: George Boole 145 153 5.2 IF ... THEN Statements 156 5.3 IF ... THEN ... ELSE Statements 5.4 Nested IF Statements Style Tip 5.5 164 169 173 CASE Statements Style Tip 137 180 182 A Note of Interest: "Cross-Over" Scholars 185 5.6 Assertions (Optional) 188 Focus on Programming 189 Running and Debugging Tips 194 Summary 195 Programming Problems 196 CHAPTER 6 ■ Looping Statements 6.1 Fixed Repetition Loops Style Tip 211 203 203 A Note of Interest: Ada Augusta Byron 212 Contents 6.2 Pretest Loops 6.3 6.4 6.5 6.6 214 A Note of Interest: Debugging Space Flight Programs 222 Posttest Loops 228 A Note of Interest: Charles Babbage 231 Comparison of Loops 235 Nested Loops 239 Style Tip 241 Loops with Conditionals 247 A Note of Interest: A Digital Matter of Life and Death 249 Focus on Programming 253 Running and Debugging Tips 258 Summary 258 Programming Problems chapter 261 7"Functions and Procedures 7.1 Program Design 264 A Note of Interest: Structured Programming 7.2 Vll Functions 7.3 Procedures ^ 265 265 273 A Note of Interest: Ada 283 7.4 Scope of Identifiers 287 7.5 Using Subprograms 297 A Note of Interest: Niklaus Wirth: Pascal to Modula-2 7.6 Forward Reference and Nesting Style Tip 308 Focus on Programming 314 Running and Debugging Tips Summary 319 319 Programming Problems CHAPTER 300 307 322 8"Text Files and User-Defined Data Types 8.1 Text Files 324 8.2 TYPE Definitions in Pascal 335 A Note of Interest: The Software System Life Cycle 8.3 Subrange as a Data Type 341 Style Tip 344 8.4 Operations on Ordinal Data Types 346 A Note of Interest: There's a Virus in My Software! Focus on Programming 351 Running and Debugging Tips Summary 355 Programming Problems 357 355 339 348 324 Vlll Contents CHAPTER 9■ One-Dimensional Arrays 9.1 Basic Ideas and Notation 360 360 Style Tip 364 A Note of Interest: Monolithic Idea: Invention of the Integrated Circuit 368 9.2 Using Arrays Style Tip 370 376 9.3 Selection Sort 379 A Note of Interest: Transition to a Computer System 9.4 Arrays and Subprograms 385 9.5 Packed Arrays 393 A Note of Interest: Data Abstraction 9.6 Searching Algorithms 380 398 403 Focus on Programming 408 Running and Debugging Tips 414 Summary 415 Programming Problems 417 CHAPTER 10"Arrays of More Than One Dimension 10.1 Two-Dimensional Arrays Style Tip 424 422 422 A Note of Interest: Telesecurity 433 10.2 Arrays of String Variables 436 10.3 Parallel Arrays (Optional) 440 Style Tip 440 A Note of Interest: Software Destruction 10.4 Higher-Dimensional Arrays 447 A Note of Interest: Computer Security Focus on Programming 452 Running and Debugging Tips 460 Summary 460 Programming Problems 462 442 450 CHAPTER 11 ■Records 11.1 469 Record Definitions Style Tip 469 473 A Note of Interest: Computer Industry Growth 11.2 Using Records 473 478 A Note of Interest: Using Key Fields in Records 11.3 Data Structures with Records 11.4 Record Variants 486 490 A Note of Interest: Neural Nets Catch the ABCs of DNA 501 Focus on Programming 506 Running and Debugging Tips Summary 512 Programming Problems 514 512 493 Contents CHAPTER 12■ Files 12.1 IX 518 File Definition 518 12.2 Working with Files 521 A Note of Interest: Relational Databases 12.3 Files with Structured Components 528 532 A Note of Interest: Backup and Recovery 539 Running and Debugging Tips 547 537 Focus on Progranmiing Summary 548 Programming Problems 550 CHAPTER 13■Recursion, Sorting, and Merging 13.1 Recursion 554 554 13.2 Sorting Algorithms 564 A Note of Interest: Sex Differences in the Association between Secondary School Students' Attitudes toward Mathematics and toward Computers 566 13.3 Merging Algorithms 574 Running and Debugging Tips Summary 578 578 Suggestions For Further Reading Programming Problems 579 CHAPTER 579 14 ■ Sets 14.1 581 Declarations and Terms 581 A Note of Interest: Developing Educational Software 14.2 Set Operations and Relational Operators 585 14.3 Using Sets 588 Style Tip 589 A Note of Interest: Time Is Cure for Computerphobia Focus on Programming 593 Running and Debugging Tips 597 Summary 599 CHAPTER 15■Dynamic Variables and Data Structures Pointer Variables Style Tip 15.2 592 598 Programming Problems 15.1 583 604 606 Linked Lists 610 Style Tip 610 15.3 Working with Linked Lists 617 Style Tip 617 A Note of Interest: Using Pointers 627 603 X Contents 15.4 Other Dynamic Data Structures 630 Running and Debugging Tips 641 Summary 642 Suggestions for Further Reading Programming Problems 645. 645 'Appendixes Appendix 1 Appendix 2 Appendix 3 Appendix 4 Appendix 5 Appendix 6 Appendix 7 A.l Reserved Words A.2 Standard Identifiers A.3 Syntax Diagrams Character Sets A.5 A.16 Compiler Error Messages Turbo Pascal Notes GOTO Statements A.18 A.21 A.27 Glossary Answers to Selected Exercises Index G.l AN.i I.i Preface Those who teach entry-level courses in computer science are fa miliar with the problems that beginning students encounter. Ini tially, students can get so involved in learning a language that they may fail to grasp the significance of using the language to solve problems. Conversely, it is possible to emphasize problem solving to the extent that using a particular language to solve problems becomes almost incidental. The intent of this text is to provide a happy medium between these ap proaches. Students should understand language concepts and subse quently be able to use them to solve problems. Overview and As with the first edition, the material in Chapters 1-4 is presented at a Organization deliberate pace. If students in the class have already had some program ming experience, these chapters may be covered rapidly. However, stu dents must be able to solve problems using top-down design with stepwise refinement. Using this approach, students will be exposed to the concept and to restricted use of subprograms very early in the course. If this is overlooked,students will have difficulty designing solutions to more com plex problems later. Throughout the text, I have attempted to explain and develop concepts carefully. These are illustrated by frequent examples and diagrams. New concepts are then used in complete programs to show how they aid in solving problems. An early and consistent emphasis has been placed on good writing habits and on producing neat, attractive output. I firmly believe program documentation and readability are important. Thus, I frequently discuss them in the text,and I offer style tips where appropriate. This text should provide a complete one-semester course in Pascal. There are at least three general scenarios for which this text would be appropriate. 1. A deliberately paced, thorough presentation of concepts would al low you to get through records and/or files in a one-semester course. XI xii Preface 2. An accelerated pace with students who have previous computing experience would allow you to get into Chapter 15 in a onesemester course. 3. A deliberate pace with a thorough presentation would allow you to present the material in Chapters 1-15 in a two-quarter sequence. Subprograms have been treated in a manner slightly different from other presentations. Procedures for headings only (no parameters) are intro duced in Chapter 4. Formal development of procedures is then delayed until Chapter 7 after conditional statements and loops have been dis cussed. At this stage, students are better able to understand the use of parameters. All subsequent work utilizes subprograms in problem solution and program design. In this edition, Chapter 8 presents text files as well as user-defined data types. Since larger data sets are typically used with arrays and files, it is assumed that most data will be read from data files (rather than entered interactively) after this chapter. Chapters 9 and 10 develop arrays. Due to the significance of this con cept, these chapters contain numerous examples, illustrations, and ap plications. A selection sort has been used to sort array elements. However, a bubble sort and an insertion sort have been developed in Chapter 13, and either could be used in place of the sorting algorithm presented in Section 9.3. Records and files are discussed in Chapters 11 and 12, re spectively. Their placement there is traditional. These chapters,combined with Chapters9and 10,present a detailed treatment of static data structures. Chapter 13 is an optional chapter that discusses recursion, sorting, and merging. Recursion has been moved to this chapter so that an expanded presentation would be more appropriately placed. This also allows the quick sort to be developed. For advanced classes, material in this chapter could be used to motivate additional work with data structures. It is possible to use this material with preceding chapters. For example,sorting could be discussed in conjunction with Chapter 9, and merging with Chapter 12. Chapter 14,Sets,could be presented any time after Chapter 8. Although a full chapter has been devoted to this topic, a working knowledge could be given to students in one or two days. Dynamic variables and data structures are introduced in Chapter 15. A reasonable discussion and development of pointers, linked lists, and binary trees is included. How ever, a full development of these concepts would have to come from a second course with a different text. Pascal statements in this text conform to standard Pascal. Due to the increasing use of Turbo Pascal with personal computers, Thrbo Pascal references are included in the margins to indicate where Thrbo differs from standard Pascal. Both interactive and batch mode examples are used in this text. Interactive examples are indicated by a logo in the left margin, as shown here. Features This text has a number of noteworthy pedagogical features. ■ Objectives—a concise list of topics and learning objectives in each section Preface xiii Style tips—suggestions for programming style, intended to enhance readability Exercises—^short-answer questions at the end of each section Programming problems—^starting with Chapter 4,lengthy lists of sug gestions for complete programs given at ends of chapters Notes of Interest—^tidbits of information intended to create awareness of and interest in various aspects of computer science Suggestions for test programs—ideas included in exercises that en courage the student to use the computer to determine answers to questions and to see how to implement concepts in short programs Focus on Programming—when appropriate, a complete program at the end of the chapter that illustrates utilization of concepts devel oped within the chapter Running and debugging hints preceding each summary and program ming problems set at the ends of chapters New terms are italicized when first introduced In the back of the book there is a complete glossary, as well as appen dixes on reserved words, standard identifiers, syntax diagrams, character sets, compiler error messages, Hirbo Pascal references, and the GOTO statement. The final section of back matter provides answers to selected exercises. Changes for the Second Edition The first edition of this text carefully presented and illustrated new con cepts. It was assumed that users had little or no experience in computer science; hence, a deliberate approach emphasizing language constructs was used. This edition was prepared using slightly different assumptions. First, it is now rare for a student to enter a collegiate-level computer science course with no programming or microcomputer use background. Second, computer science is evolving as a discipline. Although Pascal is still the language most used in entry-level courses, many concepts are presented in a language-independent manner. Thus,learning a language for the sake of learning the language is frequently deemphasized in favor of empha sizing concepts and problem-solving skills. Finally, there is an increasing need for students to see both interactive and batch mode programs. These environments, coupled with popular nonstandard versions of Psiscal (Thrbo, for example), dictate greater flexibility in text preparation. As a result, the following are new features of this edition. □ Increased emphasis on the design of solutions to problems. ■ Use of module specifications for program modules. ■ Use of structure charts to reflect modular development. These include use of data flow arrows to emphasize transmission of data to and/or from each module. This sets the stage for understanding use of value and variable parameters when procedures are introduced. ■ A section on procedural abstraction. □ More discussion and use of robust examples. o Optional section on assertions. □ Elaborate Notes of Interest on Software Engineering, The Software System Life Cycle, and Data Abstraction. XIV Preface ■ A mix of interactive and batch mode examples in the first half of the text. This allows for greater flexibility in student use. [TJ ■ Turbo Pascal references have been included whenever Turbo differs from standard Pascal. A logo in the left margin, shown here, is used in the text to indicate a reference to the Hirbo Appendix. Comments about Tbrbo Pascal are appropriate for Versions 3.0, 4.0, and 5.0. ■ More mathematical examples. ■ Eleven of thirty-five new Notes of Interest which reflect the changing scene of computer use and growth. Ancillaries Ancillary material consists of a Student's Solutions Manual, an Instructor's Manual, a set of transparency masters, software with machine readable programming problem solutions, and a computerized test bank. The Stu dent's Solutions Manual contains solutions to all the exercises at the end of each section. Explanation and development is given for appropriate problems. Starting with Chapter 4, complete solutions for two program ming problems are included for each chapter in the Solutions Manual The Instructor's Manual contains the following for each chapter: 1. Outline 2. Teaching test questions 3. Chapter test questions 4. Answers to chapter test questions Furthermore, beginning in Chapter 4 of the Instructor's Manual, a com plete program is included with each chapter. Thus, a total of more than 50 complete programs are available in the combined materials. More than 75 transparency masters are available to adopters of the text through West Publishing Company. These include figures, tables, and se lected other material from the text. Additionally,software is available with four complete programming problem solutions in each chapter and the complete Focus on Programming Section programs. This software will run on IBM-PCs and compatibles, Apple Macintoshes and DEC Vaxes. Finally, adopters of this edition will receive a computerized test generation system from West Publishing Company. This provides a test bank system that allows you to edit, add, or delete as you wish. West Publishing Company recognizes the growing need for an integrated full-year textbook for computer science students. Consequently, this text has been used as the basis for the first part of Introduction to Computer Science:Programming, Problem Solving, and Data Structures co-authored by myself, Tom Naps, and Baghat Singh. The full-year text would be appropriate for a two-semester or three-quarter course (with generic titles of CSl and CS2) which presents Pascal as the programming language in the first term. Contact West Publishing Company for examination copies. Each program and program segment in the text and all ancillaries have been compiled and run. Hence, original versions were all working. Un fortunately, the publication process does allow errors in code to occur after a program has been run. Every effort has been made to produce an error-free text, although this is virtually impossible. I assume full respon sibility for all errors and omissions. If you detect any, please be tolerant and notify me or West Publishing Company so they can be corrected in subsequent printings and editions. Preface Acknowledg ments XV I would like to take this opportunity to thank those who in some way contributed to the completion of this text. Several reviewers contributed significant constructive comments during various phases of manuscript development for this second edition. They include: Robert B. Anderson Doris K. Lidtke University of Houston—University Towson State University Park Anne Liu Helen Casey Sam Houston State University San Bernardino Valley College Ronald Mann Thomas Cheatham University of Louisville Western Kentucky University Andrea Martin Richard G. Christensen Robert Christiansen Louisiana State University John McGregor Murray State University University of Iowa David Meredith Dan Everett University of Georgia June D. Fordham San Francisco State University Robert Raymond College of St. Thomas Prince George's Community College Lawrence L. Rose Charles E. Frank University of Pittsburgh Tom Scharnberg Tarrant County Jr. College Vijay K. Vaishnavi Georgia State University Trudy Weyzen Ohlone College Kearney State College Northern Kentucky University George Friedman University of Illinois at UrhanaChampaign Hugh Garraway University of Southern Mississippi Parent C. Johnson University of Wisconsin—Oshkosh Charles B. Koontz Ball State University Three people deserve special mention because, without their expertise, this book would not exist. They are: Janet Hunter,copyeditor. This is my third book with Janet. She willingly rearranged her schedule to accommodate our deadlines. She is an out standing copyeditor, but more importantly, she is a nice person with an excellent sense of humor. Deanna Quinn, production coordinator. I have had the good fortune of working with Deanna before. She is one of the best in the business. Her helpful suggestions, attention to detail, adherence to deadlines, and gen eral positive nature make it delightful to work with her. Jerry Westhy, acquisitions editor. This is our third hook together, and my respect for Jerry keeps increasing. He has an excellent sense for what makes a book useful. Most of the special features of this text are the result of Jerry's suggestions. He has offered constant support and invaluable suggestions. My family and friends deserve special mention for their support and patience. Most of my recent spare time and energy have been devoted to this project. This would not have been possible without their encourage ment and understanding. XVI Preface Finally, there is one person without whose help this project would not have been possible. Helen, who was a student in my first Pascal class, has been of tremendous assistance since the inception of this effort. She pre pared every part of the manuscript on her word processor. She served as an "in-house" copyeditor and made many helpful suggestions regarding presentation of the material. This is the third text for which she has done all of the above. Her unfailing patience and support were remarkable. Fortunately for me, she has been my wife and best friend for more than thirty years. Douglas W. Nance Computer Science, Computer Architecture, and Computer Languages This chapter provides a quick introduction to computer science, computer architecture, and computer languages. Section 1.1 pro vides a preview of the study of computer science. Section 1.2 examines the structure and parts of a computer. Section 1.3 analyzes how computer languages are used to make a computer run. As you read this chapter, do not be overly concerned about the intro duction and early use of terminology. All terms will be subsequently developed. A good approach to an introductory chapter like this is to reread it periodically. This will help you maintain a good perspective as to how new concepts and techniques fit in the broader picture of using computers. Finally, remember that learning a language that will make a computer work can be exciting; being able to control such a machine can lead to quite a sense of power. ■ 1.1 Computer Science: A Preview Computer science is a very young discipline. Electronic computers were initially developed in the 1940s. Those who worked with computers in the 1940s and 1950s often did so by teaching themselves about computers; most schools did not then offer any instruction in computer science. However, as these early pioneers in computers learned more about the machines they were using, a collection of principles began to evolve into the discipline we now call computer science. Because it emerged from the efforts of people using computers in a variety of disciplines, the in fluence of these disciplines can often be seen in computer science. With 2 COMPUTER SCIENCE. COMPUTER ARCHITECTURE. AND COMPUTER LANGUAGES that in mind, in the next sections I will briefly define what computer science is (and what it is not). Computer Science Is Not Computer Literacy With the use of personal computers becoming increasingly widespread, a common mistake is to confuse computer science with computer literacy. In the 1980s and 1990s, computer literate people will know how to use a variety of computer software to make their professional lives and home lives more productive and easier. This software includes, for instance, word processors for writing and data-base management systems for storing every conceivable form of information (from address lists to recipes). However, knowing how to use specific pieces of computer software is not the same as acquiring an understanding of computer science,just as being able to drive a car does not qualify you as an expert mechanic. The user of computer software must merely be able to follow instructions about how to use the software. On the other hand,the modern computer scientist must, more than anything else, be a skillful problem-solver. The collection of problems that computer science encompasses and the techniques used to solve those problems are the real substance of this rapidly expanding discipline. Computer Science Is Mathematics and Logic The problem-solving emphasis of computer science borrows heavily from the areas of mathematics and logic. Faced with a problem, computer sci entists must first formulate a solution. This method of solution, or algo rithm as it is often called in computer science, must be thoroughly under stood before the computer scientists make any attempt to implement the solution on the computer. Thus, at the early stages of problem solution, computer scientists work solely with their minds and do not rely upon the machine in any way. Once the solution is understood, computer sci entists must then state the solution to this problem in a formal language called a programmmg language. This parallels the fashion in which math ematicians or logicians must develop a proof or argument in the formal language of mathematics. This formal solution as stated in a programming language must then be evaluated in terms of its correctness, style, and efficiency. Part of this evaluation process involves entering the formally stated algorithm as a programmed series of steps for the computer to follow. Another part of the evaluation process is distinctly separate from a consideration of whether or not the computer produces the "right an swer" when the program is executed. Indeed, one of the main areas of emphasis throughout this book is in developing well-designed solutions to problems and in recognizing the difference between such solutions and ones that work, but inelegantly. True computer scientists seek not just solutions to problems, but the best possible solutions. Computer Science Is Science Perhaps nothing is as intrinsic to the scientific method as the formulation of hypotheses to explain phenomena and the careful testing of these hy potheses to prove them right or wrong. This same process plays an integral role in the way computer scientists work. Upon observing a problem,such 1.1 Computer Science: A Preview 3 as a long list of names that we would like arranged in alphabetical order, computer scientists formulate a hypothesis in the form of an algorithm that they believe will effectively solve the problem. Using mathematical techniques, they can make predictions about how such a proposed al gorithm will solve the problem. But because the problems facing computer scientists arise from the world of real applications, predictive techniques relying solely upon mathematical theory are not sufficient to prove an algorithm correct. Ultimately, computer scientists must implement their solutions on computers and test them in the complex situations that orig inally gave rise to the problems. Only after such thorough testing can the hypothetical solutions be declared right or wrong. Moreover,just as many scientific principles are not 100 percent right or wrong, the hjrpothetical solutions posed by computer scientists are often subject to limitations. An understanding of those limitations—of when the method is appropriate and when it is not—is a crucial part of the knowledge that computer scientists must have. This is analogous to the way in which any scientist must be aware of the particular limitations of a scientific theory in ex plaining a given set of phenomena. Do not forget the experimental nature of computer science as you study this book. You must participate in computer science to truly learn it. Although a good book can help,yoM must solve the problems,implement those solutions on the computer, and then test the results. View each of the problems you are assigned as an experiment for which you are to propose a solution and then verify the correctness of your solution by testing it on the computer. If the solution does not work exactly as you hypothesized, do not become discouraged. Instead, ask yourself why it did not work; by doing so you will acquire a deeper understanding of the problem and your solution. In this sense, the computer represents the experimental tool of the computer scientist. Do not be afraid to use it for exploration. Computer Science Is Engineering Whatever the area of specialization, an engineer must neatly combine a firm grasp of scientific principles with implementation techniques. With out knowledge of the principles, the engineer's ability to creatively design models for a problem's solution is severely limited. Such model-building is crucial to the engineering design process. The ultimate design of a bridge, for instance, is the result of the engineer's considering many pos sible models of the bridge and then selecting the best one. The transfor mation of abstract ideas into models of a problem's solution is thus central to the engineering design process. The ability to generate a variety of models that can be explored is the hallmark of creative engineering. Sim ilarly, the computer scientist is a model-builder. Faced with a problem, the computer scientist must construct models for its solution. Such models take the form of an information structure to hold the data pertinent to the problem and the algorithmic method to manipulate that information struc ture to actually solve the problem. Just as an engineer must have an indepth understanding of scientific principles to build a model, so must a computer scientist. With these principles, the computer scientist may conceive of models that are elegant, efficient, and appropriate to the prob lem at hand. 4 COMPUTER SCIENCE, COMPUTER ARCHITECTURE. AND COMPUTER LANGUAGES An understanding of principles alone is not sufficient for either the engineer or the computer scientist. Experience in the actual implemen tation of hypothetical models is also necessary. Without such experience, you can have only very limited intuition about what is feasible and how a large-scale project should be organized to reach a successful conclusion. Ultimately,computers are used to solve problems in the real world. There, you will need to design programs that come in on time, that are within (if not under)the budget,and that solve all aspects of the original problem. The experience you acquire in designing problem solutions and then implementing them is vital to your being a complete computer scientist. Hence, remember that you cannot actually study computer science with out actively doing it. To merely read about computer science techniques will leave you with an unrealistic perspective of what is possible. Computer Science Is Interdisciplinary The problems solved by computer scientists come from a variety of dis ciplines—^mathematics, physics, chemistry, biology, geology, economics, business, engineering, linguistics, and psychology, to name a few. As a computer scientist working on a problem in one of these areas, you must be a quasi-expert in that discipline as well as in computer science. For instance, you cannot write a program to manage the checking account system of a bank unless you thoroughly understand how banks work and how that bank runs its checking accounts. At minimum, you must be literate enough in other disciplines to converse with the people for whom you are writing programs and to learn precisely what it is they want the computer to do for them. Since such people are often very naive about the computer and its capabilities, you will have to possess considerable communication skills as well as a knowledge of that other discipline. Are you beginning to think that a computer scientist must be knowl edgeable about much more than just the computer? If so, you are correct. Too often, computer scientists are viewed as technicians, tucked away in their own little worlds and not thinking or caring about anything other than computers. Nothing could be further from the truth. The successful computer scientist must be able to communicate,to learn new ideas quickly, and to adapt to ever-changing conditions. Computer science is emerging from its early dark ages into a mature process, one that I hope you will find rewarding and exciting. In studying computer science, you will be developing many talents; this text can get you started on the road to that development process. ® 1.2 Computer This section is intended to provide you with a brief overview of what computers are and how they are used. Although there are various sizes. Architecture makes, and models of computers, you will see that they all operate in basically the same straightforward manner. Whether you work on a per sonal computer that costs a few hundred dollars or on a mainframe that costs in the millions, the principles of making the machine work are essentially the same. Modern Computers The search for aids to perform calculations is almost as old as number systems. Early devices include the abacus, Napier's bones, the slide rule. 1.2 Computer Architecture 5 and mechanical adding machines. More recently,calculators have changed the nature of personal computing as a result of their availability, low cost, and high speed. The last few decades have seen the most significant change in com puting machines in the world's history as a result of improvements that have led to modern computers. As recently as the 1960s, a computer required several rooms because of its size. However, the advent of silicon chips has reduced the size and increased the availability of computers so that parents are able to purchase personal computers as presents for their children. These computers are more powerful than the early behemoths. What is a computer? According to Webster's New World Dictionary of the American Language(2nd College Edition), a computer is"an electronic machine which, by means of stored instructions and information, per forms rapid, often complex calculations or compiles, correlates, and se lects data." Basically, a computer can be thought of as a machine that manipulates information in the form of numbers and characters. This information is referred to as dxita. What makes computers remarkable is the extreme speed and precision with which they can store, retrieve, and manipulate data. Several types of computers currently are available. An oversimplifi cation is to categorize computers as mainframe, minicomputer, or micro computer. In this grouping, mainframe computers are the large machines used by major companies, government agencies, and universities. They have the capability of being used by as many as 100 or more people at the same time and can cost millions of dollars. Minicomputers, in a sense, are smaller versions of large computers. They can be used by several people at once but have less storage capacity and cost far less. Microcom puters are frequently referred to as personal computers. They have limited storage capacity (in a relative sense), are generally used by one person at a time, and can be purchased for as little as a few hundred dollars. As you begin your work with computers, you will hear people talking about hardware and software. Hardware refers to the actual machine and its support devices. Software refers to programs that make the machine do something. Many software packages exist for today's computers. They include word processing, data-base programs, spreadsheets, games, op erating systems, and compilers. You can (and will!) learn to create your own software. In fact, that is what this book is all about. A program can be thought of as a set of instructions that tells the machine what to do. When you have written a program, the computer will behave exactly as you have instructed it. It will do no more or no less than what is contained in your specific instructions. For example. PROGRAM ComputeRv (input, output); VAR A, B, C : integer; Average : real; BEGIN read (A, B, C); Average :=(A+B+C) /3; writeln (Average:ED:3) END. 6 COMPUTER SCIENCE, COMPUTER ARCHITECTURE, AND COMPUTER LANGUAGES is a Pascal program that causes a computer to get three integers (the data) from an input device, compute their average, and then print the result. Do not be concerned about specific parts of this program. It is intended only to illustrate the idea of a set of instructions. Very soon, you will be able to write significantly more sophisticated programs. Learning to write programs requires two skills. 1. You need to be able to use specific terminology and punctuation that can be understood by the machine: you need to learn a pro gramming language. 2. You need to be able to develop a plan for solving a particular problem. Such a plan is often referred to as an algorithm. This is a sequence of steps that, when followed, will lead to a solution of the problem. Initially, you may think that learning a language is the more difficult task because your problems will have relatively easy solutions. Nothing could be further from the truth! The single most important thing you can do as a student of computer science is to develop the skill to solve problems. Once you have this skill, you can learn to write programs in several different languages. Computer Hardware Let's take another look at the question: What is a computer? Our previous answer indicated it is a machine. Although there are severalforms,names, and brands of computers, each consists of a central unit that is somehow hooked to an input device and an output device (see Figure 1.1). FIGURE 1.1 Computer compo Input Central . Output nents device unit device 1. Keyboard 2. Tape 3. Disk 4. Mouse 1. Printer 2. Screen 3. Disk 4. Plotter The central unit can be thought of as containing two parts: a central processing unit (CPU), which is the "brain" of the computer, and main (primary)memory. The CPU contains an arithmetic/logic unit(ALU), which is capable of performing arithmetic operations and evaluating expressions to see if they are true or false, and the control unit, which controls the action of remaining components so your program can be followed stepby-step, or executed. Main memory can be thought of as mailboxes in a post office. It is a sequence of locations where information representing instructions, num bers, characters, and so on can be stored. If additional memory is needed, secondary (peripheral) memory devices are used. On small computers, these secondary memory devices could be floppy disks, hard disks, or magnetic tapes; on larger computers, hard disks or magnetic tapes. Main 1.2 Computer Architecture 7 memory is usable while the computer is turned on.It is where the program being executed is stored along with data it is manipulating. Other programs and data waiting to be executed are kept "waiting in the wings" in sec ondary memory. As you develop a greater appreciation of how the computer works, you might wonder: How are data stored in memory? Each memory location has an address and is capable of holding a sequence of binary (0 or 1) digits, which are commonly referred to as bits. Instructions, symbols, let ters, numbers, and so on are tremslated into an appropriate pattern of binary digits and then stored in various memory locations. These are retrieved, used, and changed according to instructions in your program. In fact, the program itself is similarly translated and stored in part of main memory. Main memory can be envisioned as in Figure 1.2, and the central unit can be envisioned as in Figure 1.3. FIGURE 1.2 Main memory Program Data FIGURE 1.3 Central unit cm Input devices are necessary to give information to the computer. A typical keyboard, floppy disk drive, and microcomputer with hard disk are shown in Figure 1.4. Whatever device you use, your program will be entered through it, and the program statements will be translated and stored as previously indicated. Output devices are necessary to show the 8 COMPUTER SCIENCE, COMPUTER ARCHITECTURE, AND COMPUTER LANGUAGES — BiEi (a) (b) FIGURE 1.4 (a) Keyboard,(b) disk drive, and (c) micro computer with hard disk results of your programs. These are normally in the form of a terminal screen, line printer, serial printer, or laser printer (Figure 1.5). Input and output devices are frequently referred to as HO devices. In summary, a simple computer system consists of an input device, a central unit, and an output device. A schematic representation of their A NOTE OF INTEREST Microprocessors The microprocessor and its silicon companion, the memory chip, are the cause of the computer erful as today's mainframes. And in manufac revolution. This revolution started in the 1970s day's video games. Since the development of the von Neumann and is far from over. By the mid-1990s, the term microcomputer will be almost synonymous with computer,and all but a very few super-computers will have silicon chips as their central process ing imits. There will be nothing small about these microcomputers, however,except their physical size; in computing power they will be as pow turing cost, they may be as inexpensive as to architecture in the late 1940s, every computer has had a central processing unit, or CPU. The CPU pulls information out of a computer's mem ory, alters it—for example, by adding another number to it—and puts it back into memory. 1.3 Computer Languages 9 (b) m (c) FIGURE 1.5 (a) Terminal screen, (b) line printer (mainframe],(c) se rial printer (micro computer), and (d) laser printer H 1.3 Computer Languages relationship is given in Figure 1.6. A more complete illustration, indi cating the range of peripheral devices together with the nature of infor mation transmission, is provided in Figure 1.7. What is a computer language? All data transmission, manipulation, stor age, and retrieval is actually done by the machine using electrical pulses generated by sequences of binary digits. If eight-digit bineiry codes are used, there are 256 numbered instructions from 00000000 to 11111111. Instructions for adding two numbers would consist of a sequence of these eight-digit codes. Instructions written in this form are referred to as machine language. It is possible to write an entire program in machine language. However, this is very time consuming and difficult to read and understand. Therefore, the next level of computer language allows words and sym bols to be used in an unsophisticated manner to accomplish simple tasks. For example, the previous machine code for adding two integers is re placed by 10 COMPUTER SCIENCE, COMPUTER ARCHITECTURE, AND COMPUTER LANGUAGES FIGURE 1.6 Input-output device relationship with computer CPU Gpntrol umt' Input Output device device MainmemGi^- 1 S^econdaiy' FIGURE 1.7 Complete computer rTerminal installation Keyboard Monitor Central unit Tape drive Line printer Disk drive LOAD A ADDB STORE C This causes the number in A to be added to the number in B and the result to be stored for later use in C.This computer language is an assembly language, which is generally referred to as a low-level language. What actually happens is that words and symbols are translated into appropriate binary digits and the machine uses the translated form. Although assembly language is an improvement on machine language for readability and program development, it is still a bit cumbersome. Consequently, many high-level languages have been developed; these in clude Pascal, PL/1, FORTRAN, BASIC, COBOL, C, Ada, Modula-2, Logo, 1.3 Computer Languages 11 and others. These languages simplify even further the terminology and symbolism necessary for directing the machine to perform various ma nipulations of data. For example, the task of adding two integers would be written as C := A + B; C = A + B; (Pascal) (PL/I) C= A +B C=A+B ADD A.B GIVING C C = A + B; (FORTRAN) (BASIC) (COBOL) (C) C:=A + B; C := A + B; MAKE "C :A + :B (Ada) (Modula-2) (Logo) A high-level language makes it easier to read, write, and understand a program. This book develops the concepts, symbolism, and terminology necessary for using Pascal as a programming language for solving prob lems. After you have become proficient in using Pascal, you should find it relatively easy to learn the nuances of other high-level languages. For a moment, let's consider how an instruction such as C := A + B; gets translated into machine code. The actual bit pattern for this code varies according to the machine and software version, but it could be as follows: 0100001lOOlllOJOOOll1101010000010010101101000010 In order for this to happen, a special program called a compiler "reads" the high-level instructions and translates them into machine code. This compiled version is then run using some appropriate data. The results are then presented through some form of output device. The special pro grams that activate the compiler, run the machine-code version, and cause output to be printed are system programs. The program you write is a source program, and the machine-code version is an object program (also referred to as object code). As you will soon see, the compiler does more than just translate in structions into machine code. It also detects certain errors in your source program and prints appropriate messages. For example, if you write the instruction C := (A + B; where a parenthesis is missing, when the compiler attempts to translate this line into machine code, it will detect that ")" is needed to close the parenthetical expression. It will then give you an error message such as ERROR IN VARIABLE You will then need to correct the error (and any others) and recompile your source program before running it with the data. Before leaving this introductory chapter, let's consider the question: Why study Pascal? Various languages have differing strengths and weak nesses. Pascal's strong features include the following: 12 COMPUTER SCIENCE, COMPUTER ARCHITECTURE, AND COMPUTER LANGUAGES A NOTE JNJTEREST Why Learn Pascal? From the point of view of many potential users, Pascal's major drawback is that it is a compiled rather than an interpreted language. This means that developing and testing a small Pascal pro gram can take a lot longer and involve many more steps than it would with an interpreted language like BASIC. The effect of this drawback has been lessened recently with the develop ment of interpreter programs for Pascal. Even so, most programs written by users of personal com puters are small ones designed for quick solu tions to particular problems, and the use of Pas cal for such programs may be a form of overkill. Ironically, the characteristics of Pascal that make it relatively unsuited for small programs are a direct consequence of its strengths as a programming language. The discipline imposed by the language makes it easier to understand large programs, but it may be more than a small program demands. For serious development of large programs or for the creation of tools that will be used over and over again (and require modifications from time to time), Pascal is clearly Experts generally consider Pascal an impor tant language for people who are planning to study computer science or to learn program ming.Indeed,the College Entrance Examination Board has recently designated Pascal as the re quired language for advanced-placemOnt courses in computer science for high school students. While it is true that an experienced programmer can write clearly structured programs in any lan guage, learning the principles of structured pro gramming is much easier in Pascal. Is Pascal difficult to learn? We don't think so, but the question is relative and may depend on which language you leam first. Programmers be come accustomed to the first language they learn, making it the standard by which all others are judged. Even the poor features of the familiar language come to be seen as necessities, and a new language seems inferior. Don't let such sub jective evaluations bar your way to learning Pas cal, a powerful and elegant programming language. superior. 1. It incorporates program structure in a reasonable approximation of English. For example, if a certain process is to be repeated until some condition is met, this could be written in the program as REPERT (process here) UNTIL (condition here] 2. It allows the use of descriptive words for variables and data types. Thus, programs for computing payrolls could use words like HoursWorked, StateTax, PICA, TotalDeductions, and GrossPay. 3. It facilitates good problem-solving habits; in fact, many people consider this to be Pascal's main strength. As previously noted, developing the skill to solve a problem using a computer program is the most important trait to develop as a beginning programmer. Pascal is structured in such a manner that it encourages—indeed, almost requires—good problem-solving skills. You are now ready to begin a detailed study of Pascal. 1 hope you find the time spent and frustrations encountered will result in an exciting and rewarding learning experience. Good luck. Summary Summary 13 Key Terms algorithm arithmetic/logic unit (ALU) assembly language binary digits bits central processing unit (CPU) executed minicomputer hardware object code high-level language input device object program program low-level language machine language programming language secondary (peripheral) mainframe central unit main (primary) memory compiler microcomputer control unit data output device I/O devices memory software source program system program GHAPT^Jglt ;_LLUJ_ Writing Your First Prograins Chapter 1 presented an overview of computers and computer lan guages. We are now ready to examine problems that computers can solve. First we need to know how to solve a problem and then we need to leam how to use a programming language to implement our so lution on the computer. Before looking at problem solving and writing programs for the com puter, we should consider some psychological aspects of working in com puter science. Studying computer science can cause a significant amount of frustration because 1. Successful problem solving and programming require extreme precision. Generally, concepts in computer science are not diffi cult; however, implementation of these concepts allows no room for error. For example, one misplaced semicolon in a 1,000-line program could prevent the program from working. 2. Time is a major problem. Writing programs is not like completing other assignments. You cannot expect to complete a programming assignment by staying up late the night before it is due. You must begin early and expect to make several revisions before your final version will be ready. 3. Planning is a critical issue. You must plan to develop instructions to solve your problem and translate those instructions into code before you sit down at the keyboard. You should not attempt to type in code "off the top of your head." In other words, you must be prepared to plan well, start early, be patient, handle frustration, and work hard to succeed in computer science. If you cannot do this, you will probably neither enjoy computer science nor be successful at it. 14 2.1 Program Development—Top-Down Design ■ 2.1 Program Devel opment—^TopDown Design OBJECTl^^S; ^ ■ to understand what an algorithm is ■ to understand what 15 The key to writing a successful program is planning. Good programs do not just happen; they are the result of careful design and patience. Just as an artist commissioned to paint a portrait would not start out by shading in the lips and eyes, a good computer programmer would not attack a problem by immediately trying to write code for a program to solve the problem. Writing a program is like writing an essay: an overall theme is envisioned, an outline of major ideas is developed, each major idea is subdivided into several parts,and each part is developed using individual sentences. top-down design is ■ to imderstand what stepwise refinement is ■ to understand what modularity is •> to be able to de velop algorithms Five Steps to Good Programming Habits In developing a program to solve a problem,five steps should be followed: understand the problem,develop an algorithm, write code for the program, run the program, and test the results. These steps will help develop good problem-solving habits and, in turn, solve programming problems cor rectly. A brief discussion of each of these steps follows: Step 1. Understand the Problem. This is not a trivial task. Before you can do anything, you must know exactly what it is you are to do. You must be able to formulate a clear and precise statement of what is to be done. You should understand completely what data are available and what may be assumed. You should also know exactly what output is desired and the form it should take. Step. 2. Develop an Algorithm. An algorithm is a finite sequence of ef fective statements that, when applied to the problem, will solve it. An effective statement is a clear, unambiguous instruction that can be carried out. Each algorithm you develop should have a specific beginning; at the completion of one step, have the next step uniquely determined; and have an ending that is reached in a reasonable amount of time. Step 3. Write Code for the Program. When the algorithm correctly solves the problem, you can think about translating your algorithm into a highlevel language. An effective algorithm will significantly reduce the time you need to complete this step. Step 4. Run the Program. After writing the code, you are ready to run the program. This means that using an editor, you type the program code into the computer, compile the program, and run the program. At this point, you may discover errors that can be as simple as typing errors or that may require a reevaluation of all or parts of your algorithm. The probability of having to make some corrections or changes is quite high. Step 5. Test the Results. After your program has run, you need to be sure that the results are correct, that they are in a form you like, and that your program produces the correct solution in all cases. To be sure the results are correct, you must look at them and compare them with what you expect. In the case of using a program with arithmetic operations, this means checking some results with pencil and paper. 16 WRITING YOUR FIRST PROGRAMS Developing Algorithms Algorithms for solving a problem can be developed by stating the problem and then subdividing the problem into major subtasks. Each subtask can then be subdivided into smaller tasks. This process is repeated until each remaining task is one that is easily solved. This process is known as topdown design, and each successive subdivision is referred to as a stepwise refinement. Tasks identified at each stage of this process are called modules. Graphically, this can be represented as shown in Figure 2.1. More spe cifically, this can be illustrated by designing a solution to the problem of updating a checkbook after a transaction has been made. A first-level development is shown in Figure 2.2. FIGURE 2.1 Illustration of topdown design Main task FIGURE 2.2 Update First-level refinement checkbook Get Perform Print information computations results An arrow pointing into a module means information is needed before the task can be performed. An arrow pointing out of a module means the module task has been completed and information required for subsequent work is available. Each of these modules could be further developed as shown in Figure 2.3. Finally, one of the last modules could be developed as shown in Figure 2.4. The complete top-down design could then be envisioned as illustrated in Figure 2.5. Notice that each remaining task can be accomplished in a very direct manner. As a further aid to understanding how data are transmitted, module specifications will be listed for each main (first-level) module. Each mod- 2.1 Program Development—^Top-Down Design FIGURE 2.3 Second-level i 17 t FIGURE 2.4 Third-level refinement Prinf transactibii ule specification includes a description of data received, information re turned, and logic used in the module. The module specification for the previous module is Get Information Module Data received: None Information returned: Starting balance Transaction type Transaction amount Logic: Have the user enter information from the keyboard. For the checkbook problem, complete module specifications are 1. Get Information Module Data received: None Information returned: Starting balance Transaction type Transaction amount Logic: Have the user enter information from the keyboard. 2. Perform Computations Module Data received: Transaction amount Transaction type Starting balance Information returned: Ending balance Logic: If transaction is a deposit, add it to the starting balance; otherwise, subtract it. FIGURE 2.5 Top-down design Gheckboblc Pejfdim GpipputatiQns Get information Get Get starting tians^tta Get traiisaction balance type amount Petermtne balance: reatuts Prmt endml startmg transaction balabce Pnnt type amouiit 2.1 Program Development—^Top-Down Design 19 3. Print Results Module Data received: Starting balance Transaction type Transaction amount Ending balance Information returned: None Logic: Print results in a readable form. At least two comments should be made about top-down design. First, different people can (and probably will) have different designs for the solution of a problem. However, each good design will have well-defined modules with functional subtasks. Second, the graphic method just used helps to formulate general logic for solving a problem but is somewhat awkward for translating to code. Thus,we will use a stylized, half-English, half-code method called pseudocode to illustrate stepwise refinement in such a design. This will be written in English, hut the sentence structure and indentations will suggest Pascal code. Major tasks will be numbered with whole numbers and subtasks with decimal numbers. First-level pseudocode for the checkbook-balancing problem is 1. Get information 2. Perform computations 3. Print results A second-level pseudocode development produces 1. Get information 1.1 get starting balance 1.2 get transaction type 1.3 get transaction amount 2. Perform computations 2.1 IF deposit THEN add to balance ELSE 3. subtract from balance Print results 3.1 print starting balance 3.2 print transaction 3.3 print ending balance Finally, step 3.2 of the pseudocode is subdivided as previously indicated into 3.2 print transaction 3.2.1 print transaction type 3.2.2 print transaction amount Two final comments are in order. First, each module developed should be tested with data for that module. Once you are sure each module does what you want, the whole program should work when the modules are used together. Second, the process of dividing a task into subtasks is especially suitable for writing programs in Pascal. 20 WRITING YOUR FIRST PROGRAMS A Pascal program for this problem follows: PROGRAM Checkbook (input, output); VAR StartingBalance, EndingBalance, TransAraount : real; TransType : char; BEGIN •{ i Main Program } Module for getting the data I write ('Enter the starting balance and press . • ); readln (StartingBalance); writeln ('Enter the transaction type (D) deposit or (W) withdrawal '); write ('and press . readln (TransType); 1' '); write ('Enter the transaction amount and press . '); readln (TransAmount); { Module for performing computations } IF TransType = 'D' THEN v 2 EndingBalance := StartingBalance + TransAmount ELSE EndingBalance := StartingBalance - TransAmount; { Module for printing results > writeln; writeln; writeln ('Starting Balance writeln ('Transaction $', StartingBalance:fl:E); $', TransAmount:fl:2, TransType:E); writeln (' ' :33); writeln ('Ending Balance END. > 3 $', EndingBalance:fl:E) Notice how sections of the program correspond to module specifica tions. Sample runs of the program produce the output Enter the Enter the and press Enter the starting balance and press . E35.lt transaction type (D) deposit or (H) withdrawal . D transaction amount and press . 75.□□ Starting Balance $ E35.lt Transaction $ 75.D0 Ending Balance $ 310.lt Enter the Enter the and press Enter the D starting balance and press . 31Q.lt transaction type (D) deposit or (W) withdrawal . H transaction amount and press . t5.75 Starting Balance $ 31D.lt Transaction $ t5.75 Ending Balance $ SAA.Al W •These numbers refer to the modules previously developed with module specifications. 2.1 Program Development—^Top-Down Design 21 A NOTE 0]E INTERESTV Software Engineering In the article "A Computer Science Perspective on Bridge Design"[Communications ofthe ACM, April 1986), Alfred Spector and David Gifford interviewed bridge designer Gerald Fox to de termine parallels between the design process fol lowed by a professional engineer who is building a bridge and a software designer who is devel oping a complex program. Not surprisingly, many similarities are found. Included among them are Engineers designing a bridge view it first as a hierarchy of substructures. This decompo sition process continues on the substruc tures themselves until a level of very funda mental objects (such as beams and plates) ultimately is reached. This decomposition technique is similar to the stepwise refine ment technique used by software designers, who break a complex problem down into a hierarchy of subproblems each of which ul timately can be solved by a relatively sim ple algorithm. Engineers build conceptual models before actually constructing a bridge. This modelbuilding allows them to evaluate various design alternatives in a way which eventu ally leads to the best possible design for the application being considered. This process is analogous to the way in which a skilled software designer builds models of a soft ware system using structure charts and firstlevel pseudocode descriptions of modules. The designer then studies these conceptual models and eventually chooses the most elegant and efficient model for the applica tion. By the fashion in which engineers initially break down the bridge design, they insure that different aspects of the design can be addressed by different subordinate groups of design engineers working in a relatively independent fashion. This is similar to the goal of a software designer who oversees a program development team. The design of the software system must insure that indi vidual components may be developed si multaneously by separate groups whose work will not have harmful side effects when the components are finally pulled together. Reliability and maintainability are of crucial importance to both the engineer who de signs a bridge and the software system de signer. The users of a bridge do not expect to be taking a risk with their lives when they use the bridge. Similarly, the users of a software package do not expect to be taking a risk with their valuable information when using a program that manipulates their in formation. Hence bridge and software de signers must be concerned with methods of thoroughly testing their products before they are put into use and then insuring that the system can be altered with relative ease to meet the changing needs of the future. One of the reasons that increasing attention is being given to similarities between the design techniques used by an engineer and a software developer is the hope that elements of the very structured development process that has been employed for years in the engineering profession may influence the very haphazard way in which computer software has often been developed. As we come to better understand the similarities and differences between the disciplines of en gineering and computer science, we may well enter a new age of software engineering in which the productivity of software developers and the reliability of their programs reach previously unattained heights. You probably would not use the power of a computer for something as simple as this program. You could just press a few calculator keys instead. However, as you will see, the language supports development of subpro grams for specific subtasks. You will,for example,soon be able to enhance this program to check for overdrafts, save the new balance for later use, and repeat the process for several transactions. Learning to think in terms of modular development now will aid you not just in creating algorithms to solve problems,but it will aid you in writing programs to solve problems. 22 WRITING YOUR FIRST PROGRAMS Exercises 2.1 1. Which of the following statements are effective? Why or why not? a. b. c. d. e. Pay the cashier $9.15. Water the plants a day before they die. Determine all positive prime numbers less than 1,000,000. Choose X to be the smallest positive fraction. ' Invest your money in a stock that will increase in value. 2. What assumptions need to be made to understand each of the following problems? a. Find the largest number of a set of numbers. b. Alphabetize a list of names. c. Compute charges for a telephone bill. 3. Outline the main tasks for solving each of the following problems. a. Write a good term paper. b. Take a vacation. c. Choose a college. d. Get a summer job. e. Compute the semester average for a student in a computer science course and print all pertinent data. 4. Refine the main tasks in each part of Exercise 3 into a sufficient number of levels so that the problem can be solved in a well-defined manner. 5. Use pseudocode to write a solution for each of the following problems. Indi cate each stage of your development. a. Compute the wages for two employees of a company. The input informa tion will consist of the hourly wage and the number of hours worked in one week. The output should contain a list of all deductions, gross pay, and net pay. For this problem, assume deductions are made for federal withholding taxes, state withholding taxes, social security, and union dues. b. Compute the average test score for five students iff a class. Input for this problem will consist of five scores. Output should include each score and the average of these scores. 6. Develop an algorithm to find the total, average, and largest number in a given list of 25 numbers. 7. Draw a structure chart and write module specifications for each of the fol lowing exercises. a. Exercise 5a. b. Exercise 5b. c. Exercise 6. ■ 2.2 Words in Pascal Writing Programs Consider the following complete Pascal program. PROGRAM Example (input, output); OBTECTIVES CONST a to be able to recog Skip = ' '; nize reserved words and predefined stan dard identifiers Objectives continued. VAR J, X, Sum : integer; Average : real; 2.2 Writing Programs to be able to recog 23 BEGIN nize and declare Sum := □; valid identifiers FOR J := 1 TO 3D DO BEGIN to know the three basic components of read a program Sura (X); := Sura + X END; to understand the Average basic structure of a writeln; Pascal program := Sura / 30; writeln; writeln (SkiprlD, 'The average is' / Average:fl:E); writeln; writeln (SkiprlG/ 'The number of scores is', 30:3) END. This program—and most every programming language—^requires the use of words when writing code. In Pascal, words that have a predefined meaning that cannot be changed are called reserved words. Some other predefined words [standard identifiers) can have their meanings changed if the programmer has strong reasons for doing so. In this text, reserved words are capitalized and in bold type; standard identifiers are lowercase and in bold type. When used in programs, reserved words are capitalized and standard identifiers are lowercase. Other words [identifiers) must be created according to a well-defined set of rules, but can have any meaning, subject to those rules. Reserved Words In Pascal, reserved words are predefined and cannot be used in a program for anjdhing other than the purpose for which they are reserved. Some examples are AND, OR, NOT, BEGIN, END, IF, and FOR. As you continue in Pascal, you will learn where and how these words are used. At this time, however, you need only become familiar with the reserved words in Table 2.1; they are also listed in Appendix 1. TABLE 2.1 Reserved words AND ELSE IF OR THEN ARRAY END IN PACKED TO BEGIN FILE LABEL PROCEDURE TYPE CASE FOR MOD PROGRAM UNTIL CONST FORWARD NIL RECORD VAR DIV FUNCTION NOT REPEAT WHILE DO GOTO OF SET WITH DOWNTO Standard Identifiers A second set of predefined words, standard identifiers, can have their meanings changed by the programmer. For example, if you could develop a better algorithm for the trigonometric function sin, you could then sub stitute it in the program. However, these words should not be used for anything other than their intended use. This list will vary somewhat from computer to computer, so you should obtain a list of standard identifiers used in your local implementation of Pascal. Some standard identifiers are listed in Table 2.2 and in Appendix 2. The term keywords is used to 24 WRITING YOUR FIRST PROGRAMS TABLE 2.2 Standard identifiers Data Types Constants boolean char false maxint abs dispose input arctan get output integer true chr new real cos pack text eof page Functions Procedures eoln put exp read in readin odd reset ord rewrite pred unpack round write sin writeln Files sqr sqrt succ trunc refer to both reserved words and predefined identifiers in subsequent discussions. Syntax and Syntax Diagrams Syntax refers to the rules governing construction of valid statements. This includes the order in which statements occur, together with appropriate punctuation. Syntax diagramming is a method to describe formally the legal syntax of language structures. Syntax diagrams show the permissible alternatives for each part of each kind of sentence and where the parts may appear. The symbolism we use is shown in Figure 2.6. A combined FIGURE 2.6 Symbols used in syntax diagrams Reserved words or terms that cannot be further defined Items that are defined by another diagram Any form of a separator listing of syntax diagrams is contained in Appendix 3. Arrows are used to indicate possible alternatives. To illustrate, a syntax diagram for forming words in the English language is letter 2.2 Writing Programs 25 If the word has to start with a vowel, the diagram is vowel 7H where vowel and letter are defined in a manner consistent with the English alphabet. Syntax diagrams are used throughout the text to illustrate formal constructs. You are encouraged to become familiar with them. Identifiers Reserved words and standard identifiers are restricted in their use; other words used in a program are identifiers, and most Pascal programs require their use. The more complicated the program,the more identifiers needed. A valid identifier must start with a letter of the alphabet and must consist only of letters and digits. A syntax diagram for forming identifiers is \ letteF Table 2.3 gives some valid and invalid identifiers along with the reasons for those that are invalid. A valid identifier can be of any length. However, some versions of Pascal recognize only the first part of a long identifier, for example,the first eight or the first ten characters. Therefore,identifiers such as MathTestScorel and MathTestScore2 might be the same identifier to a computer and could not be used as different identifiers in a program. Thus, you should learn what restrictions are imposed by your compiler. TABLE 2.3 Valid and invalid identifiers Identifier Sum Valid If Invalid, Reason Yes X+ Y No Average Yes Textl Yes IstNum No X Yes K mart No ThisIsaLongOne Yes "+"is not allowed Must start with a letter Spaces are not allowed The most common use of identifiers is to name the variables to be used in a program. Recall from algebra that variables such as x, y, and z are frequently used in functional relationships; these could also be used as identifiers in a Pascal program. However, we should generally use names that are more descriptive. A detailed explanation of the use of variables is given in Chapter 3. 26 WRITING YOUR FIRST PROGRAMS Another use of identifiers is to name S5nnbolic constants to be used in a program; for example, to identify a certain name or date to be used repeatedly. A third use of identifiers is to neime the program.Every program requires a name, and the name must be a valid identifier. Identifiers are also needed to name new data types and subprograms, but don't worry; we'll get to that in later chapters. It is important to develop the habit of using appropriate descriptive identifiers in your programs. For example, if you are using scores in a program, identifiers like Scorel, Score2, and ScoreS are better than X, Y, and Z. Similarly, use descriptive identifiers like Sum, Average, Balance, or Hours when appropriate. Initially, you may not think this important, but as programs get longer and more complex, you will appreciate the fact that descriptive identifiers make a program easier to read. Basic Program Components A program in Pascal consists of three components: a program heading, an optional declaration section, and an executable section. These three com ponents are illustrated in the program shown in Figure 2.7. The sjmtax diagram for a program is file list Figure 2.8 illustrates the program components of the sample program (PROGRAM Example) that started this section. The program beading is the first statement of any Pascal program. It is usually one line and must contain the reserved word PROGRAM; the program name, which must be a valid identifier; a list of files used; and a semicolon at the end. The respective parts of a program heading are PROGRAM name (file list); In standard Pascal, file list must include the files input and/or output. Some other versions, for example Turbo Pascal, do not have this require ment. Note: The symbol appears in the margin to alert you to cases in which Turbo differs from standard Pascal. These differences are explained in Appendix 6. The template or fill-in-the-blanks form above is used throughout this book. Reserved words and standard identifiers are shown. You must use identifiers to replace the words in lowercase letters. Examples of program headings include PROGRAM PROGRAM PROGRAM PROGRAM PROGRAM FirstOne (output); Rookie (input, output); FindSum (input, output); Checkbook (input, output); Nuraberl (output); 2.2 Writing Progrcims FIGURE 2.7 Program Components of a heading C PBOGRAM name (hie list); program CONST list of constants (Here we must TYPE list of data types list each identifier we Declaration use and how it section is to be used.) (optional) VAR list of variables list of subprograms (Here we must list any subprograms.) BEGIN body of program Executable (Here is the source program version of the algorithm: the section instructions _ END. that tell the computer what to do.) FIGURE 2.8 Components of PRO GRAM Example Program heading • C PROGRAM Example (input, output); CONST Skip = ' • ; Declaration section VAR — J, X, Sum : integer; Average : real; BEGIN Sum := □; FOR J := 1 TO 3D DO ^BEGIN read Sum Executable section (X) ; := Sum + X END; Average writeln; writeln := Sum / 3D; writeln; (SkiprlD, 'The average is'. Average:fl:2); (SkiprlD, 'The number of scores is", writeln; writeln L END. 3D:3) 27 28 WRITING YOUR FIRST PROGRAMS You need not be concerned about input and output files in the file list at this point. Merely be aware that, if a program is producing some output (and what program wouldn't?), output may be required. If data are to be read into a program, input (or a similar file) may also be required. Any list has its parts separated by commas. However, many current versions of Pascal (Apple, 1\irbo, and UCSD, for example) do not require such a list. A syntax diagram for a program heading follows: -W PROGRAM 1 IQgnuupF J idenfifier The remainder of the program is sometimes referred to as the main block; major divisions are the declaration section and the executable sec tion. The declaration section is used to declare (name) all symbolic con stants, data t3q)es, variables, and subprograms that are necessary to the program. All constants named in the declaration section are normally referred to as being defined. Thus, we generally say constants are defined and variables are declared. When constants are defined, they appear in the constant definition portion of the declaration section after the reserved word CONST. The form for defining a constant is CONST identifier 1 = value 1; identifier 2 = value 2; identifier n - value n; The syntax diagram for this part is value Values of constant identifiers cannot be changed during program execution. If a value is a string of characters,it must be enclosed in single quotation marks (apostrophes). For example, CONST Date = 'July 177t'; Any number of constants may be defined in this section. Maximum read ability is achieved when the constants are listed consecutively and aligned down the page. A typical constant definition portion of the declaration section could be 2.2 Writing Programs 29 CONST Skip = ' '; Name = 'George Washington'; Date = 'July A, 177t'; SplatS — '3|e :tc:ic:(c :4c 9|c:tc:|c :|c>|c Line = ' ^ 4^'; '; ClassSize = 35; SpeedLimit = tS; CmToInches = 0.3537; The TYPE portion of the declaration section will be explained in Section 8.1. The variable declaration portion of the declaration section should be listed after the TYPE portion, if present, and must begin with the reserved word VAR. This section must contain all identifiers for variables to be used in the program; if a variable is used that has not been declared, a syntax error will occur when the program is compiled. As with constants, variables must be valid identifiers and are usually listed down the page to enhance readability. The form required for declaring variables is somewhat different from that used for defining constants: it requires a colon instead of an equal sign and specific data types. The simplest correct form is VAR identifier 1 : data type 1; identifier n : data type n; The syntax diagram is VAR identifier type Since data types are not discussed until later in this chapter, assume for now that real, integer, and char are valid data types. The reserved word VAR may appear only once in a program (exceptions will he noted when subprograms are developed). If no variables are to be used, a variable declaration section is not needed;however,this seldom happens. A typical variable declaration section could look like this: VRR Sum : integer; Average : real; I, J, K : integer; Ch : char; Four other examples of permissible methods of writing this declaration section are 30 WRITING YOUR FIRST PROGRAMS VRR I : J : K : Sum integer; integer; integer; : integer; Ch : char; Average : real; VAR I, J, K/ Sum : integer; Ch : char; Average : real; VAR I, J, K, Sum : integer; Ch : char; Average : real; VAR 1/ J/ K/ Sum : integer; Ch : char; Average : real; The third basic program component is the executable section. This section contains the statements that cause the computer to do something. It must start with the reserved word BEGIN and conclude with the reserved word END. Also, a period must follow the last END in the executable section. The syntax diagram is BEGIN stiatemeht Writing Code in Pascal We are now ready to examine the use of the executable section of a pro gram.In Pascal,the basic unit of grammar is an executable statement, which consists of valid identifiers,standard identifiers,reserved words,numbers, and/or characters together with appropriate punctuation. One of the main rules for writing code in Pascal is that a semicolon is used to separate executable statements. For example, if the statement wrlteln ('The results are' rED, Sum:a, ' and'/ Aver:Ea:5) were to be used in a program,it would (almost always)require a semicolon between it and the next executable statement. Thus, it should be writeln ('The results are' rao, SumiO/ ' and', AverrtcE); One instance exists where an executable statement does not need a fol lowing semicolon. When a statement is followed by a reserved word END, END is not a statement by itself, but part of a BEGIN...END pair;therefore a semicolon is not required. However, as you will see in Section 2.3, if one is included, it will not affect the program. 2.2 Writing Programs 31 BEGIN FIGURE 2.9 Statement 1; Statement 2; Executable section Executable section Statement n — 1; Statement n L END Although you are not currently familiar with many executable state ments, you can visualize the executable section as shown in Figure 2.9. Two comments are now in order. First, Pascal does not require that each statement be on a separate line. Actually, you could write a program as one long line (which would wrap around to fit the screen) if you wish; however, it would be very difficult to read. Compare, for example, the readability of the following two programs. PROGRAM ReadCheck (output); CONST Name = 'George'; Age = Et; VAR J, Sum : integer; BEGIN Sum := □; FOR J := 1 TO ID DO Sura ('My name is writeln; ' :5fl/ writeln := Sura + J; Name); writeln writeln ( 'My age is ('The sum is ' isa. ':57/ Age); Sum) END. PROGRAM ReadCheck (output); CONST Name = 'George' ; Age = Et; VAR J/ Sum : integer; BEGIN Sum := □; FOR J Sum := 1 TO ID DO := Sura + J; writeln ('My name is ' :Efl/ Name); writeln ('My age is ' :E7/ Age); writeln; writeln ('The sum is ' :Efl, Sura) END. You are not expected to know what the statements mean at this point, but it should be obvious that the second program is much more readable than the first. In addition, it is easier to change if corrections are necessary. Second, Pascal ignores extra spaces and line boundaries. This explains why the two programs are identical. For example, in a program heading, the following are equivalent: PROGRAM ExtraBlanks (output); PROGRAM ExtraBlanks(output); PROGRAM ExtraBlanks ( output ); A good principle to follow is to use spacing to enhance readability. Decide on a style you like (and your instructor can tolerate) and use it consistently. Most programmers, however, include a space before a left 32 WRITING YOUR FIRST PROGRAMS A.NOTE Blaise Pascal Blaise Pascal was bom in 1623 in France. He was In 1641, at the age of 18, he invented the first calculating machine in history. This machine op acutely ill most of his life and died in 1662 at the age of 39. Mathematics was excluded from his early life for fear that he would overstrain himself by using his head. However, after a be erated using ten gears (base 10). Values were car ried by one gear activating the gear for the next lated introduction, he became fascinated with tax clerks of the era who viewed it as a threat to the subject and devoted most of the rest of his life to its study. His major contribution was the development (with Pierre de Fermat) of the the ory of probability. their jobs. Pascal presented his machine to Queen decimal place. Pascal's machine was opposed by Christina of Sweden in 1650; it is not known what she did with it. parenthesis and after a right parenthesis when appropriate but no spaces immediately inside parentheses; for example. PROGRAM LooksNlce (Input/ output); Exercises 2.2 1. List the rules for forming valid identifiers. 2. Which of the following are valid identifiers? Give an explanation for those that are invalid. a. 7Op b. Payroll c. RoomEES d. Name List e. A f. A1 g. lA h. TimeAPlace i. CONST j. X*Y k. ListOfEraployees 1. Lima/Ohio 3. Which of the following are valid program headings? Give an explanation for those that are invalid. a. b. ■c. d. e. f. g. PROGRAM Rookie (output) PROGRAM Pro (input/ output); TestProgram (input/ output); PROGRAM (output); PROGRAM GettingBetter (output); PROGRAM Have Fun (input/ output); PROGRAM EndOne (output); 4. Name the three main sections of a Pascal program. 5. Write constant definition statements for the following; a. your name b. your age c. your birth date d. your birthplace 2.3 Data Types and Output 33 6. Find all errors in the following definitions and declarations: a. CONST Company : 'General Motors'; VAR Salary : real; b. VAR Age = 25; c. VAR Days : integer; Ch : char; CONST Name = 'John Smith d. CONST 'Cadillac'; Car : e. CONST f. VAR Score : integer; X/ Y/ Z : real; Score/ Nura : integer; 7. Discuss the significance of a semicolon in writing Pascal statements. ■ 2.3 Data Types and Output OBJEQTiyjES . ■ to understand and be able to use the data types integer, real, and char ■ to understand the difference between floating-point form and fixed-point form of decimal numbers ■ to understand the syntax for and use Type integer Numbers in some form will be used in computer programs and the kind of numbers used is referred to as its data type. We will first look at numbers of type integer, which are integers that are positive, negative, or zero. Some rules that must be observed when using integers are 1. Plus"+"signs do not have to be written before a positive integer. For example, +283 and 283 have the same value and both are allowed. 2. Minus"—"signs must be written when using a negative number. 3. Leading zeros are ignored. For example, 00073 +073,0073, and 73 all have the same value. 4. Decimal points cannot be used when writing integers. Although 14 and 14.0 have the same value, 14.0 is not of type integer. 5. Commas cannot be used when writing integers. 271,362 is not al lowed; it must be written as 271362. of write and writeln for output The syntax diagram for an integer is ■ to be able to format output There is a limit on the largest and the smallest integer constant. The largest such constant is maxint and the smallest is usually -maxint or (-maxint-l). maxint and -maxint are recognized by every version of Pascal; however, different machines have different values for them. This section ends with a program that enables you to discover the value of 34 WRITING YOUR FIRST PROGRAMS maxint on your computer. Operations with integers will be examined in the next section and integer variables will be discussed in Chapter 3. Type real Working with reals is more complicated than working with integers. When using decimal notation, numbers of type real must be written with a decimal point with at least one digit on each side of the decimal. Thus, .2 is not a valid real but 0.2 is. Plus"+"and minus"-"signs for data of type real are treated exactly as with integers. When working with reals, however, both leading and trailing zeros are ignored. Thus, +23.45, 23.45, 023.45, 23.450, and 0023.45000 have the same value. All reals seen thus far have been in fixed-point form. The computer will also accept reals in floating-point or exponential form. Floating-point form is an equivalent method for writing numbers in scientific notation to accommodate numbers that may have very large or very small values. The difference is, instead of writing the base decimal times some power of 10, the base decimal is followed by E and the appropriate power of 10. For example,231.6 in scientific notation would be 2.316 x 10^ and in floating point form would be 2.316E2. Table 2.4 sets forth several fixed-point TABLE 2.4 Forms for equivalent numbers Fixed-point Floating-point Scientific Notation 46.345 4.6345X10 59214.3 5.92143X10" 5.92143E4 0.00042 4.2 X 10-" 4.2E-4 4.6345E1 36000000000.0 3.6 X 10^" 3.6E10 0.000000005 5.0X10-^ 5.0E-9 -341000.0 -3.41 X 105 -3.41E5 decimal numbers with the equivalent scientific notation and floating-point form. Floating-point form for real numbers does not require exactly one digit on the left of the decimal point. In fact, it can be used with no decimal points written. To illustrate, 4.16E1, 41.6, 416.0E-1, and 416E-1 have the same value and all are permissible. However, it is not a good habit to use floating-point form for decimal numbers unless exactly one digit appears on the left of the decimal. In most other cases, fixed-point form is preferable. The syntax diagram for a real number is )^ digit J mi 7" 1 When using reals in a program, you may use either fixed-point or floating point form. But the computer prints out reals in floating-point form unless you specify otherwise. Formatting output is discussed later in this section. 2.3 Data Types and Output 35 Type char Another data type available in Pascal is char, which is used to represent character data. In standard Pascal, data of type char can be only a single character. These characters come from an available character set that dif fers somewhat from computer to computer, but always includes the letters of the alphabet; the digits 0,1,2,3,4,5,6, 7,8,and 9; and special symbols such as #, &, !, +, and so on. Two common character sets are given in Appendix 4. Character constants of type char must be enclosed in single quotation marks when used in a program. Otherwise,they will be treated as variables and subsequent use will cause a compilation error. Thus, to use the letter A as a constant, you would type A'. The use of digits and standard op eration symbols as characters is also permitted; for example, *7' would be considered a character, but 7 is an integer. If a word of one or more characters is used as a constant in a program, it is referred to as a string constant. String constants, generally called strings, may be defined in the CONST portion of the declaration section. The entire string must be enclosed in single quotation marks. A string is not a standard Pascal data type. Some sample definitions are CONST Name = 'John Q. Public'; Date = 'July 177ti'; Splats = '************************'; Students with experience in using BASIC usually expect the equivalent m of a string variable for storing names, and other information. Standard Pascal does not have such a feature. However,an analogous feature, packed arrays of characters, is presented in Section 9.5. When a single quotation mark is needed within a string,it is represented by two single quotation marks. For example, if the name desired was O'Malley, it would be represented by '0''MALLEY' When a single quotation mark is needed as a single character, it can be represented by placing two single quotation marks within single quotation marks. When typed, this appears as Note that these are all single quotation marks; use of the double quotation mark character here will not produce the desired result. Output The goal of most programs is to print something. What gets printed (either on paper or on a screen) is referred to as output. The two program state ly ments that produce output are write and writeln (pronounced "write line"). They are usually followed by character strings, numbers, or nu merical expressions enclosed in parentheses. The general form is write (expression 1, expression 2,... , expression n) or writeln (expression 1, expression 2,... , expression n) 36 WRITING YOUR FIRST PROGRAMS A syntax diagram for write (applicable also for writeln) is write ) expression —«r— An exception to this is that writeln; is a complete statement; it causes a blank line to be printed. The write statement causes subsequent output to be on the same line; writeln causes the next output to be on the next line. This is because writeln is actually a write statement followed by a line feed. To illustrate, write ('This is a test.'); writeln ('How many lines are printed?'); causes the output This is a test.How many lines are printed? whereas, writeln ('This is a test.'); writeln ('How many lines are printed?'); causes the output This is a test. How many lines are printed? Note: 1. Some printers reserve the first column for carriage control. Thus, the first character in a string on the left side of a page would not be printed. 2. Some implementations use a buffer to gather output from write statements and then print the gathered line when a writeln is encountered. You should check with your instructor concerning these features. As indicated, character strings can be printed by enclosing the string in single quotation marks within the parentheses. Numerical data can be printed by including the desired number or numbers within the paren theses. Thus, writeln (!□□) produces IDD and writeln (!□□/ fl ?, 95) produces fl ? 95 The spaces at the beginning of a line and between numbers are caused Pf] by a default field width. Many implementations of Pascal use a predeter mined field width for output. This predetermined default width will be 2.3 Data Types and Output 37 used unless output is controlled by the programmer. Methods for con trolling field width of output will be examined shortly. EXAMPLE 2.1 Write a complete Pascal program to print the address 1403 South Drive Apartment SB Pittsburgh, PA 15238 A complete program to print this is PROGRAM Address (output); BEGIN writeln ('1403 South Drive'); writeln ('Apartment 3B'); writeln ('Pittsburgh, PA', 15230) END. When this program is run on a computer, you may get 1403 South Drive Apartment 3B Pittsburgh, PA 15230 You can also use writeln to produce blank lines in output. When writeln is used without a following expression, it causes the printer (or cursor in your monitor)to advance to the beginning of the next line. This technique is frequently used to produce more readable output. STYLE TIP Dsingrwxi at the beginningiand eiid of the exeicUtab^^^^^th>n wilLsep- arate desired output from other messages or directions. TliliSi the previous program for printing an address could have been PROGRAM Address (output); BEGIN writeln; writeln; writeln (M4D3 South DrlvO')! writeln ('Apartment 3B'); Writeln ('iEittsburgh,> PA',. 15238);writeln; writeln END. EXAMPLE 2.2 Let's now combine various methods of using writeln to write a complete Pascal program that may produce the following output: COMPUTER SCIENCE 150 TEST SCORES: IGG qa q3 aq a2 7b 73 38 WRITING YOUR FIRST PROGRAMS The program would be PROGRAM PrintScores (output); BEGIN writeln; wrlteln; writeln ('COMPUTER SCIENCE ISD'); writeln (• •); writeln; writeln ('TEST SCORES:'); writeln (!□□, Rfl, =13); writeln (6=1/ 62/ 7t); writeln (73/ ); writeln; writeln END. B When designing a program to solve a problem, you should constantly be aware of how the output should appear. The spacing of output on a line can be controlled by formatting expressions in write emd writeln statements. Formatting Integers If the programmer does not control the output, each integer will be printed in a predetermined field width (unless the integer exceeds the field width). This is referred to as a default field width. This width depends on the machine and version of Pascal being used. In this text, we will assume a width of ten spaces. Negative signs occupy one position in the field and plus signs are not printed. Spacing of output on a page will frequently be denoted by an underscore for each blank space. Some writeln statements and their output with a default field width of ten follow. Program Statement writeln writeln writeln writeln (153); (+5ab5); (-15); (□); Output 153 5Db5 -15 0 A complete Pascal program to illustrate the field width for these integers is PROGRAM Printlnteger (output); BEGIN writeln; writeln writeln writeln writeln writeln; writeln; (153); (+5Db5); (-12); (□); writeln END. Controlling output is referred to as formatting. It is relatively easy to format output for integers. Using a writeln statement, the desired field width is designated by placing a colon ":** after the integer and then an integer specifying the field width. The integer printed will be right justified in the specified field. The general form for formatting integers is 2.3 Data Types and Output 39 writeln (integer:^); Some illustrations for formatting integer output are Program Statement (123:b); (15, 10:5); writeln (-2t3:7, 21:3); writeln (+50b2:fc); writeln (b5221:3); Output writeln 123 writeln 15 ID -2b3_21 5Gb2 b5221 Note that, in line five, an attempt is made to specify a field width smaller than the number of digits contained in the integer. Most versions of Pascal will automatically print the entire integer; however, some versions will print only in the specified width. The following program will enable you to find out exactly what yoiu- machine will do. PROGRAM FieldWidth (output); BEGIN writeln; writeln; writeln ('This program will check field width'); writeln (• writeln; writeln (123:5, 123 > writeln ( 'Please enter hours worked and hourly rate.'); writeln ( 'Press when finished.'); readln (NumHours/ i HourlyRate); Compute gross pay > GrossPay := NumHours ♦ HourlyRate; ■{ Compute deductions > PICA := GrossPay * PICARate; PederalTax := GrossPay ♦ PedTaxRate; StateTax := GrossPay * StateTaxRate; TotalDeduc ■{ := OnionDues + PICA + PederalTax + StateTax; Compute net pay > NetPay := GrossPay - TotalDeduc; '$' :2a, NetPay:fl:2); > 1 4.1 Writing Code 95 Output from this program is Please enter hours worked and hourly rate. Press AO when finished. IS.75 Tite Packing Company Employee name: Frederick Adamson Hours worked: AD Hourly wage: 15.75 510.□□ Gross pay: Deductions: Union dues b.5D FICA 55.5D Federal tax State tax fi t.70 51.53 Total deductions KD.tB Net pay Exercises 4.1 $ 3b5.37 l. Assume that each of the following are lines of pseudocode. Write Pascal statements for each. a. Add the scores from Testl, Test2, Tests, and Test4 b. Let Average = Total divided by 4 c. Let Totallncome = Salary plus Tips d. Let Time = Distance divided by Rate e. Let Grade = TotalPoints divided by 6 f. Write out your name, TotalPoints, and Grade g. Write out NumberAttending, TicketPrice, and TotalReceipts 2. Assume the output for a program to compute parking lot fees is to contain a. Vehicle type (car or truck) b. Time in d. Total time e. Parking fee c. Time out Use writeln statements to produce a suitable heading for this output. 3. Given the following algorithm in pseudocode form, write a complete pro gram that will compute the volume of a box. 1. 2. Assign dimensions Compute volume 3. Print results 3.1 dimensions 3.2 volume 4. List four uses for program comments. 5. Discuss variations in program writing styles for each of the following: a. Using blank lines. b. Using program comments. c. Writing variable dictionaries. 96 DESIGNING AND WRITING COMPLETE PROGRAMS 6. Use program comments to create a program description section that might be used to solve the problem of computing semester grades for a class. 7. Which of the following are valid forms for program comments? a. •C message here } message here *) *> *) b. (* (* c. (* (* message here * message here *) message here ♦ ♦ * ♦ * * (* (* (* (* * message here *) *) * * * message here * * *) ♦) *) *) *} i* message here \^ {* S 4.2 Procedures for Output OBTECTIVES IB to understand the idea of a subprogram B to be aware of some uses for procedures a to be aware of dif ferences in procedures □ to understand the form for a procedure B to be able to use a *} »} I This section is a slight departure from most other presentations of material for a Pascal course. Some texts discuss the complete use of subprograms relatively late in the text because using subprograms is somewhat ad vanced. Disadvantages of such placement include: (1) a major concept must be assimilated and used in a short period of time; and (2) some early problems that could be readily solved using subprograms use different solutions instead. In an attempt to avoid these disadvantages, some texts include material on subprograms very early in the sequence of topics. This, however, presents some new problems since a complete presentation involves sophisticated use of variables and can be a stumbling block for some students. We will avoid some of the problems in early and late introductions to subprograms by examining a limited use of them in this chapter to help make you comfortable with the basic ideas of their design and use. In Chapter 7 we will expand our understanding of subprograms with a com plete discussion of their uses in problem solving and program design. procedure in a program Concept of a Subprogram The idea of a subprogram is not difficult to understand. It is a program within a program and is provided by most programming languages. Each 4.2 Procediires for Output 97 subprogram should perform some task; the nature of that task can range from simple to complex. You could have a subprogram that prints only a line of data, or you could write an entire program as a subprogram. The main idea is that a subprogram is used to perform some task. At present, we will use them only for relatively small tasks. Pascal provides for two kinds of subprograms: functions and proce dures. You already used some built-in functions in Chapter 3 and in Chapter 7 you will learn how to write your own functions. Therefore,for now, we will discuss a limited use of procedures. Uses for Procedures A procedure can be used as a subprogram in a variety of ways. Two significant uses are to facilitate the top-down design philosophy of prob lem solving and to avoid having to write repeated segments of code. Procedures facilitate problem solving. For instance, if the pseudocode solution to a problem is 1. Get the data 2. Process the data 3. Print the results a procedure can be written for each of these tasks and the program can then call each procedure as needed. The idea of using a procedure to implement a line of pseudocode is very important and, as you develop more programming skills, will become an integral part of how you write a program. The second use of procedures is for the repeated use of several lines of code throughout a program. A procedure can be written using those several lines of code, and whenever that task is needed, a single call to the procedure suffices. We will see examples of this type of procedure later in this section. Kinds of Procedures Generally, procedures can be categorized into two types: those that use parameters and those that do not. There are several variations of proce dures that use parameters, and we will discuss them in Chapter 7. At this point, we will examine only procedures that do not use parameters. This is a very restricted use of procedures, for our procedures will not use variables or variable values. But you will at least be familiar with pro cedures before the presentation in Chapter 7. Form for a Procedure Let's now see how a procedure is written. Basically, a procedure is a program and, as such, it has the same divisions as a complete program. Procedure heading [] Declaration section —> (optional) Executable section L —> 98 DESIGNING AND WRITING COMPLETE PROGRAMS The procedure heading must contain the reserved word PROCEDURE followed by the procedme neune, which can be any valid identifier. Since no parameters are used at this point, the form for a procedure heading is PROCEDURE procedure name; It is important to develop the habit of using descriptive names for procedures. For example, if you are going to write a procedure to print a heading for the output, PrintHeader might be a good choice. This allows you to recognize the task the procedure is supposed to accomplish and makes the program more readable. Each of the following would be a reasonable, descriptive procedure heading. PROCEDURE PrintHeader; PROCEDURE GetData; PROCEDURE CoraputeTax; TotalPoints; PROCEDURE PrintScores; PROCEDURE PROCEDURE PrintCourselnfo: The declaration section of a procedure is identical to the declaration section of a program containing CONST and VAR subsections. The executable section of a procedure resembles the executable section of a program in that it must start with the reserved word BEGIN, but it differs in a significant way: the END of a procedure is followed by a semicolon instead of a period. Thus, a procedure will have the following basic form: PROCEDURE procedure name; CONST (list of constants) VRR (list of variables) BEGIN (body of procedure) END; The syntax diagram for this is declaration part body Constemts and variables declared in a procedure can only be used within that procedure and cue said to be local to that procedure (see Chapter 7). Let's look at one quick procedure before our next example. What will the following procedure do? PROCEDURE Skip3; BEGIN writeln; writeln; writeln END; The procedure skips three lines in the output. / 4.2 Procedures for Output EXAMPLE 4.2; 99 Suppose you are writing a program for Our Lady of Mercy Hospital. The program is to print a billing statement for each patient as the patient leaves the hospital. Let's write a procedure that prints a heading for each statement as follows: //////////////////////////////////////// / / Our Lady of Mercy Hospital / / 13Db Central City / Phone ( PROCEDURE StatementHeading; CONST Marks = Edge = Skip = •/////////////////////////////////////////' ; •/ ' • ; / ' ; BEGIN writeln; writeln; writeln (Skip:lD/ Marks); writeln (Skip:10/ Edge); writeln (SkiprlD/ '/'/ Skip:?, 'Our Lady of Mercy Hospital', Skip:L, '/'); writeln {Skip:lD, '/', Skip:?, ' ', Skip:t, '/•); writeln (Skip:lD, Edge); writeln (Skip:lD, '/', Skip:ll, '13Db Central City', Skip:ll, '/' ); writeln (Skip:lD, '/', Skip:lD, 'Phone (41t) 333-5555', Skip:q, '/' ); writeln (Skip:lD, Edge); writeln (Skip:lD, Marks); writeln; END; { writeln of PROCEDURE StatementHeading } Placement in a Program Procedures are placed in the declaration section after the variable dec laration subsection in a program. Thus, a full program with a procedure would have the following form: PROGRAM program name (output); CONST VAR PROCEDURE procedure name; CONST VAR BEGIN { PROCEDURE } (body of procedure) END; •{ Now start the main program BEGIN f Main program > > (body of main program) END. •{ of main program > Calling a Procedure Now that you know how to write a procedure and where it belongs in a program, you need to know how to call the procedure from the main program. Since no parameters will be used in procedures at this point, a procedure name as a statement in the main program will cause the pro cedure to be executed by the computer. For example, if PrintHeader is the name of a procedure. 4.2 Procedures for Output BEGIN { Main program 101 > PrintHeader; (remainder of program) END. { of main program > will cause the procedure PrintHeader to be executed first in the main program. When a procedure name is encountered as a program statement, control of execution is transferred to the propedure. At that time, the procedure is run as a separate program and wljen the procedure is complete, control returns to the next statement in ^e main program following the call to the procedure. The following short program to call a procedure illustrates this control. PROGRAM FirstProcedure (output); ■{ **********************************♦*********************♦*♦****> PROCEDURE PrintMessage; BEGIN writeln ('This is written from the procedure. END; f of PROCEDURE PrintMessage ^3) > {♦*****************»***********♦♦*******************************> BEGIN -{ Main program writeln; > writeln; writeln ('This is written from the main program. ':^t); writeln; PrintMessage; writeln; END. •{ writeln of main program > The output from this program is This is written from the main program. This is written from the procedure. EXAl^PLE 4i3 As another example, let's construct a short program that calls a procedure several times and have the procedure print the message This is written by a procedure. Now return to the main program. Furthermore, let us have the main program print a message that includes a count of how often the procedure is called. A pseudocode design could be 1. Initialize counter 2. 3. Print message Call procedure 4. Increment counter 5. 6. Print message Call procedure 7. Increment counter 8. Print message 9. Call procedure 102 DESIGNING AND WRITING COMPLETE PROGRAMS The program for this design is PROGRAM ProcedurePractice (output); i This program illustrates multiple calls to a procedure > CONST Indent = • '; VAR Count : integer; PROCEDURE PrintHessage; ■{ is called. > BEGIN writeln; writeln (IndentrSO, writeln (Indent:5Dr 'This is written by a procedure. '); 'Now return to the main program. '); writeln END; i { of PROCEDURE PrintMessage Now Start the main program BEGIN > > ;= 1; writeln (IndentrlD, writeln (IndentrlD, 'This is written from the main program. '); 'It is call #', CountrR, ' to the procedure. '); PrintMessage; Count := Count + 1; writeln (IndentclD/ writeln (Indent:10, 'This is written from the main program.'); 'It is call #'/ Count:3, ' to the procedure. '); PrintMessage; Count := Count + 1; writeln (Indent:lD, writeln (Indent:10, 'This is written from the main program. '); 'It is call #', Count:3, ' to the procedure.'); PrintMessage END. i of main program > The output from this program is This is written from the main program. It is call # 1 to the procedure. This is written by a procedure. Now return to the main program. This is written from the main program. It is call # S to the procedure. This is written by a procedure. Now return to the main program. 4.2 Procedures for Output 103 This is written from the main program. It is call # 3 to the procedure. This is written by a procedure, Now return to the main program, STYLE TIP If a constant is going to be used in several procedures, it could be declared in the constant definition section of the mam program and then used by each subprogram. For example, CONST Indent = • •; Multiple Procedures You should now be able to write a procedure with no parameters, know where it belongs in a program, and be able to call it from the main body of the program. The next step is to use more than one procedure in a program. Each procedure is developed separately and listed sequentially after the variable declaration subsection of the main program. Thus, the basic program with multiple procedures appears as follows: PROGRAM program name (output); CONST VAR PROCEDURE procedure name 1; PROCEDURE procedure name 5; PROCEDURE procedure name n; BEGIN END These procedures can be called in any order and as often as needed. Just remember that when a procedure is called from the main program, control is transferred to the procedure, the procedure is executed, and control then returns to the next program statement. The following program illustrates the use of multiple procedures. PROGRAM MultipleProcedures (output); CONST Indent = • '; 104 DESIGNING AND WRITING COMPLETE PROGRAMS •{***♦******♦*♦♦********♦******♦*********♦♦♦****»**♦»»»****♦*♦***> PROCEDURE Hessagel; BEGIN writeln; writeln (IndentilD, 'This is from Procedure #1' ) END; PROCEDURE Messaged; i This is procedure two > BEGIN writeln; writeln (IndentclD, END; i 'This is from Procedure #2') of PROCEDURE MessageE > •(**♦************************♦♦************»********************* PROCEDURE Messages; { This is procedure three > BEGIN writeln; writeln (IndentrlD, END; Messagel; Messages; Messages; MessageE; Messagel; writeln; writeln END. > } The output from this program is This is from Procedure #1 This is from Procedure #E This is from Procedure #S This is from Procedure #E This is from Procedure #1 Examples of Using Procedures for Output We close this section with some examples using procedures to produce output. By learning how to write and use procedures in this very limited 4.2 Procedures for Output 105 fashion, you should be better able to work with them when they become more complicated. EXAMPLE 4.4 Your computer science instructor wants course and program information included as part of the output of a program. Consequently, you are to write a procedure that can be used to print this information. Sample output is * * * Author: Mary Smith * * Course: CPS-ISO * * Assignment: * Due Date: Program #3 September Ifi 4c * Instructor: Mr. Samson 4c 4c * 4c The procedure to do this is PROCEDURE Printlnfo; CONST Indent = • '; BEGIN (Indent:3Df (Indent:3D/ writeln (Indent:B0, writeln (Indent:3D/ writeln (Indent:BOf writenl (Indent:BO/ writeln (Indent:30/ writeln (Indent:3D/ writeln (IndentiBO/ writeln writeln END; t ) *I) •* I :4c Author: Course: Assignment: Due Date: Instructor: •* I* t* I♦ Mary Smith CPS-ISD Program #3 September Ifl Mr. Samson *•) *•) »•) *') *') *I) I* Of PROCEDURE Printlnfo EXAMPLE 4*5 As part of a program that computes and prints grades for each student in your class, you have been asked to write a procedure that produces a heading for each student report. Assuming the columns in which the various headings should be are as follows: m the border for the class name starts in column 30 m Student Name starts in column 20 □ Test Average starts in column 40 B Grade starts in column 55 the heading should appear as :«c:4c:|c:|e:4ei4c:tc:K:(c:|c:|c4c*:4c:|(:4c:|c:|c3|c:|c:|c:|(4c4c:tc * * * CPS ISO Pascal * * * :tc:((:|c)|c:|c:tc:(c:4c:tc:(c:tc4c4e:4c:4c:|c:(c:|e:tc:|e:|c3|c:tc:te4e Student Name Test Average Grade A descriptive name for this procedure could be PrintHeader. With this information, the procedure could be written as follows: 106 DESIGNING AND WRITING COMPLETE PROGRAMS PROCEDURE PrintHeader; CONST Skip = ''; BEGIN writeln; writeln; wrlteln writeln writeln writeln writeln (Skip:2'^r (Skip:21/ (Skip:21/ (Skip:21/ (Skip:21/ i*************************• '* *' '* CPS ISO Pascal *' '* *' •********************#****• writeln; write (Skip:11/ 'Student Name'); writeln (Skip:fl/ 'Test Average'/ Skip:3/ 'Grade'); write (Skip:11/ ' writeln (Skip:fl/ ' '); '/ Skip:3/ ' '); writeln; writeln END; EXAMPLE 4.6 H The Greater Metro Airport has hired you to write a program that will print a ticket for each parking lot customer. The parking lot authorities want each ticket to contain a suitable message and the amount to be paid upon leaving the parking lot. A pseudocode design for this problem is 1. For each customer 1.1 assign amount due 1.2 print heading 1.3 print amount due 1.4 print closing message We will write procedures for steps 1.2 and 1.4 of this design. Each ticket will have the following heading. Greater Metro Airport Parking Lot April 15 Each ticket will contain the following message concerning the charge for parking: Your charge is SXX.XX Each ticket will contain the following closing message. Thank you for using the Greater Metro Airport Please drive carefully A procedure to print the heading is PROCEDURE PrintHeader; •I This procedure prints a ticket heading > CONST Date = 'April 15'; BEGIN writeln; writeln (Indent:20/ 'Greater Metro Airport'); writeln; writeln (Indent:25/ 'Parking Lot'); writeln (Indent:27/ Date); writeln END; { of PROCEDURE PrintHeader > 4.2 Procedures for Output 107 A procedure to print the closing message is PROCEDURE PrlntMessage; { This procedure prints a closing message > BEGIN writeln; writeln (Indent:EDr 'Thank you for using the'); writeln (Indent:El/ 'Greater Metro Airport'); writeln; writeln (Indent:ED/ 'Please drive carefully'); writeln (IndentrlS, ' 1 ); writeln; writeln END; { of PROCEDURE PrintMessage > A complete interactive program that can be used for two customers follows. This can be modified later to accommodate several customers. PROGRAM ParkingLot (input, output); CONST Indent = ' '; VAR Fee : real; PROCEDURE PrintHeader; f This procedure prints a ticket heading > CONST Date = 'April 15'; BEGIN writeln; writeln (Indent:ED/ 'Greater Metro Airport'); writeln; writeln (Indent:E5/ 'Parking Lot'); writeln (Indent:E7, Date); writeln END; PROCEDURE PrintMessage; and its output. ************************* * » * * Federal Savings Monthly Report * * * * ************************* Thank you for banking with Federal Savings. Your current interest payment is below. $ IK.53 Thank you for banking with Federal Savings. Your current interest payment is below. $ 67.53 Rewrite this program using a. a procedure for the heading. b. a procedure for the customer message. 8. What is the output from the following program? PROGRAM ExerciseEight (output); CONST Skip = ' '; PROCEDURE Numberl; BEGIN writeln (Skip:lG/ 'She loves me.'); END; i of PROCEDURE Numberl > ' 4.3 Beginners' Errors 111 PROCEDURE NumberE; BEGIN writeln (SkipilD, 'She loves me not.'); END; •( of PROCEDURE NumberE ■{ BEGIN Main program > } Numberl; NumberE; Numberl; NumberE; Numberl END. •( of main program > 9. Rewrite the following program using indenting, blank lines, comments, and comment sections to enhance readability. PROGRAM Plain (output); VAR Scorel/ ScoreE : Average : real; integer; PROCEDURE PrintHeader; BEGIN writeln; writeln; writeln ('Your test results are below. 'cBt); writeln; writeln ('Keep up the good work! ':3D); writeln; END; writeln BEGIN PrintHeader; Scorel := AH; ScoreE := R5; Average := (Scorel + ScoreE) / E.D; writeln ( 'Scorel' :ED/ Scorelrt); writeln ('ScoreE' :ED, ScoreE:t); writeln; writeln ( 'Your average is':E3, Average:a:E) END. M 4.3 Beginners' Errors QBTECTIVES Q to be aware of tjrpical errors caused by incorrect syntax ° to be aware of errors made in the declara tion section of a program ° to be aware of typi cal errors made when using assign ment statements D to be aware of typi cal errors made when using writeln to produce output What you learn in this chapter will help you avoid problems when first working with Pascal. You are now aware of the significance of carefully designing an algorithm to solve a problem before you attempt to write a program. Also, you are now able to write code to implement a simple algorithm via a P&scal program. Therefore, to help you avoid frustration, we will examine some typical errors made when writing code. In an ideal situation, you would submit your program to the computer and it would run with no errors and produce exactly what you desire for output on the first attempt. Since this probably will not happen, you need to be aware of the kinds of errors that can occur. These fall into three general categories: compilation errors, run-time errors, and design errors. Compilation errors are errors detected when the program is being com piled. These include syntax errors, which are errors in spelling, pimctuation, or placement of certain key symbols in a program. Run-time errors are errors that are detected during execution of the program. Design errors are errors that occur in the design of the algorithm or in coding the program that implements the algorithm. These are also referred to as logic errors. 112 DESIGNING AND WRITING COMPLETE PROGRAMS Syntax In Section 2.2, it was stated that syntax refers to the rules governing construction of valid statements. This includes spelling, punctuation,and placement of certain key symbols. Errors made by improper use of syntax are usually easy to identify and correct. First, let's examine uses of the semicolon. This is the fundamental punctuation mark in Pascal: it is used to separate statements. It first ap pears after the program heading statement and then between complete statements throughout the program. It may appear that semicolons are used at the end of each line. This is not true.In particular,certain keywords appear on a line but are not complete statements. Also, semicolons are not required between a statement and END. To see how semicolons are needed,consider the example given in Table 4.1. The program to the left in this table has no semicolons; the one on TABLE 4.1 semicolons Correct Program Incorrect Program Illustration of using PROGRAM CheckSemi (output) 1. PROGRAM CheckSemi (output); VAR VAR A, B : real A/ B : real; 2. BEGIN BEGIN A := 3.D 3. B := 5 * A 4. A := 3.D; B := S * A; writeln (A:5:5/ B:5:a) writeln (A:S:E/ B:5:5) END. END. the right has the minimum number of semicolons required to make the program run: four. These are explained as follows: 1. A semicolon must appear after the program heading. PROGRAM CheckSemi (output); 2. A semicolon must appear after each declaration list in the vari able declaration section. A, B : real; 3. and 4. A semicolon must appear between complete statements in the executable portion of the program. A := 3.D; B := E * A; Two comments are in order. First, since Pascal ignores extra blanks and line boundaries, the semicolons do not have to be written directly after the statements. Second, as we've seen before, the semicolon at the end of the last statement preceding the reserved word END is unnecessary. A second syntax error results from using the symbol for equality"=" instead of the symbol for an assignment statement This is com pounded by the fact that several programming languages use the equal sign to assign values to variables, and the equal sign is used to define values in the CONST section. A third type of syntax error occurs when writing program comments. Most of these occur when a comment begins with and ends with 4.3 Beginners' Errors 113 As comments get longer and you attempt to produce attractive read able programs, you may produce some of the following errors. 1. Improper beginning (instead of (* or { 2. Improper ending )instead of *) or } * instead of $) instead of«) 3. Extra blanks (* comment * )instead of (* comment ♦) 4. No close for a long comment(no ending parenthesis or brace) * * * * This is a long comment with improper closing punctuation. * * * * A fourth type of syntax error results from omitting the period after END at the end of the executable portion of the program. This error will be detected by the compiler. A fifth type of error that some computer progreunmers consider a S5mtax error is misspelling keywords. Table 4.2 sets forth a program with seven TABLE 4.2 Incorrect Spelling Spelling keywords and identifiers PR06RH Spelling (output); VR Correct Spelling PROGRAM VAR Wage : reale; real Inital : chr; char Sere : interger; integer BE6N BEGIN Wage := 5.0; Inital := 'D'; Sere := 75; writln (Wage:lD:5/ Inital:3, Scre:5) writeln END. misspelled keywords. You may think the identifiers Inital and Sere are also misspelled keywords. But remember: they are not kejrwords and can be used as spelled in the program. It is not good practice to use identifiers like this, however, since you could easily spell them differently through out the program and they would not be recognized as variables by the compiler. Declarations Errors sometimes made when defining constants in the CONST section include: 114 DESIGNING AND WRITING COMPLETE PROGRAMS 1. Using an assignment statement rather than an equal sign Incorrect Correct CONST CONST MaxScore = IDD; MaxScore := 2. Omitting single quotation marks from string constants Incorrect Correct CONST CONST Name = Mary Smith; Name = 'Mary Smith'; Letter = Z; Letter = 'Z'; 3. Using single quotation marks around numerical constants Incorrect Correct CONST CONST MaxScore = •!□□' ; MaxScore = !□□; The declaration MaxScore = '!□□' ; will not result in an error during compilation. Technically, it is not an error. However, this declaration makes MaxScore a string rather than the integer constant 100. Consequently, you could not assign MaxScore to an integer variable or use it in arithmetic computations. More errors are usually made in the variable declaration section than in the constant definition section. Several illustrations of incorrect vari able declarations and the corrected versions are shown in Table 4.3. TABLE 4.3 Correct Incorrect Errors in declaration sections VftR VftR ft ; B; C : ft , real C : real; VftR VftR ft ge B, ; integer; ft ge integer; VftR VftR Initial = char; Initial VftR : char; VftR Wage : real; Wage : real; Score, Score Hours : : Hours integer; : integer; Assignment Statements In Section 3.2 you learned to assign a value to a variable with a statement such as Score := fl ?; Some common mistakes in assignment statements are 1. Trying to put more than one variable on the left of an assignment statement Incorrect Correct X + Y ft + 3 Z B := Z; := B; := X + Y; := ft + 3; 4.3 Beginners' Errors 115 2. Trying to make an assignment from left to right Incorrect Correct 57 := Score; Score := fl?; 3. Trying to assign the value of one identifier (A) to another identi fier (B)from left to right Incorrect Correct A := B; B := A; (This statement will not be detected as an error during compila tion; thus, your program will run, but you will probably get incor rect results.) 4. Attempting to assign a value of one data type to a variable of an other data type. If, for example. Score had been declared as an in teger variable, each of the following would produce an error. a. Score := 77.3; b. Score := 15D / 3; c. A 1= Ifl.tj; Score := A; There is an exception to this rule. The value of an integer data type can be assigned to a variable of type real. For example, if Av erage is a real, Average := 43; is a valid assignment statement. However, 43 is then stored as the real 43.0 rather than the integer 43. 5. Attempting to use undeclared variables and constants. This error often results from listing the variables used in the program in the variable declarations section after the program has been written, and inadvertently omitting some variable from the list. During the compilation, you will get an error message something like "Identi fier not declared" when the variable first appears in a line of code. This is easily corrected by adding the variable to the VAR section. This same error results from misspelling identifiers. For exam ple, if the VAR section has VAR Initial : char; and you use the statement Inital := 'D'; in the executable section, you will get an error message. The error message will be the same as that for an undeclared identifier be cause the compiler did not find Inital in its list of previously de clared identifiers. Misspellings are not obvious and are difficult to detect. This is another reason for using descriptive identifiers; they are common words and you are less likely to misspell them. This is one of the advantages of Pascal as a programming lan guage. Since you cannot use variables unless you declare them, misspelled variables are detected at compilation time. In some other languages (BASIC, for example), if you misspell a variable, create one unintentionally, or initialize one to zero, for example, the problem may not be discovered until after a sample run has been made. 116 DESIGNING AND WRITING COMPLETE PROGRAMS Using writeln The last general category of errors concerns statements used to create output. Section 2.3 discussed the use of writeln for creating a line of output. We have subsequently used this as part of executable statements in several examples.In an attempt to help you avoid making certain errors, we will examine common incorrect uses of writeln. 1. Format errors. When using format control with writeln statements, three errors are typical. a. Attempting to format an integer as a real Incorrect writeln (Score:5D:2); Correct writeln (ScoreiaO); b. Attempting to use a noninteger as a format control number Incorrect writeln (Average:SO:2.0); Correct writeln (Average:SO:S); (where Average is a real variable). c. Attempting to format a real as an integer. This will not cause a compilation error; your program will run, but you will get un expected output. For example, suppose Average is a real vari able whose value is 83.42 and you want a line of output to be The average score is: 63.42 If you use the statement writeln ('The average score is:':3D» AveragerlO); the output is The average score is: fl.3E+001 Floating-point form is used for the real but the total field width is controlled by the use of ":10". This statement should be written writeln ('The average score is:':3D, Average:ID:2); 2. Inappropriate use of quotation marks. Errors of this type result from omitting needed single quotation marks or putting quotation marks where they are not needed. Remember that character strings must be enclosed in single quotation marks. For example, assume you want the output Hello. Incorrect Correct writeln (Hello:20); writeln ('Hello':2D); A more subtle problem arises when constants and variables have been declared in the CONST and VAR declaration sections. To il lustrate, assume these sections are as follows: CONST Name = 'Mary Smith'; Age = Ifl; VAR A : integer; and consider the following program fragments. 4.3 Beginners' Errors 117 a. writeln ('My name is'iED/ NamerlS); This is correct and produces My name is Mary Smith b. writeln ('My name is':5D/ 'Name'rlS); This format is also correct but produces My name is Name This program runs, but you get incorrect output. c. writeln ('My age is':50, Age:); executed on a machine using a default field width of ten columns produces true false true_false Although Boolean variables and constants can be assigned and used in output statements, they cannot be used in input statements in standard Pascal. Thus, if Flag is a Boolean variable, a statement such as read (Flag); produces an error. Instead, one would typically read some value and then use this value to assign an appropriate Boolean value to a Boolean variable. This technique will be illustrated later. The Standard Identifiers eoln and eof as Functions Section 3.3 introduced the concepts of end-of-line and end-of-file. These were presented as markers that were put in a stream input to separate lines and designate the end of a data file. Both eoln and eof are built-in Boolean functions that are used to indicate when the pointer is positioned at one of these markers. If the data pointer is positioned at an end-of-line marker, then eoln is true; otherwise, eoln is false. Similarly, if the pointer is positioned at the end-of-file marker, eof is true; otherwise, eof is false. An exception to the eoln value being false when the pointer is not at endof-line marker is when the pointer is at an end-of-file marker. In this case, eoln may have the value true. Since eoln and eofare built-in functions,they can be used in assignment statements. To illustrate, assume we have the data file Hl|22|l3 -48B T with the pointer positioned at the beginning of the file. Furthermore, assume the variable declcuration section of a program includes VAR A/ B : integer; Chi, ChS : char; EolnFlag, EofFlag : boolean; If no previous assignments have been made, we have A B Chi Ch2 EolnFlag EofFlag 148 CONDITIONAL STATEMENTS The assignments EolnFlag := eoln; EofFlag := eof; might be envisioned as false A B Chi Ch2 false EolnFlag EofFlag If the line of code read (Chi/ Ch5); is executed, the data pointer is Hl|22|l3 -48|■ and the assignment statements EolnFlag := eoln; EofFlag := eof; result in A B H I Chi Ch2 true false EolnFlag EofFlag If the next three lines of code are readln (A); EolnFlag := eoln; EofFlag := eof; this produces Hl|22|l3 -48|■ 22 H I Chi Ch2 false false EolnFlag EofFlag Then read (A/ B); EolnFlag := eoln; EofFlag := eof; produces Hl|22|l3 -48| 13 -48 H I A B Chi Ch2 And finally read (Chi); EolnFlag := eoln; EofFlag := eof; produces true false EolnFlag EofFlag 5.1 Boolean Expressions 149 Hl|22|l3 -48|■ 13 -48 b I B Chi Ch2 true true EolnFlag EofFlag Both eoln and eof can also be used in output statements. For example, writeln (eoln, eof); write (eoln:t, eof:b); are appropriate statements. The following example illustrates the use of eoln and eof in output statements and how their values change according to the data pointer for a stream input.(This example assumes input from a data file; interactive input would produce a different result.) Let's write a short program that allows us to examine a line of data and the respective values of eoln and eof. Suppose the data file is EXAMPLE ab|i2|b and you want to produce a chart that indicates the values after each character is read. The chart heading should include the character read, eoln value, and eof value. The code needed to produce one line of the chart is read (Ch); writeln (Ch:15/ eoln:5D, eof:50); Since we can read four characters and two end-of-line markers from this data file, this segment of code needs to be executed six times. An attempt to read (Ch) seven times would produce an error since you would be trying to read past the end-of-file marker. The complete program for this example follows. PROGRAM ReadCheck (input, output); CONST Indent = ' '; VAR Ch : char; PROCEDURE PrintHeading; { This procedure prints a heading for the output > BEGIN writeln; writeln; writeln (IndentrlD, 'Character read', 'eoln value':17, 'eof value':1R); writeln (IndentrlD, ' ', ' ':!?, ' ':1'=1); writeln END; 150 CONDITIONAL STATEMENTS BEGIN read (Ch); writeln (Indent:15/ Ch, read (Ch); writeln (Indent:15, Ch, read (Ch); writeln (Indent:15, Ch, read (Ch); writeln (Indent:15, Ch, read (Ch); writeln (Indent:15, Ch, read (Ch); writeln (Indent:15, Ch, writeln; writeln END. i of main program eoln:55, eof:2D) eolnrBE, eof:ED) eolniEE, eof:ED) eoln:EE, eof:ED) eoln:SE, eof:SO) eoln:EE, eof:ED) > The output from this program is Character read eoln value eof value false false true false false false false false true false true true Relational Operators and Simple Boolean Expressions In arithmetic, integers and reals can be compared using equalities(=)and inequalities(,5^, and so on). Pascal also provides for the comparison of numbers or values of variables. The operators used for comparison are called relational operators and there are six of them. Their arithmetic notation, Pascal notation, and meaning are given in Table 5.1. TABLE 5.1 Relational operators Arithmetic Relational Operation Operator = = Is equal to > first. } CONST Skip = • • ; VAR Numl, NumE, > Temp : integer; ■{ Temporary variable } PROCEDDRE PrintHeading; { This procedure prints a heading } BEGIN writeln; writeln; writeln ( 'Larger number'. Skip:ID, 'Smaller number'); writeln ' ( ' ', Skip:ID, ^—' ); writeln END; } write ('Enter two integers and press . readln (Numl, NumE); ' ); PrintHeading; IF Numl A sample run of this program produces Enter two integers and press . Larger number 3G Ifl 30 Smaller number Id I 162 CONDITIONAL STATEMENTS Exercises 5.2 1. What is the output from each of the following program fragments? Assume the following assignment statements precede each fragment: := ID; := 5; a. IF a e. IF (A □ '); THEN writeln;/writeln; writeln ('The number is':52, Num:t>); writeln; writeln ('The number squared is' :3D/ Num * Numrt); writeln ('The number cubed is' :2fl/ Num * Num * Num:t); writeln; writeln END. b. PROGRAM Exercisetib (input, output); VAR Num : integer; BEGIN write ( 'Enter an integer and press . readln (Num); IF Num > □ THEN BEGIN { writeln; writeln writeln; writeln writeln Start output > writeln; ( 'The number is' :52, Numrt); ( 'The number squared is' :3D, Num * Numife); ( 'The number cubed is' :2a, Num * Num * Num:k); writeln; writeln END > END. 7. Discuss writing style and readability of compound statements. 8. Find all errors in the following compound statements. a. BEGIN read (A) writeln END; b. , (A) BEGIN Sum := Sum + Num ' END; c. BEGIN read (Sizel, Size2); writeln (Sizel:a, Size2:a) END. d. '); BEGIN readln (Age, Weight); TotalAge := TotalAge + Age; TotalHeight := TotalHeight + Height; writeln (Age:a, Weight:a) 164 CONDITIONAL STATEMENTS 9. Write a single compound statement that will: a. Read three integers from a data file. b. Add them to a previous total. c. Print the numbers on one line. d. Skip a line (output). e. Print the new total. 10. Write a program fragment that reads three reals from a data file, counts the number of positive reals, and accumulates the sum of positive reals. 11. Write a program fragment that reads three characters from a data file and then prints them only if they have been read in alphabetical order (for ex ample, print "boy" but do not print "dog"). 12. Given two integers, A and B, A is a divisor of B if B MOO A = 0. Write a complete program that reads two positive integers A and B and then, if A is a divisor of B, a. Print A. b. Print B. c. Print the result of B divided by A. For example, the output could be A Is lA B is AE B divided by A is 3 ^ EH H 5.3 IF ... THEN ...ELSE Statements Form and Syntax The previous section discussed the one-way control statement IF . . . THEN. The second conditional control statement we will examine is the two- way control statement IF . .. THEN ... ELSE. Correct form and syntax for IF .. . THEN ... ELSE are OBJECTIVES D to learn the form and syntax required fot using an IF... THEN ... ELSE IF Boolean expression THEN statement ELSE statement; statement □ to understand the flow of control Flow of control when using an IF when using an IF follows: ... THEN ... ELSE statement a to be able to use an IF ... THEN ... ELSE statement in a program B to be able to design programs using IF ... THEN ... ELSE statements THEN ELSE statement is as 1. The Boolean expression is evaluated. 2. If the Boolean expression is true, the statement following THEN is executed and control is transferred to the first program statement following the complete IF .. . THEN . .. ELSE statement. 3. If the Boolean expression is false, the statement following ELSE is executed and control is transferred to the first program statement following the IF ... THEN . .. ELSE statement. A flow diagram is given in Figure 5.2. To illustrate this flow of control, let us consider the problem of printing the larger of two numbers using an IF . , . THEN . .. ELSE statement in the following code. 5.3 IF ... THEN ... ELSE Statements 165 FIGURE 5.2 IF ... THEN ... f ELSE flow diagram Prior ' st^lement 1r IF ELSE Boolean statement THEN statement Subsequent statement read (Numl/ NumE); IF Nural > NumE THEN writeln (Nural) ELSE writeln (NumE); writeln ('All done'); If the values read are 80 15 Numl Num2 the Boolean expression Numl > Num2 is true and the statement writeln (Nural) is executed to produce &□ Control is then transferred to the next program statement, writeln ('All done'); and the output is 60 All done However, if the values read are 10 75 Numl Num2 the Boolean expression Numl > Num2 is false, control is transferred to writeln (NuraE); and the output is 75 All done 166 CONDITIONAL STATEMENTS with the 75 printed from the ELSE option of the IF ... THEN ... ELSE statement. A few points to remember concerning IF...THEN...ELSE statements are: 1. The Boolean expression can be any valid expression having a value of true or false at the time it is evaluated. 2. The complete IF ...THEN ... ELSE statement is one program statement and is separated from other complete statements by a semicolon whenever appropriate. 3. There is no semicolon preceding the reserved word ELSE. A semi colon preceding the reserved word ELSE causes the compiler to treat the IF ... THEN portion as a complete program statement and the ELSE portion as a separate statement. This produces an error message indicating that ELSE is being used without an IF ... THEN. 4. Writing style should include indenting within the ELSE option in a manner consistent with indenting in the IF... THEN option. EXAMPLE 5,9 Let's write a program fragment to keep separate counts of the negative and non- negative numbers entered as data. Assuming all variables have been suitably de clared, an IF ... THEN ... ELSE statement could be used as follows: write ("Please enter a number and press . •); readln (Num); IF Num □ > Thus far, nested loops have been used only with FOR loops, but any of the loop structures may be used in nesting. Our next example illustrates a REPEAT ... UNTIL loop nested within a WHILE ... DO loop. Trace the flow of control and indicate the outputfor the following program fragment. R := ID; B := □; WHILE A > B DO BEGIN wrlteln (A:5); REPEAT wrlteln (A:5, B:5/ A := A - (A + B):5); 5 UNTIL A wrlteln ("All done' :SD); The assignment statements produce 10 and A > B is true; thus, the WHILE ... DO loop is entered. The first time through this loop the REPEAT ... UNTIL loop is used. Output for the first pass is 10 ID □ ID and the values for A and B are 8 0 A B The Boolean expression A 0 UNTIL loop is 8 and the values for A and B become A B At this point, A := B + S; 242 LOOPING STATEMENTS Thus, the variable values are and the Boolean expression A > B is true. This means the WHILE ... DO loop will be repeated. The output for the second time through this loop is L L S a The inner loop is exited and the values for the variables become 4 A B Now A > B is false and control is transferred to the line following the WHILE DO loop. Output for the complete fragment is ID ID ID a a L L All done U Example 6.24 is a bit contrived and tracing the flow of control somewhat tedious. However, it is important for you to be able to follow the logic involved in using nested loops. Our next example is much more standard. Be sure you understand it thoroughly, for you will need to be able to use it as part of subsequent programs. EJCAM^LE 6,25 Use nested loops to reproduce an unknown data file. The first-level pseudocode design for the solution to this problem could be 1. WHILE NOT eof DO reproduce a line of data A second-level development could be 1. WHILE NOT eof DO 1.1 set a left margin 1.2 reproduce a data line 1.3 advance the input data pointer 1.4 advance the output pointer Step 1.2 could then be refined to 1.2 reproduce a data line 1.2.1 WHILE NOT eoln DO 1.2.1.1 1.2.1.2 read a character write a character The complete algorithm for this fragment is now 1. WHILE NOT eof DO 1.1 set a left margin 1.2 reproduce a data line 1.2.1 1.3 1.4 WHILE NOT eoln DO 1.2.1.1 read a character 1.2.1.2 write a character advance the input data pointer advance the output pointer 6.5 Nested Loops 243 We can now write code for this algorithm as follows: ■( WHILE NOT eof DO Process one line > BEGIN write (' ' :!□); WHILE NOT eoln DO i Process one character > BEGIN read (Ch); write (Ch) END; readln; writeln END; If this program fragment is run using the data file BRL 268-36-0729 M 38|HBT 231-48-2136 F 18|LMN 133-24-0966 F 211 t the output is BRL Et.fl-3E.-D75R M 3fl HBT E31- □ DO BEGIN REPEAT UNTIL condition; statement END; { of WHILE.. .DO loop > statement END; i of FOR loop > If the body of a loop becomes very long, it is sometimes diffi cult to match the BEGINs with the proper ENDs. In this case, you should either redesign the program or be especially careful. 2. Using comments. Comments can precede a loop and explain what the loop will do, or they can be used with statements inside the loop 244 LOOPING STATEMENTS to explain what the statement does.They should be used to indicate the end of a loop where the loop body is a compound statement. 3. Skipping lines. This is an effective way of isolating loops within a program and making nested loops easier to identify. A note of caution is in order with respect to writing style. Program doc umentation is important; however,excessive use of comments and skipped lines can detractfrom readability. You should develop a happy medium. We close this section with two more examples of nested loops. The first one analyzes a program fragment with nested loops, and the second asks you to write a program to produce a certain output. Let's find the output produced by the following program fragment of nested loops. Assume A and B have been declared as integer variables and the data file is 4 7|■ The fragment read (A, B); REPEAT Num := A; •t Print one line WHILE Num > A := A + 1; writeln UNTIL A = B; 7.6 Forward Reference and Nesting 311 Figure 7.17 is a schematic representation of the constants, variables, and functions used in Example 7.7. FIGURE 7.17 PROGRAM Schematic for Example 7.7 RoomRate ^IhxRate AmountOue >'KutnNights ^FUNCHON IbtalCharge 1 Exercises 7.6 1. Explain why forward reference could be necessary in a program. 2. Write a test program to illustrate what happens when one subprogram calls another subprogram that is listed later and a forward reference is not made. 3. Discuss the scope of identifiers in nested subprograms. 4. Find emd correct all errors in each of the following program segments. a. FUNCTION AddOne (A : integer) : integer; BEGIN AddOne := A END; -C + 1 of FUNCTION AddOne > PROCEDURE AddTwo (VAR B : integer); BEGIN B := AddOne(B); B := AddOne(B) END; { of PROCEDURE AddTwo > b. PROCEDURE AddTwo (VAR B : integer); BEGIN B := AddOne(B); B := AddOne(B) END; FUNCTION AddOne (A : integer) : integer; BEGIN AddOne := A END; AddOne; > BEGIN AddOne := A END; Give a schematic representation and indicate the scope of identifiers for the following subprograms contained in PROGRAM ExerciseFive. PROGRAM ExerciseFive (input, output); VAR X, Y : real; Ch : char; PROCEDURE A (VAR XI : real; Chi : char); VAR J : integer; FUNCTION Inner (M : integer; Y1 : real) : real; BEGIN END; PROCEDURE B (XI : real; VAR Ch5 : char); BEGIN END; i PROCEDURE B Of PROCEDURE B > > 7.6 Forward Reference and Nesting 6. Consider the block structure shown in Figure 7.18 for PROGRAM ExerciseSix. a. Indicate which subprograms can be called from the main program. b. Indicate all appropriate calls from one subprogram to another subprogram. c. List three inappropriate calls and explain why they cannot be made. PROGRAM ExerciseSix FIGURE 7.18 PROCEDURE One ■■ PROCEDURE Four DNIGgae ii;'' •''^ r'k■} '■ •'• f.'i ° FUNCTION IWo 7. Consider the following program. PROGRAM ExerciseSeven (input, output); VAR A/ B, integer; Num PnNCTION MaxPower (Al, 81 : integer) : integer; VAR Prod/ K : integer; PROCEDURE Sort (VAR A5/ 85 integer); : VAR Temp : BEGIN IF integer; PROCEDURE I read (A/ B); Nura := MaxPower (A/ B); writeln (Num) END. i of main program > a. Give a schematic representation and indicate the scope of identifiers. b. What is the output if the numbers read for A and B are 5 and 3, respectively? c. Explain what this program does for positive integers A and B. EQCUS ON -pjiig chapter ending program is an updated version of the program from gROORAMMINS Chapter 6. This version is interactive and includes W, ■ a bad data check ■ a sentinel value for input ■ procedures to accomplish subtasks Typical output for the integer 17 is Enter a positive integer, to quit. 17 The number is 17. The prime numbers less than or equal to 17 are: E 3 5 7 11 13 17 Enter a positive integer, to quit, -qqq A first-level pseudocode development for this problem is 1. Get a number WHILE MoreData DO 2. Process the number 3. Get a number A second-level development is 1. Get a number 1.1 Get entry from the keyboard 1.2 Check for valid entry WHILE MoreData DO 7.6 Forward Reference and Nesting 315 2. Process the number IF Number is 1 THEN 2.1 print a message for one ELSE 2.1 print primes less than Number 3. Get a number 3.1 Get entry from keyboard 3.2 Check for valid entry Step 2.1 can be refined to 2.1 print primes less than Number 2.1.1 print a message 2.1.2 check for primes less than or equal to Number Step 2.1.2 can be further developed to 2.1.2 check for primes less than or equal to Number FOR K := 2 TO Number DO 2.1.2.1 check to see if K is prime 2.1.2.2 If K is prime THEN print K in list of primes Thus, the complete pseudocode development is 1. Get a munber 1.1 Get entry from the keyboard 1.2 Check for valid entry WHILE MoreData DO 2. Process the number IF Number is 1 THEN 2.1 print a message for one ELSE 2.1 print primes less than Number 2.1.1 print a message 2.1.2 check for primes less than or equal to Number FOR K := 2 TO Number DO 2.1.2.1 check to see if K is prime 2.1.2.2 IF K is prime THEN print K in list of primes 3. Get a number 3.1 Get entry from the keyboard 3.2 Check for valid entry With this pseudocode development, the main program would be BEGIN { Main program > GetANumber (Num, MoreData); WHILE MoreData DO BEGIN IF Num = 1 THEN PrintOneMessage ELSE BEGIN PrintMessage (Num); LlstAllPrimes (Num) END; { of ELSE option } GetANumber (Num, MoreData) END END; i of main program > 316 FUNCTIONS AND PROCEDURES Procedures would be written for each of the following modules: GetANumber PrintOneMessage PrintMessage ListAllPrimes Module specifications for these modules are 1. GetANumber Module Data received: None Information returned: Number Boolean flag MoreData Logic: Get an entry from the keyboard. Make sure the entry is valid or the sentinel value for termi nating the process. If the entry is the sentinel value, set the boolean variable MoreData to false. 2. PrintOneMessage Module Data received: None Information returned: None Logic: Print a message about one. 3. PrintMessage Module Data received: Number Information returned: None Logic: Print a heading for the list of primes. 4. ListAllPrimes Module Data received: Number Information returned: None Logic: For each integer less than or equal to Number, check to see if it is prime. If it is prime, print it in a list of primes. A complete program for this problem is PROGRAM ListPrimes (input, output); CONST Skip = ' '; Dashes = ' '; VAR Num : Integer; MoreData : boolean; PROCEDURE GetANumber (VAR Num : integer; VAR MoreData : boolean); > 1 BEGIN REPEAT write ('Enter a positive integer, readln (Num); MoreData := Num UNTIL (Num > □) OR (Num = -RRS) END; i of PROCEDURE GetANumber > > > BEGIN writeln; writeln {Skip:lD, Dashes); writeln; writeln (Skip:50/ '1 is not prime by definition.'); writeln END; i of PROCEDURE PrintOneMessage > {*♦*****♦**********************************♦******»*♦♦♦♦♦♦*♦♦♦♦»> PROCEDURE PrintMessage (Num Given: Task: Return: : integer); The integer read Print a heading for the output Nothing BEGIN > writeln; writeln 3 (Skip:10/ Dashes); writeln; writeln (Skip:2D, writeln (Skip:20, 'The number is ', Num,' . The prime numbers') 'less than or equal to ', Num, ' are:'); writeln END; { i 3|C 3|e * of PROCEDURE PrintMessage * 3t( it: :4c * ♦ * 3K * * ^ PROCEDURE ListftllPrimes } 4c 4c 4: ♦ (Num : sit * 4c * 4:4c ♦ * **** > integer); •{ Given: i. Task: The integer read > List all primes less than or equal to the integer > read > Return: Nothing } •[ Prime : boolean; Candidate, LCV : integer; BEGIN FOR LCV := 2 TO Num DO BEGIN > 4 Prime := true; Candidate := 2; WHILE (Candidate writeln; writeln END; > J 318 FUNCTIONS AND PROCEDURES ■{******»♦♦**♦♦******♦******♦*♦*♦****♦*♦****♦♦*******************> BEGIN { Main program GetftNumber WHILE (Num, } HoreData); MoreData DO BEGIN IF Num = 1 THEN PrlntOneHessage ELSE BEGIN PrintHessage (Num); ListAllPrlmes (Num) END; END. > Sample output for this program is Enter a positive Integer, to quit. ID The number is ID. The prime numbers less than or equal to ID are: E 3 5 7 Enter a positive integer, to quit. 17 The number is 17. The prime numbers less than or equal to 17 are: E 3 5 7 11 13 17 Enter a positive integer, to quit, 1 is not prime by definition. Enter a positive integer, to quit. The number is E5. E5 The prime numbers less than or equal to E5 are: E 3 Summary 319 5 7 11 13 17 IR 53 Enter a positive integer, to quit. Enter a positive integer, to quit. -3 5 The number is 5. The prime numbers less than or equal to 5 are: Enter a positive integer, to quit. RUNNING AND DEBUGGING TIPS -RRR 1. Each subprogram can be tested separately to see if it is producing the desired result. This is accomplished by a main program that calls and tests only the subprogram in question. 2. You can use related but not identical variable names in the parameter lists. For example, PROCED0RE Compute (Nl, N5 VAR Av integer; real); or PROCEDURE Compute (Numberl, Numbers : integer; VAR Average : real); could be called by Compute (Numberl, Numbers, Average); 3. Be sine the t3rpe and order of actual parameters and formed parameters agree. You can do this by listing them one below the other. For example, PROCEDURE GetData (VAR Initl,InitS:char; Scrinteger); GetData (Initiall, Initials, Score); 4. Carefully distinguish between value parameters and variable parameters. If a value is to be returned to the main program,it must be passed through a variable parameter. This means it must be declared with VAR in the procedure heading. Summary Key Terms actual parameter bottom-up testing by reference formal parameter forward reference function global variable local variable main driver modularity nested subprogram procedural abstraction procedure scope of an identifier structured programming stub programming subblock user-defined function value parameter variable parameter 320 FUNCTIONS AND PROCEDURES Kejrwords FORWARD FUNCnON exp In Key Concepts ■ A user-defined function is a subprogram that performs a specific task. ■ The form for a user-defined function is FUNCTION function name (parameter list) : return type; VAR BEGIN .I(work of function here) END; ■ A formal parameter is one listed in the function or procedure heading; it is like a blank waiting to receive a value from the calling program. formal parameters / i V FUNCTION Arithmetic (Syrarchar; Nl, N5:integer) : integer; ■ An actual parameter is a variable listed in the function or procedure call in the calling program. actual parameters / i i Arithmetic (Symbol/ Numl, NumE); ■ The formal parameter list in the function heading must match the number and types of actual parameters used in the main program when the function is called. FUNCTION Arithmetic (Syrarchar; Nl, NSrinteger) : integer; Arithmetic (Symbol/ Numl/ NumE); ■ An assignment must be made to the function name in the body of the function. ■ Within the function, the function name cannot be used on the right of an as signment statement. ■ The general form for a procedure heading is PROCEDURE name (parameter list); a Value parameters are used when values are passed only from the main pro gram to the procedure; a typical parameter list is PROCEDURE PrintData (Nl/ NE : integer; X/ Y : real); ■ Variable parameters are used when values are to be returned to the main pro gram; a typical parameter list is PROCEDURE GetData (VAR Initl/ InitE : char; VAR Nl : integer); ■ Global variables can be used by the main program and all subprograms. ■ Local variables are available only to the subprogram in which they are declared. ■ Each variable is available to the block in which it is declared; this includes all subprograms contained within the block. Summary 321 D Variables are not available outside their blocks. a The scope of an identifier refers to the blocks in which the identifier is available. a Understanding scope of identifiers is aided by graphic illustration of blocks in a program; thus, PROGRAM Practice (input, output); VAR X, Y/ Z : real; PROCEDURE Subl (XI : real); VAR X2 : real; BEGIN END; of PROCEDURE Subl PROCEDURE Sub2 (XI : real); VAR ZE : real; can be visualized as shown in Figure 7.19. PROGRAM Practice FIGURE 7.19 1 ■ X PRdGEDURE Subl .. _.. _. . radCEDURESubZ □ Subprograms can be utilized to perform specific tasks in a program. Proce dures are often used to initialize variables (variable parameters), get data (variable parameters], print headings (no variables needed], perform computa tions (value and/or variable parameters], and print data (value parameters], a Forward reference of a subprogram can be achieved by listing the function or procedure heading with all parameters and following that with the reserved word FORWARD, as FUNCTION B (X : real) : real; FORWARD; 322 FUNCTIONS AND PROCEDURES ■ Programming in order to facilitate the use of subprograms in writing progreuns to solve Problems problems, the programming problems for this chapter consist of rede signing previous programs. 1. In Chapter 6 (Problem 1), you modified the program for the Caswell Catering and Convention Service so that they could use it for all of their customers. Now, revise the program so that you use a separate procediure for each of the following: a- compute meal cost. b. compute room rate. c. compute surcharge. d. compute discount, e* print a statement. Use functions to compute the tax and tip. 2. A prime number is a positive integer that can be divided evenly only by 1 and the number itself (for example, 17). Write a program that will determine whether or not a given positive integer is prime. [Hint: you only have to check for divisors less than or equal to the square root of the number being tested. Thus, if 79 is the positive integer being examined, the check of divisors would be 2, 3,..., 9.) Write a function that returns a boolean value of true for a prime number or false otherwise (a composite number). 3. Now that you have a "prime number checker," write a program that reads an integer from a data file and prints all primes less than or equal to the integer read. Include checks for negative integers, zero, and one. Use one procedure to read and check the data and another to print the primes. The second procedure should call the function developed in Problem 2. 4. In Chapter 5 (Problem 4) and Chapter 6 (Problem 3) you wrote and revised a program for the Community Hospital. Now, write functions for each of the following: a. compute room charge. b. compute telephone charge. c. compute television charge. 5- In Chapter 6 (Problem 5) you wrote a program to compute the miles per gallon for each tank of gas used by a traveler and the cumulative miles per gallon each time the tank was filled. Revise that program by writing procedures to get a line of data and print a line of output. Write functions to compute the mileage per tank and the total mileage. 6. In Chapter 6 (Problem 6), you wrote a program that read pairs of positive integers and produced Parkside's Other Triangle for each pair. Write procedures for each of the following: a- get the data. b. check for bad data. c. print the triangle. 7. Back in Chapter 5 you wrote a program for Dr. Lae Z. Programmer (Problems 9 and 10). You revised that program in Chapter 6 (Prob lem 11). Now it's time to revise it yet again. Write procedures to get the data Dr. Lae Z. Programmer has requested (the overall class aver- Programming Problems 323 age and the number of students receiving each letter grade) and to print the results. Use a function to compute the grade. 8. Problem 12 in Chapter 6 asked that you revise the Pentagon Parking Lot problem you worked on in Chapter 5 (Problem 13). Using that program, write procedmes to get the data and print results. Develop one function to compute the number of hours in the parking lot and another to compute the parking fee. JHAPTEF1 ■■ ■ I m ! 1 ■* 7 1 ■ I■11 ■ I 1 I 1 1 1 1 ■■■I r. Text Files and User- Defined Data Tjrpes In the earlier chapters on problem solving and program design, a simplified version of designing a program to solve a problem was presented as: get the data, do something with it, and print the results. We then proceeded to develop skills that allow us to do something with existing data. Now we are going to examine two features of Pascal that allow us to work with larger data bases in a more sophisticated manner. We will first examine the storage and retrieval of data. Then, we will take a closer look at managing the type of data that can be used in a program. Prior to now, we have worked exclusively with data of type real, char, integer, or boolean. In this chapter, we will see how Pascal permits other data types to be defined and subsequently used in a program. B 8.1 Text Flies OBJECTIVES a to understand how data can be stored in text files a to be able to read from a text file a to be able to write to a text file a to understand the difference between internal and exter nal files 324 The implementation of concepts presented in this section depends on the computer you are using; it is very system dependent. It is essential that your instructor supplement this material with examples and explanations suitable for your particular environment. At the very least, you should be able to use the manual for your system for reference. Consider the relatively simple problem of using a computer to compute and print water bills for a community of 30,000 customers. If the data needed consist of a customer name, address, and amount of water used, you can imagine that entering this information interactively every billing period would involve an enormous amount of time. In addition to saving that time, it is often desirable to save information between runs of a program for later use. To avoid these problems, we can store data in some secondary storage device, usually magnetic tapes or disks. Data can be created separately from a program, stored on these devices, and then accessed by programs when necesseiry. It is also possible to modify and save this information 8.1 Text Files 325 for other runs of the same program or for running another program using this same data. For now we will store all data in text files (other kinds of files are examined in Chapter 12). Text files can be created by a text editor or by a program. Often the editor you use to create your progreun can be used to create a text file. The use of text editors varies significantly and you should consult your instructor and/or manual to use this method. This, however, is how your instructor may create data files for you to use with subsequent program ming problems. Data in a text file can be thought of as a sequence of characters stored in a sequence of lines. As you've already seen, each line has an end-of- line (eoln) marker(|)after it; each file has an end-of-file (eof) marker (■) after the last end-of-line marker. For example, suppose a text file is used to store data for students in a class. If each line consists of an iden tification number for each student followed by three scores, a typical file can be envisioned as 00723 85 93 1001 00131 78 91 851 00458 82 75 861 ■ Technically these lines are stored as one continuous stream with end-ofline markers used to differentiate between lines and the end-of-file marker to signify the end of one file. 00723 85 93 100100131 78 91 85100458 82 75 861 However, we frequently use separate lines to illustrate lines in a text file. Both end-of-line and end-of-file markers are appropriately placed by the computer at the time a file is created. When characters are read, eoln markers are read as blanks. When a text file in secondary storage is to be used by a program, a file variable must be included in the file list along with the standard files input and output as part of the program heading. Thus, if ClassList is the file variable, a heading might be PROGRAM ClassRecordBook (input, output, ClassList); This file variable must be declared in the variable declaration section and is of type text. Thus, the declaration section would be VAR ClassList : text; Reading firom a Text File Reading from a text file is very similar to getting input interactively or reading from a standard input file. Standard procedures read and readln are used with appropriate variables as argimients in either format as shown. read (file variable, input list); or readln (file variable, input list); 326 TEXT FILES AND USER-DEFINED DATA TYPES If the file variable is not specified, the standard file input is assumed. Thus, data from one line of the file of student test scores, ClassList, can be obtained by readln (ClassList/ IDNumber/ Scorel/ ScoreS/ ScoreS); Before data can be read from a file, the file must be opened for reading. This is done by the statement reset (file variable); This statement moves a data pointer to the first position of the first line of the data file to be read. Thus, reset (ClassList); positions the pointer as follows: 00723 85 93 100100131 78 91 85100458 82 75 861 t pointer here As data items are read using readln, values are stored in the designated variables and the pointer is moved to the first position past the end-ofline marker. Thus, reset (ClassList); readln (ClassList/ IDNumber/ Scorel/ ScoreS/ ScoreB); results in 00723 85 IDNumber Scorel 93 100 Score2 Score3 00723 85 93 100100131 78 91 85100458 82 75 861 painter It is not necessary to read all values in a line of data. If only some values are read, a readln statement still causes the pointer to move to the first position past the end-of-line marker. Thus, reset (ClassList); readln (ClassList/ IDNumber/ Scorel); results in 00723 85 IDNumber Scorel 00723 85 93 100100131 78 91 85100458 82 75 861 pointer However, when data items are read using read, the pointer moves to the first position past the last data item read. Thus, the statement read (ClassList/ IDNumber, Scorel); results in the following: 00723 85 IDNumber Scorel 8.1 Text Files 327 00723 85 93 100100131 78 91 85100458 82 75 861 ■ T pointer Variables in the variable list of read and readln can be listed one at a time or in any combination that does not result in a type conflict. For example, readln (ClassLlst/ IDNumber/ Scorel); can be replaced by read (ClassLlst^ IDNumber); readln (ClassLlst/ Scorel); Only if the data pointer is at an end-of-line or end-of-file marker is the boolean function eolnffile variable) true. Similarly, eofffile variable] is true only when the data pointer is positioned at the end-of-file marker. This allows both eoln(£ile variable) and eof(file variable) to be used as boolean conditions when designing problem solutions. Thus, part of a solution might be WHILE NOT eof[file variable) DO process a line of data In this loop, data from one line of the text file would typically be read by a readln statement. This allows the end-of-file condition to become true after the last data line has been read. Text files can contain any character available in the character set being used. When numeric data are stored, the system converts a number to an appropriate character representation. When this number is retrieved from the file, another conversion takes place to change the character represen tation to a number. EXAMPLE 8.1 Let's now write a short program that uses the text file ClassLlst and the end-of- file (eof) condition. If the problem is to print a listing of student identification numbers, test scores, and test averages, a first-level pseudocode development is 1. Print a heading 2. WHILE NOT eof(file variable] DO 2.1 process a line of data Step 2.1 can be refined to 2.1 process a line of data 2.1.1 get the data 2.1.2 compute test average 2.1.3 print the data A short program to accomplish this task is PROGRAM ClassRecordBook (Input/ output/ ClassLlst); This program uses data from a text file. Data for each student are on a separate line in the file. Lines are processed until there are no more lines. } I > VAR Scorel/ ScoreE/ ScoreB/ IDNumber : integer; TestAverage : real; ClassLlst : text; > { External file } 328 text files and user-defined data types FUNCTION Average (Scorel/ Scores/ Score3 : integer) : real; { { { Given: Task: Return: Three integers Compute their average The average of three integers > } } BEGIN Average := (Scorel + ScoreB + ScoreB) / 3; END; PROCEDURE PrintHeading; ■( > > CONST Skip = • ' ; BEGIN writeln; writeln writeln writeln; ('Identification Number'/ Skip:5, 'Average'); (' '/ Skip:5/ ' Skip:5/ 'Test Scores'/ Skip:5/ ' '/ •); writeln END; ■( of PROCEDURE PrintHeading > BEGIN { Main program > reset (ClassList); PrintHeading; WHILE NOT eof(ClassList) DO BEGIN readln (ClassList/ IDNumber/ Scorel/ ScoreB/ ScoreB); TestAverage := Average(Scorel/ ScoreB/ ScoreB); writeln (IDNumber:ID/ Scorel:1R/ ScoreB: END. ScoreB: ')• 332 TEXT FILES AND USER-DEFINED DATA TYPES reset (TempFile); rewrite (ClassList); WHILE NOT eof(TempFile) DO BEGIN readln (TempFile, IDNumber, Scorel, Score2, ScoreB, Scored); writeln (ClassList, IDNumber, Scorel:4, Scores ScoreB:^, Scored: VAR FileWithBlanks, FileWithoutBlanks : text; Existing text file Altered text file > > Ch : char; BEGIN Write to the screen I Insert end-of-line > Advance the pointer > reset (FileWithBlanks); rewrite (FileWithoutBlanks); WHILE NOT eof(FileWithBlanks) DO begin Green) c. (Yellow = Red) 5. Assume the TYPE definition and variable declaration TYPE AllDays = (Sun, Mon, Tues, Wed, Thur, Fri, Sat); VAR Day, Weekday, Weekend : AllDays; have been given. Indicate which of the following are valid program statements. For those that are not, give an explanation. 8.3 Subrange as a Data Type 341 a* Day := Tues; b- Day := Tues + Wed; c. Weekday := Sun; d. IF Day = Sat THEN writeln ('Clean the garage. 3D); e. IP (Day Sun) THEN writeln ('It is a workday.':3G) ELSE writeln ('It is the weekend.';30); f- FOR Day := Men TO Fri DO writeln (Day); g- read (Day); IF Day h. Wed := Tues + 1; Assume the following definitions and declarations have been made in a program. TYPE Cloth = (Flannel/ Cotton/ Rayon/ Orion); VAR Material : Cloth; NumberOfYards/ Price : real; What would be the output from the following segment of code? Material := Cotton; NumberOfYards := 3.5; IF (Material = Rayon) OR (Material = Orion) THEN Price := NumberOfYards * 4.5 ELSE IF Material = Cotton THEN Price := NumberOfYards * 2.75 ELSE Price := NumberOfYards * 2.5; writeln (Price:3G:2); 7. Find the complete definition of a leap year in the Gregorian calendar. Define appropriate data types and write a segment of code that would indicate whether or not a given year was a leap year. B B B 19 ■ 8.3 Subrange as a Data Type Defining Subranges In the previous section, we learned how to define new data types using the TYPE definition section. Now we will investigate yet another way to define new data types. A subrange of an existing ordinal data type may be defined as a data " to be able to define type by a subrange as a data type " to be able to use subrange data types TYPE identifier = initial value .. final value; in a program ■ to understand com For example, we could have a subrange of the integers defined by patibility of data types Objectives continued. TYPE USYears = 177t..l5fi5; 342 text files and user-defined data types ■ to underst^d why When defining a subrange, the following items should be noted, subrange data types are used in a program 1. 2. 3. 4. The original data type must be an ordinal type, Any valid identifier may be used for the name of the type. The initial and final values must be of the original data type. Since the underlying data type is ordinal, it is ordered. In this or dering, the initial value of a defined subrange must occur before the final value. 5. Only values in the indicated subrange (endpoints included) may be assigned to a variable of the type defined by the subrange. 6. The same value may appear in different subranges. We illustrate some of these points in the following example. EXAiVtPLE Consider the subreinges Weekdays and Midweek of the user-defined ordinal Days. TYPE Days = (Sun/ Mon, TueS/ Wed/ Thur/ Fri/ Sat); Weekdays = Mon..Fri; Midweek = Tues..Thur; { { Variable for years from StartYear to LastYear > > } := StartYear TO LastYear DO read (GrossNatlProdCYear]); ■( Find maximum > Max := GrossNatlProd[StartYear]; FOR Year := StartYear + 1 IF GrossNatlProdCYear] Max TO LastYear DO > Max THEN := GrossNatlProdCYear]; 376 ONE-DIMENSIONAL ARRAYS i Now print all data > writeln ('Year'iSD/ 'Gross National Product':3D); writeln (' 'rSD/ • ':3D); writeln; FOR Year := StartYear TO LastYear DO writeln (Year:ED/ GrossNatlProdCYear];55:5); writeln; writeln {'The greatest GNP in recent years was' r^D, Max:5D:2); writeln; writeln END. { of main program > The output for this program is Gross National Product Year iqyo b7DDaD0DaDD0.0D 1571 b75aD0D0D000.aa 1572 baaDDDDDOQQO.DD 1573 b5oaoDDDDDaa.Da 1574 7DaDD0DDDD0D.DD 1575 7DbDDDDDDDaD.DD 157b 71DDaaDDD0aD.0D 1577 72aaaaDQQ0DD.0D 157a 724aDD0aDDDa.D0 1575 7344DDQDDDDD.DD 1560 75b00Q0D0DDQ.DD 15ai aiDOOODQQDOD.Oa 1562 67b7Qaaaoaaa.oa 1563 667QoaDaaaDa.oo 1564 5i2oaooDDDDa.aa 1565 560D0DDaDDDD.DD 156b i23aDDDaaaaDa.aD 1567 i755DDDoaaoaD.aa The greatest GNP in recent years was 17'R500000DD0D. STYLE TIP Indices with semantic meaning can be useful when working with arrays. For examp|le,suppose you are writing^a program that includes the inventory for shoe styles in a shoe store. If the styles are loafer, wing tip, docksider, high pump,low pump, and plain tie, yoii would define TYPE Style = (Loafer/ WingTip, Docksider, HighPump, LowPump, PlalnTie); Shoelnventory =; aRRAY ILoafer..PlalnTie3 OF integer; VAR Stock : Shoelnventory; ShoeType : Style; A tj^ical program statement could be StockCWingTipI := 25; StocklLoafer] ;= Stock(Loafer3 - 3; FOR ShoeType := Lbafer TO PlalnTie DO writeln (StockCShoeTypel); 9.2 Using Arrays 377 ExerciSBS 9.2 l. Assume the following array declarations. VAR List/ Score : ARRAY [1..5] OF Integer; Answer : ARRAY [1..10] OF boolean; Name : ARRAY 11..SQ1 OF char; Indicate the contents of the arrays after each segment of code. a. FOR J := 1 TO 5 DO ListCJl := J DIV 3; b. FOR J := E TO t DO BEGIN ListCJ-1] := J + 3; Score[J-ll := ListCJ-1] DIV 3 END; c. FOR J := 1 TO ID DO IF J MOD S = G THEN AnswertJ] ;= true ELSE AnswerCJ] := false; d. for j := 1 to so do NametJ] := chr(J + t>A); 2. Write a test program to illustrate what happens when you try to use an in dex that is not in the defined subrange for an array: for example, try to use the loop FOR J := 1 TO ID DO read (ACJi); when A has been declared as VAR A : ARRAYC1..5] OF integer; 3. Let the array Best be declared by TYPE List3D = ARRAY [1..3D] OF integer; VAR Best : List3D; and assume that test scores have been read into Best. What does the following section of code do? Count := D; FOR J := 1 TO 3D DO IF BestCJ] > =JD THEN Count := Count + 1; 4. Declare an array and write a segment of code to a. Read 20 integer test scores into the array. b. Count the number of scores greater than or equal to 55. 5. Declare an array using the TYPE definition section and write a section of code to read a name of 20 characters from a line of input. 6. Let the array List be declared by TYPE Numbers = ARRAY [11..171 OF integer; VAR List : Numbers; and assume the components have values of 378 ONE-DIMENSIONAL ARRAYS List -2 List[ll] 3 List[12] List[13] List[14] List[15] List[16] List[17] 0 -8 20 14 -121 Show what the array components would be after the following program segment is executed. FOR J := 11 TO 17 DO □ IF ListCJ] '/ ListtJl:t:5) > THEN ('Too much data. '); the IF eof AND writeln ' The procedure call CalcMean (Nural, NuraE, Ave); and the procedure heading PROCEDURE CalcMean (Nural, NuraE : integer; VAR Ave : real); have the desired matching of variables. ® Let us now modify the program so it will determine the average of 100 test scores in the array Scores. The procedure call in the program will be CalcMean (Scores, Ave); and the procedure heading will have to match these variables. If Scores also is the variable name to be used in the procedure heading, we have PROCEDURE CalcMean (Scores : ???; VAR Ave : real); Pascal requires that a TYPE definition be given. For example, if we have CONST MaxLength = 100; TYPE List = ARRAY [1..MaxLength1 OF integer; VAR Scores : List; the procedure heading could be PROCEDURE CalcMean (Scores : List; VAR Ave : real); This is consistent with allowing only identifiers of identical or compatible types to be associated. A common mistake is to attempt to build a data type inside the procedure heading. This will not work. The statement PROCEDURE CalcMean (Scores : ARRAY [1..MaxLength] OF integer; VAR Ave : real); produces an error message because Pascal compilers check for name equiv alence rather than structure equivalence. To illustrate, you could have two arrays Position : ARRAY tl..3] OF real; Nutrition : ARRAY [1..3] OF real; where Position is used to represent coordinates of a point in space and Nutrition is used to represent the volume, weight, and caloric content of 9.4 Arrays and Subprograms 387 a serving offood. Although Position and Nutrition have the same structure, they have significantly different meanings. Thus, by insisting on name equivalence, the chances of inadvertent or meaningless uses of structured variables are decreased. Also, compiler implementation of name equiv alence is easier than compiler implementation of structure equivalence. We can now write a revised version of the program in Example 9.15 to find the average and include a procedure that requires passing an array variable. 9.16 PROGRAM Average (input, output); CONST HaxLength = IQD; TYPE List = ARRAY [1..MaxLength] OF integer; VAR Scores : List; Ave : real; J, Length : integer; -{*****************************************************♦*♦*******)• PROCEDURE CalcMean (Scores : VAR Ave Length { { > > > VAR J, Sum : integer; BEGIN Sura := □; FOR J Sum Ave END; := 1 TO Length DO := Sura + ScoresCJ]; := Sum / Length i. of PROCEDURE CalcMean > •{ ♦****♦***»*******************»*************************♦*******> BEGIN Length := □; WHILE NOT eof AND (Length DO BEGIN Length := Length + 1; readln (Scores[Length]) END; CalcMean (Scores, Ave, Length); writeln ('The average of:50); writeln; FOR J := 1 TO Length DO writeln (Scores[J]:12); writeln; writeln ('is' :lD, Ave:a:2) END. { of main program > ■ 388 ONE-DIMENSIONAL ARRAYS Before we consider more procedures with arrays, we restate a rule: To pass an array to a procedure or function, the array must be declared with an identifier that uses a TYPE identifier; the matching variable in the procedure must use the same TYPE identifier. Now that we know how to pass an array, let's rewrite our last example using a completely modular development. In this version, CalcMean is a function instead of a procedure. The first-level pseudocode development is 1. Get the scores (PROCEDURE GetData) 2. Compute the average (FUNCTION CalcMean) 3. Print a header(PROCEDURE PrintHeader) 4. Print the results (PROCEDURE PrintResults) The procedure to get the scores requires a VAR declaration in the pro cedure heading for the array. If List is defined as a data type, we have PROCEDURE GetData (VAR Scores : List; VAR Length : integer; BEGIN Length := □; WHILE NOT eof AND (Length DO BEGIN Length readln := Length + 1; (Scores!Length]) END; END; i. of PROCEDURE GetData > The average score could be computed by the function CalcMean. FUNCTION CalcMean (Scores Length : : List; integer) : real; VAR J, Sum : integer; BEGIN Sura := □; FOR J := 1 TO Length DO Sum := Sura + ScoresIJ]; CalcMean := Sum / Length END; { of FUNCTION CalcMean > A procedure to print a heading would be written in a manner similar to that we have used previously. If we want the output to be Test Scores qq qa q? qb qs The average score on this test was qv.DD the procedure for the heading could be PROCEDURE PrintHeader; BEGIN writeln; writeln ( 'Test Scores'); writeln ( ' ' ) ; writeln END; { { { (Hq.5usx SBjoos jo Abjjv AbJJC UB Oq.UT BIT? BX-BP B UlOaj SBJOOS pBBH SujqtiON i(aB6ex.UT : qq.6uai aVA :ujnq.aa :3{SBX :u0AT0 } > > fqsTT : sBJtoos HVA) B^Baqso aaoaaooad ^ *************************************************************** > X UBBMOTTBD NOIIDNOa ?0 > iQNa qq.SuB'i / inns =• ubbwoTBD ttf]S9aoos + uins =: mns oa qqSuBi OX T =: r aoa ;□ =: inns Nioaa laBBequT : inns T HVA { { Bjoos aSBjeAB aqi Bjoos bSbjbab aqq ©qnduiOD ■{ saaoos IXBsa : (asBequx : IqsTT : 30 qsTT rujnqaa :3(sbi « > > :ubat9 > qqBuBi sbjoos) ubbwoXBD NOIXDNOI X *************************************************************** > laeBaqux : qqBuax 1XB9J : 9Aq fqsxi : SBJOOS HVA iaaBaquT ao [qqfiueiXBW'Tl iqaav = ^STT aaix iDDX = qqBuBiXBM XSNOO I (q.ndqno 'qndux) saaoosqsax WVaooad ')U8mdo|aAap stqi loj mBjSojd a)a|duio3 b si afduiBxa 3aiMO||oj aqx l(qq5uBi 's3Joos)uBaMOXB3 =: XI'O 'gflgW VXH BAq Aq punoj si aAy ajaqAA ICqqBua'i 'BAq 'saaoos) sqxi»saaquxxd Aq paqeo aq ppoo ampaDoid siqj. X sqxnsaaquTJd aanaaoGHd 50 } laaa 'E:9:9Aq iSB/i qsaq sxqq uo axoos aSaaaAB aqxi) uxsqi^* !uxsqi^A i ( a: crisaaoos) uxs^T^ia oa qqBuai OX T =: P HOd Nioas iaaBaqux : r aVA (jaBaqux : qqBuai fXTsaa : aAq IqsxT : saaoos) sqxnsaaquT^d aaoaaooad aq pjnoo sqnsai aip juud o; ainpaaoid y 0gg sniBjSojdqns pus sAnxiy ^*6 390 ONE-DIMENSIONAL ARRAYS BEGIN Length := □; WHILE NOT eof AND (Length Length readln := Length + 1; (ScoresCLength]) END END; i of PROCEDURE GetData PROCEDURE •I { { > PrlntHeader; Given: Task: Return: Nothing Print a heading for the output Nothing > > } BEGIN writeln; writeln; writeln (' Test Scores' : E'=l); writeln ( ' ' :ER); writeln END; i of PROCEDURE PrintHeader > PROCEDURE PrintResults (Scores Ave : Length { { : List; real; : integer); Given: Task: Array of scores and average score Print the scores in a list and print the average Return: Nothing { > } score ■I > > VAR J : integer; BEGIN FOR J := 1 TO Length DO writeln (Scores!J]:B5); writeln; writeln ( "The average score on this test was' :^3, END; Ave:L:E/ ■{ *******************+*******************************************> BEGIN PrintResults END. { (Scores, of main program Ave, Length) > ^ As previously mentioned, sorting arrays is a standard problem for pro grammers. Now that we can pass arrays to procedures and functions, let us consider a problem in which an unknown number of reals are to be read from an input file and a sorted list (high to low) is to be printed as output. A first-level pseudocode design is 1. 2. Get data (PROCEDURE GetData) Sort list (PROCEDURE Sort) 9.4 Arrays and Subprograms 391 3. Print header(PROCEDURE PrintHeader) 4. Print sorted list(PROCEDURE PrintData) Since the number of data items is unknown, we will have to declare em array that is of sufficient length to store all the data but that does not use an unreasonable amount of memory. The nature of the problem will pro vide sufficient information for this declaration. For now,assume we know there are at most 50 data items. Then the-following declaration will he sufficient. CONST MaxLength = SO; TYPE NuraList = ARRRY [1..MaxLength] OF real; VRR List : NuraList; Length : integer; The procedure to sort the array uses a version of the selection sort from Section 9.3. Both the array and the number of data items need to be passed to the procedure. An appropriate procedure is PROCEDURE Sort (VRR List : NuraList; Length : integer); VRR J/ K/ Index : integer; Terap : real; BEGIN FOR J := 1 TO Length - 1 DO BEGIN Index := J; FOR K := J + 1 TO Length DO IF List[K] > ListCIndex] THEN Index := K; Terap := ListCIndex]; ListCIndex] := ListCJ]; ListCJ] ;= Terap END { of FOR J loop END; { of PROCEDURE Sort > > This procedme could be called by the statement Sort (List/ Length); After suitable procedures are written for getting the data, printing a header and printing the data, the main body of the program could be BEGIN GetData (List/ Length); Sort (List/ Length); PrintHeader; PrintData (List/ Length) END. •{ of main program > To close this section, let's now reconsider the issue of value parameters and variable parameters used with arrays. Because value parameters re quire separate memory of approximately the same size as that used by actual parameters in the main program, value parameters that are array types can require a great deal of memory..Thus, many programmers use only variable parameters when they work with arrays. This saves memory and speeds execution. Since most of your programs are relatively short and process small data files, this will not be a major problem. However, as data bases become larger and you use more elaborate structures, you 392 ONE-DIMENSIONAL ARRAYS may wish to consider using variable parameters even when changes are not made in the variables. Exercises 9.4 l. Assume the following declarations have been made in a program. TYPE Row = ARRAY [1..1D] OF integer; Column = ARRAY II..3D] OF real; StringaO = ARRAY 11..501 OF char; Week = (Sun, Mon, Tues, Wed, Thur, Fri, Sat); VAR Listl, Lists : Row; Aray : Column; Namel, NameS : StringSD; Day : Week; A, B : ARRAY tl..lG] OF integer; , Indicate which of the following are valid PROCEDURE declarations. Write an appropriate line of code that will call each of those that are valid. Include an explanation for those that are invalid. a. PROCEDURE NewList (X : Row; Y : Column); b. C. d. e. PROCEDURE NewList (VAR X : Row : VAR Y : Column); PROCEDURE NewList (X : ARRAY 11..ID] OF integer); PROCEDURE NewList (VAR X, Y : Row); PROCEDURE NewList (VAR Column : Column); f. PROCEDURE Workweek (Days : ARRAY [Mon..Fri] OF Week); g. PROCEDURE Surname (X : Name); h. PROCEDURE Surnames (X, Y : StringSD); i. PROCEDURE GetData (X ; Week; VAR Y : Name); j. PROCEDURE Table (VAR X : Row; VAR Y : Row); 2. Write a test program that illustrates what happens when you define an array structure in a procedure heading. For example, PROCEDURE Sort (List : ARRAY 11..SD] OF real); 3. When possible, use the TYPE and VAR declaration sections of Exercise 1 to write PROCEDURE declarations so that each of the following statements in the main program is an appropriate call to a procedure. Explain any inap propriate calls. a. oldList (Listl, Aray); b. ChangeList (Listl, Namel, Day); c. Scores (A, B); d. Surname (StringSD); 4. Write an appropriate PROCEDURE declaration and a line of code to call the procedure for each of the following. a. A procedure to read 20 test scores into an array and save them for later use. b. A procedure to count the number of occurrences of the letter A in an ar ray of 50 characters. c. A procedure to take two arrays of 10 integers each and produce a sorted array of 20 integers for later use. d. A procedure to read integer test scores from a data file, count the number of scores, count the number of scores greater than or equal to 90, and save this information for later use. 9.5 Packed Arrays 393 5. Assume the following declarations have been made. TYPE ColumnlD : ftBRAY [1..1D] OF integer; VRR Listl/ Lists : ColumnlD; K : integer; Indicate the contents of each array after the call to the corresponding procedure. a. PROCEDURE Sample (VAR Listl : ColumnlD; Lists : ColumnlD); VAR J : integer; BEGIN FOR J := 1 TO ID DO BEGIN Listl[J] I— J «7; ListStJ] := ListCJl MOD S END END; t of PROCEDURE Sample BEGIN FOR K := 1 TO ID > DO BEGIN ListltKJ := D; ListSCK) := D END; Sample (Listl/ ListS); b. Replace the procedure call with Sample (Lists, Listl); c. Replace the procedure call with consecutive calls Sample (Listl, ListS); Sample (ListS, Listl); 6. For the following, declare appropriate variables, write the indicated procedures, and call the procedmes from the main program. a. read a line of text from an input file that contains 30 characters. b. Count the number of blanks in the line of text. c. Print the line of text in reverse order and print the number of blanks. 7. Write a procedure to examine an array of integers and then return the maxi mum value, minimum value, and number of negative values to the main program. S @ ■I 9.5 Packed Arrays OBJECTIVES ■ to be able to use correct notation for packed arrays Objectives continued. Basic Idea and Notation Arrays, as you recall, are useful for handling large amounts of data. One of the disadvantages of using arrays, however, is that they require large [J] amounts of memory. In particular, arrays of character data use much more memory than is necessary. To illustrate, let us take a closer look at an array declared by VAR Examine ARRAY [1. .53 OF char; 394 ONE-DIMENSIONAL ARRAYS to understand the When this structured variable is declared, the following variables are advantages and dis advantages of packed arrays reserved. Examine to use string Examine[l] Examine[2] ExaminefS] Examine[4] Examine[5] variables to use built-in pro cedures pack and unpack Each component of the array Examine is one word in memory and each word consists of several bytes. Let us consider the array Examine in which each word consists of four bytes. The array would be pictured as Examine Examine[l] Examine[2] Examine[3] Examine[4] Examine[5] byte one word We could assign the word "HELLO" to the array Examine by either Examined] Examine!E] Examine!3] Examine!^] Examine!5] = = = = = 'H'; 'E'; 'L'; 'L'; '0'; or Examine := 'HELLO' depending on which version of Pascal is being used. In either case, after the assignment, the array would look like Examine H E L L O Examine[l] Examine[2] Examine[3] Examine[4] Examine[5] because a byte is the unit of storage necessary for storing a character variable. As you can see, 20 bytes of storage have been reserved, but only 5 have been used. Pascal provides a more efficient way of defining arrays that does not use unnecessary eunounts of storage space. Instead of declaring a variable as an array, we can declare a variable as a packed array. With this declaration, the computer then packs the data in consecutive bytes. Packed arrays can be used with any data type (char, real, integer, boo lean, and so on). However, it is not always wise to do so because it takes longer to access individual components of a packed array than it does to access individual components of an array that has not been declared as packed. Storage space is saved, but time is lost. 9.5 Packed Arrays 395 Let us now consider the declaration TYPE strings = PACKED ARRAY [1..5] OF char; VAR Examine : Strings; and the assignment of the word "HELLO" as before. Using a packed array, we then have the following in memory. Examine H L L O Notice that less than two words(5 bytes) are used to store what previously required five words (20 b5des). We can still access the individual com ponents as before. For example, writeln (ExamineCSl); produces E as a line of output. Character Strings Every programming language needs to be able to handle character data. Names, words, phrases, and sentences are frequently used as part of some information that must be analyzed. In standard Pascal, character strings are formed by declaring packed arrays of character variables. For example, if the first 20 spaces of an input line are reserved for a customer's name, an appropriate character string could be declared by TYPE StringED = PACKED ARRAY [1..BD] OF char; VAR Name : StringED; If the line of input is Smith John A. t position 21 we could read the name into the packed array by the code FOR J := 1 TO ED DO read (NameCJ]); Now when we refer to the array Name, we can envision the string • Smith John A.' But since we declared a fixed length string, the actual string is •Smith John A. ' There are at least three important uses for string variables. 1. String variables of the same length can be compared (Boolean val ues); this permits alphabetizing. 2. String variables can be written using a single write or writeln statement; they cannot be read using a single read statement. 3. A single assignment statement can assign text to a string variable. Let's examine each use individually. 396 ONE-DIMENSIONAL ARRAYS Comparing String Variables. Strings of the same length can be compared using the standard relational operators:"=, , , =.'* For example, if 'Smith' and 'Jones' are strings, then 'Smith' sequence for the ASCII character set, the following comparisons yield the indicated values. Comparison Boolean Value false 'Smith' 'Jake' true 'ABC = 'ABA' false 'Smith Doug' true What would happen if you wanted to evaluate 'William Joe' computer, no decision is made until the blank following the m of William is compared to the s of Williams. Using the full ASCII character code,this Boolean expression is true, which is how these strings are alphabetized. Writing String Variables. Recall the declaration TYPE StringSD = PfiCKED RRRftY [l.-SQ] OF char; VftR Name : StringED; When data were read from an input file, a loop was used to get the data one character at a time. FOR J := 1 TO ED DO read (NamelJl); If we now wish to write the string Name,we could use a similar loop and write it one character at a time. FOR J := 1 TO ED DO write (NaraeUJ); However, Pascal provides a more convenient method for writing strings. The write loop could be replaced by write (Name); Assigning Text to a String. The third feature of string variables is that a single assignment can be used to assign text to a string. If Name is a string of length 20, then Name := 'Smith John A. •; is a valid statement. Note that there must be exactly 20 characters in the text string in order for this assignment to be valid. The statements Name := 'Smith John A.'; Name := 'Theodore Allen Washington'; are both invalid because the text strings are not exactly 20 characters long. There are some standard problems that will be encountered when trying to read data into a packed array. First, assume we have to read a line of 9.5 Packed Arrays 397 data that consists of a company name. Furthermore, assume we do not know the length of the name. The input line could be Prudent Investors Company or Com Mfg. Co. If we know the company name will be no more than 30 characters, we can declare a fixed length array in the following manner. type String3D = PACKED ARRAY [1..3D] OF char; VAR CompanyName : Strlng30; and then read the name with the segment of code FOR J := 1 TO 3D DO IF NOT eoln THEN read (CompanyNametJ]) ELSE CompanyNameCJ] := ''; readln; t Advance the pointer > This will read the name as desired and then fill the array with blanks to the desired length. Applied to the two data lines just mentioned, this segment of code would produce the following character strings. •Prudent Investors Company 'Com Mfg. Co. ' • Second, we may want to read data from an input file in which a field of fixed length is used for some character data. For example,suppose the first 30 columns of an input line are reserved for the company name and then some other information is on the same line. We could have Prudent Investors Company 1905 South Drive t column 31 This data could be accessed by the loop FOR J := 1 TO 3D DO read (CompanyNaraeCJ]); Although the second format for an input file is easier to use,it is sometimes difficult to obtain data in such a precise format. Hence, we must be able to read data both ways. We are now ready to write a short program using packed arrays. Suppose the problem is to get two names from a data file, arrange them alphabet ically, and then print the alphabetized list. Assume the names are in a field of fixed length 25 or two adjacent lines. A first-level pseudocode development is 1. Get the data (PROCEDURE GetData) 2. Arrange alphabetically (PROCEDURE Alphabetize) 3. Print the data (PROCEDURE PrintOata) 398 ONE-DIMENSIONAL ARRAYS A NOTE OF INTEREST Data Abstraction In Pascal, arrays provide examples of structured data types.(As you'll see later, records,files, and forming its logic. The relationship between data sets are also structured data types.) In a struc individual components themselves. For in stance, in a one-dimensional array of integers, we completely define the structure by giving its erarchical relationship constitutes the basis for a conceptual data structure known as a tree. We will not study trees in detail here.For one reason, Pascal provides no direct implementation for trees. The syntax of Pascal does not include a structured type that completely reflects the hi values and by specifying the positions of these erarchical relationship between items in a tree. tured data type,the relationship between the ele ments of the data t3rpe is as important as the items in this structure is hierarchical. This hi values relative to other elements in the list of Does this mean that one cannot write a Pascal integers. For example, we say that 19 is the first value in the list, 89 is the second,12 is the third, program that manipulates a tree data structure? No, the representation of trees is typically cov and so.on. ered in a second course in computer science. There are two implicit conclusions to be drawn from wh^t we have just said. First, in a data structure such as a list, we specify the structure by defining the relationships between items as However,the separation between the conceptual well as the values of individual items. Second, we can then implement that conceptually de fined structure in our programs using a tool from Pascal; for example, a Pascal array is used to implement the concept of a list. It is important to note the distinction between the conceptual data structure that we define and its implemen tation in Pascal. In the case of a list, this dis tinction may seem relatively minor because Pas cal provides a one-dimensional array as an obvious means of implementing a conceptual list. However, there is no guarantee that there will always be such a straightforward link between a conceptual data Structure and its implemen tation in Pascal. Consider,for instance, the structure charts that we have used to specify the relationships be tween modules in a Pascal program. Such a structure chart could itself be considered a data structure. As such, it is clearly a more complex definition of a data structure and its eventual implementation in a particular computer lan guage is an important one to keep in mind. This separation is often called data abstraction. The value of data abstraction is that it allows us to think in terms of data structures without being shackled by the syntactical constraints of a pro gramming language—^similar to what pseudo code allows us to do in describing an algorithm's logic. Once the data structure and the algorithms that manipulate it are understood at this con ceptual level, we can then turn our attention to ways of implementing the structure in Pascal or other languages. Some newer languages,such as Ada and Modula-2,emphasize this data abstrac tion theme to a greater degree than Pascal. They allow the programmer to write packages of rou tines with implementations for such abstract data types; these may then be called from any pro gram that works with data of that abstract type. In effect, these languages allow the programmer to extend the data typing capacity of the lan guage to emphasize the separation of the data structure thanja list. In this data structure, the data items are the module names; their relation structure's definition from its implementation. ship is that Module 2 is directly subordinate to tures seems certain to have a profound effect on computer science in the coming years. Module 1 if Module 1 calls Module 2 in per This approach to using and studying data struc A procedure to get one line of data is PROCEDURE GetData (VAR Name : StringES); VAR J : integer; BEGIN FOR J := 1 to 55 DO read (NaraelJl); readln i Advance the pointer END; } {***************************************************************). { •{ JBq-UTod aiii. eouBAp^ aanaaooHd 50 > > iaaa uippej l([ri9UIBN) PB0J oa 55 01 T =: r aoa Nioaa laeBaq-uj : r aVA 9TTJ b-^bp sq:^ inoaj auiBU B pBsa 6uTqq.ON { i (saeq.opjBqo 55 jo Bufaq-s) euiBU auQ > > KssButj^s : suiBii 'avA) B:^Ba^90 aanaaooaa iBBBuxaq-s : BaciBN "tamBU aVA !aBqo JO [55*'T] iVaa? QaHDad = 5a6uTJ:^S adA£ II I = i az-pqaqBqdiif aanaaDOHd JO ■C { AjBSsaoau uaqw aBuBqoxa NaHI* • 'dl 30 > > iQlia QNa tQIQtbN IS9IIIBK =: aauiBN dmai =: IXSUiBN =: duiax 111939 } Nam TQui^N > asuiBN ai Ni9ag iBSBufJq-S : dmai HVA ^ { ^ japjo paqjos uj sauiBU aqi AxxBOX39qBqdiB sauiBU aqq qjos safflBU OMi i(5s6BTJtqs : ssiibn 't9U3bn a\iA) luanqaa :3{SBX :uaA-F9 > > > aziq-sq^qdiif aaoaaooad SAvaav ivNOiSNai^a-aNO oofr 9.5 Packed Arrays 401 and UnpakName UnpakName[l] UnpakName[2] UnpakName[3] UnpakName[4] UnpakName[5] UnpakName[6] UnpakName[7] UnpakName[8] UnpakName[9] UnpakName[10] Now suppose that UnpakName contains the name 'John Smith'. UnpakName T 'h' 'S' m 't' *h' and we wish to put the characters into a packed array for storage, sorting, or writing. This could be accomplished by FOR J := 1 TO PakNametJ] !□ DO := UnpakNaraeCJ]; and would produce the following: PakName 7' •o' 'h' 'n* « f 'S' 'm' T r 'h' This string can still be accessed as one packed array variable. A FOR loop could also be used to transfer elements from a packed array to an unpacked array, but Pascal does provide standard procedures for both of these processes. An array can be packed by pack (UnpackedArray, J, Packedfirray); This fills all of PackedArray with elements of UnpackedArray, starting with UnpackedArray [J]. An array can be unpacked by unpack (PackedArray/ UnpackedArray, K); This copies all elements of PackedArray into UnpackedArray, putting the first element in UnpackedArray [K]. For these procedures, PackedArray and UnpackedArray do not have to be of the same length and K may be a constant or expression. Unfortunately, pack and unpack are difficult to use. Therefore, since FOR loops can accomplish the same results and are about as efficient, you would do well to use them if you wish to transfer between packed and unpacked arrays. 402 ONE-DIMENSIONAL ARRAYS Ex6rciS6S 9.5 l. indicate which of the following string comparisons are valid. For those that are, indicate whether they are true or false using the full ASCII character set. a. b. c. d. e. f. 'Mathematics' 'CompScience' 'Jefferson' a sequential search. For purposes of this discussion, assume a sequential search on a list of 15 items requires at most 15 microseconds. The nature of a sequential search is such that every time you double the list length, the maximum searching time is also doubled; Figure 9.1 illustrates this increase. FIGURE 9.1 Sequential search I u CD CO 0 h U 1 cS CO I 60H 15- 15 T 1 1 1 30 45 60 75 1 ' \/ '— 90 105 120 135 150 175 190 ... 1 1 1 1 1 240 List length Next, assume a list of 15 items requires a maximum of 60 microseconds when searched by a binary search. Since this process consists of succes sively halving the list, at most four passes will be required to locate the value. This means each pass uses 15 microseconds. When the list length is doubled,it requires only one more pass. Thus,a list of 30 items requires 75 microseconds and a list of 60 items requires 90 microseconds. This is shown graphically in Figure 9.2. The comparison of these two searches is shown on the same graph in Figure 9.3. 9.6 Searching Algorithms 407 FIGURE 9.2 Binary search •a g u 0} 60 15 —r- 15 30 45 -T" I I 60 75 90 —I 1 1 1 1 r 105 120 135 150 175 190 —I— 240 List length FIGURE 9.3 Sequential search versus binary search •a R O u CD 00 s u 60 - 15 -T— 15 —1— —I— —I I 30 45 60 75 1 1 r- 90 105 120 135 150 175 240 List length Exercises 9.6 1. Modify the sequential search in the heginning of this section to locate and print all occurrences of the same value. 2. Write a procedure for the sequential search and show how it can be called from the main program. 3. Modify the sequential search by putting a counter in the loop to count how many p£isses are made when searching a sorted array for a value. Write and run a program that uses this version on lists of length 15, 30, 60, 120, and 240. In each case, search for a value as follows and plot your results on a graph. a. In the first half b. In the second half c. That is not there 4. Repeat Exercise 3 for a binary search. 408 ONE-DIMENSIONAL ARRAYS 5. Suppose the array A is 18 25 37 92 104 A[ll A[5] Trace the values using a binary search to look for a. 18 b. 92 c. 76 6. Write a procedure to search a sorted list and remove all duplicates. 7. Suppose a sorted list of social security numbers is in secondary storage in a file named StudentNum. a. Show how this file can be searched for a certain number using a sequen tial search. b. Show how this file can be searched for a certain number using a binary search. c. Show how a binary search can be used to indicate where a new number can be inserted in proper order. d. Show how a number can be deleted from the file. 8. Write a procedure to read text from an input file and determine the number of occurrences of each vowel. 9. Using a binary search on an array of length 35, what is the maximum num ber of passes through the loop that can be made when searching for a value? 10. Using worst-case possibilities of 3 microseconds for a sequential search of a list of ten items and 25 microseconds for a binary search of the same list, construct a graph illustrating relative efficiency for these two methods ap plied to lists of longer lengths. 11. Modify the sequential search that you developed in Exercise 1 to list all occurrences of a value so that it can be used on a sorted list. That is, have it stop after the desired value has been passed in the list. The sample program for this chapter features the use of arrays and sub programs. Since sorting an array is a common practice, it has been in cluded as part of the program. Specifically, suppose the Home Sales Realty Company, Inc. wants to print a list containing the amount of all sales for a month. Each sale amount is recorded on a separate line of input and the number of homes sold is less than 20. Write a program to do the following: 1. Read the data from the input file. 2. Print the data in the order in which it is read with a suitable header and format. 3. Print a sorted list (high to low) of sales with a suitable header and format. 4. Print the total number of sales for the month, the total amount of sciles, the average sale price, and the company commission (7 percent). 9.6 Searching Algorithms 409 Sample input would be bSDOO qSlDD 7a5DD 1D175D 5£>70a where each line represents the sale price of a home. Typical output would include an unsorted list of sales, a sorted list of sales, and appropriate smnmary data. A first-level pseudocode development is 1. 2. 3. 4. 5. Get data(PROCEDURE GetData) Print header(PROCEDURE PrintHl) Print unsorted list (PROCEDURE PrintList) Sort list(PROCEDURE Sort) Print header(PROCEDURE PrintH2) 6. Print sorted list(PROCEDURE Prin^ist) 7. Compute data (FUNCTION Total and PROCEDURE Compute) 8. Print results (PROCEDURE PrintResults) Notice that PROCEDURE PrintList is called twice and PROCEDURE PrintResults includes output for number of sales, total of sales, average sale price, and company commission. These are printed with suitable headings. A structure chart for this is given in Figure 9.4. FIGURE 9.4 Main task Get data Print Print heading! list Sort list Compjute Print results Module specifications for the main modules are 1. GetData Module Data received: None Information returned: Sales for a month Number of sales Logic: Use a WHILE loop to read entries into an array. 2. PrintHeadingl Module Data received: None Information returned: None Logic: Use writeln statements to print a suitable heading for an unsorted list. 410 ONE-DIMENSIONAL ARRAYS 3. PrintList Module Data received: Array of sales with number of sales Information returned: None Logic: Use a FOR loop with the array length as a loop control vari able to print the list of sales for a month. 4. Sort Module Data received: Unsorted array of sales Number of sales Information returned: Sorted array of sales Logic: Use a selection sort to sort the array. 5. PrintHeading2 Module Data received: None Information returned: None Logic: Use writeln statements to print a suitable heading for the sorted list. 6. Compute Module Data received: Array of sales with number of sales Information returned: Total sales Average sale Company commission Logic: Use a function to compute the total sales. Use a procedure to compute the average sale. Compute company commission by using a defined constant, CommissionRate. 7. PrintResults Module Data received: Number of sales Total sales Average sales Company commission Information returned: None Logic: Use writeln statements to print a summary report. The main program is BEGIN GetData (JuneSales/ Length); PrintHeadingl; PrintList (JuneSales, Length); Sort (JuneSales, Length); PrintHeadingE; PrintList (JuneSales, Length); Compute (TotalSales, AverageSale, CorapanyCom, JuneSales, Length); PrintResults (TotalSales, AverageSale, CompanyCora, Length) END. { of main program > The complete program for this problem is PROGRAM MonthlyList (input, output); PROCEDURE PrintHeading; { Given: Nothing } ■! Task: Print a heading for the output > { Return: Nothing > BEGIN writeln; writeln; writeln ('Donor Name' :33/ writeln ( ' ' : 33, 'Donation':17); ' ' : 17) ; writeln END; i of PROCEDURE PrintHeading > {****♦**********************************************************> 10.3 P^allel Arrays (Optional) 445 FUNCTION Total (amount : amountLlst) : integer; i { { Given: Task: An array of amounts Sum the components of the array The total of array components Return: > > > VAR Sura, J : integer; BEGIN SUM := □; FOR J := 1 TO NumberOfDonors DO Sum := Sum + Amount!J]; Total END; BEGIN i Main program > GetData (Donor, Amount); Sort (Donor, Amount); TotalDonations := Total(Amount); PrintHeading; PrintData (Donor, Amount, TotalDonations) END. i of main program > Output created from an input file of 30 lines is Donor Name Donation Alexander Candy Anderson Tony Banks Harj Born Patty Brown Ron Darnell Linda Erickson Fox Thomas William Francis Denise Generous George Gillette Hancock Mike Kirk Biggins Sam Janson Kevin Johnson Ed Johnson Martha $ $ $ $ $ $ $ $ $ $ $ $ $ 3Q0 $ $ $ 500 375 375 IDD EQD 575 100 300 35D 555 350 5DD 300 350 ADO Jones Jerry Kelly Marvin $ 550 $ A7S Kneff Susan $ 3D0 John Lyon Elizabeth $ $ 455 Moore $ Lasher Robert 175 Muller Marjorie $ Smith John $ Trost Frostie $ 50 $ $ 500 Trudo Rosemary Weber Sharon 550 150 Williams Art $ 350 Williams Jane $ $ 175 $ 6575 Wilson Mary Total 575 446 arrays of more than one dimension Exercises 10.3 !• Which of the following are appropriate declarations for parallel arrays? Explain. a. type StringlS = PACKED ARRAY [1..15] OF char; ListlS = ARRAY [1..15] OF real; VAR Names : ARRAY [1..10] OF StringlS; Amounts : ListlS; b. type Chart = ARRAY [1..15/ 1..1D] OF integer; StringlD = PACKED ARRAY [1..1D] OF char; List = ARRAY [l..ia] OF StringlD; VAR Table : Chart; Names : List; 2. Write a test program to read names and amounts from a data file. Your pro gram should print out both lists and the total of the amounts. Assume each line of data is similar to 7-351 Jones Mary position 21 3. In this section you were asked to sort a list of names alphabetically and then write the sorted list together with student grades. Write a procedure to count the number of occurrences of each grade. 4. Declare appropriate arrays and write a procedure to read data from an input file where there are an unknown number of lines (but less than 100) and each line contains a name (20 spaces), an age (integer), a marital status (character), and an income (real). A typical data line is 35M 28502.161 Smith John 5- Modify the code of Exercise 4 to accommodate data entered in the data file in the following format: 20 positions Name Age| | Income Marital Status Name Age| | Income Marital Status 6* Write a procedure to sort the arrays of Exercise 4 according to income. 10.4 Higher-Dimensional Arrays ■ 10.4 Higher-Dimen sional Arrays 447 Thus far we have worked with arrays of one and two dimensions. Arrays of three, four, or higher dimensions can also be declared and used. Pascal places no limitation on the number of dimensions of an array. Declarations of Higher-Dimensional Arrays ■ to understand when arrays of dimen sions greater than Declarations of higher-dimensional arrays usually assume one of two basic forms. First, a three-dimensional array can be declared using the form two are needed in a program ARRAY [1 .. 3, 1 .. 4, 1 .. 5] OF data type; ■ to be able to define and declare data structures for higher-dimensional arrays ■ to be able to use Each dimension can vary in any of the ways used for arrays of one or two dimensions and the data type can be any standard or user-defined ordinal data type. Second, a three-dimensional array can be declared as an array of two-dimensional arrays using the form higher-dimensional arrays in a program ARRAY [1 .. 3] OF ARRAY [1 .. 4, 1 .. 5] OF integer Each of these declarations will reserve 60 locations in memory. This can be visualized as shown in Figure 10.1. FIGURE 10.1 Three-dimensional array A[1,2,4] • ; , ■ 73 1 A[3.3.5] Jt -ft i . - > An array of dimension n can be defined by ARRAY [1 .. aj, 1 ..^2 which would reserve 1 .. a„] OF data type; * ^2 * • • • * locations in memory. A general definition is ARRAY [fli.. fci, ^2.. ^2. b„] OF data type where a,- Declarations and uses of higher-dimensional arrays are usually facili tated by descriptive names and user-defined data types. For example, suppose we want to decleire a three-dimensional array to hold the contents of a book of tables. If there are 50 pages and each page contains a table of 15 rows and 10 colmnns, a reasonable declaration is 448 ARRAYS OF MORE THAN ONE DIMENSION TYPE Page = 1..50; Row = 1..15; Column = 1..ID; Book = ARRAY [Page, Row, Column] OF integer; VAR Item : Book; When this declaration is compared to TYPE Book = ARRAY [1..5D, 1..15, 1..10] OF integer; VAR Item : Book; we realize that both arrays are identical in structure, but, in the first declaration, it is easier to see what the dimensions represent. Accessing Components Elements in higher-dimensional arrays are accessed and used in a manner similar to two-dimensional arrays. The difference is that in a threedimensional array, each element needs three indices for reference. A sim ilar result holds for other dimensions. To illustrate using this notation, recall the declaration TYPE Page = 1..50; Row = 1..15; Column = 1..ID; Book = ARRAY [Page, Row, Column] OF integer; VAR Item : Book; If you want to assign a ten to the item on page three, row five, column seven, the statement Itemt3,5,7] := ID; accomplishes this. Similarly, this item can be printed by write {IteraI3,5,7]); Using this same declaration, we can 1. Print the fourth row of page 21 with the following segment of code. FOR K := 1 TO ID DO write (Itemt21, of PROCEDURE SeatlfPossible > {************»♦♦♦***♦***********************************♦********> PROCEDURE PrintSeatingChart (VARSeat : i SeatingPlan); Given: The seating chart, a two-dimensional array of Task: Print the passenger names in rows and columns Return: Nothing ■(**********************************»************»*♦************♦* PROCEDURE PrintWaitingList (VftR WaitingList : NotSeatedList; VfiR SraokeOption : SmokeOptionList; VRR SeatChoice : SeatChoiceList; WaitCount : integer); { i Given: Rn array of names of passengers not seated/ the smoking choice and seat preference for each > } VRR J : integer; 4 BEGIN writeln; writeln; writeln (Skip:10/ 'Waiting list for next flight'); writeln; writeln ('NRME' :ID, 'SMOKING CHOICE' :57, 'ROW NUMBER' :15/ 'COLUMN NUMBER' :15); write ( ' writeln ( ' ' ) ; ' ) ; writeln; FOR J := 1 TO WaitCount DO writeln (''/ WaitingList!JI:5E/ SmokeOptionCJ] SeatChoiceCJ/1]:15/ END; { # SeatChoice!J/El:15) of PROCEDURE PrintWaitingList > ■{ ********♦♦♦******************************♦♦*********************} BEGIN := □; := true; (Seat); eof DO BEGIN GetRName (Name, SraokingChoice, RowChoice, ColumnChoice); Seated := false; SeatlfPossible (Name, Seat/ RowChoice/ ColumnChoice/ SmokingChoice/ Seated); IF NOT Seated THEN WaitCount := WaitCount + 1; WaitingList!WaitCount] SmokeOption!WaitCount] := Name; := SmokingChoice; SeatChoice!WaitCount/ 11 := RowChoice; SeatChoice!WaitCount/ E] := ColumnChoice; EmptyWaitingList := false END •! of IF NOT Seated END; { of WHILE NOT eof PrintSeatingChart (Seat); } > IF NOT EmptyWaitingList THEN PrintWaitingList (WaitingList/ SraokeOption/ SeatChoice/ WaitCount) END. } 10.4 Higher-Dimensional Arrays Using the data file Smith John N 3 3 Alexander Joe S R Allen Darcy Jones Mary Humphrey H N 3 3 S fl 1 S & 3 Johnson M N 3 1 3 Eastman Ken N 1 1 Hlnston Sam S a 3 Smythe Susan S R 1 Henderson J B S R 3 Hanson Cynthia S R 3 Zoranson Steve Radamacher Joe Borack Bill Seracki Don s R Henry John N 1 3 Steveson Enghart Johansen Mary N 1 3 Smith Martha Jones Martha N 5 3 Rinehart Jim Rinehart Jane Swenson Cecil Swenson Carol Byes Nikoline Byes Jennifer S ID 1 s ID 3 s ID 5 N N 3 S 1 3 3 N 3 3 N 3 3 N 4 1 N 4 3 N 3 N 5 3 Harris John N 5 3 Harris Judy N 5 1 Hartman F G N L 1 Hartman D T N L 3 Lakes William N L 3 Lampton George N 7 1 Hayes Woodrow Champion M G Thomas Lynda N 7 3 Sisler Susan Stowers Steve Banks M J Banks H W Brown Susan N ? 3 N a 1 N a 3 N a 3 N 5 3 N 5 3 N 3 1 Haywood Ann S a Haywood Mark S 3 a 1 sample output is MOONTAIN-AIR COMMDTERS Seating Chart Nonsmoking section Allen Darcy Steveson Enghart Eastman Johnson Ken Johansen Mary Henry John Rinehart Jim Swenson Carol Harris John Smith John Rinehart Jane Smith Martha Jones Martha Swenson Cecil Byes Nikoline Byes Jennifer Harris Judy Hartman F G Hartman D T Lakes William Lampton George M 459 460 ARRAYS OF MORE THAN ONE DIMENSION Smoking section Humphrey H Jones Mary Smythe Susan Hanson Cynthia Winston Sam Henderson J B Alexander Joe Zoranson Steve Radamacher Joe Waiting list for next flight SMOKING CHOICE NAME ROW NUMBER COLUMN Borack Bill S ID 2 Seracki Don S q 2 N 7 2 N 7 3 Hayes Woodrow Champion M G Thomas Lynda N a 1 Slsler Susan N a 2 Stowers Steve N a 3 Banks M J N 5 3 Banks H W N 5 2 Susan N 3 1 S a 2 S a 1 Brown Haywood Ann Haywood Mark RUNNING AND 1. Use subrange types with descriptive identifiers for specifying index ranges. For example, DEBUGGING TIPS TYPE Page = 1..50; Row = 1..15; Column = 1..ID; Book = ARRAY [Page/ Row, Column] OF real; 2. Develop and maintain a systematic method of processing nested loops. For example, students with mathematical backgrounds will often use I, J, and K as index variables for three-dimensional arrays. Be careful to properly subscript multidimensional array components. When using an array of packed arrays as a list of strings, remember that in standard Pascal, strings must be read in one character at a time. However, strings can be written by a single wrlteln command. 5. When sorting one array in a program that uses parallel arrays, remember to make similar component exchanges in all arrays. 6. Summary Define all data structures in the TYPE definition section. Key Terms higher-dimensiona 1 parallel array two-dimensional array array Key Concepts ■ Two-dimensional arrays can be declared in several ways; one descriptive method is TYPE Chart^Xt = ARRAY VAR Table : Chart^Xb; 11..A, l..t] OF real; Summary 461 a Nested loops are frequently used to read and write values in two-dimen sional arrays; for example, data can be read by FOR Row := 1 TO A DO FOR Column := 1 TO t DO read (Table[Row, Column]); Q When processing the components of a single row or single column, leave the appropriate row or column index fixed and let the other index vary as a loop index; for example, to sum row 3, use Sura := □; FOR Column Sum := 1 TO NumOfColumns := Sum + ACS, DO Column]; To sum column 3, use Sum ;= □; FOR Row Sum := 1 TO NumOfRows := Sura + ACRow, DO 3]; D An array of strings in Pascal is a special case of a two-dimensional array; the data structure is an array of packed arrays and can be declared by TYPE Stringeo = PACKED ARRAY [1..5D] OF char; NameList = ARRAY tl..5D] OF StringaO; VAR Name : NameList; ■ Arrays of strings (packed arrays of characters) can be alphabetized by using the selection sort. a Three standard procedures used in programs that work with arrays of strings are (1) get the data, (2) alphabetize the array, and (3) print the alphabetized list. a Parallel arrays may be used to solve problems that require arrays of the same index type but of different data types, o A typical problem in which one would use parallel arrays involves working with a list of names and an associated list of numbers (for example, test scores). In the next chapter, we will see that this can also be done with a single array of records. B A typical data structure declaration for using names and scores is TYPE StringSD = PACKED ARRAY [l..aD] OF char; NameList = ARRAY [1..3D] OF StrlngED; ScoreLlst = ARRAY [1..3D] OF integer; VAR Name : NameList; Score : ScoreLlst; B Data structures for solving problems can require arrays of three or more dimensions. B A typical declaration for an array of three dimensions is TYPE Diral = 1..10; DimE = 1..ED; Dira3 = 1..30; Block = ARRAY [Dlml, DlmE, Dim3] OF real; VAR Item : Block; In this array, a typical component is accessed by IteratI,J,K] 462 ARRAYS OF MORE THAN ONE DIMENSION ■ Nested loops are frequently used when working with higher-dimensional ar rays; for example, all values on the first level of array Item as just declared can be printed by FOR J := 1 TO 2D DO BEGIN FOR K := 1 TO 30 DO BEGIN write (Iterall/J/Kl:5:2); writeln END; writeln END; ■ Programming Problems 1. The local high school sports hoosters are conducting a fund drive to h®lp money for the athletic program. As each donation is received, the person's name and eimount of donation are entered on one line in a data file. Write a program to a. Print an alphabetized list of all donors together with their corre sponding donation. b. Print a list of donations from high to low together with the do nors' names. c. Compute and print the average and total of all donations. 2. Due to not meeting the original goal, your local high school sports boosters (Problem 1) are at it again. For their second effort, each donor's name and donation are added as a separate line at the end of the previously sorted list. Write a program to produce lists, sum, and average as in Problem 1. No donor's name should appear more than once in a list. 3. Dr. Lae Z. Programmer (Problem 5, Chapter 8) now expects you to write a program to do all record keeping for the class. For each stu dent, consecutive lines of the data file contain the student's name, ten quiz scores, six program scores, and three examination scores. Your output should include a. An alphabetized list together with i. quiz total ii. program total ill. examination total iv. total points V. percentage grade vi. letter grade b. The overall class average c. A histogram depicting the grade distribution 4. The All Metro Basketball Conference consists of ten teams. The conference commissioner has created a data file in which each line contains one school's name, location, and nickname for the school team. You eire to write a program to read this data and then pro duce three lists, each of which contains all information about the school. All lists are to be sorted alphabetically, the first by school name, the second by school location, and the third by nickname. Programming Problems 463 5. Upgrade the program for Mountain-Air Commuters, Inc.(Focus on Programming) so it can be used for each of five daily flights. Pas sengers on a waiting list must be processed first. Print a seating chart for each flight. 6. Add yet another upgrade to the Mountain-Air Commuters, Inc. pro gram. Write an interactive version to consider the possibility of seating passengers who wish to be seated together in the same row. If no such seating is possible, they should then be given a choice of alternate seating (if possible) or taking a later flight. 7. Salespersons at McHenry Tool Corporation are given a monthly commission check. The commission is computed by multiplying the salesperson's gross monthly sales by the person's commission rate. Write a program to compute a salesperson's monthly commis sion computed to the nearest penny. The program should prepare a list of all salespersons in descending order based on monthly commission earned (the person earning the highest commission on top). Each salesperson's commission should be printed next to his or her name. At the bottom of the list, indicate the total monthly commission (summed across all salespersons) and the average commission per salesperson. McHenry never employs more than 60 salespersons. Any names of persons who have invalid data should be printed out separately. Data are invalid if the commission rate is not be tween 0.01 and 0.50, or if the gross monthly sales figure is negative. 8. In order to reduce their costs, the McHenry Tool Corporation (Prob lem 7) is switching from monthly to biannual commission checks. The commission is now computed by multiplying a person's com mission rate by the sum of his or her gross monthly sales for a sixmonth period. The McHenry Tool Corporation has asked that you develop the necessary computer program. The program should differ from Prob lem 7 in the following ways: a. Each name on the output should be followed by the six figures for gross monthly sales. The columns should be labeled "Janu ary" through "June." Total six-month gross sales should be given next, followed by rate of commission, and amount of six-month commission check to the nearest penny. b. Commission rates are based on gross six-month sales. If sales are less than $20,000, the commission rate is 3 percent. If sales are at least $20,000 but less than $40,000, the commission rate is 5 percent. If sales are at least $40,000 but less than $60,000, the commission rate is 5.5 percent. If sales are at least $60,000 but less than $80,000, the commission rate is 6 percent. If sales are at least $80,000 but less than $90,000, the commission rate is 6.5 percent. If sales are at least $90,000, the commission rate is 8 percent. c. At the bottom of each column, the program should provide the total and the mean for that column (the column for commission rates does not require a total, only a mean). 464 ARRAYS OF MORE THAN ONE DIMENSION 9. The dean of a small undergraduate college (enrollment less than 2,000) has asked you to write a program to figure grade point aver age for an unknown number of students. The output should be an alphabetized roster showing the sex, identification number (social security number), grade point average (rounded to three decimal places), and class status (freshman, sophomore, junior, or senior) for each student. The data provide the name, sex(M or F), social security number (ID), and number of semesters completed. Also provided are the number of courses taken and the letter grade and number of credits for each course. The possible letter grades are A (4 points), B (3 points), C (2 points), D (1 point), and E (0 points). Class status is determined by the number of credits as follows: 1-25 credits Freshman 26-55 credits Sophomore 56-85 credits Junior 86 or more credits Senior 10. You have just started work for the Michigan Association of Auto mobile Manufacturers and have been asked to analyze sales data on five subcompact cars for the last six months. Your analysis should be in table form and should include the name of each make and model, a model's sales volume for each month, a model's total and average sales volume for six months, a model's total sales revenue for six months, and the total and average sales volume for each month. In addition, your output should include the total and aver age sales volume of all models for the entire six months and the make and model name of the car with the largest total sales reve nue and the amount of that revenue. 11. You have been asked to write a program to assist with the inven tory and ordering for Tite-Jeans, Inc. They manufacture three styles: straight, flair, and peg. In each style, waist sizes vary by integer val ues from 24 to 46 and inseams vary by integer values from 26 to 40. Write a program to a. Read in the starting inventory. b. Read in daily sales. c. Print the ending inventory for each style. d. Print order charts for each style that is low in stock (fewer than three). e. Print an emergency order list for those that are out of stock. 12. Thomas H. Holmes and R. H. Rabe developed a Social Readjust ment Rating Scale of 43 items that they feel measure the effect of stress on mental and physical health. Of those people with over 300 life-change units for the past year, almost 80 percent get sick in the near future; with 150 to 299 units, about 50 percent get sick in the near future; and with fewer than 150 units, only about 30 per cent get sick in the near future. Using the following model, write an interactive program to read data for an individual and produce a table listing the Life Event, Mean Value, and Personal Value (Sum of Mean Values) for that per son. Your program should use parallel arrays to store the life event chart and associated mean values. After a user responds yes ('Y' or Programming Problems 465 'y') or no ('N' or 'n') to each event, appropriate results should be printed. Life Event 1. Death of spouse Mean Value 100 2. Divorce 73 3. Marital separation 4. Jail term 5. Death of close family member 65 63 63 6. Personal injury or illness 7. Marriage 53 8. Fired at work 47 9. Marital reconciliation 45 10. Retirement 50 45 11. Change in health of family member 44 12. Pregnancy 40 13. Sex difficulties 39 14. Gain of new family member 15. Business readjustment 16. Change in financial state 39 17. Death of close friend 37 18. Change to different line of work 19. Change in number of arguments with spouse 36 39 38 35 20. Mortgage over $10,000 31 21. Foreclosiue of mortgage or loan 30 22. Change in responsibilities at work. 23. Son or daughter leaving home 29 24. Trouble with in-laws 29 25. Outstanding personal achievement 28 26. Spouse begins or stops work 26 27. Begin or end school 28. Change in living conditions 29. Revision of personal habits 26 29 25 24 30. Trouble with boss 23 31. Change in work hours or conditions 32. Change in residence 33. Change in schools 34. Change in recreation 35. Change in church activities 36. Change in social activities 37. Mortgage or lien less than $10,000 38. Change in sleeping habits 20 39. Change in number of family get-togethers 20 20 19 19 18 17 16 15 40. Change in eating habits 15 41. Vacation 13 42. Christmas 12 43. Minor violations of the law 11 Reproduced by permission of Thomas H. Holmes, M.D., Professor of Psychiatry and Behavioral Sciences, University of Washington, Seattle, and P^rgamon Press, Inc., in whose Journal ofPsychosomatic Research the scale was first published. 13. A few members (total unknown, but no more than 25) at Oakland Mountain Country Club want to computerize their golf scores. Each 466 ARRAYS OF MORE THAN ONE DIMENSION member plays 20 games, some 18 holes and some 9 holes. Each member's name (no more than 20 characters) is written on a data card, followed on a second card by the 20 scores. Each score is im mediately followed by an 'E' or an 'N*, indicating 18 or 9 holes, respectively. Write a program to read all the names and scores into two paral lel two-dimensional arrays. Calculate everyone's 18-hole average. (Double the 9-hole scores before you store them in the array and treat as 18-hole scores.) Calculate how much each average is over or under par (par is 72 and should be declared as a constant). Out put should be each name, average, difference from par, and scores. 14. Write a program to keep statistics for a basketball team consisting of 15 players. Statistics for each player should include shots at tempted, shots made, and shooting percentage; free throws at tempted, free throws made, and free throw percentage; offensive re bounds and defensive rebounds; assists; turnovers; and total points. 15. Appropriate team totals should he listed as part of the output. A magic square is a square array of positive integers such that the sum of each row, column, and diagonal is the same constant. For example. 16 3 2 5 10 11 13 8 9 6 7 12 4 15 14 1 is a magic square whose constant is 34. Write a program to have as input four lines of fom positive inte gers. The program should then determine whether or not the square is a magic square. 16. Pascal's Triangle can be used to recognize coefficients of a quantity raised to a power. The rules for forming this triangle of integers are such that each row must start and end with a 1, and each entry in a row is the sum of the two values diagonally above the new entry. Thus, four rows of Pascal's Triangle are This triangle can be used as a convenient way to get the coeffi cients of a quantity of two terms raised to a power (binomial coeffi cients). For example, [a + by = 1 x + 3ab^ + 1 x b^ where the coefficients 1, 3, 3, and 1 come from the fourth row of Pascal's Triangle. Write a complete program to print out Pascal's Triangle for ten rows. Programming Problems 467 17. Your former high school principal has come to you for help. He wants you to develop a program to maintain a list of the 20 stu dents in the school with the highest scores on the SAT test. Input is from a text file containing the name (20 characters), and the total SAT score (verbal plus mathematical). Write a program that, when all data have been read, prints out a list of the 20 highest scores from highest to lowest, and the students' names. You may assume that no two students have the same score. 18. The transpose of a matrix (table) is a new matrix with the row and column positions reversed. That is, the transpose of matrix A, an M by N matrix is an W by M matrix, with each element, A[m,n] stored in B[n,m]. Given a 3 x 5 matrix of integers, create a matrix that is its transpose. Print both the original matrix and the new matrix. 19. Mr. Laven, a mathematics instructor at your college, wants you to write a program to help him keep his students' grades. He wants to keep track of up to 30 grades for each of up to 35 students. Your program should read grades and names from a text file, and then print the following: a. A table showing the names in alphabetical order and grades re ceived by each student. b. An alphabetical list of students with their total points and aver age score. c. A list of averages from highest to lowest with corresponding stu dents' names. 20. Write a program in which a person can enter data into a 5 x 7 ma trix. Print the original matrix along with the average of each row and column. 21. Matrix M is symmetric if it has the same number of rows as col umns, and if each element M[x,y] is equal to M[y,x]. Write a pro gram to check a matrix entered by the user to see if it is symmetric or not. 22. The following table shows the total sales for salespeople of the Fal con Manufacturing Company. Salesperson Week 1 Week 2 Week 3 Week 4 18 Anna, Michael 30 25 45 Henderson, Marge Johnson, Fred Striker, Nancy 22 30 32 35 12 17 19 15 32 30 33 31 Ryan, Renee 22 17 28 16 The price of the product being sold is $1,985.95. Write a program that permits the input of the previous data, and prints both a rep lica of the original table and a table showing the dollar value of sales for each individual during each week along with their total sales. Also, print the total sales for each week and the total sales for the company. 23. The computer science office wants a computerized system for find ing telephone numbers of students. The program should read a list 468 ARRAYS OF MORE THAN ONE DIMENSION of up to 20 students and their telephone numbers from a text file. It should permit the entry of a student's name, and then print the name and telephone number.(A binary search could he used for this.) If the name is not found, an appropriate message should he printed. 24. Write a program to permit two people to play the game of Battle ship. Your program should record the ship positions, hits, misses, and ship sinkings for each player. 25. Rewrite the Battleship program (Problem 24) to have a person play against the computer. CHAPTER ■ nni 1■ B B ~ii w - ii n B B E B i■ ■ - 11 « IB ■ MMmj Records The previous two chapters dealt extensively with the concept of a structured data type: arrays. Recall that when you declare an array, you reserve a predetermined number of variables. Each of these variables is of the same base type and can be accessed by reference to the index of an array element. All components of an array must be of the same data type; this is a serious limitation since there are many situations in which this is not possible. For example, a bank may wish to keep a record of the name, address,telephone number, marital status, social security number,annual salary,total assets,and total liabilities of each customer.Fortunately,Pascal provides another structured data type,record, which allows heterogeneous information to be stored, accessed, and manipulated. A record contains fields, which can be of different data types. This chapter shows you how to declare records, how to access the various fields within a record, and how to work with arrays of records. H 11,1 Record as a Structured Data Type Record Definitions A record is a collection of iields that may be treated as a whole or indi vidually. To illustrate, a record that contains fields for a customer's name, age, and annual income could be visualized as shown in Figure 11.1. This OBTECTIVES schematic representation may help you understand why a record is con ° to understand the sidered a structured data type and familiarize you with the idea of using basic idea of record as a structured data fields in a record. type a to be able to declare a record ■3 to be able to use fi elds of a record Declaring a RECORD Let's now consider our first example of a formally declared record. Assume we want a record to contain a customer's name, age, and annual income. The following declaration can be made. 469 470 RECORDS Customer FIGURE 11.1 Fields in a record Name Aimuallncome VAR Customer : RECORD Name : PACKED ARRAY [1..3a] OF char; Age : integer; Annuallncome : real END; Another method of declaring a record is to use the TYPE definition section to define an appropriate record type. This form is preferable because it facilitates use with subprograms. Thus, we can have TYPE Customerlnfo = RECORD Name : PACKED ARRAY [1..3D] OF char; Age : integer; Annuallncome : real END; { of RECORD Customerlnfo } VAR Customer : Customerlnfo; Components of a record are called fields and each field has an associated data type. The general form for defining a record data type using the TYPE definition section is TYPE Type identifier = RECORD field identifier 1 : data type 1; field identifier 2: data type 2; field identifier n : data type n END; { of RECORD definition } The syntax diagram for this is RECORD identifier datatype END 11.1 Record Definitions 471 The following comments are in order concerning this form. 1. The type identifier can be any valid identifier. It should be de scriptive to enhance program readability. 2. The reserved word RECORD must precede the field identifiers. 3. Each field identifier within a record must be unique. However, field identifiers in different records may use the same name. Thus, FirstRecord = RECORD Name : PACKED ARRAY [1..3D] OF char; Age : integer END; and SecondRecord = RECORD Name : PACKED ARRAY [1..3D] OF char; Age : integer; IQ : integer END; •[ of RECORD SecondRecord > can both be defined in the same program. 4. Data types for fields can be user-defined. Thus, our earlier defini tions could have been TYPE String3D = PACKED ARRAY [1..3D] OF char; Customerlnfo = RECORD Name : String3D; Age : integer; Annuallncome : real END; { of RECORD Customerlnfo > VAR Customer : Customerlnfo; 5. END; is required to signify the end of a RECORD definition. This is the second instance (remember CASE?) in which END is used without a BEGIN. 6. Fields of the same base type can be declared together. Thus, Info = RECORD Name : String3D; Age, IQ : integer END; i of RECORD Info > is appropriate. However, you are encouraged to list each field sep arately to enhance readability and reinforce the concept of fields in a record. EXAMEIiE 11.1 ' Let's now define another record. Suppose you want to keep a record for a college student; the record is to contain a field for each of the following: student's name (Smith Jane), social security number (111-22-3333), class status (Fr, So, Jr, or Sr), previous credit hours earned (56), credit hours being taken (17), and grade point average (3.27). We can define a record and declare an appropriate variable as follows: TYPE String3D = PACKED ARRAY [1..3D] OF char; Stringll = PACKED ARRAY [1..11] OF Char; Class = (Fr, So, Jr, Sr); 472 RECORDS Studentlnfo = RECORD Name : StringBD; SSN : Stringll; Status : Class; HoursEarned : O..RRS; HoursTaking : □..3D; CPA END; : real { of RECORD Studentlnfo > VAR Student : Studentlnfo; H Fields in a Record Now that you know how to define a record, you need to examine how to access fields in a record. For our discussion, let us consider a record defined by TYPE String3G = PACKED ARRAY [1..3D] OF char; Employee = RECORD Name : String3D; Age : integer; MaritalStatus Wage : END; -C : char; real of RECORD Employee } VAR Programmer : Employee; Programmer can he visualized as pictured in Figure 11.2. Programmer FIGURE 11.2 Defined fields in Programmer Name MaritalStatus Each field within a record is a variable and can be uniquely identified by record name.field name Thus, the four field variables are Programmer.Name Programmer.Age Programmer.MaritalStatus Programmer.Wage Each of these variables may be used in any manner consistent with the defined base type. To illustrate, suppose Programmer.Name and Program mer. Age have been assigned values and you wish to print the names of those employees under 30 years of age. You could have a fragment of code such as 11.1 Record Definitions 473 A NOTE OF INTEREST Computer Industry Growth In an article discussing growth of the computer industry,Joseph J. Kroger, president of Computer Systems Division of Sperry Corporation, stated: "Today we accept as commonplace reports of office and factory managers who respond to cru cial problems uncovered by a computer pro grammed to read printed material with an op tical scanner that picks out key words and phrases demanding immediate attention. Or of doctors who turn to computers that not only diagnose diseases with incredible accuracy but also pre scribe treatment. Or of geologists who use com puters to locate the exact site of valuable oil and mineral deposits. "But exciting as those applications are, there's little doubt that the best is yet to come. Expert systems—programs that perform at the level of human experts—utilize a process known as knowledge engineering to combine textbook learning with the insights that come only from experience, then set about working tirelessly to sort through thousands of 'if, then* rules of thumb and form a reasoned judgment. The implications for problem solving in such diverse fields as mathematics, science, and engineering are staggering. "Combine these systems with mechanical creatures that operate independently—^robots— and you've added a whole new dimension to the workplace." IF Programmer.ftge If you wish to compute gross salary, you might have read (Hours); Gross := Hours * Programmer.Wage; Other Fields Thus far, our fields have been declared in a relatively direct fashion. This is not always the case. Sometimes, when establishing the structure of a STYLE TIP H @ 1^ Use descriptive field names, appropriate subranges, and a descriptive vari able name when defining records. For example, if you want a record with fields for a student's n^p,age,sex, and class status, you can use TYPE StringSD = PACKED ARRAY 11..20] pF char; StudentRecord - RECORD Name : StringBD; Age : D..BR; Sex : (Hale/ Female); ClassStatus : (Fr, So, Jr, Sr) - END; { of RECORD StudentRecord VAR Student ; StudentRecord; The fields would then be Student.Name Student.Age Student.Sex Student.ClassStatus and you can use program-statements such as IF Student.Sex = Hale THEN ■or IF Student.Age 474 RECORDS record, the data type of a field needs more development. For example, suppose you wish to declare a record for each student in a class and the record is to contain student name, class name, four test scores, ten quiz scores, final average, and letter grade. This can be visualized as shown in Figure 11.3. FIGURE 11.3 Student Fields in Student Name Average In this case. Test and Quiz are both arrays. Thus, a subsequent devel opment is shown in Figure 11.4. FIGURE 11.4 Student Arrays as fields in a record Name Average LetGrade This record can now be formally defined by TYPE String3D = PfiCKED ARRAY [1..3D] OF char; StringlD = PACKED ARRAY [1..1D] OF Char; TestScores = ARRAY tl..4] OF integer; QuizScores = ARRAY [1..1D] OF integer; Studentlnfo = RECORD 11.1 Record Definitions 475 Name : StringSD; Class : StringlD; Test : TestScores; Quiz : QuizScores; Average : real; LetGrade : char END; { of RECORD Studentlnfo vaR Studentlnfo; Student If the student associated with this record earned an 89 on the first test and a 9(out of 10) on the first quiz, this information could be entered by reading the values or by assigning them appropriately. Thus, either of the following would suffice. read (Student.TestCl], Student.Quiz[1]); or student.TestCl1 := flR; Student.QulzCl] := R; Exercises 11.1 1. Explain why records are structured data types. 2. Write a test program to a. Define a RECORD tjrpe in which the record contains fields for your name and your age. b. Declare a record variable to be of this type. c. Read in your name and age from a data file. d. Print out your name and age. 3. Discuss the similarities and differences between arrays and records as struc tured data tjrpes. Use the TYPE definition section to define a record for each record illustrated in Figure 11.5(a),(b), and (c), respectively (see next page). In each case, also declare a record variable to be of the defined type. a. TeamMember b. Book c. Student FIGURE 11.5 I a) TeamMember Records with fields illustrated Name Weight ScormgAverage 476 RECORDS b) Book Author PublicatioiiDate c) Student Name Average 5. Draw a schematic representation of each of the following record definitions. a. TYPE StringBD = PACKED ARRAY [1..3D] OF char; Stringll = PACKED ARRAY [1..11] OF char; Eraployeelnfo = RECORD Name : Strlng30; SSN : Stringll; NumOfDep : integer; HourlyWage : real END; VAR Employee : Employeelnfo; b. TYPE Houselnfo = RECORD Location : PACKED ARRAY [1..PD] OF char; Age : integer; NumRooms : integer; NumBaths : integer; BuildingType : (Brick/ Frame); 11.1 Record Definitions 477 Taxes : real; Price : real END; VRR House : Houselnfo; c. TYPE StringHO = PACKED ARRAY [l..aD] OF char; StringRD = PACKED ARRAY [1.-3D] OF char; Stringfl = PACKED ARRAY OF char; PhoneBook = RECORD Name : StringBD; Address : ARRAY 11.,Al OF StringaO; PhoneNura : Stringfl END; VAR PhoneListing : PhoneBook; 6. Use the TYPE definition section to define an appropriate RECORD type for each of the following. In each case, also declare an appropriate record variable. a. Families in your former school district: each record should contain the last name, parents' first and last names, address, number of children, and the ages of children. b. Students in a school system: each record should contain the student's name, identification number, classification (Fr, So, Jr, or Sr), courses being taken (at most six), and grade point average. 7. Find all errors in each of the following definitions or declarations. a. TYPE Info : RECORD Name = PACKED ARRAY [1..3D] OF char; Age : □.. END; b. TYPE Member = RECORD Age : integer; IQ : Integer END; VAR Member c. : Member; = RECORD VAR Member Name : PACKED ARRAY Age : 0.. ; [1..3D] IQ = 50..aoo END; 8. Given the record defined by TYPE String3D = PACKED ARRAY [1..3D] OF char; Weekdays = (Men, Tues, Wed, Thur, Fri); ListOfScores = ARRAY Info = [1. .5] OF integer; RECORD Name : String3D; Day : Weekdays; Score : ListOfScores; Average END; : real OF char; 478 RECORDS VAR Contestant : Info; Sum : integer; assume values have been assigned as indicated in Figure 11.6. Indicate which of the following are valid and, if invalid, explain why. Day := Wed; Contestant.Day := Wed; Score := 70; ScoreCS] := ?D; Contestant.Score[3] := 70; Contestant[3].Score := 70; FOR J := 1 TO 5 DO Sum := Sum + Contestant.Score[J]; Contestant.Score[3] := ScoreCSl; Contestant.Score[3] := Contestant.ScoreCS] + 3; Average := (ScoreEll + ScoreES] + ScoreE31) / 3; IF Contestant.Day writeln (Contestant.Name: VAR Student : StudentRecord; and envisioned as shown in Figure 11.7. FIGURE 11.7 Student Fields in Student Name Ayeiege To use this record, we need to assign or read data into appropriate fields. Therefore, assume a line of data is Washington Joe T| 79 83 94^ This data can be read by the fragment of code FOR J := read FOR J 1 TO SO DO (Student.NametJ]); := 1 TO 3 DO read (Student.ScorelJ]); readln; The average can be computed by student.Average := (Student. Scored] + Student.ScoreCS] + Student.Score[3]) / Notice that each field identifier includes the record name. Fortunately, when working with fields of a record, Pascal provides a more convenient method of referring to these fields: a WITH ... DO statement. Using this option, the previous fragment can be rewritten as WITH student DO BEGIN FOR J read FOR J read := 1 TO SO DO (NameCJ]); : := 1 TO 3 DO (ScoretJ]); readln; Average := (Scored] END; ScoreiS] + Score[3]) Formally, a WITH . .. DO statement has the form / 3 480 RECORDS WITH record name DO BEGIN statement 1; statement 2; statement n END; where the statements used may refer to the field identifiers but do not include the record name as part of the field identifier. This eliminates use of the period following the record name.Thus,instead of Student.Score[J], you can use Score[J]. As a second illustration, suppose you have a record defined as TYPE Stringao = PACKED ARRAY [1..E01 OF char; Patientlnfo = RECORD Name : StringEO; Age : Integer; Height : integer; Height : integer; Sex : char END; { of RECORD Patientlnfo > VAR Patient : Patientlnfo; Values can be assigned to the various fields specifically by Patient.Name := 'Jones Connie '; Patient.Age := IR; Patient.Height := ; Patient.Weight := 125; Patient.Sex := 'P'; or by WITH Patient DO BEGIN Name := 'Jones Connie '; Age := IR; Height := t7; Weight := 125; Sex := 'F' END; i of WITH...DO } A single WITH...DO statement can be used with more than one record. For example, using the previous two record definitions, it is possible to write WITH student. Patient DO BEGIN Average := (ScoreCll + ScoreCEl + ScoreCBl) / 3; Age := IR END; { of WITH...DO > However, when using more than one record in a single WITH ... DO statement, each field identifier should have a unique reference to exactly one of the listed records. If a field identifier is used in more than one of the records, the reference may be ambiguous and a logic error may result. Thus, in the preceding two records. 11.2 Using Records 481 WITH Student/ Patient DO writeln (Name); is incorrect and could produce a result different from what you expect; it is not clear whether the reference is to Student.Name or Patient.Name. In some versions of Pascal, this is a compilation error. In others, it is a logic error and does not produce either a run-time error or a compilation error. Thus, while you might want to print Student.Name, you would print Patient.Name instead. This is because successive identifiers used as we just have are treated as if they are nested. Copying Records How can information contained in one record be transferred to another record? We need to do this when,for example, we want to sort an array of records. To illustrate how records can be copied,consider the following definitions and declarations. TYPE InfoA = RECORD Fieldl : integer; Fields : real; Fields : char END; -C of RECORD InfoA > InfoB = RECORD Fieldl : integer; Fields : real; Fields : char END; VAR Reel/ RecS : InfoA; RecS : InfoB; The three records declared can be envisioned as shown in Figure 11.8. Now, suppose data have been assigned to Reel by WITH Red DO BEGIN Fieldl := S5; Fields := flq.S; Fields := 'M' END; { of WITH...DO > These data can be copied to the corresponding fields of Rec2 by RecS := Reel; This single assignment statement accomplishes all the following: RecS.Fieldl := Reel.Fieldl; RecS.Fields := Reel.Fields; RecS.Fields := Reel.Fields; It is important to note that such an assignment can only be made when the records are of identical type. For example, notice that InfoA and InfoB have the same structure but have been defined as different types. In this case, if you wish to assign the values in the fields of Reel to the corre sponding fields of RecS, the statement RecS := Reel; produces a compilation error. Although Reel and RecS have the same structure, they are not of identical type. In this case, the information can be transferred by 482 RECORDS FIGURE 11.8 Reel Copying records Fieldit Pield2 Fieias Rec2 \'-r i ' Fi^ ^ . Helda ■- —-T-> R-V. -'- 'S . - . 1 Mda Rec3 . _ Fieldl ■ ■ ■■ "! Fidld2 Fields^ WITH Rec3 DO BEGIN Fieldl Fields := Reel.Fieldl; := Recl.FieldE; Field3 END; := WITH Patient DO BEGIN FOR J := 1 TO SO DO read (NameCJ]); readln (Age, Height/ Weight/ Sex) END; However, good program design would have us use a procedure for this task. Therefore, in order to use a procedure, we must be careful to use the user-defined data type Patientlnfo and a variable parameter in the pro cedure heading. With these two considerations, an appropriate procedure is pr] PROCEDURE GetData (VAR Patient : Patientlnfo); VAR J : integer; BEGIN WITH Patient DO BEGIN FOR J := 1 TO 20 DO read (NameCJ]); readln (Age, Height/ Weight/ Sex) END END; This is called from the main program by GetData (Patient); As a second example of getting data for a record, suppose you are writing a program to be used to compute grades of students in a class. As part of the program, a record type can be declared as TYPE StringSD = PACKED ARRAY [1..SD] OF char; QuizList = ARRAY [1..1D] OF integer; TestList = ARRAY [1..4] OF integer; StudentRecord = RECORD Name : StringaO; Quiz : QuizList; Test : TestList; QuizTotal : integer; TestAverage : real; LetterGrade : 'A'..'E' END; VAR Student : StudentRecord; If each line of data contains a student's name, ten quiz scores, and four test scores and looks like Smith Mary J. Name 9 8 10 7 10 9 8 10 9 4 89 92 85 97^ Quiz scores Test scores 484 RECORDS A procedure to get this data could be PBOCEDDBE GetData (VRB Student : StudentBecord); VAB J : Integer; BEGIN WITH Student DO BEGIN FOB J := 1 TO 50 DO read (NaraetJ]); FOB J := 1 TO ID DO read (QuizCJ1); FOB J := 1 TO read (TestCJl) END; > readln END; VAR Student ; StudentFile; Before we can create the file of records, we need to know how data were entered in the text file (assume input). For purposes of this example, assume data for each student are contained on a single line, 20 positions are used for the name, and an identification number is followed by three test scores. Thus, the data file could he 065 89 92 76 [ Jones Mar^ Smith John 021 93 97 85 I B A procedure to create the file of records is PROCEDURE CreateFile (VAR Student : StudentFile); VAR J : integer; BEGIN rewrite (Student); i Open for writing WHILE NOT eof(input) DO BEGIN { WITH Get data Studentt for one record } > DO BEGIN FOR J := 1 TO BO read (NameCJ]); read (IDNumber); readln (ScoreCl]/ DO Score!B]/ Score[3]) END; put (Student) t Put buffer contents in file END END; This procedure is called from the main program by CreateFile (Student); FIGURE 12.2 After it is executed, we have the records shown in Figure 12.2. File Student with values i ■ I ■ ■ NainS; Name -.l 'I Average t :«]5i Score IDNumfier ■iDNiimber Student 12.3 Files with Structured Components 535 File Manipulation Several problems are typically involved with manipulating files and file components. Generally, a program starts with cm existing file, revises it in some fashion, and then saves the revised file. Because files in standard Pascal must be accessed sequentially, this usually necessitates copying the existing external file to a temporary internal file,revising the temporary file, and copying the revised file to the external file. The existing external file is often referred to as the master file. The file containing changes to be made in the master file is called the transaction file. To illustrate a simple update problem, let's consider again the problem using the file containing records for students in a computer science class. Assume that the external file has been named Student. Now suppose we wish to delete a record from Student (master file) because some student moved to Australia. This problem can be solved by searching Student sequentially for the record in question. As the name in each record is examined, if the record is to be kept, it is put in a temporary file. The desired record is not transferred, thus accomplishing the update. Finally, Student is rewritten by copying the contents of the temporary file to Student. A first-level pseudocode development is 1. Get the name to be deleted 2. Search Student for a match copying each nonmatch to TempFile 3. Copy the remainder of Student to TempFile 4. Copy TempFile to Student Using the previous declarations and assuming that the name of the student whose record is to be deleted has been read into MovedAway, step 2 can be solved by reset (Student); Open the files > Found := false; WHILE NOT eof(Student) AND NOT Found DO BEGIN IF Studentt.Name = MovedAway THEN Found := true ELSE BEGIN TerapFileT := Studentt; put (TempFile) END; get (Student) END; { of search for a student name ■{ Now copy the rest of student file WHILE NOT eof(Student) > } DO BEGIN TempFilet := Studentt; put (TempFile); get (Student) END; We now need to copy TempFile to Student so that the revised master file is saved as an external file. A procedure for this was developed in Section 12.2; it is called from the main program by 536 FILES Copy (TempFile/ Student); As a second illustration of file manipulation,let's consider the standard problem of merging two sorted files. For example, suppose the master file is a file of records and each record contains a field for the name of a customer. Furthermore, assume this file has been sorted alphabetically by name. Now suppose an alphabetical listing of new customers is to be merged with the old file to produce a current file containing records for all customers sorted alphabetically by name. As before, we use a temporary file to hold the full sorted list and then copy the temporary file to the master file. This can be envisioned as illustrated in Figure 12.3. FIGURE 12.3 Merging files MasterList TfempFile NewList An algorithm for the merge is not too difficult. All files are first opened. Then the initial records from MasterList and NewList are compared. The record containing the name that comes first alphabetically is transferred to TempFile and the next record is obtained from the file containing the record that was transferred. This process continues until the end of one file is reached. At that time, the remainder of the other file is copied into TempFile. Assuming that each record has a field identified by Name, which is of type StringSO, and that FileType has been defined as the type for files being used, a procedure for merging is PROCEDURE Merge (VRR Master, NewFile : FileType); VRR TempFile : FileType; BEGIN reset (Master); reset (NewFile); rewrite (TempFile); WHILE NOT eof(Master) AND NOT eof(NewFile) DO BEGIN IF Mastert.Name "HOURS" :10); 544 FILES writeln (Skip:ID, ' '); writeln; i Now read the transaction file > WHILE NOT eof(TransactionFile) DO BEGIN FOR J := 1 TO q DO read (TransactionFile, IDNuraberlJ]); readln (TransactionFile, Grade, CourseHours); Index := SeqSearch(Student, IDNumber, NumberOfRecords); MatchFound := Index □; IF MatchFound THEN WITH -C Studentllndex] CASE Grade 'R' Update student record > DO OF : BEGIN GPR := NewGPR(Hours, CourseHours, Hours := Hours + GPA, 4.0); GPR, 3.G); GPR, 5.D); GPR, l.D); GPR, □.□); CourseHours END; •B' : BEGIN GPR := NewGPR(Hours, Hours := Hours + Coursehours, CourseHours END; •C : BEGIN GPR := NewGPR(Hours, Hours := Hours + CourseHours, CourseHours END; •D> : BEGIN GPR := NewGPR(Hours, Hours := Hours CourseHours, + CourseHours END; •E' : BEGIN GPR := NewGPR(Hours, Hours := Hours + CourseHours, CourseHours END; •W', do nothing } ELSE } END END END; { { { 'I' of : CRSE •{ Grade of WHILE NOT eof > (TransactionFile) of PROCEDURE UpdateRecords > } PROCEDURE PrintList (VRR Student: StudentList; NumberOfRecords : integer); { Given: Task: Return: Rn array of student records and number of records Print a list of records with appropriate heading Nothing > > > VRR J : integer; BEGIN •{ Print a heading for the revised list writeln; writeln; writeln ( 'UPDRTED REPORT' :3D); writeln ( 'STUDENT FILE LISTING' :3 ^4 12.3 Files with Structured Components writeln 'ID NUMBER':a5, 'GPA' rfi, •CREDITS 545 ID); writeln (' '); writeln; { Now print the list > FOR J := 1 TO NuraberOfRecords DO WITH StudentCJ] DO writeln (Name:ED/ IDNuraber:15/ GPA:fl:2/ Hourstfl) END; { of PROCEDURE PrintList > ^ •{********♦***********************************************♦*****#> PROCEDURE UpdateMasterFile (VAR MasterFile : RecordsFile; VAR Student : StudentList; NuinberOfRecords : integer); i > VAR J : > 5 integer; BEGIN rewrite (MasterFile); FOR J := 1 TO NumberOfRecords DO BEGIN MasterFilet := StudenttJ]; put (MasterFile) END END; ■{**********♦♦******************»*♦*******♦**************»*******> BEGIN OpenFiles (MasterFile, TransactionFile); LoadArray (MasterFile, Student, NumberOfRecords); UpdateRecords (TransactionFile, Student, NumberOfRecords); PrintList (Student, NumberOfRecords); UpdateMasterFile (MasterFile, Student, NumberOfRecords) END. If you use data in MasterFile as BARRETT RODA BORGNINE CADABRA ERNIST ABRA DJIKSTRA EDGAR GARZELONI GLUTZ HUNTER HALL MICHAEL JOHNSON ROSALYN LOCKLEAR 3.b7 E3 3bq3asat3 A,IS lA lS3 > 13.1 Recursion 559 BEGIN read (Data, OneChar); IF OneChar ' . ' THEN StackltUp; write (OneChar) END; { of PROCEDURE StackltUp BEGIN i Nain program reset (Data); StackltUp; } } writeln END. -{ of main program > Output from this program is .ecnetnes trohs a si sihT In this program, as each character is read, it is placed on a stack until the period is encountered. At that time, the period is printed and then, as each level in the stack is passed through in reverse order, the character on that level is printed. The stack created while this program is running is illustrated in Figure 13.3. FIGURE 13.3 Stack created by PROCEDURE StackltUp 560 RECURSION. SORTING. AND MERGING EXAMPLE 13 3 —— consider another example of a recursive function. Recall, the factorial qJ ^ nonnegative integer, n, is defined to be l!tc2*3*...*(w — 1] * n and is denoted by n!. Thus, 4! = 1*2*3*4 For the sake of completing this definition, l! = 1 and 0! = 1. A recursive function to compute n! is FUNCTION Factorial (N : integer) : integer; BEGIN IF N = □ THEN Factorial := 1 ELSE Factorial END; { := N * Factorial(N-1) of FUNCTION Factorial > If this function is called from the main program by a statement such as Product := Factorial(^); we envision the levels of recursion as 1. Factorial := 4 * Factorial(3) 2. Factorial := 3 * Factorial!5) 3. Factorial := E » Factorial!1) 4. Factorial := 1 * Factorial!0) 5. Factorial!□) "= 1 Successive values would then be assigned in reverse order to produce 5. 3. 2. 1. Factorial!□) 4. Factorial := 1 * Factorial := S * 1 Factorial Factorial := 3 := 4 * 1 1 B * t ■ Why Use Recursion? You may have noticed that the previous recursive functions Sigma and Factorial could have been written using iteration rather than recursion. For example, we could write FUNCTION IterSigma !N : integer) : integer; VRR J, Sura : integer; BEGIN Sura := □; FOR J Sura := 1 TO N DO := Sura + J; IterSigraa := Sum END; It is not coincidental that the recursive function Sigma can be rewritten using the iterative function IterSigma. In fact, any recursive subprogram can be rewritten in a nonrecursive manner. Furthermore, recursion gen erally requires more memory than equivalent iteration and is usually difficult for beginning programmers to comprehend. Why then do we use recursion? There are several reasons. First, a recursive thought process may be the best way to think about solving the problem. If so, it naturally 13.1 Recursion 561 leads to using recursion in a program. A classical example of this is the Towers of Hanoi problem, which requires a sequence of moving disks on pegs. This problem is fully developed as our next example. Second, some recursive solutions can be very short compared to iter ative solutions. In some instances, use of a recursive algorithm can be very simple, and some programmers consider recursive solutions elegant because of this simplicity. Third and finally, subsequent work in Pascal can be aided by recursion. For example, one of the fastest sorting algorithms available,the quick sort, uses recursion (see Section 13.2). Also, you must be able to use recursion when working with dynamic data structures (Chapter 15). In summary,recursion is a powerful and necessary programming tech nique. You should therefore become familiar with using recursive sub programs, be able to recognize when a recursive algorithm is appropriate, and be able to implement a recursive subprogram. EXAMPLE 13.4 A classic problem called the Towers of Hanoi problem involves three pegs and disks as depicted in Figure 13.4. The object is to move the disks from peg A to peg C. The rules are that only one disk may be moved at a time and a larger disk can never be placed on a smaller disk.(Legend has it that this problem—^but with 64 disks—^was given to monks in an ancient monastery. The world was to come to an end when all 64 disks were in order on peg C.) FIGURE 13.4 Towers of Hanoi problem C r A C To see how this problem can be solved, let's start with a one-disk problem. In this case, merely move the disk from peg A to peg C. The two-disk problem is almost as easy. Move disk 1 to peg B, disk 2 to peg C, and use the solution to the one-disk problem to move disk 1 to peg C. (Note the reference to the previous solution.) Things get a little more interesting with a three-disk problem. First, use the two-disk solution to get the top two disks in order on peg B. Then move disk 3 to peg C. Finally, use a two-disk solution to move the two disks from peg B to peg C. Again, notice how a reference was made to the previous solution. By now you should begin to see the pattern for solving the problem. However, before gener alizing, let's first look at the four-disk problem. As expected, the solution is to 1. use the three-disk solution to move three disks to peg B. 2. move disk four to peg C. 3. use the three-disk solution to move the three disks from peg B to peg C. This process can be generalized as a solution to the problem for n disks. 1. use the [n -l)-disk solution to move (n -1) disks to peg B. 2. move disk n to peg C. 3. use the [n — l)-disk solution to move (n — 1) disks from peg B to peg C. This general solution is recursive in nature because each particular solution de pends on a solution for the previous number of disks. This process continues until 562 RECURSION, SORTING, AND MERGING there is only one disk to move. This corresponds to the stopping state when a recursive program is written to solve the problem. A complete interactive program that prints out each step in the solution to this problem is PROGRAM TowersOfHanoi (input, output); t i This program uses recursion to solve the classic of Hanoi problem. Towers } > VRR NumDisks : integer; ■{*********************♦**************+************************** !■ PROCEDURE ListTheMove (NumDisks : integer; StartPeg, LastPeg, SparePeg { Given: The number of disks to move, i i, { : char); the initial peg FirstPeg, the working peg SparePeg, and Task: the destination peg LastPeg Move NumDisks from FirstPeg to LastPeg using Return: Nothing of PROCEDURE ListTheMove > BEGIN -t Main program > write ('How many disks in this game? ' ); readln (NumDisks); writeln; writeln ('Start with ', NumDisks, ' disks on Peg R' ); writeln; writeln ('Then proceed as follows: '); writeln; ListTheMove (NumDisks, END. 'R', > 'C, 'B') Sample runs for three-disk and four-disk problems produce the following: How many disks in this game? Start with 3 disks on Peg R Then proceed as follows: Move a disk Move a disk Move a disk Move a disk from from from from R to C R to B C to B R to C Move a disk from B Move a disk from B to C Move a disk from to R to R c 3 13.1 Recursion 563 How many disks in this game? Start with Then Exercises 13.1 Move a disk from A to B Move a disk from A to C Move a disk from B to C Move a disk from A to B Move a disk from C to Move a disk from C to B Move a disk from A to B Move a disk from A to C Move a disk from B to C Move a disk from B to A Move a disk from C to A Move a disk from B to C Move a disk from A to B Move a disk from A to C Move a disk from B to C A l. Explain what is wrong with the following recursive function: FONCTION Recur (X : real) : real; BEGIN Recur := Recur(X / 5) END; 2. Write a recursive function that reverses the digits of a positive integer. If the integer used as input is 1234, output should be 4321. 3. Consider the following recursive function: FONCTION A (X : real; N : integer) : real; BEGIN N = □ IF A := THEN l.D ELSE A END; := X * A(X, N-1) i of FONCTION A > a. What would the value of Y be for each of i. ii. iii. iv. Y := A(3.D, E); Y := A(5.0/ 3) ; Y ;= A( 2 the nth term is the sum of the previous two. Write a recur sive function to compute the nth term in the Fibonacci sequence. 5. Write a function that uses iteration to compute n!. g] g| SI SI 564 RECURSION. SORTING, AND MERGING H 13.2 Several algorithms are available for sorting elements in arrays and files. Sorting We have worked with the selection sort since Chapter 9. Three other sorting methods commonly used in programming texts are the insertion sort, the bubble sort, and the quick sort. All of these sorts work relatively well for sorting small lists of elements. However, when large data bases need to be sorted, a direct application of an elementary sorting process usually requires a great deal of computer time. Thus, some other sorting method is needed. This might involve using a different algorithm or dividing the lists into smaller parts, sorting Algorithms OBJECTIVES As expected, records can be sorted by examining some key field and then assigning the entire record accordingly. Thus, if an array type is TYPE Studentlnfo = RECORD Name : StringED; Score : integer END; { of RECORD Studentlnfo > List = ARRAY Cl..ListLength] OF Studentlnfo; and the array is to be sorted according to student scores, the field com parison in PROCEDURE InsertSort could be IF ACJ].Score RightArrow is true. Since this is still false at this point, the next RightArrow move produces Pivot 4 3 2 2 5 8 0 11 T T LeftArrow RightArrow 9 14 20 570 RECURSION,SORTING, AND MERGING and the LeftArrow move to the right yields Pivot i 4 3 2 2 5 8 0 11 9 14 20 T T LeftArrow RightArrow Since LeftArrow 4 3 2 2 5 0 8 11 9 14 20 T t LeftArrow RightArrow Notice that the pivot, 8, has been exchanged to occupy a new position. This is acceptable because Pivot is the value of the component, not the index. As before, RightArrow is moved left and Left Arrow is moved right to produce Pivot 4 3 2 2 5 0 8 11 9 14 20 T t RightArrow LeftArrow Since RightArrow 11 smaller numbers 9 14 20 larger numbers Each sublist can now he sorted by the same procedure. This would require a recursive call to the sorting procedure. In each case, the array is passed as a variable parameter together with the right and left indices for the appropriate suhlist. A procedure for this sort is PROCEDURE Quicksort (VftR Num : List; Left, Right : integer); VAR Pivot, Temp, LeftArrow, RightArrow : integer; BEGIN LeftArrow := Left; RightArrow := Right; Pivot := Nurat(Left + Right) DIV El; REPEAT WHILE NuraCRightArrow] > Pivot DO RightArrow := RightArrow - 1; WHILE NumCLeftArrow] LeftArrow := LeftArrow + 1; IF LeftArrow UNTIL RightArrow A complete interactive program to illustrate the use of quick sort follows. The design for this program is 1. Fill the array 2. Sort the numbers 3. Print the list The complete program is PROGRAM UseQuickSort (input, output); t Recursive calls are made to the PROCEDURE Quicksort. > CONST MaxLength = 30; TYPE List = ARRAY [1..MaxLength] OF integer; VAR Num : List; First, Last, Length : integer; PROCEDURE FillArray (VAR Num : List; VAR Length : integer); IF Ch IN Alphabet THEN SentenceChar := SentenceChar + [Chi END; i of WHILE NOT eoln(Data) > •{***#♦♦*»*********♦*********♦♦********************************** PROCEDURE PrintSet (SentenceChar : AlphaSyrabols); ■( > VAR Ch : char; BEGIN writeln (Skip:10/ writeln; FOR Ch := IF Ch 'The letters in this line are: ' ); write (Skip:ID); 'A' IN write TO 'z' DO SentenceChar THEN (Ch:5); writeln END; { of PROCEDURE PrintSet > {»******************♦*♦*****************************************} FUNCTION Cardinality (SentenceChar : AlphaSymbols) { { Given: Task: A set of characters Determine the number of characters } > VAR Ct : integer; X : char; 3 BEGIN Ct := D; FOR X IF := X Ct IN 'A' i 'Z' DO THEN := Ct + 1; Cardinality END; TO SentenceChar := Ct of FUNCTION Cardinality > J •{********♦**********♦*****************♦*******♦♦**+*************)■ PROCEDURE PrintMessage (SetSize : integer); Vi^en working with hiike^d^ hsts, the idenUfier Next is hequently hsed as the: name of the field JiX ithe 'iecoid that isuthe -ppinter VOTiahle' T remind you that you are pointiUg to' the next reGordi It m^eshodh s^ more meaningful. is to 15.2 Linked Lists 611 and the variable declaration section VRR Start/ Last/ Ptr : DataPtr; we can generate the desired list by BEGIN new (Start); Ptr := Start; FOR J := 1 TO ■( 4 Pointer to first node > DO BEGIN new (Last); Ptrt.Next Ptr := END; Ptrt.Next := Last; Last := NIL; Let's now examine what happens when this segment of code is executed. new (Start); causes Start Startt Ptr := Start; produces Start Ptr StartT Ptrt Now that we have started our list, the first pass through the FOR loop produces results as shown in Table 15.1. In a similar fashion, the second time through the loop causes the list to grow as shown in Table 15.2. As you can see, each pass through the body of the FOR loop adds one element to the linked list and causes both Ptr and Last to point to the last node of the list. After the loop has been executed four times, we have the following list: Start Ptr Last Lastt Ptrt At this Stage, the loop is exited and Ptrt.Next := NIL; 612 DYNAMIC VARIABLES AND DATA STRUCTURES TABLE 15.1 Adding a second Code Result node to a linked list Start T PtrT Ptrt.Next := Last; Start Lastt Ptr Start t Ptrt Ptr := Last; Start Lastt Ptr Start t TABLE 15.2 Adding a third node to a linked list Start Start t Ptrt.Next := Last; Start Start t Ptr := Last; Last Lastt Ptrt Result Code new (Last); Last Start Ptr Ptrt Ptr Ptrt Ptr Last Lastt Last Lastt Last m Start t Lastt Ptrt 15.2 Linked Lists 613 produces Start Ptr Last NIL Lastt Ptrt Start t Now when we process the list, we can check the field name Next to determine when the end of the list has been reached. In this sense, NIL is used in a manner similar to eof with files. EXAMPLE 15.1 Let's now create a linked list that can be used to simulate a deck of playing cards. We need 52 nodes,each of which is a record with a field for the suit(club,diamond, heart, or spade); a field for the number (1 to 13); and a field for the pointer. Such a record can be defined as TYPE Pointer = tCard; Suits = (Club, Diamond, Heart, Spade); Card = RECORD Suit Suits; Num : 1..13; Next END; { Pointer of RECORD Card As before, we need three pointer variables; they can be declared as VAR Start, Last, Ptr : Pointer; If an ace is represented by the number 1, we can start our list by BEGIN new (Start); Startt.Suit := Club; Startt.Nura := 1; Ptr := Start; Last := Start; This beginning is illustrated by Start Ptr Last ' >• ■ Club 1 Start! PtrT Last! We can then generate the rest of the deck by FOR J := E TO 5S DO BEGIN new (Last); IF PtrT.Num = 13 THEN Start a new suit BEGIN Lastt.Suit := succ(PtrT.Suit); Lastt.Num := 1 END ELSE 614 DYNAMIC VARIABLES AND DATA STRUCTURES BEGIN Lastt.Sult := PtrT.Suit; Lastt.Num := Ptrt.Num + 1 END; Ptrt.Next := Last; Ptr := Last END; Ptrt.Next := NIL; The first time through this loop we have Start Ptr Club Club Start t Last Lastt Ptrt This loop is processed all 51 times and then exited so that when Ptrt.Next := NIL; is executed, we have the list shown in Figure 15.5. FIGURE 15.5 Start A linked list simulat Start t Club ing a deck of cards Club 2 T Club 13 T Diamond 1 ■ Diamond 13 ■ Heart 1 ■ 13 T • • • Heart i Spade Spade 1 1 f 13 NIL Printing from a Linked List Thus far, we have seen how to create a dynamic structure and assign data to components of such a structure. We conclude this section with a look at how to print data from a linked list. 15.2 Linked Lists 615 The general idea is to start with the first component in the list, print the desired information, and then move sequentially through the list until the last component (NIL) is reached. There are two aspects of this algo rithm that need to be examined. First, the loop control depends on ex amining the current record for the value of NIL in the pointer field. If P is used to denote this field, we have WHILE P NIL DO BEGIN END; Second, the loop increment is to assign the pointer (?) used as a loop control variable the value of the Next field of the current record. To il lustrate, assume we have the definitions and declarations used previously to form a list of student names. If we declare the variable P by vaR P : DataPtr; we can then print the names by BEGIN > NIL DO BEGIN writeln (Pf.Narae: In general, printing from a linked list is done with a procedure. When a procedure is used, only the external pointer (Start, in our examples) needs to be used as a parameter. An additional loop control variable (P) needs to be declared. To illugtrate, a procedure to print the previous list of names is PROCEDDRE PrintNames (Start : DataPtr); VAR P : DataPtr; BEGIN P := Start; WHILE P NILjDO BEGIN writeln P := (Pt.Name:4D); Pt.Next END END; ■( of PROCEDURE PrintNames > This would be called from the main program by PrintNames Exercises 15.2 (Start); l. Discuss the differences and similarities between arrays and linked lists. 2. Write a test program to transfer an unknown number of integers from a data file into a linked list and then print the integers from the linked list. 3, Write a procedure to be used with the test program in Exercise 2 to print the integers. 616 DYNAMIC VARIABLES AND DATA STRUCTURES 4. Explain why a linked list is preferable when you are getting an unknown number of data items from a data file. 5. Suppose you are going to create a linked list of records where each record in the list should contain the following information about a student: name, four test scores, ten quiz scores, average, and letter grade. a. Define a record to be used for this purpose. b. What pointer type(s) and pointer variable(s) are needed? c. Assume the data for each student is on one line in the data hie as 97 98 85 90 9 8 7 10 6 9 10 8 9 71 Smith Mary i. Show how to get the data for the first student into the hrst component of a linked list. ii. Show how to get the data for the second student into the second component. 6. Why are three pointers (Start, Last, Ptr) used when creating a linked list? 7. Consider the dehnitions and declarations TYPE P = TNode; Node = RECORD Num : integer; Next : P END; VRR R/ B, C : P; a. Show how the schematic A B 2 C « ■— 3 NIL would be changed by each of the following: 1. ii. iii. iv. V. vi. R := Rt .Next; B := R; C := Rt .Next; ST.Num := Ct.Num; Rt.Num := Bt .Nextt .Num; Ct .Next := R; b. Write one statement to change A NIL to B NIL 15.3 Working with Linked Lists 617 8. Assume the definitions and declarations in Exercise 7. Indicate the output for each of the following: a. new (A) new (B) AT.Num = ID; BT.Num = EG; B := A; b. At.Num = 5 writeln (At Num/ Bt.Num) new (C) Ct.Num = IDG new (B) = Ct.Num Bt.Num MOD fl new (A) At.Num = Bt.Num + Ct.Num; writeln (At.Num/ Bt.Num/ Ct.Num) new (A) new (B) At.Num = ID; At.Next := B; At.Nextt.Num := IDD; writeln (At.Num/ Bt.Num); 9. Write a function Sum to sum the integers in a linked list of integers. Show how it is called from the main program. @ [9 ^ BO 15.3 Working with Linked Lists OBJECTIVES □ to be able to insert an element into a linked list m to be able to delete In this section, we examine some of the basic operations required when working with linked lists. Working with a list of integers, we see how to create a sorted list. We then update a linked list by searching it for a certain value and deleting tl^t element from the list. The following TYPE definition is used for most of this section. TYPE DataPtr = tNode; Node = RECORD Num : Next an element from a integer; : DataPtr END; linked list □ to be able to update an ordered linked Since most of the operations we examine will be used later, procedures are written for them. list □ to be able to search a linked list for an The dynamic nature of a linked list implies that we are able to insert an element into a list. The three cases considered are inserting an element at the beginning, in the middle, and at the end. element STYLE TIP IS s Inserting an Element When working with linked lists of records. Node is frequently used as the @ @ m record identifier. This facilitates readability of program comments. Thus, comments such as "Get new node," "Insert a node," and "Delete a node - are meaningful. 618 dynamic variables and data structures The procedure for inserting at the beginning of a list is commonly called push. Before writing code for this procedure, let's examine what should he done with the nodes and pointers. If the list is illustrated by Last Start _ 15 10 5 20 NIL and we wish to insert at the beginning, we need to get a new node by new (P); assign the appropriate value to Num Pt.Num := 3; and reassign the pointers to produce the desired result. After the first two steps, we have the list shown in Figure 15.6. FIGURE 15.6 Last Start An assigned value in 11 a new node 10 20 15 NIL Pt Pt.Next := Start; yields the list shown in Figure 15.7. FIGURE 15.7 Last Start Assigning a pointer to the first node of a linked list 10 5 P 15 20 NIL Pt Then start := P; yields the following, in which the Push is now complete. Last Start 3 5 10 A procedure for this can now he written as 15 20 NIL 15.3 Working with Linked Lists 619 PROCEDURE Push (VfiR Start : DataPtr; NewNum : integer); VRR P : DataPtr; BEGIN new (P); PT.Num := NewNum; PT.Next := Start; > } END; This procedure can be called from the main program by Push (Start/ 3); A note of caution is in order. This procedure is written assuming there is an existing list with NIL assigned to the pointer in the final node. If this is used as the first step in creating a new list, the assignment start := NIL; must be previously made. The basic idea for inserting a node somewhere in a linked list other than at the beginning or end is: get a new node, find where it belongs, and put it in the list. In order to do this, we must start at the beginning of a list and search it sequentially until we find where the new node belongs. When we next change pointers to include the new node, we must know between which pair of elements in the linked list the new node is to be inserted. Thus, if 12 is to be inserted in an ordered linked list such as Start Last 11 15 20 NIL we need to know that the link is in the list. Once this pair has been identified, the pointers will be changed to produce 10 15 12 so that the new list with the new node inserted will be Start Last 11 12 15 20 NIL Let's now see how this can be done. We can get a new node by new (P); PT.Num := NewNum; 620 DYNAMIC VARIABLES AND DATA STRUCTURES In order to find where it belongs, we need two pointer variables to keep track of successive pairs of elements as we traverse the list. Assume Before and Ptr have been appropriately declared. Then WHILE Ptrt.Num New (P); Pt.Num := NewNum; { Find where it belongs; assume not at end > NIL 15.3 Working with Linked Lists 621 Ptr := Start; WHILE Ptrt.Num NewNum THEN Looking := false ELSE BEGIN Before := Ptr; Ptr := Ptrt.Next END; Pt.Next := Ptr; Beforet.Next := P; Last := P; To see how this permits insertion at the end of a list, suppose NewNum is 30 and the list is Start 10 Last 20 25 NIL 622 DYNAMIC VARIABLES AND DATA STRUCTURES The initialization produces the list illustrated in Figure 15.10. Since Ptr NIL and Looking is true, the loop would be entered. PtrT.Num > NewNum (10 > 30) is false, so the ELSE option is exercised to produce the list shown in Figiue 15.11. At this stage, Ptr NIL and Looking is still true, so the loop is entered again. Ptr t.Num > NewNum (20 > 30)is false,so the ELSE option produces the list illustrated in Figure 15.12. Since Ptr is not yet NIL,Ptr NIL and Looking is true, the loop is entered, Ptrt.Num > NewNum is false, so the ELSE option produces the list shown in Figure 15.13. Now the condition Ptr NIL is false, so control is transferred to Pt .Next := Ptr; When this and the two lines of code following it are executed, we get the arrangement shown in Figure 15.14. FIGURE 15.10 Start Last Getting a new node for a linked list Pt _ 10 30 20 25 NIL Ptr FIGURE 15.11 Start Last Positioning Before and Ptr PT 10 30 FIGURE 15.12 20 t 1 1 1 Before Ptr Start 25 NIL Last Moving Before and Ptr Pt 30 10 FIGURE 15.13 20 25 Before Ptr Start NIL Last Before and Ptr ready for insertion Pt 30 10 20 25 NIL NIL Before Ptr 15.3 Working with Linked Lists FIGURE 15.14 Start 623 Last Insertion at end of linked list is complete 20 10 25 30 NIL NIL Before Ptr One final comment is in order. A slight modification of this procedure accommodates inserting at the beginning of a list. You may choose to reserve Push for this purpose. However, if you want a single procedure that will insert anywhere in a linked list, it is PROCEDURE Insert (VAR Start, Last : DataPtr; NewNura : integer); VAR P, Ptr, Before : DataPtr; Looking : boolean; BEGIN { Initialize > new (P); Pl.Nura := NewNum; Before := NIL; Ptr := Start; Looking := true; WHILE (Ptr NIL) and Looking DO IF Ptrt.Nura > NewNura THEN Looking := false ELSE BEGIN Before := Ptr; Ptr := PtrT.Next END; PT-Next := Ptr; Beforet.Next := P; IF Before = Last THEN Last := P END END; EXAMPLE 1S.2 To illustrate how PROCEDURE Insert can be used to create a linked list of integers sorted from high to low, let's develop a short program to read integers from a data file, create a linked list sorted from high to low, and print contents of components in the linked list. A first-level pseudocode development of this is 1. Create the list 2. Print the list 624 DYNAMIC VARIABLES AND DATA STRUCTURES Step 1 can be reiined to 1. Create the list 1.1 create the first node 1.2 WHILE NOT eof DO insert in the list Using procedures for inserting an element and printing the list, a program is PROGRAM LinkListPrac (input, output); > BEGIN { DataPtr; number to be inserted in numerical order in VAR P, > > > > 15.3 Working with Linked Lists i 625 }■ Now move the pointers IF Looking THEN Finish := Ptr; Pt.Next > new (Start); readln (Number); StartT.Num := Number; Startt.Next := NIL; new (Finish); Finish { Now := Start; create WHILE NOT the eof remainder of the list > DO BEGIN readln (Number); Insert (Start# Finish, Number) END; { of WHILE NOT eof > PrintList (Start) END. ■{ of main program > When this program is run on the data file 42l2| -10|0|45ll00|52|78|9l|99l86| the output is } y VAR P } list 626 DYNAMIC VARIABLES AND DATA STRUCTURES -ID □ E 4a 45 5E 7fl at, qi qq IGG Deleting a Node A second standard operation when working with linked lists is that of deleting a node. Let's first consider the problem of deleting the first node in a list. This process is commonly called pop. Before writing code for this procedure, however, let's examine what should he done with the pointers. Deleting the first node essentially requires a reversal of the steps used when inserting a node at the beginning of a list. If the list is Start Last 20 10 ■ ^ 30 40 NIL and you wish to produce a list as in Start Last 30 20 40 NIL you might think that start := Startt.Next; would accomplish this. Not true. There are two problems with this method. First, you may—and probably will—^want the value of some data fields returned to the main program. Thus, the appropriate fields need their values assigned to variable parameters. A second problem with this method is that the first node has not been returned to the computer for subsequent reuse. Since one of the advantages of using dynamic variables is not wasting unused storage, the procedure dispose should be used with this node. We can now write a procedure to delete the first node. Assuming the data value is to be returned to the main program, the procedure is PROCEDURE Pop (VAR Start : DataPtr; VAR Number : integer); VAR P : DataPtr; BEGIN P := Start; Move node > use > start Return > Pt to for next later 15.3 Working with Linked Lists 627 A NP^TE PE INTIREST Using Pointers Caution must be exercised when using pointers. Unless they are carefully described, it is easy to make a program hard to follow. Speaking to this point, Nazim H. Madhavji states:"It is often nec essary to traverse deeply into the structure in order to access the required data, as can be seen in the following example, using pointers Pi and P2: Such 'spaghetti-like' directions get more cum bersome as SomeType gets more complex.Often, access paths of this kind are diagrammatically represented with no absolute certainty of their correctness." He then continues, saying: "By raising the level of description of dynamic data structures, the visibility of these structures in programmed text can be increased." PI := PSt.IDTypet.ElementTypet.Fields The next kind of deletion we examine is when the list is searched for a certain key value and the node containing this value is to be removed from the linked list. For example,if the list contains records for customers of a company, you might want to update the list when a former customer moves away. To illustrate the process, suppose the list is Start Last 20 10 30 40 NIL and you wish to delete 30 The new list is Start Last 10 20 11 40 NIL 30 and the node deleted can he returned using dispose to produce Start 10 Last ■—^ 20 ■-h 40 NIL Our method of doing this uses two temporary pointers. One pointer searches the list for the specified data value and, once it is located, the second pointer points to it so we can use dispose to return it for subsequent use. If Before and P are the temporary pointers, the code is BEGIN Before WHILE := Start; Beforet.Nextt.Nura Before := Beforet.Next; P := Beforet.Next; Beforet.Next := Pt.Next; dispose (P) END; NewNum DO 628 DYNAMIC VARIABLES AND DATA STRUCTURES Let's now see how this deletes 30 from the previous list. Before := Start ; yields a list as illustrated in Figure 15.15. At this stage, NewNum is 30 and Before!.Nextt.Num is 20. Since these are not equal, the pointer Before is moved by Before := Beforet.Next; Thus, we have the list in Figure 15.16. Now Beforet.Nextt.Num = NewNum (30); so the WHILE loop is exited. P := Beforet.Next; produces the list shown in Figure 15.17. Beforet.Next := Pt.Next; yields the list in Figure 15.18. Finally, dispose (P); returns the node, so we have Start 10 FIGURE 15.15 Last —1 20 40 NIL Last Start Initializing Before 10 20 30 40 NIL Before FIGURE 15.16 Last Start Positioning Before 10 20 30 40 NIL Before FIGURE 15.17 Last Start Positioning P 10 20 Before 30 40 NIL 15.3 Working with Linked Lists FIGURE 15.18 Start 629 Last Reassigning a pointer 10 20 30 40 NIL Before This process can be combined with deleting the first node to produce the following procedure. PROCEDURE Delete (VAR Start : DataPtr; Number : integer); VAR Before/ P ; DataPtr; BEGIN IF Number = StartT.Nura THEN Pop (Start/ Number) ELSE BEGIN Before := Start; WHILE Before!.Nextt.Num Number DO Before := Beforet.Next; P := Beforet.Next; Beforet.Next := Pt.Next; dispose (P) END END; i of PROCEDURE Delete > This procedure can now be used to delete any node from a linked list. However, it will produce an error if no match is found. A modification to protect against this possibility is left as an exercise. Exercises 15.3 1. Illustrate how PROCEDURE Insert works when inserting a node in the mid dle of a linked list. 2. Write a test program to see what happens when Ptr is NIL and a reference is made to Ptr t. 3. Revise PROCEDURE Insert so that it calls PROCEDURE Push if a node is to be inserted at the beginning of a list. 4. Modify PROCEDURE Delete to protect against the possibility of not finding a match when the list is searched. 5. Modify PROCEDURE Pop so that no data value is returned when Pop is called. 6. Write a complete program to allow you to a. Create a linked list of records where each record contains a person's name and an amount of money donated to a local fund-raising group; the list should be sorted alphabetically. b. Use the linked list to print the donor names and amounts. c. Read a name that is to be deleted and then delete the appropriate record from the list. d. Print the revised list. 630 DYNAMIC VARIABLES AND DATA STRUCTURES 7. Modify PROCEDURE Delete to delete the nth node rather than a node with a particular data value. For exeunple, you might be asked to delete the fifth node. 8. Write a procedure to copy the integers in a linked list of integers into a file of integers. 9. Write a complete program that uses a linked list to sort a file of integers. Your program should create a sorted list, print the list, and save the sorted list for later use. Data Structures In this final section, we briefly examine some additional dynamic data structures: stacks, queues, and binary trees. The concepts behind them and their elementary use are emphasized. This section should serve as an introduction to these dynamic data structures. A suggested reading list is included for those wishing a more detailed development. n to understand why a stack is a dynamic Stacks ■ 15.4 Other Djmamic data structure a to understand how to use a stack in a program ■ to understand why a queue is a dy namic data structure ■ to understand how to use a queue in a program A stack can be implemented as a d5aiamic data structure in which access can be made from only one end. You can think of a stack as paper in a copying machine or trays at a cafeteria (as mentioned in the discussion on recursion in Chapter 13). In both cases, the last one in will be the first one out; that is, you put items in, one at a time, at the top and you remove them, one at a time, from the top. This last-in, first-out order is referred to as LIFO; stacks are therefore often termed LIFO structures. A stack can be envisioned as follows: ■ to understand why a binary tree is a dynamic data structure a to be able to create a binary search tree B to be able to search a binary search tree In this illustration, item E is considered the top element in the stack. The two basic operations needed for working with a stack are inserting an element to create a new stack top (Push) and removing an element from the top of the stack (Pop). If a stack is represented by a linked list. Push and Pop are merely "insert at the beginning" and "delete from the beginning" as developed in Section 15.3. To illustrate the use of a stack in a program, let's consider a program that will check an arithmetic expression to make sure that parentheses are correctly matched (nested). Our program considers (3 + A * (5 MOD 3)) to make sure that the number of left parentheses matches the number of right parentheses. A first-level pseudocode for this problem is 1. Read a character 2. IF it is a "(" THEN Push it onto the stack 3. IF it is a ")" THEN Pop the previous "(" 4. Check for an empty stack 15.4 Other Dynamic Data Structures 631 The growing and shrinking of the stack can be illustrated as shown in Table 15.3. TABLE 15.3 Using a stack Stack Before Read Character Read Stack After Character Processed 'Stack top *3b+b4b*b Stack top Stack top Stack top 5bMODb3 'Stack top 'Stack top *b represents a blank space. Two points need to be made concerning this program. First, since the stack is represented by a linked list, the illustration could have been Stack NIL Second, before Pop is used on a stack, a check must be made to make sure the stack is not already empty. Thus, the previous procedure Pop will be replaced by PopAndCheck in which a suitable error message will appear if we try to pop an empty stack. Let's now prepare code for the previous problem. The following defi nitions are used TYPE DataPtr = TNode; Node = RECORD Sym : char; Next : DataPtr END; VAR Stack : DataPtr; 632 DYNAMIC VARIABLES AND DATA STRUCTURES PROCEDURE Push is PROCEDURE Push (VRR Stack : DataPtr; Symbol : char); VAR P : DataPtr; BEGIN new (P); PT.Syra := Symbol; Pt.Next := Stack; Stack := P END; PROCEDURE PopAndCheck is PROCEDURE PopAndCheck (VAR Stack : DataPtr); VAR P ; DataPtr; BEGIN IF Stack = NIL THEN i Check for empty stack > writeln ('The parentheses are not correct.•:^D) ELSE BEGIN -C Pop the stack > P := Stack; Stack := Stackt.Next; dispose (P) END END; i of PROCEDURE PopAndCheck > With these two procedures, the main body of a program that examines an expression for correct use of parentheses is BEGIN Stack := NIL; WHILE NOT eoln DO BEGIN read (Symbol); IF Symbol = •(• THEN Push (Stack/ Symbol); IF Symbol = ')' THEN PopAndCheck (Stack) END; NIL THEN writeln ('The parentheses are not correct.': END. ) Several modifications of this short program are available and are suggested in the exercises at the end of this section. Queues A queue can be implemented as a dynamic data structure in which access can be made from both ends. Elements are entered from one end (the rear) and removed from the other end (the front). This first-in, first-out order is referred to as FIFO; queues are termed FIFO structures. A queue is like a waiting line. Think of people standing in line to purchase tickets: each new customer enters at the rear of the line and exits from the front. A queue implemented as a linked list can be illustrated as 15.4 Other Dynamic Data Structures Front 633 Rear NIL Basic operations needed for working with queues are remove an ele ment from the front of the list and insert an element at the rear of the list. If we use the definitions TYPE DataPtr = tNode; Node = RECORD Nuin : integer; Next : DataPtr END; we can use variables declared by VRR Front, Rear : DataPtr; when working with such a structure. Removing an element from the front of a queue is similar to PROCE DURE PopAndCheck used with a stack. The only difference is that after an element has been removed,if the queue is empty,Rear must be assigned the value NIL. A procedure for removing from the front of a queue follows. Here it is assumed that the value of the element removed is to be returned to the main program via a variable parameter. PROCEDURE Remove (VftR Front, Rear : DataPtr; VftR Number : Integer); VAR P : DataPtr; BEGIN IF Front = NIL THEN } ELSE BEGIN i Pop the queue > P := Front; Front := Frontt.Next; Number := PT.Num; dispose (P) END; IF Front = NIL THEN -C Set pointers for empty queue > Rear := NIL END; { of PROCEDURE Remove > This procedure is called from the main program by Remove (Front, Rear, Number); A procedure to insert an element at the rear of a queue (assuming there is at least one element in the queue) is similar to the procedure given in the previous section for inserting at the end of a linked list. You are asked to write the code as an exercise. Trees A tree can be implemented as a dynamic data structure consisting of a special node called a root that points to zero or more other nodes, each of which points to zero or more other nodes, and so on. In general, a tree 634 DYNAMIC VARIABLES AND DATA STRUCTURES can be visualized as illustrated in Figure 15.19. The root of a tree is its first, or top node. Children are nodes pointed to by an element, a parent is the node that is pointing to its children, and a leaf is a node that has no children. FIGURE 15.19 The general structure of a tree o o O o o Q Applications for trees include compiler programs,artificial intelligence, and game-playing programs. In general, trees can be applied in programs that call for information to be stored such that it can be retrieved rapidly. As illustrated in Figure 15.19, pointers are especially appropriate for im plementing a tree as a d3niamic data structure. An external pointer is used to point to the root and each parent uses pointers to point to its children. A more detailed tree is illustrated in Figure 15.20. Root FIGURE 15.20 Using pointers to create a tree y // t NIL NIL 15.4 Other Dynamic Data Structures 635 Binary Trees. From this point on, we restrict our discussion of trees to binary trees. A binary tree is a tree such that each node can point to at most two children. A binary tree is illustrated in Figure 15.21. FIGURE 15.21 A binary tree If a binary tree is used to store integer values, a reasonable definition for the pointer type is TYPE Pointer = TTreeNode; TreeNode = RECORD Info ; integer; RightChild : Pointer; LeftChild : Pointer END; A particularly important kind of binary tree is a binary search tree. A binary search tree is a binary tree formed according to the following rules: 1. The information in the key field of any node is greater than the information in the key field of any node of its left child and any 2. The information in the key field of any node is less than the infor children of the left child. mation in the key field of any node of its right child and any chil dren of the right child. Figure 15.22 illustrates a binary search tree. FIGURE 15.22 A binary search tree The reference to "search" is used because such trees are particularly efficient when semching for a value. To illustrate, suppose we wish to see whether or not 30 is in the tree. At each node, we check to see if the desired value has been found. If not,'we determine on which side to continue looking until either a match is found or the value NIL is en- 636 DYNAMIC VARIABLES AND DATA STRUCTURES countered. If a match is not found, we are at the appropriate node for adding the new value (creating a child). As we search for 30, we traverse the tree via the path indicated by heavier arrows. Notice that after only two comparisons (23), the desired value has been located, as il lustrated in Figure 15.23. FIGURE 15.23 Searching a tree for the value 30 Suppose we now search the tree for the value 65. The path (again indicated by heavier arrows) is shown in Figure 15.24. At this stage, the right child is NIL and the value has not been located. It is now relatively easy to add the new value to the tree. FIGURE 15.24 46 Searching a tree for the value 65 15 .20 Binary search trees can be used to store any data that can be ordered. For example, the registrar of a university might want to quickly access the record of a particular student. If the records are stored alphabetically by student name in a binary search tree, quick retrieval is possible. Implementing Binary Trees. We conclude this chapter with a relatively basic implementation of binary search trees: a program to create a binary search tree from integers in a data file. We print the integers in order using a variation of the general procedure for searching a tree. The operations of inserting and deleting nodes are left as exercises. Before developing algorithms and writing code for these implementa tions, we need to discuss the recursive nature of trees.(You may wish to reread Section 13.1 at this time.) When you move from one node to a right or left child, you are (in a sense) at the root of a subtree. Thus,the process of transversing a tree is 15.4 Other Dynamic Data Structures 637 1. IF LeftChild NIL THEN transverse left branch 2. Take desired action 3. IF RightChild NIL THEN transverse right branch Steps 1 and 3 are recursive; each return to them saves values associated with the current stage together with any pending action. If the desired action is to print the values of nodes in a binary search tree, step 2 is 2. Print the value and when this procedure is called, the result is to print an ordered list of values contained in the tree. If we use the previous definitions TYPE Pointer = tTreeNode; TreeNode = RECORD Info : integer; RightChild : Pointer; LeftChild : Pointer END; a procedure for printing is PROCEDURE PrintTree (T : Pointer); BEGIN IF T = NIL THEN ELSE BEGIN PrintTree (TT.LeftChild); writeln (Tl.Info); PrintTree (TT.RightChild) END END This procedure is called from the main program by PrintTree (Root); Notice how the recursive nature of this procedure provides a simple, efficient way to inspect the nodes of a binary search tree. The process of creating a binary search tree is only slightly longer than that for printing. A first-level pseudocode is 1. Initialize root to NIL 2. WHILE NOT eof DO 2.1 get a number 2.2 add a node A recursive procedure can be used to add a node. An algorithm for this is 2.2 add a node 2.2.1 if the current node is NIL, store the value and stop 2.2.2 if the new value is less than the current value, point to the left child and add the node to the left subtree 2.2.3 if the new value is greater than the current value, point to the right child and add the node to the right subtree Note that the recursive procedure to add a node adds only nodes con taining distinct values. A slight modification—left as an exercise—allows 638 DYNAMIC VARIABLES AND DATA STRUCTURES duplicate values to be included. A procedure for adding a node to a bineury search tree is PROCEDORE AddNode (VAR Node : Pointer; Number : integer); BEGIN IF Node = NIL THEN BEGIN new (Node); Nodet.Info := Number; NodeT.LeftChild := NIL; NodeT.RightChild := NIL END ELSE •( Hove down the tree IF Number Nodet.Info THEN AddNode (Nodet.LeftChild/ Number) ELSE AddNode (Nodet.RightChild/ Number) i of PROCEDURE AddNode > END; A complete program to read unordered integers from a data file, create a binary search tree, and then print an ordered list is as follows: PROGRAM TreePrac (input/ output); > } } TYPE Pointer = tTreeNode; TreeNode = RECORD Info : integer; RightChild : Pointer; LeftChild END; VAR Root : Number Pointer; i Pointer to indicate the tree root > : i Integer read from the data file > integer; PROCEDURE AddNode (VAR Node : Pointer; Number : integer); { i > > BEGIN IF Node = NIL THEN i Add a new node > down the tree > BEGIN new (Node); Nodet.Info := Number; Nodet.LeftChild := NIL; Nodet.RightChild := NIL END ELSE •( IF Number AddNode Number) Move 15.4 Other Dynamic Data Structures 639 PROCEDURE PrintTree (Node : Pointer); tc>K3lc3K>te>(e>iC3tC3|e4:3|c:|e:|c*34c:4t4c3|c:4c:|c:4c:tc:4c:4c:4c4c4c4c4c3tc:(c:|e:4e:(c4e4t4c:|c^:«c3tc:(c3(E:is4::4 > When this is run on the data file 16|8|-5|20|30|l0l|0|l0|l8| the output is -5 □ fi 10 IL la 20 30 101 Exercises 15.4 1. Using the program for checking parentheses (at the beginning of this sec tion), illustrate how the stack grows and shrinks when the following expression is examined. (S / (3 - a * (4 + 3) - (a DIV 2))) 2. Write a test program to check an arithmetic expression for correct nesting of parentheses. 3. Modify the program in Exercise 2 so that several expressions may be examined; then give more descriptive error messages. Finally, include a SET for the parentheses symbols "(" and ")". 4. Write a program that utilizes a stack to print a line of text in reverse order. 640 DYNAMIC VARIABLES AND DATA STRUCTURES 5. Stacks and queues can also be implemented using arrays rather than linked lists. With this in mind, a. Give appropriate definitions and declarations for using arrays for these data structures. b. Rewrite all procedmes using array notation. 6. Write a procedure for inserting an element at the rear of a queue. Illustrate changes made in the linked list when such a procedure is executed. 7. Write a program that uses a stack to check an arithmetic expression for cor rect use of parentheses "( ),'* brackets "[ ]," and braces "{ }." 8. Indicate which of the following are binary search trees. Explain what is wrong with those that are not. 15.4 Other Djmamic Data Structures 641 9. Modify PROCEDURE AddNode to include the possibility of having nodes equal in value. 10. Write a procedure to allow you to insert a node in a binary search tree. 11. Write a function to search a binary search tree for a given value. The func tion should return true if the value is found and false if it is not found. 12. Write a procedure to allow you to delete a node from a binary search tree. 13. Illustrate what binary search tree is created when PROGRAM TreePrac is run using the data file 25|l4|-3ll45|0|98|8l|73|85|92|56|2l| ■" @ RUNNING AND DEBUGGING TIPS g| 1. Be careful to distinguish between a pointer and its associated dynamic variable. Thus, if Ptr is a pointer, the variable is PtrT. 2. When a dynamic variable is no longer needed in a program, use dispose so that the memory location can be reallocated. 3. After using dispose with a pointer, its referenced variable is no longer available. If you use dispose (Ptr), then Ptrt does not exist. 4. Be careful not to access the referenced variable of a pointer that is NIL. Thus, if the assignment Ptr := NIL; is made, a reference to Ptrt.Info results in an error. 5. When using pointers with subprograms, be careful to pass the pointer, not the referenced variable, to the subprogram. 6. When creating dynamic data structures, be careful to initialize properly by assigning NIL where appropriate and keep track of pointers as your structures grow and shrink. 7. Operations with pointers require that they be of the same type. Thus, exercise caution when comparing or assigning them. 8. Values may be lost when pointers are inadvertently or prematurely reassigned. To avoid this, use as many auxiliary pointers as you wish. This is better than trying to use one pointer for two purposes. 642 DYNAMIC VARIABLES AND DATA STRUCTURES Summary Key Terms address (of a memory location) binary search tree binary tree FIFO leaf LIFO linked list push queue root static variable children node tree component dynamic structure parent pointer variable value (of a memory location) dynamic variable pop Keywords dispose new NIL Key Concepts ■ Values are stored in memory locations; each memory location has an address. ■ A pointer variable is one that contains the address of a memory location; pointer variables are declared by TYPE ftgeRange = □. .HR; VAR Ptr : tAgeRange; where the up arrow (T) or caret (*) is used before the predefined data type. ■ A djmamic variable is a variable that is referenced through a pointer variable; dynamic variables can be used in the same context as any other variable of that type, and they are not declared in the variable declaration section. In the declaration TYPE AgeRange = D. -RR; VAR Ptr : TAgeRange; the dynamic variable is Ptrt and is available after new (Ptr) is executed. ■ Dynamic variables are created by new (Ptr); and destroyed (memory area made available for subsequent reuse) by dispose (Ptr); ■ Assuming the definition TYPE AgeRange = □. .RR; VAR Ptr : TAgeRange; the relationship between a pointer and its associated dynamic variable is illustrated by the code new (Ptr); PtrT := El; which can be envisioned as 21 Ptr Ptr T ■ The only legal operations on pointer variables are assignments and compari son for equality. n NIL can be assigned to a pointer variable; this is used in a Boolean expres sion to detect the end of a list. Summary 643 Dynamic data structures differ from static data structures in that they are modified during the execution of the program. A linked list is a dynamic data structme formed by having each component contain a pointer that points to the next component; generally, each compo nent is a record with one field reserved for the pointer. A node is a component of a linked list. When creating a linked list, extra pointers are needed to keep track of the first, last, and newest component. When creating a linked list, the final component should have NIL assigned to its pointer field. Printing from a linked list is accomplished by starting with the first compo nent in the list and proceeding sequentially through the list imtil the leist component is reached; a typical procedure for printing from a linked list is PROCEDURE Print (First : DataPtr); VAR P : DataPtr; BEGIN P := First; WHILE P NIL DO BEGIN writeln (Pt.field name); P := Pt.Next END END; Inserting a node in a linked list should consider three cases: insert at the be ginning, insert in the middle, and insert at the end. Inserting at the beginning of a linked list is used frequently and is referred to as Push; one version of this is PROCEDURE Push (VAR Start : DataPtr; NewNura : integer); VAR P : DataPtr; BEGIN new(P); Pt.New := NewNum; PT.Next := Start; Start := P END; { of PROCEDURE Push } Searching an ordered linked list to see where a new node should be inserted is accomplished by Ptr := Start; WHILE Ptrt.Num 644 DYNAMIC VARIABLES AND DATA STRUCTURES ■ When a node is deleted from a linked list, it should be returned for subse quent use; this is done by using the standard procedure dispose. ■ A stack is a dynamic data structure where access can be made from only one end; stacks are referred to as LIFO (last-in, first-out) structures. a A queue is a dynamic data structure where access can be made from both ends; queues are referred to as FIFO (first-in, first-out) structures. a A tree is a dynamic data structure consisting of a special node (called a root) that points to zero or more other nodes, each of which points to zero or more other nodes, and so on. Trees are represented sjrmbolically as A root is the first or top node of a tree. Trees are particularly useful in programs that use data that can be ordered and that need to be retrieved quickly. Binary trees are trees where each node points to at most two other nodes; parent, right child, and left child are terms frequently used when working with binary trees. An illustration of a binary tree is Binary search trees are binary trees in which the information in any node is greater than the information in any node of its left child and any children of the left child and the information in any node is less than the information in any node of its right child and any children of the right child. An illustration of a typical binary search tree is Programming Problems 645 Recursive procedures can be used when working with trees; to illustrate, the values in the nodes of a binary search tree can he printed (sequentially) with the following procedure: PROCEDURE PrintTree (Node : Pointer); BEGIN IF Nodet.LeftChild NIL THEN PrintTree (Nodet.LeftChild); writeln (Nodet.Info); IF Nodet.RightChild NIL THEN PrintTree (Nodet.RightChild) END; ■ Suggestions for Further Reading Programming Problems Nance, Douglas W., and Thomas L. Naps Introduction to Computer Science: Pro gramming,Problem Solving, and Data Structures. St. Paul, MN:West Publishing Company, 1989. Naps, Thomas L., and Bhagat Singh. Program Design with Pascal: Principles, Al gorithms, and Data Structures. St. Paul, MN: West Publishing Company, 1988. Naps,Thomas L., Nance,Douglas W.,and Bhagat Singh.Introduction to Computer Science: Programming, Problem Solving, and Data Structures, Alternate edition. St. Paul, MN: West Publishing Company, 1989. Singh, Bhagat, and Thomas L. Naps.Introduction to Data Structures. St. Paul, MN: West Publishing Company, 1985. Tenenbaum, Aaron M., and MosheJ. Augenstein. Data Structures Using Pascal. Englewood Cliffs, NJ: Prentice-Hall, Inc., 1981. l. Creating an index for a textbook can be accomplished by a Pascal program that uses dynamic data structures and works with a text file. Assume that input for a program is a list of words to be in cluded in an index. Write a program that scans the text and pro duces a list of page numbers indicating where each word is used in the text. 2. One of the problems faced by businesses is how best to memage their lines of customers. One method is to have a separate line for each cashier or station. Another is to have one feeder line where all cus tomers wait and the customer at the front of the line goes to the first open station. Write a program to help a manager decide which method to use by simulating both options. Your program should al low for customers arriving at VEirious intervals. The manager wants to know the average wait in each system, average line length in each system (because of its psychological effect on customers), and the longest wait required. 3. Write a program to keep track of computer transactions on a main frame computer. The computer can process only one job at a time. Each line of input contains a user's identification number, a starting time, and a sequence of integers representing the duration of each job. Assume all jobs are run on a first-come, first-served basis. Your output should include a list of identification numbers, the starting and finishing times for each job, and the average waiting time for a transaction. 4. Several previous programming problems have involved keeping records and computing grades for students in some class. If linked 646 DYNAMIC VARIABLES AND DATA STRUCTURES lists are used for the students' records, such a program can be used for a class of 20 students or a class of 200 students. Write a record- keeping program that utilizes linked lists. Input is from an unsorted data file. Each student's information consists of the student's name, ten quiz scores, six program scores, and three examination scores. Output should include: a. A list, alphabetized by student name, incorporating each stu dent's quiz, program, and examination totals; total points; per centage grade; and letter grade. b. Overall class average. c. A histogram depicting the class average. 5. Modify the program you developed for Readmore Public Library (Problem 6, Chapter 11 and Problem 2, Chapter 13) to incorporate a djmamic data structure. Use a linked list to solve the same problem. 6. Mailing lists are frequently kept in a data file sorted alphabetically by customer name. However, when they are used to generate mailing labels for a bulk mailing, they must be sorted by zip code. Write a program to input an alphabetically sorted file and produce a list of labels sorted by zip code. The data for each customer are a. Name. b. Address, including street (plus number), city, two-letter abbrevia tion for the state, and zip code. c. Expiration information, including the month and year. Use a binary tree to sort by zip code. Yom labels should include some special symbol for all expiring subscriptions.(See Problem 1, Chapter 13.) Appendixes 1 Reserved Words 2 Standard Identifiers 3 Sjmtax Diagrams 4 Character Sets 5 Compiler Error Messages 6 Hirbo Pascal Notes 7 GOTD Statement A.l Appendix 1 Reserved Words The following words have predefined meanings in standard Pascal and cannot be changed. Each of these, except GOTO and LABEL, have been developed in the text. These statements are discussed in Appendix 7. AND END MOD REPEAT ARRAY FILE NIL SET BEGIN FOR NOT THEN CASE FORWARD OF TO CONST FUNCTION OR TYPE DIV GOTO PACKED UNTIL DO IF PROCEDURE VAR DOWNTO IN PROGRAM WHILE ELSE LABEL RECORD WITH Appendix 2 Standard Identifiers The standard identifiers for constants, types, files, functions, and procedures are set forth in this appendix. All have predefined meanings that could (but probably should not) he changed in a program. Summary descriptions are given for the functions and procedures. Constants Types Files false boolean input maxint char output true integer real text Functions Parameter Result Type Type Function abs(x) arctan(jc) integer integer real real integer real real chr(a) cos(x) integer integer Value Returned Absolute value of x Arctangent of x (radians) char Chsuacter with ordinal a real Cosine of x (radians) file boolean file boolean End-of-file test for F End-of-line test for F integer integer real e* real Natural logeirithm of x real eoffF) eoln(F) exp(x) ln(x) real odd(a) ord(x) pred(x) round(x) integer boolean Tests for a an odd integer nonreal scalar integer nonreal scalar same as x real integer Ordinal number of x Predecessor of x Rounds off X / ..3 A.4 Appendix 2 Standard Identifiers Parameter Type Function sin(x) integer Result Value Returned Type real Sine of x integer integer Square of x real real integer real Square root of x nonreal scalar same as x real integer Successor of x Truncated value of x real sqr(x) sqrtfx) real succ(x) truncfx) Procedures Purpose of Procedure Procedure Call dispose (Ptr) Returns variable referenced by Ptr to available space list get(F) Advances the file pointer for the file F and assigns the new value to F t Creates a variable of the type referenced new (Ptr) by Ptr and stores a pointer to the new variable in Ptr pack (U,J, P) page (F) put(F) Copies unpacked array elements from U into the packed array P; copying starts withUQ]:= P[l] Starts printing the next line of text F at the top of a new page Appends the current value of F to the fileF read (F, variable list) Reads values from file F into indicated variables; if F is not specified, input is assumed readln (F, variable list) Executes the seune as read and then advances the file pointer to the first position following the next end-of-line marker reset(F) Resets the pointer in file F to the beginning for the purpose of reading from F rewrite(F) unpack (P, U,J) Resets the pointer in file F to the beginning for the purpose of writing to F Copies packed array elements from P into the unpacked array U; copying starts with P[1]:=U[J] write (F, parameter list) Writes values specified by parameter list to the text file F; if F is not specified, output is assumed writeln (F, parameter list) Executes the same as write and then places an end-of-line marker in F Appendix 3 Syntax Diagrams Program identifier file list body declarations identifier >• letter T letter digit File List identifier A.5 A.6 Appendix 3 Syntax Diagrams Declarations and Definitions coNS-r type defiBition variable!declatation pii^aiedurie^;^^ r function deolaratidn I Label Declaration T Unsigned.mteger Constant Definition ^ idraitifier \ M) ^ cpnatant Type Definition >■ identifiep type Appendix 3 S)mtax Diagrams Variable Declaration Procedure and/or Function Declaration formal parameter list PROCEDURE. FUNCTION identifier forin^ parameter list Formal Parameter List ^VAR. identifier type A.7 A.8 Appendix 3 Syntax Diagrams Statement J A ^ assignment read or readln ;prdqeduie IF CASE WHitE REPEAT FOR compound GOTO empty Compound Statement *1 » X- Record Type -H ► File Type Set Type "H SET field'list [3 OF type A.9 A.10 Appendix 3 Syntax Diagrams Field List fixed part variantpart 7" T ^tO T Fixed Part type definition f c* identifier tjrpe name o o Variant Part tag field identifier constant o Variant Description A type name variant description T 7^ Appendix 3 Sjmtax Diagrams A.11 Assignment Statement ei^resdi^ variable fimcfidiiidi^tifier read or readln /( N yai^iapie' file variable readln file variable write or writeln file variable file variable Procedure procedure identifier I expression ' / \ T A.12 Appendix 3 Syntax Diagrams IF Statement ) ^ atatement WHILE Statement WHILES FOR Statement CASE Statement eimi^ssion {S^alaBel stamm^t Appendix 3 Syntax Diagrams REPEAT Statement ►nSBPEAT )—T*- statement r expression O WITH Statement yatiable stetement GOTO Statement statement label Empty Case Label constant Factor constant variable function identifier expression factor set vsliife expression A.13 A.14 Appendix 3 Syntax Diagrams Term factor MOD)(and factor Simple Expression term s boolean expression Boolean Expression >le expression )expression set value Appendix 3 Syntax Diagrams Variable expression fielididentifier variable identifier fieldidentifier Set Value expression expression A.15 Appendix 4 Character Sets The two tables included here show the ordering of two common character sets. Note that only printable characters are shown for each set. Ordinals without char acter representations either do not have standard representation, or they are as sociated with unprintable control characters. In each list, the blank is denoted by "h". The American Stan dard Code for Infor mation Interchange (ASCII) Right Digit Left Digit(s) 0 1 2 b 3 4 ( ) 5 2 3 6 ? A B C K L M N U V W X Y a b c - > 7 F G H I @ J 8 P Q R S T 9 Z [ \ 1 t 10 d e f g h i ) k 1 m 11 n o P q r s t u V w 12 X y z { 1 } = - ^Codes less than 32 or greater than 126 are nonprintable. A.16 . Appendix 4 Character Sets Right Digit The Extended Binary Coded Decimal Inter change Code (EBCDIC) A.17 Digit(s) 0 1 2 3 4 6 b 7 0 8 & 9 ! $ > ? * ) ; 5 6 7 8 9 . E" DO CountfCh] := □; FOR J := 1 TO ListLength DO CASE GradefJ] CountC'E'] Countf'E'] + Countf 'A' ] •B' : CountE 'B'] •C : Countf 'C'] •D" ; : •E' 1. a. 2 -1- 1; + 1; CountC'D'] Countt • A' ] Countf'B'] Countf 'C ] CountC'D'] : END; Section OF •A' 10.4 * 3 ID = to b. b * 3 » 4 = 72 0. 3 * 2 * 11 = bb d. 4 * 10 * 15 = bOO 3. TYPE Floor = l. . (3) WITH Employeel DO BEGIN Employees.Name := Name; Employees.SSN := SSN; Employees.Age := Age; Employees.HourlyWage := HourlyWage; Employees.Volunteer END; f = Volunteer of WITH...DO > b. Did you consider WITH Employees DO BEGIN Temp := HoursWorked; Employees := Eraployeel; HoursWorked := Temp END; 5. FUNCTION ComputeGrade (Pts integer) : char; VAR Percent : real; BEGIN Percent := Pts / 5; £>□ IF Percent := THEN 'E' ELSE IF Percent Grade of PROCEDURE PopAndCheck 9. Change the ELSE option to > , ELSE IF Num = Nodet.Info THEN writeln (Num, ' is a duplicate value.') ELSE IF Num AddNode (Nodet.LeftChild, Num) ELSE AddNode (Nodet.RightChild, Num) > AN.39 AN.40 Answers to Selected Exercises FUNCTION Search (Node : Pointer; NewNum : integer) : boolean; VRR Found : boolean; Current : Pointer; BEGIN Current := Node; Found := false; WHILE (Current NIL) AND NOT Found DO IF Currentt.Nura = NewNura THEN Found := true ELSE IF Currentt.Num : = Cube (X); or writeln BEGIN (Cube (X)); Count := D; readln (Scorel, Scores); Average := (Scorel + Scores) / S; ■"1 Count := Count + 1; writeln ('Average', Average:a:S) END. Conditional Statements IF Num □ > Procedures PROCEDURE GetData (VAR Amount THEN VAR Count BEGIN PosCount AmountList; integer); BEGIN := PosCount + 1; X := sqrt(Nura) END; " : : Count := □; WHILE NOT eof DO BEGIN IF Num >= □ Count THEN NonNegCount := NonNegCount + 1; X := Count + 1; readln BEGIN (AraountCCountJ) END END; := sqrt(Num) END call by GetData (Amount, Count); ELSE > BEGIN NegCount := NegCount + 1; X := abs(Num) END; CASE GasType OF 'R' : writeln 'U' : writeln 'S' END; ( 'Regular'); ( 'Unleaded');. : writeln ( 'SuperUnleaded') i of CASE GasType > Using Arrays Looping Statements FOR J := 1 TO SO DO writeln (J:5, J*J:5, J*J*J:5); Total J := WHILE WHILE NOT eof DO J . Total END; (Score); := Total + Score eof DO := J + 1; readln := Count + 1; readln NOT BEGIN BEGIN Count := □; □; (Donation!J]); Total := Total + DonationCJ] END; Count := J; Average := Total / Count; FOR REPEAT A := S B := sqrt(A) UNTIL B * > A; !□□□; K := 1 TO Count DO writeln ( '$' :10, DonationCK]rflrS); writeln; writeln ('Average', Average:11:S); Type Definitions TYPE Stringao = PACKED ARRAY [l..aO] OF char; NaraeList = ARRAY [1..ClassSizeJ OF String2D; AmountList = ARRAY [l..MaxSize] OF real; CurrentYears = lR5D..5D0a; HeatherType = (Cloudy, Sunny, Rain, Snow, Balmy) Record Definition TYPE StringED = PACKED ARRAY [1 ED] OF char; Patientlnfo = RECORD Name : StringED; Age : D..1DD; Weight : D..3DD END; { of RECORD Patientlnfo PatientList = ARRAY [1..1DD] OF Patientlnfo; VAR PatientList; Patient Using Records FOR J := 1 TO NumPatients DO BEGIN WITH PatienttJl DO BEGIN writeln (Name:3D); writeln (AgerlD, Weight:lD) END; writeln; writeln END; i of FOR...TO loop > File Definition TYPE StringED = PACKED ARRAY [1..ED] OF char; Patientlnfo = RECORD Name : StringED; Age : D..IDD; Weight : D..3DD END; { of RECORD Patientlnfo > PatientFile = FILE OF Patientlnfo; VAR Patient : PatientFile; TerapRec : Patientlnfo; Using Files rewrite (Patient); WHILE NOT eof(input) DO BEGIN GetData (Patient?); Process (Patient?); • put (Patient) END; Pascal: Understanding Programming and Problem Solving, Second Edition Douglas W. Nance © 1989'West Publishing Company
Report "Pascal: Understanding Programming and Problem Solving [2 ed.] 0314430512, 9780314430519"
We will keep fighting for all libraries - stand with us!

Internet Archive Audio
- This Just In
- Grateful Dead
- Old Time Radio
- 78 RPMs and Cylinder Recordings
- Audio Books & Poetry
- Computers, Technology and Science
- Music, Arts & Culture
- News & Public Affairs
- Spirituality & Religion
- Radio News Archive
- Flickr Commons
- Occupy Wall Street Flickr
- NASA Images
- Solar System Collection
- Ames Research Center
- All Software
- Old School Emulation
- MS-DOS Games
- Historical Software
- Classic PC Games
- Software Library
- Kodi Archive and Support File
- Vintage Software
- CD-ROM Software
- CD-ROM Software Library
- Software Sites
- Tucows Software Library
- Shareware CD-ROMs
- Software Capsules Compilation
- CD-ROM Images
- ZX Spectrum
- DOOM Level CD

- Smithsonian Libraries
- FEDLINK (US)
- Lincoln Collection
- American Libraries
- Canadian Libraries
- Universal Library
- Project Gutenberg
- Children's Library
- Biodiversity Heritage Library
- Books by Language
- Additional Collections
- Prelinger Archives
- Democracy Now!
- Occupy Wall Street
- TV NSA Clip Library
- Animation & Cartoons
- Arts & Music
- Computers & Technology
- Cultural & Academic Films
- Ephemeral Films
- Sports Videos
- Videogame Videos
- Youth Media
Search the history of over 867 billion web pages on the Internet.
Mobile Apps
- Wayback Machine (iOS)
- Wayback Machine (Android)
Browser Extensions
Archive-it subscription.
- Explore the Collections
- Build Collections
Save Page Now
Capture a web page as it appears now for use as a trusted citation in the future.
Please enter a valid web address
- Donate Donate icon An illustration of a heart shape
An introduction to programming and problem solving with PASCAL
Bookreader item preview, share or embed this item, flag this item for.
- Graphic Violence
- Explicit Sexual Content
- Hate Speech
- Misinformation/Disinformation
- Marketing/Phishing/Advertising
- Misleading/Inaccurate/Missing Metadata
![[WorldCat (this item)] [WorldCat (this item)]](https://archive.org/images/worldcat-small.png)
plus-circle Add Review comment Reviews
4 Favorites
Better World Books
DOWNLOAD OPTIONS
No suitable files to display here.
IN COLLECTIONS
Uploaded by paul nguyen on May 7, 2010
SIMILAR ITEMS (based on metadata)
- Email: [email protected]
Problem Solving & Structured Programming in Pascal.pdf

- Author / Uploaded
- Priyanka Ambastha
- Computer Data Storage
- Programming Language
- Central Processing Unit
- Computer Program
- Computer Terminal
Reference Guide to Pascal Statements Statement Example of Use program heading program GUIDE (INPUT, OUTPUT, INFILE, O
Views 452 Downloads 51 File size 27MB
Report DMCA / Copyright
Recommend Stories

Problem solving in Dynamics.pdf
Problem 1003 A stone is thrown vertically upward and return to earth in 10 sec. What was its initial velocity and how hi
65 12 202KB Read more

Problem Solving
61 0 2MB Read more

fhjooDeskripsi lengkap
95 0 174KB Read more

The current issue and full text archive of this journal is available at www.emeraldinsight.com/1352-7606.htm Problem so
78 2 90KB Read more

Problem-Solving Agent & Search
Kecerdasan Buatan (KI092301) Problem-Solving Agent & Search Chastine Fatichah Teknik Informatika Institut Teknologi Sep
6,599 525 2MB Read more

problem solving
BAB I PENDAHULUAN Problem solving sama artinya dengan pemecahan masalah. Problem solving merupakan suatu pendekatan dala
45 2 220KB Read more

Nama NIM Prog. Studi Kelas : Nadila Pitriani : 06101381520030 : Pendidikan Kimia 2015 : Palembang Dari 65 model pembel
50 5 177KB Read more

2,094 1,039 559KB Read more

BAB I PENDAHULUAN A. Latar Belakang Masalah Problem solving merupakan kemampuan yang sangat penting. Pada awal abad 20,
6,537 4,287 208KB Read more
Citation preview
Reference Guide to Pascal Statements Statement Example of Use program heading program GUIDE (INPUT, OUTPUT, INFILE, OUTFILE); comment [This section shows examples of Pascal statements.) (* Comments are ignored by Pascal. *) constant declaration integer character string real const STRINGSIZE = 20; BLANK = ' '; SCHOOL = 'TEMPLE UNIVERSITY' ; DEANSLIST = 3.5; PROBATION = 1.0; type declaration enumerated subrange string pointer record type COLLEGE = (BUSINESS, ARTS, EDUCATION, GENERAL); STUDENTRANGE = 1 .. 100; STRING = packed array [l .• STRINGSIZE] of CHAR; CLASSPOINTER = ASTUDENT; STUDENT = record NAME : STRING; GPA : REAL; INCOLLEGE : COLLEGE; NEXTSTU : CLASSPOINTER end; [STUDENT) MAJORARRAY = array [STUDENTRANGE] of COLLEGE; STUFILE = file of STUDENT; GRADESET = set of 'A' .. 'Z'; array file set variable declaration record set text file file pointer array character integer var declaring function with BOOLEAN result function MEMBER (NEXTCH : CHAR; TESTSET : GRADESET) BOOLEAN; [Returns TRUE if NEXTCH is a member of TESTSET.) assignment (BOOLEAN) set membership begin (MEMBER) MEMBER := NEXTCH in TESTSET end; [MEMBERl CURSTU STUDENT; GRADES GRADESET; INFILE TEXT; OUTFILE : STUFILE; CLASSLIST : CLASSPOINTER; MAJOR: MAJORARRAY; NEXTCH : CHAR; I, COUNTPROBATION : INTEGER; [Is NEXTCH in set?) (continued on last page) Problem Solving and Structured Programming in Pascal SECOND EDITION Problem Solving and Structured Programming in Pascal SECOND EDITION ELLIOT B. KOFFMAN Temple University A yy ADDISON-WESLEY PUBLISHING COMPANY, INC. Reading, Massachusetts • Menlo Park, California • Don Mills, Ontario > Wokingham, England> Amsterdam Sydney> Singapore· Tokyo > Mexico City> Bogota> Santiago • San Juan > James T. DeWolf, Sponsoring Editor Hugh Crawford, Manufacturing Supervisor Robert Forget, Art Editor Fran Palmer Fulton. Production Editor Karen M. Guardino, Production Manager Richard Hannus, Hannus Design Associates, Cover Design Maureen Langer, Text Designer Turbo Pascal0is a registered trademark of Borland International. UCSD Pascale is a trademark of the Regents of the University of California. Library of Congress Cataloging in Publication Data Koffman. Elliot B. Problem solving and structured programming in Pascal. Includes index. 1. Pascal (Computer program language) 2. Structured programming. I. Title. QA76.73.P2K63 1985 001.64'24 84-16811 ISBN 0-201-11736-3 ISBN 0-201-21450-4 School Reprinted with corrections, June 1985 Copyright © 1985. 1981 by Addison-Wesley Publishing Company, Inc. All rights reserved. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise. without the prior written permission of the publisher. Printed in the United States of America. Published simultaneously in Canada. BCDEFGHIJK-DO-898765 To my family-Caryn, Richard, Deborah, and Robin Koffman, for their constant love and understanding. To my parents-Edward and Leah Koffman, for all that they have given me. Preface There have been many changes in the way the first course in Computer Science is taught since the first edition of this book was published in 1981. During the past two years I have been the chairman of the ACM Task Force that has been studying these changes with an eye towards updating the description of the recommended first course for Computer Science majors (CS1).l Parallel with this effort, the Educational Testing Service (ETS) published a set of guidelines for an Advanced Placement course in Computer Science.f The text has been completely revised and reorganized to conform to both of these guidelines. This text can be used in any introductory programming course that emphasizes a careful, disciplined approach to programming in Pascal. Since the Advanced Placement course is a full year course, this text covers more material than would normally be completed in one semester. The additional material on searching and sorting algorithms (Chapter 9) and dynamic data structures (Chapter 10) are optional advanced topics in CS1 and would normally be deferred until CSZ. As in the first edition, the primary goal of this text is to illustrate and teach problem solving through the stepwise development of algorithms. To facilitate this, procedures are introduced much earlier in this edition. There are also several large case studies throughout the text that integrate 'Koffman. E, Miller. P, and Wardle. C. Recommended Curriculum for CS1. 1984. Communications ACM 27. 10 (Oct., 1964). 996-1001. 2 Advanced Placement Program of the College Board. Advanced Placement Course Description: Computer Science. Educational Testing Service. Princeton. NJ. 1963. ix topics and illustrate their application in a substantial programming problem with multiple procedures. Many new examples and programming assignment projects are provided. Some of the important features of this new edition are: Early introduction of procedures: Procedures without parameters are introduced in Chapter 2 and are used for self-contained operations that require no global variable access (no side-effects). Procedure parameters are discussed in Chapter 3. Early coverage of procedures will enable students to practice the top-down approach from the beginning and to become more adept at program modularization. Interactive programming: The emphasis is on modern technology and interactive programming. The majority of examples are written as interactive programs; however, students are shown early how to convert these programs to run in a batch environment. There are some batch-oriented examples as well. New chapter on recursion: There is a new chapter on recursion that provides many examples of recursive procedures and functions. Additional algorithms for searching and sorting arrays are also provided in this chapter. Arrays: Single and multidimensional arrays are covered in one chapter instead of in two as in the first edition. Similarly, all material on records is covered in a single chapter. New expanded case studies: There are a number of new, larger case studies within the text. The solutions to the case studies are all carefully developed. System structure charts are used to represent the flow of control and data between modules in a program system. Spiral approach: A spiral approach is used to preview topics such as the if statement, for statement, and input/output. Features are introduced as needed rather than overwhelming a student by providing all the details at once. Pedagogical aids: • Self-check Exercises are provided at the end of most sections. Solutions to selected exercises are provided at the end of the text. • Each chapter ends with a Chapter Review section that includes a summary, a table of new Pascal statements, and review questions. • Boxed material: Syntax display boxes are used to describe the syntax of each new Pascal statement as it is introduced, while Program Style boxes discuss the importance of good programming style. • Error warnings: Each chapter ends with a discussion geared toward helping students prevent and correct common programming errors. Several sections discuss debugging techniques. • Program comments: All programs are carefully commented. Loop invariants and assertions are shown for some loops. For easy identification, the first and last line of each procedure or program is in blue type. New design: The page layout is larger providing more white space and x PREFACE the overall tone is more user-friendly. The book has been completely redesigned with an eye towards making it easier for students to find figures, examples, programs, and special display boxes. A second color is used both to improve the appearance of the text and to clarify illustrations. Pascal dialects: ANSI standard Pascal is covered in the text. Common extensions are described in appendixes on ISO standard Pascal, UCSD Pascal and Turbo Pascal. Reference appendixes: There are also appendixes covering Pascal language elements, syntax diagrams, character codes, and error messages. Complete instructor's manual: An Instructor's Manual provides a discussion of how to teach the concepts in each chapter. Sample test questions will be included as well as answers to all exercises, chapter review questions, and the Programming Projects found at the end of each chapter. Transparency masters: A set of 131 transparency masters illustrating important concepts is available upon request. Acknowledgments Many people participated in the development of this text. The principal reviewers were most essential in finding errors and suggesting improvements. They include: William Eccles, University of South Carolina; Frank Friedman, Temple University; David Hannay, Union College; Helen Holzbaur, Temple University; Abraham Kandel, Florida State University; Raymond Kirsch, LaSalle College; David Moffat, North Carolina State University; Tom Nelson, North Carolina State University; Richard Rinewalt, University of Texas at Arlington; Paul Ross, Millersville University of Pennsylvania; Chris Speth, Western Kentucky University; Caroline Wardle, Boston University; Charles C. Weems, [r., University of Massachusetts at Amherst; and Brad Wilson, Western Kentucky University. I am grateful to all of them for their considerable efforts. Towards the beginning of this project, several faculty and members of the Addison-Wesley sales and marketing staffs participated in focus groups to discuss the first programming course in Pascal. These discussions were helpful in providing direction to the text and clarifying its organization. The faculty are: Linda Ottenstein, Michigan Tech University; David Neusse, University of Wisconsin at Eau Claire; Richard Rinewalt, University of Texas at Arlington; Ruth Barton, Michigan State University; and Howard Edelman, West Chester State University. Finally, a number of faculty reviewed and commented on preliminary sections of the text. These faculty include: Gideon Frieder, University of Michigan; Gary Ford, University of Colorado; Abraham Kandel, Florida State University; Paul Hanna, Florida State University; M. Main, University of Colorado; Kent Wooldridge, California State University at Chico; Richard St. Andre, Central Michigan University; C. E. Wolf, Iowa State University; Angela Wu, American University; Yure Gurevich, University of PREFACE xi Michigan; Amir Foroudi, State University of New York at Fredonia; Morris Rang, 11, Western Illinois University; Peggy R. Ayres, Linn-Benton Community College; Muhammed H. Chaudhary, Millersville University of Pennsylvania; Stanley Thomas, Wake Forest University; R. J. Del Zoppo, Jamestown Community College; David Rosenlof, Sacramento City College; George Beekman, Oregon State University; George Witter, Western Washington State University; J. M. Adams, New Mexico State University; John Lushbough, University of South Dakota; Dave Valentine, State University of New York at Potsdam; Dennis Martin, State University of New York at Brockport; Chris J. Dovolis, University of Minnesota; Barbara SmithThomas, University of North Carolina at Greensboro; Barent Johnson, University of Wisconsin at Oshkosh; Carl Wehner, University of Northern Iowa; Aboalfazl Salimi, Embry-Riddle University; Larry Wilson, Old Dominion University; Cary Laxer, Rose-Hulman Institute of Technology; J. Mailen Kootsey, Duke University; Jerry Waxman, City University of New York at Queens; Bruce J. Klein, Grand Valley State College; Eris Pas, Duke University; Gove Effinger, Bates College; Krishna Moorthy, Framingham State College; Brian Johnson, University of New Hampshire; and John Coda, Georgia Institute of Technology. There were also many people involved with the actual production of the text. From Addison-Wesley, James DeWolf was the sponsoring editor and recruited reviewers, provided input and suggestions during the writing stage, and coordinated with the production staff. Bill Gruener also was the publisher with overall responsibility for the text. Karen Guardino was the production manager and saw to it that the book was able to meet a very tight production schedule. Maureen Langer refined the design of the text. In Philadelphia, Fran Palmer Fulton served as the Production Editor and coordinated and supervised the typesetting of the manuscript. I am grateful to all of them for their involvement and extra efforts to get this book published on schedule. Philadelphia, PA December 1984 xli PREFACE E.B.K. Contents Introduction to Computers and Programming 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 Electronic Computers Then and Now 2 Components of a Computer 3 Problem Solving and Programming 6 Programming Languages 7 Processing a High-level Language Program Introduction to Pascal 11 General Form of a Pascal Program 22 Using the Computer 26 Formatting Program Output 29 Introduction to Data Types 34 Common Programming Errors 36 Chapter Review 39 Problem Solving 2.1 2.2 2.3 2.4 2.5 1 9 45 Representing and Refining Algorithms 46 Using Procedures for Subproblems 52 Decision Steps in Algorithms 59 Tracing a Program or Algorithm 67 Problem Solving Strategies 69 xIII 2.6 2.7 2.8 2.9 2.10 2.11 II II II xlv CONTENTS Repetition in Programs 72 Generalizing a Solution 79 Repeating a Program Body 83 Debugging and Testing Programs 87 Common Programming Errors 88 Chapter Review 89 Control Statements 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 Syntax Diagrams 96 The if Statement Revisited 97 The while Statement 104 Procedure Parameters 111 Adding Data Flow Information to Structure Charts Nested Procedures and Scope of Identifiers 132 Case Studies 136 Debugging a Program System 150 Common Programming Errors 151 Chapter Review 152 Simple Data Types 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10 95 159 Constant Declarations 160 Numeric Data Types-REAL and INTEGER 161 Functions in Arithmetic Expressions 169 BOOLEAN Variables, Expressions, and Operators 175 Character Variables and Functions 180 Introduction to Programmer-defined Data Types 188 Input/Output Revisited 193 Case Study 201 Common Programming Errors 206 Chapter Review 207 More Control Statements 5.1 5.2 5.3 128 217 The case Statement 218 Set Values in Decisions 221 The General for Statement 223 5.4 5.5 5.6 5.7 5.8 5.9 II The repeat Statement 225 Nested Loops 229 User-defined Functions 234 Case Studies 240 Common Programming Errors Chapter Review 252 Arrays 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 263 Declaring and Referencing Arrays 264 Arrays with Integer Subscripts 266 Case Study 270 Manipulating Entire Arrays 276 Reading Part of an Array 282 General Arrays 283 Character Strings 288 Multidimensional Arrays 295 Case Study 302 Common Programming Errors 313 Chapter Review 313 Records 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 251 325 Declaring a Record 326 Manipulating Individual Fields of a Record 328 Manipulating an Entire Record 331 Arrays of Records 334 Case Study 335 Searching an Array 342 Sorting an Array 344 General Data Structures 348 Record Variants 352 Manipulating Strings Stored in Records 357 Common Programming Errors 363 Chapter Review 364 CONTENTS xv II II II xvi CONTENTS Sets and Files 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 8.10 371 Set Data Type and Set Operators 372 RESET, REWRITE, and the File Position Pointer 379 TEXT Files 381 Case Studies 385 User-defined File Types 396 Case Study-File Merge 401 Case Study-Data Base Inquiry 405 File Buffer Variable 411 Common Programming Errors 416 Chapter Review 417 Recursion, Searching, and Sorting 425 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 The Nature of Recursion 426 Recursive Procedures 432 Recursive Functions 439 Binary Search of an Array 449 Searching by Hashing 453 Additional Sorting Algorithms 457 Case Study-The Quicksort Algorithm 462 Common Programming Errors 467 Chapter Review 468 Pointer Variables and Dynamic Data Structures 475 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 The NEW Statement and Pointer Variables 476 Understanding Dynamic Allocation 480 Introduction to Linked Lists 481 Manipulating Linked Lists Using Pointer Variables 483 Case Study-Maintaining a Linked List 487 Stacks and Queues 500 Multiple-linked Lists and Trees 506 Case Study-Maintaining a Binary Search Tree 511 Common Programming Errors 518 Chapter Review 519 II II Appendix A: Reserved Words, Standard Identifiers, Operators, Functions, and Procedures Ap-l Appendix B: Additions and Extensions to Pascal Ap-5 • • • • • B.1 Additional Features of ANSI/IEEE Pascal • • • • • B.2 ISO Pascal ~~~~~ B.3 UCSD Pascal • • • • • B.4 TURBO Pascal III Appendix C: Pascal Syntax Diagrams III Appendix D: Character Sets Ap-29 III Appendix E: Error Number Summary Ap-31 II Answers to Selected Exercises II Index 1-1 Ap-19 Ans-I CONTENTS xvii Introduction to Computers and Programming 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10 1.11 1.12 Electronic Computers Then and Now Components of a Computer Problem Solving and Programming Programming Languages Processing a High-level Language Program Introduction to Pascal General Form of a Pascal Program Using the Computer Formatting Program Output Introduction to Data Types Common Programming Errors Chapter Review This chapter introduces computers and computer programming. It begins with a brief history of computers and describes the major components of a computer including memory, central processor, input devices, and output devices. The chapter discusses how information is represented in a computer and how it is manipulated. The major categories of programming languages are introduced. Simple computer operations are described along with some short programs that demonstrate these operations. There is a brief introduction to the Pascal programming language focusing on statements for reading and displaying information and for performing simple computations. 1 Also described are the steps involved in creating a Pascal program and the roles performed by various programs that are part of a computer system. These programs include the operating system, compiler, editor, and loader. • Electronic Computers Then and Now It is difficult to live in today's society without having had some contact with computers. Computers are used to provide instructional material in some schools, print transcripts, send out bills, reserve airline and concert tickets, play games, and even help authors write books. However, it wasn't always this way. Just a short time ago, computers were fairly mysterious devices that only a small percentage of our population knew much about. Computer "know-how" turned around when advances in solid-state electronics led to drastic cuts in the size and costs of electronic computers. Today, a personal computer (see color insert, Fig. 1.1) which costs less than $3000 and sits on a desk, has as much computational power as one that 10 years ago would have cost more than $100,000 and would fill a 9 by 12 ft room. This price reduction is even more remarkable when we consider the effects of inflation over the last decade. If we take the literal definition for computer as a device for counting or computing, then the abacus might be considered the first computer. However, the first electronic digital computer was designed in the late 1930s by Dr. John Atanasoff at Iowa State University. Atanasoff designed his computer to perform mathematical computations for graduate students. The first large-scale, general-purpose electronic digital computer, called the ENIAC, was built in 1946 at the University of Pennsylvania. Its design was funded by the U. S. Army, and it was used for computing ballistics tables, for weather prediction, and for atomic energy calculations. The ENIAC weighed 30 tons and occupied a 30 by 50 ft space (see color insert, Fig. 1.2). Although we are often led to believe otherwise, computers cannot think! They are basically devices for performing computations at incredible speeds (more than one million operations per second) and with great accuracy. However, in order to accomplish anything useful, a computer must be programmed or given a sequence of explicit instructions (the program) to carry out. To program the ENIAC it was necessary to connect hundreds of wires and arrange thousands of switches in a certain way. In 1946, Dr. John von Neumann of Princeton University proposed the concept of a stored program computer. The instructions of a program would be stored in computer memory rather than be set by wires and switches. Since the contents of computer memory can be easily changed, it would not be nearly as difficult to reprogram this computer to perform different tasks as it was to reprogram the ENIAC. Von Neumann's design is the basis of the digital computer as we know it today. 2 INTRODUCTION TO COMPUTERS AND PROGRAMMING II Components of a Computer Despite large variation in cost, size, and capabilities, modern computers are remarkably similar in a number of ways. Basically, a computer consists of the five components shown in Fig. 1.3 (see color insert). The arrows connecting the components show the direction of information flow. All information that is to be processed by a computer must first be entered into the computer memory via an input device. The information in memory is manipulated by the central processor and the results of this manipulation are stored in memory. Information in memory can be displayed through an output device. A secondary storage device is often used for storing large quantities of information in a semipermanent form. These components and their interaction are described in more detail in the following sections. Computer Memory Computer memory is used for information storage. All types of information-numbers, names, lists, and even pictures-may be represented and stored in a computer memory. The memory of a computer may be pictured as an ordered sequence of storage locations called memory cells. In order to be able to store and retrieve (access) information, there must be some way to identify the individual memory cells. To accomplish this, each memory cell has associated with it a unique address that indicates its relative position in memory. Figure 1.4 shows a computer memory consisting of 1000 memory cells with addresses a through 999. Some large-scale computers have memories consisting of millions of individual cells. The information stored in a memory cell is called the contents of a memory cell. Every memory cell always contains some information although we may have no idea what that information is. Whenever new information is placed in a memory cell, any information already there is destroyed and cannot be retrieved. In Fig. 1.4, the contents of memory cell 3 is the number -26, and the contents of memory cell 4 is the letter H. Central Processor Unit The central processor unit (CPU) performs the actual processing or manipulation of information stored in memory. The CPU can retrieve information from memory. (This information may be either data or instructions for manipulating data.] It can also store the results of these manipulations back in memory for later use. The control unit within the CPU coordinates all activities of the computer. It determines which operations should be carried out and in what order; the control unit then transmits coordinating control signals to the computer components. 1.2 COMPONENTS OF A COMPUTER 3 memory cell ' - - - addresses memory cell - - - ' contents Fig. 1.4 A Computer Memory with 1000 Cells Also found within the CPU is the arithmetic-logic unit (ALU). The ALU consists of electronic circuitry to perform a variety of arithmetic operations. including addition, subtraction, multiplication, and division. These arithmetic operations are performed en data that are stored in memory; the computational results are then saved in memory. The speed with which the ALU can perform each arithmetic operation is about a millionth of a second. The ALU also consists of electronic circuitry to compare information and to make decisions based on the results of the comparison. Input and Output Devices The manipulative capability of the computer would be of little use to us if we were unable to communicate with the computer. Specifically, we must be able to enter data for a computation into memory. Later. the computational results that are stored in memory can be displayed. Most of you will be using a computer terminal (see color insert, Fig. 1.5) as both an input and output device. A terminal consists of a keyboard (used for entering information) and a monitor (used for displaying information). A terminal keyboard is similar to a typewriter keyboard except that it has some extra keys for performing special functions. A monitor is similar to a television or video screen. 4 INTRODUCTION TO COMPUTERS AND PROGRAMMING Some terminals are equipped with graphics capability (see color insert, Fig. 1.6), which enables the output to be displayed as a two-dimensional graph or picture, not just as rows of letters and numbers. With some graphics devices, the user can communicate with the computer by moving an electronic pointer using a joystick or a mouse. The only problem with using a monitor as an output device is that there is no written record of the computation. Once the image disappears from the monitor screen it is lost. If you want hard-copy output, then you have to send your computational results to an output device called a printer or use a hard-copy terminal (see color insert, Fig. 1.7). A card reader is sometimes used as an input device. A card reader reads punch cards that have been prepared using a keypunch. Pressing a symbol on the keypunch keyboard causes a particular configuration of holes to be punched on a punch card. A card reader interprets these configurations of holes and sends the information to the computer. Secondary Storage Device There is another category of device, called a secondary storage device, that is found on most computer systems. These devices are used to provide additional data storage capability. Examples of secondary storage devices are magnetic tape and disk drives with their associated magnetic tapes or disks (see color insert, Fig. 1.8). Large quantities of information may be saved on a tape or disk. The memory described in the computer memory section is often called main memory to distinguish it from secondary memory (tapes or disks). Main memory is much faster and more expensive than secondary memory. Also, most computers can have only limited quantities of it. Consequently, often it is necessary to add one or more secondary storage devices in order to expand the computer system's data storage capacity. Information stored in secondary memory is organized into aggregates called files. Results generated by the computer may be saved as data files in secondary memory. Most of the programs that you write will be saved as program files in secondary memory. Any file may be transferred easily from secondary memory to main memory for further processing. A typical computer system, including memory, a central processor. terminals, and tape and disk drives. is pictured in Fig. 1.9 (see color insert). In the remainder of this text, we will see how to use this hardware by writing software (computer programs) for specifying different kinds of data manipulation. Self-check Exercises for Section 1.2 1. What are the contents of memory cells 0 and 999 in Fig. 1.4? What memory cells contain the letter X and the fraction 0.005? 2. Explain the purpose of the arithmetic-logic unit. memory, central processor, and the disk drive and disk? What input and output device will be used with your computer? 1.2 COMPONENTS OF A COMPUTER 5 • Problem Solving and Programming We mentioned earlier that a computer cannot think; therefore, in order to get it to do any useful work, a computer must be provided with a program that is a list of instructions. Programming a computer is a lot more involved than simply writing a list of instructions. Problem solving is an important component of programming. Before we can write the program to solve a problem, we must consider carefully all aspects of the problem and then organize its solution. Like most programming students, you will probably spend a great deal of time initially in the computer laboratory entering your programs. You will spend more time later removing the errors or bugs that inevitably will be present in your programs. It is tempting to rush to the computer laboratory and start entering your program as soon as you have some idea of how to write it. You should resist this temptation and instead think carefully about the problem and its solution before writing any program statements. When you have a solution in mind, you should plan it out on paper and modify it if necessary before writing the program. Once the program is written on paper, you should desk check your solution by "executing" it much as the computer would. You should carefully determine the result of each program statement using sample data that are easy to manipulate (e.g, small whole numbers). You should compare these results with what would be expected and make any necessary corrections to the program when the results are incorrect. Only then should you go to the computer laboratory and start to enter the program. Experience has shown that a few extra minutes spent evaluating the proposed solution in this way often saves hours of frustration later. The process you should follow is shown in Fig. 1.10. In this text, we will stress a methodology for problem solving that we have found useful in helping students to learn to program. We will teach a technique called structured programming that should enable you to write programs that are relatively easy to read and understand and that contain fewer initial errors. Most students have very strong positive or negative feelings about programming; very few students are ambivalent. Some of the reasons that programming can be less than enjoyable are the following: 1. You are learning a new language with its own syntax or rules of gram- mar. 2. You must carefully plan out what actions you would like performed and their sequence. 3. You must be explicit and accurate in describing what you wish done. 4. You must implement your solution in an existing programming language. What seems simple to write in English may require considerable effort to specify in a programming language. 5. You must carefully enter all program instructions and all data since 6 INTRODUCTION TO COMPUTERS AND PROGRAMMING Fig. 1.10 Programming Strategy each instruction must correspond exactly with the syntax of the programming language. Omitting a comma can cause your program to fail. 6. You will be dealing with equipment that occasionally malfunctions and sometimes is not accessible when you want to use it. 7. When you make a mistake (and you will make lots of mistakes) it is often difficult to determine what is wrong so that you can fix it. This list is not intended to scare you, but to alert you to some of the problems that you may encounter. If you are careful, patient, and plan ahead you can avoid some of these problems. Planning ahead includes scheduling your time so that you can make use of the computer laboratory during hours when it is less busy. • Programming Languages Languages used for writing computer programs are called programming languages. There are many different programming languages, which fall into one of three broad categories: machine, assembly, or high-level languages. High-level languages are most often used by programmers (program writers). One reason for the popularity of high-level languages is that they are much easier to use than machine and assembly languages. Another reason is that a high-level language program is portable. This means that it can be executed without modification on many different types of computers. An assembly language or machine-language program, on the other hand, may only execute on one type of computer. 1.4 PROGRAMMING LANGUAGES 7 Some common high-level languages are BASIC, FORTRAN, COBOL, and Pascal. Each of these high-level languages has a language standard that describes the form and meaning of all its statements. Generally there are additional features available on a particular computer that are not part of the standard. A program will be portable only when the programmer is careful to use those features that are part of the standard. One of the most important features of high-level languages is that they allow us to write program statements that resemble English. We can reference data that are stored in memory using descriptive names (e.g. NAME, RATE) rather than numeric memory cell addresses. We can also describe operations that we would like performed using familiar symbols. For example, in several high-level languages the statement Z := X + Y means add X to Y and store the result in Z. We can also use descriptive names to reference data in assembly language; however, we must specify the operations to be performed on the data more explicitly. The high-level language statement above might be written as LOAD X ADD Y STORE Z in an assembly language. Machine language is the native tongue of a computer. Each machine language instruction is a binary string (string of D's and l's) that specifies an operation and the memory cells involved in the operation. The assembly language statements above might be written as 0010 0000 0000 0100 0100 0000 0000 0101 0011 0000 0000 0110 in a machine language. Obviously, what is easiest for a computer to understand is most difficult for a person and vice versa. A computer can execute only programs that are in machine language. Consequently, a high-level language program must first be translated into machine language using a special program called a compiler. The machine language program must then be loaded into computer memory by the loader program before it can be executed. This process is illustrated in Fig. 1.11 and described in more detail in the next section. Self-check Exercises for Section 1.4 1. Explain the role of a compiler and loader. 2. What do you think the high-level language statements below mean? X := A + B + C 8 X := Y / Z INTRODUCTION TO COMPUTERS AND PROGRAMMING D := C - B + A Fig. 1.11 Translating a high-level language program • Processing a High-level Language Program Before it can be processed, a high-level language program must be entered at the terminal. The program will be stored on disk as a file called the source file (see Fig. 1.12). Once the source file is saved, it must be translated into machine language. A compiler processes the source file and attempts to translate each statement into machine language. One or more statements in the source file may contain a syntax error. This means that these statements do not correspond exactly to the syntax of the high-level language. In this case, the compiler will cause some error messages to be displayed. At this point, you can make changes to your source file and have the compiler process it again. If there are no more errors, the compiler will create an object file, which is your program translated into machine language. The object file can then be stored in main memory by the loader program and then executed. Both the compiler and loader programs are part of your computer system. This process is shown in Fig. 1.12. Executing a Program In order to execute a program, the computer control unit must examine each program instruction in memory and send out the command signals required to carry out the instruction. Normally, the instructions are executed in sequence; however, as we will see later it is possible to have the con1.5 PROCESSING A HIGH-LEVEL LANGUAGE PROGRAM 9 Fig. 1.12 Preparing a Program for Execution trol unit skip over some instructions or execute some instructions more than once. During execution, data may be entered into memory and manipulated in some specified way. Then, the result of this data manipulation will be displayed. Figure 1.13 shows the effect of executing a payroll program stored in memory. The first step of the program requires entering data into memory that describe the employee. In step 2, the employee data are manipulated by the central processor and the results of computations are stored in memory. In the final step, the computational results may be displayed as payroll reports or employee payroll checks. An example of a program that does this is provided later in the chapter. Self-check Exercises for Section 1.5 1. What is the difference between the source file and object file? Which do you create and which does the compiler create? Which one is processed by the loader? 2. What is a syntax error and in which file would a syntax error be found? 10 INTRODUCTION TO COMPUTERS AND PROGRAMMING memory Fig. 1.13 Flow of Information during Program Execution • Introduction to Pascal Pascal was developed in 1971 by Professor Nicklaus Wirth of Zurich, Switzerland. It is currently one of the most widely used languages for teaching programming. Its popularity is due to the fact that its syntax is relatively easy to learn. Also, Pascal facilitates writing structured programs-programs that are relatively easy to read, understand, and maintain (keep in good working order). There are two similar standards for Pascal. This textbook will cover features of the language that are included in the 1983 ANSI/IEEE (American National Standards Institute/Institute for Electrical and Electronics Engineers) Standard. Features of this standard not discussed in the text are described in Appendix B1. Other features that are included in the ISO International Standard (but not in the ANSI/IEEE Standard) are described in Appendix B2. Finally, additional features that are often available but are not in either standard are described in Appendixes B3 and B4. The rest of this chapter will provide a brief introduction to Pascal. Statements for reading data, performing simple computations, and displaying results will be described. Two Sample Programs Before beginning our study of Pascal, we will examine two short programs. Don't worry about understanding the details of these programs yet; it will all be explained later. 1.6 INTRODUCTION TO PASCAL 11 program HELLO (INPUT, OUTPUT); var LETTERl, LETTER2, LETTER3 : CHAR; begin WRITELN ('Enter a 3 letter nickname and press return.'); READLN (LETTERl, LETTER2, LETTER3); WRITELN ('Hello', LETTERl, LETTER2, LETTER3, '.'); WRITELN ('We hope you enjoy studying Pascal! ') end. Enter a 3 letter nickname and press return. Bob Hello Bob. We hope you enjoy studying Pascal! Fig. 1.14 Printing a Welcoming Message Example 1.1 Figure 1.14 contains a Pascal program followed by a sample execution of that program. For easy identification, the program name and last line are in blue; the information entered by the program user also is in blue in the sample execution. The program statement starting with var identifies the names of three memory cells (LETTERl, LETTER2, LETTER3) that will be used to store each letter of the nickname. Each program statement starting with WRITELN cause a line of output to be displayed during program execution. The first WRITELN statement generates the first line of the sample output, which asks the program user to enter three letters. The program statement READLN (LETTERl, LETTER2, LETTER3); reads the three letters Bob (entered by the program user) into the three memory cells listed (one letter per cell). The next statement WRITELN ('Hello', LETTERl, LETTER2, LETTER3, '.'); displays these letters after the message string' Hello '. The string , causes a period to be printed after the third letter. Example 1.2 The program in Fig. 1.15 converts inches to centimeters. The number of inches to be converted is read into the memory cell INCHES by the statement READLN (INCHES); The statement CENT := CENTPERINCH * INCHES; 12 INTRODUCTION TO COMPUTERS AND PROGRAMMING program INCHTOCENT (INPUT, const CENTPERINCH OUTPUT)~ 2.54~ var INCHES, CENT : REAL~ begin WRITELN ('Enter a length in inches.')~ READLN (INCHES) ~ CENT := CENTPERINCH * INCHES; WRITELN ('That equals', CENT, ' centimeters. ') end. Enter a length in inches. 30.0 That equals 7.620000E+Ol centimeters. Fig. 1.15 Converting Inches to Centimeters computes the equivalent length in centimeters by multiplying the length in inches by 2.54 (the number of centimeters per inch); the product is stored in memory cell CENT. The statement WRITELN ('That equals " CENT, ' centimeters. ') displays a message string, the value of CENT, and a second message string. The value of CENT is printed in Pascal scientific notation as 7.620000E+01. This is equivalent to 7.62 X 10 or 76.2 as will be explained later. One of the nicest things about Pascal is that it lets us write program statements that resemble English. At this point, you probably can read and understand the sample programs, even though you may not know how to write your own programs. The following sections provide a detailed explanation of the Pascal statements seen so far. Reserved Words and Standard Identifiers Each of the statements in the programs in Fig 1.15 satisfies the Pascal syntax for that statement type. If the program statements that you enter do not follow this syntax, t~ey may not be translated. Each Pascal statement contains a number of different elements: reserved words, standard identifiers, special symbols, and names for data and programs. The reserved words have special meaning in Pascal and cannot be used for other purposes. Reserved words in Figs. 1.14 and 1.15 program, const, var, begin, end The standard identifiers also have special meaning but they can be used by the programmer for other purposes (not recommended). 1.6 INTRODUCTION TO PASCAL 13 Standard identifiers in Figs. 1.14 and 1.15 READLN, WRITELN, REAL, CHAR, INPUT, OUTPUT There are also some symbols (e.g. =, «, : =) that have special meaning. Appendix A contains a complete list of reserved words, standard identifiers, and special symbols. What is the difference between reserved words and standard identifiers? Although it is illegal to use a reserved word for the name of a data item, it is legal to use a standard identifier. However, if you do this, then Pascal no longer associates any special meaning with that identifier. For example, you could decide to use READLN as the name of a data item, but then you would not be able to use READLN to read a data value. Obviously, this would be a pretty silly thing to do, and we don't recommend it. Besides standard identifiers, the programs in Figs. 1.14 and 1.15 contain other identifiers that are used as the names of programs or data. The form of these identifiers is described in the next section. Other identifiers in Figs. 1.14 and 1.15 HELLO, LETTERl, LETTER2, LETTER3, INCHES, CENT, CENTPERINCH, INCHTOCENT PROGRAM STYLE Use of uppercase, lowercase, and computer type Throughout the text, issues of good programming style will be discussed in displays such as this one. Programming style displays will provide guidelines for improving the appearance and readability of programs. Most programs will be examined or studied by someone else. A program that follows some consistent style conventions will be easier to read and understand than one that is sloppy or inconsistent. Although these conventions make it easier for humans to understand programs, they have no affect whatsoever on the computer. Reserved words will always appear in lowercase in programs; all other identifiers will appear in uppercase. We recommend that you follow this convention in your programs so that it will be easy to distinguish reserved words from other identifiers. Some Pascal compilers do not allow lowercase characters in Pascal statements. If this is true for your compiler, you will have to use uppercase for reserved words as well. If both uppercase and lowercase are allowed, the compiler will not differentiate between them in reserved words or identifiers. This means that you can write the reserved word const as CaNST or the special identifier READLN as Readln. However, const and READLN would be preferred according to our convention. Within the text body, reserved words appear in a computer type font, making them easily recognizable. 14 INTRODUCTION TO COMPUTERS AND PROGRAMMING Fig. 1.1 IBM personal computer Fig. 1.2 The ENIAC computer (Photo courtesy of Sperry Corporation.) Secondary Storage Device 0 then NUMPOS := NUMPOS + 1 else if X 0) is tested; if it is true, NUMPOS is incremented and the rest of the if statement is skipped. If the first condition is false, the second condition (X Table 3.2 Trace of if Statement in Example 3.5 for X Statement Part if X > 0 then else if X 100 CONTROL STATEMENTS = - 7 Effect -7 > 0 - false -7 Add 1 to NUMNEG PROGRAM STYLE Multiple alternative decisions Nested if statements may become quite complex. If there are more than three alternatives and indentation is not done consistently, it may be difficult to determine the if to which a given else belongs. (In Pascal, this is always the closest if without an else.) We find it easier to write the nested if statement in Example 3.5 as the multipie alternative decision below. [increment NUMPOS, NUMNEG, or NUMZERO based on XI if X > then NUMPOS := NUMPOS + 1 else if X ° ° In this format, the word else and the next condition appear on the same line. All the words else align, and each dependent statement is indented under the condition that controls its execution. The general form is shown next. if condition l then s t.e t.emerit: ; else if condition 2 then s t.etiementi , else if condition n then statement n else st.at.ement ; The conditions in a multiple alternative decision are evaluated in sequence. If a condition is false, the statement following it is skipped and the next condition is tested. If a condition is true, the statement following it is executed and the rest of the multiple alternative decision is skipped. If all conditions are false, then statement; following the last else is executed. Very often the conditions in a multiple alternative decision are not mutually exclusive. This means that it may be possible for more than one condition to be true for a given data value. If this is the case, then the order of the conditions becomes very important because only the statement following the first true condition will be executed. 3,2 THE IF STATEMENT REVISITED 101 Example 3.6 The table below describes the assignment of grades based on an exam score. Exam Score Grade Assigned 90 and above 80-89 70-79 60-69 below 60 A B C D F The multiple alternative decision below prints the letter grade assigned according to this table. The last three conditions are true for an exam score of 85; however, a grade of B is assigned because the first true condition is SCORE > = 80. (correct grade assignmentj if SCORE >= 90 then WRITE ('A') else if SCORE >= 80 then WRITE ('B') else if SCORE >= 70 then WRITE (' C' ) else if SCORE >= 60 then WRITE ('D') else WRITE ('F') It would be wrong to write the decision as shown next. All passing exam scores (60 or above) would be incorrectly categorized as a grade of D because the first condition would be true and the rest would be skipped. (incorrect grade assignmentj if SCORE >= 60 then WRITE ('D') else if SCORE >= 70 then WRITE ('C') else if SCORE >= 80 then WRITE ('B') else if SCORE >= 90 then WRITE (' A' ) else WRITE ('F') Example 3.7 102 A nested if statement may be used to implement a decision table that describes several alternatives. Each line of Table 3.3 indicates a salary range and a base tax amount and tax percentage for that range. Given a salary amount, the tax is calculated by adding the Base Tax for that salary range, and the product of the Percentage of Excess and the amount of salary over the minimum salary for that range. For example, the second line of the table specifies that the tax due on a salary of $2000.00 is $225.00 plus 16% of the excess salary over $1500.00 (i.e. 16% of $500.00). Therefore, the total tax due is $225.00 plus $80.00 or $305.00. CONTROL STATEMENTS Table 3.3 Tax Table for Example 3.7 Range Salary Base Tax Percentage of Excess 0.00 - 1499.99 0.00 15% 2 1500.00 - 2999.99 225.00 16% 3 3000.00 - 4999.99 465.00 18% 4 5000.00 - 7999.99 825.00 20% 5 8000.00 - 14999.99 1425.00 25% The if statement in Fig. 3.2 implements the tax table. If the value of SALARY is within the table range (0 to 14999.99), exactly one of the statements assigning a value to TAX will be executed. A trace of the if statement for SALARY = $2000.000 is shown in Table 3.4. The value assigned to TAX is $305.00 as desired. if SALARY (first rangej (second rangej (third rangej (fourth rangej (fifth rangej Fig. 3.2 If Statement for Table 3.3 Table 3.4 Trace of if Statement in Fig. 3.3 for SALARY Statement Part = $2000.00 SALARY TAX 2000.00 ? Effect if SALARY 2000.0 else if SALARY 2000.0 else if SALARY 2000.0 TAX := (SALARY - 1500.00) * + 0.16 225.00 305.00 Evaluates to 500.00 Evaluates to 80.00 Evaluates to 305.00 3,2 THE IF STATEMENT REVISITED 103 PROGRAM STYLE Validating the value Of variables It is important to validate the value of a variable before performing computations using invalid or meaningless data. Instead of computing an incorrect tax amount, the if statement in Fig. 3.3 prints an error message if the value of SALARY is outside the range covered by the table (0 to 14999.99). The first condition is used to detect negative salaries and an error message is printed if SALARY is less than zero. If SALARY is greater than 14999.99, all conditions are false and the alternative following else causes an error message to be printed. Self-check Exercises for Section 3.2 1. What would be the effect of omitting the first be g in in the if state- 2. 3. 4. 5. 6. ment of Example 3.3? What error messages do you think would be printed as the compiler tried to translate the rest of the if statement? Write an if statement that assigns the larger of X and Y to LARGER and the smaller to SMALLER. Your statement should print 'X LARGER' or 'Y LARGER' depending on the situation. Trace the execution of the nested if statement in Fig. 3.2 when SALARY is 13500.00. What would be the effect of reversing the order of the first 2 conditions in the if statement of Fig. 3.2? Rewrite the if statement for Example 3.6 using only the relational operator Grade POint A verage 0.0 - 0.99 1.0 - 1.99 3.0 - 3.49 3.5 - 4.0 III Transcript Message Failed semester-registration suspended On probation for next semester Deans list for semester Highest honors for semester The while Statement In all the loops used so far, the exact number of loop repetitions required could be determined before the start of loop execution. We used the for statement to implement these counting loops. In many programming situations, the exact number of loop repetitions cannot be determined before loop execution begins. It may depend on some aspect of the data which is not known beforehand, but usually can be stated by a condition. For example, we may wish to continue writing checks as long as our bank balance is positive. Pascal provides additional 104 CONTROL STATEMENTS looping statements (while and repeat) to implement conditional loops. The while statement is discussed below; the repeat statement is discussed in Chapter 5. Example 3.8 The while loop in Fig. 3.3 could be used to find the sum of the first N integers. The loop body is the compound statement (beg in . . . end [wh i l e J) and is repeated as long as (while) the value of NEXTINT is less than or equal to N. In the loop body, each value of NEXTINT (starting with 1) is added to SUM and NEXTINT is incremented by 1. Loop execution stops when NEXTINT is equal to N + 1. The equivalent for loop is provided for comparison. while Loop SUM := 0; NEXTINT := 1; while NEXTINT 0, 35 is the new high score 60 > 35, 60 is the new high score 47 60, 80 is the new high score 75 Now that the algorithm for DOSCORES is refined, we can draw the system structure chart (see Fig. 3.29) that describes this step and its subproblems. Each subproblem is implemented as a procedure. The structure chart shows that SCORE is an output of procedure READSTU and an input to procedures CATEGORIZE and CHECKHIGH. Since CATEGORIZE must increment a category counter, the counters are input/output parameters for this subproblem. Since HIGH may be modified by CHECKHIGH, it is also an input/output parameter. Fig. 3.29 Structure Chart for Procedure DOSCORES. DOSCORES l' FIRST, LAST, SCORE I READSTU I SCORE, MINSAT, MINOUT ~ It NUMUNS, NUMSAT, NUMOUT ~I CATEGORIZE I SCORE ~ It HIGH ~I CHECKHIGH 3.7 CASE STUDIES 147 Procedure DOSCORES is shown in Fig. 3.30. FIRST, LAST, and SCORE are declared as local variables in the procedure; SENTINEL is a local constant. Each of the procedures shown in the structure chart for DOSCORES are nested within DOSCORES. A sample run of the complete program is shown in Fig. 3.31. Procedure DOSCORES begins by initializing all counters and HIGH to zero. It calls READ STU to read each student's initials and score and calls CHECKHIGH to check for the highest score so far. procedure DOSCORES (MINSAT, MINOUT linputl : INTEGER; var NUMUNS, NUMSAT, NUMOUT, HIGH loutputl : INTEGER); IReads each student's initials and score, finds the number of scores in each category, and finds the high score. I const SENTINEL = '*'; Isentinel value I var SCORE : INTEGER; FIRST, LAST: CHAR; leach exam scorel Istudent's in~tialsl procedure READSTU (var FIRST, LAST Ioutput I : CHAR; var SCORE loutputl : INTEGER); [re ad a student's initials and score-called by DOSCORES.I begin IREADSTUI WRITELN; WRITE ('Enter student initials or **: '); READLN (FIRST, LAST); if FIRST SENTINEL then begin WRITE (' Enter score: '); READLN (SCORE) end I.i f ] end; !READSTUI IGet Ln i t i e Ls] IGet sco re] procedure CATEGORIZE (SCORE, MINSAT, MINOUT linputl : INTEGER; var NUMUNS, NUMSAT, NUMOUT Iinput/output I : INTEGER); ICategorizes SCORE and increments the appropriate counter-called by DOSCORES. I begin ICATEGORIZE I if SCORE CONTROL STATEMENTS lunsatisfactory scorel Isatisfactory scorel begin WRITELN ('Outstanding' NUMOUT := NUMOUT + 1 end routstandingl end; !CATEGORIZEI [outstanding score] :40); procedure CHECKHIGH (SCORE [inputl : INTEGER; var HIGH I input/output I : INTEGER); [Checks whether SCORE is the highest score so far.} begin {CHECKHIGHI if SCORE > HIGH then HIGH := SCORE end; /CHECKHIGHI begin IDOSCORESI [Initialize counters and HIGH to zerol NUMUNS := 0; NUMSAT:= 0; NUMOUT:= 0; ISave new high scorel HIGH:= 0; [Categorize each score and find HIGHI READSTU (FIRST, LAST, SCORE); [Read initials and score) while FIRST SENTINEL do begin [Categorize SCORE and increment appropriate counter) CATEGORIZE (SCORE, MINSAT, MINOUT, NUMUNS, NUMSAT, NUMOUT)i CHECKHIGH (SCORE, HIGH); [Check for high score I READSTU (FIRST, LAST, SCORE) [Read initials and scorel end [wh Ll.e ] end; /DOSCORES I Fig. 3.30 Procedure DOSCORES (Replaces the Stub in Fig. 3.28) Fig. 3.31 Sample Run of Program GRADER Enter the minimum satisfactory score: 75 Enter the minimum outstanding score: 90 Enter student initials or **: EK Enter score: 100 outstanding Enter student initials or **: RK Enter score: 75 satisfactory Enter student initials or **: HH Enter score: 89 satisfactory Enter student initials or **: ** Number of outstanding scores: 1 Number of satisfactory scores: 2 Number of unsatisfactory scores: 0 High score on exam: 100 3.7 CASE STUDIES 149 Procedure DOSCORES calls procedure CATEGORIZE to find the category of each score. The multiple alternative decision in CATEGORIZE prints the score category and increments a counter. The symbols :40 in each WRITELN statement of CATEGORIZE cause the last character of the category string to be printed in column 40. making it easy to distinguish the program output from the input data. Self-check Exercises for Section 3.7 1. Modify the checkbook program so that a penalty amount of $15.00 is deducted for each overdrawn check and a count of overdrawn checks is maintained and printed next to each overdrawn check. Reset the count of overdrafts to zero whenever the balance becomes positive. 2. What would be the effect of transposing the parameters MINSAT and MINOUT in the call to procedure DOSCORES or READSCALE in Fig. 3.29? Would the compiler detect this error? 3. What would happen if the person using this program became confused and switched the data values entered for MINSAT and MINOUT? Rewrite procedure READSCALE so that it checks for this error and takes corrective action if it occurs. 4. Draw the procedure nesting diagrams (see Fig. 3.20) for both program systems. III Debugging a Program System As the number of modules and statements in a program system grows. the possibility of error also increases. If each module is kept to a manageable size. then the likelihood of error will increase much more slowly. It will also be easier to read and test each module. Finally. the limited use of global variables will minimize the chance of harmful side effects that are always difficult to locate. Whenever possible. test each procedure separately by writing a short driver program that contains all necessary declarations. The body of the driver program should assign values to the input parameters. call the procedure. and display the procedure results. Even before all procedures are written. you can test the main program flow by substituting stubs for the missing procedures. If you do this make sure that any procedure outputs needed by the main program are defined in the stub. A list of suggestions for preventing and debugging errors in a program system follows. Debugging Tips for Procedures 1. Carefully document each procedure parameter and local identifier us- ing comments. Also describe the procedure operation using comments. 2. During debugging, leave a trace of execution by printing the procedure 150 CONTROL STATEMENTS name as it is entered. Sometimes a trace showing the currently executing procedure and the procedures that called it is printed by Pascal when a run-time error occurs. 3. During debugging, print the values of all input parameters upon entry to a procedure. Make sure that these values make sense. 4. During debugging, print the values of all output parameters after returning from a procedure. Make sure that all output parameters are declared as variable parameters. • Common Programming Errors Remember to bracket each compound statement with begin and end. The compiler will detect a syntax error if either a beg in is missing or an end is missing, but not both. If both the begin and end are missing, then your program will be translated, but it will not execute as intended. For example, the while statement below is an infinite (non-terminating) loop since the loop body consists of the assignment statement only. WRITE ('Enter a number: '); READLN (NEXT); while NEXT SENTINEL do SUM := SUM + ITEM; WRITE ('Enter a number: '); READLN (NEXT) Be very careful when using tests for inequality to control the repetition of a while loop. The loop below is intended to process all transactions for a bank account while the balance is positive. while BALANCE 0.0 do UPDATE (BALANCE) If the bank balance goes from a positive to a negative amount without being exactly 0.0, the loop will not terminate. The loop below would be safer. while BALANCE> 0.0 do UPDATE (BALANCE) Unfortunately, there are many opportunities for error when using procedures with parameter lists. The proper use of parameters is difficult for beginning programmers to master. One obvious pitfall is to be sure that the actual parameter list has the same number of parameters as the formal parameter list. The syntax error "number of parameters does not agree with declaration" will indicate this problem. Each actual parameter must be the same data type as its corresponding formal parameter. An actual parameter that correponds to a variable formal parameter must be a variable. A violation of either of these rules will result in a syntax error. 3.9 COMMON PROGRAMMING ERRORS 151 A procedure result should be returned to the calling module by assigning a value to a variable parameter. Any value assigned to a value parameter will be stored locally in the procedure and will not be returned. This error cannot be detected by Pascal, • Chapter Review Syntax diagrams were introduced in this chapter and we saw how to use them to check the syntax of Pascal statement. A complete set of syntax diagrams for Pascal is provided in Appendix C. The if statement was examined more formally. We saw how to use nested if statements to implement decisions with several alternatives. A conditional looping structure, the while statement, was used to implement loops whose repetition is controlled by a condition. The while statement is useful when the exact number of repetitions required is not known before the loop begins. Separate Pascal statements are needed for initializing and updating the loop control variable associated with a while loop. One common technique for controlling the repetition of a while loop is using a special sentinel value to indicate that all required data have been processed. In this case, the loop control variable is a problem input; it is initialized when the first data value is read (priming read) and updated at the end of the loop when the next data value is read. Loop repetition terminates when the sentinel value is read into the loop control variable. The use of procedure parameters for passing data to and from procedures was also discussed. The parameter list provides a highly visible communication path between the procedure and the calling program. By using parameters, we can cause different data to be manipulated by a procedure each time we call it. This makes it easier to reuse the procedure in another program system. There are two types of parameters: value and variable. A value parameter is used only for passing data into a procedure. A variable parameter is used to return results from a procedure. The actual parameter corresponding to a value parameter may be an expression or a constant; the actual parameter corresponding to a variable parameter must be a variable. We discussed the scope of identifiers. An identifier may be referenced anywhere within the block that declares it. If one block is nested inside another and an identifier is declared in the outer block, then the identifier's meaning in the inner block is determined by its declaration in the outer block. If the identifer is declared in both blocks, then its meaning in the inner block is determined by its declaration in the inner block. A global variable is one that is declared in the main program; a local variable is one that is declared in a procedure. A local variable is defined only during the execution of the procedure; its value is lost when the procedure is done. 152 CONTROL STATEMENTS New Pascal Statements The Pascal statements introduced in Chapter 3 are shown in Table 3.14. Table 3.14 Summary of New Pascal Statements Statement Effect MUltiple alternative decision if SCORE >= 90 then If SCORE is greater than or equal to 90, then COUNTA is increased by 1; otherwise, if SCORE is greater than or equal to 80, COUNTB is increased; otherwise, COUNTC is increased. begin [Aj WRITE (' A' ) : COUNTA := COUNTA + 1 end [Aj else if SCORE >= 80 then begin [Bj WRITE (' B ' ) : COUNTB .= COUNTB + 1 end [Bj else begin [Cj WRITE (' C ' ) : COUNTC := COUNTC + 1 end [Cj While statement SUM := 0; while SUM 3 4 while DECIMAL 0 do DIGIT := DECIMAL mod BASE WRITE (DIGIT :1) DECIMAL := DECIMAL div BASE a is true Remainder is 4 Print 4 Quotient is 4 4 4 a a a is false - while DECIMAL 0 do exit In both these cases, the algebraic rule that multiplication is performed before addition is applicable. The use of parentheses in the second expression ensures that subtraction is done first. The rules for expression evaluation in Pascal are based on standard algebraic rules: a. All parenthesized subexpressions must be evaluated first. Nested parenthesized subexpressions must be evaluated inside out, with the innermost subexpression evaluated first. b. [operator precedence) Operators in the same subexpression are evaluated in the following order: *, /, first last div, mod +, - c. (left associative) Operators in the same subexpression and at the same precedence level [such as + and -) are evaluated left to right. Example 4.4 The formula for the area of a circle, a as AREA := PI * RADIUS * = PI X r 2, may be written in Pascal RADIUS where PI is the constant 3.14159. The evaluation tree for this formula is shown in Fig. 4.4. In this tree, the arrows connect each operand with its operator. The order of operator evaluation is shown by the number to the left of each operator; the rules that apply are shown to the right. We shall see another way to specify RADIUS * RADIUS in the next section. Example 4.5 The formula for the average velocity, v, of a particle traveling on a line between points P1 and P2 in time t1 to t2 is v = P2 - P1 t2 - t1 4.2 NUMERIC DATA TYPES-REAL AND INTEGER 165 AREA: = PI * RADIUS * RADIUS AREA Fig. 4.4 Evaluation Tree for AREA: = PI • RADIUS' RADIUS This formula may be written and evaluated in Pascal as shown in Fig. 4.5. Inserting parentheses in an expression affects the order of operator evaluation. Parentheses should be used freely to clarify the order of evaluation. V : = (P2 - Pi) / (T2 - 'I'L) v Fig. 4.5 Evaluation Tree for V := (P2 - P1) / (T2 - T1) Example 4.6 Refer to Fig. 4.6 as you consider the expression Z - (A + B DIV 2) + W * Y containing integer variables only. The parenthesized subexpression (A + B 2) is evaluated first [Rule (a)] beginning with B DIV 2 [(Rule (b)]. Once the value of B DIV 2 is determined, it can be added to A to obtain the value of (A + B DIV 2). Next the multiplication operation is performed [Rule (b)] and the value for W * Y is determined. Then the value of (A + B DIV 2) is subtracted from Z [Rule (c)], and finally this result is added to W * Y. DIV Writing Mathematical Formulas in Pascal There are two problem areas in writing a mathematical formula in Pascal; one concerns multiplication and the other concerns division. Multiplication 166 SIMPLE DATA TYPES z- (A + +W* B DIV 2) Fig. 4.6 Evaluation Tree for Z - (A + Y B DIV 2) + W• Y can often be implied in a mathematical formula by writing the two items to be multiplied next to each other; e.g., a = be, In Pascal, however, the * operator must always be used to indicate multiplication as in: A := B * C The other difficulty arises in formulas involving division. We normally write the numerator and denominator on separate lines: m = L=J2 x - a In Pascal, all assignment statements must be written in a linear form; consequently parentheses are often needed to separate the numerator from the denominator, and to clearly indicate the order of evaluation of the operators in the expression. The formula above would be written as M Example 4.7 := (Y - B) / (X - A) This example illustrates how several mathematical formulas can be written in Pascal. Mathematical Formula a. b 2 - 4ac b. a + b - c a + -b c. c + d d. 1 +x e. a X -(b B * B - 4 A + B - C * A * (A + B) / (C 1 / --2 1 Pascal Expression + c) A (1 + X * (-(B + C + D) * X) C) ) The points illustrated are summarized as follows: 4.2 NUMERIC DATA TYPES-REAL AND INTEGER 167 • Always specify multiplication explicitly by using the operator * where needed (see Example 4.7a). • Use parentheses when required to control the order of operator evaluation (see Examples 4.7c and d). • Never write two arithmetic operators in succession; they must be separated by an operand or parentheses (see Example 4.7e). Self-check Exercises for Section 4.2 1. What happens if BASE is 2 instead of 10 in procedure PRINTDIGITS? What result is generated for PRINTDIGITS(23) and PRINTDIGITS (64) if BASE is 2? Answer these questions if BASE is 8. 2. Evaluate the following expressions with 7 and 22 as operands. 22 div 7 7 div 22 22 mod 7 7 mod 22 Repeat this exercise for the pairs of integers: 16 15 I 3I 23 4 I 16 3. Given the declarations canst PI 3.14159; MAXI 1000; var X, Y : REAL; A, B , I : INTEGER; find the value of each of the valid statements below. Also indicate which are invalid and why. Assume that A is 3, B is 4, and Y is -1. O. a. I := A mod B b. I := (990 - MAXI) div A c. I := A mod Y d. X := PI * Y e. I := A / B f. X .= A / B g. X := A mod (A / B) h. I := B div 0 i. I := A mod (990 - MAXI) j. I := (MAXI - 990) div A k. X := A / Y I. I := PI * A m. X := PI div Y n. X := A div B o. I := (MAXI - 990) mod A p. I := A mod 0 q. I .= A mod (MAXI - 990) 168 SIMPLE DATA TYPES 4. What values are assigned by the valid statements in 3 above, assuming A is 5, B is 2, and Y is 2.01 5. Assume that you have the following variable declarations: var COLOR, LIME, STRAW, YELLOW, RED, ORANGE : INTEGER; BLACK, WHITE, GREEN, BLUE, PURPLE, CRAYON : REAL; 6. • Evaluate each of the statements below given the values: COLOR is 2, BLACK is 2.5, CRAYON is -1.3, STRAW is 1, RED is 3, PURPLE is a.3E1. a. WHITE := COLOR * 2.5 / PURPLE b. GREEN := COLOR / PURPLE c. ORANGE := COLOR DIV RED d. BLUE := (COLOR + STRAW) / (CRAYON + 0.3) e. LIME := RED DIV COLOR + RED MOD COLOR f. PURPLE := STRAW / RED * COLOR Let A, B, C, and X be the names of four type REAL variables and I, J, and K the names of three type INTEGER variables. Each of the statements below contains a violation of the rules for forming arithmetic expressions. Rewrite each statement so that it is consistent with these rules. d. K .= 3(1 + J) a. X := 4.0 A * C e. X := 5A / BC b. A := AC f. I .= 5J3 C. I .= 2 * -J Functions in Arithmetic Expressions The function is a feature of Pascal that is helpful in specifying numerical computations. Each function performs a different mathematical operation (square root, cosine, etc.] and computes a single value. Functions are referenced directly in an expression: the value computed by the function is then substituted for the function reference. Example 4.8 SQRT is the name of a function that computes the square root of a positive value. In the assignment statement Y := 5.7 + SQRT(20.25) the value computed by the function reference SQRT(20. 25) is 4.5; this value replaces the function reference in the expression and is added to 5.7. The result of the addition or 10 .2 (5.7 + 4 .5) is stored in the real variable Y. Pascal provides a number of standard mathematical functions, such as SQRT, that may be used by the programmer. The names and descriptions of these functions are given in Table 4.3. The function name is always 4.3 FUNCTIONS IN ARITHMETIC EXPRESSIONS 169 Table 4.3 Mathematical Functions Name Description of Computation Argument Result ABS The absolute value of the argument real/integer same as argument EXP The value of e (2.71828) raised to the power of the argument real/integer real LN The logarithm (to the base e) of the argument real/integer real SQR The square of the argument real/integer same as argument SQRT The positive square root of the argument real/integer (positive) real ROUND The closest integer value to the argument real integer TRUNC The integral part of the argument real integer ARCTAN The arc tangent of the argument real/integer (radians) real COS The cosine of the argument real/integer (radians) real SIN The sine of the argument real/integer (radians) real followed by its argument (an actual parameter) enclosed in parentheses as shown in Example 4.8 (argument is 20.25). Any legal arithmetic expression of the proper type may be used as an argument for these functions. Example 4.9 The Pascal functions SQR (square) and SQRT may be used to compute the roots of a quadratic equation in X of the form AX 2 + BX + C = 0 The two roots are expressed in algebraic form as ROOT = -B + yB2 - 4AC , ROO T2 = 2A 1 -B - yB2 - 4AC 2A ----==-------''------=----'- The Pascal implementation is DISC := SQR(B) - 4 i f DISC > 0 then * A * C begin ROOTl .= (-B + SQRT(DISC)) / ROOT2 := (-B - SQRT(DISC)) / end [ Lf ] 170 SIMPLE DATA TYPES (2 (2 * * A)i A) where the variable DISC represents the discriminant (B2 - 4AC) of the equation. Except for ABS. SQR. ROUND, and TRUNC. each of the functions listed in Table 4.3 returns (computes) a real value regardless of its parameter type (REAL or INTEGER). The type of the result computed by a reference to ABS or SQR is the same as the type of its parameter. The functions ROUND and TRUNC require type REAL parameters and always return integer values. These functions determine the integral part of a real-valued expression; consequently the expressions TRUNC(1.5 * GROSS) ROUND(TOTALSCORE / NUMSTUDENTS) have INTEGER values and may be assigned to INTEGER variables. TRUNC simply truncates, or removes, the fractional part of its parameter; ROUND rounds its parameter to the nearest whole number. For example, TRUNC(l7.5) is 17 while ROUND(17.5) is 18; TRUNC(-3.8) is-3 while ROUND (-3.8) is -4. Example 4.10 The program in Fig. 4.7 illustrates the use of several arithmetic functions. The function references are inserted in the output list of the WRITELN statement. The ABS function is used to find the absolute value of X before the SQRT function is called as the square root of a negative number is undefined. program ARITHFUNC (INPUT, OUTPUT); IIllustrates the arithmetic functions. I const SENTINEL = 0.0; Isentinel value I var X : REAL; leach data valuel begin {ARITHFUNCI IPrint the table heading. I WRITELN ('After each line enter a real number or 0.0 to stop'); WRITELN; WRITELN ('X', 'TRUNC(X)' :16, 'ROUND(X) , :10, 'ABS(X)' :10, 'SQR(X)' :10, 'SQRT(ABS(X))' :15); IRead and process each value of X.I READLN (X); Iget first number I while X SENTINEL do begin WRITELN (TRUNC(X) :17, ROUND (X) :10, ABS(X) :10:2, S QR ( X ) : 10 : 2 , SQRT(ABS(X)) :10:2); READLN (X) Iget next number I end [wh i Le ] end. IARITHFUNCI After each line enter a real number or 0.0 to stop 4.3 FUNCTIONS IN ARITHMETIC EXPRESSIONS 171 x SQRT(ABS(X) ) TRUNC(X) ROUND(X) ABS(X) SQR(X) 4 4 4.30 18.49 2.07 -24 -25 24.78 614 .05 4.98 4.3 -24.78 0.0 Fig. 4.7 Using the Arithmetic Functions Example 4.11 The program in Fig. 4.8 draws a sine curve. It uses the Pascal function S IN which returns the trigonometric sine of its parameter, an angle expressed in radians. The assignment statement * RADIAN := THETA / 180 PIi computes the number of radians corresponding to the angle THETA (measured in degrees). The value of the loop control variable THETA is increased by eighteen degrees (value of STEP) at the end of each repetition of the loop body. The assignment statement INDENT := 1 + ROUND(20 * (1 + SIN(RADIAN)))i assigns a value between 1 (when SIN(RADIAN) is -1) and 41 (when SIN(RADIAN) is 1) to INDENT. Finally the statement (plot * in column INDENT I WRITE (STAR :INDENT)i plots an asterisk somewhere in columns 1 through 41 as determined by the value of INDENT. Recall that a string (or character) is printed right justified in its field; the value of INDENT determines the size of the output field. The sine value is printed after each asterisk by the statement WRITELN (SIN(RADIAN) :20)i (print sine valuel PROGRAM STYLE Checking boundary values The discussion for Example 4.11 states that the value of INDENT ranges from 1 to 41 as the sine value goes from -1 to 1. It is always a good idea to check the accuracy of these assumptions; this usually can be done by checking the boundaries of the range as shown below. SIN(RADIAN) is -1, INDENT := 1 + ROUND(20 INDENT := 1 + ROUND(20 INDENT := 1 172 SIMPLE DATA TYPES * (1 + (-1)) * 0) SIN(RADIAN) is +1, INDENT := 1 + ROUND(20 INDENT := 1 + ROUND(20 INDENT := 41 * * (1 + 1)) 2) Fig. 4.8 Plotting a Sine Curve. program SINECURVE (OUTPUT); IPlots a sine curve. I const PI = 3.14159; 18; STEP r * f ,• STAR Iconstant Pij lincrement in degreesj Isymbol being plottedj var [a nq Le in degreesj langle in radiansj Icolumn of each * j THETA, RADIAN : REAL; INDENT : INTEGER; begin ISINECURVEj WRITELN ('Sine curve plot' :28); THETA := 0; linitial value of THETAj while THETA = 'a') and (LOWCHAR = '0') and (NEXT ='O' )and(NEXT='O' )and(NEXT='O' )and(NEXT O. the value of x that satisfies the original equation 1 is given by equation 2. (2) If both band mare O. then any real number satisfies the equation. (3) If m = 0 and b = 0 then no real number x satisfies this equation. 11. Each year the legislature of a state rates the productivity of the faculty of each of the state-supported colleges and universities. The rating is based on reports submitted by each faculty member indicating the average number of hours worked per week during the school year. Each faculty member is ranked. and the university also receives an overall rank. The faculty productivity rank is computed as follows: (1) Faculty members averaging over 55 hours per week are considered high- ly productive. (2) Faculty members averaging between 35 and 55 hours a week. inclusive. are considered satisfactory. (3) Faculty members averaging fewer than 35 hours a week are considered overpaid. PROGRAMMING PROJECTS 257 The productivity rating of each school is determined by first computing the faculty average for the school and then comparing the faculty average to the category ranges above. Write a program to rank the following faculty; Name HERM FLO JAKE MO SOL TONY AL Hours 63 37 20 55 72 40 12 Your program should print a three-column table giving the name, hours and productivity rank of each faculty member. It should also compute and print the school's overall productivity ranking. 12. Write a savings account transaction program that will process the following set of data ADAM W D W Z EVE w z MARY W D W Z SAM 1054.37 25.00 243.35 254.55 2008.24 15.55 24 62.48 128. 13.42 84.60 group 1 I 1 7.77 } Z JOE W D 15.27 16.12 10.00 group 2 group 3 group 4 group 5 Z BETH D 12900.001 9270.00 group 6 Z The first record in each group (header) gives the name for an account and the starting balance in the account. All subsequent records show the amount of each withdrawal (W) or deposit (D) that was made for that account followed by a sentinel value (Z). Print out the final balance for each of the accounts processed. If a balance becomes negative, print an appropriate message and take whatever corrective steps you deem proper. If there are no transactions for an account, print a message so indicating. 13. 258 Write a program to print a table of the following form. MORE CONTROL STATEMENTS Home loan mortgage interest payment table Total Payment Monthly Payment Duration (Years) 20 25 30 20 Rate (Percent) 10.00 10.00 10.00 10.25 Your program should print a table showing the monthly and total payments on a loan of $1.000 for interest rates from 10% to 14% with increments of 0.25%. The loan duration should be 20. 25. and 30 years. Your program should contain nested loops. some of which may be inside separate procedures. depending upon your solution. Be careful to remove all redundant computations from inside your loops. 14. The equation of the form (1) ax- + bx + c = 0 (a. b. c real numbers. with a 0) is called a quadratic equation in x. The real roots of this equation are those values of x for which axevaluates to zero. Thus. if a roots of = xZ are + 3 and + bx + = 1, b + c -15. then the real 2. and c 2x - 15 - 5. since (3JZ + 2(3) - 15 = 9 + 6 - 15 = 0 and (-5JZ + 2( -5) - 15 = 25 - 10 - 15 = 0 Quadratic equations of the form (1) have either 2 real and different roots. 2 real and equal roots. or no real roots. The determination as to which of these three conditions holds for a given equation can be made by evaluating the discriminant d of the equation. where d = bZ - 4ac There are three distinct possibilities: 1. 2. 3. If d > O. then the equation has two real and unequal roots. If d = O. the equation has two real and equal roots. If d Write a program to compute and print the real roots of quadratic equations having the following value of a. b, and c. a 1.0 1.0 1.0 1.0 1.0 b 2.0 -1.25 0.0 -80.0 -6.0 c -15.0 -9.375 1.0 -900.0 9.0 PROGRAMMING PROJECTS 259 If the equation has no real roots for a set of a, band c, print an appropriate message and read the next set. Hint: If the equation has two real and equal roots, then the root values are given by the expression Root 1 = Root z = -b/Za If the equation has two real and unequal roots, their values may be computed as Root 1 = -b+ V"d Za -b - V"d Root Z = --='------'--= Za 15. At Bob's Bank, Bob senior would like to keep some information on his employees readily available. Bob junior suggested he keep the data on the computer so that it would be available anytime someone ran a program. As the sole computer programmer you are to write a program which will read in the employee data and print a report. The data entered for each employee and the output corresponding to each data item are described next. Data Initials Class Age License number Code Corresponding output same as entered This will be a character A, B, C which you will convert to print one of the classifications A-MANAGEMENT B-SUPERVISOR C-CLERICAL This will be the employee's actual age, but you will print out the group that the employee falls in according to the ranges given below: 65: Group 4 This is a 4 digit number, but you will print out I EVEN I or '000' . (This is for possible gas rationing). This is to be calculated by adding up the digits of the employee license number. (For example 14, is the code number for license number 5432.) The report line shown below is generated for the data: SCS, B, 37, 4436 NAME SCS POSITION SUPERVISOR AGE GROUP 25 - 40 Use the following data in your program. TGP C 18 4737 JWW A 25 9630 TMS C 41 7000 MLH B 67 2468 260 MORE CONTROL STATEMENTS LICENSE EVEN CODE NUMBER 17 16. One of the simplest and most often used means of encoding data is the principle of shifting the alphabet some number of letters in one direction or another. For the sake of simplicity assume all the letters of some message are capitalized and all punctuation and blanks are not encoded. Write a program that will read in a series of words and convert each to some other word and then print it. The first letter that you read will indicate what the shift will be. For example if the first letter was a J then all A's would be converted to J's, B's to K's, C's to L's, etc. The amount to shift in the alphabet can be determined by calculating the difference of the ordinal value of A and the ordinal value of this first letter. When a shift exceeds Z the program should start over at A. Hint: Add the excess over the ordinal value of Z to the ordinal value of A minus 1. Sample input might be: F NIGHTS OF FUTURE'S PAST where F would be used to substitute for A, G for B, etc. Test this program with the example above. (What would need to be done to the program to decode the message back again?) 17. A problem encountered in writing compilers or determining efficient means of storing data on disks is converting a name into a unique or a reasonably unique numeric value. This procedure is called hashing. Several algorithms are used to accomplish this task. One of the simpler methods is to use the numeric representation of each letter in some type of equation. In this problem you are to convert a word into a reproducible integer value between 0 and 50 O. To get this value, add each ordinal value of a letter times that letter's position within the word. This should generate a rather large number which may not be within the required range. To calculate a number within the range, determine the modulus of this large number and 500. For example the number for ACE would be: 1 * 65 + 2 * 67 + 3 * 69 or 4 06. Test your program with several words and print out the calculated value for each word. 18. Often in doing a statistical analysis a calculation that is required is the standard deviation (sd). It is derived by summing a series of numbers and doing a few additional calculations which are depicted in the following equation. Note: The symbol i represents a summation of values from 1 to n which i=l can easily be implemented as a for loop. The first summation under the square root sign is the sum xi + x~ + ... + x~ where Xi is the ith data item and n is the count of the number of items read. sd = For this problem, read in a series of real numbers and determine PROGRAMMING PROJECTS 261 (1) the (2) the (3) the (4) the standard deviation largest and smallest values range of the numbers average value Use functions in cases where only one value is being returned. 19. Write a procedure that reads in a string of characters representing a real number. The procedure will skip any leading blanks and then read all characters through the first character that cannot be part of the number. If an illegal real value is read. a program flag will be set to indicate this; otherwise the value of the number entered will be returned as a procedure result. (Unlike the standard Pascal READ procedure. the first character following the number is also read.) Hint: This procedure must recognize all valid forms of real data including integers. real numbers. and scientific notation. The numeric value returned is type REAL. Examples of the desired procedure outputs are shown next Input Characters -1. 345 1.354E02 262 Real Value -1. 345 135.4 15E-3 0.015 999 17. .012 1.35Ew x 999.0 17.0 undefined undefined undefined MORE CONTROL STATEMENTS Valid Flag TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE Arrays 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 6.10 6.11 Declaring and Referencing Arrays Arrays with Integer Subscripts Case Study Manipulating Entire Arrays Reading Part of an Array General Arrays Character Strings Multidimensional Arrays Case Study Common Programming Errors Chapter Review In the programs written so far. each variable was associated with a single memory cell. These variables are called simple variables. and their data types are simple types. In this chapter. we will begin the study of data structures. A data structure is a grouping of related data items in memory. The Items in a data structure can be processed individually although some operations may be performed on the structure as a whole. Generally, the form of a data structure is declared in a type declaration statement. The array is a data structure used for storing a collection of data items that are all the same type (e.g. all the exam scores for a class). By using an array, we can associate a single variable name (e.g. SCORES) with an en263 tire collection of data. This enables us to save the entire collection of data in adjacent cells of main memory (one item per memory cell) and to easily reference individual items. To process an individual item, we need to specify the array name and indicate which array element is being manipulated (e.g. SCORES [3] references the third item in the array SCORES). Since each score is saved in a separate cell in main memory, we can process the individual items more than once and in any order we wish. In previous programs we reused the same cell to store each exam score. Consequently, we could no longer access the third score after the fourth score was read. We will see that the use of arrays also makes it easier for us to process textual data. Text will be stored in special arrays called strings. Some simple string manipulation operations will be discussed. II Declaring and Referencing Arrays Usually, we first describe the structure of an array in an array type declaration. Then we may allocate storage for one or more arrays of that type. The array type REALARRAY is declared below followed by the declaration of array X of type REALARRAY. type REALARRAY = array [1 .. 8] of REAL; var X REALARRAY; Pascal allocates eight memory cells for the name X; these memory cells will be adjacent to each other in memory. Each element of array X may contain a single real value so a total of eight real values may be stored and referenced using the array name X. In order to process the data stored in an array, we must be able to reference each individual element. The array subscript is used to differentiate between elements of the same array; the subscript is written in brackets after the array name. For example, if X is the array with eight elements declared above, then we may refer to the elements of the array X as shown in Fig. 6.1. The subscripted variable X [ 1] (read as X sub 1) references the first element of the array X (value is 16.0), X [ 2] references Fig. 6.1 The Eight Elements of the Array X. array X First element 264 ARRAYS Second element Third element Eighth element the second element [value is 12.0), and X [ 8] references the eighth element [value is -54.5). Example 6.1 Let X be the array shown in Fig. 6.1. Some statements that manipulate this array are shown in Table 6.1. Table 6.1 Statements that Manipulate Array X Statement Explanation WRITELN (X [ 1] ) X[4] := 25.0 SUM .= X[l] + X[2] Displays the value of X [ 1] or 16.0. Stores the value 25.0 in X [ 4 ] . Stores the sum of X [ 1] and X [ 2] or 28.0 in the variable SUM. Adds X [3] to SUM. The new SUM is 34.0. Adds 1.0 to X [ 4 ]. The new X [ 4 ] is 26.0. Stores the sum of X [ 1] and X [ 2] in X [ 3 ] . The new X [ 3] is 28.0. SUM := SUM + X[3] X[4] := X[4] + 1.0 X[3] := xt i j + X[2] The contents of array X, after execution of these statements, is shown below. Only X [ 3] and X [4] are changed array X Example 6.2 X[i] X[2] X[3] First element Second element Third element X[4] X[5] X[6] xl?] X[8] Eighth element Two array types [BOOLARRAY and SCOREARRAY) and two arrays [ANSWERS and SCORES) are declared below. type BOOLARRAY = array [1 •• 10] of BOOLEAN; SCOREARRAY = array [1 •• 50] of 0 •• 100; var ANSWERS : BOOLARRAY: SCORES : SCOREARRAY: The array ANSWERS has 10 elements and each element can store a BOOLEAN value. This array may be used to store the 10 answers for a true-false quiz [e.g. ANSWERS [1] is TRUE, ANSWERS [2] is FALSE). The array SCORES has 50 elements and each element can store an integer value from 0 to 100. This array may be used to store exam scores for up to 50 students (e.g. SCORES[l] is 90, SCORES[2] is 65). 6.1 DECLARING AND REFERENCING ARRAYS 265 ARRAY TYPE DECLARATION array-type = array [subscript-type] of element-type Interpretation: The identifier array-type describes a collection of array elements; each element can store an item of type element-type. The subscript-type may be either of the standard types BOOLEAN or CHAR, any user-defined enumerated type, or subrange. There is an array element corresponding to each value in the subscript-type. Normally, the subscript-type is expressed as a subrange of the form MIN •• MAX, where ORD (MIN) must be less than ORD (MAX) . The element-type describes the type of each element in the collection or array. All elements of an array are the same type. Note 1: The standard types REAL and INTEGER may not be used as a subscript-type: however, a subrange of the integers may be a subscript-type. Note 2: The element-type may be any standard or user-defined type. It is important to realize that no storage space is allocated when the array-type is declared. The array-type describes the structure of an array only; storage space is allocated when a variable of this type is declared. Self-check Exercise for Section 6.1 1. Execute the statements in Table 6.1 for array X shown after the table. • Arrays with Integer Subscripts As indicated in section 6.1, the subscript-type may be any ordinal type (except type INTEGER) or a subrange. The subscript (sometimes called an index) used to reference an array element must be an expression that is assignment-compatible with the subscript-type. Very often, the subscripttype is a subrange whose host type is INTEGER. In this case, the subscript must be an integer expression whose value is in the range specified by the subscript-type. For the array SCORES declared in Example 6.2, the allowable subscript values are the integers from 1 through 50. Example 6.3 266 ARRAYS Table 6.2 shows some sample statements using the array X shown in Fig. 6.1. I is assumed to be a type INTEGER variable with value 6. Be sure you understand each statement. There are two illegal attempts to display element X [ 12 I. which is not in the array. These attempts will result in an "index expression out of bounds" run-time error. The last WRITE statement uses TRUNC (X [5]) (or TRUNC (2.5)) as a subscript expression. Since this evaluates to 2, the value of X [ 2] (and not Table 6.2 Sample Statements for Array X in Fig. 6.1 (I is 6) Statement Effect WRITE (5, X[5]) Displays 5 and 2.5 (value of X [ 5 ] ). WRITE (I, X [ I ] ) Displays 6 and 12.0 (value of X [ 6 ] ). WRITE (X[I] + 1) Displays 13.0 (value of 12.0 WRITE (X[I] + I) Displays 18.0 (value of 12.0 WRITE (X[I+1]) Displays 14.0 (value of X [ 7 ] ). WRITE (X[ 1+1]) Illegal attempt to display X [ 12 l. WRITE (X[2*I]) Illegal attempt to display X [ 12 l. WRITE (X[2*I-4]) Displays -54.5 (value of X [ 8 l). WRITE (X[TRUNC(X[5])]) Displays 12.0 (value of X [ 2 ] ). := X[I] Assigns 12.0 (value of X [ 6 ]) to X [ 5 ] . := X[I+1] Assigns 14.0 (value of X [ 7 ]) to X[ 6 ] . - Illegal assignment statement X[I-1] -X[I] X[I] + 1). + 6). 1 := X[I] X [ 5 l l is printed. If the value of TRUNC (X [ 5 ]) is outside the range 1 through 8, this would be an illegal subscript expression. ARRAY REFERENCE name [subscript] Interpretation: The subscript must be an expression that is assignment-compatible with the subscript-type specified in the declaration for array name. If the expression is the wrong data type, then the syntax error "index type is not compatible with declaration" will be detected. If the expression value is not in range, then the run-time error "index expression out of bounds" will occur. Often we wish to process the elements of an array in sequence, starting with the first element. For example we might enter data into the array or print its contents. This can be accomplished using a for loop whose loop control variable (e.g. I) is also used as the array subscript [e.g. X [ I ]). Increasing the value of the loop control variable by 1 causes the next array element to be processed. Example 6.4 The array CUBE declared below will be used to store the cubes of the first 10 integers (e.g. CUBE [1] is 1, CUBE [10] is 1000). 6.2 ARRAYS WITH INTEGER SUBSCRIPTS 267 type INTARRAY = array [1 .. 10] of INTEGER; var CUBE INTARRAY; I : INTEGER; 1 array of cubes j lloop control variablej The for statement for I := 1 to 10 do CUBE[I] := I * I * I initializes this array as shown below [1] Example 6.5 [2 ] [3 ] [4 ] array CUBE [5] [6] The program in Fig. 6.2 uses three for loops to process the array X. The loop control variable I (1 'A' 'A' 'A' 'A' 'B' '1 ' 'z' 'z' 'z' 'B' 'A' '2 ' 'I' '0 ' all characters equal '3 ' > ' l ' The last line of Table 6.5 shows the curious result that '30 >= , 123' is true, This is because the condition result is based solely on the relationship between the first pair of different characters, '3' and '1'. To avoid these kinds of results, it is best to replace any blanks in numeric strings with zeros. The condition '300' >= '123' is true while the condition '030' >= '123' is false as expected. In summary, the following operations can be performed on the packed array ALPHASTR (type is packed array [1 •• 3] of CHAR). 6.7 CHARACTER STRINGS 293 • A packed array can be assigned a string value. e.g. ALPHASTR := 'ABC' • A packed array can be written without using a loop. e.g. WRITE ( 'Alpha is " ALPHASTR : 3) • A packed array can be compared to another packed array or a string. e.g. ALPHASTR 'zzz' Arrays of Strings So far, each array element has been used to store a simple data value. Array elements can also be data structures. One application that comes to mind is an array whose elements are character strings. Example 6.16 The array MONTHNAME declared below can be used to store 12 character strings. Each element of MONTHNAME is a packed array of length 9 (type STRING). type MONTH = (JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC); STRING = packed array [1 •• 9] of CHARi NAMEARRAY array [MONTH] of STRING; var MONTHNAME : NAMEARRAY; CURMONTH : MONTH; (array of month namesl If the name of each month is stored in this array as shown in Fig. 6.17 (e.g. MONTHNAME [SEP] is 'September'), the statement WRITE (MONTHNAME[CURMONTH]) prints the string corresponding to the value of CURMONTH [e.g. If CURMONTH is FEB, the string 'February , is printed.] In this way, we can print the value of a variable whose type is an enumerated type. This array can be initialized by a series of assignment statements of the form MONTHNAME[JAN] := 'January , ,. MONTHNAME[FEB] := 'February'; MONTHNAME [JAN] MONTHNAME [FEB] MONTHNAME[DEC] Fig. 6.17 Array MONTHNAME The array MONTHNAME is an array of arrays. Such a data structure is called a two-dimensional array and is the subject of the next section. 294 ARRAYS Self-check Exercises for Section 6.7 1. Write a function that finds the actual length of a string that is padded with blanks. The blank padding should not be included in the actual length. 2. Write a procedure that stores the reverse of an input string parameter in its output parameter. (e.g. if the input string is 'happy ',the output string should be 'yppah I.) The actual length of the string being reversed (excluding blank padding) should also be an input parameter. 3. Write a program that uses the procedure in Exercise 2 above to determine whether or not a string is a palindrome. A palindrome is a string that reads the same way from left to right as it does from right to left. [e.g, 'LEVEL' is a palindrome.) • Multidimensional Arrays In this section, we will see how to store tables of data and how to represent multidimensional objects using arrays. A two-dimensional object we are all familiar with is a tic-rae-toe board. The declarations type BOARDROW array [1 •• 3] of CHAR; BOARDARRAY = array [1 •• 3] of BOARDROW; var TICTACTOE : BOARDARRAY; allocate storage for the array TICTACTOE shown in Fig. 6.18. This array has nine storage cells arranged in three rows and three columns. A character value may be stored in each cell. In the declarations above, BOARDROW is declared as an array type with three elements of type CHAR; BOARDARRAY is declared as an array type with three elements of type BOARDROW. Consequently, the variable TICTACTOE (type BOARDARRAY) is an array of arrays, or a two-dimensional array. Fig. 6.18 A Tic-Tac-Toe Board Stored as Array TICTACTOE Row 1 2 3 - - - TICTACTOE [2,3] 6.8 MULTIDIMENSIONAL ARRAYS 295 Usually, it is clearer to use one type declaration for an array type that is multidimensional. The declarations type BOARDARRAY = array [1 .. 3, 1 .. 3] of CHARi var TICTACTOE : BOARDARRAYi are equivalent to the ones above in that they allocate storage for a two-dimensional array (TICTACTOE) with three rows and three columns. This array has nine elements, each of which must be referenced by specifying a row subscript (1, 2, or 3) and a column subscript (1, 2, or 3). Each array element contains a character value. The array element TICTACTOE [2,3] pointed to in Fig. 6.18 is in row 2, column 3 of the array; it contains the character '0'. The diagonal line consisting of array elements TICTACTOE [ 1 ,1], TICTACTOE [ 2 ,2], and TICTACTOE [ 3 , 3] represents a win for player X because each cell contains the character' X I . ARRAY TYPE (Multidimensional) array [subscript 1 ] of array [subscript z]'" of array [subscript n ] of element-type or array i subscript.. subscripts. ..., subscript n ] of element-type Interpretation: Subscript, represents the subscript-type of dimension i of a multidimensional array. The subscript-type may be BOOLEAN, CHAR, an enumerated type, or a subrange. The element-type may be any standard data type or a previously-defined data type. Although we will focus our discussion on arrays with two and three dimensions, there is no limit on the number of dimensions allowed in Pascal. Example 6.17 The array TABLE declared below var TABLE: array [1 .. 7, 1 .• 5, 1 .. 6] of REALi consists of three dimensions: The first subscript may take values from 1 to 7; the second, from 1 to 5; and the third, from 1 to 6. A total of 7 X 5 X 6, or 210 real numbers may be stored in the array TABLE. All three subscripts must be specified in each reference to array TABLE (e.g, TABLE [2,3,4]). 296 ARRAYS Manipulation of Two-dimensional Arrays A row and column subscript must be specified in order to reference an element of a two-dimensional array. The type of each subscript must be compatible with the corresponding subscript type specified in the array declaration. If I is type INTEGER, the statement for I := 1 to 3 WRITE (TICTACTOE[l,I]) displays the first row of array TICTACTOE (TICTACTOE [ 1 ,1], TICTACTOE [1,2], and TICTACTOE [ 1 , 3]) on the current output line. The statement for I := 1 to 3 do WRITELN (TICTACTOE[I,2]) displays the second column of TICTACTOE (TICTACTOE [ 1 , 2 ], TICTACTOE [ 2,2], and TICTACTOE [ 3 ,2]) in a vertical line. Nested loops may be used to access all elements in a multidimensional array in a predetermined order. In the next examples, the outer loop determines the row being accessed, starting with row 1; the inner loop cycles through the elements of that row. This is called row-major order. Example 6.18 Procedure PRINTBOARD in Fig. 6.19 displays the current status of a tictac-toe board. A sample output of this procedure is also shown in Fig. 6.19. Fig. 6.19 Procedure PRINTBOARD with Sample Output procedure PRINTBOARD (TICTACTOE linputl : BOARDARRAY); [Displays the status of a tic-tac-toe board (array TICTACTOE).] var ROW, COLUMN: 1 •. 3; begin IPRINTBOARDl WRITELN ('-------')i for ROW := 1 TO 3 do begin [row] IPrint all columns of current row] for COLUMN := 1 TO 3 do WRITE ('!', TICTACTOE[ROW,COLUMN])i WRITELN (' I'); WRITELN ('-------') end Irowl end; IPRINTBOARDI !XIO! ! !O!X!O! IX! IX! 6.8 MULTIDIMENSIONAL ARRAYS 297 Example 6.19 Function BOARDFILLED in Fig. 6.20 returns a value of TRUE if a tic-tactoe board is all filled up; it returns a value of FALSE if there is at least one empty cell (contains a blank). In a tic-tac-toe program, function BOARDFILLED could be called before each move to determine whether there were any possible moves left. The if statement below prints an appropriate message when there are no moves. if BOARDFILLED(TICTACTOE) then WRITELN ('Game is a draw! ') function BOARDFILLED (TICTACTOE : BOARDARRAY) BOOLEAN; lReturns TRUE if the array TICTACTOE is filled; otherwise, returns FALSE. l const EMPTY , '., var ROW, COLUMN: 1 •• 3; begin lBOARDFILLEDj BOARDFILLED := TRUE; lassume the board is filledl IReset BOARDFILLED to FALSE if an empty cell is foundl for ROW := 1 TO 3 do for COLUMN := 1 TO 3 do if TICTACTOE[ROW,COLUMN] = EMPTY then BOARDFILLED .= FALSE end; lBOARDFILLEDl Fig. 6.20 Function BOARDFILLED Example 6.20 Procedure ENTERMOVE in Fig. 6.21 is used to enter a move into the array TICTACTOE. The character value stored (' X' or '0') is determined by the value of PLAYER. Procedure ENTERMOVE reads the move coordinates (MOVEROW, MOVECOLUMN). Function VALIDMOVE is used to test whether the coordinates are valid (i.e. they are in-range and the selected cell is currently empty). procedure ENTERMOVE (PLAYER linputl : CHARi var TICTACTOE linput/outputl : BOARDARRAY)i IStores an X or 0 (identity of PLAYER) in the array TICTACTOE.l var MOVEROW , MOVECOLUMN : INTEGER; Icoordinates of selected movel function VALIDMOVE (MOVEROW, MOVE COLUMN : INTEGER) : BOOLEAN; lTests whether the move coordinates (MOVEROW, MOVECOLUMN) are O.K .• References array TICTACTOE declared as a parameter of ENTERMOVE. I 298 ARRAYS const EMPTY = , '; begin lVALIDMOVEI if (MOVEROW in [1 .. 3]) and MOVE COLUMN in [1 .. 3]) then VALIDMOVE := TICTACTOE[MOVEROW, MOVECOLUMN] = EMPTY else VALIDMOVE := FALSE end; I VALIDMOVE I begin lENTERMOVEI repeat WRITE ('Enter your move coordinates'); WRITELN ('Enter the row first and then the column: READLN (MOVEROW, MOVECOLUMN) until VALIDMOVE(MOVEROW, MOVECOLUMN); lAssert: A valid move is enteredl TICTACTOE[MOVEROW, MOVECOLUMN] := PLAYER end; 1ENTERMOVE I '); lPlace X or 0 in celli Fig. 6.21 Procedure ENTER MOVE with Function VALIDMOVE If either move coordinate is out-of-range, the statement VALIDMOVE := FALSE is executed and function VALIDMOVE returns a value of FALSE. When both coordinates are in-range, the statement VALIDMOVE := TICTACTOE[MOVEROW, MOVECOLUMN] = EMPTY is executed, and the function result depends on whether the cell selected is empty. PROGRAM STYLE Referencing a non/oca/ array Function VALIDMOVE references the array TICTACTOE which is declared as a parameter in procedure ENTERMOVE. This is the first instance of a function referencing an identifier that is not declared locally. The reason for this is to save the time and memory space required to make a local copy of array TICTACTOE each time VALIDMOVE is called. Since VALIDMOVE is a local function used only by ENTERMOVE, it is reasonable to allow this reference to an identifier declared in ENTERMOVE. Another alternative would be to declare TICTACTOE as a variable parameter in VALIDMOVE. 6.8 MULTIDIMENSIONAL ARRAYS 299 Multidimensional Arrays with Noninteger Subscripts The subscript type for each dimension of the multidimensional array TICTACTOE is a sub range of type INTEGER. It is not necessary for the subscript types to have the same host type. The arrays in the next example have a different subscript type for each dimension. Example 6.21 A university offers 50 courses at each of five campuses. We can conveniently store the enrollments of these courses in the array ENROLL declared below. const MAXCOURSE type CAMPUS = 50; Imaximum number of coursesl (MAIN, AMBLER, CENTER, DELAWARE, MONTCO); var ENROLL: array [l •• MAXCOURSE, CAMPUS] of INTEGER; This array consists of 250 elements (see Fig. 6.22). ENROLL [ 1 , CENTER] represents the number of students in course 1 at CENTER campus. Number of students taking course 1 at CENTER campus Course 1 Course 2 Course 50 MAIN AMBLER Fig. 6.22 Two-dimensional Array CENTER DELAWARE MONTCO ENROLL If we wish to have this enrollment information broken down further according to student rank, we would need a three-dimensional array with 1000 elements. This array is declared below and shown in Fig. 6.23. const MAXCOURSE = 50; Imaximum number of coursesl type CAMPUS = (MAIN, AMBLER, CENTER, DELAWARE, MONTCO); RANK (FRESHMAN, SOPHOMORE, JUNIOR, SENIOR); 300 ARRAYS var CLASSENROLL : array [l .. MAXCOURSE, CAMPUS, RANK] of INTEGER; CURCAMPUS : CAMPUS; I current campus I CLASSRANK : RANK; Icurrent r ank] TOTAL : INTEGER; [s t.uderit; totals) The subscripted variable CLASSENROLL [ 1, CENTER, SENIOR] represents the number of seniors taking course 1 at CENTER campus. Number of seniors taking course 1 at CENTER campus SENIOR JUNIOR SOPHOMORE FRESHMAN Course 1 Course 2 Course 50 MAIN AMBLER CENTER DELAWARE MONTCO Fig. 6.23 Three-Dimensional Array CLASSENROLL Example 6.22 The program segment TOTAL := 0; for CLASSRANK := FRESHMAN to SENIOR do TOTAL := TOTAL + CLASSENROLL[l, CENTER, CLASSRANK] computes the total number of students of all ranks in course 1 at CENTER campus. The program segment TOTAL := 0; for CURCAMPUS := MAIN to MONTCO do for CLASSRANK := FRESHMAN to SENIOR do TOTAL := TOTAL + CLASSENROLL[l, CURCAMPUS, CLASSRANK] 6.8 MULTIDIMENSIONAL ARRAYS 301 computes the total number of students in course 1 (regardless of rank or campus). Self-check Exercises for Section 6.8 1. Explain why the if statement below cannot replace the if statement in function VALIDMOVE (see Fig. 6.21). if (MOVEROW in [1 .. 3]) and (MOVECOLUMN in [1 .. 3]) and (TICTACTOE[MOVEROW, MOVECOLUMN] = EMPTY) then VALIDMOVE := TRUE else VALIDMOVE := FALSE 2. Redefine MAXCOURSE as 5 and write and test program segments that perform the following operations: a) Enter the enrollment data for CLASSENROLL. b) Find the number of juniors in all classes at all campuses. Students will be counted once for each course in which they are enrolled. c) Find the number of sophomores on all campuses who are enrolled in course 2. d) Compute and print the number of students at MAIN campus enrolled in each course and the total number of students at MAIN campus in all courses. Students will be counted once for each course in which they are enrolled. e) Compute and print the number of upper-class students in all courses at each campus, as well as the total number of upper-class students enrolled. (Upper-class students are juniors and seniors.] Again, students will be counted once for each course in which they are enrolled. II Case Study At this point you have learned a lot about Pascal and programming. Knowledge of arrays will enable you to write fairly sophisticated programs. In this section, we will develop a general program that could be used by a company to analyze sales figures. Sales Analysis Problem Problem: The High Risk Software Company has employed us to develop a general sales analysis program that can be marketed to many different companies. This program will be menu-driven, which means that each user will be given a choice of options to perform. The menu format follows. GENERAL SALES ANALYSIS-choose an option 1. Enter sales data 302 ARRAYS 2. 3. 4. 5. 6. 7. Display sales table Tabulate sales data Tabulate sales data Graph sales data by Graph sales data by Exit the program by year by month year month We need to write a program that can perform these operations. Discussion: An examination of the menu shows that the central data structure will be an array of sales data organized by year and month. Since this is a general program, we should make the array large enough to accommodate many companies that are likely to use this product. A good choice would be the array type SALESARRAY below. type YEARRANGE = 1900 .• 1999; MONTH = (JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC); SALESARRAY = array [YEARRANGE, MONTH] of REAL By storing the names of the months in an array of strings (e.g. MONTHNAME [1] is I January I , MONTHNAME [2] is 'February "). we can simplify printing a month name. We also need two BOOLEAN flags (MONTHDONE and YEARDONE) to keep track of whether or not the monthly sums and annual sums have been computed. The problem data requirements and algorithm follow. the sales data each selected option The sales array with sums by year or month and graphic displays an array of month names (MONTHNAME : array [MONTH] of STRING) a program flag indicating if month sums are computed (MONTHDONE : BOOLEAN) a program flag indicating if year sums are computed (YEARDONE : BOOLEAN) Algorithm 1. Initialize the month name array and flags. 2. Read in each option selected and perform it. 6.9 CASE STUDY 303 The structure chart is shown in Fig. 6.24. The array SALES is declared in procedure DOCHOICE and passed to the level two procedures that are used to carry out each menu option. The main program is shown in Fig. 6.25. t I MONTHNAME, MONTHDONE, MONTHNAME, MONTHDONE, YEARDONE YEARDONE t I INITIALIZE DOCHOICE Fig. 6.24 Structure Chart for Sales Analysis Problem program ANALYZE (INPUT, OUTPUT); IAnalyzes an array of sales data. A menu is used to determine which operations are performed. The choices include: reading the sales data, displaying the data, tabulating sums by year or month, and graphing the tabulated sums. l const EXITCHOICE = 7; type SMALLINT = 1 •. EXITCHOICE; MONTH = (JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC); STRING = packed array [1 •• 9] of CHAR; NAMEARRAY array [MONTH] of STRING; var MONTHNAME : NAMEARRAY; YEARDONE : BOOLEAN; MONTHDONE : BOOLEAN; larray of month namesj Iprogram flag for year sumsl Iprogram flag for month sumsl procedure INITIALIZE (var MONTHNAME loutputj : NAMEARRAY; var MONTHDONE, YEARDONE loutputl : BOOLEAN); 304 ARRAYS IIni tializes the array of month names and the program begin IINITIALI ZE j MONTHNAME[JAN] . = 'JANUARY , ,. MONTHNAME[FEB] := ' ,. MONTHNAME[APR] := MONTHNAME[MAR] .= 'MARCH , , MONTHNAME [JUN] := MONTHNAME[MAY] . = 'MAY , ,. MONTHNAME[AUG] := MONTHNAME[JUL] := 'JULY MONTHNAME[SEP] := ' SEPTEMBER' ; MONTHNAME[OCT] := MONTHNAME[NOV] := 'NOVEMBER ' ., MONTHNAME[DEC] := MONTHDONE := FALSE; YEARDONE := FALSE end; IINITIALI ZE j . f Laq s . ] 'FEBRUARY 'APRIL 'JUNE 'AUGUST 'OCTOBER 'DECEMBER , ,. ' ,. ' ,. ' ,. ' ,. ', . procedure DOCHOICE (var MONTHNAME linputj : NAMEARRAY; MONTHDONE, YEARDONE linputj : BOOLEAN); IReads in each option selected and perform it.j begin IDOCHOICEj WRITELN ('Procedure DOCHOICE entered. ' ) end; IDOCHOICEj begin IANALYZEj IInitialize MONTHNAME array and flags.j INITIALIZE (MONTHNAME, MONTHDONE, YEARDONE); IProcess all user choices.j DOCHOICE (MONTHNAME, MONTHDONE, YEARDONE) end. IANALYZEj Fig. 6.25 Main Program for Sales Analysis Problem The array SALES will be local to procedure DOCHOICE. There will also be local arrays used to store the sales totals by year (SUMBYYEAR) and the sales totals by month (SUMBYMONTH). Procedure DOCHOICE must read the option selected and call a level 2 procedure to process the array SALES. The local variables and algorithm for DOCHOICE are described next. the array of sales data (SALES : SALESARRAY) an array of sums by year (SUMBYYEAR : array [YEARRANGE] of REAL) an array of sums by month (SUMBYMONTH : array [MONTH] of REAL) the first sales year processed (FIRSTYEAR : YEARRANGE) the last sales year processed (LASTYEAR : YEARRANGE) each option selected (CHOICE : SMALLINT) 6.9 CASE STUDY 305 Algorithm for DOCHOICE 1. repeat 2. Read and validate the user's choice. 3. Process the option selected. until the user is done Step 3 above will be implemented as a case statement that selects a procedure based on the value of CHOICE. The structure chart for DOCHOICE (see Fig. 6.26) shows the level-two procedures that may be called in step 3 except for TABMONTH (similar to TAB YEAR) and GRAPHMONTH (similar to GRAPHYEAR). The level-two procedures are relatively straightforward to implement. We will show them nested in DOCHOICE in Fig. 6.27 and discuss them afterwards. DOCHOICE I t I SALES, FIRSTYEAR, LASTYEAR, CHOICE I SUMBYYEAR, FIRSTYEAR, LASTYEAR MONTHNAME -l, -l, READCHOICE I MONTHNAME -l, t SALES, FIRSTYEAR, LASTYEAR DISPLAY I SALES, FIRSTYEAR, LASTYEAR I -l, t SUMBYYEAR, YEARDONE I ENTERSALES TABYEAR Fig. 6.26 Structure Chart for DOCHOICE procedure DOCHOICE (var MONTHNAME linputl : NAMEARRAYi MONTHDONE , YEARDONE linputl : BOOLEAN)i IReads in each option selected and perform it.l 306 ARRAYS GRAPHYEAR type YEARRANGE = 1900 .. 1999; SALESARRAY = array [YEARRANGE, MONTH] of REAL; YEARARRAY = array [YEARRANGE] of REAL; MONTHARRAY = array [MONTH] of REAL; var SALES : SALESARRAY; SUMBYYEAR : YEARARRAY; SUMBYMONTH : MONTHARRAY; FIRSTYEAR, LASTYEAR : YEARRANGE; CHOICE : SMALLINT; Itable of sales datal Isales totals for each year) Isales totals for each monthl {per iod covered I leach option selectedl procedure READCHOICE (var CHOICE loutputl : SMALLINT); IReads and validates the user's choice.l var TEMPCHOICE : INTEGER; la possible choicel procedure PRINTMENU; [Pr Ln t s the menu. I begin IPRINTMENUl WRITELN ('Procedure PRINTMENU entered.') end; IPRINTMENUI begin IREADCHOICE I PRINTMENU; Idisplay the menul repeat WRITE ('Select an option (1 through 7): '); READLN (TEMPCHOICE) until TEMP CHOICE in [l .. EXITCHOICE]i CHOICE := TEMPCHOICE Ireturn valid choicel end; IREADCHOICE I procedure ENTERSALES (var MONTHNAME linputl : NAMEARRAY; var SALES loutputl : SALESARRAY; var FIRSTYEAR, LASTYEAR loutputl : YEARRANGE); IReads the sales data into the array SALES. The first and last years stored are read into FIRSTYEAR and LASTYEAR. Uses array MONTHNAME to prompt for monthly sales. I var CURMONTH : MONTH; CURYEAR : YEARRANGE; begin IENTERSALES) IEnter first and last years of sales data.l WRITE ('Enter first year of sales data: '); WRITE ('Enter last year of sales data: '); WRITELN; Icurrent month I [curr ent; yea.r ] READLN (FIRSTYEAR); READLN (LASTYEAR); IEnter table data. I for CURYEAR := FIRSTYEAR to LASTYEAR do 6.9 CASE STUDY 307 begin WRITELN ('For year " CURYEAR :4)j WRITELN ('Enter sales amount for each month or O')j for CURMONTH := JAN to DEC do begin WRITE (MONTHNAME[CURMONTH], ' sales $')j READLN (SALES [CURYEAR, CURMONTH]) Iget amountl endj Ifor CURMONTHl WRITELN end ffor CURYEARI endj IENTERSALESl procedure DISPLAY (var SALES linputl : SALESARRAYj FIRSTYEAR, LASTYEAR linputl : YEARRANGEj MONTHNAME linputl : NAMEARRAY)j IDisplays the sales data as a table. Due to line length limits, the first 6 months and last 6 months of each year are shown in separate tables. Uses SHOWHALF to display each table. procedure SHOWHALF (var SALES linputl : SALESARRAY; FIRSTYEAR, LASTYEAR linputl : YEARRANGEj FIRSTMONTH, LASTMONTH [inputl : MONTH); [Displays the sales amounts by year for each of the months from FIRSTMONTH to LASTMONTH. l var CURMONTH : MONTHj CURYEAR : YEARRANGEj Iloop control variablel Iloop control variablel begin ISHOWHALFl IPrint table heading for 6 months of each year.} WRITE ('YEAR')j for CURMONTH := FIRSTMONTH to LASTMONTH do WRITE (MONTHNAME[CURMONTH] :12)j WRITELN; IPrint sales figures for 6 months of each year.l for CURYEAR := FIRSTYEAR to LASTYEAR do begin WRITE (CURYEAR :4)j for CURMONTH := FIRSTMONTH to LASTMONTH do WRITE (SALES [CURYEAR, CURMONTH] :12:2)j WRITELN end Ifor CURYEARl endj ISHOWHALFI begin IDISPLAYl IDisplay first 6 months of array SALES.l SHOWHALF (SALES, FIRSTYEAR, LASTYEAR, JAN, JUN)j WRITELNj IDisplay last 6 months of array SALES.l SHOWHALF (SALES, FIRSTYEAR, LASTYEAR, JUL, DEC) endj [DISPLAYl 308 ARRAYS Iprint month namesl lend the headingl procedure TABYEAR (var SALES {inputl : SALESARRAY; FIRSTYEAR, LASTYEAR linputl : YEARRANGEi var SUMBYYEAR loutputl : YEARARRAY; var YEARDONE loutputl : BOOLEAN); ITabulates sales totals by year. Sums are printed and stored in array SUMBYYEAR. YEARDONE is set to TRUE. var CURMONTH : MONTH; CURYEAR : Y~ARRANGE; Iloop control variablel lloop control variable I SUM (sum £or each year) ; REAL; begin ITABYEAR I IPrint heading. I WRITELN ('Total sales by year'); WRITELN ('YEAR', 'TOTAL' :13); IFind and print each annual total.l for CURYEAR := FIRSTYEAR to LASTYEAR do begin IAccumulate sum for 12 months I SUM := 0.0; for CURMONTH := JAN to DEC do SUM := SUM + SALES[CURYEAR, CURMONTH); WRITELN (CURYEAR :4, SUM :13:2); [print sales totall SUMBYYEAR[CURYEAR) := SUM Istore sales totall end; Ifor CURYEARI YEARDONE := TRUE end; I TABYEAR I Iset program flagl procedure TABMONTH (var SALES linputl : SALESARRAY; var MONTHNAME [Lnpu t ] : NAMEARRAY; FIRSTYEAR, LASTYEAR linputl : YEARRANGE; var SUMBYMONTH loutputl : MONTHARRAY; var MONTHDONE loutputl : BOOLEAN); ITabulates sales totals by month. Sums are printed and stored in array SUMBYMONTH. MONTHDONE is set to TRUE. begin ITABMONTH I WRITELN ('Procedure TABMONTH entered.') end; ! TABMONTH I procedure GRAPHYEAR (var SUMBYYEAR {input) : YEARARRAY; FIRSTYEAR, LASTYEAR linputl : YEARRANGE); {Plots the annual sales totals (stored in SUMBYYEAR) as a bar graph. One line is plotted for each year from LASTYEAR to FIRSTYEAR. The graph is scaled so that the longest line is approximately 50 characters. Uses function FINDMAX to find the largest value in the array SUMBYYEAR. canst STAR = '*'j MAXPOINTS = 50; Isymbol plotted) Ilongest line length) 6.9 CASE STUDY 309 var MAXDOLLARS, PLOTVAL : REALi DOLLARINC : INTEGER: CURYEAR : YEARRANGEi Ithe largest value plottedl Ithe amount plotted so farl [the amount represented by each pointl Iloop control variablel function FINDMAX (var SUMBYYEAR : YEARARRAY: FIRSTYEAR, LASTYEAR : YEARRANGE) : REAL: IFinds the largest element in array SUMBYYEAR. Examines elements with subscripts FIRSTYEAR through LASTYEAR. l var MAXSOFAR : REAL: CURYEAR : YEARRANGE: Ilargest value found so farl Iloop control variablel begin IFINDMAXl IInitialize MAXSOFAR to first array element.l MAXSOFAR := SUMBYYEAR[FIRSTYEAR]: ICompare each element to MAXSOFAR. If current element is larger than MAXSOFAR, redefine MAXSOFAR as current element. l for CURYEAR :=FIRSTYEAR + 1 to LASTYEAR do if SUMBYYEAR[CURYEAR] > MAXSOFAR then MAXSOFAR := SUMBYYEAR[CURYEAR]i Iredefine MAXSOFARl FINDMAX ~= MAXSOFAR end: IFINDMAXl Idefine resultl begin IGRAPHYEARl IDefine the scale for the horizontal axis.l MAXDOLLARS := FINDMAX (SUMBYYEAR, FIRSTYEAR, LASTYEAR): DOLLARINC := ROUND(MAXDOLLARS / MAXPOINTS): WRITELN ('Each point on the horizontal scale represents $', DOLLARINC :9): IPlot the bar graph.l WRITELN ('YEAR AMOUNT'): [pr Lnt; headi.nq ] IPrint a bar for each element of SUMBYYEAR, start with last onel for CURYEAR := LASTYEAR downto FIRSTYEAR do begin WRITE (CURYEAR :4): Iprint the yearl [Plot points until value plotted exceeds element value.l PLOTVAL := DOLLARINC: linitialize sum plottedl while PLOTVAL 100 then Compares CUBE [ 5 ] to 100. WRITE (CUBE[l], CUBE[2]) Displays the first two cubes. WRITE (SALES[3, MON]) Displays the element of SALES for week 3 and day Monday. for WEEK := 1 to 52 do for TODAY := SUN to SAT do SALES [WEEK, TODAY] := 0.0 Initializes each element of SALES to zero. READ (SALES[l, SUN]) Reads the value for week 1 and day Sunday into SALES. Array copy COUNT := CUBE Copies contents of array CUBE to array COUNT. Operations on packed arrays NAME := 'R. Koffman' Saves' R. Koffman' in NAME. WRITELN (NAME) i f NAME = 'Daffy Duck' Displays' R. Koffman'. then Compares NAME to 'Daffy Duck'. 6.11 CHAPTER REVIEW 315 var X I REALARRAYj INTEGER; begin I : = 1; X(I) .= 8.384 [a] end. 5. What are the two common ways of selecting array elements for processing? 6. Write a Pascal fragment to print out the index of the smallest and the largest numbers in an array X of 20 integers. Array X has a range of values of 0 to 100. Assume array X already has values assigned to each element. 7. The parameters for a procedure are two arrays (type REALARRAY) and an integer representing the length of the arrays. The procedure copies the first array in the parameter list to the other array in reverse order using a loop structure. Write the procedure. 8. List two advantages to using packed character arrays. 9. Define row-major order. 10. Declare an array that can be used to store each title of the TOP4Q hits for each week of the year, given that the TITLELENGTH will be 20 characters. 11. Declare an array YEARLYHOURS for storing the hours five employees work each day of the week, each week of the year. Programming Projects 316 ARRAYS 1. Write a program to read N data items into two arrays X and Y of size 20. Store the product of corresponding elements of X and Y in a third array Z, also of size 20. Print a three-column table displaying the arrays X, Y, and Z. Then compute and print the square root of the sum of the items in Z. Make up your own data, with N less than 20. 2. Let A be an array containing 20 integers. Write a program that first reads up to 20 data items into A, and then finds and prints the subscript of the largest item in A and that item. 3. Each ports these gives 4. Assume for the moment that your computer has the very limited capability of year the Department of Traffic Accidents receives accident count refrom a number of cities and towns across the country. To summarize reports, the Department provides a frequency-distribution printout that the number of cities reporting accident counts in the following ranges: 0-99, 100-199, 200-299, 300-399, 400-499, 500 and above. The Department needs a computer program to read the number of accidents for each reporting city or town and to add one to the count for the appropriate accident range. After all the data have been processed, the resulting frequency counts are to be printed. being able to read and print only single-decimal digits at a time and to add together two integers consisting of one decimal digit each. Write a program to read in two integers of up to 10 digits each, add these numbers together, and print the result. Test your program on the following numbers. X Y X Y X Y 1487625 12783 60705202 30760832 1234567890 9876543210 Hints: Store the numbers X and Y in two character arrays X, Y, of size 10, one decimal digit per element. If the number is less than 10 digits in length, enter enough leading zeros (to the left of the number) to make the number 10 digits long. array X array Y [1] [2] [3 ] [4] [5] [6] [7 ] [8 ] [9] [10] You will need a loop to add together the digits in corresponding array elements, starting with the element with subscript 10. Don't forget to handle the carry if there is one! Use a BOOLEAN variable CARRY to indicate whether or not the sum of the last pair of digits is greater than nine. 5. Write a program for the following problem. You are given a collection of scores for the last exam in your computer course. You are to compute the average of these scores, and then assign grades to each student according to the following rule. If a student's score is within 10 points (above or below) of the average, give the student a grade of SATISFACTORY. If the score is more than 10 points higher than the average. give the student a grade of OUTSTANDING. If the score is more than 10 points below the average, give the student a grade of UNSATISFACTORY. Test your program on the following data: RICHARD LUGAR FRANK RIZZO DONALD SCHAEFFER KEVIN WHITE JAMES RIEHLE ABE BEAME TOM BRADLEY WALTER WASHINGTON 55 71 84 93 74 70 84 68 PROGRAMMING PROJECTS 317 RICHARD DALEY RICHARD HATCHER 64 82 Hint: The output from your program should consist of a labelled three-column list containing the name. exam score. and grade of each student. 6. Write a program to read N data items into each of two arrays X and Y of size 20. Compare each of the elements of X to the corresponding element of Y. In the corresponding element of a third array Z. store: +1 o - 1 if X is larger than Y if X is equal to Y if X is less than Y Then print a three-column table displaying the contents of the arrays X, Y. and Z, followed by a count of the number of elements of X that exceed Y, and a count of the number of elements of X that are less than Y. Make up your own test data with N less than 20. 7. It can be shown that a number is prime if there is no smaller prime number that divides it. Consequently, in order to determine whether N is prime, it is sufficient to check only the prime numbers less than N as possible divisors (see Section 4.8). Use this information to write a program that stores the first 100 prime numbers in an array. Then have your program print the array. 8. The results of a true-false exam given to a Computer Science class have been coded for input to a program. The information available for each student consists of a student identification number and the students' answers to 10 true-false questions. The available data are as follows: Student identification 0080 0340 0341 0401 0462 0463 0464 0512 0618 0619 0687 0700 0712 0837 Answer string FTTFTFTTFT FTFTFTTTFF FTTFTTTTTT TTFFTFFTTT TTFTTTFFTF TTTTTTTTTT FTFFTFFTFT TFTFTFTFTF TTTFFTTFTF FFFFFFFFFF TFTTFTTFTF FTFFTTFFFT FTFTFTFTFT TFTFTTFTFT Write a program that first reads in the answer string representing the 10 correct answers (use FTFFTFFTFT as data). Next, for each student, read the student's data and compute and store the number of correct answers for each student in one array. and store the student ID number in the corresponding element of another array. Determine the best score, BEST. Then print a three-column table displaying the ID number. score. and grade for 318 ARRAYS each student. The grade should be determined as follows: If the score is equal to BEST or BEST-I, give an A; if it is BEST-2 or BEST-3, give a C. Otherwise, give an F. . 9. The results of a survey of the households in your township have been made available. Each record contains data for one household, including a four-digit integer identification number, the annual income for the household, and the number of members of the household. Write a program to read the survey results into three arrays and perform the following analyses: a) b) c) Count the number of households included in the survey and print a three-column table displaying the data read in. (You may assume that no more than 25 households were surveyed.] Calculate the average household income, and list the identification number and income of each household that exceeds the average. Determine the percentage of households having incomes below the poverty level. The poverty level income may be computed using the formula P = $6500.00 + $750.00 X (m - 2) where m is the number of members of each household. This formula shows that the poverty level depends on the number of family members, m, and the poverty level increases as m gets larger. Test your program on the following data. Identification number Annual income Household members 1041 1062 1327 1483 1900 2112 2345 3210 3600 3601 4725 6217 9280 12,180 13,240 19,800 22,458 17,000 18,125 15,623 3,200 6,500 11,970 8,900 10,000 6,200 4 3 2 8 2 7 2 6 5 2 3 2 1 10. Write a program which, given the taxable income for a single taxpayer, will compute the income tax for that person. Use Schedule X shown in Fig. 6.29 on the page. Assume that "line 34," referenced in this schedule, contains the taxable income. Example: If the individual's taxable income is $8192, your program should use the tax amount and percent shown in column 3 of line 5 (see arrow). The tax in this case is $692 + 0.19(8192 - 6500) = $1013.48. For each individual processed, print taxable earnings and the total tax. Hint: Set up three arrays, one for the base tax (column 3), one for the tax percent (column 3), and the third for the excess base (column 4). Your program must then compute the correct index to these arrays, given the taxable income. 11. Write a program that removes all of the blanks from a character string and PROGRAMMING PROJECTS 319 Tax Rate Schedule Schedule X Single Taxpayers Use this schedule if you checked Filing Status Box 1 on Form 1040If theamount on Enter on line 2 Form 1040, oftheworksheet line 34 is: onthis page: Over- ---+ $0 2,300 3,400 4,400 6,500 8,500 10,800 12,900 15,000 18,200 23,500 28,800 34,100 41,500 55,300 81,800 108,300 of the amount over- But not Over$2,300 3,400 4,400 6,500 8,500 10,800 12,900 15,000 18,200 23,500 28,800 34,100 41,500 55,300 81,800 108,300 -0........ 14% $154+16% 314+18% 692+19% 1,072+21% 1,555+24% 2,059+26% 2,60~+30% 3,965+34% 5,367+39% 7,434+44% 9,766+49% 13,392+55% 20,982+63% 37,677+68% 55,697+70% $2,300 3,400 4,400 6,500 8,500 10,800 12,900 15,000 18,200 23,500 28,800 34,100 41,500 55,300 81,800 108,300 Fig. 6.29 Schedule X (from IRS Form 1040) compacts all nonblank characters in the string so that all the blanks are at the end. You should only have to scan the input string once from left to right. 12. Assume a set of sentences is to be processed. Each sentence consists of a sequence of words, separated by one or more blank spaces. Write a program that will read these sentences and count the number of words with one letter, two letters, etc., up to ten letters. 13. Write a program to read in a collection of character strings of arbitrary length. For each string read, your program should do the following: a) b) c) 14. 320 ARRAYS Print the length of the string. Count the number of occurrences of four letter words. Replace each four letter word with a string of four asterisks and print the new string. Write an interactive program that plays the game of HANGMAN. Read the word to be guessed into successive elements of the packed array WORD. The player must guess the letters belonging to WORD. The program should termi- nate when either all letters have been guessed correctly (player wins) or a specified number of incorrect guesses have been made (computer wins). Hint: Use a packed array SOLUTION to keep track of the solution so far. Initialize SOLUTION to a string of symbols I * I . Each time a letter in WORD is guessed, replace the corresponding I *' in SOLUTION with that letter. 15. Write a program that reads in a tic-tac-toe board and determines the best move for player X. Use the following strategy: Consider all squares that are empty and evaluate potential moves into them. If the move fills the third square in a row, column, or diagonal that already has two X's, add 50 to the score; if it fills the third square in a row, column or diagonal with two O's, add 25 to the score; for each row, column, or diagonal containing this move that will have two X's and one blank, add 10 to the score; add eight for each row, column or diagonal through this move that will have one 0, and X, and one blank; add four for each row, column or diagonal that will have one X and the rest blanks. Select the move that scores the highest. The possible moves for the board below are numbered. Their scores are shown to the right of the board. Move five is selected. 1 0 X 2 X 3 0 4 5 1-10 2-10 3-10 4-8 5-10 + 8 = 18 + 8 = 18 + 10 = 20 + 10 + 8 = 28 16. Write a program that reads the five cards representing a poker hand into a two-dimensional array (first dimension is suit, second dimension is rank). Evaluate the poker hand using procedures to determine whether the hand is a flush (all one suit), a straight (five consecutive cards), a straight flush (five consecutive cards of one suit), four-of-a-kind, a full house (three-of-a-kind, two of another), three-of-a-kind, two pair, or one pair. 17. Write a set of procedures to manipulate a pair of matrices. You should provide procedures for addition, subtraction, and multiplication. Each procedure should validate its input parameters [i.e., check all matrix dimensions) before performing the required data manipulation. 18. The results from the mayor's race have been reported by each precinct as follows: Candidate Candidate B Precinct A 1 2 192 147 48 3 4 186 114 5 267 12 21 13 90 Candidate C 206 312 121 408 382 Candidate D 37 21 38 39 29 Write a program to do the following: a) b) Print out the table with appropriate headings for the rows and columns. Compute and print the total number of votes received by each candidate and the percent of the total votes cast. PROGRAMMING PROJECTS 321 c) d) e) 19. If anyone candidate receives over 50% of the votes. the program should print a message declaring that candidate the winner. If no candidate receives 50% of the votes. the program should print a message declaring a run-off between the two candidates with the highest number of votes; the two candidates should be identified by their letter names. Run the program once with above data and once with candidate C receiving only 108 votes in precinct 4. The game of Life. invented by John H. Conway. is supposed to model the genetic laws for birth. survival, and death. (See Scientific American. October. 1970. p. 120.) We will play it on a board consisting of 25 squares in the horizontal and vertical directions. Each square can be empty or contain an X indicating the presence of an organism. Each square (except the border squares) has eight neighbors. The small square shown in the segment of the board drawn below connects the neighbors of the organism in row three. column three. X- - X X X X-X Generation 1 The next generation of organisms is determined according to the following criteria: 1. Birth: An organism will be born in each empty location that has exactly three neighbors. 2. Death: An organism with four or more organisms as neighbors will die from overcrowding. An organism with fewer than two neighbors will die from loneliness. 3. Survival: An organism with two or three neighbors will survive to the next generation. Generations 2 and 3 for the sample follow: X X X X X X X X Generation 2 X X X X X X Generation 3 Read in an initial configuration of organisms. Print the original game array. calculate the next generation of organisms in a new array. copy the new array into the original game array and repeat the cycle for as many genera322 ARRAYS tions as you wish. Hint: Assume that the borders of the game array are infertile regions where organisms can neither survive nor be born; you will not have to process the border squares. 20. The results of a multiple-choice exam are recorded in a computer. It is often useful to provide a simple item analysis of a set of questions to determine their effectiveness. Read the 10 answers for each exam and process the following information: (a) determine if each answer is correct, accumulate the number of correct answers, and [b] increment a respective counter for the appropriate answer whether right or wrong. Assume all of the answers are of the range of A-E. The output should consist of each question number, the correct answer, number of correct responses, number of incorrect responses, and a count of the number of A's, B's, C's, D's, and E's. Use the following sample data: (1) (2) (3) (4) (5) (6) (7) (8) (9) (10) A E C E C E E B B C A A C D A B C C B D B C C A E E B A B B C C A D C D A A D B B A D A A A A A C B E D D B C B D A D A D C A B B D B D B D B B B E B A E E A D And use as the key: E C C B E A DAB C 21. An amusing program consists of a sentence generator that will read a series of four numbers and print out a sentence. Provide three arrays containing eight words each (maximum of 10 characters to each word) called NOUN, VERB, and ADJECTIVE. Fill each of these arrays with some appropriate words and then read four numbers (each in a range from 1-8). Write out a short sentence in which each number is the appropriate subscript from arrays in the following order: NOUN, VERB, ADJECTIVE, NOUN An example would be to read 4, 5, 2, 6. This will print the strings NOUN[4 ], VERB [ 5 l. ADJECTIVE [ 2 l. and NOUN[ 6 ]. If their contents are: NOUN[4] is 'JOHN VERB[5] is 'LIKES ADJECTIVE[2] is 'CRAZY NOUN[6] is 'BREAD ' The sentence JOHN LIKES CRAZY BREAD. would be printed. A trailing blank should not be printed; however, one blank between each word is needed and a period should be supplied at the end. PROGRAMMING PROJECTS 323 22. The INDEX function is useful in character string manipulation. This function locates the first appearance of the second string within the first string and returns the subscript of this location. Parameters to this function are: (STRINGl, STRING2 : STRING: LENl, LEN2 : INTEGER) where STRING is an array type sufficiently large enough to hold each string. The length parameters (LENI. LEN2) are used to indicate how many characters of each string should be used in the processing. If no match is found the function returns a zero. Some examples are included below: Given: var A, B: STRING: X : INTEGER: begin A := 'ABCDEFGHIJK'; B := 'DEF ': X := INDEX(A, B, 11, 3); X would have a value of 4. For the same A if B contained: B := , ABD ': X := INDEX(A, B, 11,4); X would be asigned 0 since ' ABD' is not contained (in order) in string A. Test your function with several sets of data. 23. Write the appropriate procedures to process a standard address and extract the following information. First read an address of the form: LINEl: LINE2: LINE3: . For example: Dr. John E. Smith 111 Chestnut Street Kalamazoo. MI 49001 Determine and print the (a) Title. (b) Last name. (c) State. and (d) Zipcodes for each label. 324 ARRAYS Records 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 7.10 7.11 7.12 Declaring a Record Manipulating Individual Fields of a Record Manipulating an Entire Record Arrays of Records Case Study Searching an Array Sorting an Array General Data Structures Record Variants Manipulating Strings Stored in Records Common Programming Errors Chapter Review In the previous chapter we introduced the array. a data structure fundamental to programming and included in almost every high-level programming language. In this chapter we will introduce an additional data structure. the record. that is available in Pascal, but not in all other highlevel languages. The use of records makes it easier to organize and represent information in Pascal. This is a major reason for the popularity of the Pascal language. A record. like an array. is a collection of related data items. However. unlike an array. the individual components of a record can contain data of different types. We can use a record to store a variety of kinds of informa325 tion about a person, such as the person's name, marital status, age, date of birth, etc. Instead of using a subscript, we refer to the information in a record by using a field name. II Declaring a Record Normally a record is declared in two stages, as is an array. We first declare the structure or form of a record in a record type declaration. Next, we declare one or more record variables of this record type. The record type declaration specifies the name and type of each record component or field. Example 7.1 We wish to store the descriptive information shown below in a computerized payroll program. NAME: Danielson SEX : FEMALE SOCIAL SECQRITY NUMBER: 035-20-1111 NUMBER OF DEPENDENTS : 2 HOURLY SALARY RATE: 3.98 TAXABLE SALARY (for 40 hour week): 130.40 We will declare a record type EMPLOYEE with six distinct fields and a record variable, CLERK, for storage of the data above. canst STRINGSIZE = 11; type STRING = packed array [l •• STRINGSIZE] of CHAR; EMPLOYEE = record NAME : STRING; SEX: (FEMALE, MALE); SOCSECNUM : STRING ; NUMDEPEND : INTEGER; RATE, TAXSAL : REAL end; (EMPLOYEEj var CLERK : EMPLOYEE; The record variable CLERK is structured as defined in the declaration for record type EMPLOYEE. Thus the memory allocated for CLERK consists of storage space for two character strings (length 11), a scalar value (FEMALE or MALE), an integer value, and a real value. The record variable CLERK (see Fig. 7.1) assumes the values shown earlier are stored in memory. 326 RECORDS Record variable CLERK NAME SEX SOCSECNUM NUMDEPEND RATE TAXSAL Fig. 7.1 Record Variable CLERK As illustrated in the type declaration for EMPLOYEE, it is possible to specify record fields corresponding to any standard or user-defined type. In addition, the type declaration of a field can be included within the record declaration, e.g. (FEMALE, MALE). The record type declaration is described in the next display. RECORD TYPE DECLARATION ree-type = record id-Iist; : type; ~ id-list z : typez~ id-List; : type ; end~ Interpretation: The identifier ree-type is the name of the record structure being described. Each id-Iist, is a list of one or more field names separated by commas; the data type of each field in id-Iist, is specified by type j' Note: type, may be any standard or user-defined data type including a structured type such as an array or another record. If type, is a user-defined data type, it can either be defined before the record or as part of the record description. Self-check Exercises for Section 7.1 1. A catalogue listing for a textbook consists of the author's name, title, publisher, and year of publication. Define a record type CATALOGUE for storage of this information. 2. Each part in an inventory is represented by its part number, a descriptive name. the quantity on hand, and price. Define a record type PART. 7.1 DECLARING A RECORD 327 • Manipulating Individual Fields of a Record In most instances, each field of a record must be individually manipulated. We can reference a record field by using a field selector consisting of the record variable name followed by the field name. A period is used to separate the field name and the record name. Example 7.2 Fig. 7.1 gives an example of the record variable CLERK. The data shown earlier can be stored in CLERK through the sequence of assignment statements CLERK.NAME := 'Danielson '; CLERK.SEX := FEMALE; CLERK.SOCSECNUM := '035-20-1111'; CLERK.NUMDEPEND := 2; CLERK.RATE := 3.98 Once data are stored in a record, they can be manipulated in the same way as other data in memory. For example, the statements WRITE ('The clerk is '); case CLERK. SEX of FEMALE: WRITE ('Ms. '); MALE : WRITE ('Mr. ') end; [case] WRITELN (CLERK.NAME) print the character string stored in the NAME field of CLERK following an appropriate message. For the data above. the output would be The clerk is Ms. Danielson The field selector CLERK. NAME [ 1] references the first character (' D ' ) stored in the NAME field (a string) of the record variable CLERK. The assignment statement CLERK.TAXSAL := 40.0 * CLERK.RATE - 14.40 * CLERK.NUMDEPEND computes the clerk's taxable salary by deducting $14.40 for each dependent from the gross salary (40.0 * hourly rate). The computed result is saved in the record field named CLERK. TAXSAL. The with Statement It becomes tedious to write the complete field selector each time we reference a field of a record. The with statement can be used to shorten the field selector. 328 RECORDS with CLERK do begin WRITE ('The clerk is '); case SEX of FEMALE: WRITE ('Ms. '); MALE WRITE ('Mr. ') end; [cas e] WRITELN (NAME); TAXSAL := 40.0 * RATE - 14.40 * NUMDEPEND; WRITELN ('The clerk' 's taxable salary is $', TAXSAL :7:2) end lwithl As shown, it is not necessary to specify both the record variable and field names inside a with statement. The record variable CLERK is identified in the wi th statement header; consequently, only the field name is needed inside the with statement, not the complete field selector (e.g., RATE instead of CLERK. RATE). The wi th statement is particularly useful when several fields of the same record variable are being manipulated, as in this example. WITH STATEMENT wi th record-var do statement Interpretation: The statement may be a single or compound statement. Record-var is the name of a record variable. Within the statement body, any field of record-var may be referenced by specifying its field name only. Example 7.3 The program in Fig. 7.2 computes the distance from an arbitrary point on the X-Y plane to the origin (intersection of X axis and Y axis). The values of the X and Y coordinates are entered as data and stored in the fields XCOORD and YCOORD of the record variable POINTl. The formula used to compute the distance from the origin to an arbitrary point (X, Y) is distance = IIXz + yz Since the record variable POI NT1 is specified in the with statement header, only the field names XCOORD and YCOORD are needed to reference the coordinates of the data point. Each coordinate is read separately since it is illegal to use a record variable by itself in a READ (READLN) or WRITE (WRITELN) statement [i.e., only individual fields of a record variable may be read or displayed at a terminal. not the entire record). 7.2 MANIPULATING INDIVIDUAL FIELDS OF A RECORD 329 program DISTORIGIN (INPUT, OUTPUT); (Finds the distance from a point to the origin.j type POINT = record XCOORD, YCOORD end; (POINT j REAL var POINTI : POINT: DISTANCE : REAL: (the data po i n t ] (its distance from the originl begin with POINTI do begin WRITE ('X: '): READLN (XCOORD)i WRITE ('Y: '): READLN (YCOORD)i DISTANCE := SQRT(SQR(XCOORD) + SQR(YCOORD)): WRITELN ('Distance to origin is " DISTANCE :5:2) end [w i t.h] end. (DISTORIGINj 3.00 4.00 Distance to origin is 5.00 X: Y: Fig. 7.2 Distance from Point to Origin. PROGRAM STYLE A word of caution about the wi th statement Although the wi th statement shortens program statements that manipulate record components. it can also reduce the clarity of these statements. For example, in Fig. 7.2 it is not obvious that the statement DISTANCE := SQRT(SQR(XCOORD) + SQR(YCOORD)): is passing two record fields (POINTI. XCOORD and POINTI. YCOORD) to the function SQR and not two variables. The possibility of confusion and error increases when two record variables (e.g. POINTI and POINT2) are being manipulated. In this case if the field name XCOORD is referenced by itself. it is not clear whether we mean POINTI. XCOORD or POINT2. XCOORD. Pascal uses the record variable specified in the header of the closest containing wi tho 330 RECORDS Self-check Exercises for Section 7.2 1. Write the Pascal statements required to print the values stored in CLERK in the form shown in Fig. 7.1. • Manipulating an Entire Record Since arithmetic and logical operations must be performed on individual memory cells, record variables cannot be used as the operands of arithmetic and relational operators. These operators must be used with individual fields of a record as shown in the previous section. This is also true now for the standard procedures READ ( READLN) and WRI TE (WRI TELN ). In the next chapter we will learn how to read and write entire record variables to certain types of files. Copying One Record to Another All the fields of one record variable can be copied to another record variable of the same type using a record copy (assignment) statement. If CLERK and JANITOR are both record variables of type EMPLOYEE, the statement CLERK := JANITOR (copy JANITOR to CLERKI copies each field of JANITOR into the corresponding field of CLERK. Records as Parameters A record variable can be passed as a parameter to a function or procedure. As always, the actual parameter must be the same type as its corresponding formal parameter. The use of records as parameters can shorten parameter lists considerably because only one parameter (the record variable) has to be passed instead of several. Example 7.4 In a grading program, the vital statistics about an exam might consist of the highest and lowest scores, the average score, and the standard deviation. In previous problems these data would be stored in separate variables; however, it makes sense to group them together as a record. type EXAMSTATS = record LOW, HIGH: 0 .. 100: AVERAGE, STANDARDDEV end: I EXAMSTATS I REAL var EXAM : EXAMSTATS: 7.3 MANIPULATING AN ENTIRE RECORD 331 A procedure that computes one of these results (e.g. AVERAGE) could be passed a single record field (e.g. EXAM. AVERAGE). A procedure that manipulates more than one of these fields could be passed the entire record. An example would be procedure REPORT shown in Fig. 7.3. procedure REPORT (EXAM (inputj : EXAMSTATS): (Prints the exam statistics.j begin (REPORTj with EXAM do begin WRITELN WRITELN WRITELN WRITELN end [w i t.h] end: (REPORT I ('High score: " HIGH :3): ('Low score: " LOW :3): ('Average: " AVERAGE :5:1): ('Standard deviation: " STANDARDDEV :5:1) Fig. 7.3 Procedure REPORT Example 7.5 In computer simulations we need to keep track of the time of day during the progress of a simulated event or experiment. Normally the time of day is updated after a certain time period has elapsed. The record type TIME is declared below assuming a 24-hour clock. type TIME = record HOUR : 0 •• 23: MINUTE, SECOND end: (TIMEI 0 .. 59 Procedure CHANGETIME in Fig. 7.4 updates the time of day, TIMEOFDAY (type TIME), after a time interval, ELAPSEDTIME. expressed in seconds. Each statement that uses the mod operator updates a particular field of the record represented by TIMEOFDAY. The mod operator ensures that each updated value is within the required range; the di v operator converts multiples of 60 seconds to 'minutes and multiples of 60 minutes to hours. Reading a Record Normally we use a procedure to read data into a record. Procedure READEMPL in Fig. 7.5 be used to read data into the first five fields of a record variable of type EMPLOYEE. Since we can pass a record variable to READEMPL, only one parameter is needed. not five. The procedure (call) statement READEMPL (CLERK) causes the data read to be stored in record variable CLERK. 332 RECORDS procedure CHANGETIME (ELAPSEDTIME (inputj : INTEGER; var TIMEOFDAY linput/outputj : TIME); (Updates the time of day, TIMEOFDAY, assuming a 24-hour clock and an elapsed time of ELAPSEDTIME in seconds. j var NEWHOUR, NEWMIN, NEWSEC INTEGER; (temporary variablesj begin (CHANGETIMEj with TIMEOFDAY do begin NEWSEC := SECOND + ELAPSEDTIME; SECOND := NEWSEC mod 60; NEWMIN := MINUTE + (NEWSEC div 60); MINUTE := NEWMIN mod 60; NEWHOUR := HOUR + (NEWMIN div 60); HOUR := NEWHOUR mod 24 end [w i t.h] end; (CHANGETIMEI (total seconds j [s e conds mod 60j (total minutes j (minutes mod 60 j ltotal hoursj [hour-s mod 24j Fig. 7.4 Procedure CHANGETIME Fig. 7.5 Procedure READEMPL procedure READEMPL (var ONEEMPL (outputj : EMPLOYEE); (Reads one employee record into ONEEMPL. Uses procedure READSTRING to read in a string of up to 11 characters.j var LENGTH : INTEGER; SEXCHAR : CHAR; (actual length of data stringj (letter indicating sexj (Insert procedure READSTRING here.j begin (READEMPLj with ONEEMPL do begin WRITE ('Name: '); READSTRING (NAME, LENGTH); WRITE ('Sex (F or M): '); READ (SEXCHAR); case SEXCHAR of 'F', 'f' : SEX := FEMALE; 'M', 'm' : SEX := MALE end: [case ] WRITE ('Social Security number: '); READSTRING (SOCSECNUM, LENGTH); WRITE ('Number of dependents: '); READLN (NUMDEPEND): WRITE ('Hourly rate: '): READLN (RATE) end [w i t.h] end; (READEMPLI 7.3 MANIPULATING AN ENTIRE RECORD 333 The two procedure (call) statements READSTRING (NAME, LENGTH); READSTRING (SOCSECNUM, LENGTH); use procedure READSTRING (see Fig. 6.15) to enter a data string. READSTRING returns a character string and an integer value. The first actual parameter in each procedure (call) statement specifies which record field (ONEEMPL. NAME or ONEEMPL. SOCSECNUM) receives the data string. The second parameter of READSTRING represents the length of the string read. The string length is stored in local variable LENGTH but is not saved in the employee's record. II Arrays of Records In Chapter 6, we manipulated arrays with one or more dimensions. We found the array to be a useful data structure for storing a large collection of data items of the same type. We were able to represent game boards and tables of sales figures using arrays. Often a data collection contains items of different types. For example, the data representing the performance of a class of students on an exam might consist of the student names, exam scores, and grades assigned. One approach to organizing these data is to allocate separate arrays for the names, scores, and grades as shown in Fig. 7.6. These arrays are called parallel arrays because all the data items with the same subscript (for example I) pertain to a particular student (the Ith student). Related data items have the same color in the arrays shown in Fig. 7.6. The data for the first student are stored in NAMES [ 1 ], SCORE S [ 1 ], and GRADE S [ 1 ] . Fig. 7.6 Three Parallel Arrays array SCORES [1] [2] [3] [4] _il~_ [1] _ 334 RECORDS array GRADES [2] [3] [4] ••'~i.iit" A more natural organization of the class performance data is to group all the information pertaining to a particular student in a record. Then a single array of records can be used to represent the class. This array of records is illustrated in Fig. 7.7 below. NAME CLASS CLASS CLASS CLASS [1] [2] [3] [4] array CLASS SCORE GRADE - Fig. 7.7 Array of Records The data for the first student are stored in the record CLASS [ 1 I: her individual data items are CLASS [ 1] • NAME, CLASS [ 1] • SCORE, and CLASS [ 1] • GRADE. This particular data organization is used next. • Case Study The next problem illustrates the use of an array of records. Student Grading Problem Revisited Problem: In Section 3.7 we wrote a program to assign grades to each student taking an exam. Since we could not save strings, only the student's initials were read as data. The grade category (outstanding, satisfactory, unsatisfactory) was determined by comparing the student's exam score to the data values MINOUT and MINSAT. We would like to improve this program to read and display the student's last name, to display the low score, high score, average score, and standard deviation, and to assign letter grades more equitably based on the class average and standard deviation. Discussion: The input data for the new grading program consists of a name (a string) and exam score (an integer) for each student; the output consists of the exam statistics and the grade (a character) assigned to each student. The record variable EXAM can be used to provide storage for the grade statistics (see Example 7.4). Since we will have to find the class average before assigning a grade, it will be necessary to process the exam scores more than one time. Consequently we should save all the student data (name, score, and grade) in an array. If the items being stored were all the same data type, a two-dimensional array or table could be used. Since the individual items are not all the 7.5 CASE STUDY 335 same type, we can organize the data for a single student as a record; the data for the entire class can then be stored in an array of records (CLASS). Each student record should contain storage space for the student's name, score, and the grade to be assigned. The name and score of each student taking the exam (CLASS) The exam statistics including the low score, high score, average score, and standard deviation (EXAM : EXAMSTATS) The grade assigned to each student (stored in CLASS) The number of students taking the exam (NUMSTU Algorithm INTEGER) 1. Read the student data. 2. Compute the exam statistics. 3. Assign letter grades to each student. 4. Print the exam statistics. 5. Print the data and grade for each student. The structure chart for this problem is shown in Fig. 7.8; The main program is shown in Fig. 7.9 Fig. 7.8 Structure Chart for Improved Grading Problem l' I CLASS, CLASS, NUMSTU NUMSTU I + l' EXAM I READCLASS RECORDS It CLASS + +1 I EXAM + I CLASS, NUMSTU + ASSIGN FINDSTAT 336 EXAM, NUMSTU PRINTSTAT REPORT program NEWGRADER (INPUT, OUTPUT); lReads student names and scores and computes exam statistics such as low score, high score, average, standard deviation. Assigns letter grades based on the average score. Prints these results.! canst STRINGSIZE = 20; CLASSIZE 200; lMaximum length of each name string! lmaximum number of students! type STRING = packed array [l .. STRINGSIZE] of CHAR; STUDENT = record NAME : STRING; SCORE: 0 .. 100; GRADE : I A I • • I E I end; 1STUDENT! CLASSRANGE = 1 .. CLASSIZE; STUDENTARRAY = array [CLASSRANGE] of STUDENT; EXAMS TATS = record LOW, HIGH: 0 •• 100; AVERAGE, STANDARDDEV end; IEXAMS TAT I REAL var CLASS : STUDENTARRAY; EXAM: EXAMSTATS; NUMSTU: O.. CLASSIZE; larray of student recordsl Istatistics for examl Inumber of students I IInsert procedures READCLASS, FINDSTAT, ASSIGN, PRINTSTAT, REPORT. I begin INEWGRADER I IRead the student data.1 READ CLASS (CLASS, NUMSTU); lCompute the exam statistics.! FINDSTAT (CLASS, NUMSTU, EXAM); IAssign letter grades to each student. I ASSIGN (NUMSTU, EXAM, CLASS); IPrint the exam statistics. I PRINTSTAT (EXAM); IPrint the data and grade for each student.! REPORT (CLASS, NUMSTU, EXAM) end. INEWGRADER I Fig. 7.9 Main Program for Improved Grading Problem Rather than show stubs for the five level one procedures, we have simply indicated by a comment where these procedures belong in the main program. We will discuss some of the level two procedures next and leave the rest as exercises. 7.5 CASE STUDY 337 Procedure READCLASS in Fig. 7.10 is used to enter the data [student name and exam score) for the class. It also returns a count of students (NUMSTU) taking the exam. Fig. 7.10 Procedure READCLASS procedure READ CLASS (var CLASS loutputl : STUDENTARRAY; var NUMSTU loutputl : INTEGER); IReads all student records and stores them in consecutive elemen~s of the array CLASS. Returns the count of students in NUMSTU. const SENTINEL , ., Istring of 20 blanksl var NEXTSTUDENT : STUDENT; Icurrent student recordl procedure READSTUDENT (var NEXTSTUDENT loutputl : STUDENT); IReads a single student record. Reads a blank string for the NAME field if there are no more student records. I var LENGTH: O•• STRINGSIZE; lactual length of name stringl IInsert procedure READSTRING here.l begin IREADSTUDENTI with NEXTSTUDENT do begin WRITE ('NAME: '); READSTRING (NAME, LENGTH); if NAME SENTINEL then begin WRITE ('SCORE: '); READLN (SCORE) end [Lf ] end [w i t.h] end; IREADSTUDENTI begin IREADCLASSI WRITELN ('Enter the data requested for each student.'); WRITELN ('Press return (after prompt NAME: ) when done.'); NUMSTU := 0; linitial count of studentsl repeat READSTUDENT (NEXTSTUDENT); Iread next studentl if NEXTSTUDENT.NAME SENTINEL then begin NUMSTU := NUMSTU + 1; Iincrease coun t ] CLASS [NUMSTU] := NEXTSTUDENT Isave the data in CLASS I end [Lf ] until (NEXTSTUDENT.NAME = SENTINEL) or (NUMSTU = CLASSIZE); lassert: no more students or array is filledl if NUMSTU = CLASSIZE then WRITELN ('Array is filled with student data.') end; IREADCLASS I 338 RECORDS Procedure READCLASS is similar to procedure READSCORES in Fig. 6.12. It uses procedure READSTUDENT to read each student's data (name and exam score only) into the local record variable NEXTSTUDENT. Entering a blank name (by pressing 0 Thus 4! is 4 X 3 X 2 X 1 or 24. It is easy to implement this definition as a recursive function in Pascal. Example 9.4 Function FACTOR in Fig. 9.17 computes the factorial of its argument N. The recursive step FACTOR := N * FACTOR(N-l) implements the second line of the factorial definition above. This means that the result of the current call (argument N) is determined by multiplying the result of the next call (argument N-l) by N. function FACTOR (N : INTEGER) : INTEGER; IRecursively computes the factorial of N. ] begin IFACTORl. if N = 0 then FACTOR := 1 else FACTOR := N end; IFACTORl * FACTOR(N-l) FIg. 9.17 Function FACTOR A trace of FACT := FACTOR(3) is shown in Fig. 9.18. The value returned from the orizinal r.HII. FAC:- Fig. 9.18 Trace of FACT:= FACTOR(3) Example 9.5 The Fibonacci numbers are a number sequence that have varied uses. They were originally intended to model the growth of a rabbit colony. Although we will not go into details of the model here. the Fibonacci sequence 1.1,2,3,5,8,13,21,34, ... certainly seems to increase rapidly enough. The fifteenth number in the sequence is 610. (That's a lot of rabbits!) The Fibonacci sequence is defined below. • Fib, is 1 • Ftb, is 1 • Fib , is Fib n _ 2 + Fib n _ 1 for n > 2 Verify for yourself that the sequence of numbers shown in the paragraph above is correct. A recursive function that computes the Nth Fibonacci number is shown in Fig. 9.19. Fig. 9.19 Recursive Function FIBONACCI function FIBONACCI (N : INTEGER) : INTEGER; IComputes the Nth Fibonacci number.} begin IFIBONACCI} if (N = 1) or (N = 2) then FIBONACCI := 1 else FIBONACCI .= FIBONACCI(N-2) + FIBONACCI (N-l) end; I FIBONACCI I 9.3 RECURSIVE FUNCTIONS 445 Although easy to write, the FIBONACCI function is not efficient because each recursive step generates two calls to function FIBONACCI. This is similar to procedure TOWER shown earlier, in that time and memory requirements grow exponentially as N increases. Example 9.6 Euclid's algorithm for finding the greatest common divisor of two integers, GCD (M, N), is defined recursively below. The greatest Gammon divisor of two integers is the largest integer that divides them both. • GCD(M, N) is N if N This algorithm states that the divides M. If M is the smaller performed with the arguments answer is obtained by finding ed by N. The declaration and Fig. 9.20. GCD is N if N is the smaller number and N number, the GCD determination should be transposed. If N does not divide M, then the the GCD of N and the remainder of M dividuse of the Pascal function GCD is shown in Fig. 9.20 Euclid's Algorithm for the Greatest Common Divisor program FINDGCD (INPUT, OUTPUT); IPrints the greatest common divisor of two integers.l var M, N : INTEGER; Itwo input items] function GCD (M, N : INTEGER) : INTEGER; IFinds the greatest common divisor of M and N.l begin IGCDl if (N NEXTVAL do 3. Move element value down one position. 4. Check next smaller element value. 5. Define NEWPOS as the position of the last value moved. RECURSION, SEARCHING, AND SORTING procedure SHIFTBIGGER (var TABLE linput/outputj : INTARRAY; NEXTPOS, NEXTVAL (inputj : INTEGER; var NEWPOS loutput) : INTEGER); {Shifts each array element value in the sorted subarray 1 .. NEXTpOS-l that is greater than NEXTVAL down 1 element. NEWPOS is set to indicate the correct position of NEXTVAL.1 begin ISHIFTBIGGERj IShift all values> NEXTVAL. Start with element at NEXTPOS-l.j while (NEXTPOS > 2) and (TABLE[NEXTPOS-l] > NEXTVAL) do begin TABLE[NEXTPOS] := TABLE[NEXTPOS-l]; Ishift value downj NEXTPOS := NEXTPOS - 1 Itry next elementj end; [wh i Le ] lassert: NEXTPOS is 2 or NEXTVAL belongs at position NEXTPOSj IShift TABLE[l] if necessary and de fine NEWPOS. j if TABLE[l] > NEXTVAL then begin TABLE[2) := TABLE[l]i {move TABLE[l] downj NEWPOS := 1 INEXTVAL is the smallest so farj end else NEWPOS := NEXTPOS Ide fine NEWPOS j end; ISHIFTBIGGERj Fig. 9.32 Procedure SHIFTBIGGER The while statement in Fig. 9.32 compares and shifts all values greater than NEXTVAL in the subarray with subscripts 2 •• NEXTPOS -1. The if statement in Fig. 9.32 is used to compare only the first array element value to NEXTVAL and possibly shift it. This seemingly extra statement is needed because an "out of bounds subscript" error occurs if the while condition is evaluated for NEXTPOS = 1 (NEXTPOS-l = 0). The if statement also defines the value of NEWPOS. So far, we have studied three sorting algorithms: bubble sort, selection sort, and insertion sort. In each of these algorithms the time required to sort an array increases with the square of the number of array elements, or, the time required to sort an array of N elements is proportional to N2. Consequently, these algorithms are not particularly efficient for large arrays (i.e. N >= 100). A much faster sorting procedure will be discussed in the next section. Self-check Exercises for Section 9.6 1. Rewrite the selection sort without using recursion. 2. Assume the values 10, 5, 7, - 3, 4, 9, 7, - 3, - 5 are stored in consecutive array elements. Trace the execution of SELECTSORT and INSERTSORT on this array. Show the array just before each recursive call to SELECTSORT and just before each repetition of the for statement in INSERTSORT. 9.6 ADDITIONAL SORTING ALGORITHMS 461 II Case Study-The Quicksort Algorithm The time required to sort an array using a simple sorting algorithm increases with the square of the number of array elements. This means that the time required to sort an array with N elements is proportional to N2. Quicksort Problem: A faster algorithm is needed for sorting an array. We would like to see an improvement similar to that provided by binary search over simple search. Discussion: The quicksort algorithm works in the following way. Given an array with subscripts FIRST •• LAST to sort, it rearranges this array so that all element values smaller than a selected pivot value are first, followed by the pivot value, followed by all element values larger than the pivot value. After this rearrangement (called a partition), the pivot value is in its proper place. All element values smaller than the pivot value are closer to where they belong as they precede the pivot value. All element values larger than the pivot value are closer to where they belong as they follow the pivot value. An example of this process is shown below. We will assume that the first array element is arbitrarily selected as the pivot. A possible result of the partitioning process is shown beneath the original array. o pivot original array array after 1st partition After the partitioning process, the fifth array element contains the pivot value, 44. All values less than 44 are in the left subarray (blue area); all values greater than 44 are in the right subarray (grey area) as desired. The next step is to apply quicksort recursively to both subarrays. The data requirements and algorithm for quicksort follow. We will describe how to do the partitioning later. the array being sorted (TABLE : I NTARRAY) the first subscript (FIRST : INTEGER) the last subscript (LAST : INTEGER) 462 RECURSION, SEARCHING, AND SORTING the sorted array (TABLE INTARRAY) the subscript of the pivot value after partitioning (PIVINDEX : Algorithm INTEGER) 1. if FIRST 2. Partition the elements pivot value is in place 3. Apply quicksort to the 4. Apply quicksort to the in the subarray FIRST •• LAST so that the (subscript is PIVINDEX) sub array FIRST •• PIVINDEX-l subarray PIVINDEX+I •• LAST The recursive algorithm above shows that nothing is done for the simple case FIRST >= LAST. If FIRST > LAST is true, then the array bounds are improper; if FIRST = LAST is true, then a one-element array exists which is sorted by definition. The implementation of procedure QUICKSORT is shown in Fig. 9.33. The procedure (call) statement QUICKSORT (TABLE, 1, N) could be used to sort an array TABLE (type INTARRAY) with subscripts 1 •• N. The two recursive calls to QUICKSORT in Fig. 9.33 will cause the QUICKSORT procedure to be applied to the sub arrays that are separated by the value at PIVINDEX. If any subarray contains just one element (or zero elements), an immediate return will occur. Procedure PARTITION selects the pivot and performs the partitioning operation. When the arrays are randomly ordered to begin with, any element may be used as the pivot value. For simplicity, we will choose the element with subscript FIRST. We will then search for the first value at the left end of the sub array being sorted that is greater than the pivot value. When we find it, we search for the first value at the right end of the subarray that is less than or equal to the pivot value. These two values are exchanged and we repeat the search and exchange operations. This is illustrated below with UP pointing to the first value greater than the pivot and DOWN pointing to the first value less than or equal to the pivot value.. pivot o original array i UP i DOWN 9.7 CASE STUDY-THE QUICKSORT ALGORITHM 463 procedure QUICKSORT (var TABLE linput/outputl : INTARRAY; FIRST, LAST linputl : INTEGER); IRecursive procedure to sort the subarray of TABLE with subscripts FIRST •. LAST. Uses procedure PARTITION to split the array into two subarrays such that the pivot value is in its proper place (subscript PIVINDEX) preceded by all smaller values and followed by all larger values. l var PIVINDEX : INTEGER; Isubscript of pivot valuereturned by PARTITIONl procedure PARTITION (var TABLE linput/outputl : INTARRAY; FIRST, LAST linputl : INTEGER; var PIVINDEX loutputl : INTEGER); IPartitions the subarray of TABLE with subscripts FIRST •. LAST into two subarrays. All values less than or equal to TABLE[PIVINDEX] are in the left subarray; all values greater than TABLE[PIVINDEX] are in the right subarray. l begin IPARTITIONl WRITELN ('Procedure PARTITION entered.') end; (PARTITIONI begin IQUICKSORTl if FIRST Seventy-five is the first value at the left end of the array that is larger than 44; thirty-three is the first value at the right end that is less than or equal to 44 so these two values are exchanged. The pointers UP and DOWN are then advanced from their current positions to the positions below. after first exchange i i UP DOWN Fifty-five is the next value at the left end that is larger than 44; twelve is the next value at the right end that is less than or equal to 44, so these two values are exchanged, and UP and DOWN are advanced again. 464 RECURSION, SEARCHING, AND SORTING after second exchange After the second exchange above, the first five array element values are all less than or equal to the pivot; the last four element values are all larger than the pivot. Fifty-five is selected by UP once again as the next element larger than the pivot; twelve is selected by DOWN as the next element less than or equal to the pivot. Since UP has now "passed" DOWN, these values are not exchanged. Instead, the pivot value (subscript is FIRST) and the value at position DOWN are exchanged. This puts the pivot value in its proper position (new subscript is DOWN) as shown below. The partitioning process is now complete, and the value of DOWN is returned as the pivot index (PIVINDEX). QUICKSORT will be called recursively to sort the left sub array and the right subarray. The algorithm for PARTITION follows. This algorithm is implemented in Fig. 9.34. Algorithm for PARTITION 1. Define the pivot value as the contents of TABLE [FIRST]. 2. Initialize UP to FIRST and DOWN to LAST. 3. repeat 4. Assign the subscript of the first element greater than the pivot value to UP. 5. Assign the subscript of the first element less than or equal to the pivot value to DOWN. if UP 9.7 CASE STUDY - THE QUICKSORT ALGORITHM 465 procedure PARTITION (var TABLE Iinput/output! : INTARRAY; FIRST, LAST linput! : INTEGER; var PIVINDEX loutput! : INTEGER); IPartitions the subarray of TABLE with subscripts FIRST .. LAST into two subarrays. All values less than or equal to TABLE[PIVINDEX] are in the left subarray; all values greater than TABLE[PIVINDEX] are in the right subarray. var PIVOT, UP, DOWN : INTEGER; Ithe pivot value! Ipointer to values > PIVOT! Ipointer to values PIVOT do DOWN := DOWN - 1; lassert: TABLE[DOWN] = DOWN; luntil UP meets or passes DOWN! IAssert: values DOWN! IPut pivot value where it belongs and define PIVINDEX.! EXCHANGE (TABLE[FIRST] , TABLE[DOWN])i PIVINDEX := DOWN end; IPARTITION! Fig. 9.34 Procedure PARTITION 466 RECURSION, SEARCHING, AND SORTING The two while loops in Fig. 9.34 are used to advance pointers UP and DOWN to the right and left, respectively. Since TABLE [FIRST] is equal to PIVOT, the second loop will stop if DOWN reaches the left end of the array (DOWN is FIRST). The extra condition (up N X N (simple sorts) N X 1092 N (QUICKSORT) 32 64 128 256 512 1024 4096 16384 65536 262144 160 384 896 2048 4608 Self-check Exercises for Section 9.7 1. Complete the trace of QUICKSORT for the subarrays remaining after the first partition. 2. If an array contains some values that are the same, in which subarray (left or right) will all values equal to the pivot value be placed? • Common Programming Errors The most common problem with a recursive procedure is that it does not terminate properly. For example, if the terminating condition is not correct or is incomplete, the procedure may call itself indefinitely or until all available memory is used up. Normally, a "stack overflow" run-time error is an indicator that a recursive procedure is not terminating. Be sure to identify all stopping cases and provide a terminating condition for each one. Also be sure that each recursive step leads to a situation that is clos9.8 COMMON PROGRAMMING ERRORS 467 er to a stopping case and that repeated recursive calls will eventually lead to stopping cases only. The use of large arrays as value parameters can quickly consume all available memory. Unless absolutely essential for data protection, arrays should be passed as variable parameters. An expression such as N-1 must be passed as a value parameter. Debugging Recursive Procedures Sometimes it is difficult to observe the result of a recursive procedure execution. If each recursive call generates many output lines and there are many recursive calls, the output will scroll down the screen more quickly than it can be read. On most systems it is possible to stop the screen temporarily by pressing a control character sequence (e.g. Control S). If this cannot be done, it is still possible to cause your output to stop temporarily by printing a prompting message followed by a READLN. Your program will resume execution when you press the carriage return character. One problem with sort and search procedures is the possibility of going beyond the bounds of a subarray. Make sure that your Pascal system checks for subscript range errors. On some systems this important check must be activated by the programmer; otherwise, subscript range violations are not detected. If this is the case on your system, make sure that you activate this feature when debugging any program that manipulates arrays, particularly a search or sort. When debugging a search or sort procedure it is best to use relatively small arrays (e.g. 10 elements). Make sure that you print the new contents of the array after each pass through a sort procedure. • Chapter Review This chapter provided many examples of recursive procedures and functions. Hopefully, studying them has given you some appreciation of the power of recursion as a problem solving and programming tool and has provided you with valuable insight regarding its use. It may take some time to feel comfortable thinking in this new way about programming, but it is certainly worth the effort. We discussed a minor improvement to an array search and also studied the binary search technique, which provides significant improvement for larger arrays. The relationship between the number of array elements, N, and the time required to perform a binary search is on the order of 10gzN. This means that the time required to perform a binary search increases very slowly. For example, it should only take about twice as long to perform a binary search on an array with 256 elements (logz256 is 8) as it would take to perform a binary search on an array with 16 elements (log, 16 is 4). Searching an array using hashing was also discussed. In the absence of 468 RECURSION, SEARCHING, AND SORTING collisions. this technique enables a target to be found with a single probe regardless of the array size. We also discussed three new sorting algorithms. The selection sort and insertion sort are considered N X N sorts just like the bubble sort. This means that the time required to sort an array using one of these techniques is proportional to the square of the number of elements. For larger arrays. it is best to use the recursive QUICKSORT algorithm described in Section 9.7. The relationship between this algorithm and the number of array elements. N. is expressed by the formula N X logzN. Review Questions 1. 2. 3. 4. Explain the nature of a recursive problem. Discuss the efficiency of recursive procedures. Differentiate between stopping cases and a terminating condition. Write a Pascal program with a procedure that has a character string parameter (maximum length of six). The procedure should print the accumulating sum of ordinal values corresponding to each character in the string until a blank is encountered or all six characters have been summed. 5. Write a Pascal program with a function that will return the sum of ordinal values corresponding to the characters in a character string parameter (maximum length of six). The function should add up the ordinal values until a blank is encountered or all six characters have been summed. 6. Convert the Pascal program below from an iterative process to a recursive function that calculates an approximate value for e, the base of the natural logarithms, by summing the series 1 + 1/1! + 1/2! + ••• l/N! until additional terms do not affect the approximation. program ELOG (OUTPUT): var ENL, DELTA, FACT : REAL: N : INTEGER: begin IELOGI ENL := 1. 0: N := 1: FACT := 1. 0: DELTA := 1.0: repeat ENL := ENL + DELTA: N := N + 1: FACT := FACT * N: DELTA := 1 / FACT: until ENL = (ENL + DELTA): WRITE ('The value of e is " end. IELOGI ENL :18:15) 9.9 CHAPTER REVIEW 469 Write a function that will recursively search a string of maximum length of 30 characters and return the position of the first comma in the string. If the string does not contain a comma, then return 30. 8. Discuss the major differences between hashing and binary search. 7. Programming Projects 1. Write a procedure that reads each row of an array as a string and converts it to a row of GRID (see Fig. 9.21). The first character of row one corresponds to GRID [ 1,1], the second character to GRID [1,2], etc. Set the element value to EMPTY if the character is blank; otherwise, set it to FILLED. The number of rows in the array should be read first. Use this procedure in a program that reads in cell coordinates and prints the number of cells in the blob containing each coordinate pair. 2. The expression for computing C(n,r) , the number of combinations of n items taken r at a time is nl c(n,r) = - r! (n-r)! Write and test a function for computing cln.r] given that nl is the factorial of n. 3. A palindrome consists of a word that reads the same forward or backward, such as level, deed, and mom. Write a recursive function that returns the BOOLEAN value TRUE if a word, passed as a parameter, is a palindrome. 4. Write a recursive function that returns the value of the following recursive definition: F(X,Y) F(X,Y) 5. x - Y F(X-1,Y) + F(X,Y-1) if X or Y Write a recursive routine that lists all the pairs of positive integers that are the sum of a given number. For example: 7 = 6+1, 5+2, and 4+3 Do not repeat any pairs [ie. not both 6+1 and 1 +6). 6. Write a routine that lists all the pairs of subsets for a given set of letters. For example [ 'A' , 'C' , 'E' , 470 RECURSION, SEARCHING, AND SORTING 'G']~ , C' ] , [ 'A' , 'E' ] , [ 'A' , 'G' ], [ , C' , 'E' ], [ 'C' , 'G' ], [ 'E' , 'G' ] ['A', 7. Write two recursive routines that add the numerical equivalents of two character strings and save the result in a third string. The first recursive routine will accept five parameters: two strings of digits, right-justified with leading blanks, the length of each string, and a RESULT string. The routine will add each corresponding set of digits, from the right, and calculate the sum. At this point, each digit calculated by this ADDER procedure will be inserted into a character string for the RESULT. At the completion of this routine, the answer will be in reverse order in the string RESULT. The second recursive routine will take the string RESULT and reverse the digits and right-justify the answer with leading blanks. An example would be: After Routine #1: 368' STRING1 ' 4162' STRING2 , 0354 'if all are size 6 RESULT After Routine #2: ORIGINAL RESULT = '0354 PROCESSED RESULT =' 4530' 8. Write a routine that converts a character string consisting of numbers, letters, spaces, and punctuation symbols into a compressed and symbolic representation of the original string. Each consecutive string of digits, letters, blanks, or punctuation symbols will be converted to one specially defined character. Use the following conversion scheme: • • • • Letters convert to an 'L' Digits convert to a '#' Blanks convert to a blank Anything else converts to a '?' For example the following string would be converted as indicated: INITIAL STRING = 'HELLO, MY.,NUMBER IS 2716 •• ' would convert to: 'L? L?L L #?' 9. Write a routine that accepts an 8 by 8 array of characters that represent a MAZE. Each position can contain either an 'X' or a blank. Starting at position [ 1 , 1 ], list any path through the maze to get to location [8,8]. Only horizontal and vertical moves are allowed (no diagonal moves). If no path exists, write a message indicating this. Moves can only be made to locations that contain a blank. Encountering an 'X' means the path is blocked and another must be chosen. Use recursion. 10. One method of solving a continuous numerical function for a root implements a technique similar to the binary search. Given a numerical function defined as F(X), and two values of X that are known to bracket one of the roots, we can approximate this root through a method of repeated division of this bracket. PROGRAMMING PROJECTS 471 For a set of values of X to bracket a root, the value of the function for one X must be negative and the other must be positive, as illustrated in the diagram below, which plots F(X) for values of X between Xl and X2. F(x)=O--+----_~-------X Root desired F(X) X1 The algorithm requires that the midpoint between the left X and the right X be evaluated in the function; if it equals zero the root is found; otherwise, the left X(Xl) or right X (X2) is set to this midpoint. To determine whether to replace either Xl or X2, the sign of the midpoint is compared against the signs of the values of F(Xl) and F(X2). The midpoint replaces the X (Xl or X2) whose function value has the same sign as its function value. This routine can be written recursively. The terminating conditions are true when either the midpoint evaluated in the function is zero or the absolute value of the left minus the right X is less than some small predetermined value [e.g. 0.0005). If the second condition occurs then the root is said to be approximately equal to the midpoint of the last set of left and right X's. 11. We can use the file merge technique demonstrated in Section 8.6 to sort two arrays. The mergesort begins by taking adjacent pairs of array values and ordering the values in each pair. It then forms groups of four elements by merging adjacent pairs (first pair with second pair, third pair with fourth pair, etc.] into another array. It then takes adjacent groups of four elements from this new array and merges them back into the original array as groups of eight, etc. The process terminates when a single group is formed that has the same number of elements as the array. MERGESORT is illustrated in Fig. 9.35 for an array with eight elements. Write a MERGESORT procedure. Fig. 9.35 Illustration of MERGESORT original array 472 RECURSION, SEARCHING, AND SORTING pairs ordered merged pairs merged quads 12. Many compilers use the recursive descent technique for compiling. This technique consists of writing a recursive procedure for each syntactic element of the language. To determine whether or not an input line is a particular kind of statement it is parsed by the procedure for that statement. If the procedure is able to successfully process every element in the input line, then the line is accepted as satisfying the syntax of that statement. Write a parser that determines whether or not its input string is a Pascal expression. Assume that all characters of the string are squeezed together (no blanks) and that all unsigned constants are single digits and all variables are individual uppercase letters. The operators mod, di v, and, or, not are represented by single lowercase letters (m for mod, d for di v, etc.) Also, ignore sets and functions as possible syntactic elements. The symbol $ will appear at the end of each string to be parsed. The string 'X+ (y* 2m4 ) $ , represents the expression X + (Y * 2 mod 4) which is syntactically valid. The string IX + ( Y* 2m4 $ I should not be accepted as valid (missing parenthesis). To write your parser, provide a procedure corresponding to each relevant syntax diagram in Appendix C. Each procedure should return TRUE if its syntax is satisfied and should also return the length of the string that it accepted; otherwise, it should return FALSE. We will start you off with the procedure for expression in Fig. 9.36. An expression is either a simple expression (accepted by procedure SIMPEXPR) or two simple expressions separated by a relational operator. (For simplicity, the relational operators are , = only.] procedure EXPRESSION (INSTRING linputl : STRING; START linputl : INTEGER; var EXPRLENGTH loutputl : INTEGER; var ISEXPR [out.put.] : BOOLEAN); IAttempts to recognize an expression in INSTRING starting at position START. If an expression exists, ISEXPR is set to TRUE and EXPRLENGTH indicates the length of the expression. Otherwise, ISEXPR is set to FALSE. Calls SIMPEXPR. l var POSITION, SIMPEXPRLENGTH : INTEGER; ISSIMPEXPR : BOOLEAN; begin IEXPRESSION) POSITION := START; ISEXPR := FALSE; Icurrent position in INSTRINGl Ilength of last simple expressionl lis a simple expression found?l linitial positionl lassume not an expressionl IAn expression must start with a simple expression.) SIMPEXPR (INSTRING, POSITION, SIMPEXPRLENGTH, ISSIMPEXPR); if ISSIMPEXPR then begin Ifirst simple expressionl EXPRLENGTH := SIMPEXPRLENGTH; [de f i.ne Leriq t.h] POSITION := POSITION + SIMPEXPRLENGTH; ladvance in stringl PROGRAMMING PROJECTS 473 ICheck whether next character is a relational operator.l if not (INSTRING[POSITION] in [' ' ,'=']) then ISEXPR := TRUE lis an expression without reI opl else Inext character is reI opl begin Irel op] IA simple expression must follow relational operator.l POSITION := POSITION + Ii SIMPEXPR (INSTRING,POSITION, SIMEXPRLENGTH,ISSIMPEXPR)i if ISSIMPEXPR then begin Isecond simple expression\ ISEXPR := TRUEi lis an expression with reI op\ IIts length is sum of simple lengths + 1 (reI op)\ EXPRLENGTH := EXPRLENGTH + SIMPEXPRLENGTH + 1 end Isecond simple expression\ end [r e L op] end !first simple expressionl endi IEXPRESSION\ Fig. 9.36 Procedure EXPRESSION You will need procedures for simple expressions. factors. terms. variables. and unsigned constants. Your main program should read the input string and call the procedure EXPRESSION. If the value returned is TRUE and the next character is '$', the string is a valid expression 474 RECURSION, SEARCHING, AND SORTING Pointer Variables and Dynamic Data Structures 10.1 10.2 10.3 10.4 10.5 10.6 10.7 10.8 10.9 10.10 The NEW Statement and Pointer Variables Understanding Dynamic Allocation Introduction to Linked Lists Manipulating Linked Lists Using Pointer Variables Case Study-Maintaining a Linked List Stacks and Queues Multiple-linked Lists and Trees Case Study-Maintaining a Binary Search Tree Common Programming Errors Chapter Review In this chapter, we shall see how Pascal can be used to create dynamic data structures. Dynamic data structures are data structures that "grow" as a program executes. A dynamic data structure is a collection of elements [called nodes) that are normally records. Unlike an array that always contains storage space for a fixed number of elements, a dynamic data structure expands and contracts during program execution based on the data storage requirements of the program. Dynamic data structures are used for storage of real world data that are constantly changing. An example would be an airline passenger list. If this list were maintained in alphabetical order in an array, it would be neces475 sary to move all passenger records that alphabetically followed a new passenger in order to make room for that passenger's data in the array. This would require using a loop to copy the data record for each passenger being moved to the next array element. If a dynamic data structure is used instead, the new passenger data can simply be inserted between two existing passenger records with a minimum of effort. Dynamic data structures are extremely flexible. As described above, it is relatively easy to add new information by creating a new node and inserting it between two existing nodes. We shall see that it is also relatively easy to modify dynamic data structures by removing or deleting an existing node. This is more convenient than modifying an array of records, where each record is in a fixed position relative to the others as determined by its subscript. This chapter discusses four dynamic data structures: lists, stacks, queues, and trees. We will learn how to insert and delete elements from each of these data structures. We will also learn how to search a list and a tree. Before beginning our study of these data structures, we will introduce dynamic storage allocation in Pascal. • The NEW Statement and Pointer Variables Since we don't know beforehand the order or number of nodes (elements) in a dynamic data structure, we cannot allocate storage for a dynamic data structure in the conventional way (using a variable declaration statement). Instead, we must allocate storage for each individual node as needed and, somehow, join this node to the rest of the structure. The NEW statement is used to allocate storage for a new node. We must also have some way of referencing each new node that is allocated in order to store data in it. Pascal provides a special type of variable, called a pointer variable (or pointer], for this purpose. Example 10.1 The statements type STRING = packed array [1 .• 3] of CHAR; NODE = record WORD : STRING; PLACE : INTEGER end; INODEI NODE POINTER = ~NODE; var P, Q, R : NODEPOINTER; declare a record type NODE and a pointer type, NODEPOINTER, to records of type NODE. The variables P, Q, and R are defined as pointer variables of type NODEPOINTER. 476 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES The statements NEW (p); NEW (Q); allocate storage for two records that are "pointed to" (referenced) by pointers P and Q. Since P and Q are type NODEPOINTER. these new records must be type NODE as illustrated below. The value of a pointer variable is really the address in memory of a particular node. We will represent a pointer value by drawing an arrow to the node referenced by the pointer. Both fields of these new nodes are initially undefined. p Q P~.WORD Q~.WORD := 'ACE'; := 'BOY'; define the WORD field of P" (the node referenced by pointer P) and Q" (the node referenced by pointer QJ as shown next. i , ii " P , . :\ ",.' .'1.• , ',·.. - - - The diagram shows that P points to a record of type NODE whose first field contains the string 'ACE' and Q points to a record of type NODE whose first field contains the string 'BOY'. The second field of both records is still undefined. The statements P~ • PLACE : = 25 i Q~.PLACE := 37; define the PLACE fields as shown next. --.. , p" , . 11... ~: ..... 10.1 THE NEW STATEMENT AND POINTER VARIABLES 477 a--, In the example above, we used pointers P and Q to reference two different nodes. The pointer that references each node was determined when the node was created. We shall demonstrate next that it is possible to change the node referenced by a particular pointer, or to have the same node referenced by more than one pointer. Example 10.2 The pointer assignment statement R := Pi copies the value of pointer P into pointer R. This means that pointers P and R contain the same memory address and now point to the same node as shown below. The pointer assignment statements P := Qi Q := Ri would have the effect of exchanging the nodes pointed to by P and Q as shown below. R p a The statement WRITE (P~.WORD, Q~.WORD, R~.WORD) displays the WORD field (a character string) of the records pointed to by P, Q and R. The output printed would be BOYACEACE Pointers P, Q and R are similar to subscripts in that they select particular nodes or elements of a data structure. Unlike subscripts, their range of 478 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES values is not declared and their values (memory cell addresses) may not be printed. It is important to understand the difference between using P and p" in a program. P is a pointer variable (type NODE POINTER) and is used to store the address of a data structure of type NODE. P can be assigned a new value through a pointer assignment or execution of a NEW statement. P" is the name of the record pointed to by P and can be manipulated like any other record in Pascal. The field selectors p" . WORD and p" . PLACE can be used to reference data (a string and integer) stored in this record. Throughout the chapter. we will represent the value of a pointer variable by drawing an arrow to a box that denotes a record. The actual point of contact of the arrowhead with the box is not important. The arrow in the diagram below represents the value of P; the value of P". WORD is I BOY' and P" • PLACE is 37. P". WORD P". PLACE In this section. we discussed how to declare pointer variables and manipulate pointer values. We also saw how to create nodes and reference nodes using pointer variables. These operations are described in the displays that follow. POINTER TYPE pointer-id = , field-name Interpretation: The field specified by field-name of the node currently pointed to by pointer variable pointer is referenced. 10.1 THE NEW STATEMENT AND POINTER VARIABLES 479 POINTER ASSIGNMENT pointer; : = pointer; Interpretation: The address contained in variable pointer; is assigned to variable pointer.. The result is that pointer variable pointer; now points to (references) the same node as pointer.; Pointer; and pointer: must be the same pointer type. Self-check Exercises for Section 10.1 1. For the last diagram in this section. explain the effect of each legal as- signment statement below, a) R".WORD := 'CAT' b) P" : = R" c) P.WORD := 'HAT' d) P : = 54 e) P".PLACE := 0 f) P := R ~ P".WORD := -10 h) Q". PLACE : = R". PLACE 2. The sequence of assignment statements R := Pi P := Qi Q := R was used to exchange the values of pointer variables P and Q so that P points to the element containing 'BOY' and Q points to the element containing' ACE'. What would the sequence R".WORD := P".WORDi P".WORD := Q".WORDi Q".WORD := R".WORD do? What is the difference between these two sequences? • Understanding Dynamic Allocation As mentioned above. a new record is created whenever the NEW statement (a standard procedure) is executed. You may be wondering where in memory the new record is stored. Pascal maintains a storage pool of available memory cells; memory cells from this pool are allocated whenever a NEW statement is executed. 480 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES The statement NEW (P) in Example 10.1 has pointer variable P as its parameter. Since P is declared as a pointer to records of type NODE, the execution of this statement causes the allocation of memory space for the storage of three characters and an integer variable. These cells are originally undefined (they retain whatever data was last stored in them) and the address of the first cell allocated is stored in P. The cells allocated are no longer considered part of the storage pool of available cells. The only way to reference these cells is through pointer variable P (e.g. P". WORD or P". PLACE). Fig. 10.1 shows the pointer variable P and the storage pool before and after the execution of NEW (P). The before diagram shows pointer variable P as undefined before the execution of NEW (P). The after diagram shows P pointing to the first of two memory cells that were allocated for the new record (assuming that three characters and an integer can be stored in two cells). The cells considered part of the storage pool have the darker color in Fig. 10.1 After NEW (P) Before NEW (P) p III Fig. 10.1 Storage Pool before and after NEW (P) As an example. if the memory cells with addresses 1000 through 1003 were originally in the storage pool, then after the execution of NEW (P) only the memory cells with addresses 1002 and 1003 would be considered part of the storage pool. The address 1000 would be stored in pointer variable P and that cell and cell 1001 can only be referenced through P . • Introduction to Linked Lists A linked list or simply list is a sequence of nodes in which each node is linked or connected to the node following it. A list with three nodes is shown below. HEAD 10.3 INTRODUCTION TO LINKED LISTS 481 Each node in the list above has two fields: the first field contains data and the second field is a pointer (represented by an arrow) to the next list element. There is a pointer (HEAD) to the first list element or list head. The symbol/is always found in the pointer field of the last list element. Lists are important data structures because they can easily be modified. For example. a new node containing the string I BYE' can be inserted between the strings I BOY I and 'CAT' by changing only one pointer value (the one from 'BOY ') and defining the pointer from the new node. This is true regardless of how many elements there may be in the list. The list is shown below after the insertion; the pointer values that are new are shown in blue. HEAD Similarly, it is easy to delete a list element. Only one pointer value has to be changed-the pointer that currently points to the element being deleted. The linked list is redrawn below, after deleting the string 'BOY I by changing the pointer from the node I ACE I (new value shown in blue; old value in grey). The node containing string I BOY' is effectively disconnected from the list since there is no longer a pointer to it. The new list consists of the strings I ACE I , I BYE I , I CAT I • HEAD Implementing Linked Lists in Arrays Two methods are commonly used to implement linked lists. In older programming languages, linked lists are implemented using arrays. Nodes are stored in parallel arrays or arrays of records. The node value is stored in one field, and the subscript of the next list element is stored in the pointer field. A pointer value of 0 indicates the end of the list. The original threeelement list is shown at the left of Fig. 10.2. Since HEAD is 1, the first array element represents the first node in the list. The third array element is the last list node. Fig. 10.2 Representing Lists in Arrays HEAD HEAD original list 482 HEAD list after inserting 'BYE' POINTER VARIABLES AND DYNAMIC DATA STRUCTURES list after deleting 'BOY' The array element pointed to by each subscript is indicated by an arrow. The original list (' ACE I, 'BOY', I CAT I) can be traced by following the arrows. The list is shown in the middle diagram after inserting 'BYE' ( , ACE I , I BOY I , 'BYE', I CAT '); the list is shown in the diagram on the right after deleting I BOY I ( ' ACE I , I BYE I , I CAT '). Note that the node containing I BOY I is still in the array (second element), but it is no longer considered part of the list. One of the disadvantages of storing lists in arrays is that we must declare an array that is big enough to hold the largest possible list regardless of how many nodes are actually used. In Pascal, we can use pointer variables and dynamic allocation to ensure that we only allocate enough memory to store the actual list. We will see how to do this next. • Manipulating Linked Lists Using Pointer Variables In order to implement a linked list using pointer variables, we must declare a record with at least one field that is a pointer. The record type LISTNODE declared below describes a node in our sample list. type STRING = packed array [1 •• 3) of CHARi LISTPOINTER = ALISTNODEi LISTNODE = record WORD : STRINGi LINK : LISTPOINTER erid r ILISTNODEj A pointer type, LISTPOINTER, that points to elements (records) of type LISTNODE is declared. Each element of type LISTNODE contains a field named LINK that is also type LISTPOINTER. The above declaration is circular in that the record type LI STNODE appears in the declaration of LISTPOINTER; similarly, the pointer type LISTPOINTER appears in the declaration of LISTNODE. Pascal requires the pointer type to be declared first. Creating a List Let us see how we might create the list described at the start of Section 10.3. First of all, we must have some way of referencing the list. This is usually done by establishing a pointer to the list head. We will declare HEAD, Q and R as variables of type LISTPOINTER and use HEAD as the pointer to the list head. var HEAD, Q, R : LISTPOINTERi 10.4 MANIPULATING LINKED LISTS USING POINTER VARIABLES 483 In the discussion below, each statement that defines a pointer has a number comment. This comment identifies the pointer in a diagram. The statements III NEW(HEAD); HEADA.WORD := 'ACE'; define the WORD field of a new list element referenced by pointer HEAD. HEAD~ The LINK field of this element must point to the next element of our list. The statements 121 NEW(Q); 131 HEADA.LINK := Q; have the effect shown below. HEAD Q As indicated, a new element is created that is pointed to by Q. The value of Q is then copied into the link field of our first node 131 thereby connecting the two elements. The sequence of statements QA.WORD := 'BOY' ; 141 NEW(R) ; lSI QA.LINK := R; RA.WORD := 'CAT' ; completes the linked list. The first statement copies 'BOY' into the WORD field of the second element. The next statement 14 I creates a third element pointed to by R. This element is then joined to the second 151, and the value of its WORD field is defined as 'CAT I • The new data structure is shown below. The only thing left to do is to indicate that the element pointed to by R is, in fact, the last element of the list and points to no other. This is accomplished by the statement 484 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES RA.LINK := NIL The reserved word NIL is a predefined constant in Pascal that is used to designate the end of a list. The extra pointers, Q and R, in the list above may be ignored. The final list is shown below. Obviously, we do not want to go through this process each time we create a new linked list. Hence, we will write a procedure to do this for us later. Traversing a list In many list processing operations, each node in the list must be processed in sequence; this is called traversing a list. In order to traverse a list, we must start at the list head and follow the list pointers. This is illustrated in the next two examples. Example 10.3 Procedure PRINTLIST in Fig. 10.3 displays the WORD fields of each node in a list starting with the node pointed to by HEAD. Consequently, PRINTLIST may be used to print the words stored in our sample list. procedure PRINTLIST (HEAD (inputl : LISTPOINTER)i (Prints out the list pointed to by HEAD. I begin (Traverse the list until the end is reached. I while HEAD NIL do begin WRITELN (HEADA.WORD): (print the node valuel HEAD := HEADA.LINK (advance to next nodel end (while I e nd , (PRINTLISTI Fig. 10.3 Procedure PRINTLIST For our original sample list, the output of PRINTLIST would be ACE BOY CAT The statement HEAD := HEADA.LINK (advance to next nodel advances the pointer HEAD to the next list element, which is pointed to by the LINK field of the current list element. The while loop is exited when 10.4 MANIPULATING LINKED LISTS USING POINTER VARIABLES 485 HEAD becomes NIL. Since HEAD is a value parameter. a local copy of the pointer to the first list element is established when the procedure is entered. This local pointer is updated; however. the corresponding pointer in the calling program remains unchanged. Example 10.4 Algorithm for List Search List processing operations can be formulated very naturally using recursion. As an example. we will consider the problem of searching a list to find a string TARGET. The result will be a pointer to the list element containing TARGET or NIL if TARGET is not found. One stopping state would be an empty list; in this case the TARGET cannot be present. The other stopping state would be finding TARGET at the head of the list. The recursion step is to search the rest of the list (excluding the current list head) for TARGET. This algorithm is summarized below; function SEARCH is shown in Fig. 10.4. 1. if the list is empty then 2. TARGET is not present. else if TARGET is in the list head then 3. The result is a pointer to the list head. else 4. Search for TARGET in the rest of the list. function SEARCH (HEAD : LISTPOINTER; TARGET : STRING) : LISTPOINTER; (Searches a list for a specified TARGET string. Returns a pointer to TARGET if found. Returns NIL if TARGET is not in the list. begin (SEARCHl if HEAD = NIL then SEARCH := NIL (empty list-TARGET not foundl else if HEADA.WORD = TARGET then SEARCH := HEAD (TARGET is in HEADl else SEARCH := SEARCH(HEADA.LINK, TARGET) (search rest of listl end; (SEARCHl Fig. 10.4 Function SEARCH As indicated by the function header. a pointer value may be returned as a function result. In the recursive step SEARCH := SEARCH(HEADA.LINK, TARGET) (search rest of listl the function SEARCH is called again to search the rest of the list that is pointed to by HEADA. LINK. Eventually. a stopping state will be reached and a value will be assigned to the function identifier. The value returned from a lower level call is not modified; it is simply passed up as the function result. A trace of 486 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES P := SEARCH(HEAD, 'BOY') is shown in Fig. 10.5 for our sample list I ACE I , I BOY I , 'CAT I . Since the TARGET string 'BOY' is in the second list element, there is one recursive call to SEARCH after the original function call. The result, as desired, is a pointer to the node containing the string I BOY' . The address of this node is saved in pointer variable P. P : = SEARCH(HEAD, I BOY I ) Result is a pointer to I BOY I Result is a pointer to I BOY' Fig. 10.5 Trace of P:= SEARCH(HEAD, 'BOY') PROGRAM STYLE Testing for an empty list The order of evaluation of the terminating conditions in Fig. 10.4 is very important. The value of HEADA• WORD is not defined if the list is empty [HEAD is NIL); consequently, the terminating condition HEAD = NIL must be evaluated before HEADA. WORD = TARGET. In all list processing operations, you must make sure that your program does not attempt to reference a field pointed to by NIL. This illegal reference to undefined data is a very common error. Self-check Exercises for Section 10.4 1. Write procedure PRINTLIST as a recursive procedure. 2. Write an iterative version of function SEARCH. 3. Write a recursive function that finds the length of a list. • Case Study-Maintaining a Linked List We stated earlier that lists are very flexible data structures and can easily be modified. In this section we will show how to keep a list up to date and in alphabetical order while performing list insertions and deletions. 10.5 CASE STUDY-MAINTAINING A LINKED LIST 487 Maintaining a Linked List Problem: We wish to maintain a data base that contains up-to-date information about the passengers on a particular airline flight. The passenger data at the start of each day is available on a disk file. In order to be able to process new data rapidly, we would like to transfer the passenger data into main memory, process the changes that occur during the day by modifying the passenger data in main memory, and save the updated passenger data in a new disk file. Both the original passenger file and the new passenger file should be in alphabetical order by passenger name. Discussion: Since the list of passengers on an airline flight is changed frequently, a linked list is a good choice for an internal data structure. We will create a linked list by reading the passenger data from an external file. This linked list will be updated during the day as new data are entered. At the end of the day, each record stored in the linked list will be copied to another external file. We will need to provide procedures that create the original linked list, copy this list to an external file, and perform whatever updates may be required. For now, we will assume that the update operations consist of deleting passengers from the list and inserting new passenger records. We also want to be able to display the record of a particular passenger or print the entire passenger list. The data for each passenger will be stored in a record of type PASSENGER as described below. type STRING = packed array [l •• STRINGSIZE] of CHAR; PASSENGER = record NAME : STRING; CLASS: (ECONOMY, FIRSTCLASS); NUMSEATS : 1 •• MAXSEATS end; IPASSENGERl Each list element will contain a passenger record as described above (field PASS INFO) and a pointer (field LINK) to the next passenger record in the list. Irest of type declarationsl PASSPOINTER = APASSNODE; PASSNODE = record PASSINFO : PASSENGER; LINK : PASSPOINTER end; IPASSNODEl An entire record of type PASSENGER can be stored in a record of type PASSNODE. Assuming NEXT is type PASSPOINTER and ONEPASS is type PASSENGER, the statements NEW (NEXT); NEXTA.PASSINFO := ONEPASS 488 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES copy the record variable ONEPASS into the PASS INFO field of the new node pointed to by NEXT. To simplify the list processing operations, we will assume that the passenger file always begins with a record whose NAME field is 'AA ••• A ' and always ends with a record whose NAME field is 'Z Z ••• Z ' . The reason for these dummy elements will be discussed later. An empty passenger list will contain only these two elements, as shown below. H_____. An empty passenger list The problem inputs and outputs and algorithm follow. the file of passenger records in alphabetical order by NAME field beginning with I AA ••• A' and ending with 'z Z ••• Z ' . (PASSFILE : FLIGHTFILE) the updated file of passengers [NEWPASSFILE : FLIGHTFILE) Algorithm 1. Create a linked list corresponding to the (PASSFILE). 2. Process each update request. original passenger file 3. Copy the passenger records in the updated list to a new passenger file [NEWPASSFILE). Procedure CREATELIST performs step 1 and is described next. Procedure COPYLIST performs step 3 and is based on procedure PRINTLIST shown earlier (see Fig. 10.3). To perform step 2, we must first print a menu of update choices and then call a procedure to read each choice and perform it. We will call procedures PRINTMENU and MODLIST, respectively, to perform these tasks. The structure chart is shown in Fig. 10.6; the main program and COPYLIST are shown in Fig. 10.7. Procedure CREATELIST must allocate a new node for storage of each passenger record and then read the passenger data into that node. It should return a pointer, HEAD, to the first passenger record (NAME field , AA ••• A'). The procedure inputs, outputs, and algorithm follow. the file of passenger data in alphabetical order by NAME field beginning with 'AA ••• A' and ending with 'Z Z ••• Z ' . (PASSFILE : FLIGHTFILE) (continued on p. 491) 10.5 CASE STUDY-MAINTAINING A LINKED LIST 489 I PASSFILE ~ t I HEAD HEAD ~ I CREATELIST PRINTMENU t I I ~ CHOICE HEAD MODLIST t NEWPASSFILE I COPYLIST Fig. 10.6 Structure Chart for Passenger List Problem program MAINTAIN (PASSFILE, NEWPASSFILE, INPUT, OUTPUT); lstores the data in file PASSFILE in a linked list and updates the linked list by performing insertions and deletions. When done, copies the records in the linked list to file NEWPASSFILE.! const DONE = 5; MAXSEATS = 350; STRINGSIZE = 10; lfinished list updatel lnumber of seats in airplanel lmaximum length of a stringl type STRING = packed array [l •. STRINGSIZE] of CHAR; PASSENGER = record leach passenger recordl NAME : STRING; CLASS: (ECONOMY, FIRSTCLASS); NUMSEATS : 1 .. MAXSEATS end; IPASSENGERl FLIGHTFILE = file of PASSENGER; lfile of passenger recordsl PASSPOINTER = APASSNODE; PASSNODE = record PASSINFO : PASSENGER; LINK : PASSPOINTER end; IPASSNODEl leach list elementl var HEAD : PASSPOINTER; PASSFILE, NEWPASSFILE : FLIGHTFILE; CHOICE : INTEGER; lpointer to head of listl lold and new filesl loption selectedl procedure COPYLIST (HEAD linputl : PASSPOINTER; var NEWPASSFILE loutputl : FLIGHTFILE); ICopies each node of the list pointed to by HEAD to NEWPASSFILE.l begin ICOPYLISTl REWRITE (NEWPASSFILE); 490 lprepare NEWPASSFILE for outputl POINTER VARIABLES AND DYNAMIC DATA STRUCTURES while HEAD NIL do begin WRITE (NEWPASSFILE, HEADA.PASSINFO); HEAD := HEADA.LINK end [wh i Le] end; 1COPYLISTI lcopy current nodel ladvance to next nodel lInsert procedures CREATELIST, PRINTMENU, MODLIST here.l begin lRead the passenger data from PASSFILE into the linked list.l CREATELIST (PASSFILE, HEAD); lProcess each update request. I repeat PRINTMENU; MODLIST (HEAD, CHOICE) until CHOICE = DONE; ldisplay the option) lread and perform user's choicel lCopy each passenger record from the linked list to NEWPASSFILE.1 COPYLIST (HEAD, NEWPASSFILE) end. 1MAINTAIN I Fig. 10.7 Main Program and COPYL/5T a pointer to the list head (HEAD : PASSPOINTER) a pointer to the last list node (LAST Algorithm for CREATELIST PASSPOINTER) 1. Prepare PASSFILE for input. 2. Allocate a node for storage of the first list element, point HEAD to this node, and read the first record into it. 3. Initialize the pointer to the last list node (LAST) to HEAD. 4. while there are more passenger records do 5. Attach a new node to the end of the list and read the next pas- senger's data into it. 6. Reset LAST to point to the new node. In step 2, the pointer HEAD is set to point to the first node that is allocated and the first passenger record is read into this node. The local pointer variable LAST always points to the current end of the list. In step 5, a new node is allocated and attached to the current end of the list; the next passenger's data are read into the new node. Procedure CREATENODE is called to perform steps 2 and 5; procedure CREATELIST is shown in Fig. 10.8. 10.5 CASE STUDY-MAINTAINING A LINKED LIST 491 procedure CREATELIST (var PASSFILE linputl : FLIGHTFILEi var HEAD loutputl : PASSPOINTER)i IReads each passenger record from PASSFILE into a linked list. The pointer HEAD is set to point to the first list node. I var LAST : PASSPOINTERi lpointer to last list nodel procedure CREATE NODE (var PASSFILE linputl : FLIGHTFILEi var NEXT loutputl : PASSPOINTER)i IAllocates a new node that is pointed to by NEXT for storage of the next passenger's data. Reads the data from PASSFILE. I begin ICREATE NODE I III NEW (NEXT) i READ (PASSFILE, NEXTA.PASSINFO)i 12INEXTA.LINK := NIL endi ICREATENODEI lpoint NEXT to a new nodel lsave the data in new nodel lset LINK field of new node to NILI begin ICREATELISTI RESET (PASSFILE)i CREATENODE (PASSFILE, HEAD)i lprepare PASSFILE for inputl lpoint HEAD to the first recordl IRead each record and add it to the end of the list.l LAST := HEADi linitialize last node to list while not EOF(PASSFILE) do begin CREATENODE (PASSFILE, LASTA.LINK)i lattach a new to the last 13lLAST := LASTA.LINK lmake the new node the last end [wh i Le ] endi ICREATELISTI headl node nodel nodel Fig. 10.8 Procedures CREATELIST and CREATENODE In CREATENODE, the statement lpoint NEXT to a new nodel IIINEW (NEXT) i allocates a new node and points the parameter represented by NEXT to this node. The first statement below READ (PASSFILE, NEXTA.PASSINFO)i Isave the data in new nodel 12INEXTA.LINK := NIL Iset LINK field of new node to NILI reads the next record from file PASSFILE into the record NEXTA. PASS INFO, thereby defining the PASSINFO field of the new node. Statement 121 initializes the LINK field of each new node to NIL. In CREATELIST, the procedure (call) statement CREATE NODE (PASSFILE, HEAD) 492 i [po i.nt; HEAD to the first recordl POINTER VARIABLES AND DYNAMIC DATA STRUCTURES creates the list head and reads the first passenger record (name I AA ••• A ') into it. Within the while loop, the first statement below CREATE NODE (PASSFILE, LASTA.LINK); l3lLAST := LASTA.LINK lattach a new node to the last nodel lmake the new node the last nodel calls CREATENODE to attach a new node to the current last node; the next passenger's data are read into the new node. Then statement l31 advances LAST to point to the new list node. The last node attached before CREATELIST is exited will have a NAME field of I ZZ ••• Z I and a link field of NIL. The process of adding a new node to the end of the list is illustrated below. The current last node contains passenger I ALPHARD I and passenger I ATKINSON I is being added. The blue lines show the new pointer values; the grey lines show the original values of pointers that are changed. The comments identify the statement in Fig. 10.8 that caused the change. Procedure PRINTMENU simply prints out the menu of update choices (l-insert, 2-delete, 3-print passenger, 4-print passenger list, 5-quit) and is not shown. Procedure MODLIST reads the user's choice and attempts to process it. The data requirements and algorithm for MODLIST are shown below. a pointer to the head of the passenger list (HEAD : PASSPOINTER) the update operation selected (CHOICE : INTEGER) the passenger data to be inserted (NEWPASS : PASSENGER) the name of a passenger to be processed (TARGET : STRING) the length of the passenger's name (LENGTH : INTEGER) a pointer to a particular node in the list (TARGPOINT : PASSPOINTER) 10.5 CASE STUDY-MAINTAINING A LINKED LIST 493 a BOOLEAN flag indicating whether or not a passenger was deleted (DELETED : BOOLEAN) Algorithm for MODLIST 1. Read the user's update choice into CHOICE. 2. case CHOICE of 1: Read the new passenger data into NEWPASS. Insert NEWPASS in the list. 2: Read the name of the passenger to be deleted into TARGET. Delete the designated passenger from the list. . 3: Read the name of the passenger to be displayed into TARGET. Find the passenger and display the passenger's data. 4: Traverse the passenger list and print each passenger's data. 5: Do nothing The structure chart for MODLIST is shown in Fig. 10.9. The procedure is shown in Fig. 10.10. MODLIST t I NEWPASS HEAD, I HEAD, TARGET NEWPASS -!t -!t t I DELETED HEAD, TARGET -!t DELETE READ1PASS t INSERT TARGET, LENGTH I SEARCHPASS I TARGPOINT HEAD -!t -!t PRINT1PASS READSTRING Fig. 10.9 Structure Chart for PRINTPASSLIST MOD LIST procedure MODLIST (HEAD [inputl : PASSPOINTER; var CHOICE [outputl : INTEGER); [Reads each update choice (CHOICE) and performs it.1 var TARGPOINT : PASSPOINTER; NEWPASS : PASSENGER; 494 [pointer to a target node I [a passenger recordl POINTER VARIABLES AND DYNAMIC DATA STRUCTURES t I TARGPOINT TARGET : STRING; LENGTH : INTEGER; DELETED : BOOLEAN; !a passenger name! !length of a name I IBOOLEAN f Laq] !Insert READSTRING, READ1PASS, PRINT1PASS here.1 !Insert SEARCHPASS, PRINTPASSLIST, INSERT, DELETE here.) begin !MODLIST) WRITE ('Select an option 1 through 5: '); READLN (CHOICE); if CHOICE in [1 •• 5] then case CHOICE of 1: begin WRITELN ('Enter the data for the new passenger.'); READ1PASS (NEWPASS); !read new passengerl INSERT (HEADA.LINK, NEWPASS, HEAD) !insert in list) end; !ll 2: begin WRITE ('Enter name of passenger to delete: '); READSTRING (TARGET, LENGTH); DELETE (HEADA.LINK, TARGET, HEAD, DELETED); if not DELETED then WRITELN (TARGET : LENGTH , ' not found.') end; (2) 3 : begin WRITE ('Enter name of passenger to display: ') ; READSTRING (TARGET, LENGTH); TARGPOINT := SEARCHPASS(HEAD, TARGET); if TARGPOINT = NIL then WRITELN (TARGET, ' not found.') else PRINT1PASS (TARGPOINTA.PASSINFO) !show the da ta ) end; 131 4: begin WRITELN ('CURRENT PASSENGER LIST'); WRITELN ('Name' :10, 'Seats' :10, 'Class' :10); PRINTPASSLIST (HEAD) end; !41 5: WRITELN ('Passenger list update complete for today.') end [case] end; !MODLISTI Fig. 10.10 Procedure MODLIST Procedure MODLIST consists of a long case statement. Each case label implements a different option. Working backwards, option 5 simply prints a message and returns. Option 4 calls procedure PRINTPASSLIST (similar to procedure PRINTLIST in Fig. 10.3) to echo print each passenger's data. Option 3 reads a passenger's name into TARGET and then calls function SEARCHPASS (similar to function SEARCH in Fig. 10.4) to set TARGPOINT to point to the record containing this passenger's data. Procedure PRINT1PASS is then called to display the passenger information. All of these procedures are similar to earlier procedures and are left as exercises. 10.5 CASE STUDY -MAINTAINING A LINKED LIST 495 We will discuss cases 1 and 2 next. In case 1, insert a new passenger, procedure READ1PASS is first called to read the passenger's data from the keyboard. We have written many similar procedures already. Procedure INSERT is then called to insert this passenger's data where it belongs in the list. In case 2, delete a passenger, procedure READSTRING is called to read the name of the passenger to be deleted. Procedure DELETE is called to delete the corresponding passenger record from the list. If the passenger to be deleted is not in the list. an error message is printed after returning from DELETE. We will write procedures DELETE and INSERT in the next sections. Deleting a List Node We stated earlier that deleting a list node is simply a matter of changing a single pointer value. The LINK field of the predecessor of the node being deleted must be reset to point to the successor of the node being deleted. A recursive algorithm for deleting a node follows. Algorithm for DELETE 1. If the list is empty then 2. TARGET cannot be deleted. else if TARGET is in the list head then 3. Delete the list head. else 4. Delete TARGET from the rest of the list. Fig. 10.11 Procedure DELETE procedure DELETE (NEXT linputl : PASSPOINTER; TARGET Iinput) : STRING; PRED linputl : PASSPOINTER; var DELETED loutput} : BOOLEAN): IDeletes the passenger with name TARGET from the list pointed to by NEXT. The predecessor of the list head is pointed to by PRED. DELETED is a flag that is set to indicate whether or not the deletion is performed (DELETED is TRUE if performed). begin IDELETEl if NEXT = NIL then DELETED := FALSE lempty list-TARGET not foundl else if NEXTA.PASSINFO.WORD = TARGET then begin IllPREDA.LINK ;= NEXTA.LINK; Ireset LINK field of predecessor} DELETED ;= TRUE: Iset flag to indicate deletionl DISPOSE (NEXT) Ireturn node to storage pool} end else DELETE (NEXTA.LINK, TARGET, NEXT, DELETED) Itry rest of listl end; IDELETE} 496 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES Procedure DELETE is shown in Fig. 10.11. The parameter NEXT represents a pointer to the head of the list being searched; the parameter PRED represents a pointer to the predecessor of the list head. The BOOLEAN parameter DELETED is used to signal that the TARGET was found and removed from the list (DELETED set TRUE) or that the TARGET was not found (DELETED set FALSE). The assignment statement IljPREDA.LINK := NEXTA.LINK; Ireset LINK field of predecessorj performs the list deletion by changing the LINK field of the predecessor of node NEXT to point to the successor of node NEXT. The statement DISPOSE (NEXT) returns the memory cells allocated to the node pointed to by NEXT to the storage pool. If the TARGET string is not found, the recursive step DELETE (NEXTA.LINK, TARGET, NEXT, DELETED) [try rest of list 1 is used to search the rest of the list for TARGET. The current head (pointed to by NEXT) becomes the predecessor; the current second element (pointed to by NEXTA. L INK) becomes the new list head. The search is terminated when the end of the list is reached. For the original procedure (call) statement DELETE (HEADA.LINK, NEWPASS, HEAD, DELETED); the first actual list element is pointed to by NEXT and the dummy node with NAME field 'AA •• A' is pointed to by PRED as shown below. PRED NEXT [11 If the string in TARGET is 'ALPHARD', the value of PREDA. LINK would be changed as shown by the blue arrow labeled 11J; otherwise. the recursive step would cause PRED and NEXT to advance down the list. The original value of PREDA. LINK is shown by the grey arrow. Note that the value of PREDA. L INK can be changed even though PRED is a value parameter. 10.5 CASE STUDY-MAINTAINING A LINKED LIST 497 Without the dummy element at the head of the list there would be no predecessor to the first actual element. Consequently, the algorithm as shown could not be used because the deletion of the first actual element would have to be treated as a special case. DISPOSE STATEMENT DISPOSE tpotnteri Interpretation: The memory space allocated to the node pointed to by pointer is returned to the storage pool and may be reallocated later. Note: It is an error to perform the DISPOSE operation when the value of pointer is NIL or undefined. Inserting a Node in a List We stated earlier that it was relatively easy to insert a new node in a list. We must locate the first node that alphabetically follows the new node (the successor of the new node). The LINK field of the new node must be set to point to its successor; the LINK field of the new node's predecessor should be changed to point to the new node. The insertion algorithm is written below using recursion to search the list for the correct position of the new passenger. Step 2 assumes that there cannot be two passenger's with the same NAME field. If the new passenger's name matches a name already in the list, then that record is updated with the new data. Step 3 inserts a new node between two existing nodes. Step 4 is the recursive step and is executed until one of the two stopping conditions becomes true. The second stopping condition must eventually be true (i.e. 'Z Z••• Z' follows all actual passenger names). Algorithm for INSERT 1. if the name at the list head matches the new passenger's then 2. Replace the passenger's data with the new data. else if the name at the list head follows the new name then 3. Insert the new passenger just before the list head. else 4. Insert the new passenger in the rest of the list. Procedure INSERT is shown in Fig. 10.12. The parameter NEXT represents a pointer to the head of the list being searched; the parameter PRED represents a pointer to the predecessor of the list head. procedure INSERT (NEXT linputl : PASSPOINTERj NEWPASS [input) : PASSENGER; PRED linputl : PASSPOINTER)j [Inserts a new passenger (NEWPASS) in the list pointed to by NEXT. The predecessor of the list head is pointed to by PRED. I 498 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES var TEMP : PASSPOINTER; la temporary pointerl begin IINSERTI if NEXTA.PASSINFO.NAME = NEWPASS.NAME then NEXTA.PASSINFO := NEWPASS else if NEXTA.PASSINFO.NAME > NEWPASS.NAME then begin [Lrise r t ] IllNEW (TEMP); lallocate a new nodel TEMpA.PASSINFO := NEWPASS; Istore new passenger datal 12lTEMPA.LINK := NEXT; Ijoin new node to successorl (3)PREDA.LINK := TEMP Ijoin new node to predecessorl end Iinsert) else INSERT (NEXT~.LINK, NEWPASS, NEXT) linsert in rest of listl end; I INSERT I Fig. 10.12 Procedure INSERT In Fig. 10.12, the statements IllNEW (TEMP); TEMP~.PASSINFO := NEWPASS; [a Ll.ooa t.e a new node] Istore new passenger data] allocate a new node that is pointed to by the local pointer variable TEMP. Next, the new passenger data (stored in record NEWPASS) is copied into the PASS INFO field of this new node. The assignment statements (2)TEMP~.LINK (3)PRED~.LINK := NEXT; := TEMP Ijoin new node to successor) Ijoin new node to predecessor) insert the new node in the list. If the original list is in alphabetical order, then so must the new list because all insertions maintain the alphabetical ordering. For the original procedure (call) statement INSERT (HEADA.LINK, NEWPASS, HEAD) linsert in listl the first actual list element is pointed to by NEXT and the dummy node with NAME field 'AA •• A' is pointed to by PRED. Fig. 10.13 illustrates the insertion of a new first passenger, I ARNOLD I • The new pointer values are shown as blue arrows; the original values of pointers that are changed appear as grey arrows. Again, the inclusion of the dummy first element allows us to use this algorithm to insert a node at the head of the actual passenger list. 10.5 CASE STUDY-MAINTAINING A LINKED LIST 499 PRED NEXT Fig. 10.13 Inserting Passenger 'ARNOLD' Self-check Exercises for Section 10.5 1. Write procedures READ1PASS, PRINTPASSLIST, and PRINT1PASS called in Fig. 10.10. PRINTPASSLIST should use procedure PRINT lPASS. • Stacks and Queues In this section we will discuss two kinds of linked lists that find wide application in the design of compilers and operating systems, stacks and queues. We introduced stacks in Section 9.1 and described their role in implementing recursion. A stack may be thought of as a linked list in which each new node is inserted at the head of the list and each deletion removes the current head of the list. Inserting a node is a push operation and deleting a node is popping the stack. We might also want to determine whether a stack is empty (i.e, has no elements) or examine the element currently on top of the stack. The latter operation is easy since the top of the stack is always pointed to by the list head pointer. A stack created by inserting the character values 12 I , I + I , I C I , I * I in that order is shown below. TOP The character 1*' is at the top of the stack. If each character is stored in a field named DATA, then the top of the stack is referenced as TOP". DATA. The element at the top of the stack is the last element placed on the stack and is the first one that will be removed. For this reason a stack is sometimes called a LIFO [Last In First Out) list. The character value 500 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES , 2' is at the bottom of the stack and will be the last one removed; its pointer value is NIL. Example 10.5 Procedure PUSH in Fig. 10.14 is used to push a new value (type CHAR) onto a stack. We are assuming the following declarations. type STACKPOINTER = ASTACKNODE: STACKNODE = record DATA : CHAR: LINK : STACKPOINTER end: ISTACKNODEj procedure PUSH (NEXTCHAR linput] : CHAR: var TOP loutputj : STACKPOINTER): IPushes the data stored in NEXTCHAR onto the top of the stack pointed to by TOP. j var TEMP : STACKPOINTER: begin IPUSHj Ilj NEW (TEMP): TEMpA.DATA := NEXTCHAR: {2jTEMpA.LINK := TOP: 13jTOP : = TEMP end: IPUSHj [Loca L pointerj Ipoint TEMP to a new nodej lsave the next characterl Iconnect it to old topj Iredefine top of the stackj Fig. 10.14 Procedure PUSH The stack of characters is redrawn below after execution of the procedure (call) statement PUSH (I x', TOP) The character value 'X I is the new top of the stack. The value of TOP before the push operation is shown by the grey arrow. TEMP ~1j ~~ Example 10.6 Procedure POP in Fig. 10.15 returns the top of the stack pointed to by TOP. The pointer TOP is reset to point to the current second element that becomes the new top of the stack. The BOOLEAN function EMPTYSTACK is called by POP to determine whether the stack is currently empty 10.6 STACKS AND QUEUES 501 (EMPTYSTACK returns TRUE). An error message is printed if procedure POP is called when the stack is empty. function EMPTYSTACK (TOP: STACKPOINTER) : BOOLEAN; !Returns TRUE if the stack pointed to by TOP is empty.j begin !EMPTYSTACKj EMPTYSTACK := TOP = NIL end; !EMPTYSTACKJ procedure POP (var ITEM !outputj : CHAR; var TOP !input/outputj : STACKPOINTER); \Pops the top of the stack pointed to by TOP. ITEM is assigned the current top item. TOP is reset to point to the current second item. An error message is printed if the stack is empty. Calls function EMPTYSTACK. begin !POPj if EMPTYSTACK(TOP) then WRITELN ('Stack underflow error.') else begin ITEM := TapA. DATA; TOP := TOpA.LINK end end; !POPj !stack is emptyj !get ITEMj [re se t; TOPj Fig. 10.15 Procedure POP Example 10.7 The program in Fig. 10.16 reads a sequence of characters ending with '#' and echo prints the string in reverse order. The line PALINDROME#EMORDNILAP appears on the screen when the characters in blue are entered. Fig. 10.16 Using a Stack to Print Cbaracters Backwards program USESTACK (INPUT, OUTPUT); !Uses a stack of characters to print out a data string backwards.j const SENTINEL = '#'; !sentinel characterj type STACKPOINTER = ASTACKNODE; STACKNODE = record DATA : CHAR; LINK : STACKPOINTER end; !STACKNODE j 502 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES var TOP : STACKPOINTER; NEXTCHAR : CHAR; lpointer to stack topj [next; characterj lInsert function EMPTYSTACK here.j lInsert procedures PUSH and POP here.j begin lUSESTACKj TOP := NIL; lPush each input character onto the stack.j READ (NEXTCHAR); while NEXTCHAR SENTINEL do begin PUSH (NEXTCHAR, TOP); READ (NEXTCHAR) end; [whi.Le ] lPop each character and. display it.j while not EMPTYSTACK(TOP) do begin WRITE (NEXTCHAR); POP (NEXTCHAR, TOP) end; [wh i l.e ] WRITELN end. lUSESTACKj linitially stack is emptyj 1push next character j lprint last item poppedj [pop the stackj Queues A queue is a linked list used to model things such as a line of customers waiting at a checkout counter or a stream of jobs waiting to be printed by a line printer in a. computer center. In a queue. all insertions are done at one end (the rear of the queue) and all deletions are made from the other end (the front of the queue). A queue of three passengers on a waiting list for an airline flight is shown below. The name of the passenger who has been waiting the longest is I BROWN' (pointed to by FRONT); the name of the most recent arrival is I CARSON I (pointed to by REAR). The passenger pointed to by FRONT will be the first one removed. Since this is also the passenger who has been waiting the longest, a queue is sometimes called a FIFO (First In First Out) list. The last passenger who will be removed is the one pointed to by REAR. The pointer field of this passenger's node contains NIL. Note that the passengers above are listed in order of arrival into the queue rather than in alphabetical order. If an opening occurs on the flight, then passenger I BROWN' will be removed from the queue and inserted into the flight list, and FRONT will be reset to point to passenger 'WATSON' . If another passenger is added to the waiting list, the new passenger 10.6 STACKS AND QUEUES 503 will be linked to passenger 'CARSON'. and REAR will be reset to point to the new passenger. Example 10.8 Procedure ENQUEUE in Fig. 10.17 is used to add a new passenger (NEWPASS) to a waiting list of passengers assuming the declarations shown in Section 10.5. The pointer REAR is reset to point to the new passenger's data. The BOOLEAN function EMPTYQUEUE is used to test whether the queue was empty just prior to the insertion (EMPTYQUEUE returns TRUE). If so, FRONT is also reset to point to the pew passenger since there is only one passenger in the queue. function EMPTYQUEUE (FRONT : PASSPOINTER) : BOOLEAN: lReturns TRUE if the queue pointed to by FRONT is empty.j begin lEMPTYQUEUEj EMPTYQUEUE := FRONT end: lEMPTYQUEUEj = NIL procedure ENQUEUE (NEWPASS linputl : PASSENGER: var FRONT, REAR linput/outputl : PASSPOINTER): lInserts the passenger data stored in NEWPASS in the queue. REAR is reset to point to the new passenger. If the queue is empty, FRONT is assigned the same value as REAR. Calls EMPTYQUEUE. var TEMP PASSPOINTER: ltemporary pointerj begin lljNEW (TEMP): TEMpA.PASSINFO := NEWPASS: \2jREARA.LINK := TEMP: l3jTEMpA.LINK := NIL: l4jREAR : = TEMP if EMPTYQUEUE(FRONT) then FRONT := REAR end: lENQUEUEj lallocate a new lstore new passenger \attach new node to old end of lnew node is the new end of lreset REAR to new nodej dataj listj listj nodej lsingle element queuej Fig. 10.17 Procedure ENQUEUE The queue is shown in Fig. 10.18 after passenger 'MCMANN' has been added to the waiting list. The original values of pointers that are changed appear as grey arrows. Example 10.9 504 Procedure DEQUEUE in Fig. 10.19 is used to remove from the queue the passenger who has been waiting the longest (pointed to by FRONT). FRONT is reset to point to the passenger who has been waiting the second longest amount of time. If there is only one passenger in the queue when DEQUEUE is called, the queue becomes empty and FRONT and REAR are POINTER VARIABLES AND DYNAMIC DATA STRUCTURES 131 Fig. 10.18 Adding a Passenger to a Queue reset to NIL. An error message is printed if the queue is empty when DEQUEUE is called. procedure DEQUEUE (var NEXTPASS linput/outputj : PASSENGER; var FRONT, REAR linput/outputj : PASSPOINTER); lAssigns to NEXTPASS the passenger record pointed to be FRONT. Resets FRONT to point to the next passenger at the front of the list. If the queue is initially empty, an error message is printed. If the queue becomes empty, sets both FRONT and REAR to NIL. Calls EMPTYQUEUE. beg in 1DEQUEUE j if EMPTYQUEUE(FRONT) then WRITELN ('Queue underflow error. ') lqueue is already else begin [r'emove] lremove passenger at NEXTPASS := FRONTA.PASSINFO; ladvance next passenger to llJFRONT := FRONTALINK; if EMPTYQUEUE(FRONT) then REAR := NIL lqueue becomes end 1remove j end; I DEQUEUE j emptyj frontj front} emptYl Fig. 10.19 Procedure DEQUEUE The queue is shown below after deletion of the passenger at the front of the queue. Passenger' WATSON' is now at the front of the queue. The new value of FRONT is shown by the blue arrow; the original value is shown by the grey arrow. A main program should initialize pointers FRONT and REAR to NIL before any insertions or deletions are performed on the queue. The first call to procedure ENQUEUE will insert a new node in the queue, resetting both FRONT and REAR to point to this node. 10.6 STACKS AND QUEUES 505 FRONT Fig. 10.20 Deleting a Passenger from a Queue Self-check Exercises for Section 10.6 1. Draw the stack for Fig. 10.16 after the last push operation is performed. Use the data string HELLO#. Answer this question assuming the string is stored in a queue instead of a stack. 2. Modify POP and DEQUEUE so that the node removed is returned to the storage pool. Use DISPOSE. 3. Discuss how to implement a stack using an array. 4. Discuss how to implement a queue using an array. • Multiple-linked Lists and Trees All the examples seen so far have involved list elements or nodes with a single pointer field. It is possible to have lists of elements with more than one link. For example, each element in the list shown below has a forward pointer that points to the next list element and a backward pointer that points to the previous list element. This allows us to traverse the list in either the left or right direction. This structure is called a doubly linked list. The statements below declare a list element of this general form. type LINK = AMULTINODE; MULTINODE = record :} data fields LEFT, RIGHT: LINK end; !MULTINODEj Introduction to Trees A special kind of multiple-linked list that has wide applicability in computer science is a data structure called a binary tree. A sample tree is drawn in Fig. 10.21. 506 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES ROOT Fig. 10.21 A Sample Tree Trees in computer science actually grow from the top down rather than from the ground up. The topmost element is called the root of the tree. The pointer, ROOT, points to the root of the tree drawn in Fig. 10.21. Each tree node shown has a single data field and two pointer fields called the left branch and right branch, respectively. Any node with both pointer fields equal to NIL is called a leaf. The node containing the string 'HEN' is the parent of the nodes containing the strings 'HAT' and 'HOG I . Similarly, the nodes 'HAT' and , HOG' are siblings since they are both children of the same parent node. The root of the tree is an ancestor of all other nodes in the tree and they, in turn, are all descendants of the root node. Each node in a tree may be thought of as the root node of its own subtree. Since each node has two branches, it spawns two subtrees, a left subtree and a right subtree. Its left child is the root node of the left subtree, and its right child is the root node of the right subtree. The statements below describe the form of a tree node. type STRING = packed array [1 .. 3] of CHAR; BRANCH = "TREE; TREE = RECORD WORD : STRING; LEFT, RIGHT: BRANCH end; [TREEj Trees may be used for representing expressions in memory. For example, the expression (X + Y) * (A - B) could be represented as the tree drawn in Fig. 10.22. The root node contains the operator (*) that is evaluated last. Each subtree that is itself an expression has an operator in its root node. The left subtree of the root node represents the expression (X + Y}: the right subtree represents the expression (A - B). 10.7 MULTIPLE-LINKED LISTS AND TREES 507 Fig. 10.22 Tree Form of Expression (X+Y) • (A-B) Trees are also used to organize related data items as a hierarchical data structure in order to facilitate efficient search and retrieval for a desired item. For example, the binary search tree shown in Fig. 10.21 is arranged so that the left descendent of each node alphabetically precedes its parent and the right descendant alphabetically follows its parent. Hence, in searching for a particular key at any level of this tree, the left branch should be followed if the key value is "less than" the current node value, and the right branch should be followed if the key value is "greater than" the current node value. (What if the key value equals the current node value?) This effectively reduces the search space by a factor of two each time since all the descendants (children and grandchildren) in the branch not chosen are ignored. Traversing a Tree In order to process the data stored in a tree, we need to be able to traverse the tree, or visit each and every node in a systematic way. The first approach that will be illustrated is called an inorder traversal. The algorithm for an inorder traversal is described below. Algorithm 1. Traverse the left subtree. 2. Visit the root node and print its data. 3. Traverse the right subtree. Recall that the left subtree of any node is the part of the tree whose root is the left child of that node. The inorder traversal for the tree shown in Fig. 10.23 would visit the nodes in sequence 'CAT' 'DOG' 'ELF' 'FOX' 'HAT' 'HEN' 'HOG' In Fig. 10.23, a numbered circle is drawn around each subtree. The subtrees are numbered in the order that they are traversed. Subtree 1 is the left subtree of the root node. Its left subtree (number 2) has no left subtree (or right subtree); hence, the string 'CAT' would be printed first. The root node for subtree 1 would then be visited and 'DOG' would be printed. Its right subtree consists of the leaf node containing the string , ELF' (number 3). After 'ELF' is printed, the root node for the complete 508 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES ROOT Fig. 10.23 Subtrees of a Tree. tree is visited (' FOX' is printed) and the right subtree of the root node (number 4) is traversed in a like manner. Procedure INORDER in Fig. 10.24 is a recursive procedure that performs an inorder traversal of a tree and displays each node's data. The parameter ROOT represents the pointer to the root node of the tree being traversed. If the tree is empty (ROOT = NIL) an immediate return occurs. Procedure INORDER is much simpler than any nonrecursive procedure that might be written to traverse a tree. procedure INORDER (ROOT linputj : BRANCH); IPerforms an inorder traversal of the tree pointed to by ROOT. Prints each node visited.j begin 1INORDERj if ROOT NIL then begin lrecursive stepj INORDER (ROOTA.LEFT); WRITELN (ROOTA.WORD); INORDER (ROOTA.RIGHT) end Irecursive step) end; IINORDERj Fig. 10.24 ltraverse left subtreej lprint root value) Itraverse right subtreej Procedure INORDER As we saw earlier an inorder traversal of the tree shown in Fig. 10.23 would visit the nodes in alphabetical sequence. If we performed an inorder traversal of the expression tree in Fig. 10.22, the nodes would be visited in the sequence 10.7 MULTIPLE-LINKED LISTS AND TREES 509 x+ Y * A - B Except for the absence of parentheses, this is the form in which we would normally write the expression. The expression above is called an infix expression because each operator is between its operands. Switching the sequence of the three statements in the if statement shown in Fig. 10.24 will produce rather different results. The sequence WRITELN (ROOTA.WORD)i INORDER (ROOTA.LEFT)i INORDER (ROOTA.RIGHT) [print root valuej [traverse left subtreej [traverse right subtreej displays the root node before traversing its subtrees; consequently, the root value will be displayed before the values in its subtrees. This is called a pre order traversal. The nodes in Fig. 10.23 would be visited in the sequence 'FOX' 'DOG' 'CAT' 'ELF' 'HEN' 'HAT' 'HOG' The nodes in the expression tree in Fig. 10.22 would be visited in the sequence * + X Y - A B The expression above is called a prefix expression because each operator precedes its operands. The operands of + are X and Y; the operands of - are A and B; the operands of * are the two triples + X Y and - A B. Finally, the sequence INORDER (ROOTA.LEFT)i INORDER (ROOTA.RIGHT)i WRITELN (ROOTA.WORD) [traverse left subtreej [traverse right subtreej Iprint root value} displays the root node after traversing each of its subtrees; consequently, each root value will be printed after all values in its subtrees. This is called a postorder traversal. The nodes in Fig. 10.23 would be visited in the sequence 'CAT' 'ELF' 'DOG' 'HAT' 'HOG' 'HEN' 'FOX' The nodes in the expression tree in Fig. 10.22 would be visited in the sequence X Y + A B - * The expression above is called a postfix expression because each operator follows its operands. The operands of + are X and Y; the operands of are A and B; the operands of * are the two triples X Y + and A B - 510 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES Note that the left subtree is always traversed before the right subtree for all three methods discussed above. Self-check Exercises for Section 10.7 1. Draw the binary tree representation of the expression below. x * X * Y / (A + B) * C Y / A + B * C 2. What would be printed by the inorder, pre order, and postorder traversals of the tree below? III Case Study-Maintaining a Binary Search Tree We mentioned earlier that the tree in Fig. 10.23 is a binary search tree. A binary search tree has the property that for any node, all values less than that node's value are in its left subtree and all values greater than that node's value are in its right subtree. Trying to locate an item in a binary search tree is analogous to performing a binary search on an array that has already been sorted. To find a particular item or key, we compare the key to the value of the root node. If the key is less than the root node, then we can eliminate the right subtree and search only the left subtree, thereby reducing by half the number of nodes to be searched. For this reason, the time required to search a binary tree of N nodes is proportional to log2N. The algorithm for searching a binary tree is shown below. Algorithm for binary tree search 1. if the tree is empty then 2. else 3. else The key is not in the tree. if the key matches the root node data then The key is found in the root node. if the key is less than the root node data then 4. Search the left subtree. else 5. Search the right subtree. 10.8 CASE STUDY-MAINTAINING A BINARY SEARCH TREE 511 Steps 2 and 3 are stopping steps. We will leave the writing of this procedure as an exercise and describe how to build and maintain a binary search tree next. Maintaining a Binary Search Tree Problem: We want to write a concordance program that counts the number of times each word appears in a large TEXT file. After the file is completely read, an alphabetized list of the words and their occurrence counts should be printed. Discussion: For simplicity, we will assume that each word is on a separate line of the TEXT file. We can use an array of records or a binary search tree to store the words in memory. One advantage of using a binary search tree is that it is already ordered and does not need to be sorted. Each new word that is read will be entered in its proper place in the tree with an initial occurrence count of 1. If the word is already in the tree, its occurrence count should be increased by 1. Once the tree is completed, performing an inorder traversal will enable the nodes to be printed in alphabetical order. The problem inputs, outputs, and algorithm follow. the file of words, one word per line (WORDS : TEXT) an alphabetized list of words and occurrence counts Algorithm 1. Store each word in its appropriate place in a binary search tree to- gether with its occurrence count. 2. Perform an inorder traversal of the tree and print each word and its occurrence count. We can modify procedure INORDER to perform step 2. Step 1 will be performed by procedure BUILDTREE. Each node of the tree must have storage space for a character string, an integer value, and two pointers. The main program variable ROOT will point to the root of the tree. The structure chart is shown in Fig. 10.25; the main program is shown in Fig. 10.26. We will leave the modification of procedure INORDER as an exercise and discuss procedure BUILDTREE next. Procedure BUILDTREE should store the first word in the node pointed to by ROOT. Each subsequent word should be read and inserted in the tree if it is not already there. The data requirements and algorithm for BUILDTREE follow. the file of words (WORDS : TEXT) 512 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES a pointer to the root of the tree being formed (ROOT : BRANCH) the next word in file WORDS (NEXTWORD : LINE) a pointer to each ancestor of the word being inserted (ANCESTOR : BRANCH) Algorithm for BUILDTREE 1. Prepare file WORDS for input. 2. Store the first word in the root of the tree. 3. while there are more words do 4. Read the next word into NEXTWORD. 5. Insert NEXTWORD in the tree or increment its occurrence count if NEXTWORD is already in the tree. I l' ROOT ~ I WORDS I ROOT ~ BUILDTREE INORDER Fig. 10.25 Structure Chart for Concordance Program program CONCORD (WORDS, INPUT, OUTPUT); (Prints the words in file WORDS and their number of occurrences in alphabetical order. I const STRINGSIZE = 10; (maximum length of a wordl type STRING = packed array [l .. STRINGSIZE] of CHAR; BRANCH = ATREENODE; TREENODE = record WORD : STRING; COUNT : INTEGER; LEFT, RIGHT : BRANCH end; (TREENODEI var ROOT : BRANCH; WORDS : TEXT: (pointer to tree rootl (file of words in textl 10.8 CASE STUDY-MAINTAINING A BINARY SEARCH TREE 513 (Insert procedures BUILDTREE and INORDER here.! begin (CONCORD! (Build the binary search tree.! BUILDTREE (WORDS, ROOT); lPrint the words and their counts in alphabetical order.! WRITELN ('Word' :10, 'Occurrences' :15); INORDER (ROOT) end. (CONCORD! Fig. 10.26 Concordance Program Procedure READ1LINE (see Fig. 8.6) can be used to read each line of file WORDS. Step 2 will be performed by procedure ATTACHNODE. Step 5 will be performed by procedure PUTINTREE. The structure chart for procedure BUILDTREE is shown in Fig. 10.27; the procedure is written in Fig. 10.28. BUILDTREE t I NEXTWORD NEXTWORD I ~~'*"~~ ~ t ROOT I NEXTWORD ~ I t ANCESTOR I ATIACHNODE PUTINTREE I t ~ I NEXTWORD ANCESTOR ATIACHNODE Fig. 10.27 Structure Chart for BUILDTREE procedure BUILDTREE (var WORDS (input! : TEXT; var ROOT (output! : BRANCH); (Builds a tree of words and occurrence counts based on the words in file WORDS. Returns ROOT as a pointer to this tree. type LINE = record INFO : STRING; LENGTH: O•• STRINGSIZE end; (LINEl 514 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES var NEXTWORD ANCESTOR LINE; BRANCH; leach word in WORDS I [Loca l po i.n t.e r ] procedure ATTACHNODE (NEXTWORD linputl : LINE; var ANCESTOR loutputl : BRANCH); IAttaches a new tree node to the pointer ANCESTOR. The WORD field is defined as the string in NEXTWORD. The COUNT field is 1. Both pointer fields are initialized to NIL. I begin IATTACHNODEI NEW (ANCESTOR); lattach new tree node to its parenti with ANCESTORA do begin WORD := NEXTWORD.INFO; Istore the word I COUNT := 1; linitialize COUNT I LEFT : = NIL; RIGHT : = NIL linitialize pointersl end end; IATTACHNODEI IInsert procedures READ1LINE, PUTINTREE here.l begin (BUILDTREEI RESET (WORDS); READ1LINE (WORDS, NEXTWORD): ATTACHNODE (NEXTWORD, ROOT): (Insert rest of words in the tree.l while not EOF(WORDS) do begin READ1LINE (WORDS, NEXTWORD); ANCESTOR := ROOT; PUTINTREE (NEXTWORD, ANCESTOR) end [whi.Le ] end; IBUILDTREEI Fig. 10.28 Procedure lprepare WORDS for inputl 1get first wordl lplace it in rootl lroot is first ancestorl linsert next wordl BUILDTREE After reading the first word into NEXTWORD, procedure BUILDTREE calls ATTACHNODE to attach this word to the pointer ROOT. The remaining words are inserted in the tree by procedure PUTINTREE. After each word is read by READ1LINE, the local pointer variable ANCESTOR is reset to ROOT and is then passed to PUTINTREE. This local variable is needed to prevent PUTINTREE from redefining the tree root whenever it inserts a new node in the tree. The algorithm for PUTINTREE follows. Algorithm for PUTINTREE 1. if the subtree being searched is empty then 2. Attach the next word to the parent of this subtree. else if the next word is in the subtree root then 3. Increment the occurrence count by 1. else if the next word is alphabetically 515 Steps 2 and 3 are stopping steps. We will trace this algorithm for the list of words 'the', 'week', 'of', 'the', 'start'. The word 'the' is placed in the root node as shown below. ROOT The next string 'week' is alphabetically greater than 'the' so the right pointer from the root node is followed. This subtree is empty so 'week I is attached as the right subtree of the root node. The pointers represented by ANCESTOR during the search are in color. ROOT T The next string 'of' is alphabetically less than 'the' so the left pointer from the root node is followed. This subtree is empty so 'of I is attached as the left subtree of the root node. ROOT The next word is 'the'. It is found in the root so its count is increased to 2. The next word is 'start'. It is alphabetically less than' the' so the left pointer from the root node is followed. The word 'start' is alpha516 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES betically greater than 'of' so the right pointer from 'of' is followed. This subtree is empty so 'start' is attached as the right subtree of the node containing' of'. Procedure PUTINTREE is shown in Fig. 10.29. ROOT procedure PUTINTREE (NEXTWORD (inputl : LINE; var ANCESTOR (input/outputl : BRANCH); (Inserts the string in NEXTWORD in the tree if it is not already in the tree pointed to by ANCESTOR. Otherwise, increments its count. Uses procedure ATTACHNODE to attach a new node. begin (PUTINTREEI if ANCESTOR = NIL then ATTACHNODE (NEXTWORD, ANCESTOR) (attach word to its parenti else if NEXTWORD.INFO = ANCESTORA.WORD then ANCESTORA.COUNT := ANCESTORA.COUNT + 1 (increase count by 11 else if NEXTWORD.INFO If the value of ANCESTOR becomes NIL, procedure PUTINTREE calls procedure ATTACHNODE (see Fig. 10.28] to attach a new node to the tree. ATTACHNODE changes the value of the pointer represented by ANCESTOR so that it points to a newly allocated node. Self-check Exercises for Section 10.8 1. Modify procedure INORDER as needed to print the words and their counts. 2. Continue to grow the tree in this section by processing the words: 'of', 'the', 'first', 'semester', 'is', 'next', 'week'. 10.8 CASE STUDY-MAINTAINING A BINARY SEARCH TREE 517 Draw the tree. 3. Write the algorithm for searching a binary tree as a function. Return a pointer to the node containing the key or NIL. Hint: See Fig. 10.4. • Common Programming Errors It is often very difficult to debug a program involving pointer variables since the value of a pointer variable represents a memory cell address and cannot normally be printed. Hence, if a pointer value is invalid or incorrect, there may be no way of finding out what this erroneous value happens to be. Make sure that the symbol > follows each pointer variable used to designate a particular node or record. The '" must always be written when you wish to manipulate a field of a node. If the pointer variable appears without the "', the compiler will maniplate the pointer value itself (an address) rather than the node pointed to by the pointer variable. Another potential source of error involves attempting to reference a field of a node pointed to by a pointer whose value is NIL. This, of course, is illegal since the NIL pointer is a special value used to indicate the end of a list. An additional error may arise if your program gets stuck in a loop during the creation of a dynamic data structure. In this case, the number of cells allocated may exceed the memory space available in your Pascal system. This condition will result in a "stack overflow" error message. When traversing a list, make sure that the pointer to the list head is advanced down the list. The while statement below while HEAD NIL do WRITE (HEADA.WORD)i HEAD := HEADA.LINK will execute forever because the pointer assignment statement is not included in the loop body so HEAD will not be advanced down the list. Debugging Tips Because the value of a pointer variable cannot be printed, it is difficult to debug programs that manipulate pointers. You will have to trace the execution of such a program by printing an information field that identifies the list element referenced by the pointer instead of printing the pointer value itself. When writing driver programs it is often helpful to create a sample linked structure using the technique shown at the beginning of Section 10.4. The information and pointer fields of the structure can be defined using assignment statements. 518 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES II Chapter Review In this chapter, we introduced several dynamic data structures. We discussed the use of pointers to reference and connect elements of a dynamic data structure. The procedure NEW was used to allocate additional elements or nodes of a dynamic data structure. Many different aspects of manipulating linked lists were covered. We showed how to build or create a linked list, how to traverse a linked list, and how to insert and delete linked list elements. We also described how to implement stacks and queues. Procedures were written to add and remove elements from these data structures. The tree was shown to be a special list form with two links. We showed how to create a binary search tree and how to perform three kinds of tree traversal: inorder, preorder, and postorder. If you continue your study of computer science, all of these subjects will be covered in much more detail in a future course on data structures. New Pascal Statements The new Pascal statements introduced in this chapter are described in Table 10.1. Table 10.1 Summary of New Pascal Statements Statement Effect Pointer type declaration type POINT = ANODE: NODE = record INFO INTEGER: LINK : POINT The identifier POINT is declared as a pointer to a record of type NODE where NODE is a record type containing a field (LINK) of type POINT. HEAD is a pointer variable of type POINT. end: var HEAD : POINT: NEW statement NEW (HEAD) DISPOSE statement DISPOSE (HEAD) Pointer assignment HEAD := HEADA.LINK A new record is allocated of type NODE. This record is pointed to by HEAD and may be referenced as record variable HEADA. The memory space occupied by the record HEADA is returned to the storage pool. The pointer HEAD is advanced to the next node in the dynamic data structure pointed to by HEAD. 10.10 CHAPTER REVIEW 519 Review Questions 1. Differentiate between dynamic and nondynamic data structures. 2. What kind of value is contained in a pointer variable? 3. Give the necessary statements to create a pointer variable Q that points to a record type NUMBERS consisting of three integer fields called A, B, and C. Also indicate at what point actual space is allocated for Q and one occurrence of NUMBERS. 4. Define a simple linked list. Indicate how the pointers are utilized to establish a link between nodes. Also indicate any other variables that would be needed to reference the linked list. 5. Write a procedure that will link a node into an existing list. Parameters will be the HEAD of the linked list and a pointer to the node to be inserted. Assume a dummy record exists at the beginning and end of the linked list and there are no duplicate records, Given the following record definition. insert the new element preserving ID order: type PTR = ANODE; NODE = record ID : INTEGER; NAME : STRING; GPA : REAL; LINK : PTR end; 6. Write an algorithm to remove a node (identified by TARGETID) from an ordered list that does not contain a dummy record at the beginning. 7. Write the necessary procedures to duplicate all elements with a GPA of 3.5 or above in one linked list in another linked list. The original list is ordered by ID number; the new list should be ordered by GPA. Do not remove nodes from the existing list. Assume the list nodes are type NODE as described below. Parameters will be the head of the existing list (HEAD) and the head of the new linked list (GPAHEAD). type PTR = ANODE; NODE = record ID : INTEGER; NAME : STRING; GPA : REAL; LINK : PTR end; 8. Declare a node for a two-way or doubly linked list, and indicate how a traversal would be made in reverse order (from the last list element to the list head). Include any variables or fields that are necessary. 9. Discuss the differences between a simple linked list and a binary tree. Consider such things as numbers of pointer fields per node, search technique. and insertion algorithm. 520 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES 10. Write a procedure to delete all males over 25 from an existing linear linked list, given the following global statements [assume no dummy records). type PTR = ANODE; NODE = record NAME : STRING; AGE : INTEGER; SEX: (MALE,FEMALE); LINK : PTR end; The procedure parameter is the head of the list. 11. How can you determine whether a node is a leaf? 12. Traverse the tree below in inorder, pre order, and postorder. Provide one sequence that would create this ordered binary tree. Are there any letters that must occur before other letters? 13. Discuss how you might delete a node from a binary tree. Consider nodes with a or 1 child first. Programming Projects 1. Write a main program that first builds an airline passenger list in alphabetical order from passenger data provided on an input file. The program should next process commands read from system file INPUT to modify this list. The first letter of each command indicates what is to be done with any passenger data on that input line (I-Insert. D-Delete. R-Replace flight data, P-Print all passengers. Q-Quit). After the Q command is entered, the program system should display the final passenger list. 2. Redo the problem in Section 10.5 using a tree to store the passenger data. When deleting a passenger, simply blank out the information fields and leave the passenger node in the tree. Use an extra data field to indicate whether a node is still in the tree or deleted. 3. Write a program to moniter the flow of an item into and out of a warehouse. The warehouse will have numerous deliveries and shipments for this item (a PROGRAMMING PROJECTS 521 widget) during the time period covered. A shipment out is billed at a profit of 50% over the cost of a widget. Unfortunately. each shipment received may have a different cost associated with it. The accountants for the firm have instituted a first-in. first-out system for filling orders. This means that the newest widgets are the first ones sent out to fill an order. This method of inventory can be represented using a stack. The PUSH procedure will add a shipment received. The POP procedure will be used for a shipment out. Each data record will consist of: SOl' 0 # Cost Vendor for shipment received or an order to be sent a quantity received or shipped out the cost per widget (for a shipment received only) character string naming company sent to or received from. Write the necessary procedures to store the shipments received and process orders. The output for an order will consist of the total cost for all the widgets in the order as well as the quantity. Hint: Each widget price is 50% higher than its cost. The widgets used to fill an order may come from multiple shipments with different costs. 522 4. Redo Project 3, assuming the widgets are shipped using a first-in, first-out strategy. Use a queue to store the widget orders. 5. At Bob's Bank a program is needed to store the checks processed during a month for a customer. Since the checks will be processed daily, but not in numerical order. it is best to store them in a simple linked list by check number. Write a program that will input a check number. date of transaction, amount of check, and the name of the person receiving the check. Insert the checks into a list and after all checks have been entered. display all of the checks with all associated information, and a final total for all the checks written during the month. 6. In preparing mailing lists, it is often useful to be able to reference the information by using either the person's name or zipcode. This can be done if each list node has a pointer to the next node by name and a pointer to the next node by zipcode. The nodes representing each person's data should be linked together in both name and zipcode order; there should only be one copy of the data for each person. First the information can be inserted in a list by name order using a pointer field called NEXTNAME. Then the pointer field NEXTZIPCODE can be defined so that the new list node is also in zipcode order. There should be a list head that points to the first person in name order and a second list head that points to the first person in zipcode order. Write a program that reads a record containing first name (character 10), last name (character 15). street address (character 50). city (character 20), state (character 2), and zipcode (character 6) and inserts each record into the lists. After all of the information has been entered. provide a list of the information in name order and a second list in zipcode order. 7. The set capability is limited in the number of elements that can be stored in a set (often only 255). A more universal system can be implemented using list representation to store sets. POINTER VARIABLES AND DYNAMIC DATA STRUCTURES Write the necessary routines needed to insert and delete integer values from a set. Also write the routines necessary to implement the set difference, intersection, and union operations. To verify the results, list the contents of the sets before and after each operation. 8. Many card games require that each of four players receive 13 cards of a 52 card deck (for example: bridge). The computer can be utilized to shuffle a deck of cards and then deal them. To accomplish this first place all 52 cards into a linked list. Afterwards, "deal" the cards to 4 players by generating a random number between 1 and the size of the list remaining. Traverse the linked list and delete the selected card from the list. Each player's hand will consist of a record that has pointers to a list of hearts, diamonds, clubs, and spades in ascending order. [i.e. You will need 4 pointer fields). After all cards are dealt, list the contents (by suit) of each hand. 9. In this chapter we wrote recursive procedures to perform preorder, inorder, and postorder tree traversals. A tree traversal can be written without using recursion. In this case it is necessary to push the address of a tree node that is reached during the traversal onto a stack. The node will be popped off later when it is time to traverse the tree rooted at this node. For example, the algorithm for a nonrecursive pre order traversal follows. 1. Push NIL onto the stack. 2. Assign the root node as the current node. 3. while the current node is not NIL do 4. Print the current node. 5. if the current node has a right subtree then Push the right subtree root onto the stack. 6. If the current node has a left subtree then Make it the current node else Pop the stack and make the node removed the current node. In this algorithm each right subtree pointer that is not NIL is pushed onto the stack; the stack is popped when the current left subtree pointer is NIL. Implement and test a nonrecursive procedure for pre order traversal. Write a nonrecursive algorithm for inorder traversal and implement and test it as well. 10. If an arithmetic expression is written in prefix or postfix notation, then there is no need to use parentheses to specify the order of operator evaluation. For this reason, some compilers translate infix expressions to postfix notation first and then evaluate the postfix string. Write a procedure that simulates the operation of a calculator. The input will consist of an expression in postfix notation. The operands will all be single digit numbers. Your program should print the expression value. For example, if the input string is '54+3/', the result printed should be ((5 + 4) / 3) or 3. To accomplish this, examine each character in the string in left to right order. If the character is a digit, push its numeric value onto a stack. If the character is an operator, pop the top two operands, apply the operator to them, and push the result onto the stack. When the string is completely PROGRAMMING PROJECTS 523 scanned there should only be one number on the stack and that should be the expression value. Besides the operators +, -. *. and /, use the operator to indicate exponentiation. A 11. .. There are many applications in which a two-dimensional matrix with large dimensions must be stored in memory. If a majority of the elements in the matrix are zero, the matrix is called a sparse matrix. A sparse matrix may be more efficiently represented using a one-dimensional array of pointers where each element of this array, ROW, points to a linked list. ROW [ I] would point to a list whose nodes indicate the value and column number for each nonzero element in row 1. For example, if row 3 is (25 0 0 0 -14 0 0). then the third element of this array would point to the list shown below. This list indicates that there are two nonzero elements in the third row of the sparse matrix at columns 1 and 5. Write procedures to read a sparse matrix and store it as shown. to add together two sparse matrices and to print a sparse rnatrix. 12. A polynomial may be represented as a linked list where each node contains the coefficient and exponent of a term of the polynomial. The polynomial 4x 3 + 3x 2 - 5 would be represented as the linked list. Write a program system that reads two polynomials, stores them as linked lists. adds them together, and prints the result as a polynomial. The result should be a third linked list. Hint: Traverse both polynomials. If a particular exponent value is present in either of the two polynomials being summed. then it should be present in the answer. If it is present in both polynomials, then its coefficient is the sum of the corresponding coefficient in both polynomials. (If this sum is zero, the term should be deleted.] 13. Assume that the registration data for a class of students is stored as the array of records shown below. KEY POINTER 2 3 524 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES The first field in each record contains the student 1D number (four digits) and the second field contains a pointer to all classes for which the student is registered. Write a program system that builds this array from a file of randomly arranged data and prints it out. Assume each data line starts with an 1 (insert) or D (delete), followed by the student 1D and course identification string. 14. Write a program system that represents the Morse code as a binary tree. The symbol. should cause a branch to the left and the symbol - a branch to the right. The information field of each node should be the letter represented by the corresponding code. The first three levels of the tree are shown below. MORSE The Morse code should be read from an input file where each file component consists of a letter, and the corresponding code string. After building the tree, read a coded message and translate it into English. 15. Use two stacks (OPERATOR and OPERAND) and procedures PUSH and POP to help in "compiling" a simple arithmetic expression without parentheses. For example, the expression A+B*C-D should be compiled as the table: OPERATION OPERANDl + B A y OPERANDZ C Z D RESULT Z Y X The above table shows the order of the three operations (*, +, - J and their operands. The result column gives the name of an identifier selected to hold the result. PROGRAMMING PROJECTS 525 Your procedure should read each character (NEXT CHAR) and process it as follows: If it is a blank, then ignore it; otherwise, if it is an operand (A-F), then push it onto the OPERAND stack; otherwise, if it is not an operator (+, -, *, /l. then print an error message, If the character is an operator, then it should be pushed onto the OPERATOR stack if its precedence is greater than the operator currently at the top of the stack [e.g. when * is read in the example above, it is pushed onto the stack because + is on the top) or if the operator stack is empty, Otherwise, a line of the output table should be written by popping the OPERATOR stack and removing the first two elements of the OPERAND stack (two pops), A new symbol is used to hold the result (Z-G), and this symbol is pushed onto the operand stack. The process of generating output table lines continues until the precedence of NEXTCHAR is greater than the precedence of the operator at the top of the stack or the operator stack is empty. At this point. NEXTCHAR should be pushed onto the operator stack. When the end of the input line is reached, any remaining operators and operands should be popped as described above. 526 POINTER VARIABLES AND DYNAMIC DATA STRUCTURES Appenclixes Appendix A Reserved Words, Standard Identifiers, Operators, Functions, and Procedures Reserved words and array begin case const div do downto else end file for function goto if in label mod nil not of or packed procedure program record repeat set then to type until var while with Standard identifiers Constants: FALSE, TRUE, MAXINT Types: INTEGER, BOOLEAN, REAL, CHAR, TEXT Program parameters: INPUT, OUTPUT Functions: ABS, ARCTAN, CHR, COS, EOF, EOLN, EXP, LN, ODD, ORD, PRED, ROUND, SIN, SQR, SQRT, SUCC, TRUNC Procedures: GET, NEW, PACK, PAGE, PUT, READ, READLN, RESET, REWRITE, UNPACK, WRITE, WRITELN Ap-1 Table A.1 Table of Operators Operator Operation Type of Operand(s) assignment any type except file types identity sign inversion integer or real same as operand addition subtraction multiplication integer or real integer or real integer division real division modulus integer integer or real integer integer real integer equality inequality scalar, string, set, or pointer greater than := arithmetic: + (unary) - (unary) + * div / mod Result type relational: = subset set greater than or equal scalar or string -or- in superset set set membership first operand is any scalar, the second is its set type logical: not or and negation disjunction conjunction BOOLEAN BOOLEAN union set difference intersection any set type T T set: + * Ap-2 APPENDIX A Table A.2 Standard Functions Name Description of Computation Argument Result ABS The absolute value of the argument real/integer same as argument EXP The value of e (2.71828) raised to the power of the argument real/integer real LN The logarithm (to the base e) of the argument real/integer real SQR The square of the argument real/integer same as argument SQRT The positive square root of the argument real/integer (positive) real ROUND The closest integer value to the argument real integer TRUNC The integral part of the argument real integer ARCTAN The arc tangent of the argument real/integer (radians) real COS The cosine of the argument real/integer (radians) real SIN The sine of the argument real/integer (radians) real CHR Returns the character whose ordinal number is its argument integer CHAR ODD Returns TRUE if its argument is an odd number; otherwise returns integer BOOLEAN FALSE ORD Returns the ordinal number of its argument ordinal integer PRED Returns the predecessor of its argument ordinal ordinal SUCC Returns the successor of its argument ordinal ordinal APPENDIX A Ap-3 Table A.3 Table of Standard Procedures Procedure Call DISPOSE (P) Returns the record pointed to by pointer variable P to free storage. GET (F) Advances the file position pointer for file F to its next component and assigns the value of the component to FA. NEW (P) Creates a record of the type pointed to by pointer P and saves its address in P. PACK (U , I I P) Copies the elements in unpacked array U, starting with U [ I ] , to packed array P, starting with the first element. PAGE (F) Advances the printer to a new page before printing the next line of file F. PUT (F) Appends the current contents of FA to file F. READ (F , variables) Reads data from file F to satisfy the list of variables. Only one component of file F can be read unless F is a text file. If F is not specified, file INPUT is read. READLN (F I variables) Reads data from text file F to satisfy the list of variables. Skips any characters at the end of the last line read. RESET (F) Resets the file position pointer for file F to the beginning. File F may then be read. REWRITE (F) Resets the file position pointer for file F to the beginning; any prior contents are lost. File F may then be written. UNPACK (P, U, I) Copies the elements in packed array P, starting with the first element, to unpacked array U, starting with U [I]. WRITE (F I outputs) Writes the data in the order specified by outputs to file F. Only one output item can be written unless F is a text file. If F is not specified, the data are written to file OUTPUT. WRITELN (F , Ap·4 Description APPENDIX A ou~u~) Writes the data in the order specified by outputs to text file F. Writes an end-of-line mark after the data. AppendixB Additions and Extensions to Pascal I B.1[ Additional Features of ANSI/IEEE Pascal This appendix describes additional features of the ANSI/IEEE Pascal standard not covered in the text. Forward Declarations Given the procedure declarations below, procedure B can call A, but procedure A cannot call B. This is because the declaration for procedure B is not processed until after procedure A is translated. procedure A (var X : REAL); end; IAI procedure B (var Y REAL) ; end; IBI If a forward declaration for procedure then A can also call B. B is inserted before procedure 'A, procedure B (var Y REAL); FORWARD; procedure A (var X REAL) ; ......... end; IAI procedure B; ......... end; IBI As shown above, the forward declaration for procedure B consisting of only the procedure heading comes first. followed by the declaration of procedure A, and finally the declaration for procedure B. The parameter list for procedure B appears only in the forward declaration. Now procedure A can call B, and procedure B can call A; so A and B are called mutually recursive. Ap-S Functions and Procedures as Parameters A procedure or function may be passed as a parameter to another procedure or function. As an example, we may wish to compute the sum below for the integers 1 through N where f represents a function that is applied to each integer. f(l) + f(2) + f(3) + ... + f(N) If f is the function SQR (square), then we wish to compute the sum a) 1 + 22 + 32 + ... + N2 If f is the function SQRT (square root), then we wish to compute the sum b) vr+ vz+ y'3+ ... + VN In function SUMINT below, the function F is declared as a function parameter. The function designator SUMINT (SQR, 10) lO; the function designator computes sum a) above for N SUMINT (SQRT, 10) computes sum b) above for N = 10. function SUMINT (function F(X N : INTEGER) [Compu t.e s F(l) + F(2) + ... + INTEGER) REAL; REALi F(N).! var SUM : REALi I : INTEGER; beg in ISUMINT j SUM := 0.0; Ithe partial sumj (loop control variablej \ initialize SUMj for I := 1 to N do SUM := SUM + F(I)i SUMINT := SUM end; ISUMINTj [de f i.ne resultj The parameter of function F is represented by X in the heading for function SUMINT; any identifier may be used. F can also represent a user-defined function with one type INTEGER parameter. GOTO Statements and Labels The GOTO statement is used to transfer control from one program statement to another. The label (a positive integer) is used to indicate the statement to which control is transferred. Labels must be declared in label declaration statements at the beginning of a block. In function SAMEARRAY below, the GOTO statement is used to exit a for loop before the specified number of repetitions (N) are performed. Ap-6 APPENDIX B function SAMEARRAY (A, B : REALARRAY; N : INTEGER) : BOOLEAN; IReturns TRUE if arrays A[l •• N] and B[l •• N] are the same arraY.l label 100; var I : INTEGER; begin ISAMEARRAYl SAMEARRAY := FALSEi Iloop control variable] lassume arrays are not the samel ICompare elements 1 .• N until an unequal pair is found.] for I := 1 to N do if A[I] B[I] then GOTO 100i lassert: arrays A and Bare equal.l SAMEARRAY := TRUE; 100: Ireturn from function] end; ISAMEARRAY] The function result is initialized to FALSE and corresponding array elements are compared in the for loop. If an unequal pair of elements is found, the loop is exited via an immediate transfer of control to label 100. If all pairs are equal, the loop is exited after the Nth pair is tested and the function result is set to TRUE. This function can easily be implemented without using the GOTO (see Fig. 6.9 and 9.15); computer scientists generally avoid using the GOTO except when absolutely necessary. PACK and UNPACK The standard procedures PACK and UNPACK are used to transfer data between packed and unpacked arrays. Given the declarations var PA : packed array [l •• N] of CHAR; UA : array [l •• M] of CHARi I : INTEGERi the procedure (call) statement PACK (UA, I, PAl copies elements from unpacked array UA (starting with UA [ I ]) to packed array PA (starting with PA[ 1]). The procedure (call) statement UNPACK (PA, UA, I) copies elements from packed array PA (starting with PA[1]) to unpacked array UA (starting with UA[ I]). Arrays PA and UA do not have to be the same size. APPENDIX B Ap-7 1 B.21 ISO Pascal This appendix describes a feature of the Pascal standard approved by the International Organization for Standardization (ISO Pascal) that is not included in the ANSI/IEEE standard. Conformant Array Parameters One of the principal frustrations in using ANSI/IEEE standard Pascal is the fact that a function or procedure that manipulates an array of one type cannot also manipulate an array of a similar type. For example, a procedure that manipulates array NAME declared below cannot manipulate array FLOWER because the arrays have different types. type STRINGI STRING2 packed array [1 •. 20] of CHAR; packed array [1 .• 8] of CHAR; var NAME STRINGl; FLOWER: STRING2; Even though the only difference between these two arrays is their size (number of elements), separate procedures would have to be written to read data into them. In ISO Pascal, the conformant array schema packed array [u.. v : INTEGER] of CHAR describes a packed array of characters whose subscript type is a subrange of type INTEGER. The use of this schema in the procedure header below enables procedure READSTRING to read data into a packed array of characters (represented by INSTRING) of any size (represented by STRINGSIZE). procedure READSTRING (SIZE linputl : INTEGER; var INSTRING loutputl : packed array [U .• V INTEGER] of CHAR); In ISO Pascal, the procedure (call) statement READSTRING (20, NAME) could be used to read up to twenty characters into array NAME; the procedure (call) statement READSTRING (8, FLOWER) could be used to read up to eight characters into array FLOWER. Ap-a APPENDIX B Any identifiers can be used in the declaration of the index-type specification [U .. V : INTEGER] for INSTRING. The data type listed (INTEGER) must be an ordinal type. Conformant array schemas can be used with packed and unpacked arrays of any element type, not just CHAR. Conformant array schemas can also be used with multidimensional arrays. The two-dimensional conformant array schema below is valid if MONTH is declared as an enumerated type. array [U .. V : INTEGER; J .. K : MONTH] of REAL; The corresponding actual parameter must be a two dimensional array of type REAL values. The first subscript type must be a subrange of the integers; the second subscript type must be a subrange of type MONTH. I B.31 UCSD Pascal" UCSD Pascal is a complete operating system that includes facilities for editing and saving files as well as a Pascal compiler. This section covers some of the differences between UCSD Pascal and standard Pascal with emphasis on string and file processing. Identifiers in UCSD Pascal There are a number of additional reserved words and standard identifiers in UCSD Pascal. The reserved words are listed below followed by the standard identifiers discussed in this section. Additional reserved words external separate implementation unit interface uses process segment Selected standard identifiers CLOSE INTERACTIVE STRING CONCAT LENGTH COpy LOCK CRUNCH NORMAL DELETE POS INSERT PURGE UCSD Pascal uses only the first eight characters of an identifier to determine uniqueness. The underscore character C) can appear in an identifier but it is not considered one of the eight characters (i.e, TOP_SCORE and TOPSCORE are the same identifier). String Manipulation in UCSD Pascal One of the most important extensions of UCSD Pascal is the inclusion of the data type STRING. In UCSD Pascal, the declarations • UCSD Pascal is a trademark of the regents of the University of California. APPENDIX B Ap-9 var PUPILNAME, TEACHERNAME : STRING; allocate space for storage of two character strings of up to eighty characters each. The procedure READLN can be used to read data into a variable of type STRING. WRITE ('Enter the name of the teacher: READLN (TEACHERNAME); '); After the prompt above is displayed, all characters (up to 80) entered before pressing the key are stored in TEACHERNAME. UCSD Pascal keeps track of the actual length of the string stored in TEACHERNAME. The string length can change dynamically as the string is manipulated. The assignment statement TEACHERNAME := 'Mr. Chips' replaces the string stored in TEACHERNAME with a new string. The function LENGTH can be used to determine the current string length. The statement WRITELN ('The number of characters in LENGTH(TEACHERNAME) :2) displays the line ,TEACHERNAME, ' is The number of characters in Mr. Chips is 9 It is possible to set the maximum string size at any length up to 255 characters. The declarations below provide storage space for one string of up to ten characters and one string of up to 255 characters. var WORD: STRING[lO]; PARAGRAPH: STRING[255]; Strings of different sizes can be manipulated together. The first assignment statement below stores the string shown on the right in PARAGRAPH. The second assignment statement stores the ten character substring I This is a ' in WORD. This substring replaces the string originally saved in PARAGRAPH when the third assignment statement is executed. PARAGRAPH := 'This is a very, very long string'; WORD := PARAGRAPH; PARAGRAPH := WORD Because the STRING data type is part of UCSD Pascal, it is not necessary to declare your own data type STRING or to write procedures such as READSTRING (see Fig. 6.15) and READLINE (see Fig. 7.23) to enter Ap-10 APPENDIX B string data. Consequently, the programs in Chapters 6 through 10 that manipulate strings can all be rewritten to take advantage of this. The type declaration type STRING = packed array [l •• STRINGSIZE] of CHARi should be deleted since STRING is a predefined data type. The procedure READLN can be used to enter each data string instead of READSTRING or READLINE. In Section 7.10, we wrote a number of procedures that manipulate character strings. These operations are all performed by standard functions in UCSD Pascal as described in Table B.l. All arguments ending with -string are type STRING; all other arguments are type INTEGER. Table B.1 Table of String Manipulation Functions Function Description CONCAT ( string-list) CONCAT ( 'X', ' +, , y' ) COpy (source-string, index, size) COPY( 'HI HO', 4, 2) POS ( target-string, source-string) POS ( 'Find me', 'me') Returns a string formed by concatenating the strings in string-list The string-list consists of any number of strings separated by commas. Result is 'X + y'. Returns a string of size characters taken from source-string starting at position index. The source-string is unchanged. Result is 'HO'. Returns the starting position (an integer) of the first occurrence of target-string in source-string. Returns 0 if target-string is not found. Result is 6. There are two string-manipulation procedures in UCSD Pascal. They are described in Table B.2 and illustrated. The examples assume that STRl is 'Mr. & Mrs. Jones' and STR2 is 'The day'. To illustrate the use of these functions and procedures, we will write two versions of procedure REPLACE. Procedure REPLACE replaces all occurrences of a target-string in a source-string with a pattern-string. For example, the procedure (call) statement REPLACE ('Pascal', 'UCSD Pascal', TEXTSTRING) would replace all occurrences of 'Pascal' in TEXTSTRING by 'UCSD Pascal' . The first implementation (see Fig. B.l) uses the standard functions; the second implementation (see Fig. B.2) uses the standard procedures. In both APPENDIX B Ap-11 Table B.2 Table of String Manipulation Procedures Procedure DELETE (source-string, index, size) DELETE (STRl, 5, 7) INSERT (pattern-string, source-string, index) INSERT (STR2, 'next', 5) Description Removes the next size characters from source-string starting with the character at position index. The new value of STRI is 'Mr. Jones '. Inserts the pattern-string at position index of source-string. The new value of STR2 is 'The next day'. implementations, the while loop is repeated as long as the string TARGET is still present in the string SOURCE. The loop body replaces each occurrence of TARGET with PATTERN and finds the next occurrence of TARGET in SOURCE. procedure REPLACE (TARGET, PATTERN linput! : STRING; var SOURCE Iinput/output! : STRING); IReplaces each occurrence of TARGET in SOURCE by PATTERN.! var INDEX : INTEGER; HEAD, TAIL : STRING; Ithe position of TARGET if found! Ithe substring of SOURCE preceding TARGET! Ithe substring of SOURCE following TARGET! beg in IREPLACE! IFind each occurrence of TARGET and replace it with PATTERN.! INDEX := POS(TARGET, SOURCE); Ifind first occurrence! while INDEX 0 do begin IGet the head of the string SOURCE.! HEAD := COPY(SOURCE, 1, INDEX-I); IGet the tail of the string SOURCE.! TAIL := COPY(SOURCE, INDEX+LENGTH(TARGET), LENGTH(SOURCE)-INDEX-LENGTH(TARGET)+l); IConcatenate HEAD, PATTERN, and TAIL.! SOURCE := CONCAT(HEAD, PATTERN, TAIL); INDEX := POS(TARGET, SOURCE) Ifind next occurrence! end [wh i l.e ] end; IREPLACE! Fig. B.1 Procedure REPLACE Using Standard Functions Fig. B.2 Procedure REPLACE Using Standard Procedures procedure REPLACE (TARGET, PATTERN Iinput! : STRING; var SOURCE Iinput/output! : STRING); IReplaces each occurrence of TARGET in SOURCE by PATTERN.! Ap-12 APPENDIX B var INDEX : INTEGER; HEAD, TAIL : STRING; Ithe position of TARGET if foundj Ithe substring of SOURCE preceding TARGETj Ithe substring of SOURCE following TARGETj begin IREPLACEj IFind each occurrence of TARGET and replace it with PATTERN.j INDEX := POS(TARGET, SOURCE); Ifind first occurrencej while INDEX 0 do begin DELETE (SOURCE, INDEX, LENGTH(TARGET)): Idelete TARGETj INSERT (PATTERN, SOURCE, INDEX); Iinsert PATTERNj INDEX := POS(TARGET, SOURCE) Ifind next occurrencej end [whi Le ] end; IREPLACEj Compiler Directives in UCSD Pascal A special form of comment called a pseudo comment may be used to set option switches in the UCSD Pascal compiler. Each pseudo comment begins with the symbol $. One particulary useful option switch directs the compiler to insert a disk file into the source program being compiled. The comment I$1 PROCESS I causes the file PROCESS to be inserted where the comment occurs in the program. This enables the programmer to save procedures and functions in separate files and pull these files together at a later time. Sequential File Manipulation in UCSD Pascal There are a few differences in the way sequential files are processed in UCSD Pascal. There are two predefined file types in UCSD Pascal: TEXT and INTERACTIVE. The system files INPUT and OUTPUT are predeclared as type INTERACTIVE. If CH is type CHAR, the operation READ (CH) is implemented as GET (INPUT); CH := INPUT" This is the reverse of the order for a TEXT file (see Section 8.8) and facilitates interactive data entry in UCSD Pascal. The RESET and REWRITE statements have a slightly different form in UCSD Pascal. The first statement on Ap-14 associates the internal file name INFILE with the directory name 'MYDATA' and prepares this file for input. The second statement Ap-14 associates the internal file name OUTFILE with the directory name 'NEWDATA I and prepares this file for output. APPENDIX B Ap-13 RESET (INFILE, 'MYDATA'); REWRITE (OUTFILE, 'NEWDATA'); Iprepare INFILE for input} Iprepare OUTFILE for output} The internal file names must be referenced in the program. The if statement if not EOF(INFILE) then begin READ (INFILE, NEXT_RECORD); WRITE (OUTFILE, NEXT_RECORD) end; copies a record from file INFILE to file OUTFILE using NEXT_RECORD as an intermediary. After file processing is finished, the statements CLOSE (INFILE, NORMAL); CLOSE (OUTFILE, LOCK) should be used to update the disk directory. Failure to do so may result in a newly created file being lost. The second parameter of the CLOSE statement specifies the disposition of the file being closed as explained in Table B.3. The LOCK parameter should be used to save a newly created file. If the program does not close an opened file, the system performs a CLOSE (file, NORMAL) operation on that file. Table B.3 Table of CLOSE Options CLOSE Statement Effect CLOSE ( file, NORMAL) CLOSE (file) The file is closed and has the same contents that it had before it was opened. CLOSE ( file, LOCK) The file is closed and its contents as changed by the' program is saved. CLOSE ( file, PURGE) The file is closed and is removed from the disk directory. CLOSE ( file, CRUNCH) The file is closed and all records following the last one accessed are deleted. The directory name may be read into a string variable during program execution. If INNAME is type STRING, then the statements below associate the directory file specified by the program user with file INFILE. WRITE ('Enter directory name of file to be copied: '); READLN (INNAME); Iread the directory name} Iprepare INFILE for input} RESET (INFILE, INNAME) Ap-14 APPENDIX B 1 8.41 TURBO Pascal * TURBO Pascal is another version of Pascal that is available on personal computers. Like UCSD Pascal, TURBO Pascal provides facilities for editing and saving files. The text editor in TURBO Pascal uses many of the commands found in the popular WordStar t word processing program. Identifiers in TURBO Pascal There are a number of additional reserved words and standard identifiers in TURBO Pascal. The reserved words are listed below followed by the standard identifiers discussed in this section. Additional reserved words absolute external inline shl shr string xor Selected standard identifiers CLOSE CONCAT COpy DELETE INSERT LENGTH POS An identifier may consist of up to 127 characters. The underscore character C) can appear in an identifier. The case Statement in TURBO Pascal The case statement in TURBO Pascal has been extended to include an else clause. This clause is executed when the case selector value does not match any of the case labels. If the value of OPERATOR (type CHAR) is not one of the four characters listed, the WRITELN statement following else is executed in TURBO Pascal. case OPERATOR of ,+, RESULT:= OPERANDI + OPERAND2i '-' RESULT:= OPERANDI - OPERAND2i 'I' : RESULT := OPERANDI I OPERAND2i ,*' : RESULT : = OPERANDI * OPERAND2 else WRITELN ('Invalid symbol ' f OPERATOR) end [ca se ] The word otherwise is sometimes used instead of else in other extended versions of Pascal. The rest of the case statement would be unchanged. • TURBO Pascal is a trademark of Borland International. Inc. tWordStar is a trademark of MicroPro International. Inc. APPENDIX B Ap-15 String Manipulation in TURBO Pascal The string data type and string processing features of UCSD Pascal are also provided in TURBO Pascal. You should read the section entitled String Manipulation in UCSD Pascal at the beginning of Appendix B.3. There are two significant differences between the STRING data type in UCSD Pascal and TURBO Pascal. First, STRING is a reserved word in TURBO Pascal and cannot be redefined; STRING is a standard identifier in UCSD Pascal. Second, the maximum length of a string variable must always be specified in TURBO Pascal; there is no default value. The declarations var WORD: STRING[lO]i LINE: STRING[80]; PARAGRAPH: STRING[255]; allocate space for storage of three strings; the maximum length of each string is specified. The programs that manipulate character strings in Chapters 6 through 10 must be modified to run in TURBO Pascal. The declaration type STRING = packed array [1 •• STRINGSIZE] of CHAR; is invalid because STRING is a reserved word in TURBO Pascal. Replace this declaration with type A STRING = STRING[STRINGSIZE]; and substitute A_STRING for each occurrence of the type identifier STRING. The READLN procedure can be used to read up to STRINGSIZE characters into a variable of type A_STRING. The string manipulation procedures and functions described for UCSD Pascal are also implemented in TURBO Pascal. Procedure REPLACE shown in Fig. B.1 and B.2 will run in TURBO Pascal provided the type identifier A_STRING is declared and used in place of STRING as described above. Also, the statement SOURCE := HEAD + PATTERN + TAIL; can be used in Fig. B.l to concatenate the three strings listed on the right because the operator + means concatenation when used with string operands in TURBO Pascal. Compiler Directives in TURBO Pascal There are a number of compiler options which are set to default values of + or - in TURBO Pascal. In order to change the default value, the proAp-16 APPENDIX B grammer must specify the new value for a compiler directive. This new value is provided in the form of a pseudo comment. TURBO Pascal does not normally check for subscript range errors. The pseudo comment I $R+ I changes the value of the R compiler directive from - to + and enables subscript checking and should be used while debugging programs. This comment should appear before the first reference to an array element. The pseudo comment I $ I PROCESS. PAS I instructs the compiler to include the file PROCESS .PAS in the source program at the point where t~ comment occurs. The I compiler directive is necessary for compiling large programs. It enables the programmer to save procedures and functions as separate files and then pull these files together at a later time. Sequential File Manipulation in TURBO Pascal The system file INPUT may correspond to either of two logical devices in TURBO Pascal. In normal operation. the system file INPUT corresponds to the console device. This is fine for entering numeric data and allows the user to edit the data string before pressing the key. The disadvantage is that the EOLN functions and EOF functions will not work properly and character data are not read as expected. The pseudo comment [$B-] resets the value of the B compiler directive from + to -. The effect is to assign the system file INPUT to the terminal device instead of the console device. This enables data entry to proceed as described in the text. This comment must precede the program statement. When processing disk files, two additional statements must be used in TURBO Pascal. The ASSIGN statements below associate the internal file name INFILE with the directory name 'MYDATA. TXT' and the internal file name OUTFILE with the directory name' NEWDATA. TXT'. ASSIGN (INFILE, 'MYDATA.TXT'); ASSIGN (OUTFILE, 'NEWDATA.TXT'); The ASSIGN statement for a file must precede any statement that manipulates the file. The internal file names may be manipulated as before. The statements below RESET (INFILE); REWRITE (OUTFILE); if not EOF(INFILE) then begin READ (INFILE, NEXT_RECORD); WRITE (OUTFILE, NEXT RECORD) end; - prepare INFILE and OUTFILE for input and output, respectively, and copy the first record of INFILE to OUTFILE using NEXT_RECORD as an intermediary. APPENDIX B Ap-17 After file processing is finished, the statements CLOSE (INFILE); CLOSE (OUTFILE) should be used to update the disk directory. Failure to do so may result in a newly created file being lost. The directory name may be read into a string variable during program execution. If INNAME is type STRING [ 11 ], then the statements below associate the directory file specified by the program user with file INFILE. WRITE ('Enter directory name of file to be copied: I); READLN (INNAME); Iread the directory namel ASSIGN (INFILE, INNAME); RESET (INFILE) Iprepare INFILE for inputl Ap-18 APPENDIX B Appendix C Pascal Syntax Diagrams Program program parameters declaration part Program Parameters -. e 0 y f p z + 4 5 6 7 8 " # s % & 0 1 7 / 6 8 9 @ A K B L V C M W 5 ? I S ] g q h r I I J T U i s j t 9 D E 0 a N X b k u 1 v m y c w Codes 00-31 and 127 are nonprintable control characters. • CDC is a trademark of Control Da ta Corpora lion. Ap-29 Right Digit EBCDIC 0 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 3 4 5 6 7 8 9 D ¢ & ! s > ? :# @ b c d e f 0 P q r t -, * s K W 0 I L + / % A H
Report "Problem Solving & Structured Programming in Pascal.pdf"
Academia.edu no longer supports Internet Explorer.
To browse Academia.edu and the wider internet faster and more securely, please take a few seconds to upgrade your browser .
Enter the email address you signed up with and we'll email you a reset link.
- We're Hiring!
- Help Center

Chapter 4 Introduction to Pascal Programming Language
by khairul izwan
Free Related PDFs
Susan L Graham
Berkeley Pascal is designed for interactive instructional use and runs on the PDP/11 and VAX/11 computers. Interpretive code is produced, providing fast translation at the expense of slower execution speed. There is also a fully compatible compiler for the VAX/11. An execution profiler and Wirth’scross reference program are also available with the system. The system supports full Pascal. The language accepted is ‘standard’ Pascal, and a small number of extensions. There is an option to suppress the extensions. The extensions include a separate compilation facility and the ability to link to object modules produced from other source languages. The User’s Manualgives a list of sources relating to the UNIX† system, the Pascal language, and the Berkeley Pascal system. Basic usage examples are provided for the Pascal components pi , px , pix , pc , and pxp . Errors commonly encountered in these programs are discussed. Details are given of special considerations due to the interactive imp...

1993, ACM SIGPLAN Notices
Pascal was defined in 1970 and, after a slow start, became one of the most widely used languages in introductory programming courses. This article first summarises the events leading to Pascal's design and implementation, and then proceeds with a discussion of some of the language's merits and deficiencies. In the last part, developments that followed its release are recounted. Its influence chiefly derived from its being a vehicle for structured programming and a basis for further development of languages and for experiments in program verification.

paul bailes

simegnew atalay

b0aza alnaim

1983, Behavior Research Methods & Instrumentation
Some of the author’s experiences in working with simulation languages are discussed. The use of PASCAL language is detailed.

Dr.Lenin Raja

Mahmudul Faisal Al Ameen

Lambert Meertens

RELATED TOPICS
- We're Hiring!
- Help Center
- Find new research papers in:
- Health Sciences
- Earth Sciences
- Cognitive Science
- Mathematics
- Computer Science
- Academia ©2023

IMAGES
VIDEO
COMMENTS
The six steps of problem solving involve problem definition, problem analysis, developing possible solutions, selecting a solution, implementing the solution and evaluating the outcome. Problem solving models are used to address issues that...
Maytag washers are reliable and durable machines, but like any appliance, they can experience problems from time to time. Fortunately, many of the most common issues can be solved quickly and easily. Here’s a look at how to troubleshoot som...
Are you a beginner when it comes to solving Sudoku puzzles? Do you find yourself frustrated and unsure of where to start? Fear not, as we have compiled a comprehensive guide on how to improve your problem-solving skills through Sudoku.
This text can be used in any introductory programming course that em- phasizes a careful, disciplined approach to programming in Pascal. Since the Advanced
4.6 The Overall Structure of a Pascal Program. 122. 4.7 Examples of Programs
Pascal (Computer program language) I. Title. QA76.73.P2N35 1989. 005.13'3—dcl9. 88-29307. CIP. Page 3. CHAPTER. CHAPTER. X. Contents. 1 s Computer Science
All aspects of programming and problem solving in the Pascal language, with special attention to good programming habits and style are introduced.
As previously noted, developing the skill to solve a problem using a computer program is the most important trait to develop as a beginning programmer. Pascal
An introduction to programming and problem solving with PASCAL. by: Schneider, G. Michael; Weingart, Steven W., joint author; Perlman, David M
An Introduction to Programming and Problem Solving with Pascal [Schneider, G. Michael, Weingart, Steven W., Perlman, David M.] on Amazon.com.
Problem Solving and
There is a brief introduction to the Pascal programming
... Computer Hardware 33 Computer Storage 34 1.6 Common Programming Errors 37 1.7 Chapter Summary 37 Chapter 2 Problem Solving Using C++ 43 2.1 Introduction to
PDF” or “Export to HTML”. Live scripts can also be converted to code