Friday, December 4, 2015

Chapter 6 - Arrays and Pointers

                                                        

LETS LEARN

 

ARRAYS

   TYPES OF ARRAYS

   ARRAY DECLARATION

   ARRAY INITIALIZATION

   Accessing the Values of an Array

   Referring a Multi-Dimensional Array:

POINTERS

   Pointer Variables

   Pointer Operators

   Pointer Expressions

   Pointer Assignment:

   Pointer Arithmetic:

DYNAMIC MEMORY

   (a) Operators: new and new[]

     1. Handling exceptions.

     2.  nothrow method:

(b) Operator: delete and delete[]

STRINGS

   String Library Functions

     1.      strlen (), length()

     2.      strcpy()

     3.      strcat()

     4.      strcmp()

  2 Dimensional Array of Characters

PREDEFINED MATHEMATICAL FUNCTIONS


ARRAYS


If we need to store 5 integer values, we had learnt so far to declare 5 different integer variables with separate identifier names. Instead of that, lets us now learn to use one location with one name, to store these 5 integer values - using arrays.

An array is a collection of data belonging to similar data type that are stored in sequential memory locations, and are accessed using a common name indexed by integers. 

int a[5] is an array named ‘a’ that can store 5 integer values at continuous memory locations that are indexed as:
a[0], a[1], a[2], a[3], a[4]

The integer array a[5] holds 5 integer values identified by name ‘a and is graphically represented like this:


Here, each blank panel represents an integer element of the array. These elements are numbered from 0 to 4 since in arrays the first index always starts with 0.


TYPES OF ARRAYS

There are two types of arrays: One-dimensional array and Two-dimensional array.

A one-dimensional array is like a "data list" with one row and several columns or, one column and several rows.

A two-dimensional array (multi-dimensional) is like a "data table" with several rows and several columns.


ARRAY DECLARATION

An array must be declared before it is used. Declaration syntax of array is:

data type name [elements];

where data type can be int, float, char…etc., name is a valid identifier and elements enclosed in square brackets specify the total number of values the array would store. E.g. int a[5]

An array element represents the indices, or the number of elements the array is going to hold.  Since recent versions of C++ supports dynamic memory allocation for arrays, the size of an array need not be strictly specified at declaration.

ARRAY INITIALIZATION      

When an array is declared, initial values can be stored into each of its locations. These values may or may not change in the program. The process of assigning initial data values to array elements is called Array Initialization. We can initialize an array with initial values and with dynamic values.

(i) Array initialization along with declaration: Initial values are assigned to an array by specifying the element count and enclosing the data values within curly braces.

E.g. int a[5] = { 24, 28, 38, 12, 1498 };

Above declaration creates an integer array with element count 5 and data values 24, 28, 38, 12, 1498. It can be represented as below:


C++ also allows the possibility of not specifying the element count within square brackets by keeping it empty [ ]. In this case, the compiler will assume a size for the array that matches the number of values included between braces.

E.g. int  a[ ]  =  { 24, 28, 38, 12, 1498};

In the above declaration, array ‘a’ will be automatically assigned 5 memory locations, because 5 values have been initialized.

(ii) Array initialization with dynamic values: Dynamic values are assigned to an array at run time, mostly using loops. For example, look at the following code:

int a[10];
for (int i=0; i<10;++i)
     a[i]=i+5;

Here, an array ‘a’ is declared with element count 10. Using for loop, a[0] is assigned value 5, a[1] is assigned 6, a[2] is assigned 7 and so on, until a[9] which is assigned value 14.

Accessing the Values of an Array

The format for accessing values in an array is:

 name[index]

From previous example, array ‘a’ has 5 integers with following reference names for each of the element: a[0], a[1], a[2], a[3], a[4]

To store the value 75 into the third element of array “a”, we write:

a[2] = 75;

To assign the value of third element of array “a” to variable “b, we write:

b = a[2];

Note: Array locations start from 0 and so first array element is a[0]…third is a[2]

 

In C++ it is syntactically correct to exceed the valid range of indices for an array. This can create problems, since accessing out-of-range elements do not cause compilation errors but can cause runtime errors.

