There is no built-in mechanism to do this. You have to do it manually, character-by-character. However, the functions in ctype.h
may help. Specifically, in the "C" locale, the function isprint
is guaranteed to be true for all of the graphic characters in the basic execution character set, which is effectively the same as all the graphic characters in 7-bit ASCII, plus space; and it is guaranteed not to be true for all the control characters in 7-bit ASCII, which includes tab, carriage return, etc.
Here is a sketch:
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
int main(void)
{
int x;
setlocale(LC_ALL, "C"); // (1)
while ((x = getchar()) != EOF)
{
unsigned int c = (unsigned int)(unsigned char)x; // (2)
if (isprint(c) && c != '\\')
putchar(c);
else
printf("\\x%02x", c);
}
return 0;
}
This does not escape '
nor "
, but it does escape \
, and it is straightforward to extend that if you need it to.
Printing \n
for U+000A, \r
for U+000D, etc. is left as an exercise. Dealing with characters outside the basic execution character set (e.g. UTF-8 encoding of U+0080 through U+10FFFF) is also left as an exercise.
This program contains two things which are not necessary with a fully standards-compliant C library, but in my experience have been necessary on real operating systems. They are marked with (1)
and (2)
.
1) This explicitly sets the 'locale' configuration the way it is supposed to be set by default.
2) The value returned from getchar
is an int
. It is supposed to be either a number in the range representable by unsigned char
(normally 0-255 inclusive), or the special value EOF
(which is not in the range representable by unsigned char
). However, buggy C libraries have been known to return negative numbers for characters with their highest bit set. If that happens, the printf
will print (for instance) \xffffffa1
when it should've printed \xa1
. Casting x
to unsigned char
and then back to unsigned int
corrects this.
printf
without doing anything different. Have you tried it? In your example, the compiler is interpreting the\n
and replacing it with a newline. If you fill in your strings some other way, say by reading a line of a file into a string, this doesn't happen. – Iatrochemistry\n
? So if you read a file that contains a newline, it will replace it with a\n
? You could write a function to do that. – Iatrochemistryif(ch == '\n') fputs("\\n", stdout); else putchar(ch);
– Christianize