FEEG6002 - Applied Programming 5 - Tutorial Session Sam Sinayoko 2015-10-30 1 / 38
Outline Objectives Two common bugs General comments on style String formatting Questions? Summary 2 / 38
Objectives Revise code submitted during labs Understand and fix two common bugs Improve style Review string formatting Anwer questions 4 / 38
For loop bug Example for(s=1;s<25; s = s++) { printf("month %2d: debt=%.2f, interest=%.2f, " "total_interest=%7.2f, frac=%6.2f%%\n", s, b*(pow(1.03,s)), 30*(pow(1.03,s-1)), (b*(pow(1.03,s)))-b, (b*(pow(1.03,s))-b)/10); 6 / 38
For loop bug The "s = s++" puzzle int s=0; s = s++; /* Does this print 0 or 1? */ printf("%d\n", s); 0 Understanding "s = s++" /* Initialize old value of s */ old_s = 0 /* Assign it to s */ s = old_s /* 0 */ /* Increment old value of s */ old_s = old_s + 1 /* 1 */ 7 / 38
For loop bug Solutions Use postfix increment "s++" without assignment for (s = 1; s < 25; s++) Use "+=1" for (s = 1; s < 25; s += 1) Use prefix increment "++s" with (or without) assignment for (s = 1; s < 25; s = ++s) 8 / 38
The division bug Example Adapted from lab 3. List 10 numbers between XMIN and XMAX. #define N 10 #define XMIN 1 #define XMAX 10 int main(void) { double x; int i; for (i = 0; i <= N-1; i = i + 1){ x = XMIN + (XMAX - XMIN)/(N - 1) * i; printf("%3.2f ", x); return 0; 1.00 2.00 3.00 4.00 5.00 6.00 7.00 8.00 9.00 10.00 9 / 38
The division bug Same program with XMIN=2 #define N 10 #define XMIN 2 #define XMAX 10 int main(void) { double x; int i; for (i = 0; i <= N-1; i = i + 1){ x = XMIN + (XMAX - XMIN)/(N - 1) * i; printf("%3.2f ", x); return 0; 2.00 2.00 2.00 2.00 2.00 2.00 2.00 2.00 2.00 2.00 10 / 38
The division bug The division problem int x = 3; printf("%0.3f", 0.333-1 / x ); 0.333 11 / 38
The division bug Solution Input at least one decimal number "1.0" int x = 3; printf("%0.3f", 0.333-1.0 / x); -0.0 Remark 1: "1.0" is better than "1." Remark 2: not a robust solution. May break code later by mistakenly replacing 1.0 by an integer value. 12 / 38
The division bug Better solution Cast the denominator to a (double) (Defensive programming). int x = 3; printf("%0.3f", 0.333-1 / (double) x); -0.0 13 / 38
The division bug Modified code (fixed) From lab 3. List 10 numbers between XMIN and XMAX. #define N 10 #define XMIN 2 #define XMAX 10 int main(void) { double x, y, dx; int i; for (i = 0; i <= N-1; i = i + 1){ dx = (XMAX - XMIN) / ((double) (N - 1)); x = XMIN + dx * i; printf("%3.2f ", x); return 0; 2.00 2.89 3.78 4.67 5.56 6.44 7.33 8.22 9.11 10.00 14 / 38
Indentation Bad indentation int main(void){ int Lower=-30; int Upper=30; int step=2; int Celsius; float Fahrenheit; for (Celsius=Lower; Celsius<Upper+step; Celsius=Celsius+ste Fahrenheit=Celsius*( (float) 9/5)+32; printf("%3d = %5.1f",Celsius,Fahrenheit); printf("\n"); 16 / 38
Indentation Good indentation int main(void) { int Lower=-30; int Upper=30; int step=2; int Celsius; float Fahrenheit; for (Celsius=Lower; Celsius<Upper+step; Celsius=Celsius Fahrenheit=Celsius*( (float) 9/5)+32; printf("%3d = %5.1f",Celsius,Fahrenheit); printf("\n"); 17 / 38
Position of curly brackets Kernighan and Ritchie style Open curly bracket on next line for function but on the same line for control structures. int main() { for (...) {... if (...) {... 18 / 38
Position of curly brackets NASA style int main() { for (...) {... if (...) {... 18 / 38
Capital letters Too many capital letters float INI; float FAH; for (INI = -30; INI<32; INI = INI +2) { FAH = ((INI*9)/5) + 32; printf("%3.0f = %5.1f\n",INI, FAH); Reserve capital letters for: global variables 1 (to make them stand out); matrices or multi-dimensional arrays (to follow the notation in maths); 1 usually declared with #define (e.g. "#define XMIN 0") 19 / 38
White space Too much vertical white space int main( void ){ float i; float T; for (i=-30; i<=30; i = i + 2) { T = i*(9/(float)5)+32; printf("%3.0f = %5.1f\n",i,T); return 0; 20 / 38
White space Better use of vertical white space int main(void) { float i; float T; for (i=-30; i<=30; i = i + 2) { T = i*(9/(float)5)+32; printf("%3.0f = %5.1f\n",i,T); return 0; Adding vertical white space is like creating a new paragraph in prose. Group meaningful elements together. 21 / 38
White space White space around brackets No space need for extra spaces around brackets (except closing one) for functions int main(void) {... Operators and brackets Use spaces around operators (* + - / % \= < > += etc). Not enough whitespace: T = i*(9/(float)5)+32; More readable: T = i * (9 / (float) 5 ) + 32; 22 / 38
White space tip for renaming variable Hard (for computer) to differentiate variables with similar names. Example It s hard to rename the variable interest to something else with "replace all" in a text editor, because we would modify total_interest too. x=interest*debt + total_interest If we generally have whitespace around variable "interest", we can simply 2 search for " interest " (note the spaces) x = interest * debt + total_interest 2 To handle brackets, as in "(interest" or "interest)", you can use regular expressions. 23 / 38
Declaring variables within a loop int main(void) { int celsius; for(celsius=-30; celsius<=30; celsius+=2) { float fahrenheit = celsius*9/5. +32; printf("%3d = %5.1f\n", celsius, fahrenheit); return 0; A bit wasteful: the variable is declared at every single iteration. 24 / 38
Declaring variables within a loop (fixed) Declare the variables outside the loop. int main(void) { int celsius; float fahrenheit; for(celsius = -30; celsius <= 30; celsius += 2) { fahrenheit = celsius * 9 / 5.0 + 32; printf("%3d = %5.1f\n", celsius, fahrenheit); return 0; 25 / 38
Precedence rules "* % /" come before "+" and "-". Put brackets around everything else. Example from lab 2 Unnecessary brackets: F =( ( c*9)/5.) +32; More readable version: F = c * 9 / 5.0 + 32; 26 / 38
Precedence rules Casting example int x = 1; int y = 2; printf("%0.1f, %0.1f, %0.1f", (double) x / y, /* precedence rule? */ ((double) x) / y, /* this? */ (double) (x / y) /* or that? */ ); 0.5, 0.5, 0.0 In this case, to avoid any confusion, it is OK to use additionnal brackets around the numerator. 27 / 38
Variable names (example with single letter variables) What do i, s, t, and f represent? Need to refer to comments. Hard to modify with search & replace int N, i; float s, debt, rate, in, t, f; N = 25; /* number of months */ s = 1000; /* starting debt */ debt = s; rate = 0.03; t = 0; /* total interest */ f = 0; /* fraction of total interest to original d for (i=1; i<n; i=i+1) { printf("month %3d: debt=%7.2f, interest=%4.2f, " "total_interest=%7.2f, frac=%6.2f%%\n", i, debt, in, t, f); 28 / 38
Variable names (improved variable names) int month, nbmonths; float loan, debt; float rate, interest, total_interest, frac; nbmonths = 25; /* loan duration in months */ loan = 1000; /* loan amount */ debt = loan; /* current debt */ rate = 0.03; /* interest rate */ tot_interest = 0; /* total interest payed so far */ frac = 0; /* total interest / loan */ for (month = 1; month < nbmonths; month++) {... printf("month %3d: debt=%7.2f, interest=%4.2f, " "total_interest=%7.2f, frac=%6.2f%%\n", month, debt, interest, tot_interest, frac); 29 / 38
String formatting syntax http://en.wikipedia.org/wiki/printf_format_string Syntax is %[flags][width][.precision][length]type Example: parsing format string "%07.3lf" flag 0 (padd with zeros) width 7 (total width is 7) precision.3 (precision is 2) length l (long ) type f (double) # Using printf command in unix shell printf "%07.3lf" 3.14159265359 003.142 31 / 38
String formatting: width Tip: to practise/test your understanding, add the zero flag to visualize spaces. format variable flag(s) width printf(format, variable) %02d 3 0 2 03 %03d 3 0 3 003 %04d 3 0 4 0003 32 / 38
String formatting: flags 0 use 0 instead of spaces to pad the result + prefix by + or - depending on the number sign space prefix by a space before positive numbers - left align (default is right align) Example with integers Exercise: give the flag(s) corresponding to the format and predict the output for the given variable. format x flag(s) printf(format, x) %04d 3 %04d -3 %+04d 3 %+04d -3 % 04d 3 %-04d 3 33 / 38
String formatting: flags 0 use 0 instead of spaces to pad the result + prefix by + or - depending on the number sign space prefix by a space before positive numbers - left align (default is right align) Example with integers Solution: format x flag(s) printf(format, x) comment %04d 3 04 0003 %04d -3 04-003 %+04d 3 +04 +003 %+04d -3 +04-003 % 04d 3 04 003 one space + two zeros %-04d 3-04 3 three spaces after 3 33 / 38
String formatting: precision format precision printf(format, M_PI) 3 comment %4.2f 2 3.14 %4.3f 3 3.142 output width 5 not 4 %5.5f 5 3.14159 output width 7 not 5 %09.5f 5 003.14159 %02.0f 0 03 displays float as int Precision supercedes width if width is too small 3 : built-in library "math.h" includes variable M_PI that represents π. 34 / 38
Length h l L... for short integers for long / double arguments long doubles 35 / 38
Summary For loop "s = s++" bug Use "s++" Use "s = ++s" Use "s += 1" The division bug n / 3 Use n / 3.0 Use (double) n / 3.0 Use good style good indentation proper use of white space well place curly brackets meaningful variable names 38 / 38