snprintf,用于 C 中整数到字符串的转换

发布于 2024-12-10 14:27:59 字数 525 浏览 0 评论 0原文

我有一小段代码可以将 c 中的整数转换为字符串。 该代码必须在 32 位和 64 位平台上运行。

我正在循环中解析参数,因此我需要 malloc 来创建缓冲区

int tmp_integer = /*read as integer*/
char* tmp_string = malloc(20* sizeof(char)); /*enough room for the biggest integer*/
snprintf(tmp_string, 20,"%d",tmp_integer); /*can I avoid using 20 here*/
a[i - 1] = tmp_string; /*save the parsed argument for final usage*/

我的问题是: 有什么办法可以让它变得很好使用 snprintf,或者我应该回退到 sprintf。

我认为使用 snprintf 不是正确的做法,因为最初我想防止缓冲区溢出,但由于整数的大小已知,我认为它是无用的。我仍然想知道这里的最佳实践是什么。

I have a little piece of code to convert an integer to a string in c.
The code has to work on both 32-bits and 64 bits platform.

I am parsing arguments in a loop, so I need malloc to create the buffer

int tmp_integer = /*read as integer*/
char* tmp_string = malloc(20* sizeof(char)); /*enough room for the biggest integer*/
snprintf(tmp_string, 20,"%d",tmp_integer); /*can I avoid using 20 here*/
a[i - 1] = tmp_string; /*save the parsed argument for final usage*/

My question is :
Is there any way to make it nice using snprintf, or should I fall back to sprintf.

I figured that using snprintf was not the right thing to do, because originally I wanted to be protected from buffer overruns, but since the size of integer is known I think it is useless. Still I would like to know what is the best practice here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

撕心裂肺的伤痛 2024-12-17 14:27:59

在这种情况下你是对的。您知道您的数字不大于 64 位,并且您知道这意味着它的位数不会超过 20 位。因此,您实际上并不需要使用snprintf

Bug:最大的无符号 64 位数字是 18,446,744,073,709,551,615,即 20 位数字。但是,每个字符串末尾都有一个 '\0' (NUL) 字符(因此称为 nul 终止字符串术语)。因此,您应该为数组分配 21 字节,而不是 20。

You are right in this case. You know your number is not bigger than 64bits, and you know that it means it won't have more than 20 digits. Therefore, you don't really need to use snprintf.

Bug: The biggest unsigned 64 bit number you can have is 18,446,744,073,709,551,615 which is 20 digits. However, each string has a '\0' (NUL) character in the end (hence the nul-terminated string terminology). Therefore, you should allocate 21 bytes for your array and not 20.

何以笙箫默 2024-12-17 14:27:59

如果动态分配内存,则可以使用 log10 来计算字符串中所需的位置数:

int tmp_integer = /*read as integer*/ 
int signpadding = 0;
if tmpinteger < 0 then signpadding = 1;
int digitcount = (integer)floor(log10(abs(value)))+ 1 + signpadding;
char* tmp_string = malloc(digitcount * sizeof(char)); 
snprintf(tmp_string, digitcount,"%d",tmp_integer);

If you allocate memory dynamically, you can use log10 to calculate the number of places needed in your string:

int tmp_integer = /*read as integer*/ 
int signpadding = 0;
if tmpinteger < 0 then signpadding = 1;
int digitcount = (integer)floor(log10(abs(value)))+ 1 + signpadding;
char* tmp_string = malloc(digitcount * sizeof(char)); 
snprintf(tmp_string, digitcount,"%d",tmp_integer);
汹涌人海 2024-12-17 14:27:59

问题是那个神奇的“20”从何而来。由于它很神奇,因此它应该表示为符号常量,而不是代码中重复的整数文字。使用符号常量还具有让编译器为您进行错误检查的好处:(

#define MAX_INTEGER_DIGITS (20)

int value = /* ... */
char* tmp_string = malloc(MAX_INTEGER_DIGITS);
snprintf(tmp_string, MAX_INTEGER_DIGITS, "%d", value);

另请注意我如何删除 sizeof (char) 内容,因为它完全多余并且(imo)非常混乱。)

