C++自修入門實境秀、C++ Primer 5版研讀秀 58/ ~ v9循序容器-9.6. Container Adaptors





頁364

練習9.43

#include<string>

#include<iostream>

using namespace std;

string replaceExercise9_43(string s, string oldVal, string newVal) {

string::const_iterator iter = s.cbegin();

string::const_iterator iterOld = oldVal.cbegin();

string::const_iterator sB;

while (iter != s.cend())

{

if (*iter == *iterOld) {

sB = iter;

++iter;

++iterOld;

while (iterOld != oldVal.cend() && iter != s.cend())

{

if (*iter != *iterOld) break;

++iter;

++iterOld;

}

if (iterOld == oldVal.cend())//表示找到

{//迭代器(iterator)在編輯元素後就可能失效:

iter=s.erase(sB, iter);

iter=s.insert(sB, newVal.cbegin(), newVal.cend());

}

iterOld = oldVal.cbegin();

}

++iter;

}

return s;

}



int main() {

//const string s = "I decided the thru only way to make it thru the tournament and all the highs and lows was to make him a warrior.";

//string sNew = replaceExercise9_43(s, "thru", "through");

const string s = "His performance was remarkable, tho , given that tho he was playing through the pain barrier.";

string sNew = replaceExercise9_43(s, "tho", "though");

if (s != sNew)

cout << sNew << endl;

}

1:3:50

練習9.44

#include<string>

#include<iostream>

using namespace std;

string replaceExercise9_44(string s, string oldVal, string newVal) {

string::size_type iter (0);

string::size_type iterOld (0);

string::size_type sB;// (0);

while (iter != s.size())

{

if (s[iter] == oldVal[iterOld]) {

sB = iter;

++iter;

++iterOld;

while (iterOld != oldVal.size() && iter != s.size())

{

if (s[iter] != oldVal[iterOld]) break;

++iter;

++iterOld;

}

if (iterOld == oldVal.size())//表示找到

{//index沒有迭代器(iterator)在編輯元素後失效的問題:

s.replace(sB, oldVal.size(), newVal);

}

iterOld = 0;

}

++iter;

}

return s;

}



int main() {

//const string s = "I decided the thru only way to make it thru the tournament and all the highs and lows was to make him a warrior.";

//string sNew = replaceExercise9_44(s, "thru", "through");

const string s = "His performance was remarkable, tho , given that tho he was playing through the pain barrier.";

string sNew = replaceExercise9_44(s, "tho", "though");

if (s != sNew)

cout << sNew << endl;

}

練習9.45

1:18:20

#include<string>

#include<iostream>

using namespace std;

string Exercise9_45(string name, string prefix, string suffix) {

string::const_iterator iter = name.cbegin();

name.insert(name.insert(iter, prefix.cbegin(), prefix.cend())+prefix.size(), ' ');

name.append(" ");

name.append(suffix.cbegin(), suffix.cend());

return name;

}



int main() {

const string s = "Sun";

cout << Exercise9_45(s, "Mr.", "III") << endl;

}

1:39:20

練習9.46

練習9.46 :使用一個位置和長度改寫前面的練習,以管理string。這次僅使用insert函式。

管理→處理。

#include<string>

#include<iostream>

using namespace std;

string Exercise9_44(string name, string prefix, string suffix) {

string::size_type iter{ 0 };

name.insert(iter, prefix);

name.insert((name.insert((name.insert(prefix.size(), " ")).size(), " ")).size(), suffix);

return name;

}



int main() {

const string s = "Sun";

cout << Exercise9_44(s, "Mr.", "III") << endl;

}


1:48:40

9.5.3. string Search Operations

9.5.3 string搜尋運算

對字串的尋找、檢索

string類別定義了六種檢索字串的函式,每一種又各有4個重載/多載的函式

詳見表9.14(頁365)

search的成員函式回傳的是找到位置的索引值:

Each of these search operations returns a string::size_type value that is the index of where the match occurred.

If there is no match, the function returns a static member (§ 7.6 , p. 300 ) named string::npos .

npos應是no position的意思

