0%

1. 4.6 枚举

C++的枚举enum工具可以创建符号常量,和const的作用相同。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// spectrum 成为新类型的名称,被称为枚举(enumeration)
// red,orange,yellow被称为符号常量,被称为枚举量(enumerator)

enum spectrum {red,orange,yellow};
// 同等于
const int red = 0;
const int orange = 1;
const int yellow = 2;

// 可以用枚举名来生命这种类型的变量
spectrum band;
band = blue;

int color = orange; // valid

1.1. 设置枚举量的值

1.1.1. 可以显式的设置

指定的值必须是整数

1
enum bits {one = 1, two = 2, four = 4};

1.1.2. 只显式的定义其中一些

1
enum bigstep {first, second = 100, third};

first在默认情况下为0,后面没有被初始化的值将比其前面的枚举值大1,因此third=#01。

1.1.3. 可以创建多个值相同的枚举值

1
enum {zero, null = 0, one, numero_one = 1};

1.2. 枚举的取值范围

enum bigstep {first, second = 100, thrid};为例子:

  • 上限:找到bigstep最大值,他的最小2次幂减去一。这里最大值third=101,最小二次幂为128,因此取值上限是127。
  • 下限:如果最小值大于0,那么取值下限为0;否则采用和上面一样的方法,但是加上负号。假如最小的枚举量为-6,那么比他小、最大的2次幂为-8,因此下限为-7。

共用体(union)是一种数据格式。

它能存储不同的数据类型,但只能同时存储其中一种类型

共用体的用途是当数据类型可能是1种或者是更多种格式(但不同时使用)时,可节省空间。

🌰例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>

int main() {
using namespace std;

union one4all
{
int int_val;
long long_val;
double double_val;
};

one4all pail;
pail.int_val = 15;
cout << pail.int_val << endl;
pail.double_val = 12.05;
cout << pail.double_val << endl;
cout << pail.int_val << endl; // 输出-1717986918,代表无法输出
return 0;
}

🌰 例子2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

int main() {
using namespace std;
struct widget
{
char brand[20];
int type;

union id
{
long id_num;
char id_char[20];
} id_val;
};

widget prize;

prize.brand[0] = 'z';
cout << "Please enter prize type, 1 or 2 \n";
cin >> prize.type;

// prize.type = 1;
// prize.id_val.id_num = 1;
// prize.id_val.id_char[0] = 'h';

if (prize.type == 1)
{ // 要用打括号括起来,假如if里有几行的话
cout << "Please enter prize.id_val in int \n";
cin >> prize.id_val.id_num;
cout << "Prize.id_val is " << prize.id_val.id_num << endl;
}
else
{
cout << "Please enter prize.id_val in char \n";
cin >> prize.id_val.id_char;
cout << "Prize.id_val is " << prize.id_val.id_char << endl;
}

return 0;
}

8月13日(本来应该是集中隔离最后一天,可恶)github更新了一个东东:

remote: Support for password authentication was removed on August 13, 2021. Please use a personal access token instead.

remote: Please see https://github.blog/2020-12-15-token-authentication-requirements-for-git-operations/ for more information.

fatal: unable to access ‘https://github.com/zhoulujun/algorithm.git/‘: The requested URL returned error: 403

然后导致我的hexo博客上传有问题了,我是基于ssh的免密

在网上找到这两篇帖子找到了解决方法,更新后需要使用token了

1.GitHub不再支持密码验证解决方案:SSH免密与Token登录配置

2.stackoverflow:support for password …

操作很简单,记录下来以便以后别忘球了。。

    1. 打开github点击setting
    1. 左边栏目里找到developer settings
    1. 继续点击personal access tokens

这一步是为了创造一个token出来,可以选择有效期,30天,90天啥的, 按需选择

  • 4.generate new token 自己选择需要的时常和权限范围,我全选了
  • 5.生成token后,大概长这样的一串东西(这个是随便改的):
    ghp_sFhFsSHhTzMDreGRLjmks4Tzuzgthdvfsrta

复制一下

  • 6.在mac系统里打开Spotlight icon (中文:聚焦搜索)然后搜索Keychain access(中文:钥匙串访问)
  • 7.在钥匙串访问里搜索github

