PROGRAMMING
FOR
PROBLEM SOLVING
UNIT-5 +Remaining
Rajesh Tripathi
Pointer
What is Pointer in C?
The Pointer in C, is a variable that stores address of another variable. A pointer can also be used to refer to
another pointer function. A pointer can be incremented/decremented, i.e., to point to the next/ previous
memory location. The purpose of pointer is to save memory space and achieve faster execution time.
type *var-name;
Here, type is the pointer's base type; it must be a valid C data type and var-name is the name of the pointer
variable. The asterisk * used to declare a pointer is the same asterisk used for multiplication. However, in this
statement the asterisk is being used to designate a variable as a pointer. Take a look at some of the valid
pointer declarations −
int *ip; /* pointer to an integer */
double *dp; /* pointer to a double */
float *fp; /* pointer to a float */
char *ch /* pointer to a character */
C Pointers
Pointers (pointer variables) are special variables that are used to store addresses rather than values.
Pointer Syntax
Here is how we can declare pointers.
int* p;
Here, we have declared a pointer p of int type.
You can also declare pointers in these ways.
int *p1;
int * p2;
Let's take another example of declaring pointers.
int* p1, p2;
Here, we have declared a pointer p1 and a normal variable p2.
Assigning addresses to Pointers
Let's take an example.
int* pc, c;
2
c = 5;
pc = &c;
Here, 5 is assigned to the c variable. And, the address of c is assigned to the pc pointer.
Get Value of Thing Pointed by Pointers
To get the value of the thing pointed by the pointers, we use the * operator. For example:
int* pc, c;
c = 5;
pc = &c;
printf("%d", *pc); // Output: 5
Here, the address of c is assigned to the pc pointer. To get the value stored in that address, we used *pc.
What Are the Different Types of Pointers?
There are majorly four types of pointers, they are:
Null Pointer
Void Pointer
Wild Pointer
Dangling Pointer
There are the following types of pointers:
Null Pointer
A null pointer is a type of pointer created by assigning a null value to the pointer. A null pointer can be of
any data type. It has a value of 0 in it. The operating system reserves memory at address 0; most operating
systems do not allow programs to access memory at that address. The memory address 0 has unique
importance.
It indicates that the pointer is not intended to point to an accessible memory location. Dereferencing null
pointer results in undefined behavior, i.e., if you try to access as *ptr (where ptr is a NULL pointer), it will
result in a null pointer exception.
Illustration of Null pointer using following code:
#include <stdio.h>
int main()
{
int *ptr = NULL; //null pointer
printf(“The value inside variable ptr is: %x”,ptr);
return 0;
3
}
Output
The value inside variable ptr is: 0
Void Pointer
The void pointer is a generic pointer that isn't associated with any data type. A void pointer can be typecasted
to any type, so it is instrumental in assigning the different types of variables to the void pointer.
Illustration of void pointer using following code:
#include<stdio.h>
int main()
{
void *ptr=NULL; //void pointer
int x = 5;
ptr = &x;
//typecasted to int using (int *)
printf("value of *ptr is %d ", *(int *)ptr);
return 0;
}
Output
value of *ptr is 5
Wild pointer
If a pointer isn't initialized to anything, it's called a wild pointer. Dereferencing a wild pointer has undefined
behavior that may crash the program or give a garbage value.
Illustration of wild pointer using following code:
#include <stdio.h>
int main()
{
int *ptr; //wild pointer
printf("value of *ptr is %d ",*ptr);
return 0;
4
}
Output
Runtime Error
The program will result in a segmentation fault(SIGSEGV) if the garbage pointer is not a valid address.
Dangling Pointer
A dangling pointer is a pointer that refers to a memory location that has been released or deleted.
Illustration of dangling pointer using following code:
#include <stdlib.h>
#include <stdio.h>
int main()
{
//memory allocated to ptr
int *ptr = (int *) malloc(sizeof(int));
// memory released
free(ptr);
// ptr is pointing to a deleted memory location now.
// now ptr became dangling pointer
printf("value of *ptr is %d ",*ptr);
// Removing dangling pointer
ptr = NULL;
}
Output
value of *ptr is 0
Complex Pointer
A Complex pointers contains of [] , * ,(), data type, identifier. These operators have different associativity
and precedence. () & [] have the highest precedence & associativity from left to right followed by *
& Identifier having precedence 2 & associativity from right to left and Data Type having the least priority.
char (* ptr)[4]
Here, ptr is a pointer to a one-dimensional character array of size four.
5
Other Pointers
The following are some other pointers used in old 16 bit Intel architecture:
Near pointer
A near pointer works with data segments of memory that are in 64Kb of range. It can't access addresses
outside of that data segment. We can make any pointer a near pointer by using the keyword 'near'.
Illustration of Near pointer using following code:
#include<stdio.h>
int main()
{
int x=42;
int near* ptr = &x;
int sz = sizeof(ptr);
printf("size of ptr is %d byte",sz);
return 0;
}
Output
size of ptr is 2 byte
Far pointer
A far pointer has the size of 4 bytes (32 bit), and it can visit memory beyond the current segment. The
compiler allocates a segment register for segment address and another register for offset within the current
segment.
Illustration of far pointer using following code:
#include<stdio.h>
int main()
{
int x=42;
int far* ptr = &x;
int sz = sizeof(ptr);
printf("size of ptr is %d byte",sz);
return 0;
}
6
Output
size of ptr is 4 byte
Huge Pointer
A huge pointer is similar to a far pointer, the size of a huge pointer is also 4 bytes (32 bit), and it can also
visit memory beyond the current segment.
The main difference between huge and far pointer is of modification of segment. In the far pointer, the
segment part cannot be modified. But in the Huge pointer, the segment part can be changed.
Benefits of Using Pointers in C
Pointers are helpful for memory location access.
Pointers can be used for dynamic space allocation(malloc, etc.), and space can be deallocated also.
The data structures such as graphs, linked lists, trees, etc., can be created using pointers.
Pointers allow references to function and thereby help in the passing of function as arguments to
other functions.
Dynamic memory allocation in C
The concept of dynamic memory allocation in c language enables the C programmer to allocate memory
at runtime. Dynamic memory allocation in c language is possible by 4 functions of stdlib.h header file.
1. malloc()
2. calloc()
3. realloc()
4. free()
Before learning above functions, let's understand the difference between static memory allocation and
dynamic memory allocation.
static memory allocation dynamic memory allocation
memory is allocated at compile time. memory is allocated at run time.
memory can't be increased while executing memory can be increased while executing
program. program.
used in array. used in linked list.
Now let's have a quick look at the methods used for dynamic memory allocation.
malloc() allocates single block of requested memory.
7
calloc() allocates multiple block of requested memory.
realloc() reallocates the memory occupied by malloc() or calloc() functions.
free() frees the dynamically allocated memory.
malloc() function in C
The malloc() function allocates single block of requested memory.
It doesn't initialize memory at execution time, so it has garbage value initially.
It returns NULL if memory is not sufficient.
The syntax of malloc() function is given below:
1. ptr=(cast-type*)malloc(byte-size)
example of malloc() function
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
8
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
calloc() function in C
The calloc() function allocates multiple block of requested memory.
It initially initialize all bytes to zero.
It returns NULL if memory is not sufficient.
The syntax of calloc() function is given below:
1. ptr=(cast-type*)calloc(number, byte-size)
Example of calloc() function
#include<stdio.h>
#include<stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)calloc(n,sizeof(int)); //memory allocated using calloc
if(ptr==NULL)
{
printf("Sorry! unable to allocate memory");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
9
free(ptr);
return 0;
}
Output
Enter elements of array: 3
Enter elements of array: 10
10
10
Sum=30
realloc() function in C
If memory is not sufficient for malloc() or calloc(), you can reallocate the memory by realloc() function. In
short, it changes the memory size.
syntax of realloc() function
1. ptr=realloc(ptr, new-size)
free() function in C
The memory occupied by malloc() or calloc() functions must be released by calling free() function.
Otherwise, it will consume memory until program exit.
syntax of free() function
free(ptr)
10
String in C
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++ −
Difference between char array and string literal
There are two main differences between char array and literal.
o 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.
o 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(){
11
char ch[11]={'C', '', 'p', 'r', 'o', 'g', 'r', 'a', 'm', 'm', 'i', '
n', 'g','\0'};
char ch2[11]="C programming";
printf("Char Array Value is: %s\n", ch);
printf("String Literal Value is: %s\n", ch2);
return 0;
}
Output
Char Array Value is: C programming
String Literal Value is: C programming
C – String functions
String
functions Description
strcat( ) Concatenates str2 at the end of str1
strncat( ) Appends a portion of string to another
strcpy( ) Copies str2 into str1
strncpy( ) Copies given number of characters of one string to another
strlen( ) Gives the length of str1
Returns 0 if str1 is same as str2. Returns <0 if strl<
strcmp( ) str2. Returns >0 if str1 > str2
Same as strcmp() function. But, this function negotiates
strcmpi ( ) case. “A” and “a” are treated as same.
strchr( ) Returns pointer to first occurrence of char in str1
strrchr( ) last occurrence of given character in a string is found
strstr( ) Returns pointer to first occurrence of str2 in str1
12
strrstr( ) Returns pointer to last occurrence of str2 in str1
strdup( ) Duplicates the string
strlwr( ) Converts string to lowercase
strupr( ) Converts string to uppercase
strrev( ) Reverses the given string
strset( ) Sets all character in a string to given character
strnset( ) It sets the portion of characters in a string to given character
strtok( ) Tokenizing given string using delimiter
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
strcpy()
The strcpy(destination, source) function copies the source string in destination.
#include<stdio.h>
#include <string.h>
int main(){
char ch[20]={'i', 'n', 'd', 'i', 'a', 'n', '\0'};
13
char ch2[20];
strcpy(ch2,ch);
printf("Value of second string is: %s",ch2);
return 0;
}
Output:
Value of second string is: indian
Strlen():It will return an unsigned int which is the length of a given string.
strlen( ) function counts the number of characters in a given string and returns the integer value.
It stops counting the character when null character is found. Because, null character indicates the end of the
string in C.
#include <stdio.h>
#include <string.h>
int main()
{
char a[20]="Program";
char b[20]={'P','r','o','g','r','a','m','\0'};
// using the %zu format specifier to print size_t
printf("Length of string a = %zu \n",strlen(a));
printf("Length of string b = %zu \n",strlen(b));
return 0;
}
STRLWR() Function – The STRLWR() Function used to converts given string to lowercase.
EXAMPLE:
#include<stdio.h>
#include<string.h>
intmain()
{
charstr[100];
printf("Please, Enter the String = ");
gets(str);
14
printf(" \n The Lower case String is = %s",strlwr(str));
return0;
OUTPUT
Please, Enter the String =SHAMBHUNATH
The Lower case String is =shambhunath
strupr( ) function :
strupr( ) function converts a given string into uppercase. Syntax for strupr( ) function is given below.strupr(
) function is non standard function which may not available in standard library in C.
Example:
#include<stdio.h>
#include<string.h>
int main()
{
char str[ ] = "Modify This String To Upper";
printf("%s\n",strupr(str));
return 0;
}
Output
Modify This String To Upper
MODIFY THIS STRING TO UPPER
15
File Handling in C
File handling refers to the method of storing data in the C program in the form of an output or input that might have been
generated while running a C program in a data file, i.e., a binary file or a text file for future analysis and reference in that
very program.
Why Do We Need File Handling in C?
There are times when the output generated out of a program after its compilation and running do not serve our intended
purpose. In such cases, we might want to check the program’s output various times. Now, compiling and running the very
same program multiple times becomes a tedious task for any programmer. It is exactly where file handling becomes useful.
Reusability: File handling allows us to preserve the information/data generated after we run the program.
Saves Time: Some programs might require a large amount of input from their users. In such cases, file handling
allows you to easily access a part of a code using individual commands.
Commendable storage capacity: When storing data in files, you can leave behind the worry of storing all the info
in bulk in any program.
Portability: The contents available in any file can be transferred to another one without any data loss in the
computer system. This saves a lot of effort and minimizes the risk of flawed coding.
File represents a sequence of bytes on the disk where a group of related data is stored. File is created for
permanent storage of data. It is a ready made structure.
In C language, we use a structure pointer of file type to declare a file.
FILE *fp;
C provides a number of functions that helps to perform basic file operations. Following are the functions,
Function Description
fopen() create a new file or open a existing file
fclose() closes a file
getc() reads a character from a file
putc() writes a character to a file
fscanf() reads a set of data from a file
fprintf() writes a set of data to a file
getw() reads a integer from a file
putw() writes a integer to a file
fseek() set the position to desire point
ftell() gives current position in the file
rewind() set the position to the beginning point
Opening a File or Creating a File
The fopen() function is used to create a new file or to open an existing file.
General Syntax:
*fp = FILE *fopen(const char *filename, const char *mode);
Here, *fp is the FILE pointer (FILE *fp), which will hold the reference to the opened(or created) file.
16
filename is the name of the file to be opened and mode specifies the purpose of opening the file. Mode can
be of following types,
mode description
r opens a text file in reading mode
w opens or create a text file in writing mode.
a opens a text file in append mode
r+ opens a text file in both reading and writing mode
w+ opens a text file in both reading and writing mode
a+ opens a text file in both reading and writing mode
rb opens a binary file in reading mode
wb opens or create a binary file in writing mode
ab opens a binary file in append mode
rb+ opens a binary file in both reading and writing mode
wb+ opens a binary file in both reading and writing mode
Closing a File
The fclose() function is used to close an already opened file.
General Syntax :
int fclose( FILE *fp);
Here fclose() function closes the file and returns zero on success, or EOF if there is an error in closing the
file. This EOF is a constant defined in the header file stdio.h.
Input/Output operation on File
In the above table we have discussed about various file I/O functions to perform reading and writing on
file. getc() and putc() are the simplest functions which can be used to read and write individual characters to
a file.
#include<stdio.h>
int main()
{
FILE *fp;
char ch;
fp = fopen("one.txt", "w");
printf("Enter data...");
while( (ch = getchar()) != EOF) {
putc(ch, fp);
}
17
fclose(fp);
fp = fopen("one.txt", "r");
while( (ch = getc(fp)! = EOF)
printf("%c",ch);
// closing the file pointer
fclose(fp);
return 0;
}
Reading and Writing to File using fprintf() and fscanf()
#include<stdio.h>
struct emp
{
char name[10];
int age;
};
void main()
{
struct emp e;
FILE *p,*q;
p = fopen("one.txt", "a");
q = fopen("one.txt", "r");
printf("Enter Name and Age:");
scanf("%s %d", e.name, &e.age);
fprintf(p,"%s %d", e.name, e.age);
fclose(p);
do
18
{
fscanf(q,"%s %d", e.name, e.age);
printf("%s %d", e.name, e.age);
}
while(!feof(q));
}
In this program, we have created two FILE pointers and both are referring to the same file but in different
modes.
fprintf() function directly writes into the file, while fscanf() reads from the file, which can then be printed on
the console using standard printf() function.
Difference between Append and Write Mode
Write (w) mode and Append (a) mode, while opening a file are almost the same. Both are used to write in a
file. In both the modes, new file is created if it doesn't exists already.
The only difference they have is, when you open a file in the write mode, the file is reset, resulting in
deletion of any data already present in the file. While in append mode this will not happen. Append mode is
used to append or add data to the existing data of file(if any). Hence, when you open a file in Append(a)
mode, the cursor is positioned at the end of the present data in the file.
Reading and Writing in a Binary File
A Binary file is similar to a text file, but it contains only large numerical data. The Opening modes are
mentioned in the table for opening modes above.
fread() and fwrite() functions are used to read and write is a binary file.
fwrite(data-element-to-be-written, size_of_elements, number_of_elements,
pointer-to-file);
fread() is also used in the same way, with the same arguments like fwrite() function. Below mentioned is a
simple example of writing into a binary file
const char *mytext = "The quick brown fox jumps over the lazy dog";
FILE *bfp= fopen("test.txt", "wb");
if (bfp)
{
fwrite(mytext, sizeof(char), strlen(mytext), bfp);
fclose(bfp);
}
fseek(), ftell() and rewind() functions
19
fseek(): It is used to move the reading control to different positions using fseek function.
ftell(): It tells the byte location of current position of cursor in file pointer.
rewind(): It moves the control to beginning of the file.
20
C preprocessor and Macros
In this chapter, you will be introduced to c preprocessors, and you will learn to use #include, #define and
conditional compilation with the help of examples.
C Source Code Preprocessor Compiler
Working of C Preprocessor
The C preprocessor is a macro preprocessor (allows you to define macros) that transforms your program
before it is compiled. These transformations can be the inclusion of header files, macro expansions, etc.
All preprocessing directives begin with a # symbol. For example,
#define PI 3.14
Introduction to Macros in C
In C programming language, when the C program is compiled then the program is sent to the compiler which
converts the C program into machine language and then the compilation is done and executes the C program.
The C preprocessor is also known as a macro preprocessor. The macro in C can be defined as a set of
program statements is given a name and this name is used whenever these set of code has to be used. These
macros always start with symbol “#” and the statements staring with this symbol are invoked by the
compiler. There are two types of macros: object- like macro when data objects are used and function-like
macro when function calls are used.
Macros in C
A macro in C programming language is a block or set of statements of program code that can be replaced by
macro #define directive. As discussed above there are two types of macros. They are:
1. Object-Like Macro
This macro can be a pointer variable or identifier or variable defined using #define and it is replaced by its
value. This is mainly used when numeric constants are required.
Example:
#define MAX 100
In this example, we can use “MAX” as a macro name with value 100 which will be replaced with “MAX”.
2. Function-Like Macro
This macro is similar to a function call in C programming language. In this, a function name is defined with
arguments passed to the function.
Example:
21
#define ADD (p, q) (p) + (q)
In the above example, we can function named “ADD” is defined to perform the addition of two numbers “p”
and “q”.
Before using macro in C programming, we should note the following points:
In C language, when we use “define” for defining a macro with “#” prefixed is used for defining constants
for the entire program, so when we define a constant with some macro name then in the entire program the
defined constant is matched and is replaced with the value that is assigned at the starting of declaring the
macro with “#define” statement.
Example:
#include<stdio.h>
#define PI 3.14
intmain()
{
printf("The value of Pi is %f", PI);
return 0;
}
Output:
3.14
Similarly, “#include” is used to include the header files in the C program. For example, we saw in the above
code “#include<stdio.h>” in this “stdio.h” is a header file we use this header file because to read and print the
values we use “printf” and “scanf” are within this “stdio.h” header file.
You should note that when the argument passed to the function-like macro where it supports any datatype.
Let us consider an example below:
Example:
#include <stdio.h>
#define INCREMENT(n) ++n
int main()
{
char *p = "shambhunath";
int a = 20;
printf(" This use char datatype %s ", INCREMENT(p));
printf("\n This uses int datatype %d", INCREMENT(a));
return 0;
}
Output:
This use char datatype shambhunath
This use int datatype 21
The macro can also be written in multiple lines starting the statements with “\” and no need to end with “\”.
Let us see an example of this:
Example:
22
#include <stdio.h>
#define MACRO(n, limit) while (n < limit) \
{ \
printf("Shambhunath”);
n++; \
}
intmain()
{
int n = 0;
MACRO(n, 5);
return 0;
}
Output:
main.c 2:43: warning: backslash and newline separated by space
main.c 2:27: warning: backslash and newline separated by space
ShambhunathShambhunathShambhunathShambhunathShambhunath
In C, the macro can use conditional statements like if-else directives also while defining that can be used for
conditional compilation. Let us consider an example:
Example:
intmain()
{
#if VERBOSE >= 2
printf("Message");
#endif
}
No Output:
If the macro is used for a function-like macro which has arguments passed to it are not evaluated before
macro expansion. Let us see the example:
Example:
#include <stdio.h>
#define DIV(a, b) a/b
intmain()
{
printf("%d", DIV(5+3, 3+2));
return 0;
}
Output:
8
23
Here in the above macro is expanded as 2 +3 /3 + 5 = 2 + 1 + 5 =8 which is confusing so you can resolve by
below modified macro.
#include <stdio.h>
//here, instead of writing a*a we write (a)*(b)
#define DIV(a, b) (a) / (b)
intmain()
{
printf("%d", DIV(5+3, 3+2));
return 0;
}
Output:
1
The macro is expended as (2 + 3) * (3 + 5), as 5*8 = 1
The macro also supports to pass the tokens to the macro to concatenate tokens using the special operator
“##” which is known as the token pasting operator. Let us see an example:
Example:
#include <stdio.h>
#define concate(p, q) p##q
intmain()
{
printf("%d ", concate(56, 78));
}
Output:
5678
The above code defines the function-like macro where the token is passed to concatenate two values of “p”
and “q”.
The macro also can be used to pass the token that can be converted to a string by using the “#” special
symbol before the token. Let us see an example:
Example:
#include <stdio.h>
#define get_string(n) #n
intmain()
{
printf("%s", get_string(shambhunath));
}
Output:
shambhunath
24