Wie erhalte ich die Anzahl der Zeichen in einem std :: string?

112

Wie soll ich die Anzahl der Zeichen in einer Zeichenfolge in C ++ ermitteln?

Elliot
quelle
1
Mit welcher Art von Saiten haben Sie es zu tun? std :: string? cstring? null terminierte Zeichenfolge?
Steve Rowe
Der narrensicherste Weg wäre, es zu durchlaufen und die Zeichen selbst zu zählen.
Krythic

Antworten:

176

Wenn Sie a verwenden std::string, rufen Sie an length():

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

Wenn Sie einen C-String verwenden, rufen Sie auf strlen().

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

Oder wenn Sie zufällig Zeichenfolgen im Pascal-Stil verwenden (oder Zeichenfolgen, wie Joel Spolsky sie gerne nennt, wenn sie ein nachfolgendes NULL haben), dereferenzieren Sie einfach das erste Zeichen.

const char *str = "\005hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"
Finsternis
quelle
7
Wer würde bei klarem Verstand Saiten im Pascal-Stil verwenden?
Xarn
17
Gibt length () nicht die Anzahl der Bytes zurück, nicht die Anzahl der Zeichen?
2
Für einen std :: string ist es dasselbe (es sei denn, Sie speichern eine Codierung mit variabler Länge oder verwenden einen std :: string zum Speichern von Mehrbytezeichen). Wenn Sie das tun, werden Sie mit nichts aus der Standardbibliothek viel Hilfe bekommen, so dass Sie auch Ihre eigenen Strlen rollen können. Für wstring, u16string und u32string wird die Anzahl der Zeichen anstelle von Bytes zurückgegeben. (Wiederum mit der Maßgabe, dass Sie, wenn Sie in einer dieser Codierungen eine Codierung mit variabler Länge verwenden, Ihre eigene Strlen rollen müssen).
Eclipse
4
Es würde dieser hoch bewerteten Antwort einen Mehrwert verleihen, den Rückgabetyp zu erwähnen : std::size_t.
chux
3
@Eclipse +1 für f *** ed Strings
Sнаđошƒаӽ
23

Wenn Sie mit C ++ - Zeichenfolgen (std :: string) arbeiten, suchen Sie nach Länge () oder Größe () . Beide sollten Ihnen den gleichen Wert liefern. Wenn Sie jedoch mit C-Style-Zeichenfolgen arbeiten, würden Sie strlen () verwenden .

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

Ausgabe:

6
6
6
6
John T.
quelle
5
Beachten Sie, dass Sie Compiler-Warnungen (in bestimmten C ++ - Compilern) vermeiden können, indem Sie #include <cstring> anstelle des veralteten #include <string.h> verwenden
Colin
1
Ihre Beispiele verwenden nur ASCII. Würde es Ihnen etwas ausmachen, es auch für Unicode-Zeichen zu aktualisieren? Besonders die 32-Bit-Modelle wie 𝄞
Thomas Weller
17

Dies hängt davon ab, über welchen Zeichenfolgentyp Sie sprechen. Es gibt viele Arten von Zeichenfolgen:

  1. const char* - eine Multibyte-Zeichenfolge im C-Stil
  2. const wchar_t* - eine breite Saite im C-Stil
  3. std::string - eine "Standard" -Multibyte-Zeichenfolge
  4. std::wstring - eine "Standard" breite Saite

Für 3 und 4 können Sie .size()oder .length()Methoden verwenden.

Für 1 können Sie verwenden strlen(), aber Sie müssen sicherstellen, dass die Zeichenfolgenvariable nicht NULL ist (=== 0).

Für 2 können Sie verwenden wcslen(), aber Sie müssen sicherstellen, dass die Zeichenfolgenvariable nicht NULL ist (=== 0).

Es gibt andere Zeichenfolgentypen in nicht standardmäßigen C ++ - Bibliotheken wie MFCs CString, ATLs CComBSTR, ACEs ACE_CStringusw. mit Methoden wie .GetLength()usw. Ich kann mich nicht genau an die Besonderheiten erinnern.

Die STLSoft- Bibliotheken haben dies alles mit sogenannten String-Access-Shims abstrahiert, mit denen die String-Länge (und andere Aspekte) von jedem Typ abgerufen werden kann. Also für alle oben genannten (einschließlich der nicht standardmäßigen Bibliothek), die dieselbe Funktion verwenden stlsoft::c_str_len(). Dieser Artikel beschreibt, wie alles funktioniert, da es nicht ganz offensichtlich oder einfach ist.

dcw
quelle
1
Welches ist für 32-Bit-Zeichen wie 𝄞 geeignet?
Thomas Weller
3

