作者:罗源凯

Command Line Tools

  1. xcode-select –install
    xcode-select–install 实际上是启动了 /System/Library/CoreServices/Install Command Line DeveloperTools.app 应用,该应用从Apple服务器上下载「CLToolsExecutables.pkg」和「MacOSX109_SDK.pkg」执行安装。

  2. https://developer.apple.com/ 下载

gcc -v命令查看是否安装成功

安装在mac的根目录中
/Library/Developer/CommandLineTools/

ld: unsupported tapi file type ‘!tapi-tbd’ in YAML file
library not found for -lstdc++.6.0.9

Xcode10:
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/
    /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/
    /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/

Xcode11 beta
/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib 
/Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/
/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/lib/
/Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/

Qt常用

快捷键配置方法:

进入“偏好设置 ->环境->键盘”即可配置快捷键。

编号 快捷键 功能
1 Esc 切换到代码编辑状态
2 F1 查看帮助(选中某一类或函数,按下F1,出现帮助文档)
3 F2 在光标选中对象的声明和定义之间切换(和Ctrl+鼠标左键一样的效果,选中某一类或函数,按下F2,迅速定位到该类或函数声明的地方或被调用的地方)
4 F3 查找下一个
5 F4 头文件和源文件之间切换
6 F5 开始调试/继续执行
7 F9 设置和取消断点
8 F10 单步跳过
9 F11 单步进入
10 Shift + F2 声明和定义之间切换
11 Shift + F3 查找上一个
12 Shift + F5 停止调试
13 Shift + F11 单步跳出
14 Ctrl + 0 编辑界面恢复默认字体
15 Ctrl + 1 激活欢迎模式
16 Ctrl + 2 激活编辑模式
17 Ctrl + 3 激活调试模式
18 Ctrl + 4 激活项目模式
19 Ctrl + 5 激活帮助模式
20 Ctrl + 6 激活输出模式
21 Ctrl + B 编译工程
22 Ctrl + E释放后按0 删除新建的分栏
23 Ctrl + E释放后按1 删除所有分栏
24 Ctrl + E释放后按2 上下分栏
25 Ctrl + E释放后按3 左右分栏
26 Ctrl + F 查找/替换当前选中的内容,对与所选内容一致的部分进行高亮显示
27 Ctrl + I 代码格式化
28 Ctrl + K 定位文件,可以找到对应的文件(符号说明:? 帮助、: 类和方法、1 数字 定位当前文件中行、m 类、 f 方法、a 任何工程中、p 当前工程中)
29 Ctrl + L 跳到某一行
30 Ctrl + M 添加/删除书签(书签也可以添加文字标注)
31 Ctrl + W 关闭当前编辑的文件
32 Ctrl + R 运行工程
33 Ctrl + . 下一个书签
34 Ctrl + , 上一个书签
35 Ctrl + / 多行注释/取消多行注释
36 Ctrl + [ 跳到代码块的头部
37 Ctrl + ] 跳到代码块的尾部
38 Ctrl + Tab 快速切换已打开的文件
39 Ctrl + Space 自动补全(Windows系统下与输入法切换快捷键冲突)
40 Ctrl + 转动鼠标滚轮 调整编辑区字体大小
41 Ctrl + Shift + F5 重启调试
42 Ctrl + Shift + F 在项目/文件夹下查找
43 Ctrl + Shift + R 局部变量统一修改(将光标移动到需要更改的变量上,按Ctrl+Shift+ R,当前变量名称外框为红色时,表示已经已激活全局修改功能,当修改此处变量名称时将一同修改代码中所有使用该变量的变量名。),全局变量开启全局替换窗口
44 Ctrl + Shift + U 查找所有使用该符号的地方
45 Ctrl + Shift + < 折叠代码块
46 Ctrl + Shift + > 展开代码块
47 Ctrl + Shift + Up 将当前行的代码向上移动一行
48 Ctrl + Shift + Down 将当前行的代码向下移动一行
49 Alt + 0 隐藏或显示边栏,编辑模式下起作用(有时写的函数太长,屏幕不够大,就用这个)
50 Alt + 1 切换至/关闭生成窗口
51 Alt + 2 切换至/关闭搜索结果窗口
52 Alt + 3 切换至/关闭应用输出窗口
53 Alt + 4 切换至/关闭编译输出窗口
54 Alt + 5 切换至/关闭QML/JS Console窗口
55 Alt + 6 切换至/关闭概要信息窗口
56 Alt + 7 切换至/关闭版本控制窗口
57 Alt + 9 最大化/最小化输出窗口
58 Alt + 左 光标返回到上一位置
59 Alt + 右 光标前进到下一位置
60 Alt + Enter 将光标移动到h文件中的方法声明,按Alt+Enter,再按回车键将在cpp中添加对应的方法实体

格式化代码:

  1. 先全选所有代码(Ctrl + A),然后格式化所选代码(Ctrl + I)
  2. Beautifier插件+astyle
    FYI
    http://astyle.sourceforge.net/install.html
*.astylerc
style=linux             # 设置 Linux 风格
indent-switches         # 设置 switch 整体缩进
indent-namespaces       # 设置 namespace 整体缩进
indent-preproc-block    # 设置预处理模块缩进
pad-oper                # 操作符前后填充空格
delete-empty-lines      # 删除多余空行
add-braces              # 单行语句加上大括号

