在 URL 中利用#:~:text=片段可以进行页面中的文本高亮定位,使用逗号分隔开位置。

部分浏览器支持此功能。

#:~:text=START,END

示例:

http://www.npc.gov.cn/wxzl/wxzl/2000-12/06/content_4379.htm#:~:text=第五条
http://www.npc.gov.cn/wxzl/wxzl/2000-12/06/content_4379.htm#:~:text=第五条,不受处罚的除外。

扩展阅读

DeFi

去中心化金融(英语:Decentralized finance,DeFi)是一种基于区块链的金融,它不依赖券商、交易所或银行等金融机构提供金融工具,而是利用区块链上的智能合约(例如以太坊)进行金融活动。DeFi平台允许人们向他人借出或借入资金,交易加密货币,并在类似储蓄的账户中获得利息。

DAO

去中心化组织(Decentralized Autonomous Organization)这是一种基于区块链的组织结构形式。

相关链接

加密货币列表 - 维基百科

参考资料

去中心化金融 - 维基百科,自由的百科全书 https://zh.wikipedia.org/wiki/%E5%8E%BB%E4%B8%AD%E5%BF%83%E5%8C%96%E9%87%91%E8%9E%8D

基本配置

安装好后,将目录下.env.example改名为.env,编辑该文件。

这里提供一个基本配置,更详尽的内容可参阅官方文档

# Here you can control Directory Lister configuration through environment
# variables. See the configuration documentation for additional information:
# https://docs.directorylister.com/configuration

APP_DEBUG=false
APP_LANGUAGE=zh-CN #语言

DISPLAY_READMES=true
READMES_FIRST=false #README 先于文件列表展示
ZIP_DOWNLOADS=false #是否允许打包下载

GOOGLE_ANALYTICS_ID=false

MATOMO_ANALYTICS_URL=false
MATOMO_ANALYTICS_ID=false

SORT_ORDER=type
REVERSE_SORT=false

SITE_TITLE="文件管理" #站点标题
TIMEZONE="Asia/Shanghai" #时区

隐藏文件

在根目录下创建.hidden文件。该文件每行书写要隐藏的文件,如下所示。

sitemap.xml
README.md

此外,还可采用正则表达式进行配置,详见官方文档

自定义外观

如果需要修改页脚等内容,转入app/views/components目录。如修改页脚,更改footer.twig文件内容即可。保存后,若网站无变化,可能是缓存导致。此时可转入app/cache目录删除views文件夹以清空缓存,即可看到自定义外观生效。

参考资料

推测可能原因:编译时间过长导致任务退出。

解决方案

在经过一次出错后,/www/server/php/74/src/ext/fileinfo/目录下应该已经有下载好的 fileinfo 扩展(这里的74根据版本号进行修改)。

切换到该目录,并执行相关操作。

cd /www/server/php/74/src/ext/fileinfo/

make distclean

./configure --with-php-config=/www/server/php/74/bin/php-config

make

执行完make需要一定时间,耐心等待。执行完毕后,执行:

make install

到面板重载 PHP 配置即可。

参考资料

php_fileinfo宝塔安装不,宝塔面板安装fileinfo扩展报错失败的解决方法_Xi Zi的博客-CSDN博客

新建用户

假设新建用户 Truman 。

useradd Truman
passwd Truman

设置公钥

cd /home/Truman
mkdir .ssh
touch .ssh/authorized_keys

将公钥粘贴至authorized_keys

接下来一步容易忘记——修改权限。

chown -R Truman. .ssh
chmod 700 .ssh
chmod 600 .ssh/authorized_keys

设置免密码 sudo 权限(备用)

visudo

找到

root ALL=(ALL) ALL

在下一行添加

Truman ALL=(ALL) NOPASSWD:ALL

参考资料

搬了一下服务器。搬好后使用 Cloudflare 进行代理,结果发现无法登录 Typecho 后台。登录时会自动 302 重定向回至登录页。

解决方法:修改 Typecho 根目录下的config.inc.php,添加这么一行:

define('__TYPECHO_SECURE__', true);

保存即可,推测和 Cloudflare 的 HTTPS 自动重定向有关。

另外,有网友补充道可以尝试清除 Cookie 来解决这个问题。

如果还是不行,可能与缓存有关。可以清除浏览器缓存或换个浏览器再次尝试,或是尝试到 CDN 处清除缓存。

参考

命令

wget -m -p -k -E -np URL

