UNIT 4:  ARRAYS AND STRUCTURES

 

4.1 ARRAYS

 

Arrays a kind of data structure that can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.

 

Instead of declaring individual variables, such as number0, number1, …, and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and …, numbers[99] to represent individual variables. A specific element in an array is accessed by an index.

 

All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.

 

 

4.2 DEFINING AND PROCESSING

 

Declaring Arrays

 

To declare an array in C, a programmer specifies the type of the elements and the number of elements required by an array as follows –

 

type arrayName [ arraySize ];

 

This is called a single-dimensional array. The arraySize must be an integer constant greater than zero and type can be any valid C data type. For example, to declare a 10-element array called balance of type double, use this statement −

double balance[10];

 

Here balance is a variable array which is sufficient to hold up to 10 double numbers.

 

Initializing Arrays

 

You can initialize an array in C either one by one or using a single statement as follows –

double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};

 

The number of values between braces { } cannot be larger than the number of elements that we declare for the array between square brackets [ ].

 

If you omit the size of the array, an array just big enough to hold the initialization is created. Therefore, if you write −

double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};

 

You will create exactly the same array as you did in the previous example. Following is an example to assign a single element of the array −

balance[4] = 50.0;

 

The above statement assigns the 5th element in the array with a value of 50.0. All arrays have 0 as the index of their first element which is also called the base index and the last index of an array will be total size of the array minus 1. Shown below is the pictorial representation of the array we discussed above −

 

Accessing Array Elements

 

An element is accessed by indexing the array name. This is done by placing the index of the element within square brackets after the name of the array. For example −

double salary = balance[9];

The above statement will take the 10th element from the array and assign the value to salary variable. The following example Shows how to use all the three above mentioned concepts viz. declaration, assignment, and accessing arrays –

 

#include <stdio.h>

 