QT network

网络模块介绍
类名 说明 中文
QAbstractNetworkCache The interface for cache implementations 缓存实现的接口
QNetworkCacheMetaData Cache information 缓存信息
QHstsPolicy Specifies that a host supports HTTP Strict Transport Security policy (HSTS) 指定主机支持HTTP严格传输安全策略(HSTS)
QHttpMultiPart Resembles a MIME multipart message to be sent over HTTP 类似于通过HTTP发送的MIME多部分消息
QHttpPart Holds a body part to be used inside a HTTP multipart MIME message 在HTTP多部分MIME消息中保存要使用的身体部分
QNetworkAccessManager Allows the application to send network requests and receive replies 允许应用程序发送网络请求并接收回复
QNetworkCookie Holds ne network cookie 保持网络cookie
QNetworkCookieJar Implements a simple jar of QNetworkCookie objects 实现一个简单的QNetworkCookie对象
QNetworkDiskCache Very basic disk cache 非常基本的磁盘缓存
QNetworkReply Contains the data and headers for a request sent with QNetworkAccessManager 包含使用QNetworkAccessManager发送的请求的数据和标题
QNetworkRequest Holds a request to be sent with QNetworkAccessManager 持有使用QNetworkAccessManager发送的请求
QNetworkConfigurationManager Manages the network configurations provided by the system 管理系统提供的网络配置
QNetworkConfiguration Abstraction of one or more access point configurations 抽象一个或多个接入点配置
QNetworkSession Control over the system’s access points and enables session management for cases when multiple clients access the same access point 控制系统的接入点,并为多个客户端访问同一接入点的情况启用会话管理
QAuthenticator Authentication object 认证对象
QDnsDomainNameRecord Stores information about a domain name record 存储有关域名记录的信息
QDnsHostAddressRecord Stores information about a host address record 存储有关主机地址记录的信息
QDnsLookup Represents a DNS lookup 表示DNS查找
QDnsMailExchangeRecord Stores information about a DNS MX record 存储有关DNS MX记录的信息
QDnsServiceRecord Stores information about a DNS SRV record 存储有关DNS SRV记录的信息
QDnsTextRecord Stores information about a DNS TXT record 存储有关DNS TXT记录的信息
QHostAddress IP address IP地址
QHostInfo Static functions for host name lookups 用于主机名查找的静态函数
QNetworkDatagram The data and metadata of a UDP datagram UDP数据报的数据和元数据
QNetworkAddressEntry Stores one IP address supported by a network interface, along with its associated netmask and broadcast address 存储网络接口支持的一个IP地址及其关联的网络掩码和广播地址
QNetworkInterface Listing of the host’s IP addresses and network interfaces 列出主机的IP地址和网络接口
QNetworkProxy Network layer proxy 网络层代理
QNetworkProxyFactory Fine-grained proxy selection 细粒度代理选择
QNetworkProxyQuery Used to query the proxy settings for a socket 用于查询套接字的代理设置
QAbstractSocket The base functionality common to all socket types 所有套接字类型通用的基本功能
QLocalServer Local socket based server 本地套接字服务器
QLocalSocket Local socket 本地套接字
QSctpServer SCTP-based server 基于SCTP的服务器
QSctpSocket SCTP socket SCTP套接字
QTcpServer TCP-based server 基于TCP的服务器
QTcpSocket TCP socket TCP 套接字
QUdpSocket UDP socket UDP 套接字
QSslCertificate Convenient API for an X509 certificate 简单的X509证书API
QSslCertificateExtension API for accessing the extensions of an X509 certificate 用于访问X509证书扩展名的API
QSslCipher Represents an SSL cryptographic cipher 表示SSL加密密码
QSslConfiguration Holds the configuration and state of an SSL connection 保持SSL连接的配置和状态
QSslDiffieHellmanParameters Interface for Diffie-Hellman parameters for servers 服务器的Diffie-Hellman参数接口
QSslEllipticCurve Represents an elliptic curve for use by elliptic-curve cipher algorithms 表示椭圆曲线密码算法使用的椭圆曲线
QSslError SSL error SSL错误
QSslKey Interface for private and public keys 私钥和公钥的接口
QSslPreSharedKeyAuthenticator Authentication data for pre shared keys (PSK) ciphersuites 用于预共享密钥(PSK)密码套件的认证数据
QSslSocket SSL encrypted socket for both clients and servers 用于客户端和服务器的SSL加密套接字

C

常量的定义:
1、const 数据类型 常量名
2、【宏定义】#deifne 常量名 值
注意:
1、通过#define 定义的常量 是根据值来匹配数据类型的
2、const 修饰的常量是不安全 可以通过指针来修改

注意:在程序中没有办法表示一个二进制数
%d 将数据按照十进制输出
%o将数据按照八进制输出
%x将数据按照十六进制小写输出
%X将数据按照十六进制大写输出
%u 10进制无符号数 l ll c

原码、反码、补码
一个有符号的整型数据可以分为两部分一部分是符号位、一部分是数字位
无符号数据类型只包含数字位部分
signed int a= 1986(有符号标识 signed可以不用写)
二进制:11111000010

1986原码:0000 0000 0000 0000 0000 0111 1100 0010
-1986原码:1000 0000 0000 0000 0000 0111 1100 0010

1986反码: 0000 0000 0000 0000 0000 0111 1100 0010
-1986反码:1111 1111 1111 1111 1111 1000 0011 1101

