EE3491/EE3490E – Kỹ thuật lập trình / Programming Techniques Chapter 3: Functions and Libraries Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính) Department of Industrial Automation School of Electrical Engineering © HDC 2022.1 Email: chinh.hoangduc@hust.edu.vn 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++ Chapter 3: Functions and Libraries © DIA 2022.1 2 3.1 Functions and Functional programming Structure programming is based on two approaches: Function-oriented programming, sometimes called taskoriented or procedure-oriented programming T_1 Tasks T_2 T_1a T_2a T_1b T_2b T_2c T_3 T_3 Data-oriented programming Data 1 D_1 Data 2 Data 3 Chapter 3: Functions and Libraries D_2 D_3 © DIA 2022.1 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 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 Chapter 3: Functions and Libraries © DIA 2022.1 4 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: • Ask the user to provide • Assign the value to a variable Read the second integer: • Ask the user to provide • Assign the value to a variable Calculate the summation using a loop statement Print the result on the screen Chapter 3: Functions and Libraries © DIA 2022.1 5 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'); } Chapter 3: Functions and Libraries © DIA 2022.1 6 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'); } Chapter 3: Functions and Libraries © DIA 2022.1 7 Functional programming approach 1 int ReadInt() { cout << "Enter an integer number: "; int N; cin >> N; return N; } No argument. Difficult to reuse??? OK. Can’t be better! int SumInt(int a, int b) { int Total = 0; for (int i = a; i <= b; ++i) Total += i; return Total; Too many arguments. May not be effective? } void WriteResult(int a, int b, int kq) { cout << "The sum from " << a << " to " << b << " is " << kq << endl; } Chapter 3: Functions and Libraries © DIA 2022.1 8 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! Chapter 3: Functions and Libraries © DIA 2022.1 9 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'); } Chapter 3: Functions and Libraries © DIA 2022.1 10 Functional programming approach 2 int ReadInt(const char* userPrompt) { cout << userPrompt; int N; cin >> N; return N; OK. Looks better! } int SumInt(int a, int b) { int Total = 0; for (int i = a; i <= b; ++i) Total += i; return Total; } Chapter 3: Functions and Libraries © DIA 2022.1 11 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 Chapter 3: Functions and Libraries © DIA 2022.1 12 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 ; area1 = 3.14 * x ; return( area1 ); } Chapter 3: Functions and Libraries © DIA 2022.1 Argument Local variables 13 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 /* return a “random” number */ double GenRandom (void) the returning value). GenRandom() is a function of double type or GenRandom() return a double value { double result; function execution result = ... return result; } Local variable, exist during the Returning value Chapter 3: Functions and Libraries Return statement © DIA 2022.1 14 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(“***************”); printf(“***************\n”); } The function has no arguments Why and when do we need to declare a function Chapter 3: Functions and Libraries © DIA 2022.1 15 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 Chapter 3: Functions and Libraries © DIA 2022.1 16 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 int x = 5; int k = SumInt(x,10); Function name Arguments Chapter 3: Functions and Libraries It is not required to define a function when compiling, but its declaration must have been done! © DIA 2022.1 17 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 Chapter 3: Functions and Libraries © DIA 2022.1 18 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,…) Chapter 3: Functions and Libraries © DIA 2022.1 19 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. Chapter 3: Functions and Libraries © DIA 2022.1 20 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) Arguments (Inputs) a b c Fun_A Returning Arguments values / (Inputs) Output parameters d Fun_B e e Returning values / 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 Chapter 3: Functions and Libraries © DIA 2022.1 21 Representative variables and actual parameters int SumInt (int a,int b) { ... } Arguments (representative) int x = 5; Returning value (no name) int k = SumInt(x,10); ... Actual parameters int a = 2; x a k = SumInt(a,x); 10 b SumInt Arguments Chapter 3: Functions and Libraries © DIA 2022.1 k Variable assigned to returning value 22 3.3.1 Passing values int SumInt(int,int); // Function call void main() { int x = 5; int k = SumInt(x,10); ... } SP SP b = 10 a=5 k = 45 x=5 // Function definition int SumInt(int a,int b) { ... } Chapter 3: Functions and Libraries © DIA 2022.1 23 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 Chapter 3: Functions and Libraries © DIA 2022.1 24 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 Chapter 3: Functions and Libraries © DIA 2022.1 25 3.3.2 Passing a pointer int SumInt(int* p, int N); // Function call SP void main() { k = 45 int a[] = {1, 2, 3, 4}; N=4 int k = SumInt(a,4); ... p = 00A0 SP } k = 45 // Function definition a[3] = 4 int SumInt(int* p, int N) { a[2] = 3 int*p2 = p + N, k = 0; a[1] = 2 while (p < p2) k += *p++; return k; 00A0 a[0] = 1 } Chapter 3: Functions and Libraries © DIA 2022.1 26 Passing an array? int SumInt(int p[4], intN); // Function call void main() { int a[] = {1, 2, 3, 4}; int k = SumInt(a,4); ... } Similar to the previous 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; } Chapter 3: Functions and Libraries © DIA 2022.1 27 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) scanf(“%d”, &a[i][j]); } int a[][MAX_HWS] int (*a)[MAX_HWS]: a pointer to an array of 13 integers int *a[MAX_HWS]: an array of 13 pointers to integers Chapter 3: Functions and Libraries © DIA 2022.1 28 2-dimensional array as arguments 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); ... } Chapter 3: Functions and Libraries no & © DIA 2022.1 29 Retry the example of reading from keyboards #include <iostream.h> void ReadInt(constchar* 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) Chapter 3: Functions and Libraries © DIA 2022.1 30 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 Chapter 3: Functions and Libraries © DIA 2022.1 31 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 Chapter 3: Functions and Libraries © DIA 2022.1 32 Example: swap() function #include <iostream.h> void int a = b = swap(int& a, int& b) { temp = a; b; temp; } void main() { int x = 5, y = 10; swap(x,y); cout << "Now x is " << x << ", y is " << y; ... } Chapter 3: Functions and Libraries © DIA 2022.1 33 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; ... } Chapter 3: Functions and Libraries © DIA 2022.1 34 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 Chapter 3: Functions and Libraries © DIA 2022.1 35 Returning mechanism int SumInt(int a,int b){ int k = 0; for (int i=a; i <= b; ++i) k +=i; return k; } SP k >= 45 b = 10 a=5 k = 45 void main() { int x = 5, k = 0; k = SumInt(x,10); ... } Chapter 3: Functions and Libraries x=5 45 © DIA 2022.1 36 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); } Chapter 3: Functions and Libraries © DIA 2022.1 37 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; } Chapter 3: Functions and Libraries © DIA 2022.1 38 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 Chapter 3: Functions and Libraries © DIA 2022.1 39 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 } Chapter 3: Functions and Libraries © DIA 2022.1 40 Some more examples: right/wrong? int* f1(int a) { ... return &a; } int& f2(int &a) { ... return a; } int f3(int &a) { ... return a; } int* f4(int* pa) { ... return pa; } Chapter 3: Functions and Libraries int f5(int* pa) { ... return *pa; } int& f6(int* pa) { ... return *pa; } int& f7(int a) { ... return a; } int *pa; int* f8() { ... return pa; } © DIA 2022.1 41 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; } Chapter 3: Functions and Libraries © DIA 2022.1 42 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}; void subtract(int a, int b) { printf("Subtraction is %d\n", a-b); unsigned int ch, a = 15, b = 10; printf("Enter Choice: 0 for add, 1 for subtract and 2 for multiply\n"); scanf("%d", &ch); } if (ch > 2) void multiply(int a, int b) return 0; { (*fun_ptr_arr[ch])(a, b); printf("Multiplication is %d\n", a*b); } return 0; } Chapter 3: Functions and Libraries © DIA 2022.1 43 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); } Chapter 3: Functions and Libraries © DIA 2022.1 44 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; } Chapter 3: Functions and Libraries © DIA 2022.1 45 Example of Function pointer with Timer // CPP program to create a timer #include <iomanip> #include <iostream> #include <stdlib.h> #include <unistd.h> using namespace std; // hours, minutes, seconds of timer int hours = 0; int minutes = 0; int seconds = 0; void displayClock() { // function to display the timer // system call to clear the screen system("cls"); cout << setfill(' ') << setw(55) << " TIMER \n"; cout << setfill(' ') << setw(55) << " -------------------------\n"; cout cout cout cout cout << << << << << setfill(' ') << setw(29); "| " << setfill('0') << setw(2) << hours << " hrs | "; setfill('0') << setw(2) << minutes << " min | "; setfill('0') << setw(2) << seconds << " sec |" << endl; setfill(' ') << setw(55) << " -------------------------- \n"; } Chapter 3: Functions and Libraries void timer(void (*p)()){ while (true) { p(); // Call back function sleep(1); // sleep for 1 seconds seconds++; // increment seconds // if seconds reaches 60 if (seconds == 60) { // increment minutes minutes++; // if minutes reaches 60 if (minutes == 60) { // increment hours hours++; minutes = 0; } seconds = 0; } } } int main() { void (*p)() = displayClock; // start timer from 00:00:00 timer(p); return 0; } © DIA 2022.1 46 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 Chapter 3: Functions and Libraries © DIA 2022.1 47 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]) Chapter 3: Functions and Libraries © DIA 2022.1 48 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 Chapter 3: Functions and Libraries © DIA 2022.1 49 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 predefined operator symbol such as *, /, +, - instead of function calls Chapter 3: Functions and Libraries © DIA 2022.1 50 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 Chapter 3: Functions and Libraries © DIA 2022.1 51 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: • • • • Read data? NO! Check input variable (N)? Yes/No (E.g., what to do if N < 0) The first k prime number is given, identify the next prime number Store the result at each step to a suitable data structure (the desired array) • Print the output to screen? NO! Chapter 3: Functions and Libraries © DIA 2022.1 52 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! Chapter 3: Functions and Libraries © DIA 2022.1 53 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 Chapter 3: Functions and Libraries © DIA 2022.1 54 Chapter 3: Functions and Libraries © DIA 2022.1 55 Flowchart revision Symbols are defined in ISO 5807:1985 ANSI/ISO Shape Name Flowline (Arrowhead) Terminal Decision Input/Output Predefined Process Annotation (Comment) On-page Connector Off-page Connector Chapter 3: Functions and Libraries © DIA 2022.1 56 3.4.2 Designing a program with multiple functions Top-down design approach Bottom-up design approach Chapter 3: Functions and Libraries © DIA 2022.1 57 Top-down design approach Break down the program into smaller components which links together Design the structure of the program Chapter 3: Functions and Libraries © DIA 2022.1 58 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 Chapter 3: Functions and Libraries © DIA 2022.1 59 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 topdown approach They can be combined into a library C standard library is an example of bottom-up design Chapter 3: Functions and Libraries © DIA 2022.1 60 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 Chapter 3: Functions and Libraries © DIA 2022.1 61 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? • To be discussed Why do we need recursive functions? • We will see the motivations Chapter 3: Functions and Libraries © DIA 2022.1 62 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 { 0! = 1 product = product * i; value 1! = 1 } 2! = 1 * 2 return (product); 3! = 1 * 2 * 3 } ... Chapter 3: Functions and Libraries © DIA 2022.1 63 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; if (n <= 1) t = 1; else t = n * factorial(n - 1); return t; } Chapter 3: Functions and Libraries 0! is 1 1! is 1 n! is n * (n-1)!, for n>1 E.g.: 3! = 3 * 2! = 3 * 2 * 1! =3*2*1 © DIA 2022.1 64 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 • They are allocated memory space once the function is called • The allocated memory is free when exiting the function Arguments are initialized by copying values of the passing variables in function call Chapter 3: Functions and Libraries © DIA 2022.1 65 Factorial function factorial(4) = 4 * factorial(3) = 4 * 3 * factorial(2) = 4 * 3 * 2 * factorial(1) = 4 * 3 * 2 * 1 = 24 Chapter 3: Functions and Libraries © DIA 2022.1 66 ‘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; } Chapter 3: Functions and Libraries © DIA 2022.1 67 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; } Chapter 3: Functions and Libraries © DIA 2022.1 68 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 Chapter 3: Functions and Libraries © DIA 2022.1 69 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 Chapter 3: Functions and Libraries © DIA 2022.1 70 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 Chapter 3: Functions and Libraries B C © DIA 2022.1 71 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 Chapter 3: Functions and Libraries : 1 2 13 1 2 31 1 2 A B C © DIA 2022.1 72 Towers of Hanoi Move n disks from tower X to tower Z by using Y as an intermediate tower (1) Move (n-1) disks from tower X to 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 remaining n-1 disks in tower Y to Z with the intermediate tower X Chapter 3: Functions and Libraries © DIA 2022.1 73 3.5.3 Micromouse Chapter 3: Functions and Libraries © DIA 2022.1 74 Example /* ‘F’ means finished! ‘X’ means blocked ‘ ’ means ok to move */ char maze[MAXX][MAXY]; /* start in yellow */ int x =0, y=0; Unless it finds the obstacle, robot can move up, down, left, right Problem: does a route to the destination exist? Chapter 3: Functions and Libraries 0 1 2 3 y 4 5 6 7 8 9 0 F 1 2 3 4 5 6 7 x © DIA 2022.1 75 Simple cases Assume that robot is at the position (x,y) if maze[x][y] == ‘F’ • then “yes!” if no place to go • then “no!” Chapter 3: Functions and Libraries 0 1 2 3 4 y 5 6 7 8 9 a F 0 1 2 3 4 5 6 7 x © DIA 2022.1 76 Make it simpler It is not necessary to go through a cell twice 0 1 2 3 4 5 6 7 8 9 or F 0 1 2 3 4 5 6 7 Chapter 3: Functions and Libraries 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 F 1 2 3 4 5 6 7 0 0 1 2 3 4 5 6 7 8 9 ... 0 F 1 2 3 4 5 6 7 ... 0 F 1 2 3 4 5 6 7© DIA 2022.1 77 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’); } Chapter 3: Functions and Libraries © DIA 2022.1 78 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))) } } Chapter 3: Functions and Libraries © DIA 2022.1 79 Example is_path(maze, 7, 8) x y 0 1 2 3 4 5 6 7 8 9 Chapter 3: Functions and Libraries © DIA 2022.1 F 0 1 2 3 4 5 6 7 80 Example is_path(maze, 7, 8) x y is_path(maze, 7, 7) 0 1 2 3 4 5 6 7 8 9 Chapter 3: Functions and Libraries © DIA 2022.1 F 0 1 2 3 4 5 6 7 81 Example is_path(maze, 7, 8) x y is_path(maze, 7, 7) is_path(maze, 7, 9) Chapter 3: Functions and Libraries 0 1 2 3 4 5 6 7 8 9 © DIA 2022.1 0 F 1 2 3 4 5 6 7 82 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 Chapter 3: Functions and Libraries © DIA 2022.1 83 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 Chapter 3: Functions and Libraries © DIA 2022.1 84 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! Chapter 3: Functions and Libraries © DIA 2022.1 85 Time related functions in C Chapter 3: Functions and Libraries © DIA 2022.1 86 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; } Chapter 3: Functions and Libraries © DIA 2022.1 87 Time zone #include <stdio.h> #include <time.h> #define PST (-8) #define CET (1) int main () { time_t struct time ( ptr_ts printf raw_time; tm *ptr_ts; &raw_time ); = gmtime ( &raw_time ); ("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; } Chapter 3: Functions and Libraries © DIA 2022.1 88 Measure time taken in C? #include <stdio.h> #include <time.h> // for sleep() // A function that terminates // when enter key is pressed void fun() { printf("fun() starts at \n"); printf("Press enter to stop fun \n"); while(1){ if (getchar()) break; } printf("fun() ends \n"); // The main function calls fun() and m easures time taken by fun() int main() { // calculate the time // taken by fun() clock_t t; t = clock(); fun(); t = clock() - t; double time_taken = ((double)t)/CL OCKS_PER_SEC; // in seconds printf("fun() took %f seconds to e xecute \n", time_taken); return 0; } } Chapter 3: Functions and Libraries © DIA 2022.1 89 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; Chapter 3: Functions and Libraries © DIA 2022.1 90 Third approach struct timespec { #include <stdio.h> time_t tv_sec; /* whole seconds >0*/ #include <time.h> long tv_nsec; /* nano seconds */ #include <sys/time.h> } 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; } Chapter 3: Functions and Libraries © DIA 2022.1 91 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 Chapter 3: Functions and Libraries © DIA 2022.1 92 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; } Chapter 3: Functions and Libraries © DIA 2022.1 93 3.6.3 String - Revision Constant character: put within ‘’ ‘a’, ‘A’, ‘0’, ‘\n’, ‘ ’, ‘i’, ‘l’ , ‘\0’ Constant character array or string: put within “” the null character “Bill” “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); Chapter 3: Functions and Libraries © DIA 2022.1 94 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’ Chapter 3: Functions and Libraries © DIA 2022.1 95 Initialization char pet[5] = {‘l’, ‘a’, ‘m’, ‘b’, ‘\0’}; char pet[5]; pet[0] = ‘l’; pet[1] = ‘a’; pet[2] = ‘m’; pet[3] = ‘b’; pet[4] = ‘\0’; Equavalent 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 Chapter 3: Functions and Libraries © DIA 2022.1 96 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) Chapter 3: Functions and Libraries © DIA 2022.1 97 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’; Chapter 3: Functions and Libraries © DIA 2022.1 98 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’ ; } Chapter 3: Functions and Libraries © DIA 2022.1 99 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... */ Chapter 3: Functions and Libraries © DIA 2022.1 100 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 Chapter 3: Functions and Libraries © DIA 2022.1 101 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) ; } Chapter 3: Functions and Libraries © DIA 2022.1 102 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 Chapter 3: Functions and Libraries © DIA 2022.1 103 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. */ Chapter 3: Functions and Libraries © DIA 2022.1 104 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 ? ? Chapter 3: Functions and Libraries © DIA 2022.1 105 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’ Chapter 3: Functions and Libraries © DIA 2022.1 106 Errors with string comparison str1 = str2; Syntax “error” if (str1 == str2)... No syntax error (but almost surely a logic error) if (str1 < str2)... Likewise Chapter 3: Functions and Libraries © DIA 2022.1 107 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” Chapter 3: Functions and Libraries © DIA 2022.1 108 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 & Chapter 3: Functions and Libraries © DIA 2022.1 109 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? */ Chapter 3: Functions and Libraries © DIA 2022.1 110 Array of string char month[12][10] = { “January”, “February”, ... “September”, /* longest month: 9 letters */ ... “December” }; ... printf(“%s is hot\n”, month[7]); /* August */ Chapter 3: Functions and Libraries © DIA 2022.1 111 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]); } Chapter 3: Functions and Libraries © DIA 2022.1 112 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. Chapter 3: Functions and Libraries © DIA 2022.1 113 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 Chapter 3: Functions and Libraries © DIA 2022.1 114 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 Chapter 3: Functions and Libraries © DIA 2022.1 115 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 Chapter 3: Functions and Libraries © DIA 2022.1 116 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 Chapter 3: Functions and Libraries © DIA 2022.1 117 Header file (*.h) Header files are used to include Type definition (using typedef) Function declaration stdio.h Constants declaration Global variable declaration hw.c vector.h compiler ANSI lib vector.c compiler linker other libs .exe file Chapter 3: Functions and Libraries © DIA 2022.1 118 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 libraries Chapter 3: Functions and Libraries © DIA 2022.1 local libraries 119 Risk with keyboard What happens if user press A key in this situation int score; input buffer scanf(“%d”, &score); A… while (score != 0) { printf(“%d \n”, score); scanf(“%d”, &score); } Chapter 3: Functions and Libraries © DIA 2022.1 120 Returning value of scanf scanf returns an integer that Let the user know input value is entered successfully Be used to verify if all the inputs have been entered; if any input is missing, it should request to continue entering or issue an error int status, id, score; double grade; status = scanf(“%d %lf %d”, &id, &grade, &score); if (status < 3) printf(“Error in input \n”) ; Chapter 3: Functions and Libraries © DIA 2022.1 121 Robust approach /*Robustly read an integer, consuming nondigits*/ int read_int (void) { int status, input; char junk; status = scanf(“%d”, &input); while (status < 1) { /* unsuccessful read */ scanf(“%c”, &junk);/* consume 1 char */ status = scanf(“%d”, &input); /*try again*/ } return (input); } Chapter 3: Functions and Libraries © DIA 2022.1 122 Input/output data stream with file Keyboard / Screen are special cases of input/output data stream (as character arrays) error\n abc12 12 program variables hx119 8s 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 Chapter 3: Functions and Libraries © DIA 2022.1 123 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; Chapter 3: Functions and Libraries © DIA 2022.1 124 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 • 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 Chapter 3: Functions and Libraries © DIA 2022.1 125 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”); Chapter 3: Functions and Libraries © DIA 2022.1 126 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); Chapter 3: Functions and Libraries © DIA 2022.1 127 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 Chapter 3: Functions and Libraries © DIA 2022.1 128 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 Chapter 3: Functions and Libraries © DIA 2022.1 129 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 Chapter 3: Functions and Libraries © DIA 2022.1 130 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 Chapter 3: Functions and Libraries © DIA 2022.1 131 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); Chapter 3: Functions and Libraries © DIA 2022.1 132 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, ); Chapter 3: Functions and Libraries © DIA 2022.1 133 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 Chapter 3: Functions and Libraries © DIA 2022.1 134 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. Chapter 3: Functions and Libraries © DIA 2022.1 135 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); Chapter 3: Functions and Libraries © DIA 2022.1 136 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); Chapter 3: Functions and Libraries © DIA 2022.1 137 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 Chapter 3: Functions and Libraries © DIA 2022.1 138 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); Chapter 3: Functions and Libraries © DIA 2022.1 139 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); Chapter 3: Functions and Libraries © DIA 2022.1 140 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” ); outp = fopen(“result_file”, “w”); /* loop till the end-of-file */ while (fscanf(inp, “%c”, &name[0]) != EOF) { /* read name, ssn, age */ for (j = 1; j < 20; j++) fscanf(inp, “%c”, &name[j]); for (j = 0; j < 9; j++) 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); } Chapter 3: Functions and Libraries Equivalent query in SQL database language: SELECT NAME, SSN FROM DB_FILE WHERE AGE > 20; © DIA 2022.1 141 Example: extend tab #include <stdio.h> int main(void) { FILE *infilep, *outfilep; char ch; int column = 0; /* Open input and output files */ infilep = fopen(“prog.c”, “r”); outfilep = fopen(“tabless-prog.c”, “w”); /* 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; } Chapter 3: Functions and Libraries Input: a b \t c d \t e f Output: a b c d ef © DIA 2022.1 142 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; } Chapter 3: Functions and Libraries © DIA 2022.1 143 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 Chapter 3: Functions and Libraries © DIA 2022.1 144 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(); Chapter 3: Functions and Libraries © DIA 2022.1 145 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; } Chapter 3: Functions and Libraries © DIA 2022.1 146 Data transfer Temperature: 25.28 Humidity: 87 Power 111.4W Chapter 3: Functions and Libraries © DIA 2022.1 147 Sscanf/Sprintf Chapter 3: Functions and Libraries © DIA 2022.1 148 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 Chapter 3: Functions and Libraries © DIA 2022.1 149 Examle: define max() functions int max(inta, int b) { return (a > b)? a : b; } // (1) double max(double a, double b) { return (a > b)? a : b; } // (2) double max(double a, double b, double c) { if (a < b) a = b; if (a < c) a = c; return a; } // (3) double max(double *seq, int n) { inti = 0, kq= seq[0]; while (i < n) { if (kq< seq[i])kq= seq[i]; ++i; } return kq; } // (4) Chapter 3: Functions and Libraries © DIA 2022.1 150 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); double d = max(5.0,7.0); double a[] = {1,2,3,4,5,6}; d = max(d, a[1], a[2]); d = max(a, 5); d = max(5,7); d = max(d, 5); } // call (1) // call (2) // // // // call (3) call (4) ? ? It is the compiler’s responsibility to verify and chose the right function amongst those with the same name! Chapter 3: Functions and Libraries © DIA 2022.1 151 Example 2: int plusFuncInt(int x, int y) { return x + y; } int plusFunc(int x, int y) { return x + y; } double plusFunc(double x, doub double plusFuncDouble(double x le y) { , double y) { return x + y; return x + y; } } int main() { int main() { int myNum1 = plusFunc(8, 5); int myNum1 = double myNum2 = plusFuncInt(8, 5); plusFunc(4.3, 6.26); double myNum2 = cout << "Int: " << myNum1 plusFuncDouble(4.3, 6.26); << "\n"; cout << "Int: " << myNum1 cout << "Double: " << << "\n"; myNum2; cout << "Double: " << return 0; myNum2; } return 0; } Chapter 3: Functions and Libraries © DIA 2022.1 152 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 int, int int&, ...) short, const 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) Chapter 3: Functions and Libraries © DIA 2022.1 153 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 Chapter 3: Functions and Libraries © DIA 2022.1 154 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 Chapter 3: Functions and Libraries © DIA 2022.1 155 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 Chapter 3: Functions and Libraries © DIA 2022.1 156 END OF CHAPTER 3 Chapter 3: Functions and Libraries © DIA 2022.1 157