int main () {

 

int n[ 10 ]; /* n is an array of 10 integers */

int i,j;

 

/* initialize elements of array n to 0 */

for ( i = 0; i < 10; i++ ) {

n[ i ] = i + 100; /* set element at location i to i + 100 */

}

 

/* output each array element’s value */

for (j = 0; j < 10; j++ ) {

printf(“Element[%d] = %d\n”, j, n[j] );

}

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result –

 

Element[0] = 100

Element[1] = 101

Element[2] = 102

Element[3] = 103

Element[4] = 104

Element[5] = 105

Element[6] = 106

Element[7] = 107

Element[8] = 108

Element[9] = 109

 

Arrays in Detail

 

Arrays are important to C and should need a lot more attention. The following important concepts related to array should be clear to a C programmer –

 

Sr.No. Concept & Description
1 Multi-dimensional arrays

C supports multidimensional arrays. The simplest form of the multidimensional array is the two-dimensional array.

2 Passing arrays to functions

You can pass to the function a pointer to an array by specifying the array’s name without an index.

3 Return array from a function

C allows a function to return an array.

4 Pointer to an array

You can generate a pointer to the first element of an array by simply specifying the array name, without any index.

 

4.3 PASSING ARRAYS TO FUNCTIONS

 

In C programming, a single array element or an entire array can be passed to a function.

This can be done for both one-dimensional array or a multi-dimensional array.

 

Passing One-dimensional Array In Function

 

Single element of an array can be passed in similar manner as passing variable to a function.

 

 

 

C program to pass a single element of an array to function

 

#include <stdio.h>

void display(int age)

{

printf(“%d”, age);

}

 

int main()

{

int ageArray[] = { 2, 3, 4 };

display(ageArray[2]); //Passing array element ageArray[2] only.

return 0;

}

 

Output

4

 

Passing an entire one-dimensional array to a function

 

While passing arrays as arguments to the function, only the name of the array is passed (,i.e, starting address of memory area is passed as argument).

 

C program to pass an array containing age of person to a function. This function should find average age and display the average age in main function.

 

#include <stdio.h>

float average(float age[]);

 

int main()

{

float avg, age[] = { 23.4, 55, 22.6, 3, 40.5, 18};

avg = average(age); // Only name of an array is passed as an argument

printf(“Average age = %.2f”, avg);

return 0;

}

 

float average(float age[])

{

int i;

float avg, sum = 0.0;

for (i = 0; i < 6; ++i) {

sum += age[i];

}

avg = (sum / 6);

return avg;

}

 

Output

Average age = 27.08

 

Passing Multi-dimensional Arrays to Function

 

To pass two-dimensional array to a function as an argument, starting address of memory area reserved is passed as in one dimensional array

 

#include <stdio.h>

void displayNumbers(int num[2][2]);

int main()

{

int num[2][2], i, j;

printf(“Enter 4 numbers:\n”);

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

for (j = 0; j < 2; ++j)

scanf(“%d”, &num[i][j]);

// passing multi-dimensional array to displayNumbers function

displayNumbers(num);

return 0;

}

 

void displayNumbers(int num[2][2])

{

// Instead of the above line,

// void displayNumbers(int num[][2]) is also valid

int i, j;

printf(“Displaying:\n”);

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

for (j = 0; j < 2; ++j)

printf(“%d\n”, num[i][j]);

}

 

Output

Enter 4 numbers:

2

3

4

5

Displaying:

2

3

4

5

 

4.4 MULTI-DIMENSION ARRAYS

 

C programming language allows multidimensional arrays. Here is the general form of a multidimensional array declaration −

type name[size1][size2]…[sizeN];

 

For example, the following declaration creates a three dimensional integer array −

int threedim[5][10][4];

 

Two-dimensional Arrays

 

The simplest form of multidimensional array is the two-dimensional array. A two-dimensional array is, in essence, a list of one-dimensional arrays. To declare a two-dimensional integer array of size [x][y], you would write something as follows −

type arrayName [ x ][ y ];

 

Where type can be any valid C data type and arrayName will be a valid C identifier. A two-dimensional array can be considered as a table which will have x number of rows and y number of columns. A two-dimensional array a, which contains three rows and four columns can be shown as follows –

 

 

Thus, every element in the array a is identified by an element name of the form a[ i ][ j ], where ‘a’ is the name of the array, and ‘i’ and ‘j’ are the subscripts that uniquely identify each element in ‘a’.

 

Initializing Two-Dimensional Arrays

 

Multidimensional arrays may be initialized by specifying bracketed values for each row. Following is an array with 3 rows and each row has 4 columns.

 

int a[3][4] = {

{0, 1, 2, 3} ,   /*  initializers for row indexed by 0 */

{4, 5, 6, 7} ,   /*  initializers for row indexed by 1 */

{8, 9, 10, 11}   /*  initializers for row indexed by 2 */

};

 

The nested braces, which indicate the intended row, are optional. The following initialization is equivalent to the previous example −

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

 

Accessing Two-Dimensional Array Elements

 

An element in a two-dimensional array is accessed by using the subscripts, i.e., row index and column index of the array. For example −

int val = a[2][3];

 

The above statement will take the 4th element from the 3rd row of the array. You can verify it in the above figure. Let us check the following program where we have used a nested loop to handle a two-dimensional array −

 

#include <stdio.h>

 

int main () {

 

/* an array with 5 rows and 2 columns*/

int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};

int i, j;

 

/* output each array element’s value */

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

 

for ( j = 0; j < 2; j++ ) {

printf(“a[%d][%d] = %d\n”, i,j, a[i][j] );

}

}

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result –

 

a[0][0]: 0

a[0][1]: 0

a[1][0]: 1

a[1][1]: 2

a[2][0]: 2

a[2][1]: 4

a[3][0]: 3

a[3][1]: 6

a[4][0]: 4

a[4][1]: 8

 

As explained above, you can have arrays with any number of dimensions, although it is likely that most of the arrays you create will be of one or two dimensions.

 

4.5 STRINGS

 

Strings are actually one-dimensional array of characters terminated by a null character ‘\0’. Thus a null-terminated string contains the characters that comprise the string followed by a null.

 

