string

Prerequisites:

string物件

  • 動態分配記憶體位址存放一組字元
  • 自動建立記憶體位址與釋放記憶體位址,使用時程式設計師不用做釋放記憶體的動作
  • 自動擴展容量
  • 底層以ArrayList實作

string記憶體擴充

string底層是ArrayList實作。

以下程式碼證明string記憶體擴充後,capacity(最大容量)會呈倍數成長。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
int main() {
  //建立空的字串,呼叫string()空的建構子
  string s1;
  //印出string
  cout << "s1 = " << s1 << endl;
  //容量
  cout << "s1.capacity() = " << s1.capacity() << endl;
  //實際用了多少
  cout << "s1.size()" << s1.size() << endl;
  //s1的記憶體位址
  cout << "s1記憶體位址 = " << (void*)s1.c_str() << endl;
  cout << "----------------------------" << endl;
  //記憶體擴展
  //25個字元(Hello 5字元*5遍)
  s1 = "HelloHelloHelloHelloHello";
  //印出string
  cout << "s1 = " << s1 << endl;
  //容量
  cout << "s1.capacity() = " << s1.capacity() << endl;
  //實際用了多少
  cout << "s1.size()" << s1.size() << endl;
  //s1的記憶體位址
  cout << "s1記憶體位址 = " << (void*)s1.c_str() << endl;
  return 0;
}
s1 = 
s1.capacity() = 22
s1.size()0
s1記憶體位址 = 0x7ff7bfeff451
----------------------------
s1 = HelloHelloHelloHelloHello
s1.capacity() = 47
s1.size()25
s1記憶體位址 = 0x600000c00120

從執行結果可以看出

  • capacity(最大容量)呈倍數成長,從22變成47。
  • 記憶位址不同,從0x7ff7bfeff451變成0x600000c00120

    建立一個容量是47的記憶體空間,把s1的值從容量22的記憶體空間搬到容量47的記憶體空間,搬完後把容量22的記憶體空間進行記憶體釋放,所以記憶體位址才會不同。

string建構子為c字串

語法

建構子參數為c字串

string(const char *s) 

呼叫建構子

方式1

string s2("Hello world!");

方式2

string s3 = "Hello World!";

完整程式碼

1
2
3
4
5
6
7
8
9
10
#include <iostream>
using namespace std;
int main() {
	// 方式1
  string s2("Hello world!");
  cout << "s2 = " << s2 << endl;
  // 方式2
  string s3 = "Hello World!";
  cout << "s3 = " << s3 << endl;
}
s2 = Hello world!
s3 = Hello World!

string拷貝函式

拷貝函式用於從另一個已經存在的string物件來初始化新物件。

語法

string(const string &str)

方式1

1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main() {
  string s2("Hello world!");
  cout << "s2 = " << s2 << endl;
  string s3 = s2;
  cout << "s3 = " << s3 << endl;
}
s2 = Hello world!
s3 = Hello world!

方式2

1
2
3
4
5
6
7
int main() {
  string s1 = "Hello world";
  string s2(s1);
  cout << "s2 = " << s2 << endl;
  cout << "s2 size = " << s2.size() << endl;
  return 0;
}
s2 = Hello world
s2 size = 11

string assign operator=()

物件已經存在的情況下,將一個新值賦給該物件,會啟動assign operator=()

1
2
string s3;
s3 = "Hello World!";

字串連接

operator+=

// string
string& operator+= (const string& str);
// char*
string& operator+= (const char* s);
// character
string& operator+= (char c);
// initializer list
string& operator+= (initializer_list<charT> il);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <cstring>
using namespace std;
int main() {
  string s1 = "Hello";
  string s2 = "hi";
  // const char*
  s1 += " Mary!";
  // string
  s1 += s2;
  // character
  s1 += 'A';
  cout << "s1 = " << s1 << endl;
  return 0;
}
s1 = Hello Mary!hiA

append

