При печати массива появляется лишняя строка и массив меняется по неизвестной причине - PullRequest
0 голосов
/ 03 августа 2020

Вот мой класс

#include <fstream>
#include <cstdlib>
#include <math.h>
#include <iomanip>
#include <iostream>
using namespace std;

class Point {
  protected:
    int x, y;
    double operator-(const Point &def){ 
        return sqrt(pow((x-def.x),2.0)+ 
                  pow((y-def.y),2.0));
    }

};

class Circle: public Point {
  private:
    int radius;

  public:
  Circle(){     
    this->x=x;
    this->y=y;
    this->radius=radius;
  }

  Circle(int x, int y, int radius){
this->x=x;
this->y=y;
this->radius=radius;
}
    void printCircleInfo() {
      cout << x << " " << y << " " << radius << " " ;
    }
bool operator==(const Circle &def){ 
  return (x==def.x) & (y==def.y) & (radius==def.radius);
}
    bool doIBumpIntoAnotherCircle(Circle anotherCircle){
      if (anotherCircle.radius + radius >=   *this - anotherCircle    )
    return true;
      return false;
    }

};

Вот Main

int main(){
  int x,y,radius;
  const int SIZE = 13;
  Circle myCircleArry[SIZE];

Здесь я загружаю 5 9 3 в позицию 13 массива

  myCircleArry[13] = Circle(5,9,3);
   cout << endl;
   myCircleArry[13].printCircleInfo(); cout << " : ";
  ifstream Lab6DataFileHandle;

  Lab6DataFileHandle.open("Lab6Data.txt");

Это где я загружаю текстовый файл в массив, который он содержит

7 2 3
2 6 8
1 5 10
5 2 2
5 9 3
5 10 5
3 2 3
2 5 9
5 9 3
3 5 1
1 5 3
5 8 3
  while (!Lab6DataFileHandle.eof( )) {
 for (int i = 0; i < SIZE; i++) {
Lab6DataFileHandle>>x;
Lab6DataFileHandle>>y;
Lab6DataFileHandle>>radius;
 myCircleArry[i] = Circle(x,y,radius);
}
for (int i = 0; i < SIZE; i++) {
 if (myCircleArry[13].doIBumpIntoAnotherCircle(myCircleArry[i])) {
      myCircleArry[i].printCircleInfo();

Когда он достигает здесь, он выводит 5 9 3 : 7 2 3 ; 2 6 8 ; 1 5 10 ; 5 2 2 ; 5 9 3 ; 5 10 5 ; 3 2 3 ; 2 5 9 ; 5 9 3 ; 3 5 1 ; 1 5 3 ; 5 8 3 ; 5 8 3

 if ( myCircleArry[13]==myCircleArry[i])
 {cout <<"*";}

cout << " ; ";
  }

}    
}
  Lab6DataFileHandle.close();

Когда я пытаюсь распечатать позицию 13 снова напечатан массив 5 3 8

 myCircleArry[13].printCircleInfo();

}

Почему появляется дополнительный вывод и почему изменяется позиция 13? Приведите пример в свой ответ. Спасибо за уделенное время.

Ответы [ 2 ]

0 голосов
/ 04 августа 2020

Минимальное исправление

Как уже указывали другие, одна из основных проблем заключается в том, что вы выделяете встроенный массив из 13 кругов и пытаетесь получить доступ к позиции 13, которая находится прямо за пределами выделенной вами памяти.

Из вашего кода я понимаю, что вашей целью было прочитать ваш файл, который на самом деле состоит из 12 элементов, поэтому все последующие циклы пытаются слишком много читать один круг и слишком много использовать один круг. Вероятно, было бы лучше использовать отдельную переменную для вашего «ссылочного» круга.

Более того, вы используете «while not eof()» l oop, что обычно (всегда) неверно, но в в этом случае нет смысла, так как вы уже знаете и решили, что файл будет содержать 12 элементов. Таким образом, минимальное исправление для вашего основного может быть следующим:

