【问题标题】:filling an array in a loop在循环中填充数组
【发布时间】:2016-01-18 13:01:58
【问题描述】:

我有一个经常被调用的函数。我有 3 个较小的数组,每个循环需要将它们打包成一个更大的数组

float* a;
float* b;
float* c;
float* abc;

a = calloc(1, sizeof(float)*3);
b = calloc(1, sizeof(float)*3);
c = calloc(1, sizeof(float)*3);
abc = calloc(1, sizeof(float)*9);


void update() {

   for(int i = 0; i < 3; i++) {
     fill_a(a);
     fill_b(b)
     fill_c(c);

     abc[0] = a[0];
     abc[1] = b[0];
     abc[2] = c[0];

     abc[0] = a[1];
     abc[1] = b[1];
     abc[2] = c[1];

     abc[0] = a[2];
     abc[1] = b[2];
     abc[2] = c[2];
   }
}

free(a);
free(b);
free(c);
free(abc);

上面的实现存在问题,因为这些值在后续循环中被覆盖。

我已经尝试为这样的值添加偏移量:

   for(int i = 0; i < 3; i++) {
     fill_a(a);
     fill_b(b)
     fill_c(c);

     abc[(i*9)+0] = a[0];
     abc[(i*9)+1] = b[0];
     abc[(i*9)+2] = c[0];

虽然这似乎可行,但如果我尝试逐个添加也行不通。

我也尝试过通过索引值添加偏移量,但它计数到无穷大。

int idx = 0;

void update() {

   for(int i = 0; i < 3; i++) {
     fill_a(a);
     fill_b(b)
     fill_c(c);

     abc[++idx] = a[0];
     abc[++idx] = b[0];
     abc[++idx] = c[0];

     abc[++idx] = a[1];
     abc[++idx] = b[1];
     abc[++idx] = c[1];

我还尝试在一个 for 循环中填充第一个数组。然后稍后在更新循环中将这些值放入更大的数组中。

int idx;

idx = 0;
void update() {

   for(int i = 0; i < 3; i++) {
     fill_a(a);
     fill_b(b)
     fill_c(c);
   }
  int tidx = idx;
  abc[++tidx] a[0];
  abc[++tidx] b[0];
  abc[++tidx] c[0];
  ....
  idx = tidx;
 }

但 idx 又跑到无穷大了。如何安排这个算法,以便我可以用较小数组中的值填充该循环内的较大数组,同时保持偏移量有序?

较大数组的值总是会在循环中被覆盖,因此在它被填充后,它会在其他地方使用,然后覆盖下一次更新调用。

编辑 我尝试过 gdb 调试,一次通过一个变量的代码。

预期的输出是这样的:

a = { 0, 1, 2 };
b = { -3, -2, -1 };

abc = { 0, -3, 11.
        1, -2, 22 };

这是来自实际代码的完整工作示例。

    int count = 3;
    float* v_buff;
    float* c_buff;

    size_t vs = sizeof(float) * 6);
    v_buff = calloc(1, (vs));


void update() {
     for(int i = 0; i < count; i++) {
         float a[3] = { 0, 1, 2}; //these will be new every update
         float b[3] = { -3, -2, -1};
         int idx = 0;
         v_buff[++idx] = a[0];
         v_buff[++idx] = a[1];
         v_buff[++idx] = a[2];

         v_buff[++idx] = b[0];
         v_buff[++idx] = b[1];
         v_buff[++idx] = b[2];
     }
}

该示例代码可以编译,但同样适用。 尝试偏移:

v_buff[(i * 3) + (++idx)] = a[0];

使我的计数器运行到无穷大或只是覆盖 v_buff 中的第一组值。

【问题讨论】:

  • 你已经做了哪些调试?预期产出和实际产出是多少?
  • 看看第一个变体:有一个迭代变量——它在哪里被使用?
  • 查看How to Ask 并提供minimal reproducible example。你不能在函数之外有语句。并避免使用全局变量。
  • 您是否想将两个或多个数组合并成一个更大的数组?
  • 注意:array[++idx] 会先增加 idx,然后再访问数组槽。

标签: c arrays algorithm for-loop


【解决方案1】:

对于您的 abc 数组,第一种方法不起作用,因为您将数组的前 3 个条目设置为 a 的内容,然后用 b 的内容覆盖它们,然后再次使用c的内容。

您的第二种方法很接近,但不完全是因为您将 i 乘以 9 而不是 3,因此第一次迭代后索引超出范围。

您的第三种方法也很接近,但问题是您使用的是前增量 (++idx) 而不是后增量 (idx++),因此您的索引从 1 变为 9 而不是 0 到 8。

另外,您的update 函数正在循环中调用fill_afill_bfill_c。没有看到这些函数,我猜它每次都用相同的内容填充它们,所以这些可能不需要循环。

因此假设 4 个数组中的每一个的分配和释放都发生在 update 之外,函数应该如下所示:

void update()
{
    int i;

    fill_a(a);
    fill_b(b)
    fill_c(c);

    for(int i = 0; i < 3; i++) {
        abc[(i*3)+0] = a[i];
        abc[(i*3)+1] = b[i];
        abc[(i*3)+2] = c[i];
    }
}

在循环的第一次迭代中,i 为 0,因此三行计算结果为:

abc[0] = a[0];
abc[1] = b[0];
abc[2] = c[0];

在第二次迭代中,i 为 1,主体计算结果为:

abc[3] = a[1];
abc[4] = b[1];
abc[5] = c[1];

在第三次迭代中,i 为 2,主体计算结果为:

abc[6] = a[2];
abc[7] = b[2];
abc[8] = c[2];

你也可以这样实现:

void update()
{
    int i, idx;

    fill_a(a);
    fill_b(b)
    fill_c(c);

    for(int i = 0, idx = 0; i < 3; i++) {
        abc[idx++] = a[i];
        abc[idx++] = b[i];
        abc[idx++] = c[i];
    }
}

【讨论】:

  • 谢谢,我想问一个后续问题,但我想最好写一个新问题。
猜你喜欢
  • 2012-04-16
  • 2020-09-11
  • 2021-04-21
  • 2013-07-18
  • 2013-06-25
  • 2018-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多