0%

安装 nodejs, npm

  • 建议通过官网安装

    (通过 apt 安装sudo apt install nodejs npm有可能版本过低)

  • 使用ln -s [src] [obj]将 nodejs 和 npm 软链接到/usr/local/bin/

创建 Github 仓库

  • 见另一篇博客 Github 添加 SSH Key

  • 在 Github 中创建名为user_name.github.io 的 public 仓库

安装 hexo

  • hexo 本体安装

    npm install -g hexo-cli

    • 速度慢或无法下载建议换源

      • 淘宝源:

        npm config set registry https://registry.npm.taobao.org

      • cnpmjs 源:

        npm config set registry http://r.cnpmjs.org

    • 或者用 cnpm

      npm install -g cnpm --registry=https://registry.npm.taobao.org

      之后用 cnpm 安装

      cnpm install hexo

    • 还有可能是代理的问题

      npm config set proxy null
      npm config set https-proxy null

    • windows 还有可能是系统环境变量的问题

      检查环境变量HTTP_PROXYHTTPS_PROXY

  • 使用 git 远程部署需要安装

    npm install hexo-deployer-git --save

Hexo 设置

  • 初始化 hexo

    hexo init <filename>

    会从 github 上 clone 一个 blog 模版到 filename

  • 远程部署设置

    打开 filename 的_config.yml 文件
    找到

    1
    2
    3
    4
    deploy:
    type:
    repo:
    branch:

    将其填写为

    1
    2
    3
    4
    deploy:
    type: git
    repo: git@github.com:user_name/user_name.github.com.git
    branch: master

    repo 的写法不唯一
    根据部署位置的协议而定

hexo 常用操作

  • 生成新网页

    hexo n [location]<filename>

    会在sourcelocation(默认为 post)中生成filename.md文件

  • 生成新页面

    hexo n page <pagename>

    会在source中创建pagename文件夹

  • 生成静态网页

    hexo g

  • 部署博客到 远程

    hexo d

  • 本地预览博客

    hexo s

    可以在http://localhost:4000/中预览博客

众所周知
c++中 string 没有自带的 split 函数(亏你还是老大哥)
网上关于 split 函数的优秀写法很多
本人不再赘述
近几日翻 C++API 时发现了 getline 一个有趣的方法

1
istream& getline (istream& is, string& str, char delim);

第一个参数是一个输入流,第二个参数是一个对字符串的常引用,第三个参数是分割符
在读入时遇到分割符则停止
可以用这个来实现单分割符的 split 功能

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

int main() {
stringstream input("45,65,45231,4646,4564");
string str;
while (getline(input, str, ',')) {
cout << str << endl;
}
return 0;
}

简单方便快速。

反转字符串是个很简单也比较常用的方法
此文仅做杂谈,无技术含量

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
#include <iostream>
#include <algorithm>
#include <string>
using namespace std;

void myReverse(const string& str) {
char* c_str = (char*)str.c_str();
char* p, * q;
p = c_str;
q = c_str + str.size() - 1;
while (p < q) {
char temp_c = *p;
*p = *q;
*q = temp_c;
p++;
q--;
}
}

int main() {
string str = "123456789";
myReverse(str); // 反转方式1
cout << str << endl;
reverse(str.begin() + 2, str.end() - 2); // 反转方式2
cout << str << endl;
cout << string(str.rbegin(), str.rend()); // 反转方式3
return 0;
}

运用迭代器还有更多有趣的写法
这里不一一列出

之前做过九宫格输入法的题目
搜了一下网上的解法没找到高效的解法
写一个相对高效的解法
先放上原题

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
假设有九宫格输入法键盘布局如下:

[ 1,.?! ] [ 2ABC ] [ 3DEF ]
[ 4GHI ] [ 5JKL ] [ 6MNO ]
[ 7PQRS ] [ 8TUV ] [ 9WXYZ ]
[ 0空 ]
注意:中括号[ ]仅为了表示键盘的分隔,不是输入字符。
每个中括号中,位于首位的数字字符即是键盘的按键,按一下即可输入该数字字符。
多次按同一个键,则输入的字符依次循环轮流,例如按两次3,则输入D;
按5次7,则输入S;按6次2,则输入A。按键0的输入组合是0和空格字符,即按两次0输入空格。

你需要对于给定的按键组合,给出该组合对应的文本。

输入格式:
输入在一行中给出数个字符的按键组合(例如 999 表示按3次9),
每个字符的按键组合之间用空格间隔,最后一个输入法组合之后以换行结束。
输入数据至少包括一个字符的按键组合,且输入总长度不超过500个字符。

输出格式:
在一行中输出该按键组合对应的文本。

输入样例:
22 5555 22 666 00 88 888 7777 4444 666 44
输出样例:

ALAN TURING 

首先直接以数字读入肯定会爆 题中给出了总长度不超过 500
一种很直接的思路是每次读一个字符,遇到空格做一个统计,然后根据统计的个数输出结果。
但既然每组输入都是相同的数字,那用字符串处理起来可能会更方便
这里放上我的算法

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

