0% found this document useful (0 votes)
52 views84 pages

1 - C-Review - V2

Uploaded by

Azenix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
52 views84 pages

1 - C-Review - V2

Uploaded by

Azenix
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 84

WELCOME TO MY CLASS!!!

• Today’s agenda
– Brief idea how to act in a zoom lecture
– Introducing the instructor
– Course overview and brief idea about syllabus
– C review (as much as we can)
• Pointer
• Array, 2d array
• String
• Structure
• File IO
1
C programming review

Dr. Tanvir Ahmed

2
Starting with Fun!

3
Agenda
• In this lecture, we will review some advance topics in
C programming language
• Generally, it is assumed that you already have some
idea about these topics and a review will help you to
recall them.
• These topics are very important to understand the
subsequent advance topics and data structures that
we will learn in this course.
• If you think that you are not familiar with them, you
should spend good amount of time to review them
by this week.

4
Agenda
• Data and Memory
• Pointer review
– Declaring, dereferencing, pointer of pointer
– Function call by value and reference
• Arrays review
– Array concepts
– Array and pointers
– Passing array to a function
– 2D array
• String review
• Structure Review
• File I/O review 5
Data and Memory

6
Data and Memory
• Some very basic definitions:
• bit - a single zero or one. The word comes from the
contraction of "binary digit.
• byte - eight consecutive bits. Can store a char.
• word - the size of this depends on the computer, but they
are almost always either 2 or 4 bytes. Usually stores an int.

• You can imagine memory as a long array of numbered cells.


• For example, if we had 4 megabytes, then we would have
memory locations (each storing a byte) numbered from 0 to
4x220-1.

7
Data and Memory
• If we execute the line: char ch = 'A'
• and the variable ch happened to be stored in memory location 1000, our picture
would look like this:
…….

1002
1001
1000 Binary of ascii of ‘A’
……

• An integer would be stored over 4 consecutive bytes, and the address of the
variable storing the integer would be the first memory address the variable was
stored in.
• How to get a size of a variable or type?
• In certain situations, it's useful to know the size of a particular variable or
type/struct.
• The following expression returns the desired information:
• sizeof(int) or sizeof (x) //if x is a variable
8
Pointer Review
(We will briefly go through pointer
review. If you need more explanation,
please review the uploaded slide on
pointers)

9
Pointers
• A pointer can store the memory address of a variable of a
specific data type.
• Why specific data type? Because different type stored
differently and takes different size in memory.
• Example of declaring a pointer:
int *p; //You have to put * before the variable
name. Like any uninitialized variable,
here p is pointing to a garbage address as it is
not initialized yet.
- Another example bellow:
int *pointer1 = &x; // Example of both declaration and
initialization in the same line
addr of x
int x;
0x2000 1
0x9060

• The above statement also can be written as two lines


• int *pointer1;
• pointer1 = &x; 10
Basic Pointer Operators
• We can declare a pointer as follows:
• int *p;

• There are two key pointer operators:

• *p: Dereferences a pointer, returns the value stored at the


memory location p is pointing to. // note: this *p is not in
the pointer declaration line shown above;
• &x: Returns the address of where the variable x is stored.

• According to the example in the last slide, if we write


printf(“%d”, *poionter1) it will print the value
of x.

