Где слабые места в методе?

233
18 июня 2018, 18:40

Есть метод, который парсит строку вида ширина:долгота@ширина:долгота@...@@ и заполняет двумерный масив int[x][2] :

void fillArr(String line, int **arr) {
  line += "@@";
  int x = 0;
  int lng = line.length();
  byte i = 0;
  char char_array[lng + 1];
  strcpy(char_array, line.c_str());
  String str = "";
  arr[0] = new int[2];
  while( x < lng - 1 ){
    if(char_array[x] == ':' || char_array[x] == '@') {
      int num = str.toFloat() * 1000000;
      str = "";
      if (char_array[x] == ':') {
        arr[i][0] = num;
      } else {
        arr[i][1] = num;
        i++;
        arr[i] = new int[2];
      }
      x++;
      continue;
    }
    str += char_array[x++];
  }
}

вызов метода:

int **arr = new int *[2];
fillArr(str, arr);

Но после нескольких проходов (5-7 пар значений) программа сыпется, с чем могут быть проблеммы? Не ужели забивается вся оперативня память кристала?

int num = str.toFloat() * 1000000; - используется для обрезания не значимых цыфр и сохранениея только значимых

С количеством пар до 5-7 программа работает и заполняет массив как полагается. Тоесть на выводе можно получить примерно такое:

arr[0][0] - широта 1;
arr[0][1] - долгота 1;
arr[1][0] - широта 2;
arr[1][1] - долгота 2;
arr[2][0] - широта 3;
arr[2][1] - долгота 3;
arr[3][0] - широта 4;
arr[3][1] - долгота 4;

для входящей строки 49.46666813651794:32.06716351318357@49.47983057360329:32.08364300537107@49.46767217581145:32.106817291259745@49.45082390409025:32.11076550292967

выполняя код:

for (int i = 0; i < 4; i++) {
  Serial.print(arr[i][0]);  Serial.print(" "); Serial.println(arr[i][1]);
}

я получаю:

49466668 32067166
49479832 32083644
49467672 32106820
49450824 32110768
Answer 1

Это делается иначе.

/**
 *  Класс строки размеров.
 */
class WidthHeightLine : public String
{
public:
   /**
    *  Класс указателя на позицию в строке.
    */
   typedef int Pointer;
   /**
    *  Конец строки или есть ещё размеры?
    */
   inline bool isEndOfLine(const Pointer &ptr) const {
      return (*this[ptr] == '@');
   }
   /**
    *  Возвращает float.
    */
   float getFloat(Pointer &ptr) const {
      float result = 0.0;
      while( *this[ptr] != '.' ) {
        if (isEndOfLine(ptr))
           return result;
        result *= 10;
        result += *this[ptr] - '0';
        ++ptr;
      }
      ++ptr; // Скипаем точку
      float divider = 0.1;
      while( *this[ptr] != ':' && ! isEndOfLine(ptr)) {
        result += (*this[ptr] - '0') * divider;
        divider /= 10;
        ++ptr;
      }
      return result;
   }
   /**
    *  Возвращает длину
    */
   inline float getWidth(Pointer &ptr) const {
      return getFloat(ptr);
   }
   /**
    *  Возвращает высоту
    */
   inline float getHeight(Pointer &ptr) const {
      return getFloat(ptr);
   }
   /**
    * Скипает разделитель (':' или '@')
    */
   inline void skipDivider(Pointer &ptr) const {
      ++ptr;
   }
   /**
    *  Класс-вектор размеров
    */
   class WHVector 
   {
      int m_size;          /// Длина вектора
      typedef float[2] WH; /// Тип длина:высота
      typedef WH* PWH;     /// Тип указателя
      PWH *m_vector;       /// Вектор указателей
   public:
       /**
        *  Конструктор
        */
       WHVector() {
         m_size = 0;
       }
       /**
        *  Освобождает вектор
        */
       void freeVector() {
         for (int n = 0; n < m_size; ++n)
            delete m_vector[n];
         if (m_size)
            delete m_vector;
         m_size = 0;
       }
       /**
        *  Деструктор
        */
       ~WHVector() {
          freeVector();
       }
       /**
        *  Увеличивает вектор
        */
       WHVector& operator ++ () {
         PWH *newVector = new PWH[m_size+1];
         for (int n = 0; n < m_size; ++n) 
            newVector[n] = m_vector[n];           
         delete m_vector;
         newVector[m_size] = new WH;
         ++m_size;
         return *this;
       }
       /**
        *  Возвращает ссылку на элемент вектора
        */
       inline WH& operator [] (int n) {
          return *(m_vector[n]);
       }
   };
   /**
    *  Возвращает вектор переменных в заданной строке 
    */
    static int getVector( WHVector &vector, const String &line ) {
       WidthHeightLine &whLine = *((WidthHeightLine*) &line);
       vector.freeVector();
       Pointer ptr = 0;
       int n = 0;
       while( ! whLine.isEndOfLine(ptr)) {
          vector++;
          vector[n][0] = whLine.getWidth(ptr);
          whLine.skipDivider();
          vector[n][1] = whLine.getHeight(ptr);
          whLine.skipDivider();
          ++n;
       }
       return n;
    }
};

И теперь вызываем функцию, чтобы получить массив размеров типа float[2]:

WidthHeightLine::WHVector vector;
int count = WidthHeightLine::getVector( vector, line );
Serial.print(count);
Serial.println(" sizes found.");
for (int n = 0; n < count; ++n) {
   Serial.print(vector[n][0], 5);
   Serial.print(" ");
   Serial.println(vector[n][1], 5);
}

Где line - это строка с размерами.

  1. Мы не копируем строки, а работаем с указателем,
  2. Мы освобождаем выделенную память, когда она становится не нужна,
  3. Мы знаем, где конец строки,
  4. Мы знаем, сколько в строке размеров,
  5. Код читаемый и понятный.
READ ALSO
Понимание работы QListWidgetItem

Понимание работы QListWidgetItem

У меня есть список элементов QListWidget в этом списке хранятся QListWidgetItem

174
Записать один обект QJsonObject в другой

Записать один обект QJsonObject в другой

Мне нужно записать один обект QJsonObject в другойЯ создал jsonObject и мен нужно в него записать childJsonObject

197
Как получить код кириллицы?

Как получить код кириллицы?

Не могу конвертировать кириллицу в числовой код

198
Как изменить значение path через javascript?

Как изменить значение path через javascript?

Есть следующий кусок кода:

208