Làm cách nào để lấy số ký tự trong chuỗi std ::?


112

Làm cách nào để lấy số ký tự trong một chuỗi trong C ++?


1
Bạn đang xử lý loại chuỗi nào? std :: chuỗi? chuỗi C? chuỗi kết thúc null?
Steve Rowe

Cách chống đánh lừa tốt nhất là lặp lại nó và tự đếm các ký tự.
Krythic

Câu trả lời:


177

Nếu bạn đang sử dụng std::string, hãy gọi length():

std::string str = "hello";
std::cout << str << ":" << str.length();
// Outputs "hello:5"

Nếu bạn đang sử dụng chuỗi c, hãy gọi strlen().

const char *str = "hello";
std::cout << str << ":" << strlen(str);
// Outputs "hello:5"

Hoặc, nếu bạn tình cờ thích sử dụng chuỗi kiểu Pascal (hoặc chuỗi f ***** như Joel Spolsky thích gọi chúng khi chúng có dấu NULL), chỉ cần bỏ qua ký tự đầu tiên.

const char *str = "\005hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"

7
Ai trong tâm trí của họ sẽ sử dụng chuỗi kiểu Pascal?
Xarn

17
length () không trả về số byte chứ không phải số ký tự?

2
Đối với một chuỗi std :: cũng giống như vậy (trừ khi bạn đang lưu trữ mã hóa có độ dài thay đổi hoặc sử dụng chuỗi std :: để lưu trữ các ký tự nhiều byte). Nếu bạn đang làm điều đó, bạn sẽ không nhận được nhiều trợ giúp với bất kỳ thứ gì từ thư viện std, vì vậy bạn cũng có thể xử lý việc lăn strlen của riêng mình. Đối với wstring, u16string và u32string, nó trả về số lượng ký tự thay vì byte. (Một lần nữa với điều kiện là nếu bạn đang sử dụng mã hóa có độ dài thay đổi trong bất kỳ mã nào trong số đó, bạn sẽ phải cuộn strlen của riêng mình).
Nhật thực

4
Nó sẽ làm tăng thêm giá trị cho câu trả lời được đánh giá cao này đề cập đến các kiểu trả về: std::size_t.
chux - Phục hồi Monica

3
@Eclipse +1 cho chuỗi f *** ed
Sнаđошƒаӽ

23

Khi xử lý các chuỗi C ++ (std :: string), bạn đang tìm kiếm chiều dài () hoặc kích thước () . Cả hai sẽ cung cấp cho bạn giá trị như nhau. Tuy nhiên, khi xử lý các chuỗi C-Style, bạn sẽ sử dụng strlen () .

#include <iostream>
#include <string.h>

int main(int argc, char **argv)
{
   std::string str = "Hello!";
   const char *otherstr = "Hello!"; // C-Style string
   std::cout << str.size() << std::endl;
   std::cout << str.length() << std::endl;
   std::cout << strlen(otherstr) << std::endl; // C way for string length
   std::cout << strlen(str.c_str()) << std::endl; // convert C++ string to C-string then call strlen
   return 0;
}

Đầu ra:

6
6
6
6

5
Lưu ý rằng bạn có thể tránh các cảnh báo trình biên dịch (trong một số trình biên dịch C ++) bằng cách sử dụng #include <cstring> thay vì NỮA #include <string.h>
Colin

1
Ví dụ của bạn chỉ sử dụng ASCII. Bạn có phiền cập nhật nó cho các ký tự Unicode không? Đặc biệt là những người 32 bit chẳng hạn như 𝄞
Thomas Weller

17

Nó phụ thuộc vào loại chuỗi bạn đang nói đến. Có nhiều loại dây:

  1. const char* - một chuỗi multibyte kiểu C
  2. const wchar_t* - một dây rộng kiểu C
  3. std::string - một chuỗi multibyte "tiêu chuẩn"
  4. std::wstring - một chuỗi rộng "tiêu chuẩn"

Đối với 3 và 4, bạn có thể sử dụng .size()hoặc .length()các phương pháp.

Đối với 1, bạn có thể sử dụng strlen(), nhưng bạn phải đảm bảo rằng biến chuỗi không phải là NULL (=== 0)

Đối với 2, bạn có thể sử dụng wcslen(), nhưng bạn phải đảm bảo rằng biến chuỗi không phải là NULL (=== 0)

Có các kiểu chuỗi khác trong các thư viện C ++ không chuẩn, chẳng hạn như MFC CString, ATL CComBSTR, ACE ACE_CString, v.v., với các phương thức như .GetLength(), v.v. Tôi không thể nhớ chi tiết cụ thể của tất cả chúng ngay trên đỉnh đầu của mình.

