2019年3月

使用map要添加头文件#include <map>,命名空间using namespace std

初始化一个map:

map<int, bool> m1; 
map<int, const char *> m2; 

对于C++11,还可以在初始化时设定一系列初始值:

map<const char *, int> age_map = {
    pair<const char *, int>("maqian", 22),
    pair<const char *, int>("xiaobai", 1)
};

基本用法:

// 插入元素
insert();
// 删除元素
erase();
// 元素是否存在
count():
// 得到k的值
map[k];

注意的是获取key的值的时候,如果不存在这个元素,map将会自动增加一个当前key的元素。

int main() {
    map<int, bool> m1;
    map<int, const char *> m2;

    map<const char *, int> age_map = {
        pair<const char *, int>("maqian", 22),
        pair<const char *, int>("xiaobai", 1)
    };

    age_map.insert(
        pair<const char *, int>("zhouzhou", 3)
    );

    printf("count: %d, name: %s, age: %d\n", age_map.size(), "maqian", age_map["maqian"]);

    age_map.erase("maqian");
    printf("count: %d, name: %s, age: %d\n", age_map.size(), "maqian", age_map["maqian"]);


    return 0;
}
count: 3, name: maqian, age: 22
count: 3, name: maqian, age: 0
因此,注意不要通过map[x]来判断元素是否存在,使用count()方法。

给nginx配置https时报错:

the "ssl" directive is deprecated, use the "listen ... ssl" directive instead in "nginx.conf:44" 

问题原因

nginx新版本修改了ssl的配置方式,老的ssl on语法已经不推荐使用,建议使用以下形式开启ssl:

listen 443 ssl;

ssl_certificate xx.crt;
ssl_certificate_key xx.key;

低版本nginx开启ssl指令:

ssl on;
ssl_certificate xx.crt;
ssl_certificate_key xx.key;

c++中,调用c语言函数时要对函数添加声明extern "C",这是因为c和c++的符号表机制不一样导致的。

假设存在函数fun,经过gcc编译后,该函数在符号表中的名字是fun,但是经过g++编译后,该函数在符号表中的结果是xxfunxx,c++编译器会在函数两侧加上一些随机字符。因为两者的编译结果不统一,所以混合使用的时候程序找不到符号,无法运行(甚至都无法编译)。一个典型的错误就是(参考实际开发中出现的一个案例:一次undefined reference to *的编译错记录):

/tmp/cccZeFer.o: In function `main':
main.cpp:(.text+0xf): undefined reference to `add'
collect2: error: ld returned 1 exit status

extern "C"语句的作用就是告诉c++编译器:我这个是c语言函数,不要按照你的格式来修改这个函数的符号,按照我的标准来就行了。于是c++编译器编译的时候就按照c的规范来,把两者符号统一。

示例

#include<stdio.h>

int add(int i, int j) {
    return i + j;
} 

int main() {
    printf("%d\n", add(1, 2));
    return 0;
}

代码中有一个函数add,看看它经过gcc和g++编译后分别变成了什么。

使用gcc编译:

image.png

使用g++编译:

imagedb520d0468aeb499.png

两者对比,很明显能看到,使用g++编译后的add函数,符号表前后加上了一些特殊字符。而gcc编译出来的符号就是add本身。

给add函数加上extern "C"声明后:

#ifdef __cplusplus
extern "C" {
#endif

int add(int i, int j) {
    return i + j;
} 

#ifdef __cplusplus
}
#endif

再次使用g++编译,add的符号就和gcc编译出来的符号一样了:

image416e247cd34d6a8f.png

ARQ全称是Automatic repeat request,是TCP中实现可靠传输的重传协议,它的核心思想是停止等待协议。

一、停止等待协议

停止等待协议是数据链路层中最基础的协议,在数据发送出去后,如果没有收到对端的回复,会一直等待对方回复。直到触发超时机制再自动重传,确保数据传输的可靠性。

一个没差错的停止等待协议交互过程为:

一旦出现了差错,停止等待协议会重发数据包,直到数据发送成功:

TCP协议的核心思想就是这样,如果发现数据出现了丢失,就要重传这个数据包,直到数据发送成功为止。

那么如何确定数据报丢失了?TCP使用一个重传计时器对发送报文段计时,如果在计时器归零时还没有收到对端回复,那么就认为数据报已经丢失,需要重传。重传计时器的计时时间被称为RTO,他是通过数据报往返时间动态测量出来的,不同系统上实现也不同。参考:TCP中的RTT和RTO

二、连续ARQ协议

连续ARQ协议指的是每次发送数据时,不是发送一个数据报文,而是同时发送多个报文。因为如果每次都只发送一个数据报,信道的利用率极低,传输效率不高。

连续ARQ协议的作用就是为了弥补这个不足,在发送数据时,不用每次都等到上一个数据包确认后才发送下一个,而是每次都发送一组数据包。确认数据包的同时还继续发送数据包,这样就大大提高了效率。

不出现差错的情况下的交互过程:

出现差错的交互过程:

三、滑动窗口协议

连续ARQ协议是配合滑动窗口协议来完成,每次分组发送的报文数量取决于窗口大小。

参考:TCP的滑动窗口协议

使用logging模块打印日志的时候遇到错误:

Traceback (most recent call last):
  File "saas_utils.py", line 106, in <module>
    sangfor_login("192.168.10.1", login_user, login_pwd)
  File "saas_utils.py", line 72, in sangfor_login
    logging.INFO("%s: %s" % (type(cookie_str), cookie_str))
TypeError: 'int' object is not callable

网上查了一下,出现这个问题的原因是函数或者变量命名错误了,但是检查了一下没有发现有重复的函数和变量名。

后面仔细推敲了一下才发现函数名字写错了,logging.info被我写成了loggin.INFOloggin.INFO是日志的调试级别,当成函数使用当然报错了。

win10的输入法十分简洁,用起来也十分酸爽,对于程序员来说再适合不过了。

只是唯一不好的是输入法没有学习功能(默认情况下没有,需要手动开启),最基本的根据词频调整顺序的功能都没有。

想想这么牛逼的输入法连这个功能都没有岂不是个渣渣?百度一番之后,果然。。。

进入设置页面,点击隐私

然后选择语音、墨迹书写和键入,把开关打开:

enjoy it!