source

std::string 인스턴스를 소문자로 변환하는 방법

lovecheck 2023. 4. 22. 09:45
반응형

std::string 인스턴스를 소문자로 변환하는 방법

하고 std::string소문자로 변환합니다.는 그 .tolower()이 적이 에, 이은 「」, 「」, 「」, 「」, 「」와 함께 사용하는 것이 수 없습니다std::string각 문자를 반복해야 합니다.

100% 효과가 있는 대안이 있을까요?

자주 묻는 질문에서 수정:

#include <algorithm>
#include <cctype>
#include <string>

std::string data = "Abc";
std::transform(data.begin(), data.end(), data.begin(),
    [](unsigned char c){ return std::tolower(c); });

각각의 캐릭터를 반복하지 않고서는 빠져나갈 수 없습니다.소문자인지 대문자인지는 알 수 없습니다.

만약 당신이 정말로 싫다면, 나는 당신이 사용하지 않는 특별한 ASCII만의 대안을 소개합니다.

char asciitolower(char in) {
    if (in <= 'Z' && in >= 'A')
        return in - ('Z' - 'z');
    return in;
}

std::transform(data.begin(), data.end(), data.begin(), asciitolower);

「 」는 .tolower()는 단일 단위의 문자할 수 있습니다.스크립트에 하지 않습니다특히 UTF-8과 같은 에는 더욱 .이는 많은 스크립트에 적합하지 않습니다.특히 UTF-8과 같은 멀티바이트 인코딩을 사용하는 경우에는 더욱 그렇습니다.

부스트는 이를 위한 문자열 알고리즘을 제공합니다.

#include <boost/algorithm/string.hpp>

std::string str = "HELLO, WORLD!";
boost::algorithm::to_lower(str); // modifies str

또는 비인플레이스일 경우:

#include <boost/algorithm/string.hpp>

const std::string str = "HELLO, WORLD!";
const std::string lower_str = boost::algorithm::to_lower_copy(str);

dr;dr

ICU 라이브러리를 사용합니다.그렇지 않으면 기존 케이스도 인식하지 못할 경우 변환 루틴이 자동으로 중단됩니다.


먼저 다음과 같은 질문에 답해야 합니다.인코딩은 무엇입니까?std::stringISO-8859-1인가요?아니면 ISO-8859-8?또는 Windows 코드 페이지1252?대소문자를 변환하기 위해 사용하는 모든이 그것을 알고 있습니까? (또는 그 이상의 캐릭터에 대해 비참하게 실패합니까?)0x7f

UTF-8(8비트 부호화유일하게 적절한 선택)을 사용하는 경우,std::string컨테이너로서, 만약 당신이 여전히 사물을 통제하고 있다고 믿는다면 당신은 이미 자신을 속이고 있는 것이다.다중 바이트 개념을 인식하지 못하는 컨테이너에 다중 바이트 문자 시퀀스를 저장하고 있으며, 이 컨테이너에서 수행할 수 있는 대부분의 작업도 없습니다.같은 단순한 것조차도.substr()멀티바이트 시퀀스 도중에 분할하기 때문에 비활성(서브) 문자열이 발생할 수 있습니다.

std::toupper( 'ß' ) , 「」std::tolower( 'Σ' )어떤 인코딩이든 문제가 있습니다.왜냐하면 1) 표준은 한 번에 한 문자에서만 작동하기 때문에 단순히 회전할 수 없습니다.ßSS옳을 것 같소리다.2) 한 에 한 에, 이 은 '2)'가 '2)'로 되어 있는지, '2)'로 되어 있는지 는 판단할 수 없습니다.Σ σ(정답이 될 것 같습니다) 또는 마지막에)ς 다른 로는 )을 들 수 std::tolower( 'I' )로케일에 따라 다른 결과를 얻을 수 있습니다.실제로 예상할 수 있는 모든 장소에서i튀르키예.ı(LATIN DOTLESS I)를 사용합니다.

따라서 한 번에 한 문자에 대해 작동하거나 한 번에 한 바이트씩 사용할 수 있는 모든 대소문자 변환은 설계상 깨집니다.여기에는 모든 것이 포함됩니다.std::현재 존재하는 변형입니다.