11
De-referencing Example
Consider this few lines of codes bellow, It will
print 1: p
q
0x9060
int *p , q; 0x2000
1
0x9060
p=&q;
printf(“%d”, *p); //this will print the value of q
• Why it is printing the value of q?
– Because, we are de-referencing p by writing *p
– The *p in the printf means, the variable it is pointing to. As
p is pointing to q, *p means actually q.
– Now you know the differences between *p in the first line
and *p in the third line
12
Summary of using * and &
• To declare a pointer add an * in front of its
name.
• To obtain the address of a variable use & in
front of its name.
• To obtain the value of a variable pointed by a
pointer, use * in front of a pointer's name.
output:
int main()
{ Pointer example p1 = 0x7ffce97158f8
p2 = 0x7ffce97158fc
*p1 = -42
*p2 = 163
int x, y;
---------
int *p1, *p2;
p1 = 0x7ffce97158f8 *p1 = 17
x = -42;
---------
y=163;
p1 = 0x7ffce97158fc *p1 = 163
p1 = &x;
---------
p2 = &y; ---------
printf("p1 = %p *p1 = %d \n", p1, *p1); p2 = 0x7ffce97158f8 *p2 = 17
printf("p2 = %p *p2 = %d \n", p2, *p2); p1 = 0x7ffce97158fc *p1 = 17
printf("---------\n"); ---------

*p1 = 17; // dereferencing. It means put 17 to the address


where p1 is pointing to. Kind of x = 17
printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------\n");

p1 = p2; //p1 is not pointing to x anymore. Now pointing to y


printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------\n");

p2 = &x;
printf("---------\n");
printf("p2 = %p *p2 = %d \n", p2, *p2);

*p1 = *p2;
printf("p1 = %p *p1 = %d \n", p1, *p1);
printf("---------");
return 0;
14
}
Testing pointer is pointing something
meaningful ( Dealing with segmentation fault)
• If a pointer is not initialized to any address, dereferencing that pointer
might result in garbage value, or can create segmentation fault/run-
time error as your code is trying to access a memory which is not
allocated to your program. In that case we can use the following
technique to prevent such potential error.
• We can assign NULL to a pointer.
• int *aPtr = NULL;
• It's important not to dereference a null pointer. Doing so will lead to a run-time
error.
• However, before dereferencing we can check it is NULL or not:
– if (aPtr) //it checks if aPtr is not NULL.
{ write statements that can use aPtr as it is safe to do so}
• The above line checks if aPtr is NULL or not.
– You could also write: if (aPtr!= NULL) //this is same as if (aPtr)
• Note that it is programmer’s responsibility to assing NULL values when necessary
15
Why to use pointer
• C programming language WANTED the programmer to
have the ability to directly manipulate memory.

• 1) Allow you to refer to a large data structure in a


compact way.
• 2) Allow you to share data efficiently among
functions.
• 3) Allow you to dynamically reserve memory.
• 4) Allow you to record relationships between data.

16
Pointers and Function Arguments
• Call by value
• Call by reference

x: 1 x: 2
swap
y: 2 y: 1

17
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;

fakeSwap(x, y);
printf(“%d %d\n”, x, y);
return 0;
}
18
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
19
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 0x2060

a:
tmp = a; 1 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
20
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 1 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
21
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 2 0x2038
a = b;
b:
b = tmp; 2 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
22
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = a; 2 0x2038
a = b;
b:
b = tmp; 1 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
23
#include <stdio.h>
Solution 1
void fakeSwap(int a, int b)
{
int tmp;

tmp = a;
a = b;
b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
fakeSwap(x, y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
24
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{
int tmp;

tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;

trueSwap(&x, &y);
printf(“%d %d\n”, x, y);
return 0;
}
25
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{
int tmp;

tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
26
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
27
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
1 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
28
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
2 0x2010
return 0;
}
29
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ tmp:
int tmp; 1 0x2060

a:
tmp = *a; addr of x 0x2038
*a = *b;
b:
*b = tmp; addr of y 0x2040
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
1 0x2010
return 0;
}
30
#include <stdio.h>
Solution 2
void trueSwap(int* a, int* b)
{ So, truSwap
int tmp;
managed to
swap x and y!
tmp = *a;
*a = *b;
*b = tmp;
}

int main()
{
int x = 1, y = 2;
x:
2 0x2000
trueSwap(&x, &y);
printf(“%d %d\n”, x, y); y:
1 0x2010
return 0;
}
31
Call by value and call by reference example conclusion

• The first solution used call by value method.


– It just copied the values from x, y into a, b
respectively
– Change in a and b did not affect x and y
• The second solution used call by reference
– We used pointer a and be to hold the address of
x and y
– So in the function we actually changed the value
within the address of x and y.
– So after completing the function call, the value of
x and y have changed

32
Pointer of Pointer
• The concept of pointers can be further
extended.
• Pointer, we know is a variable that contains
address of another variable.
• Now this variable itself might be another
pointer.
• Thus, we now have a pointer that contains
another pointer’s address.
• The following example should make this point
clear.
33
int main( )
{
int i = 3, *j, **k ;
j = &i ;
k = &j ;// K has the capability to hold address of pointer
printf ( "\nAddress of i = %u", &i ) ; //print address of i
printf ( "\nAddress of i = %u", j ) ; //print address of i
printf ( "\nAddress of i = %u", *k ) ; //print address of i
printf ( "\nAddress of j = %u", &j ) ; //print address of j
printf ( "\nAddress of j = %u", k ) ; //print address of j
printf ( "\nAddress of k = %u", &k ) ; //print address of k
printf ( "\nValue of j = %u", j ) ; //print value of j, which is address of i
printf ( "\nValue of k = %u", k ) ; //print value of k, which is address of j
printf ( "\nValue of i = %d", i ) ; //print 3
printf ( "\nValue of i = %d", * ( &i ) ) ; //print 3
printf ( "\nValue of i = %d", *j ) ; //print print 3
printf ( "\nValue of i = %d", **k ) ; //print 3. As *k = j, and *j = i, i=3
return 0;
}
//output:
Address of i = 178371580
Address of i = 178371580 i j k
Address of i = 178371580
Address of j = 178371584 178371580 178371584
Address of j = 178371584 3
Address of k = 178371592
Value of j = 178371580 178371580 178371584 178371592
Value of k = 178371584
Value of i = 3
Value of i = 3
Value of i = 3 34
Value of i = 3
Arrays

35
Arrays
• An array is a collection of variables, with:
• 1) The items are stored in consecutive memory locations
• 2) All the variables in an array are of the same type.

