如何获取std :: string中的字符数?


Answers:


177

如果您使用std::string,请致电length()

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

如果您使用的是C字符串,请致电strlen()

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

或者,如果您碰巧喜欢使用Pascal样式的字符串(或f *****字符串,如Joel Spolsky 希望在它们具有尾随NULL时调用它们),只需取消引用第一个字符即可。

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

7
谁在他们的头脑中会使用Pascal风格的字符串?
Xarn 2014年

17
length()不返回字节数,而不是字符数吗?

2
对于std :: string,这是同一件事(除非您要存储可变长度的编码,或者使用std :: string来存储多字节字符)。如果这样做,您将不会从std库获得任何帮助,因此您也可以处理自己的问题。对于wstring,u16string和u32string,它返回字符数,而不是字节数。(此外,前提是如果您要在其中任何一种中使用可变长度编码,都将不得不滚动自己的strlen)。

4
提及返回类型:,将为该高度评价的答案增加价值std::size_t
chux-恢复莫妮卡2015年

3
@Eclipse +1 滚泥编辑字符串
Sнаđошƒаӽ

23

在处理C ++字符串(std :: string)时,您正在寻找length()size()。两者都应为您提供相同的价值。但是,在处理C样式字符串时,应使用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;
}

输出:

6
6
6
6

5
请注意,您可以使用#include <cstring>而不是已弃用的#include <string.h>来避免编译器警告(在某些C ++编译器中)
Colin,

1
您的示例仅使用ASCII。您还可以将其更新为Unicode字符吗?尤其是32位的,如𝄞
托马斯·韦勒

17

这取决于您在说什么字符串类型。字符串有很多类型:

  1. const char* -C样式的多字节字符串
  2. const wchar_t* -C风格的宽弦
  3. std::string -“标准”多字节字符串
  4. std::wstring -“标准”宽字符串

对于3和4,可以使用.size().length()方法。

对于1,可以使用strlen(),但是必须确保字符串变量不是NULL(=== 0)

对于2,可以使用wcslen(),但是必须确保字符串变量不是NULL(=== 0)

非标准C ++库中还有其他字符串类型,例如MFC CString,ATL CComBSTR,ACE ACE_CString等等,并带有诸如的方法.GetLength()。我不记得这些细节了。

STLSoft图书馆已经抽象出这一切与他们所谓的串接入垫片,可以用来从任何类型的字符串长度(和其他方面)。因此,对于上述所有(包括非标准库的库)都使用相同的函数stlsoft::c_str_len()本文介绍了是如何工作的,因为它并非一目了然或简单。


1
哪一个适合32等32位字符?
托马斯·韦勒

4

对于Unicode

此处已解决了几个答案,.length()这些错误给出了多字节字符错误的结果,但是有11个答案,但没有一个提供解决方案。

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

首先,重要的是要了解“长度”的含义。例如,考虑字符串“ Z͉̳̺ͥͬ̾a̴͕̲̒̒͌̋ͪl̨͎̰̘͉̟ͤ̀̈̚͜g͕͔̤͖̟̒͝ͅo̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚”(请注意,某些语言(尤其是泰语)实际上使用了组合变音符号,因此这不仅对15岁的模因有用,但显然这是最重要的用例) 。假设它以UTF-8编码。我们可以通过3种方式讨论此字符串的长度:

95字节

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个代码点

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个字素

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

使用ICU查找长度

ICU有C ++类,但是它们需要转换为UTF-16。您可以直接使用C类型和宏来获得一些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̵̡̡̼͚̐ͯ̅ͪ̆ͣ̚");
}

打印:

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包装ICU,并可能提供更好的接口。但是,它仍然需要与UTF-16进行相互转换。


3

如果您使用的是旧的C样式字符串而不是较新的STL样式字符串,那么strlenC运行时库中将提供以下功能:

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

3

如果您使用的是std :: string,则有两种常用方法:

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

如果您使用的是C样式字符串(使用char *或const char *),则可以使用:

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

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

.length和.size是同义词,我只是认为“长度”是一个稍微清晰的词。


不鼓励使用size(),因为我记得听说在某些实现中它将返回“ length()+ 1”(因为它包括空终止符)。因此,只需使用length()即可,因为它更干净,更可移植。

1
@LaQuet,如果您未使用符合标准的编译器或STL实现,则还有更多事情要担心。
斯特拉格2009年

2
@Nelson应该不是标准C ++字符串那样的情况,它不是以空字符结尾的。但是,使用c_str()进行转换时,会将空字节添加到末尾。
约翰T

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

2

对于实际的字符串对象:

yourstring.length();

要么

yourstring.size();

2

在C ++ std :: string中,length()和size()方法为您提供字节数,而不必为字符数!。 与c-Style sizeof()函数相同!

对于大多数可打印的7位ASCII字符,这是相同的值,但是对于不是7位ASCII的字符,则肯定不是。请参见以下示例,为您提供真实的结果(64位linux)。

没有简单的c / c ++函数可以真正计算字符数。顺便说一下,所有这些东西都依赖于实现,并且在其他环境(编译器,win 16/32,linux,嵌入式等)上可能有所不同。

请参见以下示例:

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

该示例的输出是这样的:

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

这可能是输入字符串并找到其长度的最简单方法。

// 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
您认为count:(string)没有string :: length()是什么?除了多余地复制字符串外,如果字符串中的字符数超过20亿,则返回负值。

0

获取字符串长度而不打扰std名称空间的最简单方法如下

带/不带空格的字符串

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

没有空格的字符串

#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
    cout<<"Length of given string is"<<str.length();
    return 0;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.