1986补码: 0000 0000 0000 0000 0000 0111 1100 0010
-1986补码:1111 1111 1111 1111 1111 1000 0011 1110
负数反码->补码+1
溢出:在数据进行操作的时候会导致超出数据类型大小,会向前位进1,多于原始数据类型大小,会被系统自动舍弃 保留从后面开始数据类型大小的位数

无符号整型取值:0-4294967295(2^32-1)
无符号的字符型:0-255

sizeof()
求出数据类型在内存中占的大小(BYTE)
int value =sizeof(变量名);
int value = sizeof(数据类型) / sizeof 数据类型
注意:根据32位操作系统获取的数据类型大小
char(字符型)【1】<short(短整型)【2】
<=int(整型)【4】|float (单精度浮点型)【4】|long(长整型)【4】
<long long(长长整型)【8】|double(双精度浮点型)【8】

输出和输入:
输出字符的两种方式:
1、printf(“%c”,变量)
2、putchar(字符)
输入字符的两种方式:
1、scanf(”%c”,&b变量)
2、变量=getchar()

字符型:
char 用于存储一个单一的字符
在格式化输入printf(“%c”,变量)通过占位符%c来接收的
每一个char类型都对应在ASCII中有具体的值
转义字符:计算机会使用一些字符来完成程序设计,如果在编程中想使用这些字符的本意,需要通过【\】来转义 \ddd \xhh
注意:想在控制台中输出% 需要使用【%%】

浮点型:
float 用于存储带有小数的数据
在格式化输入printf(“%f”,变量)通过占位符%f来接收的

double 用于存储带有小数的数据 数据长度比float更长
注意:因为将小数转化为二进制时不是一个精确的值,所以浮点型都会有数据偏差

求出数组元素个数:
int (size_t) unsigned int 个数 = sizeof(数组名)/sizeof(数组元素 | 数组数据类型)
求行数:sizeof(数组名)/sizeof(数组名[0]);
求列数:sizeof(数组名[0])/sizeoef(数组名[0][0])

#pragma once 头文件只包含一次
#ifndef SOMEFILE_H
#define SOMEFILE_H
#endif___SOMEFILE_H__

头文件作用:
1. 函数,变量的声明
extern int myMax(int a, int b);
1. 系统库的调用

指针的定义和使用:
1、指针:是一种数据类型 指针变量也是一种变量
2、指针格式: 对应的数据类型 * p:指针类型变量 用来指向一个变量的地址
3、通过指针修改变量的值
p = 200;
4、指针类型在内存中的大小 : 在32位操作系统中所有指针大小都是4个字节大小
打印指针内存大小格式: sizeof(int *) || sizeof(p)
5、内存按照 unsignned int 为每个一个内存分配编号
6、讲解:
①定义变量 int a =10; 数值10 存在内存 为a开辟的空间中 a的地址为0xff00
②定义指针 int * p = &a 指针变量p 在内存中存贮的是 a的地址 0xff00,指针变量p 在内存中的大小在32位系统中都是4个字节大小
p = 200 通过操作指针变量p 所存储的 a的地址 来改变a的值
④指针p 有一个自己的内存地址 指针p地址 与 定义变量a的地址 0xff00不同

野指针、空指针与 万能指针
1、野指针:野指针是指向一个未知的内存空间,可能在读写的时候出现错误。
0-255都是系统保留的 不可以读,不可以写
2、空指针 没有指向任何的地址(其指向0的地址)
空制指针就是指向内存编号为零的空间,操作该内存空间会报错,一般情况空指针用于程序条件判断
3、万能指针:void * 指针可以指向任意变量的内存空间
int a=1;void * p = &a; (int *)p=100;printf(“”%d\n”,(int )p);
int arr[10] = {0};void * p = &a; *((int *)p+0)=100;
((int *)p+1)=200;

const修饰指针
1.通过指针修改const修饰的常量
const int a = 10;
int *p += &a;
*p = 100;
a =100;
可以通过1级指针修改一个常量的值

2.const修饰指针类型 int * 不能改变指针变量指向的内存地址的值 但是可以改变指针指向的地址
const int *p = &a
p=&b
*p = 100
可以改变指针指向的地址

3.const修饰指针变量 能改变指针指向地址的值,但不能改变指针指向的地址

int * const p = &a;
*p = 100;
p=&b
可以修改指针指向地址的值

4.const修饰指针类型修饰指针变量 不能改变指针指向的的值 也不能改变指针指向的地址
const int * const *p = &a;
*p =100;
p = &b;

指针和数组、指针运算:
1、数组名是数组的首地址,这是一个常量
2、指向数组的指针
格式int arr [10] = { 0 } ;
int * p = arr;
当操作指针的时候 间接操作了数组 arr[i] = p[i];
3、指针的降级操作 ,取当前地址的值:p[5]、p
4、对指向数组的指针进行加减操作,可能会导致数组下标越界 。
5、相同的类型的指针相减 结果是两个指针相差的长度
区别:数组名通过sizeof可以求出数组大小,指针只包含数组的首地址信息
课后练习题:输入格式:【 空格 你好 空格 】输出格式为【你好】
指针数组
1、存储char *类型的地址数组
char * arr[] ={“hello”,”world”,”niao”,”baobei”};
2、指针数组,它是数组,数组的每个元素都是指针类型。
多级指针:
1、如果二级指针前面加一个
代表一级指针的值
2、二级指针前面加** 代表指针指向一级指针指向地址的值,加降维度
3、如果n级指针在前面加n个
就是指针指向一级指针指向地址的值

