2013-12-18 2 views
0

Я выполняю итерацию по строкам 2D-массива (lib) и сравнивая первые 4 записи в каждой строке с вектором кортежей (near_pts), содержащим 4 элемента. В принципе, я хочу извлечь все строки из lib, где первые 4 элемента (в этой строке) соответствуют любому из кортежей в near_pts и добавят эти строки в новый 2D-массив (sub_lib). Не должно быть никаких повторений в lib или near_pts.Стирание элементов вектора в пределах двух для циклов

Когда кортеж из near_pts сопоставляется в lib, я хочу удалить его из near_pts, чтобы не тратить время, пытаясь сопоставить этот конкретный кортеж. Я бы ожидал, что, поскольку у меня есть оператор break сразу после удаления, мы переходим к следующей итерации цикла для цикла, и итератор поверх near_pts будет сброшен для обработки модифицированной версии near_pts. Однако, похоже, это не происходит, некоторые из кортежей никогда не совпадают (и всегда должно быть совпадение). Я знаю, что проблема связана с итератором, потому что мои усилия по отладке показали, что итератор иногда только перекрывает 1 элемент near_pts, когда несколько элементов все еще существуют, но я не могу понять, почему это происходит. Код ниже, пожалуйста, дайте мне знать, нужна ли дополнительная информация и/или ясность.

int n = 0; 
for (int i=0; i<numPts; i++) { 
    for (vector<my_tup>::iterator it = near_pts.begin(); it != near_pts.end(); it++) { 
    bool match = (get<0>(*it)==lib[i][0] && get<1>(*it)==lib[i][1] && 
        get<2>(*it)==lib[i][2] && get<3>(*it)==lib[i][3]); 

    // If there is a match, add it to the sub-library, erase the entry 
    // from near_pts, and exit the interior loop. 
    if (match) { 
     for (int j=0; j<numLibCols; j++) { sub_lib[n][j] = lib[i][j]; } 
     n++; 
     near_pts.erase(it); 
     break; 
    } 
    // If we have found all of the tuples, exit the loop. 
    if (n==near_pts.size()) { break; } 
    } 
} 

Примечание: Lib фактически является 2D массив numPts размера х 13, near_pts представляет собой вектор my_tup, где my_tup является кортежем < двойных, двойной, двойной, двойной> и sub_lib является 2D массива size near_pts.size() x 13, где этот размер задан до удаления любого из элементов near_pts.

+0

Рассмотрите возможность поиска в алгоритмах std. Вы можете написать это, не беспокоясь о недействительности своих итераторов, если вы использовали std :: remove_if. – YoungJohn

ответ

2

Ваше последнее условие

// If we have found all of the tuples, exit the loop. 
if (n==near_pts.size()) { break; } 

некорректен, так как near_pts получает уменьшается, а п получает увеличился на каждый матч.

Вы, вероятно, хотите, чтобы проверить что-то вроде if (near_pts.empty()) break;

+0

Да, спасибо! – t354

0

Использование

near_pts.erase(it); 

аннулирует it. Любое использование итератора it после этой операции имеет неопределенное поведение. Вы можете использовать

near_ptrs.erase(it++); 

вместо этого: таким образом итератор it перемещается от стертого элемента, прежде чем он будет удален. Конечно, вы не можете безоговорочно увеличивать it после использования этого утверждения.

+0

Это не связано с вопросом, но позвольте мне предложить лучший способ сделать 'it' valid:' it = near_pts.erase (it) '. В C++ 11 было стандартным и последовательным, чтобы все функции erase возвращали итератор, указывающий на следующий элемент контейнера. –

1

Стирание во время итерации в векторе делает недействительным итератор, поэтому вам необходимо его обновить. Это также исключает проверку на n в конце, потому что, когда near_pts пуст, итератор должен быть в near_pts.end().

int n = 0; 
for (int i=0; i<numPts; i++) { 
    vector<my_tup>::iterator it = near_pts.begin(); 
    while(it != near_pts.end()) { 
    bool match = (get<0>(*it)==lib[i][0] && get<1>(*it)==lib[i][1] && 
        get<2>(*it)==lib[i][2] && get<3>(*it)==lib[i][3]); 

    // If there is a match, add it to the sub-library, erase the entry 
    // from near_pts, and exit the interior loop. 
    if (match) { 
     for (int j=0; j<numLibCols; j++) { sub_lib[n][j] = lib[i][j]; } 
     n++; 
     it = near_pts.erase(it); 
     break; 
    } 
    else { 
     ++it; 
    } 
    } 
} 
+0

Спасибо, что поймали это, это очень глупая ошибка с моей стороны. Извините за то, что потратил время на все, но я очень ценю это. – t354

Смежные вопросы