第二次作业:C++ 命令行文本计数统计程序

项目 链接或说明
所属课程 26软件技术基础
作业要求 第二次作业
码云仓库 https://gitee.com/Gggffxu/second-assignment
作业目标 实现英文文本计数,使用 Git 记录版本,完成单元测试和 IDE 性能分析
AI 使用情况 本项目的代码、测试、说明及本篇博客由 AI 辅助生成,详见文末提示词记录

一、项目简介

本项目使用 C++17 实现命令行文本计数工具 wc.exe,可以读取 ASCII 纯英文 TXT 文件,统计字符数、单词数和句子数。在基础功能之外,还支持 C/C++ 风格代码行、空行和注释行统计。

程序将文件读取、参数处理和计数逻辑分开:main.cpp 处理命令行与文件输入,counter.cpp 实现计数,tests.cpp 对核心函数进行测试。这样可以直接测试计数逻辑,不必为每个用例都启动一次命令行程序。

二、功能与命令接口

命令格式为:

wc.exe [参数] [文件名]
参数 功能 示例
-c 统计字符数 wc.exe -c sample.txt
-w 统计单词数 wc.exe -w sample.txt
-s 统计句子数 wc.exe -s sample.txt
-l 统计代码行 wc.exe -l counter.cpp
-b 统计空行 wc.exe -b counter.cpp
-n 统计纯注释行 wc.exe -n counter.cpp
-a 输出全部统计项 wc.exe -a sample.txt
--help 查看帮助 wc.exe --help

参数可以组合,例如 wc.exe -c -w -s sample.txt。文件名放在最后,路径中含有空格时需要加双引号。退出码为 0 表示成功,1 表示文件或编码错误,2 表示参数错误。

统计规则

为了便于实现和验证,本项目明确采用以下规则:

  • 字符数:包含英文字母、数字、空格、标点、制表符和换行字节。ASCII 文本中一个字节计一个字符,Windows 的 CRLF 换行计两个字符。
  • 单词数:连续英文字母计一个单词,字母之间的撇号属于单词的一部分,因此 Don't 计一个单词。连字符分隔单词,例如 well-known 计两个;纯数字不计单词。
  • 句子数:连续出现的 .?! 终止标点计一次,例如 ... 和 ?! 各计一次。没有终止标点的片段不计句子。本项目没有实现缩写和小数等语义识别。
  • 行分类:纯空白行计空行,包含代码的行计代码行,其余纯注释行计注释行。一行同时包含代码和注释时计代码行,三类互斥。

扩展功能可以识别 // 和跨行 /* */ 注释,并忽略普通字符串及字符字面量里的注释符号。空文件计零行,文件末尾的换行不额外增加空行,块注释内部的纯空白行仍计空行。

三、项目文件说明

文件或目录 说明
main.cpp 命令行参数校验、读取文件、输出结果
counter.h 定义统计结果结构及计数函数接口
counter.cpp 字符、单词、句子和行分类算法
tests.cpp 25 个核心函数单元测试
test_cli.ps1 8 个命令行集成测试
build.ps1 编译程序并执行测试
sample.txt 不含末尾换行的 Hello world! 示例
benchmark.cpp 性能基准,支持指定重复次数
profile.ps1 编译采样程序、收集数据和生成报告
word-counter.cbp Code::Blocks 性能分析工程
evidence/ 各版本日志、截图及原始采样证据
README.MD 项目介绍、用法、文件说明和运行结果
PERFORMANCE.md IDE 性能分析方法、结果与局限
AI_PROMPTS.md 本次项目的用户提示词记录

四、编译与运行结果

在 Windows 中准备好 MinGW-w64,并将其 bin 目录加入当前终端的 PATH。进入项目目录后,可以执行:

powershell -NoProfile -ExecutionPolicy Bypass -File .\build.ps1

也可以手动编译和运行:

g++ -std=c++17 -O2 -Wall -Wextra main.cpp counter.cpp -o wc.exe
.\wc.exe -c -w -s sample.txt
.\wc.exe -a sample.txt

sample.txt 的内容是 Hello world!,不含末尾换行。执行全部统计后得到:

characters: 12
words: 2
sentences: 1
code_lines: 1
blank_lines: 0
comment_lines: 0

这里的 code_lines: 1 表示该行既非空白行,也非纯注释行;行分类功能是对输入的文本进行词法分类,并不会判断一行是否真的是可以编译的 C++ 代码。

五、Git 版本迭代

项目通过多次真实提交记录迭代过程,保留了作业要求的三个标签。

版本 提交号 实现内容
v0.1 6c89862 初始化空项目,未跟踪源文件
v0.2 688ca60 完成基础计数、命令行输入和 10 个基本单元测试
v0.3 a3ee4ac 增加三种行数统计,扩展为 25 个单元测试和 8 个命令行测试

后续提交补充了截图、提示词记录与 IDE 性能分析,没有移动或改写上述标签。可在仓库中执行以下命令查看:

git log --oneline --decorate
git tag

