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");
}
留言