The following declaration and initialization create a string consisting of the word “Hello”. To hold the null character at the end of the array, the size of the character array containing the string is one more than the number of characters in the word “Hello.”

char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};

 

If you follow the rule of array initialization then you can write the above statement as follows –

 

char greeting[] = “Hello”;

 

Following is the memory presentation of the above defined string in C/C++ −

 

Actually, you do not place the null character at the end of a string constant. The C compiler automatically places the ‘\0’ at the end of the string when it initializes the array. Let us try to print the above mentioned string –

 

#include <stdio.h>

 

int main () {

 

char greeting[6] = {‘H’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};

printf(“Greeting message: %s\n”, greeting );

return 0;

}

When the above code is compiled and executed, it produces the following result −

Greeting message: Hello

 

C supports a wide range of functions that manipulate null-terminated strings –

 

Sr.No. Function & Purpose
1 strcpy(s1, s2);

Copies string s2 into string s1.

2 strcat(s1, s2);

Concatenates string s2 onto the end of string s1.

3 strlen(s1);

Returns the length of string s1.

4 strcmp(s1, s2);

Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.

5 strchr(s1, ch);

Returns a pointer to the first occurrence of character ch in string s1.

6 strstr(s1, s2);

Returns a pointer to the first occurrence of string s2 in string s1.

 

The following example uses some of the above-mentioned functions −

 

#include <stdio.h>

#include <string.h>

 

int main () {

 

char str1[12] = “Hello”;

char str2[12] = “World”;

char str3[12];

int  len ;

 

/* copy str1 into str3 */

strcpy(str3, str1);

printf(“strcpy( str3, str1) :  %s\n”, str3 );

 

/* concatenates str1 and str2 */

strcat( str1, str2);

printf(“strcat( str1, str2):   %s\n”, str1 );

 

/* total lenghth of str1 after concatenation */

len = strlen(str1);

printf(“strlen(str1) :  %d\n”, len );

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result −

strcpy( str3, str1) :  Hello

strcat( str1, str2):   HelloWorld

strlen(str1) :  10

 

4.6 ARRAYS AND STRINGS

 

Strings are declared in a similar wayas arrays. Only difference is that, strings are of char type.

 

Using arrays

char s[5];

 

Using pointers

Strings can also be declared using pointers.

char *p;

 

Initialization of strings

In C, string can be initialized in a number of different ways.

For convenience and ease, both initialization and declaration are done in the same step.

 

Using arrays

char c[] = “abcd”;

OR,

char c[50] = “abcd”;

OR,

char c[] = {‘a’, ‘b’, ‘c’, ‘d’, ‘\0’};

OR,

char c[5] = {‘a’, ‘b’, ‘c’, ‘d’, ‘\0’};

 

The given string is initialized and stored in the form of arrays as above.

 

4.7 STRUCTURES

 

Structure is a collection of variables of different types under a single name.

 

For example: You want to store some information about a person: his/her name, citizenship number and salary. You can easily create different variables name, citNo, salary to store these information separately.

 

However, in the future, you would want to store information about multiple persons. Now, you’d need to create different variables for each information per person: name1, citNo1, salary1, name2, citNo2, salary2

 

You can easily visualize how big and messy the code would look. Also, since no relation between the variables (information) would exist, it’s going to be a daunting task.

 

A better approach will be to have a collection of all related information under a single name Person, and use it for every person. Now, the code looks much cleaner, readable and efficient as well.

 

This collection of all related information under a single name Person is a structure.

 

Structure Definition in C

Keyword struct is used for creating a structure.

 

Syntax of structure

struct structure_name

{

data_type member1;

data_type member2;

.

.

data_type memeber;

};

 

Note: Don’t forget the semicolon }; in the ending line.

We can create the structure for a person as mentioned above as:

struct person

{

char name[50];

int citNo;

float salary;

};

 

This declaration above creates the derived data type struct person.

 

Structure variable declaration

 

When a structure is defined, it creates a user-defined type but, no storage or memory is allocated.

For the above structure of a person, variable can be declared as:

 

