std :: string에서 문자 수를 얻는 방법은 무엇입니까?


112

C ++에서 문자열의 문자 수를 어떻게 구해야합니까?


1
어떤 종류의 문자열을 다루고 있습니까? std :: string? cstring? null로 끝나는 문자열?
Steve Rowe

가장 안전한 방법은 for 루프를 통해 문자를 직접 계산하는 것입니다.
Krythic

답변:


177

을 사용하는 경우 다음으로 std::string전화하십시오 length().

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

c-string을 사용하는 경우 strlen().

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

또는 Pascal 스타일 문자열 (또는 Joel Spolsky 뒤에 NULL이있을 때 호출하기를 좋아하는 f ***** 문자열)을 사용하는 것을 좋아 한다면 첫 번째 문자를 역 참조하십시오.

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

7
누가 파스칼 스타일의 현을 사용하겠습니까?
Xarn

17
length ()는 문자 수가 아닌 바이트 수를 반환하지 않습니까?

2
std :: string의 경우에도 동일합니다 (가변 길이 인코딩을 저장하거나 std :: string을 사용하여 다중 바이트 문자를 저장하지 않는 한). 그렇게한다면 std 라이브러리에서 많은 도움을받지 못할 것이므로 자신의 strlen 롤링도 처리 할 수 ​​있습니다. wstring, u16string 및 u32string의 경우 바이트가 아닌 문자 수를 리턴합니다. (단, 가변 길이 인코딩을 사용하는 경우 자체 strlen을 굴려야 할 것입니다).
Eclipse

4
반환 유형을 언급하기 위해이 높은 등급의 답변에 가치를 추가합니다 std::size_t.
chux - 분석 재개 모니카

3
f *** ed 문자열에
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
당신이 사용하여 (컴파일러 ++ 특정 C에서) 컴파일러 경고를 방지 할 수 있습니다 사용법 #include <CString을> 대신에 사용되지 않는 사용법 #include <string.h>의
콜린

1
귀하의 예제는 ASCII를 사용합니다. 유니 코드 문자 용으로도 업데이트 하시겠습니까? 같은 𝄞로 특히 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 비트 문자에 적합한 것은 무엇입니까?
Thomas Weller

4

유니 코드의 경우

여기 .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

최신 STL 스타일 문자열 대신 이전 C 스타일 문자열을 사용하는 strlen경우 C 런타임 라이브러리에 함수가 있습니다.

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는 동의어입니다. "length"가 약간 더 명확한 단어라고 생각합니다.


size ()는 일부 구현에서 "length () + 1"을 반환한다는 소식을 들었 기 때문에 권장하지 않습니다 (널 종결자를 포함하기 때문에). 따라서 길이 ()를 사용하면 더 깨끗하고 휴대가 간편합니다.

1
@LaQuet, 표준 호환 컴파일러 또는 STL 구현을 사용하지 않는 경우 걱정할 사항이 더 많습니다.
strager

2
@Nelson은 표준 C ++ 문자열이 null로 끝나지 않기 때문에 그럴 수 없습니다. 그러나 c_str ()로 캐스팅하면 끝에 널 바이트가 추가됩니다.
John T


2

실제 문자열 객체의 경우 :

yourstring.length();

또는

yourstring.size();

2

C ++ std :: string에서 length () 및 size () 메서드는 바이트 수를 제공 하며 반드시 문자 수는 아닙니다!. c-Style sizeof () 함수와 동일합니다!

대부분의 인쇄 가능한 7bit-ASCII 문자의 경우 동일한 값이지만 7bit-ASCII가 아닌 문자의 경우 확실히 그렇지 않습니다. 실제 결과를 제공하려면 다음 예제를 참조하십시오 (64 비트 Linux).

실제로 문자 수를 셀 수있는 간단한 C / C ++ 함수는 없습니다. 그건 그렇고,이 모든 것들은 구현에 따라 다르며 다른 환경 (컴파일러, win 16/32, 리눅스, 임베디드 등)에 따라 다를 수 있습니다.

다음 예를 참조하십시오.

#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 억 개 이상의 문자가 있으면 음수 값을 반환합니다.
Eclipse

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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.