就会出现一个或者两个(不知道是不是我以前用法语系统导致有两个)的属性控制,点开显示密码的地方,把原先的密码替换成token,这里可能会要求输入电脑密码等等

  • 8.再运行hexo clean/d/g的操作就ok了

  • 9.非mac系统的解决方法在stack的那个参考链接里有写

  • 10.terminal的方法没有成功,这里就不记录了

1. 4.4 结构简介

数组只能存储同一个类型的数据(如10个int,10个float)

结构是一个更灵活的数据格式,结构是用户定义的类型,结构声明定义了这种数据的数据属性。

  1. 定义结构描述:描述并标记了能够存储在结构中的各类数据类型

  2. 按描述创建结构变量(结构数据对象)

🌰 例子:

现在要创造一个类型struct来描述其产品,这个产品必须包含名称容量售价,下面的结构可以满足:

1
2
3
4
5
6
7
8
struct inflatable
{
char name[20];
float volume;
double price;

}

这个新的数据格式名为inflatable,在创建之后,就可以像创建char或者int类型的变量那样去创建inflatable类型的数据了。

由于hat的类型是inflatable,可以使用运算符(.)来访问各个成员,如hat.volume,hat.price等等。总之,hat是一个结构,而hat.double是一个double变量。

例如:

1
2
3
ìnflatable hat; // hat is a structure variable of tyle inflatable
inflatable woopie_cushion;

1.1. 在程序中使用结构

🌰 一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//
// main.cpp
// structur
//
// Created by YujiaYANG on 2021/8/15.
//

#include <iostream>

struct inflatable
{
char name[20];
float volume;
double price;

};


int main() {
using namespace std;
inflatable guest =
{
"Glorious Gloria", // name
1.88, // volume
29.99, // price
};

inflatable pal =
{
"Audacious Arthur",
3.12,
32.99
};

cout << "Expand your guest list with " << guest.name;
cout << " and " << pal.name << "! \n";

cout << "You can have both for $";
cout << guest.price + pal.price << "!\n";

return 0;

}

一些注意的点:

  • C++不提倡使用外部变量,但提倡使用外部结构声明
  • 使用一个结构也可以这样写在一行inflatable hei = {"Dalphine",2.13,2.15};
  • pal.name[0] 是一个字符A,pal[0]没有意义(因为pal是一个结构,而不是数组)

1.2. C++结构初始化

inflatable hei = {"Dalphine",2.13,2.15}; 里的 等号(=)也是可省的
☑️ inflatable hei {"Dalphine",2.13,2.15};

其次,如果大括号内未包含任何东西,各个成员将被设置成零。

1
2
3
4
5
6
inflatable hei {};

// 输出
// hei.name =
// hei.price = 0
// hei.volume = 0

1.3. 结构可以将string类作为成员吗

用string代替char name[20] 可以吗?

🌰例如:

1
2
3
4
5
6
7
8
`struct inflatable // struct definition
{
std::string name; // 👈 重点是这个替换
float volume;
double price;

}

答案是OK哒,但要注意namespace的定义,那么将std申明放在struct定义之前,要么就在定义中写std::string嘿嘿

1.4. 其他结构属性

1.5. 结构可以传递(成员赋值)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;

struct inflatable
{
char name[20];
float volume;
double price;

};

int main(){
inflatable hat {"heihei",1.14,2.15};
inflatable big;
big = hat;


cout << "big.name = " << big.name << endl;
cout << "big.price = " << big.price << endl;



return 0;
}


1.5.1. 初始化方法1 (不那么方便阅读)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;

struct inflatable
{
string name;
float volume;
double price;

} mr_smith, ms_jone; // 同时完成定义结构和创建结构变量的工作,初始化为0

int main(){
mr_smith.name = "hei_smith";

cout << "mr_smith.name = " << mr_smith.name << endl;
cout << "mr_smith.price = " << mr_smith.price << endl;
return 0;
}

1.5.2. 初始化方法2 (不方便阅读)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;

struct inflatable
{
string name;
float volume;
double price;

} mr_smith =
{
"mr_smith",
1.14,
2.53
};

int main(){
// mr_smith.name = "hei_smith";

cout << "mr_smith.name = " << mr_smith.name << endl;
cout << "mr_smith.price = " << mr_smith.price << endl;
return 0;

1.5.3. 也可以声明没有名称的结构类型(有点类似于用一次就行)

这样将单纯创建一个名为position的结构变量,可以使用成员运算符(.)来访问它的成员position.x等等,但这种变量无名称,以后无法创建其副本,本书不使用此结构。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

struct
{
int x;
int y;
} position;

int main()
{
position.x = 2;
position.y = 4;

cout << "Position.x = " << position.x << endl;
cout << "Position.y = " << position.y << endl;

return 0;

}

1.6. 结构数组

可以创造一个元素为inflatable的数组(array):

例如要创建一个包含100个inflatable结构的数组gifts,可以这样做

1
2
3
inflatable gifts[100];
cin >> gifts[0].volume;
cout << gifts[99].price << endl;

也可以创建一个数组guests,同时初始化它的两个inflatable元素:

1
2
3
4
5
6
inflatable guests[2] =
{
{"bambi",0.5,21.99},
{"Godzilla",2000, 565.99}
};

1.7. 结构中的位字段

p78

1. 4.3 string 类简介

由文章开头的#include <string>使用string类

下面的例子比较了string和字符数组的一些相同点:

🌰 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//
// main.cpp
// strtype1
//
// Created by YujiaYANG on 2021/8/11.
//

#include <iostream>
#include <string>


// 旨在说明string对象与字符数组之间的一些相同点和不同点
int main() {
using namespace std;
char charr1[20]; // create an empty array
char charr2[20] = "jaguar"; // create an initialized array
string str1; // create an empty string object
string str2 = "panther"; // create an initialized string object

cout << "Enter a kind of feline: ";
cin >> charr1; // ocelot
cout << "Enter another kind of feline: ";
cin >> str1; //tiger

cout << "Here are some felines:\n";
cout << charr1 << " " << charr2 << " "
<< str1 << " " << str2 << endl;

cout << "The third letter in " << charr2 << " is "
<< charr2[2] << endl;
cout << "The third letter in " << str2 << " is "
<< str2[2] << endl;

return 0;

}

在很多方面,使用string对象方式与使用字符数组相同:

  • 可以使用C-风格字符串来初始化string对象
  • 可以使用cin输入string
  • 可以使用cout显示string
  • 可以使用数组表示法访问存储在string对象中的字符

类的设计可以让程序自动处理string的大小

可以说char数组视为一组用于存储一个字符串中的char存储单元,而string类变量是一个表示字符串的实体。

1.1. C++字符串初始化

string str1; 创建一个长度为0的string对象,读取过程中可以自动调整
string str2 = "panther"; 创建一个初始化了的string类对象
string str3 {"Hank's Fine Eats"}; C-风格字符串string对象

1.2. 赋值,拼接和附加

  • string 可以赋值(数值不可)

    1
    2
    3
    string str1;
    string str2 = "jaguar";
    str1 = str2; // valid
  • string类简化了字符串的合并操作(用+或者+=号)

1
2
3
string str3;
str3 = str1 + str2; // assign str3 the joined strings
str1 += str2; // add str2 to the end of str1

1.3. string类I/O

针对char数组时:
cin.getline(char,20); 需要标明数组的长度

针对string对象时:
getline(cin,str1); 不需要标注string的长度

1. 4.2 字符串

字符串是存储在内存的连续字节中的一系列字符。

C++处理字符串的方式有两种:

  1. 来自C语言,常被称为C-风格字符串(C-sytle string)

  2. 给予string类库的方法

1.1. 字符串常量

C-风格字符串具有一种特殊的性质:以空字符(null character)结尾,空字符被写作\0,其ASCII码为0,用来标记字符串的结尾。

🍑 例子:

1
2
char dog[8] = {'b','e','a','u','x','x',' ','I','I'}; // 不是string字符串
char cat[8] = {'b','e','a','u','x','x',' ','I','\0'}; // a string! 是字符串哦耶

这两个都是char,但只有第二个数组是字符串(因为有\0空字符)。

有一种比cat写法更好的将字符数组初始化为字符串的方法,用引号“”即可。

这种字符串被称为字符串常量string constant(字符串常量)或string literal(字符串面值);

1
2
char bird[11] = "Mr.Cheeps"; // the \0 is understood
char fish[] = "Bubbles"; // let the compiler count 让字符串计算
  • 由引号括起来的字符串隐式地包括结尾的空字符,因此不显式的写出来。

  • 应该确保数组足够大, 能够存储字符串中的所有字符,包括空字符。

例子:
char tryee[2] = {'1',';','s'};
错误提示:Excess elements in array initializer

  • 字符常量(如’S’)是字符串编码的简写表示,字符串常量(如”bonjour”)与其不能互换。’S’在ASCII系统上,是’83’的另外一种写法;但”S”就不是字符常量,他表示的是字符S+\0的组合。

1.2. 拼接字符串常量

🍑 例子:

1
cout << "I'd give my right arm to be" "a great violinist.\n";

和下面表达的是等效的。

1
2
cout << "I'd give my right ar"
"m to be a great vionlinist.\n"

1.3. 在数组中使用字符串

下面的code里重点函数为

  1. strlen()

    1
    2
    3
    #include <cstring>

    strlen(一个string) 可以返回string的长度
  2. 截断一个string的操作

在需要阶段的位置替换成’\0’

  1. sizeof()和strlen()的对比

sizeof()运算符是指出整个数组的长度,空字符计算在内
strlen()运算符是指出存储在数组中的字符串的长度,即可见的字符,不计算空字符

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <cstring> //为了使用strlen()工具,来确定字符串的长度


int main()
{
using namespace std;

const int Size = 15;
char name1[Size]; //创建一个空数组
char name2[Size] = "C++owboy"; //初始化数组name2

cout << "Howdy! I am " << name2;
cout << "! What's your name?\n";

cin >> name1;

cout << "Well, " << name1 << ", your name has ";
cout << strlen(name1) << " letters and is stored\n";
cout << "in an array of " << sizeof(name1) << " bytes.\n";

cout << "Your initial is " << name1[0] << ".\n";


//这个操作就截断name2了

name2[3] = '\0'; // set name2 to null character, name2[0],name2[1],name2[2] ...
cout << "Here are the first 3 characters of my name: ";
cout << name2 << endl;



return 0;
}

1.4. 字符串输入

🍑 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int main() {
using namespace std;
const int ArSize = 20;
char name[ArSize];
char dessert[ArSize];

cout << "Enter your name: \n";
cin >> name;
cout << "Enter your favorite dessert: \n";
cin >> dessert;
cout << "I have some delicious " << dessert;
cout << " for you," << name << ".\n";


return 0;
}

要注意的是cin输入的时候,cin使用空白(空格,制表符和换行符)来确定字符串结束的位置,这意味着cin在获取字符串输入时指读取一个单词。

⚠️ 假如输入一个名字Alicia Keys,在这个例子里名字就是Alicia,dessert就是keys,cin一次性得到了两个输入,之后就直接跳到最后一个cout了。

⚠️另外,ArSize的大小为20,如果输入的字符串大于20的长度,也不行哦

1.5. 每次读取一行字符串输入 —— 面对行的输入

1.5.1. getline()将丢弃换行符

getline()将丢弃换行符,通过回车键确认输入结尾,可以使用方法cin.getline()

该函数有两个参数:

  • 第一个参数存储输入行的数组的名称
  • 第二个参数是要读取的字符数(如果这个参数是20,函数最多读取19个字符,最后一个存储空字符)

1.5.2. get()不丢弃换行符

get()的工作原理,参数和getline()类似,但get()不丢弃换行符,而是将其留在输入队列中。

但是不能用连续调用两次get()的方法如下:

🈲️

1
2
cin.get(name,ArSize);
cin.get(dessert,ArSize);

🉑️采用下列做法:

1
2
3
cin.get(name,ArSize);
cin.get();
cin.get(dessert,ArSize);

🉑️也可以这样:

1
2
cin.get(name,ArSize).get(); // concatenate member functions, read newline
cin.get(dessert,ArSize);

1.6. 混合输入字符和数字

混合输入数字和面向行的字符串会导致问题。

修改方法:

  1. 第一种方法

(cin >> year).get()

  1. 第二种方法

cin >> year;
cin.get();

1. 复合类型

1.1. 4.1 数组

数组(array)是一种数据格式,能够存储多个同类型的值

要创建数组,可使用声明语句,数组声明应指出以下三点:

  • 存储在每个元素中的值的类型
  • 数组名
  • 数组中的元素数

在C++中,可以通过修改简单变量的声明,添加中括号(其中包含元素的数目)来完成数组声明:
short months[12];
代表创建了一个名为months的数组,该数组有12个元素,每个元素都可以存储一个short类型的值。
可以归纳为:typeName assayName[arraySize];

arraySize必须是整数常数,或const值。arraySize不可以是变量。

🧾 程序清单4.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int main()
{
using namespace std;

int yams[3]; // initialize int array with size of 3 elements
yams[0] = 7; // assign value to the first element of yams
yams[1] = 8;
yams[2] = 6;

// another way to initialize and assgin values to an array of integers
int yamcosts[3] = {20,30,5}; // 注意这里是大括号!!不是中括号!!


cout << "Total yams = ";
cout << yams[0] + yams[1] + yams[2] << endl;

cout << "The package with " << yams[1] << " yams costs ";
cout << yamcosts[1] << " cents per yam.\n";

int total = yams[0]*yamcosts[0] + yams[1]*yamcosts[1];
total = total + yams[2]*yamcosts[2];


cout << "The total yam expense is " << total << " cents.\n";

// 显示array的长度,显示array中一个element的长度
cout << "Size of yams array = " << sizeof yams << " bytes. \n";
cout << "Size of one element " << sizeof yams[0] << " bytes. \n";

return 0;
}

1.1.1. 数组的初始化规则

  1. 只有在定义的时候才可以使用初始化,此后就不能使用了,例如:

    1
    2
    3
    int cards[3] = {1,2,3}; // valid
    int hands[4];
    hands[4] = {1,2,3,4} // non-valid
  2. 不可以将一个数组赋给另一个数组:

    1
    hands = cards; // not allowed
  3. 可以使用下标分别给数组中的元素赋值

  4. 初始化数组的时候,提供的值可以少于数组的元素数目。下面的语句只初始化hotelTips的前两个元素:
    float hotelTips[5] = {5.0, 2.5};

如果只对数组的一部分初始化,编译器将自动把其他元素设置为0。

因此,如果想把数组中所有元素都初始化为0非常简单,只需要把第一个元素初始化为0即可。
long totals[5000] = {0};

  1. 如果初始化数组时方括号内[]为0,那么C++编译器将计算元素的个数。
    例如,对于:
    short things[] = {1,5,3,8};编译器使things数组包含4个元素。

1.1.2. C++11 数组初始化方法

  1. 初始化数组时,可省略等号(=)

    1
    double earning[4]{1.2,1.2,1.2,1.2};
  2. 可以不在大括号内包含任何内容,这将把所有元素都设置为零。

    1
    2
    unsigned int counts[10] = {}; // all elements set to 0
    float balances[100] = {}; // all elements set to 0
  3. 列表初始化禁止缩窄转换
    long plifs[] = {25,92,1.0}; // not allowed
    这条语句不能通过是因为,浮点数转换为整型(long)是缩窄操作,即便浮点数小数点后为零。

char slifs[4]{'h','i',1122011,'\0'}; // not allowed
这条语句不能通过,因为1122011超过了char变量的取值范围

char tlifs[4]{'h','i',112,'\0'}; // allowed
这条语句可以通过编译,因为虽然112是一个int值,但它在char变量的取值范围内

1. C++ 数学运算符

1.1. 5种基本的C++运算符

    • 加法运算
    • 减法运算
    • 乘法运算
  • / 除法运算(如果两个操作数都是整数,则执行整数除法,小数部分将被丢弃,结果为整数;如果有1个(或2个)操作数是浮点数,则小数部分将被保留,结果为浮点数)
  • % 求模。两个操作数必须都为整数

1.2. 类型转换

1.2.1. 初始化和赋值进行的转换

C++允许将一种类型的值赋给另一种类型的变量,这样做时,值将被转换为接受变量的类型

🍑 例子:

假设so_long的类型为long,thirty的类型为short,而程序为:

1
so_long = thirty; 

程序将thirty的值(short)扩展为long值,so_long将储存这个值,而thirty不变。


将一个值赋给取值范围更大的类型通常不会产生问题,反之,则会降低精度;

下面列出了潜在的问题

转换 潜在的问题
将较大浮点类型转换为较小的浮点类型,如将double转换为float 精度有效数位丢失
将浮点转整数 小数部分丢失
  • 将0赋给bool变量时,将被转换为false;而非零值将被转换为true;

1.2.2. 以{}方式初始化时进行的转换

1.2.3. 表达式中的转换

1.2.4. 传递参数时的转换

1.2.5. 强制类型转换

1.2.6. C++ 11 中的auto声明

auto声明让编译器能够根据初始值的类型推断变量的类型。如果使用了关键字auto,而不指定变量的类型,编译器将把变量的类型设置与初始值相同。

1
2
3
auto n = 100; // n is int
auto x = 1.5; // x is double(疑问:这里x也可以是float吗)
auto y = 1.3e12L // y is long double

1. C++数据类型:整型,bool,char和浮点型

1.1. 整型

C++内置的整型 —— unsigned long, long, unsigned int, int, unsigned short, short, char, unsigned char, signed char, bool 和 unsigned long long, long long (C++ 11新增)

1.1.1. 整型short, int, long 和 long long

计算机内存由一些叫做位(bit)的单元组成,C++的short, int, long和long long分别用不同数目的位来储存值,最多能够表示4种不同的整数宽度。

如果在所有的系统中,每种类型的宽度都相同,则使用起来十分方便。例如,short总是16位,int总是32位,但生活并非那么简单,C++提供了另一种灵活的标准:

  • short 至少16位(2 bytes.)
  • int 至少与short一样长(4 bytes.)
  • long 至少32位,且至少与int一样长 (8 bytes.)
  • long long 至少64位,且至少与long一样长 (8 bytes.)

1.1.2. 无符号类型 unsigned

unsigned 是unsigned int的缩写

如果short表示的范围为-32768到+32767,则无符号版本的表示范围为0-65535,当然,仅当数值不会为负时才应使用无符号类型,如人口等。

1
2
3
4
5
unsigned short change;
unsigned int rovert;
unsigned rovertt; // also unsigned int
unsigned long gone;
unsigned long long lang_lang;

1.1.3. 整数字面型(进制问题)

C++ 使用前一(两)位来标识数字常量的基数。

  • 如果第一位为1 —— 9基数为10(十进制)
  • 如果第一位是0,第二位为1——7,则基数为8(八进制)
  • 如果前两位为0x或0X,则基数为16(十六进制)

pseudo code如下:

1
2
3
4
5
6
7
8
9
10
int chest = 42;     // decimal integer literal 十进制
int waist = 0x42; // hexadecimal integer literal 十六进制
int inseam = 042; // octal interger literal 八进制

// 在cout输出下:

chest = 42 (42 in decimal)
waist = 66 (0x42 in hex)
inseam = 34 (042 in octal)

1.1.4. char类型:字符和小整数

char类型是专门为储存字符(如字母和数字)而设计的。char类型也是一种整型,它足够长,能够表示目标计算机系统中的所有基本符号——字母,数字和标点符号等。char最常被用来处理字符,但也可以将它比作比short更小的整型。

最常用的符号集为ASCII字符集。
例如字符A的编码为65,字母M的编码为77等。

cin输入时,cin将键盘中输入的M转换为77;输出时,cout将77转换为所显示的字符M;cin和cout的行为都是由变量类型(ch)引导的。

C++对字符用单引号'M'对字符串用双引号。

cout.put()为成员函数,提供了一个显示字符的方法,可以代替cout <<

⚠️ 注意是字符而非字符串

亲测

1
2
3
cout.put('M'); // valid
cout.put('My'); // non valid
cout.put("My bag"); // non valid

1.1.5. C++转义序列的编码

字符名称 C++代码
换行符 \n
退格 \n
回车 \r
反斜杠 \\
问号 \?
单引号 \’
双引号 \”

1.1.6. bool 类型

bool布尔变量的值可以是true或false
例如:

1
bool is_ready = true;

1.2. const 限定符

如果程序在多个地方使用相同的一个常量时,可用const来修改变量声明和初始化。
例如,表示一年中月份的符号常量:

1
const int Months = 12;

常量Months被初始化后,其值就被固定了,编译器将不允许再修改该常量的值。

一种常见的做法是常量的首字母大写Months,有助于区分常量变量。另外一种做法是以字母k打头kmonths

1.3. 浮点数

C++有3种浮点类型:float,double和long double。

浮点数能够表示带小数部分的数字,诸如2.5,3.14159,122442.32这样的数字。

计算机将这样的值分成两部分存储。一部分表示值,另一部分用于对值进行放大或缩小。

打个比方,对于数字34.1245和34124.5,他们除了小数点位置不同,其他事相同的。

可以把第一个数表示为0.341245(基准值)和100(缩放因子);第二个数0.341245(基准值)和10000(缩放因子)。

缩放因子的作用是移动小数点的位置,术语浮点也因此得名。

C++内部表示浮点数的方法与此相同,只不过它基于的是二进制数,因此缩放因子是2的幂,不是10的幂。

1.3.1. 浮点数的表示法

  • 第一种 是使用常用的标准小数点表示法:
1
2
3
12.34
0.00023
8.0 // 保证了是float而非int
  • 第二种 是使用E表示法
    其外观类似3.45E6,意思是3.45与1000000相乘的结果;E6指的是10的6次方。
    E表示法确定数字以浮点格式存储,即使没有小数点。
1
2
3
2.52e+8 // valid
8.33E5 // valid
8.33E-4 // valid, exponent can be negative

1.3.2. 浮点的类型float,double和long double

浮点数的三种类型是按它们可以表示的有效数位和允许的指数最小范围来描述的。

有效位(significant figure)是指数字中有意义的位,

🍑 例如:

某山脉额高度位14179英尺,该数字使用了5个有效位。

然而,将其高度写成约14000英尺时,其有效数位为2。因为结果进行了四舍五入精确到了千位。这种情况下,其余的3位仅仅为占位符。

有效数位不依赖于小数点的位置。

例如,可以将山脉高度写为14.162千英尺,这样仍然是5个有效位。


C++对于有效位数的要求是:

  • float 至少32位
  • double至少48位,且不少月float
  • long double至少和double一样多

但通常:

  • float为32位
  • double为64位
  • long double为80,96或128位

书本p48页提供了一个例子说明了double比float提供的精度更高。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
using namespace std;
cout.setf(ios_base::fixed, 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;
}

1.3.2.1. 浮点常量

在程序中书写副电厂粮食,像8.24或2.4E8这样的浮点都属于double类型。

如果你希望常量为float类型,请使用f或F后缀。

如果你希望常量为long double类型,可使用l或L后缀(由于l看起来很像数字1,因此L位更好的选择)

1
2
3
1.234f // a float constsant
2.3423 // a double constant
2.2L // a long double constant

1.3.2.2. 浮点和整数的对比

  • 浮点优点:浮点可以表示整数
  • 浮点优点:由于有缩放因子,他们可以表示的范围大的多
  • 浮点缺点:浮点运算速度比整数运算速度慢,其精度降低

LeetCode每日一题之451.根据字符出现频率排序

今天这题比较简单,周六愉快

给定一个字符串,请将字符串里的字符按照出现的频率降序排列。

0.0.1. 题目

示例 1:

1
2
3
4
5
6
7
8
9
输入:
"tree"

输出:
"eert"

解释:
'e'出现两次,'r''t'都只出现一次。
因此'e'必须出现在'r''t'之前。此外,"eetr"也是一个有效的答案。

示例 2:

1
2
3
4
5
6
7
8
9
10
输入:
"cccaaa"

输出:
"cccaaa"

解释:
'c''a'都出现三次。此外,"aaaccc"也是有效的答案。
注意"cacaca"是不正确的,因为相同的字母必须放在一起。

示例 3:

1
2
3
4
5
6
7
8
9
输入:
"Aabb"

输出:
"bbAa"

解释:
此外,"bbaA"也是一个有效的答案,但"Aabb"是不正确的。
注意'A''a'被认为是两种不同的字符。

0.0.2. 我的解法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution(object):
def frequencySort(self, s):
"""
:type s: str
:rtype: str
"""

# 哈希表
d = {}
for ch in s:
if not ch in d:
d[ch] = 1
else:
d[ch] += 1

# 把字典按value的大小从大到小排序
a = sorted(d.items(), key=lambda x: x[1], reverse=True)

res = ""
for aa in a:
# 小坑:出现多次的字母需要+=多次
for i in range(aa[1]):
res += str(aa[0])

return res


但是因为相当于最多遍历了两次字典,时间还是比较慢的
平平无奇小代码吧。。