Como obter o número de caracteres em uma std :: string?

112

Como devo obter o número de caracteres em uma string em C ++?

Elliot
fonte
1
Com que tipo de cordas você está lidando? std :: string? cstring? string terminada nula?
Steve Rowe
A maneira mais infalível seria fazer um loop e contar os personagens você mesmo.
Krythic

Respostas:

177

Se você estiver usando um std::string, ligue para length():

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

Se você estiver usando uma string C, chame strlen().

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

Ou, se por acaso você gosta de usar strings no estilo Pascal (ou strings f *****, como Joel Spolsky gosta de chamá-los quando têm um NULL à direita), simplesmente cancele a referência do primeiro caractere.

const char *str = "\005hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"
Eclipse
fonte
7
Quem em sã consciência usaria strings no estilo Pascal?
Xarn
17
não length () retorna o número de bytes, não o número de caracteres?
2
Para um std :: string, é a mesma coisa (a menos que você esteja armazenando uma codificação de comprimento variável ou usando um std :: string para armazenar caracteres multibyte). Se você estiver fazendo isso, não obterá muita ajuda com nada da biblioteca std, portanto, também pode lidar com o lançamento de seu próprio strlen. Para wstring, u16string e u32string, ele retorna o número de caracteres, em vez de bytes. (Novamente com a ressalva de que se você estiver usando uma codificação de comprimento variável em qualquer uma delas, você terá que rolar seu próprio strlen).
Eclipse
4
Ele gostaria de acrescentar valor a esta resposta altamente cotados para mencionar o tipo de retorno: std::size_t.
chux - Reintegrar Monica em
3
@Eclipse +1 para strings f *** ed
Sнаđошƒаӽ
23

Ao lidar com strings C ++ (std :: string), você está procurando por length () ou size () . Ambos devem fornecer o mesmo valor. No entanto, ao lidar com strings de estilo C, você usaria 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;
}

Resultado:

6
6
6
6
John T
fonte
5
Observe que você pode evitar avisos do compilador (em certos compiladores C ++) usando #include <cstring> em vez do obsoleto #include <string.h>
Colin
1
Seus exemplos usam apenas ASCII. Você se importaria de atualizá-lo para caracteres Unicode também? Especialmente os de 32 bits, como 𝄞
Thomas Weller
17

Depende de qual tipo de string você está falando. Existem muitos tipos de strings:

  1. const char* - uma string multibyte de estilo C
  2. const wchar_t* - uma corda larga estilo C
  3. std::string - uma string multibyte "padrão"
  4. std::wstring - uma corda larga "padrão"

Para 3 e 4, você pode usar os métodos .size()ou .length().

Para 1, você pode usar strlen() , mas deve garantir que a variável da string não seja NULL (=== 0)

Para 2, você pode usar wcslen(), mas deve garantir que a variável da string não seja NULL (=== 0)

Existem outros tipos de string em bibliotecas C ++ não padrão, como MFCs CString, ATLs CComBSTR, ACEs ACE_CStringe assim por diante, com métodos como .GetLength()e assim por diante. Não consigo me lembrar dos detalhes de todos eles de cara.

As bibliotecas STLSoft abstraíram tudo isso com o que chamam de shims de acesso de string , que podem ser usados ​​para obter o comprimento da string (e outros aspectos) de qualquer tipo. Portanto, para todos os itens acima (incluindo os da biblioteca não padrão) usando a mesma função stlsoft::c_str_len(). Este artigo descreve como tudo funciona, pois nem tudo é totalmente óbvio ou fácil.

dcw
fonte
1
Qual é adequado para caracteres de 32 bits, como 𝄞?
Thomas Weller
4

Para Unicode

Várias respostas aqui abordaram isso .length() dá resultados errados com caracteres multibyte, mas há 11 respostas e nenhuma delas forneceu uma solução.

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

Em primeiro lugar, é importante saber o que você entende por "comprimento". Para um exemplo motivador, considere a string "Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚" (observe que algumas línguas, notadamente o tailandês, realmente usam a combinação de marcas diacríticas, então isso não é útil apenas para memes de 15 anos, mas obviamente é o caso de uso mais importante) . Suponha que ele esteja codificado em UTF-8 . Existem 3 maneiras de falar sobre o comprimento desta string:

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 pontos de código

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 grafemas

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

Encontrar os comprimentos usando a UTI

Existem classes C ++ para ICU, mas requerem a conversão para UTF-16. Você pode usar os tipos C e macros diretamente para obter algum suporte 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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

Isso 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 envolve ICU e pode fornecer uma interface mais agradável. No entanto, ainda requer conversão de / para UTF-16.

Robert Fraser
fonte
3

Se você estiver usando strings antigas no estilo C em vez das strings mais novas no estilo STL, há a strlenfunção na biblioteca de tempo de execução C:

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

se você estiver usando std :: string, existem dois métodos comuns para isso:

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

se estiver usando a string de estilo C (usando char * ou const char *), você pode usar:

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

.length e .size são sinônimos, só acho que "comprimento" é uma palavra um pouco mais clara.

Alex Martelli
fonte
size () é desencorajado porque me lembro de ouvir que em algumas implementações ele retornará o "comprimento () + 1" (porque inclui o terminador nulo). Portanto, use length () porque é mais limpo e mais portátil.
1
@LaQuet, se você não estiver usando um compilador compatível com os padrões ou uma implementação STL, você tem mais coisas com que se preocupar.
strager
2
@Nelson, esse não deveria ser o caso, já que Strings C ++ padrão não têm terminação nula. No entanto, ao lançar com c_str (), ele adicionará o byte nulo ao final.
John T
2
std::string str("a string");
std::cout << str.size() << std::endl;
StefanB
fonte
2

para um objeto string real:

yourstring.length();

ou

yourstring.size();
Luke Schafer
fonte
2

Em C ++ std :: string, os métodos length () e size () fornecem o número de bytes, e não necessariamente o número de caracteres! Mesmo com a função sizeof () do c-Style!

Para a maioria dos caracteres ASCII de 7 bits imprimíveis, este é o mesmo valor, mas para caracteres que não são ASCII de 7 bits, definitivamente não é. Veja o exemplo a seguir para obter resultados reais (Linux de 64 bits).

Não existe uma função c / c ++ simples que possa realmente contar o número de caracteres. A propósito, tudo isso depende da implementação e pode ser diferente em outros ambientes (compilador, win 16/32, linux, incorporado, ...)

Veja o seguinte exemplo:

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

O resultado do exemplo é este:

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

Pode ser a maneira mais fácil de inserir uma string e encontrar seu comprimento.

// 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
fonte
4
O que é que você acha que count (string) que string :: length () não faz? Além de fazer desnecessariamente uma cópia extra da string e retornar um valor negativo se houver mais de 2 bilhões de caracteres na string.
Eclipse
0

A maneira mais simples de obter o comprimento da string sem se preocupar com o namespace std é a seguinte

string com / sem espaços

#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 sem espaços

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