string程式庫類別中的靜態成員

The library defines npos as a const string::size_type initialized with the value -1 .

Because npos is an unsigned type, this initializer means npos is equal to the largest possible size any string could have (§ 2.1.2 , p. 35 ).

程式庫將 npos 定義為了一個 const string: : size_ type,並以-1這個值初始化。因為npos是unsigned型別,這個初始器意味著npos等於 string可以有的最大可能大小(§2.1.2)(頁35)。

•如果我們指定一個範圍外的值給無號型別的一個物件,結果就會是以目標型別所能存放 的值之數目,對該值進行模數(modulo)運算之後的餘數(remainder)。舉例來說, 一個8-bit的unsigned char能夠持有從0到255的值(包括兩端點)。如果我們指定 了這個範圍外的值,編譯器就會用那個值除以256之後的餘數來指定。因此,指定-1 給一個8-bit的unsigned char會賦予該物件255的值。(頁35)

string name("AnnaBelle");

auto pos1 = name.find("Anna"); // pos1 == 0

安娜貝爾

2:19:00

頁365

2:20:00

只要是string相關的運算都是區分大小寫的

2:9:10

Table 9.14. string Search Operations

表9.14 : string搜尋運算

捜尋運算會回傳所找的字元之索引,或在沒找到時回傳npos

s.find(args) 在s中找出args第一個出現處。

s.rfind(args) 在s中找出args的最後一個出現處。

s.find_first_of(args) 在s中找出args中任何字元的第一個出現處。

s.find_last_of(args) 在s中找出args中任何字元的最後一個出現處。

s.find_first_not_of(args) 在s中找出不在args中的第一個字元。 s.find_last_not_of(args) 在s中找出不在args中的最後一個字元。

args必須是下列之一

c、pos 在s中從位置pos開始的地方找尋字元c。pos預設為0。

s2 、 pos 在s中從位置pos開始的地方找尋s2這個string。pos預設為0。

cp、pos 尋找指標cp所指的C-style null-terminated字串。從s中位置pos開 始查看。pos預設為0。

cp、pos、n 尋找指標cp所指的陣列中的前n個字元。從s中位置pos開始查看。 pos或n沒有預設值。

rfind,r應是reverse或right(to left)之意

Specifying Where to Start the Search

指定開始搜尋處

指定從哪裡開始找

頁366

Searching Backward

2:36:33

2:45:30

9.5.4. The compare Functions

字串的比較

頁367

習題章節9.5.3

練習9.47

中文版誤作「9.4.7」

2:51:10

#include<string>

#include<iostream>

using namespace std;

void find數字和字母Exercise9_47(string str) {

string number{ "0123456789" };

string alpha("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");

string::size_type pos{ 0 };

while ((pos = str.find_first_of(number, pos)) != string::npos)

{

cout << "number index is " << pos << endl;

++pos;

}

pos = 0;

while ((pos = str.find_first_of(alpha, pos)) != string::npos)

{

cout << "alphabetic index is " << pos << endl;

++pos;

}

}

void findnot數字和字母Exercise9_47(string str) {

string number{ "0123456789" };

string alpha("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");

string::size_type pos{ 0 };

while ((pos = str.find_first_not_of(number, pos)) != string::npos)

{

cout << "alphabetic index is " << pos << endl;

++pos;

}

pos = 0;

while ((pos = str.find_first_not_of(alpha, pos)) != string::npos)

{

cout << "number index is " << pos << endl;

++pos;

}

}



int main() {

find數字和字母Exercise9_47("ab2c3d7R4E6");

findnot數字和字母Exercise9_47("ab2c3d7R4E6");

}

3:11:50

練習9.48

#include<string>

#include<iostream>

using namespace std;

int main() {

string numbers("0123456789"), name("r2d2");

// returns 1, i.e., the index of the first digit in name

auto pos = name.find_first_of(numbers);

string::size_type p = numbers.find(name);

if (p==string::npos)

{

cout << "no position!" << endl;

}

}

3:18:30

練習9.49

中文版又漏翻了:

