C++中类似于Python的“if x in [string1, string2, …]”语句的等价写法是什么?

4
我的小项目是制作一个聊天机器人;我没有使用谷歌开源,也没有研究如何构建。我试图通过这个项目来检验自己对C++的理解程度:
我试图制作一个“盒子”,里面包含所有可能出现的“问题”,并判断是否存在于“盒子”中,如果存在就执行相应的代码。
在Python中,大致上是这样的:
Box = ["Yes", "YES", "yes", "yEs", "YeS", "yES"]

print "Will you be working today?"
response = raw_input("> ")
if response in Box:
    print "Very well, then how can I assist you?"

那么在C++中我该如何做呢?或者在C++中它被称为什么?数组?链表?向量?在C++中区分这些有点困惑。

5个回答

6

对于这个问题,我建议将响应转换为小写字母,然后进行直接比较:

#include <string>
#include <cctype>
#include <functional>
#include <algorithm>

// convert string to lowercase
std::string lower_case(std::string s)
{
    std::transform(s.begin(), s.end(), s.begin()
        , std::ptr_fun<int, int>(std::tolower));
    return s;
}

int main()
{
    std::string response;

    // ask question and get response

    // now you don't need to look at every combination
    if(lower_case(response) == "yes")
    {
        // positive response code
    }

    // etc...
}

1
即使在Python中,将字符串转换为小写然后进行比较也是更好的选择。 - phuclv
是的,我知道,只是想让它更清楚。XD真是个笨蛋!不管怎样,谢谢。 - Azhorabai
哇,你们很快回答了我的问题。包括你和其他所有人。谢谢!@Galik - Azhorabai

3
你可以像这样做,需要使用 <string><vector><algorithm>
vector<string> box = { "yes"...};
//get input
if(std::find(box.begin(), box.end(), search_str) != box.end()) {
    //found
}

3

如果您只是不区分大小写地处理输入,那么这可能会更简单且略微更具表现力。

std::string downcased(std::string s) {
  std::locale loc{"en_US.UTF-8"};
  std::transform(begin(s), end(s), begin(s), [&](auto const& c) {
    return std::tolower(c, loc);
  });
  return s;
}

那么你需要执行以下操作:
if(downcased(input_string) == "yes") ...

并且没有要处理的“框”。

如果您已安装Boost,则可以不使用downcased()函数:

if(boost::algorithm::to_lower_copy(input_string) == "yes") ...

话虽如此,C++确实拥有C的原始数组。它们与Python的列表在使用上类似,但它们是静态的,意味着它们不会改变,并且它们不会将其大小作为数据存储在某个地方。C++还在标准库中提供了std::vector<>。这是一个表达动态数组的模板类,可以自动更改其大小。这样做通常会带来算法,例如std::find()。例如:

std::vector<std::string> const ys = {"yes", "yEs", };  // &c
if(std::find(begin(ys), end(ys), "yeS") != end(ys))
  ...

2

将输入转换为小写并只测试是否等于“yes”是最简单的解决方案,但可以使用std::set来处理更一般的情况。

集合是一种有序结构,用于高速,“X是否在这里?”查找。它类似于其他人建议的std::vector,但向量需要进行线性搜索。

#include <iostream>
#include <set>

int main()
{

    std::string input;

    std::cin >> input;

    std::set<std::string> box{"Yes", "YES", "yes", "yEs", "YeS", "yES"};

    if (box.find(input) != box.end())
    {
        std::cout << "Very well, then how can I assist you?" << std::endl;
    }
    return 0;

}

1
总的来说,在C++中,您可以预期与Python相比,使用数据结构的体验会有很大不同。在Python中,list类是大多数容器需求的首选选择,而在C++中有几种容器数据结构可供选择,包括C风格数组、std::arraystd::liststd::vector。对于普通列表,std::vector往往是首选选项。

尽管如此,如果您只是想要重复测试集合中的字符串成员身份,则应使用set数据结构,而不是在列表上进行线性搜索。 C++11中等效于Python的set类的是std::unordered_set(它们都是实现为哈希表)。

#include <iostream>
#include <string>
#include <unordered_set>

int main() {
  std::unordered_set<std::string> box = {"Yes", "YES", "yes"};
  std::string input;
  std::getline(std::cin, input);
  if(box.count(input)) {
    std::cout << "Very well, then how can I assist you?\n";
  }
}

你的建议并不适用于所有情况:对于小集合来说,列表的线性扫描可能是最快的。 - Marcin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接