c - 在 glib 中向 gprtarray 添加结构元素,但无法检索

标签 c arrays linux glib gsl

我试图从一组 M^2 连续整数中生成 M 个整数的组合,然后根据一些(当前不相关的)标准排除一些组合,并尝试将它们动态存储在内存中,以便我能够以便稍后访问它们。

这些组合是使用 GNU 科学库 (docs here) 中的“gsl_combination”结构生成的。正如您从下面的代码片段中看到的,组合生成正常(并且根据需要排除)。

然后我需要将每个组合结构对象附加到内存中以供以后检索。我正在尝试使用 glib 指针数组来执行此操作。

代码:gptrwierd.c

#include <glib.h>
#include <gsl/gsl_combination.h>

//Hardcoded the size of the rigol lattice  
//MUST BE ODD !!!
#define M 3

//Returns GSL_SUCCESS if the combination contains a forbidden site, otherwise returns GSL_FAILURE  
int
is_forbidden (const gsl_combination * test)
{
  int i, forbidden = GSL_FAILURE;   //Not forbidden by default
  size_t k = test->k;
  size_t *data = test->data;
  int halfway = ((M * M - 1) / 2);  //The halfway point in the 2D grid

      ...
      ... //Some code for updating 'forbidden'
      ...
  return forbidden;
}


#undef __FUNCT__
#define __FUNCT__ "main"
int
main (int argc, char **argv)
{
  long count, istride;
  //Generate the basis states
  gsl_combination *c = gsl_combination_calloc (M * M, M);
  //An array that will contain selected basis vectors.
  GPtrArray *basis = g_ptr_array_new ();
  count = 0;
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append c to basis
      g_ptr_array_add (basis, c);   //Appends c to basis
      {
        printf ("count %ld {", count);
        gsl_combination_fprintf (stdout,
                    g_ptr_array_index (basis, count), " %u");
        printf (" }\n");
      }
      count++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);
  printf("\n\n");
  //Now, access each basis element from GArray
  for (istride = 0; istride < basis->len; istride++)
    {
      printf ("istride %ld {", istride);
      gsl_combination_fprintf (stdout, g_ptr_array_index (basis, istride),
                  " %u");
      printf (" }\n");

    }

  gsl_combination_free (c);
  g_ptr_array_free (basis, TRUE);
  return 0;
}

生成文件:

            GSL_FLAGS  = gsl-config --cflags
            GLIB_LOC = pkg-config --cflags --libs glib-2.0
            CFLAGS     = -Wall -O3 `$(GSL_FLAGS)` `$(GLIB_LOC)`

            GSL_LIBS   = gsl-config  --libs-without-cblas 
            GLIB_LIBS = pkg-config --libs glib-2.0



            gptrwierd:
                gcc $(CFLAGS) -c gptrwierd.c 
                gcc -o $@ gptrwierd.o -lgsl -lgslcblas -lm `$(GLIB_LIBS)`

            allclean: clean
                ${RM} gptrwierd *.dat

编译和运行就这样完成了(M硬编码为3):

$make gptrwierd
 gcc -Wall -O3 `gsl-config --cflags` `pkg-config --cflags --libs glib-2.0` -c gptrwierd.c 
 gcc -o gptrwierd gptrwierd.o -lgsl -lgslcblas -lm `pkg-config --libs glib-2.0`
 $./gptrwierd > out.dat

输出文件的内容粘贴在下面:

count 0 { 1 2 3 }
count 1 { 1 2 4 }
count 2 { 1 2 6 }
count 3 { 1 2 7 }
count 4 { 1 2 8 }
count 5 { 1 3 4 }
count 6 { 1 3 6 }
count 7 { 1 3 7 }
count 8 { 1 3 8 }
count 9 { 1 4 6 }
count 10 { 1 4 7 }
count 11 { 1 4 8 }
count 12 { 1 6 7 }
count 13 { 1 6 8 }

...
...

count 28 { 3 6 7 }
count 29 { 3 6 8 }
count 30 { 3 7 8 }
count 31 { 4 6 7 }
count 32 { 4 6 8 }
count 33 { 4 7 8 }
count 34 { 6 7 8 }

istride 0 { 6 7 8 }
istride 1 { 6 7 8 }
istride 2 { 6 7 8 }
istride 3 { 6 7 8 }
istride 4 { 6 7 8 }
istride 5 { 6 7 8 }
istride 6 { 6 7 8 }
istride 7 { 6 7 8 }
istride 8 { 6 7 8 }
istride 9 { 6 7 8 }
istride 10 { 6 7 8 }
istride 11 { 6 7 8 }
istride 12 { 6 7 8 }

...
...

istride 30 { 6 7 8 }
istride 31 { 6 7 8 }
istride 32 { 6 7 8 }
istride 33 { 6 7 8 }
istride 34 { 6 7 8 }