int main() {
    int x, y, radius;
    const int SIZE = 12;
    Circle myCircleArry[SIZE + 1];

    myCircleArry[SIZE] = Circle(5, 9, 3);
    cout << endl;
    myCircleArry[SIZE].printCircleInfo(); cout << " : ";
    ifstream Lab6DataFileHandle;

    Lab6DataFileHandle.open("Lab6Data.txt");
    for (int i = 0; i < SIZE; i++) {
        Lab6DataFileHandle >> x;
        Lab6DataFileHandle >> y;
        Lab6DataFileHandle >> radius;
        myCircleArry[i] = Circle(x, y, radius);
    }
    for (int i = 0; i < SIZE; i++) {
        if (myCircleArry[SIZE].doIBumpIntoAnotherCircle(myCircleArry[i])) {
            myCircleArry[i].printCircleInfo();

            if (myCircleArry[SIZE] == myCircleArry[i])
            {
                cout << "*";
            }

            cout << " ; ";
        }

    }
    Lab6DataFileHandle.close();

    myCircleArry[SIZE].printCircleInfo();
}

Обратите внимание, что мы знаем , что SIZE элементов находятся в файле, мы выделяем SIZE+1 слотов и используем один в поместите РАЗМЕР в качестве эталонного. Циклы go от 0 до SIZE (исключено).

Основная реструктуризация

Вероятно, это должно быть go до Code Review , но поскольку мы здесь ...

Старый включает

Эти

#include <cstdlib>
#include <math.h>

могут стать

#include <cmath>

Вам не нужна старая C стандартная библиотека.

Избегайте using namespace std;

Множество ответов здесь объясните почему.

Мое мнение о вашем Point

Это больше мое мнение, чем актуальные проблемы. Ваш класс

class Point {
protected:
    int x, y;
    double operator-(const Point &def) {
        return sqrt(pow((x - def.x), 2.0) +
            pow((y - def.y), 2.0));
    }
};

использует защищенные атрибуты, что выглядит бесполезным излишним дизайном. Более того, он отключает возможность инициализации с помощью фигурных скобок.

operator- между точками не должно указывать расстояние. Это действительно противоречит интуиции с математикой, которую все изучают в школе.

Позже вы сравните центры кругов, поэтому operator== будет полезно.

Наконец, почему бы не использовать double координаты?

Результат:

struct Point {
    double x, y;

    friend double distance(const Point &a, const Point &b) {
        return sqrt(pow(a.x - b.x, 2.0) + pow(a.y - b.y, 2.0));
    }

    bool operator==(const Point &rhs) const {
        return x == rhs.x && y == rhs.y;
    }
};

Мой взгляд на ваш Circle

Это ваш Circle:

class Circle : public Point {

Честно говоря, круг не Точка, поэтому я не думаю, что hineritance - правильный выбор.

private:
    int radius;

Это действительно личное: я бы избегал защиты атрибута radius, позволяя пользователям получить к нему доступ.

public:
    Circle() {
        this->x = x;
        this->y = y;
        this->radius = radius;
    }

Это совершенно неверно. Он сообщает компилятору, что инициализация по умолчанию должна принимать атрибуты класса (неинициализированные) и использовать их для инициализации тех же вещей, потому что здесь this->x совпадает с x (то же самое относится к y и radius) . Отбросьте эту бесполезную вещь.

    Circle(int x, int y, int radius) {
        this->x = x;
        this->y = y;
        this->radius = radius;
    }

Это имеет смысл, но мой личный выбор - следовать стилю Google и обозначать атрибуты объекта с подчеркиванием после имени. Другие предпочитают m_ перед именем. Это позволяет мне избежать беспорядка this-> и случайного использования этих элементов.

    void printCircleInfo() {
        cout << x << " " << y << " " << radius << " ";
    }

Это нормально, но go я бы выбрал более стандартную пару вставок / экстракторов.

    bool operator==(const Circle &def) {
        return (x == def.x) & (y == def.y) & (radius == def.radius);
    }

Неправильное использование &. Вы обязательно хотите &&.

    bool doIBumpIntoAnotherCircle(Circle anotherCircle) {
        if (anotherCircle.radius + radius >= *this - anotherCircle)
            return true;
        return false;
    }
};

Грозное имя (опять же: личное мнение). Методы должны сообщать об объекте, к которому они применяются.

anotherCircle копируется без причины.

Classi c if (something) return true; else return false; который легко заменяется на return something;.

Итак, я бы go с:

struct Circle {
    Point center_;
    double radius_;