• We define an array as follows: int data[10];


• Here the size of the array is 10.
• To index a particular variable/element of the array do as
follows:
data[4] = 120;
• The first index is data[0] and last index is data[9]
• The items are: data[0], data[1], data[2], …., data[9]
• They contains garbage data if not initialized.
• Another way of declaring and initializing array:
int data[] = {87, 99, 75, 88, 93, 56, 77, 84, 89, 79};
36
Pointers and Arrays
• Array elements are stored in consecutive memory locations
• So, if you know the first address of the array, you can easily
access the remaining array elements!
• See the following example array.
• int A[8]
Index A[0] A[1] A[2] A[3] A[4] A[5] A[6] A[7]

Value 5 6 8 23 22 9 90 4
address 1000 1004 1008 1012 1016 1020 1024 1028

Look at the address!


Increasing by 4 as each
int takes 4 bytes

37
Pointers and Arrays
int array[size];
int* pPtr = array + i; //let’s say i is an index of the array

int* qPtr = array + j; //let’s say j is an index of the array

 The name array is equivalent to &array[0]


 It means, name of an array is a pointer
 pPtr++ increments pPtr to point to the next element
of array.
 pPtr += n increments pPtr to point to n elements
beyond where it currently points.
 pPtr-qPtr equals i-j.
 Thus, we can see that a pointer arithmetic depends
on the type.
 The increment or decrement will jump to 4 bytes if
the pointer is integer pointer. 38
Pointers and Arrays

Type array[size];

 array[0] is equivalent to *array


 array[n] is equivalent to *(array + n)
 How?
 We know array name is equivalent to the address of
first element
 So, array is same as &array[0]
 So, *array is dereferencing and getting array[0]

 (array+n) is the address of nth element,


 So, *(array+n) is equivalent to array[n]
39
Basic Pointer Arithmetic
Address in
hexadecimal format
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2008 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

40
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x200C 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr now holds the address: &array[1] */

Note: pPtr is not becoming 2008 to 2009. It is jumping to the next int as it is
an int pointer. It is increased by 4 as an int takes 4 bytes 41
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 NULL

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr now holds the address: &array[4] */

42
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 0x2010

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr = &array[4] */
qPtr = array + 2; /*qPtr now holds the address &array[2]*/
43
0x2008 0x200C 0x2010 0x2014 0x2018
array:

0x2008

0 1 2 3 4

pPtr: qPtr:

0x2004 0x2018 0x2000 0x2010

float array[5];
float* pPtr = array;
float* qPtr = NULL;

pPtr++; /* pPtr = &array[1] */