또, 표준 라이브러리의 기능에 대해서는, 소프트웨어를 실행하고 있는 머신에서 서포트되고 있는 로케일에 따라 다릅니다.타겟 로케일이 클라이언트의 머신에서 지원되지 않는 로케일에 포함되어 있는 경우는 어떻게 해야 합니까?

따라서 이 모든 것을 올바르게 처리할 수 있는 문자열 클래스가 필요합니다.이러한 클래스는 어떤 변형도 아닙니다.

노트: (C++11 노트:std::u16string ★★★★★★★★★★★★★★★★★」std::u32string 낫지만 완벽하지는 않아요.C++20 가져오기std::u8string단, 부호화를 지정하는 것이 전부입니다.다른 많은 면에서 그들은 여전히 정규화, 대조 등 유니코드 역학에 대해 무지합니다.)

Boost는 보기 좋지만 API는 현명하고 Boost.로케일은 기본적으로 ICU를 둘러싼 래퍼입니다. ICU 지원을 사용하여 Boost를 컴파일하면...그렇지 않다면, 부스트.로케일은 표준 라이브러리에 대해 컴파일된 로케일 지원으로 제한됩니다.

Boost를 ICU로 컴파일하는 것은 때때로 매우 귀찮을 수 있습니다.(ICU를 포함한 Windows용 바이너리는 사전에 컴파일 되어 있지 않기 때문에 애플리케이션과 함께 제공해야 합니다.그러면 완전히 새로운 웜캔이 열립니다.)

따라서 개인적으로 Unicode의 완전한 지원을 직접 받을 수 있고 ICU 라이브러리를 직접 사용할 것을 권장합니다.

#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>

#include <iostream>

int main()
{
    /*                          "Odysseus" */
    char const * someString = u8"ΟΔΥΣΣΕΥΣ";
    icu::UnicodeString someUString( someString, "UTF-8" );
    // Setting the locale explicitly here for completeness.
    // Usually you would use the user-specified system locale,
    // which *does* make a difference (see ı vs. i above).
    std::cout << someUString.toLower( "el_GR" ) << "\n";
    std::cout << someUString.toUpper( "el_GR" ) << "\n";
    return 0;
}

컴파일 합니다(이 예에서는 G++ 사용).

g++ -Wall example.cpp -licuuc -licuio

그 결과, 다음과 같이 됩니다.

ὀδυσσεύς

단어 중간에 있는 σ 변환과 단어 끝에 있는 σ 변환에 주의해 주세요..<algorithm>-기반솔루션으로제공할수있습니다.

C++11 의 루프에 범위 베이스의 코드를 사용하는 경우는, 다음과 같습니다.

#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::tolower

int main ()
{
  std::locale loc;
  std::string str="Test String.\n";

 for(auto elem : str)
    std::cout << std::tolower(elem,loc);
}

문자열에 ASCII 범위를 벗어나는 UTF-8 문자가 포함되어 있는 경우 boost: algorithm:: to_lower는 변환하지 않습니다.UTF-8이 관련되어 있는 경우 boost::locale::to_lower를 사용하는 것이 좋습니다.http://www.boost.org/doc/libs/1_51_0/libs/locale/doc/html/conversions.html 를 참조해 주세요.

기준 변수가 있는 루프에 기반한 범위를 사용하는 또 다른 접근법

string test = "Hello World";
for(auto& c : test)
{
   c = tolower(c);
}

cout<<test<<endl;

은 Stefan Mai의 결과를한 후 Stefan Mai를 호출해야 .변환 결과를 다른 문자열에 배치하려면 호출하기 전에 스토리지 공간을 미리 할당해야 합니다.std::transformSTL은 변환된 문자를 행선지 반복기에 저장하기 때문에(루프가 반복될 때마다 증가), 행선지 문자열의 사이즈가 자동적으로 조정되지 않고, 메모리 스톰핑의 위험이 있습니다.

#include <string>
#include <algorithm>
#include <iostream>

int main (int argc, char* argv[])
{
  std::string sourceString = "Abc";
  std::string destinationString;

  // Allocate the destination space
  destinationString.resize(sourceString.size());

  // Convert the source string to lower case
  // storing the result in destination string
  std::transform(sourceString.begin(),
                 sourceString.end(),
                 destinationString.begin(),
                 ::tolower);

  // Output the result of the conversion
  std::cout << sourceString
            << " -> "
            << destinationString
            << std::endl;
}