如您所见,它在迭代组合的 do...while 循环中正确打印组合,但仅在后续循环中迭代 gptrarray 元素时打印按字典顺序排列的最终组合。

我做错了什么?

更新: 一种可能的解决方法似乎是完全取消 glib 并手动将组合数据复制到动态分配的数组中:

  gsl_combination *c = gsl_combination_calloc (M * M, M);
  long **basis;
  long dim = 0;
  //Evaluate the dimensionality of the Hilbert space (# of allowed combinations)
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append dim
      dim++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);


  //Now, generate the actual basis
  //basis is an array of arrays that will contain the 
  //selected basis vectors. Each basis vector is an array of M integers
  basis = (long **) malloc (dim * sizeof (long *));
  for (count = 0; count < dim; count++)
    basis[count] = (long *) malloc (M * sizeof (long));

  //Reset the combination to the one that is lexicographically first
  gsl_combination_init_first (c);
  count = 0;
  //Now, append all allowed combinations to the basis
  do
    {
      //c is the ith combination of M integers from M^2 integers
      //Get all the non forbidden elements
      if (is_forbidden (c) == GSL_FAILURE)
    {           //If the site is NOT forbidden, append data in c to basis
      for (istride = 0; istride < M; istride++)
        basis[count][istride] = c->data[istride];
      count++;
    }
    }
  while (gsl_combination_next (c) == GSL_SUCCESS);

  //Now, access each basis element from GArray
  //basis[i] is the ith combination. jth combination element is basis[i][j]
  printf (
  "Printing all allowed combinations of sites in basis\n"
  "---------------------------------------------------\n");


  for (istride = 0; istride < dim; istride++)
     {
       printf ("stride # %3ld:\t{", istride);
       for (count = 0; count < M; count++)
         printf (" %ld", basis[istride][count]);
   printf (" }\n");
  }
/*Do whatever*/
...
...
free(basis);

最佳答案

反例,有效!所以证明和GPtrArray没有关系, 但 g_ptr_array_add (basis, c); //Appends c to basis您总是将最新的值添加到 ptr 数组中(但始终指向相同的对象)。因此,您可以对其进行修改,以反射(reflect)下一个要添加的内容,并在同一步骤中更改最后添加的内容。

pkg-config --modversion glib-2.0
2.37.7

使用的演示代码:

#include <glib.h>
#include <glib/gprintf.h>

int main()
{
GPtrArray *a = g_ptr_array_new ();
gpointer data = a;
int i;

for (i=0; i<10; i++, data++)
{
    g_ptr_array_add (a, data);
    if (i>0)
        g_printf ("[%i] last: %p \n", i, g_ptr_array_index (a, i-1));
    g_printf ("[%i] current: %p \n", i, g_ptr_array_index (a, i));
}

g_printf ("---- cut ----\n");


for (i=0; i<10; i++, data++)
{
    g_printf ("[%i] recheck: %p \n", i, g_ptr_array_index (a, i));
}

g_ptr_array_unref (a);
return 0;
}

输出:

[0] current: 0x1c1ae00 
[1] last: 0x1c1ae00 
[1] current: 0x1c1ae01 
[2] last: 0x1c1ae01 
[2] current: 0x1c1ae02 
[3] last: 0x1c1ae02 
[3] current: 0x1c1ae03 
[4] last: 0x1c1ae03 
[4] current: 0x1c1ae04 
[5] last: 0x1c1ae04 
[5] current: 0x1c1ae05 
[6] last: 0x1c1ae05 
[6] current: 0x1c1ae06 
[7] last: 0x1c1ae06 
[7] current: 0x1c1ae07 
[8] last: 0x1c1ae07 
[8] current: 0x1c1ae08 
[9] last: 0x1c1ae08 
[9] current: 0x1c1ae09 
---- cut ----
[0] recheck: 0x1c1ae00 
[1] recheck: 0x1c1ae01 
[2] recheck: 0x1c1ae02 
[3] recheck: 0x1c1ae03 
[4] recheck: 0x1c1ae04 
[5] recheck: 0x1c1ae05 
[6] recheck: 0x1c1ae06 
[7] recheck: 0x1c1ae07 
[8] recheck: 0x1c1ae08 
[9] recheck: 0x1c1ae09

关于c - 在 glib 中向 gprtarray 添加结构元素,但无法检索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18446662/

相关文章:

php - 作为 JavaScript 数组名称的变量

python - 在 Python 中将列表列表转换为数组

php - 如何合并 PHP 数组?

c - 优化代码多个 if else 语句

c - TCL_LINK_STRING 导致段错误(核心已转储)

c++ - system() 以不同的方式执行 shell 命令 C++

linux - epoll_wait 似乎卡在了 EPOLLRDHUP

javascript - 屏幕刷新 jquery 适用于 PC 而不是服务器

java - 是否可以无限期地保持套接字打开

c - K&R 第二版是否解释了函数指针的 typedef