    friend std::ostream& operator<<(std::ostream& os, const Circle& c) {
        return os << c.center_.x << " " << c.center_.y << " " << c.radius_;
    }

    friend std::istream& operator>>(std::istream& is, Circle& c) {
        return is >> c.center_.x >> c.center_.y >> c.radius_;
    }

    bool operator==(const Circle &rhs) {
        return center_ == rhs.center_ && radius_ == rhs.radius_;
    }

    bool touches(const Circle& other) {
        return radius_ + other.radius_ >= distance(center_, other.center_);
    }
};

Теперь функция main

Давайте сделаем программу способной читать произвольное количество кругов и сравнивать их с ваша ссылка. Прекратите использовать встроенные массивы и перейдите к std::vector<>.

int main() 
{
    Circle ref = { 5, 9, 3 };
    std::cout << ref << " : ";

    std::vector<Circle> circles;

    std::ifstream is("Lab6Data.txt");
    Circle cur;
    while (is >> cur) {
        circles.push_back(cur);
    }

    for (const auto& c : circles) {
        if (ref.touches(c)) {
            std::cout << c;
            if (ref == c) {
                std::cout << " *";
            }
            std::cout << " ; ";
        }
    }
}

Обратите внимание, что мы можем инициализировать Circle с помощью фигурных скобок. Вы также можете отбросить = и go для унифицированной инициализации.

Открытие потока - это просто вызов конструктора. Закрытие будет автоматически выполнено при уничтожении объекта.

l oop теперь использует экстрактор для чтения Circle. Честно говоря, это компактно, но версия, которую я считаю наиболее дидактической c, такова:

while (true) {
    // Read
    Circle cur;
    is >> cur;
    // Check
    if (!is) {
        break;
    }
    // Use
    circles.push_back(cur);
}

Обратите внимание на шаблон: infinite l oop с Read / Check / Используйте. Проверьте, где мы можем выйти из l oop. Сначала вы читаете, затем проверяете, была ли операция чтения успешной или неудачной, после чего вы можете использовать данные или выйти на основе этого. Поверьте: напишите свои циклы так, а затем, если действительно необходимо, измените их на другие формы.

Хорошо, мы читаем все круги в файле. Теперь для всех кругов (обратите внимание на использование диапазона для l oop с const auto reference), если ссылка касается текущего круга, мы печатаем его (с *, если он равен ссылке) *. 1130 *

Надеюсь, этот длинный коротышка найдет применение ...

Полный код для упрощения копирования и вставки

#include <fstream>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <vector>

struct Point {
    double x, y;

    friend double distance(const Point &a, const Point &b) {
        return sqrt(pow(a.x - b.x, 2.0) + pow(a.y - b.y, 2.0));
    }

    bool operator==(const Point &rhs) const {
        return x == rhs.x && y == rhs.y;
    }
};

struct Circle {
    Point center_;
    double radius_;

    friend std::ostream& operator<<(std::ostream& os, const Circle& c) {
        return os << c.center_.x << " " << c.center_.y << " " << c.radius_;
    }

    friend std::istream& operator>>(std::istream& is, Circle& c) {
        return is >> c.center_.x >> c.center_.y >> c.radius_;
    }

    bool operator==(const Circle &rhs) const {
        return center_ == rhs.center_ && radius_ == rhs.radius_;
    }

    bool touches(const Circle& other) const {
        return radius_ + other.radius_ >= distance(center_, other.center_);
    }
};

int main() 
{
    Circle ref = { 5, 9, 3 };
    std::cout << ref << " : ";

    std::vector<Circle> circles;

    std::ifstream is("Lab6Data.txt");
    Circle cur;
    while (is >> cur) {
        circles.push_back(cur);
    }

    for (const auto& c : circles) {
        if (ref.touches(c)) {
            std::cout << c;
            if (ref == c) {
                std::cout << " *";
            }
            std::cout << " ; ";
        }
    }
}
0 голосов
/ 03 августа 2020

, когда вы определяете array из 13 элементов.

У вас действительно есть только 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 (0-12) индексы.

index получает доступ к определенному c element в array.

Эта строка здесь myCircleArry[13].printCircleInfo(); на самом деле должна сказать:

 myCircleArry[0].printCircleInfo();

0 - это то место, где array фактически начинается.

...