函数参数中如果有数组 都会转化为指针 sizeof(数据类型) 所以求出来的值不作为循环的值使用, 在传递数组时需要加上数组的个数

两种方式求出字符串长度 (图4)
①利用函数strlen();
②通过while循环遍历字符串直至遇到字符串结果\0结束,遍历中定义一个整型变量i,进行记录循环次数,同时也是字符串长度;

v指针作为返回值
①字符串数组 存放在栈区
②字符串常量 会在程序运行时 放在常量区 不能被修改 可以读取 程序结束时会被销毁


全局和局部变量
1、局部变量作用域:从创建到所在函数结束
2、如果在函数中 函数创建顺序从右往左,打印变量地址结果:从高向低增长
3、全局变量:作用在整个项目中,使用的前提是需要在使用的文件中进行声明
4、声明变量就是可以使用这个变量,声明不会分配内存空间 extern
注意:如果在函数外部是全局变量 在函数外面是局部变量
如果全局变量写在主函数下面,想使用需要声明

静态全局和局部变量
1、静态局部变量static和局部变量 可以被赋值
2、静态局部变量和局部变量区别: 只能被初始化一次,可以被多次赋值
全局静态变量只能作用于当前文件中,不能在全部文件中使用
3、auto区分局部变量和全局变量 注意:定义的时候自带声明,但只能在使用它的函数之上

内存布局

  1. 程序没有加载到内存前,可执行程序内部已经分好3段信息,分别为代码区(text)、初始化数据区(data)和未初始化数据区(bss)
    size testfile
  2. malloc在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域
    格式:malloc(分配大小) char* p=(char*)malloc(1);
    注意:创建完的堆空间,在使用完之后不释放,会占用内存空间 free(p);
    释放空间流程 先判断在释放 释放完成 变成空指针

strcopy操作对空间,会将拷贝的字符串全都放到堆空间中,这样就会导致超出堆空间 使程序出现错误;

重置 memset 参数:目标 值 字节大小
注意:①memset可以重置内存区域的值 初始化值为0 但在char类型中可以初始化相同的值
②memset 重置内存的值,前提是重置区域可读可写

memcpy拷贝:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上
①可以从栈区拷贝到堆区 也可以从堆区拷贝到栈区注意:源地址与目标地址不能发生重叠

strcpy 与mencpy的不同
①函数参数不同
②strcpy拷贝字符串 memcpy 可以拷贝一块内存
③strcpy与memcpy拷贝结束标志不同 (“\0”) 与个数

memmove()功能用法和memcpy()一样,
区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。

memcmp:比较s1和s2所指向内存区域的前n个字节,类型不同,但在内存中存的ASCII码相同,所以比较的内容相同

栈遵从规则:后进先出 先进后出


stdio.h

string.h

gets() 输入允许有空格,注意缓冲区溢出
scanf()输入不允许有空格,注意缓冲区溢出scanf(“%[^\n]”,arr);scanf(“%2d %d”,&a,&b);%,%[ – ]屏蔽内容
print()
fgets(指针,大小,输入流) 从stream指定的文件内读入字符,保存到指定的内存,可stdin键盘输入,>加\n\0 ,=加\0
puts() 输出一个字符串并换行
fputs() 将str指定的字符串写入到stream指定的文件中,结束符\0不写入
strlen() 字符串长度,不能处理字符数组
strcpy() 拷贝,\0也一同拷贝
strncpy()拷贝前n个字符
strcat()追加到尾部\0也一同追加
strncat()追加前n个到尾部\0也一同追加
strcmp() 按ASCII码比较大小
strncmp()按ASCII码比较前N个大小
sprintf()根据参数将源字符串来转换并格式化数据
sscanf()根据参数将源字符串来转换并格式化数据
sscanf与scanf一样需要在程序开始加入警告
strchar(字符串,‘字符’) // 失败返回空的值(UNLL)
注意 :①找汉字时格式 “ 汉字 ”,是双引号非单引号
② 字符使用单引号引起来
strstr(源字符串,“匹配字符串”)匹配字符串使用双引号引起来
strtok(目标字符串,“目标字符串中所包含的字符”)
① 将切割点用\0表示,切完之后会破坏原先字符串样式
②当连续出现多个分割字符时只替换第一个为\0
atoi 转整形 /atof转 双精度 /atol转long类型 :
跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字或字符串结束符(‘\0’)才结束转换

定义结构体变量:
①struct 结构体名称 结构体变量名
②结构体变量名.机构体成员列表 = 值
注:如果是字符串类型 需要使用strcpy;
赋值方式
按照结构顺序赋值,.加成员名赋值,结构体变量名.成员名赋值,直接在结构体后面定义变量名;,

结构体需要根据数据类型进行内存对齐;
所有数据类型的大小在内存中存储的资质一定是他的类型的倍数
写结构体位置根据数据类型从大到小的方式书写
有利于节省空间,不利于输出格式的阅读;利于输出格式的阅读,不利于节省空间;需要根据当时权重进行排列

