부호없는 루프 변수를 사용한 역 반복
동료들과 size_t의 사용에 대해 논의 해 왔습니다. 발생한 한 가지 문제는 루프 변수가 0에 도달 할 때까지 감소시키는 루프입니다.
다음 코드를 고려하십시오.
for (size_t i = n-1; i >= 0; --i) { ... }
이로 인해 부호없는 정수 랩 어라운드로 인해 무한 루프가 발생합니다. 이 경우 무엇을합니까? 위의 코드를 작성하는 것은 쉽지 않고 실수를했는지 깨닫지 못하는 것 같습니다.
우리 팀의 두 가지 제안은 다음 스타일 중 하나를 사용하는 것입니다.
for (size_t i = n-1; i != -1 ; --i) { ... }
for (size_t i = n; i-- > 0 ; ) { ... }
하지만 다른 옵션이 있는지 궁금합니다 ...
개인적으로 좋아하게되었습니다.
for (size_t i = n; i --> 0 ;)
-1
a) 재미 없음 , b) 상태 확인이 니모닉, c) 적절한 스마일리로 끝납니다.
부호없는 정수는 멋지게 래핑됩니다. 그들은 단지 산술 모듈로 2 N을 구현 합니다. 읽기 쉬운 관용구는 다음과 같습니다.
for (size_t i = n-1; i < n ; --i) { ... }
이것은 변수를 원하는 초기 값으로 설정하고 반복의 의미 (아래쪽)를 표시하며 처리하려는 값에 대한 조건을 정확하게 제공합니다.
- 루프를 알고리즘으로 대체하십시오.
- 정수 대신 역방향 반복기를 사용하십시오.
- (1) n은 카운트 다운하지만 루프 내부에서
i-1
대신i
.
실수로 이와 같은 루프를 작성하는 것이 걱정된다면 일부 컴파일러는 그런 것에 대해 경고합니다. 예를 들어 gcc에는 -Wtype-limits
옵션으로 활성화 된 경고가 있습니다 (에서도 활성화 됨 -Wextra
).
x.c:42: warning: comparison of unsigned expression >= 0 is always true
표준 라이브러리 컨테이너를 사용하고 있습니까? 만약 그렇다면reverse_iterator
vector<int> ivect;
// push, push, push...
vector<int>::reverse_iterator riter;
for(riter=riter.rbegin(); riter!=ivect.rend(); ++riter)
{
//...
}
원시 배열의 std::reverse_iterator
경우 포인터 가 반복 자라는 점에 대한 키를 사용할 수 있습니다 .
int i[] = {1, 2, 3, 4};
typedef std::reverse_iterator<const int*> irevit;
irevit iter(i+4);
irevit end(i);
for(; iter != end; ++iter) {
cout << *iter;
}
// Prints 4321
비 연속적인 객체 반복은 객체 포인터를 컨테이너 또는 배열에 저장하여 수행 할 수 있습니다.
struct Foo {
Foo(int i) I(i) { }
int I;
}
vector<Foo*> foos;
for(int i = 0; i < 10; ++i)
foos.push_back(new Foo(i));
typedef vector<Foo*>::const_reverse_iterator frevit;
frevit iter(foos.rbegin());
for(; iter != foos.rend(); ++iter) {
cout << (*iter)->I;
}
// Prints 9876543210
If you really want to use a naked size_t
then why use all of this implicitly confusing -1 trickery in the other answers? The max value of size_t
is explicitly available to use as your termination value:
int is[] = {1, 2, 3, 4};
int n = 3;
for (size_t i = n; i != std::numeric_limits<size_t>::max(); --i) {
cout << is[i] << endl;
}
// prints 4321
i != -1
relies on the -1
being silently cast to a size_t
, which seems fragile to me, so, of the alternatives you present, I'd definitely go with the post-decrement one. Another possibility (esp. if you don't actually need i
in the loop body but just need to iterate on an array in reverse order) would be to wrap the array in a std::
-like container and use an iterator on the wrapper, with the rbegin
and rend
methods. E.g., Boost.Array would support the latter choice.
Here is a pointer to a good discussion on this topic.
I would try:
for( size_t i = n; i != 0; i-- ) {
// do stuff with array[ i - 1 ]
}
size_t i = n-1;
do {
...
} while ( i-- != 0);
You may wrap that with a if (n > 0)
if necessary.
Yet another way (no signed/unsigned comparisons):
for (size_t i = n-1; i + 1 > 0; i--)
since
(i + 1 > 0) === (i > -1)
Another solution (available on POSIX compliant systems) that I found to be simple and effective is to replace size_t with ssize_t:
for (ssize_t i = n-1; i >= 0; --i) { ... }
On non-POSIX systems, ssize_t is not difficult to typedef: Alternative to ssize_t on POSIX-unconformant systems
ReferenceURL : https://stackoverflow.com/questions/3623263/reverse-iteration-with-an-unsigned-loop-variable
'IT Share you' 카테고리의 다른 글
HTML 특수 문자를 제거하는 방법? (0) | 2021.01.09 |
---|---|
실행중인 프로세스를 확인하는 Bash 스크립트 (0) | 2021.01.09 |
교리 2 OneToMany Cascade SET NULL (0) | 2021.01.09 |
jquery / javascript의 PHP 함수 number_format과 동일 (0) | 2021.01.09 |
SupportMapFragment를 두 번째로 여는 중 오류 발생 (0) | 2021.01.09 |