用C语言打印通用数组的候选函数

时间:2018-05-08 15:38:56

标签: c

问候语,

等级:从初级到中级之间

这是我的候选阵列打印功能:

(>>= uncurry ((. pure) . (:)))

我试图让它与平台无关。它适用于我的项目。我想知道如果它包含在标准C库中,这个函数会产生什么样的问题。而且,为什么C库中没有阵列打印功能?

感谢。

2 个答案:

答案 0 :(得分:0)

从技术上讲,没有什么能阻止int与其他东西的大小相同,例如我相信x64 int和float的大小完全相同。 C无论如何都没有内置它,我建议将类型作为特定代码传递,然后从那里打印阵列。

void print_array(void *arr, size_t len, int type){
    //handle print here
}

其中type参数可以具有不同类型的不同值。另请注意,使用size_t而不是int来保存数组的长度。

您也可以使用宏来执行此操作,您可以执行类似

的操作
#define DEF_NEW_ARRAY(TYPE, TYPE_NAME)
typedef struct TYPE_NAME{
    TYPE *arr;
    size_t len;
} TYPE_NAME;
void TYPENAME##_print(TYPE_NAME *arr){
    //define your function
}

那么你可以这样使用这个宏

DEF_NEW_ARRAY(int, int_arr)
int_arr x;

之后您可以初始化数组并打印您的值等。

C11还介绍了_Generic。你可以在这里阅读它

http://en.cppreference.com/w/c/language/generic

答案 1 :(得分:0)

您可以关注qsort模型并传递委托函数来处理实际格式:

void print_array( void *array, size_t arrsize, size_t eltsize, const char *(*fmt)( const void *item ) )
{
  unsigned char *cur = array;
  fprintf( stdout, "{" );
  if ( arrsize > 0 )
  {
    fprintf( stdout, "%s", fmt( cur ) );
    cur += eltsize;

    for ( size_t i = 1; i < arrsize; i++ )
    {
      fprintf( stdout, ", %s", fmt( cur ) );
      cur += eltsize;
    }
  }
  fprintf( stdout, "}" );
}

如果要打印出整数数组,可以为整数创建格式化函数并将其传递给print_array

const char *intFmt( const void *item )
{
  static char buffer[12];
  sprintf( buffer, "%d", *(const int *) item );
  return buffer;
}

如果要打印双打数组,可以创建不同的格式化功能:

const char *dblFmt( const void *item )
{
  static char buffer[12];
  sprintf( buffer, "%10.2f", *(const double  *) item );
  return buffer;
}

您可以为聚合类型(结构,联合,其他数组),枚举等创建格式化程序,为您提供几乎无限的灵活性。此外,通过将类型感知内容委托给格式化程序,您的print_array函数本身也很简单;每次想要支持新类型时,都不必破解它。

这种方法有缺点。对于给定类型使用错误的格式化程序时,编译器无法向您发出警告(只要您使用void *进行处理,就会在窗口中抛出类型安全性)。此外,在此实现中,我在格式化程序中使用静态缓冲区,使它们不可重入且不是线程安全的。最好将目标缓冲区传递给print_array(它将传递给格式化程序),但我试图让这个例子保持可读性。

您可能还希望将输出流作为参数传递,而不是始终打印到stdout

但是,这至少应该让你了解可能的情况。这是一个完整的实现,以及一些示例输出:

#include <stdio.h>

void print_array( void *array, size_t arrsize, size_t eltsize, const char *(*fmt)( const void *item ) )
{
  unsigned char *cur = array;
  fprintf( stdout, "{" );
  if ( arrsize > 0 )
  {
    fprintf( stdout, "%s", fmt( cur ) );
    cur += eltsize;

    for ( size_t i = 1; i < arrsize; i++ )
    {
      fprintf( stdout, ", %s", fmt( cur ) );
      cur += eltsize;
    }
  }
  fprintf( stdout, "}" );
}

const char *intFmt( const void *item )
{
  static char buffer[12];
  sprintf( buffer, "%d", *(const int *) item );
  return buffer;
}

const char *dblFmt( const void *item )
{
  static char buffer[12];
  sprintf( buffer, "%10.2f", *(const double  *) item );
  return buffer;
}

struct node {
  int val;
  struct node *next;
};

const char *nodeFmt( const void *item )
{
  static char buffer[50];
  const struct node *value = item;

  sprintf( buffer, "{ val: %d; next %p }", value->val, (void *) value->next );
  return buffer;
}

const char *voidFmt( const void *item )
{
  static char buffer[20];
  sprintf( buffer, "%p", item );
  return buffer;
}

int main( void )
{
  int iArr[] = {1, 2, 3, 4, 5};
  double dArr[] = {2.0, 4.0, 8.0, 16.0};
  struct node nArr[] = { {1, NULL}, {2, NULL} };

  void *arrs[] = { iArr, dArr, nArr };

  nArr[0].next = &nArr[1];

  print_array( iArr, sizeof iArr / sizeof *iArr, sizeof *iArr, intFmt );
  putchar( '\n' );
  print_array( dArr, sizeof dArr / sizeof *dArr, sizeof *dArr, dblFmt ); 
  putchar( '\n' );
  print_array( nArr, sizeof nArr / sizeof *nArr, sizeof *nArr, nodeFmt );
  putchar( '\n' );
  print_array( arrs, sizeof arrs / sizeof *arrs, sizeof *arrs, voidFmt );
  putchar( '\n' );

  return 0;
}

输出:

jbode:print_array john.bode$ ./print_array 
{1, 2, 3, 4, 5}
{      2.00,       4.00,       8.00,      16.00}
{{ val: 1; next 0x7ffeeafc5a70 }, { val: 2; next 0x0 }}
{0x7ffeeafc5a40, 0x7ffeeafc5a48, 0x7ffeeafc5a50}