std 네임스페이스를 신경 쓰지 않고 문자열을 loweercase로 변환하는 가장 간단한 방법은 다음과 같습니다.

1: 공백이 있는/없는 문자열

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    getline(cin,str);
//------------function to convert string into lowercase---------------
    transform(str.begin(), str.end(), str.begin(), ::tolower);
//--------------------------------------------------------------------
    cout<<str;
    return 0;
}

2: 공백이 없는 문자열

#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main(){
    string str;
    cin>>str;
//------------function to convert string into lowercase---------------
    transform(str.begin(), str.end(), str.begin(), ::tolower);
//--------------------------------------------------------------------
    cout<<str;
    return 0;
}

대소문자를 실행하는 나만의 템플릿 기능.

#include <string>
#include <algorithm>

//
//  Lowercases string
//
template <typename T>
std::basic_string<T> lowercase(const std::basic_string<T>& s)
{
    std::basic_string<T> s2 = s;
    std::transform(s2.begin(), s2.end(), s2.begin(), tolower);
    return s2;
}

//
// Uppercases string
//
template <typename T>
std::basic_string<T> uppercase(const std::basic_string<T>& s)
{
    std::basic_string<T> s2 = s;
    std::transform(s2.begin(), s2.end(), s2.begin(), toupper);
    return s2;
}

간단한 도우미 기능을 작성했습니다.

#include <locale> // tolower

string to_lower(string s) {        
    for(char &c : s)
        c = tolower(c);
    return s;
}

사용방법:

string s = "TEST";
cout << to_lower("HELLO WORLD"); // output: "hello word"
cout << to_lower(s); // won't change the original variable.

Boost의 대안으로 POCO(pocoproject.org가 있습니다.

POCO에는 다음 두 가지 종류가 있습니다.

  1. 첫 번째 변형은 원래 문자열을 변경하지 않고 복사본을 만듭니다.
  2. 두 번째 변형에서는 원래 문자열이 변경됩니다.
    "In Place"는 "In Place"입니다.

두 가지 버전이 모두 아래에 나와 있습니다.

#include "Poco/String.h"
using namespace Poco;

std::string hello("Stack Overflow!");

// Copies "STACK OVERFLOW!" into 'newString' without altering 'hello.'
std::string newString(toUpper(hello));

// Changes newString in-place to read "stack overflow!"
toLowerInPlace(newString);

std::ctype::tolower()표준 C++ Localization Library에서 올바르게 실행할 수 있습니다.다음은 톨로어 참조 페이지에서 추출한 예입니다.

#include <locale>
#include <iostream>

int main () {
  std::locale::global(std::locale("en_US.utf8"));
  std::wcout.imbue(std::locale());
  std::wcout << "In US English UTF-8 locale:\n";
  auto& f = std::use_facet<std::ctype<wchar_t>>(std::locale());
  std::wstring str = L"HELLo, wORLD!";
  std::wcout << "Lowercase form of the string '" << str << "' is ";
  f.tolower(&str[0], &str[0] + str.size());
  std::wcout << "'" << str << "'\n";
}

어떤 답변도 C++20 이후 표준 라이브러리에서 사용할 수 있고 현재 GitHub에서 별도로 사용할 수 있는 다가오는 Ranges 라이브러리를 언급하지 않았기 때문에range-v3이 변환을 사용하는 방법을 추가하고 싶습니다.

문자열 인플레이스를 수정하려면:

str |= action::transform([](unsigned char c){ return std::tolower(c); });

새 문자열을 생성하려면:

auto new_string = original_string
    | view::transform([](unsigned char c){ return std::tolower(c); });

)#include <cctype>「Ranges(범위)」).

" "의 : " "unsigned char람다에 대한 인수는 다음과 같은 cpp reference에서 영감을 얻습니다.

른 all 의 다른 모든 기능과 <cctype>의.std::tolower "아니다"로 정의되지 .unsigned char는 비교도 않다EOF에서 이러한 하게 사용하기 .char s(또는 s))signed char s) 인수로 .unsigned char

