Opt*_*mus 35 c c++ if-statement
只是代替的:
if ( ch == 'A' || ch == 'B' || ch == 'C' || .....
Run Code Online (Sandbox Code Playgroud)
例如,要做到这样:
if ( ch == 'A', 'B', 'C', ...
Run Code Online (Sandbox Code Playgroud)
是否有更短的方式来总结条件?
usr*_*usr 85
strchr()
可用于查看字符是否在列表中.
const char* list = "ABCXZ";
if (strchr(list, ch)) {
// 'ch' is 'A', 'B', 'C', 'X', or 'Z'
}
Run Code Online (Sandbox Code Playgroud)
dbu*_*ush 39
在这种情况下,您可以使用switch
:
switch (ch) {
case 'A':
case 'B':
case 'C':
// do something
break;
case 'D':
case 'E':
case 'F':
// do something else
break;
...
}
Run Code Online (Sandbox Code Playgroud)
虽然这比使用稍微冗长strchr
,但它不涉及任何函数调用.它也适用于C和C++.
请注意,由于使用了逗号运算符,您建议的替代语法将无法正常工作:
if ( ch == 'A', 'B', 'C', 'D', 'E', 'F' )
Run Code Online (Sandbox Code Playgroud)
这首先比较ch
来'A'
,然后丢弃结果.然后'B'
评估并丢弃,然后'C'
等等,直到'F'
评估为止.然后'F'
成为条件的值.由于任何非零值在布尔上下文中计算为true(并且'F'
非零),因此上述表达式将始终为true.
Ric*_*ges 33
模板允许我们以这种方式表达自己:
if (range("A-F").contains(ch)) { ... }
Run Code Online (Sandbox Code Playgroud)
它需要一点管道,你可以把它放在一个图书馆.
这实际上编译得非常有效(至少在gcc和clang上).
#include <cstdint>
#include <tuple>
#include <utility>
#include <iostream>
namespace detail {
template<class T>
struct range
{
constexpr range(T first, T last)
: _begin(first), _end(last)
{}
constexpr T begin() const { return _begin; }
constexpr T end() const { return _end; }
template<class U>
constexpr bool contains(const U& u) const
{
return _begin <= u and u <= _end;
}
private:
T _begin;
T _end;
};
template<class...Ranges>
struct ranges
{
constexpr ranges(Ranges...ranges) : _ranges(std::make_tuple(ranges...)) {}
template<class U>
struct range_check
{
template<std::size_t I>
bool contains_impl(std::integral_constant<std::size_t, I>,
const U& u,
const std::tuple<Ranges...>& ranges) const
{
return std::get<I>(ranges).contains(u)
or contains_impl(std::integral_constant<std::size_t, I+1>(),u, ranges);
}
bool contains_impl(std::integral_constant<std::size_t, sizeof...(Ranges)>,
const U& u,
const std::tuple<Ranges...>& ranges) const
{
return false;
}
constexpr bool operator()(const U& u, std::tuple<Ranges...> const& ranges) const
{
return contains_impl(std::integral_constant<std::size_t, 0>(), u, ranges);
}
};
template<class U>
constexpr bool contains(const U& u) const
{
range_check<U> check {};
return check(u, _ranges);
}
std::tuple<Ranges...> _ranges;
};
}
template<class T>
constexpr auto range(T t) { return detail::range<T>(t, t); }
template<class T>
constexpr auto range(T from, T to) { return detail::range<T>(from, to); }
// this is the little trick which turns an ascii string into
// a range of characters at compile time. It's probably a bit naughty
// as I am not checking syntax. You could write "ApZ" and it would be
// interpreted as "A-Z".
constexpr auto range(const char (&s)[4])
{
return range(s[0], s[2]);
}
template<class...Rs>
constexpr auto ranges(Rs...rs)
{
return detail::ranges<Rs...>(rs...);
}
int main()
{
std::cout << range(1,7).contains(5) << std::endl;
std::cout << range("a-f").contains('b') << std::endl;
auto az = ranges(range('a'), range('z'));
std::cout << az.contains('a') << std::endl;
std::cout << az.contains('z') << std::endl;
std::cout << az.contains('p') << std::endl;
auto rs = ranges(range("a-f"), range("p-z"));
for (char ch = 'a' ; ch <= 'z' ; ++ch)
{
std::cout << ch << rs.contains(ch) << " ";
}
std::cout << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
预期产量:
1
1
1
1
0
a1 b1 c1 d1 e1 f1 g0 h0 i0 j0 k0 l0 m0 n0 o0 p1 q1 r1 s1 t1 u1 v1 w1 x1 y1 z1
Run Code Online (Sandbox Code Playgroud)
作为参考,这是我原来的答案:
template<class X, class Y>
bool in(X const& x, Y const& y)
{
return x == y;
}
template<class X, class Y, class...Rest>
bool in(X const& x, Y const& y, Rest const&...rest)
{
return in(x, y) or in(x, rest...);
}
int main()
{
int ch = 6;
std::cout << in(ch, 1,2,3,4,5,6,7) << std::endl;
std::string foo = "foo";
std::cout << in(foo, "bar", "foo", "baz") << std::endl;
std::cout << in(foo, "bar", "baz") << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
Xir*_*ema 14
如果你需要针对任意一组字符检查一个字符,你可以尝试写这个:
std::set<char> allowed_chars = {'A', 'B', 'C', 'D', 'E', 'G', 'Q', '7', 'z'};
if(allowed_chars.find(ch) != allowed_chars.end()) {
/*...*/
}
Run Code Online (Sandbox Code Playgroud)
Jas*_*n C 14
关于这个过度回答的问题的另一个答案,我只是为了完整性而包括在内.在这里的所有答案之间,你应该找到适合你的应用程序的东西.
所以另一个选项是查找表:
// On initialization:
bool isAcceptable[256] = { false };
isAcceptable[(unsigned char)'A'] = true;
isAcceptable[(unsigned char)'B'] = true;
isAcceptable[(unsigned char)'C'] = true;
// When you want to check:
char c = ...;
if (isAcceptable[(unsigned char)c]) {
// it's 'A', 'B', or 'C'.
}
Run Code Online (Sandbox Code Playgroud)
如果必须的话,嘲笑C风格的静态演员,但他们确实完成了工作.我想你可以使用一个std::vector<bool>
if阵列让你在晚上.您还可以使用其他类型bool
.但是你明白了.
显然,这变得很麻烦,例如wchar_t
,并且几乎不能使用多字节编码.但是对于你的char
例子,或任何适合查找表的东西,它都可以.因人而异.
jag*_*ire 12
与C strchr
答案类似,在C++中,您可以构造一个字符串并根据其内容检查字符:
#include <string>
...
std::string("ABCDEFGIKZ").find(c) != std::string::npos;
Run Code Online (Sandbox Code Playgroud)
上面的代码将返回true
了'F'
和'Z'
而false
为'z'
或'O'
.此代码不假定字符的连续表示.
这是有效的,因为它无法在字符串中找到字符时std::string::find
返回std::string::npos
.
编辑:
还有另一种C++方法,它不涉及动态分配,但确实涉及更长的代码:
#include <algorithm> // std::find
#include <iterator> // std::begin and std::end
...
char const chars[] = "ABCDEFGIKZ";
return std::find(std::begin(chars), std::end(chars), c) != std::end(chars);
Run Code Online (Sandbox Code Playgroud)
这与第一个代码片段的工作方式类似:std::find
搜索给定范围,如果找不到该项,则返回特定值.这里,所述特定值是范围的结束.
小智 6
一种选择是unordered_set
.将感兴趣的字符放入集合中.然后只需检查相关字符的计数:
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
unordered_set<char> characters;
characters.insert('A');
characters.insert('B');
characters.insert('C');
// ...
if (characters.count('A')) {
cout << "found" << endl;
} else {
cout << "not found" << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
您的问题有解决方案,不是语言,而是编码实践 - 重构.
我非常肯定读者会发现这个答案非常不正统,但是 - 重构可以并且经常被用来隐藏方法调用背后的混乱代码.该方法可以在以后清理,也可以保留原样.
您可以创建以下方法:
private bool characterIsValid(char ch) {
return (ch == 'A' || ch == 'B' || ch == 'C' || ..... );
}
Run Code Online (Sandbox Code Playgroud)
然后可以用以下简短形式调用此方法:
if (characterIsValid(ch)) ...
Run Code Online (Sandbox Code Playgroud)
在许多检查中重用该方法,只在任何地方返回一个布尔值.