C++ 如何获取 std::string 中的字符数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/905355/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get the number of characters in a std::string?
提问by Elliot
How should I get the number of characters in a string in C++?
我应该如何在 C++ 中获取字符串中的字符数?
回答by Eclipse
If you're using a std::string
, call length()
:
如果您使用的是std::string
,请致电length()
:
std::string str = "hello";
std::cout << str << ":" << str.length();
// Outputs "hello:5"
If you're using a c-string, call strlen()
.
如果您使用的是 c 字符串,请调用strlen()
.
const char *str = "hello";
std::cout << str << ":" << strlen(str);
// Outputs "hello:5"
Or, if you happen to like using Pascal-style strings (or f***** strings as Joel Spolsky likes to call themwhen they have a trailing NULL), just dereference the first character.
或者,如果您碰巧喜欢使用 Pascal 样式的字符串(或 f***** 字符串,因为 Joel Spolsky喜欢在尾随 NULL 时调用它们),只需取消引用第一个字符即可。
const char *str = "#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;
}
5hello";
std::cout << str + 1 << ":" << *str;
// Outputs "hello:5"
回答by John T
When dealing with C++ strings (std::string), you're looking for length()or size(). Both should provide you with the same value. However when dealing with C-Style strings, you would use strlen().
在处理 C++ 字符串 (std::string) 时,您正在寻找length()或size()。两者都应该为您提供相同的价值。但是,在处理 C 样式字符串时,您将使用strlen()。
6
6
6
6
Output:
输出:
std::string Str("Some String");
size_t Size = 0;
Size = Str.size();
Size = Str.length();
回答by dcw
It depends on what string type you're talking about. There are many types of strings:
这取决于您所谈论的字符串类型。字符串有多种类型:
const char*
- a C-style multibyte stringconst wchar_t*
- a C-style wide stringstd::string
- a "standard" multibyte stringstd::wstring
- a "standard" wide string
const char*
- C 风格的多字节字符串const wchar_t*
- C 风格的宽字符串std::string
- “标准”多字节字符串std::wstring
- “标准”宽字符串
For 3 and 4, you can use .size()
or .length()
methods.
对于 3 和 4,您可以使用.size()
或.length()
方法。
For 1, you can use strlen()
, but you must ensure that the string variable is not NULL (=== 0)
对于 1,可以使用strlen()
,但必须确保字符串变量不为 NULL (=== 0)
For 2, you can use wcslen()
, but you must ensure that the string variable is not NULL (=== 0)
对于 2,可以使用wcslen()
,但必须确保字符串变量不为 NULL (=== 0)
There are other string types in non-standard C++ libraries, such as MFC's CString
, ATL's CComBSTR
, ACE's ACE_CString
, and so on, with methods such as .GetLength()
, and so on. I can't remember the specifics of them all right off the top of my head.
非标准 C++ 库中还有其他字符串类型,例如 MFC 的CString
、ATL 的CComBSTR
、ACE 的ACE_CString
等等,还有诸如.GetLength()
、等等的方法。我一时想不起来它们的具体细节。
The STLSoftlibraries have abstracted this all out with what they call string access shims, which can be used to get the string length (and other aspects) from any type. So for all of the above (including the non-standard library ones) using the same function stlsoft::c_str_len()
. This articledescribes how it all works, as it's not all entirely obvious or easy.
该STLSoft图书馆已经抽象出这一切与他们所谓的串接入垫片,可以用来从任何类型的字符串长度(和其他方面)。所以对于以上所有(包括非标准库的)使用相同的函数stlsoft::c_str_len()
。本文描述了它是如何工作的,因为它并不完全显而易见或容易。
回答by Gal Goldman
if you're using std::string, there are two common methods for that:
如果您使用的是 std::string,则有两种常用方法:
const char *pStr = "Some String";
size_t Size = strlen(pStr);
if you're using the C style string (using char * or const char *) then you can use:
如果您使用的是 C 样式字符串(使用 char * 或 const char *),那么您可以使用:
const char* p = "Hello";
size_t n = strlen(p);
回答by ChrisW
If you're using old, C-style string instead of the newer, STL-style strings, there's the strlen
function in the C run time library:
如果您使用旧的 C 样式字符串而不是新的 STL 样式字符串,则strlen
C 运行时库中有该函数:
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 ...............
回答by Robert Fraser
For Unicode
对于 Unicode
Several answers here have addressed that .length()
gives the wrong results with multibyte characters, but there are 11 answers and none of them have provided a solution.
这里的几个答案已经解决.length()
了用多字节字符给出错误结果的问题,但有 11 个答案,但没有一个提供解决方案。
The case of Z??????a????????l???????????g????????o????????????
Z的情况??????a????????l?????????????g??????????o????????? ???
First of all, it's important to know what you mean by "length". For a motivating example, consider the string "Z??????a????????l???????????g????????o????????????" (note that some languages, notably Thai, actually use combining diacritical marks, so this isn't justuseful for 15-year-old memes, but obviously that's the most important use case). Assume it is encoded in UTF-8. There are 3 ways we can talk about the length of this string:
首先,了解“长度”是什么意思很重要。作为一个激励示例,请考虑字符串“Z??????a??????????l?????????????g????????o??? ?????????” (请注意,某些语言,尤其是泰语,实际上使用组合变音符号,因此这不仅对 15 岁的模因有用,而且显然这是最重要的用例)。假设它是用UTF-8编码的。我们可以通过 3 种方式来讨论此字符串的长度:
95 bytes
95 字节
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
50 codepoints
50 个代码点
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
5 graphemes
5个字素
#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????????????");
}
Finding the lengths using ICU
使用ICU查找长度
There are C++ classes for ICU, but they require converting to UTF-16. You can use the C types and macros directly to get some UTF-8 support:
ICU 有 C++ 类,但它们需要转换为 UTF-16。您可以直接使用 C 类型和宏来获得一些 UTF-8 支持:
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
This prints:
这打印:
yourstring.length();
Boost.Localewraps ICU, and might provide a nicer interface. However, it still requires conversion to/from UTF-16.
Boost.Locale包装了 ICU,并可能提供更好的界面。但是,它仍然需要与 UTF-16 之间的转换。
回答by Luke Schafer
for an actual string object:
对于实际的字符串对象:
yourstring.size();
or
或者
string foo;
... foo.length() ...
回答by Alex Martelli
std::string str("a string");
std::cout << str.size() << std::endl;
.length and .size are synonymous, I just think that "length" is a slightly clearer word.
.length 和 .size 是同义词,我只是认为“长度”是一个稍微清晰的词。
回答by stefanB
#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;
}
回答by Hape Entner
In C++ std::string the length() and size() method gives you the number of bytes, and not necessarily the number of characters !.Same with the c-Style sizeof() function!
在 C++ std::string 中,length() 和 size() 方法为您提供字节数,而不一定是字符数!。与 c 风格的 sizeof() 函数相同!
For most of the printable 7bit-ASCII Characters this is the same value, but for characters that are not 7bit-ASCII it's definitely not. See the following example to give you real results (64bit linux).
对于大多数可打印的 7 位 ASCII 字符,这是相同的值,但对于不是 7 位 ASCII 的字符,它绝对不是。请参阅以下示例以提供真实结果(64 位 linux)。
There is no simple c/c++ function that can really count the number of characters. By the way, all of this stuff is implementation dependent and may be different on other environments (compiler, win 16/32, linux, embedded, ...)
没有简单的 c/c++ 函数可以真正计算字符数。顺便说一句,所有这些东西都依赖于实现,并且在其他环境中可能会有所不同(编译器、win 16/32、linux、嵌入式……)
See following example:
请参阅以下示例:
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
The output of the example is this:
该示例的输出是这样的:
##代码##