【问题标题】:How are strings terminated in C#?C#中的字符串是如何终止的?
【发布时间】:2023-03-31 05:36:01
【问题描述】:

这个程序抛出ArrayIndexOutOfBoundException

string name = "Naveen";
int c = 0;
while( name[ c ] != '\0' ) {
    c++;
}
Console.WriteLine("Length of string " + name + " is: " + c);

为什么会这样? 如果字符串不是以空值结尾的。在 C# 中如何处理字符串? 如何在不使用 string.Length 属性的情况下获得长度? 我在这里很困惑。!

【问题讨论】:

  • 你为什么不想使用string.Length
  • 你为什么不想使用长度属性来获取长度??
  • 我想终止字符串中包含 '\0' 的给定字符串。?例如:“Nav\0een”。
  • “为什么会这样?”因为以空结尾的字符串是个坏主意……这意味着字符串不能包含嵌入的空字符,并且如果不对其进行迭代就无法找到字符串的长度……
  • 那么该字符串以什么方式以空值结尾?那是一个长度为 7 的字符串,而不是长度为 3 的字符串。您可以轻松地 find 第一个空字符之前的部分,并根据需要获取该子字符串,但您应该真正解释更多关于 为什么你要这样做,因为这是一个相当奇怪的要求。

标签: c# .net string null-terminated


【解决方案1】:

在 C/C++ 中,字符串存储在 char 数组 AFAIR 中,没有智能和行为。因此,要表示这样的数组在某处结束,必须在末尾添加 \0。

另一方面,在 C# 中,字符串是一个容器(具有属性和方法的类);作为旁注,您可以将 null 分配给其实例化对象。您无需向其中添加任何内容来指示它的结束位置。容器为您控制一切。因此,它也有迭代器(或我认为 C# 中的枚举器)。这意味着您可以使用 foreachLINQ 表达式对其进行迭代。

话虽如此,您可以在与此类似的代码中使用简单的计数器来获取字符串的长度:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LengthOfString
{
    class Program
    {
        static void Main(string[] args)
        {
            string s = "abcde\0\0\0";
            Console.WriteLine(s);
            Console.WriteLine("s.Length = " + s.Length);
            Console.WriteLine();

            // Here I count the number of characters in s
            // using LINQ
            int counter = 0;
            s.ToList()
                .ForEach(ch => {
                    Console.Write(string.Format("{0} ", (int)ch));
                    counter++;
                });
            Console.WriteLine(); Console.WriteLine("LINQ: Length = " + counter);
            Console.WriteLine(); Console.WriteLine();

            //Or you could just use foreach for this
            counter = 0;
            foreach (int ch in s)
            {
                Console.Write(string.Format("{0} ", (int)ch));
                counter++;
            }
            Console.WriteLine(); Console.WriteLine("foreach: Length = " + counter);

            Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine();
            Console.WriteLine("Press ENTER");
            Console.ReadKey();
        }
    }
}

【讨论】:

    【解决方案2】:
     public static void Main()
     {
         unsafe
         {
             var s = "Naveen";
             fixed (char* cp = s)
             {
                 for (int i = 0; cp[i] != '\0'; i++)
                 {
                     Console.Write(cp[i]);
                 }
             }
         }
     }
    

    // 打印 Naveen

    【讨论】:

    • 你能解释一下吗?它没有在我的 Visual Studio 中编译。
    • 您需要使用 /unsafe 编译器选项。
    • 仅供参考,在 VS -> 项目的属性 -> 构建选项卡 -> 选中允许不安全代码。
    【解决方案3】:

    您正在尝试访问索引处的字符,该索引根据name 长度不可用。你可以这样解决:

    string name = "Naveen";    
    int c = 0;
    while (c < name.Length)
    {
        c++;
    }
    

    但是在c#中不需要计算字符串的长度这个 大大地。你可以试试name.Length

    编辑: 如果您想检查 \0 字符,则根据 @NaveenKumarV 在 cmets 中提供的内容,然后正如其他人所说,您可以尝试 ToCharArray 方法。代码如下:

    var result = name.ToCharArray().TakeWhile(i => i != '\0').ToList();
    

    【讨论】:

    • 多么无意义的方法……和name.Length一样
    • 您的方法不会那样做。 ToCharArray 会让你更接近。
    • 约束显示在while循环的条件表达式中。它告诉 inested 检查是否有空字符,他应该将长度与索引进行比较。
    • ToCharArray char != '\0'
    • @Hossein 感谢您提供替代解决方案: var result = name.ToCharArray().TakeWhile(i => i != '\0');
    【解决方案4】:

    C# 不像 C 和 C++ 那样使用以 NUL 结尾的字符串。您必须使用字符串的Length 属性。

    Console.WriteLine("Length of string " + name + " is: " + name.Length.ToString());
    

    或使用格式化程序

    Console.WriteLine("Length of string '{0}' is {1}.", name, name.Length);  
    

    【讨论】:

    • .ToString() 不需要第一行 stackoverflow.com/a/3398653/1315444
    • 别忘了$"Length of string #{name} is #{name.Length}" :)
    • @fubo 这不是必需的,但这样更明确。我喜欢它。
    猜你喜欢
    • 2012-01-02
    • 2013-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多