Data Structures Contents and Algorithms ! ++ Input/Output ! getopt ! Makefile ! gdb Discussion 1: Week of Sep 7, 2011 ! Unit Testing

2

C++ Input/Output C++ Input/Output

! !"#$%&'()%*&+,%-.)"#% ! !+/.$%0&".'%.+%-.)+/.% ! !'&&$%0&".'%.+%-.)'&&% ! "*-.&'(,$%+1'#%*"2'-%0".3%&'()%1'&,"--"+#% ! *-.&'(,$%+1'#%*"2'-%0".3%&'()%4%0&".'% 1'&,"--"+#%

http://www.cplusplus.com/reference/

3 4 PA1 Read char by char

! 5#1/.6+/.1/.%"-%&')"&'!.')%*&+,%*"2'-% "#.%,("#C"#.%(&@!A%!3(&DD%(&@EF% ! 761(.389:%;%"#1/.7.<.%=%+/.1/.7.<.% G% ! >;>%(#)%>"#1/.7.<.?%(&'%#+.%!+,,(#)%2"#'%(&@-A% %03"2'C!"#7@'.CF%HI%J:F% )+%#+.%(11'(&%"#%char** argv %G% ! B+/%!(#%/-'%% %%!"#7/#@'.CFK% cin.get(), cin.unget(), getline(cin, var), %%!3(&%!%I%!"#7@'.CFK% cin >> var %%!+/.%;;%!K% %L% %&'./&#%MK% L%

5 6

Command Line Read line by line ! Option: defines how the program should run

"#.%,("#C"#.%(&@!A%!3(&DD%(&@EF% ! Argument: input to the program

G% ! $ ls –a (-a is an option) %-.&"#@%-K% ! $ ls *.cpp (*.cpp is an argument) %03"2'C@'.2"#'C!"#A-FF% ! $ mysql –p –u username (username is required by option –u) %G% %%!+/.%;;%-%;;%'#)2K% %L% %&'./&#%MK% L%

7 8 getopt getopt – external variable soup

! getopt greatly simplifies command-line argument parsing. ! getopt gets and sets some external variables on execution:

! We pass it argc and argv, as well as optstring, which is a – If you set opterr to something other than zero, then if character array containing all available option characters. there is an error, it will be output to stderr.

– After an option character, you can specify a : to indicate – For unknown option characters/unknown arguments, that the option has a required parameter. :: denotes that getopt stores the value in optopt.

the argument is optional. – optind contains the index of the next element of argv

! getopt returns the option if it successfully found one. scheduled to be processed.

– ! Otherwise, it might return : which indicates a missing For options that accept arguments, optarg is set with the parameter value of the argument. • ! Or it might return ? which means one of the option characters Windows users can get wingetopt from: was unknown http://note.sonots.com/Comp/CompLang/cpp/getopt.html

! Let's look at an example. ! Or it will return -1 if it is at the end of the option list

9 10

getopt getopt

#include % testopt #include aflag = 0, bflag = 0, cvalue = (null)

int main (int argc, char **argv) { % testopt -a -b int aflag = 0; int bflag = 0; aflag = 1, bflag = 1, cvalue = (null) char *cvalue = NULL; int index, c; % testopt -ab opterr = 0; // extern var aflag = 1, bflag = 1, cvalue = (null)

while ((c = getopt (argc, argv, "abc:")) != -1) { % testopt -c foo switch (c) { aflag = 0, bflag = 0, cvalue = foo case 'a': aflag = 1; break; % testopt -cfoo case 'b': aflag = 0, bflag = 0, cvalue = foo bflag = 1; break; case 'c': % testopt arg1 cvalue = optarg; break; aflag = 0, bflag = 0, cvalue = (null) case '?': Non-option argument arg1 if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); % testopt -a arg1 else aflag = 1, bflag = 0, cvalue = (null) fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); Non-option argument arg1 return 1; default: % testopt -c foo arg1 abort (); aflag = 0, bflag = 0, cvalue = foo } Non-option argument arg1

printf ("aflag = %, bflag = %d, cvalue = %s\n", % testopt -a -- -b aflag, bflag, cvalue); aflag = 1, bflag = 0, cvalue = (null) Non-option argument -b for (index = optind; index < argc; index++) printf ("Non-option argument %s\n", argv[index]); % testopt -a - return 0; aflag = 1, bflag = 0, cvalue = (null) } 11 Non-option argument - Compiling: The old way The Solution: Makefiles

