Bir std :: string'deki karakter sayısı nasıl elde edilir?


112

C ++ 'da bir dizedeki karakter sayısını nasıl almalıyım?


1
Ne tür dizelerle uğraşıyorsun? std :: string? cstring? boş sonlandırılmış dizge?
Steve Rowe

En kusursuz yol, içinden geçip karakterleri kendiniz saymaktır.
Krythic

Yanıtlar:


177

Bir kullanıyorsanız std::string, arayın length():

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

Bir c-string kullanıyorsanız, arayın strlen().

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

Ya da, Pascal tarzı dizeleri kullanmayı seviyorsanız (veya Joel Spolsky'nin sonunda NULL olduklarında onları çağırmayı sevdiği gibi ), sadece ilk karaktere atıfta bulunun.

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

7
Aklı başında kimler Pascal tarzı dizeleri kullanır?
Xarn

17
length (), karakter sayısını değil, bayt sayısını döndürmez mi?

2
Bir std :: string için de aynı şeydir (değişken uzunluklu bir kodlama saklamıyorsanız veya çok baytlı karakterleri saklamak için bir std :: string kullanmıyorsanız). Bunu yapıyorsanız, std kütüphanesinden hiçbir şey için fazla yardım alamayacaksınız, böylece kendi strleninizi de yuvarlayabilirsiniz. Wstring, u16string ve u32string için bayt yerine karakter sayısını döndürür. (Yine şu şartla ki, eğer bunlardan herhangi birinde değişken uzunluklu bir kodlama kullanıyorsanız, kendi dizinizi döndürmeniz gerekecek).
Eclipse

4
Bu dönüş türü söz bu yüksek puanlı yanıt değer katmak istiyoruz: std::size_t.
chux

3
F *** ed dizeleri
Sнаđошƒаӽ

23

C ++ dizeleri (std :: string) ile uğraşırken, uzunluk () veya boyut () ararsınız . Her ikisi de size aynı değeri sağlamalıdır. Bununla birlikte, C-Style dizeleri ile uğraşırken strlen () kullanırsınız .

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

Çıktı:

6
6
6
6

5
Kullanımdan kaldırılmış #include <string.h> yerine #include <cstring> kullanarak derleyici uyarılarından (belirli C ++ derleyicilerinde) kaçınabileceğinizi unutmayın
Colin

1
Örnekleriniz sadece ASCII kullanıyor. Unicode karakterleri için de günceller misiniz? Özellikle 𝄞
Thomas Weller

17

Hangi dize türünden bahsettiğinize bağlıdır. Birçok dize türü vardır:

  1. const char* - C tarzı çok baytlı bir dizi
  2. const wchar_t* - C tarzı geniş bir ip
  3. std::string - "standart" çok baytlı bir dizi
  4. std::wstring - "standart" bir geniş dize

3 ve 4 için, .size()veya .length()yöntemleri kullanabilirsiniz .

1 için kullanabilirsiniz strlen(), ancak dize değişkeninin NULL olmadığından emin olmalısınız (=== 0)

2 için kullanabilirsiniz wcslen(), ancak dize değişkeninin NULL olmadığından emin olmalısınız (=== 0)

Standart olmayan C ++ kitaplıklarında, MFC'ler CString, ATL'ler CComBSTR, ACE'ler ACE_CStringvb. Gibi yöntemlerle , vb. Gibi başka dize türleri de vardır .GetLength(). Aklımın ucunda bunların ayrıntılarını hatırlayamıyorum.

STLSoft kütüphaneleri bu dedikleri tüm dışarı soyutlamak dize erişim şim türlü dize uzunluğunu (ve diğer yönlerini) almak için kullanılabilir. Yani yukarıdakilerin tümü için (standart olmayan kitaplıklar dahil) aynı işlevi kullanıyor stlsoft::c_str_len(). Bu makale , tamamen açık veya kolay olmadığı için hepsinin nasıl çalıştığını açıklıyor.


1
𝄞 gibi 32 bit karakterler için hangisi uygundur?
Thomas Weller

4

Unicode için

Buradaki birkaç cevap .length(), çokbaytlı karakterlerle yanlış sonuçlar veren ele alındı , ancak 11 cevap var ve hiçbiri bir çözüm sağlamadı.

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

Her şeyden önce, "uzunluk" ile ne kastettiğinizi bilmek önemlidir. Motive edici bir örnek olarak, "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" dizesini düşünün (bazı dillerin, özellikle Taycanın aslında aksan işaretlerini birleştirdiğini unutmayın, bu nedenle bu sadece 15 yaşındaki memler için yararlı değildir , ama açıkçası en önemli kullanım durumu budur) . UTF-8 olarak kodlandığını varsayalım . Bu dizenin uzunluğu hakkında konuşmanın 3 yolu vardır:

95 bayt

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 kod noktası

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 grafik

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

YBÜ kullanarak uzunlukları bulma

ICU için C ++ sınıfları vardır, ancak bunlar UTF-16'ya dönüştürülmeyi gerektirir. Bazı UTF-8 desteği almak için C türlerini ve makrolarını doğrudan kullanabilirsiniz:

#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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Bu yazdırır:

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 , yoğun bakım ünitesini sarar ve daha hoş bir arayüz sağlayabilir. Ancak yine de UTF-16'ya dönüştürme gerektirir.


3

Daha yeni, STL tarzı dizeler yerine eski, C tarzı dizeyi kullanıyorsanız strlen, C çalışma zamanı kitaplığında işlev vardır :

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

3

std :: string kullanıyorsanız, bunun için iki yaygın yöntem vardır:

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

C stil dizesini kullanıyorsanız (char * veya const char * kullanarak), o zaman kullanabilirsiniz:

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

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

.length ve .size eşanlamlıdır, ben sadece "uzunluk" un biraz daha net bir kelime olduğunu düşünüyorum.


size () önerilmiyor çünkü bazı uygulamalarda "length () + 1" değerini döndüreceğini duyduğumu hatırlıyorum (çünkü boş sonlandırıcı içeriyor). Bu nedenle, daha temiz ve daha taşınabilir olduğu için length () kullanın.

1
@LaQuet, Standartlara uyumlu bir derleyici veya STL uygulaması kullanmıyorsanız, endişelenmeniz gereken daha çok şey var.
strager

2
@Nelson, standart C ++ Strings'de olduğu gibi olmamalıdır. Ancak c_str () ile çevrim yaparken boş baytı sonuna ekleyecektir.
John T

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

2

gerçek bir dize nesnesi için:

yourstring.length();

veya

yourstring.size();

2

C ++ std :: string'de length () ve size () yöntemi size bayt sayısını verir ve mutlaka karakter sayısını vermez! C-Style sizeof () işleviyle aynı!

Yazdırılabilir 7 bit ASCII Karakterlerin çoğu için bu aynı değerdir, ancak 7 bit-ASCII olmayan karakterler için kesinlikle değildir. Size gerçek sonuçlar vermesi için aşağıdaki örneğe bakın (64bit linux).

Gerçekten karakter sayısını sayabilen basit bir c / c ++ işlevi yoktur. Bu arada, tüm bunlar uygulamaya bağlıdır ve diğer ortamlarda farklı olabilir (derleyici, 16/32 kazan, linux, gömülü, ...)

Aşağıdaki örneğe bakın:

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

Örneğin çıktısı şudur:

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

Bir dizeyi girmenin ve uzunluğunu bulmanın en kolay yolu bu olabilir.

// 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
Sizce count (string), string :: length () değil mi? Ayrıca gereksiz yere dizenin fazladan bir kopyasını yapmak ve dizede 2 milyardan fazla karakter varsa negatif bir değer döndürmek.
Eclipse

0

Std ad alanıyla uğraşmadan dizge uzunluğunu elde etmenin en basit yolu aşağıdaki gibidir

boşluklu / boşluksuz dize

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

boşluksuz dize

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
    cout<<"Length of given string is"<<str.length();
    return 0;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.