Exercise 9.49: A letter has an ascender if, as with d or f, part of the letter extends above the middle of the line. A letter has a descender if, as with p or g, part of the letter extends below the line. Write a program that reads a file containing words and reports the longest word that contains neither ascenders nor descenders.

練習9.49 :如果一個字母的某部分延伸到中線之上,我們就說這個字母有一個ascender (出頭部分),例如d或f ;如果一個字母的某部分延伸到中線之下,我們就說這個字母有一個 descender (伸尾部分)。寫一個程式讀取含有字詞的一個檔案,並回報既不含有ascender也 沒有descender的最長字詞。

as with p or g,漏掉沒翻

3:23:40

#include<string>

#include<vector>

#include<iostream>

#include<fstream>

using namespace std;

int main() {

string descender("gjpqy"), ascender("bdfhklt"),word;

ifstream ifstm("V:\\Programming\\C++\\1.txt");

vector<string> vecStr,vec;

while (ifstm>>word)

{

vecStr.push_back(word);

}

for (string s : vecStr) {

auto pos = s.find_first_of(descender);

string::size_type p = s.find_first_of(ascender);

if (pos==string::npos && p==string::npos )

{

vec.push_back(s);

}

}

string str,ss;

for (string s:vec)//已經吻合條件的字詞

{

if (str.size() > s.size()) {

if (str.size() > ss.size())

ss = str;

}

else if (s.size() > str.size()) {

if (s.size() > ss.size())

ss = s;

}

else

if (ss == "") ss = str;

str = s;

}

cout << ss << endl;

}

3:54:00

Table 9.15. Possible Arguments to s.compare

3:59:00

表9.15 : s.compare可能的引數

s2 把s與s2做比較。

posl、n1、s2 把s從posl開始的nl個字元與s2做比較。

posl、nl、s2、pos2、n2 把s從posl開始的nl個字元與s2中從pos2開始的n2個 字元做比較。

cp 把s與cp所指的null-terminated陣列做比較。

posl、nl、cp 把s從posl開始的nl個字元與cp做比較。

posl、nl、cp、n2 把s從posl開始的nl個字元與從指標cp開始的n2個字元 做比較。

4:1:30

9.5.5. Numeric Conversions

9.5.5數值轉換

In general, the character representation of a number differs from its numeric value.

一般來說,一個數字的字元表示值 (character representation)會與它的數值(numeric value)不同。

The numeric value 15 stored in a 16-bit short has the bit pattern 0000000000001111 , whereas the character string "15" represented as two Latin-1 char s has the bit pattern 0011000100110101 .

The first byte represents the character '1' which has the octal value 061, and the second byte represents '5' , which in Latin-1 is octal 065.

4:10:50

int i = 42;

string s = to_string(i); // converts the int i to its character representation

double d = stod(s); // converts the string s to floating-point

stod意謂 string to double



頁368

Table 9.16. Conversions between strings and Numbers

表9.16 :在string和數字之間的轉換

to_string(val); 回傳val的string表示值的重載函式。val可以是任何算術型別 (§2.1.1,頁32)。每個浮點型別都有自己版本的to_string,而int或更大 的整數型別也有。一如以往,小型的整數型別會被提升(§4.11.1,頁160)。

stoi (s, p, b) stol (s, p, b) stoul (s, p, b) stoll (s, p, b) stoull(s, p, b) 將s中有數值內容的初始子字串分別回傳為一個int、long、 unsigned long 、 long long 、 unsigned long long。b 代表用於 轉換的數值基數(numeric base) ;b預設為10。p是對size_t的一 個指標,其中放置s中第一個非數值字元的索引;p預設為0,在那種情 況中,函式不會儲存索引。Return the initial substring of s that has numeric content as an int,long, unsigned long, long long, unsigned long long, respec-tively. b indicates the numeric base to use for the conversion; b defaults to 10. p is a pointer to a size_t in which to put the index of the first nonnumeric character in s; p defaults to 0, in which case the function does not store the index.

stof(s, p)