参数解释:

  • -m 创建镜像,等价于 -r -N -l inf -nrinf是无穷;
  • -p 下载所需的资源,例如图片;
  • -k 下载完成后转换为本地相对路径;
  • -E 把文件以.html命名;
  • -np 不要追溯到父目录;

    详细参数

    原帖-A~-G参数指出要用;分隔,但实际操作中发现应该用,。所以在这里擅自修改了一下。

    启动参数:
    
    -V, –-version 显示wget的版本后退出
    -h, –-help 打印语法帮助
    -b, –-background 启动后转入后台执行
    -e, –-execute=COMMAND 执行`.wgetrc’格式的命令,wgetrc格式参见/etc/wgetrc或~/.wgetrc
    
    记录和输入文件参数:
    
    -o, –-output-file=FILE 把记录写到FILE文件中
    -a, –-append-output=FILE 把记录追加到FILE文件中
    -d, –-debug 打印调试输出
    -q, –-quiet 安静模式(没有输出)
    -v, –-verbose 冗长模式(这是缺省设置)
    -nv, –-non-verbose 关掉冗长模式,但不是安静模式
    -i, –-input-file=FILE 下载在FILE文件中出现的URLs
    -F, –-force-html 把输入文件当作HTML格式文件对待
    -B, –-base=URL 将URL作为在-F -i参数指定的文件中出现的相对链接的前缀
    –-sslcertfile=FILE 可选客户端证书
    –-sslcertkey=KEYFILE 可选客户端证书的KEYFILE
    –-egd-file=FILE 指定EGD socket的文件名
    
    下载参数:
    
    –-bind-address=ADDRESS 指定本地使用地址(主机名或IP,当本地有多个IP或名字时使用)
    -t, –-tries=NUMBER 设定最大尝试链接次数(0 表示无限制).
    -O –-output-document=FILE 把文档写到FILE文件中
    -nc, –-no-clobber 不要覆盖存在的文件或使用.#前缀
    -c, –-continue 接着下载没下载完的文件
    –progress=TYPE 设定进程条标记
    -N, –-timestamping 不要重新下载文件除非比本地文件新
    -S, –-server-response 打印服务器的回应
    –-spider 不下载任何东西
    -T, –-timeout=SECONDS 设定响应超时的秒数
    -w, –-wait=SECONDS 两次尝试之间间隔SECONDS秒
    –waitretry=SECONDS 在重新链接之间等待1…SECONDS秒
    –random-wait 在下载之间等待0…2*WAIT秒
    -Y, –-proxy=on/off 打开或关闭代理
    -Q, –-quota=NUMBER 设置下载的容量限制
    –limit-rate=RATE 限定下载输率
    
    目录参数:
    
    -nd –-no-directories 不创建目录
    -x, –-force-directories 强制创建目录
    -nH, –-no-host-directories 不创建主机目录
    -P, –-directory-prefix=PREFIX 将文件保存到目录 PREFIX/…
    –cut-dirs=NUMBER 忽略 NUMBER层远程目录
    
    HTTP 选项参数:
    
    -–http-user=USER 设定HTTP用户名为 USER.
    -–http-passwd=PASS 设定http密码为 PASS
    -C, –-cache=on/off 允许/不允许服务器端的数据缓存 (一般情况下允许)
    -E, –-html-extension 将所有text/html文档以.html扩展名保存
    -–ignore-length 忽略 `Content-Length’头域
    -–header=STRING 在headers中插入字符串 STRING
    -–proxy-user=USER 设定代理的用户名为 USER
    -–proxy-passwd=PASS 设定代理的密码为 PASS
    -–referer=URL 在HTTP请求中包含 `Referer: URL’头
    -s, –-save-headers 保存HTTP头到文件
    -U, –-user-agent=AGENT 设定代理的名称为 AGENT而不是 Wget/VERSION
    -–no-http-keep-alive 关闭 HTTP活动链接 (永远链接)
    –-cookies=off 不使用 cookies
    –-load-cookies=FILE 在开始会话前从文件 FILE中加载cookie
    -–save-cookies=FILE 在会话结束后将 cookies保存到 FILE文件中
    
    FTP 选项参数:
    
    -nr, -–dont-remove-listing 不移走 `.listing’文件
    -g, -–glob=on/off 打开或关闭文件名的 globbing机制
    -–passive-ftp 使用被动传输模式 (缺省值).
    -–active-ftp 使用主动传输模式
    -–retr-symlinks 在递归的时候,将链接指向文件(而不是目录)
    
    递归下载参数:
    
    -r, -–recursive 递归下载--慎用!
    -l, -–level=NUMBER 最大递归深度 (inf 或 0 代表无穷)
    –-delete-after 在现在完毕后局部删除文件
    -k, –-convert-links 转换非相对链接为相对链接
    -K, –-backup-converted 在转换文件X之前,将之备份为 X.orig
    -m, –-mirror 等价于 -r -N -l inf -nr
    -p, –-page-requisites 下载显示HTML文件的所有图片
    
    递归下载中的包含和不包含(accept/reject):
    
    -A, –-accept=LIST 逗号分隔的被接受扩展名的列表
    -R, –-reject=LIST 逗号分隔的不被接受的扩展名的列表
    -D, –-domains=LIST 逗号分隔的被接受域的列表
    –-exclude-domains=LIST 逗号分隔的不被接受的域的列表
    –-follow-ftp 跟踪HTML文档中的FTP链接
    –-follow-tags=LIST 逗号分隔的被跟踪的HTML标签的列表
    -G, –-ignore-tags=LIST 逗号分隔的被忽略的HTML标签的列表
    
    -H, –-span-hosts 当递归时转到外部主机
    -L, –-relative 仅仅跟踪相对链接
    -I, –-include-directories=LIST 允许目录的列表
    -X, –-exclude-directories=LIST 不被包含目录的列表
    -np, –-no-parent 不要追溯到父目录
    wget -S –-spider url 不下载只显示过程

    参考文档

    Linux wget 命令 中文手册 使用总结 | 浅若清风 https://www.whbwiki.com/298.html

