【问题标题】:Dynamically changing the size of an array and reading in values. (w/o vectors)动态改变数组的大小并读入值。 (无载体)
【发布时间】:2020-02-04 06:16:17
【问题描述】:

您好,我遇到以下困难, 我正在尝试读取双精度表(每行 1 个条目)并将其存储在一个数组中,同时动态更改该数组的大小(对于每一行/条目)。这是针对学校作业的,禁止使用向量(会容易得多...)。我的主要想法是有一个存储值的主数组,然后将前一个值和下一个值存储到一个新数组中并迭代地执行此操作。目前,我遇到的问题是只存储表的最后一个值。我知道,不知何故,我需要通过引用全局函数来传递数据,并且我正在使用的指针在它们退出下面的 while 迭代后变为空。但是,由于数据的确切长度未知,这似乎是不可能的,因为在 main() 中初始化数组是不可能的(确切长度未知)。任何帮助,将不胜感激。 代码贴在下面。

编辑:在考虑了两个 cmets 之后,我对代码进行了以下更改,但是我不确定它们是否会正常运行。我添加了一个名为add_new_datapoint 的新函数,它应该全局更改指针/长度的值,这是通过引用传递值来完成的。在有问题的 else 语句中调用 add_new_datapoint(data_ptr, data_len, new_dp)。另外,我不确定将新内存重新分配给指针变量是否会导致内存泄漏。本质上(在我重新分配data_ptr 之后,是“被指向”的内存被释放,或者我必须删除它然后在中重新初始化它。在这种情况下,我可以再次引用指针“data_ptr”吗循环的下一次迭代?

【问题讨论】:

    标签: c++ arrays pointers reference


    【解决方案1】:

    我认为简化您发布的代码比试图找到所有可能出错的地方更容易。

    如果您希望在文件中只看到double 值,您可以将用于从文件中读取数据的代码简化为:

    while ( data_file >> new_data_pt )
    {
       // Use new_data_pt
    }
    

    如果您预计可能存在doubles 以外的值,那么您可以使用:

    while ( getline(data_file, line) )
    {
        std::istringstream str(line);
        while ( str >> new_data_pt )
        {
           // Use new_data_pt
        }
    }
    

    但是您必须了解代码在遇到错误后不会再从一行中读取任何值。如果您的行包含

    10.2 K 25.4
    

    代码将读取10.2,在K遇到错误,并且不会处理25.4

    处理new_data_pt的代码是需要存储在一个动态分配的数组中。我建议把它放在一个函数中。

    double* add_point(double* data_ptr, int data_len, double new_data_pt)
    

    将该函数调用为:

    data_ptr = add_point(data_ptr, data_len, new_data_pt);
    

    假设第一个while循环,main的内容变成:

    int main()
    {   
       std::fstream data_file{ "millikan2.dat" };
    
       // It is possible that the file has nothing in it.
       // In that case, data_len needs to be zero.
       int data_len{ 0 };
    
       // There is no need to allocate memory when there is nothing in the file.
       // Allocate memory only when data_len is greater than zero.
       double* data_ptr = nullptr; 
    
       double new_data_pt;
    
       if (!data_file.good()) {
          std::cerr << "Cannot open file";
          return 1;
       }
    
       while ( data_file >> new_data_pt ) 
       {
          ++data_len;
          data_ptr = add_point(data_ptr, data_len, new_data_pt);
       }
    
       // No need of this.
       // The file will be closed when the function returns.
       // data_file.close();
    }
    

    add_point 可以实现为:

     double* add_point(double* data_ptr, int data_len, double new_data_pt)
     {
        double* new_data_ptr = new double[data_len];
    
        // This works even when data_ptr is nullptr.
        // When data_ptr is null_ptr, (data_len - 1) is zero. Hence,
        // the call to std::copy becomes a noop.
        std::copy(data_ptr, data_ptr + (data_len - 1); new_data_ptr);
    
        // Deallocate old memory.
        if ( data_ptr != nullptr )
        {
           delete [] data_ptr;
        }
    
        new_data_ptr[data_len-1] = new_data_pt;
        return new_data_ptr;
     }
    

    跟踪坏点数量的代码要复杂得多。除非您必须这样做,否则我建议您忽略它。

    【讨论】:

      【解决方案2】:

      您已经得到了很好的答案,但我认为指出代码中的一些错误可能会有所帮助,这样您就可以理解为什么它不起作用。

      在第二个 else 作用域中,您再次声明 data_ptr,即使它从外部作用域可见。 (delete[] 不会删除指针本身,它只是释放指针指向的内存。)

      else {
                  double* data_temp { new double[data_len] };
                  std::copy(data_ptr, data_ptr + data_len - 2, data_temp);
                  *(data_temp + data_len - 1) = new_data_pt;
                  delete[] data_ptr;
                  double* data_ptr{ new double[data_len] }; // <- Right here
                  //for (int j{1}; j < data_len; j++) *(data_ptr + j) = *(data_temp + j);
                  std::cout << std::endl;
              }
      

      您可以只写data_ptr = new double[data_len]。然而,仅凭这一点并不能完成这项工作。

      所有数据都消失了,因为在每次迭代中,您都会创建一个由data_temp 指向的新数组并将数据复制到那里,并且在下一次迭代中,您将data_temp 设置为再次指向一个新数组。这意味着在每次迭代中,您都会丢失之前迭代的所有数据。这也会导致内存泄漏,因为每次点击此行时都会分配更多内存:

      double* data_temp { new double[data_len] };

      但之后你没有打电话给delete[] data_temp

      我希望这有助于理解为什么它不起作用。

      【讨论】:

        猜你喜欢
        • 2012-04-17
        • 1970-01-01
        • 2011-06-19
        • 1970-01-01
        • 1970-01-01
        • 2015-06-06
        • 2014-10-07
        • 1970-01-01
        • 2023-04-07
        相关资源
        最近更新 更多