C++ 具有特殊字符的字符串的控制台输出

C++ 具有特殊字符的字符串的控制台输出,c++,c,formatted,C++,C,Formatted,是否有一种或多或少的标准方法来输出包含特殊字符(如ASCII控制代码)的字符串,以使输出为有效的C/C++文本字符串,并带有转义序列 预期输出的示例:This\nis\na\\test\n\n她说,“你好吗?”\n 如果不小心,输出将是 This is a\test She said, "How are you?" 不是你想要的。根据你可能试图实现的目标,我可以建议以下解决方案:只需将任何不可打印的字符替换为“\xnn”(nn是字符的ascii码。这可以归结为 void myprint (c

是否有一种或多或少的标准方法来输出包含特殊字符(如ASCII控制代码)的字符串,以使输出为有效的C/C++文本字符串,并带有转义序列

预期输出的示例:
This\nis\na\\test\n\n她说,“你好吗?”\n

如果不小心,输出将是

This
is
a\test

She said, "How are you?"

不是你想要的。

根据你可能试图实现的目标,我可以建议以下解决方案:只需将任何不可打印的字符替换为“\xnn”(nn是字符的ascii码。这可以归结为

void myprint (char *s) {
   while (*s) {
      printf(isalnum((unsigned char) *s) ? "%c" : "\\%03hho", *s);
      s++;
   }
}

这当然不会使用像
\n
(但是
\x0a
)这样的特殊缩写,但这应该不会是一个问题。

如果这对某人有帮助,我会很快将其组合起来:

void printfe(char* string)
{
    for (char c= *string; c; c= *(++string))
    {
        switch (c)
        {
        case '\a': printf("\\a"); break;
        case '\b': printf("\\b"); break;
        case '\f': printf("\\f"); break;
        case '\n': printf("\\n"); break;
        case '\r': printf("\\r"); break;
        case '\t': printf("\\t"); break;
        case '\v': printf("\\v"); break;
        case '\\': printf("\\\\"); break;
        case '\'': printf("\\\'"); break;
        case '\"': printf("\\\""); break;
        case '\?': printf("\\?"); break;
        default: (c < ' ' || c > '~') ? printf("\\%03o", c) : putchar(c); break;
        }
    }
}
void printfe(字符*字符串)
{
for(字符c=*字符串;c;c=*(++字符串))
{
开关(c)
{
大小写“\a”:printf(“\\a”);中断;
大小写“\b”:printf(“\\b”);中断;
大小写“\f”:printf(“\\f”);中断;
大小写“\n”:printf(“\\n”);中断;
大小写“\r”:printf(“\\r”);中断;
大小写“\t”:printf(“\\t”);中断;
大小写“\v”:printf(“\\v”);中断;
大小写“\\”:printf(“\\\”);break;
大小写“\”:printf(“\\\”);break;
大小写“\”:printf(“\ \”);break;
大小写“\?”:printf(“\?”);break;
默认值:(c)<'''\'c>'~'?printf(\\%03o',c):putchar(c);break;
}
}
}

(请注意
c的潜在不可移植性
,我想避免任何库引用)。

打印转义字符串显然很棘手

问题包括

  • 控制字符和空字符
  • 转义转义字符
  • char
  • 十六进制转义序列没有指定的长度限制。八进制转义序列限制为3位

    void EscapePrint(char ch) {
      // 1st handle all simple-escape-sequence C11 6.4.4.4
      // The important one to detect is the escape character `\`
      // Delete or adjust these 2 arrays per code's goals
      static const char *escapev = "\a\b\t\n\v\f\r\"\'\?\\";
      static const char *escapec = "abtnvfr\"\'\?\\";
      char *p = strchr(escapev, (unsigned char) ch);
      if (p && *p) {
        printf("\\%c", escapec[p - escapev]);
      }
    
      // if printable, just print it.
      else if (isprint((unsigned char) ch)) {
        fputc(ch, stdout);
      }
    
      // else use octal escape  
      else {
        // Use octal as hex is problematic reading back
        printf("\\%03hho", ch);
      }
    }
    
  • 迂腐:八进制转义序列在
    char
    范围超过9位的罕见机器上是一个问题。这可以在字符串级别使用十六进制转义序列来处理,而不是在
    char
    基础上使用
    char
    来处理,因为十六进制转义序列需要限制。例如:

      input 2 `char`:            \1 A
      //                               v----- intervening space
      output text including ":   "\\x1" "A"
    

    请不要同时用C++和C++来标记这些问题。这些是不同的语言,有不同的IO策略。决定你想要哪一个。@ J.S.GugStdt:我接受两种语言的答案,两个世界的解决方案都可以。程序中的NG文字,可以逃出字符“代码>”,这个\NIS\N“/CODE”实际上存储了字符串中的<代码> \n <代码>。否则可能不。不介意,您刚才在说ASCII格式。C<代码> Prtff <代码>(家庭)和C++ <代码> IoStry不应该与实际的“字符串”内容有任何问题。(我之前的评论与ANSI转义有关)只要你能nul终止数组,你就应该能够在
    printf
    cout
    中使用它。我对下面的
    printf没有任何问题(“这个\nis\na\\test\n\n她说,\”你好吗?\“\n”)
    如果您的字符数组包含以nul结尾的字符串,那么简单的
    printf(ptr_to_your_数组)
    工作正常。是的,这就是我需要的。我想知道是否没有更多的标准内容,但显然没有。我添加了处理转义的代码。小的改进:
    isalnum((未签名字符)*s)< /代码>处理讨厌的否定<代码> *S\<代码>和<代码> \\x%02x > <代码> > \x%02HHX“<代码> > ySavaDouthST字符,如<代码>!'<代码>和<代码> > < <代码>可打印,但使用此函数替换。您认为那些是“特殊的”吗?也是?如果一个特殊字符后跟一个作为字符串一部分的十六进制数字,则这种方法不起作用。例如,
    “?一个”
    将被打印为
    “\x3fa”
    在另一端将被读取为一个单字符代码。@JensGustedt:这是一个糟糕的设计决策,它妨碍了数字转义符和打印字符的安全混合,因为没有结尾分隔符。如果一个特殊字符后面跟一个十六进制数字,这是字符串的一部分,这种方法就不起作用。例如
    “\015a”
    将打印为
    “\x0da”
    在另一端将被读取为一个单字符代码。这也隐含着编码是ASCII。但是,
    switch
    语句中列出的所有特殊情况都不触发。@JensGustedt:我已改为八进制转义。我不介意不可移植性。您的整个案例系列仍然是c完全无用。许多平台使用有符号的
    字符
    字符c=-1;printf(\\%03o,c);
    可以打印
    “\3777777”
    。最好确保
    字符作为
    无符号字符
    传递或使用
    “\\%03hho”
    。是否保证此字符串中断也会终止十六进制值?@YvesDaoust Yes。在C源代码中,使用
    char s[]=“\xB”“ABC\0004\1”;
    s
    成为一个包含
    char
    的数组8,其值为11,'A','B',C',0',4',1,0。字符串文字的两部分合并在一起,但十六进制转义序列以
    @chus:我没有找到有关这方面的信息;人们可能想知道字符串的解析是在粘贴之前还是之后进行的。