반복기를 사용하여 벡터를 탐색하는 방법은 무엇입니까? (C ++)


105

목표는 [] 연산자 나 "at"메서드 대신 문자열 벡터의 "n 번째"요소에 액세스하는 것입니다. 내가 이해하는 바에 따르면 반복기를 컨테이너를 탐색하는 데 사용할 수 있지만 이전에는 반복기를 사용한 적이 없으며 읽고있는 내용이 혼란 스럽습니다.

누구든지 이것을 달성하는 방법에 대한 정보를 줄 수 있다면 감사하겠습니다. 감사합니다.


벡터는 C ++의 STL에만 국한되지 않습니까? 나는 관계없이 편집합니다
케빈

kevin : 벡터는 모든 언어, 특히 Mathematica 또는 Matlab과 같은 수학 관련 언어에서 사용할 수있는 일반적인 용어입니다.
Gabe

@michael, 그래 haha ​​gabe의 의견 후에 편집했습니다.
케빈

답변:


112

첫 번째 요소와 마지막 요소를 각각 참조하는 반복기를 반환하는 클래스 의 beginend메서드를 사용해야 vector합니다.

using namespace std;  

vector<string> myvector;  // a vector of stings.


// push some strings in the vector.
myvector.push_back("a");
myvector.push_back("b");
myvector.push_back("c");
myvector.push_back("d");


vector<string>::iterator it;  // declare an iterator to a vector of strings
int n = 3;  // nth element to be found.
int i = 0;  // counter.

// now start at from the beginning
// and keep iterating over the element till you find
// nth element...or reach the end of vector.
for(it = myvector.begin(); it != myvector.end(); it++,i++ )    {
    // found nth element..print and break.
    if(i == n) {
        cout<< *it << endl;  // prints d.
        break;
    }
}

// other easier ways of doing the same.
// using operator[]
cout<<myvector[n]<<endl;  // prints d.

// using the at method
cout << myvector.at(n) << endl;  // prints d.

5
이것은 std::vector랜덤 액세스 반복자가 있다는 사실을 놓친다 .
sbi

24
반복기 유형이 임의 액세스인지 여부에 관계없이 반복기를 n 칸 앞으로 이동하는 "가장 좋은"방법은 자체 루프를 작성하는 것이 아니라을 호출하는 것 std::advance(it, n)입니다. 원하는 것을 정확히 수행하도록 정의되어 it + n있으며 반복자가 임의 액세스로 태그가 지정되면 자동으로 사용하고 필요한 경우 루프를 수행합니다.
Steve Jessop

61

일반적으로 반복기는 선형 방식으로 컨테이너의 요소에 액세스하는 데 사용됩니다. 그러나 "무작위 액세스 반복자"를 사용하면 다음과 같은 방식으로 모든 요소에 액세스 할 수 있습니다.operator[] .

벡터의 임의 요소에 액세스 하려면 vec다음을 사용할 수 있습니다.

vec.begin()                  // 1st
vec.begin()+1                // 2nd
// ...
vec.begin()+(i-1)            // ith
// ...
vec.begin()+(vec.size()-1)   // last

다음은 일반적인 액세스 패턴 의 예입니다 (이전 버전의 C ++).

int sum = 0;
using Iter = std::vector<int>::const_iterator;
for (Iter it = vec.begin(); it!=vec.end(); ++it) {
    sum += *it;
}

반복기 사용의 장점은 다른 컨테이너에 동일한 패턴을 적용 할 수 있다는 것입니다 .

sum = 0;
for (Iter it = lst.begin(); it!=lst.end(); ++it) {
    sum += *it;
}

이러한 이유로 컨테이너 유형에 관계없이 동일하게 작동하는 템플릿 코드를 만드는 것은 정말 쉽습니다. . 반복자의 또 다른 장점은 데이터가 메모리에 상주한다고 가정하지 않는다는 것입니다. 예를 들어, 입력 스트림에서 데이터를 읽을 수있는 순방향 반복기를 만들거나 단순히 즉석에서 데이터를 생성하는 (예 : 범위 또는 난수 생성기) 만들 수 있습니다.

std::for_each및 람다를 사용하는 또 다른 옵션 :

sum = 0;
std::for_each(vec.begin(), vec.end(), [&sum](int i) { sum += i; });

C ++ 11부터는 auto이전에 본 것처럼 (또는 훨씬 더 복잡한) 반복자의 매우 길고 복잡한 유형 이름을 지정하지 않도록 사용할 수 있습니다 .

sum = 0;
for (auto it = vec.begin(); it!=vec.end(); ++it) {
    sum += *it;
}

또한 더 간단한 for-each 변형이 있습니다.

sum = 0;
for (auto value : vec) {
    sum += value;
}

