STRING_study

8389 ワード

STL_STRING
1.なぜstringクラスを学ぶのか
1.1 C言語では、文字列は'0'で終わるいくつかの文字の集合であり、操作を容易にするために、C標準ライブラリにはstrシリーズのライブラリ関数がいくつか提供されていますが、これらのライブラリ関数は文字列とは分離されています.OOP(オブジェクト向けプログラミング(Object Oriented Programming,OOP,オブジェクト向けプログラミング)はコンピュータプログラミングアーキテクチャ)の考え方にあまり合っていません.また、下位空間はユーザー自身が管理する必要があります.うっかりすると、境界を越えてアクセスする可能性があります.
2.標準ライブラリのstringクラス
2.1 stringクラス
1.文字列は文字列を表すクラス
2.標準文字列クラスでは、標準文字コンテナのようなインタフェースをサポートしますが、操作に特化したインタフェースが追加されています.
シングルバイト文字列の設計特性.
3.stringクラスはchar(つまり、その文字タイプとして、そのデフォルトchar_traitsとディスペンサタイプ(テンプレートの詳細について)を使用します.
詳細はbasic_を参照してください.string).
4.stringクラスはbasic_stringテンプレートクラスのインスタンスです.charを使用してbasic_をインスタンス化します.stringテンプレートクラス、char_traits
とallocatorをbasic_としてstringのデフォルトパラメータ(より多くのテンプレート情報に基づいてbasic_stringを参照).
なお、このクラスは、使用される符号化とは独立してバイトを処理する:UTF-8などのマルチバイトまたは長文字のシーケンスを処理するために使用される場合、
クラスのすべてのメンバー(長さやサイズなど)とその反復器は、実際に符号化された文字ではなくバイトで動作します.
まとめ:
1.stringは文字列を表す文字列クラス
2.このクラスの言い訳は、通常のコンテナのインタフェースと基本的に同じであり、stringを操作するための通常の操作を追加する.
3.stringは最下位で実際には:basic_stringテンプレートクラスの別名、typedef basic_string string;
4.マルチバイトや長い文字のシーケンスを操作することができない.
stringクラスを使用する場合は、#includeヘッダファイルとusing namespace stdを含む必要があります.
2.2 stringクラスの共通インタフェースの説明
1.stringクラスオブジェクトの一般的な構造
//string  
/void main()
{
	//C  
	char str1[] = { 'a', 'b', 'c', '\0' };
	cout << str1 << endl;
	char *str2 = "bit";
	cout << str2 << endl;
	string str3("abc");
	cout << "str1 len=" << strlen(str1) << endl;
	cout << "str3 len=" << str3.size() << endl;
	cout << "str3 len=" << str3.length() << endl;
}

1.string()空のstringクラスオブジェクト、すなわち空の文字列を構築する
//string()
	string str1;//      
	cout << str1 << endl;

2.stringクラスオブジェクトをC-stringで構築する
//string(const char* s)
	const char *s = "Hello world";// Cstring  string   
	//string str2(s);
	cout << "str2 = " << str2 << endl;

3.stringクラスオブジェクトにn文字cを含む
//string(size_t n,char *s)
	string str4(10, 'a');//string      n   a
	cout << "str4 = " << str4 << endl;

4.コピーコンストラクタ
//string(const string&s)
	string str5(str3);//    
	cout << "str5 = " << str5 << endl;

2.stringクラスオブジェクトの容量操作
string str("Hello world");
	cout << "size = " << str.size() << endl;//            \0
	cout << "length = " << str.length() << endl;//        
	cout << "capacity = " << str.capacity() << endl;
	cout << "empty = " << str.empty() << endl;//      
	str.clear();// str       ,        size 0,          
	cout << "size = " << str.size() << endl;
	cout << "capacity = " << str.capacity() << endl;//       
	const char *str2 = "Hello";
	string str3(str2);
	str3.resize(10, 'b');//  s          10 ,     'b'    ,      
	cout << "str3 = " << str3 << endl;
	str3.reserve(100);//
	cout << "size = " << str3.size() << endl;
	cout << "capacity = " << str3.capacity() << endl;
	//  reserve    string        ,        
	str3.reserve(50);
	cout << "size = " << str3.size() << endl;
	cout << "capacity = " << str3.capacity() << endl;

