Что описатели формата "% 02x" и "% 3o" делают в этом коде? - PullRequest
0 голосов
/ 07 октября 2019

В поисках смысла утверждения K & R C Упражнение 7-2 я основал этот ответ для Упражнения K & R C 7.2 на https://clc -wiki.net / wiki / K% 26R2_solutions: Chapter_7: Exercise_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;
    }

1 Ответ

4 голосов
/ 07 октября 2019

Вы сами нашли, что означают "% 02x" и "% 03o". Это хорошо!

Итак, ваш вопрос сводится к "Что такое непечатные символы?"и «Как они печатаются в указанных форматах?»


Непечатаемый символ определяется (в указанном источнике) строкой printable в функции can_print(). Все символы, не входящие в эту строку, преднамеренно определены как недоступные для печати. Мы можем рассуждать о выборе, но здесь это выходит за рамки. Еще одно примечание: «» и «\ t \ f \ v \ r \ n» находятся в этом наборе печатных символов и имеют значение <= 0x20 в ASCII. </em>

BTW, стандартная библиотекаимеет isprint(), который проверяет на пригодность для печати. ​​


Как вы, кажется, знаете, каждый символ кодируется как присвоенное значение. Это значение можно интерпретировать как угодно, как символ, как число, как инструкцию, как цвет, как битовый шаблон, что угодно. На самом деле все цифровые компьютеры работают только с битовыми шаблонами, это зависит от их интерпретации.

Таким образом, непечатаемый символ можно интерпретировать как число int, и это то, что происходит с помощью printf() с указанным форматом. Допустим, что прочитанным символом является '\ b', известное как backspace. (Примечание: его нет в printable.) В ASCII этот символ кодируется как 0x08. Таким образом, выходные данные будут «08» и «010» соответственно.

Вы можете изменить программу таким образом, чтобы все символы считались непечатными. Тогда вы увидите все символы, выводимые в шестнадцатеричном или восьмеричном виде.

...