12

Cái nào hiệu quả hơn cho trình biên dịch và cách thực hành tốt nhất để kiểm tra xem một chuỗi có trống không?Kiểm tra nội dung chuỗi? string Length Vs Empty String

  1. Kiểm tra xem chiều dài của chuỗi == 0
  2. Kiểm tra xem chuỗi rỗng (strVar == "")

Ngoài ra, không câu trả lời phụ thuộc vào ngôn ngữ?

Trả lời

15

Có, tùy thuộc vào ngôn ngữ, vì lưu trữ chuỗi khác nhau giữa các ngôn ngữ.

  • Chuỗi loại Pascal: Length = 0.
  • Chuỗi kiểu C: [0] == 0.
  • .NET: .IsNullOrEmpty.

vv

+2

Tôi nghĩ rằng OP đã hỏi về xác nhận chuỗi trống, không phải là vô hiệu, vì vậy khi bạn đã biết rằng chuỗi không phải là null, việc sử dụng IsNullOrEmpty chỉ là một kiểm tra không cần thiết khác. Vì vậy, câu hỏi của OP là những gì có hiệu suất hơn, myString.Length> 0 hoặc myString! = "". Đọc http://stackoverflow.com/questions/10230/checking-for-string-contents-string-length-vs-empty-string/2306659#2306659 – Shimmy

2

Trong Net:

string.IsNullOrEmpty(nystr); 

chuỗi có thể được null, vì vậy .Length đôi khi ném một NullReferenceException

13

Trong các ngôn ngữ sử dụng các chuỗi kiểu C (null-chấm dứt), so sánh với "" sẽ nhanh hơn. Đó là một hoạt động O (1), trong khi lấy chiều dài của một chuỗi kiểu C là O (n).

