第一次个人编程作业

作业基本信息

这个作业属于哪个课程 班级
这个作业要求在哪里 个人项目作业
这个作业的目标 使用PSP表格、熟悉项目的整体流程

gitcode链接

链接

PSP表格

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 20 20
Estimate 估计这个任务需要多少时间 20 10
Development 开发 200 240
Analysis 需求分析 (包括学习新技术) 60 60
Design Spec 生成设计文档 10 10
Design Review 设计复审 10 15
Coding Standard 代码规范 (为目前的开发制定合适的规范) 10 10
Design 具体设计 20 20
Coding 具体编码 200 300
Code Review 代码复审 30 50
Test 测试(自我测试,修改代码,提交修改) 120 120
Reporting 报告 20 20
Test Repor 测试报告 20 20
Size Measurement 计算工作量 10 10
Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 20 20
---- 合计 770 925

计算模块接口的设计与实现过程

模块设计与代码组织

  • 文件读取模块:read_file 函数负责将文件内容读取为字符串。
// 读取文件内容并返回字符串
char* read_file(const char* file_path) {
    FILE* file = fopen(file_path, "r");
    if (!file) {
        perror("Failed to open file");
        exit(EXIT_FAILURE);
    }

    fseek(file, 0, SEEK_END);
    long length = ftell(file);
    fseek(file, 0, SEEK_SET);

    char* buffer = (char*)malloc(length + 1);
    if (!buffer) {
        perror("Failed to allocate memory");
        fclose(file);
        exit(EXIT_FAILURE);
    }

    fread(buffer, 1, length, file);
    buffer[length] = '\0';

    fclose(file);
    return buffer;
}
  • 分词模块:split_into_words 函数将文本按非字母字符分割为单词,并统一转为小写。
// 将字符串分割成数组
int split_into_words(const char* text, wchar_t words[MAX_WORDS][MAX_WORD_LENGTH]) {
    size_t len = mbstowcs(NULL, text, 0); // 计算宽字符长度
    wchar_t* wtext = (wchar_t*)malloc((len + 1) * sizeof(wchar_t));
    mbstowcs(wtext, text, len + 1); // 转换为宽字符

    int word_count = 0;
    for (int i = 0; wtext[i] != L'\0'; i++) {
        // 判断是否是中文字符(Unicode范围:0x4E00-0x9FFF)
        if (wtext[i] >= 0x4E00 && wtext[i] <= 0x9FFF) {
            words[word_count][0] = wtext[i];
            words[word_count][1] = L'\0';
            word_count++;
        }
    }
    free(wtext);
    return word_count;
}

  • 词频统计模块:calculate_word_frequency 函数统计每个单词的出现频率。
// 计算词频向量
void calculate_word_frequency(const wchar_t words[MAX_WORDS][MAX_WORD_LENGTH], int word_count, int* frequency) {
    for (int i = 0; i < word_count; i++) {
        frequency[i] = 1;
        for (int j = i + 1; j < word_count; j++) {
            if (wcscmp(words[i], words[j]) == 0) {
                frequency[i]++;
                frequency[j] = 0; // 标记为已处理
            }
        }
    }
}
  • 相似度计算模块:cosine_similarity 函数基于词频向量计算余弦相似度。
// 计算余弦相似度
double cosine_similarity(const int* freq1, const int* freq2, int size) {
    double dot_product = 0.0;
    double magnitude1 = 0.0;
    double magnitude2 = 0.0;

    for (int i = 0; i < size; i++) {
        dot_product += freq1[i] * freq2[i];
        magnitude1 += freq1[i] * freq1[i];
        magnitude2 += freq2[i] * freq2[i];
    }

    magnitude1 = sqrt(magnitude1);
    magnitude2 = sqrt(magnitude2);

    if (magnitude1 == 0 || magnitude2 == 0) {
        return 0.0;
    }

    return dot_product / (magnitude1 * magnitude2);
}

改进思路

  • 目前的分词逻辑是通过 mbstowcs 将多字节字符串转换为宽字符字符串,然后遍历宽字符字符串提取中文字符。这种方法宽字符转换开销大,mbstowcs 的转换过程需要额外的内存和时间。而且手动分词效率低,遍历字符串并逐个字符判断是否为中文字符,效率较低。改进可以使用更高效的分词库。
  • 词频计算逻辑是通过双重循环遍历单词数组,统计每个单词的频率。这种方法的时间复杂度为 O(n^2),效率较低。

计算模块部分单元测试

void test_read_file() {
    char* text = read_file("test.txt");
    assert(text != NULL);
    free(text);
}

void test_split_into_words() {
    wchar_t words[MAX_WORDS][MAX_WORD_LENGTH];
    int count = split_into_words("这是一个测试文本", words);
    assert(count == 5);
}

void test_calculate_word_frequency() {
    wchar_t words[MAX_WORDS][MAX_WORD_LENGTH] = {L"测试", L"文本", L"测试"};
    int frequency[MAX_WORDS] = {0};
    calculate_word_frequency(words, 3, frequency);
    assert(frequency[0] == 2);
    assert(frequency[1] == 1);
}

void test_cosine_similarity() {
    int freq1[] = {1, 2, 3};
    int freq2[] = {1, 2, 3};
    double similarity = cosine_similarity(freq1, freq2, 3);
    assert(similarity == 1.0);
}

int main() {
    test_read_file();
    test_split_into_words();
    test_calculate_word_frequency();
    test_cosine_similarity();
    printf("所有测试通过!\n");
    return 0;
}

总结

第一次完整的走了一遍项目的整体流程,啊好难啊,还是代码编写的问题,这次还学到一些工具的运用方法,好难啊。

posted @ 2025-03-19 23:30  3222010125  阅读(1)  评论(0)    收藏  举报