<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>dccif&apos;s Blog</title><description>记录一些心得</description><link>https://blog.dccif.top/</link><language>zh-CN</language><item><title>Arch下Wayland使用Nvidia私有驱动</title><link>https://blog.dccif.top/2024/06/24/Arch%E4%B8%8BWayland%E4%BD%BF%E7%94%A8Nvidia%E7%A7%81%E6%9C%89%E9%A9%B1%E5%8A%A8/</link><guid isPermaLink="true">https://blog.dccif.top/2024/06/24/Arch%E4%B8%8BWayland%E4%BD%BF%E7%94%A8Nvidia%E7%A7%81%E6%9C%89%E9%A9%B1%E5%8A%A8/</guid><description>记录 Arch Linux 虚拟机使用 NVIDIA 显卡直通与专有驱动时，KDE Wayland 黑屏问题的排查和配置过程。</description><pubDate>Mon, 24 Jun 2024 02:13:12 GMT</pubDate><content:encoded>&lt;h1&gt;起因:&lt;/h1&gt;
&lt;p&gt;最近因为家用的 windows 机器遇到可能是硬件上的故障无法正常使用，没办法，为了有一台电脑用，将之前家用的 pve 上的 vGPU 也卸载了，为了性能使用了显卡直通+Nvidia 专有驱动来运行 Arch 虚拟机，但是发现在最新的 KDE+Wayland 下，默认显示全是黑屏，只有一个光标，无法正常使用。在各种地方查看了之后终于配置成功了，写下这篇文章以帮助其他朋友和备忘。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;安装 软件包与编译环境&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo pacman -Syu
sudo pacman -S base-devel linux-headers git nano --needed
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;安装 nvidia 驱动&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;sudo pacman -S nvidia nvidia-utils nvidia-settings lib32-nvidia-utils
or
sudo yay -S nvidia nvidia-utils nvidia-settings lib32-nvidia-utils
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本人使用的 &lt;a href=&quot;https://github.com/archlinux/archinstall&quot;&gt;archinstall&lt;/a&gt;，这一步应该是默认安装的，关键是后续的配置，只是先写在这里。&lt;/p&gt;
&lt;h2&gt;Wayland 环境变量配置&lt;/h2&gt;
&lt;p&gt;这下面的才是关键：&lt;/p&gt;
&lt;p&gt;NVIDIA-specific options in the root environment file &lt;code&gt;/etc/environment&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;GBM_BACKEND=nvidia-drm
__GLX_VENDOR_LIBRARY_NAME=nvidia
ENABLE_VKBASALT=1
LIBVA_DRIVER_NAME=nvidia
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;需要将如上变量写入/etc/environment&lt;/p&gt;
&lt;h2&gt;kernel modules 配置&lt;/h2&gt;
&lt;p&gt;找到 &lt;code&gt;/etc/mkinitcpio.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;找到 &lt;code&gt;MODULES=()&lt;/code&gt;行，在&lt;code&gt;()&lt;/code&gt;中加入 &lt;code&gt;nvidia nvidia_modeset nvidia_uvm nvidia_drm&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;找到 &lt;code&gt;HOOKS=()&lt;/code&gt;行，如果&lt;code&gt;()&lt;/code&gt;中有&lt;code&gt;kms&lt;/code&gt;,则删除&lt;/p&gt;
&lt;p&gt;新建一个文件 &lt;code&gt;/etc/modprobe.d/nvidia.conf&lt;/code&gt; 文件,内容如下:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;blacklist nouveau
options nvidia_drm modeset=1 fbdev=1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;之后最关键的一步&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo mkinitcpio -P
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更新 initramfs&lt;/p&gt;
&lt;h2&gt;配置 Pacman Hook&lt;/h2&gt;
&lt;p&gt;新建一个文件比如：nvidia.hook,内容如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Trigger]
Operation=Install
Operation=Upgrade
Operation=Remove
Type=Package
Target=nvidia
Target=linux
# Adjust line(6) above to match your driver, e.g. Target=nvidia-470xx-dkms
# Change line(7) above, if you are not using the regular kernel For example, Target=linux-lts

[Action]
Description=Update Nvidia module in initcpio
Depends=mkinitcpio
When=PostTransaction
NeedsTargets
Exec=/bin/sh -c &apos;while read -r trg; do case $trg in linux) exit 0; esac; done; /usr/bin/mkinitcpio -P&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;文件中的注释可以不用调整，面向的是老驱动以及非官方内核&lt;/p&gt;
&lt;p&gt;最后将文件移动到&lt;code&gt;/etc/pacman.d/hooks/&lt;/code&gt;下&lt;/p&gt;
&lt;h2&gt;完成&lt;/h2&gt;
&lt;p&gt;正常情况就可以重启了，这下可以愉快地使用 Walyland 了并且运行在 nvidia 私有驱动下了&lt;/p&gt;
&lt;h2&gt;一键脚本&lt;/h2&gt;
&lt;p&gt;如果上文不想看，那么直接新建一个&lt;code&gt;nvidia.sh&lt;/code&gt;文件，文件名任意&lt;/p&gt;
&lt;p&gt;内容如下&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

# 定义要写入 /etc/environment 的变量
nvidia_variables=(
    &quot;GBM_BACKEND=nvidia-drm&quot;
    &quot;__GLX_VENDOR_LIBRARY_NAME=nvidia&quot;
    &quot;ENABLE_VKBASALT=1&quot;
    &quot;LIBVA_DRIVER_NAME=nvidia&quot;
)

backup_file() {
    local file=$1
    sudo cp &quot;$file&quot; &quot;$file.bak&quot;
}

update_environment() {
    local env_file=&quot;/etc/environment&quot;
    backup_file &quot;$env_file&quot;

    for var in &quot;${nvidia_variables[@]}&quot;; do
        if grep -q &quot;^${var%%=*}&quot; &quot;$env_file&quot;; then
            sudo sed -i &quot;s|^${var%%=*}.*|$var|&quot; &quot;$env_file&quot;
        else
            echo &quot;$var&quot; | sudo tee -a &quot;$env_file&quot; &amp;gt; /dev/null
        fi
    done

    echo &quot;NVIDIA-specific options have been written to $env_file.&quot;
}

update_mkinitcpio_conf() {
    local mkinitcpio_conf=&quot;/etc/mkinitcpio.conf&quot;
    backup_file &quot;$mkinitcpio_conf&quot;

    sudo sed -i &apos;/^MODULES=/ s/(\(.*\))/(\1 nvidia nvidia_modeset nvidia_uvm nvidia_drm)/&apos; &quot;$mkinitcpio_conf&quot;
    sudo sed -i &apos;/^HOOKS=/ s/\(\s*kms\s*\)//g&apos; &quot;$mkinitcpio_conf&quot;

    echo &quot;mkinitcpio.conf has been updated.&quot;
}

create_nvidia_conf() {
    local nvidia_conf=&quot;/etc/modprobe.d/nvidia.conf&quot;
    sudo bash -c &quot;cat &amp;gt; $nvidia_conf&quot; &amp;lt;&amp;lt;EOL
blacklist nouveau
options nvidia_drm modeset=1 fbdev=1
EOL

    echo &quot;$nvidia_conf has been created.&quot;
}

regenerate_initramfs() {
    sudo mkinitcpio -P
    echo &quot;initramfs has been regenerated.&quot;
}

create_nvidia_hook() {
    local hook_dir=&quot;/etc/pacman.d/hooks&quot;
    local hook_file=&quot;$hook_dir/nvidia.hook&quot;

    sudo mkdir -p &quot;$hook_dir&quot;

    sudo bash -c &quot;cat &amp;gt; $hook_file&quot; &amp;lt;&amp;lt;EOL
[Trigger]
Operation=Install
Operation=Upgrade
Operation=Remove
Type=Package
Target=nvidia
Target=linux
# Adjust line(6) above to match your driver, e.g. Target=nvidia-470xx-dkms
# Change line(7) above, if you are not using the regular kernel For example, Target=linux-lts

[Action]
Description=Update Nvidia module in initcpio
Depends=mkinitcpio
When=PostTransaction
NeedsTargets
Exec=/bin/sh -c &apos;while read -r trg; do case \$trg in linux) exit 0; esac; done; /usr/bin/mkinitcpio -P&apos;
EOL

    echo &quot;nvidia.hook has been added to $hook_dir.&quot;
}

main() {
    update_environment
    update_mkinitcpio_conf
    create_nvidia_conf
    regenerate_initramfs
    create_nvidia_hook
}

main


&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;添加运行权限与执行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chmod +x nvidia.sh &amp;amp;&amp;amp; ./nvidia.sh
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;p&gt;最后感谢这些文章的作者，Thanks&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/korvahannu/arch-nvidia-drivers-installation-guide&quot;&gt;arch-nvidia-drivers-installation-guide&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://wiki.archlinux.org/title/NVIDIA/Troubleshooting&quot;&gt;Black screen at Wayland startup&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>在pve下通过9p virtio共享宿主机的目录</title><link>https://blog.dccif.top/2023/08/21/virtio%E5%85%B1%E4%BA%AB%E5%AE%BF%E4%B8%BB%E6%9C%BA%E7%9A%84%E7%9B%AE%E5%BD%95/</link><guid isPermaLink="true">https://blog.dccif.top/2023/08/21/virtio%E5%85%B1%E4%BA%AB%E5%AE%BF%E4%B8%BB%E6%9C%BA%E7%9A%84%E7%9B%AE%E5%BD%95/</guid><description>在 PVE 虚拟机中共享宿主机目录，对比 Virtio 9p、VirtioFS 和 NFS 的性能、权限与配置方式。</description><pubDate>Mon, 21 Aug 2023 14:36:21 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;前提声明本文以下性能数据全是在个人硬件，软件下测的：
PVE 8.0.4 Linux version 6.2.16-6-pve
OMV 6.5 Linux version 6.1.0-0.deb11.7-amd64
smb 共享挂载文档夹后测速&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;起因：
本人因为不想让虚拟机独占硬盘，于是想出了让虚拟机共享宿主机的文档的方案，于是就在挑选技术，同时感谢&lt;a href=&quot;https://zhuanlan.zhihu.com/p/138254689&quot;&gt;OpenMediaVault：你的开源 NAS 系统&lt;/a&gt; 韦易笑 指出的 9p 技术
以下是我选择的几种技术的对比，本人才疏学浅，如有错误请 dalao 指出&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;速度&lt;/th&gt;
&lt;th&gt;ACL（访问控制权限）&lt;/th&gt;
&lt;th&gt;支持系统&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Virtio 9p&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;/image/pve/9pspeed.webp&quot; alt=&quot;9p&quot; /&gt;&lt;/td&gt;
&lt;td&gt;默认支持在虚拟机直接改变宿主机共享文档权限&lt;/td&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NFSv4.2&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;/image/pve/nfsspeed.webp&quot; alt=&quot;nfs&quot; /&gt;&lt;/td&gt;
&lt;td&gt;无法通过虚拟机设置，需要在宿主机设置&lt;/td&gt;
&lt;td&gt;Linux，windows 额外安装&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Virtiofs&lt;/td&gt;
&lt;td&gt;&lt;img src=&quot;/image/pve/virtiofsspeed.webp&quot; alt=&quot;virtiofs&quot; /&gt;&lt;/td&gt;
&lt;td&gt;可选支持是否在虚拟机直接改变宿主机共享文档权限&lt;/td&gt;
&lt;td&gt;Linux,windows 需要额外安装驱动&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;参考上述的表格，我最终选择了使用 9p 共享文档夹。&lt;/p&gt;
&lt;p&gt;下面是介绍一下如何设置 9p 共享文档，只需要修改 3 个文档
虚拟机 conf 文档 路径在 pve 下的 &lt;code&gt;/etc/pve/qemu-server/&amp;lt;你的虚拟机 ID&amp;gt;.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在第一行添加 args：参数&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;args: -virtfs local,path=&amp;lt;你要共享的宿主机目录路径&amp;gt;,mount_tag=&amp;lt;你要取名的挂载TAG，之后挂载要用&amp;gt;,security_model=passthrough,id=fs0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更具体的参数可以参考 &lt;a href=&quot;https://wiki.qemu.org/Documentation/9psetup&quot;&gt;9psetup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Linux 虚拟机启动后，编辑 &lt;code&gt;/etc/fstab&lt;/code&gt;添加下述一行 请先确保虚拟机内的路径存在，没有就先 mkdir 一个&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;取名的挂载TAG   你虚拟机内的挂载路径        9p trans=virtio,version=9p2000.L,rw,share,nobootwait,posixacl,msize=104857600  0  0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后执行 &lt;code&gt;mount -a&lt;/code&gt; 如果没出错，&lt;code&gt;mount&lt;/code&gt; 之后就会列出所有目录
之后虚拟机就可以愉快的使用宿主共享出来文档夹了，同时还能设置 ACL&lt;/p&gt;
</content:encoded></item><item><title>QT 6.2 msvc 2019 下 静态编译</title><link>https://blog.dccif.top/2021/11/11/QT-6-2-msvc-2019-%E9%9D%99%E6%80%81%E7%BC%96%E8%AF%91/</link><guid isPermaLink="true">https://blog.dccif.top/2021/11/11/QT-6-2-msvc-2019-%E9%9D%99%E6%80%81%E7%BC%96%E8%AF%91/</guid><description>QT 6 版本全面换成了 CMake，Win 下环境需要</description><pubDate>Thu, 11 Nov 2021 02:39:30 GMT</pubDate><content:encoded>&lt;h1&gt;环境准备&lt;/h1&gt;
&lt;p&gt;QT 6 版本全面换成了 CMake，Win 下环境需要&lt;/p&gt;
&lt;p&gt;CMake, Ninja, Perl, Python &lt;a href=&quot;https://doc.qt.io/qt-6/windows-building.html&quot;&gt;官网要求&lt;/a&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Tool&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Supported Versions&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CMake&lt;/td&gt;
&lt;td&gt;Version 3.16 and newer (3.17 and newer for &lt;code&gt;-debug-and-release&lt;/code&gt; builds 3.21 and newer for &lt;code&gt;-static&lt;/code&gt; builds).&lt;/td&gt;
&lt;td&gt;Required for configuring the Qt build. Available in the Qt Online Installer and on &lt;a href=&quot;https://cmake.org/&quot;&gt;cmake.org&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ninja&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Recommended tool for building Qt. Available in the Qt Online Installer and on &lt;a href=&quot;https://ninja-build.org/&quot;&gt;ninja-build.org&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perl&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Required build tool. Popular Windows installers are &lt;a href=&quot;https://www.activestate.com/products/perl/downloads/&quot;&gt;ActiveState Perl&lt;/a&gt; and &lt;a href=&quot;https://strawberryperl.com/&quot;&gt;Strawberry Perl&lt;/a&gt;. Perl is also installed as part of &lt;a href=&quot;https://git-scm.com/download/win&quot;&gt;Git&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Version 3&lt;/td&gt;
&lt;td&gt;Required build tool. Windows installers are available on &lt;a href=&quot;https://www.python.org/downloads/windows/&quot;&gt;python.org&lt;/a&gt;, or from the &lt;a href=&quot;https://docs.python.org/3/using/windows.html#windows-store&quot;&gt;Microsoft Store&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;关于 Perl 个人推荐 &lt;a href=&quot;https://strawberryperl.com/&quot;&gt;Strawberry Perl&lt;/a&gt; 版本新，安装方便。缺工具就去下，全部环境变量中配置好就行&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h3&gt;编译环境选择：MinGW/MSVC&lt;/h3&gt;
&lt;p&gt;在 Windows 上，有两个预构建环境可供选择：一个是 MinGW ，另一个是 Microsoft Visual Studio(MSVC)。这两个环境不兼容，无法混合。你必须选择一个。&lt;/p&gt;
&lt;p&gt;这两者的区别如下：&lt;/p&gt;
&lt;p&gt;当你的项目使用 MinGW 编译的使用，想要用一个 MSVC 编译生成的库时就会有问题。使用 MinGW 编译项目的时候，所使用的 Lib 也要是 MinGW 编译的。如果你只是开发 Window 平台的软件时，最好用 Qt MSVC 组合，这样可以使用大量的第三方 lib，还有很多的构建指令，毕竟 window 上 MSVC 才是王道。&lt;/p&gt;
&lt;p&gt;我选择 MSVC，打开安装 VS 时自带安装的 MSCV：&lt;code&gt;x64 Native Tools Command Prompt for VS 2019&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;不要使用 Developer Command Prompt for VS 2019&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;编译&lt;/h2&gt;
&lt;p&gt;在随便什么盘里新建一个目录用来存放编译好的内容：&lt;code&gt;D:\qt&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;在&lt;code&gt;x64 Native Tools Command Prompt for VS 2019&lt;/code&gt;的终端进入 Qt 源代码目录：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;C:\Users\peter\Downloads&amp;gt;cd qt-everywhere-src-5.15.0

