EE3491 - Kỹ thuật lập trình
EE3490E – Programming Techniques
Chapter 3: Functions and Libraries
Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính)
Department of Automation Engineering
School of Electrical and Electronics Engineering
Email:
[email protected] © HĐC 2024.1
Content
3.1 Functions and Functional programming
3.2 Function declaration and definition
3.3 Arguments and returning values
3.4 Function design and library
3.5 Recursion
3.6 ANSI-C standard library
3.7 Working with files in C/C++
3.8 Function overloading in C++
3.9 Inline function in C++
© HĐC 2024.1 Chapter 3: Functions and Libraries 2
3.1 Functions and Functional programming
Structure programming is based on two approaches:
Function-oriented programming, sometimes called task-
oriented or procedure-oriented programming
T_1 T_1a T_1b
Tasks T_2 T_2a T_2b T_2c
T_3 T_3
Data-oriented programming
D_1
Data 1
D_2
Data 2
D_3
Data 3
© HĐC 2024.1 Chapter 3: Functions and Libraries 3
Functions
Functions help to break large computing tasks into
smaller ones, and enable people to build on what others
have done instead of starting over from scratch
reusability
Functions are related to each other via call statements,
arguments (inputs, outputs) and returning values
Implementation of a function depends on inputs
(arguments):
Results of a function should be unchanged all the time if inputs
are the same
A function without argument is less reusable
© HĐC 2024.1 Chapter 3: Functions and Libraries 4
Functions vs. Procedure vs. Routines
A procedure is a routine that can accept arguments but
does not return any values.
A function is a routine that can accept arguments and
returns one or more values.
User-defined routine (UDR) is a generic term that
includes both user-defined procedures and user-defined
functions.
In C/C++: there is no difference between a procedure
and a function, main procedure of the program, i.e.
main(), is also a function
© HĐC 2024.1 Chapter 3: Functions and Libraries 5
Example of functional programming
Problem: Calculate summation of an integer array
(continuously) with the range provided by a user. Print
the result on the screen.
Tasks:
Read the first integer:
o Ask the user to provide
o Assign the value to a variable
Read the second integer:
o Ask the user to provide
o Assign the value to a variable
Calculate the summation using a loop statement
Print the result on the screen
© HĐC 2024.1 Chapter 3: Functions and Libraries 6
4 in 1 approach
#include <iostream>
using namespace std;
void main() {
int a, b;
char c;
do {
cout << "Enter the first integer number: ";
cin >> a;
cout << "Enter the second integer number: ";
cin >> b;
int Total = 0;
for (int i = a; i <= b; ++i)
Total += i;
cout << "The sum from " << a << " to " << b
<< " is " << Total << endl;
cout << "Do you want to continue? (Y/N):";
cin >> c;
} while (c == 'y' || c == 'Y');
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 7
Functional programming approach 1
#include <iostream>
using namespace std;
int ReadInt();
int SumInt(int, int);
void WriteResult(int a, int b, int kq);
void main() {
char c;
do {
int a = ReadInt();
int b = ReadInt();
int T = SumInt(a,b);
WriteResult(a,b,T);
cout << "Do you want to continue? (Y/N):";
cin >> c;
} while (c == 'y' || c == 'Y');
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 8
Functional programming approach 1
int ReadInt() { No argument. Difficult
cout << "Enter an integer number: "; to reuse???
int N;
cin >> N;
return N;
}
int SumInt(int a, int b) { OK. Can’t be better!
int Total = 0;
for (int i = a; i <= b; ++i)
Total += i;
Too many arguments.
return Total;
May not be effective?
}
void WriteResult(int a, int b, int kq) {
cout << "The sum from " << a << " to " << b
<< " is " << kq << endl;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 9
Functional programming approach 1
Easy to read easy to find errors
Easy to extend
SumInt function can be reused
Longer code
Larger machine code
Slower execution
The solution does not rely on number of functions, the
way of function organization and design should be
optimal!
© HĐC 2024.1 Chapter 3: Functions and Libraries 10
Functional programming approach 2
#include <iostream.h>
int ReadInt(const char*);
int SumInt(int,int);
void main() {
char c;
do {
int a = ReadInt("Enter the first integer number :");
int b = ReadInt("Enter the second integer number:");
cout << "The sum from " << a << " to " << b
<< " is " << SumInt(a,b) << endl;
cout << "Do you want to continue? (Y/N):";
cin >> c;
} while (c == 'y' || c == 'Y');
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 11
Functional programming approach 2
int ReadInt(const char* userPrompt) {
cout << userPrompt;
int N;
cin >> N; OK. Looks better!
return N;
}
int SumInt(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i)
Total += i;
return Total;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 12
3.2 Function declaration and definition
Define a function: create implementation code
Returning type Function name Argument (representative)
int SumInt(int a, int b) {
int Total = 0;
for (int i = a; i <= b; ++i)
Total += i;
return Total;
}
Function declaration only: no code
int SumInt(int a, int b);
Returning type Function name Argument type
© HĐC 2024.1 Chapter 3: Functions and Libraries 13
Local variables
A function may have variables defined within it (local
variable)
Scope of these local variable is only inside the function
Local variables are allocated in memory only when the function
is called
They are free when exiting the function
Arguments are also local variables
/* Yield area of circle with radius r */
double circle_area (double r) {
double x, area1;
x = r * r ;
Argument
area1 = 3.14 * x ;
return( area1 ); Local variables
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 14
Type and returning value of a function
A function may return a value
Similar to other values in C, the returning value of a
function must have its data type. The function called has
the same type as returning value
Type of the function (same as type of
the returning value). GenRandom() is
/* return a “random” number */ a function of double type or
double GenRandom (void) GenRandom() return a double value
{
double result; Local variable, exist during the
result = ... function execution
return result; Return statement
}
Returning value
© HĐC 2024.1 Chapter 3: Functions and Libraries 15
void
Keyword void has two different meaning in this
function definition
The function does not
return any value
/* write separator line on output*/
void PrintBannerLines (void)
{
printf(“***************”);
The function has no
printf(“***************\n”);
arguments
}
Why and when do we need to declare a function
© HĐC 2024.1 Chapter 3: Functions and Libraries 16
void
In C, a function with an empty parameter list () can take
anything for its arguments.
In C, a function with the parameter list (void) explicitly
takes nothing for its arguments
In C++, these function declarations are equivalent
© HĐC 2024.1 Chapter 3: Functions and Libraries 17
Function declaration and call
Function declaration meaning:
When it is needed to use a function (call a function)
Compiler needs a declaration to verify function call syntax,
number of arguments, argument type, and returning value usage
It is possible to declare a function independently with its
definition, but it needs to assure consistency
Function call: it is required to implement function code
with actual values passed to its arguments
It is not required to define a
function when compiling, but
int x = 5;
its declaration must have been
int k = SumInt(x,10);
done!
Function name Arguments
© HĐC 2024.1 Chapter 3: Functions and Libraries 18
Where to declare?
Global scope (outside of any functions)
A function must be declared before its first call in a
source code
If using a number of functions, a lots of declaration
statements are also required (it takes effort to write, easy
to make mistakes, and longer source code?):
If a developer creates the functions and puts all the declarations
in a files Header file (*.h), users need to write just this
statement: #include <filename.h>
Source code is not larger as the declaration does not generate
code
A function can be declared multiple times
© HĐC 2024.1 Chapter 3: Functions and Libraries 19
Where to define?
Global scope (outside of any functions)
It can be in the same file of main program, or put in a
separate file:
*.c=> C compiler,
*.cpp=> C++ compiler
If a function has been called, it must be defined once in the
program (project), before using linker/compiling
A function can be defined in C, C++, ASM or another
language and then used in C/C++ using the function
without source code
A library for C/C++ includes:
Header file (usually has extension of *.h, *.hxx, …, but not
necessary)
Source code file (*.c, *.cpp, *.cxx, …) or destination file (*.obj, *.o,
*.lib, *.dll,…)
© HĐC 2024.1 Chapter 3: Functions and Libraries 20
The order of functions in *.c file
Name of the function must follow the rule that it must be
declared before being used
#include <stdio.h>
void fun2 (void) { ... }
void fun1 (void) { ...; fun2(); ... }
int main (void) { ...; fun1(); ... return 0; }
fun1 calls fun2, thus fun2 must be declared before fun1,
etc.
© HĐC 2024.1 Chapter 3: Functions and Libraries 21
3.3 Arguments and returning values
Arguments and returning values are a basic method to represent
the relationship among functions (or among features in the
system)
Fun_A Fun_B Returning
a d values /
Arguments Returning
b Arguments Output
(Inputs) values /
c (Inputs) e e parameters
Output
parameters
Besides, there are other ways:
Using global variables: in general, it is not recommended
Using files, streams: in fact, arguments are still required to represent which
files or which streams
Other interface mechanisms which depends on OS, platforms or
communication protocols, however it is still needed the support of
arguments
Passing arguments and returning values are the core basis to create
and use functions, which is crucial to decide the software quality
© HĐC 2024.1 Chapter 3: Functions and Libraries 22
Representative variables and actual parameters
int SumInt (int a,int b) {
...
Arguments
} (representative)
int x = 5;
int k = SumInt(x,10); Returning value
(no name)
...
Actual
parameters
SumInt
int a = 2; x a
k
k = SumInt(a,x); 10 b
Variable assigned
to returning value
Arguments
© HĐC 2024.1 Chapter 3: Functions and Libraries 23
3.3.1 Passing values
int SumInt(int,int);
// Function call
void main() {
int x = 5;
int k = SumInt(x,10); SP
... b = 10
} a=5
SP
k = 45
// Function definition
x=5
int SumInt(int a,int b) {
...
© HĐC 2024.1 Chapter 3: Functions and Libraries 24
Try an example
#include <iostream.h>
void ReadInt(const char* userPrompt, int N) {
cout << userPrompt;
cin >> N;
}
void main() {
int x = 5;
ReadInt("Input an integer number:", x);
cout << "Now x is " << x;
...
}
Result: x is unchanged
© HĐC 2024.1 Chapter 3: Functions and Libraries 25
Passing values
It is common use in C & C++
Arguments (function parameters) take only the copy of
input variables (actual variables)
Changing function parameters is only effective to local
memory, it does not affect the input variables
Function parameters can be used to take the inputs, they
cannot represent the function results (outputs)
Passing values are pretty safe and can avoid side-effects
It is not very efficient as it takes effort to copy data
© HĐC 2024.1 Chapter 3: Functions and Libraries 26
3.3.2 Passing a pointer
int SumInt(int* p, int N);
// Function call
void main() {
SP
int a[] = {1, 2, 3, 4}; k = 45
int k = SumInt(a,4);
N=4
...
p = 00A0
} SP
// Function definition k = 45
int SumInt(int* p, int N) { a[3] = 4
int*p2 = p + N, k = 0; a[2] = 3
while (p < p2)
a[1] = 2
k += *p++;
return k; 00A0 a[0] = 1
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 27
Passing an array?
int SumInt(int p[4], intN);
// Function call
void main() {
int a[] = {1, 2, 3, 4};
Similar to the previous
int k = SumInt(a,4); example: Passing an
... address!
}
// Function definition
int SumInt(int p[4], int N) {
int*p2 = p + N, k = 0;
while (p < p2)
k += *p++;
return k;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 28
Retry the example of reading from keyboards
#include <iostream.h>
void ReadInt(const char* userPrompt, int* pN) {
cout<< userPrompt;
cin>> *pN;
}
void main() {
int x = 5;
ReadInt("Input an integer number:", &x);
cout<< "Now x is " << x;
...
}
Output: value of x has been changed (it explained why
scanf() requires arguments of the pointer type)
© HĐC 2024.1 Chapter 3: Functions and Libraries 29
2-dimensional array as arguments
void read_2D (int a[MAX_STUDENTS][MAX_HWS],
int nstudents, int nhws)
{
int i, j;
for (i = 0; i < nstudents; i = i + 1)
for (j = 0; j < nhws; j = j + 1)
Can ignore scanf(“%d”, &a[i][j]);
} Must include
int a[][MAX_HWS]
int *a[MAX_HWS]: an array of MAX_HWS pointers to integers
int (*a)[MAX_HWS]: a pointer to an array of MAX_HWS integers
© HĐC 2024.1 Chapter 3: Functions and Libraries 30
2-dimensional array as arguments
Method 1
int main(void)
{
int score[MAX_STUDENTS][MAX_HWS];
int nstudents, nhws;
scanf(“%d %d”, &nstudents, &nhws);
if (nstudents <= MAX_STUDENTS &&
nhws <= MAX_HWS)
read_2D (score, nstudents, nhws);
...
no &
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 31
2-dimensional array as arguments
Method 2
void read_2D (int *a[MAX_HWS],
int nstudents, int nhws) { … }
int main(void)
{
int *score[MAX_HWS];
int nstudents, nhws;
scanf(“%d %d”, &nstudents, &nhws);
if (nstudents <= MAX_STUDENTS && nhws <= MAX_HWS)
read_2D (score, nstudents, nhws);
...
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 32
2-dimensional array as arguments
Method 3
void read_2D (int **a, int nstudents, int nhws) { … }
int main(void)
{
int **score;
int nstudents, nhws;
scanf(“%d %d”, &nstudents, &nhws);
if (nstudents <= MAX_STUDENTS && nhws <= MAX_HWS)
read_2D (score, nstudents, nhws);
...
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 33
When to pass a pointer (address)
When it is required to change input variables (access
directly to their addresses not the copies)
Size of the argument’s data type is large; thus, it can
avoid to copy large data to stack
Passing an array, it is a must to use pointer or passing
address
Attention: Use pointer to pass the address of input
variable memory allocation. The pointer can be changed
within the function, but the memory allocation is not
(though the content of that memory is changeable) as
shown in the SumInt functions
© HĐC 2024.1 Chapter 3: Functions and Libraries 34
3.3.3 Passing reference (C++)
#include <iostream.h>
void ReadInt(const char* userPrompt, int& N) {
cout << userPrompt;
cin >> N;
}
void main() {
int x = 5;
ReadInt("Input an integer number:", x);
cout << "Now x is " << x;
...
}
Output: the value of x is changed
© HĐC 2024.1 Chapter 3: Functions and Libraries 35
Example: swap() function
#include <iostream.h>
void swap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
}
void main() {
int x = 5, y = 10;
swap(x,y);
cout << "Now x is " << x << ", y is " << y;
...
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 36
When to pass reference
Only in C++
It is required to change “input variables” (access directly
in memory allocation, not via the copy)
A reference argument can be output (consisting of the
result), or both input and output
Size of the argument’ data type is large, thus it can avoid
to copy large data to stack, e.g.:
void copyData (const Student& sv1, Student& sv2) {
sv2.birthday= sv1.birthday;
...
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 37
3.3.4 Types of returning values
Data types of the returning values can be anything,
except an array (directly)
It can be
Values
Pointers
References
However, be careful with pointers and references:
Never returning a pointer or a reference of a local variable
Never returning a pointer or a reference of an argument which
has been passed with a value
Inexperience developer should return values only
© HĐC 2024.1 Chapter 3: Functions and Libraries 38
Returning mechanism
int SumInt(int a,int b){
int k = 0;
for (int i=a; i <= b; ++i)
k +=i;
SP
return k; k >= 45
}
b = 10
void main() { a=5
int x = 5, k = 0; k = 45
k = SumInt(x,10);
x=5
...
}
45
© HĐC 2024.1 Chapter 3: Functions and Libraries 39
Return a pointer
Write a function to return the address of the element with the
largest value in an array
int* FindMax(int* p, int n) {
int *pMax = p;
int *p2 = p + n;
while (p < p2) {
if (*p > *pMax)
pMax = p;
++p;
}
return pMax;
}
void main() {
int s[5] = { 1, 2, 3, 4, 5};
int *p = FindMax(s,5);
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 40
Example of error in returning pointer
A function returns a pointer
int* func_returns_pointer(void);
However, an error will occur if it returns a pointer to a
local variable
int* misguided(void)
{
int array[10], i;
for (i = 0; i < 10; ++i)
array[i] = i;
return array;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 41
Why do we need to return a pointer or a reference
Similar to passing a pointer or a reference to a function:
Size of the argument’s data type is large; thus, it can avoid to
copy large data to stack
When it is required to access directly and change output values
How to return a pointer or a reference
Assign it to a global variable
Assign input argument of the function via address or reference
In summary, it should be assigned to a memory allocation
which still exists after exiting the function
© HĐC 2024.1 Chapter 3: Functions and Libraries 42
A counterexample of pointer
int* FindMax (int* p, int n) {
int Max = *p;
int *p2 = p + n;
while (p < p2) {
if (*p > Max)
Max = *p;
++p;
}
return &Max;
}
void main() {
int s[5] = { 1, 2, 3, 4, 5};
int *p = FindMax(s,5);// get invalid address
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 43
Some more examples: right/wrong?
int* f1(int a) { int f5(int* pa) {
... ...
return &a; return *pa;
} }
int& f2(int &a) { int& f6(int* pa) {
... ...
return a; return *pa;
} }
int f3(int &a) { int& f7(int a) {
... ...
return a; return a;
} }
int* f4(int* pa) { int *pa;
... int* f8() {
return pa; ...
} return pa;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 44
3.3.5 Function pointer
Function pointer is a pointer variable which points to the
address of the function, its value is the starting address of the
function in the code memory segment
Function name is the pointer pointing towards the function
It is actually a variable, so the usage is the same as normal
one
#include <stdio.h>
void fun(int a){
printf("Value of a is %d\n", a);
}
int main()
{
void (*fun_ptr)(int) = fun; // & removed
fun_ptr(10); // * removed
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 45
Example of function pointer
#include <stdio.h> int main()
void add(int a, int b) {
{ // fun_ptr_arr is an array of
// function pointers
printf("Addition is %d\n",
a+b); void (*fun_ptr_arr[])(int, int)
= {add, subtract, multiply};
}
unsigned int ch;
unsigned int a = 15, b = 10;
void subtract(int a, int b)
{
printf("Enter Choice: 0 for
printf("Subtraction is add, 1 for subtract and 2 for
%d\n", a-b); multiply\n");
} scanf("%d", &ch);
void multiply(int a, int b) if (ch > 2)
{ return 0;
printf("Multiplication is (*fun_ptr_arr[ch])(a, b);
%d\n", a*b);
return 0;
}
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 46
Example of function pointer – Callback function
#include <stdio.h>
void callback_func()
{
printf(“I am a call back function”);
}
void f(void (*ptr))
{
ptr(); // a call-back function that p point to
}
int main()
{
void (*p)() = callback_func;
f(p);
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 47
Example of Function pointer with –qsort
// An example for qsort and comparator
#include <stdio.h>
#include <stdlib.h>
int compare (const void * a, const void * b)
// this is a call-back function
{
return ( *(int*)a - *(int*)b );
}
int main ()
{
int arr[] = {10, 5, 15, 12, 90, 80};
int n = sizeof(arr)/sizeof(arr[0]), i;
qsort (arr, n, sizeof(int), compare);
for (i=0; i<n; i++)
printf ("%d ", arr[i]);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 48
Example of Function pointer with Timer
// CPP program to create a timer void timer(void (*p)()){
#include <iomanip> while (true) {
#include <iostream> p(); // Call back function
#include <stdlib.h> sleep(1); // sleep for 1 seconds
#include <unistd.h> seconds++; // increment seconds
using namespace std; // if seconds reaches 60
if (seconds == 60) {
// hours, minutes, seconds of timer // increment minutes
int hours = 0; minutes++;
int minutes = 0; // if minutes reaches 60
int seconds = 0; if (minutes == 60) {
// increment hours
void displayClock() { // function to display the timer hours++;
// system call to clear the screen minutes = 0;
system("cls"); }
seconds = 0;
cout << setfill(' ') << setw(55) << " TIMER \n"; }
cout << setfill(' ') << setw(55) << " --------------------------\n"; }
cout << setfill(' ') << setw(29); }
cout << "| " << setfill('0') << setw(2) << hours << " hrs | ";
cout << setfill('0') << setw(2) << minutes << " min | "; int main() {
cout << setfill('0') << setw(2) << seconds << " sec |" << endl; void (*p)() = displayClock;
cout << setfill(' ') << setw(55) << " --------------------------\n"; // start timer from 00:00:00
} timer(p);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 49
3.3.6 Command-line arguments
C allows users to provide inputs when executing program with
command-line arguments
Structure of the main function:
int main(void)
int main(int argc, char *argv[])
argc argument count and argv argument vector.
argc is the number of arguments in the command including the
program name. Arguments are separated by space character
argv is a pointer which points to an array of string; size of the
array is argc + 1 as argv[argc]= NULL
© HĐC 2024.1 Chapter 3: Functions and Libraries 50
Example of command-line arguments
#include <stdio.h>
/* Print command-line arguments to
stdout. */
int main (int argc, char *argv[])
{
int i;
for (i = 1; i < argc; ++i)
printf("%s ", argv[i]);
printf("\n");
}
It prints input command-line arguments (except argv[0])
© HĐC 2024.1 Chapter 3: Functions and Libraries 51
3.4 Function design and designing a program with multiple functions
It is hard to write a good program, making a good library
is even harder
A function library defines:
A group/set of functions (related to the same topic)
Data types used in the functions
A few global variables (limited uses)
A good library should:
Implement useful features
Be simple and easy to use
Be efficient and highly reusable
Be complete, consistent and comprehensive
© HĐC 2024.1 Chapter 3: Functions and Libraries 52
3.4.1 Function design
Requirement analysis
Clarify assumptions (inputs) and results (outputs)
Figure out features to be implemented
Function naming: short, meaningful, self-described
Action function: a verb + an object, e.g.: printVector, displayMatrix,
addComplex, sortEventQueue, filterAnalogSignal, …
Functions to access properties: a verb or a noun combine with a
specific object, e.g.: length, size, numberOfColumns, getMatrixElem,
putShapeColor
In C++, many functions may have the same name (function
overloading), thus short names can be used, e.g.: sort, print,
display, add, putColor, getColor polymorphism in OOP
In C++, it is possible to define operator which utilizes pre-
defined operator symbol such as *, /, +, - instead of function
calls
© HĐC 2024.1 Chapter 3: Functions and Libraries 53
Function design
Choose input variables ( arguments)
Describe the meanings: the roles of those arguments
Naming: compact, self-described
Date types: minimum in size but sufficient to represent
Methods to pass variables: passing values or addresses/references to
constants
Select output variables ( use addresses/references or returning
values)
Describe the meanings, naming, data-type similar to the inputs
Define and add new data type if necessary
Describe pre-conditions: boundary constraints for input variables
and external conditions for calling the function
Describe post-conditions: the effect of using function to external
conditions, required subsequence tasks,…
Design function body based on analysed features and using
flowchart with condition/branching statements (including loops)
divide into sub-functions if required
© HĐC 2024.1 Chapter 3: Functions and Libraries 54
Example: Find prime numbers
Problem: Build a function to find the first N prime
numbers!
Analysis:
Input: N – number of the first prime number to find
Result: An array of the first N prime numbers
Features to be implemented:
o Read data? NO!
o Check input variable (N)? Yes/No (E.g., what to do if N < 0)
o The first k prime number is given, identify the next prime number
o Store the result at each step to a suitable data structure (the desired
array)
o Print the output to screen? NO!
N - number of Function to find N An array of the
the first primes prime numbers first N primes
© HĐC 2024.1 Chapter 3: Functions and Libraries 55
Example: Find prime numbers
Function name: findPrimeSequence
Input variable: 1
Meaning: number of primes to find
Name: N
Type: sufficient integer (int/long)
Passing argument: via value
Output: 1
Meaning: a sequence of N first primes to find (starts at 1)
Returning value or argument? Argument!
Name: primes
Type: an array of integer (of int/long)
Passing arguments: via address (int* or long*)
Pre-conditions:
N must be non-negative ( should we use unsigned )
primes must carry the address of a N-element array
Post-conditions: nothing special!
© HĐC 2024.1 Chapter 3: Functions and Libraries 56
Example: Find prime numbers
Function declaration:
void findPrimeSequence(int N, int* primes);
Design function body:
Flowchart
Use a new function: findNextPrime
Repeat the design steps for findNextPrime function
© HĐC 2024.1 Chapter 3: Functions and Libraries 57
© HĐC 2024.1 Chapter 3: Functions and Libraries 58
3.4.2 Designing a program with multiple functions
Top-down design approach
Bottom-up design approach
© HĐC 2024.1 Chapter 3: Functions and Libraries 59
Top-down design approach
Break down the program into smaller components which
links together
Design the structure of the program
© HĐC 2024.1 Chapter 3: Functions and Libraries 60
Implementation
Functions are implemented in tree form, with the top one
is the combination of the below functions
The process of division is carried out until the bottom
functions perform only one task
It is usually done by providing a sequence of functions
with only interface without specific content
Debug each function individually unit test
This is the best approach to design program structure,
however, the functions may not be reusable
© HĐC 2024.1 Chapter 3: Functions and Libraries 61
Bottom-up Design Approach
Indicate program components without knowing its
structure
Write each components:
With specified interface
Programming and test each component
The components are easier to reuse than that in top-down
approach
They can be combined into a library
C standard library is an example of bottom-up design
© HĐC 2024.1 Chapter 3: Functions and Libraries 62
Bottom-up Design Approach
Disadvantages
Cannot have a proper overview of the program/problem and
does not provide a good structure of a specific program
Lack of connections amongst the components
Combination of both top-down and bottom-up design
can be a solution to form a better program
© HĐC 2024.1 Chapter 3: Functions and Libraries 63
3.5 Recursion
It’s possible for a function to call itself. This is termed
recursion
int foo(int x) {
...
y = foo(...);
...
}
Questions:
How recursion works?
o To be discussed
Why do we need recursive functions?
o We will see the motivations
© HĐC 2024.1 Chapter 3: Functions and Libraries 64
3.5.1 Factorial function
Function name
Parameter/
int factorial(int n) Argument
{
int product, i;
product = 1; Local variables
Type and for (i = n; i > 1; i = i - 1)
returning {
value product = product * i;
} 0! = 1
return (product); 1! = 1
2! = 1 * 2
}
3! = 1 * 2 * 3
...
© HĐC 2024.1 Chapter 3: Functions and Libraries 65
Factorial function using recursion
The definition of factorial function is recursive itself
0! = 1! = 1; for n > 1, n! = n(n-1)!
int factorial(int n)
{
int t; 0! is 1
if (n <= 1) 1! is 1
t = 1; n! is n * (n-1)!, for n>1
else
E.g.: 3! = 3 * 2!
t = n * factorial(n - 1);
= 3 * 2 * 1!
return t;
=3*2*1
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 66
Function revision
It does not take much effort to trace the recursive
function if we remember the background of functions:
Arguments and variables declared in a functions is the local
variable of that function
o They are allocated memory space once the function is called
o The allocated memory is free when exiting the function
Arguments are initialized by copying values of the passing
variables in function call
© HĐC 2024.1 Chapter 3: Functions and Libraries 67
Factorial function
factorial(4) =
4 * factorial(3) =
4 * 3 * factorial(2) =
4 * 3 * 2 * factorial(1) =
4 * 3 * 2 * 1 = 24
© HĐC 2024.1 Chapter 3: Functions and Libraries 68
‘y’ or ‘n’ question
char yes_or_no(void)
{
char answer = ‘X’;
while(answer != ‘y’ && answer != ‘n’)
{
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
}
return answer;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 69
Implementation without loop
char yes_or_no(void)
{
char answer;
printf (“Please enter ‘y’ or ‘n’:”);
scanf (“%c”, &answer);
if(answer != ‘y’ && answer != ‘n’)
answer = yes_or_no( );
return answer;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 70
Loop and Recursion
Any algorithm using loop can be replaced by recursion
and vice versa
In some languages, recursion is the only choice
Some algorithms are represented as recursion naturally:
It is not effective if employing recursive function for simple
algorithms/application
© HĐC 2024.1 Chapter 3: Functions and Libraries 71
When to use recursion
Some cases, the problem can be solved by transforming
to simple cases
Continuously carrying out transformation until a simple
operation which is not recursive is obtained
© HĐC 2024.1 Chapter 3: Functions and Libraries 72
3.5.2 Towers of Hanoi
Tower of Hanoi is a mathematical puzzle where we have
3 rods (towers) and n disks.
The objective is to move all the disks to another rod,
Rules to be followed:
1) Only one disk can be moved at a time.
2) Only the "top" disk can be removed
3) No disk may be placed on top of a smaller disk.
1
2
3
A B C
© HĐC 2024.1 Chapter 3: Functions and Libraries 73
Towers of Hanoi
Following is an animated representation of solving a
Tower of Hanoi puzzle with three disks.
Tower of Hanoi puzzle with n disks can be solved in
minimum 2n−1 steps. This presentation shows that a
puzzle with 3 disks has taken 23 - 1 = 7 steps.
Assume that we have 64 disks, if time taken to move 1
disk is t [seconds]
Total required time is:
Let :
1 1
2 2 1
13 31 2
A B C
© HĐC 2024.1 Chapter 3: Functions and Libraries 74
Towers of Hanoi
#include <stdio.h>
void PrintMovePlate(int n,char X,char Y)
{
printf("\nMove disk %d from tower %c to tower %c",n,X,Y);
}
Move n disks from
void HanoiTower(int n,char X,char Y,char Z) tower X to tower Z by
{ using Y as an
if (n>0) intermediate tower
{
HanoiTower(n-1,X,Z,Y);
PrintMovePlate(n,X,Z); (1) Move (n-1) disks from tower X to
HanoiTower(n-1,Y,X,Z); tower Y by using Z as an intermediate
} tower as the top disks are smaller
} (2) Move disk n (the largest) from X to Z
(3) Repeat the procedure for the
void main(void)
{ remaining n-1 disks in tower Y to Z with
HanoiTower(25,'A','B','C'); the intermediate tower X
return ;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 75
3.5.3 Micromouse
© HĐC 2024.1 Chapter 3: Functions and Libraries 76
Example
/* ‘F’ means finished!
‘X’ means blocked
0
‘ ’ means ok to move */
1
char maze[MAXX][MAXY]; 2
/* start in yellow */ 3
int x =0, y=0;
y 4
Unless it finds the obstacle, 5
robot can move up, down, 6
left, right 7
8
Problem: does a route to the 9 F
destination exist? 0 1 2 3 4 5 6 7
x
© HĐC 2024.1 Chapter 3: Functions and Libraries 77
Simple cases
Assume that robot is at the position (x,y)
if maze[x][y] == ‘F’
0
o then “yes!”
1
if no place to go
o then “no!”
2
3
4
y
5
6
7
8
9 a F
0 1 2 3 4 5 6 7
x
© HĐC 2024.1 Chapter 3: Functions and Libraries 78
Make it simpler
0 0
It is not necessary to go 1 1
through a cell twice 2 2
3 3
4 4 ...
0 5 5
1 6 6
2 7 7
3 8 8
9 F 9 F
4 or
5 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
6
7 0
8 1
9 F 2
0 1 2 3 4 5 6 7 3
4
5
...
6
7
8
9 F
0 1 2 3 4 5 6 7
© HĐC 2024.1 Chapter 3: Functions and Libraries 79
Supporting function
/* Returns true if <x,y> is a legal move
given the maze, otherwise returns false */
int legal_mv (char m[MAXX ][MAXY], int x, int y)
{
return(x >= 0 && x <= MAXX && y >= 0 &&
y <= MAXY && m[x][y] != ‘X’);
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 80
An elegant solution
/* Returns true if there is a path from <x,y> to an
element of maze containing ‘F’ otherwise returns
false */
int is_path (char m[MAXX][MAXY ], int x, int y) {
if (m [x][y] == ‘F’)
return(TRUE);
else {
m[x][y] = ‘X’;
return((legal_mv(m,x+1,y) && is_path(m,x+1,y)) ||
(legal_mv(m,x-1,y) && is_path(m,x-1,y)) ||
(legal_mv(m,x,y-1) && is_path(m,x,y-1)) ||
(legal_mv(m,x,y+1) && is_path(m,x,y+1)))
}
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 81
Example
is_path(maze, 7, 8)
x 7
y 8
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
© HĐC 2024.1 Chapter 3: Functions and Libraries 82
Example
is_path(maze, 7, 8)
x 7
y 7
is_path(maze, 7, 7)
0
1
2
3
4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
© HĐC 2024.1 Chapter 3: Functions and Libraries 83
Example
is_path(maze, 7, 8)
x 7
y 9
is_path(maze, 7, 7)
0
1
2
3
is_path(maze, 7, 9) 4
5
6
7
8
9 F
0 1 2 3 4 5 6 7
© HĐC 2024.1 Chapter 3: Functions and Libraries 84
Recursion summary
Recursion is one of the programming techniques
Its principle is based on the manner that a function is called and
local variables are used in C
Every time, a function is called, everything has its new copy
It is also an approach to solve problems
It would take time and effort to master this
technique
Recursion is a natural way to work with a number
of data structures
© HĐC 2024.1 Chapter 3: Functions and Libraries 85
3.6 ANSI-C standard library
Input/output: <stdio.h>
Character and string processing <string.h>, <ctype.h>
Mathematical operations <math.h>, <float.h>
Time, date <time.h>, <locale.h>
Dynamic memory allocation <stdlib.h>
Wide char funtions <wchar.h>, <wctype.h>
Other functions <assert.h>, <threads.h>, ...
https://www.cplusplus.com/reference/
https://devdocs.io/cpp/io/c
© HĐC 2024.1 Chapter 3: Functions and Libraries 86
3.6.1 Time/date
GPS data example (Global Positioning System Fix Data)
$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
123519 Fix taken at 12:35:19 UTC
Log file data
C:\Program Files (x86)\EaseUS\Todo Backup\Agent.exe
2017-07-10 17:35:16 [M:00,T/P:1940/6300] Init Log
2017-07-10 17:35:16 [M:29,T/P:1940/6300] Ldq : Agent start install!
2017-07-10 17:35:16 [M:29,T/P:1940/6300] Ldq : Agent call CreateService!
2017-07-10 17:35:16 [M:29,T/P:1940/6300] Ldq : Agent call CreateService is success!
© HĐC 2024.1 Chapter 3: Functions and Libraries 87
Time related functions in C
© HĐC 2024.1 Chapter 3: Functions and Libraries 88
Make time function
#include <time.h>
#include <stdio.h>
int main(void) {
struct tm str_time;
time_t time_of_day;
str_time.tm_year = 2012-1900;
str_time.tm_mon = 6;
str_time.tm_mday = 5;
str_time.tm_hour = 10;
str_time.tm_min = 3;
str_time.tm_sec = 5;
str_time.tm_isdst = 0;
time_of_day = mktime(&str_time); // return the calendar-time
printf(ctime(&time_of_day)); // a string of the form day month year
hours:minutes:seconds year\n\0.
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 89
Time zone
#include <stdio.h>
#include <time.h>
#define PST (-8)
#define CET (1)
int main () {
time_t raw_time;
struct tm *ptr_ts;
time ( &raw_time );
ptr_ts = gmtime ( &raw_time );
printf ("Time Los Angeles: %2d:%02d\n",
ptr_ts->tm_hour+PST, ptr_ts->tm_min);
printf ("Time Amsterdam: %2d:%02d\n",
ptr_ts->tm_hour+CET, ptr_ts->tm_min);
printf ("Time Hanoi: %2d:%02d\n",
ptr_ts->tm_hour+ 7, ptr_ts->tm_min);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 90
Measure time taken in C?
#include <stdio.h> // The main function calls fun() and
// measures time taken by fun()
#include <time.h> // for sleep()
int main()
{
// A function that terminates // calculate the time
// when enter key is pressed // taken by fun()
clock_t t;
void fun() { t = clock();
printf("fun() starts at \n"); fun();
t = clock() - t;
printf("Press enter to stop fun \n"); double time_taken =
while(1){ ((double)t)/CLOCKS_PER_SEC;
// in seconds
if (getchar())
break; printf("fun() took %f seconds to e
xecute \n", time_taken);
}
printf("fun() ends \n"); return 0;
}
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 91
Second approach
#include <stdio.h>
#include <time.h>
#include <unistd.h>
//main function to find the execute time of a C program
int main() {
time_t begin = time(NULL);
// do some stuff here
sleep(3);
time_t end = time(NULL);
// calculate elapsed time by finding
// difference (end - begin)
printf("time elapsed is %d seconds", (end-begin));
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 92
Third approach
#include <stdio.h>
#include <time.h> struct timespec {
#include <sys/time.h> time_t tv_sec; /* whole seconds >0*/
long tv_nsec; /* nano seconds */
int main () { }
struct timespec start, finish;
clock_gettime(CLOCK_REALTIME, &start);
// chew up some CPU time
int i,j;
for (i=0,j=0; i<100000000; i++) { j+=i*i; }
clock_gettime(CLOCK_REALTIME, &finish);
long seconds = finish.tv_sec - start.tv_sec;
long ns = finish.tv_nsec - start.tv_nsec;
if (start.tv_nsec > finish.tv_nsec) { // clock underflow
--seconds;
ns += 1000000000;
}
printf("seconds without ns: %ld\n", seconds);
printf("nanoseconds: %ld\n", ns);
printf("total seconds: %e\n",
(double)seconds + (double)ns/(double)1000000000);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 93
3.6.2 Random number
int rand(void);
Return a random number within 0 and RAND_MAX
(inclusive)
RAND_MAX: 32767.
void srand( unsigned seed );
Seed value of an array created, usually start whenever rand is
called
© HĐC 2024.1 Chapter 3: Functions and Libraries 94
Example of rand/srand number
// C program to generate random numbers
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
int main(void)
{
// This program will create different sequence
// of random numbers on every program run
// Use current time as seed for random
// generator
srand(time(0));
for(int i = 0; i<5; i++)
printf(" %d ", rand());
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 95
3.6.3 String - Revision
Constant character: put within ‘’
‘a’, ‘A’, ‘0’, ‘\n’, ‘ ’, ‘i’, ‘l’ , ‘\0’
Constant character array or string: put within “”
“Bill” the null character
“Mary had a little %c%c%c%c. \n”
Character variables:
char va = ‘l’, vb = ‘a’, vc = ‘m’, vd = ‘b’;
printf(“Mary had a little
%c%c%c%c.\n”,va,vb,vc,vd);
© HĐC 2024.1 Chapter 3: Functions and Libraries 96
String or character array
String: an array of character
char pet[5] = {‘l’, ‘a’, ‘m’, ‘b’, ‘\0’};
printf(“Mary had a little %s.\n”, pet);
More precise definition: A character array terminates
with a null character (the last element is ‘\0’)
pet: ‘l’ ‘a’ ‘m’ ‘b’ ‘\0’
pet[0] pet[4]
String is not a data type in C
Developer must be sure that the terminated character is
null, i.e. ‘\0’
© HĐC 2024.1 Chapter 3: Functions and Libraries 97
Initialization
char pet[5] = {‘l’, ‘a’, ‘m’, ‘b’, ‘\0’};
char pet[5];
pet[0] = ‘l’; pet[1] = ‘a’; pet[2] = ‘m’; Equavalent
pet[3] = ‘b’; pet[4] = ‘\0’;
char pet[5] = “lamb”;
char pet[ ] = “lamb”;
Do not use:
char pet[5];
pet = “lamb”; /* No array assignment in C */
Do not use assign statement to initialize a string in C
© HĐC 2024.1 Chapter 3: Functions and Libraries 98
Can and cannot do with strings
Cannot
Use = operator to assign a string to another string (strcpy
function in the library should be used instead)
Use == operator to compare 2 strings directly (strcmp function
in the library should be used instead)
Define a function in which a returning value is a string
Can
Input/output a string by using printf and scanf (the specifier is
%s)
© HĐC 2024.1 Chapter 3: Functions and Libraries 99
Self-assign strings
char str1[10], str2[ ] = “Saturday”;
int i;
/* can’t do: str1 = str2; */
/* can do: */
i = 0;
while (str2[i] != ‘\0’) {
str1[i] = str2[i];
i = i + 1;
}
str1[i] = ‘\0’;
© HĐC 2024.1 Chapter 3: Functions and Libraries 100
strcpy function
/* strcpy is defined in string.h:
copy source string into dest, stop with
\0 */
void strcpy(char dest[ ], char source[ ])
{
int i = 0;
while (source[i] != ‘\0’) {
dest[i] = source[i];
i = i + 1;
}
dest[i] = ‘\0’ ;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 101
The risks
#include <string.h>
...
char medium[ ] = “Four score and seven”;
char big[1000];
char small[5];
strcpy(big, medium);
strcpy(big, “Bob”);
strcpy(small, big);
strcpy(small, medium);
/* looks like trouble... */
© HĐC 2024.1 Chapter 3: Functions and Libraries 102
The results when using strcpy
medium: Four score and seven\0
big: Four score and seven\0?????...
big: Bob\0 score and seven\0?????...
small: Bob\0?
small: Four score and seven\0
© HĐC 2024.1 Chapter 3: Functions and Libraries 103
Find out length of a string with strlen
/* return the length of string s, i.e.,
number of characters before terminating
'\0‘,
or equivalently, index of first '\0'.
*/
int strlen(char s[ ])
{
int n = 0;
while (s[n] != ‘\0’)
n = n + 1 ;
return (n) ;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 104
Example of string length
#include <string.h> /* defn of strlen, strcpy */
...
char pet[ ] = “lamb”;
int len1, len2, len3, len4, len5;
0 1 2 3 4 5 6
len1 = strlen(pet); l a m b \0
len2 = strlen(“wolf”); w o l f \0
len3 = strlen(“”); \0
len4 = strlen(“Help\n”); H e l p \n \0
strcpy(pet, “cat”);
len5 = strlen(pet); c a t \0 \0
© HĐC 2024.1 Chapter 3: Functions and Libraries 105
Concatenate two strings
#include <string.h>
...
char str1[ ] = “lamb”, str2[ ] = “chop”;
char str3[11];
strcpy(str3, str1);
strcat(str3, str2);
/* strcat(s1, s2)
make a copy of s2 at the end of s1. */
© HĐC 2024.1 Chapter 3: Functions and Libraries 106
Results when using strcat
str1 l a m b \0
str2 c h o p \0
str3 ? ? ? ? ? ? ? ? ? ? ?
str3 l a m b \0 ? ? ? ? ? ?
str3 l a m b c h o p \0 ? ?
© HĐC 2024.1 Chapter 3: Functions and Libraries 107
Compare two strings
String str_1 is considered to be smaller than str_2 if
j is the first positions in the strings which consist of different
values
and str_1[j] < str_2[j]
“lamb” is less than “wolf” j = 0, ‘l’ < ‘w’
“lamb” is less than “lamp” j = 3, ‘b’ < ‘p’
“lamb” is less than “lambch” j = 4, ‘\0’ < ‘c’
© HĐC 2024.1 Chapter 3: Functions and Libraries 108
Errors with string comparison
str1 = str2; // Syntax “error”
if (str1 == str2)... No syntax error
(but almost surely a logic error)
if (str1 < str2)... Likewise
© HĐC 2024.1 Chapter 3: Functions and Libraries 109
String comparing function
/* function strcmp in <string.h> */
int strcmp(char str_1[], char str_2[]);
Returning an integer which is
Negative if str_1 < str_2
0 if str_1 = str_2
Positive if str_1 > str_2
Common error
if (!strcmp(str1, str2))...
means “if they ARE equal”
© HĐC 2024.1 Chapter 3: Functions and Libraries 110
String input/output
scanf with the specifier “%s”
Ignore space character at the beginning
Insert null character ‘\0’ into the next position
Risk: no verification of string length
char in_string[10];
scanStatus = scanf(“%s”, in_string);
printf with the specifier “%s”
Not use &
© HĐC 2024.1 Chapter 3: Functions and Libraries 111
Read a line of characters
char line[LENGTH + 1];
int i, scanStatus;
/* read input characters into line until end of
input line reached or all available space in
line used */
i = 0;
scanStatus = scanf(“%c”, &line[i]);
while (1 == scanStatus && i < LENGTH &&
line[i-1] != ‘\n’) {
i++;
scanStatus = scanf(“%c”, &line[i]);
}
line [i] = ‘\0’; /* is this a bug? */
© HĐC 2024.1 Chapter 3: Functions and Libraries 112
Array of string
char month[12][10] = {
“January”,
“February”,
...
“September”, /* longest month: 9 letters */
...
“December” };
...
printf(“%s is hot\n”, month[7]); /* August */
© HĐC 2024.1 Chapter 3: Functions and Libraries 113
Example of string input/output
char name[NUM_NAMES][MAX_NAME + 1];
int age[NUM_NAMES], i;
for (i = 0; i < NUM_NAMES; i = i + 1)
{
scanf(“%s %d”, name[i], &age[i]);
printf(“%s %d \n”, name[i], age[i]);
© HĐC 2024.1 Chapter 3: Functions and Libraries 114
Many functions in <string.h>
Developer should use functions in string.h libraray
when working with strings
strcat, strncat concatentate
strcmp, strncmp compare
strtod, strtol, strtoul convert
Related useful functions in <ctype.h>
Operation with a single character
Convert character, check character type, etc.
© HĐC 2024.1 Chapter 3: Functions and Libraries 115
3.7 Files in C/C++
File is a set of data recorded in memory storage such as
harddisk
Managed by users and operating system (OS)
Stored in long-term
File name is a name used to uniquely identify a
computer file by users and OS
It follows naming rule 8.3 in DOS
© HĐC 2024.1 Chapter 3: Functions and Libraries 116
Why do we need files?
Large amount of input/output data
Storing data in long-term
Transfer data to different programs
Input/output streams are simultaneous
© HĐC 2024.1 Chapter 3: Functions and Libraries 117
File I/O
C language has a close relationship with UNIX OS
Most of C libraries follows UNIX I/O model which
considers all data streams as files
Keyboard, screen, serial ports, GPIO are all accessed via
writing/reading files
Provide a common interface for all I/O
© HĐC 2024.1 Chapter 3: Functions and Libraries 118
Revision of files for compilation
Source files
.c file: programs and functions in C
.h file: header files
Actual projects may contain hundreds *.c and *.h files
Compiled file (name and extension depend on systems)
Object files: files have been compiled and waiting for linking
Library files: set of functions have been pre-compiled
Executable files: machine code files have been linked and is
ready to be executed in computer memory
© HĐC 2024.1 Chapter 3: Functions and Libraries 119
Header file (*.h)
Header files are used to include
Type definition (using typedef)
Function declaration
stdio.h hw.c vector.h vector.c
Constants declaration
Global variable declaration
compiler compiler
ANSI lib
linker
other libs
.exe file
© HĐC 2024.1 Chapter 3: Functions and Libraries 120
Library
Files consist of functions which have been built and
compiled
Reduce system dependency
Reuse existing source code
Enhance portability
Standard
ANSI C Libraries
MSCV local libraries
libraries
© HĐC 2024.1 Chapter 3: Functions and Libraries 121
Input/output data stream with file
Keyboard / Screen are special cases of input/output data
stream (as character arrays)
error\n
abc12 12
program
hx119 8s
variables 12, 13, 13
Multiple streams are existing at the same time
In fact, a buffer is used for data stream instead of
working directly with variables
© HĐC 2024.1 Chapter 3: Functions and Libraries 122
File stdio.h
Input/output function declaration
Define useful constants
E.g. EOF
Define FILE structure to represent file information used
in C programs
File variables in C are pointers which point to FILE structure
FILE *myfile;
© HĐC 2024.1 Chapter 3: Functions and Libraries 123
Open a file
Open a file: create a link between the OS (filename) and
the C program (file variable)
Function in the library: fopen
Identify parameters “r” to read the file and “w” to write to the
file
o Attention: it must be “r” not ‘r’
File must be opened before being used
File stdin/stdout (used by scanf/printf) is opened
automatically and linked to the keyboard and screen
respectively
© HĐC 2024.1 Chapter 3: Functions and Libraries 124
Example: opening file
/*usually done only once in a program*/
/*usually done near beginning of program*/
FILE *infilep, *outfilep; /*file variables*/
char ch;
/* Open input and output files */
infilep = fopen(“Student_Data”, “r”);
outfilep = fopen(“New_Student_Data”, “w”);
© HĐC 2024.1 Chapter 3: Functions and Libraries 125
Example: closing file
Usually done once in the program
Usually perform at the end of the program
All the data file must be closed otherwise data will be
lost
FILE *infilep; /*file variable*/
...
infilep = fopen(“Student_Data”, “r”);
.../*process the file */
.../*when completely done with the file:*/
fclose(infilep);
© HĐC 2024.1 Chapter 3: Functions and Libraries 126
End of file
Defined in stdio.h
#define EOF (a certain negative value)
Usually -1
Input/output functions in the library use EOF to indicate the end
of file
Programs can also use EOF
Attention: EOF is the state, not an input value
© HĐC 2024.1 Chapter 3: Functions and Libraries 127
Basic file input/output functions
fopen and fclose: as mentioned in previous slides
fscanf: is similar to scanf, however the first
argument is a file variable
status = fscanf(filepi, “%...”, &var,...);
/* fscanf returns EOF on end of file */
fprintf: the same as printf, however the first
argument is a file variable
fprintf(filepo, “%...”, var,...);
File must be opened before calling fscanf or
fprintf
© HĐC 2024.1 Chapter 3: Functions and Libraries 128
Operations with files
Once the file is opened, all the operations with it are
performed from the beginning to the end of file
4 basis methods to work with file
Character by character
Line by line
Formatted I/O
Binary I/O
© HĐC 2024.1 Chapter 3: Functions and Libraries 129
Write characters
Functions to write character:
int fputc(int c, FILE *fp);
int putc(int c, FILE *fp);
int putchar(int c);
putchar(c) is similar to putc(c, stdout).
putc() and fputc() are the same
Returning value
If succeed, characters are written into the file
If fail: EOF
© HĐC 2024.1 Chapter 3: Functions and Libraries 130
Read characters
Read character functions:
int fgetc(FILE *fp);
int getc(FILE *fp);
int getchar(void);
getchar() is similar to getc(stdin).
getc() and fgetc() are the same
Returning value
If succeed: the next character in the stream
If fail: EOF.
If end of file: EOF.
To differentiate EOF, one can call feof() or ferror().
A character can be pushed back to the stream by using ungetc().
int ungetc(int c, FILE *fp);
© HĐC 2024.1 Chapter 3: Functions and Libraries 131
Read a line
Read a line by
char *fgets(char *buf, int max, FILE *fp);
Operations
Read maximum of (max-1) characters from a file
Also read \n character
Check both end of file and error
Returning value:
If succeed: a pointer points to buf. Note that fgets() automatically adds
\0 to the end of the string
If it is the last line of the file: NULL
If error: NULL.
Use feof() and ferror() to identify the error
© HĐC 2024.1 Chapter 3: Functions and Libraries 132
Write a line
A character array can be written to a file with
int fputs(const char *str, FILE *fp);
Character \n can be added by developer
Return value
If succeed: zero
Otherwise: EOF.
© HĐC 2024.1 Chapter 3: Functions and Libraries 133
Formating I/O
int fprintf(FILE *fp, const char *format, ...);
int fscanf(FILE *fp, const char *format, ...);
Similar to printf() and scanf()
printf() and scanf() can be written as
fprintf(stdout, format, arg1, arg2, );
fscanf(stdin, format, arg1, arg2, );
© HĐC 2024.1 Chapter 3: Functions and Libraries 134
Binary I/O
When reading and writing a binary file, the program
does work with the object directly instead of converting
this object into a character array
Binary I/O includes:
size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);
In order to write structures to a file
struct Astruct mystruct[10];
fwrite(&mystruct, sizeof(Astruct), 10, fp);
© HĐC 2024.1 Chapter 3: Functions and Libraries 135
Other operations with file
C provides other functions to work with file without
accessing it in sequence
3 basic functions
long ftell(FILE *fp); // current file position of the
// specified stream
int fseek(FILE *fp, long offset, int from);
void rewind(FILE *fp);
© HĐC 2024.1 Chapter 3: Functions and Libraries 136
Building application with file
By using fopen, fclose, fscanf and fprintf,
developers can write many applications related to file
Many errors and exceptions can occur when working
with files
A robust application must handle the errors well
The skills will be acquired gradually
© HĐC 2024.1 Chapter 3: Functions and Libraries 137
Example: copy file
/* Problem: copy an input file to an output
file */
/* Technique: loop, copying one char at a time
until EOF, files must already be open before
this */
status = fscanf(infilep, “%c”, &ch);
while (status != EOF) {
fprintf(outfilep, “%c”, ch);
status = fscanf(infilep, “%c”, &ch);
}
printf(“File copied.\n”);
fclose(infilep);
fclose(outfilep);
© HĐC 2024.1 Chapter 3: Functions and Libraries 138
Example: copy file
/* Many C programmers use this style */
...
while (fscanf(infilep, “%c”, &ch) != EOF)
fprintf(outfilep, “%c”, ch);
printf(“File copied.\n”);
fclose(infilep);
fclose(outfilep);
© HĐC 2024.1 Chapter 3: Functions and Libraries 139
Example: query database
#include <stdio.h>
int main(void) {
FILE *inp, *outp;
int age, j;
char name[20], ssn[9], ch;
inp = fopen(“db_file”, “r” ); Equivalent query in SQL
outp = fopen(“result_file”, “w”); database language:
/* loop till the end-of-file */
while (fscanf(inp, “%c”, &name[0]) != EOF) {
/* read name, ssn, age */ SELECT NAME, SSN
for (j = 1; j < 20; j++)
fscanf(inp, “%c”, &name[j]); FROM DB_FILE
for (j = 0; j < 9; j++) WHERE AGE > 20;
fscanf(inp, “%c”,&ssn[j]);
fscanf(inp, “%d”, &age);
/* read line feed character */
fscanf(inp, “%c”, &ch);
/* copy name, ssn to output if age > 20 */
if (age > 20) {
for (j = 0; j < 20; j++)
fprintf(outp, “%c”, name[j]);
for (j = 0; j < 9; j++)
fprintf(outp, “%c, ssn[j]);
fprintf(outp, ”\n”);
}
}
fclose(inp); fclose(outp);
return (0);
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 140
Example: extend tab
#include <stdio.h>
int main(void) {
FILE *infilep, *outfilep;
char ch; Input: a b \t c
int column = 0; d \t e f
/* Open input and output files */
infilep = fopen(“prog.c”, “r”); Output: a b c
outfilep = fopen(“tabless-prog.c”, “w”); d ef
/* process each input character */
while (fscanf(infilep, “%c”, &ch) != EOF){
if (ch == ‘\n’ || ch == ‘\r’) {
/* end of line: reset column counter */
column = 0;
fprintf(outfilep, “%c”, ch);
} else if (ch == ‘\t’) {
/* tab: output one or more spaces, */
/* to reach the next multiple of 8. */
do {
fprintf(outfilep, “%c”, ‘ ‘) ;
column++;
} while ((column % 8) != 0);
} else {
/* all others: count it, and copy it out */
column ++;
fprintf(outfilep, “%c”, ch);
}
}
fclose(infilep); fclose(outfilep);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 141
Example: append file to another
#include <stdio.h>
#define MAXLINE 10000 /*ASSUMES no line longer*/
int main(void) {
FILE *in1p, * in2p, *outp;
char buffer1[MAXLINE], buffer2[MAXLINE];
char *stat1, *stat2;
in1p = fopen(“sorted-file1”, “r”);
in2p = fopen(“sorted-file2”, “r”);
outp = fopen(“merged-file”, “w”);
stat1 = fgets(buffer1, MAXLINE, in1p);
stat2 = fgets(buffer2, MAXLINE, in2p);
while (stat1 != NULL && stat2 != NULL) {
if (strcmp(buffer1, buffer2) < 0) {
fprintf(outp, “%s”, buffer1);
stat1 = fgets(buffer1, MAXLINE, in1p);
} else {
fprintf(outp, “%s”, buffer2);
stat2 = fgets(buffer2, MAXLINE, in2p);
}
}
while (stat1 != NULL) {
fprintf(outp, “%s”, buffer1);
stat1 = fgets(buffer1, MAXLINE, in1p);
}
while (stat2 != NULL) {
fprintf(outp, “%s”, buffer2);
stat2 = fgets(buffer2, MAXLINE, in2p);
}
fclose(in1p); fclose(in2p); fclose(outp);
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 142
Files in C++
#include <iostream.h>
#include <fstream.h>
Define a variable:
ifstream fin; // input
ofstream fout; // output
fstream fio; // input and output
Open/create a file:
fin.open("file1.txt");
fout.open("file2.dat");
fio.open("file3.inf");
Declare variables and open/create a file together
ifstream fin("file1.txt"); // input
ofstream fout("file2.inf");// output
fstream fio("file3.dat"); // input and output
© HĐC 2024.1 Chapter 3: Functions and Libraries 143
Files in C++
Write data into a file
Similar to cout
A file may contain mixed data types, e.g.:
fout << "Nguyen Van A" << endl;
fout << 21 << endl<< false;
Read data from a file
Similar to cin
char name[32];
int age, married;
fin.getline(name,32);
fin >> age >> married;
Close a file
Automatically performs when a scope ends
Or call close();
fin.close();
fout.close();
fio.close();
© HĐC 2024.1 Chapter 3: Functions and Libraries 144
Example: working with files
#include <iostream.h>
#include <fstream.h>
void main() {
{
ofstream fout("file1.dat");// output
fout << "Nguyen Van A" << endl << 21 << endl << false;
}
{
ifstream fin("file1.dat"); // input
char name[32];
int age;
int married;
fin.getline(name,32);
fin >> age >> married;
cout << "Name:\t" << name << endl;
cout << "Age:\t" << age << endl;
cout << "Married:" << (married ? "Yes" : "No");
}
char c;
cin >> c;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 145
Data transfer
Temperature: 25.28 Humidity: 87 Power 111.4W
© HĐC 2024.1 Chapter 3: Functions and Libraries 146
Sscanf/Sprintf
© HĐC 2024.1 Chapter 3: Functions and Libraries 147
3.8 Function overloading in C++
In C++, it is possible to create multiple functions with
the same name, e.g.:
int max(int a, int b);
double max(double a, double b);
double max(double a, double b, double c);
double max(double* seq, int n);
The purposes of function overloading is
Simplify function naming (instead of maxInt, maxDouble,
maxDouble3, maxDoubleSequence, …)
Make it easy for function users who need to remember only one
familiar name
© HĐC 2024.1 Chapter 3: Functions and Libraries 148
Examle: usage of max() functions
int max(int a, int b) { // (1)
return (a > b)? a : b;
}
double max(double a, double b) { // (2)
return (a > b)? a : b;
}
double max(double a, double b, double c) { // (3)
if (a < b) a = b;
if (a < c) a = c;
return a;
}
double max(double *seq, int n) { // (4)
int i = 0, kq= seq[0];
while (i < n) {
if (kq< seq[i]) kq= seq[i];
++i;
}
return kq;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 149
Examle: usage of max() functions
int max(int a, int b); // (1)
double max(double a, double b); // (2)
double max(double a, double b, double c); // (3)
double max(double* seq, int n); // (4)
void main() {
int k = max(5,7); // call (1)
double d = max(5.0,7.0); // call (2)
double a[] = {1,2,3,4,5,6};
d = max(d, a[1], a[2]); // call (3)
d = max(a, 5); // call (4)
d = max(5,7); // ?
d = max(d, 5); // ?
}
It is the compiler’s responsibility to verify and chose the right
function amongst those with the same name!
© HĐC 2024.1 Chapter 3: Functions and Libraries 150
Example 2:
int plusFuncInt(int x, int y) { int plusFunc(int x, int y) {
return x + y; return x + y;
} }
double plusFuncDouble(double x,
double plusFunc(double x, double y)
double y) {
return x + y; {
} return x + y;
}
int main() {
int myNum1 = plusFuncInt(8, 5); int main() {
double myNum2 = int myNum1 = plusFunc(8, 5);
plusFuncDouble(4.3, 6.26); double myNum2 =
cout << "Int: "<< myNum1 <<"\n"; plusFunc(4.3, 6.26);
cout << "Double: " << myNum2;
cout << "Int: " << myNum1<< "\n";
return 0;
} cout << "Double: " << myNum2;
return 0;
}
© HĐC 2024.1 Chapter 3: Functions and Libraries 151
Principles of function overloading
Functions with the same name defined in one file / a
library or used in the same program must be different in:
Number of arguments or
Type of at least one argument (int short, const
int int, int int&, ...)
They cannot be different only in type of returning value
Why?
Compiler need to decide which functions to call
Based on call syntax (number and type of actual arguments)
compiler will choose the most suitable functions
Compile can convert type automatically in the most reasonable
manner (e.g.: short=>int, int=> double)
© HĐC 2024.1 Chapter 3: Functions and Libraries 152
3.9 inline function in C++
Problem: a normal function is useful but not very high
efficient, especially if the implementation code is short
The procedure of recording program states, allocating memory,
copying arguments, copying returning values, recovering the
program states consume too much time
If the function code is short, the usefulness cannot compensate for
large time consuming
Solution in C: Using macro, e.g.
#define max(a,b) a>b?a:b
Problem: macro is executed by preprocessor, type is not checked,
program cannot differentiate used context thus, it results in
undesired effects.
E.g.: the statement l=max(k*5-2,l);
is replaced by l=k*5-2>l?k*5-2:l; //OOPS
The method of using bracket even make the code harder to read
while cannot solve the weakness completely
© HĐC 2024.1 Chapter 3: Functions and Libraries 153
inline function in C++
Put the keyword inline at the beginning of function
declaration and definition
inline int max(int a, int b) {
return (a > b)? a : b;
}
It is different from normal function as:
“Inline function” is not really a function
When inline function is called, the call is substituted by the source
code defining the function, it does not carry out function call
procedures
E.g.:
l=max(k*5-2,1);
Is replaced by
int x=k*5-2; // temporary variable
l=(x>1)?x:1; // OK
© HĐC 2024.1 Chapter 3: Functions and Libraries 154
When to use inline
Advantages:
Useful as a normal function
As efficient as direct source code, not calling function
More reliable and safer than using Macro
Disadvantages:
If the function is called too many times in the program, the
source code will grow bigger (implementation code appears
multiple times in the program)
Function definition code must be open keep in header file
Create and use inline function when
Implementation code of the function is short (just a few line, no
loop)
Speed is the priority rather than memory capacity
© HĐC 2024.1 Chapter 3: Functions and Libraries 155
END OF CHAPTER 3