如何正确使用这个函数的if语句?

How to correctly use the if statement for this function?

本文关键字:if 语句 函数 何正确      更新时间:2023-10-16

我似乎在程序的一个函数中的 if 语句有问题。

我希望代码行停止,直到显示正确的变量,同时输出错误消息。但是,无论输入了错误还是正确的变量,代码都会继续,并且错误消息也会随之显示。

这是带有 if 语句的代码部分

string get_class(){
string char_class;
cout<<"Choose A Character Class!"<<endl;    
cout<<"The Cleric, a holy disciple!   Select C."<<endl;
cout<<"The Fighter, an unstoppable warrior!  Select F."<<endl;
cout<<"The Paladin, a holy warrior!  Select P."<<endl;
cout<<"The Rogue, a sneaky thief!  Select R."<<endl;
cout<<"The Wizard, a wizened magician!  Select W."<<endl;
cin>>classSelection;
if(classSelection != "C"||"c"||"F"||"f"||"P"||"p"||"R"||"r"||"W"||"w")
cout<<"Please Enter Given Selections"<<endl;
return char_class; 
}

如果给出的程序不够,或者如果此片段中的所有内容看起来杂乱无章,我深表歉意。

让我们简化一下这个例子。您的代码不起作用的原因与此代码不起作用的原因相同:

int x = 2;
if(x == 1 || 2) { ... }

这是因为||运算符不会以这种方式连接。上面的例子计算x == 1(false)和用2或(||)的OR,如下所示:

if(false || 2) { ... } // after evaluating of x == 1

我们现在有false || 2.在C++中,任何非零数值的计算结果都是true,所以我们得到false || true,即true

但它似乎在这个例子中有效,对吧?

它只是看起来。将2替换为3,代码仍将被计算为true,即使x既不1也不3

如何解决问题?

在小组合的情况下,应该正确提供所有表达式:

if(x == 1 || x == 2) { ... }

而不是:

if(x == 1 || 2) { ... }

因此,在您的示例中,您将需要:

if(classSelection != "C" || classSelection != "c" || classSelection != "F" ||  ... )

但这仍然不能做你想要的。例如,您不想知道classSelection是否等于"C"或不等于"c"。你想知道它是否不等于"C"也不等于"c",所以你实际上想要:

if(classSelection != "C" && classSelection != "c" && classSelection != "F" &&  ... )

您的示例需要一些键入。另一种方法,效率稍低,但可以说更具可读性,是将所有可能的匹配项存储在数据结构中并使用标准算法,例如std::all_of

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
int main() {
std::vector<const char*> not_accepted= {
"C", "c", "F", "f", "P", "p", "R", "r", "W", "w"
};
std::string choice = "f"; // provided by user
bool valid = std::all_of(not_accepted.cbegin(), not_accepted.cend(),
[&](auto arg){
return choice != arg;
});
std::cout << "valid? - " << std::boolalpha << valid;
}

std::all_of取一个范围和一个谓词,如果所有元素都满足谓词,则返回true。在这里,范围是我们的not_accepted向量,我们的谓词表示为 lambda,它将向量的每个元素与我们的choice字符串进行比较。

为了优化,可以用std::setstd::unordered_set替换std::vector,并检查集合中是否存在元素。这将摆脱算法调用:

#include <iostream>
#include <unordered_set>
#include <string>
int main() {
std::unordered_set<const char*> not_accepted = {
"C", "c", "F", "f", "P", "p", "R", "r", "W", "w"
};
std::string choice = "f";
bool valid = not_accepted.find("f") == not_accepted.end();
std::cout << "valid? - " << std::boolalpha << valid;
}

我个人的最爱

while("CcFfPpRrWw"s.find(classSelection) == string::npos)
{
cout << "Please Enter Given Selections" << endl;
cin >> classSelection;
}

在你的原始代码中,你犯了一个菜鸟错误,即选择可能的候选人。这些将单独计算为 true,导致整个表达式始终计算为 true。

我的代码将所有选择放在一个临时字符串中,并在其中搜索输入的字符。 如果找不到字符串::npos,则返回它,从而触发 while 循环。