【问题标题】:How to print string first n bytes when the string's length is greater than n?当字符串的长度大于n时如何打印字符串的前n个字节?
【发布时间】:2013-02-28 21:11:49
【问题描述】:

所以我有一个具有一定字节数(或长度)的字符串。我说字节是因为字符串末尾没有 NULL 终止符。不过,我知道字符串有多长。众所周知,通常情况下,当您printf("%s", str); 时,它会继续打印每个字节,直到达到 NULL 字符。我知道没有不是 NULL 终止的 C 字符串,但是我有一个奇怪的情况,我正在存储东西(不是特别是字符串)并且我不存储 NULL,而是“事物”的长度。

这是一个小例子:

char* str = "Hello_World"; //Let's use our imagination and pretend this doesn't have a NULL terminator after the 'd' in World
long len = 5;

//Print the first 'len' bytes (or char's) of 'str'

我知道你可以这样做:

printf("%.5s", str);

但是在这种情况下,我很难将 5 编码到其中,尽管在我的情况下,5 在变量中。我会这样做:

printf("%.(%l)s", len, str);

但我知道你不能那样做。但让您了解我想要完成的工作。

【问题讨论】:

  • 这里已经回答了一个非常相似的问题:stackoverflow.com/a/4777218/2163085
  • SO 4777218 是相关的,但有些不同(主要指分配而不是打印)。
  • 您可以使用snprintf(format, sizeof(format), "%%.%ds", len); 创建适当的格式字符串,然后在对printf() 的调用中使用format。如果你正在做scanf(),那么如果输入长度不同,你实际上必须这样做(scanf() 中的*printf() 中的* 非常不同)。 OTOH,printf("%.*s\n", len, str) 机制通常最适合printf()

标签: c string byte printf


【解决方案1】:

您可以像这样检测空字节中毒。程序将显示 Poisoning Null Byte detected

  char filename[] = "path/image.php\0.bmp";

  if ((sizeof(filename) - 1) == strlen(filename)) {

      printf("%s %s", "No poisoning Null Byte detected" , "\n");

      FILE *fp;
      fp = fopen(filename, "r");

      if ( fp == NULL ) {
        perror ( "Unable to open the file" );
        exit ( 1 );
      }

      fread ( buf, 1, sizeof buf, fp );
      printf ( "%s\n", buf );

      fclose ( fp );

  } else {
      printf("%s %s", "Poisoning Null Byte detected" , "\n");
  } 

【讨论】:

    【解决方案2】:

    你可以这样做:

    for (int i =0; i<len; i++)
    {
        printf("%c", str[i]);
    }
    

    这会将它们打印在同一行中,循环显示您需要打印的任何长度。

    【讨论】:

    • 这可能比接受的"%.*s" 答案慢得多,因为对 printf 的调用很多(我认为缓冲区刷新不是问题)
    【解决方案3】:

    printf("%.*s", len, str);

    而且,没有不以 NULL 结尾的 C 字符串。

    【讨论】:

    • 我知道没有不是 NULL 终止的 C 字符串,但是我有一个奇怪的情况,我正在存储东西并且我不存储 NULL,但是“东西”的长度.
    • @RobAveryIV 您可以像上面一样从str 打印len 的字符串数量
    • 请注意,这是有效的,因为格式中的每个 * 添加了另一个必需的参数,该参数替换为上面 len 提供的整数值。
    • @RobAveryIV 你的内存不适合:-) 特别是如果它是一台 32 位计算机。但除此之外,size_t 这是strlen 返回的类型,是unsigned int 所以,即使字符串的大小比unsigned int 大得多,我认为长字符串没有strlen_l .
    • * 的参数类型必须intstrlen() 的返回不是int(它是size_t),所以如果你使用它必须强制转换。变量len 必须是int 类型,或者您需要在对printf() 的调用中将其强制转换。如果您从 32 位迁移到 64 位 (Unix) 平台并且长度是 long 而不是 int,那么事情可能会变得非常糟糕;参数列表中其他所有内容的对齐方式不协调,导致严重错误的结果(或核心转储)。
    猜你喜欢
    • 2021-12-09
    • 2022-12-24
    • 2011-05-11
    • 1970-01-01
    • 1970-01-01
    • 2023-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多