char my_tolower(char ch)
{
    return static_cast<char>(std::tolower(static_cast<unsigned char>(ch)));
}

마찬가지로 반복자의 값 유형이 다음과 같은 경우 표준 알고리즘과 함께 직접 사용해서는 안 됩니다.char ★★★★★★★★★★★★★★★★★」signed char 값을 신대값값 the the the the the the the the 로 변환해 주세요.unsigned char 번째: 첫번::

std::string str_tolower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(), 
                // static_cast<int(*)(int)>(std::tolower)         // wrong
                // [](int c){ return std::tolower(c); }           // wrong
                // [](char c){ return std::tolower(c); }          // wrong
                   [](unsigned char c){ return std::tolower(c); } // correct
                  );
    return s;
}

에서는, 「」를 할 수 .strlwr기능 패밀리: http://msdn.microsoft.com/en-us/library/hkxwh33z.aspx

// crt_strlwr.c
// compile with: /W3
// This program uses _strlwr and _strupr to create
// uppercase and lowercase copies of a mixed-case string.
#include <string.h>
#include <stdio.h>

int main( void )
{
   char string[100] = "The String to End All Strings!";
   char * copy1 = _strdup( string ); // make two copies
   char * copy2 = _strdup( string );

   _strlwr( copy1 ); // C4996
   _strupr( copy2 ); // C4996

   printf( "Mixed: %s\n", string );
   printf( "Lower: %s\n", copy1 );
   printf( "Upper: %s\n", copy2 );

   free( copy1 );
   free( copy2 );
}

테스트를 하지 않고 대소문자를 소문자로 변환하는 방법이 있는데, 매우 간단합니다.supper() 함수/macro의 clocale.h 사용은 사용자의 위치와 관련된 문제를 해결할 수 있지만 그렇지 않을 경우 언제든지 UtoL[]을 원하는 대로 조정할 수 있습니다.

C의 문자는 실제로는 8비트 int(현재의 와이드 문자 집합은 무시)에 불과하기 때문에 대체 문자 집합을 유지하는 256바이트 배열을 작성할 수 있습니다.변환 함수에서는 문자열의 문자를 변환 배열의 첨자로 사용합니다.

단, 1 대 1 매핑 대신 대문자 배열 멤버에게 소문자의 바이트 int 값을 지정합니다.islower() isupper()는 여기서 도움이 될 수 있습니다.

여기에 이미지 설명 입력

코드는 이렇게 생겼는데...

#include <clocale>
static char UtoL[256];
// ----------------------------------------------------------------------------
void InitUtoLMap()  {
    for (int i = 0; i < sizeof(UtoL); i++)  {
        if (isupper(i)) {
            UtoL[i] = (char)(i + 32);
        }   else    {
            UtoL[i] = i;
        }
    }
}
// ----------------------------------------------------------------------------
char *LowerStr(char *szMyStr) {
    char *p = szMyStr;
    // do conversion in-place so as not to require a destination buffer
    while (*p) {        // szMyStr must be null-terminated
        *p = UtoL[*p];  
        p++;
    }
    return szMyStr;
}
// ----------------------------------------------------------------------------
int main() {
    time_t start;
    char *Lowered, Upper[128];
    InitUtoLMap();
    strcpy(Upper, "Every GOOD boy does FINE!");

    Lowered = LowerStr(Upper);
    return 0;
}

이 방법에서는 동시에 변경할 다른 문자를 다시 매핑할 수 있습니다.

이 접근방식은 최신 프로세서에서 실행할 때 하나의 큰 이점이 있습니다.브런치를 구성하는 테스트가 없기 때문에 브런치 예측을 할 필요가 없습니다.이를 통해 CPU의 분기 예측 로직이 다른 루프를 위해 저장되며 파이프라인 정지를 방지하는 경향이 있습니다.

여기에서는, EBCDIC 를 ASCII 로의 변환에 사용한 것과 같은 어프로치를 인식하고 있는 사람도 있습니다.

간단한 것을 원하는 경우 매크로 기술을 다음에 제시하겠습니다.