// char*
string &append(const char *s);
// string
string &append(const string &str);
1
2
3
4
5
6
7
8
9
10
int main() {
  string s1 = "Hello";
  // char*
  s1.append(" world!");
  string s2 = " Hi, Mary!";
  // string
  s1.append(s2);
  cout << "s1 = " << s1 << endl;
  return 0;
}
s1 = Hello world! Hi, Mary!

建構子參數為c字串與n個字元

n小於c字串的長度

目的

從c字串的位址開始複製n個字元,建立字串。

語法

  • 參數1為c字串
  • 數數2為複製n個字元
string(const char *s,size_t n);

完整程式碼

1
2
3
4
5
6
7
int main() {
	//從c字串的位址開始複製5個字元,建立字串
  string s("hello world", 5);
  cout << "s = " << s << endl;
  cout << "size = " << s.size() << endl;
  return 0;
}
s = hello
size = 5

n大於c字串的長度

從c字串的位址開始複製100個字元,建立字串。

從執行結果可以發現,並不會遇到\0結尾字元而停止複製,s物件的實際大小也是20字元。

1
2
3
4
5
6
7
int main() {
	//從c字串的位址開始複製20個字元,建立字串
  string s("hello world", 20);
  cout << "s = " << s << endl;
  cout << "size = " << s.size() << endl;
  return 0;
}
s = hello world = siz
size = 20

參數為string物件與拷貝開始與結束位置

以下是string的拷貝函式,拷貝開始位置(預設從0開始)與結束位置(預設unsigned int最大值)

string(const string & str, size_t pos = 0, size_t n = npos)
  • 參數1 string物件。
  • 參數2 拷貝開始位置(預設從0開始),可不寫。
  • 參數3 拷貝結束位置(預設unsigned int最大值),可不寫。

拷貝結束位置介於字元大小間

1
2
3
4
5
6
7
int main() {
  string s1 = "Hello world";
  string s2(s1,0,3);
  cout << "s2 = " << s2 << endl;
  cout << "s2 size = " << s2.size() << endl;
  return 0;
}
s2 = Hel
s2 size = 3

拷貝結束位置超出字元大小

從執行結果可以發現遇到\0結尾字元而停止複製,size仍是11,而不是100。

1
2
3
4
5
6
7
int main() {
  string s1 = "Hello world";
  string s2(s1,0,100);
  cout << "s2 = " << s2 << endl;
  cout << "s2 size = " << s2.size() << endl;
  return 0;
}
s2 = Hello world
s2 size = 11

建立多個相同字元的string

string(size_t n, char c)
  • 參數1個數
  • 參數2字元
1
2
3
4
5
6
int main() {
  string s1(100,'C');
  cout << "s1 = " << s1 << endl;
  cout << "s1 size = " << s1.size() << endl;
  return 0;
}
s1 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
s1 size = 100

string成員函式

取得string物件記憶體大小

size_t capacity() const;

取得string物件實際使用大小

以下二者相同

size_t length() const;
size_t size() const;
1
2
3
4
5
6
7
8
#include <iostream>
using namespace std;
int main() {
  string s1 = "123566";
  cout << "s1 length = " << s1.length() << endl;
  cout << "s1 size = " << s1.size() << endl;
  return 0;
}
s1 length = 6
s1 size = 6

strlen()是用於c字元陣列,並非string,使用strlen,需要把string轉成字元陣列指標

size_t strlen ( const char * str );
1
2
3
4
5
6
7
8
9
#include <iostream>
using namespace std;
int main() {
  string s1 = "123566";
  cout << "s1 length = " << s1.length() << endl;
  cout << "s1 size = " << s1.size() << endl;
  cout << "s1 strlen = " << strlen(s1.c_str()) << endl;
  return 0;
}
s1 length = 6
s1 size = 6
s1 strlen = 6

判斷實際使用的大小為0

若為0返回true

bool empty() const;

清空字串

void clear();

讀取string位置

使用[位置],可以取得某個位置字元

在 C++ 中,std::string 本質上是一個用於操作字元的容器,內部存儲的字元是一個連續的 char 陣列。

