【问题标题】:function which takes a string as input and splits it into words. Punctuation characters should be ignored将字符串作为输入并将其拆分为单词的函数。标点符号应该被忽略
【发布时间】:2019-10-23 14:36:10
【问题描述】:

我写了一个功能,但弹出一个错误。我不知道如何解决它。 总的来说,我是否正确地执行了结束?

void Split(char* str) 
{
    const char* punctuation = "~`!@#$%^&*()-_+=,./?;:'";
    char* ch = strtok(str, punctuation);

    while (ch) 
    {              
        std::cout << ch << '\n';
        ch = strtok(0, punctuation);
    }
}

错误 - 严重性代码描述项目文件行抑制状态 错误 C4996 'strtok':此函数或变量可能不安全。考虑改用 strtok_s。要禁用弃用,请使用 _CRT_SECURE_NO_WARNINGS。详细信息请参见在线帮助。

【问题讨论】:

  • 您应该使用ispunct 函数而不是创建自己的字符串。然后,当您拥有它时,您可以使用搜索/替换功能,使用ispunct 作为当前字符是否为标点符号的指示符。

标签: c++


【解决方案1】:

您可以在文件顶部定义_CRT_SECURE_NO_WARNINGS,如下所示。

#define _CRT_SECURE_NO_WARNINGS

或者代替strtok,尝试使用strtok_s并查看this cppreference link

【讨论】:

  • 没有帮助((我添加了 - #define _CRT_SECURE_NO_WARNINGS #define __STDC_WANT_LIB_EXT1__1
【解决方案2】:

我更喜欢 C++11 中基于正则表达式的标记,而不是 C 函数 strtokstrtok_s

void split(const std::string& s)
{
   std::regex rgx("[~`!@#$%^&*()-_+=,./?;:']+");
   std::sregex_token_iterator iter(s.begin(), s.end(), rgx, -1);
   std::sregex_token_iterator end;
   for ( ; iter != end; ++iter)
      std::cout << *iter << std::endl;
}

IMO,这要好得多,因为它适用于 std::string insted of char 数组(C 字符串)。

一个简单的用例:

std::string s("some`string?to+-be;:'tokenized");
split(s);

Live demo here.


请注意,这将为子匹配创建std::string 对象,这可能会带来一些开销(尽管可能会通过短字符串优化来减少)。本题讨论如何将子匹配转为std::string_view 对象:Iterating regex submatches represented as std::basic_string_view

重写循环形式的解决方案可能如下所示:

for ( ; iter != end; ++iter)
{
   std::string_view sv(&*iter->first, iter->length());
   std::cout << sv << std::endl;
}

【讨论】:

    猜你喜欢
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2011-06-12
    • 2017-07-03
    相关资源
    最近更新 更多