【问题标题】:using 0 instead of '\0' in C program在 C 程序中使用 0 而不是 '\0'
【发布时间】:2021-09-18 19:18:24
【问题描述】:

为什么我的程序没有进入无限循环。我没有使用'\0' 在while 循环中测试字符串结尾,而是使用0'\0'0 在 C 语言中是否相同?

如果是,那么如果0 在字符串的中间,那么printf 应该在此处结束打印字符串。 例如printf("%s", "hello how0 are you") 应该打印 'hello how'

int main( )
{
    char s[ ] = "No two viruses work similarly" ;
    int i = 0 ;
    while ( s[i] != 0 )
    {
        printf ( "%c", s[i]) ;
        i++ ;
    }
}

【问题讨论】:

  • 以下两个有何不同?
  • printf("%s", "hello how0 are you") vs printf("%s", "hello how\0 are you") 为什么上述两种情况下的输出不同?跨度>
  • 也许这不清楚:像“ABC”这样的字符串被一个空字符隐式终止,这就是你的循环结束的原因。所以在内存中“ABC”看起来像这样:65 66 67 0,65 是A 字符等的 ASCII 值。
  • @4386427 你说得对,删除评论

标签: c while-loop char printf c-strings


【解决方案1】:

我会对此发表评论,但评论太长了。

'\0' 和 0 在 C 中是否相同

我建议你试试这个:

int main( )
{
    char s[ ] = "No two viruses work similarly" ;
    int i = 0 ;
    while ( s[i] != 0 )
    {
        printf ( "%d", s[i]); // this will print decimal values of
                              // all characters before `\0`
        ++i;
    }
    printf ("%d", s[i]); // this will print decimal value of `\0`
}

您也可以这样做:

printf("%d\n", '\0');

它会回答你的第一个问题。

如果是,那么如果 0 在字符串的中间,那么 printf 应该在此处结束打印字符串。例如printf("%s", "hello how0 are you") 应该打印 'hello how'。

"" 或 '' 中的 0 被视为 ASCII 字符,因此试试这个:

printf("%d\n", '0');

这应该给你ASCII字符'0'的十进制值。看看ASCII字符表。

作为有趣的练习,您可以这样做:

printf("%d\n", '0' - '\0');

