Итерация по массиву объекта с использованием указателя на массив - PullRequest
0 голосов
/ 15 ноября 2018

Я новичок в C ++ и работаю для назначения, используя C ++ 98. Я пытаюсь перебрать массив объектов, используя указатель на массив.

Правильно печатается первая точка, а после этого какое-то значение.

Вот фрагменты кода:

struct Point { int x, y; };
int randomNumber(int low, int high ) {
   int randomNumber = low + (rand())/ (RAND_MAX/(high-low));
   cout << setprecision(2);
   return randomNumber;
}

Point *generateCoordinates(int nodesPerBlock) {
    Point cities[nodesPerBlock];
    for (int i = 0; i < nodesPerBlock; i++) {
        cities[i].x = randomNumber(1, 50);
        cities[i].y = randomNumber(1, 50);
    }
    return cities;
}
int main() {
  int nodesPerBlock = 5;
  Point *points = generateCoordinates(nodesPerBlock);
  for (int n = 0; n < (nodesPerBlock-2); n++) {
    cout << "n: x=" << points[n].x << ", y=" << points[n].y << endl;
    cout << "n+1: x=" << points[n+1].x << ", y=" << points[n+1].y << endl;
  }
}

это печатает:

n: x=1, y=4
n+1: x=18, y=11
n: x=2049417976, y=32767
n+1: x=2049417976, y=32767
n: x=2049417976, y=32767
n+1: x=2049417984, y=167804927

в то время как фактические напечатанные очки были:

Point : x=1, y=4.
Point : x=18, y=11.
Point : x=13, y=6.
Point : x=2, y=16.
Point : x=16, y=22.

передал это вопросы и это , но пока безуспешно.

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

В вашем коде три ошибки:

  • В generateCoordinates вы объявляете массив cities с размером, определяемым параметром nodesPerBlock. Это недопустимо, потому что c ++ запрещает объявлять массив переменной длины. Когда у вас есть массив с переменным размером, вы должны явно выделить память. Хотя код все еще может компилироваться из-за расширения gnu (если вы используете gcc), но все равно не соответствует стандарту.

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

  • Вы забыли включить соответствующие заголовки.

Правильный способ выполнения задачи может быть следующим:

  • Выделите массив в main()

  • Передать указатель на generateCoordinates

  • Также не забудьте освободить массив

Пример кода:

#include <cstdlib>
#include <iomanip>
#include <iostream>

struct Point { int x, y; };
    int randomNumber(int low, int high ) {
       int randomNumber = low + (rand())/ (RAND_MAX/(high-low));
       std::cout << std::setprecision(2);
       return randomNumber;
    }

    void generateCoordinates(int nodesPerBlock, Point *cities) {
        for (int i = 0; i < nodesPerBlock; i++) {
            cities[i].x = randomNumber(1, 50);
            cities[i].y = randomNumber(1, 50);
        }
    }
    int main() {
      int nodesPerBlock = 5;
      Point *points = new Point[nodesPerBlock];
      generateCoordinates(nodesPerBlock, points);
      for (int n = 0; n < (nodesPerBlock-2); n++) {
         std::cout << "n: x=" << points[n].x << ", y=" << points[n].y << std::endl;
         std::cout << "n+1: x=" << points[n+1].x << ", y=" << points[n+1].y << std::endl;
      }
      delete[] points;
    }

В качестве заключительного комментария: в заголовочной части кода вам следует избегать using namespace std, потому что, если вы когда-нибудь разбиваете заголовок на отдельный файл, каждый раз, когда вы его включаете, вы увидите все имена std в глобальное пространство, таким образом, возможно, сталкиваясь с именами из других #include.

0 голосов
/ 15 ноября 2018

cities[nodesPerBlock] является локальной переменной в функции generateCoordinates и выходит из области действия при выходе из функции.
Вы возвращаете ему адрес и получаете доступ к этому адресу в main. Это неопределенное поведение, чтобы сделать это.

Вы должны выделить cities в куче, используя new (поскольку вы используете C ++ 98), а затем вернуть этот адрес в main. Тогда вы сможете надежно получить доступ к этому адресу.

После обработки не забудьте удалить память, выделенную в конце main.

Вы можете избежать выделения и удаления памяти, изменив свою функцию, чтобы получить дополнительный параметр, который вы можете передать из main. Тогда cities может быть массивом Point s в стеке.

void generateCoordinates(Point cities[], int nodesPerBlock);
...