마지막으로 std::accumulate정수 또는 부동 소수점 숫자를 추가 할 때주의해야 할 부분도 있습니다.


53

C ++-11에서는 다음을 수행 할 수 있습니다.

std::vector<int> v = {0, 1, 2, 3, 4, 5};
for (auto i : v)
{
   // access by value, the type of i is int
   std::cout << i << ' ';
}
std::cout << '\n';

변형은 여기를 참조하십시오 : https://en.cppreference.com/w/cpp/language/range-for


4
왜 좋아요가 0인가요?! <3
jperl

3
@jperl 8 년 늦게 게시 됨. 충분한
찬성 투표

@jperl, 대답은 주제에서 벗어났습니다. 이 루프 기능은 좋지만 OP의 질문 인 n 번째 요소에있을 때 알 수는 없습니다. 또한, 이와 같이 O (n) 시간 복잡성이 필요한 모든 답변은 매우 나쁩니다. 벡터의 n 번째 요소에 액세스하는 것은 항상 O (1)이어야합니다.
Elliott

@lashgar 배열로 시도했지만 실패했습니다. 어레이에서 작동합니까?
era s'q

@ eras'q, 7.5.0Ubuntu 18.04 에서 gcc로 시도 했으며 동일한 방식으로 배열에서 작동합니다.
lashgar

17

Vector의 반복기는 랜덤 액세스 반복기이므로 일반 포인터처럼 보이고 느껴집니다.

컨테이너의 begin()메서드 에서 반환 된 반복기에 n을 추가하여 n 번째 요소에 액세스 하거나 operator를 사용할 수 있습니다 [].

std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();

int sixth = *(it + 5);
int third = *(2 + it);
int second = it[1];

또는 모든 종류의 반복자와 함께 작동 하는 고급 기능을 사용할 수 있습니다 . (비 랜덤 액세스 반복기를 사용하여 "무작위 액세스"를 수행 할 것인지 여부를 고려해야합니다. 비용이 많이들 수 있기 때문입니다.)

std::vector<int> vec(10);
std::vector<int>::iterator it = vec.begin();

std::advance(it, 5);
int sixth = *it;

1
advance랜덤 액세스 반복자 또는 알 수없는 범주의 반복자에도 사용할 수 있습니다 .이 경우 일정한 시간에 작동하도록 보장되기 때문입니다. 이것이 사용자 정의 반복기가 올바르게 태그되어야하는 이유입니다.
Steve Jessop

사실,하지만 advance랜덤 액세스 반복자를 다루는 것을 안다면 (out 매개 변수 사용으로 인해) 사용하기가 정말 짜증납니다. 단지 일반적인 코드에서 추천 할 것, 그리고 (많이 사용하지 않을 경우 알고리즘이 잘 아닌 임의 접근 반복자를 지원하지 않는 경우, 그래서 수 - 예를 들어, std::sort 를 정렬 std::list하지만 그것이 엄청나게 비효율적하지 않기 때문에 ).
UncleBens 2010 년

물론 고전적인 예는 알고리즘에 실제로 InputIterator 만 필요한 경우이지만 어떤 이유로 든 간혹 건너 뛰기 때문에 반복기에 임의 액세스 권한이있는 경우 더 효율적 이길 원합니다. 을 사용하여 알고리즘을 임의 액세스로 제한하는 것은 가치가 없습니다 operator+. 그러나 질문은 명시 적으로 벡터에 관한 것이기 때문에 답변의 첫 번째 부분에는 잘못된 것이 없습니다. 두 번째 부분은 "원한다고해도 랜덤 액세스 반복기와 함께 advance를 사용할 수 없다"는 것을 advance전에 본 적이없는 사람에게 암시 할 수 있다고 생각했습니다 .
Steve Jessop

좋아, 그 비트를 바꾸고 벡터로 예제를 주었다.
UncleBens 2010 년

둘째 줄은 Vector소문자되어야
레이 양

0

다음은 두 반복자를 증가시킬 필요가없는 루프 내에서 사용하여 의 ith인덱스 에 액세스하는 예입니다 .std::vectorstd::iterator

std::vector<std::string> strs = {"sigma" "alpha", "beta", "rho", "nova"};
int nth = 2;
std::vector<std::string>::iterator it;
for(it = strs.begin(); it != strs.end(); it++) {
    int ith = it - strs.begin();
    if(ith == nth) {
        printf("Iterator within  a for-loop: strs[%d] = %s\n", ith, (*it).c_str());
    }
}

for 루프없이

it = strs.begin() + nth;
printf("Iterator without a for-loop: strs[%d] = %s\n", nth, (*it).c_str());

및 사용 at방법 :

printf("Using at position: strs[%d] = %s\n", nth, strs.at(nth).c_str());
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.