Unit 2
Arrays, Strings, Structures and Pointers
Arrays:
An array is a collection of data items, all of the same type, accessed using a common name.
A one-dimensional array is like a list; A two dimensional array is like a table; The C language places no limits on the number of dimensions in an array, though specific implementations may.
Some texts refer to one-dimensional arrays as vectors, two-dimensional arrays as matrices, and use the general term arrays when the number of dimensions is unspecified or unimportant.
Declaring Arrays
Array variables are declared identically to variables of their data type, except that the variable name is followed by one pair of square [ ] brackets for each dimension of the array.
Uninitialized arrays must have the dimensions of their rows, columns, etc. listed within the square brackets.
Dimensions used when declaring arrays in C must be positive integral constants or constant expressions.
In C99, dimensions must still be positive integers, but variables can be used, so long as the variable has a positive value at the time the array is declared. ( Space is allocated only once, at the time the array is declared. The array does NOT change sizes later if the variable used to declare it changes. )
Examples:
Int i, j, intArray[ 10 ], number;
Float floatArray[ 1000 ];
Int tableArray[ 3 ][ 5 ]; /* 3 rows by 5 columns */
Const int NROWS = 100; // ( Old code would use #define NROWS 100 )
Const int NCOLS = 200; // ( Old code would use #define NCOLS 200 )
Float matrix[ NROWS ][ NCOLS ];
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
1-D array has 1 row and multiple columns but multidimensional array has of multiple rows and multiple columns.
Two Dimensional array:
It is the simplest multidimensional array. They are also called as matrix.
Declaration:
Data-type array_name[no.of rows][no. Of columns];
Total no of elements= No.of rows * No. Of Columns
Example 3: int a[2][3]
This example illustrates two-dimensional array a of 2 rows and 3 columns.
Col 0 Col 1 Col 2
Row 0
a[0][0]
| a[0][1]
| a[0][2]
|
a[1][0]
| a[1][1]
| a[1][2]
|
Row 1
Fig.2: Index positions of elements of a[2][3]
Total no of elements: 2*3=6
Total no of bytes occupied: 6( total no.of elements )*2(Size of one element)=12
Initialization and Storage Representation:
In C, two dimensional arrays can be initialized in different number of ways. Specification of no. Of columns in 2 dimensional array is mandatory while no of rows is optional.
Int a[2][3]={{1,3,0}, // Elements of 1st row
{-1,5,9}}; // Elements of 2nd row
OR
Int a[][3]={{1,3,0}, // Elements of 1st row
{-1,5,9}}; // Elements of 2nd row
OR
Int a[2][3]={1,3,0,-1,5,9};
Fig. 3 gives general storage representation of 2 dimensional array
Col 0 Col 1 Col n
Row 0
a[0][0]
| a[0][1]
|
--- | a[0][n]
|
a[1][0]
| a[1][1]
|
--- | a[1][n]
|
- | -
| - | - |
a[m][0] |
a[m][1] |
|
a[m][n] |
Row 1
-
-
Row m
Fig.3 General Storage Representation of 2 dimensional array.
Eg 4. Int a[2][3]={1,3,0,-1,5,9}
1
| 3 | 0 |
-1
| 5 | 9 |
Row 0
Row 1
Col 0 col1 col2
Accessing Two-Dimensional Array Elements:
An element in 2-dimensional array is accessed by using the subscripts i.e. row index and column index of the array. For example:
Int val = A[1][2];
The above statement will access element from the 2nd row and third column of the array A i.e. element 9.
Strings:
The string can be defined as the one-dimensional array of characters terminated by a null ('\0'). The character array or the string is used to manipulate text such as word or sentences. Each character in the array occupies one byte of memory, and the last character must always be 0. The termination character ('\0') is important in a string since it is the only way to identify where the string ends. When we define a string as char s[10], the character s[10] is implicitly initialized with the null in the memory.
There are two ways to declare a string in c language.
- By char array
- By string literal
Let's see the example of declaring string by char array in C language.
- Char ch[10]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
As we know, array index starts from 0, so it will be represented as in the figure given below.
While declaring string, size is not mandatory. So we can write the above code as given below:
- Char ch[]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
We can also define the string by the string literal in C language. For example:
- Char ch[]="javatpoint";
In such case, '\0' will be appended at the end of the string by the compiler.
Difference between char array and string literal
There are two main differences between char array and literal.
- We need to add the null character '\0' at the end of the array by ourself whereas, it is appended internally by the compiler in the case of the character array.
- The string literal cannot be reassigned to another set of characters whereas, we can reassign the characters of the array.
String Example in C
Let's see a simple example where a string is declared and being printed. The '%s' is used as a format specifier for the string in c language.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char ch[11]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
- Char ch2[11]="javatpoint";
- Printf("Char Array Value is: %s\n", ch);
- Printf("String Literal Value is: %s\n", ch2);
- Return 0;
- }
Output
Char Array Value is: javatpoint
String Literal Value is: javatpoint
Traversing String
Traversing the string is one of the most important aspects in any of the programming languages. We may need to manipulate a very large text which can be done by traversing the text. Traversing string is somewhat different from the traversing an integer array. We need to know the length of the array to traverse an integer array, whereas we may use the null character in the case of string to identify the end the string and terminate the loop.
Hence, there are two ways to traverse a string.
- By using the length of string
- By using the null character.
Let's discuss each one of them.
Using the length of string
Let's see an example of counting the number of vowels in a string.
- #include<stdio.h>
- Void main ()
- {
- Char s[11] = "javatpoint";
- Int i = 0;
- Int count = 0;
- While(i<11)
- {
- If(s[i]=='a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u' || s[i] == 'o')
- {
- Count ++;
- }
- i++;
- }
- Printf("The number of vowels %d",count);
- }
Output
The number of vowels 4
Using the null character
Let's see the same example of counting the number of vowels by using the null character.
- #include<stdio.h>
- Void main ()
- {
- Char s[11] = "javatpoint";
- Int i = 0;
- Int count = 0;
- While(s[i] != NULL)
- {
- If(s[i]=='a' || s[i] == 'e' || s[i] == 'i' || s[i] == 'u' || s[i] == 'o')
- {
- Count ++;
- }
- i++;
- }
- Printf("The number of vowels %d",count);
- }
Output
The number of vowels 4
Accepting string as the input
Till now, we have used scanf to accept the input from the user. However, it can also be used in the case of strings but with a different scenario. Consider the below code which stores the string while space is encountered.
- #include<stdio.h>
- Void main ()
- {
- Char s[20];
- Printf("Enter the string?");
- Scanf("%s",s);
- Printf("You entered %s",s);
- }
Output
Enter the string?javatpoint is the best
You entered javatpoint
It is clear from the output that, the above code will not work for space separated strings. To make this code working for the space separated strings, the minor changed required in the scanf function, i.e., instead of writing scanf("%s",s), we must write: scanf("%[^\n]s",s) which instructs the compiler to store the string s while the new line (\n) is encountered. Let's consider the following example to store the space-separated strings.
- #include<stdio.h>
- Void main ()
- {
- Char s[20];
- Printf("Enter the string?");
- Scanf("%[^\n]s",s);
- Printf("You entered %s",s);
- }
Output
Enter the string?javatpoint is the best
You entered javatpoint is the best
Here we must also notice that we do not need to use address of (&) operator in scanf to store a string since string s is an array of characters and the name of the array, i.e., s indicates the base address of the string (character array) therefore we need not use & with it.
Some important points
However, there are the following points which must be noticed while entering the strings by using scanf.
- The compiler doesn't perform bounds checking on the character array. Hence, there can be a case where the length of the string can exceed the dimension of the character array which may always overwrite some important data.
- Instead of using scanf, we may use gets() which is an inbuilt function defined in a header file string.h. The gets() is capable of receiving only one string at a time.
Pointers with strings
We have used pointers with the array, functions, and primitive data types so far. However, pointers can be used to point to the strings. There are various advantages of using pointers to point strings. Let us consider the following example to access the string via the pointer.
- #include<stdio.h>
- Void main ()
- {
- Char s[11] = "javatpoint";
- Char *p = s; // pointer p is pointing to string s.
- Printf("%s",p); // the string javatpoint is printed if we print p.
- }
Output
Javatpoint
As we know that string is an array of characters, the pointers can be used in the same way they were used with arrays. In the above example, p is declared as a pointer to the array of characters s. P affects similar to s since s is the base address of the string and treated as a pointer internally. However, we can not change the content of s or copy the content of s into another string directly. For this purpose, we need to use the pointers to store the strings. In the following example, we have shown the use of pointers to copy the content of a string into another.
- #include<stdio.h>
- Void main ()
- {
- Char *p = "hello javatpoint";
- Printf("String p: %s\n",p);
- Char *q;
- Printf("copying the content of p into q...\n");
- q = p;
- Printf("String q: %s\n",q);
- }
Output
String p: hello javatpoint
Copying the content of p into q...
String q: hello javatpoint
Once a string is defined, it cannot be reassigned to another set of characters. However, using pointers, we can assign the set of characters to the string. Consider the following example.
- #include<stdio.h>
- Void main ()
- {
- Char *p = "hello javatpoint";
- Printf("Before assigning: %s\n",p);
- p = "hello";
- Printf("After assigning: %s\n",p);
- }
Output
Before assigning: hello javatpoint
After assigning: hello
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
There are many important string functions defined in "string.h" library.
No. | Function | Description |
1) | Strlen(string_name) | Returns the length of string name. |
2) | Strcpy(destination, source) | Copies the contents of source string to destination string. |
3) | Strcat(first_string, second_string) | Concats or joins first string with second string. The result of the string is stored in first string. |
4) | Strcmp(first_string, second_string) | Compares the first string with second string. If both strings are same, it returns 0. |
5) | Strrev(string) | Returns reverse string. |
6) | Strlwr(string) | Returns string characters in lowercase. |
7) | Strupr(string) | Returns string characters in uppercase. |
C String Length: strlen() function
The strlen() function returns the length of the given string. It doesn't count null character '\0'.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char ch[20]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
- Printf("Length of string is: %d",strlen(ch));
- Return 0;
- }
Output:
Length of string is: 10
C Copy String: strcpy()
The strcpy(destination, source) function copies the source string in destination.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char ch[20]={'j', 'a', 'v', 'a', 't', 'p', 'o', 'i', 'n', 't', '\0'};
- Char ch2[20];
- Strcpy(ch2,ch);
- Printf("Value of second string is: %s",ch2);
- Return 0;
- }
Output:
Value of second string is: javatpoint
C String Concatenation: strcat()
The strcat(first_string, second_string) function concatenates two strings and result is
Returned to first_string.
#include<stdio.h>
#include <string.h>
Int main(){
Char ch[10]={'h', 'e', 'l', 'l', 'o', '\0'};
Char ch2[10]={'c', '\0'};
Strcat(ch,ch2);
Printf("Value of first string is: %s",ch);
Return 0;
}
Output:
Value of first string is: helloc
C Compare String: strcmp()
The strcmp(first_string, second_string) function compares two string and returns 0 if both strings are equal.
Here, we are using gets() function which reads string from the console.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char str1[20],str2[20];
- Printf("Enter 1st string: ");
- Gets(str1);//reads string from console
- Printf("Enter 2nd string: ");
- Gets(str2);
- If(strcmp(str1,str2)==0)
- Printf("Strings are equal");
- Else
- Printf("Strings are not equal");
- Return 0;
- }
Output:
Enter 1st string: hello
Enter 2nd string: hello
Strings are equal
C Reverse String: strrev()
The strrev(string) function returns reverse of the given string. Let's see a simple example of strrev() function.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char str[20];
- Printf("Enter string: ");
- Gets(str);//reads string from console
- Printf("String is: %s",str);
- Printf("\nReverse String is: %s",strrev(str));
- Return 0;
- }
Output:
Enter string: javatpoint
String is: javatpoint
Reverse String is: tnioptavaj
C String Lowercase: strlwr()
The strlwr(string) function returns string characters in lowercase. Let's see a simple example of strlwr() function.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char str[20];
- Printf("Enter string: ");
- Gets(str);//reads string from console
- Printf("String is: %s",str);
- Printf("\nLower String is: %s",strlwr(str));
- Return 0;
- }
Output:
Enter string: JAVATpoint
String is: JAVATpoint
Lower String is: javatpoint
C String Uppercase: strupr()
The strupr(string) function returns string characters in uppercase. Let's see a simple example of strupr() function.
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char str[20];
- Printf("Enter string: ");
- Gets(str);//reads string from console
- Printf("String is: %s",str);
- Printf("\nUpper String is: %s",strupr(str));
- Return 0;
- }
Output:
Enter string: javatpoint
String is: javatpoint
Upper String is: JAVATPOINT
C String strstr()
The strstr() function returns pointer to the first occurrence of the matched string in the given string. It is used to return substring from first match till the last character.
Syntax:
- Char *strstr(const char *string, const char *match)
String strstr() parameters
String: It represents the full string from where substring will be searched.
Match: It represents the substring to be searched in the full string.
String strstr() example
- #include<stdio.h>
- #include <string.h>
- Int main(){
- Char str[100]="this is javatpoint with c and java";
- Char *sub;
- Sub=strstr(str,"java");
- Printf("\nSubstring is: %s",sub);
- Return 0;
- }
Output:
Javatpoint with c and java
In C/C++, a string is a 1-D array of characters and an array of string in C is a 2D array of characters. This comes quite handy in C++. There are 3 ways in which an Array of Strings in C or C++ can be created.
- Using Pointers (Both C and C++): We actually create string literals by creating an array of pointers.
// C++ program to demonstrate array of strings using // 2D character array #include <bits/stdc++.h> Using namespace std;
Int main() { // Initialize array of pointer Const char *colour[4] = { "Blue", "Red", "Orange", "Yellow" };
// Printing Strings stored in 2D array For (int i = 0; i < 4; i++) Cout << colour[i] << "\n";
Return 0; } |
Output:
Blue
Red
Orange
Yellow
Drawbacks:
- Number of strings are fixed
- Strings are constants and contents cannot be changed.
- Using 2D array (Both C and C++): This method is useful for shuffling, comparing and accessing characters randomly.
Syntax:
Char “Name” [“Number of Strings”][“MaxSize of String”]
Example:
Char colour [4][10]
// Here 4 colours can be inserted
// with max String size of 10.
// C++ program to demonstrate array of strings using // 2D character array #include <bits/stdc++.h> Using namespace std;
Int main() { // Initialize 2D array Char colour[4][10] = { "Blue", "Red", "Orange", "Yellow" };
// Printing Strings stored in 2D array For (int i = 0; i < 4; i++) Cout << colour[i] << "\n";
Return 0; } |
Output:
Blue
Red
Orange
Yellow
Drawbacks:
- Both the number of Strings and Size of String are fixed.
- A 2D array is allocated, whose second dimension is equal to maximum sized string which causes wastage of space.
- Using string Keyword (Only in C++): In this method, size of the string is not fixed, hence space is saved.
Syntax:
String Name_ofString [number_of_string]
Example:
String geeks[50]
// C++ program to demonstrate array of strings using // array of strings. #include <bits/stdc++.h> Using namespace std;
Int main() { // Initialize String Array String colour[4] = { "Blue", "Red", "Orange", "Yellow" };
// Print Strings For (int i = 0; i < 4; i++) Cout << colour[i] << "\n"; } |
Output:
Blue
Red
Orange
Yellow
Drawback: The array is of fixed size.
4. Using Vectors (Only C++): STL Container Vector can be used to dynamically allocate array.
Syntax:
Vector “Name”
Example:
Vector Colour
// C++ program to demonstrate vector of strings using #include <bits/stdc++.h> Using namespace std;
Int main() { // Declaring Vector of String type Vector<string> colour;
// Initialize vector with strings using push_back // command Colour.push_back("Blue"); Colour.push_back("Red"); Colour.push_back("Orange"); Colour.push_back("Yellow");
// Print Strings stored in Vector For (int i = 0; i < colour.size(); i++) Cout << colour[i] << "\n"; } |
Output:
Blue
Red
Orange
Yellow
Structures:
A structure can be considered as a template used for defining a collection of variables under a single name. Structures help programmers to group elements of different data types into a single logical unit (Unlike arrays which permit a programmer to group only elements of same data type).
- Why Use Structures
• Ordinary variables can hold one piece of information
• arrays can hold a number of pieces of information of the same data type.
For example, suppose you want to store data about a book. You might want to store its name (a string), its price (a float) and number of pages in it (an int).
If data about say 3 such books is to be stored, then we can follow two approaches:
Construct individual arrays, one for storing names, another for storing prices and still another for storing number of pages.
Use a structure variable.
Suppose we want to create a employee database. Then, we can define a structure
Called employee with three elements id, name and salary. The syntax of this structure is as
Follows:
Struct employee
{ int id;
Char name[50];
Float salary;
};
Note:
Struct keyword is used to declare structure.
Members of structure are enclosed within opening and closing braces.
Usually structure type declaration appears at the top of the source code file, before any variables or functions are defined or maintained in separate header file.
Declaration of Structure reserves no space.
It is nothing but the “ Template / Map / Shape ” of the structure .
Memory is created , very first time when the variable is created / Instance is created.
- Structure variable declaration:
We can declare the variable of structure in two ways
- Declare the structure inside main function
- Declare the structure outside the main function.
1. Declare the structure inside main function
Following example show you, how structure variable is declared inside main function
Struct employee
{
Int id;
Char name[50];
Float salary;
};
Int main()
{
Struct employee e1, e2;
Return 0;
}
In this example the variable of structure employee is created inside main function that e1 ,e2.
2. Declare the structure outside main function
Following example show you, how structure variable is declared outside the main function
Struct employee
{
Int id;
Char name[50];
Float salary;
}e1,e2;
- Memory allocation for structure
Memory is allocated to the structure only when we create the variable of structure.
Consider following example
- Structure Initialization
1. When we declare a structure, memory is not allocated for un-initialized variable.
2. Let us discuss very familiar example of structure student , we can initialize structure variable
In different ways –
Way 1 : Declare and Initialize
Struct student
{
Char name[20];
Int roll;
Float marks;
}std1 = { "Poonam",89,78.3 };
In the above code snippet, we have seen that structure is declared and as soon as after declaration we
Have initialized the structure variable.
Std1 = { "Poonam",89,78.3 }
This is the code for initializing structure variable in C programming
Way 2 : Declaring and Initializing Multiple Variables
Struct student
{
Char name[20];
Int roll;
Float marks;
}
Std1 = {"Poonam" ,67, 78.3};
Std2 = {"Vishal",62, 71.3};
In this example, we have declared two structure variables in above code. After declaration of variable we have initialized two variable.
Std1 = {"Poonam" ,67, 78.3};
Std2 = {"Vishal",62, 71.3};
Way 3 : Initializing Single member
Struct student
{
Int mark1;
Int mark2;
Int mark3;
} sub1={67};
Though there are three members of structure, only one is initialized , Then remaining two members
Are initialized with Zero. If there are variables of other data type then their initial values will be –
Data Type Default value if not initialized
Integer 0
Float 0.00
Char NULL
Way 4 : Initializing inside main
Struct student
{
Int mark1;
Int mark2;
Int mark3;
};
Void main()
{
Struct student s1 = {89,54,65};
- - - - --
- - - - --
- - - - --
};
When we declare a structure then memory won’t be allocated for the structure. i.e only writing below
Declaration statement will never allocate memory
Struct student
{
Int mark1;
Int mark2;
Int mark3;
};
We need to initialize structure variable to allocate some memory to the structure.
Struct student s1 = {89,54,65};
- When we declare a structure, memory is not allocated for un-initialized variable.
- Let us discuss very familiar example of structure student , we can initialize structure variable in different ways –
Way 1 : Declare and Initialize
Struct student
{
Char name[20];
Int roll;
Float marks;
}std1 = { "Pritesh",67,78.3 };
In the above code snippet, we have seen that structure is declared and as soon as after declaration we have initialized the structure variable.
Std1 = { "Pritesh",67,78.3 }
This is the code for initializing structure variable in C programming
Way 2 : Declaring and Initializing Multiple Variables
Struct student
{
Char name[20];
Int roll;
Float marks;
}
Std1 = {"Pritesh",67,78.3};
Std2 = {"Don",62,71.3};
In this example, we have declared two structure variables in above code. After declaration of variable we have initialized two variable.
Std1 = {"Pritesh",67,78.3};
Std2 = {"Don",62,71.3};
Way 3 : Initializing Single member
Struct student
{
Int mark1;
Int mark2;
Int mark3;
} sub1={67};
Though there are three members of structure, only one is initialized , Then remaining two members are initialized with Zero. If there are variables of other data type then their initial values will be –
Data Type | Default value if not initialized |
Integer | 0 |
Float | 0.00 |
Char | NULL |
Way 4 : Initializing inside main
Struct student
{
Int mark1;
Int mark2;
Int mark3;
};
Void main()
{
Struct student s1 = {89,54,65};
- - - - --
- - - - --
- - - - --
};
When we declare a structure then memory won’t be allocated for the structure. i.e only writing below declaration statement will never allocate memory
Struct student
{
Int mark1;
Int mark2;
Int mark3;
};
We need to initialize structure variable to allocate some memory to the structure.
Struct student s1 = {89,54,65};
Unions are quite similar to the structures in C. Union is also a derived type as
Structure. Union can be defined in same manner as structures just the keyword
Used in defining union in union where keyword used in defining structure was struct.
Union car
{
Char name[50];
Int price;
};
Union variables can be created in similar manner as structure variable.
Union car
{
Char name[50];
Int price;
}c1, c2, *c3;
OR;
Union car
{
Char name[50];
Int price;
};
-------Inside Function-----------
Union car c1, c2, *c3;
In both cases, union variables c1, c2 and union pointer variable c3 of type union
Car is created.
- Memory allocation for union
Like structure memory is allocated to union only when we create the variable of it.
The memory is allocated to union according to the largest data members of the union.
- Accessing members of an union
Array elements are accessed using the Subscript variable, Similarly Union members are accessed using dot [.] operator.
(.) is called as “union member Operator”.
Use this Operator in between “Union variable” & “member name”
Union employee
{
Int id;
Char name[50];
Float salary;
} ;
Void main()
{
Union employee e1= { 1, “ABC”, 50000 };
Printf(“%d”, e. Id);
Printf(“%s”, e. Name);
}
O/P- garbage value, ABC
Structure is collection of different data type. An object of structure represents a single record in memory, if we want more than one record of structure type, we have to create an array of structure or object. As we know, an array is a collection of similar type, therefore an array can be of structure type.
Syntax for declaring structure array
Struct struct-name
{
Datatype var1;
Datatype var2;
- - - - - - - - - -
- - - - - - - - - -
Datatype varN;
};
Struct struct-name obj [ size ];
Example for declaring structure array
#include<stdio.h>
Struct Employee
{
Int Id;
Char Name[25];
Int Age;
Long Salary;
};
Void main()
{
Int i;
Struct Employee Emp[ 3 ]; //Statement 1
For(i=0;i<3;i++)
{
Printf("\nEnter details of %d Employee",i+1);
Printf("\n\tEnter Employee Id : ");
Scanf("%d",&Emp[i].Id);
Printf("\n\tEnter Employee Name : ");
Scanf("%s",&Emp[i].Name);
Printf("\n\tEnter Employee Age : ");
Scanf("%d",&Emp[i].Age);
Printf("\n\tEnter Employee Salary : ");
Scanf("%ld",&Emp[i].Salary);
}
Printf("\nDetails of Employees");
For(i=0;i<3;i++)
Printf("\n%d\t%s\t%d\t%ld",Emp[i].Id,Emp[i].Name,Emp[i].Age,Emp[i].Salary);
}
Output :
Enter details of 1 Employee
Enter Employee Id : 101
Enter Employee Name : Suresh
Enter Employee Age : 29
Enter Employee Salary : 45000
Enter details of 2 Employee
Enter Employee Id : 102
Enter Employee Name : Mukesh
Enter Employee Age : 31
Enter Employee Salary : 51000
Enter details of 3 Employee
Enter Employee Id : 103
Enter Employee Name : Ramesh
Enter Employee Age : 28
Enter Employee Salary : 47000
Details of Employees
101 Suresh 29 45000
102 Mukesh 31 51000
103 Ramesh 28 47000
In the above example, we are getting and displaying the data of 3 employee using
Array of object. Statement 1 is creating an array of Employee Emp to store the records
Of 3 employees.
Array within Structure
As we know, structure is collection of different data type. Like normal data type, It can
Also store an array as well.
Syntax for array within structure
Struct struct-name
{
Datatype var1; // normal variable
Datatype array [size]; // array variable
- - - - - - - - - -
- - - - - - - - - -
Datatype varN;
};
Struct struct-name obj;
Example for array within structure
Struct Student
{
Int Roll;
Char Name[25];
Int Marks[3]; //Statement 1 : array of marks
Int Total;
Float Avg;
};
Void main()
{
Int i;
Struct Student S;
Printf("\n\nEnter Student Roll : ");
Scanf("%d",&S.Roll);
Printf("\n\nEnter Student Name : ");
Scanf("%s",&S.Name);
S.Total = 0;
For(i=0;i<3;i++)
{
Printf("\n\nEnter Marks %d : ",i+1);
Scanf("%d",&S.Marks[i]);
S.Total = S.Total + S.Marks[i];
}
S.Avg = S.Total / 3;
Printf("\nRoll : %d",S.Roll);
Printf("\nName : %s",S.Name);
Printf("\nTotal : %d",S.Total);
Printf("\nAverage : %f",S.Avg);
}
Output :
Enter Student Roll : 10
Enter Student Name : Kumar
Enter Marks 1 : 78
Enter Marks 2 : 89
Enter Marks 3 : 56
Roll : 10
Name : Kumar
Total : 223
Average : 74.00000
In the above example, we have created an array Marks[ ] inside structure representing
3 marks of a single student. Marks[ ] is now a member of structure student and to
Access Marks[ ] we have used dot operator(.) along with object S.
Pointers:
Pointers in C language is a variable that stores/points the address of another variable. A Pointer in C is used to allocate memory dynamically i.e. at run time. The pointer variable might be belonging to any of the data type such as int, float, char, double, short etc.
Pointer Syntax : data_type *var_name; Example : int *p; char *p;
Where, * is used to denote that “p” is pointer variable and not a normal variable.
Normal variable stores the value whereas pointer variable stores the address of the variable.
The content of the C pointer always be a whole number i.e. address.
Always C pointer is initialized to null, i.e. int *p = null.
The value of null pointer is 0.
& symbol is used to get the address of the variable.
* symbol is used to get the value of the variable that the pointer is pointing to.
If a pointer in C is assigned to NULL, it means it is pointing to nothing.
Two pointers can be subtracted to know how many elements are available between these two pointers.
But, Pointer addition, multiplication, division are not allowed.
The size of any pointer is 2 byte (for 16 bit compiler).
Example:
#include <stdio.h>
Int main()
{
Int *ptr, q;
q = 50;
/* address of q is assigned to ptr */
Ptr = &q;
/* display q's value using ptr variable */
Printf("%d", *ptr);
Return 0;
}
1
2
3
4
5
6
7
8
9
10
11
Pointers are declare with the help of operator ‘*’. ‘*’ is known as ‘value at address’. Pointers are the variables which are used to store the address of another variable As the address of variable is always whole numbers so pointer always contains whole numbers. The declaration of pointer are as follows.
Syntax : Data type * pointer Name.
Example: int *I;
Data type defines the type of value defined at the address of pointer variable. In the above example value at the address of ‘I’ is of type integer.
Consider the following program.
# include<stdio.h>
# include<conio.h>
Void main()
{
Int a,b,c;
Int *p,*q,*r;
p=&a;
q=&b;
r=&c;
Printf(“Enter two numbers”);
Scanf(“%d%d,&a,&b);
c=a + b;
Printf(“\n Address of variable C is %d”,&C);
Printf(“\n Address of variable C is %d,r);
Printf(“\n Address of variable r is %d”,&r);
Printf(“\n value of variable C is %d”,C);
Printf(“\n value of variable C is %d,*^);
Getch ();
}
In the above program variable ‘r’ is the integer pointer which holds the address of variable ‘C’
Case 1: In ‘printf’ statement whenever we used (“%d”,r) men me value of r is printed but ‘r’ is holding the address of variable ‘C’. So, address of variable C is copied to the value of ‘r’ and it is printed on output screen
Case 2: Whenever we used (“%d”,&r) in ‘printf’ function men the address of variable ‘r’ is pointed on o/p screen.
Case 3: When we used (“%d”,*r) in pointf function at mat time value which is stored at the address which holds by variable ‘r’ is printed.
Now me variable ‘r’ is holding the address of variable ‘C’. So, the value which is stored at the address of ‘C’ is printed on the output screen.
Consider the following example.
#include<stdio.h>
#include<conio.h>
Void main()
{
Int a=3;
Int *p;
p=&a;
Printf(“\n%d”,a);
Printf(“\n%d”,&a);
Printf(“\n%d”,P);
Printf(“\n%d”,&P);
Printf(“\n%d”,*P);
Printf(“\n%d”,*(&a));
}
Run the above program on the computer system so that you will familiar with the basic use of pointers. Following is the explanation O/p of above program.
- The first ‘printf’ statement prints the value of ‘C’ ie. 3
- The second ‘printf’ statement prints the address of ‘a’
- The third ‘printf’ statement prints me value of ‘p’ ie. The address of ‘a’
- The forth ‘printf’ statement prints the address of ‘p’
- The fifth ‘printf’ statement prints the value which is stored at the address holds in ‘p’ ie. 3
- The sixth ‘printf’ statement prints the value which is stored at the address of ‘a’ ie. 3
Data type of pointer variable can be anything. Such as char *C;
In the above instruction pointer ‘C’ is of type character so the variable ‘C’ can store the address of variable which contains character type of value. Consider the following program.
#include<stdio.h>
#include<conio.h>
Void main()
{
Int I,*ip;
Char C, *cp;
I = 3;
Ip = & I;
c=’M’;
Cp=&c;
Printf(“%d”,I);
Printf(“\n%d”,*ip);
Printf(“\n%C;,C);
Printf(“\n%c”, *cp);
Getch();
}
The output of above program is.
3
3
m
m
Pointer to an Array
It is most likely that you would not understand this section until you are through with the chapter 'Pointers'.
Assuming you have some understanding of pointers in C, let us start: An array name is a constant pointer to the first element of the array. Therefore, in the declaration −
Double balance[50];
Balance is a pointer to &balance[0], which is the address of the first element of the array balance. Thus, the following program fragment assigns p as the address of the first element of balance −
Double *p;
Double balance[10];
p = balance;
It is legal to use array names as constant pointers, and vice versa. Therefore, *(balance + 4) is a legitimate way of accessing the data at balance[4].
Once you store the address of the first element in 'p', you can access the array elements using *p, *(p+1), *(p+2) and so on. Given below is the example to show all the concepts discussed above −
#include <stdio.h>
Int main () {
/* an array with 5 elements */
Double balance[5] = {1000.0, 2.0, 3.4, 17.0, 50.0};
Double *p;
Int i;
p = balance;
/* output each array element's value */
Printf( "Array values using pointer\n");
For ( i = 0; i < 5; i++ ) {
Printf("*(p + %d) : %f\n", i, *(p + i) );
}
Printf( "Array values using balance as address\n");
For ( i = 0; i < 5; i++ ) {
Printf("*(balance + %d) : %f\n", i, *(balance + i) );
}
Return 0;
}
When the above code is compiled and executed, it produces the following result −
Array values using pointer
*(p + 0) : 1000.000000
*(p + 1) : 2.000000
*(p + 2) : 3.400000
*(p + 3) : 17.000000
*(p + 4) : 50.000000
Array values using balance as address
*(balance + 0) : 1000.000000
*(balance + 1) : 2.000000
*(balance + 2) : 3.400000
*(balance + 3) : 17.000000
*(balance + 4) : 50.000000
In the above example, p is a pointer to double, which means it can store the address of a variable of double type. Once we have the address in p, *p will give us the value available at the address stored in p, as we have shown in the above example.
Pointers to Structures
You can define pointers to structures in the same way as you define pointer to any other variable −
Struct Books *struct_pointer;
Now, you can store the address of a structure variable in the above defined pointer variable. To find the address of a structure variable, place the '&'; operator before the structure's name as follows −
Struct_pointer = &Book1;
To access the members of a structure using a pointer to that structure, you must use the → operator as follows −
Struct_pointer->title;
Let us re-write the above example using structure pointer.
#include <stdio.h>
#include <string.h>
Struct Books {
Char title[50];
Char author[50];
Char subject[100];
Int book_id;
};
/* function declaration */
Void printBook( struct Books *book );
Int main( ) {
Struct Books Book1; /* Declare Book1 of type Book */
Struct Books Book2; /* Declare Book2 of type Book */
/* book 1 specification */
Strcpy( Book1.title, "C Programming");
Strcpy( Book1.author, "Nuha Ali");
Strcpy( Book1.subject, "C Programming Tutorial");
Book1.book_id = 6495407;
/* book 2 specification */
Strcpy( Book2.title, "Telecom Billing");
Strcpy( Book2.author, "Zara Ali");
Strcpy( Book2.subject, "Telecom Billing Tutorial");
Book2.book_id = 6495700;
/* print Book1 info by passing address of Book1 */
PrintBook( &Book1 );
/* print Book2 info by passing address of Book2 */
PrintBook( &Book2 );
Return 0;
}
Void printBook( struct Books *book ) {
Printf( "Book title : %s\n", book->title);
Printf( "Book author : %s\n", book->author);
Printf( "Book subject : %s\n", book->subject);
Printf( "Book book_id : %d\n", book->book_id);
}
When the above code is compiled and executed, it produces the following result −
Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700
Bit Fields
Bit Fields allow the packing of data in a structure. This is especially useful when memory or data storage is at a premium. Typical examples include −
- Packing several objects into a machine word. e.g. 1 bit flags can be compacted.
- Reading external file formats -- non-standard file formats could be read in, e.g., 9-bit integers.
C allows us to do this in a structure definition by putting: bit length after the variable. For example −
Struct packed_struct {
Unsigned int f1:1;
Unsigned int f2:1;
Unsigned int f3:1;
Unsigned int f4:1;
Unsigned int type:4;
Unsigned int my_int:9;
} pack;
Here, the packed_struct contains 6 members: Four 1 bit flags f1..f3, a 4-bit type and a 9-bit my_int.
C automatically packs the above bit fields as compactly as possible, provided that the maximum length of the field is less than or equal to the integer word length of the computer. If this is not the case, then some compilers may allow memory overlap for the fields while others would store the next field in the next word.
Self -Referential structures are those structures that have one or more pointers which point to the same type of structure, as their member.
The structures pointing to the same type of structures are self-referential in nature.
Struct node {
Int data1;
Char data2;
Struct node* link;
};
Int main()
{
Struct node ob;
Return 0;
}
In the above example ‘link’ is a pointer to a structure of type ‘node’. Hence, the structure ‘node’ is a self-referential structure with ‘link’ as the referencing pointer.
An important point to consider is that the pointer should be initialized properly before accessing, as by default it contains garbage value.
Linked List is a collection of multiple nodes. Each node is connected to other node via link or pointer. Every node consists of two fields.
- Data
- Pointer to next node.
Data |
Address of next node |
Fig.1 Structure of a node
Data Field is used to store information and Address Field stores the memory address of next node.
Fig.2 Structure of a Linked List
This Linked List consists of three nodes. First node is called as Head node. Assume that first node is stored at memory location 1000.First node stores value 2 in data field. Second node starts at memory address 2000 and hence 2000 is stored at address field of First node. Third node is located at memory location 3000 and hence 3000 is stored at address field of Second node. Same concept is used for all nodes in Linked List. Address field of last node contains NULL as last node does not point to any other node.
Types of Linked List:
- Singly Linked List
- Doubly Linked List
- Circular Linked List
We will discuss these types in more detail.
Singly Linked List
Each node in singly linked list points to next node and it appears to move in one direction. Thus SLL is unidirectional. Fig.4 shows schematic diagram of singly linked list with 4 nodes.
DOUBLY LINKED LIST:
Singly or Circular Linked List can be traversed only in forward direction since node contains only one pointer field. Node in doubly linked list contains one data field and two pointer fields.
Left link | Data | Right Link |
Fig.5 Structure of a node in DLL
Left Link points to predecessor node and right link points to successor node. Information is stored in data field. Left link of First node and Right link of last node points to NULL. These two links enable bi-directional traversing, i.e. traversing the list in backward and forward direction. Hence called as bidirectional or doubly linked list.
CIRCULAR LINKED LIST:
A circular linked list is a linked list in which last node points to first node i.e next pointer of last node points to first node. Circular linked list does not contain NULL pointers.
Here A is the first node and C is the last node. C points to A and hence C stores address of A.
The enum in C is also known as the enumerated type. It is a user-defined data type that consists of integer values, and it provides meaningful names to these values. The use of enum in C makes the program easy to understand and maintain. The enum is defined by using the enum keyword.
The following is the way to define the enum in C:
- Enum flag{integer_const1, integer_const2,.....integter_constN};
In the above declaration, we define the enum named as flag containing 'N' integer constants. The default value of integer_const1 is 0, integer_const2 is 1, and so on. We can also change the default value of the integer constants at the time of the declaration.
For example:
- Enum fruits{mango, apple, strawberry, papaya};
The default value of mango is 0, apple is 1, strawberry is 2, and papaya is 3. If we want to change these default values, then we can do as given below:
- Enum fruits{
- Mango=2,
- Apple=1,
- Strawberry=5,
- Papaya=7,
- };
Enumerated type declaration
As we know that in C language, we need to declare the variable of a pre-defined type such as int, float, char, etc. Similarly, we can declare the variable of a user-defined data type, such as enum. Let's see how we can declare the variable of an enum type.
Suppose we create the enum of type status as shown below:
- Enum status{false,true};
Now, we create the variable of status type:
- Enum status s; // creating a variable of the status type.
In the above statement, we have declared the 's' variable of type status.
To create a variable, the above two statements can be written as:
- Enum status{false,true} s;
In this case, the default value of false will be equal to 0, and the value of true will be equal to 1.
Let's create a simple program of enum.
- #include <stdio.h>
- Enum weekdays{Sunday=1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
- Int main()
- {
- Enum weekdays w; // variable declaration of weekdays type
- w=Monday; // assigning value of Monday to w.
- Printf("The value of w is %d",w);
- Return 0;
- }
In the above code, we create an enum type named as weekdays, and it contains the name of all the seven days. We have assigned 1 value to the Sunday, and all other names will be given a value as the previous value plus one.
Output
Let's demonstrate another example to understand the enum more clearly.
- #include <stdio.h>
- Enum months{jan=1, feb, march, april, may, june, july, august, september, october, november, december};
- Int main()
- {
- // printing the values of months
- For(int i=jan;i<=december;i++)
- {
- Printf("%d, ",i);
- }
- Return 0;
- }
In the above code, we have created a type of enum named as months which consists of all the names of months. We have assigned a '1' value, and all the other months will be given a value as the previous one plus one. Inside the main() method, we have defined a for loop in which we initialize the 'i' variable by jan, and this loop will iterate till December.
Output
Why do we use enum?
The enum is used when we want our variable to have only a set of values. For example, we create a direction variable. As we know that four directions exist (North, South, East, West), so this direction variable will have four possible values. But the variable can hold only one value at a time. If we try to provide some different value to this variable, then it will throw the compilation error.
The enum is also used in a switch case statement in which we pass the enum variable in a switch parenthesis. It ensures that the value of the case block should be defined in an enum.
Let's see how we can use an enum in a switch case statement.
- #include <stdio.h>
- Enum days{sunday=1, monday, tuesday, wednesday, thursday, friday, saturday};
- Int main()
- {
- Enum days d;
- d=monday;
- Switch(d)
- {
- Case sunday:
- Printf("Today is sunday");
- Break;
- Case monday:
- Printf("Today is monday");
- Break;
- Case tuesday:
- Printf("Today is tuesday");
- Break;
- Case wednesday:
- Printf("Today is wednesday");
- Break;
- Case thursday:
- Printf("Today is thursday");
- Break;
- Case friday:
- Printf("Today is friday");
- Break;
- Case saturday:
- Printf("Today is saturday");
- Break;
- }
- Return 0;
- }
Output
Some important points related to enum
- The enum names available in an enum type can have the same value. Let's look at the example.
- #include <stdio.h>
- Int main(void) {
- Enum fruits{mango = 1, strawberry=0, apple=1};
- Printf("The value of mango is %d", mango);
- Printf("\nThe value of apple is %d", apple);
- Return 0;
- }
Output
- If we do not provide any value to the enum names, then the compiler will automatically assign the default values to the enum names starting from 0.
- We can also provide the values to the enum name in any order, and the unassigned names will get the default value as the previous one plus one.
- The values assigned to the enum names must be integral constant, i.e., it should not be of other types such string, float, etc.
- All the enum names must be unique in their scope, i.e., if we define two enum having same scope, then these two enums should have different enum names otherwise compiler will throw an error.
Let's understand this scenario through an example.
- #include <stdio.h>
- Enum status{success, fail};
- Enum boolen{fail,pass};
- Int main(void) {
- Printf("The value of success is %d", success);
- Return 0;
- }
Output
- In enumeration, we can define an enumerated data type without the name also.
- #include <stdio.h>
- Enum {success, fail} status;
- Int main(void) {
- Status=success;
- Printf("The value of status is %d", status);
- Return 0;
- }
Output
Enum vs. Macro in C
- Macro can also be used to define the name constants, but in case of an enum, all the name constants can be grouped together in a single statement.
For example,
# define pass 0;
# define success 1;
The above two statements can be written in a single statement by using the enum type.
enum status{pass, success};
- The enum type follows the scope rules while macro does not follow the scope rules.
- In Enum, if we do not assign the values to the enum names, then the compiler will automatically assign the default value to the enum names. But, in the case of macro, the values need to be explicitly assigned.
- The type of enum in C is an integer, but the type of macro can be of any type.