struct person

{

char name[50];

int citNo;

float salary;

};

 

int main()

{

struct person person1, person2, person3[20];

return 0;

}

 

Another way of creating a structure variable is:

struct person

{

char name[50];

int citNo;

float salary;

} person1, person2, person3[20];

 

In both cases, two variables person1, person2 and an array person3 having 20 elements of type struct person are created.

 

Accessing members of a structure

 

There are two types of operators used for accessing members of a structure.

  1. Member operator(.)
  2. Structure pointer operator(->)

 

Any member of a structure can be accessed as:

structure_variable_name.member_name

 

Suppose, we want to access salary for variable person2. Then, it can be accessed as:

person2.salary

 

Example of structure

Write a C program to add two distances entered by user. Measurement of distance should be in inch and feet. (Note: 12 inches = 1 foot)

 

#include <stdio.h>

struct Distance

{

int feet;

float inch;

} dist1, dist2, sum;

 

int main()

{

printf(“1st distance\n”);

 

// Input of feet for structure variable dist1

printf(“Enter feet: “);

scanf(“%d”, &dist1.feet);

 

// Input of inch for structure variable dist1

printf(“Enter inch: “);

scanf(“%f”, &dist1.inch);

 

printf(“2nd distance\n”);

 

// Input of feet for structure variable dist2

printf(“Enter feet: “);

scanf(“%d”, &dist2.feet);

 

// Input of feet for structure variable dist2

printf(“Enter inch: “);

scanf(“%f”, &dist2.inch);

 

sum.feet = dist1.feet + dist2.feet;

sum.inch = dist1.inch + dist2.inch;

 

if (sum.inch > 12)

{

//If inch is greater than 12, changing it to feet.

++sum.feet;

sum.inch = sum.inch – 12;

}

 

// printing sum of distance dist1 and dist2

printf(“Sum of distances = %d\’-%.1f\””, sum.feet, sum.inch);

return 0;

}

 

Output

 

1st distance

Enter feet: 12

Enter inch: 7.9

2nd distance

Enter feet: 2

Enter inch: 9.8

Sum of distances = 15′-5.7″

 

Keyword typedef while using structure

 

Writing struct structure_name variable_name; to declare a structure variable isn’t intuitive as to what it signifies, and takes some considerable amount of development time.

 

So, developers generally use typedef to name the structure as a whole. For example:

typedef struct complex

{

int imag;

float real;

} comp;

 

int main()

{

comp comp1, comp2;

}

 

Here, typedef keyword is used in creating a type comp (which is of type as struct complex).

Then, two structure variables comp1 and comp2 are created by this comp type.

 

Structures within structures

 

Structures can be nested within other structures in C programming.

struct complex

{

int imag_value;

float real_value;

};

 

struct number

{

struct complex comp;

int real;

} num1, num2;

 

Suppose, you want to access imag_value for num2 structure variable then, following structure member is used.

num2.comp.imag_value

 

4.8 USER DEFINED DATA TYPES

 

For better understanding of arguments and return value from the function, user-defined functions can be categorized as:

 

 

The 4 programs below check whether an integer entered by the user is a prime number or not. And, all these programs generate the same output.

 

No arguments passed and no return Value

#include <stdio.h>

 

void checkPrimeNumber();

 

int main()

{

checkPrimeNumber();    // no argument is passed to prime()

return 0;

}

 

// return type of the function is void because no value is returned from the function

void checkPrimeNumber()

{

int n, i, flag=0;

 

printf(“Enter a positive integer: “);

scanf(“%d”,&n);

 

for(i=2; i <= n/2; ++i)

{

if(n%i == 0)

{

flag = 1;

}

}

if (flag == 1)

printf(“%d is not a prime number.”, n);

else

printf(“%d is a prime number.”, n);

}

The checkPrimeNumber() function takes input from the user, checks whether it is a prime number or not and displays it on the screen.

 

The empty parentheses in checkPrimeNumber(); statement inside the main() function indicates that no argument is passed to the function.

 

