Bagaimana cara mendapatkan jumlah karakter dalam std :: string?

112

Bagaimana cara mendapatkan jumlah karakter dalam string di C ++?

Elliot
sumber
1
Jenis string apa yang Anda hadapi? std :: string? cstring? null dihentikan string?
Steve Rowe
Cara paling mudah adalah dengan mengulanginya dan menghitung karakternya sendiri.
Krythic

Jawaban:

177

Jika Anda menggunakan std::string, telepon length():

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

Jika Anda menggunakan c-string, panggil strlen().

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

Atau, jika Anda kebetulan suka menggunakan string gaya Pascal (atau string f ***** seperti yang Joel Spolsky suka menyebutnya ketika mereka memiliki NULL di belakang), cukup dereferensi karakter pertama.

const char *str = "\005hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"
Gerhana
sumber
7
Siapa yang waras yang akan menggunakan string gaya Pascal?
Xarn
17
bukankah length () mengembalikan jumlah byte, bukan jumlah karakter?
2
Untuk std :: string, itu hal yang sama (kecuali Anda menyimpan encoding panjang variabel, atau menggunakan std :: string untuk menyimpan karakter multi-byte). Jika Anda melakukan itu, Anda tidak akan mendapatkan banyak bantuan dengan apa pun dari perpustakaan std, sehingga Anda dapat menangani pengguliran strlen Anda sendiri juga. Untuk wstring, u16string dan u32string, ini mengembalikan jumlah karakter, bukan byte. (Sekali lagi dengan syarat bahwa jika Anda menggunakan pengkodean variabel-panjang dalam salah satu dari itu, Anda harus menggulung strlen Anda sendiri).
Gerhana tanggal
4
Ini akan menambah nilai yang sangat dinilai jawaban ini menyebutkan jenis kembali: std::size_t.
chux - Kembalikan Monica
3
@Eclipse +1 untuk string f *** ed
Sнаđошƒаӽ
23

Saat berurusan dengan string C ++ (std :: string), Anda mencari length () atau size () . Keduanya harus memberi Anda nilai yang sama. Namun saat berhadapan dengan string C-Style, Anda akan menggunakan 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;
}

Keluaran:

6
6
6
6
John T
sumber
5
Perhatikan bahwa Anda dapat menghindari peringatan compiler (di compiler C ++ tertentu) dengan menggunakan #include <cstring> daripada #include <string.h>
Colin
1
Contoh Anda cukup menggunakan ASCII. Maukah Anda memperbaruinya untuk karakter Unicode juga? Terutama yang 32 bit seperti 𝄞
Thomas Weller
17

Itu tergantung pada jenis string yang Anda bicarakan. Ada banyak jenis string:

  1. const char* - string multibyte gaya C.
  2. const wchar_t* - senar lebar model C.
  3. std::string - string multibyte "standar"
  4. std::wstring - string lebar "standar"

Untuk 3 dan 4, Anda dapat menggunakan .size()atau .length()metode.

Untuk 1, Anda dapat menggunakan strlen(), tetapi Anda harus memastikan bahwa variabel string bukan NULL (=== 0)

Untuk 2, Anda dapat menggunakan wcslen(), tetapi Anda harus memastikan bahwa variabel string bukan NULL (=== 0)

Ada jenis string lain di pustaka C ++ non-standar, seperti MFC CString, ATL CComBSTR, ACE ACE_CString, dan seterusnya, dengan metode seperti .GetLength(), dan seterusnya. Saya tidak dapat mengingat secara spesifik semuanya langsung dari atas kepala saya.

The STLSoft perpustakaan telah disarikan ini semua keluar dengan apa yang mereka sebut shims akses tali , yang dapat digunakan untuk mendapatkan panjang string (dan aspek-aspek lain) dari jenis apa pun. Jadi untuk semua hal di atas (termasuk pustaka non-standar) menggunakan fungsi yang sama stlsoft::c_str_len(). Artikel ini menjelaskan bagaimana semuanya bekerja, karena tidak semuanya jelas atau mudah.

dcw
sumber
1
Mana yang cocok untuk karakter 32 bit seperti 𝄞?
Thomas Weller
4

