091. 编写代码实现简单的自然语言处理算法

在C语言中实现一个简单的自然语言处理(NLP)算法可以是一个很好的练习,帮助你理解文本处理的基本概念。这里我将展示一个简单的文本分词(Tokenization) 算法的实现。分词是自然语言处理中的一个基本步骤,目的是将文本分割成单词、短语或符号等有意义的单元。

简单的文本分词算法

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_TOKENS 100
#define MAX_TOKEN_LENGTH 50

// 判断是否是分隔符
int isDelimiter(char c) {
    return isspace(c) || ispunct(c);
}

// 分词函数
void tokenize(const char* text, char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH]) {
    int tokenCount = 0;
    int tokenLength = 0;
    int i = 0;

    while (text[i] != '\0' && tokenCount < MAX_TOKENS) {
        // 跳过分隔符
        while (isDelimiter(text[i])) {
            i++;
        }

        // 读取单词
        tokenLength = 0;
        while (!isDelimiter(text[i]) && text[i] != '\0') {
            if (tokenLength < MAX_TOKEN_LENGTH - 1) {
                tokens[tokenCount][tokenLength++] = text[i];
            }
            i++;
        }

        // 添加字符串结束符
        tokens[tokenCount][tokenLength] = '\0';

        // 如果单词不为空,则增加tokenCount
        if (tokenLength > 0) {
            tokenCount++;
        }
    }
}

int main() {
    char text[1000];
    char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH];

    printf("Enter text: ");
    fgets(text, sizeof(text), stdin);

    // 去掉换行符
    text[strcspn(text, "\n")] = '\0';

    // 分词
    tokenize(text, tokens);

    // 打印分词结果
    printf("Tokens:\n");
    for (int i = 0; i < MAX_TOKENS && tokens[i][0] != '\0'; i++) {
        printf("%s\n", tokens[i]);
    }

    return 0;
}

代码说明

输入文本

  • 使用 fgets 从用户输入中读取文本。

  • 去掉输入字符串末尾的换行符。

分隔符判断

  • 使用 isDelimiter 函数判断字符是否是分隔符(空格、标点符号等)。

分词逻辑

  • 遍历输入文本,跳过分隔符,读取单词。

  • 将单词存储到二维字符数组 tokens 中。

打印结果

  • 遍历 tokens 数组,打印所有分词结果。

示例运行

假设用户输入以下文本:Enter text: Hello, world! This is a simple NLP example.

程序输出:

Tokens:
Hello
world
This
is
a
simple
NLP
example

扩展功能

  1. 支持更多分隔符:可以扩展 isDelimiter 函数,支持更多类型的分隔符,例如特殊字符。
  2. 大小写转换:在分词过程中,可以将所有单词转换为小写,以便进行不区分大小写的处理。
  3. 停用词过滤:可以添加一个停用词列表,过滤掉常见的无意义单词(如“the”、“is”等)。
  4. 词干提取(Stemming):实现一个简单的词干提取算法,将单词还原到其基本形式。

大小写转换和停用词过滤

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define MAX_TOKENS 100
#define MAX_TOKEN_LENGTH 50
#define MAX_STOP_WORDS 10

char stopWords[MAX_STOP_WORDS][MAX_TOKEN_LENGTH] = {
    "the", "is", "a", "an", "and", "in", "on", "at", "to", "of"
};

// 判断是否是分隔符
int isDelimiter(char c) {
    return isspace(c) || ispunct(c);
}

// 判断是否是停用词
int isStopWord(const char* word) {
    for (int i = 0; i < MAX_STOP_WORDS; i++) {
        if (strcmp(word, stopWords[i]) == 0) {
            return 1;
        }
    }
    return 0;
}

// 分词函数
void tokenize(const char* text, char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH]) {
    int tokenCount = 0;
    int tokenLength = 0;
    int i = 0;

    while (text[i] != '\0' && tokenCount < MAX_TOKENS) {
        // 跳过分隔符
        while (isDelimiter(text[i])) {
            i++;
        }

        // 读取单词
        tokenLength = 0;
        while (!isDelimiter(text[i]) && text[i] != '\0') {
            if (tokenLength < MAX_TOKEN_LENGTH - 1) {
                tokens[tokenCount][tokenLength++] = tolower(text[i]); // 转换为小写
            }
            i++;
        }

        // 添加字符串结束符
        tokens[tokenCount][tokenLength] = '\0';

        // 如果单词不为空且不是停用词,则增加tokenCount
        if (tokenLength > 0 && !isStopWord(tokens[tokenCount])) {
            tokenCount++;
        }
    }
}

int main() {
    char text[1000];
    char tokens[MAX_TOKENS][MAX_TOKEN_LENGTH];

    printf("Enter text: ");
    fgets(text, sizeof(text), stdin);

    // 去掉换行符
    text[strcspn(text, "\n")] = '\0';

    // 分词
    tokenize(text, tokens);

    // 打印分词结果
    printf("Tokens:\n");
    for (int i = 0; i < MAX_TOKENS && tokens[i][0] != '\0'; i++) {
        printf("%s\n", tokens[i]);
    }

    return 0;
}

示例运行

假设用户输入以下文本:Enter text: The quick brown fox jumps over the lazy dog.

程序输出:

Tokens:
quick
brown
fox
jumps
over
lazy
dog

视频讲解

BiliBili: 视睿网络-哔哩哔哩视频 (bilibili.com)