The return type of the function is void. Hence, no value is returned from the function.

 

No arguments passed but a return value

#include <stdio.h>

int getInteger();

 

int main()

{

int n, i, flag = 0;

 

// no argument is passed to the function

// the value returned from the function is assigned to n

n = getInteger();

 

for(i=2; i<=n/2; ++i)

{

if(n%i==0){

flag = 1;

break;

}

}

 

if (flag == 1)

printf(“%d is not a prime number.”, n);

else

printf(“%d is a prime number.”, n);

 

return 0;

}

 

// getInteger() function returns integer entered by the user

int getInteger()

{

int n;

 

printf(“Enter a positive integer: “);

scanf(“%d”,&n);

 

return n;

}

 

The empty parentheses in n = getInteger(); statement indicates that no argument is passed to the function. And, the value returned from the function is assigned to n.

 

Here, the getInteger() function takes input from the user and returns it. The code to check whether a number is prime or not is inside the main() function.

 

Argument passed but no return value

#include <stdio.h>

void checkPrimeAndDisplay(int n);

 

int main()

{

int n;

 

printf(“Enter a positive integer: “);

scanf(“%d”,&n);

 

// n is passed to the function

checkPrimeAndDisplay(n);

 

return 0;

}

 

// void indicates that no value is returned from the function

void checkPrimeAndDisplay(int n)

{

int i, flag = 0;

 

for(i=2; i <= n/2; ++i)

{

if(n%i == 0){

flag = 1;

break;

}

}

if(flag == 1)

printf(“%d is not a prime number.”,n);

else

printf(“%d is a prime number.”, n);

}

The integer value entered by the user is passed to checkPrimeAndDisplay() function.

Here, the checkPrimeAndDisplay() function checks whether the argument passed is a prime number or not and displays the appropriate message.

 

Argument passed and a return value

#include <stdio.h>

int checkPrimeNumber(int n);

 

int main()

{

int n, flag;

 

printf(“Enter a positive integer: “);

scanf(“%d”,&n);

 

// n is passed to the checkPrimeNumber() function

// the value returned from the function is assigned to flag variable

flag = checkPrimeNumber(n);

 

if(flag==1)

printf(“%d is not a prime number”,n);

else

printf(“%d is a prime number”,n);

 

return 0;

}

 

// integer is returned from the function

int checkPrimeNumber(int n)

{

/* Integer value is returned from function checkPrimeNumber() */

int i;

 

for(i=2; i <= n/2; ++i)

{

if(n%i == 0)

return 1;

}

 

return 0;

}

 

The input from the user is passed to checkPrimeNumber() function.

 

The checkPrimeNumber() function checks whether the passed argument is prime or not. If the passed argument is a prime number, the function returns 0. If the passed argument is a non-prime number, the function returns 1. The return value is assigned to flag variable.

 

Then, the appropriate message is displayed from the main() function.

 

4.9 PASSING STRUCTURES TO FUNCTIONS

 

In C, structure can be passed to functions by two methods:

  1. Passing by value (passing actual value as argument)
  2. Passing by reference (passing address of an argument)

 

Passing structure by value

 

A structure variable can be passed to the function as an argument as a normal variable.

If structure is passed by value, changes made to the structure variable inside the function definition does not reflect in the originally passed structure variable.

 

C program to create a structure student, containing name and roll and display the information.

#include <stdio.h>

struct student

{

char name[50];

int roll;

};

 

void display(struct student stu);

// function prototype should be below to the structure declaration otherwise compiler shows error

 

int main()

{

struct student stud;

 

printf(“Enter student’s name: “);

scanf (“%[^\n]%*c”, stud.name);

 

printf(“Enter roll number:”);

scanf(“%d”, &stud.roll);

 

display(stud);   // passing structure variable stud as argument

 

return 0;

}

void display(struct student stu){

printf(“Output\nName: %s”,stu.name);

printf(“\nRoll: %d”,stu.roll);

}

 

Output

 

Enter student’s name: Kevin Amla

Enter roll number: 149

Output

Name: Kevin Amla

