Comment obtenir le nombre de caractères dans une chaîne std :: string?

112

Comment obtenir le nombre de caractères d'une chaîne en C ++?

Elliot
la source
1
Avec quel genre de cordes traitez-vous? std :: string? C chaîne? chaîne terminée par null?
Steve Rowe
Le moyen le plus infaillible serait de le parcourir et de compter les caractères vous-même.
Krythic

Réponses:

177

Si vous utilisez un std::string, appelez length():

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

Si vous utilisez une chaîne C, appelez strlen().

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

Ou, si vous aimez utiliser des chaînes de style Pascal (ou des chaînes f ***** comme Joel Spolsky aime les appeler quand elles ont un NULL à la fin), déréférencer simplement le premier caractère.

const char *str = "\005hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"
Éclipse
la source
7
Qui, sain d'esprit, utiliserait des chaînes de style Pascal?
Xarn
17
length () ne renvoie-t-il pas le nombre d'octets, pas le nombre de caractères?
2
Pour un std :: string, c'est la même chose (à moins que vous ne stockiez un encodage de longueur variable, ou que vous n'utilisiez un std :: string pour stocker des caractères multi-octets). Si vous faites cela, vous n'obtiendrez pas beaucoup d'aide avec quoi que ce soit de la bibliothèque std, vous pouvez donc également gérer le roulement de votre propre strlen. Pour wstring, u16string et u32string, il renvoie le nombre de caractères, plutôt que d'octets. (Encore une fois avec la condition que si vous utilisez un encodage à longueur variable dans l'un de ceux-ci, vous devrez rouler votre propre strlen).
Eclipse
4
Il ajouterait de la valeur à cette réponse très apprécié de mentionner le type de retour: std::size_t.
chux
3
@Eclipse +1 for f *** ed strings
Sнаđошƒаӽ
23

Lorsque vous traitez avec des chaînes C ++ (std :: string), vous recherchez length () ou size () . Les deux devraient vous fournir la même valeur. Cependant, lorsque vous traitez avec des chaînes de style C, vous utiliserez 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;
}

Production:

6
6
6
6
John T
la source
5
Notez que vous pouvez éviter les avertissements du compilateur (dans certains compilateurs C ++) en utilisant #include <cstring> au lieu du #include <string.h> obsolète
Colin
1
Vos exemples utilisent simplement ASCII. Pourriez-vous également le mettre à jour pour les caractères Unicode? Surtout les 32 bits tels que 𝄞
Thomas Weller
17

Cela dépend du type de chaîne dont vous parlez. Il existe de nombreux types de chaînes:

  1. const char* - une chaîne multi-octets de style C
  2. const wchar_t* - une corde large de style C
  3. std::string - une chaîne multi-octets "standard"
  4. std::wstring - une chaîne large "standard"

Pour 3 et 4, vous pouvez utiliser les méthodes .size()ou .length().

Pour 1, vous pouvez utiliser strlen(), mais vous devez vous assurer que la variable chaîne n'est pas NULL (=== 0)

Pour 2, vous pouvez utiliser wcslen(), mais vous devez vous assurer que la variable chaîne n'est pas NULL (=== 0)

Il existe d'autres types de chaîne dans les bibliothèques C ++ non standard, telles que MFC CString, ATL CComBSTR, ACE ACE_CString, etc., avec des méthodes telles que .GetLength(), etc. Je ne me souviens pas de leurs détails tout de suite du haut de ma tête.