まとめ:
1.size()はlength()法の下地実装原理と全く同じである、size()を導入したのは他の容器の言い訳と一致するためであり、半分の場合は基本的にsize()を用いる.
2.clear()はstringの有効文字をクリアするだけで、下位空間の大きさを変更しない.
3.resize(size_t n)とresize(size_t n,char c)は、文字列の有効文字数をn個に変更します.異なるのは、文字数が多くなると、resize(n)は0で多くの要素空間を埋め、resize(size_t n,char c)は文字cで多くの要素空間を埋めます.
要素空間.注意:resizeは、要素の数を変更するときに、要素の数を増やすと、最下位の容量の大きさを変更する可能性があります.
小さい、エレメントの個数を減らす場合、下位空間の合計サイズは変更されません.
  • reserve(size_t res_arg=0):stringのために空間を予約し、有効要素の個数を変更しない.reserveのパラメータが
  • 未満である場合.
    stringの下位空間の合計が小さい場合、reserverは容量の大きさを変更しません.
  • stringクラスオブジェクトへのアクセスおよび遍歴操作
    void main()
    {
    	string str = "hello world";
    	cout << "str = " << str << endl;//    
    	//operator[]         
    	for (int i = 0; i < str.size(); i++)
    		cout << str[i];
    	cout << endl;
    
    	//C++11            ++
    	for (auto &e : str)//         str        ,  &     ,        ,      .
    		cout << e;
    	cout << endl;
      //    iteraror
    	string::iterator it = str.begin();//    
    	while (it != str.end())
    	{
    		cout << *it;
    		++it;
    	}
    	cout << endl;
    	//     
    	/*string::reverse_iterator rit = str.rbegin();//    
    	while(rit != str.rend())
    	{
    		cout << *rit;
    		++rit;
    	}
    	cout << endl;
    }
    
  • stringクラスオブジェクトの修正操作push_back文字列後尾に文字c appendを挿入文字列後に文字列operator+=(ポイント)文字列後に文字列str c_を追加str(アクセント)は、C形式の文字列fififind+npos(アクセント)を返し、文字列posの位置から文字cを後にし、文字列中の位置rfifindを返し、文字列posの位置から文字cを前にし、文字列中の位置substrを返し、strの中でposの位置からn文字を切り取り、それを返す.

  • void main()
    {
    	string str;
    	str.push_back('a');//   
    	str.append("a");//    
    	str += 'b';
    	str += "b";
    	cout << str << endl;
    	cout << str.c_str() << endl; //  C          
    	string email("[email protected]");
    	size_t pos = email.find('@');//       ,             .
    	if (pos != string::npos)
    	{
    		cout << "pos = " << pos << endl;
    	}
    	else
    		cout << "not find" << endl;
    	//  
    	string email_type;
    	size_t strat_pos = email.find('@');
    	size_t end_pos = email.rfind('.');
    	email_type = email.substr(strat_pos+1, end_pos-strat_pos-1);
    	cout << email_type << endl;
    }
    

    注意:
  • string末尾に文字を追加する場合、s.push_back©/s.append(1,c)/s+='c'の3つの実装方式の差は一般的ではない
  • 場合stringクラスの+=操作が多く、+=操作は単一の文字だけでなく文字列にも接続できます.
  • 対string操作の場合、どのくらいの文字を入れるかを概算できるなら、まずreserveで空間を予約することができる.
  • stringクラス非メンバー関数operator+は、値が返されるため、できるだけ少なく使用します.深いコピー効率が低いoperator>(アクセント)入力演算子を再ロードoperator<(アクセント)出力演算子を再ロードgetline(重点)1行の文字列relational operatorsサイズ比較
    //void main()
    //{
    //	string s1;
    //	getline(cin, s1);//      
    //	cout << s1 << endl;
    //}
    //void main()
    //{
    //	string s1("hello");
    //	string s2("world");
    //	bool res = (s1 > s2);//       
    //}
    
    2.stringクラスのシミュレーション実装1.浅いコピーと深いコピー浅いコピー:値コピーとも呼ばれ、コンパイラはオブジェクトの値をコピーするだけです.オブジェクトにリソースがある場合は.(スタック上のメモリ)では、最後に複数のオブジェクトが同じリソースを共有することになり、1つのオブジェクトが破棄されるとそのリソースが解放するが、他のオブジェクトはそのリソースが解放されたことを知らず、まだ有効であると考えているため、スタックリソースの操作を継続すると不正アクセスが発生する.深いコピー:クラスにリソースの管理が含まれている場合は、共有リソースによって複数のオブジェクト間で複数回解放されるプログラムのクラッシュの問題が発生しないように、各オブジェクトに独立したリソースを割り当てる必要があります.クラス内のリソースの管理に関連する場合、そのコピー構造関数、コピー演算子の再ロード、および構造解析関数は明示的に指定する必要があります.一般的には、深いコピー方式で提供されます.書き込みコピー:一、書き込みコピーとは何ですか.つまり、あなたが空間を読み取ると、システムはあなたのために同じ空間を開くことはありません.あなたが本当に修正したときだけ、空間を開いてあげます.二、書き込み時のコピーをどのように実現しますか.(1)、参照カウントを使用して実装されます.したがって、空間を割り当てる際に、この空間を指すポインタが何個あるかを記録するために、4バイト以上割り当てる必要があります.(2)、新しいポインタがこの空間を指す場合、参照カウントは1つ加算され、1つのポインタがこの空間を解放する場合、参照カウントは1つ減算されます.(3)、ポインタがこの空間を修正しようとすると、そのポインタに自分の空間を再割り当てし、元の空間の参照カウントを1つ減らし、新しい空間の参照カウントを1つ加える.練習問題344.反転文字列
    class Solution {
    public:
        void reverseString(vector& s) {
            size_t start = 0, end = s.size() - 1;
            while (start < end)
                swap(s[start++], s[end--]);
        }
    };
    
    387.文字列の最初の一意文字
    class Solution {
    public:
        int firstUniqChar(string s) {
            int count[256]={0};
            int size = s.size();
            for(int i=0;i
  • コピー構築シミュレーションの実装
    class String
    {
    public:
    	/*String()
    	:_str(new char[1])
    	{*_str = '\0';}
    	*/
    	//String(const char* str = "\0")     
    	//String(const char* str = nullptr)     
    	String(const char* str = "")
    	{
    		//   string    ,    nullptr  ,      ,     
    		if (nullptr == str)
    		{
    			assert(false);
    			return;
    		}
    
    		_str = new char[strlen(str) + 1];
    		strcpy(_str, str);
    	}
    	~String()
    	{
    		if (_str)
    		{
    			delete[] _str;
    			_str = nullptr;
    		}
    	}
    private:
    	char* _str;
    };
    void main()
    {
    	string s("hello bit");
    	string s1(s);
    }