步骤 1: 下载OpenSSL

https://www.openssl.org/source/
  • 通常推荐下载最新的、非轻量版(non-light)的版本以获得完整的功能。

步骤 2: 安装OpenSSL

  1. 运行安装程序
    双击下载的安装程序文件,按提示进行安装。建议选择“Copy OpenSSL DLLs to: The OpenSSL binaries (/bin) directory”选项,以便将OpenSSL动态链接库放在可执行文件同一目录下,简化配置过程。
  2. 选择安装目录
    配置自定义安装目录:D:\myEnvironment

步骤 3: 配置环境变量

  • 更新Path变量
    在“编辑环境变量”窗口中,点击“新建(N)”并输入OpenSSL的安装目录下的bin目录路径,例如刚才的:D:\myEnvironment

步骤 4: 验证安装

输入openssl version命令并回车。如果安装成功,你将看到OpenSSL的版本信息输出。

在配置支付方式如连连支付(LianLian Pay)时
RSA公钥和私钥是一对,公钥用于加密信息,而私钥用于解密信息。

RSA 密钥对简介

RSA加密算法是基于一对密钥——公钥和私钥——工作的,这两个密钥是一起生成的。公钥和私钥在数学上是相关联的,但是设计上确保了只有生成它们的过程能够知道这种联系。公钥用于加密数据,而私钥用于解密数据。私钥还用于数字签名的生成,而公钥用于签名的验证。

生成私钥和公钥的过程涉及复杂的数学运算,包括大质数的选择和乘积,以及与之相关的一系列计算。私钥包含了这个过程中的所有秘密参数,而公钥则只包含了一部分信息,不足以还原出私钥。
这种设计确保了即使有人知道了公钥,也无法逆向工程来获取私钥。实际上,公钥可以自由共享和分发,而不会危及到私钥的安全性。这就是为什么私钥必须被严格保密,而公钥则可以公开的原因。
因此,如果你失去了私钥,就没有办法仅通过公钥来重新生成或恢复私钥。这种情况下,你需要生成一对新的密钥对,并在必要的场合(如配置支付系统)使用新的公钥。

Windows PowerShell

Get-ChildItem -Filter *.webp | ForEach-Object {
    $newName = $_.BaseName + ".jpg"
    magick $_.Name $newName
}
  • Get-ChildItem -Filter *.webp:获取当前目录下所有.webp扩展名的文件。
  • ForEach-Object:对获取到的每一个文件执行接下来的代码块。
  • 在代码块中,$_.BaseName + ".jpg"用于构造新的文件名(即将原文件的.webp扩展名替换为.jpg),然后调用magick命令将原文件转换为新的.jpg文件。

linux 和 Mac OS

for file in *.webp; do
  magick "$file" "${file%.webp}.jpg"
done

ImageMagick是一个功能强大的创建、编辑、合成、转换图像的工具。它支持超过200种图像格式,包括WebP到PNG的转换。

官方文档

//https://imagemagick.org/script/index.php

Windows 安装

下载:访问ImageMagick的官方下载页面,选择适合的Windows版本的安装程序下载。
安装:运行下载的安装程序。在安装过程中,确保选择了“Add application directory to your system path”选项,这样您就可以在命令提示符中直接调用ImageMagick了。
验证安装:打开命令提示符(CMD)或PowerShell,输入magick -version,如果看到版本信息,表明安装成功。

  • 转换图像格式:
    magick input.png output.jpg
  • 调整图像大小:将图像缩放到指定的尺寸(例如,宽度为100像素)。
    magick input.png -resize 100x output.png
  • 旋转图像:将图像逆时针旋转90度。
    magick input.png -rotate 90 output.png
  • 旋转图像:将图像逆时针旋转90度。
    magick input.png -rotate 90 output.png
  • 查看图像信息:查看图像的详细信息。
    magick identify -verbose input.png

