第二次作业

这个作业属于哪个课程 https://edu.cnblogs.com/campus/zjlg/rjjc
这个作业的目标 实现一个命令行文本计数统计程序。能正确统计导入的纯英文txt文本中的字符数,单词数,句子数
姓名-学号 吴誉斐-2022329301102
Gitee地址 https://gitee.com/wnmdsqwnhkmc/second-assignment.git

注:本文并不包含主函数,完整代码请移步Gitee
路径:[项目>>ConsoleApplication1>>(无前缀)ConsoleApplication1>>ConsoleApplication1.cpp]

一、项目的简介及其相关的用法

(一)项目介绍

该项目旨在实现一个命令行文本计数统计程序。
基础功能:能正确统计导入的纯英文txt文本中的字符数,单词数,句子数。
拓展功能:能正确统计导入的txt文本中的代码行,空白行,注释行。
具体命令行界面要求举例:

命令模式: wc.exe + [参数] [文件名]

以下为示例:

  1. wc.exe -c file.txt 统计字符数
  2. wc.exe -w file.txt 统计单词数
  3. wc.exe -s file.txt 统计句子数
  4. wc.exe -code file.txt 统计代码行
  5. wc.exe -e file.txt 统计空白行
  6. wc.exe -n file.txt 统计注释行

其中,"wc"为应用程序的名称,"-c""-w""-s"等为命令参数,"file"为txt文件的名称。

(二)具体操作

  1. win+r,输入cmd
  2. 输入应用程序exe文件所在位置(本程序位于D盘的“测试”文件夹中,注意cd后需有空格)
  3. 输入示例命令"ConsoleApplication1.exe -c word.txt"。该处程序名为"ConsoleApplication1",txt文件名为word。

二、文件列表及其相关说明

(一)v0.1 空项目:该项目为C++读取文本文件的简单测试。

#include <iostream>  
#include <fstream>    // 包含用于文件输入输出的头文件  
#include <string>  

using namespace std;

int main() {
    string path = "./word.txt";

    // 直接在构造函数中打开文件  
    ifstream in_file(path);

    // 检查文件是否成功打开  
    if (in_file) {
        cout << "Open File Successfully" << endl;
        string line;
        // 逐行读取文件内容并打印到控制台  
        while (getline(in_file, line)) {
            cout << line << endl;
        }
    }
    else {
        // 使用cerr进行错误输出  
        cerr << "Cannot Open File: " << path << endl;
        return EXIT_FAILURE; // 直接返回失败状态  
    }

    return EXIT_SUCCESS; // 返回成功状态  
}

(二)v0.2 项目完成基础功能:该项目可实现对txt文件的读取操作,并对其中字符数,单词数,句子数进行统计。

  • 统计字符数
//在本项目中,字符数包括标点、空格、字母
long count(string file) {
    char c;
    long number = 0;
    ifstream infile(file);
    assert(infile.is_open());
    while (infile.get(c)) {
        number++;
    }

    infile.close();
    return number;
}
  • 统计单词数
long word(string file) {
    char c;
    long number = 0;
    bool inWord = false;
    ifstream infile(file);
    assert(infile.is_open());
    infile >> noskipws;
    while (infile.get(c)) {
        if (isalpha(c)) {
            if (!inWord) {
                inWord = true;
                number++;
            }
        }
        else {
            inWord = false;
        }
    }
    infile.close();
    return number;
}
  • 统计句子数
long sentence(string file) {
    char c;
    long number = 0;
    bool inSentence = false;
    ifstream infile(file);
    assert(infile.is_open());
    infile >> noskipws;
    while (infile.get(c)) {
        if (isalpha(c) || isdigit(c)) {
            if (!inSentence) {
                inSentence = true;
            }
        }
        else if (c == '.' || c == ';') {
            if (inSentence) {
                number++;
                inSentence = false;
            }
        }
        else {
            inSentence = false;
        }
    }
    // 判断最后一个字符是不是句子的一部分 
    if (inSentence) number++;
    infile.close();
    return number;
}

(三)v0.3 项目完成扩展功能:实现统计代码行、空行、注释行等操作。

  • 统计代码行
long cod(string file) {
    long number = 0;
    ifstream infile(file);
    assert(infile.is_open());
    string line;
    while (getline(infile, line)) {
        number++;
    }
    infile.close();
    return number;
}
  • 统计空行
long empty(string file) {
    long number = 0;
    ifstream infile(file);
    assert(infile.is_open());
    string line;
    while (getline(infile, line)) {
        if (line.empty()) {
            number++;
        }
    }
    infile.close();
    return number;
}
  • 统计注释行
