Как избежать создания пустого объекта? - PullRequest
0 голосов
/ 01 мая 2019

Я делаю домашнее задание и у меня есть 2 функции unionRect и intersectRect. Я создаю набор моего первого класса Rectangle из файла.Я должен вернуть объединение и пересечь прямоугольник этого oColl. У меня проблема с возвратом значений, потому что объект возвращает два значения 0.

Я пытался вернуть разные вещи, но я не мог этого сделать.

Это из первого класса Rectangle

Rectangle unionRect(const Rectangle& rec) const {
            int ux1, ux2, uy1, uy2;
            ux1 = min(ix1, rec.ix1);
            uy1 = min(iy1, rec.iy1);
            ux2 = max(ix2, rec.ix2);
            uy2 = max(iy2, rec.iy2);
            Rectangle a(ux1, ux2, uy1, uy2);
            return a;
    }

Это функция второго класса RectangleCollection для чтения из файла

RectangleCollection(const string& strFileName) {
        ifstream ifile(strFileName.data());
        copy(istream_iterator<Rectangle>(ifile), istream_iterator<Rectangle>(), inserter(oColl,oColl.begin()));
    };

Это моя функция класса RectangleCollection для объединенияRect

Rectangle calcUnionColl() {
        set<Rectangle>::iterator it;
        Rectangle a;
        for (it = oColl.begin(); it != oColl.end(); ++it) {
         a = unionRect(*it);
        }
        return a;

    }

и файл .txt

5 5 10 10
6 6 12 12

, но когда я вызываю calcUnionColl, он возвращает мне

x1:0 x2:6 y1:0 y2:12

Я ожидаю, что результат будет x1:5 x2: 6 y1: 5 y2: 12.Заранее спасибо!

Ответы [ 2 ]

0 голосов
/ 02 мая 2019

Ответ от Реми Лебо имеет незначительную проблему. Если oColl пусто, calcUnionColl вернет значение по умолчанию a. Таким образом, если значение по умолчанию a равно x1:0, x2:0, y1:0, y2:0, то, если calcUnionColl возвращает это значение, невозможно узнать, является ли это действительным объединением значений в oColl, или если oColl было пусто.

Обычный прием при поиске максимального значения, кратного int с, - инициализация рабочего максимума с помощью INT_MIN. И таким же образом, при поиске минимального значения, мы запускаем рабочий минимум с помощью INT_MAX.

Найти объединение прямоугольников - это не что иное, как найти минимальное / максимальное значение координат углов прямоугольников, поэтому мы можем использовать описанный выше прием.

Например, если a = {x1:INT_MAX, x2:INT_MIN, y1:INT_MAX, y2:INT_MIN}, то при вычислении объединения a и любого прямоугольника b мы будем иметь:

b.x1 <= a.x1  // a.x1 == INT_MAX
b.y1 <= a.y1  // a.y1 == INT_MAX
b.x2 >= a.x1  // a.x1 == INT_MIN
b.y2 >= a.y2  // a.y2 == INT_MIN

Таким образом, объединение a и b в этом случае будет b

Использование этого в calcUnionColl():

// I assume the data-type for your rectangle coordinates is `int`.
// If you use another datatype, change this accoringly.

Rectangle RectangleCollection::calcUnionColl() const {
    int i_min = std::numeric_limit<int>::min(); // c++ way of getting INT_MIN
    int i_max = std::numeric_limit<int>::max(); // c++ way of getting INT_MAX

    set<Rectangle>::iterator it;
    Rectangle a(i_max, i_min, i_max, i_min);

    for (it = oColl.begin(); it != oColl.end(); ++it) {
        a = a.unionRect(*it);
    }
    return a;
}

Теперь, если oColl пусто, calcUnionColl() вернет x1:INT_MAX, x2:INT_MIN, y1:INT_MAX, y2:INT_MIN. Это должно быть недопустимым значением для прямоугольника, начиная с x1>x2 и y1>y2, и его должно быть легко проверить.

Иногда вам даже не нужно проверять его, поскольку оно часто является недопустимым значением, «которое имеет смысл» для дальнейших вычислений.

0 голосов
/ 01 мая 2019

Вы не объединяете все Rectangle вместе в коллекции. Вы объединяете каждого индивидуума Rectangle только с одним Rectangle, для которого вызывается calcUnionColl(), а затем вы возвращаете результат только последнего выполненного объединения.

Попробуйте вместо этого что-нибудь еще:

class Rectangle {
public:
    ...
    Rectangle unionRect(const Rectangle& rec) const;
    ...
}

Rectangle Rectangle::unionRect(const Rectangle& rec) const {
    int ux1, ux2, uy1, uy2;
    ux1 = std::min(ix1, rec.ix1);
    uy1 = std::min(iy1, rec.iy1);
    ux2 = std::max(ix2, rec.ix2);
    uy2 = std::max(iy2, rec.iy2);
    return Rectangle(ux1, ux2, uy1, uy2);
}

...

class RectangleCollection {
public:
    ...
    Rectangle calcUnionColl() const;
    ...
}

Rectangle RectangleCollection::calcUnionColl() const {
    Rectangle a;
    if (!oColl.empty()) {
        std::set<Rectangle>::iterator it = oColl.begin();
        a = *it++;
        while (it != oColl.end()) {
            a = a.unionRect(*it++);
        }
    }
    return a;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...