1. while循环

  • 特点:while循环会在每次循环开始前检查条件表达式,如果条件为真,则执行循环体。
  • 适用场景:当你不确定需要循环执行多少次时,while循环是一个好选择。适用于循环次数依赖于外部条件的情况。
  • 示例:
    int i = 0;
    while (i < 5) {
        printf("%d ", i);
        i++;
    }

    2. for循环

  • 特点:for循环将循环的初始化、条件检查和更新都集成在一个语句中,使得循环控制更加集中和明确。
  • 适用场景:当你知道循环需要执行的确切次数,或者对循环变量的初始化和更新有明确的要求时,for循环是最佳选择。常用于遍历数组或集合。
  • 示例:
    for (int i = 0; i < 5; i++) {
        printf("%d ", i);
    }

    3. do-while循环

  • 特点:do-while循环至少执行一次循环体,然后再检查条件表达式。循环体总是在条件检查之前执行。
  • 适用场景:适用于至少需要执行一次循环体的情况,例如,至少需要显示一次菜单的用户交互程序。
  • 示例:
    int i = 0;
    do {
        printf("%d ", i);
        i++;
    } while (i < 5);

总结:

  • 使用while循环时,如果初始条件不满足,循环体可能一次都不会执行。
  • for循环适用于循环次数已知或者对循环变量的控制较为复杂的情况,它使代码更加紧凑和清晰。
  • do-while循环保证了循环体至少执行一次,适用于先执行后判断的场景。

在C语言中,char是一种基本数据类型,用来存储单个字符。在内存中,char类型通常占用1个字节(但这也取决于具体的编译器和系统架构),可以存储标准的ASCII字符集中的任意字符。ASCII字符集包括英文大小写字母、数字、标点符号以及控制字符等,每个字符都对应一个介于0到127的整数值。