long note(string file) {
    char c;
    long number = 0;
    bool inComment = false;
    ifstream infile(file);
    assert(infile.is_open());
    while (infile.get(c)) {
        if (c == '/') {
            char nextChar;
            infile.get(nextChar);
            if (nextChar == '/') {
                inComment = true;
                number++; // 用 '//' 判断一段注释行  
                break; // 只要检测到了,就可以停止这一行的检测 
            }
            else {
                infile.putback(nextChar);
            }
        }
        else if (c == '\n') {
            inComment = false;
        }
    }

    infile.clear(); // 清除 EOF flag  
    infile.seekg(0, ios::beg); 
    string line;
    while (getline(infile, line)) {
        if (line.find("//") != string::npos) {
            number++;
        }
    }
    infile.close();
    if (number > 0) number--;
    return number;
}

(四)单元测试及性能测试

  • 单元测试
void test_count() {
    ofstream file("file1.txt");
    file << "Hello, World!";
    file.close();
    assert(count("file1.txt") == 13);
}

void test_word() {
    ofstream file("file2.txt");
    file << "This is a test.";
    file.close();
    assert(word("file2.txt") == 4);
}

void test_sentence() {
    ofstream file("file2.txt");
    file << "This is a test. It works well;";
    file.close();
    assert(sentence("file2.txt") == 2);
}

void test_cod() {
    ofstream file("file3.txt");
    file << "int main() {\n";
    file << "  // this is a comment\n";
    file << "  return 0;\n";
    file << "}\n\n";
    file.close();

    assert(cod("file3.txt") == 5);
}

void test_empty() {
    ofstream file("file3.txt");
    file << "int main() {\n";
    file << "\n";
    file << "  return 0;\n";
    file << "}\n\n";
    file.close();
    assert(countEmpty("file3.txt") == 2);
}

void test_note() {
    ofstream file("file3.txt");
    file << "// comment 1\n";
    file << "int main() {\n";
    file << "  // comment 2\n";
    file << "  return 0;\n";
    file << "}\n";
    file.close();
    assert(note("file3.txt") == 2);
}

void run_tests() {
    test_count();
    test_word();
    test_sentence();
    test_cod();
    test_empty();
    test_note();
    cout << "所有单元测试通过!" << endl;
}

  • 性能测试
void performance_test() {
    ofstream file("large_file.txt");
    for (int i = 0; i < 100000; i++) {
        file << "This is line " << i << ". // Comment line\n";
        file << "int value" << i << " = " << i << ";\n";
        if (i % 10 == 0) {
            file << "\n";
        }
    }
    file.close();
    auto start = chrono::high_resolution_clock::now();
    cout << "字符数: " << count("large_file.txt") << endl;
    auto end = chrono::high_resolution_clock::now();
    cout << "字符统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";

    start = chrono::high_resolution_clock::now();
    cout << "单词数: " << word("large_file.txt") << endl;
    end = chrono::high_resolution_clock::now();
    cout << "单词统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";

    start = chrono::high_resolution_clock::now();
    cout << "句子数: " << sentence("large_file.txt") << endl;
    end = chrono::high_resolution_clock::now();
    cout << "句子统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";

    start = chrono::high_resolution_clock::now();
    cout << "代码行数: " << cod("large_file.txt") << endl;
    end = chrono::high_resolution_clock::now();
    cout << "代码统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";

    start = chrono::high_resolution_clock::now();
    cout << "空行数: " << countEmpty("large_file.txt") << endl;
    end = chrono::high_resolution_clock::now();
    cout << "空行统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";

    start = chrono::high_resolution_clock::now();
    cout << "注释行数: " << note("large_file.txt") << endl;
    end = chrono::high_resolution_clock::now();
    cout << "注释统计用时: "
        << chrono::duration_cast<chrono::milliseconds>(end - start).count() << " ms\n";
}

三、例程运行及其相关结果

(一)v0.1 空项目

(二)v0.2 项目完成基础功能

(三)v0.3 项目完成扩展功能

(四)单元测试与性能测试

  • CPU使用率

四、心得感悟

  • Git推送代码失败时,在Bash输入"git push -f origin master"

这次作业让我对C++编程语言及其相关拓展库有了深入的理解。在编写一个命令行文本计数统计程序的过程中,我掌握了处理文本文件的方法,并能够统计字符数、单词数、句子数,以及实现拓展功能。此外,我还了解了单元测试以及性能测试等相关知识,虽然不太会用,但也算拓宽了知识面,还从零学习使用Gitee,收获了很多。
PS:每次上传新代码,推送都会失败,然后库就清空了,然后readme也没了,然后gitee上显示的提交次数就很少。

posted @ 2024-10-27 14:38  Lemuria-mo  阅读(101)  评论(0编辑  收藏  举报