const string keys[10] = {
"0 ",
"1,.?!","2ABC","3DEF",
"4GHI","5JKL","6MNO",
"7PQRS","8TUV","9WXYZ",
};

int main() {
string str;
while (cin >> str) { // 从流中读取输入信息
string key = keys[str[0] - '0']; // 按键
int counts = (str.size() - 1) % key.size(); // 按下次数
cout << key[counts]; // 输出
}
return 0;
}

可以说是钻了题目的空子。

先看一段正常的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <string>
using namespace std;

int main() {

string str = "123456789";
str.erase(str.begin() + 2, str.end() - 2);
cout << str;

return 0;

}

移除中间的一段字符
很好的发挥了作用
然后改了一下 希望依次删除字符串中的元素

1
2
3
4
5
6
7
string::iterator it;
// 错误写法
for (it = str.begin(); it != str.end(); it++)
{
cout << *it << " str: " << str << endl;
str.erase(it);
}

错误结果

结果出错并且返回异常
查资料得知 erase 的返回值为被删除迭代器的下一个迭代器
修改程序

1
2
3
4
5
6
7
// 正确写法
for (it = str.begin(); it != str.end(); ) // 注意这里去掉了it++
{
cout << *it << " str: " << str << endl;
it = str.erase(it);

}

正确结果

结果无异常

在实验课上用自己的算法画直线被 diss 效率低
花了半天时间看了下 Bresenham 算法真 🐮🍺
总结一下其中的精妙之处
Bresebham 直线生成算法的基本原理是,每次在最大位移方向上走一步,而另一个方向是走步还是不走步取决于误差项的判别。
声明 k 为斜率
在 0≤k<1 的情况下,假设当前点是 P($x_1$,$y_1$),则下一个点在 $P_u$($x_1$+1,$y_1$+1)与 $P_d$($x_1$+1,$y_1$)中选一。
以 M 表示 $P_u$ 与 $P_d$ 的中点,即 M($x_1$+1,$y_1$+0.5)。设 Q 是理想直线与 x=$x_i$+1 的交点;
显然,若 M 在 Q 的下方,则 Pu($x_1$+1,$y_1$+1)离直线较近,应取为下一个像素;否则应取 $P_d$($x_1$+1,$y_1$)。
理解并不难 主要在于实现
依据该算法的原理基本能够实现
窝先试着自己写了一会
如果要实现各个方向的二维直线绘制
需要考虑多种情况 写出来很不美观
教材上给出了更好的解决方案:
同样以 0≤k<1 为例
每次选取下个点时理想直线的 y 坐标都步进 k 个单位长度
累加值即为误差项 $d_i$
当 $d_i$ 大于 0.5 时选取 Pu 否则选取 $P_d$ 并使 $d_i$-1
令 $e_i$=$d_i$-0.5
则 $e_i$>0 时选取 Pu 否则选取 $P_d$
经过改进,算法的效率大幅提升
但其中在计算斜率与误差项时会用到小数和除法
并且下一步的选择只与误差项的符号有关
因此可以进一步改进:
可知 $e_i$ 的值由三种值组成:$e_i$=-1/2(初始值)+(n 个)y/x(步进值)-(m 个)1(调整值)…
同乘 2x 即得 2x*$e_i$=-x+(n 个)2*y-(m 个)2*x….
这样即可得到仅由整数构成的算法
以上仅为对 0≤k<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
45
46
47
48
point<Type> now_point = start;
point<Type> e_step, point_step;
e_step.x = abs(step.x);
e_step.y = abs(step.y);
glBegin(GL_POINTS);
if (step.x == 0 && step.y == 0) //No Step
return;
point_step.x = (step.x == 0) ? 1 : step.x / e_step.x;
point_step.y = (step.y == 0) ? 1 : step.y / e_step.y;
if (step.x == 0) { // k is endless
do{
glVertex2i(now_point.x, now_point.y);
now_point.y += point_step.y;
} while (now_point.y != end.y);
}
else if (step.y == 0) { //k is zero
do {
glVertex2i(now_point.x, now_point.y);
now_point.x += point_step.x;
} while (now_point.x != end.x);
}
else if (abs(step.y / step.x) == 0) { // |k| < 1
Type e = -e_step.x;
do {
glVertex2i(now_point.x, now_point.y);
e += 2 * e_step.y;
now_point.x += point_step.x;
if (e > 0) {
now_point.y += point_step.y;
e -= 2 * e_step.x;
}
} while (now_point.x != end.x);
}
else { // |k| >= 1
Type e = -e_step.y;
do {
glVertex2i(now_point.x, now_point.y);
e += 2 * e_step.x;
now_point.y += point_step.y;
if (e > 0) {
now_point.x += point_step.x;
e -= 2 * e_step.y;
}
} while (now_point.y != end.y);
}
glEnd();
glFlush();