效率是核心,但效率高的教程会忽略掉非常多的细节。
解决问题的思路和细节对于一个问题的有效求解至关重要。
资料
云课五分钟-02第一个代码复现-终端甜甜圈C++-CSDN博客
从云课五分钟到五秒钟焦虑的甜甜圈向前冲-CSDN博客
说明
复现重要性没有那么大,重点功利角度在于不断提升学习效率(多赚分),社会角度(多赚钱)。
回到ROS云课。
1. c++
#include <stdio.h>
#include <math.h>
#include <cstring>
#include <unistd.h>int main() {float A = 0, B = 0;float i, j;int k;float z[1760];char b[1760];printf("\x1b[2J");for (;;) {memset(b, 32, 1760);memset(z, 0, 7040);for (j = 0; j < 6.28; j += 0.07) {for (i = 0; i < 6.28; i += 0.02) {float c = sin(i);float d = cos(j);float e = sin(A);float f = sin(j);float g = cos(A);float h = d + 2;float D = 1 / (c * h * e + f * g + 5);float l = cos(i);float m = cos(B);float n = sin(B);float t = c * h * g - f * e;int x = 40 + 30 * D * (l * h * m - t * n);int y = 12 + 15 * D * (l * h * n + t * m);int o = x + 80 * y;int N = 8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n);if (22 > y && y > 0 && x > 0 && 80 > x && D > z[o]) {z[o] = D;b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];}}}printf("\x1b[H");for (k = 0; k < 1761; k++) {putchar(k % 80 ? b[k] : 10);A += 0.00004;B += 0.00002;}usleep(30000);}return 0;
}
2. g++
g++ -o donut donut.cpp
3. app
./donut
如上是纯手工复现。
采用自动化方式复现如下:
echo "终端焦虑的甜甜圈"git clone https://gitcode.com/ZhangRelay1/donut.gitcd ~/donutg++ colordonut.cpp -o donut./donutecho "突破封印的甜甜圈"
视频
ROS云课基础题库-C++案例-甜甜圈
你提到的代码是一个在终端中绘制动态甜甜圈图案的 C++ 程序。这个程序通过使用数学函数和 ASCII 字符在终端中创建了一个视觉上类似甜甜圈的旋转效果。复现这个代码的过程不仅有助于理解如何使用 C++ 进行图形编程(尽管是简单的字符图形),还可以提升学习效率,并通过对代码进行修改和优化来提高编程技能。
代码说明
-
包含头文件:
cpp复制代码
#include <stdio.h>
#include <math.h>
#include <cstring>
#include <unistd.h>
这些头文件提供了基本的输入输出、数学函数、内存操作和睡眠功能。
-
变量初始化:
cpp复制代码
float A = 0, B = 0;
float i, j;
int k;
float z[1760];
char b[1760];
这些变量用于存储计算过程中的中间值和最终的字符图形。
-
主循环:
- 使用无限循环
for (;;)
不断刷新终端屏幕。 memset
函数用于清空数组b
和z
。- 嵌套循环计算每个点的位置和亮度。
- 使用数学函数
sin
和cos
计算 3D 空间中的点。 - 通过计算确定每个点对应的 ASCII 字符。
- 使用无限循环
-
输出:
- 使用 ANSI 转义序列
\x1b[H
移动光标到屏幕顶部,并用\x1b[2J
清屏。 - 输出字符数组
b
中的字符,形成图形。 - 使用
usleep(30000)
暂停 30 毫秒以控制刷新率。
- 使用 ANSI 转义序列
自动化复现步骤
你提供的自动化步骤使用 Git 和命令行来快速复现这个项目:
bash复制代码
echo "终端焦虑的甜甜圈" | |
git clone https://gitcode.com/ZhangRelay1/donut.git | |
cd ~/donut | |
g++ colordonut.cpp -o donut | |
./donut | |
echo "突破封印的甜甜圈" |
这些命令的作用是:
- 输出提示信息。
- 克隆包含代码的 Git 仓库。
- 进入项目目录。
- 编译 C++ 源代码并生成可执行文件。
- 运行可执行文件以查看甜甜圈效果。
- 输出完成提示信息。
提升学习效率
- 实践:通过手动编写和调试代码,加深对 C++ 和算法的理解。
- 自动化:利用脚本和工具简化重复性任务,专注于代码的优化和改进。
- 分享:将学习过程和成果记录下来,分享给他人,巩固自己的知识。
社会角度
- 项目经验:这种小型项目可以作为简历上的项目经验,展示你的编程能力和创造力。
- 社区参与:通过分享和参与开源项目,扩大人脉,了解行业动态。
- 持续学习:不断提升自己的技能,适应快速变化的技术环境,增加职业竞争力。
通过复现和优化这样的项目,不仅可以提高编程技能,还可以在学习和工作中获得实际的收益。
C++知识点
这段代码是一个简单的ASCII艺术动画程序,使用数学函数生成一个动态变化的图案。以下是代码中涉及的C++知识点及其详细介绍:
1. 头文件
c复制代码
#include <stdio.h> | |
#include <math.h> | |
#include <cstring> | |
#include <unistd.h> |
<stdio.h>
: 提供输入输出功能,例如printf
和putchar
。<math.h>
: 提供数学函数,例如sin
和cos
。<cstring>
: 提供字符串处理函数,例如memset
。<unistd.h>
: 提供POSIX操作系统API访问,包括usleep
函数。
2. 变量声明和初始化
c复制代码
float A = 0, B = 0; | |
float i, j; | |
int k; | |
float z[1760]; | |
char b[1760]; |
- 基本数据类型: 使用
float
和int
声明变量。 - 数组:
z
和b
是数组,分别用于存储深度和字符。
3. 无限循环
c复制代码
for (;;) { | |
// ... | |
} |
- 无限循环: 使用
for (;;)
创建一个无限循环,常用于需要持续运行的程序。
4. 内存设置
c复制代码
memset(b, 32, 1760); | |
memset(z, 0, 7040); |
memset
函数: 用于将数组b
和z
初始化为特定值。32
是ASCII空格字符,0
用于浮点数数组的初始化。
5. 嵌套循环和数学计算
c复制代码
for (j = 0; j < 6.28; j += 0.07) { | |
for (i = 0; i < 6.28; i += 0.02) { | |
// ... | |
} | |
} |
- 嵌套循环: 用于遍历二维空间。
- 数学函数: 使用
sin
和cos
计算图案的坐标和亮度。
6. 数组索引和条件判断
c复制代码
int x = 40 + 30 * D * (l * h * m - t * n); | |
int y = 12 + 15 * D * (l * h * n + t * m); | |
int o = x + 80 * y; | |
if (22 > y && y > 0 && x > 0 && 80 > x && D > z[o]) { | |
z[o] = D; | |
b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0]; | |
} |
- 数组索引计算: 计算二维坐标
(x, y)
对应的一维数组索引o
。 - 条件判断: 确保坐标在有效范围内,并更新深度缓冲区
z
和字符缓冲区b
。
7. 字符映射
c复制代码
b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0]; |
- 字符数组: 使用字符数组实现亮度到字符的映射。
8. 屏幕输出和动画
c复制代码
printf("\x1b[H"); | |
for (k = 0; k < 1761; k++) { | |
putchar(k % 80 ? b[k] : 10); | |
A += 0.00004; | |
B += 0.00002; | |
} | |
usleep(30000); |
- ANSI转义序列:
\x1b[H
移动光标到屏幕左上角。 - 字符输出: 使用
putchar
输出字符,每80个字符换行。 - 动画效果: 通过改变
A
和B
实现图案的动态变化,并使用usleep
控制帧率。
9. 主函数返回值
c复制代码
return 0; |
- 程序结束:
return 0
表示程序正常结束。
总结
这段代码结合了数学计算、字符处理、内存操作和ANSI转义序列生成动态ASCII艺术图案。它展示了如何在C语言中使用基本图形技术和动画原理。
Linux g++知识点
使用 g++
编译 C++ 程序时,了解编译器的选项和过程是很重要的。下面详细介绍如何使用 g++
编译器将源代码文件 donut.cpp
编译成可执行文件 donut
,并解释其中涉及的知识点。
1. 基本命令结构
bash复制代码
g++ -o donut donut.cpp |
g++
: GNU Compiler Collection(GCC)中的C++编译器。它是用于编译C++程序的主要工具。-o donut
: 指定输出文件名为donut
。如果没有这个选项,默认输出文件名是a.out
。donut.cpp
: 输入的C++源代码文件。
2. 编译过程
编译过程通常包括几个阶段:预处理、编译、汇编和链接。g++
会自动处理这些阶段。
- 预处理: 处理
#include
和#define
指令,展开宏,生成预处理后的代码。 - 编译: 将预处理后的代码翻译成汇编代码。
- 汇编: 将汇编代码转换成机器码,生成目标文件(
.o
文件)。 - 链接: 将目标文件和库文件链接在一起,生成最终的可执行文件。
3. 常见的 g++
选项
-c
: 只编译,不链接。生成目标文件而不是可执行文件。-Wall
: 启用所有常见的警告信息。有助于发现潜在的编程错误。-Wextra
: 启用额外的警告信息,进一步帮助发现潜在问题。-O[n]
: 优化代码,n
为优化级别,0
到3
,0
表示无优化,3
表示最高级别的优化。-g
: 生成调试信息,用于在调试器中查看源代码和执行过程。-std=c++[version]
: 指定C++标准版本,例如-std=c++11
、-std=c++14
、-std=c++17
、-std=c++20
等。-I[directory]
: 指定头文件搜索路径。-L[directory]
: 指定库文件搜索路径。-l[library]
: 链接指定的库文件。
4. 示例解释
在命令 g++ -o donut donut.cpp
中:
- 没有使用优化选项,所以编译器不会进行优化。对于生产代码,通常会使用
-O2
或-O3
来提高性能。 - 没有指定标准版本,所以编译器将使用默认的C++标准版本。为了确保兼容性,通常会显式指定标准版本,例如
-std=c++17
。 - 输出文件
donut
是指定的可执行文件名称。运行这个文件可以通过./donut
在终端中执行。
5. 执行编译后的程序
编译成功后,可以通过以下命令运行生成的可执行文件:
bash复制代码
./donut |
6. 调试和错误处理
- 查看警告和信息: 使用
-Wall
和-Wextra
来捕获潜在的警告。 - 调试: 如果需要调试程序,使用
-g
选项生成调试信息,然后使用调试器(如gdb
)进行调试。
总结
使用 g++
编译器可以有效地将C++源代码转换为可执行文件。通过理解和使用不同的编译器选项,可以控制编译过程,优化代码,生成调试信息,并确保代码与特定的C++标准兼容。
Linux命令知识点
在终端执行 ./donut
命令时,涉及的知识点主要包括以下几个方面:
1. 可执行文件与权限
- 可执行文件:在Linux系统中,可执行文件是一种特殊的文件类型,它包含可以被操作系统直接执行的机器码。
- 执行权限:为了执行一个文件,该文件必须具有执行权限。你可以使用
ls -l
命令查看文件的权限,其中x
表示执行权限。如果没有执行权限,可以使用chmod +x donut
命令来添加执行权限。
2. 当前工作目录
- 当前工作目录:在终端中执行命令时,命令会在当前工作目录(也称为当前目录)中查找文件和可执行文件。
- 路径:如果
donut
文件不在当前工作目录中,你需要提供文件的完整路径或相对路径。例如,如果donut
文件在/home/user/bin
目录下,你需要执行./home/user/bin/donut
或先切换到该目录,再执行./donut
。
3. 命令解释与执行
- 命令解释器(shell):当你输入命令并按下回车键时,终端会调用当前的shell(如bash、zsh等)来解释和执行该命令。
- 动态链接库:如果
donut
程序依赖于某些动态链接库(如libstdc++、libc等),这些库必须在系统的库路径中,或者你需要通过LD_LIBRARY_PATH
环境变量指定库的路径。
4. 环境变量
- 环境变量:环境变量是操作系统中用于配置程序运行环境的参数。例如,
PATH
环境变量指定了shell查找可执行文件的目录列表。 - 影响执行:环境变量可以影响程序的执行,例如,
LANG
环境变量设置程序的语言环境,TZ
环境变量设置程序使用的时区。
5. 终端与输入输出
- 标准输入输出:程序通过标准输入(stdin)、标准输出(stdout)和标准错误输出(stderr)与终端进行交互。默认情况下,
./donut
命令的输出会显示在终端上。 - 重定向:你可以使用重定向符号(如
>
、>>
、<
等)来改变输入输出流的方向。例如,./donut > output.txt
会将程序的输出重定向到文件output.txt
中。
6. 进程管理
- 进程创建:执行
./donut
命令时,系统会创建一个新的进程来运行该程序。 - 进程终止:程序运行结束后,该进程会被终止,并返回控制权给终端。
- 信号处理:在程序运行过程中,你可以通过发送信号来控制程序的执行。例如,使用
Ctrl+C
可以发送SIGINT
信号来终止程序。
7. 错误处理
- 错误报告:如果
donut
程序执行失败,终端通常会显示错误信息,帮助诊断问题。 - 退出状态:程序执行结束后,会返回一个退出状态码。通常,
0
表示成功,非零值表示失败或错误。
8. 安全性
- 可执行文件来源:在执行任何可执行文件之前,应确保文件来源可信,避免执行恶意软件。
- 权限设置:合理设置文件的权限,避免不必要的执行权限。
总结来看,在终端执行 ./donut
命令时,涉及的知识点包括可执行文件与权限、当前工作目录、命令解释与执行、环境变量、终端与输入输出、进程管理、错误处理以及安全性等方面。这些知识点共同构成了在Linux终端中执行程序的基础。
自动化脚本知识点
你提供的命令序列是一个简单的自动化脚本示例,它利用终端命令来执行一系列操作。以下是对每个命令的详细介绍,包括它们涉及的知识点:
1. echo "终端焦虑的甜甜圈"
echo
命令:- 用于在终端输出文本。
- 这里的
"终端焦虑的甜甜圈"
是输出的字符串。 - 知识点:基本的终端命令使用,字符串输出。
2. git clone https://gitcode.com/ZhangRelay1/donut.git
git clone
命令:- 用于从远程Git仓库复制代码到本地。
https://gitcode.com/ZhangRelay1/donut.git
是远程仓库的URL。- 知识点:Git版本控制系统,克隆远程仓库。
3. cd ~/donut
cd
命令:- 用于更改当前工作目录。
~/donut
表示当前用户目录下的donut
文件夹。- 知识点:文件系统导航,路径使用(绝对路径和相对路径)。
4. g++ colordonut.cpp -o donut
g++
编译器:- 用于编译C++源代码文件。
colordonut.cpp
是要编译的源代码文件。-o donut
选项指定输出的可执行文件名为donut
。- 知识点:C++编译过程,
g++
编译器的基本使用。
5. ./donut
- 执行可执行文件:
./donut
命令用于执行当前目录下的donut
可执行文件。- 知识点:可执行文件的执行权限,进程管理。
6. echo "突破封印的甜甜圈"
- 再次使用
echo
命令:- 输出
"突破封印的甜甜圈"
。 - 知识点:同第一个
echo
命令。
- 输出
脚本自动化涉及的知识点
- 顺序执行:
- 脚本中的每个命令按顺序执行。
- 知识点:基本的脚本编写,命令的顺序和依赖关系。
- 脚本文件:
- 可以将这些命令保存到一个文本文件中(如
run.sh
),并通过chmod +x run.sh
赋予执行权限,然后通过./run.sh
来运行整个脚本。 - 知识点:脚本文件的创建和执行权限。
- 可以将这些命令保存到一个文本文件中(如
- 错误处理:
- 在实际应用中,通常需要添加错误处理机制,以确保每个步骤成功执行。
- 知识点:条件判断(如使用
if
语句),错误码检查。
- 环境配置:
- 确保所有依赖的工具(如
git
和g++
)已安装,并在系统的PATH
中可用。 - 知识点:环境变量配置,软件包管理(如使用
apt
、yum
或brew
安装工具)。
- 确保所有依赖的工具(如
总结
这个简单的自动化脚本展示了如何在终端中使用基本命令来执行一系列任务,包括输出文本、克隆Git仓库、编译C++代码和执行可执行文件。涉及的知识点包括终端命令的使用、Git版本控制、C++编译过程、脚本编写和执行权限管理等。通过将这些命令整合到一个脚本中,可以自动化执行这些任务,提高效率和一致性。