pPtr += 3; /* pPtr = &array[4] */
qPtr = array + 2; /* qPtr = &array[2] */
printf(“%d\n”, pPtr-qPtr); //the answer is 2. There are
two integers between them. 44
int main() Example: traversing through array using pointer
{
int data[] = {87, 99, 75, 88, 93};
int *p;
int i;
for(i = 0; i<5; i++)
printf("address: %p, value: %d, test: %d\n", data+i,
*(data+i), *data+i);

printf("--------using p-------------\n");
p = data; // p is now &data[0]
for(i = 0; i<5; i++)
{
printf("address: %p, value: %d \n", p, *p);
p++;
} output:
address: 0x7ffd8ec91e10, value: 87, test: 87
address: 0x7ffd8ec91e14, value: 99, test: 88
return 0; address: 0x7ffd8ec91e18, value: 75, test: 89
} address: 0x7ffd8ec91e1c, value: 88, test: 90
The values of address: 0x7ffd8ec91e20, value: 93, test: 91
the array also --------using p-------------
address: 0x7ffd8ec91e10, value: 87 It is just adding i to
can be accessed data[0].
using: address: 0x7ffd8ec91e14, value: 99
address: 0x7ffd8ec91e18, value: 75 *data is dereferencing
data[i] data (which is &data[0])
*(i+data) address: 0x7ffd8ec91e1c, value: 88
45
i[data] address: 0x7ffd8ec91e20, value: 93
What is the difference between
pointer and array?
• While double values[10]; allocates 10
locations to store doubles, double *p; does
not.
• Instead double *p; only allocates the
memory to store a single location in memory.
• However, we CAN use a pointer to
dynamically allocate memory, that we will
learn later in the semester (if we get time).

