Проверять содержимое строки? Длина строки против пустой строки - PullRequest
13 голосов
/ 13 августа 2008

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

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

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

Ответы [ 13 ]

15 голосов
/ 13 августа 2008

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

  • Строки типа Паскаля: Length = 0.
  • Струны в стиле C: [0] == 0.
  • .NET: .IsNullOrEmpty.

Etc.

14 голосов
/ 13 августа 2008

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

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

2 голосов
/ 13 августа 2008

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

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

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

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

2 голосов
/ 13 августа 2008

В .Net:

string.IsNullOrEmpty( nystr );

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

1 голос
/ 21 февраля 2010

Если ваш вопрос .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 голос
/ 14 августа 2008

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

1 голос
/ 13 августа 2008

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

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

0 голосов
/ 13 декабря 2015

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

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

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. Проверка на равенство пустого строкового литерала и статической строки. Свойство Empty класса System.string для всех практических целей идентично. Единственное различие между двумя фрагментами кода - это источник первой команды перемещения, и оба являются смещениями относительно ds, что подразумевает, что оба относятся к запеченным константам.

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

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

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

Заключение

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

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

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

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

0 голосов
/ 02 октября 2008

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

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

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

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

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

0 голосов
/ 14 августа 2008

@ Nathan

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...