联合union是一个能在同一个存储空间存储不同类型数据的类型;
格式:union 共用体名称 成员列表 共用体变量名
枚举
enum 将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。
typedef
作用:为一种数据类型(基本类型或自定义数据类型)定义一个新名字,不能创建新类型
结构体在.h头文件中定义,在当前它文件中引用其头文件可直接使用


文件操作

1、文件分类:
①文本文件(例:记事本)、
②二进制文件(例:视频文件),优点:所占内存较小
操作文件地址的两种方式:①相对路径 ②绝对路径
2、文件打开与关闭
①格式:FILE *fp = fopen(“路径”,“r”) 做判断 文件是否为空;
打开失败情况:
①找不到文件②没有权限 ③程序打开文件超出上线;
关闭文件操做:fclose(fp);
3、按字符写文件
格式:fputc(‘A’,fp)
4、按字符读取文件
格式:fgetc( fp) 读取整篇文件使用EOF作为判断结束标志
3、按行符写文件
格式:fputcs(‘A’,fp) \0换行
4、按行符读取文件
格式:fgetcs(buf,size, fp)

打开模式:
w:文件不存在会创建一个新文件,如果有文件则清空文件原始内容;
r以只读形式打开,不会创建新文件 如果文件不会存在会报错
a以追加的方式打开文件 文件不存在则创建文件 有文件则在文件结尾追加文件

feof判断文件流是否到结尾, eof判断字符是否到结尾
格式:feof(fp)

格式化文件
①写文件fprintf()
②读文件fscanf()

二进制读写:
fwrite写入
fread读取
fseek() 移动光标为位置,参数(文件流 ,移动字节,模式) 模式: SEEK_SET 以文件开头
SEEK_CUR 以文件当前位置 SEEK_END 以文件结尾
ftell (文件流) 获取光标当前为位置 返回值是long类型 -1代表失败
rewind(文件流 ) 重置光标到文件起始位置

文件删除remove
重命名 移动剪切 rename

文件缓冲区更新flush(文件流)


stdlib.h

system() 调用其它程序


windows.h

WinExec(“calc”,SW_HIDE) 系统调用时默认隐藏黑窗口


time.h

1、添加头文件 time.h stdlib.h
2、添加随机数种子 srand((unsigend int )time(NULL));
3、生成随机数 rand() %
生成随机数 int num=rand()%100+1;1-100



VS 汇编

int a,b,c;
__asm{
    mov a,3
     mov b,4
    mov eax,a
     add eax,b
     mov c,eax
}

QT
Ctrl+i自动格式化代码
Ctrl+/注释取消注释
Alt+Enter 自动完成函数定义
F4 .h .cpp文件切换


VS
Ctrl+k,f自动格式化代码
Ctrl+k,c注释
Ctrl+k,u取消注释


工具
dependency walker 分析库 ldd


错误
处理由C语言函数的警告操作:
1、#define _CRT_SECURE_NO_WARNINGS
放在程序第一行
2、#pragma warning(disable:4996
3、在项目中右击选择属性,在打开对话框中选择C/C++处理器
在预处理器定义中编辑 _CRT_SECURE_NO_WARNINGS

vue使用说明

url参数获取

import Qs from 'qs'
// hash模式
// const query = Qs.parse(location.hash.substring(3))
// history模式
const query = Qs.parse(location.search.substring(1))
let autoId = query.id
// console.log('autoId ' + autoId)
Vue.prototype.autoId = autoId

    return {
      autoId: this.autoId,
      }

 <div>设备编号:{{autoId}}</div>

vue 点击打开新窗口

<el-button  type="primary" class="r" @click="getUrl">按钮</el-button>

methods中:
getUrl(){
  let routeData = this.$router.resolve({ path: '/test' });
  window.open(routeData.href, '_blank');
},

路由文件 router/index.js中:
{
  path: '/test',
  component: () => import('@/views/newPage/test'),
  hidden: true
},

MQ消息队列

  1. 什么是MQ?
    消息总线(Message Queue),是一种跨进程、异步的通信机制,用于上下游传递消息。由消息系统来确保消息的可靠传递。
  2. MQ是干什么用的?
    应用解耦、异步、流量削锋、数据分发、错峰流控、日志收集等等…
  3. MQ衡量标准
    服务性能、数据存储、集群架构