Trong các ngôn ngữ lưu trữ độ dài như một phần của đối tượng chuỗi (C#, Java, ...), hãy kiểm tra độ dài cũng là O (1). Trong trường hợp này, việc kiểm tra trực tiếp chiều dài nhanh hơn, bởi vì nó tránh được chi phí xây dựng chuỗi rỗng mới.

+3

Trong C#, nếu bạn so sánh với chuỗi.Empty thì bạn là bạn đang so sánh với một chuỗi đã được xây dựng. Sau đó, nó là O (1) là tốt. –

1

Trong Java 1.6, lớp String có một phương pháp mới isEmpty

Ngoài ra còn có các commons Jakarta thư viện, trong đó có phương pháp isBlank. Trống được định nghĩa là một chuỗi chỉ chứa khoảng trắng.

0

Trong trường hợp này, kiểm tra trực tiếp chiều dài nhanh hơn, bởi vì nó tránh được chi phí xây dựng chuỗi trống mới.

@DerekPark: Điều đó không phải lúc nào cũng đúng. "" là một chuỗi ký tự như vậy, trong Java, nó gần như chắc chắn đã được thực tập.

0

Đối với chuỗi C,

if (s[0] == 0) 

sẽ nhanh hơn so với một trong hai

if (strlen(s) == 0) 

hoặc

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

bởi vì bạn sẽ tránh được những chi phí của một cuộc gọi chức năng.

2

Trong các ngôn ngữ sử dụng C-style chuỗi (null-terminated), so với "" sẽ nhanh hơn

Trên thực tế, nó có thể tốt hơn để kiểm tra xem char đầu tiên trong chuỗi là ' \ 0 ':

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

Trong Perl có tùy chọn thứ ba, chuỗi đó chưa được xác định. Đây là một chút khác nhau từ một con trỏ NULL trong C, nếu chỉ vì bạn không nhận được một lỗi phân đoạn để truy cập một chuỗi không xác định.

0

@ Nathan

Trên thực tế, nó có thể tốt hơn để kiểm tra xem char đầu tiên trong chuỗi là '\ 0':

Tôi gần như đã đề cập rằng, nhưng cuối cùng lại rời nó ra , kể từ khi gọi strcmp() với chuỗi rỗng và trực tiếp kiểm tra ký tự đầu tiên trong chuỗi là cả O (1). Bạn về cơ bản chỉ trả tiền cho một cuộc gọi chức năng bổ sung, đó là khá rẻ. Nếu bạn thực sự cần tốc độ tốt nhất tuyệt đối, mặc dù, chắc chắn đi với một so sánh trực tiếp-char-to-0.

Thành thật mà nói, tôi luôn sử dụng strlen() == 0, vì tôi có không bao giờ viết chương trình thực sự là vấn đề hiệu suất có thể đo lường được và tôi nghĩ đó là cách dễ đọc nhất để thể hiện séc.

1

String.IsNullOrEmpty() chỉ hoạt động trên .net 2.0 trở lên, cho .net 1/1.1, tôi có xu hướng sử dụng:

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

tôi sử dụng String.Empty như trái ngược với "" bởi vì "" sẽ tạo ra một đối tượng , trong khi String.Empty wont - Tôi biết một cái gì đó của nó nhỏ và tầm thường, nhưng id vẫn không tạo ra các đối tượng khi tôi không cần chúng! (Source)

+0

Tôi sẽ thực sự ngạc nhiên nếu "" thực sự dẫn đến một sự khởi tạo bên trong trình biên dịch C#. – jsight

+1

Sử dụng 'inputString.Length == 0', thay vì 'inputString == String.Empty' để có hiệu suất tốt hơn –

+0

Id cho rằng inputString == String.Empty dễ đọc hơn .Length == 0 ... –

0

Một lần nữa, không biết ngôn ngữ, không thể nói được.

Tuy nhiên, tôi khuyên bạn nên chọn kỹ thuật phù hợp nhất với người lập trình bảo trì sau và sẽ phải duy trì công việc của bạn.

tôi khuyên bạn nên viết một hàm một cách rõ ràng những gì bạn muốn, chẳng hạn như

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

hoặc tương đương. Bây giờ không có nghi ngờ tại là bạn đang kiểm tra.

1

Giả sử câu hỏi của bạn là.NET:

Nếu bạn muốn xác thực chuỗi của mình với giá trị rỗng cũng như sử dụng IsNullOrEmpty, nếu bạn biết rằng chuỗi của bạn không rỗng, ví dụ khi kiểm tra TextBox.Text v.v., không sử dụng IsNullOrEmpty, và sau đó đi kèm câu hỏi của bạn.
Vì vậy, đối với ý kiến ​​của tôi String.Length là ít perfomance hơn so sánh chuỗi.

tôi sự kiện thử nghiệm nó (Tôi cũng đã thử nghiệm với C#, cùng kết quả):

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 

Kết quả:

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

Có nghĩa là so sánh có cách hơn kiểm tra chiều dài chuỗi.

+0

Tuy nhiên, trong. Net bạn có thể tránh so sánh chuỗi rõ ràng bằng cách so sánh với chuỗi.Empty chứ không phải chuỗi rỗng (""). Điều đó sẽ làm cho nó trở thành một hoạt động O (1). –

+0

Tôi nghĩ rằng string.Empty chỉ giống như chữ "", tôi thực sự không nhận được sự khác biệt. – Shimmy

+0

string.Empty là một thể hiện của lớp chuỗi có giá trị là "". Tuy nhiên chuỗi quá tải cho Equals và (==) sẽ làm so sánh tham chiếu trước khi nó thực hiện một nhân vật để so sánh nhân vật. Nếu các tham chiếu bằng nhau so với so sánh nhân vật bị bỏ qua. Vì vậy, so sánh một giá trị là string.Empty đến string.Empty sẽ nhanh hơn đáng kể so với so sánh nó với "", nó sẽ tạo ra một đối tượng chuỗi mới và đặt giá trị ban đầu của nó thành "". Chúng không giống nhau. –

0

Sau khi đọc chủ đề này, tôi đã thực hiện một thí nghiệm nhỏ, mang lại hai phát hiện khác biệt và thú vị.

Hãy xem xét những điều sau đây.

strInstallString "1" string 

Ở trên được sao chép từ cửa sổ cục bộ của trình gỡ lỗi Visual Studio. Cùng một giá trị được sử dụng trong cả ba ví dụ sau.

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

Tiếp theo là các mã được hiển thị trong cửa sổ tháo của Visual Studio 2013 debugger cho hai về cơ bản giống hệt nhau các trường hợp.

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) là không đáng kể khác nhau

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 

Từ danh sách mã máy trên, được tạo ra bởi các mô-đun NGEN của .NET Framework, phiên bản 4.5 , Tôi rút ra các kết luận sau đây.

  1. Kiểm tra tính bình đẳng đối với chuỗi ký tự trống và chuỗi tĩnh.Địa chỉ trống trên lớp System.string, cho tất cả mục đích thực tế, giống hệt nhau. Sự khác biệt duy nhất giữa hai đoạn mã là nguồn của lệnh di chuyển đầu tiên, và cả hai đều là các offset tương ứng với ds, ngụ ý rằng cả hai tham chiếu đến các hằng số được nạp sẵn.

  2. Kiểm tra tính bình đẳng đối với chuỗi trống, dưới dạng thuộc tính theo chuỗi hoặc thuộc tính string.Empty, thiết lập cuộc gọi hàm hai đối số, cho biết bất bình đẳng bằng cách trả về số không. Tôi căn cứ vào kết luận này về các bài kiểm tra khác mà tôi đã thực hiện một vài tháng trước, trong đó tôi theo một số mã của riêng tôi trên phân chia quản lý/không được quản lý và ngược lại. Trong mọi trường hợp, bất kỳ cuộc gọi nào yêu cầu hai hoặc nhiều đối số đều đặt đối số đầu tiên trong ECX đăng ký và đối số thứ hai trong thanh ghi EDX. Tôi không nhớ các lập luận tiếp theo đã được thông qua như thế nào. Tuy nhiên, thiết lập cuộc gọi trông giống như __fastcall hơn __stdcall. Tương tự như vậy, giá trị trả về dự kiến ​​luôn hiển thị trong EAX đăng ký, gần như là phổ biến.

  3. Kiểm tra độ dài của chuỗi thiết lập cuộc gọi hàm một đối số, trả về 1 (trong EAX đăng ký), xảy ra là độ dài của chuỗi đang được kiểm tra.Cho rằng mã máy ngay lập tức có thể nhìn thấy gần như giống hệt nhau, lý do duy nhất tôi có thể hình dung rằng hiệu suất của chuỗi bình đẳng trên chiều dài sting được báo cáo bởi Shinny là hàm hai đối số thực hiện so sánh được tối ưu hóa tốt hơn đáng kể so với hàm một đối số đọc độ dài của thể hiện chuỗi.

Kết luận

Là một vấn đề nguyên tắc, tôi tránh so sánh với chuỗi rỗng như một chữ, vì chuỗi rỗng đen có thể xuất hiện mơ hồ trong mã nguồn. Để kết thúc, các lớp trợ giúp .NET của tôi từ lâu đã định nghĩa chuỗi rỗng làm hằng số. Mặc dù tôi sử dụng chuỗi.Empty để so sánh trực tiếp, nội tuyến kiếm được hằng số để xác định các hằng số khác có giá trị là chuỗi rỗng, vì hằng số không thể được gán string.Empty làm giá trị của nó.

Bài tập này giải quyết, một lần và cho tất cả mọi thắc mắc về chi phí, nếu có, so sánh với số chuỗi.Empty hoặc hằng số được xác định bởi lớp trợ giúp của tôi.

Tuy nhiên, nó cũng đặt ra một câu hỏi khó hiểu để thay thế nó; tại sao so sánh với string.Empty hiệu quả hơn kiểm tra độ dài của chuỗi? Hoặc là thử nghiệm được sử dụng bởi Shinny vô hiệu hóa bởi vì bằng cách vòng lặp được thực hiện? (Tôi thấy khó tin, nhưng, sau đó một lần nữa, tôi đã bị lừa trước đây, như tôi chắc chắn rằng bạn có, quá!)

Tôi đã giả định rằng hệ thống.string đối tượng được tính chuỗi, về cơ bản tương tự như chuỗi cơ bản được thiết lập lâu dài (BSTR) mà chúng ta đã biết từ lâu từ COM.

Các vấn đề liên quan