以下版本截图是实际运行日志在记事本中的显示截图,原始文字日志也在仓库中保留,便于核对;它们不是终端现场截图。v0.2 的运行结果来自该标签源码重新编译后的程序。

v0.1:空项目验证。

v0.1 空项目验证

v0.2:基础计数与基本测试。

v0.2 基础功能与测试

v0.3:扩展统计、测试及提交记录。

v0.3 扩展功能与全部测试

六、单元测试与命令行测试

核心函数测试使用独立的 tests.exe,通过比较实际统计值和期望值验证结果;不一致时抛出异常并让测试失败。命令行测试由 test_cli.ps1 调用程序,检查输出和退出码。

类别 代表用例 检查内容
空输入 空字符串、空文件 各项计数为零
基础英文 Hello world! 字符 12、单词 2、句子 1
句末标点 One. Two? Three! 三个句子
撇号与连续标点 Don't stop... Really?! 三个单词、两个句子
边界字符 空白、制表符、CRLF、纯数字 空白与换行按既定规则计数,数字不计单词
单词边界 well-known、连续撇号 验证分词边界
较长输入 100000 个连续字母 字符数 100000、单词数 1
行分类 行注释、块注释、代码和注释混合 验证三类行数互斥
字面量 字符串或字符中的注释符号 避免误判为注释
错误输入 未知参数、缺少参数、文件不存在、非 ASCII 文件 检查错误处理与退出码

实际运行结果为:

PASS: 25 unit cases
PASS: 8 CLI cases

总计 33 项测试通过。这些用例覆盖了当前实现的规则,但不意味着程序实现了完整的英文语法分析或 C++ 语法分析。

七、IDE 附带工具的性能分析

本项目使用 Code::Blocks 25.03 官方发行版附带的 Code Profiler。它是 GNU gprof 的图形界面,可在 IDE 的 Plugins → Code profiler 中打开。官方用户手册的 Code profiler 一节介绍了该工具。

测试方法

基准程序先将一行英文文本重复 200000 次,构造 4600000 字节的输入。随后对同一段内存调用 count_text 500 次,累计统计返回值作为校验。

采样构建和数据收集命令为:

powershell -NoProfile -ExecutionPolicy Bypass -File .\profile.ps1 -Iterations 500

采样完成后,在 Code::Blocks 中打开 word-counter.cbp,选择 Profile 目标,执行 Plugins → Code profiler,查看 Flat Profile,再通过 Export to File 导出报告。分析针对的是内存中的计数函数,不包括读取 TXT 文件和命令行启动的时间。

环境与结果

测试环境为 Windows 11 64 位,Intel Core i5-11400H,6 核 12 线程;工具链为 GCC 12.2.0 和 GNU gprof 2.39,采用 -O2 优化及 -pg 采样构建。

测量项目 本次结果
每轮输入大小 4600000 字节
重复次数 500
累计处理字节数 2300000000
墙钟总耗时 8461.41 ms
平均每轮墙钟耗时 16.92282 ms
累计返回值校验 2800000000
count_text 调用次数 500
count_text 自身采样时间 7.16 s
count_text 自身采样时间占比 95.47%

Code::Blocks Code Profiler 实际分析结果

主要热点位于 count_text,与程序逐字符扫描并完成行分类的设计一致。另有少量采样时间位于字符串查找和 memchr。

程序计数的时间复杂度为 O(N)。命令行程序当前一次性读入文件,输入存储空间为 O(N)。本轮采样复用内存,不能据此推断磁盘读取速度或峰值内存。

-pg 插桩存在额外开销,采样时间和墙钟时间的统计口径也不同,因此本次结果不应直接作为普通发布版的端到端性能。报告没有声称经过优化后取得了性能提升,也没有用单轮数据推断统计置信区间。

完整证据可在仓库的 PERFORMANCE.md 和 evidence/performance 中查看,其中包含 IDE 原生导出报告、截图、原始 gmon.out 及匹配的可执行文件压缩包。

八、当前限制与可改进方向

本项目采用明确的 ASCII 和标点规则,没有实现英文缩写、缩写句点与小数的语义识别。注释统计支持常见 C/C++ 风格,但不支持 C++ 原始字符串、预处理行拼接或嵌套注释。

后续可以将整文件读取改为分块读取,在保留跨块单词、句子和注释状态的同时减少内存占用;也可以补充更接近真实英文文档和真实源码的测试集。若开展性能优化,应在相同输入、编译配置和机器负载下进行多轮对照测试。

九、AI 使用说明与提示词记录

本项目全程使用 AI 协助生成代码、测试、文档和本篇博客,并通过工具在本机完成编译、测试及性能采样;码云和课程平台的登录验证由用户在登录窗口中完成。

按作业要求,本次相关用户提示词已整理到 AI_PROMPTS.md,包括原始作业要求、补充指令和后续操作请求。文件不包含密码或私人令牌,原始对话保留在本次聊天中。

最终项目仓库地址:https://gitee.com/Gggffxu/second-assignment


原文地址: https://www.cveoy.top/t/topic/qHPT 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录