我们有一份来自大学的小作业,要求我们在C中完成一些工作。
该问题的一部分是将无符号长号转换为字符串,该无符号长号在程序过程中生成,因此无需预先确定它。当然,我使用了snprintf
。我初始化了一个数组(str [50]),其大小足以避免任何类型的缓冲区错误。
然而,在提交时,我的教授说我的避免缓冲错误的方法是无效的。
我现在的问题是,当我创建一个char数组来保存unsigned long值时,我将它作为什么尺寸?是否有一些C宏来帮助确定无符号长整数可以容纳的最大字符数?
可能有点像,
char str[MAX_NUMBER_OF_DIGITS_OF_UNSIGNED_LONG_ON_MACHINE];
我已经浏览过limit.h和一些博客和这个论坛,但没有任何协议。任何帮助将不胜感激!
答案 0 :(得分:1)
来自snprintf
的文件:
关于snprintf(),SUSv2和C99的返回值 顶撞 彼此:当使用size = 0调用snprintf()时,SUSv2规定 未指定的返回值小于1,而C99允许str为 在这种情况下为NULL,并给出返回值(一如既往)作为数字 在输出字符串的情况下写入的字符数 已经够大了。
如果您使用的是C99,可以使用snprintf确定尺寸(如BLUEPIXY所评论):
int size = snprintf(NULL, 0, "%lu", ULONG_MAX);
但是,如果您不能使用C99,则可以通过确定所需的位数并为终止\0
字符添加其他字符来确定字符串大小:
int size = (int) log10((double) ULONG_MAX) + 1;
为了使用size
字节分配数组,您只需使用
char str[size];
然而,只有当您的编译器/版本支持VLAs时,这才有效,如果编译器不支持此功能,您可以使用
动态分配数组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
答案 1 :(得分:1)
#if ULONG_MAX == 4294967295UL
# define SIZE (10 + 1)
#elif ULONG_MAX <= 18446744073709551615ULL
# define SIZE (20 + 1)
#endif
答案 2 :(得分:1)
为了简洁,请使用@BLUEPIXY。
更深层次的回答。
C允许各种“语言环境”,理论上,snprintf(..., "%lu",...)
可以打印比预期更长的字符串。而不是“1234567”,输出可能是“1,234,567”。
推荐:
1.确定最大整数的位大小n
2. n * log2(10)
四舍五入+ 1然后计算char
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);
}
如果代码真的,那么简单编写自己的
#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
}