EE3491/EE3490E –
Kỹ thuật lập trình /
Programming Techniques
Chapter 5: Program
design & efficiency
Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính)
Department of Industrial Automation
School of Electrical Engineering
Email:
[email protected] © DIA 2022.2
Program design and efficiency
“Designing object-oriented software is hard, and designing
reusable object-oriented software is even harder...It takes a long
time for novices to learn what object-oriented design is all about.
Experienced designers evidently know something inexperienced
ones don't...
One thing expert designers know not to do is solve every
problem from first principles. Rather, they reuse solutions that
have worked for them in the past. When they find a good
solution, they use it again and again. Such experience is part of
what makes them experts. Consequently, you'll find recurring
patterns of classes and communicating objects in many object-
oriented systems. These patterns solve specific design problems
and make object-oriented design more flexible, elegant, and
ultimately reusable...”
Erich Gamma et. al.: Design Patterns: Elements of Reusable Object-
Oriented Software, Addison-Wesley, 1995.
Chapter 5: Program design & efficiency © DIA 2022.2 2
Content
5.1. Program design process revision
5.2. Code optimization
5.3. Good habits in programming
5.4. Event-driven programming
Chapter 5: Program design & efficiency © DIA 2022.2 3
5.1. Program design process
Analysis Design Programming
Analyse the problem
Propose a big-picture/generic solution
Functions are divided together with a diagram illustrating
function call diagram
Design each specific function
These functions depends only existing low level (basic)
functions if applicable
Finally, it’s the coding task
Chapter 5: Program design & efficiency © DIA 2022.2 4
Define function features
Find common aspects
Parameterize distinguish features
Specify which functions are called by the one being
designed
Draw a diagram to illustrate the relationship between the
functions
Chapter 5: Program design & efficiency © DIA 2022.2 5
Design steps
Requirements and technical specifications
Data flow of the program
Data structure
Top-down or bottom-up approaches
Write the source code
Debug and test
Design is not a sequential process but performed with
complete steps one by one
Chapter 5: Program design & efficiency © DIA 2022.2 6
Requirements and technical
specifications
Requirements:
what are the main objectives of the program
requirements must be clear but do not need to be detailed
Technical specifications: describe specifications of the
program in details
E.g.: format, response of the program, memory constraint
Technical specifications can be extended subsequently
as the program is developed
Chapter 5: Program design & efficiency © DIA 2022.2 7
Data flow
Draw a diagram of the main features
Sequence of the functions, loops, …
Two main diagrams: design and state-transition
diagrams
Goals: clear vision of
Main components and operations of the software
How the transition among these components happens
Relationship amongst program components
Chapter 5: Program design & efficiency © DIA 2022.2 8
Example: flowchart diagram
START
statements
statements
conditional
FALSE
TRUE
statements
END
Chapter 5: Program design & efficiency © DIA 2022.2 9
Data structure
Decide which type of data structure to be used mainly
in the program and exchanged amongst program
components
The data structure would be identified in the design
diagram of the software
Chapter 5: Program design & efficiency © DIA 2022.2 10
Format design
Two approaches (revised): top-down and bottom-up
Propose a set of function but not the detailed
implementation
Describe the program in written language or pseudo-
code
loop number of times
prompt user and get integer value
calculate factorial
print factorial
Then replace each component by the respective C
function
Chapter 5: Program design & efficiency © DIA 2022.2 11
Example: Game of Tic-Tac-Toe
Requirements:
Enable user to play tic-tac-toe game with computer (placing X
and O)
Allow user to choose if they want to play first or computer
starts first
Ask if user wants to play again once the game finishes
Chapter 5: Program design & efficiency © DIA 2022.2 12
Description
Welcome message:
Welcome to TIC-TAC-TOE.
-----------------------
The object of this game is to get a line of X's
before the computer gets a line of O's. A line may
be across, down, or diagonal.
Play area is illustrated with 1 – 9 as the followings:
1|2|3
-----
4|5|6
-----
7|8|9
Chapter 5: Program design & efficiency © DIA 2022.2 13
Description
The user plays first:
Do you wish to go first (1-Yes, 0-No) ?
The user select position by choosing the number:
Your turn (1 - 9):
Display the game layout after each step
X| |
-----
X|O|
-----
|X|O
Chapter 5: Program design & efficiency © DIA 2022.2 14
Description
Print out the final result:
You win. Congratulations!!
You lose. Better luck next time.
Its a draw. How dull.
Ask if the user want to continue?
Do you wish to play again (1-Yes, 0-No) ?
Chapter 5: Program design & efficiency © DIA 2022.2 15
5.2 Code optimization
Efficient Programs
Selecting the algorithm
Developer should use the best applicable algorithm
Then considering the efficiency of the code
E.g.: Calculating the summation of n continuous integer
starting at m
void main() { void main()
long n,m,i , sum ; {
cout << ‘ Enter n ‘ ; cin << n; long n,m , sum ;
cout << ‘ Enter m ‘ ; cin << m; cout << ‘ Enter n ‘ ; cin << n;
sum =0; cout << ‘ Enter m ‘ ; cin << m;
for(i = m ; i < = m+n; i++) sum =(m + m+ n) * n / 2;
sum += i; cout << ‘ Sum = ‘ <<sum;
cout << ‘ Sum = ‘ <<sum; }
}
Chapter 5: Program design & efficiency © DIA 2022.2 16
Utilizing the compiler flags
Some compilers play a very important role in
optimizing the program
They analyse the source code deeply and perform all the
possible tasks “machinely”
E.g.: GNU g++ compiler in Linux/Cygwin used for a C
program
g++ –O5 –o myprog myprog.c
The above compiler command can improve the efficiency by
10% to 300%
Chapter 5: Program design & efficiency © DIA 2022.2 17
But …
There may be still room improvement which cannot be
done by the compiler
Inappropriate parts of the code should be removed
Increase the efficiency as high as possible
Need to relook at the program when it runs slowly
How to achieve fast and best enhancement?
Chapter 5: Program design & efficiency © DIA 2022.2 18
Writing Efficient Code
Identify the cause of inefficiency
Redundant computation, especially
In procedures
Loops
Chapter 5: Program design & efficiency © DIA 2022.2 19
Initialize once, use multiple times
Before float f()
{ double value = sin(0.25);
//
…..
}
double defaultValue = sin(0.25);
After
float f()
{ double value =
defaultValue;
//
…..
}
Chapter 5: Program design & efficiency © DIA 2022.2 20
Static Variables
Type of data refers to global or 'static' variables, memory is
allocated during compile-time
int int_array[100];
int main() {
static float float_array[100];
double double_array[100];
char *pchar;
pchar = (char *)malloc(100);
/* .... */
return (0);
}
Chapter 5: Program design & efficiency © DIA 2022.2 21
Static Variables
Variables declared in functions are allocated memory when the functions are
called, they will be deleted (memory is freed) when the functions complete
They are reallocated memory and re-initialized when the functions are called
again
If it is required to reserve a value until the program finishes, the local variable
should be declared as static one and initialized with a value
The initialization is done once when the function is called and the value changed is stored for
subsequent calls
Using this method, the function can “memorize” a few pieces of information after each call
Using Static variable instead of Global one:
The advantage of a static variable is that it is the local one in a function,
thus side effects can be avoided
Chapter 5: Program design & efficiency © DIA 2022.2 22
Stack, heap revisions
Data segment of a program contains 3 parts:
static, stack, and heap data.
Static: global or static variables
Stack data:
Local variables of a function, e.g. double_array in the previous
example
Heap data:
Memory of the data is allocated dynamically, e.g. pchar in the previous
example
The data is presented until it is freed or the program ends
Chapter 5: Program design & efficiency © DIA 2022.2 23
Macros revisions
#define max(a,b) (a>b?a:b)
Inline are the same as macros as they are performed at
compile-time
Macros are carried out by preprocessors, and inline functions are
inserted by compiler
However, there are some differences:
Inline functions follows the procedures as a normal function
Inline functions use the same syntax as a normal function, except the
keyword inline in the declaration
Operations passed as arguments in inline functions are used once. In
some cases, operations passed as arguments in macros can be used
more than once.
It is impossible to debug macros, but it can be done for inline
functions
Chapter 5: Program design & efficiency © DIA 2022.2 24
Remove ordinary expressions
Do not perform an expression multiple times!
Some compilers can recognize and process
for (i = 1; i<=10;i++)
x += strlen(str);
Y = 15 + strlen(str);
len = strlen(str);
for (i = 1;i<=10;i++)
x += len;
Y = 15 + len;
Chapter 5: Program design & efficiency © DIA 2022.2 25
Move constant expressions out of the
loops
Do not repeat unnecessary expressions
Some Compilers can process automatically!
for (i =0; i<100;i++)
plot(i, i*sin(d));
M = sin(d);
for (i =0; i<100;i++)
plot(i, i*M);
Chapter 5: Program design & efficiency © DIA 2022.2 26
Reduce computation time
In Neural Network simulation, a
function named sigmoid is often 1
sigmoid ( x)
used 1 e kx
If x is a large positive number
sigmoid(x) 1
If x is a large negative number
sigmoid (x) 0
Chapter 5: Program design & efficiency © DIA 2022.2 27
sigmoid function
float sigmoid (float x )
{
return 1.0 / (1.0 + exp(-x))
};
Chapter 5: Program design & efficiency © DIA 2022.2 28
sigmoid function
Calculation of exp(-x) is very time-consuming!
It is usually computed approximately by using series expansion
Taylor/Maclaurin formula
Calculate the sum of ((-x)n / n!)
Each of this expression requires to work with floating point numbers
In many cases, neural network simulation call the function
hundred millions times for each run
Thus, the time taken to compute sigmoid(x) is very large (70-
80% of total running duration)
Chapter 5: Program design & efficiency © DIA 2022.2 29
sigmoid function – a solution
Instead of calling the function all the time x0 sigmoid(x0)
Calculating with N points and save to an array x1 sigmoid(x1)
x2 sigmoid(x2)
In each call of sigmoid:
x3 sigmoid(x3)
• Find the nearest value of x and its respected result
x4 sigmoid(x4)
• Perform linear interpolation to find the final result
x5 sigmoid(x5)
x6 sigmoid(x6)
.
.
.
x99 sigmoid(x99)
Chapter 5: Program design & efficiency © DIA 2022.2 30
sigmoid function – a solution
Choose the number of points (N = 1000, 10000, etc.)
depending on the desired accuracy
Memory resource required for each point is 2 float or
double, i.e. 8 – 16 bytes/point
Initialize values for the array at the beginning of the
procedure
Chapter 5: Program design & efficiency © DIA 2022.2 31
sigmoid function – a solution
X0 is known
Compute Delta = X1-X0
Comput Xmax = X0 + N * Delta;
With a given X
Compute i = (X – X0)/Delta;
• Which needs a substation of two real numbers and a division of real
numbers
Comput sigmoid(x)
• Which needs a multiplication of floats and a addition of floats
Chapter 5: Program design & efficiency © DIA 2022.2 32
Result
If using exp(x) :
Each call takes 300 nanoseconds on a computer equipped with
a Pentium 4, 2 Ghz CPU.
If using array searching and linear interpolation:
Each call takes 30 nanoseconds
The speed increase 10 times
The tradeoff is the increment of required memory space from
64KBytes to 640 KBytes
Chapter 5: Program design & efficiency © DIA 2022.2 33
Basis rules
Code Simplification
Most of the programs which can run fast are simple. Thus,
developer should simplify the source code to make it run fast.
Problem Simplification
To improve the program efficiency, the developer should
simplify the problem to solve
Relentless Suspicion
One should question the necessary of each code block and each
field/property in data structure
Early Binding
Carry out the task immediately to avoid redoing multiple times
later
Chapter 5: Program design & efficiency © DIA 2022.2 34
Loop Rules
Hot spots in most of the programs are caused by loops
Move the code out of the loop
Instead of performing computation in each iteration of the loop,
it should happen once outside the loop if applicable
Loop fusion:
If two loops perform a similar task on the same set of elements,
they should be integrated into one loop
Chapter 5: Program design & efficiency © DIA 2022.2 35
Optimize the following code
found = FALSE;
for(i=0;i<10000;i++) {
if( list[i] == -99 ) {
found = TRUE;
}
}
if( found ) printf("Yes, there is a -
99. !\n");
Chapter 5: Program design & efficiency © DIA 2022.2 36
5.3. Good habits in programming
“It is not enough for code to
work.”
… Robert C. Martin, Clean Code: A Handbook of Agile
Software Craftsmanship
Chapter 5: Program design & efficiency © DIA 2022.2 37
5.3.1 Good programming style
1. Write clearly / don't be too clever
2. Say what you mean, simply and directly
3. Use library functions whenever feasible
4. Avoid too many temporary variables
5. Write clearly / don't sacrifice clarity for efficiency
Chapter 5: Program design & efficiency © DIA 2022.2 38
Good programming style
6. Let the machine do the dirty work
7. Replace repetitive expressions by calls to common
functions
8. Parenthesize to avoid ambiguity
9. Choose variable names that won't be confused
10. Avoid unnecessary branches
11. If a logical expression is hard to understand, try
transforming it
12. Choose a data representation that makes the
program simple
Chapter 5: Program design & efficiency © DIA 2022.2 39
Good programming style
13. Write first in easy-to-understand pseudo
language; then translate into whatever language
you have to use
14. Modularize. Use procedures and functions
15. Avoid gotos completely if you can keep the
program readable
16. Don't patch bad code / rewrite it
17. Write and test a big program in small pieces
Chapter 5: Program design & efficiency © DIA 2022.2 40
Good programming style
18. Use recursive procedures for recursively-defined
data structures
19. Test input for plausibility and validity
20. Make sure input doesn't violate the limits of the
program
21. Terminate input by end-of-file marker, not by
count
22. Identify bad input; recover if possible
23. Make input easy to prepare and output self-
explanatory
Chapter 5: Program design & efficiency © DIA 2022.2 41
Good programming style
24. Use uniform input formats
25. Make sure all variable are initialized before use
26. Test programs at their boundary values
26. Check some answers by hand
27. 10.0 times 0.1 is hardly ever 1.0
28. 7/8 is zero while 7.0/8.0 is not zero
29. Make it right before you make it faster
Chapter 5: Program design & efficiency © DIA 2022.2 42
Good programming style
30. Make it clear before you make it faster
31. Let your compiler do the simple optimizations
32. Don't strain to re-use code; reorganize instead
33. Make sure special cases are truly special
34. Keep it simple to make it faster
35. Make sure comments and code agree
36. Don't comment bad code | rewrite it
37. Use variable names that mean something
38. Format a program to help the reader understand
it
39. Don't over-comment
Chapter 5: Program design & efficiency © DIA 2022.2 43
5.3.2 Program Style
Why is the program style important?
Errors are usually due to developers’ mistakes
• What is the use of a variable?
• How is a function called?
Good code = code which is easy to read
How to make the code easy to read?
Program structure must be neat and easy to understand
Use popular terms
Select suitable and self-described names
Write clear and comprehensive comments
Use module
Chapter 5: Program design & efficiency © DIA 2022.2 44
Structure: “Paragraphs”
Use blank line to differentiate blocks/paragraphs
#include <stdio.h>
#include <stdlib.h>
int main(void)
/* Read a circle's radius from stdin, and compute and write its
diameter and circumference to stdout. Return 0 if successful. */
{
const double PI = 3.14159;
int radius;
int diam;
double circum;
printf("Enter the circle's radius:\n");
if (scanf("%d", &radius) != 1)
{
fprintf(stderr, "Error: Not a number\n");
exit(EXIT_FAILURE); /* or: return EXIT_FAILURE; */
}
…
Chapter 5: Program design & efficiency © DIA 2022.2 45
Structure: Expressions
Write expression in original format
E.g.: Verify if n satisfies that j < n < k
Bad code
if (!(n >= k) && !(n <= j))
Good code
if ((j < n) && (n < k))
Conditional expressions should be written in such a
way that you can read normally
Do not write the conditional expressions in a form that you
never use
Chapter 5: Program design & efficiency © DIA 2022.2 46
Structure: Expressions (cont.)
Use () to avoid confusion
E.g.: Verify if n satisfies that j < n < k
Moderately bad code
if (j < n && n < k)
Moderately better code
if ((j < n) && (n < k))
Groups should be classified clearly
Relation operators (e.g.: “>”) has the higher priority than logic
operators (e.g.: “&&”), but who can remember that?
Chapter 5: Program design & efficiency © DIA 2022.2 47
Structure: Expressions (cont.)
Use () to avoid confusion
E.g.: reand and print the characters till the end of file
Wrong code (what is going on???)
while (c = getchar() != EOF)
putchar(c);
Right code
while ((c = getchar()) != EOF)
putchar(c);
Groups should be classified clearly:explicit
Logic operator (“!=”) has the higher priority than assignment
operator (“=”)
Chapter 5: Program design & efficiency © DIA 2022.2 48
Structure: Expressions (cont.)
Simplify complicated expressions
E.g.: Identify the characters with respect to the months in a
year
Bad code
if ((c == 'J') || (c == 'F') || (c ==
'M') || (c == 'A') || (c == 'S') || (c
== 'O') || (c == 'N') || (c == 'D'))
Good code
if ((c == 'J') || (c == 'F') ||
(c == 'M') || (c == 'A') ||
(c == 'S') || (c == 'O') ||
(c == 'N') || (c == 'D'))
Should organize parallel expressions!
Chapter 5: Program design & efficiency © DIA 2022.2 49
Spaces
Should use blank line to separate the main code block
Align vertically
x = 5;
y_prime = 7;
z_axis = 4.3;
Leave spaces around the operators
No: y=slope*x+intercept;
Yes: y = slope * x + intercept;
Use () to emphasize
Yes: y = (slope * x) + intercept;
Justify minor parts of the code
Chapter 5: Program design & efficiency © DIA 2022.2 50
Naming (revised)
Name
Letters, digits and underscore (_)
Cannot start with a digit
Cannot be C/C++ keywords such as double, return
Differentiate UPPERCASE and lowercase text
VAR, Var, var, vAr are treated differently
It is valid to use all uppercase letters
However, all uppercase text are used in #define statement (will
be discussed) conventionally
Chapter 5: Program design & efficiency © DIA 2022.2 51
Naming (revised)
Precious material
Microsoft Excel has more than 65.000 variables
How long should the name be?
m
mph
miles_per_hour
average_miles_per_hour_that_the_car_went
Avoid similar names, e.g.: mph vs. Mph vs. mqh
Chapter 5: Program design & efficiency © DIA 2022.2 52
Naming (revised)
OK Invalid Valid, but …
rectangleWidth 10TimesLength a1
rectangle_Width My Variable l
rectangle_width int O
length_10_Rectangle rectangleWidth and
rectanglewidth or
rectangle_Width
Chapter 5: Program design & efficiency © DIA 2022.2 53
Purity
Use familiar methods for familiar problems
No: x = (y = x) + 1;
Yes: y = x;
x = x + 1;
It is note required to be concise or complicated without
proper reasons. If it is, specific explanation should be
provided
Chapter 5: Program design & efficiency © DIA 2022.2 54
#define
NO = sign NO ;
Naming the constant:
#define PI 3.14159265
#define AVOGADRO 6.02e23
#define LINE_WIDTH 80
#define FIELD_WIDTH 10
#define FIELDS_PER_LINE LINE_WIDTH / FIELD_WIDTH)
...
area = PI * radius * radius;
lines = fields / FIELDS_PER_LINE;
Attention!
yes UPPER CASE
yes ( )
Chapter 5: Program design & efficiency © DIA 2022.2 55
Why to use #define?
Convenient to modify and maintain
No strange numbers (without explanation)
Use names with emotion
Avoid typos
Avoid assignment to constants
double pi; vs.
pi = 3.14; #define PI 3.14
... ...
pi = 17.2; PI = 17.2; syntax error
Chapter 5: Program design & efficiency © DIA 2022.2 56
Function Comments
Describe necessary information to call a function
precisely
Describe what a function does, not how it does
The code itself must be clear, easy to understand how it
operates…
If not, write the comments inside function definition
Describe inputs: input arguments, files to read, global
variables to use
Describe outputs: returning value, output arguments,
files to write, global variables affected
Chapter 5: Program design & efficiency © DIA 2022.2 57
/* Comments */
/*************************************************
Explanation at * Program: Mi_To_Km
the beginning * Purpose: Miles to kilometers conversion
of the code * Author: A. Hacker, 1/18/00 Section AF (Turing)
*************************************************/
/* Calculate volume of cylinder and ...
Explanation of
* Inputs: radius, height, ...
the main code
* Output: volume, ...
block
* Assumes: radius, height nonnegative */
.
.
Sparsely
.
individual
/* Tell user it’s negative. */
explanation
Chapter 5: Program design & efficiency © DIA 2022.2 58
/* Comments */
Tell the cause, not description
Should not:
/* subtract one from sheep */
sheep = sheep - 1;
Should:
/* account for the sheep that
the big bad wolf just ate */
sheep = sheep - 1;
Chapter 5: Program design & efficiency © DIA 2022.2 59
/* Comments */ for documentation
/**
* A brief history of JavaDoc-style (C-style) comments.
*
* This is the typical JavaDoc-style C-style comment. It starts with two
* asterisks.
*
* @param theory Even if there is only one possible unified theory. it is just a
* set of rules and equations.
*/
void cstyle( int theory );
Chapter 5: Program design & efficiency © DIA 2022.2 60
/* Comments */ for documentation
/*******************************************************************************
* A brief history of JavaDoc-style (C-style) banner comments.
*
* This is the typical JavaDoc-style C-style "banner" comment. It starts with
* a forward slash followed by some number, n, of asterisks, where n > 2. It's
* written this way to be more "visible" to developers who are reading the
* source code.
*
* Often, developers are unaware that this is not (by default) a valid Doxygen
* comment block!
*
* However, as long as JAVADOC_BLOCK = YES is added to the Doxyfile, it will
* work as expected.
*
* This style of commenting behaves well with clang-format.
*
* @param theory Even if there is only one possible unified theory. it is just a
* set of rules and equations.
******************************************************************************/
void javadocBanner( int theory );
Chapter 5: Program design & efficiency © DIA 2022.2 61
/* Comments */ for documentation
/***************************************************************************/
/**
* A brief history of Doxygen-style banner comments.
*
* This is a Doxygen-style C-style "banner" comment. It starts with a "normal"
* comment and is then converted to a "special" comment block near the end of
* the first line. It is written this way to be more "visible" to developers
* who are reading the source code.
* This style of commenting behaves poorly with clang-format.
*
* @param theory Even if there is only one possible unified theory. it is just a
* set of rules and equations.
******************************************************************************/
void doxygenBanner( int theory );
Chapter 5: Program design & efficiency © DIA 2022.2 62
Programming style
A program is a document:
Computer read it partially
Human read it completely
Donald Knuth: “literate programming”
Programming style is a term useful to developers and
related to:
Comments, spaces, indentation, name
Understandable, straightforward, elegant code
Code quality
Usually present a good design
Chapter 5: Program design & efficiency © DIA 2022.2 63
Example
/* Convert miles per hour to feet per second
* Author:...
* Date: ...
*/
#include <stdio.h>
/* conversion constants. */
#define FEET_PER_MILE 5280.0
#define SECONDS_PER_HOUR (60.0 * 60.0)
int main(void)
{
double miles_per_hour; /* input mph */
double feet_per_second; /* corresponding feet/sec */
double feet_per_hour; /* corresponding feet/hr */
/* prompt user for input */
printf(“Enter a number of miles per hour: ”);
scanf(“%lf”, &miles_per_hour);
/* convert from miles per hour to feet per second */
feet_per_hour = miles_per_hour * FEET_PER_MILE;
feet_per_second = feet_per_hour / SECONDS_PER_HOUR;
/* format and print results */
printf(“%f miles per hour is equal to %f feet per ”
“second.\n”, miles_per_hour, feet_per_second);
return(0);
}
Chapter 5: Program design & efficiency © DIA 2022.2 64
Small things big impact
#include<stdio.h>
int main(void){double v1,v2,v3,v4,v5;pr\
intf(“Enter a number of miles per hour:\
”);scanf(“%lf”,&v1);v5=v1*14.6666667;pr\
intf(“%f miles per hour is equal to %f \
feet per second.\n”,v1,v5);return(0);}
Chapter 5: Program design & efficiency © DIA 2022.2 65
5.3.3 Error handling – Error code
Developers often need a mechanism to indicate that the
function can't accomplish its work because of some kind of
error.
It might be invalid, an unexpected result being received from a
peripheral device, or a resource allocation issue.
One of the most traditional and widespread ways to report
an error condition is through error codes.
This is an efficient and ubiquitous mechanism that does not depend
on the programming language or the operating system.
Due to its efficiency, versatility, and ability to cross various platform
boundaries, it is highly used in embedded software development.
Designing a function interface that returns either a value or
an error code may be tricky, especially if the value and the
error code have different types.
Chapter 5: Program design & efficiency © DIA 2022.2 66
fprintf revise
Prototype:
int fprintf ( FILE * stream,
const char * format, ... );
Return Value:
On success, the total number of characters written is returned.
If a writing error occurs, the error indicator (ferror) is set and a
negative number is returned.
If a multibyte character encoding error occurs while writing wide
characters, errno is set to EILSEQ and a negative number is
returned.
errno is a macro of type int indicating “Last error
number”
Chapter 5: Program design & efficiency © DIA 2022.2 67
fprintf revise
#include <stdio.h>
#include <errno.h>
#include <string.h>
extern int errno ;
int main () {
FILE * pf;
int errnum;
pf = fopen ("unexist.txt", "rb");
if (pf == NULL) {
errnum = errno;
fprintf(stderr, "Value of errno: %d\n", errno);
perror("Error printed by perror");
fprintf(stderr, "Error opening file: %s\n", strerror( errnum ));
} else {
fclose (pf);
}
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 68
Error code examples
// first implementation
#include <iostream>
int Receive(int input, std::string& output) {
if (input < 0) {
return -1;
}
output = "Hello";
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 69
Error code examples
// second implementation
#include <iostream>
std::string Receive(int input, int& error) {
if (input < 0) {
error = -1;
return "";
}
error = 0;
return "Hello";
}
Chapter 5: Program design & efficiency © DIA 2022.2 70
Error code examples
// third second implementation
std::pair<int, std::string> Receive(int input){
std::pair<int, std::string> result;
if (input < 0) {
result.first = -1;
} else {
result.second = "Hello";
}
return result;
}
Chapter 5: Program design & efficiency © DIA 2022.2 71
Error code examples
void Display(const char* prefix, int err, const std::string& result) {
if (err < 0) {
std::cout << prefix << " error: " << err << std::endl;
} else {
std::cout << prefix << " result: " << result << std::endl;
}
}
void Test(int input) {
std::string outputResult;
int err = Receive(input, outputResult);
Display(" Receive 1", err, outputResult);
int outputErr = -1;
std::string result = Receive(input, outputErr);
Display(" Receive 2", outputErr, result);
std::pair<int, std::string> ret = Receive(input);
Display(" Receive 3", ret.first, ret.second);
}
Chapter 5: Program design & efficiency © DIA 2022.2 72
Error code examples
int main() {
std::cout << "Input: -1" <<
std::endl;
Test(-1);
std::cout << "Input: 1" << std::endl;
Test(1);
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 73
5.3.4 Exception handling
C++ offers another mechanism for error handling, called
exceptions.
Exceptions aim to simplify error handling and make it more
reliable. It help to avoid lots of if-else constructs when using
error code which makes the function logic more obscure.
When using exceptions, developers do not need to check for
errors after every function invocation. Exceptions propagate
through the call stack automatically, until they reach the code
that can handle it properly by logging, retrying, or terminating
the application.
While exceptions are the default error handling mechanism of the
C++ standard library, communicating with peripheral devices or
the underlying operating system layer still involves error codes.
Chapter 5: Program design & efficiency © DIA 2022.2 74
Exception handling statements
try {
// Block of code to try
throw exception; // Throw an
exception when a problem arise
}
catch () {
// Block of code to handle errors
}
Chapter 5: Program design & efficiency © DIA 2022.2 75
Exception handling example 1
try {
int age = 15;
if (age > 18) {
cout << "Access granted - you are old enough.";
} else {
throw (age);
}
}
catch (int myNum) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Age is: " << myNum;
}
Chapter 5: Program design & efficiency © DIA 2022.2 76
Exception handling example 1
try {
int age = 15;
if (age > 18) {
cout << "Access granted - you are old enough.";
} else {
throw 505;
}
}
catch (int myNum) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Error number: " << myNum;
}
Chapter 5: Program design & efficiency © DIA 2022.2 77
Exception handling example 1
try {
int age = 15;
if (age > 18) {
cout << "Access granted - you are old enough.";
} else {
throw 505;
}
}
catch (. . .) {
cout << "Access denied - You must be at least 18 years old.\n";
cout << "Error number: " << myNum;
}
Chapter 5: Program design & efficiency © DIA 2022.2 78
Exception handling example 2
#include <iostream>
#include <system_error>
#include <fcntl.h>
#include <unistd.h>
class Device
{
int fd;
public:
Device(const std::string &deviceName) {
fd = open(deviceName.c_str(), O_RDWR);
if (fd < 0) {
throw std::system_error(errno, std::system_category(),
"Failed to open device file");
}
}
~Device() {
close(fd);
}
// continue in next slide …
Chapter 5: Program design & efficiency © DIA 2022.2 79
Exception handling example 2
// continue from previous slides
void Send(const std::string &data) {
size_t offset = 0;
size_t len = data.size();
while (offset < data.size() - 1) {
int sent = write(fd, data.data() + offset, data.size() -
offset);
if (sent < 0) {
throw std::system_error(errno,
std::system_category(),
"Failed to send data");
}
offset += sent;
}
}
};
Chapter 5: Program design & efficiency © DIA 2022.2 80
Exception handling example 2
int main() {
try {
Device serial("/dev/ttyUSB0");
// change to “COMx”, e.g. “COM2” in Windows
serial.Send("Hello");
}
catch (std::system_error &e) {
std::cout << "Error: " << e.what() << std::endl;
std::cout << "Code: " << e.code() << " means \"“
<< e.code().message()
<< "\"" << std::endl;
}
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 81
5.4 Event-driven programming
Event-driven programming is a programming paradigm
in which the flow of the program is determined by
events such as
Starting the program, initializing variables
Stepping in a loop, waiting for a command or an event
occurring such as mouse clicks, key presses, sensor outputs, or
messages from other programs or threads, timer stop
Event handling subroutines/functions
Getting back to the loop and wait for subsequent
events/commands
Embedded software also follows this paradigm
Chapter 5: Program design & efficiency © DIA 2022.2 82
Example
Read “command” from keyboard and perform
corresponding tasks
Inputs: character from keyboard
a: execute “command A” via function A_handler()
b: execute “command B” via function B_handler()
q: exit the software
Pseudo code of the main loop
Wait for the next command
If a, execute command A
If b, execute command B
If q, exit
Chapter 5: Program design & efficiency © DIA 2022.2 83
Loop control scheme
Repeat until stopping condition matches
Use variable done to verify stopping condition
set done to false
while not done
body statements
if quit command, set done to true
Chapter 5: Program design & efficiency © DIA 2022.2 84
Source code
#define FALSE 0
#define TRUE 1
int main(void) {
char command;
int done;
done = FALSE;
while (!done) {
command = ReadCommand( );
/* Input command from user */
switch (command) {
case ‘a’: A_handler(); /* Execute command A */
break;
case ‘b’: B_handler(); /* Execute command B */
break;
case ‘q’: done = TRUE; /* quit */
break;
default: printf(“Unrecognized command\n”);
}
}
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 85
Multithreading
Multithreading is a specialized form of multitasking
which allows the computer to run two or more tasks
concurrently
Two types of multitasking:
Process-based multitasking handles the concurrent execution of
programs.
Thread-based multitasking deals with the concurrent execution
of pieces of the same program.
A multithreaded program contains two or more parts
that can run concurrently. Each part of such a program
is called a thread, and each thread defines a separate
path of execution.
Chapter 5: Program design & efficiency © DIA 2022.2 86
Multithreading
Image courtesy: https://en.wikipedia.org/wiki/Thread_(computing)#/media/File:Multithreaded_process.svg
Chapter 5: Program design & efficiency © DIA 2022.2 87
Multithreading
Chapter 5: Program design & efficiency © DIA 2022.2 88
Function call within a thread
1. Using The Function Object
/</em>/ Define the class for function object
class functionObject_class {
// Overload () operator
void operator()(params)
{
// code to be executed
}
};
// Cr
Chapter 5: Program design & efficiency © DIA 2022.2 89
Function call within a thread
2. Using Function Pointer
void funct_call(params){
//code to be executed
}
std::thread thread_obj(funct_call, params);
Chapter 5: Program design & efficiency © DIA 2022.2 90
Function call within a thread
3. Using A Lambda Expression
// Define a lambda expression
auto f = [](params) {
// code for execution
};
std::thread thread_object(f, params);
Chapter 5: Program design & efficiency © DIA 2022.2 91
Example
#include <iostream> int main() {
#include <thread> // Define a Lambda Expression
using namespace std; auto f = [](int n) {
// function to be used in callable for (int i = 0; i < n; i++)
void func_dummy(int N) { cout << "Thread 3 :: callable => lambda
for (int i = 0; i < N; i++) { expression\n";
cout << "Thread 1 :: callable => };
function pointer\n"; //launch thread using function pointer as
} callable
} thread th1(func_dummy, 2);
// A callable object // launch thread using function object as
class thread_obj { callable
public: thread th2(thread_obj(), 2);
void operator()(int n) { //launch thread using lambda expression
for (int i = 0; i < n; i++) as callable
cout << "Thread 2 :: callable => thread th3(f, 2);
function object\n"; // Wait for thread t1 to finish
} th1.join();
}; // Wait for thread t2 to finish
th2.join();
// Wait for thread t3 to finish
th3.join();
return 0;
}
Chapter 5: Program design & efficiency © DIA 2022.2 92
END OF CHAPTER 5
Chapter 5: Program design & efficiency © DIA 2022.2 93