Escape all special characters in printf()

2019-01-15 21:47发布

Is there an easy way to escape all special characters in the printf() function?

The reason why I would like to know how to do this is because I am printing a number of characters which may include special characters such as the null character (\0) and the beep character and I just want to see the contents of the string.

Currently I am using the following code

It works for null characters. What would be the easiest way to escape all special characters?

int length;
char* data = GetData( length ); // Fills the length as reference

for( int i = 0;  i < length;  i++ )
{
    char c = data[ i ];
    printf( "%c", ( c == 0  ?  '\\0'  :  data[ i ] ) );
}

3条回答
淡お忘
2楼-- · 2019-01-15 22:02

Use the isprint library function to determine if the character is printable:

#include <ctype.h>
...
if (isprint(data[i]))
  printf(" %c", data[i]);    // prints character
else
  printf(" %d", data[i]);    // prints code value for character
查看更多
再贱就再见
3楼-- · 2019-01-15 22:20

In case code needs to write with no ambiguity, using C syntax:

#include <ctype.h>
#include <string.h>
#include <stdio.h>

void EscapePrint(int ch) {
  // Delete or adjust these 2 arrays per code's goals
  // All simple-escape-sequence C11 6.4.4.4
  static const char *escapev = "\a\b\t\n\v\f\r\"\'\?\\";
  static const char *escapec = "abtnvfr\"\'\?\\";
  char *p = strchr(escapev, ch);
  if (p && *p) {
    printf("\\%c", escapec[p - escapev]);
  } else if (isprint(ch)) {
    fputc(ch, stdout);
  } else {
    // Use octal as hex is problematic reading back
    printf("\\%03o", ch);
  }
}

void EscapePrints(const char *data, int length) {
  while (length-- > 0) {
    EscapePrint((unsigned char) *data++);
  }
}

Alternatively, code could

void EscapePrint(char sch) {
  int ch = (unsigned char) sch;
  ...
}
void EscapePrints(const char *data, int length) {
  while (length-- > 0) {
    EscapePrint(*data++);
  }
}

To use a hexadecimal-escape-sequence or a shorten octal-escape-sequence, code needs to insure that the next character does not create ambiguity. That complication does not occur in the above code as it uses 3-digit octal-escape-sequences. Amended code would be something like:

  } else {
    if ((ch == 0) && (nextch < '0' || nextch > '7')) {
      fputs("\\0", stdout);
    }
    else if (!isxdigit((unsigned char) nextch)) {
      printf("\\x%X", ch);
    }
    else {
      // Use octal as hex is problematic reading back
      printf("\\%03o", ch);
    }
  }
查看更多
女痞
4楼-- · 2019-01-15 22:26

First of all, '\\0' is a two-character literal, which should really be a two-character string. As for printing all special characters as escape code, you need some more code:

switch (data[i])
{
case '\0':
    printf("\\0");
    break;
case '\n':
    printf("\\n");
    break;

/* Etc. */

default:
    /* Now comes the "hard" part, because not all characters here
     * are actually printable
     */
    if (isprint(data[i]))
        printf("%c", data[i]);  /* Printable character, print it as usual */
    else
        printf("\\x%02x", data[i]); /* Non-printable character, print as hex value */

    break;
}
查看更多
登录 后发表回答