c++ - 使用 C/C++ 从已解析的文本中解析名词短语

标签 c++ c parsing text

我想从已解析的文本中解析名词短语(NN、NNP、NNS、NNPS)。例如:

Input sentence -
John/NNP
works/VBZ
in/IN
oil/NN
industry/NN
./.
Output: John Oil Industry

我对逻辑感到困惑,因为我需要搜索字符串,例如 /NN/NNP/NNS/NNPS 并打印它之前的前一个单词。 使用 C 或 C++ 解析名词短语的逻辑是什么?

我自己的尝试如下:

char* SplitString(char* str, char sep 
{
    return str;
}
main()
{
    char* input = "John/NNP works/VBZ in/IN oil/NN industry/NN ./.";
    char *output, *temp;
    char * field;
    char sep = '/NNP';
    int cnt = 1;
    output = SplitString(input, sep);

    field = output;
    for(temp = field; *temp; ++temp){ 
       if (*temp == sep){
          printf(" %.*s\n", temp-field, field);
          field = temp+1;
       }
    }
    printf("%.*s\n", temp-field, field);
}

我的修改如下:

#include <regex>
#include <iostream>

int main()
{
    const std::string s = "John/NNP works/VBZ in/IN oil/NNS industry/NNPS ./.";
    std::regex rgx("(\\w+)\/NN[P-S]{0,2}");
    std::smatch match;

    if (std::regex_search(s.begin(), s.end(), match, rgx))
        std::cout << " " << match[1] << '\n';
}

我得到的输出只是“John”。其他/NNS 标签不会出现。

我的第二种方法:

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

char** str_split(char* a_str, const char a_delim)
{
    char** result = 0;
    size_t count = 0;
    char* tmp = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}

int main()
{
    char text[] = "John/NNP works/VBZ in/IN oil/NN industry/NN ./.";
    char** tokens;

    //printf("INPUT SENTENCE=[%s]\n\n", text);

    tokens = str_split(text, '');

    if (tokens)
    {
        int i;
        for (i = 0; *(tokens + i); i++)
        {
            printf("[%s]\n", *(tokens + i));
            free(*(tokens + i));
        }
        printf("\n");
        free(tokens);
    }

    return 0;
}

输出是:

[John/NNP]
[works/VBZ]
[in/IN]
[oil/NN]
[industry/NN]
[./.]

我只想要 /NNP/NN 解析数据,即 Johnoilindustry 。如何得到这个?正则表达式有帮助吗?如何在 C 中像 C++ 一样使用正则表达式?

最佳答案

如果一切都与打印有关,请尝试这种方法。它使用 regular expression在搜索函数中查找是否存在模式 \/NN[A-Z]{0,3} 即/NN 后跟 0 到 3 个大写字母并捕获 () \\w+ 之前的单词。

虽然这是未经测试的:

#include <regex>
#include <iostream>

int main()
{
    const std::string s = "John/NNP works/VBZ in/IN oil/NN industry/NN ./.";
    std::regex rgx("(\\w+)\/NN[A-Z]{0,3}");
    std::smatch match;

    while (std::regex_search(s, match, rgx))
        std::cout << "match: " << match[1] << '\n';
}

关于c++ - 使用 C/C++ 从已解析的文本中解析名词短语,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33560880/

相关文章:

c++ - 调用非模板类 C++ 的模板函数时出错

c - malloc 的 K&R C 示例 - moreroce 指针

c - 如何让编译器选择标志更新 ARM 指令?

spring - JsonParser 已弃用

c# - 是否有与 boost::interprocess::basic_string 等效的 C#?

c++ - 如何为 libsvm 创建训练数据(作为 svm_node 结构)

php - 用增量值替换字符串

javascript - 整数被错误地解析为字符串

c++ - 此套接字选择代码有什么问题?

c - 石头剪刀布的随机数