2013-06-19 31 views
9

Để tìm kiếm lần xuất hiện đầu tiên của một phần tử trong C-Array với các phần tử POD, một cách dễ dàng có thể thực hiện điều này với std::find_if(begin, end, findit). Nhưng tôi cần sự xuất hiện cuối cùng. This answer cho tôi ý tưởng rằng điều này có thể được thực hiện với std::reverse_iterator. Vì vậy tôi đã cố gắng:Làm thế nào để bạn sử dụng find_if cùng với reverse_iterator trên một mảng kiểu C?

std::find_if(std::reverse_iterator<podtype*>(end), 
      std::reverse_iterator<podtype*>(begin), 
      findit); 

này đã cho tôi lỗi:

cannot convert 'std::reverse_iterator< xyz* > ' to 'xyz*' in assignment

Bạn có một ý tưởng làm thế nào để làm điều đó theo cách này hoặc bạn có biết một giải pháp tốt hơn?

Đây là mã:

#include <iostream> 
#include <iterator> 
#include <algorithm> 

struct xyz { 
    int a; 
    int b; 
}; 

bool findit(const xyz& a) { 
    return (a.a == 2 && a.b == 3); 
} 

int main() { 
    xyz begin[] = { {1, 2}, {2, 3}, {2, 3}, {3, 5} }; 
    xyz* end = begin + 4; 

    // Forward find 
    xyz* found = std::find_if(begin, end, findit); 
    if (found != end) 
     std::cout << "Found at position " 
        << found - begin 
        << std::endl; 

    // Reverse find 
    found = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 
    if (found != std::reverse_iterator<xyz*>(end)); 
     std::cout << "Found at position " 
        << found - std::reverse_iterator<xyz*>(end) 
        << std::endl; 

    return 0; 
} 

compiler error on codepad.org

Trả lời

11

Chức năng std::find_if có một kiểu trả về tương ứng với loại iterator thông qua tại như một tham số. Trong trường hợp của bạn, vì bạn đang chuyển trong các tham số std::reverse_iterator<xyz*> s, kiểu trả về sẽ là std::reverse_iterator<xyz*>. Điều này có nghĩa là

found = std::find_if(std::reverse_iterator<xyz*>(end), 
        std::reverse_iterator<xyz*>(begin), 
        findit); 

sẽ không biên dịch, vì foundxyz*.

Để sửa lỗi này, bạn có thể thử này:

std::reverse_iterator<xyz*> 
rfound = std::find_if(std::reverse_iterator<xyz*>(end), 
         std::reverse_iterator<xyz*>(begin), 
         findit); 

này sẽ sửa chữa các lỗi biên dịch. Tuy nhiên, tôi nghĩ rằng bạn hai lỗi phổ thông trong dòng này:

if (found != std::reverse_iterator<xyz*>(end)); 

Đầu tiên, lưu ý rằng bạn có một dấu chấm phẩy sau khi tuyên bố if, vì vậy cơ thể của báo cáo kết quả if sẽ được đánh giá bất kể điều kiện là đúng .

Thứ hai, lưu ý rằng std::find_if trả về trình lặp thứ hai làm dấu gửi nếu không có gì khớp với vị từ. Do đó, xét nghiệm này nên

if (rfound != std::reverse_iterator<xyz*>(begin)) 

find_if sẽ trở lại std::reverse_iterator<xyz*>(begin) nếu nguyên tố này không được tìm thấy.

Hy vọng điều này sẽ hữu ích!

+0

Có điều này giúp, cảm ơn bạn. Chỉ số trả về bây giờ là 1 trong cả hai trường hợp có vẻ đúng nhưng sẽ rất tuyệt nếu kết quả tìm ngược lại cho chỉ số 2. Tôi không thể trừ 'bắt đầu' từ' rfound' vì điều này dẫn đến lỗi giống như trước . –

+0

@ ChristianAmmer- Tôi nghĩ đó là bởi vì logic của bạn để có được chỉ số là sai. Phép trừ của bạn tính toán khoảng cách từ trình lặp ngược tới phần tử cuối cùng của mảng, cung cấp khoảng cách * từ phía sau * của mảng, chứ không phải từ phía trước. – templatetypedef

+0

Tôi nghĩ rằng tôi đã nhận nó ngay bây giờ. Logic đã sai nhưng với '(kết thúc - bắt đầu) - (rfound - std :: reverse_iterator (kết thúc)) - 1' Tôi nhận được chỉ mục chính xác. –

Các vấn đề liên quan