C:\Users\peter\Downloads\qt-everywhere-src-5.15.0&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;s&gt;（不推荐,可跳过）1.修改源码里的&lt;code&gt;qtbase\mkspecs\common\msvc-desktop.conf&lt;/code&gt;文件&lt;/s&gt;&lt;/h3&gt;
&lt;p&gt;修改-MD 为-MT&lt;/p&gt;
&lt;p&gt;修改前：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QMAKE_CFLAGS_RELEASE    = $$QMAKE_CFLAGS_OPTIMIZE -MD
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MD
QMAKE_CFLAGS_DEBUG      = -Zi -MDd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改后：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;QMAKE_CFLAGS_RELEASE    = $$QMAKE_CFLAGS_OPTIMIZE -MT
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MT
QMAKE_CFLAGS_DEBUG      = -Zi -MTd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;D 的意思是动态编译(dynamic link)，T 的意思是静态编译（static link）。 这一步官方教程没有要求&lt;/p&gt;
&lt;p&gt;目的仅有让编译出来的 Win 上静态文件是最小的（不推荐使用）会导致 example 等动态链接的库无法使用编译好的静态 QT 编译&lt;/p&gt;
&lt;h3&gt;配置 config 文件：&lt;/h3&gt;
&lt;p&gt;主要需要在 VS 2019 的命令行中运行，如果一次配置不通过，出错下一次也是无法通过的，因为有&lt;code&gt;CMakeCache.txt&lt;/code&gt; 文件，需要删除上一步失败的&lt;code&gt;CMakeCache.txt&lt;/code&gt;文件&lt;/p&gt;
&lt;p&gt;我的配置文件：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;configure.bat -static -prefix &quot;D:\qt&quot; -confirm-license -opensource -debug-and-release -platform win32-msvc -optimize-size -no-pch -nomake examples -nomake tests -nomake tools -plugin-sql-sqlite -plugin-sql-odbc -qt-zlib -qt-libpng -qt-freetype -qt-pcre -qt-harfbuzz -qt-libjpeg -opengl desktop -mp
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;具体含义如下：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;configure.bat
-static  #指明静态编译
-prefix &quot;D:\qt&quot; #安装目录，最好使用不需要管理员权限的目录
-confirm-license -opensource #指明是开源版本
-debug-and-release #指明需要debug版和release版，可以单独选择release版
-platform win32-msvc #指明使用msvc编译，这里的win32并不指32位
-optimize-size #最优化文件大小而不是速度(可选)
-no-pch #不使用预编译头文件（可选）
-nomake examples -nomake tests -nomake tools #不编译用不上的东西
-plugin-sql-sqlite -plugin-sql-odbc -qt-zlib -qt-libpng -qt-freetype -qt-pcre -qt-harfbuzz -qt-libjpeg #可选插件
-opengl desktop  #用系统自带的opengl
-mp #多核编译
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果无报错&lt;/p&gt;
&lt;p&gt;接着运行&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cmake --build . ---parallel //编译本目录，parallel为并行，即多核心编译
cmake --install . //安装命令
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;配置 QtCreator&lt;/h2&gt;
&lt;p&gt;Qt version 下找到刚才编译的&lt;code&gt;bin/qmake.exe&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Kits 下选择刚才的 Qt version 注意编译器选择需要和上面编译时使用的一样&lt;/p&gt;
&lt;p&gt;至此，编译完成&lt;/p&gt;
&lt;h2&gt;测试大小&lt;/h2&gt;
&lt;p&gt;选择 release 模式编译，等待编译完成后打开编译文件夹，即可看到编译后的文件大小大约 12.7MB&lt;/p&gt;
&lt;p&gt;如果是动态编译，再使用&lt;code&gt;windeployqt&lt;/code&gt;个人测试的大小是 78MB 左右，所以还是静态编译时省事&lt;/p&gt;
&lt;h2&gt;参考&lt;/h2&gt;
&lt;p&gt;最后感谢这些文章的作者，Thanks&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://last2win.com/qt-5.15-static-link/&quot;&gt;Qt5.15 在 Windows 环境静态编译安装和部署的完整过程 VS 2019-Qt static link build Windows 64 bit&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://aymetic.com/post/2273ab9c.html&quot;&gt;使用 MSVC2019 静态编译生成 Qt 库&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://decovar.dev/blog/2018/02/17/build-qt-statically/&quot;&gt;At last, let&apos;s build Qt statically&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>博客的一键部署2</title><link>https://blog.dccif.top/2021/11/06/%E5%8D%9A%E5%AE%A2%E7%9A%84%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B22/</link><guid isPermaLink="true">https://blog.dccif.top/2021/11/06/%E5%8D%9A%E5%AE%A2%E7%9A%84%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B22/</guid><description>承接以前的 博客的一键部署</description><pubDate>Sat, 06 Nov 2021 16:45:03 GMT</pubDate><content:encoded>&lt;h1&gt;博客的一键部署 2&lt;/h1&gt;
&lt;p&gt;承接以前的 &lt;a href=&quot;https://blog.dccif.top/2017/11/27/%E5%8D%9A%E5%AE%A2%E7%9A%84%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2/&quot;&gt;&lt;strong&gt;博客的一键部署&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;时隔几年，我又开始写博客了，这次一开始还是纠结了是选用传统的动态博客还是静态博客，考虑的价钱和安全性的问题，可能还是静态博客更适合我目前的阶段&lt;/p&gt;
&lt;h2&gt;曾经的一键部署不好用了吗？&lt;/h2&gt;
&lt;p&gt;的确曾经我的一键部署把简单的问题复杂了，想着利用一个仓库的两个分支保存原始文件和生成文件。的确这没有问题，目前我的博客也是这个方式，但是有问题的是我过去的整个工作流程。曾经我的流程完全和现在相反，难怪当初的用法那么难受 😂&lt;/p&gt;
&lt;h2&gt;现在的方法&lt;/h2&gt;
&lt;p&gt;用现在 Modern 一点的词来说，就是现在使用了&lt;strong&gt;持续集成 ( Continuous integration )&lt;/strong&gt;, 毕竟博客这种&lt;em&gt;项目&lt;/em&gt;也算一种&lt;strong&gt;持续交付（Continuous delivery）&lt;/strong&gt;，&lt;strong&gt;持续部署（continuous deployment）&lt;/strong&gt;，只不过现在我只需写文章，然后推送，现代的在线工具就可以完成部署任务了，可以说能让我更专注于写作了。不过如果要长时间保持产出干货文章还是有点难度的啊，还是评说评说游戏什么的好了 🤣&lt;/p&gt;
</content:encoded></item><item><title>小谈绘画中的RGB与HSB(V)</title><link>https://blog.dccif.top/2020/07/27/%E5%B0%8F%E8%B0%88%E7%BB%98%E7%94%BB%E4%B8%AD%E7%9A%84RGB%E4%B8%8EHSB(V)/</link><guid isPermaLink="true">https://blog.dccif.top/2020/07/27/%E5%B0%8F%E8%B0%88%E7%BB%98%E7%94%BB%E4%B8%AD%E7%9A%84RGB%E4%B8%8EHSB(V)/</guid><description>看了网络上的关于数字绘画，图层混合模式还有所谓的不同色彩空间的描述，感觉还是不够满意，便有了这篇文章，本人才疏学浅，试图从原理上说明一下，如有疏漏和错误，还是请真大佬来指出了吧。以下都是本人个人闭门造车的一些经验。</description><pubDate>Mon, 27 Jul 2020 03:11:06 GMT</pubDate><content:encoded>&lt;h1&gt;开篇一段废话：&lt;/h1&gt;
&lt;p&gt;看了网络上的关于数字绘画，图层混合模式还有所谓的不同色彩空间的描述，感觉还是不够满意，便有了这篇文章，本人才疏学浅，试图从原理上说明一下，如有疏漏和错误，还是请真大佬来指出了吧。以下都是本人个人闭门造车的一些经验。&lt;/p&gt;
&lt;h1&gt;首先什么是RGB,HSB(V)：&lt;/h1&gt;
&lt;p&gt;能点进来看的人，多半这两个都是知道的吧。但是这两本质是一个“&lt;strong&gt;色彩空间&lt;/strong&gt;”，只不过HSB(V)是RGB的另一种坐标表达方式。但是绘画中还是HSB(V)好用，但是图层混合模式中使用的又是RGB，这反正就使得我个人对使用HSB(V)颜色时对图层混合的不断“试错”。&lt;/p&gt;
&lt;p&gt;归根到底还是要知道RGB&amp;lt;-&amp;gt;HSB(V) 到底发生了什么&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/draw/rgbtohsv.webp&quot; alt=&quot;RGB to HSV&quot; /&gt;&lt;/p&gt;
&lt;p&gt;最快方式就是看公式。&lt;/p&gt;
&lt;p&gt;看$RGB \to HSB(V)$的公式，很快我们能发现S和V的值的定义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;$S=\frac{\text{最亮光}-\text{最暗光}}{\text{最亮光}}$&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;V简单明了，就是当前最亮光的值。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我个人感觉知道这两就够了，特别是B(V)值得由来，毕竟绘画时也是这个最重要。&lt;/p&gt;
&lt;p&gt;这样随便一个RGB的颜色的明度都能“脑内”换算了。整一个图的明度也知道依照的是什么了。&lt;/p&gt;
&lt;p&gt;HSB(V)-&amp;gt;RGB公式的实用意义不大，我也就不列了&lt;/p&gt;
&lt;p&gt;所以最重要的结论便是 &lt;strong&gt;RGB中最亮的光就是当前颜色的明度。饱和度是最亮光与最暗光的差值与最亮光的比值&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;色彩与明度的关系：&lt;/h1&gt;
&lt;p&gt;不同的颜色会给人产生不同的明度感。比如下图&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/draw/hueandvalue.webp&quot; alt=&quot;hue and value&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这种明度感，我们可以通过转换成灰度，一下就能看出&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/draw/grayandvalue.webp&quot; alt=&quot;gray and value&quot; /&gt;&lt;/p&gt;
&lt;p&gt;明明RGB上一样光数值的颜色，为什么给人的“明度”感不一样呢？&lt;/p&gt;
&lt;p&gt;说到底颜色就是一种幻觉，一切颜色不过是电磁波打在了视锥，视杆细胞上产生了电信号后经大脑处理后产生的罢了。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/draw/eyeballandcolor.webp&quot; alt=&quot;eyeball and color&quot; /&gt;&lt;/p&gt;
&lt;p&gt;一张图就能说明一切，因为人眼对不同光线的“灵敏度”不同。&lt;/p&gt;
&lt;p&gt;举上面的黄光为例，人之所为看到黄光，本质是绿色视锥细胞和红色视锥细胞被激活了，这两细胞被激活的同时，感受“明度”的视杆细胞同时被两种“光线”刺激，很显然就会觉得“明度”高了。&lt;/p&gt;
&lt;p&gt;这就可以得出结论&lt;strong&gt;哪怕RGB上同明度的混合色，人眼感知明度也比同明度的原色高。&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;图层混合模式：&lt;/h1&gt;
&lt;p&gt;说到绘画中最常用的模式，多半还是Multiply/正片叠底/色彩增值 和 Screen/滤色了。一个是变暗，一个是加亮&lt;/p&gt;
&lt;p&gt;Multiply/正片叠底/色彩增值：直接2种颜色相乘，公式网上都是。因为最亮的白色是1，所以1*任何颜色 = 任何颜色，这样就能去白留黑。&lt;/p&gt;
&lt;p&gt;然而在绘画中，多半是用来绘制阴影。与其用中性灰来压暗，绘画中可能更多的是&lt;strong&gt;使用光线的颜色来直接绘制“带颜色”的阴影&lt;/strong&gt;。直接使用光线的颜色，这样的阴影还会有光源的颜色信息，因为都是比例，两个小数会越乘越小。&lt;/p&gt;
&lt;p&gt;Screen/滤色：其实同理，只不过是两个颜色的“负片”正片叠底后再负片。负片越暗再负片就越亮，同理&lt;strong&gt;直接使用光源的颜色，能反映出光源信息。&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;总结&lt;/h1&gt;
&lt;p&gt;写这种多本质还是想说绘画时其实也可以通过RGB思考颜色，并不一定总是HSB(V)，通过RGB思考颜色，还能比较方便的转换到CMYK的手绘上，毕竟颜色的本质都是反射多少光线。&lt;/p&gt;
&lt;h1&gt;附：RGB-&amp;gt;HSV的3维过程&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;/image/draw/rgbtohsv3d.webp&quot; alt=&quot;RGB to HSV in 3D&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>关于《疯狂系列》</title><link>https://blog.dccif.top/2018/02/24/%E5%85%B3%E4%BA%8E%E3%80%8A%E7%96%AF%E7%8B%82%E7%B3%BB%E5%88%97%E3%80%8B/</link><guid isPermaLink="true">https://blog.dccif.top/2018/02/24/%E5%85%B3%E4%BA%8E%E3%80%8A%E7%96%AF%E7%8B%82%E7%B3%BB%E5%88%97%E3%80%8B/</guid><description>首先感谢李刚老师的《疯狂 HTML5》的一书，本文以下的内容也是基于这本目前我看完的书得出的，作为对比的是《Head First HTML5》。</description><pubDate>Sat, 24 Feb 2018 12:38:06 GMT</pubDate><content:encoded>&lt;h1&gt;关于《疯狂系列》&lt;/h1&gt;
&lt;p&gt;首先感谢李刚老师的《疯狂 HTML5》的一书，本文以下的内容也是基于这本目前我看完的书得出的，作为对比的是《Head First HTML5》。&lt;/p&gt;
&lt;p&gt;下面我就从我暂时能想到的几个方面来谈谈这本《疯狂 HTML5》或者同样的《疯狂系列》和《Head Fist》系列的对比吧。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;目标受众&lt;/h2&gt;
&lt;p&gt;很多人评价书时没有注意到这本书是写个谁的，举个不恰当的例子，就像小学生买了高数书，然后说这本书不好，这样对书的评价我觉得是不客观的，也是不公平的，我竟然从这两个系列面向的不同的受众说说吧，当然本来我的水平也不高 😅&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;《疯狂系列》&lt;/th&gt;
&lt;th&gt;《Head First》&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;已经从事软件开发的人员&lt;/td&gt;
&lt;td&gt;还未入门的人士&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这不是我说的，是这两本书前言自己写的。&lt;/p&gt;
&lt;p&gt;所以有人拿着一本《疯狂系列》然后说没法入门，是本&lt;s&gt;垃圾&lt;/s&gt;书我个人觉得是有失客观的。&lt;/p&gt;
&lt;h2&gt;内容深度和广度&lt;/h2&gt;
&lt;p&gt;说到一本入门级的书，到底要到什么程度？每个人有自己的看法，但是就书的广度来说，《疯狂系列》不愧是看完之后还能作作参考书的“入门书”，而《Head First》更像一个领路人，告诉读者这里可以这样，原理是什么。&lt;/p&gt;
&lt;p&gt;所以就我看的这一本来说&lt;/p&gt;
&lt;p&gt;深度：《疯狂》部分 &amp;lt;≈，其余 &amp;gt;《Head First》&lt;/p&gt;
&lt;p&gt;广度：《疯狂》&amp;gt;《Head First》&lt;/p&gt;
&lt;h3&gt;暂时的结语&lt;/h3&gt;
&lt;p&gt;所以如果我推荐，还是两本都看看，不重要的可以先跳过，但是《Head First》要先看，之后再看《疯狂系统》&lt;/p&gt;
&lt;p&gt;当然最好的入门还是 best practices，在做的过程中学得最快。&lt;/p&gt;
</content:encoded></item><item><title>致过去的一年</title><link>https://blog.dccif.top/2018/01/02/%E8%87%B4%E8%BF%87%E5%8E%BB%E7%9A%84%E4%B8%80%E5%B9%B4/</link><guid isPermaLink="true">https://blog.dccif.top/2018/01/02/%E8%87%B4%E8%BF%87%E5%8E%BB%E7%9A%84%E4%B8%80%E5%B9%B4/</guid><description>眨眼间，2017就过去了，回首这一年，也许我最大的收获就是发现了自己有多弱了吧。从编译到算法，从语言到实现，我看上去每一门都知道那么一点，可是却又都不都不深入，也没自己实现过大一点的项目。</description><pubDate>Tue, 02 Jan 2018 05:03:11 GMT</pubDate><content:encoded>&lt;h1&gt;致过去的一年&lt;/h1&gt;
&lt;p&gt;眨眼间，2017就过去了，回首这一年，也许我最大的收获就是发现了自己有多弱了吧。从编译到算法，从语言到实现，我看上去每一门都知道那么一点，可是却又都不都不深入，也没自己实现过大一点的项目。&lt;/p&gt;
</content:encoded></item><item><title>近期随想</title><link>https://blog.dccif.top/2017/12/18/%E8%BF%91%E6%9C%9F%E9%9A%8F%E6%83%B3/</link><guid isPermaLink="true">https://blog.dccif.top/2017/12/18/%E8%BF%91%E6%9C%9F%E9%9A%8F%E6%83%B3/</guid><description>自从我上次写好一键脚本后，过了快半个月，我却完全没有因为有了方便的脚本而增加写文产量😥，于是打算今天写一篇，并说说今日的学习记录吧。</description><pubDate>Mon, 18 Dec 2017 15:07:37 GMT</pubDate><content:encoded>&lt;h1&gt;近期的随想&lt;/h1&gt;
&lt;p&gt;自从我上次写好一键脚本后，过了快半个月，我却完全没有因为有了方便的脚本而增加写文产量😥，于是打算今天写一篇，并说说今日的学习记录吧。&lt;/p&gt;
&lt;h2&gt;学习的一些心得&lt;/h2&gt;
&lt;p&gt;最近因为Java Web中要使用Java而又对Java不太熟悉的我，翻出了以前库存的一大批书中，写给Java新人的书&lt;/p&gt;
&lt;p&gt;《Head First Java》顿时有种相见恨晚的感觉，这书有些难度又不失趣味的介绍了Java的核心思想和技术，对于我这种要巩固Java应用与提高使用水平的我来说，如一盏明灯，在Java的世界中给我照亮了一片前进与深入的方向，请允许我这这里用这种修饰来表达我对这本书的赞誉，虽然这和我以前的博文风格有着极大的不同😅，但是我相信读者朋友（如果有的话）一定可以感受出这本书，或者说这一系列书对我的帮助（下面会说Head First一系列的书），在此，我真的给每一位在自我感觉在入门到中高级的朋友推荐Head First系列的书。&lt;/p&gt;
</content:encoded></item><item><title>博客的一键部署</title><link>https://blog.dccif.top/2017/11/27/%E5%8D%9A%E5%AE%A2%E7%9A%84%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2/</link><guid isPermaLink="true">https://blog.dccif.top/2017/11/27/%E5%8D%9A%E5%AE%A2%E7%9A%84%E4%B8%80%E9%94%AE%E9%83%A8%E7%BD%B2/</guid><description>终于在一番折腾和学习下，我用“三脚猫”的水平写了一个能一键写博客的脚本 😂，这样以后写博客我只需要想写什么东西了，不用再在部署上折腾了。。。</description><pubDate>Mon, 27 Nov 2017 10:31:26 GMT</pubDate><content:encoded>&lt;h1&gt;博客的一键部署&lt;/h1&gt;
&lt;p&gt;终于在一番折腾和学习下，我用“三脚猫”的水平写了一个能一键写博客的脚本 😂，这样以后写博客我只需要想写什么东西了，不用再在部署上折腾了。。。&lt;/p&gt;
&lt;h2&gt;为什么要折腾&lt;/h2&gt;
&lt;p&gt;说来这么折腾的写博客，也是我自找没趣。。。承接&lt;a href=&quot;https://blog.dccif.top/2017/10/23/%E5%8D%9A%E5%AE%A2%E5%A4%87%E4%BB%BD-Git%E5%B0%8F%E6%8A%80%E5%B7%A7/&quot;&gt;《博客的备份》&lt;/a&gt;，我这的写作环境我备份了好多份，每次要在这么多环境之间选择那些可见，那些不可见太麻烦了。。。写脚本的目的也是为了这个，当然脚本我是存在私有仓库的 😋&lt;s&gt;(写得太烂不好意放出来丢人现眼)&lt;/s&gt;&lt;/p&gt;
</content:encoded></item><item><title>数组扩展的效率</title><link>https://blog.dccif.top/2017/11/04/%E6%95%B0%E7%BB%84%E6%89%A9%E5%B1%95%E7%9A%84%E6%95%88%E7%8E%87/</link><guid isPermaLink="true">https://blog.dccif.top/2017/11/04/%E6%95%B0%E7%BB%84%E6%89%A9%E5%B1%95%E7%9A%84%E6%95%88%E7%8E%87/</guid><description>说来惭愧，我现在才开始认真的学习算法和程序的效率 😓。</description><pubDate>Sat, 04 Nov 2017 10:53:00 GMT</pubDate><content:encoded>&lt;h1&gt;数组扩展的效率差异&lt;/h1&gt;
&lt;p&gt;说来惭愧，我现在才开始认真的学习算法和程序的效率 😓。&lt;/p&gt;
&lt;p&gt;本文是我在阅读&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Data Structures,Algorithms,and Applications in C++&lt;/strong&gt; Second Edition
&lt;em&gt;Sartaj Sahni&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;遇到的一个小细节，与数组扩展的效率差异的原理。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h1&gt;原始代码&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;template&amp;lt;class T&amp;gt;
void arrayList&amp;lt;T&amp;gt;::insert(int theIndex, const T&amp;amp; theElement)
{// Insert theElement so that its index is theIndex.
   if (theIndex &amp;lt; 0 || theIndex &amp;gt; listSize)
   {// invalid index
      ostringstream s;
      s &amp;lt;&amp;lt; &quot;index = &quot; &amp;lt;&amp;lt; theIndex &amp;lt;&amp;lt; &quot; size = &quot; &amp;lt;&amp;lt; listSize;
      throw illegalIndex(s.str());
   }

   // valid index, make sure we have space
   if (listSize == arrayLength)
      {// no space, double capacity
         changeLength1D(element, arrayLength, 2 * arrayLength);
         arrayLength *= 2;
      }

   // shift elements right one position
   copy_backward(element + theIndex, element + listSize,
                 element + listSize + 1);

   element[theIndex] = theElement;

   listSize++;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不知道各位有没有觉得奇怪，为什么&lt;strong&gt;12-16&lt;/strong&gt;行是当空间不足的时候，数组空间翻倍呢？&lt;/p&gt;
&lt;p&gt;同样的问题书上也提供了解答。。。。不过也许是我数学基础太差了，一时半会没理解 😥&lt;/p&gt;
&lt;p&gt;本文也参考了&lt;em&gt;Stack Overflow&lt;/em&gt;上的&lt;a href=&quot;https://stackoverflow.com/questions/19146037/efficiency-of-growing-a-dynamic-array-by-a-fixed-constant-each-time&quot;&gt;Efficiency of growing a dynamic array by a fixed constant each time?&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;背后原理&lt;/h2&gt;
&lt;p&gt;这就要用的数学知识了&lt;/p&gt;
&lt;p&gt;让我们假设现在有一个初始长度为 1 的空数组，需要执行 $n=2^k+1$&lt;/p&gt;
&lt;p&gt;n 次的插入操作，每次都在尾部插入。&lt;/p&gt;
&lt;p&gt;于是，每次插入我们都不需要移动已经存在的元素，n 次插入的时间是 Θ(n)加上数组扩展长度的时间。&lt;/p&gt;
&lt;h3&gt;数组每次增加 1 的情况&lt;/h3&gt;
&lt;p&gt;如果数组每次增加 1，那么增加数组长度的时间为
$$\Theta (\sum _{i=1}^{n-1} i)=\Theta(1+2+3+4+...+(n-1))=\Theta(\frac{n(n-1)}{2} )=\Theta(n^2)$$&lt;/p&gt;
&lt;p&gt;利用等差数列的公式，得到，如果数组每次长度增加 1，n 次插入的总时间是 Θ(n^2)。&lt;/p&gt;
&lt;h3&gt;数组每次翻倍的情况&lt;/h3&gt;
&lt;p&gt;下面来解释为什么原始代码中的数组扩展使用的翻倍&lt;/p&gt;
&lt;p&gt;如果数组长度每次增倍，那么改变数组长度的时间是&lt;/p&gt;
&lt;p&gt;$$\Theta(\sum _{i=0}^k 2^i)=\Theta(2^0+2^1+2^2+...+2^k)=\Theta(2^{k+1}-1)$$&lt;/p&gt;
&lt;p&gt;$$k={\log _2(n-1)}$$&lt;/p&gt;
&lt;p&gt;$$\Theta(2^{k+1}-1)=\Theta(2^{\log _2(n-1)+1}-1)=\Theta(2n-3)=\Theta(n)$$&lt;/p&gt;
&lt;p&gt;利用等比数列公式，得到，如果每次数组长度翻倍，n 次插入的总时间是 Θ(n)。&lt;/p&gt;
&lt;h3&gt;推论&lt;/h3&gt;
&lt;p&gt;从数组每次翻倍的情况的公式，我们可以看出如果我们总是在原数组上按一个乘法因子来倍增，得到的总时间都是是 Θ(n)&lt;/p&gt;
&lt;p&gt;这也是为什么&lt;a href=&quot;#%E5%8E%9F%E5%A7%8B%E4%BB%A3%E7%A0%81&quot;&gt;原始代码&lt;/a&gt;中使用的是把长度翻倍的原因。&lt;/p&gt;
</content:encoded></item><item><title>Ubuntu的个性化配置</title><link>https://blog.dccif.top/2017/10/27/Ubuntu%E7%9A%84%E4%B8%AA%E6%80%A7%E5%8C%96%E9%85%8D%E7%BD%AE/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/27/Ubuntu%E7%9A%84%E4%B8%AA%E6%80%A7%E5%8C%96%E9%85%8D%E7%BD%AE/</guid><description>因为使用 Linux 开发方便的缘故，我在虚拟机上用全性能搭建了一个 Ubuntu 环境~~(别问我为什么不装双系统)~~</description><pubDate>Fri, 27 Oct 2017 11:40:10 GMT</pubDate><content:encoded>&lt;h1&gt;Ubuntu 下的个性化配置&lt;/h1&gt;
&lt;p&gt;因为使用 Linux 开发方便的缘故，我在虚拟机上用全性能搭建了一个 Ubuntu 环境~~(别问我为什么不装双系统)~~&lt;/p&gt;
&lt;p&gt;于是和之前那篇 Windows 的重装一样，也想写一篇文章记录一下，以后搭建时可以方便一些&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;Java 环境&lt;/h2&gt;
&lt;p&gt;本文参考&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-install-java-with-apt-get-on-ubuntu-16-04&quot;&gt;How To Install Java with Apt-Get on Ubuntu 16.04&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里是 Java8&lt;/p&gt;
&lt;p&gt;添加 Oracle&apos;s PPA&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, depending on the version you want to install, execute one of the following commands:&lt;/p&gt;
&lt;h3&gt;Oracle JDK 8&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install oracle-java8-installer
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Linux 下的添加 Java 环境变量&lt;/h3&gt;
&lt;p&gt;Many programs, such as Java servers, use the &lt;code&gt;JAVA_HOME&lt;/code&gt; environment variable to determine the Java installation location. To set this environment variable, we will first need to find out where Java is installed. You can do this by executing the same command as in the previous section:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo update-alternatives --config java
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Copy the path from your preferred installation and then open &lt;code&gt;/etc/environment&lt;/code&gt; using &lt;code&gt;nano&lt;/code&gt; or your favorite text editor.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo nano /etc/environment
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At the end of this file, add the following line, making sure to replace the highlighted path with your own copied path.&lt;/p&gt;
&lt;p&gt;/etc/environment&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;JAVA_HOME=&quot;/usr/lib/jvm/java-8-oracle&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Save and exit the file, and reload it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;source /etc/environment
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can now test whether the environment variable has been set by executing the following command:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;echo $JAVA_HOME
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;开发环境&lt;/h2&gt;
&lt;p&gt;Vim-gtk 官方源已经有最新的了，直接 apt install 就行了&lt;/p&gt;
&lt;p&gt;Emacs (需要手动添加源)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo add-apt-repository ppa:kelleyk/emacs
sudo apt update
sudo apt install emacs25
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其余 jetbrains 全家桶，因为没有 VS 只好用 Clion 了&lt;/p&gt;
&lt;h2&gt;oh-my-zsh 配置 zsh&lt;/h2&gt;
&lt;p&gt;ubuntu 默认不是 zsh，输入下面命令安装 zsh&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install zsh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;接下来我们需要下载 oh-my-zsh 项目来帮我们配置 zsh，注意此时一定要用 超级权限。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;wget https://github.com/robbyrussell/oh-my-zsh/raw/master/tools/install.sh -O - | sh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;查看你的 zsh 位置，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cat /etc/shells
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code&gt;➜  ~ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/dash
/bin/bash
/bin/rbash
/bin/zsh
/usr/bin/zsh
➜  ~
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更改默认 shell，输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo vim /etc/passwd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更改 root 和用户默认 shell&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;root:x:0:0:root:/root:/usr/bin/zsh
song:x:1000:1000:song,,,:/home/song:/usr/bin/zsh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;zsh 的配置文件是在用户目录下的 .zshrc&lt;/p&gt;
&lt;p&gt;每一行的配置前面都有#号,如果想要配置生效,去掉 #号即可.&lt;/p&gt;
&lt;h2&gt;补全插件 incr.zsh&lt;/h2&gt;
&lt;p&gt;这个插件的官网是: &lt;a href=&quot;http://link.zhihu.com/?target=http%3A//mimosa-pudica.net/zsh-incremental.html&quot;&gt;Incremental completion on zsh&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;最新版本是 incr-0.2.zsh&lt;/p&gt;
&lt;p&gt;新建一个 incr-0.2.zsh 文件把他放进 用户目录下的 .oh-my-zsh/plugins/incr 目录下，没有的目录自己新建，其实放哪都一样。&lt;/p&gt;
&lt;p&gt;分别编辑 root 目录下的 .zshrc 和用户目录下的 .zsnrc&lt;/p&gt;
&lt;p&gt;加上一句&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;source /home/song/.oh-my-zsh/plugins/incr/incr-0.2.zsh
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;/home/song/.oh-my-zsh/plugins/incr 是你放的不同的目录。&lt;/p&gt;
&lt;p&gt;最后还有一个小问题，原来我们用的 超级用户创建的 oh-my-zsh 导致 .oh-my-zsh 目录下的缓存目录 cache 所有者和用户组也是 root 这样就导致我们在普通用户下使用有些问题，下面改变 cache 的所有者&lt;/p&gt;
&lt;p&gt;输入&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;chown song:song cache/ -R
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样就不会在命令提示时候弹出错误了。&lt;/p&gt;
</content:encoded></item><item><title>博客备份-Git小技巧</title><link>https://blog.dccif.top/2017/10/23/%E5%8D%9A%E5%AE%A2%E5%A4%87%E4%BB%BD-Git%E5%B0%8F%E6%8A%80%E5%B7%A7/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/23/%E5%8D%9A%E5%AE%A2%E5%A4%87%E4%BB%BD-Git%E5%B0%8F%E6%8A%80%E5%B7%A7/</guid><description>可能是因为被害妄想症的原因吧，我怕博客的丢失，在我的硬盘，电脑和 GitHub 和私有服务器上备份了四份，在本博客的仓库的 Public 分支上就是我的博客文章的备份</description><pubDate>Mon, 23 Oct 2017 15:53:27 GMT</pubDate><content:encoded>&lt;h1&gt;Hexo 博客的备份&lt;/h1&gt;
&lt;p&gt;可能是因为被害妄想症的原因吧，我怕博客的丢失，在我的硬盘，电脑和 GitHub 和私有服务器上备份了四份，在本博客的仓库的 Public 分支上就是我的博客文章的备份&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;为什么要备份&lt;/h2&gt;
&lt;p&gt;备份的重要性我觉的不用我说了吧，为了防止数据的丢失 &lt;s&gt;虽然好像没什么宝贵的数据&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;其实是突然发奇想想利用 Git 的分支来在一个仓库管理我的博客&lt;/p&gt;
&lt;h2&gt;为什么只备份文章&lt;/h2&gt;
&lt;p&gt;毕竟文章本来就是给各位看的，但是私人的配置文件中有个人 APIKey 和一些个性化设定，这些可不好 Public 了 😃&lt;/p&gt;
&lt;h2&gt;Git 小技巧&lt;/h2&gt;
&lt;p&gt;因为这次忽略文件是我临时添加的，再修改了 &lt;strong&gt;.gitignore&lt;/strong&gt; 文件后在次上传并没有生效&lt;/p&gt;
&lt;p&gt;感谢 pfeng 的作者，本文参考 http://www.pfeng.org/archives/840&lt;/p&gt;
&lt;p&gt;在&lt;strong&gt;git&lt;/strong&gt;中如果想忽略掉某个文件，不让这个文件提交到版本库中，可以使用修改根目录中 &lt;strong&gt;.gitignore&lt;/strong&gt; 文件的方法（如无，则需自己手工建立此文件）。这个文件每一行保存了一个匹配的规则例如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# 此为注释 – 将被 Git 忽略
*.a         # 忽略所有 .a 结尾的文件
!lib.a      # 但 lib.a 除外
/TODO`      # 仅仅忽略项目根目录下的 TODO 文件，不包括 subdir/TODO
build/      # 忽略 build/ 目录下的所有文件
doc/*.txt   # 会忽略 doc/notes.txt 但不包括 doc/server/arch.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;规则很简单，不做过多解释，但是有时候在项目开发过程中，突然心血来潮想把某些目录或文件加入忽略规则，按照上述方法定义后发现并未生效，原因是 &lt;strong&gt;.gitignore&lt;/strong&gt; 只能忽略那些原来没有被 track 的文件，如果某些文件已经被纳入了版本管理中，则修改 &lt;strong&gt;.gitignore&lt;/strong&gt; 是无效的。那么解决方法就是先把本地缓存删除（改变成未 track 状态），然后再提交：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;git rm -r --cached .
git add .
git commit -m &apos;update .gitignore&apos;
&lt;/code&gt;&lt;/pre&gt;
</content:encoded></item><item><title>重装系统程序清单</title><link>https://blog.dccif.top/2017/10/16/%E9%87%8D%E8%A3%85%E7%B3%BB%E7%BB%9F%E7%A8%8B%E5%BA%8F%E6%B8%85%E5%8D%95/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/16/%E9%87%8D%E8%A3%85%E7%B3%BB%E7%BB%9F%E7%A8%8B%E5%BA%8F%E6%B8%85%E5%8D%95/</guid><description>我不得不重装我这用了快3年的电脑，心里一阵苦，本清单用于个人重装系统后的恢复工作，日后也能参考</description><pubDate>Mon, 16 Oct 2017 02:55:50 GMT</pubDate><content:encoded>&lt;h1&gt;因为种种原因&lt;/h1&gt;
&lt;p&gt;我不得不重装我这用了快3年的电脑，心里一阵苦，本清单用于个人重装系统后的恢复工作，日后也能参考&lt;/p&gt;
&lt;h1&gt;驱动安装&lt;/h1&gt;
&lt;p&gt;&lt;s&gt;这步我就不说了&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;这个周末被这个折腾的够呛，我觉得还是有必要说一下了😭&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;p&gt;首先说下我遇到的坑吧，现在事后说起来觉得好蠢，可以当我遇到的时候真是百思不得其解。&lt;/p&gt;
&lt;p&gt;这次我遇到的坑一句话就是驱动的冲突，我原本的罗技鼠标和这个国产软件----驱动精灵，检测出来的不一样，于是就给我装了一个雷蛇的驱动。。。关键是我装好了之后还没法卸载。导致的现象就是每次开机我都要手动用管理员权限打开罗技的&lt;code&gt;游戏软件&lt;/code&gt;，也许是我强迫症吧，为了发现和解决这个问题，我重装了5次系统。。。&lt;/p&gt;
&lt;p&gt;好好的一个周末都被浪费掉了。。。&lt;/p&gt;
&lt;p&gt;收获就是国产的驱动软件不能完全相信。。，每一步安装前要先确认一下这个驱动是什么&lt;/p&gt;
&lt;p&gt;还有2个被土啬的驱动检测软件，这两个的驱动都是没有问题的，名字我就先不提了。&lt;/p&gt;
&lt;h2&gt;程序清单&lt;/h2&gt;
&lt;p&gt;没有链接的文件在个人备份的磁盘中&lt;/p&gt;
&lt;h3&gt;语言环境&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html&quot;&gt;Java8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tomcat.apache.org/download-90.cgi&quot;&gt;Tomcat9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.python.org/downloads/&quot;&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nodejs.org/en/&quot;&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;别忘了配置环境变量&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;开发工具&lt;/h3&gt;
&lt;h4&gt;微软&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.visualstudio.com/zh-hans/&quot;&gt;Visual Studio&lt;/a&gt; (&lt;s&gt;之所以重装都是因为这个巨无霸&lt;/s&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.visualstudio.com/zh-hans/&quot;&gt;VIsual Studio Code&lt;/a&gt; (还好没有什么配置文件)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;GNU&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://mirrors.ustc.edu.cn/gnu/emacs/windows/&quot;&gt;Emacs&lt;/a&gt;，GVIM (硬盘中拷备份件)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://git-scm.com/download/win&quot;&gt;Git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://desktop.github.com/&quot;&gt;GitHub Desktop&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;JetBrains&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/idea/&quot;&gt;Intellij IDEA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.android.com/studio/index.html&quot;&gt;Android Studio&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/webstorm/?fromMenu&quot;&gt;WebStorm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.jetbrains.com/pycharm/?fromMenu&quot;&gt;PyCharm&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;其他&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://www.eclipse.org/home/index.php&quot;&gt;Eclipse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://racket-lang.org/download/&quot;&gt;DrRacket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;VMware Workstation Pro&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.wampserver.com/en/&quot;&gt;wampserver&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.wireshark.org/download.html&quot;&gt;Wireshark&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://notepad-plus-plus.org/download/v7.5.1.html&quot;&gt;Notepad++&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;多媒体&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://potplayer.daum.net/&quot;&gt;Potplayer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;PDFX&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.sina.com.cn/s/blog_6fcc51420102wv92.html&quot;&gt;foobar2000&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://calibre-ebook.com/download&quot;&gt;Calibre&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Sigil&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mp3tag.de/en/download.html&quot;&gt;Mp3tag&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;娱乐&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://store.steampowered.com/about/&quot;&gt;Steam&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;学习&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;GoldenDict&lt;/li&gt;
&lt;li&gt;wolfram mathematica&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.manictime.com/&quot;&gt;ManicTime&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;效率工具&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.voidtools.com/downloads/&quot;&gt;Everything&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;IDM&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://justgetflux.com/&quot;&gt;f.lux&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ditto-cp.sourceforge.net/&quot;&gt;Ditto&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.chuyu.me/zh-Hans/&quot;&gt;Dism++&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.teamviewer.com/zhcn/download/windows/&quot;&gt;TeamViewer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.kcsoftwares.com/?download&quot;&gt;Sumo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/Wox-launcher/Wox/releases&quot;&gt;Wox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TriDnet&lt;/li&gt;
&lt;li&gt;XYplorer&lt;/li&gt;
&lt;li&gt;Total Commander&lt;/li&gt;
&lt;li&gt;MySpeed&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.listary.com/download&quot;&gt;Listary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.inputdirector.com/downloads.html&quot;&gt;Input Director&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Capture2Tex&lt;/li&gt;
&lt;li&gt;Process&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;SSH工具&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;XX-net&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.echoteen.com/proxifier-newway.html&quot;&gt;Proxifier&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Xshell5 &amp;amp; Xftp&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://filezilla-project.org/&quot;&gt;FileZilla&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;浏览器及插件&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.google.com/chrome/browser/desktop/index.html&quot;&gt;Chrome32bit&lt;/a&gt;
备份文件&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mozilla.org/zh-CN/firefox/desktop/&quot;&gt;Firefox&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;其余&lt;/h2&gt;
&lt;p&gt;在个人备份硬盘中&lt;/p&gt;
</content:encoded></item><item><title>IDEA下的Java Webapp环境搭建</title><link>https://blog.dccif.top/2017/10/14/IDEA%E4%B8%8B%E7%9A%84Java-Webapp%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/14/IDEA%E4%B8%8B%E7%9A%84Java-Webapp%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</guid><description>本文在以下环境搭建：</description><pubDate>Sat, 14 Oct 2017 07:14:55 GMT</pubDate><content:encoded>&lt;h1&gt;IDEA 下 Java Webapp 的环境搭建&lt;/h1&gt;
&lt;p&gt;本文在以下环境搭建：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;IntelliJ IDEA 2017.2.5
JDK 1.8.0_144
JRE: 1.8.0_152-release-915-b12 amd64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Apache Tomcat 9.0.1 Server
Windows 10 x64 15063.674&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;注意!!&lt;/strong&gt; 本文不包括 JAVA 环境及 Tomcat 的搭建！&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;写文缘由&lt;/h2&gt;
&lt;p&gt;可能有人问我既然不是写给新人看的，还不写重点的 JAVA 环境及 Tomcat 的搭建，你写这有什么用？那么你可以&lt;strong&gt;Ctrl+w&lt;/strong&gt;了。因为现在网上的都是关于 Eclipse 或者老版本的 IDEA 的教程，所以想写一篇新的，顺带拉一波新人入 IDEA 的坑。&lt;/p&gt;
&lt;p&gt;&lt;s&gt;个人不喜欢课堂上老师用的旧工具&lt;/s&gt;&lt;/p&gt;
&lt;h3&gt;新建 Project&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/newproject.jpg&quot; alt=&quot;新建项目&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/select.jpg&quot; alt=&quot;选择应用module&quot; /&gt;&lt;/p&gt;
&lt;p&gt;下一步随便给项目取一个名字&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;下面是重点了&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;可能是我的环境太新了，和网上的教程生成的目录结构是不一样的。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/struct.jpg&quot; alt=&quot;目录结构&quot; /&gt;&lt;/p&gt;
&lt;p&gt;我们要新建 2 个文件夹，都是在 web/WEB-INF/目录下&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;classes      --编译后的文件&lt;/li&gt;
&lt;li&gt;lib             --以后要引入的库&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;新的目录结构 &lt;img src=&quot;/image/IDEA/after.jpg&quot; alt=&quot;新建Servlet和新的目录结构&quot; /&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/newservlet.jpg&quot; alt=&quot;新建Servlet&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;更改项目目录结构 &lt;img src=&quot;/image/IDEA/newstruct.jpg&quot; alt=&quot;更改目录结构&quot; /&gt;&lt;/h3&gt;
&lt;h4&gt;更改 out 目录 &lt;img src=&quot;/image/IDEA/newout.jpg&quot; alt=&quot;更改out目录&quot; /&gt;&lt;/h4&gt;
&lt;h4&gt;更改 lib 目录 &lt;img src=&quot;/image/IDEA/newlib.jpg&quot; alt=&quot;更改lib目录&quot; /&gt;&lt;/h4&gt;
&lt;h4&gt;更改 out 结构 &lt;img src=&quot;/image/IDEA/outset.jpg&quot; alt=&quot;更改out结构&quot; /&gt;&lt;/h4&gt;
&lt;h3&gt;配置服务器 &lt;img src=&quot;/image/IDEA/configserver.jpg&quot; alt=&quot;配置服务器&quot; /&gt;&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/setserver1.jpg&quot; alt=&quot;IDEA下的Java Webapp环境搭建&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/setserver2.jpg&quot; alt=&quot;配置服务器&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;测试代码&lt;/h2&gt;
&lt;p&gt;Jsp 测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;%@ page contentType=&quot;text/html;charset=UTF-8&quot; language=&quot;java&quot; %&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;简单的JSP页面&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;h1&amp;gt;Hello,World!&amp;lt;/h1&amp;gt;
现在的时间是: &amp;lt;%= new java.util.Date() %&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/result1.jpg&quot; alt=&quot;Jsp页面测试&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Servlet 测试：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = &quot;HelloServlet&quot;, urlPatterns = {&quot;/helloServlet.do&quot;})
public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType(&quot;text/html;charset=UTF-8&quot;);
        PrintWriter out = response.getWriter();
        out.println(&quot;&amp;lt;html&amp;gt;&quot;);
        out.println(&quot;&amp;lt;head&amp;gt;&amp;lt;title&amp;gt;当前时间&amp;lt;/title&amp;gt;&amp;lt;/head&amp;gt;&amp;lt;body&amp;gt;&quot;);
        out.println(&quot;&amp;lt;h3&amp;gt;Hello,World!&amp;lt;/h3&amp;gt;&quot;);
        out.println(&quot;现在时间是：&quot; + new java.util.Date());
        out.println(&quot;&amp;lt;/body&amp;gt;&quot;);
        out.println(&quot;&amp;lt;/html&amp;gt;&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;结果：
&lt;img src=&quot;/image/IDEA/result2.jpg&quot; alt=&quot;Servlet测试&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;搭建完成&lt;/h2&gt;
&lt;p&gt;至此完成了在 IDEA 上 Servlet 的环境搭建。&lt;/p&gt;
&lt;p&gt;&lt;s&gt;你以为接这样结束了？&lt;/s&gt;&lt;/p&gt;
&lt;p&gt;你难道想每次都按怎么多才能搭建好环境？
&lt;s&gt;其实可以选择 Maven 的，但是 Maven 更难掌握&lt;/s&gt;
有个简单的方法能节省几步以后搭建的操作&lt;/p&gt;
&lt;h3&gt;保存模版&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/savetemp.jpg&quot; alt=&quot;保存模版&quot; /&gt;&lt;/p&gt;
&lt;p&gt;之后就能看到了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/IDEA/usertemp.jpg&quot; alt=&quot;用户模版&quot; /&gt;&lt;/p&gt;
&lt;p&gt;然而这个功能支持 Java 项目并不完美，所以以后每次都要新建两个文件夹，就是 classes 和 lib，但之后的目录结构设置会自动完成的&lt;/p&gt;
</content:encoded></item><item><title>Prologue</title><link>https://blog.dccif.top/2017/10/10/Prologue/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/10/Prologue/</guid><description>可以说是“机缘巧合”吧，我从原来的自建服务器迁移到了GitHub Pages上，具体的原因我绝的可以留到下一篇博文再说了😜</description><pubDate>Tue, 10 Oct 2017 15:28:00 GMT</pubDate><content:encoded>&lt;h1&gt;一些闲话来作为我博客的序章吧&lt;/h1&gt;
&lt;p&gt;可以说是“&lt;strong&gt;机缘巧合&lt;/strong&gt;”吧，我从原来的自建服务器迁移到了&lt;a href=&quot;https://pages.github.com/&quot;&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt;&lt;/a&gt;上，具体的原因我绝的可以留到下一篇博文再说了😜&lt;/p&gt;
&lt;h2&gt;写作的缘由&lt;/h2&gt;
&lt;p&gt;在一番折腾之后终于搭成了这个博客，想着也不能浪费，于是就来写写东西了，主要也是个人生活或者学习的记录。不过鉴于我个人的水平，如果有读者有幸看到这篇文章的话，那么也请别抱太大的希望，因为我本质上还是一个&lt;code&gt;理工男&lt;/code&gt;。在本博客中你可能看不到什么精彩的文风或者犀利的批判。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;本博客以后和现在的内容&lt;/h2&gt;
&lt;p&gt;想了半天也不知道和清楚写什么，于是就想先介绍一下博客好了。&lt;/p&gt;
&lt;p&gt;以后包括未来博主主要写的文章大多是&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;编程类&lt;/li&gt;
&lt;li&gt;细节类&lt;/li&gt;
&lt;li&gt;感想类&lt;/li&gt;
&lt;li&gt;推荐类&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下面就来细说一下好了。&lt;s&gt;我又想到扯得东西了&lt;/s&gt;&lt;/p&gt;
&lt;h3&gt;编程类&lt;/h3&gt;
&lt;p&gt;因为本人专业和兴趣的原因，我还是写的编程的多点，因为这个博客我也想当成我学习编程的成长记录吧。&lt;/p&gt;
&lt;h3&gt;细节类&lt;/h3&gt;
&lt;p&gt;怎么定义呢？说实话我也很难说什么属于细节，只是因为以前写的文章算是细节，便单独开了一个目录了，因为我现在的编程学习，个人还是理论派，看的书比写的码多，于是便把一些书上好的地方记录下来，日后也许可以写一些物品在实践中处理问题遇到的细节。&lt;/p&gt;
&lt;h3&gt;感想类&lt;/h3&gt;
&lt;p&gt;虽然我现在一篇此类的文章都没写，但是我觉得一个博客之所以能叫博客就是因为能抒发作者自己的想法，所以我的博客也不例外，如果没有这个类的话，我的博客就不能说是我的博客了，只能说是一些零散知识的拼凑。&lt;/p&gt;
&lt;h3&gt;推荐类&lt;/h3&gt;
&lt;p&gt;个人觉得这也许是我以后写的最多的文章了，因为个人对新奇软件和数码的喜好，我个人会推荐和介绍一些本人正在使用的好的软件或硬件，甚至是上文编程类中的好东西，当然这也是否考验功力，你凭什么推荐这个？&lt;/p&gt;
</content:encoded></item><item><title>递归的两种优化方法</title><link>https://blog.dccif.top/2017/10/10/%E9%80%92%E5%BD%92%E7%9A%84%E4%B8%A4%E7%A7%8D%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/10/%E9%80%92%E5%BD%92%E7%9A%84%E4%B8%A4%E7%A7%8D%E4%BC%98%E5%8C%96%E6%96%B9%E6%B3%95/</guid><description>最近学习了一些递归的优化方法，于是想写一篇文章记录一下，方便以后查看，并想分享一下。 虽然平日的上课中老师都是建议我们不要使用递归，但是在函数式编程（functional programming）中递归是很常用的，而且掌握递归的思想有时能让我们找到最优解。</description><pubDate>Tue, 10 Oct 2017 14:24:04 GMT</pubDate><content:encoded>&lt;h1&gt;递归（Recursion）的两种优化方法&lt;/h1&gt;
&lt;p&gt;最近学习了一些递归的优化方法，于是想写一篇文章记录一下，方便以后查看，并想分享一下。
虽然平日的上课中老师都是建议我们不要使用递归，但是在**函数式编程（functional programming）**中递归是很常用的，而且掌握递归的思想有时能让我们找到最优解。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;1. 最经典的斐波那契数列&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;int Fibonacci(int n) {
    if (n == 1 || n == 2) {
        return 1;
    }
    else
    {
        return Fibonacci(n - 2) + Fibonacci(n - 1);
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个算法一般计算到 40 左右就不行了，因为运行栈已经被函数的递归调用占满了&lt;/p&gt;
&lt;h2&gt;2. 尾递归（Tail Recursive）&lt;/h2&gt;
&lt;p&gt;传说中的&lt;a href=&quot;https://www.wikiwand.com/zh/%E5%B0%BE%E8%B0%83%E7%94%A8&quot;&gt;&lt;strong&gt;尾递归&lt;/strong&gt;&lt;/a&gt;。具体我不细说了，就是上一个版本的优化，每次调用函数时不生成新的运行栈，利用上一次的结果
&lt;strong&gt;注意：&lt;strong&gt;不是所有语言都有&lt;/strong&gt;尾递归&lt;/strong&gt;优化的（Java 就没有）
也不是所有算法都能写成&lt;strong&gt;尾递归&lt;/strong&gt;的形式的&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;int fiboTail(int n, int acc, int cal)
//acc充当收集器的左右，收集上一次运行栈的返回值，因为之后栈空间会被回收
//cal是每一次递归的计算
{
    if (n == 1) return acc;
    if (n == 2) return cal;
    return fiboTail(n - 1, cal, acc+cal);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到尾递归的函数比原始的版本多了 2 个参数，一个起到**收集器（accumulator)**的作用，记录每上一次栈的返回值，因为原来栈的空间会被下一层递归覆盖。
还有一个参数就是每次递归的操作了，因为是斐波那契，所以这里是相加。&lt;/p&gt;
&lt;p&gt;尾递归的调用方法也与原来的不一样，因为斐波那契的初始值 ( 1. 1 . 2 . 3 ......)
所以以下的调用，acc 要用初始值 1，cal 也要用第二位的值这里也是 1
调用的方法就是 &lt;strong&gt;fiboTail(n, 1，1）&lt;/strong&gt;
尾递归的方法计算基本上是秒出的，可是比起下面一种方法还是要慢，就是在 32 位机器上要注意 &lt;strong&gt;int 范围&lt;/strong&gt; 第 47 位已经超过 int 的表示范围了&lt;/p&gt;
&lt;h2&gt;3. 利用缓存&lt;/h2&gt;
&lt;p&gt;典型的空间换时间&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;enum { gnFib = 99 };
int gFib[gnFib];      // 生成一个数组记录已经生成的斐波那契数

int fib(int n)
{
    if (n &amp;lt; 0 || n &amp;gt;= gnFib) return 0;
    int &amp;amp;fn = gFib[n];
    if (!fn) {            //如果当前数不在数组中才计算
        if (n == 0 || n == 1) fn = 1;
            else fn = fib(n - 1) + fib(n - 2);
    }
    return fn;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;核心思想就是利用之前信息，每次递归不用再重新计算了&lt;/p&gt;
</content:encoded></item><item><title>短路求值(Short-circuit evaluation)</title><link>https://blog.dccif.top/2017/10/10/%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC-Short-circuit-evaluation/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/10/%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC-Short-circuit-evaluation/</guid><description>&gt; Short-circuit evaluation</description><pubDate>Tue, 10 Oct 2017 08:05:27 GMT</pubDate><content:encoded>&lt;h1&gt;短路求值&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Short-circuit evaluation&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;最早是在&lt;strong&gt;php&lt;/strong&gt;中接触到的这种求值，后来在学习&lt;strong&gt;Lisp&lt;/strong&gt;中又一次接触到了，于是想写一篇文章记录一下，并分享一下，这个被我忽略的可能可以说是细节的点吧&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h2&gt;什么是短路求值（Short-circuit evaluation）&lt;/h2&gt;
&lt;p&gt;以下摘自&lt;a href=&quot;https://www.wikiwand.com/en/Short-circuit_evaluation&quot;&gt;Short-circuit evaluation&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Short-circuit evaluation&lt;/strong&gt;, minimal evaluation, or McCarthy evaluation (after John McCarthy) is the semantics of some Boolean operators in some programming languages in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND function evaluates to false, the overall value must be false; and when the first argument of the OR function
evaluates to true, the overall value must be true.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;概况来说就是在求&lt;strong&gt;布尔表达式&lt;/strong&gt;的时候程序并不会执行全部的&lt;strong&gt;Expression&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;比如&lt;strong&gt;AND&lt;/strong&gt;或者&lt;strong&gt;OR&lt;/strong&gt;操作时如果后面第一个 Expression 为 True，那么之后的 Expression 就不会再求值了。&lt;/p&gt;
&lt;h2&gt;一些例子&lt;/h2&gt;
&lt;h3&gt;普通的&lt;strong&gt;C&lt;/strong&gt;程序&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;int denom = 0;
if (denom != 0 &amp;amp;&amp;amp; num / denom)
{
    ... // ensures that calculating num/denom never results in divide-by-zero error
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;使用了短路求值的&lt;strong&gt;C&lt;/strong&gt;程序&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;int a = 0;
if (a != 0 &amp;amp;&amp;amp; myfunc(b))
{
    do_something();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在这个例子中 &lt;strong&gt;&amp;amp;&amp;amp;&lt;/strong&gt; 后的 &lt;strong&gt;myfunc(b)&lt;/strong&gt; 将永远不会执行，因为 &lt;strong&gt;a!=0&lt;/strong&gt; 永远是 &lt;strong&gt;FALSE&lt;/strong&gt; 。
利用短路求值有 2 个有用的技巧&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;如果条件判断的 expression 需要复杂的计算，并且第一个结果为 &lt;strong&gt;False&lt;/strong&gt; ，则可以不计算之后的表达式&lt;/li&gt;
&lt;li&gt;可以构造一个 expression 来使第二个可能会发生运行时错误的 expression 成功运行&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;bool is_first_char_valid_alpha_unsafe(const char *p)
{
    return isalpha(p[0]); // SEGFAULT highly possible with p == NULL
}

bool is_first_char_valid_alpha(const char *p)
{
    return p != NULL &amp;amp;&amp;amp; isalpha(p[0]); // 1) no unneeded isalpha() execution with p == NULL, 2) no SEGFAULT risk
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这个例子避免了空指针&lt;/p&gt;
&lt;h3&gt;最近学习的 Lisp 中的例子：&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;(defparameter *is-it-even* nil)
(or (oddp 5)
(setf *is-it-even* t))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;利用短路求值，用&lt;strong&gt;OR&lt;/strong&gt;实现了条件判断&lt;/p&gt;
&lt;h2&gt;可能的问题：&lt;/h2&gt;
&lt;p&gt;尽管有上面说的优点，但是可能会带来没有意识到的问题，比如：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (expressionA &amp;amp;&amp;amp; myfunc(b)) {
    do_something();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当&lt;strong&gt;expressionA&lt;/strong&gt;为&lt;strong&gt;True&lt;/strong&gt;时无论**do_something()**是否执行，**myfunc(b)**都会执行，例如分配系统资源的操作。&lt;/p&gt;
&lt;p&gt;相反，&lt;strong&gt;expressionA&lt;/strong&gt;为&lt;strong&gt;False&lt;/strong&gt;时**myfunc(b)**永远不会执行&lt;/p&gt;
&lt;h2&gt;支持的语言&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;并不是所有语言和所有操作符支持的&lt;/strong&gt;
Java 支持&lt;strong&gt;非短路求值&lt;/strong&gt;也支持&lt;strong&gt;短路求值&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;常见的语言&lt;/th&gt;
&lt;th&gt;支持的操作符&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C, Obejective-C, C++, C#&lt;/td&gt;
&lt;td&gt;&amp;amp;&amp;amp;, ∥, ?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java, MATLAB, R, Swift&lt;/td&gt;
&lt;td&gt;&amp;amp;&amp;amp;, ∥&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JavaScript, GO, Haskel&lt;/td&gt;
&lt;td&gt;&amp;amp;&amp;amp;, ∥&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lisp, Lua, Scheme&lt;/td&gt;
&lt;td&gt;and, or&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;&amp;amp;&amp;amp;, and, ∥, or&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;and, or&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visual Basic&lt;/td&gt;
&lt;td&gt;不支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content:encoded></item><item><title>my test page</title><link>https://blog.dccif.top/2017/10/10/my-test-page/</link><guid isPermaLink="true">https://blog.dccif.top/2017/10/10/my-test-page/</guid><description>my test page</description><pubDate>Tue, 10 Oct 2017 05:05:03 GMT</pubDate><content:encoded>&lt;h1&gt;个人测试页&lt;/h1&gt;
&lt;h2&gt;这是我的一个测试页面&lt;/h2&gt;
&lt;h3&gt;我也不知道写什么好&lt;/h3&gt;
</content:encoded></item><item><title>一个简单的简谱转调程序</title><link>https://blog.dccif.top/2017/08/07/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E7%AE%80%E8%B0%B1%E8%BD%AC%E8%B0%83%E7%A8%8B%E5%BA%8F/</link><guid isPermaLink="true">https://blog.dccif.top/2017/08/07/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E7%AE%80%E8%B0%B1%E8%BD%AC%E8%B0%83%E7%A8%8B%E5%BA%8F/</guid><description>从《记第一个对我有实际作用的程序》之后已经过了602天。终于我更新了第二个版本😂</description><pubDate>Mon, 07 Aug 2017 02:19:03 GMT</pubDate><content:encoded>&lt;h1&gt;老版本的问题&lt;/h1&gt;
&lt;p&gt;从&lt;a href=&quot;https://blog.dccif.top/2015/12/14/%E8%AE%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AF%B9%E6%88%91%E6%9C%89%E5%AE%9E%E9%99%85%E4%BD%9C%E7%94%A8%E7%9A%84%E7%A8%8B%E5%BA%8F%EF%BC%88%E9%80%83%EF%BC%89/&quot;&gt;《记第一个对我有实际作用的程序》&lt;/a&gt;之后已经过了602天。终于我更新了第二个版本😂&lt;/p&gt;
&lt;p&gt;尴尬.......其实我也只是为了练习前几天新学的新方法（不然谁还挖以前的坑）🤣&lt;/p&gt;
&lt;p&gt;回想我上一个版本的程序，只能转换&lt;strong&gt;全音&lt;/strong&gt;，还没法识别&lt;strong&gt;半音&lt;/strong&gt;。。。。现在来看就是因为那时我用了&lt;strong&gt;键值对&lt;/strong&gt;的方法来转换的。。。我没功夫把所有的音阶都记录下键值对。。。&lt;/p&gt;
&lt;p&gt;同时感谢贴吧 &lt;a href=&quot;https://tieba.baidu.com/home/main?id=tb.1.8026e840.pvGEopbxnwZpX2aH7NkVfg&quot;&gt;DverysGetime&lt;/a&gt; 的贴，让我理解的转调原理，原文 &lt;a href=&quot;https://tieba.baidu.com/p/2473627200&quot;&gt;【申精】DG教你看简谱音阶转调图，转调翻译再也不求人&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;我的&lt;strong&gt;参照表&lt;/strong&gt;也是原贴中的：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/jp1.webp&quot; alt=&quot;jp1&quot; /&gt;&lt;/p&gt;
&lt;p&gt;这样一看下来&lt;/p&gt;
&lt;p&gt;如果全部写成键值对的话就要&lt;/p&gt;
&lt;p&gt;$12&lt;em&gt;3&lt;/em&gt;12=432$&lt;/p&gt;
&lt;p&gt;一共这么多对，当然理论上也不是不行，但是当写成这么傻的方法时，应该要考虑换一下方法了。。。。&lt;/p&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;p&gt;各位这时不妨也思考一下怎么转换好了，这篇文章我是不会贴代码了（反正我知道也没人会看）我只分享我的思路&lt;/p&gt;
&lt;h1&gt;新思路&lt;/h1&gt;
&lt;p&gt;怎么样，思考好了吗？（多半也没人认真想吧!😝)&lt;/p&gt;
&lt;p&gt;那么我分享一下我的思路&lt;/p&gt;
&lt;p&gt;首先原来的音阶表上的音名。。。ABC 这些对我干扰太大了😥，&lt;a href=&quot;https://github.com/dccif-zz/Bauble/blob/master/TuneChange/TuneChange.py&quot;&gt;老的版本&lt;/a&gt;上我就傻傻地把简谱的1,2,3还先转换成音名CDE&lt;/p&gt;
&lt;p&gt;然后利用CDE在我提前输入的转换表中查找来进行音调转换&lt;/p&gt;
&lt;p&gt;因为原来我天真地认为是&lt;/p&gt;
&lt;p&gt;不管输入什么简谱的1，2，3对应到表上第一排的音名是不变的，再利用音名转换到目标简谱上就行了。。。&lt;/p&gt;
&lt;p&gt;看过我&lt;a href=&quot;https://github.com/dccif-zz/Bauble/blob/master/TuneChange/TuneChange.py&quot;&gt;原先的程序&lt;/a&gt;的就知道了，很傻很天真的方法表情&lt;/p&gt;
&lt;p&gt;所以我就参考了&lt;strong&gt;转调的定义&lt;/strong&gt;：不同调的&lt;strong&gt;Do位置&lt;/strong&gt;不同，在上面的图上中间灰色的矩形很好的表示了这一点，也就是说不同的调的转换只需要移动&lt;strong&gt;Do的位置&lt;/strong&gt;就行了，并不用原先的我用的那种还需要音名CDE来当两个不同简谱间桥梁的转换方法。&lt;/p&gt;
&lt;p&gt;那么发现了转调的定义后，如何实现的这个所谓的“&lt;strong&gt;移动的Do的位置&lt;/strong&gt;”呢？&lt;/p&gt;
&lt;p&gt;用户的输入都是各自调的1,2,3,4...... 程序要做的是移动他们输入调的Do到目标调上。&lt;/p&gt;
&lt;h2&gt;换一个角度看问题&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/jp2.webp&quot; alt=&quot;jp2&quot; /&gt;&lt;/p&gt;
&lt;p&gt;怎么样？有答案了吗？这样建立坐标后，就不用管什么音调，音名了，要做的只有坐标之间的转换。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/jp3.webp&quot; alt=&quot;jp3&quot; /&gt;&lt;/p&gt;
&lt;p&gt;是不是一下觉得很简单了？&lt;/p&gt;
&lt;p&gt;要做的就是把输入转换成一个坐标，然后再转到目标调所在的坐标就行了。这样就能实现“&lt;strong&gt;移动D的位置&lt;/strong&gt;”&lt;/p&gt;
&lt;p&gt;根本不用考虑如何把1,2,3与C D E 对上，我们要考虑的问题又从“&lt;strong&gt;移动D的位置&lt;/strong&gt;”变成了如何获取输入的“&lt;strong&gt;坐标&lt;/strong&gt;”位置。&lt;/p&gt;
&lt;p&gt;再仔细看这个2位&lt;strong&gt;坐标&lt;/strong&gt;的转换问题；我原先旧的程序就是已知一个调转换到另一个调，也就是在上图的两行之间转换，&lt;/p&gt;
&lt;p&gt;提前选择的要转换的调就是告诉我们初始&lt;strong&gt;X坐标&lt;/strong&gt;了，要转换的目标调也就是告诉我们另一个点的&lt;strong&gt;X&lt;/strong&gt;值了&lt;/p&gt;
&lt;p&gt;也就是程序提前就能知道两个&lt;strong&gt;坐标（X,Y）&lt;strong&gt;中的&lt;/strong&gt;X&lt;/strong&gt;值，实际上的计算只要在&lt;strong&gt;Y&lt;/strong&gt;上计算不同行之间的差了。也就是说这样就实现了“&lt;strong&gt;移动Do的位置&lt;/strong&gt;”&lt;/p&gt;
&lt;h2&gt;怎么样，思路有了，剩下就是实现了吧！&lt;/h2&gt;
&lt;p&gt;既然我已经写了这篇文章&lt;/p&gt;
&lt;p&gt;就是我个人已经实现了😀&lt;/p&gt;
&lt;p&gt;上次我的做的是（没人会再用的）命令行程序&lt;/p&gt;
&lt;p&gt;这次我打包成exe文件了，顺带还做了图形界面，毕竟隔了那么久了（这602天不能白过啊）&lt;/p&gt;
&lt;p&gt;如果还是做是命令行，再做一次就没什么意思了&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/dccif-zz/TuneChange/releases&quot;&gt;程序地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Version 0.1&lt;/p&gt;
&lt;p&gt;个人画的GUI，有点丑，这就不要在意了&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/jp4.webp&quot; alt=&quot;jp4&quot; /&gt;&lt;/p&gt;
&lt;p&gt;简单明了(一堆Bug)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/jp5.webp&quot; alt=&quot;jp5&quot; /&gt;&lt;/p&gt;
&lt;p&gt;现在的版本也就是简单的“&lt;strong&gt;坐标转换&lt;/strong&gt;”，输入格式不对的话就不能转换了&lt;/p&gt;
&lt;p&gt;这次的版本使用因为使用了上面说的方法，核心的“&lt;strong&gt;坐标转换&lt;/strong&gt;”就用了一个&lt;strong&gt;键值对&lt;/strong&gt;表和4行代码就实现了，当然这是Python的版本。。。。用其他麻烦一点的语言可能就不止了。&lt;/p&gt;
&lt;p&gt;后续会不会再升级或者修Bug什么的（多半是不可能了，看看和上次隔了多久），倒是我可能会顺带尝试一下Android端，因为做以上这个程序只是顺带的&lt;/p&gt;
&lt;p&gt;实际是练习前面文章第二行说的新方法：一种和&lt;strong&gt;面向对象编程&lt;/strong&gt;（OOP）不同但是又同样强大的方法——&lt;strong&gt;函数式编程&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/dccif-zz/TuneChange&quot;&gt;项目地址&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>记第一个对我有实际作用的程序（逃）</title><link>https://blog.dccif.top/2015/12/13/%E8%AE%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AF%B9%E6%88%91%E6%9C%89%E5%AE%9E%E9%99%85%E4%BD%9C%E7%94%A8%E7%9A%84%E7%A8%8B%E5%BA%8F%EF%BC%88%E9%80%83%EF%BC%89/</link><guid isPermaLink="true">https://blog.dccif.top/2015/12/13/%E8%AE%B0%E7%AC%AC%E4%B8%80%E4%B8%AA%E5%AF%B9%E6%88%91%E6%9C%89%E5%AE%9E%E9%99%85%E4%BD%9C%E7%94%A8%E7%9A%84%E7%A8%8B%E5%BA%8F%EF%BC%88%E9%80%83%EF%BC%89/</guid><description>1. 玩乐器的同学知道，简谱上的不同调之间的转换不如五线谱上方便，我原来最先是参照转调表一个一个人工查找 😥 太累，后来就想写个程序完成了。 2. ———关于调，不懂的可以百毒一下。。。就是与起始音 do 的位置，或者末音 la 的位置（这不是小调了吗，不管，乐理也不太精通，如有大神求指出）</description><pubDate>Sun, 13 Dec 2015 17:14:35 GMT</pubDate><content:encoded>&lt;h1&gt;问题的起因（挖坑原因）：&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;玩乐器的同学知道，简谱上的不同调之间的转换不如五线谱上方便，我原来最先是参照转调表一个一个人工查找 😥 太累，后来就想写个程序完成了。&lt;/li&gt;
&lt;li&gt;———关于调，不懂的可以百毒一下。。。就是与起始音 do 的位置，或者末音 la 的位置（这不是小调了吗，不管，乐理也不太精通，如有大神求指出）&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;问题的实现：&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;脑洞昨天太大 😓，明明只是一个会 C 调的，你干嘛要写个转换任意调的。。。。
原始目的只是想任意调转成 C，后来写着写着觉得这样这程序太弱了（虽然本来就不强)，就临时想转成任意调了。。。。于是有琢磨了一会就有了实现。。。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;实现思路：当初第一目的——任意调到 C，最初是想通过 if 一句一句判断进行实现。。。。后来想写任意调后发现不现实，因为会有 C(6,2)，15 种可能，每个 if 下还要再进行判断是否是 1，2，3，4，这类的简谱名，这样会造成程序的冗长与无用。。。于是就放弃了&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;于是想到了 Python 的 dict 数据结构，使用 key-value 对，便可以便捷的实现调之间转换，只需提前输入好 dict&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&amp;lt;!--more--&amp;gt;&lt;/p&gt;
&lt;h1&gt;实现过程中的问题：&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;我就不应该用 command line（命令行）来获取输入数据 🙈&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;命令行输入的数据我要考虑各种间隔，因为 input()函数获取的输入是“&lt;strong&gt;**&lt;/strong&gt;“中的所有字符，其中考虑如何实现区分，b7,7 ，8 这类输入都头疼了我好久。。&lt;/p&gt;
&lt;p&gt;b7 在 input()中会当成 b 和 7 两个单独的字符，而我想表示的是低音 7，&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/image/tuneChange/cmd.webp&quot; alt=&quot;cmd&quot; /&gt;&lt;/p&gt;
&lt;p&gt;7，8 在 input()中也会傻不拉唧的把逗号（，）也识别进入，我要想办法去除符号后才能进行数据操作&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;问题的解决&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;input()的问题，假设用户配合，全用空格分开，便可利用.split(&quot; &quot;)方法进行去除，之后便可传入列表就行操作&lt;/li&gt;
&lt;li&gt;函数中局部变量和函数定义好后，不会自行调用真是够了&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;一些感想&lt;/h1&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;变量名要取好，我这么一点我都有时忘记了这个变量是干嘛（水平太差）&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;函数中的变量尽量与函数外的变量不要重名，我这个就是重名的，有时搞不懂为何会没有输出，就是因为函数中变量是局部的&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;写什么要先写好第一目的，不要想我这样，写着写着又想写其他目的了，也不要想我一样边写边调试，大部分时间都废在找 bug 和纠错上了。。。。当然因为我是写着写着就想别的目的了，所以边写边调试还是没什么问题的。。。（我觉得）&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h1&gt;垃圾代码&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt;#一时兴起想写的转换简谱调的代码，可以实现任意调之间的转换，啪啪啪，如果在字典中
#有的话。。。字典还没填完备，暂时只有其他调的全音，还无半音
#因为字典还不完备，任意调之间的转换可能会出问题，转c调是没问题的
#（啪啪，打脸，@_@，原本只是想任意调转c，后来脑洞又开，写任意调了）
#命令行版本。。command line version。我觉得还是函数版本好写，不管了以后有空再补
#输入
print(&quot;Please enter the original an&apos;dand ambition tune(use space splite)&quot;)
tuneer = input(&quot;The default is to C:&quot;)
&apos;&apos;&apos;#b表示低音，#表示升（半音阶），g表示高音，用b#表示低半音，用g#表示高半音&apos;&apos;&apos;
putin = input(&quot;please enter number:&quot;)
first1 = &quot;&quot;
listin1 = []
listin2 = []
listout1 = []
listout2 = []
listoutTemp = []
listTemp = []
changekey = {}
changekey2 = {}

# #如有空格去除后再操作
# first1 =&quot;&quot;
# listin1 = []
# listin2 = []
# listout1 = []
# first1 = putin.strip()
# final1 = first1.split(&quot; &quot;)
# for i in final1:
    # listin1.append(i)
# print(listin1)
# #对tune去除
# first2 =&quot;&quot;
# first2 = tuneer.strip()
# final2 = first2.split(&quot; &quot;)
# for i in final2:
    # listin2.append(i)
# print(listin2)

#清除空格和转换大小写，默认到c调
def checkspace(listin):
    &apos;&apos;&apos;#b表示低音，#表示升（半音阶），g表示高音，用b#表示低半音，用g#表示高半音&apos;&apos;&apos;
    listTemp = &quot;&quot;
    listTemp = listin.strip()
    listlow = listTemp.lower()
    listOut = listlow.split(&quot; &quot;)
    if len(listOut) == 1:
        listOut.append(&quot;c&quot;)
    return listOut

#获取原始输入
listin1 = checkspace(putin)
formtuneer = checkspace(tuneer)
tuneerin = formtuneer[0]
tuneerout = formtuneer[1]

#b表示低音，#表示升（半音阶），g表示高音，用b#表示低升半音，用g#表示高半音

#keys
GtoC = {&quot;1&quot; : &quot;b5&quot;, &quot;2&quot; : &quot;b6&quot;, &quot;3&quot; : &quot;b7&quot;, &quot;4&quot; : &quot;1&quot;, &quot;5&quot; : &quot;2&quot;, &quot;6&quot;: &quot;3&quot;,
&quot;7&quot; : &quot;#4&quot;, &quot;g1&quot; : &quot;5&quot;, &quot;g2&quot;:&quot;6&quot;,&quot;g3&quot;:&quot;7&quot;,&quot;g4&quot;:&quot;g1&quot;,&quot;g5&quot;:&quot;g2&quot;,&quot;g6&quot;:&quot;3&quot;,
&quot;g7&quot;:&quot;g#4&quot;,&quot;gg1&quot;:&quot;g5&quot;}
AtoC = {&quot;b7&quot; : &quot;#5&quot;, &quot;1&quot; : &quot;b6&quot;, &quot;2&quot; : &quot;b7&quot;, &quot;3&quot; : &quot;#1&quot;, &quot;4&quot; : &quot;2&quot;, &quot;5&quot; : &quot;3&quot;,
&quot;6&quot; : &quot;#4&quot;, &quot;7&quot; : &quot;#5&quot;, &quot;g1&quot; : &quot;6&quot;, &quot;g2&quot; : &quot;7&quot;, &quot;g3&quot; : &quot;g#1&quot;, &quot;g4&quot; : &quot;g2&quot;,
&quot;g5&quot; : &quot;g3&quot;, &quot;g6&quot; : &quot;g#4&quot; }
BtoC = {&quot;b6&quot; : &quot;b#5&quot;, &quot;b7&quot;:&quot;b#6&quot;, &quot;1&quot; : &quot;b7&quot;, &quot;2&quot; : &quot;#1&quot;, &quot;3&quot; : &quot;#2&quot;, &quot;4&quot; : &quot;3&quot;,
&quot;5&quot; : &quot;#4&quot;, &quot;6&quot; : &quot;#5&quot;, &quot;7&quot; : &quot;#6&quot;, &quot;g1&quot; : &quot;7&quot;, &quot;g2&quot; : &quot;g#1&quot;, &quot;g3&quot; : &quot;g#2&quot;,
&quot;g4&quot; : &quot;g3&quot;, &quot;g5&quot; : &quot;g#4&quot;}
DtoC = {&quot;b4&quot; : &quot;b5&quot;, &quot;b5&quot; : &quot;b6&quot;, &quot;b6&quot; : &quot;b7&quot;, &quot;b7&quot; : &quot;#1&quot;, &quot;1&quot; : &quot;2&quot;,
&quot;2&quot; : &quot;3&quot;, &quot;3&quot; : &quot;#4&quot;, &quot;4&quot; : &quot;5&quot;, &quot;5&quot; : &quot;6&quot;, &quot;6&quot; : &quot;7&quot;, &quot;7&quot; : &quot;g#1&quot;,
&quot;g1&quot; : &quot;g2&quot;, &quot;g3&quot; : &quot;g#4&quot;, &quot;g4&quot; : &quot;g5&quot;}
EtoC = {&quot;b3&quot; : &quot;b#5&quot;, &quot;b4&quot; : &quot;b6&quot;, &quot;b5&quot; : &quot;b7&quot;, &quot;b6&quot; : &quot;#1&quot;, &quot;b7&quot; : &quot;#2&quot;,
&quot;1&quot; : &quot;3&quot;, &quot;2&quot; : &quot;#4&quot;, &quot;3&quot; : &quot;#5&quot;, &quot;4&quot; : &quot;6&quot;, &quot;5&quot; : &quot;7&quot;, &quot;6&quot; : &quot;g#1&quot;,
&quot;7&quot; : &quot;g#2&quot;, &quot;g1&quot; : &quot;g3&quot;, &quot;g2&quot; : &quot;g#4&quot;}
FtoC = {&quot;b2&quot; : &quot;b5&quot;, &quot;b3&quot; : &quot;b6&quot;, &quot;b4&quot; : &quot;b#6&quot;, &quot;b5&quot; : &quot;1&quot;, &quot;b6&quot; : &quot;2&quot;,
&quot;b7&quot; : &quot;3&quot;, &quot;1&quot; : &quot;4&quot;, &quot;2&quot; : &quot;5&quot;, &quot;3&quot; : &quot;6&quot;, &quot;4&quot; : &quot;#6&quot;, &quot;5&quot; : &quot;g1&quot;, &quot;6&quot; : &quot;g2&quot;,
&quot;7&quot; : &quot;g3&quot;, &quot;g1&quot; : &quot;g4&quot;, &quot;g2&quot; : &quot;g5&quot;}

Fulltunekey = {&quot;g&quot;:GtoC, &quot;a&quot; : AtoC, &quot;b&quot; : BtoC, &quot;d&quot; : DtoC,
&quot;e&quot; : EtoC, &quot;f&quot; : FtoC}

#Anykeys，key转换
def inverse(dict):
    dictout = {v : k for k,v in dict.items()}
    return dictout

CtoG = inverse(GtoC)
CtoA = inverse(AtoC)
CtoB = inverse(BtoC)
CtoD = inverse(DtoC)
CtoE = inverse(EtoC)
CtoF = inverse(FtoC)

Fulltuneanykey = {&quot;g&quot; : CtoG, &quot;a&quot; : CtoA, &quot;b&quot; : CtoB, &quot;d&quot; : CtoD,
&quot;e&quot; : CtoE, &quot;f&quot; : CtoF}

#转换key-values对 （first 全到C)
def dictoc(tuneerin,tuneerout):
    if tuneerin == &quot;a&quot;:
        changekey = Fulltunekey[&quot;a&quot;]
    elif tuneerin == &quot;g&quot;:
        changekey = Fulltunekey[&quot;g&quot;]
    elif tuneerin == &quot;b&quot;:
        changekey = Fulltunekey[&quot;b&quot;]
    elif tuneerin == &quot;d&quot;:
        changekey = Fulltunekey[&quot;d&quot;]
    elif tuneerin == &quot;e&quot;:
        changekey = Fulltunekey[&quot;e&quot;]
    elif tuneerin == &quot;f&quot;:
        changekey = Fulltunekey[&quot;f&quot;]
    return changekey
# def dicany(tuneerin,tuneerout):
    # if tuneerin != &quot;c&quot;:
        # changekey = Fulltunekey[tuneerin]

#判断输出，如不是C，再进行转换
def dictoany(tuneerout):
    if tuneerout == &quot;a&quot;:
        changekey2 = Fulltuneanykey[&quot;a&quot;]
    elif tuneerout == &quot;g&quot;:
        changekey2 = Fulltuneanykey[&quot;g&quot;]
    elif tuneerout == &quot;b&quot;:
        changekey2 = Fulltuneanykey[&quot;b&quot;]
    elif tuneerout == &quot;d&quot;:
        changekey2 = Fulltuneanykey[&quot;d&quot;]
    elif tuneerout == &quot;e&quot;:
        changekey2 = Fulltuneanykey[&quot;e&quot;]
    elif tuneerout == &quot;f&quot;:
        changekey2 = Fulltuneanykey[&quot;f&quot;]
    return changekey2

#强制全部到c调
def alltoC(tuneerin):
    changekey = dictoc(tuneerin, tuneerout)
    for i in listin1:
        listout1.append(changekey[i])
    #print(listout1)
    return listout1


# print(listout1)
def ctoall(tuneerout):
    if tuneerout != &quot;c&quot;:
        changekey2 = dictoany(tuneerout)
        listout1 = alltoC(tuneerin)
        for i in listout1:
            listout2.append(changekey2[i])
    return listout2
# ctoall(tuneerout)
# print(listout2)

# if tuneerout != &quot;c&quot;:
    # dicany(tuneerout)
    # for i in listoutTemp:
        # listout1.append(changekey[i])
    # print(listout1)


#最后输出
def checkout(tuneerin,tuneerout):
    if tuneerout == &quot;c&quot;:
        alltoC(tuneerin)
        print(tuneerin,listin1)
        print(&quot;-&amp;gt;&quot;)
        print(&quot;c&quot;,listout1)
    else:
        listout2 = ctoall(tuneerout)
        print(tuneerin,listin1)
        print(&quot;-&amp;gt;&quot;)
        print(tuneerout,listout2)
    return

checkout(tuneerin,tuneerout)


#AtoC = {&quot;b7&quot; : &quot;#5&quot;, &quot;1&quot; : &quot;b6&quot;, &quot;2&quot; : &quot;b7&quot;, &quot;3&quot; : &quot;#1&quot;, &quot;4&quot; : &quot;2&quot;,
&quot;5&quot; : &quot;3&quot;, &quot;6&quot; : &quot;#4&quot;, &quot;7&quot; : &quot;#5&quot;, &quot;g1&quot; : &quot;6&quot;, &quot;g2&quot; : &quot;7&quot;, &quot;g3&quot; : &quot;g#1&quot;,
&quot;g4&quot; : &quot;g2&quot;, &quot;g5&quot; : &quot;g3&quot;, &quot;g6&quot; : &quot;g#4&quot; }
# if tuneerout == &quot;c&quot;:
    # for i in listin1:
        # listout1.append(changekey[i])
    # print(listout1)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如有大神愿意改良或者提出修改的话。。。求到 &lt;a href=&quot;https://github.com/dccif-zz/Bauble/blob/master/TuneChange/TuneChange.py&quot;&gt;Github 地址&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;感激不尽。。。。（半路出家，最近更快期末了，压力山大 ）&lt;/p&gt;
</content:encoded></item></channel></rss>