Untuk Unicode

Beberapa jawaban di sini telah dialamatkan yang .length()memberikan hasil yang salah dengan karakter multibyte, namun terdapat 11 jawaban dan tidak ada satupun yang memberikan solusi.

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

Pertama-tama, penting untuk mengetahui apa yang Anda maksud dengan "panjang". Untuk contoh yang memotivasi, pertimbangkan string "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (perhatikan bahwa beberapa bahasa, terutama Thai, sebenarnya menggunakan kombinasi tanda diakritik, jadi ini tidak hanya berguna untuk meme berusia 15 tahun, tapi jelas itu kasus penggunaan yang paling penting) . Asumsikan itu dikodekan dalam UTF-8 . Ada 3 cara untuk membicarakan panjang string ini:

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 titik kode

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 grafem

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

Menemukan panjangnya menggunakan ICU

Ada kelas C ++ untuk ICU, tetapi perlu dikonversi ke UTF-16. Anda dapat menggunakan tipe C dan makro secara langsung untuk mendapatkan beberapa dukungan 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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Ini mencetak:

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 membungkus ICU, dan mungkin menyediakan antarmuka yang lebih baik. Namun, masih membutuhkan konversi ke / dari UTF-16.

Robert Fraser
sumber
3

Jika Anda menggunakan string gaya-C yang lama dan bukan yang lebih baru, string gaya-STL, ada strlenfungsi di pustaka C run time:

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

jika Anda menggunakan std :: string, ada dua metode umum untuk itu:

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

jika Anda menggunakan string gaya C (menggunakan char * atau const char *) maka Anda dapat menggunakan:

const char *pStr = "Some String";
size_t Size = strlen(pStr);
Gal Goldman
sumber
2
string foo;
... foo.length() ...

.length dan .size adalah sinonim, saya hanya berpikir bahwa "length" adalah kata yang sedikit lebih jelas.

Alex Martelli
sumber
size () tidak disarankan karena saya ingat pernah mendengar bahwa dalam beberapa implementasi akan mengembalikan "length () + 1" (karena termasuk terminator null). Jadi gunakan saja length () karena lebih bersih dan lebih portabel.
1
@ LaQuet, Jika Anda tidak menggunakan kompilator yang memenuhi standar atau implementasi STL, Anda memiliki lebih banyak hal yang perlu dikhawatirkan.
strager
2
@Nelson yang seharusnya tidak demikian karena dengan String C ++ standar tidak diakhiri null. Namun saat melakukan casting dengan c_str () itu akan menambahkan byte nol ke akhir.
John T
2
std::string str("a string");
std::cout << str.size() << std::endl;
StefanB
sumber
2

untuk objek string yang sebenarnya:

yourstring.length();

atau

yourstring.size();
Luke Schafer
sumber
2

Dalam C ++ std :: string metode length () dan size () memberi Anda jumlah byte, dan belum tentu jumlah karakter!. Sama dengan fungsi c-Style sizeof ()!

Untuk sebagian besar Karakter 7bit-ASCII yang dapat dicetak nilainya sama, tetapi untuk karakter yang bukan 7bit-ASCII jelas bukan. Lihat contoh berikut untuk memberi Anda hasil nyata (64bit linux).

Tidak ada fungsi c / c ++ sederhana yang benar-benar dapat menghitung jumlah karakter. Omong-omong, semua hal ini bergantung pada implementasi dan mungkin berbeda di lingkungan lain (kompiler, win 16/32, linux, tertanam, ...)

Lihat contoh berikut:

#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;
}

Output dari contoh ini adalah ini:

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
Hape Entner
sumber
0

Ini mungkin cara termudah untuk memasukkan string dan mencari panjangnya.

// 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());

}
pengguna2808359
sumber
4
Apa yang menurut Anda count (string) apakah string :: length () tidak? Selain tidak perlu membuat salinan tambahan dari string, dan mengembalikan nilai negatif jika ada lebih dari 2 miliar karakter dalam string.
Gerhana
0

Cara termudah untuk mendapatkan panjang string tanpa repot-repot tentang namespace std adalah sebagai berikut

string dengan / tanpa spasi

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

string tanpa spasi

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