Introduction to programming

1,173 views
962 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,173
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
42
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Introduction to programming

  1. 1. AAU Introduction to Programming Instructor Seble M.T 2005 WWW.AAU.EDU.ET
  2. 2. Chapter One 1.1 Introduction to programming A Computer is an electronic device that accepts data, performs computations, and makes logical decisions according to instructions that have been given to it; then produces meaningful information in a form that is useful to the user. In current world we live in, computers are almost used in all walks of life for different purposes. They have been deployed to solve different real life problems, from the simplest game playing up to the complex nuclear energy production. Computers are important and widely used in our society because they are cost-effective aids to problem solving in business, government, industry, education, etc. In order to solve a given problem, computers must be given the correct instruction about how they can solve it. The terms computer programs, software programs, or just programs are the instructions that tells the computer what to do. Computer requires programs to function, and a computer programs does nothing unless its instructions are executed by a CPU. Computer programming (often shortened to programming or coding) is the process of writing, testing, debugging/troubleshooting, and maintaining the source code of computer programs. Writing computer programs means writing instructions, that will make the computer follow and run a program based on those instructions. Each instruction is relatively simple, yet because of the computer's speed, it is able to run millions of instructions in a second. A computer program usually consists of two elements: Data – characteristics Code – action Computer programs (also know as source code) is often written by professionals known as Computer Programmers (simply programmers). Source code is written in one of programming languages. A programming language is an artificial language that can be used to control the behavior of a machine, particularly a computer. Programming languages, like natural language (such as Amharic), are defined by syntactic and semantic rules which describe their structure and meaning respectively. The syntax of a language describes the possible combinations of symbols that form a syntactically correct program. The meaning given to a combination of symbols is handled by semantics. Many programming languages have some form of written specification of their syntax and semantics; some are defined only by an official implementation. In general, programming languages allow humans to communicate instructions to machines. A main purpose of programming languages is to provide instructions to a computer. As such, programming languages differ from most other forms of human expression in that they require a greater degree of precision and completeness. When using a natural language to communicate with other people, human authors and speakers can be ambiguous and make small errors, and still expect their intent to be understood. However, computers do exactly what they are told to do, and cannot understand the code the programmer "intended" to write. So computers need to be instructed to perform all the tasks. The combination of the language definition, the program, and the program's inputs must fully specify the external behavior that occurs when the program is executed. Computer languages have relatively few, exactly defined, rules for composition of programs, and strictly controlled vocabularies in which unknown words must be defined before they can be used. 1
  3. 3. Available programming languages come in a variety of forms and types. Thousands of different programming languages have been developed, used, and discarded. Programming languages can be divided in to two major categories: low-level and high-level languages. Low-level languages Computers only understand one language and that is binary language or the language of 1s and 0s. Binary language is also known as machine language, one of low-level languages. In the initial years of computer programming, all the instructions were given in binary form. Although the computer easily understood these programs, it proved too difficult for a normal human being to remember all the instructions in the form of 0s and 1s. Therefore, computers remained mystery to a common person until other languages such as assembly language was developed, which were easier to learn and understand. Assembly language correspondences symbolic instructions and executable machine codes and was created to use letters (called mnemonics) to each machine language instructions to make it easier to remember or write. For example: ADD A, B – adds two numbers in memory location A and B Assembly language is nothing more than a symbolic representation of machine code, which allows symbolic designation of memory locations. However, no matter how close assembly language is to machine code, computers still cannot understand it. The assembly language must be translated to machine code by a separate program called assembler. The machine instruction created by the assembler from the original program (source code) is called object code. Thus assembly languages are unique to a specific computer (machine). Assemblers are written for each unique machine language. High-level languages Although programming in assembly language is not as difficult and error prone as stringing together ones and zeros, it is slow and cumbersome. In addition it is hardware specific. The lack of portability between different computers led to the development of high-level languages—so called because they permitted a programmer to ignore many low-level details of the computer's hardware. Further, it was recognized that the closer the syntax, rules, and mnemonics of the programming language could be to "natural language" the less likely it became that the programmer would inadvertently introduce errors (called "bugs") into the program. High-level languages are more English-like and, therefore, make it easier for programmers to "think" in the programming language. High-level languages also require translation to machine language before execution. This translation is accomplished by either a compiler or an interpreter. Compilers translate the entire source code program before execution. Interpreters translate source code programs one line at a time. Interpreters are more interactive than compilers. FORTRAN (FORmula TRANslator), BASIC (Bingers All Purpose Symbolic Instruction Code), PASCAL, C, C++, Java are some examples of high-level languages. The question of which language is best is one that consumes a lot of time and energy among computer professionals. Every language has its strengths and weaknesses. For example, FORTRAN is a particularly good language for processing numerical data, but it does not lend itself very well to organizing large programs. Pascal is very good for writing well-structured and readable programs, but it is not as flexible as the C programming language. C++ embodies powerful object-oriented features As might be expected in a dynamic and evolving field, there is no single standard for classifying programming languages. Another most fundamental ways programming languages are characterized (categorized) is by programming paradigm. A programming paradigm provides the programmer's view 2
  4. 4. of code execution. The most influential paradigms are examined in the next three sections, in approximate chronological order. Procedural Programming Languages Procedural programming specifies a list of operations that the program must complete to reach the desired state. Each program has a starting state, a list of operations to complete, and an ending point. This approach is also known as imperative programming. Integral to the idea of procedural programming is the concept of a procedure call. Procedures, also known as functions, subroutines, or methods, are small sections of code that perform a particular function. A procedure is effectively a list of computations to be carried out. Procedural programming can be compared to unstructured programming, where all of the code resides in a single large block. By splitting the programmatic tasks into small pieces, procedural programming allows a section of code to be re-used in the program without making multiple copies. It also makes it easier for programmers to understand and maintain program structure. Two of the most popular procedural programming languages are FORTRAN and BASIC. Structured Programming Languages Structured programming is a special type of procedural programming. It provides additional tools to manage the problems that larger programs were creating. Structured programming requires that programmers break program structure into small pieces of code that are easily understood. It also frowns upon the use of global variables and instead uses variables local to each subroutine. One of the wellknown features of structural programming is that it does not allow the use of the GOTO statement. It is often associated with a "top-down" approach to design. The top-down approach begins with an initial overview of the system that contains minimal details about the different parts. Subsequent design iterations then add increasing detail to the components until the design is complete. The most popular structured programming languages include C, Ada, and Pascal. Object-Oriented Programming Languages Object-oriented programming is one the newest and most powerful paradigms. In object- oriented programs, the designer specifies both the data structures and the types of operations that can be applied to those data structures. This pairing of a piece of data with the operations that can be performed on it is known as an object. A program thus becomes a collection of cooperating objects, rather than a list of instructions. Objects can store state information and interact with other objects, but generally each object has a distinct, limited role. 1.2 Problem solving Techniques Computer solves varieties of problems that can be expressed in a finite number of steps leading to a precisely defined goal by writing different programs. A program is not needed only to solve a problem but also it should be reliable, (maintainable) portable and efficient. In computer programming two facts are given more weight: The first part focuses on defining the problem and logical procedures to follow in solving it. The second introduces the means by which programmers communicate those procedures to the computer system so that it can be executed. There are system analysis and design tools, particularly flowchart and structure chart, that can be used to define the problem in terms of the steps to its solution. The programmer uses programming language to communicate the logic of the solution to the computer. 3
  5. 5. Before a program is written, the programmer must clearly understand what data are to be used, the desired result, and the procedure to be used to produce the result. The procedure, or solution, selected is referred to as an algorithm. An algorithm is defined as a step-by-step sequence of instructions that must terminate and describe how the data is to be processed to produce the desired outputs. Simply, algorithm is a sequence of instructions. Algorithms are a fundamental part of computing. There are three commonly used tools to help to document program logic (the algorithm). These are flowcharts, structured chart, and Pseudocode. We will use the three methods here. Generally, flowcharts work well for small problems but Pseudocode is used for larger problems. 1.2.1 Pseudocode Pseudocode (derived from pseudo and code) is a compact and informal high-level description of a computer algorithm that uses the structural conventions of programming languages, but typically omits detailes such as subroutines, variables declarations and system-specific syntax. The programming language is augmented with natural language descriptions of the details, where convenient, or with compact mathematical notation. The purpose of using pseudocode is that it may be easier for humans to read than conventional programming languages, and that it may be a compact and environmentindependent generic description of the key principles of an algorithm. No standard for pseudocode syntax exists, as a program in pseudocode is not an executable program. As the name suggests, pseudocode generally does not actually obey the synatx rules of any particular language; there is no systematic standard form, although any particular writer will generally borrow the appearance of a particular language. The programming process is a complicated one. You must first understand the program specifications, of course, Then you need to organize your thoughts and create the program. This is a difficult task when the program is not trivial (i.e. easy). You must break the main tasks that must be accomplished into smaller ones in order to be able to eventually write fully developed code. Writing pseudocode will save you time later during the construction & testing phase of a program's development. Example: Original Program Specification: Write a program that obtains two integer numbers from the user. It will print out the sum of those numbers. Pseudocode: Prompt the user to enter the first integer Prompt the user to enter a second integer Compute the sum of the two user inputs Display an output prompt that explains the answer as the sum Display the result 4
  6. 6. 1.2.2 Structured Charts Structured chart depicts the logical functions to the solution of the problem using a chart. It provides an overview that confirms the solution to the problem without excessive consideration to detail. It is highlevel in nature. Example: Write a program that asks the user to enter a temperature reading in centigrade and then prints the equivalent Fahrenheit value. Input Centigrade Process Prompt for centigrade value Read centigrade value Compute Fahrenheit value Display Fahrenheit value Output Fahrenheit CelsusToFarh (main func) centigard InPutCen centigard CalcFar Fahrenheit OutFahFenheit Put r ar 1.2.3 Flowchart A flowchart (also spelled flow-chart and flow chart) is a schematic representation of an algorithm or a process . The advantage of flowchart is it doesn’t depend on any particular programming language, so that it can used, to translate an algorithm to more than one programming language. Flowchart uses different symbols (geometrical shapes) to represent different processes. The following table shows some of the common symbols. 5
  7. 7. Example 1: - Draw flow chart of an algorithm to add two numbers and display their result. Algorithm description Read the rules of the two numbers (A and B) Add A and B Assign the sum of A and B to C Display the result ( c) The flow chart is: Start Read A, B C= A+B Print C End 6
  8. 8. Example 2: Write an algorithm description and draw a flow chart to check a number is negative or not. Algorithm description. 1/ Read a number x 2/ If x is less than zero write a message negative else write a message not negative Some times there are conditions in which it is necessary to execute a group of statements repeatedly. Until some condition is satisfied. This condition is called a loop. Loop is a sequence of instructions, which is repeated until some specific condition occurs. A loop normally consists of four parts. These are: Initialization: - Setting of variables of the computation to their initial values and setting the counter for determining to exit from the loop. Computation: - Processing Test: - Every loop must have some way of exiting from it or else the program would endlessly remain in a loop. Increment: - Re-initialization of the loop for the next loop. Example 3: - Write the algorithmic description and draw a flow chart to find the following sum. Sum = 1+2+3+…. + 50 Algorithmic description 1. Initialize sum too and counter to 1 1.1.If the counter is less than or equal to 50 1.2.Else • Exit • Add counter to sum • Increase counter by 1 • Repeat step 1.1 2. Write sum 7
  9. 9. 1.3 System Development Life Cycle (SDLC) The Systems Development Life Cycle (SDLC) is a conceptual model used in project management that describes the stages involved in a computer system development project from an initial feasibility study through maintenance of the completed application. The phases of SDLC is discussed below briefly. 1.3.1 Feasibility study The first step is to identify a need for the new system. This will include determining whether a business problem or opportunity exists, conducting a feasibility study to determine if the proposed solution is cost effective, and developing a project plan. This process may involve end users who come up with an idea for improving their work or may only involve IS people. Ideally, the process occurs in tandem with a review of the organization's strategic plan to ensure that IT is being used to help the organization achieve its strategic objectives. Management may need to approve concept ideas before any money is budgeted for its development. A preliminary analysis, determining the nature and scope of the problems to be solved is carried out. Possible solutions are proposed, describing the cost and benefits. Finally, a preliminary plan for decision making is produced. The process of developing a large information system can be very costly, and the investigation stage may require a preliminary study called a feasibility study, which includes e.g. the following components: a. Organizational Feasibility How well the proposed system supports the strategic objectives of the organization. 8
  10. 10. b. Economic Feasibility Cost savings Increased revenue Decreased investment Increased profits c. Technical Feasibility Hardware, software, and network capability, reliability, and availability d. Operational Feasibility End user acceptance Management support Customer, supplier, and government requirements 1.3.2 Requirements analysis Requirements analysis is the process of analyzing the information needs of the end users, the organizational environment, and any system presently being used, developing the functional requirements of a system that can meet the needs of the users. Also, the requirements should be recorded in a document, email, user interface storyboard, executable prototype, or some other form. The requirements documentation should be referred to throughout the rest of the system development process to ensure the developing project aligns with user needs and requirements. End users must be involved in this process to ensure that the new system will function adequately and meets their needs and expectations. 1.3.3 Designing solution After the requirements have been determined, the necessary specifications for the hardware, software, people, and data resources, and the information products that will satisfy the functional requirements of the proposed system can be determined. The design will serve as a blueprint for the system and helps detect problems before these errors or problems are built into the final system. The created system design, but must reviewed by users to ensure the design meets users' needs. 1.3.4 Testing designed solution A smaller test system is sometimes a good idea in order to get a “proof-of-concept” validation prior to committing funds for large scale fielding of a system without knowing if it really works as intended by the user. 1.3.5 Implementation The real code is written here. Systems implementation is the construction of the new system and its delivery into production or day-to-day operation.The key to understanding the implementation phase is to 9
  11. 11. realize that there is a lot more to be done than programming. Implementation requires programming, but it also requires database creation and population, and network installation and testing. You also need to make sure the people are taken care of with effective training and documentation. Finally, if you expect your development skills to improve over time, you need to conduct a review of the lessons learned. 1.3.6 Unit testing Normally programs are written as a series of individual modules, these subject to separate and detailed test. 1.3.7 Integration and System testing Brings all the pieces together into a special testing environment, then checks for errors, bugs and interoperability. The system is tested to ensure that interfaces between modules work (integration testing), the system works on the intended platform and with the expected volume of data (volume testing) and that the system does what the user requires (acceptance/beta testing). 1.3.8 Maintenance What happens during the rest of the software's life: changes, correction, additions, moves to a different computing platform and more. This, the least glamorous and perhaps most important step of all, goes on seemingly forever. 10
  12. 12. Chapter Two 2. C++ Basics ........................................................................................ 2 2.1. Structure of C++ Program................................................................................... 2 2.2. C++ IDE .............................................................................................................. 2 2.3. Showing Sample program ................................................................................... 3 2.4. Basic Elements .................................................................................................... 5 2.4.1. Keywords (reserved words) ........................................................................ 5 2.4.2. Identifiers .................................................................................................... 5 2.4.3. Literals ........................................................................................................ 6 2.4.4. Comments ................................................................................................... 6 2.5. Data Types, Variables, and Constants ................................................................ 7 2.5.1. Variables ..................................................................................................... 7 2.5.2. Basic Data Types ........................................................................................ 9 2.5.3. Signed and Unsigned ................................................................................ 10 2.5.4. Characters ................................................................................................. 12 2.5.5. Characters and Numbers ........................................................................... 12 2.6. Operators ........................................................................................................... 12 2.6.1. Assignment Operators ............................................................................... 13 2.6.2. Arithmetic Operators ................................................................................ 14 2.6.3. Relational Operators ................................................................................. 15 2.6.4. Logical Operators...................................................................................... 16 2.6.5. Bitwise Operators...................................................................................... 17 2.6.6. Increment/decrement Operators ................................................................ 18 2.7. Precedence of Operators ................................................................................... 18 2.8. Simple Type Conversion................................................................................... 20 2.9. Statements ......................................................................................................... 21 2.10. Input/Output Statements ............................................................................... 21 -1-
  13. 13. 2. C++ Basics 2.1. Structure of C++ Program A C++ program has the following structure [Comments] [Preprocessor directives] [Global variable declarations] [Prototypes of functions] [Definitions of functions] 2.2. C++ IDE The complete development cycle in C++ is: Write the program, compile the source code, link the program, and run it. Writing a Program To write a source code, your compiler may have its own built-in text editor, or you may be using a commercial text editor or word processor that can produce text files. The important thing is that whatever you write your program in, it must save simple, plaintext files, with no word processing commands embedded in the text. Examples of safe editors include Windows Notepad, the DOS Edit command, EMACS, and vi. Many commercial word processors, such as WordPerfect, Word, and dozens of others, also offer a method for saving simple text files. The files you create with your editor are called source files, and for C++ they typically are named with the extension .CPP. Compiling Your source code file can't be executed, or run, as a program can. To turn your source code into a program, you use a compiler. How you invoke your compiler, and how you tell it where to find your source code, will vary from compiler to compiler; check your documentation. In Borland's Turbo C++ you pick the RUN menu command or type tc <filename> -2-
  14. 14. from the command line, where <filename> is the name of your source code file (for example, test.cpp). Other compilers may do things slightly differently. After your source code is compiled, an object file is produced. This file is often named with the extension .OBJ. This is still not an executable program, however. To turn this into an executable program, you must run your linker. Linking C++ programs are typically created by linking together one or more OBJ files with one or more libraries. A library is a collection of linkable files that were supplied with your compiler, that you purchased separately, or that you created and compiled. All C++ compilers come with a library of useful functions (or procedures) and classes that you can include in your program. A function is a block of code that performs a service, such as adding two numbers or printing to the screen. A class is a collection of data and related functions. Summary The steps to create an executable file are 1. Create a source code file, with a .CPP extension. 2. Compile the source code into a file with the .OBJ extension. 3. Link your OBJ file with any needed libraries to produce an executable program. 2.3. Showing Sample program Any meaningful program written in C++ has to contain a number of components: the main function; some variable declarations; and some executable statements. For example, the following is a very basic C++ program: 1: #include <iostream.h> 2: 3: int main() 4: { 5: cout << "Hello World!n"; 6: return 0; 7: } On line 1, the file iostream.h is included in the file. The first character is the # symbol, which is a signal to the preprocessor. Each time you start your compiler, the preprocessor is run. The preprocessor reads through your source code, looking for lines that begin with the pound symbol (#), and acts on those lines before the compiler runs. -3-
  15. 15. include is a preprocessor instruction that says, "What follows is a filename. Find that file and read it in right here." The angle brackets around the filename tell the preprocessor to look in all the usual places for this file. If your compiler is set up correctly, the angle brackets will cause the preprocessor to look for the file iostream.h in the directory that holds all the H files for your compiler. The file iostream.h (Input-Output-Stream) is used by cout, which assists with writing to the screen. The effect of line 1 is to include the file iostream.h into this program as if you had typed it in yourself. The preprocessor runs before your compiler each time the compiler is invoked. The preprocessor translates any line that begins with a pound symbol (#) into a special command, getting your code file ready for the compiler. Line 3 begins the actual program with a function named main(). Every C++ program has a main() function. In general, a function is a block of code that performs one or more actions. Usually functions are invoked or called by other functions, but main() is special. When your program starts, main() is called automatically. main(), like all functions, must state what kind of value it will return. The return value type for main() in HELLO.CPP is int, which means that this function will return an integer value. All functions begin with an opening brace ({) and end with a closing brace (}). The braces for the main() function are on lines 4 and 7. Everything between the opening and closing braces is considered a part of the function. The meat and potatoes of this program is on line 5. The object cout is used to print a message to the screen. cout is used in C++ to print strings and values to the screen. A string is just a set of characters. Here's how cout is used: type the word cout, followed by the output redirection operator (<<). Whatever follows the output redirection operator is written to the screen. If you want a string of characters written, be sure to enclose them in double quotes ("), as shown on line 5. A text string is a series of printable characters. The final two characters, n, tell cout to put a new line after the words Hello World! All ANSI-compliant programs declare main() to return an int. This value is "returned" to the operating system when your program completes. Some programmers signal an error by returning the value 1. -4-
  16. 16. The main() function ends on line 7 with the closing brace. 2.4. Basic Elements 2.4.1. Keywords (reserved words) Reserved/Key words have a unique meaning within a C++ program. These symbols, the reserved words, must not be used for any other purposes. All reserved words are in lower-case letters. The following asm const_cast dynamic_cast explicit goto namespace reinterpret_cast static_cast throw union wchar_t are some of the reserved words of C++. auto class do extern if new register static true unsigned bool const double false inline operator return struct tr y us i ng break char delete float int private short switch typedef virtual case continue else for l ong protected signed template typeid void catch default enum friend mutable public sizeof this typename volatile Notice that main is not a reserved word. However, this is a fairly technical distinction, and for practical purposes you are advised to treat main, cin, and cout as if they were reserved as well. 2.4.2. Identifiers An identifier is name associated with a function or data object and used to refer to that function or data object. An identifier must:  Start with a letter or underscore  Consist only of letters, the digits 0-9, or the underscore symbol _  Not be a reserved word Syntax of an identifier Letter Letter - Digit - -5-
  17. 17. For the purposes of C++ identifiers, the underscore symbol, _, is considered to be a letter. Its use as the first character in an identifier is not recommended though, because man y library functions in C++ use such identifiers. Similarly, the use of two consecutive underscore symbols, _ _, is forbidden. The following are valid identifiers Length days_in_year DataSet1 Int _Pressure first_one Although using _Pressure is not recommended. Profit95 first_1 The following are invalid: days-in-year throw 1data my__best int No## first.val bestWish! Although it may be easier to type a program consisting of single character identifiers, modifying or correcting the program becomes more and more difficult. The minor typing effort of using meaningful identifiers will repay itself many fold in the avoidance of simple programming errors when the program is modified. At this stage it is worth noting that C++ is case-sensitive. That is lower-case letters are treated as distinct from upper-case letters. Thus the word NUM different from the word num or the word Num. Identifiers can be used to identify variable or constants or functions. Function identifier is an identifier that is used to name a function. 2.4.3. Literals Literals are constant values which can be a number, a character of a string. For example the number 129.005, the character ‘A’ and the string “hello world” are all literals. There is no identifier that identifies them. 2.4.4. Comments A comment is a piece of descriptive text which explains some aspect of a program. Program comments are totally ignored by the compiler and are only intended for human readers. C++ provides two types of comment delimiters:  Anything after // (until the end of the line on which it appears) is considered a comment. -6-
  18. 18.  Anything enclosed by the pair /* and */ is considered a comment. 2.5. Data Types, Variables, and Constants 2.5.1. Variables A variable is a symbolic name for a memory location in which data can be stored and subsequently recalled. Variables are used for holding data values so that they can be utilized in various computations in a program. All variables have two important attributes:  A type, which is, established when the variable is defined (e.g., integer, float, character). Once defined, the type of a C++ variable cannot be changed.  A value, which can be changed by assigning a new value to the variable. The kind of values a variable can assume depends on its type. For example, an integer variable can only take integer values (e.g., 2, 100, -12) not real numbers like 0.123. Variable Declaration Declaring a variable means defining (creating) a variable. You create or define a variable by stating its type, followed by one or more spaces, followed by the variable name and a semicolon. The variable name can be virtually any combination of letters, but cannot contain spaces and the first character must be a letter or an underscore. Variable names cannot also be the same as keywords used by C++. Legal variable names include x, J23qrsnf, and myAge. Good variable names tell you what the variables are for; using good names makes it easier to understand the flow of your program. The following statement defines an integer variable called myAge: int myAge; IMPORTANT- Variables must be declared before used! As a general programming practice, avoid such horrific names as J23qrsnf, and restrict single-letter variable names (such as x or i) to variables that are used only very briefly. Try to use expressive names such as myAge or howMany. -7-
  19. 19. A point worth mentioning again here is that C++ is case-sensitive. In other words, uppercase and lowercase letters are considered to be different. A variable named age is different from Age, which is different from AGE. Creating More Than One Variable at a Time You can create more than one variable of the same type in one statement by writing the type and then the variable names, separated by commas. For example: int myAge, myWeight; // two int variables long area, width, length; // three longs As you can see, myAge and myWeight are each declared as integer variables. The second line declares three individual long variables named area, width, and length. However keep in mind that you cannot mix types in one definition statement. Assigning Values to Your Variables You assign a value to a variable by using the assignment operator (=). Thus, you would assign 5 to Width by writing int Width; Width = 5; You can combine these steps and initialize Width when you define it by writing int Width =5; Initialization looks very much like assignment, and with integer variables, the difference is minor. The essential difference is that initialization takes place at the moment you create the variable. Just as you can define more than one variable at a time, you can initialize more than one variable at creation. For example: // create two int variables and initialize them int width = 5, length = 7; This example initializes the integer variable width to the value 5 and the length variable to the value 7. It is possible to even mix definitions and initializations: int myAge = 39, yourAge, hisAge = 40; This example creates three type int variables, and it initializes the first and third. -8-
  20. 20. 2.5.2. Basic Data Types When you define a variable in C++, you must tell the compiler what kind of variable it is: an integer, a character, and so forth. This information tells the compiler how much room to set aside and what kind of value you want to store in your variable. Several data types are built into C++. The varieties of data types allow programmers to select the type appropriate to the needs of the applications being developed. The data types supported by C++ can be classified as basic (fundamental) data types, user defined data types, derived data types and empty data types. However, the discussion here will focus only on the basic data types. Basic (fundamental) data types in C++ can be conveniently divided into numeric and character types. Numeric variables can further be divided into integer variables and floating-point variables. Integer variables will hold only integers whereas floating number variables can accommodate real numbers. Both the numeric data types offer modifiers that are used to vary the nature of the data to be stored. The modifiers used can be short, long, signed and unsigned. The data types used in C++ programs are described in Table 1.1. This table shows the variable type, how much room it takes in memory, and what kinds of values can be stored in these variables. The values that can be stored are determined by the size of the variable types. Type unsigned short int short int(signed short int) unsigned long int long int(signed long int) int unsigned int signed int char float double long double Size 2 bytes 2 bytes 4 bytes 4 bytes 2 bytes 2 bytes 2 bytes 1 byte 4 bytes 8 bytes 10 bytes Table C++ data types and their ranges -9- Values 0 to 65,535 -32,768 to 32,767 0 to 4,294,967,295 -2,147,483,648 to 2,147,483,647 -32,768 to 32,767 0 to 65,535 -32,768 to 32,767 256 character values 3.4e-38 to 3.4e38 1.7e-308 to 1.7e308 1.2e-4932 to 1.2e4932
  21. 21. 2.5.3. Signed and Unsigned As shown above, integer types come in two varieties: signed and unsigned. The idea here is that sometimes you need negative numbers, and sometimes you don't. Integers (short and long) without the word "unsigned" are assumed to be signed. signed integers are either negative or positive. Unsigned integers are always positive. Because you have the same number of bytes for both signed and unsigned integers, the largest number you can store in an unsigned integer is twice as big as the largest positive number you can store in a signed integer. An unsigned short integer can handle numbers from 0 to 65,535. Half the numbers represented by a signed short are negative, thus a signed short can only represent numbers from -32,768 to 32,767. Example: A demonstration of the use of variables. 2: #include <iostream.h> 3: 4: int main() 5: { 6: unsigned short int Width = 5, Length; 7: Length = 10; 8: 9: // create an unsigned short and initialize with result 10: // of multiplying Width by Length 11: unsigned short int Area = Width * Length; 12: 13: cout << "Width:" << Width << "n"; 14: cout << "Length: " << Length << endl; 15: cout << "Area: " << Area << endl; 16: return 0; 17: } Output: Width:5 Length: 10 Area: 50 Line 2 includes the required include statement for the iostream's library so that cout will work. Line 4 begins the program. On line 6, Width is defined as an unsigned short integer, and its value is initialized to 5. Another unsigned short integer, Length, is also defined, but it is not initialized. On line 7, the value 10 is assigned to Length. On line 11, an unsigned short integer, Area, is defined, and it is initialized with the value obtained by multiplying Width times Length. On lines 13-15, the values of the variables are printed to the screen. Note that the special word endl creates a new line. - 10 -
  22. 22. Wrapping around integer values The fact that unsigned long integers have a limit to the values they can hold is only rarely a problem, but what happens if you do run out of room? When an unsigned integer reaches its maximum value, it wraps around and starts over, much as a car odometer might. The following example shows what happens if you try to put too large a value into a short integer. Example: A demonstration of putting too large 1: #include <iostream.h> 2: int main() 3: { 4: unsigned short int smallNumber; 5: smallNumber = 65535; 6: cout << "small number:" << smallNumber 7: smallNumber++; 8: cout << "small number:" << smallNumber 9: smallNumber++; 10: cout << "small number:" << smallNumber 11: return 0; 12: } Output: small number:65535 small number:0 small number:1 a value in a variable << endl; << endl; << endl; A signed integer is different from an unsigned integer, in that half of the values you can represent are negative. Instead of picturing a traditional car odometer, you might picture one that rotates up for positive numbers and down for negative numbers. One mile from 0 is either 1 or -1. When you run out of positive numbers, you run right into the largest negative numbers and then count back down to 0. The whole idea here is putting a number that is above the range of the variable can create unpredictable problem. Example: A demonstration of integer. 1: #include <iostream.h> 2: int main() 3: { 4: short int smallNumber; 5: smallNumber = 32767; 6: cout << "small number:" 7: smallNumber++; 8: cout << "small number:" 9: smallNumber++; 10: cout << "small number:" 11: return 0; 12: } Output: small number:32767 adding too large a number to a signed << smallNumber << endl; << smallNumber << endl; << smallNumber << endl; - 11 -
  23. 23. small number:-32768 small number:-32767 IMPORTANT – To any variable, do not assign a value that is beyond its range! 2.5.4. Characters Character variables (type char) are typically 1 byte, enough to hold 256 values. A char can be interpreted as a small number (0-255) or as a member of the ASCII set. ASCII stands for the American Standard Code for Information Interchange. The ASCII character set and its ISO (International Standards Organization) equivalent are a way to encode all the letters, numerals, and punctuation marks. In the ASCII code, the lowercase letter "a" is assigned the value 97. All the lower- and uppercase letters, all the numerals, and all the punctuation marks are assigned values between 1 and 128. Another 128 marks and symbols are reserved for use by the computer maker, although the IBM extended character set has become something of a standard. 2.5.5. Characters and Numbers When you put a character, for example, `a', into a char variable, what is really there is just a number between 0 and 255. The compiler knows, however, how to translate back and forth between characters (represented by a single quotation mark and then a letter, numeral, or punctuation mark, followed by a closing single quotation mark) and one of the ASCII values. The value/letter relationship is arbitrary; there is no particular reason that the lowercase "a" is assigned the value 97. As long as everyone (your keyboard, compiler, and screen) agrees, there is no problem. It is important to realize, however, that there is a big difference between the value 5 and the character `5'. The latter is actually valued at 53, much as the letter `a' is valued at 97. 2.6. Operators C++ provides operators for composing arithmetic, relational, logical, bitwise, and conditional expressions. It also provides operators which produce useful side-effects, such as assignment, increment, and decrement. We will look at each category of - 12 -
  24. 24. operators in turn. We will also discuss the precedence rules which govern the order of operator evaluation in a multi-operator expression. 2.6.1. Assignment Operators The assignment operator is used for storing a value at some memory location (typically denoted by a variable). Its left operand should be an lvalue, and its right operand may be an arbitrary expression. The latter is evaluated and the outcome is stored in the location denoted by the lvalue. An lvalue (standing for left value) is anything that denotes a memory location in which a value may be stored. The only kind of lvalue we have seen so far is a variable. Other kinds of lvalues (based on pointers and references) will be described later. The assignment operator has a number of variants, obtained by combining it with the arithmetic and bitwise operators. Operato r = += -= *= /= %= &= |= ^= <<= >>= Example Equivalent To n = 25 n += 25 n -= 25 n *= 25 n /= 25 n %= 25 n &= 0xF2F2 n |= 0xF2F2 n ^= 0xF2F2 n <<= 4 n >>= 4 n = n + 25 n = n - 25 n = n * 25 n = n / 25 n = n % 25 n = n & 0xF2F2 n = n | 0xF2F2 n = n ^ 0xF2F2 n = n << 4 n = n >> 4 An assignment operation is itself an expression whose value is the value stored in its left operand. An assignment operation can therefore be used as the right operand of another assignment operation. Any number of assignments can be concatenated in this fashion to form one expression. For example: int m, n, p; m = n = p = 100; m = (n = p = 100) + 2; // means: n = (m = (p = 100)); // means: m = (n = (p = 100)) + 2; This is equally applicable to other forms of assignment. For example: - 13 -
  25. 25. m = 100; m += n = p = 10; // means: m = m + (n = p = 10); 2.6.2. Arithmetic Operators C++ provides five basic arithmetic operators. These are summarized in table below Operator + * / % Name Example Addition 12 + 4.9 Subtraction 3.98 - 4 Multiplication 2 * 3.4 Division 9 / 2.0 Remainder 13 % 3 Arithmetic operators. // gives 16.9 // gives -0.02 // gives 6.8 // gives 4.5 //gives 1 Except for remainder (%) all other arithmetic operators can accept a mix of integer and real operands. Generally, if both operands are integers then the result will be an integer. However, if one or both of the operands are reals then the result will be a real (or double to be exact). When both operands of the division operator (/) are integers then the division is performed as an integer division and not the normal division we are used to. Integer division always results in an integer outcome (i.e., the result is always rounded down). For example: 9 / 2 -9 / 2 // gives 4, not 4.5! // gives -5, not -4! Unintended integer divisions are a common source of programming errors. To obtain a real division when both operands are integers, you should cast one of the operands to be real: int int double cost = 100; volume = 80; unitPrice = cost / (double) volume; // gives 1.25 The remainder operator (%) expects integers for both of its operands. It returns the remainder of integer-dividing the operands. For example 13%3 is calculated by integer dividing 13 by 3 to give an outcome of 4 and a remainder of 1; the result is therefore 1. - 14 -
  26. 26. It is possible for the outcome of an arithmetic operation to be too large for storing in a designated variable. This situation is called an overflow. The outcome of an overflow is machine-dependent and therefore undefined. For example: unsigned char k = 10 * 92; // overflow: 920 > 255 It is illegal to divide a number by zero. This results in a run-time division-by-zero failure, which typically causes the program to terminate. There are also a number of predefined library functions, which perform arithmetic operations. As with input & output statements, if you want to use these you must put a #include statement at the start of your program. Some of the more common library functions are Header File <stdlib.h> <math.h> <math.h> <math.h> <math.h> <math.h> <math.h> Function summarised Parameter Type(s) Result abs(i) cos(x) fabs(x) pow(x, y) sin(x) sqrt(x) tan(x) Type int float float float float float float int float float float float float float below. Result Absolute value of i Cosine of x (x is in radians) Absolute value of x x raised to the power of y Sine of x (x is in radians) Square root of x Tangent of x 2.6.3. Relational Operators C++ provides six relational operators for comparing numeric quantities. These are summarized in table below. Relational operators evaluate to 1 (representing the true outcome) or 0 (representing the false outcome). Operator == != < <= > >= Name Example Equality 5 == 5 // gives 1 Inequality 5 != 5 // gives 0 Less Than 5 < 5.5 // gives 1 Less Than or Equal 5 <= 5 // gives 1 Greater Than 5 > 5.5 // gives 0 Greater Than or Equal 6.3 >= 5 // gives 1 Relational operators - 15 -
  27. 27. Note that the <= and >= operators are only supported in the form shown. In particular, =< and => are both invalid and do not mean anything. The operands of a relational operator must evaluate to a number. Characters are valid operands since they are represented by numeric values. For example (assuming ASCII coding): 'A' < 'F' // gives 1 (is like 65 < 70) The relational operators should not be used for comparing strings, because this will result in the string addresses being compared, not the string contents. For example, the expression "HELLO" < "BYE" causes the address of "HELLO" to be compared to the address of "BYE". As these addresses are determined by the compiler (in a machinedependent manner), the outcome may be 0 or 1, and is therefore undefined. C++ provides library functions (e.g., strcmp) for the lexicographic comparison of string. 2.6.4. Logical Operators C++ provides three logical operators for combining logical expression. These are summarized in the table below. Like the relational operators, logical operators evaluate to 1 or 0. Operator ! && || Name Example Logical Negation !(5 == 5) // gives 0 Logical And 5 < 6 && 6 < 6 // gives 1 Logical Or 5 < 6 || 6 < 5 // gives 1 Logical operators Logical negation is a unary operator, which negates the logical value of its single operand. If its operand is nonzero it produces 0, and if it is 0 it produces 1. Logical and produces 0 if one or both of its operands evaluate to 0. Otherwise, it produces 1. Logical or produces 0 if both of its operands evaluate to 0. Otherwise, it produces 1. Note that here we talk of zero and nonzero operands (not zero and 1). In general, any nonzero value can be used to represent the logical true, whereas only zero represents the logical false. The following are, therefore, all valid logical expressions: - 16 -
  28. 28. !20 10 && 5 10 || 5.5 10 && 0 // gives 0 // gives 1 // gives 1 // gives 0 C++ does not have a built-in boolean type. It is customary to use the type int for this purpose instead. For example: int int sorted = 0; // false balanced = 1; // true 2.6.5. Bitwise Operators C++ provides six bitwise operators for manipulating the individual bits in an integer quantity. These are summarized in the table below. Operator ~ & | ^ << >> Name Example Bitwise Negation ~'011' Bitwise And '011' & '027' Bitwise Or '011' | '027' Bitwise Exclusive '011' ^ '027' Or Bitwise Left Shift '011' << 2 Bitwise Right Shift '011' >> 2 Bitwise operators // gives '366' // gives '001' // gives '037' // gives '036' // gives '044' // gives '002' Bitwise operators expect their operands to be integer quantities and treat them as bit sequences. Bitwise negation is a unary operator which reverses the bits in its operands. Bitwise and compares the corresponding bits of its operands and produces a 1 when both bits are 1, and 0 otherwise. Bitwise or compares the corresponding bits of its operands and produces a 0 when both bits are 0, and 1 otherwise. Bitwise exclusive or compares the corresponding bits of its operands and produces a 0 when both bits are 1 or both bits are 0, and 1 otherwise. Bitwise left shift operator and bitwise right shift operator both take a bit sequence as their left operand and a positive integer quantity n as their right operand. The former produces a bit sequence equal to the left operand but which has been shifted n bit positions to the left. The latter produces a bit sequence equal to the left operand but which has been shifted n bit positions to the right. Vacated bits at either end are set to 0. - 17 -
  29. 29. Table 2.1 illustrates bit sequences for the sample operands and results in Table 2.Error! Bookmark not defined.. To avoid worrying about the sign bit (which is machine dependent), it is common to declare a bit sequence as an unsigned quantity: unsigned char x = '011'; unsigned char y = '027'; Table 2.1 Example x y ~x x&y x|y x^y x << 2 x >> 2 How the bits are calculated. Octal Value 011 027 366 001 037 036 044 002 Bit Sequence 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 0 1 1 0 0 0 1 1 0 1 1 1 0 0 1 1 0 1 1 0 1 1 1 0 1 1 0 0 0 2.6.6. Increment/decrement Operators The auto increment (++) and auto decrement (--) operators provide a convenient way of, respectively, adding and subtracting 1 from a numeric variable. These are summarized in the following table. The examples assume the following variable definition: int k = 5; Operator ++ ++ Name Auto Increment (prefix) Auto Increment (postfix) Example ++k + 10 k++ + 10 --- Auto Decrement (prefix) --k + 10 Auto Decrement (postfix) k-- + 10 Increment and decrement operators // gives 16 // gives 15 // gives 14 // gives 15 Both operators can be used in prefix and postfix form. The difference is significant. When used in prefix form, the operator is first applied and the outcome is then used in the expression. When used in the postfix form, the expression is evaluated first and then the operator applied. Both operators may be applied to integer as well as real variables, although in practice real variables are rarely useful in this form. 2.7. Precedence of Operators The order in which operators are evaluated in an expression is significant and is determined by precedence rules. These rules divide the C++ operators into a number of - 18 -
  30. 30. precedence levels. Operators in higher levels take precedence over operators in lower levels. Level Highest Operator Kind Unary Both Binary Left to Right Unary Right to Left Binary Left to Right Binary :: Order Left to Right () [] -> . + ++ ! * new - -- ~ & delete ->* .* * / + - Binary Left to Right << >> Binary Left to Right < <= Binary Left to Right == != Binary Left to Right & Binary Left to Right ^ Binary Left to Right | Binary Left to Right & Binary Left to Right || Binary Left to Right ?: Ternary Left to Right Binary Right to Left Binary Left to Right sizeof() % > >= & = *= ^= &= <<= -= Lowest += /= %= |= >>= , For example, in a == b + c * d c * d is evaluated first because * has a higher precedence than + and ==. The result is then added to b because + has a higher precedence than ==, and then == is evaluated. Precedence rules can be overridden using brackets. For example, rewriting the above expression as a == (b + c) * d - 19 -
  31. 31. causes + to be evaluated before *. Operators with the same precedence level are evaluated in the order specified by the last column of Table 2.7. For example, in a = b += c the evaluation order is right to left, so first b += c is evaluated, followed by a = b. 2.8. Simple Type Conversion A value in any of the built-in types we have see so far can be converted (type-cast) to any of the other types. For example: (int) 3.14 // converts 3.14 to an int to give 3 (long) 3.14 // converts 3.14 to a long to give 3L (double) 2 // converts 2 to a double to give 2.0 (char) 122 // converts 122 to a char whose code is 122 (unsigned short) 3.14 // gives 3 as an unsigned short As shown by these examples, the built-in type identifiers can be used as type operators. Type operators are unary (i.e., take one operand) and appear inside brackets to the left of their operand. This is called explicit type conversion. When the type name is just one word, an alternate notation may be used in which the brackets appear around the operand: int(3.14) // same as: (int) 3.14 In some cases, C++ also performs implicit type conversion. This happens when values of different types are mixed in an expression. For example: double d = 1; int i = 10.5; i = i + d; // d receives 1.0 // i receives 10 // means: i = int(double(i) + d) In the last example, i + d involves mismatching types, so i is first converted to double (promoted) and then added to d. The result is a double which does not match the type of i on the left side of the assignment, so it is converted to int (demoted) before being assigned to i. The above rules represent some simple but common cases for type conversion. - 20 -
  32. 32. 2.9. Statements This chapter introduces the various forms of C++ statements for composing programs. Statements represent the lowest-level building blocks of a program. Roughly speaking, each statement represents a computational step which has a certain side-effect. (A sideeffect can be thought of as a change in the program state, such as the value of a variable changing because of an assignment.) Statements are useful because of the side-effects they cause, the combination of which enables the program to serve a specific purpose (e.g., sort a list of names). A running program spends all of its time executing statements. The order in which statements are executed is called flow control (or control flow). This term reflect the fact that the currently executing statement has the control of the CPU, which when completed will be handed over (flow) to another statement. Flow control in a program is typically sequential, from one statement to the next, but may be diverted to other paths by branch statements. Flow control is an important consideration because it determines what is executed during a run and what is not, therefore affecting the overall outcome of the program. Like many other procedural languages, C++ provides different forms of statements for different purposes. Declaration statements are used for defining variables. Assignmentlike statements are used for simple, algebraic computations. Branching statements are used for specifying alternate paths of execution, depending on the outcome of a logical condition. Loop statements are used for specifying computations which need to be repeated until a certain logical condition is satisfied. Flow control statements are used to divert the execution path to another part of the program. We will discuss these in turn. 2.9.1. Input/Output Statements The most common way in which a program communicates with the outside world is through simple, character-oriented Input/Output (IO) operations. C++ provides two useful operators for this purpose: >> for input and << for output. We have already seen examples of output using <<. Example 2.1 also illustrates the use of >> for input. Example - 21 -
  33. 33. #include <iostream.h> int main (void) { int workDays = 5; float workHours = 7.5; float payRate, weeklyPay; cout << "What is the hourly pay rate? "; cin >> payRate; } weeklyPay = workDays * workHours * payRate; cout << "Weekly Pay = "; cout << weeklyPay; cout << 'n'; Analysis This line outputs the prompt ‘What is the hourly pay rate? ’ to seek user input. This line reads the input value typed by the user and copies it to payRate. The input operator >> takes an input stream as its left operand (cin is the standard C++ input stream which corresponds to data entered via the keyboard) and a variable (to which the input data is copied) as its right operand. When run, the program will produce the following output (user input appears in bold): What is the hourly pay rate? 33.55 Weekly Pay = 1258.125 Both << and >> return their left operand as their result, enabling multiple input or multiple output operations to be combined into one statement. This is illustrated by example below which now allows the input of both the daily work hours and the hourly pay rate. Example #include <iostream.h> int main (void) { int workDays = 5; float workHours, payRate, weeklyPay; cout << "What are the work hours and the hourly pay rate? "; cin >> workHours >> payRate; weeklyPay = workDays * workHours * payRate; - 22 -
  34. 34. cout << "Weekly Pay = " << weeklyPay << 'n'; } Analysis This line reads two input values typed by the user and copies them to workHours and payRate, respectively. The two values should be separated by white space (i.e., one or more space or tab characters). This statement is equivalent to: (cin >> workHours) >> payRate; Because the result of >> is its left operand, (cin >> workHours) evaluates to cin which is then used as the left operand of the next >> operator. This line is the result of combining lines 10-12 from example 2.1. It outputs "Weekly Pay = ", followed by the value of weeklyPay, followed by a newline character. This statement is equivalent to: ((cout << "Weekly Pay = ") << weeklyPay) << 'n'; Because the result of << is its left operand, (cout << "Weekly Pay = ") evaluates to cout which is then used as the left operand of the next << operator, etc. When run, the program will produce the following output: What are the work hours and the hourly pay rate? 7.5 33.55 Weekly Pay = 1258.125 2.9.2. Null statement Syntax: ; Description: Do nothing 2.9.3. The block statement Syntax: { [<Declarations>]. <List of statements/statement block>. } Any place you can put a single statement, you can put a compound statement, also called a block. A block begins with an opening brace ({) and ends with a closing brace (}). - 23 -
  35. 35. Although every statement in the block must end with a semicolon, the block itself does not end with a semicolon. For example { temp = a; a = b; b = temp; } This block of code acts as one statement and swaps the values in the variables a and b. 2.9.4. The Assignment statement. Syntax: <Variable Identifier> = < expression>; Description: The <expression> is evaluated and the resulting value is stored in the memory space reserved for <variable identifier>. Eg: - int x,y ; x=5; y=x+3; x=y*y; - 24 -
  36. 36. Chapter Three 3. Control Statements......................................................................................................... 1 3.1. INTRODUCTION ............................................................................................................... 1 3.2. CONDITIONAL STATEMENTS .......................................................................................... 1 3.2.1. The if Statement .................................................................................................... 1 3.2.2. The switch Statement ............................................................................................ 3 3.3. LOOPING STATEMENTS .................................................................................................. 5 3.3.1. The ‘for’ Statement ............................................................................................... 6 3.3.2. The ‘while’ Statement ........................................................................................... 5 3.3.3. The ‘do…while’ Statement ................................................................................... 8 3.4. OTHER STATEMENTS ...................................................................................................... 8 3.4.1. The ‘continue’ Statement ...................................................................................... 8 3.4.2. The ‘break’ Statement ........................................................................................... 9 3.4.3. The ‘goto’ Statement ........................................................................................... 10 3.4.4. The ‘return’ Statement......................................................................................... 10
  37. 37. 3. Control Statements 3.1. Introduction A running program spends all of its time executing statements. The order in which statements are executed is called flow control (or control flow). This term reflect the fact that the currently executing statement has the control of the CPU, which when completed will be handed over (flow) to another statement. Flow control in a program is typically sequential, from one statement to the next, but may be diverted to other paths by branch statements. Flow control is an important consideration because it determines what is executed during a run and what is not, therefore affecting the overall outcome of the program. Like many other procedural languages, C++ provides different forms of statements for different purposes. Declaration statements are used for defining variables. Assignment-like statements are used for simple, algebraic computations. Branching statements are used for specifying alternate paths of execution, depending on the outcome of a logical condition. Loop statements are used for specifying computations, which need to be repeated until a certain logical condition is satisfied. Flow control statements are used to divert the execution path to another part of the program. We will discuss these in turn. 3.2. Conditional Statements 3.2.1. The if Statement It is sometimes desirable to make the execution of a statement dependent upon a condition being satisfied. The if statement provides a way of expressing this, the general form of which is: if (expression) statement; First expression is evaluated. If the outcome is nonzero (true) then statement is executed. Otherwise, nothing happens. For example, when dividing two values, we may want to check that the denominator is nonzero: if (count != 0) average = sum / count; To make multiple statements dependent on the same condition, we can use a compound statement: if (balance > 0) { interest = balance * creditRate; balance += interest; } -1-
  38. 38. A variant form of the if statement allows us to specify two alternative statements: one which is executed if a condition is satisfied and one which is executed if the condition is not satisfied. This is called the if-else statement and has the general form: if (expression) statement1; else statement2; First expression is evaluated. If the outcome is nonzero (true) then statement1 is executed. Otherwise, statement2 is executed. For example: if (balance > 0) { interest = balance * creditRate; balance += interest; } else { interest = balance * debitRate; balance += interest; } Given the similarity between the two alternative parts, the whole statement can be simplified to: if (balance > 0) interest = balance * creditRate; else interest = balance * debitRate; balance += interest; Or simplified even further using a conditional expression: interest = balance * (balance > 0 ? creditRate : debitRate); balance += interest; Or just: balance += balance * (balance > 0 ? creditRate : debitRate); If statements may be nested by having an if statement appear inside another if statement. For example: if (callHour > 6) { if (callDuration <= 5) charge = callDuration * tarrif1; else charge = 5 * tarrif1 + (callDuration - 5) * tarrif2; } else charge = flatFee; A frequently-used form of nested if statements involves the else part consisting of another if-else statement. For example: if (ch >= '0' && ch <= '9') kind = digit; else { -2-
  39. 39. } if (ch >= 'A' && ch <= 'Z') kind = upperLetter; else { if (ch >= 'a' && ch <= 'z') kind = lowerLetter; else kind = special; } For improved readability, it is conventional to format such cases as follows: if (ch >= '0' && ch <= '9') kind = digit; else if (cha >= 'A' && ch <= 'Z') kind = capitalLetter; else if (ch >= 'a' && ch <= 'z') kind = smallLetter; else kind = special; 3.2.2. The switch Statement The switch statement provides a way of choosing between a set of alternatives, based on the value of an expression. The general form of the switch statement is: switch (expression) { case constant1: statements; ... case constantn: statements; default: statements; } First expression (called the switch tag) is evaluated, and the outcome is compared to each of the numeric constants (called case labels), in the order they appear, until a match is found. The statements following the matching case are then executed. Note the plural: each case may be followed by zero or more statements (not just one statement). Execution continues until either a break statement is encountered or all intervening statements until the end of the switch statement are executed. The final default case is optional and is exercised if none of the earlier cases provide a match. For example, suppose we have parsed a binary arithmetic operation into its three components and stored these in variables operator, operand1, and operand2. The following switch statement performs the operation and stores the result in result. -3-
  40. 40. switch (operator) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; default:cout << "unknown operator: " << ch << 'n'; break; } As illustrated by this example, it is usually necessary to include a break statement at the end of each case. The break terminates the switch statement by jumping to the very end of it. There are, however, situations in which it makes sense to have a case without a break. For example, if we extend the above statement to also allow x to be used as a multiplication operator, we will have: switch (operator) { case '+': result = operand1 + operand2; break; case '-': result = operand1 - operand2; break; case 'x': case '*': result = operand1 * operand2; break; case '/': result = operand1 / operand2; break; default:cout << "unknown operator: " << ch << 'n'; break; } Because case 'x' has no break statement (in fact no statement at all!), when this case is satisfied, execution proceeds to the statements of the next case and the multiplication is performed. It should be obvious that any switch statement can also be written as multiple if-else statements. The above statement, for example, may be written as: if (operator == '+') result = operand1 + operand2; else if (operator == '-') result = operand1 - operand2; else if (operator == 'x' || operator == '*') result = operand1 * operand2; else if (operator == '/') result = operand1 / operand2; else cout << "unknown operator: " << ch << 'n'; However, the switch version is arguably neater in this case. In general, preference should be given to the switch version when possible. The if-else approach should be reserved for situation where a -4-
  41. 41. switch cannot do the job (e.g., when the conditions involved are not simple equality expressions, or when the case labels are not numeric constants). 3.3. Looping Statements 3.3.1. The ‘while’ Statement The while statement (also called while loop) provides a way of repeating a statement while a condition holds. It is one of the three flavors of iteration in C++. The general form of the while statement is: while (expression) statement; First expression (called the loop condition) is evaluated. If the outcome is nonzero then statement (called the loop body) is executed and the whole process is repeated. Otherwise, the loop is terminated. For example, suppose we wish to calculate the sum of all numbers from 1 to some integer denoted by n. This can be expressed as: i = 1; sum = 0; while (i <= n) sum += i; For n set to 5, Table 2.9 provides a trace of the loop by listing the values of the variables involved and the loop condition. Iteration F i rs t Second Third F o u rt h Fi fth Sixth Table 5.1 i 1 2 3 4 5 6 While loop trace n i <= n sum 5 1 5 1 5 1 5 1 5 1 5 0 += i++ 1 3 6 10 15 It is not unusual for a while loop to have an empty body (i.e., a null statement). The following loop, for example, sets n to its greatest odd factor. while (n % 2 == 0 && n /= 2) ; -5-
  42. 42. Here the loop condition provides all the necessary computation, so there is no real need for a body. The loop condition not only tests that n is even, it also divides n by two and ensures that the loop will terminate should n be zero. 3.3.2. The ‘for’ Statement The for statement (also called for loop) is similar to the while statement, but has two additional components: an expression which is evaluated only once before everything else, and an expression which is evaluated once at the end of each iteration. The general form of the for statement is: for (expression1; expression2; expression3) statement; First expression1 is evaluated. Each time round the loop, expression2 is evaluated. If the outcome is nonzero then statement is executed and expression3 is evaluated. Otherwise, the loop is terminated. The general for loop is equivalent to the following while loop: expression1; while (expression2) { statement; expression3; } The most common use of for loops is for situations where a variable is incremented or decremented with every iteration of the loop. The following for loop, for example, calculates the sum of all integers from 1 to n. sum = 0; for (i = 1; i <= n; ++i) sum += i; This is preferred to the while-loop version we saw earlier. In this example, i is usually called the loop variable. C++ allows the first expression in a for loop to be a variable definition. In the above loop, for example, i can be defined inside the loop itself: for (int i = 1; i <= n; ++i) sum += i; -6-
  43. 43. Contrary to what may appear, the scope for i is not the body of the loop, but the loop itself. Scopewise, the above is equivalent to: int i; for (i = 1; i <= n; ++i) sum += i; Any of the three expressions in a for loop may be empty. For example, removing the first and the third expression gives us something identical to a while loop: for (; i != 0;) something; // is equivalent to: while (i != 0) // something; Removing all the expressions gives us an infinite loop. This loop's condition is assumed to be always true: for (;;) something; // infinite loop For loops with multiple loop variables are not unusual. In such cases, the comma operator is used to separate their expressions: for (i = 0, j = 0; i + j < n; ++i, ++j) something; Because loops are statements, they can appear inside other loops. In other words, loops can be nested. For example, for (int i = 1; i <= 3; ++i) for (int j = 1; j <= 3; ++j) cout << '(' << i << ',' << j << ")n"; produces the product of the set {1,2,3} with itself, giving the output: (1,1) (1,2) (1,3) (2,1) (2,2) (2,3) (3,1) (3,2) (3,3) -7-
  44. 44. 3.3.3. The ‘do…while’ Statement The do statement (also called do loop) is similar to the while statement, except that its body is executed first and then the loop condition is examined. The general form of the do statement is: do statement; while (expression); First statement is executed and then expression is evaluated. If the outcome of the latter is nonzero then the whole process is repeated. Otherwise, the loop is terminated. The do loop is less frequently used than the while loop. It is useful for situations where we need the loop body to be executed at least once, regardless of the loop condition. For example, suppose we wish to repeatedly read a value and print its square, and stop when the value is zero. This can be expressed as the following loop: do { cin >> n; cout << n * n << 'n'; } while (n != 0); Unlike the while loop, the do loop is never used in situations where it would have a null body. Although a do loop with a null body would be equivalent to a similar while loop, the latter is always preferred for its superior readability. 3.4. Other Statements 3.4.1. The ‘continue’ Statement The continue statement terminates the current iteration of a loop and instead jumps to the next iteration. It applies to the loop immediately enclosing the continue statement. It is an error to use the continue statement outside a loop. In while and do loops, the next iteration commences from the loop condition. In a for loop, the next iteration commences from the loop’s third expression. For example, a loop which repeatedly reads in a number, processes it but ignores negative numbers, and terminates when the number is zero, may be expressed as: do { cin >> num; if (num < 0) continue; // process num here... } while (num != 0); This is equivalent to: -8-
  45. 45. do { cin >> num; if (num >= 0) { // process num here... } } while (num != 0); A variant of this loop which reads in a number exactly n times (rather than until the number is zero) may be expressed as: for (i = 0; i < n; ++i) { cin >> num; if (num < 0) continue; // process num here... } // causes a jump to: ++i When the continue statement appears inside nested loops, it applies to the loop immediately enclosing it, and not to the outer loops. For example, in the following set of nested loops, the continue applies to the for loop, and not the while loop: while (more) { for (i = 0; i < n; ++i) { cin >> num; if (num < 0) continue; // process num here... } //etc... } // causes a jump to: ++i 3.4.2. The ‘break’ Statement A break statement may appear inside a loop (while, do, or for) or a switch statement. It causes a jump out of these constructs, and hence terminates them. Like the continue statement, a break statement only applies to the loop or switch immediately enclosing it. It is an error to use the break statement outside a loop or a switch. For example, suppose we wish to read in a user password, but would like to allow the user a limited number of attempts: for (i = 0; i < attempts; ++i) { cout << "Please enter your password: "; cin >> password; if (Verify(password)) // check password for correctness break; // drop out of the loop cout << "Incorrect!n"; } Here we have assumed that there is a function called Verify which checks a password and returns true if it is correct, and false otherwise. -9-
  46. 46. Rewriting the loop without a break statement is always possible by using an additional logical variable (verified) and adding it to the loop condition: verified = 0; for (i = 0; i < attempts && !verified; ++i) { cout << "Please enter your password: "; cin >> password; verified = Verify(password)); if (!verified) cout << "Incorrect!n"; } The break version is arguably simpler and therefore preferred. 3.4.3. The ‘goto’ Statement The goto statement provides the lowest-level of jumping. It has the general form: goto label; where label is an identifier which marks the jump destination of goto. The label should be followed by a colon and appear before a statement within the same function as the goto statement itself. For example, the role of the break statement in the for loop in the previous section can be emulated by a goto: for (i = 0; i < attempts; ++i) { cout << "Please enter your password: "; cin >> password; if (Verify(password)) // check password for correctness goto out; // drop out of the loop cout << "Incorrect!n"; } out: //etc... Because goto provides a free and unstructured form of jumping (unlike break and continue), it can be easily misused. Most programmers these days avoid using it altogether in favor of clear programming. Nevertheless, goto does have some legitimate (though rare) uses. 3.4.4. The ‘return’ Statement The return statement enables a function to return a value to its caller. It has the general form: return expression; where expression denotes the value returned by the function. The type of this value should match the return type of the function. For a function whose return type is void, expression should be empty: return; - 10 -
  47. 47. The only function we have discussed so far is main, whose return type is always int. The return value of main is what the program returns to the operating system when it completes its execution. Under UNIX, for example, it its conventional to return 0 from main when the program executes without errors. Otherwise, a non-zero error code is returned. For example: int main (void) { cout << "Hello Worldn"; return 0; } When a function has a non-void return value (as in the above example), failing to return a value will result in a compiler warning. The actual return value will be undefined in this case (i.e., it will be whatever value which happens to be in its corresponding memory location at the time). - 11 -
  48. 48. Chapter Four Array, Pointers and Strings 4. Arrays and Strings....................................................................................................... 2 4.1. Introduction ......................................................................................................... 2 4.2. What is an arrays ................................................................................................. 3 4.3. One Dimensional Array ...................................................................................... 3 4.3.1. Declaration of Arrays .................................................................................. 3 4.3.2. Accessing Array Elements .......................................................................... 4 4.3.3. Initialization of arrays ................................................................................. 6 4.3.4. Copying Arrays ........................................................................................... 9 4.4. Multidimensional arrays ................................................................................... 10 4.4.1. Initializing Multidimensional Arrays ........................................................ 11 4.4.2. Omitting the Array Size ............................................................................ 11 4.5. Strings representation and manipulation ........................................................... 13 4.5.1. String Output ............................................................................................. 13 4.5.2. String Input ............................................................................................... 14 4.5.3. Avoiding buffer over flow ........................................................................ 16 4.5.4. String constants ......................................................................................... 16 4.5.5. Copying string the hard way ..................................................................... 16 4.5.6. Copying string the easy way ..................................................................... 17 4.5.7. Concatenating strings ................................................................................ 18 4.5.8. Comparing strings ..................................................................................... 19 4.6. Pointers ............................................................................................................. 19 4.6.1. Dynamic Memory ..................................................................................... 21 4.6.2. Pointer Arithmetic..................................................................................... 22 4.6.3. Function Pointers ...................................................................................... 24 4.6.4. References ................................................................................................. 26 4.6.5. Typedefs .................................................................................................... 28 1
  49. 49. Chapter Four 4. Arrays and Strings 4.1. Introduction Variables in a program have values associated with them. During program execution these values are accessed by using the identifier associated with the variable in expressions etc. In none of the programs written so far have very many variables been used to represent the values that were required. Thus even though programs have been written that could handle large lists of numbers it has not been necessary to use a separate identifier for each number in the list. This is because in all these programs it has never been necessary to keep a note of each number individually for later processing. For example in summing the numbers in a list only one variable was used to hold the current entered number which was added to the accumulated sum and was then overwritten by the next number entered. If that value were required again later in the program there would be no way of accessing it because the value has now been overwritten by the later input. If only a few values were involved a different identifier could be declared for each variable, but now a loop could not be used to enter the values. Using a loop and assuming that after a value has been entered and used no further use will be made of it allows the following code to be written. This code enters six numbers and outputs their sum: sum = 0.0; for (i = 0; i < 6; i++) { cin >> x; sum += x; } This of course is easily extended to n values where n can be as large as required. However if it was required to access the values later the above would not be suitable. It would be possible to do it as follows by setting up six individual variables: float a, b, c, d, e, f; and then handling each value individually as follows: 2
  50. 50. sum cin cin cin cin cin cin = 0.0; >> a; >> b; >> c; >> d; >> e; >> f; sum sum sum sum sum sum += += += += += += a; b; c; d; e; f; which is obviously a very tedious way to program. To extend this solution so that it would work with more than six values then more declarations would have to be added, extra assignment statements added and the program re-compiled. If there were 10000 values imagine the tedium of typing the program (and making up variable names and remembering which is which)! To get round this difficulty all high-level programming languages use the concept of a data structure called an Array. 4.2. What is an arrays An array is a data structure which allows a collective name to be given to a group of elements which all have the same type. An individual element of an array is identified by its own unique index (or subscript). An array can be thought of as a collection of numbered boxes each containing one data item. The number associated with the box is the index of the item. To access a particular item the index of the box associated with the item is used to access the appropriate box. The index must be an integer and indicates the position of the element in the array. Thus the elements of an array are ordered by the index. 4.3. One Dimensional Array 4.3.1. Declaration of Arrays An array declaration is very similar to a variable declaration. First a type is given for the elements of the array, then an identifier for the array and, within square brackets, the number of elements in the array. The number of elements must be an integer. For example data on the average temperature over the year in Ethiopia for each of the last 100 years could be stored in an array declared as follows: float annual_temp[100]; 3
  51. 51. This declaration will cause the compiler to allocate space for 100 consecutive float variables in memory. The number of elements in an array must be fixed at compile time. It is best to make the array size a constant and then, if required, the program can be changed to handle a different size of array by changing the value of the constant, const int NE = 100; float annual_temp[NE]; then if more records come to light it is easy to amend the program to cope with more values by changing the value of NE. This works because the compiler knows the value of the constant NE at compile time and can allocate an appropriate amount of space for the array. It would not work if an ordinary variable was used for the size in the array declaration since at compile time the compiler would not know a value for it. 4.3.2. Accessing Array Elements Given the declaration above of a 100-element array the compiler reserves space for 100 consecutive floating point values and accesses these values using an index/subscript that takes values from 0 to 99. The first element in an array in C++ always has the index 0, and if the array has n elements the last element will have the index n-1. An array element is accessed by writing the identifier of the array followed by the subscript in square brackets. Thus to set the 15th element of the array above to 1.5 the following assignment is used: annual_temp[14] = 1.5; Note that since the first element is at index 0, then the ith element is at index i-1. Hence in the above the 15th element has index 14. An array element can be used anywhere an identifier may be used. Here are some examples assuming the following declarations: const int NE = 100, N = 50; int i, j, count[N]; float annual_temp[NE]; float sum, av1, av2; A value can be read into an array element directly, using cin cin >> count[i]; The element can be increased by 5, 4
  52. 52. count[i] = count[i] + 5; or, using the shorthand form of the assignment count[i] += 5; Array elements can form part of the condition for an if statement, or indeed, for any other logical expression: if (annual_temp[j] < 10.0) cout << "It was cold this year " << endl; for statements are the usual means of accessing every element in an array. Here, the first NE elements of the array annual_temp are given values from the input stream cin. for (i = 0; i < NE; i++) cin >> annual_temp[i]; The following code finds the average temperature recorded in the first ten elements of the array. sum = 0.0; for (i = 0; i <10; i++) sum += annual_temp[i]; av1 = sum / 10; Notice that it is good practice to use named constants, rather than literal numbers such as 10. If the program is changed to take the average of the first 20 entries, then it all too easy to forget to change a 10 to 20. If a const is used consistently, then changing its value will be all that is necessary. For example, the following example finds the average of the last k entries in the array. k could either be a variable, or a declared constant. Observe that a change in the value of k will still calculate the correct average (provided k<=NE). sum = 0.0; for (i = NE - k; i < NE; i++) sum += annual_temp[i]; av2 = sum / k; Important - C++ does not check that the subscript that is used to reference an array element actually lies in the subscript range of the array. Thus C++ will allow the assignment of a value to annual_temp[200], however the effect of this assignment is unpredictable. For example it could lead to the program attempting to assign a value to a memory element that is outside the program's allocated memory space. This would lead 5
  53. 53. to the program being terminated by the operating system. Alternatively it might actually access a memory location that is within the allocated memory space of the program and assign a value to that location, changing the value of the variable in your program which is actually associated with that memory location, or overwriting the machine code of your program. Similarly reading a value from annual_temp[200] might access a value that has not been set by the program or might be the value of another variable. It is the programmer's responsibility to ensure that if an array is declared with n elements then no attempt is made to reference any element with a subscript outside the range 0 to n-1. Using an index, or subscript, that is out of range is called Subscript Overflow. Subscript overflow is one of the commonest causes of erroneous results and can frequently cause very strange and hard to spot errors in programs. 4.3.3. Initialization of arrays The initialization of simple variables in their declaration has already been covered. An array can be initialized in a similar manner. In this case the initial values are given as a list enclosed in curly brackets. For example initializing an array to hold the first few prime numbers could be written as follows: int primes[] = {1, 2, 3, 5, 7, 11, 13}; Note that the array has not been given a size, the compiler will make it large enough to hold the number of elements in the list. In this case primes would be allocated space for seven elements. If the array is given a size then this size must be greater than or equal to the number of elements in the initialization list. For example: int primes[10] = {1, 2, 3, 5, 7}; would reserve space for a ten element array but would only initialize the first five elements. Example Program: Printing Outliers in Data The requirement specification for a program is: A set of positive data values (200) are available. It is required to find the average value of these values and to count the number of values that are more than 10% above the average value. 6
  54. 54. Since the data values are all positive a negative value can be used as a sentinel to signal the end of data entry. Obviously this is a problem in which an array must be used since the values must first be entered to find the average and then each value must be compared with this average. Hence the use of an array to store the entered values for later re-use. An initial algorithmic description is: initialize. enter elements into array and sum elements. evaluate average. scan array and count number greater than 10% above average. output results. This can be expanded to the complete algorithmic description: set sum to zero. set count to zero. set nogt10 to zero. enter first value. while value is positive { put value in array element with index count. add value to sum. increment count. enter a value. } average = sum/count. for index taking values 0 to count-1 if array[index] greater than 1.1*average then increment nogt10. output average, count and nogt10. In the above the variable nogt10 is the number greater than 10% above the average value. It is easy to argue that after exiting the while loop, count is set to the number of positive numbers entered. Before entering the loop count is set to zero and the first number is entered, that is count is one less than the number of numbers entered. Each time round the loop another number is entered and count is incremented hence count remains one less than the number of numbers entered. But the number of numbers entered is one greater than the number of positive numbers so count is therefore equal to the number of positive numbers. A main() program written from the above algorithmic description is given below: void main() { const int NE = 200; float sum = 0.0; int count = 0; int nogt10 = 0; // // // // maximum no of elements in array accumulates sum number of elements entered counts no greater than 10% 7
  55. 55. float x; float indata[NE]; float average; int i; // // // // // above average holds each no as input array to hold input average value of input values control variable // Data entry, accumulate sum and count // number of +ve numbers entered cout << "Enter numbers, -ve no to terminate: " << endl; cin >> x; while (x >= 0.0) { sum = sum + x; indata[count] = x; count = count + 1; cin >> x; } // calculate average average = sum/count; // Now compare input elements with average for (i = 0; i < count; i++) { if (indata[i] > 1.1 * average) nogt10++; } } // Output results cout << "Number of values input is " << n; cout << endl << "Number more than 10% above average is " << nogt10 << endl; Since it was assumed in the specification that there would be less than 200 values the array size is set at 200. In running the program less than 200 elements may be entered, if n elements where n < 200 elements are entered then they will occupy the first n places in the array indata. It is common to set an array size to a value that is the maximum we think will occur in practice, though often not all this space will be used. Example Program: Test of Random Numbers The following program simulates the throwing of a dice by using a random number generator to generate integers in the range 0 to 5. The user is asked to enter the number of trials and the program outputs how many times each possible number occurred. An array has been used to hold the six counts. This allows the program to increment the correct count using one statement inside the loop rather than using a switch statement 8
  56. 56. with six cases to choose between variables if separate variables had been used for each count. Also it is easy to change the number of sides on the dice by changing a constant. Because C++ arrays start at subscript 0 the count for an i occurring on a throw is held in the i-1th element of this count array. By changing the value of the constant die_sides the program could be used to simulate a die_sides-sided die without any further change. #include <iostream.h> #include <stdlib.h> #include <time.h> // time.h and stdlib.h required for // random number generation void main() { const int die_sides = 6; int count[die_sides]; // int no_trials, // roll, // i; // float sample; // // maxr-sided die // holds count of each possible value number of trials random integer control variable random fraction 0 .. 1 // initialize random number generation and count // array and input no of trials srand(time(0)); for (i=0; i < die_sides; i++) count[i] = 0; cout << "How many trials? "; cin >> no_trials; // carry out trials for (i = 0; i < no_trials; i++) { sample = rand()/float(RAND_MAX); roll = int ( die_sides * sample); // returns a random integer in 0 to die_sides-1 count[roll]++; // increment count } } // Now output results for (i = 0; i < die_sides; i++) { cout << endl << "Number of occurrences of " << (i+1) << " was " << count[i]; } cout << endl; 4.3.4. Copying Arrays The assignment operator cannot be applied to array variables: const int SIZE=10 int x [SIZE] ; int y [SIZE] ; 9

×