C ++의 "for… else"Python 루프에 해당하는 것이 있습니까?
파이썬에는 절 for
을 지정할 수 있는 흥미로운 문장이 있습니다 else
.
다음과 같은 구조에서 :
for i in foo:
if bar(i):
break
else:
baz()
이 else
절은 뒤에 실행 되지만가 정상적으로 종료되는 for
경우에만 실행 for
됩니다 (a가 break
아님).
C ++에 상응하는 것이 있는지 궁금합니다. 사용할 수 있습니까 for ... else
?
실제 논리를 표현하는 더 간단한 방법은 다음과 std::none_of
같습니다.
if (std::none_of(std::begin(foo), std::end(foo), bar))
baz();
C ++ 17에 대한 범위 제안이 수락되면 다음과 같이 단순화되기를 바랍니다.
if (std::none_of(foo, bar)) baz();
사용해 goto
도 괜찮다면 다음과 같이 할 수 있습니다. 이것은 추가 if
검사와 더 높은 범위의 변수 선언 에서 절약됩니다 .
for(int i = 0; i < foo; i++)
if(bar(i))
goto m_label;
baz();
m_label:
...
예 : 다음과 같은 방법으로 동일한 효과를 얻을 수 있습니다.
auto it = std::begin(foo);
for (; it != std::end(foo); ++it)
if(bar(*it))
break;
if(it == std::end(foo))
baz();
이것은 C ++의 대략적인 구현입니다.
bool other = true;
for (int i = 0; i > foo; i++) {
if (bar[i] == 7) {
other = false;
break;
}
} if(other)
baz();
이를 위해 람다 함수를 사용할 수 있습니다.
[&](){
for (auto i : foo) {
if (bar(i)) {
// early return, to skip the "else:" section.
return;
}
}
// foo is exhausted, with no item satisfying bar(). i.e., "else:"
baz();
}();
이것은 Python의 "for..else"와 똑같이 작동해야하며 다른 솔루션에 비해 몇 가지 장점이 있습니다.
- "for..else"의 진정한 드롭 인 대체품입니다. "for"섹션은 부작용이있을 수 있으며 (조건자가 인수를 수정해서는 안되는 none_of와 달리) 외부 범위에 액세스 할 수 있습니다.
- 특수 매크로를 정의하는 것보다 더 읽기 쉽습니다.
- 특별한 플래그 변수가 필요하지 않습니다.
하지만 ... 나는 투박한 플래그 변수를 사용합니다.
C / C ++ (플래그 변수를 포함하지 않음)에서 이것을 수행하는 우아한 방법을 알지 못합니다. 제안 된 다른 옵션은 그보다 훨씬 더 끔찍합니다 ...
실제 사용에 대해 @Kerrek SB에 대답하기 위해 코드에서 몇 가지를 찾았습니다 (간단한 스 니펫).
예 1 : 일반적인 찾기 / 실패
for item in elements:
if condition(item):
do_stuff(item)
break
else: #for else
raise Exception("No valid item in elements")
예 2 : 제한된 시도 횟수
for retrynum in range(max_retries):
try:
attempt_operation()
except SomeException:
continue
else:
break
else: #for else
raise Exception("Operation failed {} times".format(max_retries))
다음과 같은 것 :
auto it = foo.begin(), end = foo.end();
while ( it != end && ! bar( *it ) ) {
++ it;
}
if ( it != foo.end() ) {
baz();
}
트릭을 수행해야하며 구조화되지 않은 break
.
C ++에서만 가능할뿐만 아니라 C에서도 가능합니다. 코드를 이해하기 쉽게 만들기 위해 C ++를 고수하겠습니다.
for (i=foo.first(); i != NULL || (baz(),0); i = i.next())
{
if bar(i):
break;
}
코드 검토를 통해 그렇게 할 수 있을지 의심 스럽지만 효과가 있고 효율적입니다. 내 생각에는 다른 제안보다 더 명확합니다.
C ++에는 이러한 언어 구조가 없지만 전 처리기의 "마법"덕분에 직접 만들 수 있습니다. 예를 들어 다음과 같습니다 (C ++ 11).
#include <vector>
#include <iostream>
using namespace std;
#define FOR_EACH(e, c, b) auto e = c.begin(); for (; e != c.end(); ++e) {b} if (e == c.end()) {}
int main()
{
vector<int> v;
v.push_back(1);
v.push_back(2);
FOR_EACH(x, v, {
if (*x == 2) {
break;
}
cout << "x = " << *x << " ";
})
else {
cout << "else";
}
return 0;
}
출력해야합니다 x = 1 else
.
당신이 변경하는 경우 if (*x == 2) {
에 if (*x == 3) {
, 출력해야한다 x = 1 x = 2
.
현재 범위에 변수가 추가된다는 사실이 마음에 들지 않으면 약간 변경할 수 있습니다.
#define FOR_EACH(e, c, b, otherwise) {auto e = c.begin(); for (; e != c.end(); ++e) {b} if (e == c.end()) {} otherwise }
사용은 다음과 같습니다.
FOR_EACH(x, v, {
if (*x == 2) {
break;
}
cout << "x = " << *x << " ";
},
else {
cout << "else";
})
물론 완벽하지는 않지만주의해서 사용하면 타이핑을 줄일 수 있고 많이 사용하면 프로젝트의 "어휘"의 일부가 될 것입니다.
모든 문제에 가장 적합한 단일 솔루션은 없을 것입니다. 제 경우에는 플래그 변수와 지정자가있는 범위 기반 for
루프가 auto
가장 잘 작동했습니다. 다음은 문제의 코드에 해당하는 것입니다.
bool none = true;
for (auto i : foo) {
if (bar(i)) {
none = false;
break;
}
}
if (none) baz();
반복자를 사용 하는 것보다 타이핑이 적습니다 . 특히 for
루프를 사용하여 변수를 초기화하는 경우 부울 플래그 대신 사용할 수 있습니다.
auto
입력 덕분에 std::none_of
호출하는 대신 조건을 인라인하려는 bar()
경우 (그리고 C ++ 14를 사용하지 않는 경우) 보다 낫습니다 .
두 조건이 모두 발생하는 상황이 발생했습니다. 코드는 다음과 같습니다.
for (auto l1 : leaves) {
for (auto x : vertices) {
int l2 = -1, y;
for (auto e : support_edges[x]) {
if (e.first != l1 && e.second != l1 && e.second != x) {
std::tie(l2, y) = e;
break;
}
}
if (l2 == -1) continue;
// Do stuff using vertices l1, l2, x and y
}
}
No need for iterators here, because v
indicates whether break
occurred.
Using std::none_of
would require specifying the type of support_edges[x]
elements explicitly in arguments of a lambda expression.
Direct answer: no, you probably can't, or it is compiler-based, at best. BUT here's a hack of a macro that kind of works!
A few notes:
I usually program with Qt, so I'm used to having a foreach loop, and never have to deal with iterators directly.
I tested this with Qt's compiler (v 5.4.2) but it should work. This is gross for several reasons, but generally does what you'd want. I don't condone coding like this, but there's no reason it shouldn't work as long as you're careful with the syntax.
#include <iostream>
#include <vector>
#define for_else(x, y) __broke__ = false; for(x){y} if (__broke__) {}
#define __break__ __broke__ = true; break
bool __broke__; // A global... wah wah.
class Bacon {
public:
Bacon(bool eggs);
inline bool Eggs() {return eggs_;}
private:
bool eggs_;
};
Bacon::Bacon(bool eggs) {
eggs_ = eggs;
}
bool bar(Bacon *bacon) {
return bacon->Eggs();
}
void baz() {
std::cout << "called baz\n";
}
int main()
{
std::vector<Bacon *>bacons;
bacons.push_back(new Bacon(false));
bacons.push_back(new Bacon(false));
bacons.push_back(new Bacon(false));
for_else (uint i = 0; i < bacons.size(); i++,
std::cout << bacons.at(i)->Eggs();
if (bar(bacons.at(i))) {
__break__;
}
) else {
baz();
}
bacons.push_back(new Bacon(true));
bacons.push_back(new Bacon(false));
for_else (uint i = 0; i < bacons.size(); i++,
std::cout << bacons.at(i)->Eggs();
if (bar(bacons.at(i))) {
__break__;
}
) else {
baz();
}
return EXIT_SUCCESS;
}
You can use for-else almost like in Python by defining two macros:
#define BREAK {CONTINUETOELSE = false; break;}
#define FORWITHELSE(x, y) {bool CONTINUETOELSE = true; x if(!CONTINUETOELSE){} y}
Now you put the for
and the else
inside the FORWITHELSE
macro separated by a comma and use BREAK
instead of break
. Here is an example:
FORWITHELSE(
for(int i = 0; i < foo; i++){
if(bar(i)){
BREAK;
}
},
else{
baz();
}
)
There are two things you need to remember: to put a comma before the else
and to use BREAK
instead of break
.
I came here because I had the same question, in C though. The best thing I came out with is
bool notTerminated = true;
for (int i = 0; i < 50 || (notTerminated = false); i++)
if (bar(i))
break;
if (! notTerminated)
baz();
Explanation: the (notTerminated = false)
is an assignment that will always return the false value, it will never affect the condition and will be evaluated iif the condition if true.
참고URL : https://stackoverflow.com/questions/24693694/is-there-an-equivalent-to-the-for-else-python-loop-in-c
'development' 카테고리의 다른 글
Android SDK가 JDK 1.7에서 작동 할 수 있습니까? (0) | 2020.12.01 |
---|---|
MATLAB의 폴더에있는 파일을 반복 (0) | 2020.12.01 |
Azure SDK 2.5.1이 cloudService를 게시하지 못함 (0) | 2020.12.01 |
Visual Studio에서 메이크 파일을 사용하는 방법은 무엇입니까? (0) | 2020.12.01 |
git-diff에서 파일 제외 (0) | 2020.12.01 |