There are 2 uses of square brackets [ ] in arrays. One is to specify the size of arrays when they are declared. Second one is to specify indices for accessing array elements. Here are 2 examples:

int a[5];                     // declaration of a new array

a[2] = 75;                 // access to an element of the array

PROGRAM 31

Q. Write a program to initialize an integer array and display the values.

 

#include <iostream>

using namespace std;

int a[] = {28, 12, 18, 9, 38};

int i;

main ()

{

  cout<<"Array Values are\n"; 

  for (i=0 ; i<5 ; i++)

  {

    cout << a[i] <<"\n";

  }

}


OUTPUT








PROGRAM 32

Q. Write a program to accept ‘n’ numbers into an array, display them and print their sum.

#include<iostream>

#define SIZE 100

using namespace std;

main()

{

 int ar[SIZE],n,i, sum=0;

 cout<<"How many array elements? ";  cin>>n;

 /* input numbers into array */

 cout<<"Enter the  numbers: \n";

 for(i=0; i<n; i++)

   {

     cin>>ar[i];

     sum+=ar[i];

   }

 /*Print values from the array*/

 cout<<"The entered numbers are: \n";

 for(i=0; i<n; i++)

   cout<<ar[i]<<endl;

cout<<"Sum of numbers in array is:\n"<<sum;

}


 

OUTPUT









Program 33

Q. Assign the names of 4 districts in a string array and display the 3rd district.

#include<iostream>

using namespace std;

main()

{

  string district[4] = {"Kollam", "Ernakulam", "Trissur", "Wayanad"};

  cout << "Fourth District is: "<< district[3];

}

 

 

 

 

 

 

 

 


OUTPUT





MULTI DIMENSIONAL ARRAYS

Multidimensional (bi-dimensional) arrays can be described as an “array of arrays” that is made up of elements of the same data type. A multi-dimensional array has rows and columns. Syntax for declaration of multi-dimensional array is:

ArrayName [index1][index2]

where index1 is the Rows and index2 is the Columns.

 

A bi-dimensional array can be imagined as a bi-dimensional table of data that are made up of elements, all of them of the same data type.





In the above memory illustration, jimmy represents a bi-dimensional array of 3 per 5 (3 by 5 or 3 X 5) elements of type int. Format to declare this array in C++ is:

int jimmy [3][5];

Referring a Multi-Dimensional Array: The way to reference the second element vertically and fourth horizontally in an expression would be:

jimmy[1][3]






(remember that array indices always begin with zero)

Multidimensional arrays are not limited to two dimensions. They can contain as many indices as needed. But be careful! The amount of memory needed for an array rapidly increases with each dimension. For example:

 char century [100][365][24][60][60];

It declares an array with a char element for each second in a century, that is more than 3 billion chars. So this declaration would consume more than 3 gigabytes of memory !

PROGRAM 34

Q.  Write a program to accept values into two 3X3 matrix arrays and find its SUM.


#include<iostream>
using namespace std;
main()
{
int a[3][3], b[3][3], s[3][3];
int i, j ;

cout<<“Enter values for the first matrix\n”;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
cin>>a[i][j];

cout<<“Enter values for the second matrix\n”;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
cin>>b[i][j];

/* calculate the sum */
for(i=0;i<3;i++)
for(j=0;j<3;j++)
s[i][j]=a[i][j]+b[i][j];

cout<<“\n SUM MATRIX \n”;
for(i=0;i<3;i++)
{
cout<<endl;
for(j=0;j<3;j++)
cout<<“\t”<<s[i][j];
}
}

OUTPUT

Enter values for the first matrix
10       20        30
11       22        33
15       25        46
Enter values for the second matrix
5         8          9
9         5          4
10       40        12
SUM MATRIX
15       28        39
20       27        37
25        65        58
   

POINTERS

Pointer is a variable that holds memory address of another variable. In C++, you can convert one type of pointer into another using explicit type cast. Pointers are memory addresses that:

1.     Points to variables, arrays, functions, strings, structures, class.

2.     Can be returned from a function.

3.     Supports dynamic memory allocation.

4.   Helps to interchange values within variables without physically moving them.

Pointer Variables

A variable that points to the memory address of data storage location is called the pointer variable. It can be declared by a base type, and a pointer (*) to the variable name. Syntax for declaring a pointer variable is: type *name;

