C++ 入門学習ノート ----- 第 17 章: 標準ライブラリの特別な機能

いくつかの標準ライブラリの使用:

1. タプルの型
ここに画像の説明を挿入
1.1. タプルの定義と初期化

tuple<int,int> t1;		//默认值初始化
tuple<int,string,vector<int>> t2(1,"a",{
    
    1,2});		//直接初始化
tuple<int, int> t3{
    
     1,2 };
auto t4 = make_tuple(1, "a");	//自动推断类型

タプルメンバーにアクセスする

tuple<int,string> t(1,"a");
auto item = get<0>(t);	//第一个元素
get<1>(t) = "b";

typedef decltype(t) v;
size_t sz = tuple_size<v>::value;			//tuple中成员数量,返回2
tuple_element<1,v>::type cnt = get<1>(t);	//cnt是一个int,获取指定元素的类型

関係演算子と等価演算子

为了使用tuple的相等或不等运算符,对每对成员使用==运算符必须都是合法的;
为了使用关系运算符,对每对成员使用<必须都是合法的。
tuple<int,int> t1(1,2);
tuple<int,int> t2(1,2);
bool b = (t1==t2);		
b = (t1<t2);
由于tuple定义了<==运算符,可以将tuple序列传递给算法,并且可以在无序容器中将tuple作为关键字类型。

1.2. タプルを使用して複数の値を返す

tuple<int, int> fun()
{
    
    
	return make_tuple(1, 2);
}

auto d = fun();
auto first = get<0>(d);

2.ビットセットタイプ

2.1. ビットセットの定義と初期化 ビット
ここに画像の説明を挿入
セットを符号なし値で初期化する

bitset<4> b(3);
bitset<128> b2(~0ULL);	前面64位补0,后面64位为1~0ULL之后全为1

文字列からビットセットを初期化する

bitset<8> bitvec("1100");	//2、3两位为1,剩余两位为0;
位值:0000 1100
bitset中的下标从低位到高位,顺序和字符串中的下标顺序是反的。

string s("1111111100000000");
bitset<32> b(s,5,4);	//从s[5]开始的四个二进制位
bitset<32> b2(s,s.size()-4);	//最后四个字符

ここに画像の説明を挿入
2.2. ビットセット操作

ここに画像の説明を挿入
3. 正規表現

ここに画像の説明を挿入
ここに画像の説明を挿入
3.1. 正規表現ライブラリの使用

string s("[0-9]+");
regex r(s);
smatch result;
string str = "b123de4567";
if(regex_search(str, result, r))
	cout << result.str();

[[::alpha::]]	匹配任意字母
[[::alpha::]]*	匹配零个或多个字母
[[::alpha::]]+	匹配一个或多个字母

正規表現オブジェクトのオプションを指定する
ここに画像の説明を挿入

编写程序识别文件扩展名:
//一个或多个字母或数字字符后接一个.再接cpp或cxx或cc
string p = "[[:alnum:]]+\\.(cpp|cxx|cc)$";
regex r(p, regex::icase);
smatch result;
string fileName;
while (cin >> fileName)
	if (regex_search(fileName, result, r))
		cout << result.str() << endl;

由于.是通配符,所以需要加反斜杠,反斜杠也是C++中的特殊字符,因此再加一个反斜杠

正規表現を指定または使用する際のエラー

一个正则表达式的语法是否正确是在运行时解析的。

regex_error成员:
what():错误信息
code():错误类型对应的数值编码

try
{
    
    
	regex r("[[:alnum:]]+\\.(cpp|cxx|cc)$",regex::icase);
}
catch(regex_error e)
{
    
    
	cout<<e.what()<<endl;
	cout<<e.code()<<endl;
}

ここに画像の説明を挿入
ここに画像の説明を挿入
正規表現クラスと入力シーケンス タイプ
ここに画像の説明を挿入

输入类型要匹配:处理什么输入序列类型,用什么类型的表达式类
string p = "[[:alnum:]]+.(cpp|cxx|cc)$";
regex r(p, regex::icase);
smatch result;
string fileName;
while (cin >> fileName)
	if (regex_search(fileName, result, r))	//这里的result只能是smatch,不能是cmatch等其他类型
		cout << result.str() << endl;


