C++-17 C++新功能

17 C++新功能
17.1

数位分隔符
允许使用单引号(’)作为数为分隔符

my_func(1'123'445,33'566,100);

数位分隔符在需要写大数字时很好用

long long int big_int=100'000'000'000;

除了整肃,还可应用于小数

double pi=3.141'592'653;

编译器实际会忽略数字中的单引号。和注释一样,数为分隔符支队阅读和维护代码的人有用。

字符串字面值后缀
向字符串字面值应用s后缀,使其称为真正的string对象而不是C字符串(字符数组)

"text"s;

原来,string sname=“Jone”+“ Adams“ 这样的语句是错误的,因为C字符串本身(具有char*类型)没有定义+操作符的行为。相反必须使用strcat函数来列娜姐
加了s后缀的字符串字面值称为真正的string对象,能合法写成+语句

string sname="Jone"s + "Adams"s;

s后缀有助于澄清是想要返回一个真正的string对象,而不是char数组

return "Hello!"s; // 作为string对象返回

二进制字面值
C++14允许使用0b或0B写二进制字面值
0bdigits
例如:

cout<<0b110+0b001; //打印7(=0b111)

写掩码更为方便:

cout << data | 0b1111;  //低4位开
cout << data & 0b1111;  //将除了第四位的其他所有位都遮掩掉(置0)

位操作符

操作符名称说明
&按位AND(与)两个操作数对应的都是1,就将该位设为1.其他位设为0
|按位OR(或)两个操作数对应的位任何一个是1,就将该位设为1,其他设为0
^按位XOR(异或)两个操作数对应的不同,就将该位设为1,否则设为0
~按位NOT(取反)一元操作符。反转操作符每一位的值,例如1变成0,反之亦然

可以同时使用单引号数位分割符

cout << ob1111'0000 |0b0000'1111 <<endl;
//结果是255

要打印二进制,一个简单的方式是使用bitset模板。该模板不要指定基础类型,而要指定一个固定位数。bitset打印时会生成一个包含0和1的数字字符串

#include <bitset>
using namespace std;

bitset<8> my_bit(0b1111'0000 & 0b1100'0000);
cout << my_bit <<endl;
//结果位11000000
17.2 C++11引入的功能

long long 类型
64位,限制40亿的平方
(long 32位,short 16位,char 8位)
均有无符版本,无符号类型不能存储负数,但能存储两倍大的正数
除了int本身,其他整形在声明时都可去掉int关键字

使用64位字面值
用LL后缀存储大数字
用ULL后缀表示unsigned long long

//long long n=123000123000456;报错
long long n=123000123000456LL; 
long long n=12300123000456ULL;
long long n=123'000'123'000'456ULL;

接收long long输入
之前使用atoi函数将字符串转会为整数
atoll将char* 字符串

char *input_string[MAX_WIDTH+1];
cin.get(input_string,MAX_WIDTH);
long long n=atoll(input_string);

若是输入使用了分隔符,例如123,145,677,789,987,就在转换成数字前剥离这些字
支持atoll函数需要包含<cstdlib>

#define GROUP_SEP ','

long long reat_formatted_input(string s){
	for(int i=0;i<s.size();++i){
		if(s[i]==GROUP_SEP)
			s.erase(i,1);
		}
		return atoll(s.c_str());
}

格式化long long 数字
用正确数位分隔符打印格式化数字
用到STL stringstream类:该特殊类允许向字符串写入,类似于向控制台或文件写入,要包含一下文件

#include <string>
#include <sstream>

然后创建并使用一个“字符串流”,完成对流的写入后,用str成员函数把他转换为 实际字符串

stringstream s_out;
s_out << "i的值是" << i <<endl;
string s=s_out.str();

现在可以写一个函数来获取long long 作为输入,返回一个格式化字符串

#define GROUP_SEP ','
#define GROUP_SIZE 3
string output_formatted_input(long long num){
	//将数据读入字符串s
	stringstream temp,out;
	temp<<num;
	string s=temp.str();

//在第一个分隔符(GROUP_SEP)前写第一组字符
	int n=s.size()%GROUP_SIZE;
	int i=0;
	if(n>0 && s.size()>GROUP_SIZE){
		out<<s.substr(i,n)<<GROUP_SEP; 
		i+=n;
		}
	//处理其他分组
	n=s.size()/GROUP_SIZE-1;
	while(n-->0{
		out<<s.substr(i,GROUP_SIZE)<<GROUP_SEP;
		i+=GROUP_SIZE;
	}
	out<<s.substr(i);
	return out.str();
}

substr函数
第一个参数是起始位置(基于0),第二个参数是从起始位置开始选取的字符数
substr函数返回从起始位置到所需个数的字符串

本地化数字

#define 符号名称 替代文本

基于范围的for(For Each)

处理容器中的每一项,而不必关心从哪里开始或者从哪里结束
两种常规语法(区别是**&**)

for (基类型& 变量 : 容器) //传引用
	语句
for(基类型 变量 : 容器)  //传值
	语句

第一种形式,变量是引用类型,意味着能修改原始数据,要修改容器中的值,推荐使用该类型
第二种形式只能访问值的拷贝

int my_array[10];
for(int& i : my_array){
	i=0;
	}
	//将my——arr的每个成员设为5
for(int& i : my_array){
	i=5;
	}

如果不打算修改任何值,就拿掉&符号保护数据

for(int i : my_array){
	cout<<i<<endl;
	}

保留&符号也能保护值,但是要将循环变量声明位const

for(const int& i : my_array){
	cout<<i<<endl;
	}

基于范围的for,容器可以是下面的任意一种:

  1. 任何数组
  2. STL string对象(string对象中的元素就是单独的字符),基类型是char
  3. 定义了迭代器的STL类的实例,如list和vector
  4. 初始化列表

基于范围的for支持大括号中的初始化列表,如一下打印大量数字的最简方式

for(int& i : {1,1,2,3,5,8,13,21,34,55,89,144}){
	cout<<i<<endl;
	}
int j=0;
for(int& i : array){
	i=j++;
}

关键字auto和decltype
auto关键字可以指定自动(基于栈的)存储类,除非特都声明为静态,否则局部变量默认都属于该存储类
一旦auto关键字声明变量,变量类型就有上下文决定(由初始化它的东西决定),一旦固定,变量的类型就不能改变。auto并不是用来定义可变数据类型

auto x1=5;

假设w是一个指针数组,包含指向Fraction对象的指针的指针可以这样写:

for (Fraction& **x : w)...
for (auto& x : w)...
for (auto& 变量 : 容器) //传引用
	语句
for(auto 变量 : 容器)  //传值
	语句

关键字decltype返回实参的类型

decltype(x) y;//声明y具有和x一样的类型

关键字nullptr
nullptr:不指向任何地方,指针专用
任何指针设为空(nullptr),作为条件测试是就等价于false

强类型枚举
关键字enum,将元素创建成符号常量,并自动赋予连续的整数0,1,2…(默认从0开始)

enum和class合并使用,不仅创建符号名称,还创建一个类,
这会创建一个独立的命名空间,其中的值除非进行强制类型转换,否则不能赋给其他整型,或从其他整型赋值

扩展enum语法:控制存储

enum class 枚举类型 : 存储类型{
	符号
	};

例如,可指定C++将你的符号作为unsigned long来实现

enum class Choice : unsighned long{
	符号
	};

可选择为特定符号指定值

枚举默认从0开始,不显式赋值,每个符号默认是上一个符号的值加1

原始字符串字面值
传统C++要表示,'等字符,必须使用转义字符
C++11规范新的“原始字符串”规范:R“( 和 **)"**之间的一切被视为字符串的一部分,无需对字符进行转义

char s[]=R"(The "file" is C:\\users\\1.txt.)";

R前缀告诉编译器这是一个原始字符串字面值

R"(原始字符串文本)"

还可添加另一个字符(或最长16个字符的字符串)来进一步界定字符串
下面例子使用*做定界符

char s[]=R"*(The "file" is C:\\users\\1.txt.)*";
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值