Как завершаются строки в C#?

Эта программа выдает ArrayIndexOutOfBoundException.

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

Почему это так? Если строки не заканчиваются нулем. Как обрабатываются строки в C#? Как я могу получить длину без использования свойства string.Length? Я тут запутался.!


person Naveen Kumar V    schedule 25.09.2015    source источник
comment
почему вы не хотите использовать string.Length?   -  person Domysee    schedule 25.09.2015
comment
Почему бы вам не использовать свойство length для получения длины??   -  person domdomcodecode    schedule 25.09.2015
comment
Я хочу завершить данную строку, где в строку включено «\ 0».? например: Nav\0een.   -  person Naveen Kumar V    schedule 25.09.2015
comment
Почему это так? Поскольку строки с нулевым завершением - плохая идея... это означает, что строки не могут содержать встроенные нулевые символы, и вы не можете найти длину строки, не перебирая ее...   -  person Jon Skeet    schedule 25.09.2015
comment
Каким же образом эта строка завершается нулем? Это строка длиной 7, а не строка длиной 3. Вы можете легко найти часть перед первым нулевым символом и взять эту подстроку, если хотите, но вам действительно следует подробнее объяснить почему вы хотите это сделать, поскольку это достаточно странное требование.   -  person Jon Skeet    schedule 25.09.2015
comment
в .net String — это класс MSDN. Это не нулевое завершение char[], как в С++.   -  person bansi    schedule 25.09.2015
comment
Он завершается нулем. Но обертка вокруг него обрабатывает ПОЧТИ ВСЁ   -  person kevintjuh93    schedule 25.09.2015
comment
@all Спасибо за ваши усилия, чтобы заставить меня понять :)   -  person Naveen Kumar V    schedule 25.09.2015


Ответы (4)


C# не использует строки с завершением NUL, как C и C++. Вы должны использовать свойство Length строки.

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

или с помощью форматтеров

Console.WriteLine("Length of string '{0}' is {1}.", name, name.Length);  
person Richard Schneider    schedule 25.09.2015
comment
.ToString() в 1-й строке не требуется stackoverflow.com/a/3398653/1315444 - person fubo; 25.09.2015
comment
Не забудьте $"Length of string #{name} is #{name.Length}" :) - person async; 25.09.2015
comment
@fubo Это не обязательно, но так более явно. Мне это нравится. - person Søren Lorentzen; 25.09.2015

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

// печатает Навин

person yue shi    schedule 25.09.2015
comment
Вы можете это объяснить? Он не компилируется в моей Visual Studio. - person Naveen Kumar V; 25.09.2015
comment
Вам нужно использовать параметр /unsafe компилятора. - person yue shi; 25.09.2015
comment
К вашему сведению, в VS -> Свойства проекта -> вкладка сборки -> Установите флажок Разрешить небезопасный код. - person Naveen Kumar V; 25.09.2015

В C/C++ строка хранится в массиве char AFAIR без интеллекта и поведения. Следовательно, чтобы указать, что такой массив где-то заканчивается, нужно было добавить \0 в конце.

С другой стороны, в C# строка — это контейнер (класс со свойствами и методами); в качестве побочного примечания вы можете присвоить null его созданному объекту. Вам не нужно ничего добавлять к нему, чтобы указать, где он заканчивается. Контейнер управляет всем за вас. Таким образом, у него также есть итератор (или, я думаю, перечислитель в С#). Это означает, что вы можете использовать выражения foreach и LINQ для его повторения.

Сказав это, вы можете использовать простой счетчик в коде, подобном этому, чтобы получить длину строки:

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();
        }
    }
}
person Celdor    schedule 25.09.2015

Вы пытаетесь получить доступ к символу по индексу, который недоступен в соответствии с длиной name. Вы можете решить это следующим образом:

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

Однако таким образом нет необходимости подсчитывать длину строки в С#. Вы можете попробовать просто name.Length

EDIT: на основе того, что @NaveenKumarV предоставляет в комментариях, если вы хотите проверить наличие \0 символов, тогда, как говорили другие, вы можете попробовать метод ToCharArray. Вот код:

var result = name.ToCharArray().TakeWhile(i => i != '\0').ToList();
person Hossein Narimani Rad    schedule 25.09.2015
comment
Что за бессмысленный метод... это то же самое, что и name.Length - person kevintjuh93; 25.09.2015
comment
Ваш метод НЕ делает этого. ToCharArray сделает вас ближе. - person kevintjuh93; 25.09.2015
comment
Ограничение показано в условном выражении в цикле while. Он сообщает, что при проверке нулевого символа он должен сравнить длину с индексом. - person Hossein Narimani Rad; 25.09.2015
comment
@Hossein Спасибо за альтернативное решение: var result = name.ToCharArray().TakeWhile(i =› i != '\0'); - person Naveen Kumar V; 25.09.2015
comment
@NaveenKumarV рад быть полезным - person Hossein Narimani Rad; 25.09.2015