ここに画像の説明を挿入ここに画像の説明を挿入
3.2. sregex_iterator を使用したRegex イテレーター型とのマッチング

查找字符串中的数字串
string p = "[0-9]+";
regex r(p);
smatch result;
string str = "abc123efo345op";
sregex_iterator end;
for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it)
{
    
    
	cout << it->str() << endl;
	cout <<"前子串"<<it->prefix().str() << "长度" << it->prefix().length() << endl;
	cout <<"后子串"<<it->suffix().str() << "长度" << it->suffix().length() << endl;
}

マッチングデータの使用
ここに画像の説明を挿入
3.3. 部分式の使用

string p = "([0-4]+)([5-9]+)";	//一个小括号代表一个子表达式,两个子表达式
regex r(p);
smatch result;
string str = "abc123789efo345op";
sregex_iterator end;
for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it)
{
    
    
	cout << it->str() <<" First: "<<it->str(1) << " Second: "<<it->str(2) <<endl;
}
例如:匹配的一个子串:123789str(0)),子串中第一个子表达式是123str(1)),第二个子表达式是789str(2)str(0)是第一个子匹配位置,表示整个模式对应的匹配

データ検証用の部分式

string p = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ]?)(\\d{4})";
regex r(p);
smatch result;
string str = "abcd(123).123.1324";
sregex_iterator end;
for (sregex_iterator it(str.begin(), str.end(), r); it != end; ++it)
{
    
    
	cout << it->str() << endl;	//匹配(123).123.1324
	valid(*it);	//验证
}
(\\()?  		:匹配(
(\\d{
    
    3})		:匹配3个数字
(\\))?			:匹配)
([-. ])?		:匹配-.空格分隔符
(\\d{
    
    4})"		:匹配4个数字

サブマッチ操作を使用する
ここに画像の説明を挿入

bool valid(const smatch& m)
{
    
    
	if(m[1].matched)	//有左括号,就得有有括号
		return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
	else				//没有左括号,也没有右括号
		return !m[3].matched && m[4].str() == m[6].str();	//分隔符必须匹配
}

3.4. regex_replace の使用

ここに画像の説明を挿入
入力シーケンスの一部を置き換える

regex r("[0-9]+");	
string str("abc123aoe");
string fmt("BBB$1AAA");					//$1表示第一个子表达式,在第一个子表达式前面置BBB,后面置AAA
cout<<regex_replace(str, r, fmt);		//结果:abcBBBAAAaoe

マッチングとフォーマットを制御するフラグ
ここに画像の説明を挿入

フォーマット フラグを使用する

regex r("[0-9]+");	
string str("abc123aoe");
string fmt("BBB$1AAA")
cout<<regex_replace(str, r, fmt,format_no_copy);	//只拷贝它替换的文本,结果:BBBAAA

4.乱数

C++ プログラムでは、ライブラリ関数 rand を使用しないでください。ただし、default_random_engine クラスと適切な部分クラス オブジェクトを使用する必要があります。

4.1. 乱数エンジンと分布
ここに画像の説明を挿入

default_random_engine e;
cout << e() << endl;		

配布タイプとエンジン

default_random_engine e(1);						//设置随机种子
uniform_int_distribution<unsigned> u(0, 9);		//设置范围
cout << u(e) << endl;

乱数エンジンと rand 関数の比較

//下面的函数每次返回的值都是一样的
unsigned getRandom(unsigned min, unsigned max, unsigned seed = 0)
{
    
    
	default_random_engine e(seed);
	uniform_int_distribution<unsigned> u(min, max);
	return u(e);
}

静态对象会保存状态,所以会不一样
unsigned getRandom(unsigned min, unsigned max, unsigned seed = 0)
{
    
    
	static default_random_engine e(seed);
	static uniform_int_distribution<unsigned> u(min, max);
	return u(e);
}

4.2. その他の乱数分布

ランダムな実数を生成する

default_random_engine e(1);
uniform_real_distribution<double> u2(0,1);	//随机浮点数
cout << u(e) << endl;

