Lecture 10 Class string Namespaces Preprocessor directives Macros Conditional compilation Command line arguments Character handling library void* <cctype> TNCG18(C++): Lec 10 1 Class string Template class basic_string String manipulation (copying, searching, etc.) typedef basic_string< char > string; #include <string> string initialization string s1( "Hello" ); string s2( 8, 'x' ); s2 gets xxxxxxxx string month = "March ; Implicitly calls constructor (not the assignment operator); string month( March ); TNCG18(C++): Lec 10 2 1
string features Class string Not necessarily null terminated length member function: s1.length() Use [] to access individual characters: s1[0] 0 to length-1 string not a pointer Many member functions take start position and length Stream extraction White space delimited input. cin >> stringobject; getline(cin, s); Delimited by newline TNCG18(C++): Lec 10 3 string Assignment and Concatenation Assignment s2 = s1; Makes a separate copy s2.assign(s1); Same as s2 = s1; mystring.assign(s, start, N); Copies N characters from s, beginning at index start Several overloaded versions of assign() See http://www.cplusplus.com/reference/string/string/assign.html Individual characters s2[0] = s3[2]; s2.at(0) = s3.at(2); // performs range check TNCG18(C++): Lec 10 4 2
string Assignment and Concatenation Range checking s3.at( index ); Returns character at index Can throw out_of_range exception [] has no range checking Concatenation s3.append( "pet" ); s3 += "pet"; Both add "pet" to end of s3 s3.append( s1, start, N ); Appends N characters from s1, beginning at index start Other overloaded versions of append exist TNCG18(C++): Lec 10 5 Comparing strings Overloaded operators ==,!=, <, >, <= and >= Return bool s1.compare(s2) Returns positive if s1 lexicographically greater Compares letter by letter 'B' lexicographically greater than 'A' Returns negative if less, zero if equal s1.compare(start1,length1, s2, start2, length2) Compare portions of s1 and s2 s1.compare(start1, length1, s2) Compare portion of s1 with all of s2 TNCG18(C++): Lec 10 6 3
Substrings and Swapping strings Function substr gets substring s1.substr( start, N ); Gets N characters, beginning with index start Returns substring string str= "We think in generalities, but we live in details."; string str2; str2 = str.substr (12,12); // "generalities" s1.swap(s2); Switch contents of two strings TNCG18(C++): Lec 10 7 Member functions string Characteristics s1.size() and s1.length() Number of characters in string s1.capacity() Number of elements that can be stored without reallocation s1.max_size() Maximum possible string size If exceeded, a length_error exception is thrown s1.empty() Returns true if empty s1.resize(newlength) Resizes string to newlength TNCG18(C++): Lec 10 8 4
Finding Strings and Characters in a string Find functions If found, index returned If not found, string::npos returned Public static constant in class string s1.find( s2 ) s1.find( s2, pos ) s1.rfind( s2 ) Searches right-to-left s1.find_first_of( s2 ) Returns first occurrence of any character in s2 s1.find_first_of( "abcd" ) Returns index of first 'a', 'b', 'c' or 'd' TNCG18(C++): Lec 10 9 Finding Strings and Characters in a string Find functions s1.find_last_of( s2 ) Finds last occurrence of any character in s2 s1.find_first_not_of( s2 ) Finds first character NOT in s2 s1.find_last_not_of( s2 ) Finds last character NOT in s2 TNCG18(C++): Lec 10 10 5
Replacing Characters in a string s1.erase( start ) Erase from index start to end of string, including start Replace s1.replace( begin, N, s2) begin: index in s1 to start replacing N: number of characters to replace s2: replacement string s1.replace( begin, N, s2, index, num ) index: element in s2 where replacement begins num: number of elements to use when replacing Replacement can overwrite characters TNCG18(C++): Lec 10 11 An Example int position = string1.find(. ); //replace all periods with two semicolons //Note: this will overwrite characters while ( position!= string::npos ) { string1.replace(position, 2, ;; ); position = string1.find(., position+1); } TNCG18(C++): Lec 10 12 6
Inserting Characters into a string s1.insert( index, s2 ) Inserts s2 at index It does not overwrite other characters s1.insert( index, s2, index2, N ); Inserts substring of s2 at position index Substring is N characters, starting at index2 Example: String s1( beginning end ); String s2 ( middle ); S1.insert(10, s2); cout << s1; // beginning middle end TNCG18(C++): Lec 10 13 Conversion to C-Style char* Strings Conversion functions strings not necessarily null-terminated s1.copy( ptr, N, index ) Copies N characters into the array ptr (char*) Starts at location index of s1 Add explicitly null as last character s1.c_str() Returns const char* Null terminated s1.data() Returns const char* NOT null-terminated TNCG18(C++): Lec 10 14 7
Namespaces Program has identifiers in different scopes Sometimes scopes overlap, lead to problems Namespace defines scope Place identifiers and variables within namespace Access with namespace_name::member Note guaranteed to be unique namespace Name { contents } Unnamed namespaces are global Need no qualification Namespaces can be nested TNCG18(C++): Lec 10 15 using statement Namespaces using namespace namespace_name; Members of that namespace can be used without preceding namespace_name:: Can also be used with individual member Examples using namespace std; using namespace std::cout Can write cout instead of std::cout TNCG18(C++): Lec 10 16 8
1 // Fig. 22.3: fig22_03.cpp 2 // Demonstrating namespaces. 3 #include <iostream> 4 5 using namespace std; // use std namespace 6 7 int integer1 = 98; // global variable 8 9 // create namespace Example 10 namespace Example { 11 12 // declare two constants and one variable 13 const double PI = 3.14159; 14 const double E = 2.71828; 15 int integer1 = 8; 16 17 void printvalues(); // prototype 18 19 // nested namespace 20 namespace Inner { 21 22 // define enumeration 23 enum Years { FISCAL1 = 1990, FISCAL2, FISCAL3 }; 24 25 } // end Inner 26 TNCG18(C++): Lec 10 17 27 } // end Example 28 29 // create unnamed namespace 30 namespace { 31 double doubleinunnamed = 88.22; // declare variable 32 33 } // end unnamed namespace 34 35 int main() 36 { 37 // output value doubleinunnamed of unnamed namespace 38 cout << "doubleinunnamed = " << doubleinunnamed; 39 40 // output global variable 41 cout << "\n(global) integer1 = " << integer1; 42 43 // output values of Example namespace 44 cout << "\npi = " << Example::PI << "\ne = " 45 << Example::E << "\ninteger1 = " 46 << Example::integer1 << "\nfiscal3 = " 47 << Example::Inner::FISCAL3 << endl; 48 51 return 0; 52 53 } // end main How useful can it be unnamed namespaces? TNCG18(C++): Lec 10 18 9
Preprocessing Occurs before program compiled All directives begin with # Inclusion of external files #include <iostream> Definition of symbolic constants Macros Conditional compilation Conditional execution Directives not C++ statements Do not end with ; TNCG18(C++): Lec 10 19 The #include Preprocessor Directive #include directive Puts copy of file in place of directive Seen many times in example code Two forms #include <filename> For standard library header files Searches pre-designated directories #include "filename.h" Searches in current directory Normally used for programmer-defined files TNCG18(C++): Lec 10 20 10
The #define Preprocessor Directive: Symbolic Constants Format #define identifier replacement-text #define PI 3.14159 When program compiled, all occurrences PI are replaced by 3.14159 Advantages: takes no memory Disadvantage: name PI not be seen by debugger Everything to right of identifier replaces text #define PI=3.14159 Replaces PI with "=3.14159 An alternative const double PI = 3.14159; Probably, an error!! TNCG18(C++): Lec 10 21 Macro Macros Operation specified in #define Intended for legacy C programs Macro without arguments Treated like a symbolic constant Macro with arguments Arguments substituted for replacement text Macro expanded Performs a text substitution No data type checking TNCG18(C++): Lec 10 22 11
Macros: Example #define CIRCLE_AREA( x ) ( PI * ( x ) * ( x ) ) area = CIRCLE_AREA( 4 ); becomes area = ( 3.14159 * ( 4 ) * ( 4 ) ); Use parentheses Without them, #define CIRCLE_AREA( x ) PI * x * x area = CIRCLE_AREA( c + 2 ); becomes area = 3.14159 * c + 2 * c + 2; which evaluates incorrectly May not give the right Passing arguments with side effects results!!! area = CIRCLE_AREA( ++i ); Use inline functions. TNCG18(C++): Lec 10 23 inline Functions inline double CIRCLE_AREA( double x ) { return PI * x * x; } Advise the compiler to replace function calls with functions code To help reduce function call overhead Use with small functions Inline funtions appear in header files (.h) Type checking is performed TNCG18(C++): Lec 10 24 12
Conditional Compilation Structure similar to if #ifndef FLAG #if!defined( FLAG ) #define FLAG #define FLAG 1 //code //code #endif #endif Determines if symbolic constant FLAG is defined If FLAG defined, #defined FLAG 1 is skipped All code until #endif is ignored Every #if ends with #endif TNCG18(C++): Lec 10 25 Conditional Compilation A header file Limousine.h may start with #ifndef LIMOUSIN_H #define LIMOUSIN_H Avoid multiple inclusions of Limousine.h class Limousin : public Taxi { public: Limousin( string = """", int = 0 ); }; #endif File1.h File2.cpp #include Limousine.h #include Limousine.h #include File1.h TNCG18(C++): Lec 10 26 13
Conditional Compilation Debugging #define DEBUG 1 #ifdef DEBUG cerr << "Variable x = " << x << endl; #endif Defining DEBUG enables code After code corrected Remove #define statement Debugging statements are now ignored TNCG18(C++): Lec 10 27 assert is a macro Assertions Header <cassert> assert( x <= 10 ); Tests value of an expression If 0 (false) prints error message, calls abort Terminates program, prints line number and file Good for checking for illegal values If 1 (true), program continues as normal To remove assert statements No need to delete them manually #define DEBUG All subsequent assert statements ignored TNCG18(C++): Lec 10 28 14
Using Command-Line Arguments Can pass arguments to main in UNIX/DOS Include parameters in main int main( int argc, char* argv[] ) int argc char** Number of arguments char *argv[] Array of strings that contains command-line arguments Example: $ copy input.txt output.txt argc: 3 argv[0]: "copy" argv[1]: "input.txt" argv[2]: "output.txt" TNCG18(C++): Lec 10 29 And More Character-handling library #include <cctype> Includes functions that perform tests and manipulations in char data int isdigit(int c); int toupper(int c); Pointer-based string conversions #include <cstdlib> double atof(const char *p); double d = atof( 99.6 ); double strtod(const char *p1, char **p2); const char str1[] = 99.9% pass 10%. char *str2; double d = (str1, &str2); Search for more information about it in cplusplus.com TNCG18(C++): Lec 10 30 15
void *ptr; void* Can be assigned any other type of pointer int i = 5; ptr = &i; Pointers to void cannot be derreferenced cout << *ptr; \\Compiler ERROR!! Pointers to void can be casted to any other type of pointer Be careful with its use, then!! cout << *(char *)ptr; Use to make functions more generic, i.e. accept different types of arguments TNCG18(C++): Lec 10 31 16