当我使用以下代码时:
#include <stdio.h>
int main(void)
{
printf("%s","Hello world\nHello world");
return 0;
}
打印为:
Hello world
Hello world
如何防止这种情况并将其作为C中的原始字符串文字打印?我的意思是它应该显示在终端窗口中,如下所示:
Hello world\nHello world
我知道我可以通过对printf使用反斜杠来实现这一点但是有没有其他C函数或方法来做到这一点而没有反斜杠?阅读文件时会有所帮助。
答案 0 :(得分:5)
没有内置机制来执行此操作。你必须逐个字符手动完成。但是,ctype.h
中的功能可能有所帮助。具体来说,在&#34; C&#34;在locale中,函数isprint
保证对于基本执行字符集中的所有图形字符都是真的,这实际上与7位ASCII中的所有图形字符相同,加空间;并且保证不对于7位ASCII中的所有控制字符都是如此,其中包括制表符,回车符等。
这是一幅草图:
#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;
}
这不会逃避'
也不会"
,但它会逃脱\
,如果需要,可以直接扩展它。
为U + 000A打印\n
,为U + 000D打印\r
等,留作练习。处理基本执行字符集之外的字符(例如U + 0080到U + 10FFFF的UTF-8编码)也可以作为练习。
该程序包含两个完全符合标准的C库不需要的东西,但根据我的经验,在实际操作系统上是必要的。它们标有(1)
和(2)
。
1)这明确设置了&#39; locale&#39;配置默认设置假设的方式。
2)getchar
返回的值为int
。 假设是unsigned char
(通常为0-255)可表示范围内的数字,或特殊值EOF
(不< / em>在unsigned char
)可表示的范围内。但是,已知有错误的C库为具有最高位设置的字符返回负数。如果发生这种情况,printf
会在打印\xffffffa1
时打印(例如)\xa1
。将x
投射到unsigned char
然后再投回unsigned int
会更正此问题。
答案 1 :(得分:1)
这样的事情可能就是你想要的。运行myprint(c)
以打印字符C或其可打印的表示形式:
#include <ctype.h>
void myprint(int c)
{
if (isprint(c))
putchar(c); // just print printable characters
else if (c == '\n')
printf("\\n"); // display newline as \n
else
printf("%02x", c); // print everything else as a number
}
如果您使用的是Windows,我认为您的所有新行都是CRLF(回车,换行),因此它们将按照我编写该功能的方式打印为0d\n
。
答案 2 :(得分:0)
如果我理解了这个问题,如果你有一个包含控制字符的字符串,如换行符,制表符,退格键等,你想要打印这些字符的文本表示,而不是将它们解释为控制字符。
不幸的是,没有内置的printf
转换说明符会为您执行此操作。你必须逐个字符地遍历字符串,测试每个字符串以查看它是否是一个控制字符,并为它写一些等效的文本。
这是一个快速,轻微测试的例子:
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
...
char *src="This\nis\ta\btest";
char *lut[CHAR_MAX] = {0}; // look up table for printable equivalents
// of non-printable characters
lut['\n'] = "\\n";
lut['\t'] = "\\t";
lut['\b'] = "\\b";
...
for ( char *p = src; *p != 0; p++ )
{
if ( isprint( *p ) )
putchar( *p );
else
fputs( lut[ (int) *p], stdout ); // puts adds a newline at the end,
// fputs does not.
}
putchar( '\n' );
答案 3 :(得分:0)
感谢用户 @chunk 为此答案做出贡献。
你为什么不写通用解决方案?这将使你在未来避免许多问题。
char *
str_escape(char str[])
{
char chr[3];
char *buffer = malloc(sizeof(char));
unsigned int len = 1, blk_size;
while (*str != '\0') {
blk_size = 2;
switch (*str) {
case '\n':
strcpy(chr, "\\n");
break;
case '\t':
strcpy(chr, "\\t");
break;
case '\v':
strcpy(chr, "\\v");
break;
case '\f':
strcpy(chr, "\\f");
break;
case '\a':
strcpy(chr, "\\a");
break;
case '\b':
strcpy(chr, "\\b");
break;
case '\r':
strcpy(chr, "\\r");
break;
default:
sprintf(chr, "%c", *str);
blk_size = 1;
break;
}
len += blk_size;
buffer = realloc(buffer, len * sizeof(char));
strcat(buffer, chr);
++str;
}
return buffer;
}
int
main(const int argc, const char *argv[])
{
puts(str_escape("\tAnbms\n"));
puts(str_escape("\tA\v\fZ\a"));
puts(str_escape("txt \t\n\r\f\a\v 1 \t\n\r\f\a\v tt"));
puts(str_escape("dhsjdsdjhs hjd hjds "));
puts(str_escape(""));
puts(str_escape("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\f\a\v"));
puts(str_escape("\x0b\x0c\t\n\r\f\a\v"));
puts(str_escape("\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14"));
}
\tAnbms\n
\tA\v\fZ\a
txt \t\n\r\f\a\v 1 \t\n\r\f\a\v tt
dhsjdsdjhs hjd hjds
0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ \t\n\r\f\a\v
\v\f\t\n\r\f\a\v
\a\b\t\n\v\f\r
此解决方案基于维基百科https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences的信息 以及stackoverflow.com的其他用户的答案。
$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.6 (jessie)
Release: 8.6
Codename: jessie
$ uname -a
Linux localhost 3.16.0-4-amd64 #1 SMP Debian 3.16.36-1+deb8u2 (2016-10-19) x86_64 GNU/Linux
$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
答案 4 :(得分:0)
仅使用putchar(specialCharName)。显示输入的特殊字符。
答案 5 :(得分:0)
/// My experience Win 10 Code blocks GCC MinGW
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <windows.h>
///#include <threads.h>
#include <conio.h>
/// #include <dos.h>
#include <direct.h>
int main(void)
{
/// This will give your desired result, turn string into Raw string :
printf(R"(Hello world\nHello world)");
printf(R"(Raw string support printing *&^%$#@!~()_+-=,<.>/?:;"' )");
printf("\n");
printf(R"(.C with a Capital C file format does not support raw string )");
printf("\n");
printf(R"(.c with a small c file format does support raw string )");
printf("\n");
printf(R"( Raw string did not support \n new line )");
printf("\n");
printf(
R"(More reading material at - https: // en.wikipedia.org/wiki/String_literal#Raw_strings;)");
printf("\n");
printf(
R"(More reading material at - https: // en.wikipedia.org/wiki/String_literal;)");
printf("\n");
printf(
R"(More reading material at - https://stackoverflow.com/questions/24850244/does-c-support-raw-string-literals;)");
printf("\n");
printf(
R"(More reading material at - https: // docs.microsoft.com/en-us/cpp/c-language/c-string-literals?view=vs-2019)");
printf("\n");
printf(
R"(More reading material at-https: // docs.microsoft.com/en-us/cpp/c-language/string-literal-concatenation?view=vs-2019)");
printf("\n");
/// Raw string.
printf(R"(More reading material at - https://www.geeksforgeeks.org/const-qualifier-in-c/;)");
printf("\n");
return 0;
}
答案 6 :(得分:-2)
您正在寻找的是:
#include <stdio.h>
int main(void)
{
printf("%s","Hello world\\nHello world");
return 0;
}
这将产生以下输出: Hello world \ n你好世界