For example: int    *ptr;

simply means that ptr is a pointer to an integer.

Pointer Operators

There are two special pointer operators * and &.

1. & is a unary operator that returns the memory address of its operand. It is also called address operator. Eg: ptr = &a;

2. * is a unary operator that returns the value located at the address pointed. It is specifically called the pointer operator and is also called the Value at” operator or the Indirection” operator. Eg: *ptr

Following program will help you clarify what we just learned. Please also check Chapter 3, Program 12.

Program 35

Q. Write a program to declare an integer variable (with initial value). Declare an integer pointer and point it to the variable. Display memory address and data value using the pointer.

#include <iostream>

 using namespace std;

main()

{

int a = 10;

int *ptr;

ptr = &a; // pointer ‘ptr’ is assigned address of variable ‘a’

cout << “Address pointed by ptr = ” << ptr;

cout << “Value within Address Pointer ptr = ” << *ptr;

  }

OUTPUT




POINTER EXPRESSIONS

Expressions involving pointers conform to the same rules as other expressions. This section examines a few special aspects of pointer expressions.

Pointer Assignment: As with any variable, you may use a pointer on the right-hand side of an assignment statement to assign its value to another pointer. For example,

#include  <iostream.h>

void  main()

{

int  x ;

int   *p1,    *p2;

p1  =   &x;

p2  =  p1;

cout<< p2;   /*  prints  the address of x, not value of x  */    

   }

Pointer Arithmetic: There are only two arithmetic operations that you may use on pointers: addition and subtraction. Now let’s consider the following expressions:

  1.     ++ptr  // ptr = ptr + sizeof (data-type)

Increases memory address by 1. If ptr is of type int and ptr = 2000, then ++ptr would store memory address 2002, not 2001. The reason for this is that each time ptr is incremented, it will point to the next integer which is 2 bytes away. The same is true of decrements.

Note : Memory space occupied by integer is 2 bytes.


2.     - -ptr   // ptr = ptr - sizeof (data-type)

Decreases memory address by 1. If ptr is of type int and ptr = 2000, then - -ptr would store memory address 1998 (2 Bytes less than 2000).

 

3.     ++*ptr   // ++(*ptr)  : Add 1 to value pointed by *ptr

Increase the value that is located at address pointer ptr, by 1. 

    int a = 10;

    int *ptr;

    cout<< ++*ptr ;

Above code prints 11 (value pointed by ptr + 1, OR, 10+1)

4.     --*ptr   // - - (*ptr)   : Subtract 1 from  value pointed by *ptr

Decrease the value which is located at address pointer ptr, by 1

For example:

int a = 10;

int *ptr;

cout<< - -*ptr ;

Above code prints 9 (value pointed by ptr - 1, OR, 10-1)

General Rules for Pointer Arithmetics:

Each time a pointer is incremented, it points to the memory location of the next element of its base type. Each time it is decremented, it points to the location of the previous element. When applied to character pointers, this will appear as “normal” arithmetic because characters are always 1 Byte long. All other pointers will increase or decrease by the length of the data type they point to. You can also add or subtract integers to or from pointers. The expression:

p1 =   p1   +   12;

makes p1 point to the twelfth element of p1’s type beyond the one it currently points to.

PROGRAM 36

Q. Using Pointers, interchange the values of two integer variables.
  
#include<iostream>
using namespace std;
main()
{
int var1=100, var2=200,t;
int *ptr1,*ptr2;

ptr1=&var1;      
ptr2=&var2;
cout<<“\n Before changing the values\n”;
cout<<“\n Variable 1  :  “<<var1;         
cout<<“\n Variable 2  :  “<<var2;

/* Interchanging values using pointers */
t=*ptr1;
*ptr1=*ptr2;
*ptr2=t;

cout<<“\n After changing the values\n”;
cout<<“\n Variable 1  :  “<<var1;         
cout<<“\n Variable 2  :  “<<var2;
}

 OUTPUT

Before changing the value 
Variable 1   :  100
Variable 2   :  200
After changing the value 
Variable 1   :  200
Variable 2   :  100



DYNAMIC MEMORY

