Clings 是由 Lingrui Studio 维护的 Rustlings 风格 C 语言练习工具。它读取题库仓库中的 C 源码和 TOML 测试用例,在文件保存后自动编译、运行并反馈结果。
本仓库只包含通用 CLI,不内置课程、题目或参考答案。课程团队可以独立维护题库仓库,并通过 GitHub Classroom 将题目分发给学生。
- Python 3.11+ 标准库实现,无运行时第三方依赖
- 支持 GCC、Clang 和常见 MinGW 环境
- Watch 模式保存即检查,并记录本地学习进度
- 支持退出码、标准输出、仅编译、Makefile 等评测方式
- 题目、提示和公开测试全部由题库仓库管理
- 支持教师使用独立参考答案目录验证题库
需要 Python 3.11+ 和 C 编译器。GNU Make 只在题目使用 Makefile 时需要;题库的 setup.sh 可以一键安装。
#!/bin/sh
set -eu
command -v uv >/dev/null 2>&1 || {
echo "未找到 uv,正在安装。.."
UV_INSTALL_DIR="${UV_INSTALL_DIR:-$HOME/.local/bin}"
export UV_INSTALL_DIR
if command -v curl >/dev/null 2>&1; then
curl -LsSf https://astral.sh/uv/install.sh | sh
elif command -v wget >/dev/null 2>&1; then
wget -qO- https://astral.sh/uv/install.sh | sh
else
echo "安装 uv 需要 curl 或 wget" >&2
exit 1
fi
PATH="$UV_INSTALL_DIR:$PATH"
export PATH
}
command -v uv >/dev/null 2>&1 || {
echo "uv 安装失败,请检查网络连接后重试" >&2
exit 1
}
uv tool install --force \
"git+https://github.com/Lingrui-Studio/clings.git"
clings doctor在包含 clings.toml 和 exercises/ 的题库根目录运行:
clings # 进入交互式 Watch 模式
clings list # 查看题目与进度
clings hint # 查看下一道未完成题目的提示
clings tests 01_hello # 查看公开测试用例
clings run 01_hello # 运行指定题目
clings check # 依次检查全部题目,遇到失败即停止
clings score --json # 检查全部题目并生成 JSON 报告
clings reset 01_hello # 用 Git 中的版本恢复题目文件
clings reset progress # 清除本地进度题目可以通过名称、名称前缀、Unit 或 Lesson 编号筛选:
clings watch unit1
clings check unit1
clings run 2
clings hint pointer进度保存在 .clings-state.txt,编译产物保存在 .clings/build/。这两个路径应加入题库仓库的 .gitignore。
一个最小题库仓库如下:
c-exercises/
├── README.md
├── setup.sh
├── clings.toml
├── tests/ # 可选:独立公开测试
│ └── 01_hello.toml
└── exercises/
├── 01_hello/
│ ├── README.md # 题目说明
│ ├── exercises.toml # 元数据、提示和内联测试
│ └── hello.c # 学生编辑的代码
└── 02_sum/
├── README.md
├── exercises.toml
└── sum.c
根目录必须存在 clings.toml。Unit 信息可集中写在这里:
[[units]]
id = "unit1"
title = "C 语言基础"
lessons = "01-10"Clings 会自动扫描 exercises/**/exercises.toml,无需在根配置中重复登记每道题。
推荐每个 Lesson 使用一个目录。一个目录可以包含一道或多道练习:
[[exercises]]
name = "01_hello"
title = "输出 Hello, World!"
unit = "unit1"
lesson = 1
order = 1
mode = "stdout"
source = "hello.c"
hint = "使用 printf,并注意末尾换行。"
[[exercises.cases]]
stdin = ""
stdout = """
Hello, World!
"""学生源码可以使用 #error TODO 标记尚未完成的位置:
#include <stdio.h>
int main(void) {
#error TODO
return 0;
}| 模式 | 配置 | 行为 |
|---|---|---|
return |
expected_return = 0 |
编译并检查程序退出码 |
stdout |
[[exercises.cases]] |
编译后逐个运行测试用例 |
compile |
无额外配置 | 只要求编译成功 |
make |
make_targets = ["test"] |
运行一个或多个 Make target |
make+stdout |
binary、make_targets、测试用例 |
使用 Makefile 构建后检查程序输出 |
stdout 和 make+stdout 用例支持以下字段:
[[exercises.cases]]
stdin = "3 4\n"
args = ["--verbose"]
exit_code = 0
stdout = "7\n"
timeout = 2.0
trim_trailing_ws = true还可以使用 stdout_contains、stdout_not_contains、stdout_regex 或 stdout_b64 描述不适合精确字符串比较的输出。
测试用例默认直接写在 exercises.toml 中。较长的用例可以放在题库根目录的 tests/<exercise-name>.toml:
[[cases]]
stdin = "3 4\n"
stdout = "7\n"如果外部测试文件存在,它会覆盖该题的内联用例。所有这些测试都是题库的一部分,学生可以查看。
教师可以在另一个目录维护参考答案,目录结构与题库中的 exercises/ 一致:
solutions/
├── 01_hello/hello.c
└── 02_sum/sum.c
通过环境变量指定该目录:
CLINGS_SOLUTIONS_DIR=/path/to/solutions clings check --solutions参考答案不应提交到面向学生的题库仓库。
git clone https://github.com/Lingrui-Studio/clings.git
cd clings
uv sync --extra dev
uv run pytest
uv run python -m clings --versionCLI 的运行时功能只使用 Python 标准库。pytest 和 pytest-cov 仅用于本仓库开发测试。
本项目采用 MIT License。
本项目基于 OpenCamp C Camp Team 的 clings 修改:
https://cnb.cool/opencamp/learning-nccl/clings
原项目与本项目均采用 MIT License。感谢原作者和贡献者的开源工作。