46
Passing Entire Array to Function
main( )
{
int num[ ] = { 24, 34, 12, 44, 56, 17 } ;
What are we
int i;
printf("Original Array: ");
passing?
for(i=0; i<6; i++) Reference or value?
printf("%d ", num[i]);

incBy2( num, 6 ) ; !!!also can be written


as: incBy2(int A[], int n)
printf("\nArray after calling incBy2: "); or incBy2(int A[6], int n)
for(i=0; i<6; i++)
printf("%d ", num[i]);
}
void incBy2(int *A, int n)//also can be written as: incBy2(int A[], int n) or incBy2(int A[6], int n)
{
int i ;
for ( i = 0 ; i < n ; i++ )
{
*A = *A + 2; //in crease an a particular array element by 2
A++; //A is jumping to the next array element’s address
}
} Output:
Original Array: 24 34 12 44 56 17
Array after calling incBy2: 26 36 14 46 58 19 47
Another version-Passing Entire Array to Function (Generally we use this approach
main( )
{ !!!even A is a
int num[ ] = { 24, 34, 12, 44, 56, 17 } ; pointer, you can use
int i; array syntax with it
printf("Original Array: "); as you have passed an
for(i=0; i<6; i++) array here.
printf("%d ", num[i]); We generally use this
syntax as it is easy
to follow like an
incBy2( num, 6 ) ; array

printf("\nArray after calling incBy2: ");


for(i=0; i<6; i++)
printf("%d ", num[i]);
}
void incBy2(int *A, int n)//also can be written as: incBy2(int A[], int n) or incBy2(int A[6], int n)
{
int i ;
for ( i = 0 ; i < n ; i++ )
{
//even A is a pointer, you can write it like an array as you have passed an array here
A[i] = A[i] + 2;
Output:
} Original Array: 24 34 12 44 56 17
} Array after calling incBy2: 26 36 14 46 58 19
48
Multidimensional Arrays
• It is also possible to have array with two or more
dimensions
• 2 dimensional array also called a matrix and easy to
visualize in tabular form.
• An example declaration:
• int grid[4][2];
• This array as 4 rows and 2 columns. Can be seen as:
Colum 0 Column 1
Row 0 grid[0][0] grid[0][1]
Row 1 grid[1][0] grid[1][1]
Row 2 grid[2][0] grid[2][1]
Row 3 grid[3][0] grid[3][1]
49
Multidimensional Arrays
• The declaration int grid[4][2]; can also be
interpreted as:
• This is an array of 4 elements
– Each element is an array of 2 elements
• So, it is kind of 4 one-dimensional arrays.
• Example: grid[0] is an array of 2 elements
– grid[0][0], and grid[0][1]
• The elements are laid out sequentially in
memory, just like a one-dimensional array

50
Multidimensional Arrays
Index grid[0][0] grid[0][1] grid[1][0] grid[1][1] grid[2][0] grid[2][1] grid[3][0] grid[3][1]

Value 5 6 8 23 22 9 90 4
address 1000 1004 1008 1012 1016 1020 1024 1028

• The above table shows the memory map for the


2D array we have declared. The address and
data are assumed. We consider int takes 4
bytes.
• See, grid[1][0] starts after completing full
grid[0] array.

51
2D Array is an array of arrays
main( )
{
int grid[4][2] = {
{ 5, 6 },
{ 8, 23 },
{ 22, 9 },
{ 90, 4 }
} ;
int i ;
for ( i = 0 ; i <= 3 ; i++ )
printf ( "\nAddress of %d th 1-D array = %u", i, grid[i] ) ;
}

Output:
Address of 0 th 1-D array = 2961709872
Address of 1 th 1-D array = 2961709880
Address of 2 th 1-D array = 2961709888
Address of 3 th 1-D array = 2961709896

52
Accessing 2D array using pointer
• The following are equivalent:
• s[2][1] //second row, first col
• *(s[2]+1)
• *(*(s+2)+1) //here 2 indicates
the array number

53
Accessing 2D array using pointer
main( )
{
int s[4][2] = {
{ 5, 6 },
{ 8, 23 },
{ 22, 9 },
{ 90, 4 }
} ;
int i, j ;
for ( i = 0 ; i <= 3 ; i++ )
{
printf ( "\n" ) ;
for ( j = 0 ; j <= 1 ; j++ )
printf ( "%d ", *( *( s + i ) + j ) ) ;
}
}

Output:
5 6
8 23
22 9
90 4

54
2D array as parameter
• Only first subscript may be left unspecified
• void f1(int grid[][10]) // valid
• void f3(int grid[][]); //invalid
• Generally, array sizes are also passed to functions while
dealing with 1D or multi dimensional array
• void print( int a[ ][4], int row, int col )
• The sizes allow to iterate properly and access the elements
within the ranges.

55
main( )
Accessing 2D array using pointer
{ print ( int q[ ][4], int row, int col )
int a[3][4] = { {
1, 2, 3, 4, int i, j ;
5, 6, 7, 8, for ( i = 0 ; i < row ; i++ )
9, 0, 1, 6 {
} ; for ( j = 0 ; j < col ; j++ )
printf ( "%d ", q[i][j] ) ;
print ( a, 3, 4 ) ; printf ( "\n" ) ;
} }
printf ( "\n" ) ;
display ( int *q, int row, int col ) }
{
int i, j ;
for ( i = 0 ; i < row ; i++ )
{
Our favorite one as
for ( j = 0 ; j < col ; j++ ) we are very
printf("%d ",*(q+i*col+j));
printf ( "\n" ) ; familiar with this
}
printf ("\n" ) ;
syntax. So, in
} general use this
one

56
Output of the code in the last slide

57
main( )
Accessing 2D array using pointer
{
Let’s see how this display function works
int a[3][4] = {
1, 2, 3, 4, - *q is receiving the address of a[0][0]. It
5, 6, 7, 8, has no idea about 2D array.
9, 0, 1, 6
} ; - We will use this loop to go to
display ( a, 3, 4 ) ; different rows and columns.
print ( a, 3, 4 ) ; - i will track row number and j will
}
track column number
display ( int *q, int row, int col )
{ - We will use this formula to access a
int i, j ; particular item in our 2D array:
for ( i = 0 ; i < row ; i++ )
{ - q+i*col+j //here col is the total
for ( j = 0 ; j < col ; j++ ) number of columns in the array
printf("%d ",*(q+i*col+j));
printf ( "\n" ) ;
- But how?:
}
printf ("\n" ) ; - See, q is always pointing to the first
} address of the array. It is not moving.
- Adding i*col will help to jump i*col
number of items. (kind of ith row)
- Then, adding j will help you to navigate
different items in that particular row 58
main( )
Accessing 2D array using pointer
{ i*4 is helping Let’s see how the display function works
int a[3][4] = { us to jump to - When, i = 0 (dealing with row 0):
1, 2, 3, 4,
5, 6, 7, 8,
ith row. (skip 4 - j = 0:
9, 0, 1, 6 numbers in each - *(q+ 0*4 + 0) = *(q+0) = 1
} ; row)
- j=1:
display ( a, 3, 4 ) ; - *(q+0*4 +1) = *(q+1) = 2
print ( a, 3, 4 ) ; - j=2:
} - *(q+0*4 +2) = *(q+2) = 3
display ( int *q, int row, int col )
- j=3:
{ - *(q+0*4 +3) = *(q+1) = 4
int i, j ;
for ( i = 0 ; i < row ; i++ ) - When, i = 1 (dealing with row 1):
{
for ( j = 0 ; j < col ; j++ ) - j = 0:
printf("%d ",*(q+i*col+j)); - *(q+ 1*4 + 0) = *(q+4) = 5
printf ( "\n" ) ; - j=1:
}
- *(q+1*4 +1) = *(q+5) = 6
printf ("\n" ) ;
} - j=2:
- *(q+1*4 +2) = *(q+6) = 7
- j=3:
- *(q+1*4 +3) = *(q+7) = 8
- Try for i = 2!
59
Strings

60
Strings review
• String is a char array
• Sequence of zero or more characters
terminated by null (‘\0’) character
• Note that ‘\0’ terminates the string but it is
not part of the string.
• strlen() function returns the length of a string.
null is not part of the length
• there are many useful functions for strings
are available at string.h
61
Strings review
• char s[10] = “cat”;
• Here s is an string and 10 bytes are allocated for the
string or array.
0 1 2 3 4 5 6 7 8 9
c a t ‘\0’

• Also can be declared using pointer:


char *s = “cat”; //but you cannot change the content in this
case. We have to use dynamic memory allocation to work on
it.
• You can access each character in the string like an
array.
• You can pass string to a function in the same way you
pass an array.
62
Strings review
• You can use scanf and gets method for taking
string input
• Be careful while using scanf to read string as it
will skip anything after space.
int main()
{
char name[20];
printf("Enter name: ");
scanf("%s", name);
printf("Your name is %s.", name);
return 0;
}
Output:
Enter name: Nusair Ahmed
Your name is . Nusair //see it failed to keep Ahmed
in the string
63
Strings review
• gets and puts methods for string.
• If you use gets, it can take string with spaces.
#include <stdio.h>
int main()
{
char name[30];
printf("Enter name: ");
gets(name); // read string
printf("Name: ");
puts(name); // display string
return 0;
}

Output:
Enter name: Nusair Ahmed
Name: Nusair Ahmed

64
Alternative of gets() method for string input
• gets() method is dangerous as it does not care about the
size of the char array and can takes more than the size.
As a result your program can crash and become unsafe.
• Alternative:
char name[30];
printf("Enter name: ");
scanf("%[^\n]s",name);
• you can also use: fgets(name, sizeof(name),
stdin);
• In case of fgets, it also keep the ‘\n’ in the string. The following
line will remove that ‘\n’
• name[strcspn(name, "\n")] = 0;
• See uploaded example code: fgets_DifferentScanf.c
• You will also get explanation in the code 65
Problems with getting string input after another input
int main()
{
int id;
char name[30];
char ch, c;
while(1){
printf("\nMenu, e: enter, x: exit: ");
scanf("%c",&ch);
if(ch=='x’){
printf("\n<<<<<<<EXIT>>>>>>\n\n\n");
break;
}
if(ch=='e'){
printf("\nEnter student id: ");
scanf("%d",&id);
printf("\nEnter student name: ");
scanf("%[^\n]s",name);
printf("Your entered %d %s", id, name);
}
}
return 0;
} 66
Problems with getting string input after another input
• In the example shown at previous slide, the
string input after the integer input will be
skipped.
– The reason is when you press the enter key after
providing an integer input, the enter key is passed
to the next string input and the console does not
wait to take an string input as it already found the
input.
– To avoid this types of problem, use the following
loop before the string input and after other scanf:
– while ((c = getchar()) != '\n' && c != EOF); //you should
declare c before using it
– See example code in the next slide 67
int main()
{
int id;
char name[30];
char ch, c;
while(1){
printf("\nMenu, e: enter, x: exit: ");
scanf("%c",&ch);
if(ch=='x'){
printf("\n<<<<<<<EXIT>>>>>>\n\n\n");
break;
}
if(ch=='e'){
printf("\nEnter student id: ");
scanf("%d",&id);
printf("\nEnter student name: ");
while ((c = getchar()) != '\n' && c != EOF); //added this to eat the \n
scanf("%[^\n]s",name);
printf("Your entered %d %s", id, name);
while ((c = getchar()) != '\n' && c != EOF); //added this to eat the \n
for next input
}
}
return 0;
}
68
Some useful methods for string available in string.h (you will
need them very often in this semester)
• char *strcpy(char *dst, char const *src);
– It copies src string to the dst string
– It is programmers responsibility to ensure dst has enough space to copy from src.
• char *strcat(char *dest, const char *src)
– It takes two arguments, i.e, two strings or character arrays, and stores the resultant
concatenated string in the first string specified in the argument.
• size_t strlen(const char *str);
– Get the length of the passed string
• char *strstr(const char *haystack, const char *needle)
– Search for needle string inside haystack string and returns a pointer to the first occurrence in
haystack. Or a null pointer will be returned if needle is not found in haystack.
• int strcmp(char const *s1, char const *s2);
– Compares two strings. See the following table to understand he returned date

Return Value Remarks

0 if both strings are identical (equal)

negative if the ASCII value of first unmatched character is less than second.

positive integer if the ASCII value of first unmatched character is greater than second.
69
int main()
{
strcmp test
char str1[] = "abcd", str2[] = "abde", str3[]="abCd",
str4[]="abcd";
int result;
result = strcmp(str1, str2);
printf("strcmp(str1, str2) = %d\n", result);

result = strcmp(str2, str1);


printf("strcmp(str2, str1) = %d\n", result);

result = strcmp(str1, str3);


printf("strcmp(str1, str3) = %d\n", result);

result = strcmp(str3, str1);


printf("strcmp(str3, str1) = %d\n", result);

result = strcmp(str1, str4); /*output


printf("strcmp(str1, str4) = %d\n", result);strcmp(str1, str2) = -1
strcmp(str2, str1) = 1
result = strcmp(str4, str1); strcmp(str1, str3) = 32
printf("strcmp(str4, str1) = %d\n", result);strcmp(str3, str1) = -32
strcmp(str1, str4) = 0
return 0; strcmp(str4, str1) = 0
} */
70
STRUCTS

71
Struct review
• When the data you want to store doesn't fit neatly into a predefined C
type, you can create your own. Here is an example:

struct employee {
char[20] name;
double salary;
int empID;
};

• Now, to declare a variable of this new data type, we write:

struct employee officeworker;

• To access the fields of a struct employee variable do as follows:

officeworker.empID = 1;

72
Struct and Pointer
• Structure is used to group related variables (members) of
various types together in an organized way. Also, we call it
custom data type.
struct employee {
char[20] name;
double salary;
int empID;
};
• Now, to declare a variable of this declared type, we write:
struct employee officeworker;
• Often times, for efficiency purposes, it's easier to declare pointers to structs and use those to manipulate
the structures formed.
• Consider the following:
struct employee *temp;// declare a pointer of type employee
temp = &officeworker; //store the address of office worker to temp
(*temp).salary = 50000; //dereference temp to access salary of officeworker
• Since expressions similar to the last one are used so often, there is a shorthand to access a field/member of
a record through a pointer to that record. The last statement can also be written as:
temp->salary = 50000 // -> is mostly used to dereference structure pointer.
• Another reason to use a pointer to a struct is to dynamically allocate the memory for the struct. (We will
briefly discuss about dynamic memory allocation in our next class).
• This allows the memory to be allocated beyond the “life”/”scope” of the function within which it was
declared.

73
Typedef and Pointers and Structures

temp
typedef struct bookRec{
float price;
char name[7];
}Book;
//if you use typedef, you don’t have to write struct
every time when you declare a variable of your
structure

Book temp; //this line is possible as we have used typedef

scanf("%d %s", &temp.price, temp.name);


74
Pointers and Structures

aPtr
temp
struct bookRec{
float price;
char name[7];
}Book;

Book *aPtr;
Book temp;
aPtr = &temp;

scanf("%d %s", &(aPtr->price), aPtr->name);

75
Structures and Functions
• Example 1: Passing individual structure members
struct book{
char title[40];
char author[40]; This parameter list has no
int price; idea about the structure. It
}; can just take two char
void display(char *t, char *a, int p) pointers and one int
{
printf(“\n%s %s %d”,t, a, p);
}

Here, we are not really passing


a structure. Just passing
int main(){ individual members
struct book b1={“Programming knights”,”Arup Guha”,50};

display(b1.title, b1.author, b1.price);


}
Structures and Functions
• Example 2: Passing entire structure variable
struct book{
char title[40]; This function takes a book
char author[40]; structure variable.
int price; Just a note: structures are
}; passed by value like other
types of variables.
void display(struct book b)
{
printf(“\n%s %s %d”,b.title,b.author,b.price);
}

main(){
struct book b1={“Programming knights”,”Arup
Guha”,50};
Here, we are passing our
display(b1); structure variable.
} Note: we are not passing
reerence
Passing reference to a structure in function
struct book{
char title[40];
char author[40];
int price; This function takes address
}; of a book structure variable.
This function has the ability
to change the value of b1.
void display(struct book *b)
{
printf(“\n%s %s %d”,b->title,b->author,b->price);
}

main(){
struct book b1={“Programming knights”,”Arup
Guha”,50};
Here, we are passing our
display(&b1); structure variable.
} Note: we are not passing
reerence
Returning a structure from a function
struct point{
int x;
int y; This function returns a point
type data
};

struct point get()


{
struct point p;
scanf(“%d %d”, &p.x, &p.y);
return p;
}

main(){
struct point p1, p2;
p1 = get();//calling get() function and storing the result in p1
p2 = get();

}
Array of Structures
• Let’s consider a case where we want to store data of
100 books. We would be required to use 100
different structure variables from b1 to b100, which
is definitely not very convenient.
• A better approach would be to use an array of
structures. books[0] title, author, price, pages
• Example: books[1] title, author, price, pages
typedef struct Book { books[2] title, author, price, pages
char title[50];
books[3] title, author, price, pages
char author[50];
float price; ……
int pages;
……
}Book;
Books[99] title, author, price, pages
Book books[100];

This provides space in memory for 100 structure variables


of type Book .
Example Array of structure
#include <stdio.h> Declaring array of structure. As we have used typedef, no
#include <string.h> need to write struct key word. Otherwise you have to
#define SIZE 3
write struct keyword. Continuation of the code
typedef struct Book {
char title[50]; printf("Displaying the book list:
char author[50]; \n");
float price; for(int i=0; i<SIZE; i++)
int pages; {
}Book; printf("Information for book
int main( ) { %d:\n Name: %s Auhor: %s Price:
Book books[SIZE]; %0.2f Pages: %d\n",i+1,
char x; books[i].title, books[i].author,
books[i].price, books[i].pages);
for(int i=0; i<SIZE; i++) { }
printf("Enter book title for book %d: ", return 0;
i+1); }
scanf("%[^\n]s", books[i].title);
//clearing up the \n from the last input
while((x=getchar() != '\n') && x != EOF);
printf("Enter author for book %d: ", i+1);
scanf("%[^\n]s", books[i].author);
printf("Enter price for book %d: ", i+1);
scanf("%f", &books[i].price);
printf("Enter total pages for book %d: ",
i+1);
scanf("%d", &books[i].pages);
while((x=getchar() != '\n') && x != EOF);
//clearing up the \n from the last input
}
Example output of the last slide’s code
File I/O
• Please go through the File I/O example codes under
C review folder in webcourses.
• See how fscanf and fprintf works.
• We will need to use fscanf and fprintf in various
codes in this semester.

83
Source Codes
• All the codes in the slides as well as more
examples are available in creview folder in
webcourses.

84

You might also like