2017-01-07 7 views
0

У меня проблема с использованием find на двумерных массивах. Каждый раз, когда я пытаюсь выполнить такую ​​находку, я получаю ununderstandable ошибкуНевозможно использовать find() с двумерным массивом

Мой код:

#include <iostream> 
#include <stdio.h> 
#include <algorithm> 
using namespace std; 

int st[200*1000][2]; 
int si[200*1000][2]; 

int main() { 
    if (find(si, si+200000, true) == si+200000){ 
     //do something 
    } 
    for (int j = 0; j < ileSt; j++){ 
     for (int k = 0; k < 2; k++){ 
      if (find(st[j], st[j]+2, si[znakSi][k]) != st[j]+2){ 
       //do another thing 
      } 
     } 
    } 
    return 0; 
} 

Ошибка:

In file included from /usr/include/c++/5/bits/stl_algobase.h:71:0, 
       from /usr/include/c++/5/bits/char_traits.h:39, 
       from /usr/include/c++/5/ios:40, 
       from /usr/include/c++/5/ostream:38, 
       from /usr/include/c++/5/iostream:39, 
       from prog.cpp:1: 
/usr/include/c++/5/bits/predefined_ops.h: In instantiation of 'bool __gnu_cxx::__ops::_Iter_equals_val<_Value>::operator()(_Iterator) [with _Iterator = int (*)[2]; _Value = const bool]': 
/usr/include/c++/5/bits/stl_algo.h:120:14: required from '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with _RandomAccessIterator = int (*)[2]; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const bool>]' 
/usr/include/c++/5/bits/stl_algo.h:161:23: required from '_Iterator std::__find_if(_Iterator, _Iterator, _Predicate) [with _Iterator = int (*)[2]; _Predicate = __gnu_cxx::__ops::_Iter_equals_val<const bool>]' 
/usr/include/c++/5/bits/stl_algo.h:3790:28: required from '_IIter std::find(_IIter, _IIter, const _Tp&) [with _IIter = int (*)[2]; _Tp = bool]' 
prog.cpp:19:31: required from here 
/usr/include/c++/5/bits/predefined_ops.h:194:17: error: ISO C++ forbids comparison between pointer and integer [-fpermissive] 
    { return *__it == _M_value; } 
       ^

Кроме того, это мой первый вопрос, так что если вы думаете, это может быть написано лучше, не стесняйтесь редактировать его!

ответ

0

Каждый из si[n] является int[2], а не int или bool. Поэтому вы не можете выполнить find на si, который представляет собой массив int[2], для значения true, который является bool (или int с неявным преобразованием). Сообщение об ошибке говорит вам, в основном то же самое:

/usr/include/c++/5/bits/predefined_ops.h:194:17: error: ISO C++ forbids comparison between pointer and integer [-fpermissive] 

Вместо этого, следующий код должен позволить вам найти любойtrue (т.е. 1) в массиве 2-D:

int* const si_begin = &si[0][0]; 
int* const si_end = &si[200*1000][0]; 
if (find(si_begin, si_end, true) == si_end){ 
    //do something 
} 

Если ваше намерение состояло в том, чтобы найти true только в 1-м элементе внутреннего массива, то, как предложено в комментарии Swift, лучше использовать настраиваемый цикл для поиска. std::find() используется только для поиска совпадающего элемента в 1-D массиве.

+1

он, вероятно, хотел, чтобы проверить каждый первый элемент подрешетки, так что код не будет работать. почему бы не использовать только петли for() и создать собственную подпрограмму find? std :: find good только для одномерных случаев.И должно быть (int) true – Swift

+0

@Swift: Спасибо. Было непонятно, каково было его намерение, но вы можете быть правы. Отредактировано для включения ваших комментариев. – Edy

0

Вы пытаетесь адресовать память за пределами массива, и вы должны использовать указатель на один элемент массива для адресации многомерного массива как одномерный.

Указатели si и st имеют тип int*[2] не int*, так (si+1) точки на 3-й Int (второй суб-массив int*[2] типа), (si+200000) точек на 400001th Int в этом массиве. Компилятор пытается специализировать шаблон find(), считая, что вы дал ему правильный итератор, следует этой семантике и работает неправильно. Указатель на тривиальный тип может быть итератором, указатель на массив, по-видимому, терпит неудачу. Вы должны использовать указатель на int* или char* (только из определения стандарта C++ 11 char* получил определенные результаты, но все существующие компиляторы следуют поведению C99), например. литая си:

int *pSi = (int*)si; 

Во-вторых, вы пытаетесь сравнить логическое значение (истина), константу целого. Шаблон требует, чтобы третий параметр был того же типа, что и цель итератора. если вы используете int *, то это int. Либо бросьте это явно, либо пересмотрите, если это то, что вы на самом деле хотите сделать там.

1

Вы можете переписать его, используя прямую адресацию для элементов массива 2d. Например:

for (int j = 0; j < ileSt; j++) 
{ 
    for (int k = 0; k < 2; k++) 
    { 
     if (find(&st[j][0], &st[j][0] + 2, si[znakSi][k]) != &st[j][0] + 2) 
     { 
      //do another thing 
     } 
    } 
} 

Или с помощью зОго :: начать, чтобы получить адрес строки для массива

find(std::begin(st[j]), std::begin(st[j]) + 2, si[znakSi][k]) != std::begin(st[j]) + 2 
+0

Если я использую 'std :: begin', я получаю' 'begin ', не является членом ошибки std'', и если я использую только' begin', я получаю '' begin', не был объявлен в этом scope' ошибка. –

+0

std :: begin был предоставлен с C++ 11 – arturx64