Roll: 149

 

Passing structure by reference

 

The memory address of a structure variable is passed to function while passing it by reference.

If structure is passed by reference, changes made to the structure variable inside function definition reflects in the originally passed structure variable.

C program to add two distances (feet-inch system) and display the result without the return statement.

 

#include <stdio.h>

struct distance

{

int feet;

float inch;

};

void add(struct distance d1,struct distance d2, struct distance *d3);

 

int main()

{

struct distance dist1, dist2, dist3;

 

printf(“First distance\n”);

printf(“Enter feet: “);

scanf(“%d”, &dist1.feet);

printf(“Enter inch: “);

scanf(“%f”, &dist1.inch);

 

printf(“Second distance\n”);

printf(“Enter feet: “);

scanf(“%d”, &dist2.feet);

printf(“Enter inch: “);

scanf(“%f”, &dist2.inch);

 

add(dist1, dist2, &dist3);

 

//passing structure variables dist1 and dist2 by value whereas passing structure variable dist3 by reference

printf(“\nSum of distances = %d\’-%.1f\””, dist3.feet, dist3.inch);

 

return 0;

}

void add(struct distance d1,struct distance d2, struct distance *d3)

{

//Adding distances d1 and d2 and storing it in d3

d3->feet = d1.feet + d2.feet;

d3->inch = d1.inch + d2.inch;

 

if (d3->inch >= 12) {     /* if inch is greater or equal to 12, converting it to feet. */

d3->inch -= 12;

++d3->feet;

}

}

 

Output

First distance

Enter feet: 12

Enter inch: 6.8

Second distance

Enter feet: 5

Enter inch: 7.5

 

Sum of distances = 18′-2.3″

 

In this program, structure variables dist1 and dist2 are passed by value to the add function (because value of dist1 and dist2 does not need to be displayed in main function).

 

But, dist3 is passed by reference ,i.e, address of dist3 (&dist3) is passed as an argument.

 

Due to this, the structure pointer variable d3 inside the add function points to the address of dist3 from the calling main function. So, any change made to the d3 variable is seen in dist3 variable in main function.

As a result, the correct sum is displayed in the output.

4.10 SELF-REFERENTIAL STRUCTURES

 

A self referential data structure is essentially a structure definition which includes at least one member that is a pointer to the structure of its own kind. A chain of such structures can thus be expressed as follows.

struct name {

member 1;

member 2;

. . .

struct name *pointer;

};

 

The above illustrated structure prototype describes one node that comprises of two logical segments. One of them stores data/information and the other one is a pointer indicating where the next component can be found. Several such inter-connected nodes create a chain of structures.

 

The following figure depicts the composition of such a node. The figure is a simplified illustration of nodes that collectively form a chain of structures or linked list.

 

Such self-referential structures are very useful in applications that involve linked data structures, such as lists and trees. Unlike a static data structure such as array where the number of elements that can be inserted in the array is limited by the size of the array, a self-referential structure can dynamically be expanded or contracted. Operations like insertion or deletion of nodes in a self- referential structure involve simple and straight forward alteration of pointers.

 

Linear (Singly) Linked List

 

A linear linked list is a chain of structures where each node points to the next node to create a list. To keep track of the starting node’s address a dedicated pointer (referred as start pointer) is used. The end of the list is indicated by a NULL pointer. In order to create a linked list of integers, we define each of its element (referred as node) using the following declaration.

 

struct node_type {

int data;

struct node_type *next;

};

struct node_type *start = NULL;

 

Note: The second member points to a node of same type.

 

A linear linked list illustration:

 

Example

 

Let us now develop a C program to manipulate linked lists. For this purpose we introduce a few basic functions, which can be used to create a list, displaying its contents, inserting into a list and deleting an existing element. We also introduce two functions reverse and recReverse for reversing the elements of the list.

 

When a list is created a pointer called start is used to indicate the beginning of the list. A function createNode, creates a node and returns a pointer to it. The function insert is used to insert a new node in an existing list provided the data is not already present in the list. If it is not present, we place the data in a manner so that the new element is appended at the end of the list.

 

