40、CGI环境变量、HTTP请求头、正则表达式及ASCII表详解

CGI环境变量、HTTP请求头、正则表达式及ASCII表详解

1. CGI环境变量

CGI程序能以多种形式接收信息,其中CGI环境变量是非常实用的一种。这些变量由父Web服务器进程提供给CGI程序,服务器依据三个不同来源的信息创建这些变量:
- 传入的HTTP请求:可提供 REMOTE_ADDR 信息。
- Web服务器程序自身:例如 SERVER_SOFTWARE 变量由Web服务器提供。
- Web客户端提供给Web服务器的HTTP请求头:像 REQUEST_METHOD CONTENT_TYPE QUERY_STRING 等信息,由Web服务器从HTTP请求头中提取并放入环境变量。

部分环境变量由上述多个来源的信息组合填充。例如, REMOTE_HOST 需要 REMOTE_ADDR ,还要求服务器能为给定的IP地址解析出名称; PATH_TRANSLATED 部分来自Web客户端请求的URL,部分来自Web服务器软件确定的服务器目录结构。

有些从HTTP请求头派生的环境变量并非CGI规范严格要求的,但CGI规范为Web客户端提供了扩展Web服务器提供给CGI程序的标准环境变量集的方法。一个非常流行的通过此扩展派生的CGI环境变量是 HTTP_USER_AGENT ,它包含用于调用CGI程序的Web客户端软件的名称,在创建生成特定浏览器网页的CGI程序时至关重要。扩展派生的变量以 HTTP_ 为前缀。

以下是标准CGI规范环境变量以及一些非常流行的扩展派生变量的表格:
| CGI环境变量 | 描述 |
| — | — |
| AUTH_TYPE | 用于验证用户的特定协议认证方法(如适用) |
| CONTENT_LENGTH | Web客户端提供的附加注释的字节数,可参考 CONTENT_TYPE 环境变量 |
| CONTENT_TYPE | 附加到Web客户端创建的HTTP头的数据内容类型(如果有),例如 POST PUT |
| HTTP_ACCEPT | 客户端将接受的MIME类型,由HTTP响应头给出。这是一个扩展变量,虽不属于基本CGI环境变量规范,但使用极为普遍 |
| HTTP_USER_AGENT | 客户端用于发送请求的浏览器。这是一个扩展变量,虽不属于基本CGI环境变量规范,但使用极为普遍 |
| GATEWAY_INTERFACE | 此服务器遵循的CGI规范版本 |
| PATH_INFO | Web客户端提供的额外路径信息 |
| PATH_TRANSLATED | Web服务器创建的 PATH_INFO 的转换版本,会进行必要的虚拟到物理的映射 |
| QUERY_STRING | 引用相关CGI程序的URL中 ? 后面的信息 |
| REMOTE_ADDR | 发出请求的远程主机的IP地址 |
| REMOTE_HOST | 发出请求的远程主机的DNS名称。如果服务器无法获取此信息,可能有两种情况:要么服务器不设置此变量,要么将其设置为与 REMOTE_ADDR 相同的值 |
| REMOTE_IDENT | 如果HTTP服务器和客户端都支持RFC 931标识,此变量将设置为从服务器检索到的远程用户名 |
| REMOTE_USER | 如果服务器支持用户认证且脚本受保护,这是用户认证的用户名 |
| REQUEST_METHOD | 用于发出HTTP请求的方法,最可能是 GET POST |
| SCRIPT_NAME | 正在执行的脚本的虚拟路径,用于自引用URL |
| SERVER_NAME | 服务器的主机名、DNS别名或IP地址,会出现在自引用URL中 |
| SERVER_PORT | HTTP请求发送到的端口号 |
| SERVER_PROTOCOL | 请求所使用的协议的名称和版本,几乎总是 HTTP |
| SERVER_SOFTWARE | 响应请求的Web服务器软件的名称和版本 |

下面是一个简单实用的Perl程序 showenv.cgi ,用于输出所有适用的环境变量:

#!/usr/local/bin/perl
print "Content-type: text/plain\n\n";
while (($key,$value) = each %ENV) {
    print "[$key]\t[$value]\n";
}