Các thư viện STLSoft đã tóm tắt tất cả điều này với cái mà họ gọi là miếng đệm truy cập chuỗi , có thể được sử dụng để lấy độ dài chuỗi (và các khía cạnh khác) từ bất kỳ loại nào. Vì vậy, đối với tất cả những điều trên (bao gồm cả những thư viện không chuẩn) sử dụng cùng một chức năng stlsoft::c_str_len(). Bài viết này mô tả cách tất cả hoạt động, vì nó không hoàn toàn rõ ràng hoặc dễ dàng.


1
Cái nào phù hợp với các ký tự 32 bit như 𝄞?
Thomas Weller

4

Đối với Unicode

Một số câu trả lời ở đây đã được giải quyết .length()cho kết quả sai với các ký tự nhiều byte, nhưng có 11 câu trả lời và không có câu trả lời nào trong số đó cung cấp giải pháp.

Trường hợp của Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚

Trước hết, điều quan trọng là phải biết ý của bạn về "độ dài". Đối với một ví dụ thúc đẩy, hãy xem xét chuỗi "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (lưu ý rằng một số ngôn ngữ, đặc biệt là tiếng Thái, thực sự sử dụng kết hợp các dấu phụ, vì vậy điều này không chỉ hữu ích cho meme 15 tuổi, nhưng rõ ràng đó là trường hợp sử dụng quan trọng nhất) . Giả sử nó được mã hóa bằng UTF-8 . Có 3 cách chúng ta có thể nói về độ dài của chuỗi này:

95 byte

00000000: 5acd a5cd accc becd 89cc b3cc ba61 cc92  Z............a..
00000010: cc92 cd8c cc8b cdaa ccb4 cd95 ccb2 6ccd  ..............l.
00000020: a4cc 80cc 9acc 88cd 9ccc a8cd 8ecc b0cc  ................
00000030: 98cd 89cc 9f67 cc92 cd9d cd85 cd95 cd94  .....g..........
00000040: cca4 cd96 cc9f 6fcc 90cd afcc 9acc 85cd  ......o.........
00000050: aacc 86cd a3cc a1cc b5cc a1cc bccd 9a    ...............

50 điểm mã

LATIN CAPITAL LETTER Z
COMBINING LEFT ANGLE BELOW
COMBINING DOUBLE LOW LINE
COMBINING INVERTED BRIDGE BELOW
COMBINING LATIN SMALL LETTER I
COMBINING LATIN SMALL LETTER R
COMBINING VERTICAL TILDE
LATIN SMALL LETTER A
COMBINING TILDE OVERLAY
COMBINING RIGHT ARROWHEAD BELOW
COMBINING LOW LINE
COMBINING TURNED COMMA ABOVE
COMBINING TURNED COMMA ABOVE
COMBINING ALMOST EQUAL TO ABOVE
COMBINING DOUBLE ACUTE ACCENT
COMBINING LATIN SMALL LETTER H
LATIN SMALL LETTER L
COMBINING OGONEK
COMBINING UPWARDS ARROW BELOW
COMBINING TILDE BELOW
COMBINING LEFT TACK BELOW
COMBINING LEFT ANGLE BELOW
COMBINING PLUS SIGN BELOW
COMBINING LATIN SMALL LETTER E
COMBINING GRAVE ACCENT
COMBINING DIAERESIS
COMBINING LEFT ANGLE ABOVE
COMBINING DOUBLE BREVE BELOW
LATIN SMALL LETTER G
COMBINING RIGHT ARROWHEAD BELOW
COMBINING LEFT ARROWHEAD BELOW
COMBINING DIAERESIS BELOW
COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW
COMBINING PLUS SIGN BELOW
COMBINING TURNED COMMA ABOVE
COMBINING DOUBLE BREVE
COMBINING GREEK YPOGEGRAMMENI
LATIN SMALL LETTER O
COMBINING SHORT STROKE OVERLAY
COMBINING PALATALIZED HOOK BELOW
COMBINING PALATALIZED HOOK BELOW
COMBINING SEAGULL BELOW
COMBINING DOUBLE RING BELOW
COMBINING CANDRABINDU
COMBINING LATIN SMALL LETTER X
COMBINING OVERLINE
COMBINING LATIN SMALL LETTER H
COMBINING BREVE
COMBINING LATIN SMALL LETTER A
COMBINING LEFT ANGLE ABOVE

5 grapheme

Z with some s**t
a with some s**t
l with some s**t
g with some s**t
o with some s**t

Tìm độ dài bằng ICU

