Проверять содержимое строки? Длина строки против пустой строки

Что является более эффективным для компилятора и лучший способ проверить, является ли строка пустой?

  1. Проверка, соответствует ли длина строки == 0
  2. Проверка, является ли строка пустой (strVar == "")

Кроме того, зависит ли ответ от языка?

13 ОТВЕТОВ
РЕШЕНИЕ

Да, это зависит от языка, так как хранение строк отличается в разных языках.

  • Строки Паскаля типа: Length = 0.
  • Строки C-стиль: [0] == 0.
  • .NET: .IsNullOrEmpty.

И т.п.

17
7.02.2016 18:30:08
Я думаю, что OP спрашивал о проверке пустых строк, а не обнулении, поэтому, когда вы уже знаете, что строка не является нулевой, использование IsNullOrEmpty является просто еще одной ненужной проверкой. Поэтому вопрос ОП заключается в том, что требует большей производительности: myString.Length> 0 или myString! = "". Читайте stackoverflow.com/questions/10230/…
Shimmy 21.02.2010 18:49:48

В .Net:

string.IsNullOrEmpty( nystr );

строки могут быть нулевыми, поэтому .Length иногда создает исключение NullReferenceException

2
13.08.2008 19:05:54

На самом деле IMO лучший способ определить это метод IsNullOrEmpty () класса string.

http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.

Обновление: я предположил .Net, на других языках, это может быть иначе.

0
13.08.2008 19:06:38

В языках, которые используют строки в стиле C (с нулевым символом в конце), сравнение ""будет быстрее. Это операция O (1), в то время как длина строки в стиле C равна O (n).