从性能的角度来看,您可能可以取消字符串格式化程序的受保护变体,但由于您无论如何都在这里调用 malloc() (不便宜),因此它可能不是一个很好的选择赢来删除它。

The question becomes where that magical "20" came from. Since it's magical, it should be represented as a symbolic constant, not an integer literal repeated in the code. Using a symbolic constant also has the benefit of having the compiler do the error-checking for you:

#define MAX_INTEGER_DIGITS (20)

int value = /* ... */
char* tmp_string = malloc(MAX_INTEGER_DIGITS);
snprintf(tmp_string, MAX_INTEGER_DIGITS, "%d", value);

(Also notice how I dropped the sizeof (char) thing, since it's totally redundant and (imo) very cluttering.)

From a performance point of view, you can probably do away with the protected variant of the string formatter, but since you're calling malloc() here anyway (not cheap) it's probably not a great win to remove it.

骄傲 2024-12-17 14:27:59

您可以在临时缓冲区中使用 sprintf ,然后分配合适的大小(随着 sprintf 的返回),然后将临时值复制到缓冲区中。

int tmp_integer = /*read as integer*/
static char tmp_string[20];
int size = sprintf(tmp_string,"%d",tmp_integer); 
char *myValueString = malloc((size+1)*sizeof(char));
a[i - 1] = strcpy(myValueString,tmp_string); 

You can sprintf in a temp buffer and then alloc the good size (with the return of sprintf), and then copy the temp into your buffer.

int tmp_integer = /*read as integer*/
static char tmp_string[20];
int size = sprintf(tmp_string,"%d",tmp_integer); 
char *myValueString = malloc((size+1)*sizeof(char));
a[i - 1] = strcpy(myValueString,tmp_string); 
东风软 2024-12-17 14:27:59

这是另一种(可能不是那么漂亮)基于 sum1stolemyname 代码片段进行转换的方法:

char *convert_int_to_string(int value)
{
    int digitcount;
    char * tmp_string;
    int increment = 2; // one for rounding, one for '\0' terminator
    if(value <0){
            increment += 1; // make room for sign 
    }
    if(0 == value){
            tmp_string = malloc(2* sizeof(char));
            sprintf(tmp_string, "%u", 0);
    }
    else{
            digitcount = (int)floor(log10((double)abs(value)))+ increment;
            tmp_string = malloc(digitcount * sizeof(char));
            sprintf(tmp_string, "%d", value);
    }
    return tmp_string;
}

This is another (maybe not so pretty) way to convert it based on sum1stolemyname code snippet:

char *convert_int_to_string(int value)
{
    int digitcount;
    char * tmp_string;
    int increment = 2; // one for rounding, one for '\0' terminator
    if(value <0){
            increment += 1; // make room for sign 
    }
    if(0 == value){
            tmp_string = malloc(2* sizeof(char));
            sprintf(tmp_string, "%u", 0);
    }
    else{
            digitcount = (int)floor(log10((double)abs(value)))+ increment;
            tmp_string = malloc(digitcount * sizeof(char));
            sprintf(tmp_string, "%d", value);
    }
    return tmp_string;
}
梦幻的味道 2024-12-17 14:27:59

解决此问题的一个简单、可移植(跨不同位数、平台和 CPU)的解决方案是:

int tmp_integer = /*read as integer*/
const size_t len = 4 * sizeof(int);
char tmp_string[len];
snprintf(tmp_string, len, "%d", tmp_integer);

A simple, portable (across various bitnesses, platforms and cpus) solution to this problem is:

int tmp_integer = /*read as integer*/
const size_t len = 4 * sizeof(int);
char tmp_string[len];
snprintf(tmp_string, len, "%d", tmp_integer);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文