Wenn Sie anstelle der neueren Zeichenfolgen im STL-Stil alte Zeichenfolgen strlenim C -Stil verwenden, gibt es die folgende Funktion in der C-Laufzeitbibliothek:

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

Wenn Sie std :: string verwenden, gibt es dafür zwei gängige Methoden:

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

Wenn Sie die Zeichenfolge im C-Stil verwenden (mit char * oder const char *), können Sie Folgendes verwenden:

const char *pStr = "Some String";
size_t Size = strlen(pStr);
Gal Goldman
quelle
3

Für Unicode

Es wurden mehrere Antworten angesprochen, .length()die mit Multibyte-Zeichen zu falschen Ergebnissen führen. Es gibt jedoch 11 Antworten, von denen keine eine Lösung bietet.

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

Zunächst ist es wichtig zu wissen, was Sie unter "Länge" verstehen. Betrachten Sie als motivierendes Beispiel die Zeichenfolge "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (beachten Sie, dass einige Sprachen, insbesondere Thai, tatsächlich kombinierte diakritische Zeichen verwenden, sodass dies nicht nur für 15 Jahre alte Meme nützlich ist, sondern offensichtlich der wichtigste Anwendungsfall ist). . Angenommen, es ist in UTF-8 codiert . Es gibt drei Möglichkeiten, wie wir über die Länge dieser Zeichenfolge sprechen können:

95 Bytes

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 Codepunkte

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

Ermitteln der Längen auf der Intensivstation

Es gibt C ++ - Klassen für die Intensivstation, die jedoch eine Konvertierung in UTF-16 erfordern. Sie können die C-Typen und Makros direkt verwenden, um UTF-8-Unterstützung zu erhalten:

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

Dies druckt:

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 umschließt die Intensivstation und bietet möglicherweise eine schönere Benutzeroberfläche. Es ist jedoch weiterhin eine Konvertierung zu / von UTF-16 erforderlich.

Robert Fraser
quelle
2
string foo;
... foo.length() ...

.length und .size sind synonym, ich denke nur, dass "length" ein etwas klareres Wort ist.

Alex Martelli
quelle
size () wird nicht empfohlen, da ich mich daran erinnere, dass in einigen Implementierungen "length () + 1" zurückgegeben wird (da es den Nullterminator enthält). Verwenden Sie einfach length (), da es sauberer und tragbarer ist.
1
@LaQuet, Wenn Sie keinen standardkonformen Compiler oder keine STL-Implementierung verwenden, müssen Sie sich mehr Sorgen machen.
Strager
2
@ Nelson, das sollte nicht der Fall sein, da Standard-C ++ - Zeichenfolgen nicht nullterminiert sind. Beim Casting mit c_str () wird jedoch das Null-Byte am Ende hinzugefügt.
John T
2
std::string str("a string");
std::cout << str.size() << std::endl;
stefanB
quelle
2

für ein tatsächliches String-Objekt:

yourstring.length();

oder

yourstring.size();
Luke Schafer
quelle
2

In C ++ std :: string geben die Methoden length () und size () die Anzahl der Bytes und nicht unbedingt die Anzahl der Zeichen an! Gleiches gilt für die Funktion c-Style sizeof ()!

Für die meisten druckbaren 7-Bit-ASCII-Zeichen ist dies der gleiche Wert, für Zeichen, die nicht 7-Bit-ASCII sind, jedoch definitiv nicht. Sehen Sie sich das folgende Beispiel an, um echte Ergebnisse zu erzielen (64-Bit-Linux).

Es gibt keine einfache c / c ++ - Funktion, die die Anzahl der Zeichen wirklich zählen kann. Übrigens ist all dieses Zeug implementierungsabhängig und kann in anderen Umgebungen unterschiedlich sein (Compiler, Win 16/32, Linux, Embedded, ...).

Siehe folgendes Beispiel:

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

Die Ausgabe des Beispiels lautet wie folgt:

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
quelle
0

Dies ist möglicherweise der einfachste Weg, eine Zeichenfolge einzugeben und ihre Länge zu ermitteln.

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

}
user2808359
quelle
4
Was ist Ihrer Meinung nach count (string), was string :: length () nicht tut? Außerdem müssen Sie unnötig eine zusätzliche Kopie der Zeichenfolge erstellen und einen negativen Wert zurückgeben, wenn die Zeichenfolge mehr als 2 Milliarden Zeichen enthält.
Eclipse
0

Der einfachste Weg, die Länge eines Strings zu ermitteln, ohne sich um den Standard-Namespace zu kümmern, ist der folgende

Zeichenfolge mit / ohne Leerzeichen

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

Zeichenfolge ohne Leerzeichen

#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
quelle