Có các lớp C ++ cho ICU, nhưng chúng yêu cầu chuyển đổi sang UTF-16. Bạn có thể sử dụng trực tiếp các loại C và macro để nhận được một số hỗ trợ UTF-8:

#include <memory>
#include <iostream>
#include <unicode/utypes.h>
#include <unicode/ubrk.h>
#include <unicode/utext.h>

//
// C++ helpers so we can use RAII
//
// Note that ICU internally provides some C++ wrappers (such as BreakIterator), however these only seem to work
// for UTF-16 strings, and require transforming UTF-8 to UTF-16 before use.
// If you already have UTF-16 strings or can take the performance hit, you should probably use those instead of
// the C functions. See: http://icu-project.org/apiref/icu4c/
//
struct UTextDeleter { void operator()(UText* ptr) { utext_close(ptr); } };
struct UBreakIteratorDeleter { void operator()(UBreakIterator* ptr) { ubrk_close(ptr); } };
using PUText = std::unique_ptr<UText, UTextDeleter>;
using PUBreakIterator = std::unique_ptr<UBreakIterator, UBreakIteratorDeleter>;

void checkStatus(const UErrorCode status)
{
    if(U_FAILURE(status))
    {
        throw std::runtime_error(u_errorName(status));
    }
}

size_t countGraphemes(UText* text)
{
    // source for most of this: http://userguide.icu-project.org/strings/utext
    UErrorCode status = U_ZERO_ERROR;
    PUBreakIterator it(ubrk_open(UBRK_CHARACTER, "en_us", nullptr, 0, &status));
    checkStatus(status);
    ubrk_setUText(it.get(), text, &status);
    checkStatus(status);
    size_t charCount = 0;
    while(ubrk_next(it.get()) != UBRK_DONE)
    {
        ++charCount;
    }
    return charCount;
}

size_t countCodepoints(UText* text)
{
    size_t codepointCount = 0;
    while(UTEXT_NEXT32(text) != U_SENTINEL)
    {
        ++codepointCount;
    }
    // reset the index so we can use the structure again
    UTEXT_SETNATIVEINDEX(text, 0);
    return codepointCount;
}

void printStringInfo(const std::string& utf8)
{
    UErrorCode status = U_ZERO_ERROR;
    PUText text(utext_openUTF8(nullptr, utf8.data(), utf8.length(), &status));
    checkStatus(status);

    std::cout << "UTF-8 string (might look wrong if your console locale is different): " << utf8 << std::endl;
    std::cout << "Length (UTF-8 bytes): " << utf8.length() << std::endl;
    std::cout << "Length (UTF-8 codepoints): " << countCodepoints(text.get()) << std::endl;
    std::cout << "Length (graphemes): " << countGraphemes(text.get()) << std::endl;
    std::cout << std::endl;
}