需要注意的是, %ENV 是Perl用于存储环境变量信息的哈希数组。

运行上述代码后,可能会得到如下输出(名称和IP地址已更改):

[SERVER_SOFTWARE]       [NCSA/1.5]
[GATEWAY_INTERFACE]     [CGI/1.1]
[DOCUMENT_ROOT] [/var/spool/www]
[REMOTE_ADDR]   [255.255.255.255]
[SERVER_PROTOCOL]       [HTTP/1.0]
[REQUEST_METHOD]        [GET]
[REMOTE_HOST]   [www.mywebsite.com]
[QUERY_STRING]  []
[HTTP_USER_AGENT]       [Mozilla/4.04 [en] (WinNT; U) via Harvest Cache version 2.1-beta-internal-41]
[PATH]  [/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin:.]
[HTTP_CONNECTION]       [Keep-Alive]
[HTTP_ACCEPT]   [image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*]
[HTTP_ACCEPT_LANGUAGE]  [en]
[SCRIPT_NAME]   [/show_env_var.cgi]
[SERVER_NAME]   [www.mywebsite.com]
[HTTP_ACCEPT_CHARSET]   [iso-8859-1,*,utf-8]
[SERVER_PORT]   [80]
[HTTP_HOST]     [www.mywebsite.com]
[HTTP_VHOSTING_AGENT]   [255.255.255.255 via www.mywebsite.com:80 to www2.mywebsite.com:80]
[SERVER_ADMIN]  [admin@mywebsite.com]

关于上述列出的环境变量,有两点需要说明:
- 一些以 HTTP_ 开头的环境变量是扩展变量,但它们由Web服务器添加,而非HTTP请求头的内容所致。
- PATH 环境变量确实是环境变量,但不是CGI环境变量,它是Perl脚本环境的产物。

2. HTTP请求头

当用户在Web客户端中输入URL并“发送”以获取网页时,Web客户端会使用该URL创建HTTP请求头。这个请求头发送到Web服务器,服务器对其进行解码并返回适当的HTTP回复。

简单的请求头可能只包含一个 GET 行,但实际上请求头可能更加复杂和广泛。例如,Netscape Web客户端请求一个虚拟网站的根索引时生成的请求头如下:

GET / HTTP/1.0
Connection: Keep-Alive
User-Agent: Mozilla/4.04 [en] (WinNT; U)
Host: www.mywebsite.com
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8

这个请求头的第一行很熟悉,类似于之前附录中使用的单个 GET 头命令,只是多了一些指定客户端可接受的HTTP版本的信息。可以注意到,这些头信息会对应到 REQUEST_METHOD SERVER_PROTOCOL CGI环境变量。 User-Agent 头行表明使用的Web客户端是Mozilla(Netscape的别名),三个 Accept 头行则会转换为前面列表中显示的 HTTP_ 环境变量。

如果指定的URL是 http://www.mywebsite.com/mycgiprogram.cgi?this=that 并通过另一个页面的链接访问,HTTP请求头会稍有变化:

GET /mycgiprogram.cgi?this=that HTTP/1.0
Referer: http://www.mywebsite.com/refererlink.html
Connection: Keep-Alive
User-Agent: Mozilla/4.04 [en] (WinNT; U)
Host: www.mywebsite.com
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8

此时查询字符串隐藏在 GET 行中,Web服务器负责解码此信息并将其放入 QUERY_STRING 环境变量。 Referer 头行的内容会被放入 HTTP_REFERER 环境变量。

当表单以 ACTION 方式提交到CGI程序时,会生成不同的HTTP请求头。以下是HTML源代码:

<html><head><title>a test form</title></head>
<body>
<form method=post action=http://www.mywebsite.com/test.cgi>
<input type=text name=texttest value="first bit ‘o’ stuff"><br>
<textarea name=textareatest rows=4 cols=30> 2nd bit o stuff,
this time in a textarea.</textarea>
<input type=submit name=submit value=submit>
</form></body></html>

生成的HTTP请求头如下:

POST /test.cgi HTTP/1.0
Referer: http://www.mywebsite.com/formtest.html
Connection: Keep-Alive
User-Agent: Mozilla/4.04 [en] (WinNT; U)
Host: www.mywebsite.com
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png, */*
Accept-Language: en
Accept-Charset: iso-8859-1,*,utf-8
Content-type: application/x-www-form-urlencoded
Content-length: 105
mytest=first+bit+%27o%27+stuff&bubba=2nd+bit+o+stuff%2C%0D%0Athis+time+in+a+text area.%0D%0A&submit=submit

可以看到,这里使用的方法是 POST 而非 GET ,并且添加了一些新的头信息。 Content-type 告知Web服务器,头信息附带了 application/x-www-form-urlencoded MIME类型的内容,这是CGI编程中常见的标准编码方案的正式名称。 Content-length 显示了附带内容的字节长度。最后,提交表单的内容中,空格被转换为 + ,特殊字符被转换为 %- 转义的十六进制代码,这些内容通过 STDIN 文件流提供给CGI程序。

以下是HTTP请求头的简要参考列表:
| 头信息 | 描述 |
| — | — |
| From: | 请求用户的Internet电子邮件格式的名称 |
| Accept: | 以分号分隔的表示方案列表( Content-Type 元信息值),表示此请求响应中可接受的内容 |
| Accept-Encoding: | 与 Accept 类似,但列出响应中可接受的 Content-Encoding 类型 |
| Accept-Language: | 与 Accept 类似,但列出响应中首选的语言值 |
| User-Agent: | 给出原始使用的Web客户端软件的名称,不受代理影响。虽然是可选的,但建议包含此头信息 |
| Referer: | 一个可选的头字段,用于告知服务器请求的URL是从哪个文档获取的 |
| Authorization: | 包含授权信息,可能是访问某些受保护Web文档所需的 |
| ChargeTo: | 包含用于货币计费的账户信息,为支持电子商务而引入 |
| If-Modified-Since: | 此请求头与 GET 方法一起使用,使请求具有条件性。如果请求的文档自该字段指定的时间以来未更改,Web服务器将发送 Not Modified 304 回复,而不是请求的文档 |
| Pragma: | 为中间和代理服务器提供的Pragma指令 |

3. 正则表达式总结

正则表达式是一种指定模式的方式,用于过滤文本并仅匹配特定的字符串。一旦匹配到字符串,就可以从较大的文本主体中提取该字符串或用另一个字符串替换它。在Perl中,另一种常见的技术是将正则表达式用作 if 语句的条件,这样当特定文本字符串包含与表达式匹配的文本时,语句将评估为 True

正则表达式由一系列合法符号和合法运算符组成。以下是正则表达式的元字符、元括号和元序列的详细说明:

3.1 元字符

元字符 描述
^ 匹配字符串的开头,或者如果使用 /m 选项,则匹配行的开头。它是两个模式锚点之一,另一个是 $
. 匹配除换行符之外的任何单个字符(除非指定了 /s 选项,此时也会匹配换行符)
$ 匹配字符串的结尾,或者如果使用 /m 选项,则匹配行的结尾。它是两个模式锚点之一,另一个是 ^
| 允许指定两个可以使匹配成功的值。例如, m/a|b/ 表示 $_ 变量必须包含 a b 字符才能匹配成功
* 表示其左侧的项应匹配0次或更多次才能评估为 True 。因此, .* 可以匹配任意数量的字符
+ 表示其左侧的项应匹配1次或更多次才能评估为 True
? 表示其左侧的项应匹配0次或1次才能评估为 True 。当与 + ? {n, m} 元字符和括号一起使用时,意味着正则表达式应采用非贪婪模式,匹配尽可能小的字符串

3.2 元括号

元括号 描述
() 括号可影响模式评估的顺序,并作为一种模式记忆形式
(?…) 如果左括号后紧跟一个问号,表示正在指定扩展模式组件(Perl 5新增)
(?#comment) 扩展: comment 可以是任何文本,用于添加注释
(?:regx) 扩展: regx 可以是任何正则表达式,但括号不会作为反向引用保存
(?=regx) 扩展:允许匹配零宽度的正向预查字符(即正则表达式被匹配,但不返回为已匹配)
(?!regx) 扩展:允许匹配零宽度的负向预查字符(即 (?=regx) 的否定形式)
(?options) 扩展:将指定的选项应用于模式,无需以常规方式指定选项。有效选项包括: i (不区分大小写)、 m (视为多行)、 s (视为单行)和 x (允许空格和注释)
{n, m} 花括号用于指定其左侧的项应匹配的次数。 {n} 表示应精确匹配 n 次, {n,} 表示至少匹配 n 次, {n, m} 表示至少匹配 n 次但不超过 m
[] 方括号用于创建字符类。例如, m/[abc]/ 如果 $_ 中包含 a b c 中的任何一个字符,则评估为 True 。方括号是 \| 元字符的更易读替代方案

3.3 元序列

元序列 描述
\ 转义其后的字符,使其忽略通常附带的特殊含义。例如,如果需要在模式中包含美元符号,必须使用 \$ 以避免Perl的变量插值。使用 \\ 指定模式中的反斜杠字符
\nnn 任何八进制字节,其中 nnn 表示八进制数,允许通过八进制数指定任何字符
\a 警报字符,打印时会产生警告铃声
\A 表示字符串的开头,其含义不受 /m 选项影响
\b 在字符类中表示退格字符,否则表示单词边界,即单词 (\w) 和非单词 (\W) 字符之间的位置。Perl认为 \W 元序列匹配字符串末尾的虚拟字符
\B 匹配非单词边界
\cn 任何控制字符(其中 n 是字符,例如 \cY 表示 Ctrl+Y
\d 匹配单个数字字符
\D 匹配单个非数字字符
\e 转义字符
\E 终止 \L \U 序列
\f 换页字符
\G 仅匹配上一次 m//g 停止的位置
\l 将下一个字符转换为小写
\L 将后续字符转换为小写,直到遇到 \E 序列
\n 换行字符
\Q 逐字引用正则表达式元字符,直到遇到 \E 序列
\r 回车字符
\s 匹配单个空白字符
\S 匹配单个非空白字符
\t 制表符
\u 将下一个字符转换为大写
\U 将后续字符转换为大写,直到遇到 \E 序列
\v 垂直制表符
\w 匹配单个单词字符(单词字符包括字母数字和下划线字符)
\W 匹配单个非单词字符
\xnn 任何十六进制字节
\Z 表示字符串的结尾,其含义不受 /m 选项影响
\$ 美元字符
\@ 与符号
\% 百分号字符

下面通过一个简单的mermaid流程图展示正则表达式匹配的基本流程:

graph TD;
    A[开始] --> B[输入文本和正则表达式];
    B --> C[进行匹配操作];
    C --> D{是否匹配成功};
    D -- 是 --> E[输出匹配结果];
    D -- 否 --> F[输出未匹配信息];
    E --> G[结束];
    F --> G;

4. ASCII表

ASCII(美国信息交换标准代码)表定义了字符与数字之间的映射关系。以下是部分ASCII表内容:
| 十进制(Dec) | 十六进制(Hex) | 二进制(Binary) | ASCII字符 |
| — | — | — | — |
| 000 | 00 | 0000 0000 | null |
| 001 | 01 | 0000 0001 | A |
| 002 | 02 | 0000 0010 | B |
|… |… |… |… |
| 255 | FF | 1111 1111 | ˛ |

ASCII表涵盖了从控制字符到可打印字符的广泛范围,在计算机编程和数据处理中起着重要作用。例如,在处理文本文件、网络通信等场景中,经常需要根据ASCII码进行字符的编码和解码。

通过对CGI环境变量、HTTP请求头、正则表达式和ASCII表的详细了解,我们可以更好地进行Web开发和数据处理工作。在实际应用中,合理运用这些知识可以提高程序的效率和稳定性。例如,在编写CGI程序时,准确理解和使用环境变量和请求头信息,能够实现与Web客户端的有效交互;掌握正则表达式可以方便地进行文本的匹配和处理;而熟悉ASCII表则有助于处理字符编码和转换问题。

5. 正则表达式的应用示例

正则表达式在实际编程中有广泛的应用,下面通过几个具体的例子来展示其强大的功能。

5.1 验证邮箱地址

邮箱地址通常有特定的格式,我们可以使用正则表达式来验证一个字符串是否为有效的邮箱地址。以下是一个简单的Perl代码示例:

#!/usr/local/bin/perl
use strict;
use warnings;

my $email = "example@example.com";
if ($email =~ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/) {
    print "$email 是有效的邮箱地址\n";
} else {
    print "$email 不是有效的邮箱地址\n";
}

在这个正则表达式中:
- ^ 表示字符串的开头。
- [a-zA-Z0-9._%+-]+ 表示匹配一个或多个字母、数字、点、下划线、百分号、加号或减号,这部分用于匹配邮箱地址的用户名部分。
- @ 是邮箱地址中必须包含的符号。
- [a-zA-Z0-9.-]+ 匹配一个或多个字母、数字、点或减号,用于匹配域名部分。
- \. 表示匹配一个点。
- [a-zA-Z]{2,} 表示匹配两个或更多的字母,用于匹配顶级域名(如 .com , .org 等)。
- $ 表示字符串的结尾。

5.2 提取HTML标签中的内容

在处理HTML文档时,我们可能需要提取特定标签中的内容。以下是一个使用正则表达式提取 <title> 标签内容的Perl代码示例:

#!/usr/local/bin/perl
use strict;
use warnings;

my $html = '<html><head><title>这是标题</title></head><body></body></html>';
if ($html =~ /<title>(.*?)<\/title>/) {
    my $title = $1;
    print "提取到的标题是: $title\n";
} else {
    print "未找到标题标签\n";
}

在这个正则表达式中:
- <title> 匹配 <title> 标签的开头。
- (.*?) 是一个捕获组,使用非贪婪模式匹配任意字符,直到遇到 </title> 标签。
- <\/title> 匹配 </title> 标签的结尾。

5.3 替换文本中的特定内容

正则表达式还可以用于替换文本中的特定内容。以下是一个将文本中的所有数字替换为 X 的Perl代码示例:

#!/usr/local/bin/perl
use strict;
use warnings;

my $text = "abc123def456";
$text =~ s/\d/X/g;
print "替换后的文本是: $text\n";

在这个正则表达式中:
- \d 匹配任意数字。
- s/// 是Perl中的替换操作符。
- g 表示全局替换,即替换文本中所有匹配的数字。

下面通过一个mermaid流程图展示正则表达式在文本处理中的应用流程:

graph TD;
    A[开始] --> B[输入文本和正则表达式及操作类型];
    B --> C{操作类型};
    C -- 验证 --> D[进行验证操作];
    C -- 提取 --> E[进行提取操作];
    C -- 替换 --> F[进行替换操作];
    D --> G{验证结果};
    G -- 通过 --> H[输出验证通过信息];
    G -- 未通过 --> I[输出验证未通过信息];
    E --> J[输出提取结果];
    F --> K[输出替换后的文本];
    H --> L[结束];
    I --> L;
    J --> L;
    K --> L;

6. CGI环境变量和HTTP请求头的实际应用

6.1 根据用户代理生成不同页面

在Web开发中,我们可以根据 HTTP_USER_AGENT 环境变量生成不同的页面,以提供更好的用户体验。以下是一个简单的Perl CGI程序示例:

#!/usr/local/bin/perl
use strict;
use warnings;

print "Content-type: text/html\n\n";

my $user_agent = $ENV{HTTP_USER_AGENT};
if ($user_agent =~ /Mobile/) {
    print "<html><body><h1>这是移动设备访问的页面</h1></body></html>";
} else {
    print "<html><body><h1>这是桌面设备访问的页面</h1></body></html>";
}

在这个程序中,我们首先获取 HTTP_USER_AGENT 环境变量的值,然后使用正则表达式检查是否包含 Mobile 关键字。如果包含,则认为是移动设备访问,输出适合移动设备的页面;否则,输出适合桌面设备的页面。

6.2 处理表单提交数据

当用户通过表单提交数据时,我们可以使用 REQUEST_METHOD CONTENT_TYPE 环境变量来处理不同类型的请求。以下是一个处理 POST 请求的Perl CGI程序示例:

#!/usr/local/bin/perl
use strict;
use warnings;

if ($ENV{REQUEST_METHOD} eq 'POST') {
    my $content_length = $ENV{CONTENT_LENGTH};
    my $input;
    read(STDIN, $input, $content_length);

    my %form_data;
    my @pairs = split(/&/, $input);
    foreach my $pair (@pairs) {
        my ($key, $value) = split(/=/, $pair);
        $key =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
        $value =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
        $form_data{$key} = $value;
    }

    print "Content-type: text/html\n\n";
    print "<html><body>";
    print "<h1>表单提交的数据如下:</h1>";
    foreach my $key (keys %form_data) {
        print "<p>$key: $form_data{$key}</p>";
    }
    print "</body></html>";
} else {
    print "Content-type: text/html\n\n";
    print "<html><body><h1>只支持POST请求</h1></body></html>";
}

在这个程序中:
1. 首先检查 REQUEST_METHOD 是否为 POST
2. 如果是 POST 请求,获取 CONTENT_LENGTH 环境变量的值,用于读取 STDIN 中的数据。
3. 将读取的数据按 & 分割成键值对,再按 = 分割每个键值对。
4. 对键和值进行 %- 转义的十六进制代码解码。
5. 最后将解码后的数据存储在哈希表中,并输出到页面上。

6.3 操作步骤总结

以下是处理表单提交数据的操作步骤列表:
1. 检查 REQUEST_METHOD 是否为 POST
2. 获取 CONTENT_LENGTH 环境变量的值。
3. 从 STDIN 读取指定长度的数据。
4. 将读取的数据按 & 分割成键值对。
5. 对每个键值对按 = 分割。
6. 对键和值进行 %- 转义的十六进制代码解码。
7. 将解码后的数据存储在哈希表中。
8. 输出表单提交的数据到页面上。

7. 总结与展望

通过对CGI环境变量、HTTP请求头、正则表达式和ASCII表的深入学习,我们了解了它们在Web开发和数据处理中的重要作用。CGI环境变量和HTTP请求头为Web服务器和CGI程序之间的通信提供了丰富的信息,正则表达式则为文本处理提供了强大的工具,而ASCII表则是字符编码和转换的基础。

在未来的Web开发中,这些知识将继续发挥重要作用。随着技术的不断发展,我们可以预见,正则表达式的功能将更加完善,能够处理更复杂的文本匹配和替换任务;CGI环境变量和HTTP请求头的使用也将更加灵活,以适应不断变化的Web应用需求。同时,随着Unicode等更广泛的字符编码标准的普及,ASCII表的应用可能会逐渐减少,但字符编码和转换的基本原理仍然是我们需要掌握的重要知识。

希望本文能够帮助读者更好地理解和应用这些技术,在Web开发和数据处理中取得更好的效果。

六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,详细介绍了正向与逆向运动学求解、正向动力学控制以及基于拉格朗日-欧拉法推导逆向动力学方程的理论与Matlab代码实现过程。文档还涵盖了PINN物理信息神经网络在微分方程求解、主动噪声控制、天线分析、电动汽车调度、储能优化等多个工程与科研领域的应用案例,并提供了丰富的Matlab/Simulink仿真资源和技术支持方向,体现了其在多学科交叉仿真与优化中的综合性价值。; 适合人群:具备一定Matlab编程基础,从事机器人控制、自动化、智能制造、电力系统或相关工程领域研究的科研人员、研究生及工程师。; 使用场景及目标:①掌握六自由度机械臂的运动学与动力学建模方法;②学习人工神经网络在复杂非线性系统控制中的应用;③借助Matlab实现动力学方程推导与仿真验证;④拓展至路径规划、优化调度、信号处理等相关课题的研究与复现。; 阅读建议:建议按目录顺序系统学习,重点关注机械臂建模与神经网络控制部分的代码实现,结合提供的网盘资源进行实践操作,并参考文中列举的优化算法与仿真方法拓展自身研究思路。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值