В языках, которые хранят длину как часть строкового объекта (C #, Java, ...), проверка длины также составляет O (1). В этом случае прямая проверка длины выполняется быстрее, поскольку она позволяет избежать затрат на создание новой пустой строки.

15
13.08.2008 19:12:19
В C #, если вы сравниваете с string.Empty, то вы сравниваете с уже созданной строкой. Тогда это тоже O (1).
Orion Adrian 1.11.2011 14:23:45

В Java 1.6 класс String имеет новый метод isEmpty

Также есть библиотека Джакарты, в которой есть метод isBlank . Пустой определяется как строка, которая содержит только пробелы.

1
13.08.2008 19:49:48

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

@DerekPark: это не всегда так. "" является строковым литералом, поэтому в Java он почти наверняка уже будет интернирован.

0
13.08.2008 19:35:37

Для струн C,

if (s[0] == 0)

будет быстрее чем либо

if (strlen(s) == 0)

или

if (strcmp(s, "") == 0)

потому что вы избежите накладных расходов при вызове функции.

0
13.08.2008 19:51:33

В языках, которые используют строки в стиле C (с нулевым символом в конце), сравнение с "" будет быстрее

На самом деле, может быть лучше проверить, является ли первый символ в строке '\ 0':

char *mystring;
/* do something with the string */
if ((mystring != NULL) && (mystring[0] == '\0')) {
    /* the string is empty */
}

В Perl есть третий вариант, что строка не определена. Это немного отличается от NULL-указателя в C, хотя бы потому, что вы не получите ошибку сегментации для доступа к неопределенной строке.

2
13.08.2008 19:56:15

@Натан

На самом деле, может быть лучше проверить, является ли первый символ в строке '\ 0':

Я почти упомянул об этом, но в итоге не учел это, поскольку вызов strcmp()с пустой строкой и прямая проверка первого символа в строке - это O (1). Вы просто платите за дополнительный вызов функции, который довольно дешев. Если вам действительно нужна абсолютная лучшая скорость, определенно используйте прямое сравнение «первый символ с нулем».

Честно говоря, я всегда использую strlen() == 0, потому что я никогда не писал программу, где это было бы измеримой проблемой производительности, и я думаю, что это самый читаемый способ выразить проверку.

0
13.08.2008 20:00:55

String.IsNullOrEmpty() работает только на .net 2.0 и выше, для .net 1 / 1.1 я склонен использовать:

if (inputString == null || inputString == String.Empty)
{
    // String is null or empty, do something clever here. Or just expload.
}

Я использую String.Empty, а не "" потому что "" создаст объект, тогда как String.Empty не будет - я знаю, что это что-то маленькое и тривиальное, но id все равно не создает объекты, когда они мне не нужны! ( Источник )

2
7.02.2016 18:30:17
Я был бы очень удивлен, если "" на самом деле приводит к созданию экземпляра внутри компилятора C #.
jsight 23.09.2008 20:27:51
Используйте «inputString.Length == 0» вместо «inputString == String.Empty» для повышения производительности
Matt Lacey 2.10.2008 08:37:40

Опять же, не зная языка, невозможно сказать.

Тем не менее, я рекомендую вам выбрать метод, который больше всего подходит программисту по техническому обслуживанию, который следует и должен будет поддерживать вашу работу.

Я бы порекомендовал написать функцию, которая явно делает то, что вы хотите, например,

#define IS_EMPTY(s) ((s)[0]==0)

или сопоставимы. Теперь нет никаких сомнений в том, что вы проверяете.

0
2.10.2008 17:32:08

Предполагая, что ваш вопрос .NET:

Если вы хотите проверить вашу строку на предмет отсутствия значений, также используйте IsNullOrEmpty, если вы уже знаете, что ваша строка не равна нулю, например, при проверке TextBox.Text и т. Д., Не используйте IsNullOrEmpty, и тогда возникает вопрос.
Так что, на мой взгляд, String.Length меньше производительности, чем сравнение строк.

Я проверил это событие (я также тестировал с C #, тот же результат):

Module Module1
  Sub Main()
    Dim myString = ""


    Dim a, b, c, d As Long

    Console.WriteLine("Way 1...")

    a = Now.Ticks
    For index = 0 To 10000000
      Dim isEmpty = myString = ""
    Next
    b = Now.Ticks

    Console.WriteLine("Way 2...")

    c = Now.Ticks
    For index = 0 To 10000000
      Dim isEmpty = myString.Length = 0
    Next
    d = Now.Ticks

    Dim way1 = b - a, way2 = d - c

    Console.WriteLine("way 1 took {0} ticks", way1)
    Console.WriteLine("way 2 took {0} ticks", way2)
    Console.WriteLine("way 1 took {0} ticks more than way 2", way1 - way2)
    Console.Read()
  End Sub
End Module

Результат:

Way 1...
Way 2...
way 1 took 624001 ticks
way 2 took 468001 ticks
way 1 took 156000 ticks more than way 2

Это означает, что сравнение занимает гораздо больше времени, чем проверка длины строки.

1
21.02.2010 22:00:31
Однако в .Net вы можете избежать явного сравнения строк, сравнивая их с string.Empty, а не с пустой строкой (""). Это должно сделать это O (1) операция.
Orion Adrian 1.11.2011 14:32:57
Я думаю, что string.Empty такой же буквальный, как и "", я действительно не понимаю разницу.
Shimmy 1.11.2011 22:47:45
string.Empty является экземпляром класса string, значение которого равно "". Однако перегрузка строки для Equals и (==) выполнит сравнение ссылок перед тем, как выполнить сравнение символов. Если ссылки равны, сравнение символов пропускается. Таким образом, сравнение значения string.Empty со string.Empty будет значительно быстрее, чем сравнение его с "", которое сгенерирует новый строковый объект и установит его начальное значение равным "". Они не одинаковы.
Orion Adrian 2.11.2011 20:53:39

После прочтения этой темы я провел небольшой эксперимент, который дал два отличных и интересных вывода.

Учтите следующее.

strInstallString    "1" string

Вышеупомянутое скопировано из локального окна отладчика Visual Studio. Одно и то же значение используется во всех трех следующих примерах.

if (strInstallString == "") === if (strInstallString == string.Empty)

Ниже приведен код, отображаемый в окне разборки отладчика Visual Studio 2013 для этих двух принципиально идентичных случаев.

if ( strInstallString == "" )
003126FB  mov         edx,dword ptr ds:[31B2184h]
00312701  mov         ecx,dword ptr [ebp-50h]
00312704  call        59DEC0B0            ; On return, EAX = 0x00000000.
00312709  mov         dword ptr [ebp-9Ch],eax
0031270F  cmp         dword ptr [ebp-9Ch],0
00312716  sete        al
00312719  movzx       eax,al
0031271C  mov         dword ptr [ebp-64h],eax
0031271F  cmp         dword ptr [ebp-64h],0
00312723  jne         00312750

if ( strInstallString == string.Empty )
00452443  mov         edx,dword ptr ds:[3282184h]
00452449  mov         ecx,dword ptr [ebp-50h]
0045244C  call        59DEC0B0        ; On return, EAX = 0x00000000.
00452451  mov         dword ptr [ebp-9Ch],eax
00452457  cmp         dword ptr [ebp-9Ch],0
0045245E  sete        al
00452461  movzx       eax,al
00452464  mov         dword ptr [ebp-64h],eax
00452467  cmp         dword ptr [ebp-64h],0
0045246B  jne         00452498

if (strInstallString == string.Empty) существенно не отличается

if ( strInstallString.Length == 0 )
003E284B  mov         ecx,dword ptr [ebp-50h]
003E284E  cmp         dword ptr [ecx],ecx
003E2850  call        5ACBC87E        ; On return, EAX = 0x00000001.
003E2855  mov         dword ptr [ebp-9Ch],eax
003E285B  cmp         dword ptr [ebp-9Ch],0
003E2862  setne       al
003E2865  movzx       eax,al
003E2868  mov         dword ptr [ebp-64h],eax
003E286B  cmp         dword ptr [ebp-64h],0
003E286F  jne         003E289C

Из приведенных выше списков машинного кода, сгенерированных модулем NGEN .NET Framework версии 4.5, я делаю следующие выводы.

  1. Проверка на равенство пустого строкового литерала и статического свойства string.Empty в классе System.string для всех практических целей идентична. Единственное различие между двумя фрагментами кода - источник первой команды перемещения, и оба являются смещениями относительно ds, подразумевая, что оба ссылаются на запеченные константы.

  2. Проверка на равенство с пустой строкой, как литералом, так и свойством string.Empty, устанавливает вызов функции с двумя аргументами, который указывает на неравенство , возвращая ноль. Я основываю этот вывод на других тестах, которые я выполнил пару месяцев назад, в которых я следовал некоторым собственным кодам через управляемое / неуправляемое разделение и обратно. Во всех случаях при любом вызове, требующем двух или более аргументов, первый аргумент помещается в регистр ECX, а второй - в регистр EDX. Я не помню, как были переданы последующие аргументы. Тем не менее, настройка вызова была больше похожа на __fastcall, чем __stdcall. Аналогично, ожидаемые возвращаемые значения всегда обнаруживались в регистре EAX, который является почти универсальным.

  3. Проверка длины строки устанавливает вызов функции с одним аргументом, который возвращает 1 (в регистре EAX), что соответствует длине тестируемой строки.

  4. Учитывая, что машинный код, видимый сразу же, почти идентичен, единственная причина, по которой я могу представить, что это объясняет лучшую производительность равенства строк по длине строки, о которой сообщает Шинни, заключается в том, что функция с двумя аргументами, которая выполняет сравнение, значительно лучше оптимизирован, чем функция с одним аргументом, которая считывает длину из экземпляра строки.

Заключение

В принципе, я избегаю сравнения с пустой строкой как литералом, потому что литерал пустой строки может выглядеть неоднозначно в исходном коде. Для этого мои вспомогательные классы .NET давно определили пустую строку как константу. Хотя я использую string.Empty для прямых, встроенных сравнений, константа зарабатывает свое время для определения других констант, значение которых является пустой строкой, потому что константе не может быть присвоено string.Empty в качестве ее значения.

Это упражнение раз и навсегда решает любую проблему, которую я могу иметь в связи со стоимостью, если таковая имеется, сравнения со строкой.Empty или константой, определенной моими вспомогательными классами.

Однако, это также поднимает загадочный вопрос, чтобы заменить его; почему сравнение со string.Empty более эффективно, чем проверка длины строки? Или тест, используемый Шинни, признан недействительным из-за того, как реализован цикл? (Мне трудно в это поверить, но опять же, я был одурачен раньше, как, я уверен, и вы тоже!)

Я давно предполагал, что объекты system.string были подсчитанными строками, в основном похожими на давно установленную Basic String (BSTR), которую мы давно знаем из COM.

1
13.12.2015 07:13:43