【问题标题】:What does the format specifiers "%02x " and "%3o " do in this code?格式说明符“%02x”和“%3o”在这段代码中有什么作用?
【发布时间】:2019-10-07 02:24:35
【问题描述】:

在搜索 K&R C 练习 7-2 语句的含义时,我在 https://clc-wiki.net/wiki/K%26R2_solutions:Chapter_7:Exercise_2 上找到了 K&R C 练习 7.2 的答案

练习要求

编写一个程序,以合理的方式打印任意输入。作为最低限度,它应该根据当地习惯以八进制或十六进制打印非图形字符,并打破长文本行。

我也无法理解练习的句子的含义,特别是“至少应根据当地习惯以八进制或十六进制打印非图形字符”部分。

这个练习 7-2 要求什么?请解释运动陈述的含义。

下面的代码使用格式说明符“%02x”和“%3o”在代码末尾用于打印不可打印的字符,但是这个格式说明符对 Non-Printables 究竟做了什么?

 else
    {
      if(textrun > 0 || binaryrun + width >= split)
      {
        printf("\nBinary stream: ");
        textrun = 0;
        binaryrun = 15;
      }
      printf(format, ch);
      binaryrun += width;
    }

其余代码将长行拆分为较小的行并按原样打印所有可打印字符。

完整程序如下:

    #include <stdio.h>

    #define OCTAL        8
    #define HEXADECIMAL 16


    void ProcessArgs(int argc, char *argv[], int *output)
    {
      int i = 0;
      while(argc > 1)
      {
        --argc;
        if(argv[argc][0] == '-')
        {
          i = 1;
          while(argv[argc][i] != '\0')
          {
            if(argv[argc][i] == 'o')
            {
              *output = OCTAL;
            }
            else if(argv[argc][i] == 'x')
            {
              *output = HEXADECIMAL;
            }
            else
            {
              /* Quietly ignore unknown switches, because we don't want to
              * interfere with the program's output. Later on in the
              * chapter, the delights of fprintf(stderr, "yadayadayada\n")
              * are revealed, just too late for this exercise.
              */
            }
          ++i;
          }
        }
      }
    }

    int can_print(int ch)
    {
      char *printable = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890 !\"#%&'()*+,-./:;<=>?[\\]^_{|}~\t\f\v\r\n";

      char *s;
      int found = 0;

      for(s = printable; !found && *s; s++)
      {
        if(*s == ch)
        {
          found = 1;
        }
      }

      return found;
    }

    int main(int argc, char *argv[])
    {
      int split = 80;
      int output = HEXADECIMAL;
      int ch;
      int textrun = 0;
      int binaryrun = 0;
      char *format;
      int width = 0;

      ProcessArgs(argc, argv, &output);

      if(output == HEXADECIMAL)
      {
        format = "%02X ";
        width = 4;
      }
      else
      {
        format = "%3o ";
        width = 4;
      }

      while((ch = getchar()) != EOF)
      {
        if(can_print(ch))
        {
          if(binaryrun > 0)
          {
            putchar('\n');
            binaryrun = 0;
            textrun = 0;
          }
          putchar(ch);
          ++textrun;
          if(ch == '\n')
          {
            textrun = 0;
          }

          if(textrun == split)
          {
            putchar('\n');
            textrun = 0;
          }
        }
        else
        {
          if(textrun > 0 || binaryrun + width >= split)
          {
            printf("\nBinary stream: ");
            textrun = 0;
            binaryrun = 15;
          }
          printf(format, ch);
          binaryrun += width;
        }
      }

      putchar('\n');

      return 0;
    }

【问题讨论】:

  • 是的.. 我读过关于 %o 和 %x 的文章(以及关于 %02x 的文章)。他们将 i/p 整数打印为八进制或 hexDec 格式(如果宽度小于 2,则填充 0)。我的主要障碍是理解将这些说明符用于打印不可见字符的目的。我可以 i/p 哪些非图形或不可打印字符以及如何输入?我知道从 0x00 到 0x20 是不可见的 ASCII 字符。我也无法准确理解练习的陈述,除了它要求以固定长度打破长文本行。
  • 接下来,阅读ctype.h 中的字符分类功能。或者只看您发布的代码中的can_print() 函数。

标签: c format-specifiers


【解决方案1】:

您自己已经找到了“%02x”和“%03o”的含义。这很好!

所以您的问题归结为“什么是不可打印字符?”和“它们是如何使用上述格式打印的?”


在函数can_print() 中,字符串printable 定义了一个不可打印的字符(在显示的源代码中)。不在此字符串中的所有字符都被故意定义为不可打印。 我们可以对选择进行推理,但这超出了这里的范围。另一个注意事项:" " 和 "\t\f\v\r\n" 在这组可打印字符中,在 ASCII 中具有

顺便说一句,标准库有 isprint() 来检查可打印性。


您似乎知道每个字符都被编码为一个赋值。这个值可以被解释为你喜欢的,作为一个字符,作为一个数字,作为一个指令,作为一种颜色,作为一个位模式,任何东西。实际上所有的数字计算机都只是在处理位模式,这取决于它们的含义。

所以一个不可打印的字符可以被解释为一个int 数字,这就是printf() 使用上述格式所发生的事情。假设读取的字符是'\b',即退格。 (注意:它不在printable 中。) 在 ASCII 中,此字符编码为 0x08。所以输出将分别为“08”和“010”。

您可能希望更改程序,使所有字符都被视为不可打印。然后你会看到所有字符输出为十六进制或八进制。

【讨论】:

  • 好,去吧!简而言之,程序要求用户以 8 进制和 16 进制打印不可打印字符的 ASCII 字符。我是否正确解释它?我对确定程序的确切目标感到困惑。
猜你喜欢
  • 2013-08-28
  • 2014-06-22
  • 1970-01-01
  • 1970-01-01
  • 2010-11-28
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
相关资源
最近更新 更多