Les bibliothèques STLSoft ont résumé tout cela avec ce qu'elles appellent des shims d'accès aux chaînes , qui peuvent être utilisés pour obtenir la longueur de la chaîne (et d'autres aspects) de n'importe quel type. Donc, pour tout ce qui précède (y compris les bibliothèques non standard) en utilisant la même fonction stlsoft::c_str_len(). Cet article décrit comment tout cela fonctionne, car ce n'est pas tout à fait évident ou facile.

dcw
la source
1
Lequel convient aux caractères 32 bits tels que 𝄞?
Thomas Weller
4

Pour Unicode

Plusieurs réponses ici ont abordé ce qui .length()donne de mauvais résultats avec des caractères multi-octets, mais il y a 11 réponses et aucune d'entre elles n'a fourni de solution.

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

Tout d'abord, il est important de savoir ce que vous entendez par «longueur». Pour un exemple motivant, considérons la chaîne "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (notez que certaines langues, notamment le thaï, utilisent en fait la combinaison de signes diacritiques, donc ce n'est pas seulement utile pour les mèmes de 15 ans, mais c'est évidemment le cas d'utilisation le plus important) . Supposons qu'il soit encodé en UTF-8 . Il y a 3 façons de parler de la longueur de cette chaîne:

95 octets

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 points de code

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 graphèmes

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

Trouver les longueurs en utilisant ICU

Il existe des classes C ++ pour ICU, mais elles nécessitent une conversion en UTF-16. Vous pouvez utiliser les types C et les macros directement pour obtenir un support 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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Cela imprime:

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 encapsule ICU et pourrait fournir une interface plus agréable. Cependant, il nécessite toujours une conversion vers / depuis UTF-16.

Robert Fraser
la source
3

Si vous utilisez une ancienne chaîne de style C au lieu des nouvelles chaînes de style STL, il y a la strlenfonction dans la bibliothèque d'exécution C:

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

si vous utilisez std :: string, il existe deux méthodes courantes pour cela:

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

si vous utilisez la chaîne de style C (en utilisant char * ou const char *), vous pouvez utiliser:

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

.length et .size sont synonymes, je pense simplement que "longueur" est un mot un peu plus clair.

Alex Martelli
la source
size () est déconseillé car je me souviens avoir entendu dire que dans certaines implémentations, il retournera le "length () + 1" (car il inclut le terminateur nul). Alors utilisez simplement length () car il est plus propre et plus portable.
1
@LaQuet, Si vous n'utilisez pas de compilateur conforme aux normes ou d'implémentation STL, vous avez plus de choses à craindre.
strager
2
@Nelson, cela ne devrait pas être le cas, car les chaînes C ++ standard ne sont pas terminées par un nul. Cependant, lors de la conversion avec c_str (), il ajoutera l'octet nul à la fin.
John T
2
std::string str("a string");
std::cout << str.size() << std::endl;
stefanB
la source
2

pour un objet string réel:

yourstring.length();

ou

yourstring.size();
Luke Schafer
la source
2

En C ++ std :: string, la méthode length () et size () vous donne le nombre d'octets, et pas nécessairement le nombre de caractères!. Idem avec la fonction sizeof () de c-Style!

Pour la plupart des caractères ASCII 7 bits imprimables, il s'agit de la même valeur, mais ce n'est certainement pas le cas pour les caractères qui ne sont pas ASCII 7 bits. Voir l'exemple suivant pour vous donner de vrais résultats (Linux 64 bits).

Il n'y a pas de fonction c / c ++ simple qui puisse vraiment compter le nombre de caractères. En passant, tout cela dépend de l'implémentation et peut être différent sur d'autres environnements (compilateur, win 16/32, linux, embarqué, ...)

Voir l'exemple suivant:

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

La sortie de l'exemple est la suivante:

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
la source
0

Cela peut être le moyen le plus simple de saisir une chaîne et de trouver sa longueur.

// 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
la source
4
Que pensez-vous que count (string) fait que string :: length () ne le fait pas? En plus de faire inutilement une copie supplémentaire de la chaîne et de renvoyer une valeur négative s'il y a plus de 2 milliards de caractères dans la chaîne.
Eclipse
0

Le moyen le plus simple d'obtenir la longueur d'une chaîne sans se soucier de l'espace de noms std est le suivant

chaîne avec / sans espaces

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

chaîne sans espaces

#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
la source