#define STRTOLOWER(x) std::transform (x.begin(), x.end(), x.begin(), ::tolower)
#define STRTOUPPER(x) std::transform (x.begin(), x.end(), x.begin(), ::toupper)
#define STRTOUCFIRST(x) std::transform (x.begin(), x.begin()+1, x.begin(),  ::toupper); std::transform (x.begin()+1, x.end(),   x.begin()+1,::tolower)

다만, ASCII 문자만이 아닌 것에 임하고 있는 경우는, 이 회답에 대한 @AndreasSpindler의 코멘트는, 여전히 중요한 고려 사항입니다.

100% 효과가 있는 대안이 있을까요?

아니요.

낮은 캐싱 방법을 선택하기 전에 자신에게 물어봐야 할 몇 가지 질문이 있습니다.

  1. 문자열은 어떻게 부호화됩니까?플레인 ASCII?UTF-8? 확장 ASCII 레거시 인코딩 같은 거?
  2. 어쨌든 소문자가 무슨 뜻이죠?케이스 매핑 규칙은 언어에 따라 다릅니다.사용자 로케일로 로컬화된 것을 원하십니까?소프트웨어가 실행되고 있는 모든 시스템에서 일관되게 동작하는 것을 원하십니까?ASCII 문자를 소문자로 하고 다른 문자를 모두 통과하시겠습니까?
  3. 사용할 수 있는 라이브러리는 무엇입니까?

이러한 질문에 대한 답을 얻으면 자신의 요구에 맞는 솔루션을 찾을 수 있습니다.어디에 있든 모든 사람에게 맞는 사이즈는 없습니다!

C++가 .tolower ★★★★★★★★★★★★★★★★★」toupper「」에 있는 std::string ,, 음, 음, 음, 다, 다, 다, 습, 습, 습, 습, ,, ,, ,에 사용할 수 있습니다.char문자열의 각 문자를 쉽게 읽고 필요한 대소문자로 변환하여 문자열로 다시 넣을 수 있습니다.서드파티 라이브러리를 사용하지 않는 샘플코드:

#include<iostream>
    
int main(){
    std::string str = std::string("How ARe You");
    for(char &ch : str){
        ch = std::tolower(ch);
    }
    std::cout<<str<<std::endl;
    return 0;
}

문자열에 대한 문자 기반 조작의 경우 : 문자열 내의 모든 문자

// tolower example (C++)
#include <iostream>       // std::cout
#include <string>         // std::string
#include <locale>         // std::locale, std::tolower

int main ()
{
  std::locale loc;
  std::string str="Test String.\n";
  for (std::string::size_type i=0; i<str.length(); ++i)
    std::cout << std::tolower(str[i],loc);
  return 0;
}

상세한 것에 대하여는, http://www.cplusplus.com/reference/locale/tolower/ 를 참조해 주세요.

답변을 개선할 수 없으므로 복사하십시오.감사합니다.


string test = "Hello World";
for(auto& c : test)
{
   c = tolower(c);
}

설명:

for(auto& c : test)루프를 위한 범위 기반입니다.
for (range_declaration:range_expression)다음과 같습니다loop_statement.

  1. 다음과 같습니다range_declaration.auto& c
    여기서 자동 지정자는 자동 유형 차감에 사용됩니다.따라서 변수 이니셜라이저에서 유형이 차감됩니다.

  2. 다음과 같습니다range_expression.test
    입니다.test

" " " "test는 for 할 수 .이러한 루프는 루프를 통과하는 입니다.c.

이 기능을 시험해 보겠습니다. : )

string toLowerCase(string str) {

    int str_len = str.length();

    string final_str = "";

    for(int i=0; i<str_len; i++) {

        char character = str[i];

        if(character>=65 && character<=92) {

            final_str += (character+32);

        } else {

            final_str += character;

        }

    }

    return final_str;

}

뛰어난 c++17 cpp-unicodelib(GitHub)를 보세요.단일 파일이고 헤더 전용입니다.


#include <exception>
#include <iostream>
#include <codecvt>

// cpp-unicodelib, downloaded from GitHub
#include "unicodelib.h"
#include "unicodelib_encodings.h"

using namespace std;
using namespace unicode;

// converter that allows displaying a Unicode32 string
wstring_convert<codecvt_utf8<char32_t>, char32_t> converter;

std::u32string  in = U"Je suis là!";
cout << converter.to_bytes(in) << endl;

