SOMETHING ABOUT PROGRAMMING
Introduction
Today almost everybody knows what a computer system is. The reason behind this is that we have come in contact with computers in all areas of our daily lives, such as paying our electricity bills, shopping bills, telephone bills and so on. You can say that it would be easier to list those areas of our lives not affected by computers. In fact, the field of computer is so vast that it is not possible to cover all those fields in just one book. The fields of computer depend upon the environment in which it is intended to solve problems by writing programs. Be forewarned: This book is not just about computers in the abstract. This is a text to teach you how to solve several problems in a variety of domains by writing programs in a language ‘C’.
In this MY ARTICLE you will also study – what a computer program is, what is programming, what are the basic steps involved in writing a program, what are major parts of a computer system and how they work together, and what is a programming language. In MY NEXT ARTICLE you will study history of ‘C’ as well as some the features associated with the ‘C’ programming – one of the most exciting languages. Firstly we will study about programming.
What is a Computer?
At this stage it is not mandatory to understand much about a computer in order to use it as an efficient tool because this book is intended for writing programs in a programming language ‘C’. But if you know something about the physical components of a computer system, you can better understand the effect of each instruction in the programming language.
Let us begin with the definition of a computer. Computer is a programmable device that can store, retrieve, and process data. A typical computer system has three major components:
- Memory
- Central Processing Unit
- Input / Output Devices
Figure-1 shows these components.
The memory unit is a used to hold the data and instructions. The memory unit is an ordered sequence of storage cells, each capable of holding a piece of data. Each memory cell has a distinct address to which one refers in order to store or retrieve information.
Central Processing Unit (CPU) is the part of the computer system that executes the instructions of a program stored in memory. The CPU has two main components: arithmetic/logic unit (ALU) and control unit (CU). The arithmetic/logic unit performs arithmetic operations, such as addition, subtraction, multiplication, division, and logical operations (comparison of two numbers). The control unit controls the actions of the other components in order to execute instructions (the program) in sequence.
Input/Output devices are used to receive information from the outside world and to produce the result to outside world respectively. The keyboard is a typical standard input device and a video display unit (VDU) is a standard output device. A printer is another example of a device that is used for output from the computer.
The differences among various types of computers basically involve the size of the memory, the speed with which data can be recalled from it, the efficiency by which the data can be transferred, and limitations of Input/Output devices.
Computers can also have a wide variety of peripheral devices. Peripheral devices are input, output, or auxiliary device of a computer. An auxiliary device, often called as a secondary storage device, is used to hold coded data, ready for use by the computer, in between the times when we actually want to use the data. An auxiliary device is external to computer’s memory.
The Concept of Programming
Have you ever noticed that your behavior and your thoughts are characterized by logical sequences. Every step of your life has a certain order to it. No doubt, a lot of what you do everyday is done automatically, on an unconscious level since it is not necessary for you to consciously think of every step involved in a process as simple as you brush your teeth. If you try to do this at conscious level then it involves all the following actions in a certain order or sequence as follows:
- take a brush
- clean it with water
- put some toothpaste on it
- rub the brush against your teeth for a minute
- take a glass of water and clean your teeth
Initially you had to learn this. But after some time, the action is completely automatic. In other words much of what you do unconsciously you once had to learn. After all every music requires a definite a sequence of notes in order to be recognizable.
The ultimate conclusion is that whatever we do at conscious level or at unconscious level, it takes place in a prescribed order. This ordering is called programming and when this programming is done on a computer language it is called computer programming. On the similar track, a computer program is a sequence of instructions that must be understood by the computer.
The programming process is basically a two step process:
- A problem solving phase
- An implementation phase
In problem solving phase, we firstly understand (define) the problem or you can say what a problem is. After knowing the problem, we develop a logical sequence of steps to be used to solve this problem because the computer can not itself analyze the problem and come up with a solution. It is the user or you can say a programmer who must arrive at a solution and communicate it to the computer. Thus the programmer begins the programming process by analyzing the problem and developing a general solution called an algorithm. In other words, an algorithm is just a step-by-step procedure for solving a problem in a finite amount of time.
After developing a general solution, the programmer “walk through” the algorithm by following logical sequences step by step mentally or manually. If programmer finds that this testing of the algorithm does not produce satisfactory result, he/she repeats the problem solving phase, understand the problem again and coming up with another algorithm. Of course there may be more than one solution to a problem, it is the programmer who selects which is the best one.
Once the solution is selected, it is programmer’s duty to translate this algorithm into a programming language. Translating an algorithm into a programming language is called coding the algorithm. For this we use ‘C’ programming language in this book. Like any simple language, a programming language is a set of rules, symbols, and special words used to construct a program. A programming language is essentially a simplified form of English (with math symbols) that adheres to a strict set of grammar rules.
After coding the algorithm, the resulting program is tested by executing (running) it on the computer system. If the program produces correct result then it is OK; otherwise the programmer must determine what is wrong and modify the algorithm and program as needed. If the program produces the desired results then it is used in practical application. The combination of coding and testing an algorithm is often referred to as implementing an algorithm.
Figure-2 shows the relationship between a problem solving phase and an implementation phase.
Here one should not confuse with the definition of a program and an algorithm. An algorithm is just a way of expressing the solution. It may be in a programming language or in English. And when an algorithm is expressed in a programming language it is called a program. Another main point to note is that you should not try to take a short cut in the programming process by going directly from the problem definition to the coding of the program as shown in figure-3.
Of course it saves a lot of time, but if the program does not produce the desired result in first chance then you will spend a lot of extra time in correcting errors (debugging) and revising an ill-conceived program. Therefore the best strategy is to go to problem solving phase first and then implementation phase.
The Programming Style
The concept of programming involves more than simply writing a program. In addition, using meaningful names to variables and functions, documentation and maintenance of programs are important parts of programming.
Documentation
Documentation is just a written text and comments that make a program easier for others to understand, use and modify. Documentation should be kept up to date. Any change made in the program should be marked in all of the pertinent documentation. As far as small programs are concerned you indeed can keep all the details in your head, and so needs documentation only to explain the program to someone else. But as far as large and complex programs are concerned it becomes impossible to remember how every detail relates every other and therefore, it is essential that appropriate documentation be prepared along with each small part of the program. Thus the important point is that keep your documentation concise but descriptive.
Spaces, blank lines, and indentation in a program are an important form of documentation. These white space characters make the program easy to read, allow you to tell at a glance which parts of the program relate to each other, which statements are contained in which loop, and so on. In other words, you can say that using white space characters, it is easier to determine the structure of the program.
Once a program is fully debugged and in use, it is necessary to maintain it. Maintenance of programs is the modification of programs needed to meet new requests after they have been completed.
Naming Variables and Functions
While writing a program, one should give meaningful names to variables and functions so that their places in the program can be properly recognized and appreciated. Although finding good names is not an easy task, the careful choice of names go a long way in clarifying a program and in helping to avoid common errors. Let us see what should be kept in mind while selecting names.
- Use the meaningful names for variables, constants and functions such that they should suggest clearly the purpose of variables and functions.
- Use a single letter for the variable controlling a loop.
- Use common prefixes or suffixes to associate names to variables and functions as:
- readArray
- displayArray
- insert
- delete
Debugging of Programs
The process of detecting and removing errors in a program is referred as program testing and debugging. No body is perfect, at least I am not. When we code the algorithm then it is not necessary that our program should be 100 percent error–free. It means that there may occur any type of errors in the program. And it is totally our duty to trace out such errors and correct them that are likely to be present in the program.
There are four basic types of errors:
- Syntax errors
- Run–time errors
- Logical errors
- Latent errors
Syntax Errors
Every programming language has its own set of rules and the errors, which violate such rules, are referred as syntax errors. Fortunately syntax errors are immediately detected and isolated by the compiler during compilation purpose. The compilation phase of the program would not be completed until any syntax error is present in the program.
Following are the example of some syntax errors:
- int area-square, radius-of-circle; /* no hyphen */
- float 10salary; /* starts with a number sign */
- char @basic /* starts with a @ sign */
Normally the compiler specifies the line number where the error has occurred. But in some cases, the line number may not exactly indicate the place of error. So you have to find out that place.
Run–Time Errors
The errors, which occur during the runtime of a program, are referred as run–time errors or execution–time errors. Generally run–time errors come when there is any mismatch of basic data types or make an illegal reference and so on.
Logical Errors
The errors, which are directly related to the logic of the program, are referred as logical errors. Logical errors occurs due to wrong jumping, failure to satisfy a particular condition, and any incorrect order of evaluation of statements. Like run–time errors, the logical errors are not recognized by the compiler.
Following are the examples of some logical errors:
- if (i=1)
{
stat1;
stat2;
}
Here instead of using logical equal to (==) operator we have used assignment operator. A test condition like this would always be result in true.
- if (num==sum)
printf (“Both are equal”);
If ‘num’ and ‘sum’ are float types values, then it is not necessary to become equal due to truncation error. Generally such type of errors occur due to incorrect coding of the algorithm.
Latent Errors
The errors that come in existence when we enter some special values during the execution of a program are called as latent errors. Consider the following statements:
- a = 1 / b;
In this statement an error occurs only when b is equal to 0.
- x = 4 + c / (a-b);
Here an error occurs when ‘a’ and ‘b’ are equal.
Latent errors can be detected only by using all possible combination of test data.
Program Testing
Program testing is the process of running the program on sample data chosen to find errors, if they are present, before the program is used on actual data. Earlier we have discussed that the compiler can detect only the syntactic and semantics errors. All other errors can be traced out at run time only. Therefore it is necessary for the programmers to detect all such errors by taking some realistic data.
One of the most effective way to find errors is called a structured walkthrough. You can also call it as human testing. In this the programmer shows the complete source code to another programmer or a peer group. Structured walkthrough is carried out statement by statement by the programmer and is analyzed with respect to a checklist of common errors.
The testing should be done initially on function level and when all goes well then it should be made on the complete program level. When we talk about the program testing, it is also necessary to point out the quality of test data. The quality of test data should be selected in the following ways:
- Easy values – The program is tested with data that are easy to check; otherwise the complicated data may embarrass the programmer.
- Typical Realistic value – The testing data should be simple realistic so that the result can be checked by hand.
- Extreme values – Testing should be done at the limits of his range of application.
- Illegal values – The program should also be tested for some illegal values so that it becomes able to produce a sensible error message.
The ultimate conclusion is that program testing can be used to show the presence of errors but never their absence.
Methodology for Developing Programs
We have already studied that the programming process consists of a problem solving phase and an implementation phase. Whatever may be the problem, you were warned not to try to bypass the problem solving phase even when a problem is small. When we solve even small problem we must need to take care of every details and follow a methodological approach. The practice of applying the following methodology approach to small problems will prepare you to tackle larger programming problems that you can not solve directly.
Top-Down Approach
The top-down approach divides the problem into smaller problems (subproblems) that can be handled more easily. If these subproblems are still too difficult to handle then they are subdivided again and so on. This process continues until each subproblem can not be further divided. Figure-4 shows this. It is the programmer who decides exactly how the work will be divided among them.
Sometimes we also follow bottom-up approach in which the programmer might choose to solve different parts of the problem directly in his programming language and them combine these pieces into a complete program. Experience suggests that the top-down approach should be followed when creating a program.
It is true that it is often not easy to decide exactly how to divide the work into subproblems and sometimes even a decision once made must later be modified. But once a problem has been divided into subproblems, each subproblem can be solved independently of the others. These subproblems are also called modules. That’s why the top-down approach is also called as modular programming or step-wise programming. Modules at one level can call on the services of the module at lower level. For example one module could read elements of a matrix, another could display these values, and some other modules could add, subtract, or multiply matrices.
The top-down approach can be broken down as follows:
- Understand the problem very carefully.
- Write the main (super) module.
- Write the remaining sub modules, if any.
- Resequence and revise, if necessary.
Programming Languages
Every computer system stores data and information, whether it is alphabetic or numeric, in binary codes of 0’s and 1’s. For earlier computer systems, the only programming language was machine language.
Machine Language
Machine language is the language that is used directly by the computer and composed of binary-coded instruction. Almost every computer provides some kinds of operations, therefore different system designers have chosen different sets of binary codes of 0’s and 1’s to stand for each operation. That’s why every computer system has its own machine language that depends on the specific hardware of the computer system.
While programming in machine language, one has to sufficient knowledge of the numeric codes of various operations. Obviously it is very tedious and error prone process. Even if you want to modify a correct program, you need to study the whole program repeatedly. To overcome this limitation assemble languages were developed.
Assembly Language
Assembly language is a low level programming language in which the sequence of 0’s and 1’s are replaced by mnemonic (pronounced “ni-monic”) codes. Data items and operations are specified in mnemonic codes. Typical instructions for addition and subtraction might look like this ADD and SUB. But unfortunately the instructions written in assembly language could not be directly executed by a computer because a computer does not understand assembly language program. So a system program, known as assembler, was designed to translate an assembly language program into a machine language program. Figure-5 shows the role of assembler.
However the programming in assembly language was still highly machine dependent and the programmer was still concerned with the large and complex programs. Eventually it was the first step towards the development of high-level programming languages.
High-level Languages
High-level programming languages were closer to natural languages, such as English. They also relieve programmer from the burden of low-level details of the computer system. High-level languages require a little or no knowledge of machine instructions. The main advantage of a high level language is that they are much easier to maintain and modify.
But like assembly language programs, high-level language programs needs to be translated into machine language programs prior to their execution. Therefore a system program, compiler, is written. A compiler translates a high-level language program into machine instructions. Each high-level language has its own compiler. Figure 6 shows the role of compiler.
A program written in high-level language is called a source program. When this source program is compiled by the compiler with the program as its input, an object program is produced by the compiler. Thus an object program is the machine language equivalent of a source program that results when a compiler translates a source program into binary codes for a particular computer.
Actually it is a two step process – first step translates the source program into an object program (compilation) and second step executes the object program (machine language version of the program). Figure-7 shows this two step process.
The source program is entered through an interactive program, editor. An editor is an interactive program that is used to create and modify source programs or data. Fortunately C has an built-in text editor. While coding an algorithm the programmer should keep in mind the things a computer can do.
Almost every programming language uses certain structures to express algorithms as programs. There are four basic structures, as follows:
- Sequential
- Conditional
- Repetition
- Procedures
The sequential structure is composed of statements executed one after another. The conditional structure (selection structure) executes different set of statements depending upon certain condition. The repetitive structures repeat a set of statements while certain conditions are met. The procedure enables us to replace a set of statements with a single statement. Figure-8 shows these basic structures of programming languages.
A procedure is a combination of the basic structures that is considered as a single statement in the program. In C procedures are called as functions. They allow you to write parts of your programs separately, then assemble into final form.
NOTE : IN MY NEXT ARTICLE( THE OTHER P[ART OF THIS ARTICLE ) YOU WILL READ ABOUT THE C LANGUAGE.