char类型的使用

  • 声明字符变量:使用char关键字可以声明字符变量。
    char letter = 'A';
    char digit = '1';
    char symbol = '@';

    在这里,字符常量用单引号(')括起来,表示它是一个字符,而不是字符串。

  • 字符数组与字符串:char类型的数组可以用来存储字符串。在C语言中,字符串实际上是以空字符'\0'(ASCII值为0)结尾的字符数组。
    char name[5] = "John";

    在这个例子中,name数组将包含字符'J'、'o'、'h'、'n'和'\0'。虽然只有4个可见字符,但C语言的字符串总是以空字符结束,因此需要一个额外的位置来存储这个空字符。

    char和整数类型的转换

    在C语言中,char类型实际上存储的是整数值,这意味着char类型的变量可以参与数值运算。

  • 每个字符都有一个与之对应的ASCII值。例如,字符'A'的ASCII值是65,字符'0'的ASCII值是48。
  • 可以直接将char类型的变量与整数进行比较或赋值。
    char letter = 65; // 等同于 char letter = 'A';

    符号问题

    char类型分为两种:signed char和unsigned char。

  • signed char:可以表示的范围通常是-128到127(取决于系统和编译器),它可以存储负值。
  • unsigned char:可以表示的范围是0到255,仅用来存储正值或零。
    默认情况下,如果没有显式指定signed或unsigned,char的有符号性(是否可以表示负数)是由编译器决定的。
    应用
    char类型在处理字符数据时非常有用,比如读写文本文件、处理用户输入、显示消息等场合。理解char类型及其与整数值之间的关系是掌握C语言字符串和字符操作的基础。
// 函数用起泡法对输入的10个整数按由小到大的顺序排列
#include <stdio.h>
// 该函数接受一个整型数组x[] 作为参数。它用两层嵌套循环实现冒泡排序,外层循环控制遍历的轮数,内层循环用于实际的比较和交换两个相邻的元素。如果发现顺序错误(即x[i] > x[i + 1]),则通过中间变量t交换这两个元素的位置。这个过程会持续直到数组完全排序。
int paixu(int x[])
{
    int i, j, t;
    for (j = 1; j < 10; j++)
        for (i = 0; i <= 9 - j; i++)
            if (x[i] > x[i + 1])
            {
                t = x[i + 1]; //将x[i + 1]的值暂存到变量t中。
                x[i + 1] = x[i]; //将x[i]的值赋给x[i + 1],这样x[i + 1]就存放了较大的值
                x[i] = t; //将暂存的较小的值(原x[i + 1]的值,现存储于t中)赋给x[i]
            }
}
//**函数main**:这是程序的入口点。首先,它声明了一个整型数组y[10]用于存放用户输入的10个整数。通过一个for循环,程序使用scanf函数读取用户输入的10个整数并存储在数组y中。然后,调用paixu函数对这些数进行排序。最后,再次使用一个for循环和printf函数,按排序后的顺序输出这10个整数。
int main()
{
    int y[10];
    int i;
    for (i = 0; i < 10; i++)
        scanf("%d", &y[i]); // 在C语言中,使用&操作符获取变量的地址。因为scanf需要知道在内存中的哪个位置存放读入的值,所以必须传递变量的地址而不是变量的值。这里,&y[i]表示数组y中第i个元素的地址。
    paixu(y);
    for (i = 0; i < 10; i++)
        printf("%5d", y[i]); // 用于格式化输出数组y的元素。其中,%5d指示printf以十进制整数的形式输出y[i]的值,并且为这个值分配至少5个字符的宽度。如果y[i]的值占用的字符数少于5个,输出将通过在前面添加空格来对齐,确保每个值占用的空间都是相同的。这样做的目的是为了使输出整齐、易于阅读。
    printf("\n");
    // 用于在输出完数组的所有元素后换行。没有这个语句,所有的输出会连续显示在一行上,可能会让人难以阅读。通过添加换行符\n,可以在输出每个数组之后将光标移动到下一行,从而使输出结果更加清晰。
    return 0;
}

在JavaScript中,forEach 方法和 for...of 循环都可以用于遍历数组(或类数组对象)中的元素。但是,它们在使用上有一些关键的区别:

for...of 循环

  • 更多控制:for...of 循环提供了对循环的更多控制,包括使用 break, continue 和 return(如果在函数内部)来控制循环流程。
  • 更广泛的适用性:除了数组之外,for...of 可以用来遍历任何实现了迭代协议的对象,包括字符串、Map、Set等。
  • 异步迭代:for...of 循环可以与异步迭代(for await...of)结合使用,便于处理异步迭代对象,如异步生成器函数。
  • 示例:
    for (const link of myLinks) {
    link.onclick = (e) => {
        e.preventDefault();
        const linkData = e.target.getAttribute("data-page");
        getData(linkData);
    };
    }

    forEach 方法

  • 针对数组设计:forEach 方法特定于数组,是 Array 的一个方法。它不适用于没有实现 forEach 方法的其他可迭代对象。
  • 不能使用 break 和 continue:在 forEach 函数中不能使用 break 或 continue 来退出循环或跳过当前迭代。
  • 回调函数的作用域:forEach 允许为回调函数指定一个可选的第二参数,用作回调函数内 this 的值。而在 for...of 循环中,通常通过闭包或外部变量来访问外部作用域。
  • 无法直接使用异步操作:虽然在 forEach 的回调函数中可以执行异步操作,但是 forEach 本身不会等待这些异步操作完成。如果需要处理异步操作,可能需要使用 for...of 循环结合 async/await 或其他方法。
    示例:

    myLinks.forEach((myLink) => {
    myLink.addEventListener("click", function(e) {
        e.preventDefault();
        const linkData = e.target.getAttribute("data-page");
        getData(linkData);
    })
    });
const reqHeaders = new Headers();
// a cached response is okay unless it's more than a week oldreqHeaders.set("Cache-Control", "max-age=604800");

Cache-Control 是一个 HTTP 头部字段,用于定义缓存策略。在客户端和服务端都有广泛的应用。一些常见的 Cache-Control 指令包括:

  • max-age=<seconds>: 指定一个时间长度,在这段时间内,缓存的副本仍然是新鲜的。
  • no-cache: 强制所有缓存了该响应的缓存器在使用已缓存的数据前,发送请求到原始服务器进行验证。
  • no-store: 禁止缓存,表示请求或响应中的信息不应被存储在缓存中。