std::u32string  lc = to_lowercase(in);
cout << converter.to_bytes(lc) << endl;

산출량

Je suis là!
je suis là!

fplus::to_lower_case()fplus 라이브러리에서.

★★to_lower_casefplus API 검색에서

예:

fplus::to_lower_case(std::string("ABC")) == std::string("abc");

의 ★★★★absl에는 「」가 있습니다.absl::AsciiStrToLowerabsl::AsciiStrToUpper

하고 있기 c++.std:: string을 .은 화려하게가 없습니다.c++11 이상이면 됩니다. ifwordsvector<string> 그럼아니다,아니다,아니다,아니다,아니다,아니다.

    for (auto & str : words) {
        for(auto & ch : str)
            ch = tolower(ch);
    }

이상한 예외는 없습니다.w_char 를 사용하고 싶은 경우도 있습니다만, 그 이외의 경우는 모두 사용할 수 있습니다.

다른 관점에서 보면 Unicode 문자열에서 local neutral case 폴딩을 수행하는 매우 일반적인 사용 사례가 있습니다.이 경우 접이식 문자 세트가 유한하고 비교적 작다는 것을 깨달았을 때(유니코드 포인트 2000 미만) 케이스 폴딩 성능을 얻을 수 있습니다.생성된 완전 해시(제로 충돌 보장)를 사용하여 모든 입력 문자를 소문자로 변환할 수 있습니다.

UTF-8에서는 멀티바이트 문자를 의식하고 그에 따라 반복해야 합니다.다만, UTF-8 에는, 이 조작을 효율적으로 하기 위한 매우 간단한 부호화 룰이 있습니다.

Unicode 표준의 관련 부분에 대한 링크 및 완벽한 해시 생성기에 대한 자세한 내용은 "C++에서 Unicode 대소문자를 구분하지 않는 비교를 달성하는 방법" 질문에 대한 답변참조하십시오.

코드 조각

#include<bits/stdc++.h>
using namespace std;


int main ()
{
    ios::sync_with_stdio(false);

    string str="String Convert\n";

    for(int i=0; i<str.size(); i++)
    {
      str[i] = tolower(str[i]);
    }
    cout<<str<<endl;

    return 0;
}

ASCII 문자열의 일부 옵션 라이브러리를 to_lower에 추가합니다. 둘 다 프로덕션 수준이고 마이크로 최적화가 적용되어 있습니다(TODO: add benchmark result).

페이스북의 어리석음:

void toLowerAscii(char* str, size_t length)

구글 압세일:

void AsciiStrToLower(std::string* s);

어떤 문자열에서도 사용할 수 있는 템플릿 버전을 작성했습니다.

#include <type_traits> // std::decay
#include <ctype.h>    // std::toupper & std::tolower


template <class T = void> struct farg_t { using type = T; };
template <template<typename ...> class T1, 
class T2> struct farg_t <T1<T2>> { using type = T2*; };
//---------------

template<class T, class T2 = 
typename std::decay< typename farg_t<T>::type >::type>
void ToUpper(T& str) { T2 t = &str[0]; 
for (; *t; ++t) *t = std::toupper(*t); }


template<class T, class T2 = typename std::decay< typename 
farg_t<T>::type >::type>
void Tolower(T& str) { T2 t = &str[0]; 
for (; *t; ++t) *t = std::tolower(*t); }

gcc 컴파일러로 테스트 완료:

#include <iostream>
#include "upove_code.h"

int main()
{

    std::string str1 = "hEllo ";
    char str2 [] = "wOrld";

    ToUpper(str1);
    ToUpper(str2);
    std::cout << str1 << str2 << '\n'; 
    Tolower(str1);
    Tolower(str2);
    std::cout << str1 << str2 << '\n'; 
    return 0;
}

출력:

>HELLO WORLD
>
>hello world

이 코드를 사용하여 c++ 문자열 대소문자를 변경합니다.

#include<bits/stdc++.h>

using namespace std;

int main(){
  string a = "sssAAAAAAaaaaDas";
  transform(a.begin(),a.end(),a.begin(),::tolower);
  cout<<a;
}

언급URL : https://stackoverflow.com/questions/313970/how-to-convert-an-instance-of-stdstring-to-lower-case

반응형