代码之家  ›  专栏  ›  技术社区  ›  Dr. Debasish Jana

Linux:打印指定长度的零填充字符串

  •  3
  • Dr. Debasish Jana  · 技术社区  · 8 年前

    在Linux上,我使用GNU gcc 4.9.2版本,在打印指定长度的零填充字符串时,出现了一个奇怪的意外行为。下面是我正在尝试的代码片段:

    #include <cstdio>
    #include <cstring>
    int main()
    {
      char buff[5];
      sprintf(buff,"%04s","12");
      printf("%s\n", buff);
      return 0;
    }
    

    http://www.cplusplus.com/reference/cstdio/printf/ 明确指出,在指定填充时,flag left用零(0)而不是空格填充数字。 救济

    2 回复  |  直到 8 年前
        1
  •  5
  •   Andre Kampling    8 年前

    manpage of printf

    0

    该值应填充为零。对于 d , i o , u , x , X a , A , e E , f F g G 转换时,转换后的值在左侧填充为零,而不是空白。[…]对于其他转换,行为未定义。

    因此,它没有为字符串定义。一个实现可以用0填充,但不一定要。这是未定义的行为。

    %.*s

    char buff[5];
    char str[] = "12";
    size_t len = strlen(str);
    sprintf(buff, "%.*s%s", len >= 4 ? 0 : (int)(4 - len), "0000", str);
    

    此外,您应该考虑使用 snprintf 防止缓冲区溢出。

    snprintf(buff, sizeof(buff), "%.*s%s", len >= 4 ? 0 : (int)(4 - len), "0000", str);
    

    格式化输出 snprintf公司 '\0' 。Visual Studio 2010编译器无法确保要写入的字符串是否大于或等于缓冲区。

        2
  •  3
  •   Community Mohan Dere    5 年前

    这个 C11 7.21.6.1p6 明确指出 0 s

    0

    对于 d , i o , u x , X a , A , e , E , f , F g G 转换时,前导零(在任何符号或基数指示之后)用于填充字段宽度,而不是执行空格填充,除非转换无穷大或NaN。如果 0 - 0 d , , o , , x , 转换,如果指定了精度 0 忽略标志。 对于其他转换,行为未定义。

    因此 %04s 而你是 有好运的 当它不符合你的期望马上!


    a complete library 为了最有效地执行左键盘操作:

    char *leftpad(char *str, size_t length, char fill, char buf[]) {
        size_t s_len = strlen(str);
        if (s_len > length) {
            return NULL;
        }
    
        size_t padding = length - s_len;
        memset(buf, fill, padding);
        strcpy(buf + padding, str);
        return buf;
    }
    

    这也将与

    int main(void) {
        char buf[65], *s;
        if (s = leftpad(buf, 64, '0', "12")) {
            puts(s);
        }
    }
    

    当然,如果字符串恰好是 消极的