#include<iostream>
using namespace std;
struct LinkNode{
    int data;
    LinkNode *link;
};
typedef LinkNode* NodePtr;

//头部插入 
void Insert(NodePtr &head, int data){
    NodePtr temp = new LinkNode;
    temp -> link = head;
    temp -> data = data;
    head = temp;
}

//迭代输出 
void Iter(NodePtr head){
    for(NodePtr here = head; here != 0; here = here -> link){
        cout << here -> data << endl;
    }
}

//搜索 data 返回指针 
NodePtr Search(NodePtr head, int target){
    for(NodePtr here = head; here != 0; here = here -> link){
        if(here -> data == target){
            return here;
        }
    }
}

//后插入 
void AfterInit(NodePtr head, int target, int value){
    NodePtr afterMe = Search(head, target);
    NodePtr newNode = new LinkNode;
    newNode -> link = afterMe -> link;
    newNode -> data = value;
    afterMe -> link = newNode;
}

//前插入 
void BeforeInit(NodePtr head, int target, int value){
    NodePtr beforeMe = Search(head, target); //位于新元素之后 
    NodePtr newNode = new LinkNode;
    newNode -> data = value;
    for(NodePtr here = head; here != 0; here = here -> link){
        if(here -> link == beforeMe){
            //此时的 here 就是新元素之前的元素 
            here -> link = newNode;
            newNode -> link = beforeMe;
            break;
        }
    }
}

int main(){
    NodePtr head;
    head = new LinkNode;
    head -> data = 13;
    head -> link = 0;
    cout << head -> data << endl << "---" << endl;
    Insert(head, 11);
    Insert(head, 10);
    Insert(head, 9);
    Insert(head, 8);
    Iter(head);
    cout << "---" << endl;
    BeforeInit(head, 13, 12);
    Iter(head);
    return 0;
}

零、先决条件

要学习链表,您应当懂得如何使用structtypedef的用法,和 C++ 语言的一定基础。可以参考文章《数据结构简明入门教程》

链表亦可以使用进行创造,本文采用 C++ 语言的结构进行创造。

一、链表的创建

《数据结构简明入门教程》的第三部分,我们已经了解了链表。接下来将直接介绍链表的创建。

我们先构造一个最简单的链表:只有一个头指针和一个节点

链表示意图1

先决条件下,我们创造一个链表的结构。该链表包含数据部分和指针部分。

struct ListNode
{
    int data; //数据
    ListNode *link; //下一个地址的指针
};
typedef ListNode* ListNodePtr; //我们设指向节点的指针类型叫 ListNodePtr。

//Ptr是 pointer 的缩写,即指针。

我们先创造一个头指针,使之指向一个节点

ListNodePtr head;
head = new ListNode;

使用箭头操作符对该节点进行赋值。由于没有后续节点,link部分我们设为NULLnullptr

head -> data = 12;
head -> link = nullptr; //指向“空”

这样,我们就造好了一个链表。可以用以下代码验证我们真的把数据存进去了:

cout << head -> data;

二、在链表的头部插入节点

链表的头部,通常被称作首元节点。我们现在写一个函数,使得可以插入任意链表的头部。

假设头指针已经定义好为head