stod(s, p) stold(s, p) 將s中的初始數值子字串分別回傳為一個float、double或long double。p的行為與整數轉換中所描述的相同。

p的行為與整數轉換中所描述的相同。「整數」指表格中上一列stoi、stol、……等所述者。

b預設為10應該是指十進位。

p是對size_t的一個指標,其中放置s中第一個非數值字元的索引→p是指篇一個size_t型別的指標,此型別的值是在s中第一個非數值字元的索引值

4:44:00

The first non-whitespace character in the string must be a sign ( + or - ) or a digit. The string can begin with 0x or 0X to indicate hexadecimal.

For the functions that convert to floating-point the string may also start with a decimal point ( . ) and may contain an e or E to designate the exponent.

For the functions that convert to integral type, depending on the base, the string can contain alphabetic characters corresponding to numbers beyond the digit 9.16進位9後面就是abcdef

( + or - )應該是翻成正負號,而不是加減號

小心擲出的例外:

Note:

If the string can’t be converted to a number, These functions throw an invalid_argument exception (§ 5.6, p. 193). If the conversion generates a value that can’t be represented, they throw out_of_range.

頁369

4:59:55

9.6. Container Adaptors

9.6容器轉接器

程式庫定義了3個適配器

In addition to the sequential containers, the library defines three sequential container adaptors: stack , queue , and priority_queue .

An adaptor is a general concept in the library.

There are container, iterator, and function adaptors.

Essentially, an adaptor is a mechanism for making one thing act like another.

5:5:20

習題章節9.5.5

練習9.50

5:11:10

#include<string>

#include<vector>

#include<iostream>

using namespace std;

int main() {

/*vector<string> vecS{"2","-21","11","5","3"};

int i=0;

for (string s : vecS)

i+=stoi(s);

cout << i << endl;*/

vector<string> vecS{ "2","-21","11","5","3" };

float f = 0;

for (string s : vecS)

f += stof(s);

cout << f << endl;

}

5:22:20

練習9.51

6:17:00

exercise9_51.h:

#ifndef EXERCISE9_51_H

#define EXERCISE9_51_H

#include<string>

#include<vector>

using namespace std;

class EXERCISE9_51 {

unsigned y = 0;

unsigned m = 0;

unsigned d = 0;

public:

EXERCISE9_51() : y(2019), m(1), d(1) {}

EXERCISE9_51(string date) {

//January 1, 1900

//Jan 1, 1900

//1/1/1900

//找月份

vector<string>mon{ "January","February","March","April","May","June","July","August","September","October","November","December" };

string::size_type i = 0;

for (string s : mon) {

if (date.find(s) != string::npos) {

m = i + 1;

break;

}

++i;

}

//找不到 m==0

//找日期

string::size_type half_space = date.find(" ");

string::size_type comma = date.find(",");

if (half_space != string::npos)

{

if (comma != string::npos)

{

d = stoul(date.substr(half_space + 1, comma - half_space));

}

}

//找年份

if (comma != string::npos)

{

if (comma + 1 < date.size())

y = stoul(date.substr(comma + 1));

}

if (m == 0) {//還沒找到月份的話

mon={ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };

i = 0;

for (string s : mon) {

if (date.find(s) != string::npos) {

m = i + 1;

break;

}

++i;

}

}

string::size_type slash = date.find("/");

if (m == 0) {//還沒找到月份的話

if (slash != string::npos) {

m = stoul(date.substr(0, slash));

}

}

string::size_type slash1 = date.find("/", slash + 1);

if (d == 0) {

if (slash!=string::npos)

{

d = stoul(date.substr(slash + 1, slash1- slash));

}

}

if (y == 0) {

if (slash1!=string::npos)

{

y = stoul(date.substr(slash1 + 1));

}

}

}

};

#endif



Run:

#include<string>

#include<vector>

#include<iostream>

#include"exercise9_51.h"

using namespace std;

int main() {

EXERCISE9_51 e;

EXERCISE9_51 e1("January 1, 1920");

EXERCISE9_51 e2("Feb 11, 1900");

EXERCISE9_51 e3("11/1/1995");

}


留言

熱門文章