ここに画像の説明を挿入
分布にデフォルトの結果タイプを使用する

uniform_real_distribution<> u(0,1);		//<>默认生成double值
uniform_int_distribution<> u(0, 9);		//默认生成int值

一様に分布していない乱数を生成する

正态分布
default_random_engine e;
normal_distribution<> n(4, 1.5);	//均值4,标准差1.5
n(e);

ベルヌーイ分布

default_random_engine e;
bernoulli_distribution b;	//普通类
b(e);		//默认是50/50的机会

bernoulli_distribution b(.55);		55/45的机会

5. IO ライブラリを調査中

5.1. フォーマットされた入力と出力
ここに画像の説明を挿入ここに画像の説明を挿入
出力フィラー
ここに画像の説明を挿入

cout << left;	//左对齐
cout << "i:" << setw(6) << "AAA" << endl;		i:AAA
cout << right;	//右对齐
cout << "i:" << setw(6) << "AAA" << endl;		i:   AAA
cout << internal;	//用空白填充
cout << "i:" << setw(6) << "AAA" << endl;		i:   AAA
cout << setfill('#');	//用字符填充
cout << "i:" << setw(6) << "AAA" << endl;		i:###AAA

制御入力フォーマット

空白符:空格符、制表符、换行符、换纸符、回车符
默认cin会忽略空白符	
noskipws:设置cin读取空白符

输入:
a b  c
d
默认输出:abcd
设置noskipws输出:
a b  c
d

5.2. フォーマットされていない入出力操作

标准库还提供了一组底层操作,支持未格式化IO。这些操作允许我们将一个流当作一个无解释的字节序列来处理。

シングルバイト操作
ここに画像の説明を挿入

char ch;
while(cin.get(ch))
	cout.put(ch);

文字を入力ストリームに戻す

cin.peek();
cin.unget();
cin.putback(1);

入力操作から返された int 値

int i;
while (i = cin.get() != EOF)
{
    
    
	cout.put(i);
}

マルチバイト操作
ここに画像の説明を挿入ここに画像の説明を挿入

読み取られた文字数を特定する

ここに画像の説明を挿入

5.3. ストリーム ランダム アクセス

随机IO本质上是依赖于系统的,为了理解如何使用这些特性,你必须查询系统文档。
标准库提供了一对函数来定位(seek)到流中给定的位置,已经告诉(tell)我们当前位置。
虽然标准库为所有流类型都定义了seek和tell函数,但它们是否会做有意义的事情依赖于流绑定到哪个设备。
在大多数系统中,cin、cout、cerr、clog的流不支持随机访问:当向cout直接输出数据时,类似向回跳十个
位置这种操作是没有意义的。对这些流我们可以调用seek、tell函数,但在运行时会出错,将流置于一个无效
状态。

由于istream和ostream类型通常不支持随机访问,剩余内容只适用于fstream和sstream类型。

関数を探して伝える

为了支持随机访问,IO类型维护了一个标记来确定下一个读写操作要在哪里进行。
提供了两个函数:
seek:将标记定位到一个给定位置
tell:告诉我们标记的当前位置
标准库定义了两队seek和tell函数,一对用于输入流(后缀g,获得数据),另一对用于输出流(后缀p,放置数据)

ここに画像の説明を挿入

1つのマークのみ

流中只维护单一的标记:并不存在独立的读标记和写标记

移転タグ

seekg(new_pos);			//绝对位置
seekg(offset,from);		//相对位置

アクセストークン

tellg();
fstream::beg
sstream::beg

例如:
fstream fs("path",fstream::ate|fstream::in|fstream::out);	//定位到文件尾
auto endPos= fs.tellg();		//获取文件尾位置
fs.seek(0,fstream::beg);	//从定位到文件开始位置
fs.seek(endPos)				//定位到文件尾
fs<<"abc";					
fs<<"abc\n";				//输入5个字符,\n添加了两个字符,最后一个字符是‘\n’

おすすめ

転載: blog.csdn.net/weixin_41155760/article/details/126142324
おすすめ