通過 s1[0],你可以訪問 std::string 中存儲的第一個字元。

&s1[0] 的含義:

  • s1[0] 返回的是第一個字元,型別是 char。
  • &s1[0] 取得的是該字元在內存中的地址,因此它的型別是 char*。
char &operator[](size_t n); 

取值

1
2
  string s1 = "Hello";
  cout << "s1[1] = " << s1[1] << endl;
s1[1] = e

取出位址

使用以下此法,傳回的是char*,是沒有const

1
2
  string s1 = "Hello";
  cout << "s1 address = " << (void*)&s1[0] << endl;
s1 address = 0x7ff7bfeff2d1

取得string物件存放字串的記憶體位址

&是取得物件的位址

以下是取得string物件中動態分配記憶體空間存放字串的位址,注意!傳回的是const char*,是有const

const char *c_str() const;
const char *data() const; 
1
2
3
4
5
6
7
8
9
int main() {
  string s1 = "Hello";
  //取得string物件的記憶體位址
  cout << "s1 & address = " << &s1 << endl;
  //取得string物件中動態分配記憶體空間存放字串的位址
  cout << "s1 c_str address = " << (void*)s1.c_str() << endl;
  cout << "s1 data address = " << (void*)s1.data() << endl;
  return 0;
}
s1 & address = 0x7ff7bfeff450
s1 c_str address = 0x7ff7bfeff451
s1 data address = 0x7ff7bfeff451

字串作為函式參數

參數語法

const string& str

以下函式參數的寫法,不僅可以接收c字串指標,也可以接收string類別

若函式參數為const char *,參數就只能接收c字串指標,string類別要再透過c_str()函式轉成c字串指標。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
void func1(const string& str) {
  cout << str << endl;
}
int main() {
  char * s1 = "http://www.google.com";
  //可以接受c字串指標
  func1(s1);
  string s2 = "被討厭的勇氣";
  //可以接受字串
  func1(s2);
  return 0;
}
http://www.google.com
被討厭的勇氣

字串截取

string substr(size_t pos = 0,size_t n = npos) const;
1
2
3
4
5
int main() {
  string s1 = "Hello";
  cout << "s1 = " << s1.substr(1,3) << endl;
  return 0;
}
s1 = ell

字串比較

bool operator==(const string &str1,const string &str2) const;
1
2
3
4
5
6
int main() {
  string s1 = "Hello";
  string s2 = "world";
  cout << "compare result = " << (s1 == s2) << endl;
  return 0;
}

清空

1
2
3
4
  string name = "Bill";
  cout << "name: " << name << endl;
  name.clear();
  cout << "name: " << name << endl;
name: Bill
name: 

resize()

若要對string記憶體位址操作,手動操作會使string本身的動態記憶體分配失效,要手動重新分配它的大小。

1
2
3
4
5
6
7
8
9
10
bool recv(string &buffer, const size_t maxlen) {
  buffer.clear();
  buffer.resize(maxlen);
  // 如果接收成功,recv()會傳回收到資料的大小,-1代表接收失敗,0代表socket斷線,大於0代表成功
  int readn = ::recv(client_fd, &buffer[0], buffer.size(), 0);
  if (readn <= 0) return false;
  // recv()會傳回收到資料的大小,重置大小
  buffer.resize(readn);
  return true;
}

string陣列

判斷數字,印出月份英文

1
2
3
4
5
6
7
8
9
10
11
12
13
//12個月
const int MAX_MONTH = 12;
int main() {
  string mon_arr[MAX_MONTH] =
    {"January", "February", "March", "April", "May", "June", 
     "July","August","September","October","November","December"};
  int month;
  cout << "請輸入數字月份(1~12):";
  cin >> month;
  //陣列索引介於0..11,所以要把month-1
  cout << mon_arr[month-1] << endl;
  return 0;
}
請輸入數字月份(1~12):1
January

其它更多成員函式

results matching ""

    No results matching ""