首页 > 编程语言 >C++ Primer Plus第三章(操作数据)笔记

C++ Primer Plus第三章(操作数据)笔记

时间:2022-12-19 15:35:56浏览次数:48  
标签:变量 int ios C++ base Plus Primer cout

简单变量

程序为了将信息储存在计算机中,程序必须记录3个基本属性

  • 信息将储存在哪
  • 要存储什么值
  • 存储什么类型的信息

我们可以利用代码来看看程序到底做了什么:

int braincout = 5;

这个语句告诉程序有一个整数变量需要存储,那么接下来,程序做了什么?

graph TB A["找到一个能存储整数的内存单元,标记为braincout"] B["将5复制到这个单元当中"] C["用户在需要时可以访问该内存单元"] A-->B-->C

变量名及其命制

C++有以下的规则必须遵守:

  • 名称仅能有字母数字与下划线
  • 第一个字符不能是数字
  • 区分大小写
  • 不能用关键字
  • 名称长度无限制
  • 以两个下划线或者下划线和大写字母开头名称将被保留给编译器及其使用的资源使用

整型变量

整型变量对应整数,即没有小数部分的数字,为了满足不同需求,C++提供了不同的整型变量。下面我们分别介绍不同的整型变量。

short、int、long、long long

C++在整型变量的规定中对这些变量提供了一个标准。

  • short占用2B的内存,最大位32767
  • int和long均占用4B的内存,且最大值为2147483647
  • long long则占用8B的内存,最大为9223372036854775807

运算符sizeof和头文件limits

以上我们并不需要去专门记忆,当我们使用时,可以使用climits当中的符号常量
注意在使用下列常量时先有头文件:

#include<climits>

符号常量:
CHAR_MIN
CHAR_MAX
SHRT_MAX
....诸如此类,可由后端推出最大值最小值。

climits是怎么工作的?看看文件中对应的语句行:

#define INT_MAX 32767

这个定义常量的方式是C语言遗留下来的,事实上我们自己定义变量时,C++给我们提供了const关键字来实现它。

而有关占用的大小可以使用sizeof(),例如:

cout<<sizeof(int)<<endl;

上述代码可以输出int变量的大小。

变量初始化

传统C语言有着这样的初始化方法:

int uncles = 5;

这个地方给uncles变量赋值了5,这个在C++中也是成立的。

此外C++也有别的初始化方法:

int wrens(432);	//将wrens赋值为432

还有初始化方法可以用于数组和结构,但是在C++98中也可用于单值变量:

int hamburgers = {24}//将hamburgers赋值为24

无符号类型

对于前面的4种整型变量,我们都有无符号的变体,这样可以使得变量能存储的最大值变大。在声明时只需加unsigned即可:

unsigned short change;

这样无符号变量最大值变为原来的两倍,但是已经无法存储负值

整型字面值

C++通过使用前一两位来表示数字常量的基数,如果第一位是1~9,那么基数为10(即10进制),如果第一位是0,那么表示8进制,如果前位是0x或0X,那么则为16进制。

同样的值如果我们想输出为其他的进制,怎么办呢?

int a = 100;
cout<<oct; //转化为八进制输出
cout<<a<<endl;
cout<<hex; //转化为十六进制输出
cout<<a<<endl;

随后我们在屏幕上就能看到100的八进制和十六进制形式的输出。

如何让C++确定常量类型

cout<<1492<<endl;

上述代码将打印出1492,现在问题来了:C++把这个值存储为了什么变量?

事实上,除非有理由存储为其他类型,C++默认将整型常量存储为int类型。

char型:字符和小整数

char型数据实际上是用整数来存储对应的字符,当我们传入单字符的时候,实质上它会存储为对应的字符编码。

char ch = 'M'; // 存储为77
cout<<ch;      //输出为M而不是77

此外输出单个字符还可以用两个函数:

putchar();  // 这个是C语言中的函数
cout.put('a'); // 这个是C++中的函数

cout.put() 函数是一个成员函数,通过类对象cout来使用函数put().

