Come ottenere il numero di caratteri in una std :: string?


112

Come devo ottenere il numero di caratteri in una stringa in C ++?


1
Con che tipo di corde hai a che fare? std :: string? CString? stringa terminata con null?
Steve Rowe,

Il modo più infallibile sarebbe farlo scorrere e contare i personaggi da soli.
Krythic

Risposte:


177

Se stai usando a std::string, chiama length():

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

Se stai usando una stringa C, chiama strlen().

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

Oppure, se ti piace usare stringhe in stile Pascal (o stringhe f ***** come piace chiamarle a Joel Spolsky quando hanno un NULL finale), dereferenzia semplicemente il primo carattere.

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

7
Chi sano di mente userebbe stringhe in stile Pascal?
Xarn

17
length () non restituisce il numero di byte, non il numero di caratteri?

2
Per uno std :: string, è la stessa cosa (a meno che non si memorizzi una codifica a lunghezza variabile o si utilizzi uno std :: string per memorizzare caratteri multibyte). Se lo fai, non otterrai molto aiuto con nulla dalla libreria std, quindi puoi gestire anche il rollio del tuo strlen. Per wstring, u16string e u32string, restituisce il numero di caratteri, anziché i byte. (Ancora una volta con la condizione che se stai usando una codifica a lunghezza variabile in uno di questi, dovrai eseguire il tuo strlen).
Eclipse

4
Sarebbe un valore aggiunto a questa risposta molto quotato di menzionare il tipo di ritorno: std::size_t.
chux - Ripristina Monica il

3
@Eclipse +1 for f *** ed strings
Sнаđошƒаӽ

23

Quando si ha a che fare con stringhe C ++ (std :: string), si cerca length () o size () . Entrambi dovrebbero fornire lo stesso valore. Tuttavia, quando si ha a che fare con stringhe in stile C, si usa 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;
}

Produzione:

6
6
6
6

5
Si noti che è possibile evitare gli avvisi del compilatore (in alcuni compilatori C ++) utilizzando #include <cstring> invece del deprecato #include <string.h>
Colin

1
I tuoi esempi usano solo ASCII. Ti dispiacerebbe aggiornarlo anche per i caratteri Unicode? Soprattutto quelli a 32 bit come 𝄞
Thomas Weller

17

Dipende dal tipo di stringa di cui parli. Esistono molti tipi di stringhe:

  1. const char* - una stringa multibyte in stile C.
  2. const wchar_t* - una corda larga in stile C.
  3. std::string - una stringa multibyte "standard"
  4. std::wstring - una stringa larga "standard"

Per 3 e 4, puoi usare .size()o .length()metodi.

Per 1, puoi usare strlen(), ma devi assicurarti che la variabile stringa non sia NULL (=== 0)

Per 2, puoi usare wcslen(), ma devi assicurarti che la variabile stringa non sia NULL (=== 0)

Esistono altri tipi di stringhe nelle librerie C ++ non standard, come MFC CString, ATL CComBSTR, ACE ACE_CStringe così via, con metodi come .GetLength()e così via. Non riesco a ricordare tutti i dettagli di loro dalla parte superiore della mia testa.

Le librerie STLSoft hanno astratto tutto questo con quelli che chiamano shim di accesso alle stringhe , che possono essere usati per ottenere la lunghezza della stringa (e altri aspetti) da qualsiasi tipo. Quindi per tutto quanto sopra (compresi quelli di libreria non standard) utilizzando la stessa funzione stlsoft::c_str_len(). Questo articolo descrive come funziona il tutto, poiché non è del tutto ovvio o facile.


1
Quale è adatto per caratteri a 32 bit come 𝄞?
Thomas Weller

4

Per Unicode

Diverse risposte qui sono state affrontate che .length()danno risultati sbagliati con caratteri multibyte, ma ci sono 11 risposte e nessuna di esse ha fornito una soluzione.

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

Prima di tutto, è importante sapere cosa intendi per "lunghezza". Per un esempio motivante, considera la stringa "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (nota che alcune lingue, in particolare il thailandese, usano effettivamente la combinazione di segni diacritici, quindi questo non è utile solo per i meme di 15 anni, ma ovviamente è il caso d'uso più importante) . Supponiamo che sia codificato in UTF-8 . Ci sono 3 modi in cui possiamo parlare della lunghezza di questa stringa:

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 punti di codice

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 grafemi

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

Trovare le lunghezze utilizzando ICU

Esistono classi C ++ per ICU, ma richiedono la conversione in UTF-16. Puoi utilizzare i tipi C e le macro direttamente per ottenere supporto 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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Questo stampa:

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 avvolge l'ICU e potrebbe fornire un'interfaccia migliore. Tuttavia, richiede ancora la conversione da / a UTF-16.


3

Se stai usando una vecchia stringa in stile C invece delle nuove stringhe in stile STL, c'è la strlenfunzione nella libreria di runtime C:

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

3

se stai usando std :: string, ci sono due metodi comuni per questo:

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

se stai usando la stringa in stile C (usando char * o const char *) puoi usare:

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

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

.length e .size sono sinonimi, penso solo che "lunghezza" sia una parola leggermente più chiara.


size () è sconsigliato perché ricordo di aver sentito che in alcune implementazioni restituirà "length () + 1" (perché include il terminatore nullo). Quindi usa length () in quanto è più pulito e portatile.

1
@LaQuet, se non utilizzi un compilatore conforme agli standard o un'implementazione STL, hai più cose di cui preoccuparti.
strager

2
@Nelson che non dovrebbe essere il caso in quanto dallo standard C ++ le stringhe non terminano con null. Tuttavia, quando si esegue il cast con c_str (), aggiungerà il byte nullo alla fine.
John T,

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

2

per un oggetto stringa effettivo:

yourstring.length();

o

yourstring.size();

2

In C ++ std :: string il metodo length () e size () fornisce il numero di byte, e non necessariamente il numero di caratteri!. Lo stesso con la funzione sizeof () dello stile c!

Per la maggior parte dei caratteri ASCII a 7 bit stampabili questo è lo stesso valore, ma per i caratteri che non sono ASCII a 7 bit non lo è assolutamente. Vedere il seguente esempio per ottenere risultati reali (Linux a 64 bit).

Non esiste una semplice funzione c / c ++ che possa realmente contare il numero di caratteri. A proposito, tutto questo dipende dall'implementazione e può essere diverso su altri ambienti (compilatore, win 16/32, linux, embedded, ...)

Vedere il seguente esempio:

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

Il risultato dell'esempio è questo:

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

Potrebbe essere il modo più semplice per inserire una stringa e trovarne la lunghezza.

// 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
Cos'è che pensi che count (string) fa quella stringa :: length () no? Oltre a fare inutilmente una copia extra della stringa e restituire un valore negativo se ci sono più di 2 miliardi di caratteri nella stringa.
Eclipse

0

Il modo più semplice per ottenere la lunghezza della stringa senza preoccuparsi dello spazio dei nomi std è il seguente

stringa con / senza spazi

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

stringa senza spazi

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
    cout<<"Length of given string is"<<str.length();
    return 0;
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.