C 有效确定字符数组大小以使用snprintf()

C 有效确定字符数组大小以使用snprintf(),c,C,我们有一个来自大学的小作业,要求我们在C。 该问题的一部分是将程序过程中生成的无符号长数字(因此没有任何方法对其进行预测试)转换为字符串。当然,我使用了snprintf。我初始化了一个数组(str[50]),该数组的大小非常大,可以避免任何类型的缓冲区错误 然而,在提交时,我的教授说我避免缓冲区错误的方法是无效的 我现在的问题是,当我创建一个char数组来保存无符号的long值时,它的大小是多少?是否有一些C宏可以帮助确定无符号长字符可以容纳的最大字符数 可能是 char str[MAX_NUM

我们有一个来自大学的小作业,要求我们在C。 该问题的一部分是将程序过程中生成的无符号长数字(因此没有任何方法对其进行预测试)转换为字符串。当然,我使用了
snprintf
。我初始化了一个数组(str[50]),该数组的大小非常大,可以避免任何类型的缓冲区错误

然而,在提交时,我的教授说我避免缓冲区错误的方法是无效的

我现在的问题是,当我创建一个char数组来保存无符号的long值时,它的大小是多少?是否有一些C宏可以帮助确定无符号长字符可以容纳的最大字符数

可能是

char str[MAX_NUMBER_OF_DIGITS_OF_UNSIGNED_LONG_ON_MACHINE];

我浏览了limits.h和一些博客以及这个论坛,但没有达成一致。任何帮助都将不胜感激

来自
snprintf
的文档:

关于snprintf()、SUSv2和C99的返回值 反驳 彼此:当使用size=0调用snprintf()时,SUSv2 未指定的返回值小于1,而C99允许使用str 在本例中为NULL,并将返回值(一如既往)作为数字 输出字符串的大小写中本应写入的字符数 已经足够大了

如果您使用的是C99,则可以使用snprintf确定大小(如BLUEPIXY所述):

但是,如果不能使用C99,则可以通过确定所需的位数并为终止的
\0
字符添加额外字符来确定字符串大小:

int size = (int) log10((double) ULONG_MAX) + 1;
为了给数组分配
大小
字节,您只需使用

char str[size];
但是,这仅在编译器/版本支持的情况下有效,如果编译器不支持,则可以使用

char *str = malloc(size);    //< Allocate the memory dynamically
// TODO: Use the str as you would the character array
free(str);                   //< Free the array when you are finished
char*str=malloc(大小);//<动态分配内存
//TODO:像使用字符数组一样使用str
自由(str);//<完成后释放阵列
#如果ULONG_MAX==4294967295UL
#定义大小(10+1)
#elif ULONG_MAX为简洁起见,请使用

更深层次的回答

C允许各种“区域设置”,因此理论上,
snprintf(…,%lu,…)
可以打印比预期更长的字符串。输出可以是“1234567”,而不是“1234567”

推荐:
1.确定最大整数的大小(位)
n

2. <代码>n*log2(10)
向上取整+1,得到字符数。
char
count。
3.设置一个最大需要2倍的缓冲区。
4.检查snprintf结果。
5.利基问题:使用带有
snprintf()
的双重调用需要确保“区域设置”和号码在调用之间不发生变化-不要在这里使用,因为
snprintf()
是一个功能上昂贵的调用

char *ulong_to_buf(char *buf, size_t size, unsigned long x) {
    int n = snprintf(buf, size, "%lu", x);
    if (n < 0 || n >= size) return NULL;
    return buf;
}

// Usage example
void foo(unsigned long x)
  // 1/3 --> ~log2(10)
  #define ULONG_PRT_LEN (sizeof(unsigned long)*CHAR_BIT/3 + 2)
  char buf[ULONG_PRT_LEN*2 + 1];  // 2x for unexpected locales
  if (ulong_to_buf(, sizeof buf, x)) {
    puts(buf);
  }
char*ulong\u to\u buf(char*buf,size\t size,无符号长x){
int n=snprintf(buf,大小,“%lu”,x);
如果(n<0 | | n>=size)返回NULL;
返回buf;
}
//用法示例
void foo(无符号长x)
//1/3-->~log2(10)
#定义ULONG_PRT_LEN(sizeof(无符号长)*字符位/3+2)
字符buf[ULONG_PRT_LEN*2+1];//意外地区的2倍
if(ulong_至_buf(,尺寸buf,x)){
put(buf);
}

如果代码真的很重要,请编写自己的简单代码

#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define PRT_ULONG_SIZE (sizeof(unsigned long) * CHAR_BIT * 10 / 33 + 3)

char *ulong_strnull(int x, char *dest, size_t dest_size) {
  char buf[PRT_ULONG_SIZE];
  char *p = &buf[sizeof buf - 1];
  // Form string
  *p = '\0';
  do {
    *--p = x % 10 + '0';
    x /= 10;
  } while (x);
  size_t src_size = &buf[sizeof buf] - p;
  if (src_size > dest_size) {
    // Not enough room
    return NULL;
  }
  return memcpy(dest, p, src_size); // Copy string
}
#包括
#包括
#包括
#定义PRT_ULONG_大小(sizeof(无符号长)*字符位*10/33+3)
char*ulong\u strnull(整数x,char*dest,size\u t dest\u size){
char buf[PRT_ULONG_SIZE];
char*p=&buf[sizeof buf-1];
//表单字符串
*p='\0';
做{
*--p=x%10+‘0’;
x/=10;
}而(x),;
大小src大小=&buf[sizeof buf]-p;
如果(src\U尺寸>目的地尺寸){
//空间不够
返回NULL;
}
返回memcpy(dest,p,src_size);//复制字符串
}

1)
int size=snprintf(NULL,0,“%lu”,ULONG_MAX)2)
int size=(int)log10((double)ULONG_MAX)+1
then+1表示NUL。虽然这给了我一个很好的估计,它能容纳多少位数字,但我不能用这个信息在c中创建一个如此大小的数组!您是否将数字从
无符号长
转换为十进制或十六进制的
字符串
?因为在十六进制的情况下,你可能会使用一些通用的东西,比如为STR(sizeof(你使用的类型)*2+1)
你不能在宏条件下使用
1不能使用
sizeof
\elif
行替换为
\else
char *ulong_to_buf(char *buf, size_t size, unsigned long x) {
    int n = snprintf(buf, size, "%lu", x);
    if (n < 0 || n >= size) return NULL;
    return buf;
}

// Usage example
void foo(unsigned long x)
  // 1/3 --> ~log2(10)
  #define ULONG_PRT_LEN (sizeof(unsigned long)*CHAR_BIT/3 + 2)
  char buf[ULONG_PRT_LEN*2 + 1];  // 2x for unexpected locales
  if (ulong_to_buf(, sizeof buf, x)) {
    puts(buf);
  }
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#define PRT_ULONG_SIZE (sizeof(unsigned long) * CHAR_BIT * 10 / 33 + 3)

char *ulong_strnull(int x, char *dest, size_t dest_size) {
  char buf[PRT_ULONG_SIZE];
  char *p = &buf[sizeof buf - 1];
  // Form string
  *p = '\0';
  do {
    *--p = x % 10 + '0';
    x /= 10;
  } while (x);
  size_t src_size = &buf[sizeof buf] - p;
  if (src_size > dest_size) {
    // Not enough room
    return NULL;
  }
  return memcpy(dest, p, src_size); // Copy string
}