archlinux 如何安装snapd

  • git clone https://aur.archlinux.org/snapd.git
  • cd snapd
  • makepkg -si
  • sudo systemctl enable –now snapd.socket
  • sudo ln -s /var/lib/snapd/snap /snap

在安装的过程中可能会有某些软件依赖要安装, 根据报错信息安装缺失的软件即可. 最终通过snap安装的软件的位置在 /snap/bin 目录下, 将该目录加到环境变量中即可.

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

qtcreator常用快捷键

对编辑工具越熟悉, 开发效率越高. 快捷键则是其中非常重要的一部分. 下面来看一下qtcreator常用的快捷键.

快捷键说明
Ctrl+B编译当前项目
Ctrl+R运行当前项目
Ctrl+I对选择的文字进行缩进
Ctrl+/注释或取消注释
Ctrl+Shift+S保存全部文件
Ctrl+Shift+R光标下关联的符号进行统一修改
Shift+F2函数定义与实现切换
F1光标下的内容显示帮助文档
F2光标下变量定位位置查找或函数定义与实现间切换
F3查找下一个
F4在头文件和源文件间快速切换
F5开始调试
F9设置或取消断点
F10单步执行
F11单步进入

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

QT信号与槽

QT中的信号与槽是一个比较有用的功能, 主要用于连接不同组件. 通过组件A的事件触发, 执行组件B的槽函数, 实现不同组件间的通信. 代码的一般形式: QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

使用connect函数时需要注意一下几点:

  • 一个信号可以连接多个槽
  • 多个信号可以连接同一个槽
  • 必须在类中加入 Q_OBJECT 宏定义
  • 信号被触发, 槽函数立刻执行
  • signal 函数的参数应该与 slot 函数的参数保持一致, 至少 signal 函数的参数不能少于 slot 函数参数

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

QT类关系

mainwindow.h里的Ui::MainWindow是mainwindow.ui生成的ui_mainwindow.h里定义的类, 是窗体元素文件生成的代码. 这里要以class MainWindow区分开来. 我们能够访问窗体文件定义的元素都是通过class MainWindowui成员进行访问的. 明白这一点之后, 就能够将.ui文件定义的窗体元素, 与实际的代码联系起来.

namespace Ui {
    class MainWindow;
}

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
};

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

QT程序目录结构

在qtcreator中创建一个项目的目录结构如下:

  • HelloWorld.pro为项目管理文件, 里面保存项目文件结构和qt版本等信息.
  • Headers目录保存C++头文件
  • Sources保存C++源文件.
  • widget.ui保存窗体上的文件及其布局的文件

下面来详细介绍一下.pro文件:

# 加入核心图形界面库模块
QT       += core gui

# QT的主版本号超过4, 就添加widgets模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

# 生成可执行文件的名称
TARGET = HelloWorld

# 什么类型的程序, app为图形界面类型的程序
TEMPLATE = app

# 使用过时的库函数时警告
DEFINES += QT_DEPRECATED_WARNINGS

# 源文件
SOURCES += \
        main.cpp \
        mainwindow.cpp

# 头文件
HEADERS += \
        mainwindow.h

# 窗口界面元素文件
FORMS += \
        mainwindow.ui

从上面可以看出, qtcreator项目管理是非常简洁的, 只保存必要的信息. 如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

LAMDBA 宏

写程序最麻烦的一件事, 就是给变量命名. 有的时候不想命名, 就会使用匿名函数. 但C语言并没有为我们提供匿名函数的功能. 而我们可以通过宏定义配合上({block;})形式构造出匿名函数的宏表达式. 下面是一个例子, 该例子在GCC上能过顺利编译通过, 但在G++上无法通过编译.

#include <stdio.h>

#define LAMDBA(return_type, args_type, block)       \
    ({                                              \
        return_type _ args_type block;              \
        _;                                          \
    })

int main(int argc, char *argv[]) {
    int b = LAMDBA(int, (int a, int b), {
        int c = a * a;
        int d = b * 2;
        return c + d;
    })(12, 13);

    printf("%d\n", b);

    return 0;
}

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

动态规划资源

动态规划的主要思想是: 通过历史值计算出当前值, 这也是与递归重要的区别. 动态规划能够有效避免重复计算, 达到更高的性能, 但往往伴随值更高的内存占用.

动态规划的主要步骤:

  • 定义数组元素的含义
  • 找到数组元素之间的关系
  • 找到初始化元素值

动态规划问题的特性:

  • 无后性: 过去与未来无关, 过去只影响现在
  • 最优子结构: 大问题的最优解可有由小问题的最优解推出

更详细的解释可参考下面的链接:

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.

C++ set 交, 并, 差集用法

有时做数据过滤时, 需要使用到集合的交,并,差集. 下面用一个例子记录一下用法:

#include <algorithm>
#include <iostream>
#include <set>
#include <vector>

using namespace std;

int main(void) {
    set<int> a{1, 2, 3};
    set<int> b{2, 3, 4};
    set<int> c;

    // 交集: 2, 3
    set_intersection(a.begin(), a.end(), b.begin(), b.end(),
                     inserter(c, c.begin()));
    c.clear();

    // 并集: 1, 2, 3, 4
    set_union(a.begin(), a.end(), b.begin(), b.end(), inserter(c, c.begin()));
    c.clear();

    // 差集: 1
    set_difference(a.begin(), a.end(), b.begin(), b.end(),
                   inserter(c, c.begin()));
    c.clear();

    // 差集: 4
    set_difference(b.begin(), b.end(), a.begin(), a.end(),
                   inserter(c, c.begin()));

    auto it = c.find(5);
    if (it == c.end()) {
        cout << "c don't have element 5 " << endl;
    }

    int n = c.erase(4);
    cout << n << endl;
}

如果觉得有帮助, 可以扫描右边的微信打赏码支持一下.