void InsertAfterHead(ListNodePtr &head, int data){
    //注意,上方 head 前要有“&”,因为我们需要修改 head 的值。
    
    cin >> data;   //传入新节点 data
    ListNodePtr temp; //创建一个“指向新节点的指针”
    temp = new ListNode; //该指针指向一个新节点
    
    temp -> data = data; //把 data 写入新节点
    temp -> link = head; //新节点的指针用原来的头指针
    head = temp; //把原来的头指针换做“指向新节点的指针”
    
}

三、查找节点

假设有下图的结构,我们需要查找第一项值为9的节点,并将其改为6

链表示意图2

我们设计一个函数,返回值类型是指针,以命中符合要求的链表的节点。

LinkNodePtr Search(LinkNodePtr head, int target){
    //head 为头指针,target 是要查找的目标值
    LinkNodePtr here = head; //设置一个指针,并使之指向头部
    bool gotIt = false;      //设置一个判断标志,如果标志为真则证明找到了目标
    for(; here != nullptr; here = here -> link){ 
        //当指针没有到链表尾部(为空)时进行,并搜索完一个就跳到下一个链表的地址
        
        if(here -> data == target){
            gotIt = true;
            break;
            //如果找到了,就退出循环
        }
        
    }
    
    if(gotIt) return here;
    else return nullptr;
}
LinkNodePtr target = Search(head, 9);
target -> data = 6;

对于上述代码中的 for 循环行为,有一个很酷的名字——迭代。指针here叫做迭代器。

for(LinkNodePtr here = head; here != nullptr; here = here -> link){
    //需要迭代做的事情
}

比如这样就可以逐一打印链表的数据:

for(LinkNodePtr here = head; here != nullptr; here = here -> link){
    cout << here -> data << endl;
}

四、插入节点

假如我们需要找到第一个值为6的节点,并在其后插入数据9

我们写一个插入函数,可以在指定的地址after_me后插入一个节点。

void Insert(LinkNodePtr &after_me, int data){
    LinkNodePtr temp;
    temp = new LinkNode;
    temp -> data = data;
    temp -> link = after_me -> link;
    after_me -> link = temp;
}

为了方便,我们沿用上面写好的Search函数。可以得到下面的代码:

LinkNodePtr target = Search(head, 6);
Insert(target, 9);

五、删除节点

删除节点,即从把该节点上方的指针直接指向下方节点地址。

假设指向上方节点的指针为before,指向待删除的指针为discard

before -> link = discard -> link;
delete discard; //如果要永久删除,使用 delete

六、后记

关于其他的链表,如双向链表、循环链表,请参考教材。相信你看到这里已经能够学会了。

七、参考资料

Walter Savitch 《 C++入门经典(第九版)》。

零、前言

为了弥补教材衔接处的设计问题,特查阅相关资料后书成此文,以助更好地使用教材自学。

为了方便展示,部分代码采用了中文命名的变量名,若需编译,需要使用 C++11 标准的编译器,否则会报错。

一、struct 关键字

struct可以创建结构

假设我们要创建一个名为“银行存单”的结构,其中包含“金额”、“利率”和“时长”三个信息,我们可以得到下图的结构示意。

结构,图示1.jpg

在 C++ 中,利用struct就可以这么写:

struct 银行存单
{
    double 金额;
    double 利率;
    int    时长;//按月份计算
};

注意,别忘了上面括号结尾后的分号。至于为什么会有分号,会在后面说明。

创建好结构之后,我们便可以使用结构。像定义其他变量一样定义一个银行存单类型变量test

int alpha; //变量 alpha,类型为“整型(int)”。
银行存单 test; //变量 test,类型为“银行存单”。

我们可以定义一个函数方便对类型进行数据的写入。

void 数据写入(银行存单 &temp)
{
    cout << "存入金额?";
    cin >> temp.金额;
    
    cout << "利率?";
    cin >> temp.利率;
    
    cout << "存入几个月?";
    cin >> temp.时长;
}

这样,一个完整的程序就写好了:

#include<iostream>
using namespace std;

/*
* 定义结构
*/

struct 银行存单
{
    double 金额;
    double 利率;
    int    时长;//按月份计算
};

/*
* 定义写入结构的函数
*/

void 数据写入(银行存单 &temp)
{
    cout << "存入金额?";
    cin >> temp.金额;
    
    cout << "利率?";
    cin >> temp.利率;
    
    cout << "存入几个月?";
    cin >> temp.时长;
}

int main()
{
    银行存单 test; //定义变量
    数据写入(test);//写入变量
    cout << "一共存入" << test.金额 << "元。"; //使用变量
    return 0;
}

一些更方便的写法,你可以定义一个结构类型的函数,并予以赋值:

银行存单 创建存单(double 金额, double 利率, int 时长)
{
    银行存单 temp;
    temp.金额 = 金额;
    temp.利率 = 利率;
    temp.时长 = 时长;
    return temp;
}

这样,可以在声明变量后快速赋值:

银行存单 test = 创建存单(2000, 0.003, 12);

事实上,还有这种赋值方法:

银行存单 test = {2000, 0.003, 12}; //按照顺序

此外,结构还可以套入结构

例如需要有以下结构层次:

结构,图示2.jpg

我们可以这么写:

struct Date
{
    int year;
    int month;
    int day;
};

struct person
{
    string name;
    char sex;
    Date birthday;
};

让我们回到最开始遗留的一个问题,为什么struct的花括号结尾要多一个分号?这是因为struct支持你在定义好结构后立即创建一个变量,比如:

struct 银行存单
{
    //...
} test1, test2;

但更规范一些的写法,最好是将结构变量的声明分开来写。

二、typedef 关键字

typedef用于简写或重命名类型。

假如,一个不恰当的例子——你不喜欢“int”这个词,你希望它变为“cafe”,即:

int num; //不喜欢
cafe num; //喜欢

有了typedef,你可以这么做:

typedef int cafe;
cafe num;

同样的,你可以给上文的结构起名。假如我们命名一个结构shopTicket,我们希望 以ST称呼这个结构,我们可以这么做:

typedef shopTicket ST;

或者在定义结构的时候就用上:

typedef struct shopTicket
{
    //...
} ST;

也就是说,下面两段代码等价。

struct shopTicket
{
    //...
};
typedef shopTicket ST;
typedef struct shopTicket
{
    //...
} ST;

我个人觉得,用前一种分开定义的写法更利于阅读。

三、链表

假如存在一种这样的模式:

结构,图示3.jpg

一个结构,包含数据和下一个结构地址的指针,这样构成的就是单链表。为了知道第一个结构的位置,我们还需要一个额外的head指针指向第一个结构。像这样的一个结构,我们称之为节点(list node)

struct ListNode
{
    int data; //数据
    ListNode *link; //下一个地址的指针
};
typedef ListNode* ListNodePtr; //我们设指向节点的指针类型叫 ListNodePtr。

//Ptr是 pointer 的缩写,即指针。

我们先创建一个指向第一个结构的指针,叫head

ListNodePtr head;

然后,我们像图里那样,向该结构的数据部分(即data)写入12

(*head).data = 12;

由于圆点操作符.的优先级高于*,所以我们需要用括号把*head围住。

这样写看起来很麻烦,对吧?在 C++ 中,我们有更好的写法——箭头操作符->。也就是说,上面的语句可以简化为

head->data = 12;

其实这很像自然语言——自head指向的data,值为12

利用相同的方法,你可以创建多个ListNode类型的变量,逐一连接起来他们。

对于最后一个节点,他的指针应该宣告结束,否则乱指的指针可能会造成灾难性后果。我们通常设置为NULL

在 C++ 中,NULL等同于0。尽管如此,我们通常还是把结束节点的指针设置为NULL而不是0NULL意味着链的结束。由于NULL0的相等,有时候会带来麻烦。在 C++11 中,引入了专门代表空指针的字面量nullptr。可选地,我们可以用这个代替NULL

四、结语

至此,你已经对数据结构以及链表做了初步的入门,相信接下来你已经可以借助书本学习了。祝你好运。

五、参考资料

  1. Walter Savitch 《 C++ 入门经典(第九版)》ISBN 978-7-302-40297-8
  2. C typedef | 菜鸟教程

先决条件

设备:中兴 MF253S

网络:中国移动

CPE 端设置

打开 CPE 后台,默认是 http://192.168.0.1/

在主页面左侧“断开连接”。

切换到“设置”界面,在“网络设置”下选择“APN”。

新建一个配置文件,

  1. “PDP类型”选择IPv4 & IPv6
  2. “配置文件名称”自己设置;
  3. “IPv4 APN”和“IPv6 APN”设置为CMTDSCMNET
  4. “IPv4 鉴权方式”和“IPv6 鉴权方式”设置为 NONE
  5. 其余留空,点击“应用”并“设为默认”。

回到主页,点击“连接”。

电脑端设置

使用管理员权限打开终端,键入

netsh interface teredo set state enterpriseclient server=default

访问 test-ipv6.com 或执行

ping ipv6.test-ipv6.com -6

查看是否已联通。

参考

win10开启IPv6的两种方法 - twoseee - 博客园

git init
git add .
git commit -m "提交说明"
git branch -M main
git remote add origin git@github.com:用户/仓库.git
git push -u origin main