Проверка содержимого строки? строка Длина Vs Пустая строка

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

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

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

Ответы

Ответ 1

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

  • Строки типа Pascal: Length = 0.
  • Строки в стиле C: [0] == 0.
  • .NET: .IsNullOrEmpty.

Etc.

Ответ 2

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

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

Ответ 3

В .Net:

string.IsNullOrEmpty( nystr );
Строки

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

Ответ 4

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

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

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

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

Ответ 5

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

Существует также библиотека Jakarta commons, которая имеет метод isBlank. Бланк определяется как строка, содержащая только пробелы.

Ответ 6

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 wont - я знаю его что-то маленькое и тривиальное, но id еще не создает объекты, когда мне они не нужны! ( Источник)

Ответ 7

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

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

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

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

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

Ответ 8

Собственно, IMO - лучший способ определить метод IsNullOrEmpty() класса string.

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

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

Ответ 9

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

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

Ответ 10

Для строк C,

if (s[0] == 0)

будет быстрее, чем

if (strlen(s) == 0)

или

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

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

Ответ 11

@Натан

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

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

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

Ответ 12

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

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

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

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

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

Ответ 13

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

Рассмотрим следующее.

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, я делаю следующие выводы.

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

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

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

  • Учитывая, что сразу видимый машинный код почти идентичен, единственная причина, по которой я могу представить, что будет учитывать лучшую производительность равенства строк по длине строки, указанному Shinny, - это что функция с двумя аргументами, которая выполняет сравнение, значительно оптимизирована, чем функция с одним аргументом, которая считывает длину от экземпляра строки.

Заключение

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

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

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

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