主流竞品分析
RabbitMQ、Kafka、ActiveMQ、ZeroMQ和阿里巴巴捐献给Apache的RocketMQ。甚至连redis这种NoSQL都支持MQ的功能。

  1. ActiveMQ
    是apache出品,最流行的,能力强劲的开源消息总线,并且它一个完全支持JMS规范的消息中间件。其丰富的API、多种集群构建模式使得它成为业界老牌消息中间件,在中小型企业中应用广泛。
    但是其性能稍差,在面对高并发的情况下,会出现消息阻塞、堆积、延迟等问题。
    集群构架模式
    Master-Slave模式:通过zookeeper对主从进行管理,正常情况下,从节点不会提供服务。当主节点出现问题后,zookeeper会高效的将主节点下掉,从节点来提供服务。
    NetWork模式:两套主从Master-Slave节点。由网络联通,将其变为分布式的集群架构。
  2. Kafka
    是LinkedIn开源的分布式发布-订阅消息系统,目前归属于Apache顶级项目。Kafka主要特点就是基于Pull的模式来处理消息消费,追求高吞吐量,一开始的目的就是用于日志收集和传输。0.8版本开始支持复制,不支持事务,对消息的重复、丢失、错误没有严格要求,适合产生大量数据的互联网服务的数据收集业务。能够支持廉价的服务器上以每秒100k条数据的吞吐量。(有ack机制,可以保证不丢失,不能保证不重复。)
    高效的读写基于操作系统低层的Page Cache。仅仅使用内存管理,不存在内存和磁盘之间的IO操作。
    通过replicate进行节点间数据的复制,尽量保证数据的可靠性
  3. RocketMQ
    是阿里开源的消息中间件,目前也已经孵化为Apache顶级项目,它是纯Java开发,具有高吞吐量、高可靠性、适合大规模分布式系统应用的特点。RocketMQ思路起源于Kafka,它对消息的可靠传输以及事务性做了优化,目前在阿里集团被广泛应用于交易、充值、流计算、消息推送、日志流式处理、binlog分发等场景。
    在2.0版本,RocketMQ集群也是通过Zookeeper进行管理。在3.0之后,放弃Zookeeper,使用NameServer进行集群的管理和协调。
    能够保障消息的顺序消费,提供了丰富的消息拉取等处理模式,消费者可以高效进行水平扩展,能够承载上亿级别数据量级。
    可以支持多种集群架构模式:Master-Slave模式、双Master-Slave模式、多主多从模式等等。
    支持多种刷盘策略:同步双写、异步复制。借助了零拷贝等技术。
  4. RabbitMQ
    是一个开源的消息代理和队列服务器,用来通过普通协议在不同的应用之间共享数据(跨平台跨语言)。RabbitMQ是使用Erlang语言编写,并且基于AMQP协议实现。
    RabbitMQ的优势:
    可靠性(Reliablity):使用了一些机制来保证可靠性,比如持久化、传输确认、发布确认。
    灵活的路由(Flexible Routing):在消息进入队列之前,通过Exchange来路由消息。对于典型的路由功能,Rabbit已经提供了一些内置的Exchange来实现。针对更复杂的路由功能,可以将多个Exchange绑定在一起,也通过插件机制实现自己的Exchange。
    消息集群(Clustering):多个RabbitMQ服务器可以组成一个集群,形成一个逻辑Broker。
    高可用(Highly Avaliable Queues):队列可以在集群中的机器上进行镜像,使得在部分节点出问题的情况下队列仍然可用。
    多种协议(Multi-protocol):支持多种消息队列协议,如STOMP、MQTT等。
    多种语言客户端(Many Clients):几乎支持所有常用语言,比如Java、.NET、Ruby等。
    管理界面(Management UI):提供了易用的用户界面,使得用户可以监控和管理消息Broker的许多方面。
    跟踪机制(Tracing):如果消息异常,RabbitMQ提供了消息的跟踪机制,使用者可以找出发生了什么。
    插件机制(Plugin System):提供了许多插件,来从多方面进行扩展,也可以编辑自己的插件。

Netty

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.48.Final</version>
        </dependency>

NioEventLoop-->thread客服端接收客户端连接
Channel连接的封装-->Socket                       PipeLine逻辑处理链-->Logic Chain
ChanneHandler-->Logic逻辑处理链的处理   ByteBut数据流读写-->IO Bytes

BIO:一个线程负责连接,一请求一应答 阻塞同步
伪异步IO:线程池负责连接,M请求N应答 阻塞同步
NIO:缓冲区Buffer,通道Channel,多路复用器Selector 非阻塞同步
AIO:连接注册读写事件和回调函数,读写方法异步,主动通知程序 非阻塞异步

服务端启动
1. 创建服务端Channel
bind()用户代码入口->initAndRegister()初始化并注册->newChannel()创建ServerSocketChannel ->newSocket()通过JDK创建底层jdk channel->NioServerSocketChannelConfig()配制TCP参数类->AbstractNioChannel()->configureBlocking(false)阻塞模式:AbstractChannel()创建id,undafe,pipeline
1. 初始化服务端Channel
init()初始化入口->set ChannelOptions,ChannelAttrs->set ChildOptions,ChildAttrs->config handler配制服务端pipeline逻辑处理链->add ServerBootstrapAcceptor添加连接器
1. 注册事件轮寻器selector
AbstractChannel.register(channel)入口->this.eventLoop=eventLoop绑定线程->resgiter0()实际注册–doRegister()调用JDK底层注册:invokeHandlerAddIfNeeded()用户回调->fireChannelRegistered)传播事件
1. 端口绑定
AbstractUnsafe.bind()入口->doBind()->javaChannel().bind()JDK底层绑定->pipeline.fireChannelActive()事件传播->HeadContext.readIfIsAutoRead()


NioEventLoop
每次执行创建一个线程实体FastThreadLocalThread,线程命名规则nioEventLoop-1-xx
创建->new NioEventLoopGroup()线程组,默认2*cpu->new ThreadPerTaskExecutor)线程创建器->for(){newChild()}构造NioEventLoop->chooserFactory.newChooser()线程选择器

newChild()
保存x线程执行器ThreadPerTaskExecutor
创建一个MpscQueue
创建一个selector

启动->bind()->execute(task)入口->startThread()->doStartThread()创建线程->ThreadPerTaskExecutor.execute()->thread=Thread.currentThread()->NioEventLoop.run()启动->for(;;)->select()检查是否有IO事件->processSelectedKeys()处理io事件->runAllTasks()处理异步任务队列


