C编程-整数/长到字符串表示法
我只是在读“C接口和实现”。书中描述了一些非常有趣的概念。代码有时很难看(在我看来),但现在我遇到了一个关于将整数/长字符转换为字符串(字符数组)的问题。书中描述的是:C编程-整数/长到字符串表示法,c,arrays,printf,long-integer,C,Arrays,Printf,Long Integer,我只是在读“C接口和实现”。书中描述了一些非常有趣的概念。代码有时很难看(在我看来),但现在我遇到了一个关于将整数/长字符转换为字符串(字符数组)的问题。书中描述的是: const char *Atom_int(long n) { char str[43]; char *s = str + sizeof str; unsigned long m; if (n == LONG_MIN) m = LONG_MAX + 1UL; else if
const char *Atom_int(long n) {
char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n == LONG_MIN)
m = LONG_MAX + 1UL;
else if (n < 0)
m = -n;
else
m = n;
do
*--s = m%10 + '0';
while ((m /= 10) > 0);
if (n < 0)
*--s = '-';
return Atom_new(s, str + sizeof str - s);
}
有什么区别吗?关于我使用sprintf的“简单”方法,我有没有遗漏任何可能导致与本书中的函数不同的结果?我的意思是,如果只是为了展示如何不使用ltoa/sprintf/将长字符串转换为字符串,那就太好了。但是如果这是唯一的原因,那么它就不必要复杂了,…您为这两个函数发布的原始代码有两个主要问题:
数组未str
终止,在传递到'\0'
时调用未定义的行为printf
- 将指针
返回到具有自动存储s
的数组也是不正确的。取消引用此返回值也将调用未定义的行为str
sprintf
无法达到此目的。注意作者如何处理INT\u MIN
:计算-n
会调用未定义的行为,因为大多数系统上都存在整数溢出,即使结果在所有现代系统上都是正确的。但是,完全符合标准操作系统是一门困难的艺术:他的解决方案假定是2s补充,否则将失败
这是一个使用相同原型的改进解决方案。它更便于携带,不需要特殊情况下的长时间,进行更少的除法和模运算
const char *Atom_int(long n) {
char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n < 0)
m = (unsigned long)-(n + 1) + 1;
else
m = n;
while (m >= 10) {
*--s = m % 10 + '0';
m /= 10;
}
*--s = m + '0';
if (n < 0)
*--s = '-';
return Atom_new(s, str + sizeof str - s);
}
同意,第一个函数不会0终止。这两个函数都返回指向自动存储的指针。丑陋的除此之外,只要看看“long-to-char-array”转换过程:任何能说明这个过于复杂的版本的东西?
snprintf
都比sprintf
@a3f:好吧,那么你应该这么说。C不仅仅是PC、服务器和ARM。不管怎么说,这就是为什么我们有并需要。实际上,这些不完整的问题不应该回答,而是要求先完成。@a3f:我发布了一个更简单、更可移植的解决方案,可以处理2s补码表示的不对称范围。它只假定long
类型的最大范围在128位左右。@artm:在原始代码中,return语句使用局部变量s
s
被初始化为指向自动数组str
的末尾,并且仅通过连续递减操作进行相对更新。编译器似乎不够聪明,无法确定s
仍然指向自动存储。在这种情况下,这似乎是可行的,可惜的是,gcc
无法做到这一点,但在一般情况下,这要困难得多,而且可能是不可能的。你不应该指望书中的C接口和实现中的内置函数会违背这本书的目的。我的这本书已经返回了Atom\u new,(str+sizeof str)-s)
而不是返回s
。如果该函数真的是书中的1:1,则最终获得另一本书!它返回一个带有无效值的指针!是的,你是对的。也没有“printf”打印值。这只是出于测试目的,也就是删除返回的Atom_new…@inzanez:通过声明代码来自一本书,但实际上修改了它,并在破坏它的过程中,你以一种严重损害作者声誉的方式歪曲了这本书。如果我是你,我会编辑这本书如果我是作者,我现在会非常生气。
const char *Atom_int(long n) {
char str[43];
char *s = str + sizeof str;
unsigned long m;
if (n < 0)
m = (unsigned long)-(n + 1) + 1;
else
m = n;
while (m >= 10) {
*--s = m % 10 + '0';
m /= 10;
}
*--s = m + '0';
if (n < 0)
*--s = '-';
return Atom_new(s, str + sizeof str - s);
}
const char *Atom_int(long n) {
char str[43];
return Atom_new(str, snprintf(str, sizeof str, "%ld", n));
}