处理数据
3.1 简单变量
3.1.1 变量名
- 在名称中只能使用字母字符、数字和下划线 ( _ );
- 名称的第一个字符不能是数字;
- 区分大写字符与小写字符;
- 不能将C++关键字用作名称;
- 以两个下划线 或 下划线+大写字母 打头的名称被保留给实现(编译器及其使用的资源)使用;
- 以 一个下划线 开头的名称被保留给实现,用作全局标识符;
- C++对于名称的长度没有限制,名称中所有的字符都有意义,但有些平台有长度限制。
{% hint style="info" %}
倒数第二三点与前面几点有些不同,因为使用像 __time_stop 或 _Donut 这样的名称不会导致编译器错误,而会导致行为的不确定性。换句话说,不知道结果将是什么。不出现编译器错误的原因是,这样的名称不 是非法的,但要留给实现使用。
{% hint style="warning" %}
TODO
命名风格
3.1.2 整型
整数无限大,每一种 C++的整形只是数学上的整数的一部分。
3.1.3 short、int、long、long long
- 用 climits.md 来确定各种整形的最大最小值
- 赋值竟然可以这样:
int a = {}; // 这个就是 0,int b = {100}; // 就是 100
3.1.4 无符号类型
why:比如人口等,不需要负数,无符号类型可以扩展数的范围
无符号类型的越界
// exceed.cpp -- exceeding some integer limits
#include <iostream>
#define ZERO 0 // makes ZERO symbol for 0 value
#include <climits> // defines INT_MAX as largest int value
int main()
{
using namespace std;
short sam = SHRT_MAX; // initialize a variable to max value
unsigned short sue = sam; // okay if variable sam already defined
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Add $1 to each account." << endl
<< "Now ";
sam = sam + 1;
sue = sue + 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited.\nPoor Sam!" << endl;
sam = ZERO;
sue = ZERO;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl;
cout << "Take $1 from each account." << endl
<< "Now ";
sam = sam - 1;
sue = sue - 1;
cout << "Sam has " << sam << " dollars and Sue has " << sue;
cout << " dollars deposited." << endl
<< "Lucky Sue!" << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"exceed"
Sam has 32767 dollars and Sue has 32767 dollars deposited.
Add $1 to each account.
Now Sam has -32768 dollars and Sue has 32768 dollars deposited.
Poor Sam!
Sam has 0 dollars and Sue has 0 dollars deposited.
Take $1 from each account.
Now Sam has -1 dollars and Sue has 65535 dollars deposited.
Lucky Sue!
3.1.5 如何选择具体的整型
原则:能省则省
3.1.6 整形字面量
不同进制的字面量
// hexoct1.cpp -- shows hex and octal literals
#include <iostream>
int main()
{
using namespace std;
int chest = 42; // decimal integer literal
int waist = 0x42; // hexadecimal integer literal
int inseam = 042; // octal integer literal
cout << "Monsieur cuts a striking figure!\n";
cout << "chest = " << chest << " (42 in decimal)\n";
cout << "waist = " << waist << " (0x42 in hex)\n";
cout << "inseam = " << inseam << " (042 in octal)\n";
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"hexoct1"
Monsieur cuts a striking figure!
chest = 42 (42 in decimal)
waist = 66 (0x42 in hex)
inseam = 34 (042 in octal)
print成不同进制:std::hex,std::oct
// hexoct2.cpp -- display values in hex and octal
#include <iostream>
using namespace std;
int main()
{
using namespace std;
int chest = 42;
int waist = 42;
int inseam = 42;
cout << "Monsieur cuts a striking figure!" << endl;
cout << "chest = " << chest << " (decimal for 42)" << endl;
cout << hex; // manipulator for changing number base
cout << "waist = " << waist << " (hexadecimal for 42)" << endl;
cout << oct; // manipulator for changing number base
cout << "inseam = " << inseam << " (octal for 42)" << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"hexoct2"
Monsieur cuts a striking figure!
chest = 42 (decimal for 42)
waist = 2a (hexadecimal for 42)
inseam = 52 (octal for 42)
3.1.7 常量
| 进制 | int | long | long long |
|---|---|---|---|
| 十 | 1234 | 1234L 或 1234l | 1234LL 或 1234ll |
| 八 | 01234 | 01234L 或 01234l | 01234LL 或 01234ll |
| 十六 | 0x1234 | 0x1234L 或 0x1234l | 0x1234LL 或 0x1234ll |
3.1.8 字符:ASCII(大小位 1 个字节)
1. cin 来输入一个字符
// chartype.cpp -- the char type
#include <iostream>
int main()
{
using namespace std;
char ch; // declare a char variable
cout << "Enter a character: " << endl;
cin >> ch;
cout << "Hola! ";
cout << "Thank you for the " << ch << " character." << endl;
// cin.get();
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"chartype"
Enter a character:
M
Hola! Thank you for the M character.
2. char and int
// morechar.cpp -- the char type and int type contrasted
#include <iostream>
int main()
{
using namespace std;
char ch = 'M'; // assign ASCII code for M to ch
int i = ch; // store same code in an int
cout << "The ASCII code for " << ch << " is " << i << endl;
cout << "Add one to the character code:" << endl;
ch = ch + 1; // change character code in ch
i = ch; // save new character code in i
cout << "The ASCII code for " << ch << " is " << i << endl;
// using the cout.put() member function to display a char
cout << "Displaying char ch using cout.put(ch): ";
cout.put(ch);
// using cout.put() to display a char constant
cout.put('!');
cout << endl
<< "Done" << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"morechar"
The ASCII code for M is 77
Add one to the character code:
The ASCII code for N is 78
Displaying char ch using cout.put(ch): N!
Done
3. 既生“<<”何生".put()" :历史原因
答案与历史有关。在 C++的 Release 2.0 之前,cout 将字符变量显示为字符,而将字符常量(如 ‘M’和‘N’)显示为数字。问题是,C++的早期版本与 C 一样,也将把字符常量存储为 int 类型。也就是 说,‘M’的编码 77 将被存储在一个 16 位或 32 位的单元中。而 char 变量一般占 8 位。
遗憾的是,这意味着对 cout 来说,‘M’和 ch 看上去有天壤之别,虽然它们存储的值相同。因此,下 面的语句将打印
cout << '
在Release 2.0之后,C++将字符常量存储为char类型,而不是int类型。这意味着cout现在可以正确 处理字符常量了。
</details>
4. 转义字符
| 字符名称 | ASCII符号 | C++代码 | 十进制ASCII码 | 十六进制ASCII码 |
| ------------ | ------- | ----- | --------- | ---------- |
| 换行符(NL (LF)) | NL(LF) | `\n` | 10 | 0xA |
| 水平制表符(HT) | HT | `\t` | 9 | 0x9 |
| 垂直制表符(VT) | VT | `\v` | 11 | 0xB |
| 退格(BS) | BS | `\b` | 8 | 0x8 |
| 回车(CR) | CR | `\r` | 13 | 0xD |
| 振铃(BEL) | BEL | `\a` | 7 | 0x7 |
| 反斜杠(\) | \\ | `\\` | 92 | 0x5C |
| 问号(?) | ? | `\?` | 63 | 0x3F |
| 单引号(') | ' | `\'` | 39 | 0x27 |
| 双引号(") | " | `\"` | 34 | 0x22 |
5. signed char 和 unsigned char
与 int 不同的是,char 在默认情况下既不是没有符号,也不是有符号。是否有符号由 C++实现决定, 这样编译器开发人员可以最大限度地将这种类型与硬件属性匹配起来。如果 char 有某种特定的行为对您来 说非常重要,则可以显式地将类型设置为 signed char 或 unsigned char
```cpp
char a; // 可能是有符号,也有可能无符号
unsigned char b; // 一定丝滑无符号
signed char c; // 一定是无符号
- wcha_t(宽字符类型):用来表示比如日语,汉语这种 ASCII 表示不了的字符。
wchar_t bob = L'P';
wcout << L"tall" << endl;
3.1.7 bool
- true:true,非 0 的整数比如-1, 10
- false:false,整数 0
3.2 const 限定符
通用模板如下
const 类型 名字 = value;
const 比 define 好:可以限制类型,可以更精确的控制作用域
3.3 浮点数
3.3.1 书写浮点数
- 直接写小数点:12.34,8.0
- 科学计数法(E 和 e 都可以):2.52e+8,8.33E-3,3.3e2
3.3.2 浮点类型
Demo
// floatnum.cpp -- floating-point types
#include <iostream>
int main()
{
using namespace std;
cout.setffixed, ios_base::floatfield; // fixed-point
float tub = 10.0 / 3.0; // good to about 6 places
double mint = 10.0 / 3.0; // good to about 15 places
const float million = 1.0e6;
cout << "tub = " << tub;
cout << ", a million tubs = " << million * tub;
cout << ",\nand ten million tubs = ";
cout << 10 * million * tub << endl;
cout << "mint = " << mint << " and a million mints = ";
cout << million * mint << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"floatnum"
tub = 3.333333, a million tubs = 3333333.250000,
and ten million tubs = 33333332.000000
mint = 3.333333 and a million mints = 3333333.333333
cout.setf():用来重新定义输出的小数位数。floatfield 是 6,就是说保留六位小数。- 这个例子可以看出 float 和 double 的有效位的区别,float 只有 32-9=24bits 表示位数,也就是24/4=6 位有效数字。
{% hint style="info" %}
弹幕大神:因为尾数:2^23是8388608个数字,也就是没有触及边界的情况下,7位精确,但是触及边界就6位精确
3.3.3 浮点常量
1.234f // float const
2.45E20F // float const
2.345E28 // double const
2.2L // long double const
3.3.4 浮点数的优缺点
浮点数损失精度
// fltadd.cpp -- precision problems with float
#include <iostream>
int main()
{
using namespace std;
float a = 2.34E+22f;
float b = a + 1.0f;
cout << "a = " << a << endl;
cout << "b - a = " << b - a << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"fltadd"
a = 2.34e+22
b - a = 0
3.4 C++算术运算符
3.4.1 运算符优先级和结合性
+,-,*,/,%
取余数只能整数和整数运算
3.4.2 除法分支
Demo
// divide.cpp -- integer and floating-point division
// 如果两个操作数都是整数,则 C++将执行整数除法。
// 这意味着结果的小数部分将被丢弃,使得最后的结果是一个整数。
// 如果其中有一个(或两个)操作数是浮点值,则小数部分将保留,结果为浮点数
#include <iostream>
int main()
{
using namespace std;
cout.setffixed, ios_base::floatfield;
cout << "Integer division: 9/5 = " << 9 / 5 << endl;
cout << "Floating-point division: 9.0/5.0 = ";
cout << 9.0 / 5.0 << endl;
cout << "Mixed division: 9.0/5 = " << 9.0 / 5 << endl;
cout << "double constants: 1e7/9.0 = ";
cout << 1.e7 / 9.0 << endl;
cout << "float constants: 1e7f/9.0f = ";
cout << 1.e7f / 9.0f << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"divide"
Integer division: 9/5 = 1
Floating-point division: 9.0/5.0 = 1.800000
Mixed division: 9.0/5 = 1.800000
double constants: 1e7/9.0 = 1111111.111111
float constants: 1e7f/9.0f = 1111111.125000
3.4.3 求模运算符
Demo
// modulus.cpp -- uses % operator to convert lbs to stone
#include <iostream>
int main()
{
using namespace std;
const int Lbs_per_stn = 14;
int lbs;
cout << "Enter your weight in pounds: ";
cin >> lbs;
int stone = lbs / Lbs_per_stn; // whole stone
int pounds = lbs % Lbs_per_stn; // remainder in pounds
cout << lbs << " pounds are " << stone
<< " stone, " << pounds << " pound(s).\n";
// cin.get();
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"modulus"
Enter your weight in pounds: 100
100 pounds are 7 stone, 2 pound(s).
3.4.4 类型转换
情况:赋值,表达式求值,函数传参
Demo
// assign.cpp -- type changes on assignment
#include <iostream>
int main()
{
using namespace std;
cout.setffixed, ios_base::floatfield;
float tree = 3; // int converted to float
int guess = 3.9832; // float converted to int
int debt = 7.2E12; // result not defined in C++
cout << "tree = " << tree << endl;
cout << "guess = " << guess << endl;
cout << "debt = " << debt << endl;
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"assign"
tree = 3.000000
guess = 3
debt = 4098
{}的初始化,不允许类型转换
const int code = 66; // √
int x = 66; // √
char c1 {31325}; // √
char c2 = {66}; // √
char c3 {code}; // √
char c4 = {x}; // x {}里边不能是变量
char c5 = x; // √
强制类型转换
// typecast.cpp -- forcing type changes
#include <iostream>
int main()
{
using namespace std;
int auks, bats, coots;
// the following statement adds the values as double,
// then converts the result to int
auks = 19.99 + 11.99;
// these statements add values as int
bats = (int) 19.99 + (int) 11.99; // old C syntax
coots = int (19.99) + int (11.99); // new C++ syntax
cout << "auks = " << auks << ", bats = " << bats;
cout << ", coots = " << coots << endl;
char ch = 'Z';
cout << "The code for " << ch << " is "; // print as char
cout << int(ch) << endl; // print as int
cout << "Yes, the code is ";
cout << static_cast<int>(ch) << endl; // using static_cast
// cin.get();
return 0;
}
(base) kimshan@MacBook-Pro output % ./"typecast"
auks = 31, bats = 30, coots = 30
The code for Z is 90
Yes, the code is 90
3.4.5 C++11 中的 auto 声明
使用关键字auto,而不指定变量的类型,编译器将把变量的类型设置成 与初始值相同(推断完就固定了,不能改了)
auto a = 1.0;
auto b = 3;
其实 auto 更适合 STL,标准模块库
std::vector<double> scores;
// std::vector<double>::iterator pv = scoress.begin();
auto pv = scoress.begin();
```;
在Release 2.0之后,C++将字符常量存储为char类型,而不是int类型。这意味着cout现在可以正确 处理字符常量了。
- 转义字符
| 字符名称 | ASCII符号 | C++代码 | 十进制ASCII码 | 十六进制ASCII码 |
|---|---|---|---|---|
| 换行符(NL (LF)) | NL(LF) | \n |
10 | 0xA |
| 水平制表符(HT) | HT | \t |
9 | 0x9 |
| 垂直制表符(VT) | VT | \v |
11 | 0xB |
| 退格(BS) | BS | \b |
8 | 0x8 |
| 回车(CR) | CR | \r |
13 | 0xD |
| 振铃(BEL) | BEL | \a |
7 | 0x7 |
| 反斜杠(\) | \ | \\ |
92 | 0x5C |
| 问号(?) | ? | \? |
63 | 0x3F |
| 单引号(') | ' | \' |
39 | 0x27 |
| 双引号(") | " | \" |
34 | 0x22 |
- signed char 和 unsigned char
与 int 不同的是,char 在默认情况下既不是没有符号,也不是有符号。是否有符号由 C++实现决定, 这样编译器开发人员可以最大限度地将这种类型与硬件属性匹配起来。如果 char 有某种特定的行为对您来 说非常重要,则可以显式地将类型设置为 signed char 或 unsigned char
{{CODE_BLOCK_8}}
- wcha_t(宽字符类型):用来表示比如日语,汉语这种 ASCII 表示不了的字符。
3.1.7 bool
- true:true,非 0 的整数比如-1, 10
- false:false,整数 0
3.2 const 限定符
通用模板如下
{{CODE_BLOCK_10}}
const 比 define 好:可以限制类型,可以更精确的控制作用域
3.3 浮点数
3.3.1 书写浮点数
- 直接写小数点:12.34,8.0
- 科学计数法(E 和 e 都可以):2.52e+8,8.33E-3,3.3e2
3.3.2 浮点类型
Demo
{{CODE_BLOCK_11}}
{{CODE_BLOCK_12}}
cout.setf():用来重新定义输出的小数位数。floatfield 是 6,就是说保留六位小数。- 这个例子可以看出 float 和 double 的有效位的区别,float 只有 32-9=24bits 表示位数,也就是24/4=6 位有效数字。
{% hint style="info" %}
弹幕大神:因为尾数:2^23是8388608个数字,也就是没有触及边界的情况下,7位精确,但是触及边界就6位精确
3.3.3 浮点常量
{{CODE_BLOCK_13}}
3.3.4 浮点数的优缺点
浮点数损失精度
{{CODE_BLOCK_14}}
{{CODE_BLOCK_15}}
3.4 C++算术运算符
3.4.1 运算符优先级和结合性
{{CODE_BLOCK_16}}
取余数只能整数和整数运算
3.4.2 除法分支
Demo
{{CODE_BLOCK_17}}
{{CODE_BLOCK_18}}
3.4.3 求模运算符
Demo
{{CODE_BLOCK_19}}
{{CODE_BLOCK_20}}
3.4.4 类型转换
情况:赋值,表达式求值,函数传参
Demo
{{CODE_BLOCK_21}}
{{CODE_BLOCK_22}}
{}的初始化,不允许类型转换
{{CODE_BLOCK_23}}
强制类型转换
{{CODE_BLOCK_24}}
{{CODE_BLOCK_25}}
3.4.5 C++11 中的 auto 声明
使用关键字auto,而不指定变量的类型,编译器将把变量的类型设置成 与初始值相同(推断完就固定了,不能改了)
{{CODE_BLOCK_26}}
其实 auto 更适合 STL,标准模块库
{{CODE_BLOCK_27}}