Példa 1 ========= template<class Ch> struct char_traits { }; Példa 2 ========= template<> struct char_traits<char> { // char_traits operations should not throw exceptions typedef char char_type; // type of character static void assign(char_type&, const char_type&); // = for char_type // integer representation of characters: typedef int int_type; // type of integer value of character static char_type to_char_type(const int_type&); // int to char conversion static int_type to_int_type(const char_type&); // char to int conversion static bool eq_int_type(const int_type&, const int_type&); // == // char_type comparisons: static bool eq(const char_type&, const char_type&); // == static bool lt(const char_type&, const char_type&); // < // operations on s[n] arrays: static char_type* move(char_type* s, const char_type* s2, size_t n); static char_type* copy(char_type* s, const char_type* s2, size_t n); static char_type* assign(char_type* s, size_t n, char_type a); static int compare(const char_type* s, const char_type* s2, size_t n); static size_t length(const char_type*); static const char_type* find(const char_type* s, int n, const char_type&); // I/O related: typedef streamoff off_type; // offset in stream typedef streampos pos_type; // position in stream typedef mbstate_t state_type; // multi-byte stream state static int_type eof(); // end-of-file static int_type not_eof(const int_type& i); // i unless i equals eof(); if not any value!=eof() static state_type get_state(pos_type p); // multibyte conversion state of character in p }; Példa 3 ========= template<> struct char_traits<wchar_t> { typedef wchar_t char_type; typedef wint_t int_type; typedef wstreamoff off_type; typedef wstreampos pos_type; // like char_traits<char> }; Példa 4 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class std::basic_string { public: // ... }; Példa 5 ========= typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; Példa 6 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // types (much like vector, list, etc. ): typedef Tr traits_type; // specific to basic_string typedef typename Tr::char_type value_type; typedef A allocator_type; typedef typename A::size_type size_type; typedef typename A::difference_type difference_type; typedef typename A::reference reference; typedef typename A::const_reference const_reference; typedef typename A::pointer pointer; typedef typename A::const_pointer const_pointer; typedef implementation_defined1 iterator; typedef implementation_defined2 const_iterator; typedef std::reverse_iterator<iterator> reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator; // ... }; Példa 7 ========= typedef basic_string<unsigned char> Ustring; struct Jchar { /* ... */ }; // Japanese character type typedef basic_string<Jchar> Jstring; Példa 8 ========= Ustring first_word(const Ustring& us) { Ustring::size_type pos = us.find(' '); return Ustring(us,0,pos); } Jstring first_word(const Jstring& js) { Jstring::size_type pos = js.find(' '); return Jstring(js,0,pos); } Példa 9 ========= template<class S> S first_word(const S& s) { typename S::size_type pos = s.find(' '); return S(s,0,pos); } Példa 10 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // iterators (like vector, list, etc.): iterator begin(); const_iterator begin() const; iterator end(); const_iterator end() const; reverse_iterator rbegin(); const_reverse_iterator rbegin() const; reverse_iterator rend(); const_reverse_iterator rend() const; // ... }; Példa 11 ========= void f(string& s) { string::iterator p = find(s.begin(),s.end(),'a'); // ... } Példa 12 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // element access (like vector): const_reference operator[](size_type n) const; // unchecked access reference operator[](size_type n); const_reference at(size_type n) const; // checked access reference at(size_type n); // ... }; Példa 13 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // constructors, etc. (a bit like vector and list) explicit basic_string(const A& a = A()); basic_string(const basic_string& s, size_type pos = 0, size_type n = npos, const A& a = A()); basic_string(const Ch* p, size_type n, const A& a = A()); basic_string(const Ch* p, const A& a = A()); basic_string(size_type n, Ch c, const A& a = A()); template<class In> basic_string(In first, In last, const A& a = A()); ~basic_string(); static const size_type npos; // ``all characters'' marker // ... }; Példa 14 ========= void f(char* p,vector<char>&v) { string s0; // the empty string string s00 = ""; // also the empty string string s1 = 'a'; // error: no conversion from char to string string s2 = 7; // error: no conversion from int to string string s3(7); // error: no constructor taking one int argument string s4(7,'a'); // 7 copies of 'a'; that is "aaaaaaa" string s5 = "Frodo"; // copy of "Frodo" string s6 = s5; // copy of s5 string s7(s5,3,2); // s5[3] and s5[4]; that is "do" string s8(p+7,3); // p[7], p[8], and p[9] string s9(p,7,3); // string(string(p),7,3), possibly expensive string s10(v.begin(),v.end()); // copy all characters from v } Példa 15 ========= void f(string s) { wstring ws(s.begin(),s.end()); // copy all characters from s // ... } Példa 16 ========= void f() { string s = "Snobol4"; string s2(s,100,2); // character position beyond end of string: throw out_of_range() string s3(s,2,100); // character count too large: equivalent to s3(s,2,s.size()\-2) string s4(s,2,string::npos); // the characters starting from s[2] } Példa 17 ========= void g(string& s) { string s5(s,-2,3); // large position!: throw out_of_range() string s6(s,3,-2); // large character count!: ok } Példa 18 ========= string s(string::npos,'a'); // throw length_error() Példa 19 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // assignment (a bit like vector and list): basic_string& operator=(const basic_string& s); basic_string& operator=(const Ch* p); basic_string& operator=(Ch c); basic_string& assign(const basic_string&); basic_string& assign(const basic_string& s, size_type pos, size_type n); basic_string& assign(const Ch* p, size_type n); basic_string& assign(const Ch* p); basic_string& assign(size_type n, Ch c); template<class In> basic_string& assign(In first, In last); // ... }; Példa 20 ========= void g() { string s1 = "Knold"; string s2 = "Tot"; s1 = s2; // two copies of "Tot" s2[1] = 'u'; // s2 is "Tut", s1 is still "Tot" } Példa 21 ========= void f() { string s = 'a'; // error: initialization by char s = 'a'; // ok: assignment s = "a"; s = s; } Példa 22 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // conversion to C-style string: const Ch* c_str() const; const Ch* data() const; size_type copy(Ch* p, size_type n, size_type pos = 0) const; // ... }; Példa 23 ========= void f() { string s = "equinox"; // s.length()==7 const char* p1 = s.data(); // p1 points to seven characters printf("p1 = %s\n",p1); // bad: missing terminator p1[2] = 'a'; // error: p1 points to a const array s[2] = 'a'; char c = p1[1]; // bad: access of s.data() after modification of s const char* p2 = s.c_str(); // p2 points to eight characters printf("p2 = %s\n",p2); // ok: c_str() adds terminator } Példa 24 ========= void f(string s) { int i = atoi(s.c_str()); // get int value of digits in string // ... } Példa 25 ========= char* c_string(const string& s) { char* p = new char[s.length()+1]; // note: +1 s.copy(p,string::npos); p[s.length()] = 0; // note: add terminator return p; } Példa 26 ========= extern "C" int atoi(const char*); int atoi(const string& s) { return atoi(s.c_str()); } Példa 27 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... int compare(const basic_string& s) const; // combined > and == int compare(const Ch* p) const; int compare(size_type pos, size_type n, const basic_string& s) const; int compare(size_type pos, size_type n, const basic_string& s, size_type pos2, size_type n2) const; int compare(size_type pos, size_type n, const Ch* p, size_type n2 = npos) const; // ... }; Példa 28 ========= int cmp_nocase(const string& s, const string& s2) { string::const_iterator p = s.begin(); string::const_iterator p2 = s2.begin(); while (p!=s.end() && p2!=s2.end()) { if (toupper(*p)!=toupper(*p2)) return (toupper(*p)<toupper(*p2)) ? -1 : 1; ++p; ++p2; } return (s2.size()==s.size()) ? 0 : (s.size()<s2.size()) ? -1 : 1; // size is unsigned } void f(const string& s, const string& s2) { if (s == s2) { // case sensitive compare of s and s2 // ... } if (cmp_nocase(s,s2) == 0) { // case insensitive compare of s and s2 // ... } // ... } Példa 29 ========= template<class Ch, class Tr, class A> bool operator==(const basic_string<Ch,Tr,A>&, const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> bool operator==(const Ch*, const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> bool operator==(const basic_string<Ch,Tr,A>&, const Ch*); // similar declarations for !=, >, <, >=, and <= Példa 30 ========= void f(const string& name) { if (name =="Obelix" || "Asterix"==name) { // use optimized == // ... } } Példa 31 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // add characters after (*this)[length()-1]: basic_string& operator+=(const basic_string& s); basic_string& operator+=(const Ch* p); basic_string& operator+=(Ch c); void push_back(Ch c); basic_string& append(const basic_string& s); basic_string& append(const basic_string& s, size_type pos, size_type n); basic_string& append(const Ch* p, size_type n); basic_string& append(const Ch* p); basic_string& append(size_type n, Ch c); template<class In> basic_string& append(In first, In last); // insert characters before (*this)[pos]: basic_string& insert(size_type pos, const basic_string& s); basic_string& insert(size_type pos, const basic_string& s, size_type pos2, size_type n); basic_string& insert(size_type pos, const Ch* p, size_type n); basic_string& insert(size_type pos, const Ch* p); basic_string& insert(size_type pos, size_type n, Ch c); // insert characters before p: iterator insert(iterator p, Ch c); void insert(iterator p, size_type n, Ch c); template<class In> void insert(iterator p, In first, In last); // ... }; Példa 32 ========= string complete_name(const string& first_name, const string& family_name) { string s = first_name; s += ' '; s += family_name; return s; } Példa 33 ========= string complete_name2(const string& first_name, const string& family_name) // poor algorithm { string s = family_name; s.insert(s.begin(),' '); return s.insert(0,first_name); .. return s; } Példa 34 ========= template<class Ch, class Tr, class A> basic_string<Ch,Tr,A> operator+(const basic_string<Ch,Tr,A>&, const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> basic_string<Ch,Tr,A> operator+(const Ch*, const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> basic_string<Ch,Tr,A> operator+(Ch, const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> basic_string<Ch,Tr,A> operator+(const basic_string<Ch,Tr,A>&, const Ch*); template<class Ch, class Tr, class A> basic_string<Ch,Tr,A> operator+(const basic_string<Ch,Tr,A>&, Ch); Példa 35 ========= string complete_name3(const string& first_name, const string& family_name) { return first_name + ' ' + family_name; } Példa 36 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // find subsequence (like search()): size_type find(const basic_string& s, size_type i = 0) const; size_type find(const Ch* p, size_type i, size_type n) const; size_type find(const Ch* p, size_type i = 0) const; size_type find(Ch c, size_type i = 0) const; // find subsequence searching backwards from the end (like find_end()): size_type rfind(const basic_string& s, size_type i = npos) const; size_type rfind(const Ch* p, size_type i, size_type n) const; size_type rfind(const Ch* p, size_type i = npos) const; size_type rfind(Ch c, size_type i = npos) const; // find character (like find_first_of() in _algo.find_): size_type find_first_of(const basic_string& s, size_type i = 0) const; size_type find_first_of(const Ch* p, size_type i, size_type n) const; size_type find_first_of(const Ch* p, size_type i = 0) const; size_type find_first_of(Ch c, size_type i = 0) const; // find character from argument searching backwards from the end: size_type find_last_of(const basic_string& s, size_type i = npos) const; size_type find_last_of(const Ch* p, size_type i, size_type n) const; size_type find_last_of(const Ch* p, size_type i = npos) const; size_type find_last_of(Ch c, size_type i = npos) const; // find character not in argument: size_type find_first_not_of(const basic_string& s, size_type i = 0) const; size_type find_first_not_of(const Ch* p, size_type i, size_type n) const; size_type find_first_not_of(const Ch* p, size_type i = 0) const; size_type find_first_not_of(Ch c, size_type i = 0) const; // find character not in argument searching backwards from the end: size_type find_last_not_of(const basic_string& s, size_type i = npos) const; size_type find_last_not_of(const Ch* p, size_type i, size_type n) const; size_type find_last_not_of(const Ch* p, size_type i = npos) const; size_type find_last_not_of(Ch c, size_type i = npos) const; // ... }; Példa 37 ========= void f() { string s = "accdcde"; .. typedef ST; .. string::size_type i1 = s.find("cd"); // i1 = 2 s[2]=='c' && s[3]=='d' string::size_type i2 = s.rfind("cd"); // i2 = 4 s[4]=='c' && s[5]=='d' string::size_type i3 = s.find_first_of("cd"); // i3 = 1 s[1] == 'c' string::size_type i4 = s.find_last_of("cd"); // i4 = 5 s[5] == 'd' string::size_type i5 = s.find_first_not_of("cd"); // i5 = 0 s[0]!='c' && s[0]!='d' string::size_type i6 = s.find_last_not_of("cd"); // i6 = 6 s[6]!='c' && s[6]!='d' } Példa 38 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // replace [ (*this)[i], (*this)[i+n] [ with other characters: basic_string& replace(size_type i, size_type n, const basic_string& s); basic_string& replace(size_type i, size_type n, const basic_string& s, size_type i2, size_type n2); basic_string& replace(size_type i, size_type n, const Ch* p, size_type n2); basic_string& replace(size_type i, size_type n, const Ch* p); basic_string& replace(size_type i, size_type n, size_type n2, Ch c); basic_string& replace(iterator i, iterator i2, const basic_string& s); basic_string& replace(iterator i, iterator i2, const Ch* p, size_type n); basic_string& replace(iterator i, iterator i2, const Ch* p); basic_string& replace(iterator i, iterator i2, size_type n, Ch c); template<class In> basic_string& replace(iterator i, iterator i2, In j, In j2); // remove characters from string (``replace with nothing''): basic_string& erase(size_type i = 0, size_type n = npos); iterator erase(iterator i); iterator erase(iterator first, iterator last); // ... }; Példa 39 ========= void f() { string s = "but I have heard it works even if you don't believe in it"; s.erase(0,4); // erase initial "but " s.replace(s.find("even"),4,"only"); s.replace(s.find("don't"),5,""); // erase by replacing with "" } Példa 40 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // address substring: basic_string substr(size_type i = 0, size_type n = npos) const; // ... }; Példa 41 ========= template<class Ch> class Basic_substring { public: typedef typename basic_string<Ch>::size_type size_type; Basic_substring(basic_string<Ch>& s, size_type i, size_type n); // s[i]..s[i+n\-1] Basic_substring(basic_string<Ch>& s, const basic_string<Ch>& s2); // s2 in s Basic_substring(basic_string<Ch>& s, const Ch* p); // *p in s Basic_substring& operator=(const basic_string<Ch>&); // write through to *ps Basic_substring& operator=(const Basic_substring<Ch>&); Basic_substring& operator=(const Ch*); Basic_substring& operator=(Ch); operator basic_string<Ch>() const; // read from *ps operator const Ch* () const; // use c_str() private: basic_string<Ch>* ps; size_type pos; size_type n; }; Példa 42 ========= template<class Ch> Basic_substring<Ch>::Basic_substring(basic_string<Ch>& s, const basic_string<Ch>& s2) :ps(&s), n(s2.length()) { pos = s.find(s2); } template<class Ch> Basic_substring<Ch>& Basic_substring<Ch>::operator=(const basic_string<Ch>& s) { ps->replace(pos,n,s); // write through to *ps return *this; } template<class Ch> Basic_substring<Ch>::operator basic_string<Ch>() const { return basic_string<Ch>(*ps,pos,n); // copy from *ps } Példa 43 ========= typedef Basic_substring<char> Substring; void f() { string s = "Mary had a little lamb"; Substring(s,"lamb") = "fun"; Substring(s,"a little") = "no"; string s2 = "Joe" + Substring(s,s.find(' '),string::npos); } Példa 44 ========= template<class Ch, class Tr = char_traits<Ch>, class A = allocator<Ch> > class basic_string { public: // ... // size, capacity, etc. // size_type size() const; // number of characters size_type max_size() const; // largest possible string size_type length() const { return size(); } bool empty() const { return size()==0; } void resize(size_type n, Ch c); void resize(size_type n) { resize(n,Ch()); } size_type capacity() const; // like vector: void reserve(size_type res_arg = 0); // like vector allocator_type get_allocator() const; }; Példa 45 ========= template<class Ch, class Tr, class A> basic_istream<Ch,Tr>& operator>>(basic_istream<Ch,Tr>&, basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>&,const basic_string<Ch,Tr,A>&); template<class Ch, class Tr, class A> basic_istream<Ch,Tr>& getline(basic_istream<Ch,Tr>&, basic_string<Ch,Tr,A>&, Ch eol); template<class Ch, class Tr, class A> basic_istream<Ch,Tr>& getline(basic_istream<Ch,Tr>&, basic_string<Ch,Tr,A>&); Példa 46 ========= template<class Ch, class Tr, class A> void swap(basic_string<Ch,Tr,A>&, basic_string<Ch,Tr,A>&); Példa 47 ========= char* strcpy(char* p, const char* q); // copy from q into p (incl. terminator) char* strcat(char* p, const char* q); // append from q to p (incl. terminator) char* strncpy(char* p, const char* q, int n); // copy n char from q into p char* strncat(char* p, const char* q, int n); // append n char from q to p size_t strlen(const char* p); // length of p (not counting the terminator) int strcmp(const char* p, const char* q); // compare: p and q int strncmp(const char* p, const char* q, int n); // compare first n char char* strchr(char* p, int c); // find first c in p const char* strchr(const char* p, int c); char* strrchr(char* p, int c); // find last c in p const char* strrchr(const char* p, int c); char* strstr(char* p, const char* q); // find first q in p const char* strstr(const char* p, const char* q); char* strpbrk(char* p, const char* q); // find first char from q in p const char* strpbrk(const char* p, const char* q); size_t strspn(const char* p, const char* q); // number of char in p before any char in q size_t strcspn(const char* p, const char* q); // number of char in p before a char not in q Példa 48 ========= void f(const char* pcc, char* pc) // C++ { *strchr(pcc,'a') = 'b'; // error: cannot assign to const char *strchr(pc,'a') = 'b'; // ok, but sloppy: there might not be an 'a' in pc } Példa 49 ========= char* strchr(const char* p, int c); /* C standard library function, not C++ */ void g(const char* pcc, char* pc) /* C, will not compile in C++ */ { *strchr(pcc,'a') = 'b'; /* converts const to non-const: ok in C, error in C++ */ *strchr(pc,'a') = 'b'; /* ok in C and C++ */ } Példa 50 ========= void f(char* p, char* q) { if (p==q) return; // pointers are equal if (strcmp(p,q)==0) { // string values are equal int i = strlen(p); // number of characters (not counting the terminator) // ... } char buf[200]; strcpy(buf,p); // copy p into buf (including the terminator) // sloppy: will overflow some day. strncpy(buf,p,200); // copy 200 char from p into buf // sloppy: will fail to copy the terminator some day. // ... } Példa 51 ========= double atof(const char* p); // convert p to double int atoi(const char* p); // convert p to int long atol(const char* p); // convert p to long Példa 52 ========= int isalpha(int); // letter: 'a'..'z' 'A'..'Z' in C locale (_string.traits_, _io.locale_) int isupper(int); // upper case letter: 'A'..'Z' in C locale (_string.traits_, _io.locale_) int islower(int); // lower case letter: 'a'..'z' in C locale (_string.traits_, _io.locale_) int isdigit(int); // decimal digit: '0'..'9' int isxdigit(int); // hexadecimal digit: '0'..'9' or 'a'..'f' or 'A'..'F' int isspace(int); // ' ' '\t' '\v' return newline formfeed int iscntrl(int); // control character (ASCII 0..31 and 127) int ispunct(int); // punctuation: none of the above int isalnum(int); // isalpha() | isdigit() int isprint(int); // printable: ascii ' '..'~' int isgraph(int); // isalpha() | isdigit() | ispunct() int toupper(int c); // uppercase equivalent to c int tolower(int c); // lowercase equivalent to c Példa 53 ========= if (('a'<=c && c<='z') || ('A'<=c && c<='Z')) { // alphabetic // ... }