新连接接入
检测新连接->创建NioSocketChannel->分配线程及注册selector->向selector注册读事件

processSwlectdKey(key,channel)入口->NioMessageUnsafe.read()->doReadMessages()循环while->javaChannel().accept()

new NioSocketChannel(parent,ch)入口->AbstractNioByteChannel(p,ch,op_read)->configureBlocking(false)&save op:-:create id,unsafe,pipeline->new NioSocketChannelConfig()->setTcpNoDelay(true)禁止Nagle算法

channel分类
NioServerSocketChannel
NioSocketChannel
Unsafe

head->ServerBootstrapAcceptor->Tail


pipeline
1. pipeline初始化
在创建Channel的时候创建,节点数据结构ChannelHandlerContext,两大哨兵head和tail
1. 添加删除ChannelHandler
注意顺序
1. 事件和异常的传播
inBound head->a1->b1->…->tail
在处理ByteBuf时不往下传播注意处理要释放资源,SimpleChannelInboundHandler已实现自动释放,都没有处理的在tail中会释放
outBound head<-a2<-b2<-…<-tail 异常触发链 b1->…->a2->b2->…->tail 最好在链最后添加异常处理器,没有处理过的在最后能一同处理


ByteBuf
内存与内存管理器的抽象
不同规格大小和不同类别的内存的分配策略
内存的回收过程

结构:discardable bytes |readable bytes|writable bytes
批针:0<=readerIndex<=writerIndex<=capacity<=maxCapacity
方法:read write set(在当前位置操作,不会移动指针) mark(保存指针),reset(复位指针)
分类:ByteBuf<-AbstratByteBuf<-
PooledHeapByteBuf:<-PooledUnsafeHeapByteBuf
PooledUnsafeDirectByteBUf:
PooledDirectByteBuf:
UnPooledHeapByteBuf:<-UnPooledUnsafeHeapByteBuf
UnPooledUnsafeDirectByteBUf:
UnPooledDirectByteBuf
Pooled从预先分配好的内存操作 UnPooled直接API分配内存
Unsafe可以通过内存直接拿到 非Unsafe没有依赖底层内存JDK
Heap堆上分配内存 Direct虚拟机外的内存中分配了一块缓冲区,不参与GC,手动释放
Direct Buffer创建和销毁的代价很高,所以要用在尽可能重用的地方。 比如周期长传输文件大采用direct buffer,不然一般情况下就直接用heap buffer 就好。

Thread -> PoolThreadCache(tinyCaheSize smallCacheSize normalCacheSize) -> Area
(SubPage)0–>tiny(N*16B共32种)<--512B-->small<–8K(page 512B,1K,2K,4K)–normal—16M(Chunk 8K,16K,32K)—>huge

释放:连续的内存区段加到缓存,标记连续的内存区段为未使用,ByteBuf加到对象池


解码 ByteToMessageDecoder
累加字节流->调用子类的decode方法解析->解析的ByteBuf向下传播

基于固定长度 FixedLengthFrameDecoder:n长度
基本行解码 LineBasedFrameDecoder:\n,\r\n换行结束符,丢弃和非丢弃模式
基于分隔符 DelimiterBasedFrameDecoder 先行处理,找到最小分隔符,解码
基于长度域 LengthFieldBasedFrameDecoder lengthFieldOffset:2偏移lengthFieldLength:2长度


编码 writeAndFlush
从tail节点往前传播-逐个调用channelHandler的write方法->逐个调用channelHandler的flush方法

模拟百万连接
突破局部文件限制和全局文件限制

Server 8000~8100 Client 1025~65535
ulimit -n
sudo vi /etc/security/limits.conf 增加
* hard nofile 1000000
* soft nofile 1000000

cat /proc/sys/fs/file-max
临时使用,重启回到10000
sudo -s
echo 100000 > /proc/sys/fs/file-max
exit
持久使用
/etc/sysctl.conf 增加
fs.file-max=1000000
sudo sysctl -p /etc/sysctl.conf 后重启

业务优化
1. 在单个业务中使用线程池
1. 给handler指定使用JDK的线程池,做不到内存共享

Qt

#include <QDebug>
#include <QString>
#include <QTread>

QSting s1="d:\\";
s1 += "tt";
s1.append("tt");
int pos = s1.indexOf("\\");
s1 = s1.mid(pos+1,QStringLiteral("tt").length());
s1.clear();

str = QString::number(3.14);

Qstring s3="123";
qDebud("d3 value: %s")<< qPrintable(s3)<<endl;
int d3=s3.toInt();
qDebud("d3 value: %d")<< d3<<endl;

QScopedPointer<int> i(new int(3));
QScopedArrayPointer<SPA>spArr(new APS[10]);

class MyThread:public QTread{
public:
    MyThread(){ isStop =false;}
    ~MyThread(){}
    void CloseThread(){isStop = true;}
    void run(){
        while(!isStop){
            qDebud()<< tr("MyThread")<<QThread::currentThreadld();<<endl;
            sleep(10);
        }
    }
private:
    bool isStop;
}

MyThread* pT = new MyThread();
pT->start();

MyThread pT ;
pT.start();

pT.CloseThread();


QPushButton * btn = new QPushButton; //无参构造
//btn->show(); //show用顶层方式弹出
btn->setParent(this); //设置上级
bth->setText("btn"); //将char*隐式转换为QString