signed 和 unsigned char

实际上char本身并不存在是否有符号的情形,加这两个前缀是在将char用作数值类型时扩大表示范围的。signed char范围为-128到127,而unsigned char范围为0~255。

wcha_t类型

当字符集无法用一个8位的字节表示,比如汉字和日文系统,那么我们就需要扩展字符集。

wcha_t类型还是一个整数类型,可以表示系统用的最大扩展字符集。

但是这种情况下原有的cout和cin就不起作用了。它们将输入输出看作char流。这个时候我们有:

wcha_t bob = L'P';
wcout<<L"tall"<<endl;
wcin>>bob;

我们需要加上前缀L来指示宽字符常量和宽字符串。

char16_t & char32_t

两者分别是长16和32的无符号常量。它们是C++11才新增的类型。我们分别使用前缀u和U来指示它们。

char16_t和/u00F6的通用字符名匹配。而char32_t和/U000022B的形式匹配。


bool类型

实际上C++和C原本将非零认作true,而0认作false。但是后来出现了bool类型,所以可以直接写:

bool is_ready = true;
int ans = true; // 直接赋值成1
bool start = -100 //赋值成true

const 限定符

const在定义的时候,会把对应的变量变为常量,或者更准确地来说叫只读变量

需要注意的是C语言原来有#define的方式来实现定义常量,但是现在用const更好。

需要注意的是,如果你在定义一个常量时赋值用的是变量,那么在VS当中实际上还是会把它认为成变量。

例如下面的代码:

int n = 10;
cin>>n;
const int num = n;
int array[num];

这段代码在VS中会报错,原因是VS仍然会把num视为变量,而VS是不允许用变量来定义数组长度的。


浮点数

小数点表示法:

  • 1.00
  • 0.0023

E表示法:

  • 2.52e+8 (2.52 * 10^8)
  • 7E5 (7*10^5)
  • 9.1e-31 (9.1*10^(-31))

浮点数在C++里面也不可避免地有浮点误差,这一点的解决在这里留一个空白。

算术运算符

整除和求模

这里的加减乘除求模的符号省去,需要注意的有以下几点:

  • /运算符如果两侧都是整数,那么结果也是商的整数部分。如果有一个是浮点数,那么结果就是浮点数。
  • 求模运算符%,C++与Python在这个上面有所不同,尤其是在负数的求模运算上,C++遵循的规则是:\((a/b)\times b+a\%b = a\).

cout.setf()函数

C++ Primer Plus中的divide.cpp当中出现了代码cout.setf(ios_base::fixed,ios_base::floatfield)​这个代码应该如何理解?

实际上这个函数是用来实现格式化输出的,其中的ios_base::fixed​是指用正常计数方法(科学计数法)显示浮点数,然后ios_base::floatfield​表示小数点后6位保留。

这个函数有两个原型:

cout.setf(fmtflage);
cout.setf(fmtflage,fmtflags);

第二个原型中的第一个参数实际上和第一个原型参数是同样的。

我们可以直接像书中那样使用格式标志,常见的标志如下:

标志 功能
boolalpha 可以使用单词"true"和"false"进行输入/输出的布尔值.
oct 用八进制格式显示数值.
dec 用十进制格式显示数值.
hex 用十六进制格式显示数值.
left 输出调整为左对齐.
right 输出调整为右对齐.
scientific 用科学记数法显示浮点数.
fixed 用正常的记数方法显示浮点数(与科学计数法相对应).
showbase 输出时显示所有数值的基数.
showpoint 显示小数点和额外的零,即使不需要.
showpos 在非负数值前面显示"+(正号)".
skipws 当从一个流进行读取时,跳过空白字符(spaces, tabs, newlines).
unitbuf 在每次插入以后,清空缓冲区.
internal 将填充字符回到符号和数值之间.
uppercase 以大写的形式显示科学记数法中的"e"和十六进制格式的"x".

我们也可以直接在cout流里面直接使用操作符,如cout<<dec<<endl;​这样。