#include <stdio.h>

 

struct node_type {

int data;

struct node_type *next;

};

typedef struct node_type list;

 

void showList();          //displays list contents

list *reverse(); //reverses the list

list *insert();

list *createNode();

list *delete();

list *find();

 

main()

{

list *temp, *start = NULL; //start will point to first node of the list

char c = ‘y’;

int n;

 

while(c != ‘n’ && c != ‘N’)

{

printf(“\nEnter the data: “);

scanf(“%d”,&n); getchar(); fflush(stdin);

temp = createNode();

temp->data = n;

temp->next = NULL;

if(!find(start,temp->data))

start = insert(start,temp);

 

printf(“\nDo you want to add new data in the list? (y/n): “);

scanf(“%c”,&c); fflush(stdin);

}

printf(“\nTHE LIST IS: “); showList(start); printf(“\n\n”);

 

c = ‘y’;

while(c != ‘n’ && c != ‘N’)

{

printf(“\nEnter the data to be deleted: “);

scanf(“%d”,&n); getchar(); fflush(stdin);

if(find(start, n)) start = delete(start, n);

 

printf(“\nDo you want to delete another data from the list? (y/n):”);

scanf(“%c”, &c) ; fflush(stdin);

}

printf(“\nTHE LIST AFTER DATA DELETION IS: “); showList(start); printf(“\n\n”);

 

start = reverse(start);

printf(“\nTHE REVERSED LIST IS: “); showList(start); printf(“\n\n”);

}

 

 

/* Function to create a Node. Allocates memory for a new node. */

list *createNode()

{

list *new;

new = (list *)malloc(sizeof(list));

return(new);

}

 

 

/* Recursive function to create and insert a new node at the end of the list */

list *insert(list *st, list *ndt)

{

if(!st) return(ndt);

st->next = insert(st->next, ndt);

return(st);

}

 

 

/*

Function to search a data item in the list and return the node address

that matches data. In case no match found, returns NULL

*/

list *find(list *st, int dt)

{

while(st)

if(st->data == dt)

return (st);

else

st = st->next;

return(st);

}

 

void showList(list *temp)

{

while(temp)

{

printf(“%d “, temp->data);

temp = temp->next;

}

printf(“\n”);

}

 

 

/* Function to reverse the list */

list *reverse(list *l)

{

list *nxt, *temp;

if(!l) return(l);

else

{

nxt = l->next;

l->next = NULL;

while(nxt)

{

temp = nxt->next;

nxt->next = l;

l = nxt;

nxt = temp;

}

return(l);

}

}

 

 

/* Recursive function for deleting a node from the list */

list *delete(list *st, int n)

{

list *tmp;

if(!st) return(st);

if(st->data == n)

{

tmp = st;

st = st->next;

free(tmp);

return(st);

}

st->next = delete(st->next,n);

return(st);

}

 

4.11 UNIONS

 

A union is a special data type available in C that allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time. Unions provide an efficient way of using the same memory location for multiple-purpose.

 

Defining a Union

 

To define a union, you must use the union statement in the same way as you did while defining a structure. The union statement defines a new data type with more than one member for your program. The format of the union statement is as follows −

union [union tag] {

member definition;

member definition;

member definition;

} [one or more union variables];

 

The union tag is optional and each member definition is a normal variable definition, such as int i; or float f; or any other valid variable definition. At the end of the union’s definition, before the final semicolon, you can specify one or more union variables but it is optional. Here is the way you would define a union type named Data having three members i, f, and str –

 

union Data {

int i;

float f;

char str[20];

} data;

 

Now, a variable of Data type can store an integer, a floating-point number, or a string of characters. It means a single variable, i.e., same memory location, can be used to store multiple types of data. You can use any built-in or user defined data types inside a union based on your requirement.

 

The memory occupied by a union will be large enough to hold the largest member of the union. For example, in the above example, Data type will occupy 20 bytes of memory space because this is the maximum space which can be occupied by a character string. The following example displays the total memory size occupied by the above union −

 