void main(int argc, char** argv)
{
    printStringInfo(u8"Hello, world!");
    printStringInfo(u8"หวัดดีชาวโลก");
    printStringInfo(u8"\xF0\x9F\x90\xBF");
    printStringInfo(u8"Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Bản in này:

UTF-8 string (might look wrong if your console locale is different): Hello, world!
Length (UTF-8 bytes): 13
Length (UTF-8 codepoints): 13
Length (graphemes): 13

UTF-8 string (might look wrong if your console locale is different): หวัดดีชาวโลก
Length (UTF-8 bytes): 36
Length (UTF-8 codepoints): 12
Length (graphemes): 10

UTF-8 string (might look wrong if your console locale is different): 🐿
Length (UTF-8 bytes): 4
Length (UTF-8 codepoints): 1
Length (graphemes): 1

UTF-8 string (might look wrong if your console locale is different): Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚
Length (UTF-8 bytes): 95
Length (UTF-8 codepoints): 50
Length (graphemes): 5

Boost.Locale kết hợp ICU và có thể cung cấp một giao diện đẹp hơn. Tuy nhiên, nó vẫn yêu cầu chuyển đổi sang / từ UTF-16.


3

Nếu bạn đang sử dụng chuỗi kiểu C cũ thay vì chuỗi kiểu STL mới hơn, thì có strlenhàm trong thư viện thời gian chạy C:

const char* p = "Hello";
size_t n = strlen(p);

3

nếu bạn đang sử dụng std :: string, có hai phương pháp phổ biến cho điều đó:

std::string Str("Some String");
size_t Size = 0;
Size = Str.size();
Size = Str.length();

nếu bạn đang sử dụng chuỗi kiểu C (sử dụng char * hoặc const char *) thì bạn có thể sử dụng:

const char *pStr = "Some String";
size_t Size = strlen(pStr);

2
string foo;
... foo.length() ...

.length và .size đồng nghĩa, tôi chỉ nghĩ rằng "length" là một từ rõ ràng hơn một chút.


size () không được khuyến khích vì tôi nhớ đã nghe nói rằng trong một số triển khai, nó sẽ trả về "length () + 1" (vì nó bao gồm dấu chấm hết null). Vì vậy, chỉ cần sử dụng length () vì nó rõ ràng hơn và dễ di chuyển hơn.

1
@LaQuet, Nếu bạn không sử dụng trình biên dịch tuân thủ tiêu chuẩn hoặc triển khai STL, bạn có nhiều điều phải lo lắng.
strager

2
@Nelson không nên như vậy vì các Chuỗi C ++ tiêu chuẩn không bị kết thúc bằng null. Tuy nhiên khi ép kiểu với c_str () nó sẽ thêm byte null vào cuối.
John T

2
std::string str("a string");
std::cout << str.size() << std::endl;

2

cho một đối tượng chuỗi thực tế:

yourstring.length();

hoặc là

yourstring.size();

2

Trong C ++ std :: string, phương thức length () và size () cung cấp cho bạn số byte chứ không nhất thiết phải là số ký tự !. Tương tự với hàm c-Style sizeof ()!

Đối với hầu hết các Ký tự 7bit-ASCII có thể in được, đây là cùng một giá trị, nhưng đối với các ký tự không phải là 7bit-ASCII thì chắc chắn là không. Xem ví dụ sau để cung cấp cho bạn kết quả thực tế (64bit linux).

Không có hàm c / c ++ đơn giản nào thực sự có thể đếm số ký tự. Nhân tiện, tất cả những thứ này đều phụ thuộc vào việc triển khai và có thể khác trên các môi trường khác (trình biên dịch, win 16/32, linux, nhúng, ...)

Xem ví dụ sau:

#include <string>
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int main()
{
/* c-Style char Array */
const char * Test1 = "1234";
const char * Test2 = "ÄÖÜ€";
const char * Test3 = "αβγ𝄞";

/* c++ string object */
string sTest1 = "1234";
string sTest2 = "ÄÖÜ€";
string sTest3 = "αβγ𝄞";

printf("\r\nC Style Resluts:\r\n");
printf("Test1: %s, strlen(): %d\r\n",Test1, (int) strlen(Test1));
printf("Test2: %s, strlen(): %d\r\n",Test2, (int) strlen(Test2));
printf("Test3: %s, strlen(): %d\r\n",Test3, (int) strlen(Test3));

printf("\r\nC++ Style Resluts:\r\n");
cout << "Test1: " << sTest1 << ", Test1.size():  " <<sTest1.size() <<"  sTest1.length(): " << sTest1.length() << endl;
cout << "Test1: " << sTest2 << ", Test2.size():  " <<sTest2.size() <<"  sTest1.length(): " << sTest2.length() << endl;
cout << "Test1: " << sTest3 << ", Test3.size(): " <<sTest3.size() << "  sTest1.length(): " << sTest3.length() << endl;
return 0;
}

Đầu ra của ví dụ là:

C Style Results:
Test1: ABCD, strlen(): 4    
Test2: ÄÖÜ€, strlen(): 9
Test3: αβγ𝄞, strlen(): 10

C++ Style Results:
Test1: ABCD, sTest1.size():  4  sTest1.length(): 4
Test2: ÄÖÜ€, sTest2.size():  9  sTest2.length(): 9
Test3: αβγ𝄞, sTest3.size(): 10  sTest3.length(): 10

0

Đây có thể là cách dễ nhất để nhập một chuỗi và tìm độ dài của nó.

// Finding length of a string in C++ 
#include<iostream>
#include<string>
using namespace std;

int count(string);

int main()
{
string str;
cout << "Enter a string: ";
getline(cin,str);
cout << "\nString: " << str << endl;
cout << count(str) << endl;

return 0;

}

int count(string s){
if(s == "")
  return 0;
if(s.length() == 1)
  return 1;
else
    return (s.length());

}

4
Bạn nghĩ số đếm (chuỗi) mà chuỗi :: length () không có là gì? Ngoài việc tạo bản sao bổ sung của chuỗi không cần thiết và trả về giá trị âm nếu có hơn 2 tỷ ký tự trong chuỗi.
Nhật thực

0

Cách đơn giản nhất để có được độ dài của chuỗi mà không cần bận tâm về không gian tên std là như sau

chuỗi có / không có khoảng trắng

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    getline(cin,str);
    cout<<"Length of given string is"<<str.length();
    return 0;
}

chuỗi không có khoảng trắng

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
    cout<<"Length of given string is"<<str.length();
    return 0;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.