QPushButton * btn2 = new QPushButton("btn2",this); //有参构造,窗口按btn2大小显示
this->resize(宽,高);//重置窗口大小
btn2->move(x,y);//按钮移动
btn2->resize(50,50);//按钮大小也可以重置

setWindowTitle("w1");//重置窗口标题setWidgetTitle
setFixedSize(600,400);//设置固定窗口大小

//坐标系X-向右 Y向下

//connect(信号的发送者,发送的信号地址,信号的接收者,处理的函数(槽函数)的地址)
connect(btn,&QPushButton::clicked,this,&QWidget::colose);
//自定类继承public QObject
signals:
    //自定信号,只声明不实现
    void hungry();
public slots:
    //算定槽函数,高版本可以写到public下或全局函数,要声明要实现
    void treat();
    //触发 emit zt->hugry();

//同时也有有参 重载时,利用函数指针明确指向哪个函数的地址
void(T1:: *t1Signal)(QString) = &T1::hungry;
void(S1:: *s1Slot)(QString)=&S1::treat;
connect(t1,t1Signal,s1,s1Slot);
//断开连接
disconnect(t1,t1Signal,s1,s1Slot);
信号与槽参数必须对应,信号的参数个数可以多于槽的参数个数,反之不可以,但必须类型一一对应
connect(zt,SIGNAL(huangry(void)),st,SLOT(treat(void)));//QT4写法,不推荐,类型匹配不检测,当字符串处理,优点,参数类型直观,发生重载不用写函数指针
无参调用有参时可以使用lambda表达式实现

//QString转char* 先转QBtyeArray
QStringName.toUft8.data()

使用lambda表达式C++版本大于11
CONFIG +=  C++11
[](1)-> int {}(2)
[]值引用:空,不使用任何函数对象参数,=值传递方式&引用传递方式,this可以使用所在类的成员变量,a传值默认是const的,要修改传入a的拷贝增加mutable修饰符
(1):参数
-> int:返回值类型
{}:逻辑实现体
(2):()执行
//做信号槽连接时,默认内部变量进行锁状态只读,进行写操作会出错
connect(btn,&QPushButton::clicked,this,[&](){
    btn->setText("dd");//[&]改用[=]
});

connect(ui->actionNew,&QAction::triggered,this,[=](){
        //模态(不可以对其它窗口操作)与非模态(还可以对其它操作)对话框
//        QDialog dlg;
//        dlg.resize(200,100);
//        dlg.exec();  //模态 阻塞

        // 标准调用
        //QMessageBox::critical(this,"错误","critical");
        //QMessageBox::information(this,"信息","infomation");
        //QMessageBox::question(this,"问题","question");
        //QMessageBox::warning(this,"警告","warning");
        if (QMessageBox::Save == QMessageBox::question(this,"问题","question",QMessageBox::Save | QMessageBox::Discard,
                              QMessageBox::Discard)){
            qDebug()<<"Save";
        }else{
            qDebug()<<"Discard";
        };

    });

    connect(ui->actionOpen,&QAction::triggered,this,[=](){
        //模态(不可以对其它窗口操作)与非模态(还可以对其它操作)对话框
        // QDialog dlg2; //一闪而过,应创建在堆上
        //dlg2.resize(200,100);
        //dlg2.show();  //非模态

        QDialog * dlg2 = new QDialog(this);
        dlg2->resize(200,100);
        dlg2->show();  //非模态
        //注意当前对象没有及时释放,防止内存泄露,设置属性关闭弹窗
        dlg2->setAttribute(Qt::WA_DeleteOnClose);

//        QColor color = QColorDialog::getColor(QColor(255,0,0));
//        qDebug()<<color.red() <<color.green() << color.blue();

        QString path = QFileDialog::getOpenFileName(this,"打开文件","c:\\","(*.txt,*.jpg)");
    });

标准对话框
QColorDialog 选择颜色、
QFileDialog 文件
QFontDialog 字体
QInputDialog 允许用户输入一个值,并返回
QMessageDialog 模态对话框
QpageSetupDialog 打印机纸张相关
QPrintDialog 打印配制
QPrintPreviewDialog 打印预览
QProgressDialog 显示操作过程

//    QListWidgetItem  * item = new QListWidgetItem("锄禾日当午");

//    //设置对齐方式
//    item->setTextAlignment(Qt::AlignHCenter);
//    ui->listWidget->addItem(item);

    //QStringList ===  QList<QString>
    QStringList list;
    list << "锄禾日当午"<< "汗滴禾下土"<< "谁知盘中餐"<< "粒粒皆辛苦";
    //QStringList()<<"锄禾日当午"<< "汗滴禾下土"<< "谁知盘中餐"<< "粒粒皆辛苦" 匿名对象也可以直接使用
    ui->listWidget->addItems(list);

//定时器第二种方式
    QTimer * timer1 = new QTimer(this);
    //启动定时器对象
    timer1->start(500); //毫秒做单位
    //每隔0.5秒发送信号
    connect(timer1,&QTimer::timeout,[=](){
        static int num = 0;
        ui->label_4->setText( QString::number(num++));
    });

    //点击按钮 暂停定时器
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        timer1->stop();
    });

设置图标
RC_ICONS = app.ico
MainWindow:windowsIcon 选择图标