! @NN%,("#7!11%*"2':7!11%*"2'87!11%O+%,("#% ! The command becomes " Way too long to re-type over and over. " ,(P'% " Compare to ! Potential Problems: " @NN%,("#7!11%*"2':7!11%*"2'87!11%O+%,("#% " @NN%,("#%O+%,("#7!11% " @NN%,("#7!11%O+%,("#7!11% ! What happens in the two above commands?

13 14

Structure of a Makefile Dependencies

! The file must be called `Q(P'*"2'’ ! It consists of rules as follows:

15 16 make make

! Let's look at an example 3-file project. ! make is a utility that can simplify the building process. classname.h As the size of a C++ project grows, it becomes critical to void writeClassName( void ); modularize the code for the sake of both the build time classname.cpp and for the sanity of the programmer (and the grader!). #include ! make is better than a shell script because it detects the using namespace std; files that have been changed and only recomplies and void writeClassName( void ) { relinks when needed. cout << "Hello EECS 281!" << endl; }

! make looks at a file called Makefile, created by you, to hello.cpp

determine the dependency graph of your project. #include #include "classname.h"

using namespace std;

int main( void ) { cout << "Hello world!" << endl; writeClassName(); }

17 18

make - Makefile make – macros

! Here is our simple Makefile: ! It's possible to define and use macros in your Makefile: # top-level dependency OBJECTS = hello.o classname.o helloWorld281: hello.o classname.o CPPFLAGS = -c -Wall g++ hello.o classname.o -o helloWorld281 # top-level dependency # hello module helloWorld281: $(OBJECTS) hello.o: hello.cpp classname.h g++ $(OBJECTS) -o helloWorld281 g++ -c hello.cpp # hello module # the classname module hello.o: hello.cpp classname.h classname.o: classname.cpp classname.h g++ $(CPPFLAGS) hello.cpp g++ -c classname.cpp # the classname module ! We define a dependency graph in Makefile. To the left of the colon classname.o: classname.cpp classname.h g++ $(CPPFLAGS) classname.cpp is a label often denoting a file. To the right are dependencies. For example, helloWorld281 depends on hello.o and classname.o. # clean the project clean: ! The indented lines are, in a nutshell, the commands executed to rm -rf *o helloWorld281 create the object denoted by the label. Compiled in order. These ! Note above we've also defined a “clean” operation. This is an lines must be indented. action, not a g++ operation. To use, type make clean at the command prompt. ! # denotes comments

19 20 make - sub-makefiles make

! You can also embed other makefiles inside Makefile. This allows ! make is a powerful and complex utility, and we're just barely you to modularize your build process even further. To specify a scratching the surface. For more information, do a man make or make file with a different name than Makefile, use the -f option: check out one of the many tutorials on the web.

make -f MyOtherMakeFile ! http://www.eng.hawaii.edu/Tutor/Make/

21 22

Makefiles Summary Makefiles Summary ! Basic syntax

" Target: sources ! Suppose we run the following command to compile our " [tab] system command program: " g++ main.cpp hello.cpp factorial.cpp -o hello ! To run a makefile, simply use: ! Then we can do the same thing in our makefile by just " make -f makefilename doing this: ! BUT, if you simply name your makefile all: “Makefile”, then you only have to type: g++ main.cpp hello.cpp factorial.cpp -o hello ! Remember tabs, of course make ! All is default target for makefiles. That's why it works here. Makefiles Summary GNU Debugger (gdb)

! Dependencies are important! ! Here is an example makefile for the same source code: ! Text-based debugging tool all: hello hello: main.o factorial.o hello.o ! Useful for solving segmentation faults g++ main.o factorial.o hello.o -o hello main.o: main.cpp Program received signal SIGSEGV, Segmentation fault. g++ -c main.cpp factorial.o: factorial.cpp or memory issues, e.g., index out of bounds g++ -c factorial.cpp hello.o: hello.cpp g++ -c hello.cpp clean: rm -rf *o hello ! When compiling, add -g to Makefile ! What advantages does this code have? " Adds debugging symbols to binary

26

gdb Helpful Commands gdb Usage # (r)un: start the executable # (b)reak: sets points where gdb will halt # where: prints function line where seg. fault occurred ! To start gdb, type gdb # (b)ack(t)race: prints the full chain of function calls # (s)tep: executes current line of the program, enters function calls # (n)ext: like step but does not enter functions # (c)ontinue: continue to the next breakpoint # (p)rint : prints the value of # watch : watch a certain variable # (l)ist : list source code near ! At this point, gdb is waiting. To start the # kill: terminate the executable program, type run # (q)uit: quit gdb

27 28 Unit Testing gdb Live Example ! Unit testing is a methodology by which you test the software of your program.

! Tests are unit tests because they usually operate on a ! See live example" small, specific part of the system.

! They are organized in classes.

! We can implement an extremely simple version of unit testing with assert.

29 37

Unit testing Unit Testing PowerRaiser.h ! assert is the most important macro in C++ (at least in terms of debugging). class PowerRaiser { public: ! We assert that something is true. If, when the PowerRaiser( unsigned int base );

program counter reaches an assert and the expression unsigned int getBase() const; turns out to be false, it triggers a breakpoint, and we unsigned int raise( unsigned int power ) const;

break into the code. private: unsigned int base_; ! It's incredibly useful and convenient. Use it! }; assert( 3 == 3 ); // OK assert( false == false ); // OK assert( myFunc( 123 ) ); // OK if myFunc returns true assert( 5 == 2 + 2 ); // Will break into code!!!!

39 Unit Testing Unit Testing PowerRaiser.cpp PowerRaiserTest.h

PowerRaiser::PowerRaiser( unsigned int base ) : class PowerRaiserTest { base_( base ) public: { void runAllTests(); } void testGetBase(); void testGetPower(); unsigned int PowerRaiser::getBase() const { ... return base_; }; }

unsigned int PowerRaiser::raise( unsigned int power ) const { if ( 0 == number ) { return 1; } else { return base_ * raise( power – 1 ); }

40 41

Unit Testing Unit Testing

PowerRaiserTest.cpp ! Each time we make a change to the code base, we void PowerRaiserTest::testGetBase() { run all unit tests to make sure that all of the PowerRaiser p( 10 ); functionality is still there. assert( 10 == p.getBase() ); } ! If an error occurs, it signals a bug. We can figure out void PowerRaiserTest::testGetPower() { where it is with our tests, identify it immediately, and PowerRaiser p( 3 ); assert( 1 == p.raise( 0 ) ); correct it. assert( 3 == p.raise( 1 ) ); assert( 9 == p.raise( 2 ) ); ! Or, if the bug cannot be resolved, we can revert our assert( 4782969 == p.raise( 12 ) ); assert( 15625 == PowerRaiser( 5 ).raise( 6 ) ); code (using SVN or CVS, for example) to the prior assert( 1000000 == PowerRaiser( 10 ).raise( 6 ) ); state. ... } ! Thus, code repositories play a big part in unit testing. void PowerRaiserTest::testAll() { testGetBase(); testGetPower(); ... } 42 43