#include <stdio.h>

#include <string.h>

 

union Data {

int i;

float f;

char str[20];

};

 

int main( ) {

 

union Data data;

 

printf( “Memory size occupied by data : %d\n”, sizeof(data));

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result −

Memory size occupied by data : 20

 

Accessing Union Members

 

To access any member of a union, we use the member access operator (.). The member access operator is coded as a period between the union variable name and the union member that we wish to access. You would use the keyword union to define variables of union type. The following example shows how to use unions in a program –

 

#include <stdio.h>

#include <string.h>

 

union Data {

int i;

float f;

char str[20];

};

 

int main( ) {

 

union Data data;

 

data.i = 10;

data.f = 220.5;

strcpy( data.str, “C Programming”);

 

printf( “data.i : %d\n”, data.i);

printf( “data.f : %f\n”, data.f);

printf( “data.str : %s\n”, data.str);

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result −

data.i : 1917853763

data.f : 4122360580327794860452759994368.000000

data.str : C Programming

 

Here, we can see that the values of i and f members of union got corrupted because the final value assigned to the variable has occupied the memory location and this is the reason that the value of str member is getting printed very well.

 

Now let’s look into the same example once again where we will use one variable at a time which is the main purpose of having unions −

#include <stdio.h>

#include <string.h>

 

union Data {

int i;

float f;

char str[20];

};

 

int main( ) {

 

union Data data;

 

data.i = 10;

printf( “data.i : %d\n”, data.i);

 

data.f = 220.5;

printf( “data.f : %f\n”, data.f);

 

strcpy( data.str, “C Programming”);

printf( “data.str : %s\n”, data.str);

 

return 0;

}

 

When the above code is compiled and executed, it produces the following result −

data.i : 10

data.f : 220.500000

data.str : C Programming

Here, all the members are getting printed very well because one member is being used at a time.

 

 

4.12 BIT WISE OPERATIONS

 

The following table lists the Bitwise operators supported by C. Assume variable ‘A’ holds 60 and variable ‘B’ holds 13, then –

 

Operator Description Example
& Binary AND Operator copies a bit to the result if it exists in both operands. (A & B) = 12, i.e., 0000 1100
| Binary OR Operator copies a bit if it exists in either operand. (A | B) = 61, i.e., 0011 1101
^ Binary XOR Operator copies the bit if it is set in one operand but not both. (A ^ B) = 49, i.e., 0011 0001
~ Binary Ones Complement Operator is unary and has the effect of ‘flipping’ bits. (~A ) = -60, i.e,. 1100 0100 in 2’s complement form.
<< Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. A << 2 = 240 i.e., 1111 0000
>> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. A >> 2 = 15 i.e., 0000 1111

 

Example

Try the following example to understand all the bitwise operators available in C −

 

#include <stdio.h>

 

main() {

 

unsigned int a = 60; /* 60 = 0011 1100 */

unsigned int b = 13; /* 13 = 0000 1101 */

int c = 0;

 

c = a & b;       /* 12 = 0000 1100 */

printf(“Line 1 – Value of c is %d\n”, c );

 

c = a | b;       /* 61 = 0011 1101 */

printf(“Line 2 – Value of c is %d\n”, c );

 

c = a ^ b;       /* 49 = 0011 0001 */

printf(“Line 3 – Value of c is %d\n”, c );

 

c = ~a;          /*-61 = 1100 0011 */

printf(“Line 4 – Value of c is %d\n”, c );

 

c = a << 2;     /* 240 = 1111 0000 */

printf(“Line 5 – Value of c is %d\n”, c );

 

c = a >> 2;     /* 15 = 0000 1111 */

printf(“Line 6 – Value of c is %d\n”, c );

}

 

When you compile and execute the above program, it produces the following result −

Line 1 – Value of c is 12

Line 2 – Value of c is 61

Line 3 – Value of c is 49

Line 4 – Value of c is -61

Line 5 – Value of c is 240

Line 6 – Value of c is 15