常用的操作符如下:

iostream当中的:

操作符 描述 输入 输出
boolalpha 启用boolalpha标志
dec 启用dec标志
endl 输出换行标示,并清空缓冲区
ends 输出空字符
fixed 启用fixed标志
flush 清空流
hex 启用 hex 标志
internal 启用 internal 标志
left 启用 left 标志
noboolalpha 关闭boolalpha 标志
noshowbase 关闭showbase 标志
noshowpoint 关闭showpoint 标志
noshowpos 关闭showpos 标志
noskipws 关闭skipws 标志
nounitbuf 关闭unitbuf 标志
nouppercase 关闭uppercase 标志
oct 启用 oct 标志
right 启用 right 标志
scientific 启用 scientific 标志
showbase 启用 showbase 标志
showpoint 启用 showpoint 标志
showpos 启用 showpos 标志
skipws 启用 skipws 标志
unitbuf 启用 unitbuf 标志
uppercase 启用 uppercase 标志
ws 跳过所有前导空白字符

iomanip中定义的操作符:

操作符 描述 输入 输出
resetiosflags(long f) 关闭被指定为f的标志
setbase(int base) 设置数值的基本数为base
setfill(int ch) 设置填充字符为ch
setiosflags(long f) 启用指定为f的标志
setprecision(int p) 设置数值的精度(四舍五入)
setw(int w) 设置域宽度为w

如科学计数法:

cout<<setiosflags(ios_base::scientific)<<255.255<<endl;
// 输出结果是2.55255e+02

第二原型中的第二个参数直接上表格对照即可:

第二个参数 第一个参数 含义
ios_base::basefield
ios_base::dec 使用10进制
ios_base::oct 使用8进制
ios_base::hex 使用16进制
ios_base::floatfield ios_base::fixed 一般计数法
ios_base::scientific 科学计数法
ios_base::adjustfield ios_base::left 左对齐
ios_base::right 右对齐
ios_base::internal 符合或前缀左对齐,值右对齐

类型转换

初始化和赋值转换

将取值范围较小的值赋给取值范围更大的类型通常不会有什么问题,例如下面这个代码:

long so_long;
short thirty;
so_long = thirty;  // 这样不会出问题

只不过占用字节依旧是按照对应的数据类型来的。

但是反过来的话,结果将会是不确定的。例如下面这些行为:

  • double转换为float
  • 浮点类型转换为整型(小数部分丢失)
  • 较大的换为较小的(看这个值是否在取值范围里面)

同时在初始化的时候,我们也可以用{}来初始化转换,但是这个时候不能够缩窄,比如赋过大的值,浮点型不能转换为整型。

char c1 {66}  // 可以
int x = {33.2}	// 不可以

表达式中的转换

书中提到了整型提升的概念,C++在计算表达式的时候会将bool、char、short等等整型转换为int类型,因为使用int类型计算时更快。

在计算中的转换是根据列表来的,但是实际上规律很简单:

  1. 最高为long double,其中一个是,另一个不是那么就会转换为long double.
  2. 下一级是double。
  3. 然后是float。
  4. 都是整型就依照整型提升。
  5. 都是无(有)符号,就根据级别来。
  6. 如果符号不同,并且无符号级别更高,则转有符号到无符号。
  7. 有符号可表示无符号类型取值则转无符号到有符号。
  8. 否则都转到有符号的无符号版本。

强制类型转换

通用格式如下:

(typename) value  // 来自C
typename (value)  // C++
(long) thorn
long (thorn)

但是这种用法实际上不改变原来变量的值,只是像调用函数一样暂时得到相应的值罢了。

C++11当中的auto声明

这个关键字是根据你设置的初始值而设置变量的类型。

auto cars = 100; // 自动变为int类型
auto z = 0;  // 这个还是int类型

整数一般识别为int类型,小数识别为double类型。

标签:变量,int,ios,C++,base,Plus,Primer,cout
From: https://www.cnblogs.com/han-son-xiong/p/16992277.html

相关文章