【讨论】:

    【解决方案2】:

    在C语言中,对于每个字符,都有一个对应的ASCII值,基本上是0到127之间的整数。

    例如,当你声明:

    char a[] = "Hello";
    

    那么,数组实际上有 6 个元素,而不是 5。您可以使用以下方法对其进行测试:

    int n = sizeof(s)/sizeof(s[0]);
    printf("%d\n", n);
    

    该字符串的实际表示已变为:Hello\0

    在这里,您可以看到 \ 符号,称为 Escape Character,类似于对该字符的另一种解释。这里 \0 表示 char 数组索引上的 ASCII 值 0。但是,如果没有转义字符,0 只是一个普通字符 - 不是替代表示。

    现在如果你想查看前一个字符串的每个字符对应的 ASCII 值 - Hello,运行这个:

    int i;
    for (i = 0; i < 6; i++) {
        printf("%d ", s[i]);
    }
    
    // Output: 72 101 108 108 111 0 
    

    现在关于您最初的问题:

    '\0' 和 0 在 C 中是否相同?

    ASCII 0 和 char 0 是不同的。但是char \0表示0的ASCII值。

    【讨论】:

      【解决方案3】:

      '\0'value 为 0 的字符。它用于终止 C 中的字符串。所以,是的,循环

      while ( s[i] != 0 )
      

      工作得很好,虽然更传统的写法是

      while ( s[i] != '\0' )
      

      强调我们正在处理角色。

      另一方面,'0'是看起来像数字0的字符,虽然这个字符在ASCII字符集中的是48。但是在任何情况下,该值都不为 0!所以当你写

      printf("%s", "hello how0 are you");
      

      它打印hello how0 are you,因为0 是一个普通字符,并且不会终止字符串。如果你写了

      printf("%s", "hello how\0 are you");
      

      那么你会有一个空字符,它终止字符串。

      【讨论】:

        【解决方案4】:

        在 C 语言中有很多情况可以使用整数值0。显然,它可以用作普通整数或数组索引。但它也可以用来创建空指针。还有一个用途是字符串的空终止。

        由于空指针和字符串的空终止是完全不同的东西,因此混淆术语的风险很大。在黑暗时代的某个时刻,通过将空指针称为NULL 并创建一个类似名称的宏,扩展为空指针常量来进行区分。并且符号表中的字符 0(“空字符”)被称为 NUL,带有一个 L。仍然令人困惑。

        此外,C 从未为空终止定义转义序列,就像对换行符 \n、制表符 \n 等所做的那样。因此,作为字符串的一部分,没有办法键入空终止字符。

        然后有人(Kernighan 和 Ritchie?)想出了在 C 中使用其他已经存在的转义序列的想法。在字符串或字符文字中,我们可以使用转义序列来输入表中符号的索引。这可以使用八进制或十六进制表示法来完成。

        例如,十进制值10 的换行符可以在字符串中键入\012(八进制)或\xA(十六进制)。这些被称为八进制/十六进制转义序列。示例:

        puts("test\ntest\012test\xAtest");
        

        给予

        test
        test
        test
        test
        

        同样,我们可以使用转义序列写入空字符,八进制 \0 或十六进制 \x0。八进制版本成为空终止的约定和事实上的标准。

        【讨论】:

          【解决方案5】:

          '\0'0 在 C 中是相等的,因为 ASCII(ANSI、UTF-8 等)字符编码将 '\0' 字符的代码定义为 0。在 C 中,可以将一个字符隐式转换为整数,得到的整数将等于字符代码(例如,'A' 将转换为65)。

          如果您将字符串的字符设置为'\0'0,它将终止该字符串。

          测试代码(online):

          #include <stdio.h>
          
          int main() {
              // Are they equal? Yes!
              char zc = '\0';
              char zi = 0;
              printf("%d\n", zc == zi); // Prints 1
              
              
              // Does setting a char to 0 terminate a string? Yes!
              char s[] = "hello, world";
              printf("%s\n", s); // Prints hello, world
              s[5] = 0;
              printf("%s\n", s); // Prints hello
              
              return 0;
          }
          

          同样重要的是,字符串文字(如上面代码中的 s)自动具有终止符 '\0',但它不会显示在字符串文字中。

          将内部'\0' 字符放入字符串文字中可能听起来很愚蠢,因为字符串的长度定义为直到第一个'\0' 之前的字符数,而printf 也只打印这些字符。但是内部'\0's 确实在实践中使用,例如在 Windows 上为“打开/保存文件”对话框设置文件类型过滤器时(linklink)。这里使用内部零字符作为过滤分隔符:

          ofn.lpstrFilter = "Text files (*.txt)\0*.txt\0All files (*.*)\0*.*\0";
          

          【讨论】:

          • "'\0' 和 0 有不同的类型" 他们实际上没有。两者都有类型int。按照惯例,我们在不同的情况下使用它们,这是唯一的区别。
          • @Lundin 我发现:“在 C 中,'a' 或 '\n' 等字符常量的类型为 int,而不是 char。” en.cppreference.com/w/cpp/language/character_literal 这可以使用 _Generic 进行验证:mycompiler.io/view/2j1vfVR 谢谢,我会修正我的答案。
          【解决方案6】:

          0 是字符 '\0' 的 ascii 值。 0 不是 '0' 字符的 ascii 值。

          【讨论】:

            【解决方案7】:

            '\0' 和 0 在 C 中是否相同?

            是的,它们是编写相同整数常量 0 的不同方式。C 中的两个常量(与 C++ 相反)具有 int 类型和相同的表示形式。

            为什么我的程序没有进入无限循环。我没有使用 '\0' 在 while 循环中测试字符串结束,而不是我使用 0

            这个while循环中的条件

            while ( s[i] != 0 )
            

            等价于条件

            while ( s[i] != '\0' )
            

            如上所述。

            如果 0 在字符串的中间,那么 printf 应该结束打印 字符串就在那里。例如printf("%s", "hello how0 are you") 应该 打印'你好'

            这个字符串字面量

            "hello how0 are you"
            

            没有嵌入的零字符。这个带有嵌入零字符的字符串可以看起来像下面这样

            "hello how\0 are you" 
            

            【讨论】:

              【解决方案8】:

              在 C 源代码中,0'\0' 实际上是相同的:每个都是值为零的 int 常量。 '\0' 用于表示我们正在处理字符,但对于编译器来说它与0 相同。 (在 C++ 中,'\0'char 而不是 int。)

              显示字符“0”的代码不为零。在 ASCII 中,它是 48。在任何 C 实现中,它都可以写成'0'。即使 C 实现使用 ASCII 以外的某些字符编码,它的值也将始终为正而不是零。所以字符串中间有一个字符“0”不会作为空终止符。

              【讨论】:

                【解决方案9】:

                在 C 语言中,'\0' 的含义与整数常量 0 完全相同(相同的值为零,相同的 int 类型)。

                此外,对于阅读代码的人来说,写 '\0' 表明您打算使用这个特定的零作为字符(null)。

                【讨论】:

                  【解决方案10】:

                  '\0'0 含义相同,但'0'0 含义不同。

                  printf("%s", "hello how0 are you") 将打印hello how0 are you

                  printf("%s", "hello how\0 are you") 将打印hello how

                  【讨论】:

                  • 为了好玩,OP也可以试试printf("%s", "hello how\060 are you");
                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-01-13
                  • 2010-09-21
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多