Until now, in all our programs, we have used fixed memory that was made available as per variable declaration at the start. But, what if we need a variable amount of memory that can only be determined during runtime? For example, in the case that we need some user input to determine the necessary amount of memory space. The answer is dynamic memory, for which C++ integrates the operators new and delete.

(a) Operators: new and new[]

The operator new is used to request allocation of dynamic memory. new is followed by a data type specifier and the total number of  memory locations to be allocated within square brackets []. It returns a pointer to the beginning of the new block of memory that is allocated. General syntax are:

pointer = new type;
pointer = new type [number_of_elements];

The first expression is used to allocate memory to contain one single element of specific type. The second one is used to assign a block (an array) of elements of specific type, where number_of_elements is an integer value representing the number of elements. For example:

int * bobby;
bobby = new int [5];

In this case, the system dynamically assigns space for five elements of type int and returns a pointer to the first element of the sequence, which is assigned to bobby. Therefore, now, bobby points to a valid block of memory with space for five elements of type int.






The first element pointed by bobby can be accessed either with the expression bobby[0] or the expression *bobby. The second element can be accessed either with bobby[1] or *(bobby+1) and so on.

You could be wondering the difference between declaring a normal array and assigning dynamic memory to a pointer, as we have just done. The most important difference is that the size of an array has to be a constant value, which limits its size to what we decide at the moment of designing the program, before its execution, whereas the dynamic memory allocation allows us to assign memory during the execution of the program (runtime) using any variable or constant value as its size.

The dynamic memory requested by our program is allocated by the system from the memory heap. However, computer memory is a limited resource, and it can be exhausted. Therefore, it is important to have some mechanism to check if our request to allocate memory was successful or not.

C++ provides two standard methods to check if the memory allocation was successful:

1. By handling exceptions. Using this method an exception of type bad_alloc is thrown when the allocation fails. This exception method is the default method used by new, and is the one used in a declaration like:

bobby = new int [5];  // if it fails an exception is thrown

Note: Exceptions are a powerful C++ feature that checks if statements (between blocks) are successfully executed for unseen errors like for example, trying to allocate memory when there’s no memory space left.

2. The nothrow method: In this method, when a memory allocation fails, instead of throwing a bad_alloc exception or terminating the program, the pointer returned by new is a null pointer, and the program continues its execution. This method can be specified by using a special object called nothrow as parameter for new:

bobby = new (nothrow) int [5];

In this case, if the allocation of this block of memory failed, the failure could be detected by checking if bobby took a null pointer value:

int * bobby; bobby = new (nothrow) int [5];
if (bobby == 0)
  {  
      // error assigning memory. Take measures.  
   };

This nothrow method requires more work than the exception method, since the value returned has to be checked after each and every memory allocation. Anyway this method can become tedious for larger projects, where the exception method is generally preferred.

(b) Operator: delete and delete[]

Since the necessity of dynamic memory is usually limited to specific moments within a program, once it is no longer needed it should be freed so that the memory becomes available again for other requests of dynamic memory. This is the purpose of the operator delete, whose format is:

delete pointer;
delete [] pointer;

The expression delete pointer; should be used to delete memory allocated for a single element, and the expression delete [] pointer; is used when memory is allocated for an array of elements.

The value passed as argument to delete must be either a pointer to a memory block previously allocated with new, or a null pointer (in the case of a null pointer, delete produces no effect).

PROGRAM 37

Q. Enter “n” integers using dynamic memory allocation. Ensure successful allocation and freeing of memory.

main ()
{
   int i, n;
   int * p;
   char x;
   cout << "How many numbers would you like to type? ";
   cin >> i;
   p= new (nothrow) int[i];
   if (p == 0)
     cout << "Error: memory could not be allocated";
   else
   {
       for (n=0; n<i; n++)
       {
         cout << "Enter number: ";
         cin >> p[n];
       }
      cout << "You have entered: ";
      for (n=0; n<i; n++)
         cout << p[n] << ", ";
      delete[] p;
   }
   cout << "\nAfter memory deallocation\n";
   for (n=0; n<i; n++)
         cout << p[n] << ", ";
}


OUTPUT








Notice how the value within brackets in the new statement is a variable value i entered by the user, not a constant value:

p= new (nothrow) int[i];

It is a good practice to always check if a dynamic memory block was successfully allocated. Therefore, if you use the nothrow method, you should always check the value of the pointer returned. Otherwise, use the exception method, even if you do not handle the exception. This way, the program will terminate at that point without causing the unexpected results of continuing executing a code that assumes a block of memory to have been allocated when in fact it has not.

STRING

A String is an array of characters (char). There are specific functions that can be used for strings, like adding to strings, finding the length of strings, and also checking to see if strings match. The definition of a String would be anything that contains more than one character strung (joined) together. For example, “This” is a string. String literals are words surrounded by double quotation marks. Example: “This is a static string”

A string constant is a one dimensional array of characters terminated by a null   ('\0’). For example, 

  char name[ ] = { ‘I’, ’N’, ’F’, ’O’, ’S’, ’Y’, ’S’, ’\0’};

Each character in the array occupies one byte of memory and the last character is always ‘\0’. What character is this? It looks like two characters, but it is actually only one character, with the \ indicating that what follows it is something special. ‘\0’ is called null character. Note that ‘\0’ and ‘0’ are not same. The terminating null (‘\0’) is important, because it is the only way the function that work with a string can know where the string ends. In fact, a string not terminated by a ‘\0’ is not really a string, but merely a collection of characters.

C++ provides a shortcut for initializing string. For example, the string used above can also be initialized as,

char name[ ] = “INFOSYS” ;

Note that in this declaration ‘\0’ is not necessary. C++ inserts the null character automatically.

Note: There is a difference between a character and a string. A character takes only a single byte to store a character where as a string takes one extra character to store the null value. The examples below show the difference.

char a[ ] = ’A’        /* a is declared as a character */ 

This is how a is stored in memory

char b[ ] = ”A”       /* b is declared as a string */ 

This is how b is stored in memory

char c[50];

Declaring a string of 49 letters

 

The last example would declare a string with a length of 50 characters. Do not forget that arrays begin at zero, not 1 for the index number. In addition, a string ends with a null character, literally a ‘\0’ character. However, just remember that there will be an extra character on the end on a string. It is like a period at the end of a sentence, it is not counted as a letter, but it still takes up a space. Technically, in a fifty char array you could only hold 49 letters and one null character at the end to terminate the string.

TAKE NOTE: 

char *arry; 

This can also be used as a string. Using dynamic memory allocation, you can declare:  

arry = new char[256];

This allows you to access arry just as if it were an array. Keep in mind that to use delete you must put [] between delete and arry to tell it to free all 256 bytes of memory allocated. For example: 

delete [] arry;

Strings are useful for holding all types of long input. If you want the user to input his or her name, you must use a string. Using cin>> to input a string works, but it will terminate the string after it reads the first space. The best way to handle this situation is to use the function cin.getline. The prototype for this function is:

istream& getline(char *buffer, int length, char terminal_char);

The char *buffer is a pointer to the first element of the character array, so that it can actually be used to access the array. The int length is simply how long the string to be input can be at its maximum (how big the array is). The char terminal_char means that the string will terminate if the user inputs that particular character. It is possible to make a function call of cin.getline(arry, 50); without the terminal character. Note that ‘\n’ is the way of actually telling the compiler you mean a new line, i.e. someone hitting the enter key.

PROGRAM 38

Q. Write a program to accept text content for a paragraph containing multiple words and multiple lines. Use of TAB KEY must end the paragraph. (Note: After pressing TAB KEY, you will also have to press the Enter Key to exit from input stream)

#include <iostream>

using namespace std;

main()

{

  char a[256];                              

  cout<<"Please enter Paragraph Content:\n";

  cin.getline ( a, 256, '\t' );        

  cout<<"\nYour Paragraph >>>\n\n"<< a <<endl;

}


OUTPUT


















String Library Functions

C++ compiler comes with a large set of useful String handling Library Functions. Few commonly used functions include: strlen(), length(), strcpy(), strcat() and strcmp()

1.      strlen(), length()

These functions count the number of characters present in a string. Note: You can also use size() 


PROGRAM 39

Q.  Write a program to find the length of:

 (1) “initialized” character array,

 (2) “initialized” string,

 (3) “initialized” dynamic string/characters.


#include<cstring>

#include<iostream>

using namespace std;

main()

{

 char arr[] = "Groware Education";

 string s = "I am CPP student";

 int len1, len2, len3;

 len1 = strlen (arr);

 len2 = s.length();

 len3 = strlen ("IT Kerala");

 cout<<"String1 = "<< arr <<"\nLength = "<< len1<< "\n";

 cout<<"String2 = "<<s<<"\nLength = "<< len2<< "\n";

 cout<<"String3 = IT Kerala \nLength = "<< len3;

}

  OUTPUT













2.     strcpy()

This function copies the contents of one string into another. The base addresses of the source and target string should be supplied to this function.

PROGRAM 40         

Q.  Program to copy a String from one storage location to another.

#include<cstring>

#include <iostream>

using namespace std;

main()

{

  char source[ ] = "Sayonara";

  char target[20];

  strcpy(target, source);

  cout<<"\n Source string = "<<source;

  cout<<"\n Target string = "<<target;

}



        OUTPUT
Source string = Sayonara
Target string = Sayonara

3.     strcat()

This function concatenates (joins) 2 strings - the source string at the end of target string. For example ‘Info’ and ‘Sys’ on concatenation would result into a string ‘InfoSys’. 

Note: You can also concatenate 2 strings by the plus sign (+). For example:

string s1 = "Groware";

string s2;

s2=s1 + " Education";

         // s2 will contain "Groware Education"


PROGRAM 41   
   
Q.   Write a program to initialize two words and join them to form a single word.

#include<cstring>

#include <iostream>

using namespace std;

main()

{

 char a[30] = "Good";

 char b[] = " Morning";

 strcat (a, b);

 cout << "\n Source string = " << b;

 cout << "\n Target string = " << a;

}

  
OUTPUT

Source String =  Morning
Target String  = Good Morning

4.     strcmp()

This is a function which compares two strings to find out whether they are same or different. The two strings are compared character by character until there is a mismatch or end of one of the strings. strcmp() returns a zero value if both the strings are identical.

PROGRAM 42 

Q.  Accept two words. Compare the Two Words. Check if they are same.


#include <cstring>

#include <iostream>

using namespace std;

main()

{

  char s1 [25];

  char s2 [25];

  int val;

  cout << "Enter a word : "; cin >> s1;

  cout << "Enter another word : "; cin >> s2;

  val = strcmp(s1,s2);

  if (val == 0)

    cout << "Same Words";

  else 

    cout << "Not Same Words";

}


OUTPUT


2 Dimensional Array of Characters

Let’s see how 2 dimensional array of characters can be managed.

PROGRAM 43

Q.  Write a program to store few names into a character array. Then accept any name from the keyboard. Check if the accepted name is one among the stored names.
  

#include<iostream>

#include<cstring>

using namespace std;

main()

{    

  char names[5][10] = {"akshay", "parag", "raman", "srinivas", "gopal"};

  int i, a, flag;

  char n[10];

  cout << "\nEnter your name: ";

  cin >> n;

  flag = 0;

  for (i=0; i<5; i++)

  {

     a = strcmp (names[i], n);

     if (a == 0)

     {

         cout << "You are Welcome" ;

         flag = 1 ;

         break ;

      }

    }

  If (flag ==0)

   cout << "Sorry, you are not a Member";

}

    OUTPUT

NOTE: You can try working out with these string functions – find(), substr(), swap()

PREDEFINED MATHEMATICAL FUNCTIONS

Name            Function
abs(x)             absolute value
csgn(x)           complex sign
sqrt(x)            square root
sin(x)              sine
cos(x)             cosine
tan(x)              tangent
exp(x)             exponential function
log(x)              natural logarithm
pow(x,e)          power

PROGRAM 44Demonstrate the use of standard function “sqrt”.


#include <iostream>
#include <cmath>
using namespace std;
main ()
{
  float x;
  cout<<"Please enter a number: ";
  cin>>x;
  cout<<"Square Root of "<< x <<" is "<<sqrt(x);
}

OUTPUT
Please enter a number: 81
Square Root of 81 is 9

          

No comments:

Post a Comment